From 891efd7e13f01a60ec7fbe400417ce5f1f31411b Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sat, 20 Jan 2024 18:20:58 +1100 Subject: [PATCH 01/12] Added `monitor-focus-follows-mouse` option and implementation. --- schemas/gschemas.compiled | Bin 7981 -> 8021 bytes ...gnome.shell.extensions.paperwm.gschema.xml | 5 +++++ settings.js | 3 ++- stackoverlay.js | 10 ++++++---- tiling.js | 4 +++- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/schemas/gschemas.compiled b/schemas/gschemas.compiled index d42b14facba1a729152cefd9f66f84153109eb15..6d8f7f6deb90ba0d8a381ad7eaf4b1682ba35c10 100644 GIT binary patch delta 1904 zcmYk7YiJx*9L4X(jZO1t-r3n#x_NfeWK5b+2uL23Rw7u5O0Z}?bdsGUgS$KH%qE+Z zHXD(EphECcjMPA(#bB|RSfO8RX$(ROeJDQ2mq@mvWD*$F76yOH|5Znc`;Y>sXRDo(CGNJ~i9&AN# z_ES0kA~7c3f;QtSg-wMa=Jd?Fp~t}3y*pdX>4V5mLJd$|cP`G{^}G(UcftJ9XTLJ1 z&p|#5ol`PGT>a=sm<@9XO3<(Xy#w-V>n<^;uRy*I-2`2?Ue=k@mm<%>-z)$>sOwA2 z=>y1BXbX6yvu%_)eHro|=y6b~p7zw^{_c-rG@L|u24uhI^>P3`Z#)Z~18L{*5Oex4 z@*B|G;6!}UVNSmf`5N>g$m$DbnA7JX=UU`|r-RdD%;__JG^j8w;Lol3KiELe3H3mG z!HqMMdH>);pN;$kGy^IwEW3}CJ`ec}bQwH*u;l@-L(eC=0$l@j@2KvC=nIf<2C)9y z__3XQsg?ui3(-)79a9e8>{)%DIX&071$r2Ka_Z-M%;^>6z0f{z_CtMxIej(qap)Ad z*s*b)IX(N&Lg&DBnHf6I2L5o@9{L6Nbp5W)oSp+#psU~w<7NqSdOqq+=r%Yzt}igB z45|m#hBCck3E9^4JOyFxKEni-HZxe$_QBevhiyUpyv(R zp&cL_FE!VmUWn&JH1ZP~9mNqx}J2CbN7JF+J*FOLOFJ*wOY?9WmMh`1{y3ZYIpQp46N{J!YW2&HXHQ2{qaG;7ST$4nzFIy%p#x7_lF$a*p)e+?&vc;J-ad&pr7FT7;V(ZS5#ze|pv_1sVp= zYDLePCgOtwzddKp zoqO-xxikM=>HMg3V#423BSgS^W5FeaI3E1@)leKZJ$I3H*<0=Dygw%$&X&`7P*e@X6lXOIO&y z6E@t3x)mW##OG}0^t+HNP#t9L_CDtHLF7lFJ>cobS~r-}S0GP8hr#3O_z-h?AM#0P z9{gDsf0lVZhZC+~9=ZS?q@HtDMqi428M*?l%Dy~1&~t)S=mvP>ZTBta^d-o-2m3)t z8+9?KFGt=DwLtZ`>vx&c7bDN5V9tThPmLA-jf38Uh6~Uo(DZ3EE!|va15Sj>f$-*d!H2K@ zxWt@Z;Xu%KFmvr=X9e`zkspFS1xlMs1H7J|6P$p)3|_MqE11)BD^t)>@W=Yh??KG( zobVA%Ae;mx;l_*XK+kt#7CH~Uoas8uoSxS&Lw^DnFPpv0>A7Y1p?vi{_%!%LozFl# z<75-a3y!PK6QwW0`b8e*0;q4CigO^xa{^>5;L7_?2AR`4dk^&>xU~9BnmIk6P%X3( ze5b8mV@~f!ehAtPe(O9QV@}U;UV$F8@H5?U?(a!m=!+MrU1Yg|I>mASxf){Zs#m9Je+`!ug<^%;Y)jNX@w4BC1;Xc~hWX6f0enHkXSjFqz4EaW96RGdww zPueLXV%huTgul(xk}@&_@~A7kTL?QIO+@2HO1C3Mj8lp>=eXV_G*dpWh6^x9lP_HP z?;v_48B3-)ynMZ8rrwO&yc_gS8=1&}9!==UAuBx;wXz%yhup7*AI(M+sdVz;U1^5h zl*U?;Sj$Okq&J!{AKtBI%kR}%+3K$Z`-{G;_8yq2^p3Q|-X3GzShow the focus mode icon in the topbar + + true + Sets whether monitor focus / activation follows mouse movement + + 0.25 Duration of animations in seconds diff --git a/settings.js b/settings.js index 6cbcf989..2082433a 100644 --- a/settings.js +++ b/settings.js @@ -40,7 +40,8 @@ export function enable(extension) { 'show-window-position-bar', 'show-focus-mode-icon', 'disable-topbar-styling', 'default-focus-mode', 'gesture-enabled', 'gesture-horizontal-fingers', 'gesture-workspace-fingers', 'open-window-position', - 'overview-ensure-viewport-animation'] + 'overview-ensure-viewport-animation', 'monitor-focus-follows-mouse', + ] .forEach(k => setState(null, k)); prefs.__defineGetter__("minimum_margin", () => { return Math.min(15, prefs.horizontal_margin); diff --git a/stackoverlay.js b/stackoverlay.js index b01cb6e7..9d957486 100644 --- a/stackoverlay.js +++ b/stackoverlay.js @@ -90,14 +90,16 @@ export function enableMultimonitorSupport() { return; } - // if drag/grabbing window, do simple activate + // if grab/dragging window if (Tiling.inGrab) { - space?.activate(false, false); + space.activate(false, false); return; } - const selected = space?.selectedWindow; - space?.activateWithFocus(selected, false, false); + // if monitor focus follow mouse ==> activate space on mouse + if (Settings.prefs.monitor_focus_follows_mouse) { + space.activateWithFocus(space?.selectedWindow, false, false); + } }); console.debug('paperwm multimonitor support is ENABLED'); } diff --git a/tiling.js b/tiling.js index cf757793..29a78b25 100644 --- a/tiling.js +++ b/tiling.js @@ -1612,6 +1612,9 @@ border-radius: ${borderWidth}px; this.signals.connect(this.background, 'button-press-event', (actor, event) => { + // ensure this space is active if clicked + this.activate(false, false); + if (inGrab) { return; } @@ -1712,7 +1715,6 @@ border-radius: ${borderWidth}px; // transforms break if there's no height this.cloneContainer.height = this.monitor.height; - this.layout(true, { centerIfOne: false }); this.emit('monitor-changed'); } From 99cb5eb9ef12cea3dc20f095ae6a7fd508feed98 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sat, 20 Jan 2024 18:49:22 +1100 Subject: [PATCH 02/12] Added option to PaperWM settings. --- Settings.ui | 37 +++++++++++++++++++++++++++++++++++++ prefs.js | 21 ++------------------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/Settings.ui b/Settings.ui index 1719fefb..65aa3e64 100644 --- a/Settings.ui +++ b/Settings.ui @@ -277,6 +277,43 @@ + + + False + False + + + False + Monitor focus/activation follows mouse movement + 12 + 12 + 6 + 6 + 32 + + + False + 1 + Monitor focus follows mouse + 0 + + 0 + 0 + + + + + + + 1 + 0 + + + + + + + diff --git a/prefs.js b/prefs.js index f3d3044e..f6fc697d 100644 --- a/prefs.js +++ b/prefs.js @@ -126,25 +126,6 @@ class SettingsWidget { }); }; - const gestureFingersChanged = key => { - const builder = this.builder.get_object(key); - const setting = this._settings.get_int(key); - const valueToFingers = { - 0: 'fingers-disabled', - 3: 'three-fingers', - 4: 'four-fingers', - }; - const fingersToValue = Object.fromEntries( - Object.entries(valueToFingers).map(a => a.reverse()) - ); - - builder.set_active_id(valueToFingers[setting] ?? 'fingers-disable'); - builder.connect('changed', obj => { - const value = fingersToValue[obj.get_active_id()] ?? 0; - this._settings.set_int(key, value); - }); - }; - // General intValueChanged('window_gap_spin', 'window-gap'); intValueChanged('hmargin_spinner', 'horizontal-margin'); @@ -299,6 +280,8 @@ class SettingsWidget { this._settings.set_boolean('show-workspace-indicator', !state); }); + booleanStateChanged('monitor-focus-follows-mouse'); + // Workspaces booleanStateChanged('use-default-background'); From 4e819d09472d4aaec83f7c72b70eeadfac62b755 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sat, 20 Jan 2024 18:57:03 +1100 Subject: [PATCH 03/12] FIXES: to properly focus/activation window (if exists). --- stackoverlay.js | 2 +- tiling.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stackoverlay.js b/stackoverlay.js index 9d957486..e71c2505 100644 --- a/stackoverlay.js +++ b/stackoverlay.js @@ -98,7 +98,7 @@ export function enableMultimonitorSupport() { // if monitor focus follow mouse ==> activate space on mouse if (Settings.prefs.monitor_focus_follows_mouse) { - space.activateWithFocus(space?.selectedWindow, false, false); + space.activateWithFocus(space.selectedWindow, false, false); } }); console.debug('paperwm multimonitor support is ENABLED'); diff --git a/tiling.js b/tiling.js index 29a78b25..e3d1854a 100644 --- a/tiling.js +++ b/tiling.js @@ -1613,7 +1613,7 @@ border-radius: ${borderWidth}px; this.signals.connect(this.background, 'button-press-event', (actor, event) => { // ensure this space is active if clicked - this.activate(false, false); + this.activateWithFocus(this.selectedWindow, false, false); if (inGrab) { return; From e0e42353c8cd607053ad987ae80cf129a96ccc0b Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sat, 20 Jan 2024 22:44:20 +1100 Subject: [PATCH 04/12] Update selection when clicking to select new monitor. --- tiling.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tiling.js b/tiling.js index e3d1854a..d946764c 100644 --- a/tiling.js +++ b/tiling.js @@ -1619,6 +1619,10 @@ border-radius: ${borderWidth}px; return; } + // update selection on spaces + setAllWorkspacesInactive(); + this.setSelectionActive(); + /** * if user clicks on window, then ensureViewport on that window before exiting */ From c8dc383b401f15f4b643c64537c2a0625ce7e065 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 21 Jan 2024 07:44:21 +1100 Subject: [PATCH 05/12] FIXES: for drag n drop targets. --- grab.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/grab.js b/grab.js index 977f3bf3..331c773a 100644 --- a/grab.js +++ b/grab.js @@ -38,6 +38,8 @@ export class MoveGrab { // save whether this was tiled window at start of grab this.wasTiled = !(this.initialSpace.isFloating(metaWindow) || Scratch.isScratchWindow(metaWindow)); + + this.dndTargets = []; } begin({ center } = {}) { @@ -286,11 +288,12 @@ export class MoveGrab { }; if (!sameTarget(target, this.dndTarget)) { - // deactivate only if target exists + // has a new zone target if (target) { - this.deactivateDndTarget(this.dndTarget); - this.activateDndTarget(target, initial); + this.dndTargets.push(target); } + this.dndTarget = null; + this.activateDndTarget(target, initial); } } @@ -495,6 +498,9 @@ export class MoveGrab { } activateDndTarget(zone, first) { + if (!zone) { + return; + } const mkZoneActor = props => { let actor = new St.Widget({ style_class: "tile-preview" }); actor.x = props.x ?? 0; @@ -506,6 +512,10 @@ export class MoveGrab { zone.actor = mkZoneActor({ ...zone.actorParams }); + // deactivate previous target + this.dndTargets.filter(t => t !== zone).forEach(t => this.deactivateDndTarget(t)); + this.dndTargets = [zone]; + this.dndTarget = zone; this.zoneActors.add(zone.actor); const raise = () => Utils.actor_raise(zone.actor); @@ -545,13 +555,12 @@ export class MoveGrab { time: Settings.prefs.animation_time, [zone.originProp]: zone.center, [zone.sizeProp]: 0, - onComplete: () => { zone.actor.destroy(); + onComplete: () => { + zone.actor.destroy(); this.zoneActors.delete(zone.actor); }, }); } - - this.dndTarget = null; } } From 569065dc049895823b597e6f9ab6291a24116d89 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 21 Jan 2024 20:47:51 +1100 Subject: [PATCH 06/12] FX: for case where move drag window to another monitor but NOT on a drag target. --- grab.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/grab.js b/grab.js index 331c773a..512a65bc 100644 --- a/grab.js +++ b/grab.js @@ -372,7 +372,7 @@ export class MoveGrab { if (dndTarget) { let space = dndTarget.space; - space.selection.show(); + space.showSelection(); if (Scratch.isScratchWindow(metaWindow)) Scratch.unmakeScratch(metaWindow); @@ -414,6 +414,7 @@ export class MoveGrab { metaWindow.move_frame(true, clone.x, clone.y); Scratch.makeScratch(metaWindow); this.initialSpace.moveDone(); + this.initialSpace.showSelection(); actor.set_scale(clone.scale_x, clone.scale_y); actor.opacity = clone.opacity; @@ -542,7 +543,7 @@ export class MoveGrab { } zone.space.cloneContainer.add_child(zone.actor); - zone.space.selection.hide(); + zone.space.hideSelection(); zone.actor.show(); raise(); Easer.addEase(zone.actor, params); @@ -550,7 +551,7 @@ export class MoveGrab { deactivateDndTarget(zone) { if (zone) { - zone.space.selection.show(); + zone.space.showSelection(); Easer.addEase(zone.actor, { time: Settings.prefs.animation_time, [zone.originProp]: zone.center, From b70e0ab352f39332f070f7aad2f1a881f290848d Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 21 Jan 2024 21:11:49 +1100 Subject: [PATCH 07/12] When monitor focus follows mouse, inactivate selection when switching to another monitor. --- stackoverlay.js | 1 + 1 file changed, 1 insertion(+) diff --git a/stackoverlay.js b/stackoverlay.js index e71c2505..b7e10365 100644 --- a/stackoverlay.js +++ b/stackoverlay.js @@ -98,6 +98,7 @@ export function enableMultimonitorSupport() { // if monitor focus follow mouse ==> activate space on mouse if (Settings.prefs.monitor_focus_follows_mouse) { + Tiling.setAllWorkspacesInactive(); space.activateWithFocus(space.selectedWindow, false, false); } }); From 548a0ca270d956b2fa3b0de6b27a020eea5d0a87 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Sun, 21 Jan 2024 23:00:52 +1100 Subject: [PATCH 08/12] Replaced `add_actor` and `remove_actor` deprecated methods. --- minimap.js | 12 ++++++------ patches.js | 8 ++++---- stackoverlay.js | 2 +- tiling.js | 32 ++++++++++++++++---------------- topbar.js | 20 ++++++++++---------- utils.js | 2 +- virtTiling.js | 10 +++++----- 7 files changed, 43 insertions(+), 43 deletions(-) diff --git a/minimap.js b/minimap.js index 24ab7014..71db1263 100644 --- a/minimap.js +++ b/minimap.js @@ -42,13 +42,13 @@ export class Minimap extends Array { let container = new St.Widget({ name: 'minimap-container' }); this.container = container; - actor.add_actor(highlight); + actor.add_child(highlight); actor.add_actor(label); - actor.add_actor(clip); - clip.add_actor(container); + actor.add_child(clip); + clip.add_child(container); clip.set_position(12 + Settings.prefs.window_gap, 12 + Math.round(1.5 * Settings.prefs.window_gap)); highlight.y = clip.y - 10; - Main.uiGroup.add_actor(this.actor); + Main.uiGroup.add_child(this.actor); this.actor.opacity = 0; this.createClones(); @@ -143,8 +143,8 @@ export class Minimap extends Array { clone.meta_window = mw; container.clone = clone; container.meta_window = mw; - container.add_actor(clone); - this.container.add_actor(container); + container.add_child(clone); + this.container.add_child(container); return container; } diff --git a/patches.js b/patches.js index 915d24d3..1c4c9d2d 100644 --- a/patches.js +++ b/patches.js @@ -321,21 +321,21 @@ export function setupOverrides() { } switch (mode) { case AppIconMode.THUMBNAIL_ONLY: - this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor)); + this._icon.add_child(_createWindowClone(mutterWindow, size * scaleFactor)); break; case AppIconMode.BOTH: - this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor)); + this._icon.add_child(_createWindowClone(mutterWindow, size * scaleFactor)); if (this.app) { - this._icon.add_actor( + this._icon.add_child( this._createAppIcon(this.app, APP_ICON_SIZE_SMALL)); } break; case AppIconMode.APP_ICON_ONLY: size = APP_ICON_SIZE; - this._icon.add_actor(this._createAppIcon(this.app, size)); + this._icon.add_child(this._createAppIcon(this.app, size)); } this._icon.set_size(size * scaleFactor, size * scaleFactor); diff --git a/stackoverlay.js b/stackoverlay.js index b7e10365..c1347f76 100644 --- a/stackoverlay.js +++ b/stackoverlay.js @@ -268,7 +268,7 @@ export class StackOverlay { clone.opacity = 255 * 0.95; clone.set_scale(scale, scale); - Main.uiGroup.add_actor(clone); + Main.uiGroup.add_child(clone); let monitor = this.monitor; let scaleWidth = scale * clone.width; diff --git a/tiling.js b/tiling.js index d946764c..485d98a7 100644 --- a/tiling.js +++ b/tiling.js @@ -268,7 +268,7 @@ export class Space extends Array { workspaceIndicator.connect('button-press-event', () => Main.overview.toggle()); this.workspaceIndicator = workspaceIndicator; let workspaceLabel = new St.Label(); - workspaceIndicator.add_actor(workspaceLabel); + workspaceIndicator.add_child(workspaceLabel); this.workspaceLabel = workspaceLabel; workspaceLabel.hide(); @@ -281,15 +281,15 @@ export class Space extends Array { clip.space = this; cloneContainer.space = this; - container.add_actor(clip); - clip.add_actor(actor); - actor.add_actor(workspaceIndicator); + container.add_child(clip); + clip.add_child(actor); + actor.add_child(workspaceIndicator); actor.add_child(this.focusModeIcon); - actor.add_actor(cloneClip); - cloneClip.add_actor(cloneContainer); + actor.add_child(cloneClip); + cloneClip.add_child(cloneContainer); this.border = new St.Widget({ name: "border" }); - this.actor.add_actor(this.border); + this.actor.add_child(this.border); this.border.hide(); let monitor = Main.layoutManager.primaryMonitor; @@ -891,10 +891,10 @@ export class Space extends Array { this.visible.splice(this.visible.indexOf(metaWindow), 1); let clone = metaWindow.clone; - this.cloneContainer.remove_actor(clone); + this.cloneContainer.remove_child(clone); // Don't destroy the selection highlight widget if (clone.first_child.name === 'selection') - clone.remove_actor(clone.first_child); + clone.remove_child(clone.first_child); let actor = metaWindow.get_compositor_private(); if (actor) actor.remove_clip(); @@ -930,7 +930,7 @@ export class Space extends Array { if (i === -1) return false; this._floating.splice(i, 1); - this.actor.remove_actor(metaWindow.clone); + this.actor.remove_child(metaWindow.clone); return true; } @@ -1313,11 +1313,11 @@ export class Space extends Array { let showTopBar = this.getShowTopBarSetting(); // remove window position bar actors - this.actor.remove_actor(this.windowPositionBarBackdrop); - this.actor.remove_actor(this.windowPositionBar); + this.actor.remove_child(this.windowPositionBarBackdrop); + this.actor.remove_child(this.windowPositionBar); if (showTopBar) { - this.actor.add_actor(this.windowPositionBarBackdrop); - this.actor.add_actor(this.windowPositionBar); + this.actor.add_child(this.windowPositionBarBackdrop); + this.actor.add_child(this.windowPositionBar); } this.updateShowTopBar(); @@ -3007,7 +3007,7 @@ export function registerWindow(metaWindow) { let cloneActor = new Clutter.Clone({ source: actor }); let clone = new Clutter.Actor(); - clone.add_actor(cloneActor); + clone.add_child(cloneActor); clone.targetX = 0; clone.meta_window = metaWindow; @@ -4645,7 +4645,7 @@ export function takeWindow(metaWindow, space, { navigator }) { navigator._moving.push(metaWindow); let parent = backgroundGroup; - parent.add_actor(metaWindow.clone); + parent.add_child(metaWindow.clone); let lowest = navigator._moving[navigator._moving.length - 2]; lowest && parent.set_child_below_sibling(metaWindow.clone, lowest.clone); let point = space.cloneContainer.apply_relative_transform_to_point( diff --git a/topbar.js b/topbar.js index b729ffeb..d8644b9a 100644 --- a/topbar.js +++ b/topbar.js @@ -177,9 +177,9 @@ export function popupMenuEntryHelper(text) { this.prevIcon.grab_key_focus(); }); - this.actor.add_actor(this.prevIcon); - this.actor.add_actor(this.label); - this.actor.add_actor(this.nextIcon); + this.actor.add_child(this.prevIcon); + this.actor.add_child(this.label); + this.actor.add_child(this.nextIcon); this.actor.label_actor = this.label; this.label.clutter_text.connect('activate', this.emit.bind(this, 'activate')); } @@ -213,7 +213,7 @@ class Color { this.color = color; this.actor = new St.Button(); let icon = new St.Widget(); - this.actor.add_actor(icon); + this.actor.add_child(icon); icon.set_style(`background: ${color}`); icon.set_size(20, 20); icon.set_position(4, 4); @@ -235,11 +235,11 @@ class ColorEntry { let flowbox = new St.Widget(); let flowLayout = new Clutter.FlowLayout(); let flow = new St.Widget(); - flowbox.add_actor(flow); + flowbox.add_child(flow); flow.layout_manager = flowLayout; flow.width = 24 * 16; for (let c of colors) { - flow.add_actor(new Color(c, this).actor); + flow.add_child(new Color(c, this).actor); } this.entry = new PopupMenuEntry(startColor, 'Set color'); @@ -251,8 +251,8 @@ class ColorEntry { this.entry.button.connect('clicked', this.clicked.bind(this)); - this.actor.add_actor(this.entry.actor); - this.actor.add_actor(flowbox); + this.actor.add_child(this.entry.actor); + this.actor.add_child(flowbox); } clicked() { @@ -429,7 +429,7 @@ export const WorkspaceMenu = GObject.registerClass( this.setName(Meta.prefs_get_workspace_name(workspaceManager.get_active_workspace_index())); - this.add_actor(this.label); + this.add_child(this.label); this.signals = new Utils.Signals(); this.signals.connect(global.window_manager, @@ -531,7 +531,7 @@ export const WorkspaceMenu = GObject.registerClass( this._navigator = Navigator.getNavigator(); Tiling.spaces.initWorkspaceSequence(); this._enterbox = new Clutter.Actor({ reactive: true }); - Main.uiGroup.add_actor(this._enterbox); + Main.uiGroup.add_child(this._enterbox); this._enterbox.set_position(panelBox.x, panelBox.y + panelBox.height + 20); this._enterbox.set_size(global.screen_width, global.screen_height); Main.layoutManager.trackChrome(this._enterbox); diff --git a/utils.js b/utils.js index 8b7aca61..86f12bfb 100644 --- a/utils.js +++ b/utils.js @@ -117,7 +117,7 @@ export function toggleWindowBoxes(metaWindow) { boxes.push(makeFrameBox(actor, "yellow")); } - boxes.forEach(box => global.stage.add_actor(box)); + boxes.forEach(box => global.stage.add_child(box)); metaWindow._paperDebugBoxes = boxes; return boxes; diff --git a/virtTiling.js b/virtTiling.js index 49425268..6b61a31a 100644 --- a/virtTiling.js +++ b/virtTiling.js @@ -55,13 +55,13 @@ export function repl() { let tilingStyle = `background-color: rgba(190, 190, 0, 0.3);`; let tilingContainer = new St.Widget({ name: "tiling", style: tilingStyle }); - global.stage.add_actor(virtStage); + global.stage.add_child(virtStage); virtStage.x = 3000; virtStage.y = 300; - virtStage.add_actor(monitor); - monitor.add_actor(panel); - monitor.add_actor(tilingContainer); + virtStage.add_child(monitor); + monitor.add_child(panel); + monitor.add_child(tilingContainer); function sync(space_ = space) { let columns = layout( @@ -143,7 +143,7 @@ export function render(columns, tiling) { for (let col of columns) { for (let window of col) { let windowActor = createWindowActor(window); - tiling.add_actor(windowActor); + tiling.add_child(windowActor); } } } From b7c7ec22fa40a84e456d916cc072d574bb61a6db Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Mon, 22 Jan 2024 22:34:53 +1100 Subject: [PATCH 09/12] FIX: for case where switchWorkspace by clicking link (which opens window in another space on another monitor) - if space is shown on that monitor don't do gnome workspace switch animation. --- patches.js | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/patches.js b/patches.js index 1c4c9d2d..bfbf635e 100644 --- a/patches.js +++ b/patches.js @@ -140,21 +140,47 @@ export function setupOverrides() { // WorkspaceAnimation.WorkspaceAnimationController.animateSwitch // Disable the workspace switching animation in Gnome 40+ function (_from, _to, _direction, onComplete) { + // ensure swipeTrackers are disabled after this + const reset = () => { + // gnome windows switch animation time = 250, do that plus a little more + pillSwipeTimer = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 300, () => { + swipeTrackers.forEach(t => { + t.enabled = false; + }); + pillSwipeTimer = null; + return false; // on return false destroys timeout + }); + }; + + if (Tiling.inPreview) { + onComplete(); + reset(); + return; + } + // if using PaperWM workspace switch animation, just do complete here - if (Tiling.inPreview || !Tiling.spaces.space_defaultAnimation) { + if (!Tiling.spaces.space_defaultAnimation) { onComplete(); + reset(); + return; } - else { - const saved = getSavedPrototype(WorkspaceAnimation.WorkspaceAnimationController, 'animateSwitch'); - saved.call(this, _from, _to, _direction, onComplete); + + // if switching to a paperwm space that is already shown on a monitor + // from / to are workspace indices + const toSpace = Tiling.spaces.spaceOfIndex(_to); + + const spaces = Array.from(Tiling.spaces.monitors.values()); + const toOnMonitor = spaces.some(space => space === toSpace); + if (toOnMonitor) { + onComplete(); + reset(); + return; } - // ensure swipeTrackers are disabled after this - pillSwipeTimer = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500, () => { - swipeTrackers.forEach(t => t.enabled = false); - pillSwipeTimer = null; - return false; // on return false destroys timeout - }); + // standard gnome switch animation + const saved = getSavedPrototype(WorkspaceAnimation.WorkspaceAnimationController, 'animateSwitch'); + saved.call(this, _from, _to, _direction, onComplete); + reset(); }); registerOverridePrototype(WorkspaceAnimation.WorkspaceAnimationController, '_prepareWorkspaceSwitch', From 21efa47d0443064ccd044bcde7190a1fc1f44fa9 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Tue, 23 Jan 2024 08:39:19 +1100 Subject: [PATCH 10/12] Added `touch-event` on space backvround to activate space. --- tiling.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tiling.js b/tiling.js index 485d98a7..68579a67 100644 --- a/tiling.js +++ b/tiling.js @@ -1637,8 +1637,13 @@ border-radius: ${borderWidth}px; Navigator.finishNavigation(); }); - this.signals.connect( - this.background, 'scroll-event', + // ensure this space is active if touched + this.signals.connect(this.background, 'touch-event', + (actor, event) => { + this.activateWithFocus(this.selectedWindow, false, false); + }); + + this.signals.connect(this.background, 'scroll-event', (actor, event) => { if (!inGrab && !Navigator.navigating) return; From 7be53ae2ebeec10ae40e717c1db0304386d5b771 Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Wed, 24 Jan 2024 22:19:17 +1100 Subject: [PATCH 11/12] Created create extra virtual click at cursor when monitor-focus-follow-mouse is disabled (first click enables space, 2nd virtual click happens after). --- grab.js | 28 +--------------------------- tiling.js | 16 +++++++++++++++- utils.js | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 29 deletions(-) diff --git a/grab.js b/grab.js index 512a65bc..f425267c 100644 --- a/grab.js +++ b/grab.js @@ -8,23 +8,6 @@ import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import { Settings, Utils, Tiling, Navigator, Scratch } from './imports.js'; import { Easer } from './utils.js'; -/** - * Returns a virtual pointer (i.e. mouse) device that can be used to - * "clickout" of a drag operation when `grab_end_op` is unavailable - * (i.e. as of Gnome 44 where `grab_end_op` was removed). - * @returns Clutter.VirtualInputDevice -*/ -let virtualPointer; -export function getVirtualPointer() { - if (!virtualPointer) { - virtualPointer = Clutter.get_default_backend() - .get_default_seat() - .create_virtual_device(Clutter.InputDeviceType.POINTER_DEVICE); - } - - return virtualPointer; -} - export class MoveGrab { constructor(metaWindow, type, space) { this.window = metaWindow; @@ -484,16 +467,7 @@ export class MoveGrab { */ Utils.later_add(Meta.LaterType.IDLE, () => { if (!global.display.end_grab_op && this.wasTiled) { - // move to current cursor position - let [x, y, _mods] = global.get_pointer(); - getVirtualPointer().notify_absolute_motion( - Clutter.get_current_event_time(), - x, y); - - getVirtualPointer().notify_button(Clutter.get_current_event_time(), - Clutter.BUTTON_PRIMARY, Clutter.ButtonState.PRESSED); - getVirtualPointer().notify_button(Clutter.get_current_event_time(), - Clutter.BUTTON_PRIMARY, Clutter.ButtonState.RELEASED); + Utils.clickAtCursorPoint(); } }); } diff --git a/tiling.js b/tiling.js index 68579a67..299d9d0e 100644 --- a/tiling.js +++ b/tiling.js @@ -89,7 +89,7 @@ let signals, backgroundGroup, grabSignals; let gsettings, backgroundSettings, interfaceSettings; let displayConfig; let saveState; -let startupTimeoutId, timerId, fullscrenStartTimeout; +let startupTimeoutId, timerId, fullscrenStartTimeout, backgroundClickTimout; let workspaceSettings; export let inGrab; export function enable(extension) { @@ -191,6 +191,8 @@ export function disable () { timerId = null; Utils.timeout_remove(fullscrenStartTimeout); fullscrenStartTimeout = null; + Utils.timeout_remove(backgroundClickTimout); + backgroundClickTimout = null; grabSignals.destroy(); grabSignals = null; @@ -1633,6 +1635,18 @@ border-radius: ${borderWidth}px; ensureViewport(windowAtPoint, this); } + /** + * if not monitor focus follows, then do a virtual click (first click + * activated space). + */ + if (!Settings.prefs.monitor_focus_follows_mouse) { + backgroundClickTimout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 150, () => { + Utils.clickAtCursorPoint(); + backgroundClickTimout = null; + return false; + }); + } + spaces.selectedSpace = this; Navigator.finishNavigation(); }); diff --git a/utils.js b/utils.js index 86f12bfb..389a3145 100644 --- a/utils.js +++ b/utils.js @@ -15,7 +15,7 @@ import { Lib } from './imports.js'; const Display = global.display; export let version = Config.PACKAGE_VERSION.split('.').map(Number); -let warpRipple; +let warpRipple, virtualPointer; export function enable() { warpRipple = new Ripples.Ripples(0.5, 0.5, 'ripple-pointer-location'); warpRipple.addTo(Main.uiGroup); @@ -217,6 +217,38 @@ export function warpPointer(x, y) { warpRipple.playAnimation(x, y); } +/** + * Returns a virtual pointer (i.e. mouse) device that can be used to + * "clickout" of a drag operation when `grab_end_op` is unavailable + * (i.e. as of Gnome 44 where `grab_end_op` was removed). + * @returns Clutter.VirtualInputDevice +*/ +export function getVirtualPointer() { + if (!virtualPointer) { + virtualPointer = Clutter.get_default_backend() + .get_default_seat() + .create_virtual_device(Clutter.InputDeviceType.POINTER_DEVICE); + } + + return virtualPointer; +} + +/** + * Clicks at cursor point (with virtual pointer). + */ +export function clickAtCursorPoint() { + // move to current cursor position + let [x, y, _mods] = global.get_pointer(); + getVirtualPointer().notify_absolute_motion( + Clutter.get_current_event_time(), + x, y); + + getVirtualPointer().notify_button(Clutter.get_current_event_time(), + Clutter.BUTTON_PRIMARY, Clutter.ButtonState.PRESSED); + getVirtualPointer().notify_button(Clutter.get_current_event_time(), + Clutter.BUTTON_PRIMARY, Clutter.ButtonState.RELEASED); +} + /** * Return current modifiers state (or'ed Clutter.ModifierType.*) */ From 645711aff824ccdb0ed417c037d7c9d84d460aff Mon Sep 17 00:00:00 2001 From: Jay Ta'ala Date: Thu, 25 Jan 2024 08:38:49 +1100 Subject: [PATCH 12/12] FIX: monitor lastSpace check should be dynamic (ensures if space activated by other means then pointer check remains valid). --- stackoverlay.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/stackoverlay.js b/stackoverlay.js index c1347f76..70806d34 100644 --- a/stackoverlay.js +++ b/stackoverlay.js @@ -43,14 +43,13 @@ import { Settings, Utils, Tiling, Navigator, Grab, Scratch } from './imports.js' restack loops) */ -let pointerWatch, lastSpace; +let pointerWatch; export function enable(extension) { } export function disable() { disableMultimonitorSupport(); - lastSpace = null; } /** @@ -74,11 +73,9 @@ export function enableMultimonitorSupport() { const space = Tiling.spaces.monitors.get(monitor); // same space - if (space === lastSpace) { + if (space === Tiling.spaces.activeSpace) { return; } - // update to space - lastSpace = space; // check if in the midst of a window resize action if (Tiling.inGrab &&