Skip to content
Open
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
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ MSGSRC = $(wildcard po/*.po)

.PHONY: all clean install schemas uninstall enable disable log debug patchcss

# Targets like "build: clean ..." rely on prerequisite order; with -j the
# clean step races and deletes freshly compiled schemas.
.NOTPARALLEL:

all: build install enable restart

dev: build debug install
Expand Down
70 changes: 49 additions & 21 deletions lib/extension/window.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,10 @@ export class WindowManager extends GObject.Object {
const shellWm = global.window_manager;

this._displaySignals = [
display.connect("window-created", this.trackWindow.bind(this)),
display.connect("window-created", (_display, metaWindow) => {
this._awaitFirstFrame(metaWindow);
this.trackWindow(_display, metaWindow);
}),
display.connect("grab-op-begin", this._handleGrabOpBegin.bind(this)),
display.connect("window-entered-monitor", (_, monitor, metaWindow) => {
this.updateMetaWorkspaceMonitor("window-entered-monitor", monitor, metaWindow);
Expand Down Expand Up @@ -958,20 +961,52 @@ export class WindowManager extends GObject.Object {
});
}

/**
* Mark a freshly created window as not ready until its actor paints the
* first frame. Touching its geometry earlier crashes mutter 51
* (meta_window_move_resize_internal: priv->is_ready).
*/
_awaitFirstFrame(metaWindow) {
let windowActor = metaWindow?.get_compositor_private();
if (!windowActor) return;
metaWindow.forgeAwaitingFirstFrame = true;
let signalId = windowActor.connect("first-frame", () => {
windowActor.disconnect(signalId);
metaWindow.forgeAwaitingFirstFrame = false;
this.queueEvent(
{
name: "window-first-frame",
callback: () => {
if (!metaWindow.get_compositor_private()) return;
this._unmaximize(metaWindow);
this.renderTree("window-first-frame", true);
},
},
50
);
});
}

_unmaximize(metaWindow) {
if (metaWindow.forgeAwaitingFirstFrame) return;
if (typeof metaWindow.get_maximize_flags === "function") {
// GNOME 49+
let flags = metaWindow.get_maximize_flags();
// MaximizeFlags.NONE (= 0) only exists since GNOME 51
if (flags !== 0) metaWindow.set_unmaximize_flags(flags);
return;
}
// pre-49 fallback
metaWindow.unmaximize(Meta.MaximizeFlags.BOTH);
}

// Window movement API
move(metaWindow, rect) {
if (!metaWindow) return;
if (metaWindow.grabbed) return;
try {
// GNOME 49+
metaWindow.set_unmaximize_flags(Meta.MaximizeFlags.BOTH);
metaWindow.unmaximize();
} catch (e) {
// pre-49 fallback
metaWindow.unmaximize(Meta.MaximizeFlags.HORIZONTAL);
metaWindow.unmaximize(Meta.MaximizeFlags.VERTICAL);
metaWindow.unmaximize(Meta.MaximizeFlags.BOTH);
}
// Mutter 51 segfaults when resizing/unmaximizing a window that is not ready yet
if (metaWindow.forgeAwaitingFirstFrame) return;
this._unmaximize(metaWindow);

let windowActor = metaWindow.get_compositor_private();
if (!windowActor) return;
Expand Down Expand Up @@ -1541,16 +1576,8 @@ export class WindowManager extends GObject.Object {
{
name: "window-create-queue",
callback: () => {
try {
// GNOME 49+
metaWindow.set_unmaximize_flags(Meta.MaximizeFlags.BOTH);
metaWindow.unmaximize();
} catch (e) {
// pre-49 fallback
metaWindow.unmaximize(Meta.MaximizeFlags.HORIZONTAL);
metaWindow.unmaximize(Meta.MaximizeFlags.VERTICAL);
metaWindow.unmaximize(Meta.MaximizeFlags.BOTH);
}
if (!metaWindow.get_compositor_private()) return;
this._unmaximize(metaWindow);
this.renderTree("window-create", true);
},
},
Expand Down Expand Up @@ -2730,6 +2757,7 @@ export class WindowManager extends GObject.Object {
tiledWindows.forEach((nodeWin) => {
if (nodeWin.nodeValue === draggingMetaWin) return; // GNOME owns this
if (nodeWin.isFloat()) return;
if (nodeWin.nodeValue.forgeAwaitingFirstFrame) return;
if (!nodeWin.renderRect) return;
const r = nodeWin.renderRect;
if (r.width > 0 && r.height > 0) {
Expand Down