summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Samoilov <[email protected]>2026-09-09 08:07:15 -0400
committerLuke from DC <[email protected]>2026-09-10 18:20:55 +0000
commit8db29b3efea6a07060d75842c0a5da1d8742c365 (patch)
tree62accc6cf8572f1a4cc3869b412b3e73241a1386
parent6b27279e0de76222441196affaa95d0b90111c05 (diff)
downloadmate-panel-8db29b3efea6a07060d75842c0a5da1d8742c365.tar.bz2
mate-panel-8db29b3efea6a07060d75842c0a5da1d8742c365.tar.xz
wayland: implement scroll, middle-click close and urgent highlights
-rw-r--r--applets/wncklet/wayland-backend.c146
-rw-r--r--applets/wncklet/wayland-backend.h2
-rw-r--r--applets/wncklet/window-list.c12
3 files changed, 158 insertions, 2 deletions
diff --git a/applets/wncklet/wayland-backend.c b/applets/wncklet/wayland-backend.c
index 4a2d1755..0f7767ef 100644
--- a/applets/wncklet/wayland-backend.c
+++ b/applets/wncklet/wayland-backend.c
@@ -59,6 +59,8 @@ typedef struct
ContextMenu *context_menu;
XfwScreen *screen;
GList *tasks;
+ gboolean scroll_enabled;
+ gboolean middle_click_close;
} TasklistManager;
typedef struct
@@ -74,6 +76,7 @@ typedef struct
gboolean maximized;
gboolean minimized;
gboolean fullscreen;
+ gboolean urgent;
} ToplevelTask;
static int tasklist_invocations = 0;
@@ -89,6 +92,7 @@ static GtkTargetEntry source_targets[] =
static gboolean has_initialized = FALSE;
static ToplevelTask *toplevel_task_new (TasklistManager *tasklist, XfwWindow *window);
+static gboolean tasklist_scroll_event (GtkWidget *widget, GdkEventScroll *event, TasklistManager *tasklist);
static guint buttons, tasklist_width;
@@ -105,10 +109,18 @@ update_task_state (ToplevelTask *task)
task->maximized = (state & XFW_WINDOW_STATE_MAXIMIZED) != 0;
task->minimized = (state & XFW_WINDOW_STATE_MINIMIZED) != 0;
task->fullscreen = (state & XFW_WINDOW_STATE_FULLSCREEN) != 0;
+ task->urgent = (state & XFW_WINDOW_STATE_URGENT) != 0;
if (task->button)
+ {
+ if (task->urgent)
+ gtk_style_context_add_class (gtk_widget_get_style_context (task->button), "urgent");
+ else
+ gtk_style_context_remove_class (gtk_widget_get_style_context (task->button), "urgent");
+
gtk_button_set_relief (GTK_BUTTON (task->button),
task->active ? GTK_RELIEF_NORMAL : GTK_RELIEF_NONE);
+ }
}
static void
@@ -324,6 +336,11 @@ tasklist_manager_new (void)
(GDestroyNotify)tasklist_manager_disconnected_from_widget);
tasklist->context_menu = context_menu_new ();
+ /* mouse scroll to switch windows */
+ gtk_widget_add_events (tasklist->list, GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK);
+ g_signal_connect (tasklist->list, "scroll-event",
+ G_CALLBACK (tasklist_scroll_event), tasklist);
+
/* add all existing windows on this screen */
windows = xfw_screen_get_windows (screen);
for (l = windows; l != NULL; l = l->next)
@@ -589,6 +606,16 @@ toplevel_task_handle_clicked (GtkButton *button, ToplevelTask *task)
static gboolean on_toplevel_button_press (GtkWidget *button, GdkEvent *event, TasklistManager *tasklist)
{
/* Assume event is a button press */
+
+ if (((GdkEventButton*)event)->button == GDK_BUTTON_MIDDLE &&
+ tasklist->middle_click_close)
+ {
+ ToplevelTask *task = g_object_get_data (G_OBJECT (button), toplevel_task_key);
+ if (task && task->window)
+ xfw_window_close (task->window, ((GdkEventButton*)event)->time, NULL);
+ return TRUE;
+ }
+
if (((GdkEventButton*)event)->button == GDK_BUTTON_SECONDARY)
{
ContextMenu *menu = tasklist->context_menu;
@@ -613,6 +640,104 @@ static gboolean on_toplevel_button_press (GtkWidget *button, GdkEvent *event, Ta
}
}
+static gboolean
+tasklist_scroll_event (GtkWidget *widget, GdkEventScroll *event, TasklistManager *tasklist)
+{
+ ToplevelTask *child;
+ GList *li, *lnew = NULL;
+ GdkScrollDirection direction;
+ gboolean wrap_windows = TRUE;
+
+ if (!tasklist->scroll_enabled)
+ return TRUE;
+
+ /* get the current active window button */
+ for (li = tasklist->tasks; li != NULL; li = li->next)
+ {
+ child = li->data;
+ if (child->window && xfw_window_is_active (child->window))
+ break;
+ }
+
+ if (li == NULL)
+ return TRUE;
+
+ if (event->direction != GDK_SCROLL_SMOOTH)
+ direction = event->direction;
+ else if (event->delta_y < 0)
+ direction = GDK_SCROLL_UP;
+ else if (event->delta_y > 0)
+ direction = GDK_SCROLL_DOWN;
+ else if (event->delta_x < 0)
+ direction = GDK_SCROLL_LEFT;
+ else if (event->delta_x > 0)
+ direction = GDK_SCROLL_RIGHT;
+ else
+ return TRUE;
+
+ switch (direction)
+ {
+ case GDK_SCROLL_UP:
+ /* find the previous button on the tasklist */
+ for (lnew = g_list_previous (li);; lnew = lnew->prev)
+ {
+ if (lnew == NULL)
+ {
+ if (wrap_windows)
+ {
+ lnew = g_list_last (li);
+ wrap_windows = FALSE;
+ if (lnew == NULL)
+ break;
+ }
+ else
+ break;
+ }
+
+ child = lnew->data;
+ if (child->window != NULL)
+ break;
+ }
+ break;
+
+ case GDK_SCROLL_DOWN:
+ /* find the next button on the tasklist */
+ for (lnew = g_list_next (li);; lnew = lnew->next)
+ {
+ if (lnew == NULL)
+ {
+ if (wrap_windows)
+ {
+ lnew = g_list_first (li);
+ wrap_windows = FALSE;
+ if (lnew == NULL)
+ break;
+ }
+ else
+ break;
+ }
+
+ child = lnew->data;
+ if (child->window != NULL)
+ break;
+ }
+ break;
+
+ case GDK_SCROLL_LEFT:
+ case GDK_SCROLL_RIGHT:
+ default:
+ return TRUE;
+ }
+
+ if (lnew != NULL)
+ {
+ child = lnew->data;
+ xfw_window_activate (child->window, NULL, event->time, NULL);
+ }
+
+ return TRUE;
+}
+
static ToplevelTask *
toplevel_task_new (TasklistManager *tasklist, XfwWindow *window)
{
@@ -657,6 +782,11 @@ toplevel_task_new (TasklistManager *tasklist, XfwWindow *window)
G_CALLBACK (on_toplevel_button_press),
tasklist);
+ /* mouse scroll to switch windows */
+ gtk_widget_add_events (task->button, GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK);
+ g_signal_connect (task->button, "scroll-event",
+ G_CALLBACK (tasklist_scroll_event), tasklist);
+
/* drag-and-drop to reorder task buttons */
gtk_drag_source_set (task->button, GDK_BUTTON1_MASK,
source_targets, G_N_ELEMENTS (source_targets),
@@ -810,3 +940,19 @@ wayland_tasklist_set_orientation (GtkWidget* tasklist_widget, GtkOrientation ori
gtk_orientable_set_orientation (GTK_ORIENTABLE (tasklist->list), orient);
gtk_orientable_set_orientation (GTK_ORIENTABLE (tasklist->outer_box), orient);
}
+
+void
+wayland_tasklist_set_middle_click_close (GtkWidget *tasklist_widget, gboolean enabled)
+{
+ TasklistManager *tasklist = tasklist_widget_get_tasklist (tasklist_widget);
+ g_return_if_fail (tasklist);
+ tasklist->middle_click_close = enabled;
+}
+
+void
+wayland_tasklist_set_scroll_enabled (GtkWidget *tasklist_widget, gboolean enabled)
+{
+ TasklistManager *tasklist = tasklist_widget_get_tasklist (tasklist_widget);
+ g_return_if_fail (tasklist);
+ tasklist->scroll_enabled = enabled;
+}
diff --git a/applets/wncklet/wayland-backend.h b/applets/wncklet/wayland-backend.h
index e2402236..38cadf7c 100644
--- a/applets/wncklet/wayland-backend.h
+++ b/applets/wncklet/wayland-backend.h
@@ -37,6 +37,8 @@ extern "C" {
GtkWidget* wayland_tasklist_new (void);
void wayland_tasklist_set_orientation (GtkWidget* tasklist_widget, GtkOrientation orient);
+void wayland_tasklist_set_middle_click_close (GtkWidget* tasklist_widget, gboolean enabled);
+void wayland_tasklist_set_scroll_enabled (GtkWidget* tasklist_widget, gboolean enabled);
#ifdef __cplusplus
}
diff --git a/applets/wncklet/window-list.c b/applets/wncklet/window-list.c
index d7e9f438..c7fd152e 100644
--- a/applets/wncklet/window-list.c
+++ b/applets/wncklet/window-list.c
@@ -144,7 +144,13 @@ static void tasklist_update(TasklistData* tasklist)
}
#endif /* HAVE_X11 */
- /* Not implemented for Wayland */
+#ifdef HAVE_WAYLAND
+ if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default()))
+ {
+ wayland_tasklist_set_scroll_enabled (tasklist->tasklist, tasklist->scroll_enable);
+ wayland_tasklist_set_middle_click_close (tasklist->tasklist, tasklist->middle_click_close);
+ }
+#endif /* HAVE_WAYLAND */
}
static void tasklist_apply_orientation(TasklistData* tasklist)
@@ -848,7 +854,9 @@ gboolean window_list_applet_fill(MatePanelApplet* applet)
".mate-panel-menu-bar button,\n"
" #tasklist-button {\n"
" padding: 0px;\n"
- " margin: 0px;\n }",
+ " margin: 0px;\n }\n"
+ " #tasklist-button.urgent {\n"
+ " font-weight: bold;\n }",
-1, NULL);
gtk_style_context_add_provider_for_screen (gtk_widget_get_screen (tasklist->applet),
GTK_STYLE_PROVIDER (provider),