From f7e98fc2271133bd4dbfb0d4acc01b65726e344a Mon Sep 17 00:00:00 2001 From: Joshua Strobl Date: Sat, 4 Jan 2025 15:03:26 +0200 Subject: [PATCH] workspace-applet: Fix more issues related to Wayland The big thing is that the applet no longer crashes when a new window is opened. When a window is opened, it may not yet have an application assigned to it. When that happens, set the item's icon to a generic one, and wait for it to update naturally. In practice, I have yet to see the generic icon; it's always been updated by the time I can see it. --- src/panel/applets/workspaces/WindowIcon.vala | 50 +++---- .../applets/workspaces/WorkspaceItem.vala | 9 +- .../applets/workspaces/WorkspacesApplet.vala | 137 +++++++----------- 3 files changed, 82 insertions(+), 114 deletions(-) diff --git a/src/panel/applets/workspaces/WindowIcon.vala b/src/panel/applets/workspaces/WindowIcon.vala index b7183c87f..d9d0231df 100644 --- a/src/panel/applets/workspaces/WindowIcon.vala +++ b/src/panel/applets/workspaces/WindowIcon.vala @@ -11,19 +11,30 @@ namespace Workspaces { public const int WORKSPACE_ICON_SIZE = 16; + public const string FALLBACK_ICON_NAME = "image-missing"; public class WindowIcon : Gtk.Button { - private libxfce4windowing.Window window; - - public WindowIcon(libxfce4windowing.Window window) { - this.window = window; + public libxfce4windowing.Window window { get; construct; } + construct { this.set_relief(Gtk.ReliefStyle.NONE); this.get_style_context().add_class("workspace-icon-button"); this.set_tooltip_text(window.get_name()); - Gtk.Image icon = new Gtk.Image.from_gicon(window.get_gicon(), Gtk.IconSize.INVALID); - icon.set_pixel_size(WORKSPACE_ICON_SIZE); + Gtk.Image icon; + + // When a window has just been created, its application + // may not be set yet, so default to a generic icon if + // there is no application. It will be set when the + // icon_changed signal is called. + if (this.window.application != null) { + unowned var pixbuf = window.get_icon(WORKSPACE_ICON_SIZE, get_scale_factor()); + icon = new Gtk.Image.from_pixbuf(pixbuf); + } else { + icon = new Gtk.Image.from_icon_name(FALLBACK_ICON_NAME, Gtk.IconSize.INVALID); + icon.pixel_size = WORKSPACE_ICON_SIZE; + } + this.add(icon); icon.show(); @@ -32,8 +43,10 @@ namespace Workspaces { }); window.icon_changed.connect(() => { - icon.set_from_gicon(window.get_gicon(), Gtk.IconSize.INVALID); + unowned var pixbuf = window.get_icon(WORKSPACE_ICON_SIZE, get_scale_factor()); + icon.set_from_pixbuf(pixbuf); icon.queue_draw(); + Gtk.drag_source_set_icon_pixbuf(this, pixbuf); }); Gtk.drag_source_set( @@ -43,8 +56,6 @@ namespace Workspaces { Gdk.DragAction.MOVE ); - Gtk.drag_source_set_icon_gicon(this, window.get_gicon()); - this.drag_begin.connect(on_drag_begin); this.drag_end.connect(on_drag_end); this.drag_data_get.connect(on_drag_data_get); @@ -52,6 +63,10 @@ namespace Workspaces { this.show_all(); } + public WindowIcon(libxfce4windowing.Window window) { + Object(window: window); + } + public override bool button_release_event(Gdk.EventButton event) { if (event.button != 1) return Gdk.EVENT_STOP; @@ -72,22 +87,7 @@ namespace Workspaces { } public void on_drag_data_get(Gtk.Widget widget, Gdk.DragContext context, Gtk.SelectionData selection_data, uint target_type, uint time) { - ulong window_xid = (ulong)window.x11_get_xid(); - uchar[] buf; - convert_ulong_to_bytes(window_xid, out buf); - selection_data.set( - selection_data.get_target(), - 8, - buf - ); - } - - private void convert_ulong_to_bytes(ulong number, out uchar[] buffer) { - buffer = new uchar[sizeof(ulong)]; - for (int i=0; i> 8; - } + selection_data.set_text(string.joinv(",", window.get_class_ids()), -1); } } } diff --git a/src/panel/applets/workspaces/WorkspaceItem.vala b/src/panel/applets/workspaces/WorkspaceItem.vala index ef76ee904..5ff2f8585 100644 --- a/src/panel/applets/workspaces/WorkspaceItem.vala +++ b/src/panel/applets/workspaces/WorkspaceItem.vala @@ -11,7 +11,7 @@ namespace Workspaces { const Gtk.TargetEntry[] target_list = { - { "application/x-wnck-window-id", 0, 0 } + { "text/plain", 0, 0 } }; public class WorkspaceItem : Gtk.EventBox { @@ -174,12 +174,13 @@ namespace Workspaces { private void on_drag_data_received(Gtk.Widget widget, Gdk.DragContext context, int x, int y, Gtk.SelectionData selection_data, uint target_type, uint time) { bool dnd_success = false; - ulong* data = (ulong*)selection_data.get_data(); + string? data = selection_data.get_text(); if (data != null) { try { foreach (libxfce4windowing.Window window in WorkspacesApplet.xfce_screen.get_windows()) { - if (window.x11_get_xid() == *data) { + string all_class_names = string.joinv(",", window.get_class_ids()); + if (all_class_names == data) { window.move_to_workspace(this.workspace); dnd_success = true; break; @@ -193,7 +194,7 @@ namespace Workspaces { Gtk.drag_finish(context, dnd_success, true, time); } - public void update_windows(List window_list) { + public void update_windows(List window_list) { int num_columns = (real_alloc.width - 4) / 20; int num_rows = (real_alloc.height - 4) / 20; diff --git a/src/panel/applets/workspaces/WorkspacesApplet.vala b/src/panel/applets/workspaces/WorkspacesApplet.vala index 35509e663..2c1bd45dd 100644 --- a/src/panel/applets/workspaces/WorkspacesApplet.vala +++ b/src/panel/applets/workspaces/WorkspacesApplet.vala @@ -39,14 +39,7 @@ namespace Workspaces { } } - [DBus (name="org.budgie_desktop.BudgieWM")] - public interface BudgieWM : GLib.Object { - public abstract void RemoveWorkspaceByIndex(int index, uint32 time) throws Error; - public abstract int AppendNewWorkspace(uint32 time) throws Error; - } - public class WorkspacesApplet : Budgie.Applet { - private BudgieWM? wm_proxy = null; private Gtk.EventBox ebox; private Gtk.Box main_layout; private Gtk.Box workspaces_layout; @@ -100,9 +93,6 @@ namespace Workspaces { dynamically_created_workspaces = new List(); window_connections = new HashTable(str_hash, str_equal); - Bus.watch_name(BusType.SESSION, "org.budgie_desktop.BudgieWM", BusNameWatcherFlags.NONE, - has_wm, lost_wm); - ebox = new Gtk.EventBox(); ebox.add_events(Gdk.EventMask.SCROLL_MASK); this.add(ebox); @@ -143,13 +133,12 @@ namespace Workspaces { add_button.button_release_event.connect((event) => { try { - int new_index = wm_proxy.AppendNewWorkspace(event.time); + add_new_workspace(); + uint new_index = workspace_group.get_workspace_count() - 1; - if (new_index != -1) { - set_current_workspace(); - } else if (!below_max_workspace_count()) { // Last workspace - add_button_revealer.set_reveal_child(false); // Hide add button - } + if (new_index != -1) { + set_current_workspace(); + } } catch (Error e) { warning("Failed to append new workspace: %s", e.message); } @@ -171,24 +160,24 @@ namespace Workspaces { ebox.enter_notify_event.connect(() => { if (button_visibility != AddButtonVisibility.HOVER) { - return false; + return Gdk.EVENT_PROPAGATE; } - if (below_max_workspace_count()) { // Is below max workspace count + if (below_max_workspaces()) { add_button_revealer.set_transition_type(show_transition); add_button_revealer.set_reveal_child(true); } - return false; + return Gdk.EVENT_PROPAGATE; }); ebox.leave_notify_event.connect(() => { if (dragging || button_visibility != AddButtonVisibility.HOVER) { - return false; + return Gdk.EVENT_PROPAGATE; } add_button_revealer.set_transition_type(hide_transition); add_button_revealer.set_reveal_child(false); - return false; + return Gdk.EVENT_PROPAGATE; }); ebox.scroll_event.connect((e) => { @@ -225,8 +214,9 @@ namespace Workspaces { private void on_settings_change(string key) { if (key == "addbutton-visibility") { - button_visibility = (AddButtonVisibility)settings.get_enum(key); - add_button_revealer.set_reveal_child(((button_visibility == AddButtonVisibility.ALWAYS) && below_max_workspace_count())); + button_visibility = (AddButtonVisibility) settings.get_enum(key); + var should_show = below_max_workspaces() && button_visibility == AddButtonVisibility.ALWAYS; + add_button_revealer.set_reveal_child(should_show); } else if (key == "item-size-multiplier") { item_size_multiplier = (float) settings.get_enum(key) / 4; foreach (Gtk.Widget widget in workspaces_layout.get_children()) { @@ -253,28 +243,8 @@ namespace Workspaces { } } - private void lost_wm() { - wm_proxy = null; - } - - private void on_wm_get(Object? o, AsyncResult? res) { - try { - wm_proxy = Bus.get_proxy.end(res); - } catch (Error e) { - warning("Failed to get BudgieWM proxy: %s", e.message); - } - } - - private void has_wm() { - if (wm_proxy == null) { - Bus.get_proxy.begin(BusType.SESSION, - "org.budgie_desktop.BudgieWM", - "/org/budgie_desktop/BudgieWM", 0, null, on_wm_get); - } - } - - private bool below_max_workspace_count() { - return (workspace_group.get_workspace_count() < 8); + private bool below_max_workspaces() { + return workspace_group.get_workspace_count() < 8; } private void connect_signals() { @@ -320,7 +290,7 @@ namespace Workspaces { workspaces_layout.pack_start(revealer, true, true, 0); revealer.set_reveal_child(true); - if (!below_max_workspace_count()) { + if (!below_max_workspaces()) { add_button_revealer.set_reveal_child(false); } } @@ -348,6 +318,8 @@ namespace Workspaces { return; } + if (libxfce4windowing.windowing_get() != libxfce4windowing.Windowing.WAYLAND) return; + if (window_connections.contains(window)) { ulong conn = window_connections.get(window); if (SignalHandler.is_connected(window, conn)) { @@ -395,7 +367,7 @@ namespace Workspaces { return; } - ulong* data = (ulong*) selection_data.get_data(); + string? data = selection_data.get_text(); if (data == null) { Gtk.drag_finish(context, false, true, time); return; @@ -403,7 +375,8 @@ namespace Workspaces { libxfce4windowing.Window? window = null; foreach (libxfce4windowing.Window win in xfce_screen.get_windows()) { - if (win.x11_get_xid() == *data) { + string all_class_names = string.joinv(",", window.get_class_ids()); + if (all_class_names == data) { window = win; break; } @@ -414,25 +387,20 @@ namespace Workspaces { return; } - try { - int index = wm_proxy.AppendNewWorkspace(time); - - if (index != -1) { // Successfully added workspace - dynamically_created_workspaces.append(index); - Timeout.add(50, () => { - libxfce4windowing.Workspace? workspace = get_workspace_by_index(index); - try { - if (workspace != null) window.move_to_workspace(workspace); - } catch (Error e) { - warning("Failed to move window to workspace: %s", e.message); - } - return false; - }); - } - } catch (Error e) { - warning("Failed to append new workspace: %s", e.message); - Gtk.drag_finish(context, false, true, time); - return; + add_new_workspace(); + uint new_index = workspace_group.get_workspace_count() - 1; + + if (new_index != -1) { // Successfully added workspace + dynamically_created_workspaces.append((int) new_index); + Timeout.add(50, () => { + libxfce4windowing.Workspace? workspace = get_workspace_by_index(new_index); + try { + if (workspace != null) window.move_to_workspace(workspace); + } catch (Error e) { + warning("Failed to move window to workspace: %s", e.message); + } + return false; + }); } Gtk.drag_finish(context, true, true, time); @@ -479,21 +447,20 @@ namespace Workspaces { } } - private void remove_workspace(uint index, uint32 time) { - if (wm_proxy == null) { - return; + private void add_new_workspace() { + try { + workspace_group.create_workspace("Workspace %lu".printf(workspace_group.get_workspace_count() + 1)); + workspace_group.set_layout((int) workspace_group.get_workspace_count(), 1); + } catch (Error e) { + warning("Failed to append new workspace: %s", e.message); } + } + private void remove_workspace(uint index, uint32 time) { var workspace = get_workspace_by_index((uint)index); try { - wm_proxy.RemoveWorkspaceByIndex((int)index, time); - - var _workspace = workspace_group.get_active_workspace(); - if (_workspace != null && _workspace == workspace) { - var previous = get_workspace_by_index((index == 0) ? index : index - 1); - if (previous != null) previous.activate(); - } + workspace.remove(); } catch (Error e) { warning("Failed to remove workspace at index %lu: %s", index, e.message); } @@ -525,31 +492,31 @@ namespace Workspaces { foreach (Gtk.Widget widget in workspaces_layout.get_children()) { Gtk.Revealer revealer = widget as Gtk.Revealer; WorkspaceItem item = revealer.get_child() as WorkspaceItem; - List windows = xfce_screen.get_windows_stacked().copy(); - windows.reverse(); - List window_list = new List(); + unowned List? windows = xfce_screen.get_windows(); + List window_list = new List(); + windows.foreach((window) => { if (window.get_workspace() == item.get_workspace() && !window.is_skip_tasklist() && !window.is_skip_pager() && window.get_window_type() == libxfce4windowing.WindowType.NORMAL) { window_list.append(window); } }); + int index = (int)item.get_workspace().get_number(); unowned List? dyn = dynamically_created_workspaces.find(index); + if (window_list.is_empty() && dyn != null) { dynamically_created_workspaces.remove(index); dyn = dynamically_created_workspaces.find(index+1); + if (dyn == null) { Timeout.add(200, () => { - try { - wm_proxy.RemoveWorkspaceByIndex(index, Gdk.CURRENT_TIME); - } catch (Error e) { - warning("Failed to remove workspace at index %i: %s", index, e.message); - } + remove_workspace(index, Gdk.CURRENT_TIME); return false; }); } } + item.update_windows(window_list); }