Skip to content

Commit

Permalink
workspace-applet: Fix more issues related to Wayland
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
JoshStrobl authored and EbonJaeger committed Feb 12, 2025
1 parent 915925f commit f7e98fc
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 114 deletions.
50 changes: 25 additions & 25 deletions src/panel/applets/workspaces/WindowIcon.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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(
Expand All @@ -43,15 +56,17 @@ 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);

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;

Expand All @@ -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<sizeof(ulong); i++) {
buffer[i] = (uchar)(number & 0xFF);
number = number >> 8;
}
selection_data.set_text(string.joinv(",", window.get_class_ids()), -1);
}
}
}
9 changes: 5 additions & 4 deletions src/panel/applets/workspaces/WorkspaceItem.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand All @@ -193,7 +194,7 @@ namespace Workspaces {
Gtk.drag_finish(context, dnd_success, true, time);
}

public void update_windows(List<weak libxfce4windowing.Window> window_list) {
public void update_windows(List<libxfce4windowing.Window> window_list) {
int num_columns = (real_alloc.width - 4) / 20;
int num_rows = (real_alloc.height - 4) / 20;

Expand Down
137 changes: 52 additions & 85 deletions src/panel/applets/workspaces/WorkspacesApplet.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -100,9 +93,6 @@ namespace Workspaces {
dynamically_created_workspaces = new List<int>();
window_connections = new HashTable<unowned libxfce4windowing.Window, ulong>(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);
Expand Down Expand Up @@ -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);
}
Expand All @@ -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) => {
Expand Down Expand Up @@ -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()) {
Expand All @@ -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<BudgieWM>(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() {
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -395,15 +367,16 @@ 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;
}

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;
}
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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<unowned libxfce4windowing.Window> windows = xfce_screen.get_windows_stacked().copy();
windows.reverse();
List<unowned libxfce4windowing.Window> window_list = new List<unowned libxfce4windowing.Window>();
unowned List<libxfce4windowing.Window>? windows = xfce_screen.get_windows();
List<libxfce4windowing.Window> window_list = new List<libxfce4windowing.Window>();

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<int>? 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);
}

Expand Down

0 comments on commit f7e98fc

Please sign in to comment.