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;