diff options
Diffstat (limited to 'applets/wncklet')
-rw-r--r-- | applets/wncklet/Makefile.am | 4 | ||||
-rw-r--r-- | applets/wncklet/org.mate.panel.applet.window-list.gschema.xml.in | 10 | ||||
-rw-r--r-- | applets/wncklet/showdesktop.c | 68 | ||||
-rw-r--r-- | applets/wncklet/showdesktop.h | 1 | ||||
-rw-r--r-- | applets/wncklet/wayland-backend.c | 400 | ||||
-rw-r--r-- | applets/wncklet/wayland-backend.h | 2 | ||||
-rw-r--r-- | applets/wncklet/window-list.c | 421 | ||||
-rw-r--r-- | applets/wncklet/window-list.ui | 602 | ||||
-rw-r--r-- | applets/wncklet/window-menu.c | 36 | ||||
-rw-r--r-- | applets/wncklet/wncklet.c | 1 | ||||
-rw-r--r-- | applets/wncklet/workspace-switcher.c | 276 |
11 files changed, 1331 insertions, 490 deletions
diff --git a/applets/wncklet/Makefile.am b/applets/wncklet/Makefile.am index 38dfaca5..14f8a5c7 100644 --- a/applets/wncklet/Makefile.am +++ b/applets/wncklet/Makefile.am @@ -1,3 +1,5 @@ +AUTOMAKE_OPTIONS = subdir-objects + AM_CPPFLAGS = \ $(LIBMATE_PANEL_APPLET_CFLAGS) \ $(WNCKLET_CFLAGS) \ @@ -76,9 +78,9 @@ $(applet_in_files): $(applet_in_files).in Makefile $(applet_DATA): $(applet_in_files) $(AM_V_GEN) $(MSGFMT) --desktop --keyword= --keyword=Name --keyword=Description --template $< -d $(top_srcdir)/po -o $@ +service_in_files = org.mate.panel.applet.WnckletFactory.service.in if !WNCKLET_INPROCESS servicedir = $(datadir)/dbus-1/services -service_in_files = org.mate.panel.applet.WnckletFactory.service.in service_DATA = $(service_in_files:.service.in=.service) org.mate.panel.applet.WnckletFactory.service: $(service_in_files) diff --git a/applets/wncklet/org.mate.panel.applet.window-list.gschema.xml.in b/applets/wncklet/org.mate.panel.applet.window-list.gschema.xml.in index 0f2d871d..93f32b46 100644 --- a/applets/wncklet/org.mate.panel.applet.window-list.gschema.xml.in +++ b/applets/wncklet/org.mate.panel.applet.window-list.gschema.xml.in @@ -20,5 +20,15 @@ <summary>Move windows to current workspace when unminimized</summary> <description>If true, then when unminimizing a window, move it to the current workspace. Otherwise, switch to the workspace of the window.</description> </key> + <key name="scroll-enabled" type="b"> + <default>true</default> + <summary>Whether to enable mouse scrolling in the switch window list</summary> + <description>If true, enable mouse scrolling in window list, otherwise disable mouse scrolling in window list.</description> + </key> + <key name="middle-click-close" type="b"> + <default>true</default> + <summary>Close window on middle mouse click</summary> + <description>If true, then clicking the middle mouse button over a taskbar item will close the window.</description> + </key> </schema> </schemalist> diff --git a/applets/wncklet/showdesktop.c b/applets/wncklet/showdesktop.c index c3454a0f..190077f1 100644 --- a/applets/wncklet/showdesktop.c +++ b/applets/wncklet/showdesktop.c @@ -22,7 +22,7 @@ */ #ifdef HAVE_CONFIG_H - #include <config.h> +#include <config.h> #endif #include <glib/gi18n.h> @@ -43,7 +43,6 @@ #define TIMEOUT_ACTIVATE_SECONDS 1 #define SHOW_DESKTOP_ICON "user-desktop" - typedef struct { /* widgets */ GtkWidget* applet; @@ -316,7 +315,7 @@ static gboolean do_not_eat_button_press(GtkWidget* widget, GdkEventButton* event { if (event->button != 1) { - g_signal_stop_emission_by_name(widget, "button_press_event"); + g_signal_stop_emission_by_name(widget, "button-press-event"); } return FALSE; @@ -371,15 +370,20 @@ static void show_desktop_applet_realized(MatePanelApplet* applet, gpointer data) #ifdef HAVE_X11 if (GDK_IS_X11_DISPLAY (gdk_display_get_default ())) - sdd->wnck_screen = wnck_screen_get(gdk_x11_screen_get_screen_number (screen)); + { + sdd->wnck_screen = wnck_screen_get (gdk_x11_screen_get_screen_number (screen)); + if (sdd->wnck_screen != NULL) + wncklet_connect_while_alive (sdd->wnck_screen, + "showing_desktop_changed", + G_CALLBACK (show_desktop_changed_callback), + sdd, + sdd->applet); + else + g_warning ("Could not get WnckScreen!"); + } #endif /* HAVE_X11 */ - if (sdd->wnck_screen != NULL) - wncklet_connect_while_alive(sdd->wnck_screen, "showing_desktop_changed", G_CALLBACK(show_desktop_changed_callback), sdd, sdd->applet); - else - g_warning("Could not get WnckScreen!"); - - show_desktop_changed_callback(sdd->wnck_screen, sdd); + show_desktop_changed_callback (sdd->wnck_screen, sdd); sdd->icon_theme = gtk_icon_theme_get_for_screen (screen); wncklet_connect_while_alive(sdd->icon_theme, "changed", G_CALLBACK(theme_changed_callback), sdd, sdd->applet); @@ -422,7 +426,9 @@ gboolean show_desktop_applet_fill(MatePanelApplet* applet) sdd->size = mate_panel_applet_get_size(MATE_PANEL_APPLET(sdd->applet)); - g_signal_connect(G_OBJECT(sdd->applet), "realize", G_CALLBACK(show_desktop_applet_realized), sdd); + g_signal_connect (sdd->applet, "realize", + G_CALLBACK (show_desktop_applet_realized), + sdd); sdd->button = gtk_toggle_button_new (); @@ -442,23 +448,29 @@ gboolean show_desktop_applet_fill(MatePanelApplet* applet) atk_obj = gtk_widget_get_accessible(sdd->button); atk_object_set_name (atk_obj, _("Show Desktop Button")); - g_signal_connect(G_OBJECT(sdd->button), "button_press_event", G_CALLBACK(do_not_eat_button_press), NULL); + g_signal_connect (sdd->button, "button-press-event", + G_CALLBACK(do_not_eat_button_press), + NULL); - g_signal_connect(G_OBJECT(sdd->button), "toggled", G_CALLBACK(button_toggled_callback), sdd); + g_signal_connect (sdd->button, "toggled", + G_CALLBACK (button_toggled_callback), + sdd); gtk_container_set_border_width(GTK_CONTAINER(sdd->button), 0); gtk_container_add(GTK_CONTAINER(sdd->button), sdd->image); gtk_container_add(GTK_CONTAINER(sdd->applet), sdd->button); - g_signal_connect (G_OBJECT(sdd->button), "size_allocate", G_CALLBACK(button_size_allocated), sdd); + g_signal_connect (sdd->button, "size-allocate", + G_CALLBACK (button_size_allocated), + sdd); /* FIXME: Update this comment. */ /* we have to bind change_orient before we do applet_widget_add since we need to get an initial change_orient signal to set our initial oriantation, and we get that during the _add call */ - g_signal_connect(G_OBJECT (sdd->applet), "change_orient", G_CALLBACK (applet_change_orient), sdd); - - mate_panel_applet_set_background_widget(MATE_PANEL_APPLET (sdd->applet), GTK_WIDGET(sdd->applet)); + g_signal_connect (sdd->applet, "change-orient", + G_CALLBACK (applet_change_orient), + sdd); action_group = gtk_action_group_new("ShowDesktop Applet Actions"); gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE); @@ -468,12 +480,18 @@ gboolean show_desktop_applet_fill(MatePanelApplet* applet) action_group); g_object_unref(action_group); - g_signal_connect(G_OBJECT(sdd->applet), "destroy", G_CALLBACK(applet_destroyed), sdd); + g_signal_connect (sdd->applet, "destroy", + G_CALLBACK (applet_destroyed), + sdd); gtk_drag_dest_set(GTK_WIDGET(sdd->button), 0, NULL, 0, 0); - g_signal_connect(G_OBJECT(sdd->button), "drag_motion", G_CALLBACK (button_drag_motion), sdd); - g_signal_connect(G_OBJECT(sdd->button), "drag_leave", G_CALLBACK (button_drag_leave), sdd); + g_signal_connect (sdd->button, "drag-motion", + G_CALLBACK (button_drag_motion), + sdd); + g_signal_connect (sdd->button, "drag-leave", + G_CALLBACK (button_drag_leave), + sdd); gtk_widget_show_all(sdd->applet); @@ -506,13 +524,13 @@ static void display_about_dialog(GtkAction* action, ShowDesktopData* sdd) "comments", _("This button lets you hide all windows and show the desktop."), "copyright", _("Copyright \xc2\xa9 2002 Red Hat, Inc.\n" "Copyright \xc2\xa9 2011 Perberos\n" - "Copyright \xc2\xa9 2012-2020 MATE developers"), + "Copyright \xc2\xa9 2012-2021 MATE developers"), "documenters", documenters, "icon-name", SHOW_DESKTOP_ICON, "logo-icon-name", SHOW_DESKTOP_ICON, "translator-credits", _("translator-credits"), "version", VERSION, - "website", "http://www.mate-desktop.org/", + "website", PACKAGE_URL, NULL); } @@ -554,7 +572,9 @@ static void button_toggled_callback(GtkWidget* button, ShowDesktopData* sdd) g_object_add_weak_pointer(G_OBJECT(dialog), (gpointer) &dialog); - g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), NULL); + g_signal_connect (dialog, "response", + G_CALLBACK(gtk_widget_destroy), + NULL); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); gtk_window_set_screen(GTK_WINDOW(dialog), gtk_widget_get_screen(button)); @@ -575,7 +595,7 @@ static void show_desktop_changed_callback(WnckScreen* screen, ShowDesktopData* s { #ifdef HAVE_X11 if (sdd->wnck_screen != NULL) - sdd->showing_desktop = wnck_screen_get_showing_desktop(sdd->wnck_screen); + sdd->showing_desktop = (wnck_screen_get_showing_desktop(sdd->wnck_screen) != FALSE); #endif /* HAVE_X11 */ update_button_state (sdd); diff --git a/applets/wncklet/showdesktop.h b/applets/wncklet/showdesktop.h index e82ed713..7aa7e60d 100644 --- a/applets/wncklet/showdesktop.h +++ b/applets/wncklet/showdesktop.h @@ -39,4 +39,3 @@ gboolean show_desktop_applet_fill(MatePanelApplet* applet); #endif - diff --git a/applets/wncklet/wayland-backend.c b/applets/wncklet/wayland-backend.c index 658eb6d3..f10b2d65 100644 --- a/applets/wncklet/wayland-backend.c +++ b/applets/wncklet/wayland-backend.c @@ -26,25 +26,45 @@ #endif #include <gdk/gdkwayland.h> +#include <gio/gdesktopappinfo.h> #include "wayland-backend.h" #include "wayland-protocol/wlr-foreign-toplevel-management-unstable-v1-client.h" -static const int window_button_width = 140; +/*shorter than wnck-tasklist due to common use of larger fonts*/ +#define TASKLIST_TEXT_MAX_WIDTH 16 + +/*In the future this could be changable from the panel-prefs dialog*/ +static const int max_button_width = 180; +static const int icon_size = 16; + +typedef struct +{ + GtkWidget *menu; + GtkWidget *maximize; + GtkWidget *minimize; + GtkWidget *on_top; + GtkWidget *close; +} ContextMenu; typedef struct { GtkWidget *list; GtkWidget *outer_box; + ContextMenu *context_menu; struct zwlr_foreign_toplevel_manager_v1 *manager; } TasklistManager; typedef struct { GtkWidget *button; + GtkWidget *icon; GtkWidget *label; struct zwlr_foreign_toplevel_handle_v1 *toplevel; gboolean active; + gboolean maximized; + gboolean minimized; + gboolean fullscreen; } ToplevelTask; static const char *tasklist_manager_key = "tasklist_manager"; @@ -55,9 +75,10 @@ static struct wl_registry *wl_registry_global = NULL; static uint32_t foreign_toplevel_manager_global_id = 0; static uint32_t foreign_toplevel_manager_global_version = 0; -static TasklistManager *tasklist_manager_new (); static ToplevelTask *toplevel_task_new (TasklistManager *tasklist, struct zwlr_foreign_toplevel_handle_v1 *handle); +guint buttons, tasklist_width; + static void wl_registry_handle_global (void *_data, struct wl_registry *registry, @@ -92,7 +113,7 @@ static const struct wl_registry_listener wl_registry_listener = { }; static void -wayland_tasklist_init_if_needed () +wayland_tasklist_init_if_needed (void) { if (has_initialized) return; @@ -120,7 +141,7 @@ foreign_toplevel_manager_handle_toplevel (void *data, { TasklistManager *tasklist = data; ToplevelTask *task = toplevel_task_new (tasklist, toplevel); - gtk_box_pack_start (GTK_BOX (tasklist->list), task->button, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (tasklist->list), task->button, TRUE, TRUE, 0); } static void @@ -162,16 +183,84 @@ tasklist_manager_disconnected_from_widget (TasklistManager *tasklist) if (tasklist->manager) zwlr_foreign_toplevel_manager_v1_stop (tasklist->manager); + + if (tasklist->context_menu) + { + gtk_widget_destroy (tasklist->context_menu->menu); + g_free (tasklist->context_menu); + tasklist->context_menu = NULL; + } +} + +static void +menu_on_maximize (GtkMenuItem *item, gpointer user_data) +{ + ToplevelTask *task = g_object_get_data (G_OBJECT (item), toplevel_task_key); + if (task->toplevel) { + if (task->maximized) { + zwlr_foreign_toplevel_handle_v1_unset_maximized (task->toplevel); + } else { + zwlr_foreign_toplevel_handle_v1_set_maximized (task->toplevel); + } + } +} + +static void +menu_on_minimize (GtkMenuItem *item, gpointer user_data) +{ + ToplevelTask *task = g_object_get_data (G_OBJECT (item), toplevel_task_key); + if (task->toplevel) { + if (task->minimized) { + zwlr_foreign_toplevel_handle_v1_unset_minimized (task->toplevel); + } else { + zwlr_foreign_toplevel_handle_v1_set_minimized (task->toplevel); + } + } +} + +static void +menu_on_close (GtkMenuItem *item, gpointer user_data) +{ + ToplevelTask *task = g_object_get_data (G_OBJECT (item), toplevel_task_key); + if (task->toplevel) { + zwlr_foreign_toplevel_handle_v1_close (task->toplevel); + } +} + +static ContextMenu * +context_menu_new () +{ + ContextMenu *menu = g_new0 (ContextMenu, 1); + menu->menu = gtk_menu_new (); + menu->maximize = gtk_menu_item_new (); + menu->minimize = gtk_menu_item_new (); + menu->on_top = gtk_check_menu_item_new_with_label ("Always On Top"); + menu->close = gtk_menu_item_new_with_label ("Close"); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), menu->maximize); + gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), menu->minimize); + gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), gtk_separator_menu_item_new ()); + gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), menu->on_top); + gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), gtk_separator_menu_item_new ()); + gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), menu->close); + + gtk_widget_show_all (menu->menu); + + g_signal_connect (menu->maximize, "activate", G_CALLBACK (menu_on_maximize), NULL); + g_signal_connect (menu->minimize, "activate", G_CALLBACK (menu_on_minimize), NULL); + g_signal_connect (menu->close, "activate", G_CALLBACK (menu_on_close), NULL); + gtk_widget_set_sensitive (menu->on_top, FALSE); + return menu; } static TasklistManager * -tasklist_manager_new () +tasklist_manager_new (void) { if (!foreign_toplevel_manager_global_id) return NULL; TasklistManager *tasklist = g_new0 (TasklistManager, 1); - tasklist->list = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + tasklist->list = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_set_homogeneous (GTK_BOX (tasklist->list), TRUE); tasklist->outer_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start (GTK_BOX (tasklist->outer_box), tasklist->list, FALSE, FALSE, 0); @@ -187,6 +276,7 @@ tasklist_manager_new () tasklist_manager_key, tasklist, (GDestroyNotify)tasklist_manager_disconnected_from_widget); + tasklist->context_menu = context_menu_new (); return tasklist; } @@ -208,7 +298,27 @@ foreign_toplevel_handle_app_id (void *data, struct zwlr_foreign_toplevel_handle_v1 *toplevel, const char *app_id) { - /* ignore */ + ToplevelTask *task = data; + + gchar *app_id_lower = g_utf8_strdown (app_id, -1); + gchar *desktop_app_id = g_strdup_printf ("%s.desktop", app_id_lower); + GDesktopAppInfo *app_info = g_desktop_app_info_new (desktop_app_id); + + if (app_info) { + GIcon *icon = g_app_info_get_icon (G_APP_INFO (app_info)); + if (icon) { + gtk_image_set_from_gicon (GTK_IMAGE (task->icon), icon, GTK_ICON_SIZE_MENU); + goto cleanup; + } + } + gtk_image_set_from_icon_name (GTK_IMAGE (task->icon), app_id_lower, GTK_ICON_SIZE_MENU); + +cleanup: + if (app_info) { + g_object_unref (G_OBJECT (app_info)); + } + g_free (app_id_lower); + g_free (desktop_app_id); } static void @@ -235,6 +345,9 @@ foreign_toplevel_handle_state (void *data, ToplevelTask *task = data; task->active = FALSE; + task->maximized = FALSE; + task->minimized = FALSE; + task->fullscreen = FALSE; enum zwlr_foreign_toplevel_handle_v1_state *i; wl_array_for_each (i, state) @@ -244,7 +357,15 @@ foreign_toplevel_handle_state (void *data, case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED: task->active = TRUE; break; - + case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED: + task->maximized = TRUE; + break; + case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED: + task->minimized = TRUE; + break; + case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN: + task->fullscreen = TRUE; + break; default: break; } @@ -265,10 +386,87 @@ foreign_toplevel_handle_closed (void *data, struct zwlr_foreign_toplevel_handle_v1 *toplevel) { ToplevelTask *task = data; + if (task->button) + { + GtkOrientation orient; + GtkWidget *button; + GtkWidget *box; + GtkWidget *outer_box = gtk_widget_get_parent (GTK_WIDGET (task->button)); gtk_widget_destroy (task->button); -} + buttons = buttons -1; + + if (buttons == 0) + return; + /* We don't need to modify button size on a vertical panel*/ + orient = gtk_orientable_get_orientation (GTK_ORIENTABLE (outer_box)); + if (orient == GTK_ORIENTATION_VERTICAL) + return; + + /* Horizontal panel: if buttons can now fit + * with both labels and icons show them + */ + if (tasklist_width / buttons > icon_size * 3) + { + GList* children = gtk_container_get_children (GTK_CONTAINER (outer_box)); + while (children != NULL) + { + button = GTK_WIDGET (children->data); + + /* If maximum width buttons fix, expand to that dimension*/ + if (buttons * max_button_width < tasklist_width) + gtk_widget_set_size_request (button, max_button_width, -1); + + /* Otherwise expand remaining buttons to fill the tasklist*/ + else + gtk_widget_set_size_request (button, tasklist_width / buttons, -1); + + gtk_widget_show_all (button); + children = children->next; + } + } + /* If buttons with icons will fit, bring them back*/ + else if (tasklist_width / buttons > icon_size * 2) + { + GtkWidget *widget; + GList* children = gtk_container_get_children (GTK_CONTAINER (outer_box)); + while (children != NULL) + { + button = GTK_WIDGET (children->data); + box = gtk_bin_get_child (GTK_BIN (button)); + GList* contents = gtk_container_get_children (GTK_CONTAINER (box)); + while (contents != NULL) + { + widget = GTK_WIDGET (contents->data); + if (GTK_IS_LABEL (widget)) + gtk_widget_hide (widget); + + if (GTK_IS_IMAGE (widget)) + gtk_widget_show (widget); + + contents = contents->next; + gtk_widget_show (box); + gtk_widget_show (button); + } + + children = children->next; + gtk_widget_set_size_request (button, tasklist_width / buttons, -1); + } + } + /* If we still cannot fit labels or icons, just fill the available space*/ + else + { + GList* children = gtk_container_get_children (GTK_CONTAINER (outer_box)); + while (children != NULL) + { + button = GTK_WIDGET (children->data); + gtk_widget_set_size_request (button, tasklist_width / buttons, -1); + children = children->next; + } + } + } +} static const struct zwlr_foreign_toplevel_handle_v1_listener foreign_toplevel_handle_listener = { .title = foreign_toplevel_handle_title, @@ -286,6 +484,7 @@ toplevel_task_disconnected_from_widget (ToplevelTask *task) struct zwlr_foreign_toplevel_handle_v1 *toplevel = task->toplevel; task->button = NULL; + task->icon = NULL; task->label = NULL; task->toplevel = NULL; @@ -314,13 +513,25 @@ toplevel_task_handle_clicked (GtkButton *button, ToplevelTask *task) } } -static gboolean on_toplevel_button_press (GtkWidget *widget, GdkEvent *event, gpointer user_data) +static gboolean on_toplevel_button_press (GtkWidget *button, GdkEvent *event, TasklistManager *tasklist) { /* Assume event is a button press */ if (((GdkEventButton*)event)->button == GDK_BUTTON_SECONDARY) { - /* Returning true for secondary clicks suppresses the applet's default context menu, - * which we do not want to show up for task buttons */ + ContextMenu *menu = tasklist->context_menu; + ToplevelTask *task = g_object_get_data (G_OBJECT (button), toplevel_task_key); + + g_object_set_data (G_OBJECT (menu->maximize), toplevel_task_key, task); + g_object_set_data (G_OBJECT (menu->minimize), toplevel_task_key, task); + g_object_set_data (G_OBJECT (menu->close), toplevel_task_key, task); + + gtk_menu_item_set_label (GTK_MENU_ITEM (menu->minimize), + task->minimized ? "Unminimize" : "Minimize"); + gtk_menu_item_set_label (GTK_MENU_ITEM (menu->maximize), + task->maximized ? "Unmaximize" : "Maximize"); + + gtk_menu_popup_at_widget (GTK_MENU (menu->menu), button, + GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_SOUTH_WEST, event); return TRUE; } else @@ -333,18 +544,172 @@ static ToplevelTask * toplevel_task_new (TasklistManager *tasklist, struct zwlr_foreign_toplevel_handle_v1 *toplevel) { ToplevelTask *task = g_new0 (ToplevelTask, 1); + GtkWidget *button; + GtkOrientation orient; + buttons = buttons + 1; + orient = gtk_orientable_get_orientation (GTK_ORIENTABLE (tasklist->outer_box)); task->button = gtk_button_new (); g_signal_connect (task->button, "clicked", G_CALLBACK (toplevel_task_handle_clicked), task); + task->icon = gtk_image_new_from_icon_name ("unknown", icon_size); + task->label = gtk_label_new (""); - gtk_label_set_max_width_chars (GTK_LABEL (task->label), 1); - gtk_widget_set_size_request (task->label, window_button_width, -1); + gtk_label_set_max_width_chars (GTK_LABEL (task->label), TASKLIST_TEXT_MAX_WIDTH); gtk_label_set_ellipsize (GTK_LABEL (task->label), PANGO_ELLIPSIZE_END); - gtk_container_add (GTK_CONTAINER(task->button), task->label); + gtk_label_set_xalign (GTK_LABEL (task->label), 0.0); + + GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start (GTK_BOX (box), task->icon, FALSE, FALSE, 6); + gtk_box_pack_start (GTK_BOX (box), task->label, TRUE, TRUE, 2); + gtk_container_add (GTK_CONTAINER (task->button), box); + gtk_widget_set_name (task->button , "tasklist-button"); gtk_widget_show_all (task->button); + /* Buttons on a vertical panel are not affected by how many are needed + * GTK handles compressing contents as needed as the window width tells + * GTK how much space to allocate the label and icon. Buttons will use + * the full width of a vertical panel without any special attention + * so break out here instead of breaking the vertical panel case + */ + + if (orient == GTK_ORIENTATION_VERTICAL) + { + gtk_widget_show_all (task->button); + task->toplevel = toplevel; + zwlr_foreign_toplevel_handle_v1_add_listener (toplevel, + &foreign_toplevel_handle_listener, + task); + g_object_set_data_full (G_OBJECT (task->button), + toplevel_task_key, + task, + (GDestroyNotify)toplevel_task_disconnected_from_widget); + + g_signal_connect (task->button, "button-press-event", + G_CALLBACK (on_toplevel_button_press), + tasklist); + + return task; + } + + /* On horizontal panels, GTK does not by default limit the width of the tasklist + * as it does not run out of space in the window until the entire panel is used, + * leaving buttons at full width until then and overflowing all other applets + * + * Thus we must get the tasklist's allocated width when extra space remains, + * which will be most of the distance between the handle and the next applet + * From there, we can expand buttons and/or hide elements as needed + */ + + + tasklist_width = gtk_widget_get_allocated_width (GTK_WIDGET (tasklist->outer_box)); + + /* First button can be buggy with this so hardcode it to expand to the limit */ + if (buttons == 1) + gtk_widget_set_size_request (task->button, max_button_width, -1); + + /* if the number of buttons forces width to less than 3x the icon size, shrink them */ + if ((buttons != 0) && (tasklist_width > 1 )&& (tasklist_width / buttons < (icon_size * 3))) + { + /* adjust the current button first or it can be missed */ + if (tasklist_width / buttons > icon_size * 2) + { + gtk_widget_hide (task->label); + gtk_widget_show (task->icon); + } + else + { + gtk_widget_show (task->label); + gtk_widget_hide (task->icon); + } + gtk_widget_show (box); + gtk_widget_show (task->button); + + /* iterate over all the buttons, first hide labels + * then hide icons and bring back labels + */ + GtkWidget *widget; + + GList* children = gtk_container_get_children (GTK_CONTAINER (tasklist->list)); + while (children != NULL) + { + button = GTK_WIDGET (children->data); + box = gtk_bin_get_child (GTK_BIN (button)); + + /* hide labels of all buttons but show icons if only icons will fit */ + if (tasklist_width / buttons > icon_size * 2) + { + /* find the icon and the label, show just the icon */ + GList* contents = gtk_container_get_children (GTK_CONTAINER (box)); + + while (contents != NULL) + { + widget = GTK_WIDGET (contents->data); + if (GTK_IS_LABEL (widget)) + gtk_widget_hide (widget); + + if (GTK_IS_IMAGE (widget)) + gtk_widget_show (widget); + + contents = contents->next; + } + } + else + { + /* find the icon and the label, show just the label as it is more + * compressable than the icon. Though less meaningful at this size, + * it is enough to keep the tasklist from disappearing on themes + * that do not set borders around tasklist buttons. + * This is same behavior as on x11 save that an extreme number of + * buttons (50+ on 700px of space) can still overflow + */ + + GList* contents = gtk_container_get_children (GTK_CONTAINER (box)); + while (contents != NULL) + { + widget = GTK_WIDGET (contents->data); + if (GTK_IS_LABEL (widget)) + gtk_widget_show (widget); + + if (GTK_IS_IMAGE (widget)) + gtk_widget_hide (widget); + + contents = contents->next; + } + } + /*expand buttons with labels or everything hidden to fit remaining space*/ + gtk_widget_set_size_request (button, tasklist_width / buttons, -1); + /*show the button and any contents that fit, then get the next button*/ + gtk_widget_show (box); + gtk_widget_show (button); + + children = children->next; + } + } + else + { + GList* children = gtk_container_get_children (GTK_CONTAINER(tasklist->list)); + while (children != NULL) + { + button = GTK_WIDGET (children->data); + if (((buttons ) * max_button_width < tasklist_width) || (buttons == 1)) + + /*Don't let buttons expand over the maximum button size*/ + gtk_widget_set_size_request (button, max_button_width, -1); + + else + /*if full width buttons won't fit, size them to just fill the tasklist*/ + gtk_widget_set_size_request (button, tasklist_width / buttons, -1); + + children = children->next; + } + gtk_widget_show_all (task->button); + } + + /*Reset the tasklist width after button adjustments*/ + tasklist_width = gtk_widget_get_allocated_width (GTK_WIDGET (tasklist->outer_box)); + task->toplevel = toplevel; zwlr_foreign_toplevel_handle_v1_add_listener (toplevel, &foreign_toplevel_handle_listener, @@ -354,10 +719,9 @@ toplevel_task_new (TasklistManager *tasklist, struct zwlr_foreign_toplevel_handl task, (GDestroyNotify)toplevel_task_disconnected_from_widget); - g_signal_connect (G_OBJECT (task->button), - "button-press-event", + g_signal_connect (task->button, "button-press-event", G_CALLBACK (on_toplevel_button_press), - task); + tasklist); return task; } diff --git a/applets/wncklet/wayland-backend.h b/applets/wncklet/wayland-backend.h index 0ea4634a..e2402236 100644 --- a/applets/wncklet/wayland-backend.h +++ b/applets/wncklet/wayland-backend.h @@ -38,11 +38,9 @@ extern "C" { GtkWidget* wayland_tasklist_new (void); void wayland_tasklist_set_orientation (GtkWidget* tasklist_widget, GtkOrientation orient); - #ifdef __cplusplus } #endif #endif /* _WNCKLET_APPLET_WAYLAND_BACKEND_H_ */ - diff --git a/applets/wncklet/window-list.c b/applets/wncklet/window-list.c index dd18fc72..93785cc1 100644 --- a/applets/wncklet/window-list.c +++ b/applets/wncklet/window-list.c @@ -62,6 +62,8 @@ typedef struct { TasklistGroupingType grouping; gboolean move_unminimized_windows; + gboolean scroll_enable; + gboolean middle_click_close; GtkOrientation orientation; int size; @@ -69,10 +71,9 @@ typedef struct { gboolean needs_hints; #endif - GtkIconTheme* icon_theme; - /* Properties: */ GtkWidget* properties_dialog; + GtkWidget* wayland_info_label; GtkWidget* show_current_radio; GtkWidget* show_all_radio; #ifdef HAVE_WINDOW_PREVIEWS @@ -85,6 +86,8 @@ typedef struct { GtkWidget* auto_group_radio; GtkWidget* always_group_radio; GtkWidget* move_minimized_radio; + GtkWidget* mouse_scroll_check; + GtkWidget* middle_click_close_check; GtkWidget* change_workspace_radio; GtkWidget* minimized_windows_box; GtkWidget* window_grouping_box; @@ -119,14 +122,23 @@ static void tasklist_update(TasklistData* tasklist) WnckTasklistGroupingType grouping; switch (tasklist->grouping) { - case TASKLIST_NEVER_GROUP: grouping = WNCK_TASKLIST_NEVER_GROUP; - case TASKLIST_AUTO_GROUP: grouping = WNCK_TASKLIST_AUTO_GROUP; - case TASKLIST_ALWAYS_GROUP: grouping = WNCK_TASKLIST_ALWAYS_GROUP; - default: grouping = WNCK_TASKLIST_NEVER_GROUP; + case TASKLIST_NEVER_GROUP: + grouping = WNCK_TASKLIST_NEVER_GROUP; + break; + case TASKLIST_AUTO_GROUP: + grouping = WNCK_TASKLIST_AUTO_GROUP; + break; + case TASKLIST_ALWAYS_GROUP: + grouping = WNCK_TASKLIST_ALWAYS_GROUP; + break; + default: + grouping = WNCK_TASKLIST_NEVER_GROUP; } wnck_tasklist_set_grouping(WNCK_TASKLIST(tasklist->tasklist), grouping); wnck_tasklist_set_include_all_workspaces(WNCK_TASKLIST(tasklist->tasklist), tasklist->include_all_workspaces); wnck_tasklist_set_switch_workspace_on_unminimize(WNCK_TASKLIST(tasklist->tasklist), tasklist->move_unminimized_windows); + wnck_tasklist_set_scroll_enabled (WNCK_TASKLIST(tasklist->tasklist), tasklist->scroll_enable); + wnck_tasklist_set_middle_click_close (WNCK_TASKLIST (tasklist->tasklist), tasklist->middle_click_close); } #endif /* HAVE_X11 */ @@ -191,11 +203,6 @@ static void response_cb(GtkWidget* widget, int id, TasklistData* tasklist) } } -static void applet_realized(MatePanelApplet* applet, TasklistData* tasklist) -{ - tasklist->icon_theme = gtk_icon_theme_get_for_screen(gtk_widget_get_screen(tasklist->applet)); -} - static void applet_change_orient(MatePanelApplet* applet, MatePanelAppletOrient orient, TasklistData* tasklist) { GtkOrientation new_orient; @@ -236,91 +243,134 @@ static void applet_change_background(MatePanelApplet* applet, MatePanelAppletBac #ifdef HAVE_X11 #ifdef HAVE_WINDOW_PREVIEWS -static GdkPixbuf *preview_window_thumbnail (WnckWindow *wnck_window, TasklistData *tasklist) +static cairo_surface_t* +preview_window_thumbnail (WnckWindow *wnck_window, + TasklistData *tasklist, + int *thumbnail_width, + int *thumbnail_height, + int *thumbnail_scale) { GdkWindow *window; - GdkPixbuf *screenshot; - GdkPixbuf *thumbnail; + Window win; + cairo_surface_t *thumbnail; + cairo_t *cr; double ratio; - int width, height; - int scale; + int width, height, scale; - window = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), wnck_window_get_xid (wnck_window)); + win = wnck_window_get_xid (wnck_window); - if (window == NULL) + if ((window = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), win)) == NULL) + { return NULL; + } - scale = gdk_window_get_scale_factor (window); + *thumbnail_scale = scale = gdk_window_get_scale_factor (window); width = gdk_window_get_width (window) * scale; height = gdk_window_get_height (window) * scale; - /* Generate window screenshot for preview */ - screenshot = gdk_pixbuf_get_from_window (window, 0, 0, width / scale, height / scale); - g_object_unref (window); - - if (screenshot == NULL) - return NULL; - - /* Determine whether the contents of the screenshot are empty */ - if (gdk_pixbuf_get_byte_length (screenshot) == 0) - { - g_object_unref (screenshot); - return NULL; - } - /* Scale to configured size while maintaining aspect ratio */ if (width > height) { - ratio = (double) height / (double) width; - width = MIN(width, tasklist->thumbnail_size); - height = width * ratio; + int max_size = MIN (width, tasklist->thumbnail_size * scale); + ratio = (double) max_size / (double) width; + *thumbnail_width = max_size; + *thumbnail_height = (int) ((double) height * ratio); } else { - ratio = (double) width / (double) height; - height = MIN(height, tasklist->thumbnail_size); - width = height * ratio; + int max_size = MIN (height, tasklist->thumbnail_size * scale); + ratio = (double) max_size / (double) height; + *thumbnail_height = max_size; + *thumbnail_width = (int) ((double) width * ratio); } - thumbnail = gdk_pixbuf_scale_simple (screenshot, width, height, GDK_INTERP_BILINEAR); - g_object_unref (screenshot); + gdk_x11_display_error_trap_push (gdk_window_get_display (window)); + + thumbnail = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + *thumbnail_width, + *thumbnail_height); + cairo_surface_set_device_scale (thumbnail, scale, scale); + cr = cairo_create (thumbnail); + cairo_scale (cr, ratio, ratio); + gdk_cairo_set_source_window (cr, window, 0, 0); + cairo_paint (cr); + cairo_destroy (cr); + + if (gdk_x11_display_error_trap_pop (gdk_window_get_display (window))) + { + cairo_surface_destroy (thumbnail); + thumbnail = NULL; + } + + g_object_unref (window); return thumbnail; } +static int g_int_compare(gconstpointer a, gconstpointer b) +{ + gint a_val = GPOINTER_TO_INT(a); + gint b_val = GPOINTER_TO_INT(b); + if (a_val > b_val) return -1; + if (a_val == b_val) return 0; + return 1; +} + +static int find_offset(GList *list, gdouble target) +{ + GList *node = list; + while (node != NULL) { + int value = GPOINTER_TO_INT(node->data); + if (value <= target) + return value; + node = node->next; + } + return -1; +} + #define PREVIEW_PADDING 5 -static void preview_window_reposition (TasklistData *tasklist, GdkPixbuf *thumbnail) +static void +preview_window_reposition (WnckTasklist *tl, + TasklistData *tasklist, + int width, + int height, + int scale) { + /* Known issues: + * - When grouping is toggled the previews won't be centered correctly until a new window is opened or one is closed. + * - Previews are not shown at all for grouped windows, this function is not called when hovering over those. + */ + GdkMonitor *monitor; GdkRectangle monitor_geom; - int x_pos, y_pos; - int width, height; + MatePanelAppletOrient orient; + gdouble x_pos, y_pos; + int x_offset, y_offset; - width = gdk_pixbuf_get_width (thumbnail); - height = gdk_pixbuf_get_height (thumbnail); - - /* Resize window to fit thumbnail */ - gtk_window_resize (GTK_WINDOW (tasklist->preview), width, height); - - /* Set position at pointer, then re-adjust from there to just outside of the pointer */ - gtk_window_set_position (GTK_WINDOW (tasklist->preview), GTK_WIN_POS_MOUSE); - gtk_window_get_position (GTK_WINDOW (tasklist->preview), &x_pos, &y_pos); + /* Get mouse position */ + gdk_device_get_position_double (gdk_seat_get_pointer (gdk_display_get_default_seat (gdk_display_get_default ())), NULL, &x_pos, &y_pos); /* Get geometry of monitor where tasklist is located to calculate correct position of preview */ monitor = gdk_display_get_monitor_at_point (gdk_display_get_default (), x_pos, y_pos); gdk_monitor_get_geometry (monitor, &monitor_geom); + /* Get the position where the window list applet starts */ + gdk_window_get_origin (gtk_widget_get_window (gtk_widget_get_parent (GTK_WIDGET(tl))), &x_offset, &y_offset); + + /* Get panel orientation */ + orient = mate_panel_applet_get_orient (MATE_PANEL_APPLET (tasklist->applet)); + /* Add padding to clear the panel */ - switch (mate_panel_applet_get_orient (MATE_PANEL_APPLET (tasklist->applet))) + switch (orient) { case MATE_PANEL_APPLET_ORIENT_LEFT: - x_pos = monitor_geom.width + monitor_geom.x - (width + tasklist->size) - PREVIEW_PADDING; + x_pos = monitor_geom.width + monitor_geom.x - width - tasklist->size - PREVIEW_PADDING; break; case MATE_PANEL_APPLET_ORIENT_RIGHT: x_pos = tasklist->size + PREVIEW_PADDING; break; case MATE_PANEL_APPLET_ORIENT_UP: - y_pos = monitor_geom.height + monitor_geom.y - (height + tasklist->size) - PREVIEW_PADDING; + y_pos = monitor_geom.height + monitor_geom.y - height - tasklist->size - PREVIEW_PADDING; break; case MATE_PANEL_APPLET_ORIENT_DOWN: default: @@ -328,24 +378,77 @@ static void preview_window_reposition (TasklistData *tasklist, GdkPixbuf *thumbn break; } + /* Collect the allocation.x/y values of each button into lists. + * We need to iterate over all of them because grouped buttons will be the last children, + * even though they are positioned at the beginning. And not all buttons will have the exact same width. + * This allows us to avoid off-by-one errors that would cause the preview to be positioned over the adjacent button. */ + GList *alloc_x_list = NULL; + GList *alloc_y_list = NULL; + GtkAllocation last_alloc; + GList* children = gtk_container_get_children (GTK_CONTAINER(tl)); + while (children != NULL) + { + if (g_strcmp0 (gtk_widget_get_name (children->data), "tasklist-button") == 0) { + GtkAllocation alloc; + gtk_widget_get_allocation (children->data, &alloc); + + /* Skip grouped buttons: these usually have alloc width/heigh=1, except right after grouping is toggled. + * Then simply open or close a new window to get the correct offset. */ + if (alloc.width < 2 || alloc.height < 2) + { + children = children->next; + continue; + } + + /* Keep x and y offsets in sorted lists */ + alloc_x_list = g_list_insert_sorted (alloc_x_list, GINT_TO_POINTER(alloc.x), g_int_compare); + alloc_y_list = g_list_insert_sorted (alloc_y_list, GINT_TO_POINTER(alloc.y), g_int_compare); + + /* The width/height from the last allocation will be used for centering the preview. + * It might be off by a pixel because not all buttons have the exact same width/height but this isn't critical. */ + last_alloc = alloc; + } + children = children->next; + } + + /* Center preview at the midpoint of the tasklist button */ + if (orient == MATE_PANEL_APPLET_ORIENT_LEFT || orient == MATE_PANEL_APPLET_ORIENT_RIGHT) + { + /* Vertical panel */ + y_pos = y_offset + find_offset (alloc_y_list, y_pos - y_offset) + (last_alloc.height - height) / 2; + y_pos = y_pos < PREVIEW_PADDING ? PREVIEW_PADDING : y_pos; + } + else if (orient == MATE_PANEL_APPLET_ORIENT_UP || orient == MATE_PANEL_APPLET_ORIENT_DOWN) + { + /* Horizontal panel */ + x_pos = x_offset + find_offset (alloc_x_list, x_pos - x_offset) + (last_alloc.width - width) / 2; + x_pos = x_pos < PREVIEW_PADDING ? PREVIEW_PADDING : x_pos; + } + + g_list_free (alloc_x_list); + g_list_free (alloc_y_list); + gtk_window_move (GTK_WINDOW (tasklist->preview), x_pos, y_pos); } -static gboolean preview_window_draw (GtkWidget *widget, cairo_t *cr, GdkPixbuf *thumbnail) +static gboolean preview_window_draw (GtkWidget *widget, cairo_t *cr, cairo_surface_t *thumbnail) { GtkStyleContext *context; context = gtk_widget_get_style_context (widget); - gtk_render_icon (context, cr, thumbnail, 0, 0); + gtk_render_icon_surface (context, cr, thumbnail, 0, 0); return FALSE; } static gboolean applet_enter_notify_event (WnckTasklist *tl, GList *wnck_windows, TasklistData *tasklist) { - GdkPixbuf *thumbnail; + cairo_surface_t *thumbnail; WnckWindow *wnck_window = NULL; int n_windows; + int thumbnail_width; + int thumbnail_height; + int thumbnail_scale; if (tasklist->preview != NULL) { @@ -373,7 +476,7 @@ static gboolean applet_enter_notify_event (WnckTasklist *tl, GList *wnck_windows wnck_screen_get_active_workspace (wnck_screen_get_default ()))) return FALSE; - thumbnail = preview_window_thumbnail (wnck_window, tasklist); + thumbnail = preview_window_thumbnail (wnck_window, tasklist, &thumbnail_width, &thumbnail_height, &thumbnail_scale); if (thumbnail == NULL) return FALSE; @@ -382,13 +485,16 @@ static gboolean applet_enter_notify_event (WnckTasklist *tl, GList *wnck_windows tasklist->preview = gtk_window_new (GTK_WINDOW_POPUP); gtk_widget_set_app_paintable (tasklist->preview, TRUE); + gtk_window_set_default_size (GTK_WINDOW (tasklist->preview), thumbnail_width/thumbnail_scale, thumbnail_height/thumbnail_scale); gtk_window_set_resizable (GTK_WINDOW (tasklist->preview), TRUE); - - preview_window_reposition (tasklist, thumbnail); + preview_window_reposition (tl, tasklist, thumbnail_width/thumbnail_scale, thumbnail_height/thumbnail_scale, thumbnail_scale); gtk_widget_show (tasklist->preview); - g_signal_connect_data (G_OBJECT (tasklist->preview), "draw", G_CALLBACK (preview_window_draw), thumbnail, (GClosureNotify) G_CALLBACK (g_object_unref), 0); + g_signal_connect_data (tasklist->preview, "draw", + G_CALLBACK (preview_window_draw), thumbnail, + (GClosureNotify) G_CALLBACK (cairo_surface_destroy), + 0); return FALSE; } @@ -505,6 +611,11 @@ static void tasklist_update_thumbnail_size_spin(TasklistData* tasklist) gtk_spin_button_set_value(GTK_SPIN_BUTTON(button), (gdouble)tasklist->thumbnail_size); } +static void show_thumbnails_changed(GSettings* settings, gchar* key, TasklistData* tasklist) +{ + tasklist->show_window_thumbnails = g_settings_get_boolean (settings, key); +} + static void thumbnail_size_changed(GSettings *settings, gchar* key, TasklistData* tasklist) { tasklist->thumbnail_size = g_settings_get_int(settings, key); @@ -567,7 +678,6 @@ static void tasklist_update_unminimization_radio(TasklistData* tasklist) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE); } - static void move_unminimized_windows_changed(GSettings* settings, gchar* key, TasklistData* tasklist) { gboolean value; @@ -580,6 +690,18 @@ static void move_unminimized_windows_changed(GSettings* settings, gchar* key, Ta tasklist_update_unminimization_radio(tasklist); } +static void scroll_enabled_changed (GSettings* settings, gchar* key, TasklistData* tasklist) +{ + tasklist->scroll_enable = g_settings_get_boolean (settings, key); + tasklist_update(tasklist); +} + +static void middle_click_close_changed (GSettings* settings, gchar* key, TasklistData* tasklist) +{ + tasklist->middle_click_close = g_settings_get_boolean (settings, key); + tasklist_update(tasklist); +} + static void setup_gsettings(TasklistData* tasklist) { tasklist->settings = mate_panel_applet_settings_new (MATE_PANEL_APPLET (tasklist->applet), WINDOW_LIST_SCHEMA); @@ -593,6 +715,11 @@ static void setup_gsettings(TasklistData* tasklist) tasklist->preview_settings = mate_panel_applet_settings_new (MATE_PANEL_APPLET (tasklist->applet), WINDOW_LIST_PREVIEW_SCHEMA); g_signal_connect (tasklist->preview_settings, + "changed::show-window-thumbnails", + G_CALLBACK (show_thumbnails_changed), + tasklist); + + g_signal_connect (tasklist->preview_settings, "changed::thumbnail-window-size", G_CALLBACK (thumbnail_size_changed), tasklist); @@ -605,6 +732,14 @@ static void setup_gsettings(TasklistData* tasklist) "changed::move-unminimized-windows", G_CALLBACK (move_unminimized_windows_changed), tasklist); + g_signal_connect (tasklist->settings, + "changed::scroll-enabled", + G_CALLBACK (scroll_enabled_changed), + tasklist); + g_signal_connect (tasklist->settings, + "changed::middle-click-close", + G_CALLBACK (middle_click_close_changed), + tasklist); } static void applet_size_allocate(GtkWidget *widget, GtkAllocation *allocation, TasklistData *tasklist) @@ -639,55 +774,6 @@ static void applet_size_allocate(GtkWidget *widget, GtkAllocation *allocation, T mate_panel_applet_set_size_hints(MATE_PANEL_APPLET(tasklist->applet), size_hints, len, 0); } -#ifdef HAVE_X11 -/* Currently only used on X11, but should work on Wayland as well when needed */ -static GdkPixbuf* icon_loader_func(const char* icon, int size, unsigned int flags, void* data) -{ - TasklistData* tasklist; - GdkPixbuf* retval; - char* icon_no_extension; - char* p; - - tasklist = data; - - if (icon == NULL || strcmp(icon, "") == 0) - return NULL; - - if (g_path_is_absolute(icon)) - { - if (g_file_test(icon, G_FILE_TEST_EXISTS)) - { - return gdk_pixbuf_new_from_file_at_size(icon, size, size, NULL); - } - else - { - char* basename; - - basename = g_path_get_basename(icon); - retval = icon_loader_func(basename, size, flags, data); - g_free(basename); - - return retval; - } - } - - /* This is needed because some .desktop files have an icon name *and* - * an extension as icon */ - icon_no_extension = g_strdup(icon); - p = strrchr(icon_no_extension, '.'); - - if (p && (strcmp(p, ".png") == 0 || strcmp(p, ".xpm") == 0 || strcmp(p, ".svg") == 0)) - { - *p = 0; - } - - retval = gtk_icon_theme_load_icon(tasklist->icon_theme, icon_no_extension, size, 0, NULL); - g_free(icon_no_extension); - - return retval; -} -#endif /* HAVE_X11 */ - gboolean window_list_applet_fill(MatePanelApplet* applet) { TasklistData* tasklist; @@ -728,6 +814,10 @@ gboolean window_list_applet_fill(MatePanelApplet* applet) tasklist->move_unminimized_windows = g_settings_get_boolean (tasklist->settings, "move-unminimized-windows"); + tasklist->scroll_enable = g_settings_get_boolean (tasklist->settings, "scroll-enabled"); + + tasklist->middle_click_close = g_settings_get_boolean (tasklist->settings, "middle-click-close"); + tasklist->size = mate_panel_applet_get_size(applet); #if !defined(WNCKLET_INPROCESS) && !GTK_CHECK_VERSION (3, 23, 0) @@ -752,12 +842,13 @@ gboolean window_list_applet_fill(MatePanelApplet* applet) { tasklist->tasklist = wnck_tasklist_new(); - wnck_tasklist_set_middle_click_close (WNCK_TASKLIST (tasklist->tasklist), TRUE); - wnck_tasklist_set_icon_loader(WNCK_TASKLIST(tasklist->tasklist), icon_loader_func, tasklist, NULL); - #ifdef HAVE_WINDOW_PREVIEWS - g_signal_connect(G_OBJECT(tasklist->tasklist), "task_enter_notify", G_CALLBACK(applet_enter_notify_event), tasklist); - g_signal_connect(G_OBJECT(tasklist->tasklist), "task_leave_notify", G_CALLBACK(applet_leave_notify_event), tasklist); + g_signal_connect (tasklist->tasklist, "task-enter-notify", + G_CALLBACK (applet_enter_notify_event), + tasklist); + g_signal_connect (tasklist->tasklist, "task-leave-notify", + G_CALLBACK (applet_leave_notify_event), + tasklist); #endif /* HAVE_WINDOW_PREVIEWS */ } else @@ -777,27 +868,33 @@ gboolean window_list_applet_fill(MatePanelApplet* applet) tasklist_apply_orientation(tasklist); - g_signal_connect(G_OBJECT(tasklist->tasklist), "destroy", G_CALLBACK(destroy_tasklist), tasklist); - g_signal_connect(G_OBJECT(tasklist->applet), "size_allocate", G_CALLBACK(applet_size_allocate), tasklist); + g_signal_connect (tasklist->tasklist, "destroy", + G_CALLBACK (destroy_tasklist), + tasklist); + g_signal_connect (tasklist->applet, "size-allocate", + G_CALLBACK (applet_size_allocate), + tasklist); gtk_container_add(GTK_CONTAINER(tasklist->applet), tasklist->tasklist); - g_signal_connect(G_OBJECT(tasklist->applet), "realize", G_CALLBACK(applet_realized), tasklist); - g_signal_connect(G_OBJECT(tasklist->applet), "change_orient", G_CALLBACK(applet_change_orient), tasklist); - g_signal_connect(G_OBJECT(tasklist->applet), "change_size", G_CALLBACK(applet_change_pixel_size), tasklist); - g_signal_connect(G_OBJECT(tasklist->applet), "change_background", G_CALLBACK(applet_change_background), tasklist); - - mate_panel_applet_set_background_widget(MATE_PANEL_APPLET(tasklist->applet), GTK_WIDGET(tasklist->applet)); + g_signal_connect (tasklist->applet, "change-orient", + G_CALLBACK (applet_change_orient), + tasklist); + g_signal_connect (tasklist->applet, "change-size", + G_CALLBACK (applet_change_pixel_size), + tasklist); + g_signal_connect (tasklist->applet, "change-background", + G_CALLBACK(applet_change_background), + tasklist); action_group = gtk_action_group_new("Tasklist Applet Actions"); gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE); gtk_action_group_add_actions(action_group, tasklist_menu_actions, G_N_ELEMENTS(tasklist_menu_actions), tasklist); - /* disable the item of system monitor, if not exists. * example, mate-system-monitor, o gnome-system-monitor */ char* programpath; - int i; + gsize i; for (i = 0; i < G_N_ELEMENTS(system_monitors); i += 1) { @@ -819,7 +916,6 @@ gboolean window_list_applet_fill(MatePanelApplet* applet) _system_monitor_found:; /* end of system monitor item */ - mate_panel_applet_setup_menu_from_resource (MATE_PANEL_APPLET (tasklist->applet), WNCKLET_RESOURCE_PATH "window-list-menu.xml", action_group); @@ -843,7 +939,7 @@ gboolean window_list_applet_fill(MatePanelApplet* applet) static void call_system_monitor(GtkAction* action, TasklistData* tasklist) { - int i; + gsize i; for (i = 0; i < G_N_ELEMENTS(system_monitors); i += 1) { @@ -861,7 +957,6 @@ static void call_system_monitor(GtkAction* action, TasklistData* tasklist) } } - static void display_help_dialog(GtkAction* action, TasklistData* tasklist) { wncklet_display_help(tasklist->applet, "mate-user-guide", "windowlist", WINDOW_LIST_ICON); @@ -889,13 +984,13 @@ static void display_about_dialog(GtkAction* action, TasklistData* tasklist) "comments", _("The Window List shows a list of all windows in a set of buttons and lets you browse them."), "copyright", _("Copyright \xc2\xa9 2002 Red Hat, Inc.\n" "Copyright \xc2\xa9 2011 Perberos\n" - "Copyright \xc2\xa9 2012-2020 MATE developers"), + "Copyright \xc2\xa9 2012-2021 MATE developers"), "documenters", documenters, "icon-name", WINDOW_LIST_ICON, "logo-icon-name", WINDOW_LIST_ICON, "translator-credits", _("translator-credits"), "version", VERSION, - "website", "http://www.mate-desktop.org/", + "website", PACKAGE_URL, NULL); } @@ -959,6 +1054,8 @@ static void setup_sensitivity(TasklistData* tasklist, GtkBuilder* builder, const #ifdef HAVE_WAYLAND static void setup_dialog_wayland(TasklistData* tasklist) { + gtk_widget_show(tasklist->wayland_info_label); + gtk_widget_set_sensitive(tasklist->window_list_content_box, FALSE); gtk_widget_set_sensitive(tasklist->window_grouping_box, FALSE); gtk_widget_set_sensitive(tasklist->minimized_windows_box, FALSE); @@ -972,10 +1069,8 @@ static void setup_dialog_wayland(TasklistData* tasklist) static void setup_dialog(GtkBuilder* builder, TasklistData* tasklist) { GtkWidget* button; -#ifdef HAVE_WINDOW_PREVIEWS - GtkAdjustment *adjustment; -#endif /* HAVE_WINDOW_PREVIEWS */ + tasklist->wayland_info_label = WID("wayland_info_label"); tasklist->show_current_radio = WID("show_current_radio"); tasklist->show_all_radio = WID("show_all_radio"); @@ -1004,16 +1099,14 @@ static void setup_dialog(GtkBuilder* builder, TasklistData* tasklist) g_object_bind_property(tasklist->show_thumbnails_check, "active", tasklist->thumbnail_size_label, "sensitive", G_BINDING_DEFAULT); g_object_bind_property(tasklist->show_thumbnails_check, "active", tasklist->thumbnail_size_spin, "sensitive", G_BINDING_DEFAULT); - adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(tasklist->thumbnail_size_spin)); - gtk_adjustment_set_lower (adjustment, 0); - gtk_adjustment_set_upper (adjustment, 999); - gtk_adjustment_set_step_increment (adjustment, 1); #else gtk_widget_hide(WID("window_thumbnail_box")); #endif tasklist->move_minimized_radio = WID("move_minimized_radio"); tasklist->change_workspace_radio = WID("change_workspace_radio"); + tasklist->mouse_scroll_check = WID("mouse_scroll_check"); + tasklist->middle_click_close_check = WID("middle_click_close_check"); tasklist->minimized_windows_box = WID("minimized_windows_box"); tasklist->window_grouping_box = WID("window_grouping_box"); tasklist->window_list_content_box = WID("window_list_content_box"); @@ -1027,26 +1120,56 @@ static void setup_dialog(GtkBuilder* builder, TasklistData* tasklist) g_object_set_data(G_OBJECT(tasklist->auto_group_radio), "group_value", "auto"); g_object_set_data(G_OBJECT(tasklist->always_group_radio), "group_value", "always"); - g_signal_connect(G_OBJECT(tasklist->never_group_radio), "toggled", (GCallback) group_windows_toggled, tasklist); - g_signal_connect(G_OBJECT(tasklist->auto_group_radio), "toggled", (GCallback) group_windows_toggled, tasklist); - g_signal_connect(G_OBJECT(tasklist->always_group_radio), "toggled", (GCallback) group_windows_toggled, tasklist); + g_signal_connect (tasklist->never_group_radio, "toggled", + (GCallback) group_windows_toggled, + tasklist); + g_signal_connect (tasklist->auto_group_radio, "toggled", + (GCallback) group_windows_toggled, + tasklist); + g_signal_connect (tasklist->always_group_radio, "toggled", + (GCallback) group_windows_toggled, + tasklist); + + /* Mouse Scroll: */ + g_settings_bind (tasklist->settings, + "scroll-enabled", + tasklist->mouse_scroll_check, + "active", + G_SETTINGS_BIND_DEFAULT); + + /* Middle mouse click to close window: */ + g_settings_bind (tasklist->settings, + "middle-click-close", + tasklist->middle_click_close_check, + "active", + G_SETTINGS_BIND_DEFAULT); #ifdef HAVE_WINDOW_PREVIEWS /* change thumbnail size: */ tasklist_update_thumbnail_size_spin(tasklist); - g_signal_connect(G_OBJECT(tasklist->thumbnail_size_spin), "value-changed", (GCallback) thumbnail_size_spin_changed, tasklist); + g_signal_connect (tasklist->thumbnail_size_spin, "value-changed", + (GCallback) thumbnail_size_spin_changed, + tasklist); #endif /* move window when unminimizing: */ tasklist_update_unminimization_radio(tasklist); - g_signal_connect(G_OBJECT(tasklist->move_minimized_radio), "toggled", (GCallback) move_minimized_toggled, tasklist); + g_signal_connect (tasklist->move_minimized_radio, "toggled", + (GCallback) move_minimized_toggled, + tasklist); /* Tasklist content: */ tasklist_properties_update_content_radio (tasklist); - g_signal_connect(G_OBJECT(tasklist->show_all_radio), "toggled", (GCallback) display_all_workspaces_toggled, tasklist); - - g_signal_connect_swapped(WID("done_button"), "clicked", (GCallback) gtk_widget_hide, tasklist->properties_dialog); - g_signal_connect(tasklist->properties_dialog, "response", G_CALLBACK(response_cb), tasklist); + g_signal_connect (tasklist->show_all_radio, "toggled", + (GCallback) display_all_workspaces_toggled, + tasklist); + + g_signal_connect_swapped (WID ("done_button"), "clicked", + (GCallback) gtk_widget_hide, + tasklist->properties_dialog); + g_signal_connect (tasklist->properties_dialog, "response", + G_CALLBACK (response_cb), + tasklist); #ifdef HAVE_WAYLAND if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) { diff --git a/applets/wncklet/window-list.ui b/applets/wncklet/window-list.ui index 2161d427..4cc49f9c 100644 --- a/applets/wncklet/window-list.ui +++ b/applets/wncklet/window-list.ui @@ -1,41 +1,46 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.36.0 --> +<!-- Generated with glade 3.38.2 --> <interface> <requires lib="gtk+" version="3.22"/> + <object class="GtkAdjustment" id="adjustment1"> + <property name="upper">999</property> + <property name="step-increment">1</property> + <property name="page-increment">10</property> + </object> <object class="GtkImage" id="image1"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">help-browser</property> + <property name="can-focus">False</property> + <property name="icon-name">help-browser</property> </object> <object class="GtkImage" id="image2"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">window-close</property> + <property name="can-focus">False</property> + <property name="icon-name">window-close</property> </object> <object class="GtkDialog" id="tasklist_properties_dialog"> - <property name="can_focus">False</property> - <property name="border_width">5</property> + <property name="can-focus">False</property> + <property name="border-width">5</property> <property name="title" translatable="yes">Window List Preferences</property> - <property name="type_hint">normal</property> + <property name="resizable">False</property> + <property name="icon-name">mate-panel-window-list</property> + <property name="type-hint">normal</property> <child internal-child="vbox"> - <object class="GtkBox" id="dialog-vbox2"> - <property name="visible">True</property> - <property name="can_focus">False</property> + <object class="GtkBox"> + <property name="can-focus">False</property> <property name="orientation">vertical</property> <property name="spacing">2</property> <child internal-child="action_area"> <object class="GtkButtonBox" id="dialog-action_area2"> - <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <child> <object class="GtkButton" id="help_button"> <property name="label" translatable="yes">_Help</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="receives_default">False</property> + <property name="can-focus">True</property> + <property name="can-default">True</property> + <property name="receives-default">False</property> <property name="image">image1</property> - <property name="use_underline">True</property> + <property name="use-underline">True</property> </object> <packing> <property name="expand">False</property> @@ -47,12 +52,12 @@ <object class="GtkButton" id="done_button"> <property name="label" translatable="yes">_Close</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="has_default">True</property> - <property name="receives_default">False</property> + <property name="can-focus">True</property> + <property name="can-default">True</property> + <property name="has-default">True</property> + <property name="receives-default">False</property> <property name="image">image2</property> - <property name="use_underline">True</property> + <property name="use-underline">True</property> </object> <packing> <property name="expand">False</property> @@ -64,149 +69,206 @@ <packing> <property name="expand">False</property> <property name="fill">False</property> - <property name="pack_type">end</property> - <property name="position">1</property> + <property name="position">0</property> </packing> </child> <child> - <object class="GtkBox" id="vbox1"> + <object class="GtkNotebook"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="border_width">5</property> - <property name="orientation">vertical</property> - <property name="spacing">18</property> + <property name="can-focus">True</property> <child> - <object class="GtkBox" id="window_list_content_box"> + <object class="GtkBox" id="behaviour_vbox"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="border-width">12</property> <property name="orientation">vertical</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="label1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Window List Content</property> - <property name="xalign">0</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> + <property name="spacing">18</property> <child> - <object class="GtkAlignment" id="alignment1"> + <object class="GtkBox" id="window_thumbnail_box"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="left_padding">12</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> <child> - <object class="GtkBox" id="vbox9"> + <object class="GtkLabel" id="thumbnails_label"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes">Window Thumbnails</property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="vbox16"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="margin-start">6</property> <property name="orientation">vertical</property> <property name="spacing">6</property> <child> - <object class="GtkRadioButton" id="show_current_radio"> - <property name="label" translatable="yes">Sh_ow windows from current workspace</property> + <object class="GtkCheckButton" id="show_thumbnails_check"> + <property name="label" translatable="yes">Show _thumbnails on hover</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> </object> <packing> <property name="expand">False</property> - <property name="fill">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <object class="GtkRadioButton" id="show_all_radio"> - <property name="label" translatable="yes">Show windows from a_ll workspaces</property> + <object class="GtkBox" id="thumbnail_box"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - <property name="group">show_current_radio</property> + <property name="can-focus">False</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="thumbnail_size_label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="tooltip-text" translatable="yes">Thumbnail width in pixels. Window aspect ratio will be maintained.</property> + <property name="label" translatable="yes">Thumbnail width:</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkSpinButton" id="thumbnail_size_spin"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="max-length">3</property> + <property name="text" translatable="yes">0</property> + <property name="caps-lock-warning">False</property> + <property name="placeholder-text" translatable="yes">px</property> + <property name="input-purpose">number</property> + <property name="adjustment">adjustment1</property> + <property name="climb-rate">1</property> + <property name="numeric">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> </object> <packing> <property name="expand">False</property> - <property name="fill">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="window_thumbnail_box"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="label4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Window Thumbnails</property> - <property name="xalign">0</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> <property name="position">0</property> </packing> </child> <child> - <object class="GtkAlignment" id="alignment4"> + <object class="GtkBox" id="window_grouping_box"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="left_padding">12</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> <child> - <object class="GtkBox" id="vbox16"> + <object class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes">Window Grouping</property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="vbox12"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> + <property name="margin-start">6</property> <property name="orientation">vertical</property> <property name="spacing">6</property> <child> - <object class="GtkCheckButton" id="show_thumbnails_check"> - <property name="label" translatable="yes">Show _thumbnails on hover</property> + <object class="GtkRadioButton" id="never_group_radio"> + <property name="label" translatable="yes">_Never group windows</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="use-underline">True</property> + <property name="active">True</property> + <property name="draw-indicator">True</property> </object> <packing> <property name="expand">False</property> - <property name="fill">True</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="auto_group_radio"> + <property name="label" translatable="yes">Group windows when _space is limited</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> + <property name="group">never_group_radio</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> <property name="position">1</property> </packing> </child> + <child> + <object class="GtkRadioButton" id="always_group_radio"> + <property name="label" translatable="yes">_Always group windows</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> + <property name="group">never_group_radio</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> </child> </object> <packing> @@ -216,22 +278,42 @@ </packing> </child> <child> - <object class="GtkAlignment" id="alignment5"> + <object class="GtkBox" id="middle_click_close_box"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="left_padding">12</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> <child> - <object class="GtkBox" id="hbox1"> + <object class="GtkLabel" id="middle_click_close_label"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes">Middle mouse button</property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="middle_click_close_vbox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="margin-start">6</property> + <property name="orientation">vertical</property> <property name="spacing">6</property> <child> - <object class="GtkLabel" id="thumbnail_size_label"> + <object class="GtkCheckButton" id="middle_click_close_check"> + <property name="label" translatable="yes">_Click to close window</property> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Thumbnail width in pixels. Window aspect ratio will be maintained.</property> - <property name="label" translatable="yes">Thumbnail width:</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> </object> <packing> <property name="expand">False</property> @@ -239,82 +321,135 @@ <property name="position">0</property> </packing> </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkBox" id="mouse_scroll_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="mouse_scrolling_label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes">Mouse Scrolling</property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="mouse_scrolling_vbox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="margin-start">6</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> <child> - <object class="GtkSpinButton" id="thumbnail_size_spin"> + <object class="GtkCheckButton" id="mouse_scroll_check"> + <property name="label" translatable="yes">_Enable mouse scrolling</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="max_length">3</property> - <property name="caps_lock_warning">False</property> - <property name="placeholder_text" translatable="yes">px</property> - <property name="input_purpose">number</property> - <property name="climb_rate">1</property> - <property name="numeric">True</property> - <property name="value">200</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> </object> <packing> <property name="expand">False</property> <property name="fill">False</property> - <property name="position">1</property> + <property name="position">0</property> </packing> </child> </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">2</property> + <property name="position">3</property> </packing> </child> </object> + </child> + <child type="tab"> + <object class="GtkLabel" id="behaviour_label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes">Behaviour</property> + </object> <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> + <property name="tab-fill">False</property> </packing> </child> <child> - <object class="GtkBox" id="window_grouping_box"> + <object class="GtkBox" id="workspaces_vbox"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> + <property name="border-width">12</property> <property name="orientation">vertical</property> - <property name="spacing">6</property> + <property name="spacing">18</property> <child> - <object class="GtkLabel" id="label3"> + <object class="GtkBox" id="window_list_content_box"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Window Grouping</property> - <property name="xalign">0</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="alignment2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="left_padding">12</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> <child> - <object class="GtkBox" id="vbox12"> + <object class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes">Window List Content</property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="vbox9"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> + <property name="margin-start">6</property> <property name="orientation">vertical</property> <property name="spacing">6</property> <child> - <object class="GtkRadioButton" id="never_group_radio"> - <property name="label" translatable="yes">_Never group windows</property> + <object class="GtkRadioButton" id="show_current_radio"> + <property name="label" translatable="yes">Sh_ow windows from current workspace</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="use-underline">True</property> + <property name="active">True</property> + <property name="draw-indicator">True</property> </object> <packing> <property name="expand">False</property> @@ -323,14 +458,14 @@ </packing> </child> <child> - <object class="GtkRadioButton" id="auto_group_radio"> - <property name="label" translatable="yes">Group windows when _space is limited</property> + <object class="GtkRadioButton" id="show_all_radio"> + <property name="label" translatable="yes">Show windows from a_ll workspaces</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - <property name="group">never_group_radio</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> + <property name="group">show_current_radio</property> </object> <packing> <property name="expand">False</property> @@ -338,80 +473,58 @@ <property name="position">1</property> </packing> </child> - <child> - <object class="GtkRadioButton" id="always_group_radio"> - <property name="label" translatable="yes">_Always group windows</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - <property name="group">never_group_radio</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">2</property> - </packing> - </child> </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> - </child> - <child> - <object class="GtkBox" id="minimized_windows_box"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="minimized_windows_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Restoring Minimized Windows</property> - <property name="xalign">0</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> <property name="position">0</property> </packing> </child> <child> - <object class="GtkAlignment" id="alignment3"> + <object class="GtkBox" id="minimized_windows_box"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="left_padding">12</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="minimized_windows_label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes">Restoring Minimized Windows</property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> <child> <object class="GtkBox" id="vbox14"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> + <property name="margin-start">6</property> <property name="orientation">vertical</property> <property name="spacing">6</property> <child> <object class="GtkRadioButton" id="move_minimized_radio"> <property name="label" translatable="yes">Restore to current _workspace</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="use-underline">True</property> + <property name="active">True</property> + <property name="draw-indicator">True</property> </object> <packing> <property name="expand">False</property> @@ -423,10 +536,10 @@ <object class="GtkRadioButton" id="change_workspace_radio"> <property name="label" translatable="yes">Restore to na_tive workspace</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> <property name="group">move_minimized_radio</property> </object> <packing> @@ -436,6 +549,11 @@ </packing> </child> </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> </child> </object> <packing> @@ -446,9 +564,18 @@ </child> </object> <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">4</property> + <property name="position">1</property> + </packing> + </child> + <child type="tab"> + <object class="GtkLabel" id="workspaces_label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes">Workspaces</property> + </object> + <packing> + <property name="position">1</property> + <property name="tab-fill">False</property> </packing> </child> </object> @@ -462,10 +589,7 @@ </child> <action-widgets> <action-widget response="-11">help_button</action-widget> - <action-widget response="0">done_button</action-widget> + <action-widget response="-7">done_button</action-widget> </action-widgets> - <child type="titlebar"> - <placeholder/> - </child> </object> </interface> diff --git a/applets/wncklet/window-menu.c b/applets/wncklet/window-menu.c index 48b1c31b..4b4e48dc 100644 --- a/applets/wncklet/window-menu.c +++ b/applets/wncklet/window-menu.c @@ -26,7 +26,7 @@ */ #ifdef HAVE_CONFIG_H - #include <config.h> +#include <config.h> #endif #include <string.h> @@ -88,13 +88,13 @@ static void window_menu_about(GtkAction* action, WindowMenu* window_menu) "Copyright \xc2\xa9 2001 Free Software Foundation, Inc.\n" "Copyright \xc2\xa9 2003 Sun Microsystems, Inc.\n" "Copyright \xc2\xa9 2011 Perberos\n" - "Copyright \xc2\xa9 2012-2020 MATE developers"), + "Copyright \xc2\xa9 2012-2021 MATE developers"), "documenters", documenters, "icon-name", WINDOW_MENU_ICON, "logo-icon-name", WINDOW_MENU_ICON, "translator-credits", _("translator-credits"), "version", VERSION, - "website", "http://www.mate-desktop.org/", + "website", PACKAGE_URL, NULL); } @@ -218,7 +218,7 @@ static gboolean window_menu_key_press_event(GtkWidget* widget, GdkEventKey* even static gboolean filter_button_press(GtkWidget* widget, GdkEventButton* event, gpointer data) { if (event->button != 1) - g_signal_stop_emission_by_name(widget, "button_press_event"); + g_signal_stop_emission_by_name(widget, "button-press-event"); return FALSE; } @@ -239,7 +239,7 @@ gboolean window_menu_applet_fill(MatePanelApplet* applet) window_menu->orient = mate_panel_applet_get_orient(applet); g_signal_connect(window_menu->applet, "destroy", G_CALLBACK(window_menu_destroy), window_menu); - g_signal_connect(window_menu->applet, "key_press_event", G_CALLBACK(window_menu_key_press_event), window_menu); + g_signal_connect(window_menu->applet, "key-press-event", G_CALLBACK(window_menu_key_press_event), window_menu); action_group = gtk_action_group_new("WindowMenu Applet Actions"); gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE); @@ -253,8 +253,6 @@ gboolean window_menu_applet_fill(MatePanelApplet* applet) if (GDK_IS_X11_DISPLAY (gdk_display_get_default ())) { window_menu->selector = wnck_selector_new(); - mate_panel_applet_set_background_widget(MATE_PANEL_APPLET(window_menu->applet), GTK_WIDGET(window_menu->selector)); - } else #endif /* HAVE_X11 */ @@ -273,13 +271,23 @@ gboolean window_menu_applet_fill(MatePanelApplet* applet) gtk_container_add(GTK_CONTAINER(window_menu->applet), window_menu->selector); - g_signal_connect(window_menu->applet, "size-allocate", G_CALLBACK(window_menu_size_allocate), window_menu); - - g_signal_connect_after(G_OBJECT(window_menu->applet), "focus-in-event", G_CALLBACK(gtk_widget_queue_draw), window_menu); - g_signal_connect_after(G_OBJECT(window_menu->applet), "focus-out-event", G_CALLBACK(gtk_widget_queue_draw), window_menu); - g_signal_connect_after(G_OBJECT(window_menu->selector), "draw", G_CALLBACK(window_menu_on_draw), window_menu); - - g_signal_connect(G_OBJECT(window_menu->selector), "button_press_event", G_CALLBACK(filter_button_press), window_menu); + g_signal_connect (window_menu->applet, "size-allocate", + G_CALLBACK(window_menu_size_allocate), + window_menu); + + g_signal_connect_after (window_menu->applet, "focus-in-event", + G_CALLBACK (gtk_widget_queue_draw), + window_menu); + g_signal_connect_after (window_menu->applet, "focus-out-event", + G_CALLBACK (gtk_widget_queue_draw), + window_menu); + g_signal_connect_after (window_menu->selector, "draw", + G_CALLBACK (window_menu_on_draw), + window_menu); + + g_signal_connect (window_menu->selector, "button_press_event", + G_CALLBACK (filter_button_press), + window_menu); gtk_widget_show_all(GTK_WIDGET(window_menu->applet)); diff --git a/applets/wncklet/wncklet.c b/applets/wncklet/wncklet.c index 67b2ae78..3b185910 100644 --- a/applets/wncklet/wncklet.c +++ b/applets/wncklet/wncklet.c @@ -148,7 +148,6 @@ static gboolean wncklet_factory(MatePanelApplet* applet, const char* iid, gpoint return retval; } - #ifdef WNCKLET_INPROCESS MATE_PANEL_APPLET_IN_PROCESS_FACTORY("WnckletFactory", PANEL_TYPE_APPLET, "WindowNavigationApplets", wncklet_factory, NULL) #else diff --git a/applets/wncklet/workspace-switcher.c b/applets/wncklet/workspace-switcher.c index 2335bb1d..e3fda355 100644 --- a/applets/wncklet/workspace-switcher.c +++ b/applets/wncklet/workspace-switcher.c @@ -53,17 +53,166 @@ #define WORKSPACE_SWITCHER_ICON "mate-panel-workspace-switcher" +/* Container for the WnckPager to work around the sizing issues we have in the + * panel. See + * https://github.com/mate-desktop/mate-panel/issues/1230#issuecomment-1046235088 */ + +typedef struct _PagerContainer PagerContainer; +typedef GtkBinClass PagerContainerClass; + +static GType pager_container_get_type (void); + +#define PAGER_CONTAINER_TYPE (pager_container_get_type ()) +#define PAGER_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PAGER_CONTAINER_TYPE, PagerContainer)) + +struct _PagerContainer +{ + GtkBin parent; + GtkOrientation orientation; + int size; +}; + +G_DEFINE_TYPE (PagerContainer, pager_container, GTK_TYPE_BIN) + +static gboolean +queue_resize_idle_cb (gpointer user_data) +{ + gtk_widget_queue_resize (GTK_WIDGET (user_data)); + return G_SOURCE_REMOVE; +} + +static void +pager_container_get_preferred_width (GtkWidget *widget, + int *minimum_width, + int *natural_width) +{ + PagerContainer *self; + + self = PAGER_CONTAINER (widget); + + if (self->orientation == GTK_ORIENTATION_VERTICAL) + { + /* self->size is panel width */ + *minimum_width = *natural_width = self->size; + } + else + { + /* self->size is panel size/height, that will get allocated to pager, request width for this size */ + gtk_widget_get_preferred_width_for_height (gtk_bin_get_child (GTK_BIN (self)), + self->size, + minimum_width, + natural_width); + } +} + +static void +pager_container_get_preferred_height (GtkWidget *widget, + int *minimum_height, + int *natural_height) +{ + PagerContainer *self; + + self = PAGER_CONTAINER (widget); + + if (self->orientation == GTK_ORIENTATION_VERTICAL) + { + /* self->size is panel size/width that will get allocated to pager, request height for this size */ + gtk_widget_get_preferred_height_for_width (gtk_bin_get_child (GTK_BIN (self)), + self->size, + minimum_height, + natural_height); + } + else + { + /* self->size is panel height */ + *minimum_height = *natural_height = self->size; + } +} + +static void +pager_container_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + PagerContainer *self; + int size; + + self = PAGER_CONTAINER (widget); + + if (self->orientation == GTK_ORIENTATION_VERTICAL) + size = allocation->width; + else + size = allocation->height; + + size = MAX (size, 1); + + if (self->size != size) + { + self->size = size; + g_idle_add (queue_resize_idle_cb, self); + return; + } + + GTK_WIDGET_CLASS (pager_container_parent_class)->size_allocate (widget, + allocation); +} + +static void +pager_container_class_init (PagerContainerClass *self_class) +{ + GtkWidgetClass *widget_class; + + widget_class = GTK_WIDGET_CLASS (self_class); + + widget_class->get_preferred_width = pager_container_get_preferred_width; + widget_class->get_preferred_height = pager_container_get_preferred_height; + widget_class->size_allocate = pager_container_size_allocate; +} + +static void +pager_container_init (PagerContainer *self) +{ +} + +static GtkWidget * +pager_container_new (GtkWidget *child, + GtkOrientation orientation) +{ + PagerContainer *self; + + self = g_object_new (PAGER_CONTAINER_TYPE, "child", child, NULL); + + self->orientation = orientation; + + return GTK_WIDGET (self); +} + +static void +pager_container_set_orientation (PagerContainer *self, + GtkOrientation orientation) +{ + if (self->orientation == orientation) + return; + + self->orientation = orientation; + + gtk_widget_queue_resize (GTK_WIDGET (self)); +} + +/* Pager applet itself */ + typedef enum { PAGER_WM_MARCO, PAGER_WM_METACITY, PAGER_WM_COMPIZ, PAGER_WM_I3, + PAGER_WM_XMONAD, PAGER_WM_UNKNOWN } PagerWM; typedef struct { GtkWidget* applet; + GtkWidget* pager_container; GtkWidget* pager; WnckScreen* screen; @@ -107,7 +256,8 @@ static void pager_update_wnck(PagerData* pager, WnckPager* wnck_pager) if (pager->display_names && ( pager->wm == PAGER_WM_MARCO || pager->wm == PAGER_WM_METACITY || - pager->wm == PAGER_WM_I3)) + pager->wm == PAGER_WM_I3 || + pager->wm == PAGER_WM_XMONAD)) { display_mode = WNCK_PAGER_DISPLAY_NAME; } @@ -171,6 +321,20 @@ static void update_properties_for_wm(PagerData* pager) if (pager->cell) g_object_set (pager->cell, "editable", FALSE, NULL); break; + case PAGER_WM_XMONAD: + if (pager->workspaces_frame) + gtk_widget_show(pager->workspaces_frame); + if (pager->num_workspaces_spin) + gtk_widget_set_sensitive(pager->num_workspaces_spin, FALSE); + if (pager->workspace_names_label) + gtk_widget_hide(pager->workspace_names_label); + if (pager->workspace_names_scroll) + gtk_widget_hide(pager->workspace_names_scroll); + if (pager->display_workspaces_toggle) + gtk_widget_show(pager->display_workspaces_toggle); + if (pager->cell) + g_object_set (pager->cell, "editable", FALSE, NULL); + break; case PAGER_WM_COMPIZ: if (pager->workspaces_frame) gtk_widget_show(pager->workspaces_frame); @@ -200,14 +364,13 @@ static void update_properties_for_wm(PagerData* pager) static void window_manager_changed(WnckScreen* screen, PagerData* pager) { +#ifdef HAVE_X11 const char *wm_name = NULL; -#ifdef HAVE_X11 if (pager->screen) { wm_name = wnck_screen_get_window_manager_name (pager->screen); } -#endif /* HAVE_X11 */ if (!wm_name) pager->wm = PAGER_WM_UNKNOWN; @@ -217,10 +380,15 @@ static void window_manager_changed(WnckScreen* screen, PagerData* pager) pager->wm = PAGER_WM_METACITY; else if (strcmp(wm_name, "i3") == 0) pager->wm = PAGER_WM_I3; + else if (strcmp(wm_name, "xmonad") == 0) + pager->wm = PAGER_WM_XMONAD; else if (strcmp(wm_name, "Compiz") == 0) pager->wm = PAGER_WM_COMPIZ; else pager->wm = PAGER_WM_UNKNOWN; +#else + pager->wm = PAGER_WM_UNKNOWN; +#endif /* HAVE_X11 */ update_properties_for_wm(pager); pager_update(pager); @@ -270,6 +438,8 @@ static void applet_change_orient(MatePanelApplet* applet, MatePanelAppletOrient pager->orientation = new_orient; pager_update(pager); + pager_container_set_orientation(PAGER_CONTAINER(pager->pager_container), pager->orientation); + if (pager->label_row_col) gtk_label_set_text(GTK_LABEL(pager->label_row_col), pager->orientation == GTK_ORIENTATION_HORIZONTAL ? _("rows") : _("columns")); } @@ -321,11 +491,13 @@ static void applet_style_updated (MatePanelApplet *applet, GtkStyleContext *cont */ static gboolean applet_scroll(MatePanelApplet* applet, GdkEventScroll* event, PagerData* pager) { +#ifdef HAVE_X11 GdkScrollDirection absolute_direction; int index; int n_workspaces; int n_columns; int in_last_row; +#endif /* HAVE_X11 */ if (event->type != GDK_SCROLL) return FALSE; @@ -340,7 +512,6 @@ static gboolean applet_scroll(MatePanelApplet* applet, GdkEventScroll* event, Pa n_workspaces = wnck_screen_get_workspace_count(pager->screen); } else -#endif /* HAVE_X11 */ { index = 0; n_workspaces = 1; @@ -431,7 +602,6 @@ static gboolean applet_scroll(MatePanelApplet* applet, GdkEventScroll* event, Pa break; } -#ifdef HAVE_X11 if (pager->screen) { wnck_workspace_activate(wnck_screen_get_workspace(pager->screen, index), event->time); @@ -470,11 +640,12 @@ static const GtkActionEntry pager_menu_actions[] = { static void num_rows_changed(GSettings* settings, gchar* key, PagerData* pager) { - int n_rows = DEFAULT_ROWS; + int n_rows; - n_rows = g_settings_get_int (settings, key); - - n_rows = CLAMP(n_rows, 1, MAX_REASONABLE_ROWS); + n_rows = CLAMP (g_settings_get_int (settings, key), + 1, + MIN (wnck_screen_get_workspace_count (pager->screen), + MAX_REASONABLE_ROWS)); pager->n_rows = n_rows; pager_update(pager); @@ -499,12 +670,9 @@ static void display_workspace_names_changed(GSettings* settings, gchar* key, Pag } } - static void all_workspaces_changed(GSettings* settings, gchar* key, PagerData* pager) { - gboolean value = TRUE; /* Default value */ - - value = g_settings_get_boolean (settings, key); + gboolean value = g_settings_get_boolean (settings, key); pager->display_all = value; pager_update(pager); @@ -630,23 +798,37 @@ gboolean workspace_switcher_applet_fill(MatePanelApplet* applet) context = gtk_widget_get_style_context (pager->pager); gtk_style_context_add_class (context, "wnck-pager"); - g_signal_connect(G_OBJECT(pager->pager), "destroy", G_CALLBACK(destroy_pager), pager); + g_signal_connect (pager->pager, "destroy", + G_CALLBACK (destroy_pager), + pager); /* overwrite default WnckPager widget scroll-event */ - g_signal_connect(G_OBJECT(pager->pager), "scroll-event", G_CALLBACK(applet_scroll), pager); - - gtk_container_add(GTK_CONTAINER(pager->applet), pager->pager); - - g_signal_connect(G_OBJECT(pager->applet), "realize", G_CALLBACK(applet_realized), pager); - g_signal_connect(G_OBJECT(pager->applet), "unrealize", G_CALLBACK(applet_unrealized), pager); - g_signal_connect(G_OBJECT(pager->applet), "change_orient", G_CALLBACK(applet_change_orient), pager); - g_signal_connect(G_OBJECT(pager->applet), "change_background", G_CALLBACK(applet_change_background), pager); - g_signal_connect(G_OBJECT(pager->applet), "style-updated", G_CALLBACK(applet_style_updated), context); - - gtk_widget_show(pager->pager); - gtk_widget_show(pager->applet); - - mate_panel_applet_set_background_widget(MATE_PANEL_APPLET(pager->applet), GTK_WIDGET(pager->applet)); + g_signal_connect (pager->pager, "scroll-event", + G_CALLBACK (applet_scroll), + pager); + + pager->pager_container = pager_container_new(pager->pager, pager->orientation); + gtk_container_add(GTK_CONTAINER(pager->applet), pager->pager_container); + + g_signal_connect (pager->applet, "realize", + G_CALLBACK (applet_realized), + pager); + g_signal_connect (pager->applet, "unrealize", + G_CALLBACK (applet_unrealized), + pager); + g_signal_connect (pager->applet, "change-orient", + G_CALLBACK (applet_change_orient), + pager); + g_signal_connect (pager->applet, "change-background", + G_CALLBACK (applet_change_background), + pager); + g_signal_connect (pager->applet, "style-updated", + G_CALLBACK (applet_style_updated), + context); + + gtk_widget_show (pager->pager); + gtk_widget_show (pager->pager_container); + gtk_widget_show (pager->applet); action_group = gtk_action_group_new("WorkspaceSwitcher Applet Actions"); gtk_action_group_set_translation_domain(action_group, GETTEXT_PACKAGE); @@ -668,7 +850,6 @@ gboolean workspace_switcher_applet_fill(MatePanelApplet* applet) return TRUE; } - static void display_help_dialog(GtkAction* action, PagerData* pager) { wncklet_display_help(pager->applet, "mate-user-guide", "overview-workspaces", WORKSPACE_SWITCHER_ICON); @@ -697,13 +878,13 @@ static void display_about_dialog(GtkAction* action, PagerData* pager) "comments", _("The Workspace Switcher shows you a small version of your workspaces that lets you manage your windows."), "copyright", _("Copyright \xc2\xa9 2002 Red Hat, Inc.\n" "Copyright \xc2\xa9 2011 Perberos\n" - "Copyright \xc2\xa9 2012-2020 MATE developers"), + "Copyright \xc2\xa9 2012-2021 MATE developers"), "documenters", documenters, "icon-name", WORKSPACE_SWITCHER_ICON, "logo-icon-name", WORKSPACE_SWITCHER_ICON, "translator-credits", _("translator-credits"), "version", VERSION, - "website", "http://www.mate-desktop.org/", + "website", PACKAGE_URL, NULL); } @@ -796,13 +977,17 @@ static void workspace_destroyed(WnckScreen* screen, WnckWorkspace* space, PagerD } #endif /* HAVE_X11 */ -static void num_workspaces_value_changed(GtkSpinButton* button, PagerData* pager) +static void +on_num_workspaces_value_changed (GtkSpinButton *button, + PagerData *pager) { #ifdef HAVE_X11 if (pager->screen) { - int workspace_count = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(pager->num_workspaces_spin)); + int workspace_count = gtk_spin_button_get_value_as_int (button); wnck_screen_change_workspace_count(pager->screen, workspace_count); + if (workspace_count < pager->n_rows) + g_settings_set_int (pager->settings, "num-rows", workspace_count); } #endif /* HAVE_X11 */ } @@ -978,7 +1163,6 @@ static void setup_dialog(GtkBuilder* builder, PagerData* pager) if (marco_workspaces_settings != NULL) g_object_unref (marco_workspaces_settings); - /* Wrap workspaces: */ if (pager->wrap_workspaces_toggle) { @@ -986,18 +1170,24 @@ static void setup_dialog(GtkBuilder* builder, PagerData* pager) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pager->wrap_workspaces_toggle), pager->wrap_workspaces); } - g_signal_connect(G_OBJECT(pager->wrap_workspaces_toggle), "toggled", (GCallback) wrap_workspaces_toggled, pager); + g_signal_connect (pager->wrap_workspaces_toggle, "toggled", + (GCallback) wrap_workspaces_toggled, + pager); /* Display workspace names: */ - g_signal_connect(G_OBJECT(pager->display_workspaces_toggle), "toggled", (GCallback) display_workspace_names_toggled, pager); + g_signal_connect (pager->display_workspaces_toggle, "toggled", + (GCallback) display_workspace_names_toggled, + pager); value = pager->display_names; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pager->display_workspaces_toggle), value); /* Display all workspaces: */ - g_signal_connect(G_OBJECT(pager->all_workspaces_radio), "toggled", (GCallback) all_workspaces_toggled, pager); + g_signal_connect (pager->all_workspaces_radio, "toggled", + (GCallback) all_workspaces_toggled, + pager); if (pager->display_all) { @@ -1015,13 +1205,13 @@ static void setup_dialog(GtkBuilder* builder, PagerData* pager) } /* Num rows: */ - g_signal_connect(G_OBJECT(pager->num_rows_spin), "value_changed", (GCallback) num_rows_value_changed, pager); + g_signal_connect (pager->num_rows_spin, "value-changed", G_CALLBACK (num_rows_value_changed), pager); gtk_spin_button_set_value(GTK_SPIN_BUTTON(pager->num_rows_spin), pager->n_rows); gtk_label_set_text(GTK_LABEL(pager->label_row_col), pager->orientation == GTK_ORIENTATION_HORIZONTAL ? _("rows") : _("columns")); g_signal_connect(pager->properties_dialog, "destroy", G_CALLBACK(properties_dialog_destroyed), pager); - g_signal_connect(pager->properties_dialog, "delete_event", G_CALLBACK(delete_event), pager); + g_signal_connect(pager->properties_dialog, "delete-event", G_CALLBACK(delete_event), pager); g_signal_connect(pager->properties_dialog, "response", G_CALLBACK(response_cb), pager); g_signal_connect(WID("done_button"), "clicked", (GCallback) close_dialog, pager); @@ -1043,9 +1233,13 @@ static void setup_dialog(GtkBuilder* builder, PagerData* pager) } #endif /* HAVE_X11 */ - g_signal_connect(G_OBJECT(pager->num_workspaces_spin), "value_changed", (GCallback) num_workspaces_value_changed, pager); + g_signal_connect (pager->num_workspaces_spin, "value-changed", + G_CALLBACK (on_num_workspaces_value_changed), + pager); - g_signal_connect(G_OBJECT(pager->workspaces_tree), "focus_out_event", (GCallback) workspaces_tree_focused_out, pager); + g_signal_connect (pager->workspaces_tree, "focus-out-event", + (GCallback) workspaces_tree_focused_out, + pager); pager->workspaces_store = gtk_list_store_new(1, G_TYPE_STRING, NULL); update_workspaces_model(pager); |