diff options
Diffstat (limited to 'applets/wncklet')
-rw-r--r-- | applets/wncklet/Makefile.am | 2 | ||||
-rw-r--r-- | applets/wncklet/org.mate.panel.applet.window-list.gschema.xml.in | 10 | ||||
-rw-r--r-- | applets/wncklet/showdesktop.c | 60 | ||||
-rw-r--r-- | applets/wncklet/showdesktop.h | 1 | ||||
-rw-r--r-- | applets/wncklet/wayland-backend.c | 395 | ||||
-rw-r--r-- | applets/wncklet/wayland-backend.h | 2 | ||||
-rw-r--r-- | applets/wncklet/window-list.c | 273 | ||||
-rw-r--r-- | applets/wncklet/window-list.ui | 618 | ||||
-rw-r--r-- | applets/wncklet/window-menu.c | 28 | ||||
-rw-r--r-- | applets/wncklet/wncklet.c | 1 | ||||
-rw-r--r-- | applets/wncklet/workspace-switcher.c | 252 |
11 files changed, 1250 insertions, 392 deletions
diff --git a/applets/wncklet/Makefile.am b/applets/wncklet/Makefile.am index ed442671..14f8a5c7 100644 --- a/applets/wncklet/Makefile.am +++ b/applets/wncklet/Makefile.am @@ -78,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 aabc1a63..190077f1 100644 --- a/applets/wncklet/showdesktop.c +++ b/applets/wncklet/showdesktop.c @@ -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,21 +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); + 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); @@ -466,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); @@ -552,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)); @@ -573,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 a6f50a77..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"; @@ -57,6 +77,8 @@ static uint32_t foreign_toplevel_manager_global_version = 0; 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, @@ -119,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 @@ -161,6 +183,74 @@ 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 * @@ -170,7 +260,7 @@ tasklist_manager_new (void) 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); @@ -186,6 +276,7 @@ tasklist_manager_new (void) tasklist_manager_key, tasklist, (GDestroyNotify)tasklist_manager_disconnected_from_widget); + tasklist->context_menu = context_menu_new (); return tasklist; } @@ -207,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 @@ -234,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) @@ -243,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; } @@ -264,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, @@ -285,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; @@ -313,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 @@ -332,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, @@ -353,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 ce3ddbb4..a87649b1 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; @@ -86,6 +88,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; @@ -135,6 +139,8 @@ static void tasklist_update(TasklistData* tasklist) 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 */ @@ -252,7 +258,6 @@ preview_window_thumbnail (WnckWindow *wnck_window, int *thumbnail_scale) { GdkWindow *window; - GdkWindow *window_wrapper = NULL; Window win; cairo_surface_t *thumbnail; cairo_t *cr; @@ -261,20 +266,9 @@ preview_window_thumbnail (WnckWindow *wnck_window, win = wnck_window_get_xid (wnck_window); - if ((window = gdk_x11_window_lookup_for_display (gdk_display_get_default (), win)) == NULL) + if ((window = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), win)) == NULL) { - if ((window = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), win)) == NULL) - { - return NULL; - } - else - { - window_wrapper = window; - } - } - else - { - g_object_ref (window); + return NULL; } *thumbnail_scale = scale = gdk_window_get_scale_factor (window); @@ -297,6 +291,8 @@ preview_window_thumbnail (WnckWindow *wnck_window, *thumbnail_width = (int) ((double) width * ratio); } + gdk_x11_display_error_trap_push (gdk_window_get_display (window)); + thumbnail = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, *thumbnail_width, *thumbnail_height); @@ -307,44 +303,81 @@ preview_window_thumbnail (WnckWindow *wnck_window, cairo_paint (cr); cairo_destroy (cr); - if (window_wrapper) - g_object_unref (window_wrapper); + 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, - cairo_surface_t *thumbnail, +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; + MatePanelAppletOrient orient; + gdouble x_pos, y_pos; + int x_offset, y_offset; - /* 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/scale + 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/scale + 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: @@ -352,6 +385,56 @@ preview_window_reposition (TasklistData *tasklist, 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); } @@ -411,12 +494,14 @@ static gboolean applet_enter_notify_event (WnckTasklist *tl, GList *wnck_windows 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, thumbnail_width, thumbnail_height, thumbnail_scale); + 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 (cairo_surface_destroy), 0); + g_signal_connect_data (tasklist->preview, "draw", + G_CALLBACK (preview_window_draw), thumbnail, + (GClosureNotify) G_CALLBACK (cairo_surface_destroy), + 0); return FALSE; } @@ -533,6 +618,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); @@ -595,7 +685,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; @@ -608,6 +697,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); @@ -621,6 +722,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); @@ -633,6 +739,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) @@ -756,6 +870,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) @@ -780,12 +898,15 @@ 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 @@ -805,25 +926,36 @@ 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); + g_signal_connect (tasklist->applet, "realize", + G_CALLBACK (applet_realized), + tasklist); + 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) { @@ -845,7 +977,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); @@ -869,7 +1000,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) { @@ -887,7 +1018,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); @@ -1000,9 +1130,6 @@ 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"); @@ -1033,16 +1160,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"); @@ -1056,26 +1181,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 765b5b68..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,165 +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> - <child> - <object class="GtkLabel" id="wayland_info_label"> - <property name="visible">False</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Some options not available on Wayland</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="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">1</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> @@ -232,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="GtkLabel" id="middle_click_close_label"> + <property name="visible">True</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="hbox1"> + <object class="GtkBox" id="middle_click_close_vbox"> <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="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> @@ -255,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">2</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> - <child> - <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> + <property name="spacing">18</property> <child> - <object class="GtkAlignment" id="alignment2"> + <object class="GtkBox" id="window_list_content_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="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> @@ -339,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> @@ -354,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> @@ -439,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> @@ -452,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> @@ -462,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> @@ -478,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 804898d8..4b4e48dc 100644 --- a/applets/wncklet/window-menu.c +++ b/applets/wncklet/window-menu.c @@ -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); @@ -271,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 22b473bd..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); @@ -216,6 +380,8 @@ 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 @@ -272,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")); } @@ -472,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; - - n_rows = g_settings_get_int (settings, key); + int n_rows; - 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); @@ -501,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); @@ -632,21 +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); + 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); @@ -805,6 +986,8 @@ on_num_workspaces_value_changed (GtkSpinButton *button, { 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 */ } @@ -980,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) { @@ -988,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) { @@ -1023,7 +1211,7 @@ static void setup_dialog(GtkBuilder* builder, PagerData* pager) 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); @@ -1045,9 +1233,13 @@ static void setup_dialog(GtkBuilder* builder, PagerData* pager) } #endif /* HAVE_X11 */ - g_signal_connect (pager->num_workspaces_spin, "value-changed", G_CALLBACK (on_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); |