summaryrefslogtreecommitdiff
path: root/applets/wncklet
diff options
context:
space:
mode:
Diffstat (limited to 'applets/wncklet')
-rw-r--r--applets/wncklet/Makefile.am28
-rw-r--r--applets/wncklet/org.mate.panel.Wncklet.mate-panel-applet.desktop.in.in2
-rw-r--r--applets/wncklet/showdesktop.c75
-rw-r--r--applets/wncklet/wayland-backend.c411
-rw-r--r--applets/wncklet/wayland-backend.h1
-rw-r--r--applets/wncklet/window-list.c146
-rw-r--r--applets/wncklet/window-list.ui1
-rw-r--r--applets/wncklet/window-menu.c13
-rw-r--r--applets/wncklet/wncklet.c27
-rw-r--r--applets/wncklet/wncklet.h7
-rw-r--r--applets/wncklet/workspace-switcher.c171
11 files changed, 726 insertions, 156 deletions
diff --git a/applets/wncklet/Makefile.am b/applets/wncklet/Makefile.am
index ed442671..a59b1192 100644
--- a/applets/wncklet/Makefile.am
+++ b/applets/wncklet/Makefile.am
@@ -19,12 +19,18 @@ WNCKLET_SOURCES = \
window-menu.h \
window-list.c \
window-list.h \
- workspace-switcher.c \
- workspace-switcher.h \
showdesktop.c \
showdesktop.h \
$(BUILT_SOURCES)
+if ENABLE_X11
+WNCKLET_SOURCES += \
+ workspace-switcher.c \
+ workspace-switcher.h
+endif
+
+
+
WNCKLET_LDADD = \
../../libmate-panel-applet/libmate-panel-applet-4.la \
$(WNCKLET_LIBS) \
@@ -78,9 +84,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)
@@ -93,10 +99,18 @@ ui_FILES = \
showdesktop-menu.xml \
window-list-menu.xml \
window-list.ui \
- window-menu-menu.xml \
+ window-menu-menu.xml
+
+if ENABLE_X11
+ui_FILES += \
workspace-switcher-menu.xml \
workspace-switcher.ui
+endif
+
+
+
+
wncklet-resources.c: wncklet.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/wncklet.gresource.xml)
$(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --generate --c-name wncklet $<
@@ -107,16 +121,10 @@ BUILT_SOURCES = \
wncklet-resources.c \
wncklet-resources.h
-if HAVE_WINDOW_PREVIEWS
wncklet_gschemas_in = \
org.mate.panel.applet.window-list.gschema.xml.in \
org.mate.panel.applet.window-list-previews.gschema.xml.in \
org.mate.panel.applet.workspace-switcher.gschema.xml.in
-else
-wncklet_gschemas_in = \
- org.mate.panel.applet.window-list.gschema.xml.in \
- org.mate.panel.applet.workspace-switcher.gschema.xml.in
-endif
gsettings_SCHEMAS = $(wncklet_gschemas_in:.xml.in=.xml)
@GSETTINGS_RULES@
diff --git a/applets/wncklet/org.mate.panel.Wncklet.mate-panel-applet.desktop.in.in b/applets/wncklet/org.mate.panel.Wncklet.mate-panel-applet.desktop.in.in
index 99e7815c..ec53ade3 100644
--- a/applets/wncklet/org.mate.panel.Wncklet.mate-panel-applet.desktop.in.in
+++ b/applets/wncklet/org.mate.panel.Wncklet.mate-panel-applet.desktop.in.in
@@ -50,7 +50,7 @@ Description=Hide application windows and show the desktop
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=user-desktop
MateComponentId=OAFIID:MATE_ShowDesktopApplet;
-Platforms=X11;
+Platforms=X11;Wayland;
X-MATE-Bugzilla-Bugzilla=MATE
X-MATE-Bugzilla-Product=mate-panel
X-MATE-Bugzilla-Component=Show Desktop Button
diff --git a/applets/wncklet/showdesktop.c b/applets/wncklet/showdesktop.c
index 190077f1..882e55d6 100644
--- a/applets/wncklet/showdesktop.c
+++ b/applets/wncklet/showdesktop.c
@@ -35,11 +35,21 @@
#include <libwnck/libwnck.h>
#endif
+#ifndef HAVE_X11
+#include <gdk/gdkwayland.h>
+#define GDK_IS_X11_DISPLAY(object) !(G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DISPLAY))
+#endif
+
#include "wncklet.h"
#include "showdesktop.h"
#include <string.h>
+#ifdef HAVE_WAYLAND
+#include "wayland-protocol/wlr-foreign-toplevel-management-unstable-v1-client.h"
+#include "wayland-backend.h"
+#include <gdk/gdkwayland.h>
+#endif
#define TIMEOUT_ACTIVATE_SECONDS 1
#define SHOW_DESKTOP_ICON "user-desktop"
@@ -52,6 +62,9 @@ typedef struct {
GtkOrientation orient;
int size;
+#ifdef HAVE_X11
+ WnckHandle* wnck_handle;
+#endif
WnckScreen* wnck_screen;
guint showing_desktop: 1;
@@ -72,6 +85,11 @@ static void theme_changed_callback(GtkIconTheme* icon_theme, ShowDesktopData* sd
static void button_toggled_callback(GtkWidget* button, ShowDesktopData* sdd);
static void show_desktop_changed_callback(WnckScreen* screen, ShowDesktopData* sdd);
+#ifdef HAVE_WAYLAND
+GtkWidget* tasklist;
+gboolean desktop_showing;
+#endif
+
/* this is when the panel orientation changes */
static void applet_change_orient(MatePanelApplet* applet, MatePanelAppletOrient orient, ShowDesktopData* sdd)
@@ -308,6 +326,10 @@ static void applet_destroyed(GtkWidget* applet, ShowDesktopData* sdd)
sdd->icon_theme = NULL;
}
+#ifdef HAVE_X11
+ g_clear_object(&sdd->wnck_handle);
+#endif
+
g_free (sdd);
}
@@ -371,7 +393,7 @@ 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 = wncklet_get_screen (sdd->wnck_handle, sdd->applet);
if (sdd->wnck_screen != NULL)
wncklet_connect_while_alive (sdd->wnck_screen,
"showing_desktop_changed",
@@ -382,7 +404,14 @@ static void show_desktop_applet_realized(MatePanelApplet* applet, gpointer data)
g_warning ("Could not get WnckScreen!");
}
#endif /* HAVE_X11 */
-
+#ifdef HAVE_WAYLAND
+if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()))
+{
+ /*/initialize wayland show desktop applet*/
+ tasklist = wayland_tasklist_new();
+ desktop_showing = FALSE;
+}
+#endif
show_desktop_changed_callback (sdd->wnck_screen, sdd);
sdd->icon_theme = gtk_icon_theme_get_for_screen (screen);
@@ -426,6 +455,13 @@ gboolean show_desktop_applet_fill(MatePanelApplet* applet)
sdd->size = mate_panel_applet_get_size(MATE_PANEL_APPLET(sdd->applet));
+#ifdef HAVE_X11
+ if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
+ {
+ sdd->wnck_handle = wnck_handle_new(WNCK_CLIENT_TYPE_PAGER);
+ }
+#endif
+
g_signal_connect (sdd->applet, "realize",
G_CALLBACK (show_desktop_applet_realized),
sdd);
@@ -545,9 +581,39 @@ static void button_toggled_callback(GtkWidget* button, ShowDesktopData* sdd)
gdk_atom_intern("_NET_SHOWING_DESKTOP",
FALSE));
}
- else
+#ifdef HAVE_WAYLAND
+ else if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()))
+#endif
#endif
- { /* not using X11 */
+#ifdef HAVE_WAYLAND
+#ifndef HAVE_X11
+ if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()))
+#endif
+ {
+ static GtkWidget* outer_box;
+ GList *children1, *children2;
+ if (desktop_showing == FALSE)
+ desktop_showing = TRUE;
+
+ else
+ desktop_showing = FALSE;
+
+ can_show_desktop = TRUE;
+ children1 = gtk_container_get_children (GTK_CONTAINER (tasklist));
+ outer_box = g_list_first(children1)->data;
+ children2 = gtk_container_get_children (GTK_CONTAINER (outer_box));
+ while (children2 != NULL)
+ {
+ button = GTK_WIDGET (children2->data);
+ toggle_show_desktop (button, desktop_showing);
+ children2 = children2->next;
+ }
+ }
+#endif
+
+else
+
+ { /* not using X11 or wayland */
can_show_desktop = FALSE;
}
@@ -588,6 +654,7 @@ static void button_toggled_callback(GtkWidget* button, ShowDesktopData* sdd)
wnck_screen_toggle_showing_desktop(sdd->wnck_screen, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
#endif /* HAVE_X11 */
+
update_button_display (sdd);
}
diff --git a/applets/wncklet/wayland-backend.c b/applets/wncklet/wayland-backend.c
index f82b7fee..30469894 100644
--- a/applets/wncklet/wayland-backend.c
+++ b/applets/wncklet/wayland-backend.c
@@ -26,27 +26,50 @@
#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;
+int full_button_width;
+
+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 int tasklist_invocations = 0;
+
static const char *tasklist_manager_key = "tasklist_manager";
static const char *toplevel_task_key = "toplevel_task";
@@ -57,6 +80,10 @@ 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;
+
+gboolean window_hidden;
+
static void
wl_registry_handle_global (void *_data,
struct wl_registry *registry,
@@ -119,7 +146,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 +188,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 +265,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 +281,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 +303,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 +350,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 +362,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;
}
@@ -260,12 +387,143 @@ foreign_toplevel_handle_done (void *data,
}
static void
+adjust_buttons (GtkContainer *outer_box, int button_space, int real_buttons, ToplevelTask *task)
+{
+ GtkWidget *widget, *button, *box;
+
+ /*catch the case of an added button that can be missed
+ *Note that button space can come up zero on a first button
+ */
+ if (real_buttons < 2)
+ {
+ if(task)
+ {
+ gtk_widget_set_size_request (task->button, full_button_width, -1);
+ }
+ }
+
+ if ((task) && (button_space > 0) && (button_space < icon_size * 3))
+ {
+ gtk_widget_hide (task->icon);
+ }
+ else if (task)
+ {
+ gtk_widget_show (task->icon);
+ }
+
+ if ((task) && (button_space > 0) && (button_space < icon_size))
+ {
+ gtk_widget_hide (task->label);
+ }
+ else if (task)
+ {
+ gtk_widget_show (task->label);
+ }
+
+ 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));
+
+ if ((real_buttons < 2) || (real_buttons * full_button_width < tasklist_width * 0.75))
+ {
+ gtk_widget_set_size_request (button, full_button_width, -1);
+ gtk_widget_show_all (button);
+ return;
+ }
+ else
+ {
+ gtk_widget_set_size_request (button, MIN(button_space, full_button_width), -1);
+ }
+
+ /* if the number of buttons forces width to less than 3x the icon size, hide the icons
+ * if the number of buttons forces width to less than the icon size, hide the labels too.
+ * This is roughy the same behavior as on x11
+ * To find the icon and label we must iterate through the children of the box we packed
+ * into the button, there are two of them
+ */
+
+ GList* contents = gtk_container_get_children (GTK_CONTAINER (box));
+ while (contents != NULL)
+ {
+ widget = GTK_WIDGET (contents->data);
+ /*Show or hide the icon*/
+ if (GTK_IS_IMAGE (widget))
+ {
+ if ((button_space < icon_size * 3) && (button_space > 1))
+ gtk_widget_hide (widget);
+
+ else
+ gtk_widget_show (widget);
+
+ }
+
+ /*Show or hide the label*/
+ if (GTK_IS_LABEL (widget))
+ {
+ if ((button_space < icon_size) && (button_space > 1))
+ {
+ gtk_widget_hide (widget);
+ /*We can go a little wider for empty buttons*/
+ gtk_widget_set_size_request (button, tasklist_width / real_buttons * 0.9, -1);
+ if (task)
+ gtk_widget_hide (task->label);
+
+ }
+ else
+ {
+ gtk_widget_show (widget);
+ }
+ }
+ contents = contents->next;
+ }
+ children = children->next;
+ }
+ return;
+}
+
+static void
foreign_toplevel_handle_closed (void *data,
struct zwlr_foreign_toplevel_handle_v1 *toplevel)
{
ToplevelTask *task = data;
+
if (task->button)
+ {
+ GtkOrientation orient;
+ GtkWidget *outer_box, *parent_box;
+ int real_buttons, button_space;
+
+ outer_box = gtk_widget_get_parent (GTK_WIDGET (task->button));
gtk_widget_destroy (task->button);
+ buttons = buttons -1;
+
+ if (tasklist_invocations > 1)
+ real_buttons = buttons / 2;
+
+ else
+ real_buttons = buttons;
+
+ if (real_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;
+
+ /*Get the box the tasklist outer box sits in
+ *and leave a little space so the buttons don't push other applets off the panel
+ */
+
+ parent_box = gtk_widget_get_ancestor ((outer_box), GTK_TYPE_BOX);
+ tasklist_width = MAX(gtk_widget_get_allocated_width (parent_box), tasklist_width) ;
+ button_space = (tasklist_width / real_buttons) * 0.75;
+ button_space = MIN(button_space, full_button_width);
+ adjust_buttons (GTK_CONTAINER(outer_box), button_space, real_buttons, NULL);
+ }
}
static const struct zwlr_foreign_toplevel_handle_v1_listener foreign_toplevel_handle_listener = {
@@ -284,6 +542,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;
@@ -293,6 +552,34 @@ toplevel_task_disconnected_from_widget (ToplevelTask *task)
g_free (task);
}
+/*We have to use the "activate" signal here
+ *as only signals valid for GtkButton work,
+ *"clicked" is taken, and we need to separate
+ *showing the desktop from mouse clicks on window buttons
+ */
+void
+toggle_show_desktop(GtkWidget *button, gboolean desktop_showing)
+{
+ window_hidden = desktop_showing;
+ g_signal_emit_by_name (button, "activate");
+}
+
+static void
+toggle_window(GtkButton *button, ToplevelTask *task)
+{
+ if (task->toplevel)
+ {
+ if (window_hidden)
+ {
+ zwlr_foreign_toplevel_handle_v1_set_minimized (task->toplevel);
+ }
+ else
+ {
+ zwlr_foreign_toplevel_handle_v1_unset_minimized (task->toplevel);
+ }
+ }
+}
+
static void
toplevel_task_handle_clicked (GtkButton *button, ToplevelTask *task)
{
@@ -312,13 +599,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
@@ -331,16 +630,29 @@ static ToplevelTask *
toplevel_task_new (TasklistManager *tasklist, struct zwlr_foreign_toplevel_handle_v1 *toplevel)
{
ToplevelTask *task = g_new0 (ToplevelTask, 1);
+ GtkOrientation orient;
+ GtkWidget *whole_panel_box, *parent_box;
+ int real_buttons, button_space, panel_width;
+ 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);
+ g_signal_connect (task->button, "activate", G_CALLBACK (toggle_window), 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);
task->toplevel = toplevel;
@@ -354,8 +666,81 @@ toplevel_task_new (TasklistManager *tasklist, struct zwlr_foreign_toplevel_handl
g_signal_connect (task->button, "button-press-event",
G_CALLBACK (on_toplevel_button_press),
- task);
+ tasklist);
+
+ /* 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)
+ 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
+ * For some reason this function always gets called twice, so use half the value of buttons
+ * but do not attempt to adjust the global value as it would get adjusted twice
+ * Since we are adding a button here the true value cannot be zero
+ */
+ whole_panel_box = gtk_widget_get_toplevel(GTK_WIDGET (tasklist->outer_box));
+ parent_box = gtk_widget_get_ancestor(GTK_WIDGET (tasklist->outer_box), GTK_TYPE_BOX);
+ if (gtk_widget_get_allocated_width (parent_box) > 1)
+ {
+ tasklist_width = gtk_widget_get_allocated_width (parent_box);
+ }
+ else
+ {
+ tasklist_width = MAX(gtk_widget_get_allocated_width (parent_box), tasklist_width);
+ }
+
+ panel_width = gtk_widget_get_allocated_width (whole_panel_box);
+ /*on startup we get an allocated with of zero, so start with 1/3 the panel width
+ *as a sane default
+ *This may overflow on very crowded panels where the tasklist is less than 1/3ed the
+ *panel witth but will self-correct on opening or closing a few windows
+ */
+
+ if (tasklist_width <= 2)
+ tasklist_width = panel_width / 3;
+
+ if (tasklist_invocations > 1)
+ real_buttons = MAX ((buttons / 2), 1);
+
+ else
+ real_buttons = MAX ((buttons), 1);
+
+ /*always allow at least three buttons to fit without adjustment
+ *so short window lists don't overflow
+ */
+ if (tasklist_width > 0)
+ {
+ full_button_width = MIN(max_button_width, tasklist_width / 3);
+ }
+
+ /*Leave a little space so the buttons don't push other applets off the panel*/
+ button_space = (tasklist_width / real_buttons) * 0.75;
+ button_space = MIN(button_space, full_button_width);
+
+ /* iterate over all the buttons*/
+ adjust_buttons (GTK_CONTAINER (tasklist->list), button_space, real_buttons, task);
+
+ /*Reset the tasklist width after button adjustments*/
+ if (gtk_widget_get_allocated_width (parent_box) > 1)
+ {
+ tasklist_width = gtk_widget_get_allocated_width (parent_box);
+ }
+ else
+ {
+ tasklist_width = MAX(gtk_widget_get_allocated_width (parent_box), tasklist_width);
+ }
return task;
}
@@ -364,6 +749,8 @@ wayland_tasklist_new ()
{
wayland_tasklist_init_if_needed ();
TasklistManager *tasklist = tasklist_manager_new ();
+
+ tasklist_invocations = tasklist_invocations + 1;
if (!tasklist)
return gtk_label_new ("Shell does not support WLR Foreign Toplevel Control");
return tasklist->outer_box;
diff --git a/applets/wncklet/wayland-backend.h b/applets/wncklet/wayland-backend.h
index e2402236..0bff2b5f 100644
--- a/applets/wncklet/wayland-backend.h
+++ b/applets/wncklet/wayland-backend.h
@@ -35,6 +35,7 @@
extern "C" {
#endif
+void toggle_show_desktop(GtkWidget *button, gboolean desktop_showing);
GtkWidget* wayland_tasklist_new (void);
void wayland_tasklist_set_orientation (GtkWidget* tasklist_widget, GtkOrientation orient);
diff --git a/applets/wncklet/window-list.c b/applets/wncklet/window-list.c
index 85c305d4..17821cdd 100644
--- a/applets/wncklet/window-list.c
+++ b/applets/wncklet/window-list.c
@@ -25,6 +25,11 @@
#include <libwnck/libwnck.h>
#endif /* HAVE_X11 */
+#ifndef HAVE_X11
+#include <gdk/gdkwayland.h>
+#define GDK_IS_X11_DISPLAY(object) !(G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DISPLAY))
+#endif
+
#ifdef HAVE_WAYLAND
#include <gdk/gdkwayland.h>
#include "wayland-backend.h"
@@ -39,9 +44,7 @@
#define WINDOW_LIST_ICON "mate-panel-window-list"
#define WINDOW_LIST_SCHEMA "org.mate.panel.applet.window-list"
-#ifdef HAVE_WINDOW_PREVIEWS
#define WINDOW_LIST_PREVIEW_SCHEMA "org.mate.panel.applet.window-list-previews"
-#endif /* HAVE_WINDOW_PREVIEWS */
typedef enum {
TASKLIST_NEVER_GROUP,
@@ -52,17 +55,20 @@ typedef enum {
typedef struct {
GtkWidget* applet;
GtkWidget* tasklist;
-#ifdef HAVE_WINDOW_PREVIEWS
GtkWidget* preview;
+#ifdef HAVE_X11
+ WnckHandle* wnck_handle;
+#endif
+
gboolean show_window_thumbnails;
gint thumbnail_size;
-#endif
gboolean include_all_workspaces;
TasklistGroupingType grouping;
gboolean move_unminimized_windows;
gboolean scroll_enable;
+ gboolean middle_click_close;
GtkOrientation orientation;
int size;
@@ -70,33 +76,28 @@ 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
GtkWidget* window_thumbnail_box;
GtkWidget* show_thumbnails_check;
GtkWidget* thumbnail_size_label;
GtkWidget* thumbnail_size_spin;
-#endif
GtkWidget* never_group_radio;
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;
GtkWidget* window_list_content_box;
GSettings* settings;
-#ifdef HAVE_WINDOW_PREVIEWS
GSettings* preview_settings;
-#endif
} TasklistData;
static void call_system_monitor(GtkAction* action, TasklistData* tasklist);
@@ -138,6 +139,7 @@ static void tasklist_update(TasklistData* tasklist)
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 */
@@ -202,11 +204,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;
@@ -246,7 +243,6 @@ static void applet_change_background(MatePanelApplet* applet, MatePanelAppletBac
}
#ifdef HAVE_X11
-#ifdef HAVE_WINDOW_PREVIEWS
static cairo_surface_t*
preview_window_thumbnail (WnckWindow *wnck_window,
TasklistData *tasklist,
@@ -371,14 +367,14 @@ preview_window_reposition (WnckTasklist *tl,
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;
+ x_pos = monitor_geom.x + tasklist->size + PREVIEW_PADDING;
break;
case MATE_PANEL_APPLET_ORIENT_UP:
y_pos = monitor_geom.height + monitor_geom.y - height - tasklist->size - PREVIEW_PADDING;
break;
case MATE_PANEL_APPLET_ORIENT_DOWN:
default:
- y_pos = tasklist->size + PREVIEW_PADDING;
+ y_pos = monitor_geom.y + tasklist->size + PREVIEW_PADDING;
break;
}
@@ -477,7 +473,7 @@ static gboolean applet_enter_notify_event (WnckTasklist *tl, GList *wnck_windows
/* Do not show preview if window is not visible nor in current workspace */
if (!wnck_window_is_visible_on_workspace (wnck_window,
- wnck_screen_get_active_workspace (wnck_screen_get_default ())))
+ wnck_screen_get_active_workspace (wncklet_get_screen (tasklist->wnck_handle, tasklist->applet))))
return FALSE;
thumbnail = preview_window_thumbnail (wnck_window, tasklist, &thumbnail_width, &thumbnail_height, &thumbnail_scale);
@@ -513,7 +509,6 @@ static gboolean applet_leave_notify_event (WnckTasklist *tl, GList *wnck_windows
return FALSE;
}
-#endif /* HAVE_WINDOW_PREVIEWS */
#endif /* HAVE_X11 */
static void applet_change_pixel_size(MatePanelApplet* applet, gint size, TasklistData* tasklist)
@@ -602,7 +597,6 @@ static void display_all_workspaces_changed(GSettings* settings, gchar* key, Task
tasklist_properties_update_content_radio(tasklist);
}
-#ifdef HAVE_WINDOW_PREVIEWS
static void tasklist_update_thumbnail_size_spin(TasklistData* tasklist)
{
GtkWidget* button;
@@ -625,7 +619,6 @@ static void thumbnail_size_changed(GSettings *settings, gchar* key, TasklistData
tasklist->thumbnail_size = g_settings_get_int(settings, key);
tasklist_update_thumbnail_size_spin(tasklist);
}
-#endif
static GtkWidget* get_grouping_button(TasklistData* tasklist, TasklistGroupingType type)
{
@@ -700,6 +693,12 @@ static void scroll_enabled_changed (GSettings* settings, gchar* key, TasklistDat
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);
@@ -709,7 +708,6 @@ static void setup_gsettings(TasklistData* tasklist)
G_CALLBACK (display_all_workspaces_changed),
tasklist);
-#ifdef HAVE_WINDOW_PREVIEWS
tasklist->preview_settings = mate_panel_applet_settings_new (MATE_PANEL_APPLET (tasklist->applet), WINDOW_LIST_PREVIEW_SCHEMA);
g_signal_connect (tasklist->preview_settings,
@@ -721,7 +719,6 @@ static void setup_gsettings(TasklistData* tasklist)
"changed::thumbnail-window-size",
G_CALLBACK (thumbnail_size_changed),
tasklist);
-#endif
g_signal_connect (tasklist->settings,
"changed::group-windows",
G_CALLBACK (group_windows_changed),
@@ -734,6 +731,10 @@ static void setup_gsettings(TasklistData* tasklist)
"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)
@@ -768,77 +769,26 @@ 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;
GtkActionGroup* action_group;
GtkCssProvider *provider;
- GdkScreen *screen;
tasklist = g_new0(TasklistData, 1);
tasklist->applet = GTK_WIDGET(applet);
provider = gtk_css_provider_new ();
- screen = gdk_screen_get_default ();
gtk_css_provider_load_from_data (provider,
".mate-panel-menu-bar button,\n"
" #tasklist-button {\n"
" padding: 0px;\n"
" margin: 0px;\n }",
-1, NULL);
- gtk_style_context_add_provider_for_screen (screen,
- GTK_STYLE_PROVIDER (provider),
- GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ gtk_style_context_add_provider_for_screen (gtk_widget_get_screen (tasklist->applet),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref (provider);
mate_panel_applet_set_flags(MATE_PANEL_APPLET(tasklist->applet), MATE_PANEL_APPLET_EXPAND_MAJOR | MATE_PANEL_APPLET_EXPAND_MINOR | MATE_PANEL_APPLET_HAS_HANDLE);
@@ -847,11 +797,9 @@ gboolean window_list_applet_fill(MatePanelApplet* applet)
tasklist->include_all_workspaces = g_settings_get_boolean (tasklist->settings, "display-all-workspaces");
-#ifdef HAVE_WINDOW_PREVIEWS
tasklist->show_window_thumbnails = g_settings_get_boolean (tasklist->preview_settings, "show-window-thumbnails");
tasklist->thumbnail_size = g_settings_get_int (tasklist->preview_settings, "thumbnail-window-size");
-#endif
tasklist->grouping = g_settings_get_enum (tasklist->settings, "group-windows");
@@ -859,6 +807,8 @@ gboolean window_list_applet_fill(MatePanelApplet* applet)
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)
@@ -881,19 +831,15 @@ gboolean window_list_applet_fill(MatePanelApplet* applet)
#ifdef HAVE_X11
if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
{
- tasklist->tasklist = wnck_tasklist_new();
+ tasklist->wnck_handle = wnck_handle_new(WNCK_CLIENT_TYPE_PAGER);
+ tasklist->tasklist = wnck_tasklist_new_with_handle(tasklist->wnck_handle);
- 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 (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
#endif /* HAVE_X11 */
@@ -921,9 +867,6 @@ gboolean window_list_applet_fill(MatePanelApplet* applet)
gtk_container_add(GTK_CONTAINER(tasklist->applet), tasklist->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);
@@ -1051,12 +994,10 @@ static void group_windows_toggled(GtkToggleButton* button, TasklistData* tasklis
}
}
-#ifdef HAVE_WINDOW_PREVIEWS
static void thumbnail_size_spin_changed(GtkSpinButton* button, TasklistData* tasklist)
{
g_settings_set_int(tasklist->preview_settings, "thumbnail-window-size", gtk_spin_button_get_value_as_int(button));
}
-#endif
static void move_minimized_toggled(GtkToggleButton* button, TasklistData* tasklist)
{
@@ -1107,9 +1048,7 @@ static void setup_dialog_wayland(TasklistData* tasklist)
gtk_widget_set_sensitive(tasklist->window_grouping_box, FALSE);
gtk_widget_set_sensitive(tasklist->minimized_windows_box, FALSE);
-#ifdef HAVE_WINDOW_PREVIEWS
gtk_widget_set_sensitive(tasklist->window_thumbnail_box, FALSE);
-#endif /* HAVE_WINDOW_PREVIEWS */
}
#endif /* HAVE_WAYLAND */
@@ -1129,7 +1068,6 @@ static void setup_dialog(GtkBuilder* builder, TasklistData* tasklist)
setup_sensitivity(tasklist, builder, "never_group_radio", "auto_group_radio", "always_group_radio", "group-windows" /* key */);
-#ifdef HAVE_WINDOW_PREVIEWS
tasklist->window_thumbnail_box = WID("window_thumbnail_box");
tasklist->show_thumbnails_check = WID("show_thumbnails_check");
tasklist->thumbnail_size_label = WID("thumbnail_size_label");
@@ -1146,13 +1084,10 @@ 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);
-#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");
@@ -1183,13 +1118,18 @@ static void setup_dialog(GtkBuilder* builder, TasklistData* tasklist)
"active",
G_SETTINGS_BIND_DEFAULT);
-#ifdef HAVE_WINDOW_PREVIEWS
+ /* Middle mouse click to close window: */
+ g_settings_bind (tasklist->settings,
+ "middle-click-close",
+ tasklist->middle_click_close_check,
+ "active",
+ G_SETTINGS_BIND_DEFAULT);
+
/* change thumbnail size: */
tasklist_update_thumbnail_size_spin(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);
@@ -1247,11 +1187,9 @@ static void destroy_tasklist(GtkWidget* widget, TasklistData* tasklist)
{
g_signal_handlers_disconnect_by_data (G_OBJECT (tasklist->applet), tasklist);
-#ifdef HAVE_WINDOW_PREVIEWS
g_signal_handlers_disconnect_by_data (G_OBJECT (tasklist->tasklist), tasklist);
g_signal_handlers_disconnect_by_data (tasklist->preview_settings, tasklist);
g_object_unref(tasklist->preview_settings);
-#endif
g_signal_handlers_disconnect_by_data (tasklist->settings, tasklist);
@@ -1260,9 +1198,11 @@ static void destroy_tasklist(GtkWidget* widget, TasklistData* tasklist)
if (tasklist->properties_dialog)
gtk_widget_destroy(tasklist->properties_dialog);
-#ifdef HAVE_WINDOW_PREVIEWS
if (tasklist->preview)
gtk_widget_destroy(tasklist->preview);
+
+#ifdef HAVE_X11
+ g_clear_object(&tasklist->wnck_handle);
#endif
g_free(tasklist);
diff --git a/applets/wncklet/window-list.ui b/applets/wncklet/window-list.ui
index 4cc49f9c..2ed06c0e 100644
--- a/applets/wncklet/window-list.ui
+++ b/applets/wncklet/window-list.ui
@@ -76,6 +76,7 @@
<object class="GtkNotebook">
<property name="visible">True</property>
<property name="can-focus">True</property>
+ <property name="border_width">5</property>
<child>
<object class="GtkBox" id="behaviour_vbox">
<property name="visible">True</property>
diff --git a/applets/wncklet/window-menu.c b/applets/wncklet/window-menu.c
index 4b4e48dc..18f33f19 100644
--- a/applets/wncklet/window-menu.c
+++ b/applets/wncklet/window-menu.c
@@ -45,6 +45,10 @@
#include <gdk/gdkwayland.h>
#endif /* HAVE_WAYLAND */
+#ifndef HAVE_X11
+#define GDK_IS_X11_DISPLAY(object) !(G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DISPLAY))
+#endif
+
#include "wncklet.h"
#include "window-menu.h"
@@ -53,6 +57,9 @@
typedef struct {
GtkWidget* applet;
GtkWidget* selector;
+#ifdef HAVE_X11
+ WnckHandle* wnck_handle;
+#endif
int size;
MatePanelAppletOrient orient;
} WindowMenu;
@@ -119,6 +126,9 @@ static const GtkActionEntry window_menu_actions[] = {
static void window_menu_destroy(GtkWidget* widget, WindowMenu* window_menu)
{
+#ifdef HAVE_X11
+ g_clear_object(&window_menu->wnck_handle);
+#endif
g_free(window_menu);
}
@@ -252,7 +262,8 @@ gboolean window_menu_applet_fill(MatePanelApplet* applet)
#ifdef HAVE_X11
if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
{
- window_menu->selector = wnck_selector_new();
+ window_menu->wnck_handle = wnck_handle_new(WNCK_CLIENT_TYPE_PAGER);
+ window_menu->selector = wnck_selector_new_with_handle(window_menu->wnck_handle);
}
else
#endif /* HAVE_X11 */
diff --git a/applets/wncklet/wncklet.c b/applets/wncklet/wncklet.c
index 3b185910..1ced4507 100644
--- a/applets/wncklet/wncklet.c
+++ b/applets/wncklet/wncklet.c
@@ -35,11 +35,15 @@
#include <gdk/gdkx.h>
#define WNCK_I_KNOW_THIS_IS_UNSTABLE
#include <libwnck/libwnck.h>
+#include "workspace-switcher.h"
+#endif
+#ifndef HAVE_X11
+#include <gdk/gdkwayland.h>
+#define GDK_IS_X11_DISPLAY(object) !(G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DISPLAY))
#endif
#include "wncklet.h"
#include "window-menu.h"
-#include "workspace-switcher.h"
#include "window-list.h"
#include "showdesktop.h"
@@ -96,18 +100,19 @@ void wncklet_display_help(GtkWidget* widget, const char* doc_id, const char* lin
}
#ifdef HAVE_X11
-WnckScreen* wncklet_get_screen(GtkWidget* applet)
+WnckScreen* wncklet_get_screen(WnckHandle* handle, GtkWidget* applet)
{
+ g_return_val_if_fail (WNCK_IS_HANDLE (handle), NULL);
g_return_val_if_fail (GDK_IS_X11_DISPLAY (gdk_display_get_default ()), NULL);
int screen_num;
if (!gtk_widget_has_screen(applet))
- return wnck_screen_get_default();
+ return wnck_handle_get_default_screen(handle);
screen_num = gdk_x11_screen_get_screen_number(gtk_widget_get_screen(applet));
- return wnck_screen_get(screen_num);
+ return wnck_handle_get_screen(handle, screen_num);
}
#endif /* HAVE_X11 */
@@ -124,22 +129,12 @@ static gboolean wncklet_factory(MatePanelApplet* applet, const char* iid, gpoint
{
gboolean retval = FALSE;
-#ifdef HAVE_X11
- if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
- {
- static gboolean type_registered = FALSE;
- if (!type_registered)
- {
- wnck_set_client_type(WNCK_CLIENT_TYPE_PAGER);
- type_registered = TRUE;
- }
- }
-#endif /* HAVE_X11 */
-
if (!strcmp(iid, "WindowMenuApplet"))
retval = window_menu_applet_fill(applet);
+#ifdef HAVE_X11
else if (!strcmp(iid, "WorkspaceSwitcherApplet") || !strcmp(iid, "PagerApplet"))
retval = workspace_switcher_applet_fill(applet);
+#endif
else if (!strcmp(iid, "WindowListApplet") || !strcmp(iid, "TasklistApplet"))
retval = window_list_applet_fill(applet);
else if (!strcmp(iid, "ShowDesktopApplet"))
diff --git a/applets/wncklet/wncklet.h b/applets/wncklet/wncklet.h
index 145cbce3..4b1dccea 100644
--- a/applets/wncklet/wncklet.h
+++ b/applets/wncklet/wncklet.h
@@ -28,17 +28,18 @@
#include <gtk/gtk.h>
#include <mate-panel-applet.h>
+#define WNCK_I_KNOW_THIS_IS_UNSTABLE
+#include <libwnck/libwnck.h>
+
#define WNCKLET_RESOURCE_PATH "/org/mate/panel/applet/wncklet/"
#ifdef __cplusplus
extern "C" {
#endif
-typedef struct _WnckScreen WnckScreen;
-
void wncklet_display_help(GtkWidget* widget, const char* doc_id, const char* link_id, const char* icon_name);
-WnckScreen* wncklet_get_screen(GtkWidget* applet);
+WnckScreen* wncklet_get_screen(WnckHandle* handle, GtkWidget* applet);
void wncklet_connect_while_alive(gpointer object, const char* signal, GCallback func, gpointer func_data, gpointer alive_object);
diff --git a/applets/wncklet/workspace-switcher.c b/applets/wncklet/workspace-switcher.c
index 065e951a..cba0ecbd 100644
--- a/applets/wncklet/workspace-switcher.c
+++ b/applets/wncklet/workspace-switcher.c
@@ -53,6 +53,153 @@
#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,
@@ -65,8 +212,12 @@ typedef enum {
typedef struct {
GtkWidget* applet;
+ GtkWidget* pager_container;
GtkWidget* pager;
+#ifdef HAVE_X11
+ WnckHandle* wnck_handle;
+#endif
WnckScreen* screen;
PagerWM wm;
@@ -251,7 +402,7 @@ static void applet_realized(MatePanelApplet* applet, PagerData* pager)
#ifdef HAVE_X11
if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
{
- pager->screen = wncklet_get_screen(GTK_WIDGET(applet));
+ pager->screen = wncklet_get_screen(pager->wnck_handle, GTK_WIDGET(applet));
wncklet_connect_while_alive(pager->screen, "window_manager_changed", G_CALLBACK(window_manager_changed), pager, pager->applet);
}
#endif /* HAVE_X11 */
@@ -290,6 +441,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"));
}
@@ -522,9 +675,7 @@ 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);
@@ -624,7 +775,8 @@ gboolean workspace_switcher_applet_fill(MatePanelApplet* applet)
#ifdef HAVE_X11
if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
{
- pager->pager = wnck_pager_new();
+ pager->wnck_handle = wnck_handle_new(WNCK_CLIENT_TYPE_PAGER);
+ pager->pager = wnck_pager_new_with_handle(pager->wnck_handle);
wnck_pager_set_shadow_type(WNCK_PAGER(pager->pager), GTK_SHADOW_IN);
}
else
@@ -659,7 +811,8 @@ gboolean workspace_switcher_applet_fill(MatePanelApplet* applet)
G_CALLBACK (applet_scroll),
pager);
- gtk_container_add(GTK_CONTAINER(pager->applet), pager->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),
@@ -678,6 +831,7 @@ gboolean workspace_switcher_applet_fill(MatePanelApplet* applet)
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");
@@ -1138,5 +1292,10 @@ static void destroy_pager(GtkWidget* widget, PagerData* pager)
if (pager->properties_dialog)
gtk_widget_destroy(pager->properties_dialog);
+
+#ifdef HAVE_X11
+ g_clear_object(&pager->wnck_handle);
+#endif
+
g_free(pager);
}