diff --git a/README.md b/README.md index 19b289af..17d25e97 100644 --- a/README.md +++ b/README.md @@ -95,13 +95,13 @@ Swiping the trackpad horizontally with three fingers (only available in Wayland) | CtrlAltTab | Cycle through previously active scratch windows | | ShiftCtrlAltTab | Cycle through previously active scratch windows (backward order) | | ShiftSuperC | Switch between window focus modes | -| ShiftSuperW | Switch between positions for creating new windows | -| _Not set by default (set in extension settings)_ | Create new windows to the right of current window | -| _Not set by default (set in extension settings)_ | Create new windows to the left of current window | -| _Not set by default (set in extension settings)_ | Create new windows in vertical stack (down) | -| _Not set by default (set in extension settings)_ | Create new windows in vertical stack (up) | -| _Not set by default (set in extension settings)_ | Create new windows at start position | -| _Not set by default (set in extension settings)_ | Create new windows at end position | +| ShiftSuperW | Switch between positions for creating/dropping new windows | +| _Not set by default (set in extension settings)_ | Create/drop windows to the right of current window | +| _Not set by default (set in extension settings)_ | Create/drop windows to the left of current window | +| _Not set by default (set in extension settings)_ | Create/drop windows in vertical stack (down) | +| _Not set by default (set in extension settings)_ | Create/drop windows in vertical stack (up) | +| _Not set by default (set in extension settings)_ | Create/drop windows at start position | +| _Not set by default (set in extension settings)_ | Create/drop windows at end position | | SuperCtrl, or SuperCtrl. | Move the current window to the left or right | | ShiftSuper, or ShiftSuper. | Move the current window to the left or right | | SuperCtrlLeft or SuperCtrlRight | Move the current window to the left or right | @@ -280,9 +280,9 @@ You do this by using the special "match all" operator `*` as an input for `wm_cl This special operator is at a lower precedence, so more specific properties that match a window will always take precedence and be applied. -## Window insertion position for new windows +## Window insertion position for new windows (and dropped windows in `take` mode) -By default PaperWM inserts new windows to the right of the currently active window. This behaviour can be changed via PaperWM settings, or with the `Open Window Position` button/icon (which is to the right of the focus mode icon): +By default PaperWM inserts new windows (and drops windows in `take` mode, see [Managing multiple windows at once](#managing-multiple-windows-at-once)) to the right of the currently active window. This behaviour can be changed via PaperWM settings, or with the `Open Window Position` button/icon (which is to the right of the focus mode icon): ![Open positions button](media/open-position-button.png) diff --git a/schemas/org.gnome.shell.extensions.paperwm.gschema.xml b/schemas/org.gnome.shell.extensions.paperwm.gschema.xml index d4d5cf3f..531272b2 100644 --- a/schemas/org.gnome.shell.extensions.paperwm.gschema.xml +++ b/schemas/org.gnome.shell.extensions.paperwm.gschema.xml @@ -182,31 +182,31 @@ w']]]> - Switch between positions for creating windows (e.g. right, left) + Switch between positions for creating/dropping windows - Create new windows to the right + Create/drop windows to the right - Create new windows to the left + Create/drop windows to the left - Create new windows in vertical stack (down) + Create/drop windows in vertical stack (down) - Create new windows in vertical stack (up) + Create/drop windows in vertical stack (up) - Create new windows at start position + Create/drop windows at start position - Create new windows at end position + Create/drop windows at end position diff --git a/tiling.js b/tiling.js index 0ca4ac66..27856500 100644 --- a/tiling.js +++ b/tiling.js @@ -3964,7 +3964,11 @@ export function add_handler(_ws, metaWindow) { and `Display::window-created` through `WindowActor::show` if window is newly created to ensure that the WindowActor exists. */ -export function insertWindow(metaWindow, { existing }) { +export function insertWindow(metaWindow, options = {}) { + const existing = options?.existing ?? false; + const dropping = options?.dropping ?? false; + const dropCallback = options?.dropCallback ?? function() {}; + // Add newly created windows to the space being previewed if (!existing && !metaWindow.is_on_all_workspaces() && @@ -4096,6 +4100,40 @@ export function insertWindow(metaWindow, { existing }) { // run a simple layout in pre-prepare layout space.layout(false); + const slurpCheck = timeout => { + let slurpPosition; + switch (Settings.prefs.open_window_position) { + case Settings.OpenWindowPositions.DOWN: + slurpPosition = SlurpInsertPosition.BELOW; + break; + case Settings.OpenWindowPositions.UP: + slurpPosition = SlurpInsertPosition.ABOVE; + break; + } + + if (!slurpPosition) { + dropCallback(metaWindow); + return; + } + + // has slurpPosition but no timeout + if (!timeout) { + slurp(active, slurpPosition); + dropCallback(metaWindow); + return; + } + + // if need to slurp (i.e. vertical stack) + stackSlurpTimeout = GLib.timeout_add( + GLib.PRIORITY_DEFAULT, + 100, + () => { + slurp(active, slurpPosition); + dropCallback(metaWindow); + return false; // on return false destroys timeout + }); + }; + /** * If window is new, then setup and ensure is in view * after actor is shown on stage. @@ -4118,26 +4156,7 @@ export function insertWindow(metaWindow, { existing }) { ensureViewport(space.selectedWindow, space); space.setSpaceTopbarElementsVisible(true); - let slurpPosition; - switch (Settings.prefs.open_window_position) { - case Settings.OpenWindowPositions.DOWN: - slurpPosition = SlurpInsertPosition.BELOW; - break; - case Settings.OpenWindowPositions.UP: - slurpPosition = SlurpInsertPosition.ABOVE; - break; - } - - // if need to slurp (i.e. vertical stack) - if (slurpPosition) { - stackSlurpTimeout = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, - 100, - () => { - slurp(active, slurpPosition); - return false; // on return false destroys timeout - }); - } + slurpCheck(true); }); return; @@ -4152,6 +4171,10 @@ export function insertWindow(metaWindow, { existing }) { } else { ensureViewport(space.selectedWindow, space); } + + if (dropping) { + slurpCheck(false); + } } /** @@ -5130,6 +5153,10 @@ export function slurp(metaWindow, insertAt = SlurpInsertPosition.BOTTOM) { } const space = spaces.spaceOfWindow(metaWindow); + if (!space) { + return; + } + const index = space.indexOf(metaWindow); let to, from, metaWindowToSlurp; @@ -5299,11 +5326,11 @@ export function moveUpSpace(_mw, _space) { Detach the @metaWindow, storing it at the bottom right corner while navigating. When done, insert all the detached windows again. */ -export function takeWindow(metaWindow, space, params) { +export function takeWindow(metaWindow, space, options = {}) { space = space ?? spaces.selectedSpace; metaWindow = metaWindow ?? space.selectedWindow; - const navigator = params?.navigator ?? Navigator.getNavigator(); - const existing = params?.existing ?? false; + const navigator = options?.navigator ?? Navigator.getNavigator(); + const existing = options?.existing ?? false; if (!existing && !space.removeWindow(metaWindow)) return; @@ -5375,7 +5402,7 @@ export function takeWindow(metaWindow, space, params) { const pop = navigator._moving.pop(); if (pop) { changeSpace(pop); - insertWindow(pop, { existing: true }); + insertWindow(pop, { existing: true, dropping: true }); // make space selectedWindow (keeps index for next insert) selectedSpace().selectedWindow = pop; ensureViewport(pop); @@ -5400,8 +5427,15 @@ export function takeWindow(metaWindow, space, params) { case Clutter.KEY_q: { navigator._moving.forEach(w => { changeSpace(w); - insertWindow(w, { existing: true }); - w.delete(global.get_current_time()); + insertWindow( + w, + { + existing: true, + dropping: true, + dropCallback: mw => { + mw.delete(global.get_current_time()); + }, + }); }); navigator._moving = []; @@ -5421,7 +5455,7 @@ export function takeWindow(metaWindow, space, params) { let selectedSpace = spaces.selectedSpace; navigator._moving.forEach(w => { changeSpace(w); - insertWindow(w, { existing: true }); + insertWindow(w, { existing: true, dropping: true }); // make space selectedWindow (keeps index for next insert) selectedSpace.selectedWindow = w;