Update extension.js

This commit is contained in:
2025-07-25 00:14:31 +02:00
committed by GitHub
parent 5204d40168
commit 89982c883d
+304 -95
View File
@@ -1,5 +1,5 @@
// ---------------------------------------------------- // // ---------------------------------------------------- //
// Simple-Tiling GNOME Shell 3.38 (X11) - Version 3 // // Simple-Tiling GNOME Shell 3.38 (X11) - Version 4 //
// © 2025 domoel MIT // // © 2025 domoel MIT //
// ---------------------------------------------------- // // ---------------------------------------------------- //
@@ -14,10 +14,25 @@ const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const ByteArray = imports.byteArray; const ByteArray = imports.byteArray;
const TILING_DELAY_MS = 20; // Change Tiling Window Delay
const CENTERING_DELAY_MS = 5; // Change Centered Window Delay
const Me = ExtensionUtils.getCurrentExtension(); const Me = ExtensionUtils.getCurrentExtension();
const SCHEMA_NAME = 'org.gnome.shell.extensions.simple-tiling.domoel'; const SCHEMA_NAME = "org.gnome.shell.extensions.simple-tiling.domoel";
const WM_SCHEMA = 'org.gnome.desktop.wm.keybindings'; const WM_SCHEMA = "org.gnome.desktop.wm.keybindings";
const KEYBINDINGS = {
"swap-master-window": (self) => self._swapWithMaster(),
"swap-left-window": (self) => self._swapInDirection("left"),
"swap-right-window": (self) => self._swapInDirection("right"),
"swap-up-window": (self) => self._swapInDirection("up"),
"swap-down-window": (self) => self._swapInDirection("down"),
"focus-left": (self) => self._focusInDirection("left"),
"focus-right": (self) => self._focusInDirection("right"),
"focus-up": (self) => self._focusInDirection("up"),
"focus-down": (self) => self._focusInDirection("down"),
};
// ---------------------------------------------------- // // ---------------------------------------------------- //
// InteractionHandler // // InteractionHandler //
@@ -37,63 +52,97 @@ class InteractionHandler {
enable() { enable() {
if (this._wmKeysToDisable.length) { if (this._wmKeysToDisable.length) {
this._wmKeysToDisable.forEach(key => this._wmSettings.set_value(key, new GLib.Variant('as', []))); this._wmKeysToDisable.forEach((key) =>
this._wmSettings.set_value(key, new GLib.Variant("as", []))
);
} }
this._bindAllShortcuts(); this._bindAllShortcuts();
this._settingsChangedId = this._settings.connect('changed', this._onSettingsChanged); this._settingsChangedId = this._settings.connect(
this._grabOpIds.push(global.display.connect('grab-op-begin', (display, screen, window) => { "changed",
if (this.tiler.windows.includes(window)) { this.tiler.grabbedWindow = window; } this._onSettingsChanged
})); );
this._grabOpIds.push(global.display.connect('grab-op-end', this._onGrabEnd.bind(this))); this._grabOpIds.push(
global.display.connect(
"grab-op-begin",
(display, screen, window) => {
if (this.tiler.windows.includes(window)) {
this.tiler.grabbedWindow = window;
}
}
)
);
this._grabOpIds.push(
global.display.connect("grab-op-end", this._onGrabEnd.bind(this))
);
} }
disable() { disable() {
if (this._wmKeysToDisable.length) { if (this._wmKeysToDisable.length) {
this._wmKeysToDisable.forEach(key => this._wmSettings.set_value(key, this._savedWmShortcuts[key])); this._wmKeysToDisable.forEach((key) =>
this._wmSettings.set_value(key, this._savedWmShortcuts[key])
);
} }
this._unbindAllShortcuts(); this._unbindAllShortcuts();
if (this._settingsChangedId) { if (this._settingsChangedId) {
this._settings.disconnect(this._settingsChangedId); this._settings.disconnect(this._settingsChangedId);
this._settingsChangedId = null; this._settingsChangedId = null;
} }
this._grabOpIds.forEach(id => global.display.disconnect(id)); this._grabOpIds.forEach((id) => global.display.disconnect(id));
} }
_bind(key, callback) { _bind(key, callback) {
Main.wm.addKeybinding(key, this._settings, Meta.KeyBindingFlags.NONE, Shell.ActionMode.NORMAL, callback.bind(this)); Main.wm.addKeybinding(key, this._settings, Meta.KeyBindingFlags.NONE, Shell.ActionMode.NORMAL,
() => callback(this));
} }
_bindAllShortcuts() { _bindAllShortcuts() {
this._bind('swap-master-window', this._swapWithMaster); for (const [key, handler] of Object.entries(KEYBINDINGS)) {
this._bind('swap-left-window', () => this._swapInDirection('left')); this._bind(key, handler);
this._bind('swap-right-window', () => this._swapInDirection('right')); }
this._bind('swap-up-window', () => this._swapInDirection('up'));
this._bind('swap-down-window', () => this._swapInDirection('down'));
} }
_unbindAllShortcuts() { _unbindAllShortcuts() {
['swap-master-window', 'swap-left-window', 'swap-right-window', 'swap-up-window', 'swap-down-window'] for (const key in KEYBINDINGS) {
.forEach(key => Main.wm.removeKeybinding(key)); Main.wm.removeKeybinding(key);
}
} }
_onSettingsChanged() { _onSettingsChanged() {
this._unbindAllShortcuts(); this._unbindAllShortcuts();
this._bindAllShortcuts(); this._bindAllShortcuts();
} }
_prepareWmShortcuts() { _prepareWmShortcuts() {
const schema = this._wmSettings.settings_schema; const schema = this._wmSettings.settings_schema;
const keys = []; const keys = [];
if (schema.has_key('toggle-tiled-left')) keys.push('toggle-tiled-left', 'toggle-tiled-right'); if (schema.has_key("toggle-tiled-left"))
else if (schema.has_key('tile-left')) keys.push('tile-left', 'tile-right'); keys.push("toggle-tiled-left", "toggle-tiled-right");
if (schema.has_key('toggle-maximized')) keys.push('toggle-maximized'); else if (schema.has_key("tile-left"))
keys.push("tile-left", "tile-right");
if (schema.has_key("toggle-maximized")) keys.push("toggle-maximized");
else { else {
if (schema.has_key('maximize')) keys.push('maximize'); if (schema.has_key("maximize")) keys.push("maximize");
if (schema.has_key('unmaximize')) keys.push('unmaximize'); if (schema.has_key("unmaximize")) keys.push("unmaximize");
} }
if (keys.length) { if (keys.length) {
this._wmKeysToDisable = keys; this._wmKeysToDisable = keys;
keys.forEach(key => this._savedWmShortcuts[key] = this.tiler.wmSettings.get_value(key)); keys.forEach(
(key) =>
(this._savedWmShortcuts[
key
] = this._wmSettings.get_value(key))
);
}
}
_focusInDirection(direction) {
const sourceWindow = global.display.get_focus_window();
if (!sourceWindow || !this.tiler.windows.includes(sourceWindow)) return;
const targetWindow = this._findTargetInDirection(
sourceWindow,
direction
);
if (targetWindow) {
targetWindow.activate(global.get_current_time());
} }
} }
@@ -104,7 +153,10 @@ class InteractionHandler {
if (!focusedWindow || !windows.includes(focusedWindow)) return; if (!focusedWindow || !windows.includes(focusedWindow)) return;
const focusedIndex = windows.indexOf(focusedWindow); const focusedIndex = windows.indexOf(focusedWindow);
if (focusedIndex > 0) { if (focusedIndex > 0) {
[windows[0], windows[focusedIndex]] = [windows[focusedIndex], windows[0]]; [windows[0], windows[focusedIndex]] = [
windows[focusedIndex],
windows[0],
];
} else if (focusedIndex === 0) { } else if (focusedIndex === 0) {
[windows[0], windows[1]] = [windows[1], windows[0]]; [windows[0], windows[1]] = [windows[1], windows[0]];
} }
@@ -117,14 +169,21 @@ class InteractionHandler {
if (!sourceWindow || !this.tiler.windows.includes(sourceWindow)) return; if (!sourceWindow || !this.tiler.windows.includes(sourceWindow)) return;
let targetWindow = null; let targetWindow = null;
const sourceIndex = this.tiler.windows.indexOf(sourceWindow); const sourceIndex = this.tiler.windows.indexOf(sourceWindow);
if (sourceIndex === 0 && direction === 'right' && this.tiler.windows.length > 1) { if (
sourceIndex === 0 &&
direction === "right" &&
this.tiler.windows.length > 1
) {
targetWindow = this.tiler.windows[1]; targetWindow = this.tiler.windows[1];
} else { } else {
targetWindow = this._findTargetInDirection(sourceWindow, direction); targetWindow = this._findTargetInDirection(sourceWindow, direction);
} }
if (!targetWindow) return; if (!targetWindow) return;
const targetIndex = this.tiler.windows.indexOf(targetWindow); const targetIndex = this.tiler.windows.indexOf(targetWindow);
[this.tiler.windows[sourceIndex], this.tiler.windows[targetIndex]] = [this.tiler.windows[targetIndex], this.tiler.windows[sourceIndex]]; [this.tiler.windows[sourceIndex], this.tiler.windows[targetIndex]] = [
this.tiler.windows[targetIndex],
this.tiler.windows[sourceIndex],
];
this.tiler.tileNow(); this.tiler.tileNow();
sourceWindow.activate(global.get_current_time()); sourceWindow.activate(global.get_current_time());
} }
@@ -136,10 +195,18 @@ class InteractionHandler {
if (win === source) continue; if (win === source) continue;
const targetRect = win.get_frame_rect(); const targetRect = win.get_frame_rect();
switch (direction) { switch (direction) {
case 'left': if (targetRect.x < sourceRect.x) candidates.push(win); break; case "left":
case 'right': if (targetRect.x > sourceRect.x) candidates.push(win); break; if (targetRect.x < sourceRect.x) candidates.push(win);
case 'up': if (targetRect.y < sourceRect.y) candidates.push(win); break; break;
case 'down': if (targetRect.y > sourceRect.y) candidates.push(win); break; case "right":
if (targetRect.x > sourceRect.x) candidates.push(win);
break;
case "up":
if (targetRect.y < sourceRect.y) candidates.push(win);
break;
case "down":
if (targetRect.y > sourceRect.y) candidates.push(win);
break;
} }
} }
if (candidates.length === 0) return null; if (candidates.length === 0) return null;
@@ -148,7 +215,7 @@ class InteractionHandler {
for (const win of candidates) { for (const win of candidates) {
const targetRect = win.get_frame_rect(); const targetRect = win.get_frame_rect();
let deviation; let deviation;
if (direction === 'left' || direction === 'right') { if (direction === "left" || direction === "right") {
deviation = Math.abs(sourceRect.y - targetRect.y); deviation = Math.abs(sourceRect.y - targetRect.y);
} else { } else {
deviation = Math.abs(sourceRect.x - targetRect.x); deviation = Math.abs(sourceRect.x - targetRect.x);
@@ -168,7 +235,13 @@ class InteractionHandler {
if (targetWindow) { if (targetWindow) {
const sourceIndex = this.tiler.windows.indexOf(grabbedWindow); const sourceIndex = this.tiler.windows.indexOf(grabbedWindow);
const targetIndex = this.tiler.windows.indexOf(targetWindow); const targetIndex = this.tiler.windows.indexOf(targetWindow);
[this.tiler.windows[sourceIndex], this.tiler.windows[targetIndex]] = [this.tiler.windows[targetIndex], this.tiler.windows[sourceIndex]]; [
this.tiler.windows[sourceIndex],
this.tiler.windows[targetIndex],
] = [
this.tiler.windows[targetIndex],
this.tiler.windows[sourceIndex],
];
} }
this.tiler.queueTile(); this.tiler.queueTile();
this.tiler.grabbedWindow = null; this.tiler.grabbedWindow = null;
@@ -176,13 +249,27 @@ class InteractionHandler {
_findTargetUnderPointer(excludeWindow) { _findTargetUnderPointer(excludeWindow) {
let [pointerX, pointerY] = global.get_pointer(); let [pointerX, pointerY] = global.get_pointer();
let windows = global.get_window_actors().map(actor => actor.meta_window).filter(win => { let windows = global
if (!win || win === excludeWindow || !this.tiler.windows.includes(win)) return false; .get_window_actors()
.map((actor) => actor.meta_window)
.filter((win) => {
if (
!win ||
win === excludeWindow ||
!this.tiler.windows.includes(win)
)
return false;
let frame = win.get_frame_rect(); let frame = win.get_frame_rect();
return pointerX >= frame.x && pointerX < frame.x + frame.width && return (
pointerY >= frame.y && pointerY < frame.y + frame.height; pointerX >= frame.x &&
pointerX < frame.x + frame.width &&
pointerY >= frame.y &&
pointerY < frame.y + frame.height
);
}); });
if (windows.length > 0) { return windows[windows.length - 1]; } if (windows.length > 0) {
return windows[windows.length - 1];
}
let bestTarget = null; let bestTarget = null;
let maxOverlap = 0; let maxOverlap = 0;
@@ -190,8 +277,20 @@ class InteractionHandler {
for (const win of this.tiler.windows) { for (const win of this.tiler.windows) {
if (win === excludeWindow) continue; if (win === excludeWindow) continue;
const targetFrame = win.get_frame_rect(); const targetFrame = win.get_frame_rect();
const overlapX = Math.max(0, Math.min(sourceFrame.x + sourceFrame.width, targetFrame.x + targetFrame.width) - Math.max(sourceFrame.x, targetFrame.x)); const overlapX = Math.max(
const overlapY = Math.max(0, Math.min(sourceFrame.y + sourceFrame.height, targetFrame.y + targetFrame.height) - Math.max(sourceFrame.y, targetFrame.y)); 0,
Math.min(
sourceFrame.x + sourceFrame.width,
targetFrame.x + targetFrame.width
) - Math.max(sourceFrame.x, targetFrame.x)
);
const overlapY = Math.max(
0,
Math.min(
sourceFrame.y + sourceFrame.height,
targetFrame.y + targetFrame.height
) - Math.max(sourceFrame.y, targetFrame.y)
);
const overlapArea = overlapX * overlapY; const overlapArea = overlapX * overlapY;
if (overlapArea > maxOverlap) { if (overlapArea > maxOverlap) {
maxOverlap = overlapArea; maxOverlap = overlapArea;
@@ -211,85 +310,125 @@ class Tiler {
this.windows = []; this.windows = [];
this.grabbedWindow = null; this.grabbedWindow = null;
this._settings = ExtensionUtils.getSettings(SCHEMA_NAME); this._settings = ExtensionUtils.getSettings(SCHEMA_NAME);
this.wmSettings = new Gio.Settings({ schema: WM_SCHEMA });
this._signalIds = new Map(); this._signalIds = new Map();
this._tileInProgress = false; this._tileInProgress = false;
this._innerGap = this._settings.get_int('inner-gap'); this._innerGap = this._settings.get_int("inner-gap");
this._outerGapVertical = this._settings.get_int('outer-gap-vertical'); this._outerGapVertical = this._settings.get_int("outer-gap-vertical");
this._outerGapHorizontal = this._settings.get_int('outer-gap-horizontal'); this._outerGapHorizontal = this._settings.get_int(
"outer-gap-horizontal"
);
// Window Delay Settings this._tilingDelay = TILING_DELAY_MS;
this._tilingDelay = 20; // General Tiling Window Delay this._centeringDelay = CENTERING_DELAY_MS;
this._centeringDelay = 5; //Delay for centered Apps on the Exception List
this._exceptions = []; this._exceptions = [];
this._interactionHandler = new InteractionHandler(this); this._interactionHandler = new InteractionHandler(this);
this._onWindowAdded = this._onWindowAdded.bind(this); this._onWindowAdded = this._onWindowAdded.bind(this);
this._onWindowRemoved = this._onWindowRemoved.bind(this); this._onWindowRemoved = this._onWindowRemoved.bind(this);
this._onActiveWorkspaceChanged = this._onActiveWorkspaceChanged.bind(this); this._onActiveWorkspaceChanged = this._onActiveWorkspaceChanged.bind(
this._onWindowMinimizedStateChanged = this._onWindowMinimizedStateChanged.bind(this); this
);
this._onWindowMinimizedStateChanged = this._onWindowMinimizedStateChanged.bind(
this
);
this._onSettingsChanged = this._onSettingsChanged.bind(this); this._onSettingsChanged = this._onSettingsChanged.bind(this);
} }
enable() { enable() {
this._loadExceptions(); this._loadExceptions();
const workspaceManager = global.workspace_manager; const workspaceManager = global.workspace_manager;
this._signalIds.set('workspace-changed', { object: workspaceManager, id: workspaceManager.connect('active-workspace-changed', this._onActiveWorkspaceChanged) }); this._signalIds.set("workspace-changed", {
object: workspaceManager,
id: workspaceManager.connect(
"active-workspace-changed",
this._onActiveWorkspaceChanged
),
});
this._connectToWorkspace(); this._connectToWorkspace();
this._interactionHandler.enable(); this._interactionHandler.enable();
this._signalIds.set('settings-changed', { object: this._settings, id: this._settings.connect('changed', this._onSettingsChanged) }); this._signalIds.set("settings-changed", {
object: this._settings,
id: this._settings.connect("changed", this._onSettingsChanged),
});
} }
disable() { disable() {
this._interactionHandler.disable(); this._interactionHandler.disable();
this._disconnectFromWorkspace(); this._disconnectFromWorkspace();
for (const [, signal] of this._signalIds) { for (const [, signal] of this._signalIds) {
try { signal.object.disconnect(signal.id); } catch(e) {} try {
signal.object.disconnect(signal.id);
} catch (e) {}
} }
this._signalIds.clear(); this._signalIds.clear();
this.windows = []; this.windows = [];
} }
_onSettingsChanged() { _onSettingsChanged() {
this._innerGap = this._settings.get_int('inner-gap'); this._innerGap = this._settings.get_int("inner-gap");
this._outerGapVertical = this._settings.get_int('outer-gap-vertical'); this._outerGapVertical = this._settings.get_int("outer-gap-vertical");
this._outerGapHorizontal = this._settings.get_int('outer-gap-horizontal'); this._outerGapHorizontal = this._settings.get_int(
"outer-gap-horizontal"
);
this.queueTile(); this.queueTile();
} }
_loadExceptions() { _loadExceptions() {
const file = Gio.file_new_for_path(Me.path + '/exceptions.txt'); const file = Gio.file_new_for_path(Me.path + "/exceptions.txt");
if (!file.query_exists(null)) { this._exceptions = []; return; } if (!file.query_exists(null)) {
this._exceptions = [];
return;
}
const [ok, data] = file.load_contents(null); const [ok, data] = file.load_contents(null);
this._exceptions = ok ? ByteArray.toString(data).split('\n') this._exceptions = ok
.map(l => l.trim()).filter(l => l && !l.startsWith('#')) ? ByteArray.toString(data)
.map(l => l.toLowerCase()) : []; .split("\n")
.map((l) => l.trim())
.filter((l) => l && !l.startsWith("#"))
.map((l) => l.toLowerCase())
: [];
} }
_isException(win) { _isException(win) {
return !!win && this._exceptions.includes((win.get_wm_class() || '').toLowerCase()); return (
!!win &&
this._exceptions.includes((win.get_wm_class() || "").toLowerCase())
);
} }
_isTileable(win) { _isTileable(win) {
return win && !win.minimized && !this._isException(win) && win.get_window_type() === Meta.WindowType.NORMAL; return (
win &&
!win.minimized &&
!this._isException(win) &&
win.get_window_type() === Meta.WindowType.NORMAL
);
} }
_centerWindow(win) { _centerWindow(win) {
Mainloop.timeout_add(this._centeringDelay, () => { Mainloop.timeout_add(this._centeringDelay, () => {
if (!win || !win.get_display()) return GLib.SOURCE_REMOVE; if (!win || !win.get_display()) return GLib.SOURCE_REMOVE;
if (win.get_maximized()) { win.unmaximize(Meta.MaximizeFlags.BOTH); } if (win.get_maximized()) {
win.unmaximize(Meta.MaximizeFlags.BOTH);
}
const monitorIndex = win.get_monitor(); const monitorIndex = win.get_monitor();
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitorIndex); const workArea = Main.layoutManager.getWorkAreaForMonitor(
monitorIndex
);
const frame = win.get_frame_rect(); const frame = win.get_frame_rect();
win.move_frame(true, win.move_frame(
true,
workArea.x + Math.floor((workArea.width - frame.width) / 2), workArea.x + Math.floor((workArea.width - frame.width) / 2),
workArea.y + Math.floor((workArea.height - frame.height) / 2)); workArea.y + Math.floor((workArea.height - frame.height) / 2)
);
Mainloop.idle_add(() => { Mainloop.idle_add(() => {
if (win.get_display()) { if (win.get_display()) {
if (typeof win.set_keep_above === 'function') win.set_keep_above(true); if (typeof win.set_keep_above === "function")
else if (typeof win.make_above === 'function') win.make_above(); win.set_keep_above(true);
else if (typeof win.make_above === "function")
win.make_above();
} }
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
@@ -310,16 +449,32 @@ class Tiler {
} }
if (this._isTileable(win)) { if (this._isTileable(win)) {
if (this._settings.get_string('new-window-behavior') === 'master') { if (this._settings.get_string("new-window-behavior") === "master") {
this.windows.unshift(win); this.windows.unshift(win);
} else { } else {
this.windows.push(win); this.windows.push(win);
} }
const id = win.get_id(); const id = win.get_id();
this._signalIds.set(`unmanaged-${id}`, { object: win, id: win.connect('unmanaged', () => this._onWindowRemoved(null, win)) }); this._signalIds.set(`unmanaged-${id}`, {
this._signalIds.set(`size-changed-${id}`, { object: win, id: win.connect('size-changed', () => { if (!this.grabbedWindow) this.queueTile(); }) }); object: win,
this._signalIds.set(`minimized-${id}`, { object: win, id: win.connect('notify::minimized', this._onWindowMinimizedStateChanged) }); id: win.connect("unmanaged", () =>
this._onWindowRemoved(null, win)
),
});
this._signalIds.set(`size-changed-${id}`, {
object: win,
id: win.connect("size-changed", () => {
if (!this.grabbedWindow) this.queueTile();
}),
});
this._signalIds.set(`minimized-${id}`, {
object: win,
id: win.connect(
"notify::minimized",
this._onWindowMinimizedStateChanged
),
});
this.queueTile(); this.queueTile();
} }
@@ -331,11 +486,13 @@ class Tiler {
this.windows.splice(index, 1); this.windows.splice(index, 1);
} }
['unmanaged', 'size-changed', 'minimized'].forEach(prefix => { ["unmanaged", "size-changed", "minimized"].forEach((prefix) => {
const key = `${prefix}-${win.get_id()}`; const key = `${prefix}-${win.get_id()}`;
if (this._signalIds.has(key)) { if (this._signalIds.has(key)) {
const { object, id } = this._signalIds.get(key); const { object, id } = this._signalIds.get(key);
try { object.disconnect(id); } catch(e) {} try {
object.disconnect(id);
} catch (e) {}
this._signalIds.delete(key); this._signalIds.delete(key);
} }
}); });
@@ -349,19 +506,29 @@ class Tiler {
_connectToWorkspace() { _connectToWorkspace() {
const workspace = global.workspace_manager.get_active_workspace(); const workspace = global.workspace_manager.get_active_workspace();
workspace.list_windows().forEach(win => this._onWindowAdded(workspace, win)); workspace
this._signalIds.set('window-added', { object: workspace, id: workspace.connect('window-added', this._onWindowAdded) }); .list_windows()
this._signalIds.set('window-removed', { object: workspace, id: workspace.connect('window-removed', this._onWindowRemoved) }); .forEach((win) => this._onWindowAdded(workspace, win));
this._signalIds.set("window-added", {
object: workspace,
id: workspace.connect("window-added", this._onWindowAdded),
});
this._signalIds.set("window-removed", {
object: workspace,
id: workspace.connect("window-removed", this._onWindowRemoved),
});
this.queueTile(); this.queueTile();
} }
_disconnectFromWorkspace() { _disconnectFromWorkspace() {
this.windows.slice().forEach(win => this._onWindowRemoved(null, win)); this.windows.slice().forEach((win) => this._onWindowRemoved(null, win));
['window-added', 'window-removed'].forEach(key => { ["window-added", "window-removed"].forEach((key) => {
if (this._signalIds.has(key)) { if (this._signalIds.has(key)) {
const { object, id } = this._signalIds.get(key); const { object, id } = this._signalIds.get(key);
try { object.disconnect(id); } catch(e) {} try {
object.disconnect(id);
} catch (e) {}
this._signalIds.delete(key); this._signalIds.delete(key);
} }
}); });
@@ -386,7 +553,13 @@ class Tiler {
_splitLayout(windows, area) { _splitLayout(windows, area) {
if (windows.length === 0) return; if (windows.length === 0) return;
if (windows.length === 1) { if (windows.length === 1) {
windows[0].move_resize_frame(true, area.x, area.y, area.width, area.height); windows[0].move_resize_frame(
true,
area.x,
area.y,
area.width,
area.height
);
return; return;
} }
@@ -397,12 +570,32 @@ class Tiler {
if (area.width > area.height) { if (area.width > area.height) {
const primaryWidth = Math.floor(area.width / 2) - gap; const primaryWidth = Math.floor(area.width / 2) - gap;
primaryArea = { x: area.x, y: area.y, width: primaryWidth, height: area.height }; primaryArea = {
secondaryArea = { x: area.x + primaryWidth + this._innerGap, y: area.y, width: area.width - primaryWidth - this._innerGap, height: area.height }; x: area.x,
y: area.y,
width: primaryWidth,
height: area.height,
};
secondaryArea = {
x: area.x + primaryWidth + this._innerGap,
y: area.y,
width: area.width - primaryWidth - this._innerGap,
height: area.height,
};
} else { } else {
const primaryHeight = Math.floor(area.height / 2) - gap; const primaryHeight = Math.floor(area.height / 2) - gap;
primaryArea = { x: area.x, y: area.y, width: area.width, height: primaryHeight }; primaryArea = {
secondaryArea = { x: area.x, y: area.y + primaryHeight + this._innerGap, width: area.width, height: area.height - primaryHeight - this._innerGap }; x: area.x,
y: area.y,
width: area.width,
height: primaryHeight,
};
secondaryArea = {
x: area.x,
y: area.y + primaryHeight + this._innerGap,
width: area.width,
height: area.height - primaryHeight - this._innerGap,
};
} }
this._splitLayout(primaryWindows, primaryArea); this._splitLayout(primaryWindows, primaryArea);
@@ -410,33 +603,49 @@ class Tiler {
} }
_tileWindows() { _tileWindows() {
const windowsToTile = this.windows.filter(win => !win.minimized); const windowsToTile = this.windows.filter((win) => !win.minimized);
if (windowsToTile.length === 0) return; if (windowsToTile.length === 0) return;
const monitor = Main.layoutManager.primaryMonitor; const monitor = Main.layoutManager.primaryMonitor;
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor.index); const workArea = Main.layoutManager.getWorkAreaForMonitor(
monitor.index
);
const innerArea = { const innerArea = {
x: workArea.x + this._outerGapHorizontal, x: workArea.x + this._outerGapHorizontal,
y: workArea.y + this._outerGapVertical, y: workArea.y + this._outerGapVertical,
width: workArea.width - 2 * this._outerGapHorizontal, width: workArea.width - 2 * this._outerGapHorizontal,
height: workArea.height - 2 * this._outerGapVertical height: workArea.height - 2 * this._outerGapVertical,
}; };
windowsToTile.forEach(win => { if (win.get_maximized()) win.unmaximize(Meta.MaximizeFlags.BOTH); }); windowsToTile.forEach((win) => {
if (win.get_maximized()) win.unmaximize(Meta.MaximizeFlags.BOTH);
});
if (windowsToTile.length === 1) { if (windowsToTile.length === 1) {
windowsToTile[0].move_resize_frame(true, innerArea.x, innerArea.y, innerArea.width, innerArea.height); windowsToTile[0].move_resize_frame(
true,
innerArea.x,
innerArea.y,
innerArea.width,
innerArea.height
);
return; return;
} }
const gap = Math.floor(this._innerGap / 2); const gap = Math.floor(this._innerGap / 2);
const masterWidth = Math.floor(innerArea.width / 2) - gap; const masterWidth = Math.floor(innerArea.width / 2) - gap;
const master = windowsToTile[0]; const master = windowsToTile[0];
master.move_resize_frame(true, innerArea.x, innerArea.y, masterWidth, innerArea.height); master.move_resize_frame(
true,
innerArea.x,
innerArea.y,
masterWidth,
innerArea.height
);
const stackArea = { const stackArea = {
x: innerArea.x + masterWidth + this._innerGap, x: innerArea.x + masterWidth + this._innerGap,
y: innerArea.y, y: innerArea.y,
width: innerArea.width - masterWidth - this._innerGap, width: innerArea.width - masterWidth - this._innerGap,
height: innerArea.height height: innerArea.height,
}; };
this._splitLayout(windowsToTile.slice(1), stackArea); this._splitLayout(windowsToTile.slice(1), stackArea);
} }