summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSunderland93 <[email protected]>2026-07-20 12:09:52 +0400
committerLuke from DC <[email protected]>2026-07-31 07:57:23 +0000
commit827ddfd429c105d6afbdb35705c72d4643135d97 (patch)
treedac260b49e66a77f8d78953917d5eb990beaeb44
parentcbb9c2589291bcee42ded23ddc7ed2005609db5e (diff)
downloadmate-panel-827ddfd429c105d6afbdb35705c72d4643135d97.tar.bz2
mate-panel-827ddfd429c105d6afbdb35705c72d4643135d97.tar.xz
Use libxfce4windowing for handle panel-related procotols, applet fixes
-rw-r--r--applets/wncklet/Makefile.am10
-rw-r--r--applets/wncklet/wayland-workspace.c780
-rw-r--r--applets/wncklet/wayland-workspace.h3
-rw-r--r--applets/wncklet/workspace-switcher.c85
-rw-r--r--configure.ac5
5 files changed, 396 insertions, 487 deletions
diff --git a/applets/wncklet/Makefile.am b/applets/wncklet/Makefile.am
index 9d84c331..abfb5113 100644
--- a/applets/wncklet/Makefile.am
+++ b/applets/wncklet/Makefile.am
@@ -44,15 +44,15 @@ WNCKLET_SOURCES += \
wayland-workspace.c \
wayland-workspace.h \
wayland-protocol/wlr-foreign-toplevel-management-unstable-v1-code.c \
- wayland-protocol/wlr-foreign-toplevel-management-unstable-v1-client.h \
- wayland-protocol/ext-workspace-v1-code.c \
- wayland-protocol/ext-workspace-v1-client.h
+ wayland-protocol/wlr-foreign-toplevel-management-unstable-v1-client.h
WNCKLET_LDADD += \
- $(WAYLAND_LIBS)
+ $(WAYLAND_LIBS) \
+ $(XFW_LIBS)
AM_CPPFLAGS += \
- $(WAYLAND_CFLAGS)
+ $(WAYLAND_CFLAGS) \
+ $(XFW_CFLAGS)
endif
if WNCKLET_INPROCESS
diff --git a/applets/wncklet/wayland-workspace.c b/applets/wncklet/wayland-workspace.c
index 5f42783d..646ab802 100644
--- a/applets/wncklet/wayland-workspace.c
+++ b/applets/wncklet/wayland-workspace.c
@@ -19,572 +19,375 @@
#include <config.h>
-#include <gdk/gdkwayland.h>
#include <gtk/gtk.h>
+#include <libxfce4windowing/libxfce4windowing.h>
#include "wayland-workspace.h"
-#include "wayland-protocol/ext-workspace-v1-client.h"
-typedef struct _WaylandWorkspaceData WaylandWorkspaceData;
+typedef struct _GroupSignal GroupSignal;
+
+struct _GroupSignal {
+ XfwWorkspaceGroup *group;
+ gulong handlers[3]; /* active-changed, added, removed */
+};
-typedef struct {
- struct ext_workspace_handle_v1 *handle;
- WaylandWorkspaceData *pager;
- char *name;
- gboolean active;
- gboolean hidden;
- gboolean urgent;
-} WaylandWorkspace;
-
-typedef struct {
- struct ext_workspace_group_handle_v1 *handle;
- WaylandWorkspaceData *pager;
- GList *workspaces;
-} WaylandWorkspaceGroup;
+typedef struct _WaylandWorkspaceData WaylandWorkspaceData;
struct _WaylandWorkspaceData {
GtkWidget *grid;
- GtkWidget *outer_box;
- struct ext_workspace_manager_v1 *manager;
- GList *workspace_groups;
- GList *pending_workspaces;
+ XfwScreen *screen;
+ XfwWorkspaceManager *workspace_manager;
+ GList *group_signals; /* list of GroupSignal* */
GtkOrientation orientation;
int n_rows;
gboolean display_all;
gboolean display_names;
+ gboolean ignore_toggle;
};
-static struct wl_registry *wl_registry_global = NULL;
-static uint32_t workspace_manager_global_id = 0;
-static uint32_t workspace_manager_global_version = 0;
-static gboolean has_initialized = FALSE;
-
static void rebuild_ui (WaylandWorkspaceData *data);
-static void
-wl_registry_handle_global (void *_data,
- struct wl_registry *registry,
- uint32_t id,
- const char *interface,
- uint32_t version)
-{
- if (strcmp (interface, ext_workspace_manager_v1_interface.name) == 0)
- {
- workspace_manager_global_id = id;
- workspace_manager_global_version =
- MIN ((uint32_t) ext_workspace_manager_v1_interface.version, version);
- }
-}
+/* ---- Helpers ---- */
-static void
-wl_registry_handle_global_remove (void *_data,
- struct wl_registry *_registry,
- uint32_t id)
+static int
+count_visible_workspaces (WaylandWorkspaceData *data)
{
- if (id == workspace_manager_global_id)
+ GList *workspaces, *l;
+ int n = 0;
+
+ workspaces = xfw_workspace_manager_list_workspaces (data->workspace_manager);
+
+ for (l = workspaces; l != NULL; l = l->next)
{
- workspace_manager_global_id = 0;
+ XfwWorkspace *ws = l->data;
+ XfwWorkspaceState state = xfw_workspace_get_state (ws);
+
+ if (data->display_all || !(state & XFW_WORKSPACE_STATE_HIDDEN))
+ n++;
}
-}
-static const struct wl_registry_listener wl_registry_listener = {
- .global = wl_registry_handle_global,
- .global_remove = wl_registry_handle_global_remove,
-};
+ return MAX (n, 1);
+}
-static void
-wayland_workspace_init_if_needed (void)
+static XfwWorkspace *
+get_nth_workspace (WaylandWorkspaceData *data, int index)
{
- if (has_initialized)
- return;
+ GList *workspaces, *l;
+ int i = 0;
- GdkDisplay *gdk_display = gdk_display_get_default ();
- g_return_if_fail (gdk_display);
- g_return_if_fail (GDK_IS_WAYLAND_DISPLAY (gdk_display));
+ workspaces = xfw_workspace_manager_list_workspaces (data->workspace_manager);
- struct wl_display *wl_display = gdk_wayland_display_get_wl_display (gdk_display);
- wl_registry_global = wl_display_get_registry (wl_display);
- wl_registry_add_listener (wl_registry_global, &wl_registry_listener, NULL);
- wl_display_roundtrip (wl_display);
+ for (l = workspaces; l != NULL; l = l->next)
+ {
+ XfwWorkspace *ws = l->data;
+ XfwWorkspaceState state = xfw_workspace_get_state (ws);
- if (!workspace_manager_global_id)
- g_warning ("%s not supported by Wayland compositor",
- ext_workspace_manager_v1_interface.name);
+ if (data->display_all || !(state & XFW_WORKSPACE_STATE_HIDDEN))
+ {
+ if (i == index)
+ return ws;
+ i++;
+ }
+ }
- has_initialized = TRUE;
+ return NULL;
}
-static WaylandWorkspace *
-wayland_workspace_new_from_handle (struct ext_workspace_handle_v1 *handle,
- WaylandWorkspaceData *pager)
-{
- WaylandWorkspace *ws = g_new0 (WaylandWorkspace, 1);
- ws->handle = handle;
- ws->pager = pager;
- ws->name = g_strdup ("");
- ws->active = FALSE;
- ws->hidden = FALSE;
- ws->urgent = FALSE;
- return ws;
-}
+/* ---- Build / rebuild the button grid ---- */
static void
-wayland_workspace_free (WaylandWorkspace *ws)
+on_button_toggled (GtkToggleButton *button, WaylandWorkspaceData *data)
{
- if (ws)
- {
- g_free (ws->name);
- g_free (ws);
- }
-}
+ int index;
-static WaylandWorkspaceGroup *
-wayland_workspace_group_new (struct ext_workspace_group_handle_v1 *handle,
- WaylandWorkspaceData *pager)
-{
- WaylandWorkspaceGroup *group = g_new0 (WaylandWorkspaceGroup, 1);
- group->handle = handle;
- group->pager = pager;
- group->workspaces = NULL;
- return group;
-}
+ if (data->ignore_toggle)
+ return;
-static void
-wayland_workspace_group_free (WaylandWorkspaceGroup *group)
-{
- if (group)
+ if (gtk_toggle_button_get_active (button))
{
- g_list_free_full (group->workspaces, (GDestroyNotify) wayland_workspace_free);
- g_free (group);
+ index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "ws-index"));
+ XfwWorkspace *ws = get_nth_workspace (data, index);
+ if (ws)
+ {
+ GError *error = NULL;
+ if (!xfw_workspace_activate (ws, &error))
+ {
+ g_warning ("Failed to activate workspace: %s",
+ error ? error->message : "unknown error");
+ g_clear_error (&error);
+ }
+ }
+ }
+ else
+ {
+ /* User clicked the already-active button — keep it toggled on */
+ data->ignore_toggle = TRUE;
+ gtk_toggle_button_set_active (button, TRUE);
+ data->ignore_toggle = FALSE;
}
}
static void
-workspace_handle_id (void *data,
- struct ext_workspace_handle_v1 *handle,
- const char *id)
+rebuild_ui (WaylandWorkspaceData *data)
{
-}
+ GList *children, *l;
+ int n_spaces, i, col, row;
+ int rows, cols;
-static void
-workspace_handle_name (void *data,
- struct ext_workspace_handle_v1 *handle,
- const char *name)
-{
- WaylandWorkspace *ws = data;
- g_free (ws->name);
- ws->name = g_strdup (name ? name : "");
-}
+ /* Destroy old buttons */
+ children = gtk_container_get_children (GTK_CONTAINER (data->grid));
+ for (l = children; l != NULL; l = l->next)
+ gtk_widget_destroy (GTK_WIDGET (l->data));
+ g_list_free (children);
-static void
-workspace_handle_coordinates (void *data,
- struct ext_workspace_handle_v1 *handle,
- struct wl_array *coordinates)
-{
-}
+ n_spaces = count_visible_workspaces (data);
-static void
-workspace_handle_state (void *data,
- struct ext_workspace_handle_v1 *handle,
- uint32_t state)
-{
- WaylandWorkspace *ws = data;
- ws->active = (state & EXT_WORKSPACE_HANDLE_V1_STATE_ACTIVE) != 0;
- ws->hidden = (state & EXT_WORKSPACE_HANDLE_V1_STATE_HIDDEN) != 0;
- ws->urgent = (state & EXT_WORKSPACE_HANDLE_V1_STATE_URGENT) != 0;
-}
+ /* Determine grid dimensions */
+ if (data->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ rows = data->n_rows;
+ cols = (n_spaces + rows - 1) / rows;
+ }
+ else
+ {
+ cols = data->n_rows;
+ rows = (n_spaces + cols - 1) / cols;
+ }
-static void
-workspace_handle_capabilities (void *data,
- struct ext_workspace_handle_v1 *handle,
- uint32_t capabilities)
-{
-}
+ gtk_grid_set_column_homogeneous (GTK_GRID (data->grid), TRUE);
+ gtk_grid_set_row_homogeneous (GTK_GRID (data->grid), TRUE);
-static void
-workspace_handle_removed (void *data,
- struct ext_workspace_handle_v1 *handle)
-{
-}
+ /* Create buttons */
+ for (i = 0; i < n_spaces; i++)
+ {
+ XfwWorkspace *ws;
+ const char *name;
+ char *free_name = NULL;
+ GtkWidget *button;
+ XfwWorkspaceState ws_state;
-static const struct ext_workspace_handle_v1_listener workspace_handle_listener = {
- .id = workspace_handle_id,
- .name = workspace_handle_name,
- .coordinates = workspace_handle_coordinates,
- .state = workspace_handle_state,
- .capabilities = workspace_handle_capabilities,
- .removed = workspace_handle_removed,
-};
+ ws = get_nth_workspace (data, i);
-static void
-workspace_group_handle_capabilities (void *data,
- struct ext_workspace_group_handle_v1 *handle,
- uint32_t capabilities)
-{
-}
+ if (data->display_names && ws)
+ {
+ name = xfw_workspace_get_name (ws);
+ if (!name || name[0] == '\0')
+ name = xfw_workspace_get_id (ws);
+ if (!name)
+ name = "";
+ }
+ else
+ {
+ free_name = g_strdup_printf ("%d", i + 1);
+ name = free_name;
+ }
-static void
-workspace_group_handle_output_enter (void *data,
- struct ext_workspace_group_handle_v1 *handle,
- struct wl_output *output)
-{
-}
+ button = gtk_toggle_button_new_with_label (name);
+ g_free (free_name);
-static void
-workspace_group_handle_output_leave (void *data,
- struct ext_workspace_group_handle_v1 *handle,
- struct wl_output *output)
-{
-}
+ gtk_widget_set_name (button, "wnck-pager-button");
+ g_object_set_data (G_OBJECT (button), "ws-index", GINT_TO_POINTER (i));
-static void
-workspace_group_handle_workspace_enter (void *data,
- struct ext_workspace_group_handle_v1 *handle,
- struct ext_workspace_handle_v1 *workspace_handle)
-{
- WaylandWorkspaceGroup *group = data;
- WaylandWorkspaceData *pager = group->pager;
- GList *l;
- WaylandWorkspace *ws = NULL;
+ /* Set active state */
+ ws_state = ws ? xfw_workspace_get_state (ws) : XFW_WORKSPACE_STATE_NONE;
+ data->ignore_toggle = TRUE;
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+ (ws_state & XFW_WORKSPACE_STATE_ACTIVE) != 0);
+ data->ignore_toggle = FALSE;
- for (l = pager->pending_workspaces; l != NULL; l = l->next)
- {
- WaylandWorkspace *ws_candidate = l->data;
- if (ws_candidate->handle == workspace_handle)
+ g_signal_connect (button, "toggled",
+ G_CALLBACK (on_button_toggled), data);
+
+ /* Calculate grid position */
+ if (data->orientation == GTK_ORIENTATION_HORIZONTAL)
{
- ws = ws_candidate;
- pager->pending_workspaces = g_list_delete_link (pager->pending_workspaces, l);
- break;
+ col = i / rows;
+ row = i % rows;
+ }
+ else
+ {
+ col = i % cols;
+ row = i / cols;
}
- }
- if (!ws)
- {
- ws = wayland_workspace_new_from_handle (workspace_handle, pager);
- ext_workspace_handle_v1_add_listener (workspace_handle,
- &workspace_handle_listener,
- ws);
+ gtk_grid_attach (GTK_GRID (data->grid), button, col, row, 1, 1);
}
- group->workspaces = g_list_append (group->workspaces, ws);
+ gtk_widget_show_all (data->grid);
}
+/* ---- Signal handlers on workspace groups ---- */
+
static void
-workspace_group_handle_workspace_leave (void *data,
- struct ext_workspace_group_handle_v1 *handle,
- struct ext_workspace_handle_v1 *workspace_handle)
+on_active_workspace_changed (XfwWorkspaceGroup *group,
+ XfwWorkspace *previous,
+ WaylandWorkspaceData *data)
{
- WaylandWorkspaceGroup *group = data;
- GList *l;
-
- for (l = group->workspaces; l != NULL; l = l->next)
- {
- WaylandWorkspace *ws = l->data;
- if (ws->handle == workspace_handle)
- {
- group->workspaces = g_list_delete_link (group->workspaces, l);
- wayland_workspace_free (ws);
- break;
- }
- }
+ rebuild_ui (data);
}
static void
-workspace_group_handle_removed (void *data,
- struct ext_workspace_group_handle_v1 *handle)
+on_workspace_added (XfwWorkspaceGroup *group,
+ XfwWorkspace *workspace,
+ WaylandWorkspaceData *data)
{
+ rebuild_ui (data);
}
-static const struct ext_workspace_group_handle_v1_listener workspace_group_handle_listener = {
- .capabilities = workspace_group_handle_capabilities,
- .output_enter = workspace_group_handle_output_enter,
- .output_leave = workspace_group_handle_output_leave,
- .workspace_enter = workspace_group_handle_workspace_enter,
- .workspace_leave = workspace_group_handle_workspace_leave,
- .removed = workspace_group_handle_removed,
-};
-
static void
-manager_handle_workspace_group (void *data,
- struct ext_workspace_manager_v1 *manager,
- struct ext_workspace_group_handle_v1 *group_handle)
+on_workspace_removed (XfwWorkspaceGroup *group,
+ XfwWorkspace *workspace,
+ WaylandWorkspaceData *data)
{
- WaylandWorkspaceData *pager = data;
-
- WaylandWorkspaceGroup *group = wayland_workspace_group_new (group_handle, pager);
- ext_workspace_group_handle_v1_add_listener (group_handle,
- &workspace_group_handle_listener,
- group);
- pager->workspace_groups = g_list_append (pager->workspace_groups, group);
+ rebuild_ui (data);
}
+/* ---- Group signal management ---- */
+
static void
-manager_handle_workspace (void *data,
- struct ext_workspace_manager_v1 *manager,
- struct ext_workspace_handle_v1 *workspace_handle)
+disconnect_group_signals (WaylandWorkspaceData *data)
{
- WaylandWorkspaceData *pager = data;
- WaylandWorkspace *ws = wayland_workspace_new_from_handle (workspace_handle, pager);
-
- ext_workspace_handle_v1_add_listener (workspace_handle,
- &workspace_handle_listener,
- ws);
+ for (GList *l = data->group_signals; l != NULL; l = l->next)
+ {
+ GroupSignal *gs = l->data;
+ g_signal_handler_disconnect (gs->group, gs->handlers[0]);
+ g_signal_handler_disconnect (gs->group, gs->handlers[1]);
+ g_signal_handler_disconnect (gs->group, gs->handlers[2]);
+ g_free (gs);
+ }
- pager->pending_workspaces = g_list_append (pager->pending_workspaces, ws);
+ g_list_free (data->group_signals);
+ data->group_signals = NULL;
}
static void
-manager_handle_done (void *data,
- struct ext_workspace_manager_v1 *manager)
+connect_group_signals (WaylandWorkspaceData *data)
{
- WaylandWorkspaceData *pager = data;
- GList *l;
+ GList *groups, *l;
- /* Fallback: if workspaces are still pending (compositor didn't send
- * workspace_enter for them), assign them to the first group */
- if (pager->pending_workspaces != NULL && pager->workspace_groups != NULL)
- {
- WaylandWorkspaceGroup *first_group = pager->workspace_groups->data;
+ disconnect_group_signals (data);
- for (l = pager->pending_workspaces; l != NULL; l = l->next)
- {
- WaylandWorkspace *ws = l->data;
- first_group->workspaces = g_list_append (first_group->workspaces, ws);
- }
- g_list_free (pager->pending_workspaces);
- pager->pending_workspaces = NULL;
- }
+ groups = xfw_workspace_manager_list_workspace_groups (data->workspace_manager);
+ if (!groups)
+ return;
- rebuild_ui (pager);
+ for (l = groups; l != NULL; l = l->next)
+ {
+ XfwWorkspaceGroup *group = l->data;
+ GroupSignal *gs = g_new0 (GroupSignal, 1);
+
+ gs->group = group;
+ gs->handlers[0] = g_signal_connect (group, "active-workspace-changed",
+ G_CALLBACK (on_active_workspace_changed), data);
+ gs->handlers[1] = g_signal_connect (group, "workspace-added",
+ G_CALLBACK (on_workspace_added), data);
+ gs->handlers[2] = g_signal_connect (group, "workspace-removed",
+ G_CALLBACK (on_workspace_removed), data);
+
+ data->group_signals = g_list_append (data->group_signals, gs);
+ }
}
static void
-manager_handle_finished (void *data,
- struct ext_workspace_manager_v1 *manager)
+on_workspace_group_created (XfwWorkspaceManager *manager,
+ XfwWorkspaceGroup *group,
+ WaylandWorkspaceData *data)
{
- WaylandWorkspaceData *pager = data;
-
- pager->manager = NULL;
- ext_workspace_manager_v1_destroy (manager);
-
- if (pager->outer_box)
- g_object_set_data (G_OBJECT (pager->outer_box),
- "wayland_pager_data",
- NULL);
+ connect_group_signals (data);
+ rebuild_ui (data);
}
-static const struct ext_workspace_manager_v1_listener manager_listener = {
- .workspace_group = manager_handle_workspace_group,
- .workspace = manager_handle_workspace,
- .done = manager_handle_done,
- .finished = manager_handle_finished,
-};
-
static void
-workspace_button_clicked (GtkButton *button, WaylandWorkspace *ws)
+on_workspace_group_destroyed (XfwWorkspaceManager *manager,
+ XfwWorkspaceGroup *group,
+ WaylandWorkspaceData *data)
{
- if (ws->handle && ws->pager->manager)
- {
- ext_workspace_handle_v1_activate (ws->handle);
- ext_workspace_manager_v1_commit (ws->pager->manager);
- }
+ connect_group_signals (data);
+ rebuild_ui (data);
}
static void
-rebuild_ui (WaylandWorkspaceData *data)
+on_workspace_created (XfwWorkspaceManager *manager,
+ XfwWorkspace *workspace,
+ WaylandWorkspaceData *data)
{
- GList *l;
- int n_workspaces = 0;
- int n_cols, n_visual_rows;
- int row, col;
- int i;
-
- /* Remove existing children */
- if (data->grid)
- {
- gtk_widget_destroy (data->grid);
- data->grid = NULL;
- }
-
- /* Count visible workspaces */
- for (l = data->workspace_groups; l != NULL; l = l->next)
- {
- WaylandWorkspaceGroup *group = l->data;
- GList *wl;
- for (wl = group->workspaces; wl != NULL; wl = wl->next)
- {
- WaylandWorkspace *ws = wl->data;
- if (!ws->hidden || data->display_all)
- n_workspaces++;
- }
- }
-
- if (n_workspaces == 0)
- {
- /* Show at least one empty slot */
- n_workspaces = 1;
- }
-
- /* Calculate grid dimensions */
- if (data->orientation == GTK_ORIENTATION_HORIZONTAL)
- {
- n_visual_rows = data->n_rows;
- n_cols = n_workspaces / n_visual_rows;
- if (n_workspaces % n_visual_rows != 0)
- n_cols++;
- }
- else
- {
- n_cols = data->n_rows;
- n_visual_rows = n_workspaces / n_cols;
- if (n_workspaces % n_cols != 0)
- n_visual_rows++;
- }
-
- data->grid = gtk_grid_new ();
- gtk_grid_set_column_homogeneous (GTK_GRID (data->grid), TRUE);
- gtk_grid_set_row_homogeneous (GTK_GRID (data->grid), TRUE);
- gtk_container_add (GTK_CONTAINER (data->outer_box), data->grid);
-
- /* Create buttons for each workspace */
- i = 0;
- for (l = data->workspace_groups; l != NULL; l = l->next)
- {
- WaylandWorkspaceGroup *group = l->data;
- GList *wl;
- for (wl = group->workspaces; wl != NULL; wl = wl->next)
- {
- WaylandWorkspace *ws = wl->data;
- GtkWidget *button;
- GtkWidget *label;
- char *text;
-
- if (ws->hidden && !data->display_all)
- continue;
-
- button = gtk_button_new ();
- gtk_widget_set_name (button, "wnck-pager-button");
-
- if (data->display_names && ws->name && ws->name[0] != '\0')
- text = g_strdup (ws->name);
- else
- text = g_strdup_printf ("%d", i + 1);
-
- label = gtk_label_new (text);
- g_free (text);
-
- gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
- gtk_label_set_max_width_chars (GTK_LABEL (label), 8);
- gtk_container_add (GTK_CONTAINER (button), label);
-
- g_signal_connect (button, "clicked",
- G_CALLBACK (workspace_button_clicked), ws);
-
- g_object_set_data (G_OBJECT (button), "workspace_data", ws);
-
- /* Add CSS class for active workspace styling */
- GtkStyleContext *context = gtk_widget_get_style_context (button);
- gtk_style_context_add_class (context, "wnck-pager");
- if (ws->active)
- gtk_style_context_add_class (context, "selected");
-
- if (data->orientation == GTK_ORIENTATION_HORIZONTAL)
- {
- row = i % n_visual_rows;
- col = i / n_visual_rows;
- }
- else
- {
- col = i % n_cols;
- row = i / n_cols;
- }
-
- gtk_grid_attach (GTK_GRID (data->grid), button, col, row, 1, 1);
- gtk_widget_show_all (button);
-
- i++;
- }
- }
-
- /* If no workspaces were visible, show an empty placeholder */
- if (i == 0)
- {
- GtkWidget *button = gtk_button_new ();
- gtk_widget_set_sensitive (button, FALSE);
- gtk_widget_set_name (button, "wnck-pager-button");
- GtkWidget *label = gtk_label_new ("1");
- gtk_container_add (GTK_CONTAINER (button), label);
- gtk_grid_attach (GTK_GRID (data->grid), button, 0, 0, 1, 1);
- gtk_widget_show_all (button);
- }
-
- gtk_widget_show (data->grid);
+ rebuild_ui (data);
}
static void
-wayland_pager_disconnected (WaylandWorkspaceData *data)
+on_workspace_destroyed (XfwWorkspaceManager *manager,
+ XfwWorkspace *workspace,
+ WaylandWorkspaceData *data)
{
- if (data->grid)
- {
- gtk_widget_destroy (data->grid);
- data->grid = NULL;
- }
-
- if (data->manager)
- ext_workspace_manager_v1_stop (data->manager);
+ rebuild_ui (data);
+}
- g_list_free_full (data->workspace_groups, (GDestroyNotify) wayland_workspace_group_free);
- data->workspace_groups = NULL;
+/* ---- Cleanup ---- */
- g_list_free_full (data->pending_workspaces, (GDestroyNotify) wayland_workspace_free);
- data->pending_workspaces = NULL;
+static void
+wayland_pager_data_free (WaylandWorkspaceData *data)
+{
+ disconnect_group_signals (data);
+ g_free (data);
}
+/* ---- Public API ---- */
+
GtkWidget *
wayland_workspace_new (void)
{
- wayland_workspace_init_if_needed ();
+ WaylandWorkspaceData *data;
- WaylandWorkspaceData *data = g_new0 (WaylandWorkspaceData, 1);
+ xfw_set_client_type (XFW_CLIENT_TYPE_PAGER);
+
+ data = g_new0 (WaylandWorkspaceData, 1);
data->orientation = GTK_ORIENTATION_HORIZONTAL;
data->n_rows = 1;
data->display_all = TRUE;
data->display_names = FALSE;
+ data->ignore_toggle = FALSE;
- data->outer_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_show (data->outer_box);
+ data->grid = gtk_grid_new ();
+ gtk_widget_set_size_request (data->grid, 48, -1);
- g_object_set_data_full (G_OBJECT (data->outer_box),
+ GtkStyleContext *context = gtk_widget_get_style_context (data->grid);
+ gtk_style_context_add_class (context, "wnck-pager");
+
+ g_object_set_data_full (G_OBJECT (data->grid),
"wayland_pager_data",
data,
- (GDestroyNotify) wayland_pager_disconnected);
+ (GDestroyNotify) wayland_pager_data_free);
- if (!workspace_manager_global_id)
+ data->screen = xfw_screen_get_default ();
+ if (!data->screen)
{
- g_warning ("ext_workspace_manager_v1 not available");
- return data->outer_box;
+ g_warning ("xfw_screen_get_default() failed");
+ return data->grid;
}
- data->manager = wl_registry_bind (wl_registry_global,
- workspace_manager_global_id,
- &ext_workspace_manager_v1_interface,
- workspace_manager_global_version);
-
- ext_workspace_manager_v1_add_listener (data->manager,
- &manager_listener,
- data);
-
- /* Trigger initial roundtrip to get workspace state */
- GdkDisplay *gdk_display = gdk_display_get_default ();
- if (gdk_display)
+ data->workspace_manager = xfw_screen_get_workspace_manager (data->screen);
+ if (!data->workspace_manager)
{
- struct wl_display *wl_display = gdk_wayland_display_get_wl_display (gdk_display);
- wl_display_roundtrip (wl_display);
+ g_warning ("xfw_screen_get_workspace_manager() failed");
+ return data->grid;
}
- return data->outer_box;
+ g_signal_connect (data->workspace_manager, "workspace-group-created",
+ G_CALLBACK (on_workspace_group_created), data);
+ g_signal_connect (data->workspace_manager, "workspace-group-destroyed",
+ G_CALLBACK (on_workspace_group_destroyed), data);
+
+ g_signal_connect (data->workspace_manager, "workspace-created",
+ G_CALLBACK (on_workspace_created), data);
+ g_signal_connect (data->workspace_manager, "workspace-destroyed",
+ G_CALLBACK (on_workspace_destroyed), data);
+
+ connect_group_signals (data);
+ rebuild_ui (data);
+
+ return data->grid;
}
static WaylandWorkspaceData *
@@ -603,9 +406,7 @@ wayland_workspace_set_orientation (GtkWidget *pager_widget, GtkOrientation orien
return;
data->orientation = orientation;
-
- if (data->grid)
- rebuild_ui (data);
+ rebuild_ui (data);
}
void
@@ -620,9 +421,7 @@ wayland_workspace_set_rows (GtkWidget *pager_widget, int n_rows)
return;
data->n_rows = n_rows;
-
- if (data->grid)
- rebuild_ui (data);
+ rebuild_ui (data);
}
void
@@ -635,9 +434,7 @@ wayland_workspace_set_show_all (GtkWidget *pager_widget, gboolean show_all)
return;
data->display_all = show_all;
-
- if (data->grid)
- rebuild_ui (data);
+ rebuild_ui (data);
}
void
@@ -650,49 +447,80 @@ wayland_workspace_set_show_names (GtkWidget *pager_widget, gboolean show_names)
return;
data->display_names = show_names;
-
- if (data->grid)
- rebuild_ui (data);
+ rebuild_ui (data);
}
int
wayland_workspace_get_count (GtkWidget *pager_widget)
{
WaylandWorkspaceData *data = pager_widget_get_data (pager_widget);
- int count = 0;
- GList *l;
g_return_val_if_fail (data, 0);
- for (l = data->workspace_groups; l != NULL; l = l->next)
+ return g_list_length (xfw_workspace_manager_list_workspaces (data->workspace_manager));
+}
+
+const char *
+wayland_workspace_get_name (GtkWidget *pager_widget, int index)
+{
+ WaylandWorkspaceData *data = pager_widget_get_data (pager_widget);
+ XfwWorkspace *ws;
+
+ g_return_val_if_fail (data, "workspace");
+
+ ws = get_nth_workspace (data, index);
+ if (ws)
{
- WaylandWorkspaceGroup *group = l->data;
- count += g_list_length (group->workspaces);
+ const char *name = xfw_workspace_get_name (ws);
+ if (name && name[0] != '\0')
+ return name;
+ return xfw_workspace_get_id (ws);
}
- return count;
+ return "workspace";
}
-const char *
-wayland_workspace_get_name (GtkWidget *pager_widget, int index)
+int
+wayland_workspace_get_active_index (GtkWidget *pager_widget)
{
WaylandWorkspaceData *data = pager_widget_get_data (pager_widget);
+ GList *workspaces, *l;
int i = 0;
- GList *l, *wl;
- g_return_val_if_fail (data, "workspace");
+ g_return_val_if_fail (data, 0);
- for (l = data->workspace_groups; l != NULL; l = l->next)
+ workspaces = xfw_workspace_manager_list_workspaces (data->workspace_manager);
+
+ for (l = workspaces; l != NULL; l = l->next)
{
- WaylandWorkspaceGroup *group = l->data;
- for (wl = group->workspaces; wl != NULL; wl = wl->next)
+ XfwWorkspace *ws = l->data;
+ XfwWorkspaceState state = xfw_workspace_get_state (ws);
+
+ if (state & XFW_WORKSPACE_STATE_ACTIVE)
+ return i;
+ i++;
+ }
+
+ return 0;
+}
+
+void
+wayland_workspace_activate_nth (GtkWidget *pager_widget, int index)
+{
+ WaylandWorkspaceData *data = pager_widget_get_data (pager_widget);
+ XfwWorkspace *ws;
+
+ g_return_if_fail (data);
+
+ ws = get_nth_workspace (data, index);
+ if (ws)
+ {
+ GError *error = NULL;
+ if (!xfw_workspace_activate (ws, &error))
{
- WaylandWorkspace *ws = wl->data;
- if (i == index)
- return ws->name ? ws->name : "";
- i++;
+ g_warning ("Failed to activate workspace: %s",
+ error ? error->message : "unknown error");
+ g_clear_error (&error);
}
}
-
- return "workspace";
}
diff --git a/applets/wncklet/wayland-workspace.h b/applets/wncklet/wayland-workspace.h
index 4df1bda1..36d84c47 100644
--- a/applets/wncklet/wayland-workspace.h
+++ b/applets/wncklet/wayland-workspace.h
@@ -41,6 +41,9 @@ void wayland_workspace_set_show_names (GtkWidget *pager_widget,
int wayland_workspace_get_count (GtkWidget *pager_widget);
const char* wayland_workspace_get_name (GtkWidget *pager_widget,
int index);
+int wayland_workspace_get_active_index (GtkWidget *pager_widget);
+void wayland_workspace_activate_nth (GtkWidget *pager_widget,
+ int index);
#ifdef __cplusplus
}
diff --git a/applets/wncklet/workspace-switcher.c b/applets/wncklet/workspace-switcher.c
index 689979a5..93318314 100644
--- a/applets/wncklet/workspace-switcher.c
+++ b/applets/wncklet/workspace-switcher.c
@@ -492,7 +492,6 @@ static void applet_style_updated (MatePanelApplet *applet, GtkStyleContext *cont
provider = gtk_css_provider_new ();
- /* Provide a fallback color for the highlighted workspace based on the current theme */
gtk_style_context_lookup_color (context, "theme_selected_bg_color", &color);
color_str = gdk_rgba_to_string (&color);
bg_css = g_strconcat (".wnck-pager:selected {\n"
@@ -504,7 +503,7 @@ static void applet_style_updated (MatePanelApplet *applet, GtkStyleContext *cont
gtk_style_context_add_provider (context,
GTK_STYLE_PROVIDER (provider),
- GTK_STYLE_PROVIDER_PRIORITY_FALLBACK);
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref (provider);
}
@@ -530,10 +529,84 @@ static gboolean applet_scroll(MatePanelApplet* applet, GdkEventScroll* event, Pa
#ifdef HAVE_WAYLAND
if (pager->is_wayland)
{
- /* The Wayland backend handles its own scroll internally via
- * the scroll event on the workspace widget. We don't need to
- * do anything here since the workspace widget connects its
- * own scroll handler. Just return TRUE to consume the event. */
+ GdkScrollDirection absolute_direction;
+ int index;
+ int n_workspaces;
+ int n_columns;
+ int in_last_row;
+
+ index = wayland_workspace_get_active_index (pager->pager);
+ n_workspaces = wayland_workspace_get_count (pager->pager);
+
+ if (n_workspaces <= 0)
+ return TRUE;
+
+ n_columns = n_workspaces / pager->n_rows;
+ if (n_workspaces % pager->n_rows != 0)
+ n_columns++;
+
+ in_last_row = n_workspaces % n_columns;
+
+ absolute_direction = event->direction;
+
+ if (gtk_widget_get_direction (GTK_WIDGET (applet)) == GTK_TEXT_DIR_RTL)
+ {
+ switch (event->direction)
+ {
+ case GDK_SCROLL_RIGHT:
+ absolute_direction = GDK_SCROLL_LEFT;
+ break;
+ case GDK_SCROLL_LEFT:
+ absolute_direction = GDK_SCROLL_RIGHT;
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (absolute_direction)
+ {
+ case GDK_SCROLL_DOWN:
+ if (index + n_columns < n_workspaces)
+ index += n_columns;
+ else if (pager->wrap_workspaces && index == n_workspaces - 1)
+ index = 0;
+ else if ((index < n_workspaces - 1 && index + in_last_row != n_workspaces - 1) ||
+ (index == n_workspaces - 1 && in_last_row != 0))
+ index = (index % n_columns) + 1;
+ break;
+
+ case GDK_SCROLL_RIGHT:
+ if (index < n_workspaces - 1)
+ index++;
+ else if (pager->wrap_workspaces)
+ index = 0;
+ break;
+
+ case GDK_SCROLL_UP:
+ if (index - n_columns >= 0)
+ index -= n_columns;
+ else if (index > 0)
+ index = ((pager->n_rows - 1) * n_columns) + (index % n_columns) - 1;
+ else if (pager->wrap_workspaces)
+ index = n_workspaces - 1;
+
+ if (index >= n_workspaces)
+ index -= n_columns;
+ break;
+
+ case GDK_SCROLL_LEFT:
+ if (index > 0)
+ index--;
+ else if (pager->wrap_workspaces)
+ index = n_workspaces - 1;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ wayland_workspace_activate_nth (pager->pager, index);
return TRUE;
}
#endif /* HAVE_WAYLAND */
diff --git a/configure.ac b/configure.ac
index 92dd8aae..abec2640 100644
--- a/configure.ac
+++ b/configure.ac
@@ -216,8 +216,13 @@ fi
AM_CONDITIONAL(ENABLE_WAYLAND, [test "x$have_wayland" = "xyes"])
+have_xfw=no
if test "x$have_wayland" = "xyes"; then
AC_DEFINE(HAVE_WAYLAND, 1, [Have the Wayland development library])
+
+ PKG_CHECK_MODULES(XFW, libxfce4windowing-0 >= 4.19.0, have_xfw=yes, [
+ AC_MSG_ERROR([Wayland support requires libxfce4windowing-0 >= 4.19.0])
+ ])
fi
AC_SUBST(WAYLAND_CFLAGS)