Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions keybindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,15 @@ export function setupActions(settings) {
registerMinimapAction("move-down",
(_mw, space) => space.swap(Meta.MotionDirection.DOWN));

registerMinimapAction("move-global-left",
(_mw, space) => space.swapGlobal(Meta.MotionDirection.LEFT));
registerMinimapAction("move-global-right",
(_mw, space) => space.swapGlobal(Meta.MotionDirection.RIGHT));
registerMinimapAction("move-global-up",
(_mw, space) => space.swapGlobal(Meta.MotionDirection.UP));
registerMinimapAction("move-global-down",
(_mw, space) => space.swapGlobal(Meta.MotionDirection.DOWN));

registerPaperAction("toggle-scratch-window",
Scratch.toggleScratchWindow);

Expand Down
4 changes: 4 additions & 0 deletions prefsKeybinding.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ const actions = {
'move-right',
'move-up',
'move-down',
'move-global-left',
'move-global-right',
'move-global-up',
'move-global-down',
'slurp-in',
'barf-out',
'barf-out-active',
Expand Down
Binary file modified schemas/gschemas.compiled
Binary file not shown.
21 changes: 19 additions & 2 deletions schemas/org.gnome.shell.extensions.paperwm.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -347,11 +347,11 @@

<key type="as" name="move-right">
<default><![CDATA[['<Super><Ctrl>period', '<Super><Shift>period', '<Super><Ctrl>Right']]]></default>
<summary>Move the active window to the right</summary>
<summary>Move the active window to the right, staying on the same monitor</summary>
</key>
<key type="as" name="move-left">
<default><![CDATA[['<Super><Ctrl>comma', '<Super><Shift>comma', '<Super><Ctrl>Left']]]></default>
<summary>Move the active window to the left</summary>
<summary>Move the active window to the left, staying on the same monitor</summary>
</key>
<key type="as" name="move-up">
<default><![CDATA[['<Super><Ctrl>Up']]]></default>
Expand All @@ -362,6 +362,23 @@
<summary>Move the active window down</summary>
</key>

<key type="as" name="move-global-right">
<default><![CDATA[[]]]></default>
<summary>Move the active window to the right</summary>
</key>
<key type="as" name="move-global-left">
<default><![CDATA[[]]]></default>
<summary>Move the active window to the left</summary>
</key>
<key type="as" name="move-global-up">
<default><![CDATA[[]]]></default>
<summary>Move the active window up or to the workspace above</summary>
</key>
<key type="as" name="move-global-down">
<default><![CDATA[[]]]></default>
<summary>Move the active window down or to the workspace below</summary>
</key>

<key type="as" name="slurp-in">
<default><![CDATA[['<Super>i']]]></default>
<summary>Consume window into the active column</summary>
Expand Down
106 changes: 96 additions & 10 deletions tiling.js
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,46 @@ export class Space extends Array {
ensureViewport(this.selectedWindow, this, { force: true });
}

swapGlobal(direction, metaWindow) {
metaWindow = metaWindow || this.selectedWindow;

let [index, row] = this.positionOf(metaWindow);
let targetIndex = index;
let targetRow = row;
const dir = Utils.motionToDisplayDirection[direction];
switch (direction) {
case Meta.MotionDirection.LEFT:
targetIndex--;
break;
case Meta.MotionDirection.RIGHT:
targetIndex++;
break;
case Meta.MotionDirection.DOWN:
targetRow++;
break;
case Meta.MotionDirection.UP:
targetRow--;
break;
}
if (targetIndex < 0 || targetIndex >= this.length) {
spaces.switchMonitor(dir, true, true, metaWindow);
return;
}
let column = this[index];
if (targetRow < 0 || targetRow >= column.length) {
spaces.selectSequenceSpace(direction, true);
Navigator.finishNavigation();
return;
}

Lib.swap(this[index], row, targetRow);
Lib.swap(this, index, targetIndex);

this.layout();
this.emit('swapped', index, targetIndex, row, targetRow);
ensureViewport(this.selectedWindow, this, { force: true });
}

switchLinear(dir, loop) {
let index = this.selectedIndex();
let column = this[index];
Expand Down Expand Up @@ -1190,13 +1230,8 @@ export class Space extends Array {
switchGlobalUp() { this.switchGlobal(Meta.MotionDirection.UP); }
switchGlobalDown() { this.switchGlobal(Meta.MotionDirection.DOWN); }
switchGlobal(direction) {
const motionToDisplayDirection = {
[Meta.MotionDirection.LEFT]: Meta.DisplayDirection.LEFT,
[Meta.MotionDirection.RIGHT]: Meta.DisplayDirection.RIGHT,
[Meta.MotionDirection.UP]: Meta.DisplayDirection.UP,
[Meta.MotionDirection.DOWN]: Meta.DisplayDirection.DOWN,
};
const dir = motionToDisplayDirection[direction]
const dir = Utils.motionToDisplayDirection[direction];

let space = this;

const switchMonitor = () => {
Expand Down Expand Up @@ -2566,8 +2601,10 @@ export const Spaces = class Spaces extends Map {
return nSpaces <= nMonitors;
}

switchMonitor(direction, move, warp = true) {
let focus = display.focus_window;
switchMonitor(direction, move, warp = true, focus = null) {
// For unkown reasons, display.focus_window is null if you are in the
// middle of moving a winodw, aka if navigation is open.
focus = focus ?? display.focus_window;
let monitor = focusMonitor();
let currentSpace = this.monitors.get(monitor);
let i = display.get_monitor_neighbor_index(monitor.index, direction);
Expand All @@ -2580,6 +2617,12 @@ export const Spaces = class Spaces extends Map {
let space = this.monitors.get(newMonitor);

if (move && focus) {
const customIndex = getMoveWindowPositionIndex(space, direction);
if (customIndex !== null) {
// namespaced prop to avoid possible future collisions
focus.paperwm_openAtIndex = customIndex;
}

let metaWindow = focus.get_transient_for() || focus;

if (currentSpace && currentSpace.indexOf(metaWindow) !== -1) {
Expand Down Expand Up @@ -4164,7 +4207,13 @@ Opening "${metaWindow?.title}" on current space.`);
}
ok && clone.set_position(x, y);

if (!space.addWindow(metaWindow, getOpenWindowPositionIndex(space)))
// When moving a window from another monitor, we may request a certain index
const openAtIndex = metaWindow.paperwm_openAtIndex ?? getOpenWindowPositionIndex(space);
if (metaWindow.paperwm_openAtIndex) {
delete metaWindow.paperwm_openAtIndex;
}

if (!space.addWindow(metaWindow, openAtIndex))
return;

metaWindow.unmake_above();
Expand Down Expand Up @@ -4267,6 +4316,43 @@ Opening "${metaWindow?.title}" on current space.`);
}
}

/**
* When we're moving a window from an existing monitor, we want to insert with
* minimal disruption. E.g. if we're moving window E to the left,
*
* ([a b] c d) ([E f])
* (a [b E] c d) ([f])
*
* so that visually it looks like this:
*
* [a b] [E f]
* [b E] [f g]
*
* regardless of the setting for inserting new windows.
*/
function getMoveWindowPositionIndex(space, direction) {
const visibleColumns = space.filter(([mw]) => space.isVisible(mw));

if (visibleColumns.length === 0) {
return null;
}

switch (direction) {
case Meta.DisplayDirection.LEFT: {
const windowAtTarget = visibleColumns[visibleColumns.length - 1][0];
return space.indexOf(windowAtTarget) + 1;
break;
}
case Meta.DisplayDirection.RIGHT: {
const windowAtTarget = visibleColumns[0][0];
return space.indexOf(windowAtTarget);
}
default:
// No special handling yet for moving up/down
return null;
}
}

/**
* Gets the window index to add a new window in the space:
* { RIGHT: 0, LEFT: 1, START: 2, END: 3 };
Expand Down
7 changes: 7 additions & 0 deletions utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ export function setBackgroundImage(actor, resource_path) {
actor.content_repeat = Clutter.ContentRepeat.BOTH;
}

export const motionToDisplayDirection = {
[Meta.MotionDirection.LEFT]: Meta.DisplayDirection.LEFT,
[Meta.MotionDirection.RIGHT]: Meta.DisplayDirection.RIGHT,
[Meta.MotionDirection.UP]: Meta.DisplayDirection.UP,
[Meta.MotionDirection.DOWN]: Meta.DisplayDirection.DOWN,
};

/**
* Backwards compatible function. Attempts to use Cogl.Color with a fallback
* to Clutter.Color.
Expand Down