main: Add help function for moving window to monitor/workspace

MetaWindow.move_to_monitor() can no longer be assumed to have updated
the monitor on return, as under wayland, if the move involves a size
change, the monitor state will only be updated after the new size has
been synced with the client.

If that happens, trying to change the workspace of the moved window
fails, as it is still considered on-all-workspaces until it leaves
the secondary monitor.

It's possible to work around this by waiting for the window to actually
enter the requested monitor. That's finicky enough to warrant a helper
funtion, so add one.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/893

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2259>
This commit is contained in:
Florian Müllner 2022-03-31 16:59:49 +02:00
parent e831a9240d
commit 1cb01ec5b1

View File

@ -5,7 +5,8 @@
shellAccessDialogDBusService, shellAudioSelectionDBusService,
screenSaverDBus, uiGroup, magnifier, xdndHandler, keyboard,
kbdA11yDialog, introspectService, start, pushModal, popModal,
activateWindow, createLookingGlass, initializeDeferredWork,
activateWindow, moveWindowToMonitorAndWorkspace,
createLookingGlass, initializeDeferredWork,
getThemeStylesheet, setThemeStylesheet, screenshotUI */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
@ -720,6 +721,33 @@ function activateWindow(window, time, workspaceNum) {
panel.closeCalendar();
}
/**
* Move @window to the specified monitor and workspace.
*
* @param {Meta.Window} window - the window to move
* @param {number} monitorIndex - the requested monitor
* @param {number} workspaceIndex - the requested workspace
* @param {bool} append - create workspace if it doesn't exist
*/
function moveWindowToMonitorAndWorkspace(window, monitorIndex, workspaceIndex, append = false) {
// We need to move the window before changing the workspace, because
// the move itself could cause a workspace change if the window enters
// the primary monitor
if (window.get_monitor() !== monitorIndex) {
// Wait for the monitor change to take effect
const id = global.display.connect('window-entered-monitor',
(dsp, num, w) => {
if (w !== window)
return;
window.change_workspace_by_index(workspaceIndex, append);
global.display.disconnect(id);
});
window.move_to_monitor(monitorIndex);
} else {
window.change_workspace_by_index(workspaceIndex, append);
}
}
// TODO - replace this timeout with some system to guess when the user might
// be e.g. just reading the screen and not likely to interact.
var DEFERRED_TIMEOUT_SECONDS = 20;