Open danmou opened 5 years ago
I like the idea, in the mean time you might want to map up some keys for easier multi monitor management.
I have added these:
function getSortedMonitors() {
var Main = imports.ui.main;
let monitors = [...Array.from(Main.layoutManager.monitors)];
monitors.sort((a, b) => a.x - b.x);
return monitors;
}
function navigateMonitor(baseBinding = "<Super><Shift>") {
var Tiling = Extension.imports.tiling;
function goToMonitorByIndex(sortedMonitors, index) {
let monitor = sortedMonitors[index];
let space = Tiling.spaces.monitors.get(monitor);
if (space) {
space.workspace.activate(global.get_current_time());
}
}
Keybindings.bindkey(
`${baseBinding}Left`,
"monitor-left",
() => {
let monitors = getSortedMonitors();
let curMonitor = Tiling.spaces.selectedSpace.monitor;
let curMonitorI = monitors.indexOf(curMonitor);
let prevMonitorI =
(curMonitorI === 0 ? monitors.length : curMonitorI) - 1;
goToMonitorByIndex(monitors, prevMonitorI);
},
{ activeInNavigator: true }
);
Keybindings.bindkey(
`${baseBinding}Right`,
"monitor-right",
() => {
let monitors = getSortedMonitors();
let curMonitor = Tiling.spaces.selectedSpace.monitor;
let curMonitorI = monitors.indexOf(curMonitor);
let nextMonitorI = (curMonitorI + 1) % monitors.length;
goToMonitorByIndex(monitors, nextMonitorI);
},
{ activeInNavigator: true }
);
}
function navigateMonitorWithWindow(baseBinding = "<Super><Shift><Ctrl>") {
var Tiling = Extension.imports.tiling;
function moveToMonitorByIndex(sortedMonitors, index) {
let monitor = sortedMonitors[index];
let currentSpace = Tiling.spaces.selectedSpace;
let newSpace = Tiling.spaces.monitors.get(monitor);
if (newSpace) {
const window = currentSpace.selectedWindow;
if (window) {
currentSpace.removeWindow(window);
}
newSpace.workspace.activate(global.get_current_time());
if (window) {
window.change_workspace(newSpace.workspace);
if (window.get_workspace() === newSpace.workspace) {
Tiling.insertWindow(window, { existing: true });
}
}
}
}
Keybindings.bindkey(
`${baseBinding}Left`,
"move-monitor-left",
() => {
let monitors = getSortedMonitors();
let curMonitor = Tiling.spaces.selectedSpace.monitor;
let curMonitorI = monitors.indexOf(curMonitor);
let prevMonitorI =
(curMonitorI === 0 ? monitors.length : curMonitorI) - 1;
moveToMonitorByIndex(monitors, prevMonitorI);
},
{ activeInNavigator: true }
);
Keybindings.bindkey(
`${baseBinding}Right`,
"move-monitor-right",
() => {
let monitors = getSortedMonitors();
let curMonitor = Tiling.spaces.selectedSpace.monitor;
let curMonitorI = monitors.indexOf(curMonitor);
let nextMonitorI = (curMonitorI + 1) % monitors.length;
moveToMonitorByIndex(monitors, nextMonitorI);
},
{ activeInNavigator: true }
);
}
The idea is that Super+Shift should behave similar to just Super but for monitors, so Super+Shift+Left/Right navigates and Super+Shift+Ctrl+Left/Right moves the current window.
I also tried to map up Super+Shift+y for swapping the workspace between two monitors but I have not been able to get that to work yet :/
EDIT: The previous version did not handle three or more monitors that where arranged in a different order than their display number. It still does not handle configurations where monitors are also stacked vertically, but frankly I do not care so if someone want that they will have to implement it themselves.
I also tried to map up Super+Shift+y for swapping the workspace between two monitors but I have not been able to get that to work yet :/
I added a moveSpaceToMonitor
function to the examples keybindings which does this.
I like the way multi-monitor support is implemented currently, with one workspace on each monitor. However, sometimes it would be nice to be able to see two windows from the same workspace on different monitors (without having to move them to an empty workspace). This would also feel quite intuitive because monitors are typically side-by-side.
I realize that it's a bit complicated to make this work because the monitors can have different sizes, but I have a suggestion for how it could be accomplished in an intuitive and not too complicated way. I think the easiest way to describe it is to describe how it could be implemented, although it could of course be done differently.
As now you would be able to choose a workspace independently on each monitor. However, with the new system you could also choose the same workspace on both monitors (already open workspaces would not be filtered from the list). If you do, an invisible placeholder entry
monitor_change
is added to the list of windows in that workspace. Windows to the left of this window are displayed on the leftmost monitor and windows to the right of it are displayed on the rightmost monitor. If you add a third monitor, anothermonitor_change
is added to divide the windows into left, middle and right, and so on. If you move the rightmost window on the leftmost monitor to the right, it will pass themonitor_change
placeholder and therefore be moved to the next monitor, exactly as one would expect. As a bonus, the placeholders could be kept in place but ignored when the monitor is disconnected, allowing you to switch back and forth between single-monitor and dual-monitor with no hassle.This system would be intuitive to use, avoids complications with windows overlapping between different-size monitors and won't require any additional keyboard shortcuts.
To make it even smarter, and avoid having monitors with no windows on them, a simple rule could be implemented such that, if two
monitor_change
placeholders are next to each other (meaning a monitor has no windows on it) and at least one monitor has more than one window, one of the placeholders will be shifted to "steal" a window from the next monitor. (The direction of the shift should be right by default, unless no monitor to the right has more than one window in which case it would be left, because new windows are opened to the right). This process would continue recursively until the windows are distributed.Sorry for the long description. I understand that this feature won't be a high priority, but I wanted to put it out there. If you think it would be useful, but don't have time to implement it, I might find the time to make a PR myself at some point in the (distant) future, although I would have to refresh my JS skills first.