Skip to content

Commit 9d2f8e5

Browse files
authored
Merge pull request #360 from Leleat/asssert-window-exists
moveHandler: Assert window exists before operating on it
2 parents 3dc55cb + f4aaabc commit 9d2f8e5

File tree

2 files changed

+81
-52
lines changed

2 files changed

+81
-52
lines changed

tiling-assistant@leleat-on-github/src/extension/moveHandler.js

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -212,52 +212,56 @@ export default class TilingMoveHandler {
212212
}
213213

214214
_onMoveFinished(window) {
215-
if (this._posChangedId) {
216-
window.disconnect(this._posChangedId);
217-
this._posChangedId = 0;
218-
}
215+
try {
216+
window.assertExistence();
217+
218+
if (this._tileRect) {
219+
// Ctrl-drag to replace some windows in a tile group / create a new tile group
220+
// with at least 1 window being part of multiple tile groups.
221+
let isCtrlReplacement = false;
222+
const ctrlReplacedTileGroup = [];
223+
const topTileGroup = Twm.getTopTileGroup({ skipTopWindow: true });
224+
const pointerPos = { x: global.get_pointer()[0], y: global.get_pointer()[1] };
225+
const twHovered = topTileGroup.some(w => w.tiledRect.containsPoint(pointerPos));
226+
if (this._currPreviewMode === MoveModes.ADAPTIVE_TILING && !this._splitRects.size && twHovered) {
227+
isCtrlReplacement = true;
228+
ctrlReplacedTileGroup.push(window);
229+
topTileGroup.forEach(w => {
230+
if (!this._tileRect.containsRect(w.tiledRect))
231+
ctrlReplacedTileGroup.push(w);
232+
});
233+
}
219234

220-
if (this._tileRect) {
221-
// Ctrl-drag to replace some windows in a tile group / create a new tile group
222-
// with at least 1 window being part of multiple tile groups.
223-
let isCtrlReplacement = false;
224-
const ctrlReplacedTileGroup = [];
225-
const topTileGroup = Twm.getTopTileGroup({ skipTopWindow: true });
226-
const pointerPos = { x: global.get_pointer()[0], y: global.get_pointer()[1] };
227-
const twHovered = topTileGroup.some(w => w.tiledRect.containsPoint(pointerPos));
228-
if (this._currPreviewMode === MoveModes.ADAPTIVE_TILING && !this._splitRects.size && twHovered) {
229-
isCtrlReplacement = true;
230-
ctrlReplacedTileGroup.push(window);
231-
topTileGroup.forEach(w => {
232-
if (!this._tileRect.containsRect(w.tiledRect))
233-
ctrlReplacedTileGroup.push(w);
235+
this._splitRects.forEach((rect, w) => Twm.tile(w, rect, { openTilingPopup: false }));
236+
this._splitRects.clear();
237+
Twm.tile(window, this._tileRect, {
238+
monitorNr: this._monitorNr,
239+
openTilingPopup: this._currPreviewMode !== MoveModes.ADAPTIVE_TILING,
240+
ignoreTA: this._ignoreTA
234241
});
235-
}
242+
this._tileRect = null;
236243

237-
this._splitRects.forEach((rect, w) => Twm.tile(w, rect, { openTilingPopup: false }));
238-
this._splitRects.clear();
239-
Twm.tile(window, this._tileRect, {
240-
monitorNr: this._monitorNr,
241-
openTilingPopup: this._currPreviewMode !== MoveModes.ADAPTIVE_TILING,
242-
ignoreTA: this._ignoreTA
243-
});
244-
this._tileRect = null;
244+
// Create a new tile group, in which some windows are already part
245+
// of a different tile group, with ctrl-(super)-drag. The window may
246+
// be maximized by ctrl-super-drag.
247+
isCtrlReplacement && window.isTiled && Twm.updateTileGroup(ctrlReplacedTileGroup);
248+
}
249+
} finally {
250+
if (this._posChangedId) {
251+
window.disconnect(this._posChangedId);
252+
this._posChangedId = 0;
253+
}
245254

246-
// Create a new tile group, in which some windows are already part
247-
// of a different tile group, with ctrl-(super)-drag. The window may
248-
// be maximized by ctrl-super-drag.
249-
isCtrlReplacement && window.isTiled && Twm.updateTileGroup(ctrlReplacedTileGroup);
255+
this._favoriteLayout = [];
256+
this._favoritePreviews?.forEach(p => p.destroy());
257+
this._favoritePreviews = [];
258+
this._freeScreenRects = [];
259+
this._anchorRect = null;
260+
this._topTileGroup = null;
261+
this._tilePreview.close();
262+
this._currPreviewMode = MoveModes.ADAPTIVE_TILING;
263+
this._isGrabOp = false;
250264
}
251-
252-
this._favoriteLayout = [];
253-
this._favoritePreviews?.forEach(p => p.destroy());
254-
this._favoritePreviews = [];
255-
this._freeScreenRects = [];
256-
this._anchorRect = null;
257-
this._topTileGroup = null;
258-
this._tilePreview.close();
259-
this._currPreviewMode = MoveModes.ADAPTIVE_TILING;
260-
this._isGrabOp = false;
261265
}
262266

263267
// If lowPerfMode is enabled in the settings:

tiling-assistant@leleat-on-github/src/extension/tilingWindowManager.js

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,28 @@ export class TilingWindowManager {
1616
// { windowId1: [windowIdX, windowIdY, ...], windowId2: [...], ... }
1717
this._tileGroups = new Map();
1818

19-
// [windowIds]
20-
this._unmanagingWindows = [];
19+
const assertExistenceFor = window => {
20+
window.assertExistence = () => {};
21+
22+
window.connectObject(
23+
'unmanaging',
24+
() => {
25+
window.assertExistence = () => {
26+
throw new Error(
27+
'Trying to operate on an unmanaging window!'
28+
);
29+
};
30+
},
31+
this
32+
);
33+
};
34+
35+
global.display.list_all_windows().forEach(w => assertExistenceFor(w));
36+
global.display.connectObject(
37+
'window-created',
38+
(_, window) => assertExistenceFor(window),
39+
this
40+
);
2141

2242
global.workspace_manager.connectObject(
2343
'workspace-added',
@@ -36,9 +56,15 @@ export class TilingWindowManager {
3656
this._signals = null;
3757

3858
global.workspace_manager.disconnectObject(this);
59+
global.display.disconnectObject(this);
60+
61+
global.display.list_all_windows().forEach(w => {
62+
w.disconnectObject(this);
63+
64+
delete w.assertExistence;
65+
});
3966

4067
this._tileGroups.clear();
41-
this._unmanagingWindows = [];
4268

4369
if (this._openAppTiledTimerId) {
4470
GLib.Source.remove(this._openAppTiledTimerId);
@@ -411,9 +437,8 @@ export class TilingWindowManager {
411437
const unmanagingSignal = signals.get(TilingSignals.UNMANAGING);
412438
unmanagingSignal && window.disconnect(unmanagingSignal);
413439

414-
const umId = window.connect('unmanaging', w => {
440+
const umId = window.connect('unmanaging', () => {
415441
this.clearTilingProps(windowId);
416-
this._unmanagingWindows.push(w.get_stable_sequence());
417442
});
418443
signals.set(TilingSignals.UNMANAGING, umId);
419444

@@ -1194,9 +1219,8 @@ export class TilingWindowManager {
11941219
const unmanagingSignal = signals.get(TilingSignals.UNMANAGING);
11951220
unmanagingSignal && window.disconnect(unmanagingSignal);
11961221

1197-
const umId = window.connect('unmanaging', w => {
1222+
const umId = window.connect('unmanaging', () => {
11981223
this.clearTilingProps(window.get_id());
1199-
this._unmanagingWindows.push(w.get_stable_sequence());
12001224
});
12011225
signals.set(TilingSignals.UNMANAGING, umId);
12021226

@@ -1278,11 +1302,12 @@ export class TilingWindowManager {
12781302
*/
12791303
static _onWindowWorkspaceChanged(window) {
12801304
// Closing a window triggers a ws-changed signal, which may lead to a
1281-
// crash, if we try to operate on it any further. So we listen to the
1282-
// 'unmanaging'-signal to see, if there is a 'true workspace change'
1283-
// or whether the window was just closed
1284-
if (this._unmanagingWindows.includes(window.get_stable_sequence()))
1305+
// crash, if we try to operate on it any further.
1306+
try {
1307+
window.assertExistence();
1308+
} catch {
12851309
return;
1310+
}
12861311

12871312
if (this._ignoreWsChange)
12881313
return;

0 commit comments

Comments
 (0)