From ff2e3acfbf716c55fa332b7ebe5a69ae4ab85757 Mon Sep 17 00:00:00 2001 From: TKY Date: Sat, 25 Apr 2026 16:49:23 +0800 Subject: [PATCH] Add option to restrict swap and focus to the current workspace `swap-*` shortcuts currently move every window on the two monitors, including windows on inactive workspaces, because `swapWindowsWith` only filters by monitor. After a swap or `monitor-*` navigation, focus can also jump to a different workspace because `_focusMostRecentWindowOnMonitor` calls `get_tab_list(0, null)`, which scans all workspaces. Add a new boolean `current-workspace-only` preference (default `true`) exposed in Preferences -> Window Focus Settings. When enabled, `swapWindowsWith` and `_focusMostRecentWindowOnMonitor` only consider windows on the currently active workspace; disabling it preserves the original behavior. Co-Authored-By: Claude Opus 4.7 (1M context) --- monitor.js | 13 ++++++++++--- prefs.js | 17 +++++++++++++++++ schemas/gschemas.compiled | Bin 1485 -> 1565 bytes ...rg.gnome.shell.extensions.binu.gschema.xml | 6 ++++++ utils.js | 5 +++++ 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/monitor.js b/monitor.js index acb5e00..173943e 100644 --- a/monitor.js +++ b/monitor.js @@ -69,9 +69,13 @@ export class MonitorNavigator { return; } + const activeWorkspace = this.settings.isCurrentWorkspaceOnlyEnabled() + ? global.workspace_manager.get_active_workspace() + : null; + const inWorkspace = win => !activeWorkspace || win.get_workspace() === activeWorkspace; const windows = global.get_window_actors().map(actor => actor.meta_window); - const windowsOnCurrent = windows.filter(win => win.get_monitor() === currentMonitor); - const windowsOnTarget = windows.filter(win => win.get_monitor() === targetMonitor); + const windowsOnCurrent = windows.filter(win => win.get_monitor() === currentMonitor && inWorkspace(win)); + const windowsOnTarget = windows.filter(win => win.get_monitor() === targetMonitor && inWorkspace(win)); for (const win of windowsOnCurrent) { win.move_to_monitor(targetMonitor); @@ -92,7 +96,10 @@ export class MonitorNavigator { } _focusMostRecentWindowOnMonitor(monitorIndex) { - const recentWindows = global.display.get_tab_list(0, null); + const workspace = this.settings.isCurrentWorkspaceOnlyEnabled() + ? global.workspace_manager.get_active_workspace() + : null; + const recentWindows = global.display.get_tab_list(0, workspace); for (const win of recentWindows) { if (!win.minimized && !win.skip_taskbar && win.get_monitor() === monitorIndex) { win.activate(global.get_current_time()); diff --git a/prefs.js b/prefs.js index 87d1edc..772e28a 100644 --- a/prefs.js +++ b/prefs.js @@ -166,6 +166,23 @@ class PreferencesSettings { focusGroup.add(changeFocus); + const currentWorkspaceOnlySwitch = new Gtk.Switch({ + active: this.schema.get_boolean('current-workspace-only'), + valign: Gtk.Align.CENTER + }); + const currentWorkspaceOnlyRow = new Adw.ActionRow({ + title: _('Restrict actions to the current workspace'), + subtitle: _('When enabled, swap and focus updates only consider windows on the active workspace') + }); + currentWorkspaceOnlyRow.add_suffix(currentWorkspaceOnlySwitch); + currentWorkspaceOnlyRow.activatable_widget = currentWorkspaceOnlySwitch; + + currentWorkspaceOnlySwitch.connect('notify::active', () => { + this.schema.set_boolean('current-workspace-only', currentWorkspaceOnlySwitch.active); + }); + + focusGroup.add(currentWorkspaceOnlyRow); + this.page.add(cursorGroup); this.page.add(focusGroup); } diff --git a/schemas/gschemas.compiled b/schemas/gschemas.compiled index f7df1bedbdbac6128aa715feb31ac878a9a0a7d6..745810dbc5f08270bddad25a6f60cd45856c5d74 100644 GIT binary patch literal 1565 zcmZuxO=uHA7@bzr#wO{H+B9l{9ushr`tPN+YNb6y5TvCCJ#3S0vY70~-A$rs#hZHT z!K2m+_R@oT@CQL52!$dD1rhY%y_ep5Df-@Iw#MMV+xNaV-+VJWyE7Bhx?}2=Csd1p zXPP?M>6_rdpb)>&ntfTBa}EB@#i=JuqdqJq#a-~@T|#t#ZKsefSa#V+yG5f^N*lL4 z!*WgAa?`V>RYitK#`#2Jz7Nhzpp3+Ba4Q0ci7ueK4MD^`Kp5x+`hmSb6gU7J0>(c! z;;hegc8Qu;0xttspI461r;fsJfL8(k-KmAhiZ$>s7WC@bipPBFUgVE~F9C(_(Qovr zL-4PFr+}Z)cb)X9!|;pXGVpm~e1$&s5d4SW1)yi~QJ6mU9{5Y(Wgw({YWlCiZ-ILL zy{u2o`fK2?)GD8v`9HwFfTN{&mi4LWZ-6&}h{~s?zXjd~M%2DhbKipa2oa!H;N)T|T4j~f9lDxaEu44eSmx?a)FU;?(J?xu28$1yBVtJ}^Ex1#3^ z&9+LnWp{^2&ZeOFYhtK8Lp&4zI|uvV^Bn94uoSGZd9EVhK41XgSs4Nj0z4~hA%JIx zcY|)3W!*D0EXlPU&WHKScFlKGY?+?zXckU9#>mF^_;;|DuR6Mi>wx`vK9VL%HHQu} zX5%>DJk}Oh9HSgrzlUE|{vuqrTn878#<*I^ d^Bc|CxvJZAo8L+1sZHA%$Cp9diMd!6{{fv$8{Xc~W@un2+(LO?C-(xkT$Y(&p_^CnIP2hN^z&%1Nyz5BR3by;^z-SUKb zvfwL$&b5XnIMFA>A3VWYN#cR;$i+?pbcmTI)F}~OCbp+Qa}di26}*fzySc;6aBz|0?!f0 zL3n50HV0Xgdu$U6;uiQeP*grO{rlhtz>(TuiTTu>@SlL60?p-{N%n&}0e=Jh6*#Nv zP_xb!cpG^Bc->J0o};NQSGl~2w54m2SRoL4?I{VaG0m{dMB{Tw(Ce0nn^_esrt zo(7Kt;k{7{Q4&S)8qhcLY>oS&P9c8-`~v7&y_=#>%{oo+2cX(M@r6Eh68iJ%U1f-+~+8G49KWD)T~nk zUjVw5Pfh<4cpB(YJ~jOrumSWcpPGIH>;sFHSMs~m{O%p_Jz!k*pPK!D2wnl+Pff0K zpVR~JUxS;#gvzI8{zvdzEv ze?z5ls5F$8~oZ8C+p_&cCmi4mSV* diff --git a/schemas/org.gnome.shell.extensions.binu.gschema.xml b/schemas/org.gnome.shell.extensions.binu.gschema.xml index 85047f8..5e435f8 100644 --- a/schemas/org.gnome.shell.extensions.binu.gschema.xml +++ b/schemas/org.gnome.shell.extensions.binu.gschema.xml @@ -82,6 +82,12 @@ Update the focus to the window on the navigated monitor + + true + Restrict actions to the current workspace + When enabled, swap and focus actions only consider windows on the currently active workspace. + + diff --git a/utils.js b/utils.js index 3efea79..89a6677 100644 --- a/utils.js +++ b/utils.js @@ -92,6 +92,11 @@ export class Preferences{ return this._settings.get_boolean('update-focus'); } + isCurrentWorkspaceOnlyEnabled() { + // Restrict swap/focus actions to the active workspace + return this._settings.get_boolean('current-workspace-only'); + } + getAnimationDuration() { return this._settings.get_int('animate-cursor-duration'); }