feat: enable the window manager to be able to drag across monitors and support keybindings propperly in the extension settings

This commit is contained in:
Lucas Oskorep
2025-05-20 01:20:48 -04:00
parent 04f402c686
commit 5e9bc796ea
9 changed files with 304 additions and 173 deletions

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@ node_modules
dist dist
/schemas/gschemas.compiled /schemas/gschemas.compiled
/aerospike.zip /aerospike.zip
/debug.log

View File

@@ -21,6 +21,7 @@ export default class aerospike extends Extension {
enable() { enable() {
Logger.log("STARTING AEROSPIKE!") Logger.log("STARTING AEROSPIKE!")
this.bindSettings(); this.bindSettings();
this.setupKeybindings();
this.windowManager.enable() this.windowManager.enable()
} }
@@ -32,24 +33,24 @@ export default class aerospike extends Extension {
private bindSettings() { private bindSettings() {
// Monitor settings changes // Monitor settings changes
this.settings.connect('changed::keybinding-1', () => { this.settings.connect('changed::move-left', () => {
log(`Keybinding 1 changed to: ${this.settings.get_strv('keybinding-1')}`); log(`Keybinding 1 changed to: ${this.settings.get_strv('move-left')}`);
this.refreshKeybinding('keybinding-1'); this.refreshKeybinding('move-left');
}); });
this.settings.connect('changed::keybinding-2', () => { this.settings.connect('changed::move-right', () => {
log(`Keybinding 2 changed to: ${this.settings.get_strv('keybinding-2')}`); log(`Keybinding 2 changed to: ${this.settings.get_strv('move-right')}`);
this.refreshKeybinding('keybinding-2'); this.refreshKeybinding('move-right');
}); });
this.settings.connect('changed::keybinding-3', () => { this.settings.connect('changed::join-with-left', () => {
log(`Keybinding 3 changed to: ${this.settings.get_strv('keybinding-3')}`); log(`Keybinding 3 changed to: ${this.settings.get_strv('join-with-left')}`);
this.refreshKeybinding('keybinding-3'); this.refreshKeybinding('join-with-left');
}); });
this.settings.connect('changed::keybinding-4', () => { this.settings.connect('changed::join-with-right', () => {
log(`Keybinding 4 changed to: ${this.settings.get_strv('keybinding-4')}`); log(`Keybinding 4 changed to: ${this.settings.get_strv('join-with-right')}`);
this.refreshKeybinding('keybinding-4'); this.refreshKeybinding('join-with-right');
}); });
this.settings.connect('changed::dropdown-option', () => { this.settings.connect('changed::dropdown-option', () => {
@@ -67,24 +68,24 @@ export default class aerospike extends Extension {
} }
switch (settingName) { switch (settingName) {
case 'keybinding-1': case 'move-left':
this.bindKeybinding('keybinding-1', () => { this.bindKeybinding('move-left', () => {
log('Keybinding 1 was pressed!'); Logger.info('Keybinding 1 was pressed!');
}); });
break; break;
case 'keybinding-2': case 'move-right':
this.bindKeybinding('keybinding-2', () => { this.bindKeybinding('move-right', () => {
log('Keybinding 2 was pressed!'); Logger.info('Keybinding 2 was pressed!');
}); });
break; break;
case 'keybinding-3': case 'join-with-left':
this.bindKeybinding('keybinding-3', () => { this.bindKeybinding('join-with-left', () => {
log('Keybinding 3 was pressed!'); Logger.info('Keybinding 3 was pressed!');
}); });
break; break;
case 'keybinding-4': case 'join-with-right':
this.bindKeybinding('keybinding-4', () => { this.bindKeybinding('join-with-right', () => {
log('Keybinding 4 was pressed!'); Logger.info('Keybinding 4 was pressed!');
}); });
break; break;
} }
@@ -98,20 +99,20 @@ export default class aerospike extends Extension {
} }
private setupKeybindings() { private setupKeybindings() {
this.bindKeybinding('keybinding-1', () => { this.bindKeybinding('move-left', () => {
log('Keybinding 1 was pressed!'); Logger.info('Keybinding 1 was pressed!');
}); });
this.bindKeybinding('keybinding-2', () => { this.bindKeybinding('move-right', () => {
log('Keybinding 2 was pressed!'); Logger.info('Keybinding 2 was pressed!');
}); });
this.bindKeybinding('keybinding-3', () => { this.bindKeybinding('join-with-left', () => {
log('Keybinding 3 was pressed!'); Logger.info('Keybinding 3 was pressed!');
}); });
this.bindKeybinding('keybinding-4', () => { this.bindKeybinding('join-with-right', () => {
log('Keybinding 4 was pressed!'); Logger.info('Keybinding 4 was pressed!');
}); });
} }
@@ -125,7 +126,7 @@ export default class aerospike extends Extension {
const keyBindingAction = Main.wm.addKeybinding( const keyBindingAction = Main.wm.addKeybinding(
settingName, settingName,
this.settings, this.settings,
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, Meta.KeyBindingFlags.NONE,
Shell.ActionMode.NORMAL, Shell.ActionMode.NORMAL,
callback callback
); );

View File

@@ -1,4 +1,4 @@
// This file is just a wrapper around the compiled TypeScript code // This file is just a wrapper around the compiled TypeScript code
import MyExtensionPreferences from './src/prefs/prefs.js'; import AerospikeExtensions from './src/prefs/prefs.js';
export default MyExtensionPreferences; export default AerospikeExtensions;

View File

@@ -1,30 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<schemalist> <schemalist>
<schema id="org.gnome.shell.extensions.aerospike" path="/org/gnome/shell/extensions/aerospike/"> <schema id="org.gnome.shell.extensions.aerospike" path="/org/gnome/shell/extensions/aerospike/">
<key name="keybinding-1" type="as">
<default><![CDATA[['<Super>1']]]></default>
<summary>Keybinding for action 1</summary>
<description>Keyboard shortcut for triggering action 1</description>
</key>
<key name="keybinding-2" type="as">
<default><![CDATA[['<Super>2']]]></default>
<summary>Keybinding for action 2</summary>
<description>Keyboard shortcut for triggering action 2</description>
</key>
<key name="keybinding-3" type="as">
<default><![CDATA[['<Super>3']]]></default>
<summary>Keybinding for action 3</summary>
<description>Keyboard shortcut for triggering action 3</description>
</key>
<key name="keybinding-4" type="as">
<default><![CDATA[['<Super>4']]]></default>
<summary>Keybinding for action 4</summary>
<description>Keyboard shortcut for triggering action 4</description>
</key>
<key name="dropdown-option" type="s"> <key name="dropdown-option" type="s">
<default>'option1'</default> <default>'option1'</default>
<summary>Dropdown selection</summary> <summary>Dropdown selection</summary>
@@ -36,5 +12,30 @@
<summary>Selected color</summary> <summary>Selected color</summary>
<description>Color chosen from the color picker</description> <description>Color chosen from the color picker</description>
</key> </key>
<key name="move-left" type="as">
<default><![CDATA[['<Super>1']]]></default>
<summary>Keybinding for action 1</summary>
<description>Keyboard shortcut for triggering action 1</description>
</key>
<key name="move-right" type="as">
<default><![CDATA[['<Super>2']]]></default>
<summary>Keybinding for action 2</summary>
<description>Keyboard shortcut for triggering action 2</description>
</key>
<key name="join-with-left" type="as">
<default><![CDATA[['<Super>3']]]></default>
<summary>Keybinding for action 3</summary>
<description>Keyboard shortcut for triggering action 3</description>
</key>
<key name="join-with-right" type="as">
<default><![CDATA[['<Super>4']]]></default>
<summary>Keybinding for action 4</summary>
<description>Keyboard shortcut for triggering action 4</description>
</key>
</schema> </schema>
</schemalist> </schemalist>

View File

@@ -0,0 +1,83 @@
// Gnome imports
import Adw from 'gi://Adw';
import Gtk from 'gi://Gtk';
import Gio from 'gi://Gio';
import GObject from 'gi://GObject';
import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
import { Logger } from '../utils/logger.js';
/**
* EntryRow class for handling text input including keybindings
*/
export class EntryRow extends Adw.EntryRow {
static {
GObject.registerClass(this);
}
constructor(params: {
title: string,
settings: Gio.Settings,
bind: string,
map?: {
from: (settings: Gio.Settings, bind: string) => string,
to: (settings: Gio.Settings, bind: string, value: string) => void
}
}) {
super({ title: params.title });
const { settings, bind, map } = params;
// When text changes, update settings
this.connect('changed', () => {
const text = this.get_text();
if (typeof text === 'string') {
if (map) {
map.to(settings, bind, text);
} else {
settings.set_string(bind, text);
}
}
});
// Set initial text from settings
const current = map ? map.from(settings, bind) : settings.get_string(bind);
this.set_text(current ?? '');
// Add reset button
this.add_suffix(
new ResetButton({
settings,
bind,
onReset: () => {
this.set_text((map ? map.from(settings, bind) : settings.get_string(bind)) ?? '');
},
})
);
}
}
/**
* Reset button for settings
*/
export class ResetButton extends Gtk.Button {
static {
GObject.registerClass(this);
}
constructor(params: {
settings?: Gio.Settings,
bind: string,
onReset?: () => void
}) {
super({
icon_name: 'edit-clear-symbolic',
tooltip_text: _('Reset'),
valign: Gtk.Align.CENTER,
});
this.connect('clicked', () => {
params.settings?.reset(params.bind);
params.onReset?.();
});
}
}

View File

@@ -4,8 +4,9 @@ import Gtk from 'gi://Gtk';
import Gdk from 'gi://Gdk'; import Gdk from 'gi://Gdk';
import { ExtensionPreferences, gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; import { ExtensionPreferences, gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
import {Logger} from "../utils/logger.js"; import {Logger} from "../utils/logger.js";
import {EntryRow} from "./keybindings.js";
export default class MyExtensionPreferences extends ExtensionPreferences { export default class AerospikeExtensions extends ExtensionPreferences {
async fillPreferencesWindow(window: Adw.PreferencesWindow) { async fillPreferencesWindow(window: Adw.PreferencesWindow) {
// Create settings object // Create settings object
const settings = this.getSettings('org.gnome.shell.extensions.aerospike'); const settings = this.getSettings('org.gnome.shell.extensions.aerospike');
@@ -17,17 +18,6 @@ export default class MyExtensionPreferences extends ExtensionPreferences {
}); });
window.add(page); window.add(page);
// Create keybindings group
const keybindingsGroup = new Adw.PreferencesGroup({
title: _('Keyboard Shortcuts'),
});
page.add(keybindingsGroup);
// Add keybinding rows
this.addKeybindingRow(keybindingsGroup, settings, 'keybinding-1', _('Action 1'));
this.addKeybindingRow(keybindingsGroup, settings, 'keybinding-2', _('Action 2'));
this.addKeybindingRow(keybindingsGroup, settings, 'keybinding-3', _('Action 3'));
this.addKeybindingRow(keybindingsGroup, settings, 'keybinding-4', _('Action 4'));
// Create options group // Create options group
const optionsGroup = new Adw.PreferencesGroup({ const optionsGroup = new Adw.PreferencesGroup({
@@ -115,49 +105,82 @@ export default class MyExtensionPreferences extends ExtensionPreferences {
const color = colorButton.get_rgba().to_string(); const color = colorButton.get_rgba().to_string();
settings.set_string('color-selection', color); settings.set_string('color-selection', color);
}); });
// Create keybindings group
const keybindingsGroup = new Adw.PreferencesGroup({
title: _('Keyboard Shortcuts'),
description: `${_("Syntax")}: <Super>h, <Shift>g, <Super><Shift>h
${_("Legend")}: <Super> - ${_("Windows key")}, <Primary> - ${_("Control key")}
${_("Delete text to unset. Press Return key to accept.")}`,
});
page.add(keybindingsGroup);
// Add keybinding rows as EntryRows with proper mapping
// Use the helper function to create the map object
const keybindingMap = this.createKeybindingMap();
keybindingsGroup.add(
new EntryRow({
title: _('Action 1'),
settings: settings,
bind: 'move-left',
map: keybindingMap
})
);
keybindingsGroup.add(
new EntryRow({
title: _('Action 2'),
settings: settings,
bind: 'move-right',
map: keybindingMap
})
);
keybindingsGroup.add(
new EntryRow({
title: _('Action 3'),
settings: settings,
bind: 'join-with-left',
map: keybindingMap
})
);
keybindingsGroup.add(
new EntryRow({
title: _('Action 4'),
settings: settings,
bind: 'join-with-right',
map: keybindingMap
})
);
} }
private addKeybindingRow( // Helper function to create a keybinding mapping object
group: Adw.PreferencesGroup, private createKeybindingMap() {
settings: Gio.Settings, return {
key: string, from(settings: Gio.Settings, bind: string) {
title: string return settings.get_strv(bind).join(',');
) { },
const shortcutsRow = new Adw.ActionRow({ to(settings: Gio.Settings, bind: string, value: string) {
title: title, if (!!value) {
}); const mappings = value.split(',').map((x) => {
const [, key, mods] = Gtk.accelerator_parse(x);
group.add(shortcutsRow); return Gtk.accelerator_valid(key, mods) && Gtk.accelerator_name(key, mods);
});
// Create a button for setting shortcuts // Filter out any false values to ensure we only have strings
const shortcutButton = new Gtk.Button({ const stringMappings = mappings.filter((x): x is string => typeof x === 'string');
valign: Gtk.Align.CENTER, if (stringMappings.length > 0) {
label: settings.get_strv(key)[0] || _("Disabled") Logger.debug("setting", bind, "to", stringMappings);
}); settings.set_strv(bind, stringMappings);
}
shortcutsRow.add_suffix(shortcutButton); } else {
shortcutsRow.set_activatable_widget(shortcutButton); // If value deleted, unset the mapping
settings.set_strv(bind, []);
// When clicking the button, show a dialog or start listening for keystroke }
shortcutButton.connect('clicked', () => { },
// Show a simple popup stating that the shortcut is being recorded };
const dialog = new Gtk.MessageDialog({
modal: true,
text: _("Press a key combination to set as shortcut"),
secondary_text: _("Press Esc to cancel or Backspace to disable"),
buttons: Gtk.ButtonsType.CANCEL,
transient_for: group.get_root() as Gtk.Window
});
// Create a keypress event controller
const controller = new Gtk.EventControllerKey();
dialog.add_controller(controller);
controller.connect('key-pressed', (_controller, keyval, keycode, state) => {
});
dialog.present();
});
} }
} }

View File

@@ -34,7 +34,7 @@ export default class WindowContainer {
// Add window to managed windows // Add window to managed windows
this._tiledItems.push(winWrap); this._tiledItems.push(winWrap);
this._tiledWindowLookup.set(winWrap.getWindowId(), winWrap); this._tiledWindowLookup.set(winWrap.getWindowId(), winWrap);
winWrap.setParent(this); // winWrap.setParent(this);
queueEvent({ queueEvent({
name: "tiling-windows", name: "tiling-windows",
callback: () => { callback: () => {

View File

@@ -14,6 +14,7 @@ export class WindowWrapper {
readonly _windowMinimizedHandler: WindowMinimizedHandler; readonly _windowMinimizedHandler: WindowMinimizedHandler;
readonly _signals: number[] = []; readonly _signals: number[] = [];
_parent: WindowContainer | null = null; _parent: WindowContainer | null = null;
_dragging: boolean = false;
constructor( constructor(
window: Meta.Window, window: Meta.Window,
@@ -43,16 +44,23 @@ export class WindowWrapper {
return this._window.get_frame_rect(); return this._window.get_frame_rect();
} }
setParent(parent: WindowContainer): void { startDragging(): void {
this._parent = parent; this._dragging = true;
}
stopDragging(): void {
this._dragging = false;
} }
getParent(): WindowContainer | null { // setParent(parent: WindowContainer): void {
if (this._parent == null) { // this._parent = parent;
Logger.warn(`Attempting to get parent for window without parent ${JSON.stringify(this)}`); // }
} //
return this._parent // getParent(): WindowContainer | null {
} // if (this._parent == null) {
// Logger.warn(`Attempting to get parent for window without parent ${JSON.stringify(this)}`);
// }
// return this._parent
// }
connectWindowSignals( connectWindowSignals(
windowManager: IWindowManager, windowManager: IWindowManager,
@@ -115,6 +123,10 @@ export class WindowWrapper {
// This is meant to be an exact copy of Forge's move function, renamed to maintain your API // This is meant to be an exact copy of Forge's move function, renamed to maintain your API
safelyResizeWindow(rect: Rect): void { safelyResizeWindow(rect: Rect): void {
// Keep minimal logging // Keep minimal logging
if (this._dragging) {
Logger.info("STOPPED RESIZE BECAUSE ITEM IS BEING DRAGGED")
return
}
Logger.log("SAFELY RESIZE", rect.x, rect.y, rect.width, rect.height); Logger.log("SAFELY RESIZE", rect.x, rect.y, rect.width, rect.height);
const actor = this._window.get_compositor_private(); const actor = this._window.get_compositor_private();

View File

@@ -44,6 +44,7 @@ export default class WindowManager implements IWindowManager {
_grabbedWindowMonitor: number = _UNUSED_MONITOR_ID; _grabbedWindowMonitor: number = _UNUSED_MONITOR_ID;
_grabbedWindowId: number = _UNUSED_WINDOW_ID; _grabbedWindowId: number = _UNUSED_WINDOW_ID;
_changingGrabbedMonitor: boolean = false;
constructor() { constructor() {
@@ -73,7 +74,6 @@ export default class WindowManager implements IWindowManager {
}), }),
global.display.connect("window-entered-monitor", (display, monitor, window) => { global.display.connect("window-entered-monitor", (display, monitor, window) => {
Logger.log("WINDOW HAS ENTERED NEW MONITOR!") Logger.log("WINDOW HAS ENTERED NEW MONITOR!")
// this._moveWindowToMonitor(window, monitor);
}), }),
global.display.connect('window-created', (display, window) => { global.display.connect('window-created', (display, window) => {
this.handleWindowCreated(display, window); this.handleWindowCreated(display, window);
@@ -91,11 +91,11 @@ export default class WindowManager implements IWindowManager {
}), }),
) )
this._windowManagerSignals = [ // this._windowManagerSignals = [
global.window_manager.connect("show-tile-preview", (_, _metaWindow, _rect, _num) => { // global.window_manager.connect("show-tile-preview", (_, _metaWindow, _rect, _num) => {
Logger.log("SHOW TITLE PREVIEW!") // Logger.log("SHOW TITLE PREVIEW!")
}), // }),
]; // ];
this._workspaceManagerSignals = [ this._workspaceManagerSignals = [
global.workspace_manager.connect("showing-desktop-changed", () => { global.workspace_manager.connect("showing-desktop-changed", () => {
@@ -204,81 +204,75 @@ export default class WindowManager implements IWindowManager {
this._grabbedWindowId = _UNUSED_WINDOW_ID; this._grabbedWindowId = _UNUSED_WINDOW_ID;
var rect = window.get_frame_rect() var rect = window.get_frame_rect()
Logger.info("Release Location", window.get_monitor(), rect.x, rect.y, rect.width, rect.height) Logger.info("Release Location", window.get_monitor(), rect.x, rect.y, rect.width, rect.height)
const old_mon_id = this._grabbedWindowMonitor; // previously window was moved to a new monitor here instead of it being fluid during drag events.
const new_mon_id = window.get_monitor();
Logger.info("MONITOR MATCH", old_mon_id !== new_mon_id);
if (old_mon_id !== new_mon_id) {
Logger.trace("MOVING MONITOR");
let old_mon = this._monitors.get(old_mon_id);
let new_mon = this._monitors.get(new_mon_id);
if (old_mon === undefined || new_mon === undefined) {
return;
}
let wrapped = old_mon.getWindow(window.get_id())
if (wrapped === undefined) {
wrapped = new WindowWrapper(window, this.handleWindowMinimized);
} else {
old_mon.removeWindow(wrapped)
}
new_mon.addWindow(wrapped)
}
this._tileMonitors(); this._tileMonitors();
Logger.info("monitor_start and monitor_end", this._grabbedWindowMonitor, window.get_monitor()); Logger.info("monitor_start and monitor_end", this._grabbedWindowMonitor, window.get_monitor());
} }
_moveWindowToMonitor(window: Meta.Window, monitorId: number): void { _moveWindowToMonitor(window: Meta.Window, monitorId: number): void {
Logger.info("MOVING WINDOW TO MONITOR", window.get_id(), monitorId);
let wrapped = undefined; let wrapped = undefined;
for (const monitor of this._monitors.values()) { for (const monitor of this._monitors.values()) {
wrapped = monitor.getWindow(window.get_id()); wrapped = monitor.getWindow(window.get_id());
if (wrapped !== undefined) { if (wrapped !== undefined) {
Logger.error("FOUND WINDOW IN MONITOR")
monitor.removeWindow(wrapped); monitor.removeWindow(wrapped);
break; break;
} }
} }
if (wrapped === undefined) { if (wrapped === undefined) {
Logger.error("WINDOW NOT DEFINED")
wrapped = new WindowWrapper(window, this.handleWindowMinimized); wrapped = new WindowWrapper(window, this.handleWindowMinimized);
wrapped.connectWindowSignals(this); wrapped.connectWindowSignals(this);
} }
wrapped.startDragging()
let new_mon = this._monitors.get(monitorId); let new_mon = this._monitors.get(monitorId);
new_mon?.addWindow(wrapped) new_mon?.addWindow(wrapped)
this._tileMonitors(); Logger.info("UPDATE MONITOR", new_mon);
this._grabbedWindowMonitor = monitorId;
wrapped.stopDragging();
} }
public handleWindowPositionChanged(winWrap: WindowWrapper): void { public handleWindowPositionChanged(winWrap: WindowWrapper): void {
if (this._changingGrabbedMonitor) {
return;
}
if (winWrap.getWindowId() === this._grabbedWindowId) { if (winWrap.getWindowId() === this._grabbedWindowId) {
const rect = winWrap.getRect();
// Logger.log("GRABBED WINDOW POSITION CHANGED", rect.x);
const [mouseX, mouseY, _] = global.get_pointer(); const [mouseX, mouseY, _] = global.get_pointer();
this._monitors.get(winWrap.getMonitor())?.itemDragged(winWrap, mouseX, mouseY);
// Log or use the coordinates let monitorIndex = -1;
// console.log(`Mouse position: X=${mouseX}, Y=${mouseY}`); for (let i = 0; i < global.display.get_n_monitors(); i++) {
const workArea = global.workspace_manager.get_active_workspace().get_work_area_for_monitor(i);
if (mouseX >= workArea.x && mouseX < workArea.x + workArea.width &&
mouseY >= workArea.y && mouseY < workArea.y + workArea.height) {
monitorIndex = i;
break;
}
}
if (monitorIndex === -1) {
return
}
if (monitorIndex !== this._grabbedWindowMonitor) {
this._changingGrabbedMonitor = true;
Logger.log("CHANGING MONITOR FOR WINDOW");
this._moveWindowToMonitor(winWrap.getWindow(), monitorIndex);
this._changingGrabbedMonitor = false
}
this._monitors.get(monitorIndex)?.itemDragged(winWrap, mouseX, mouseY);
} }
} }
public handleWindowMinimized(winWrap: WindowWrapper): void { public handleWindowMinimized(winWrap: WindowWrapper): void {
Logger.warn("WARNING MINIMIZING WINDOW");
Logger.log("WARNING MINIMIZED", JSON.stringify(winWrap));
const monitor_id = winWrap.getWindow().get_monitor() const monitor_id = winWrap.getWindow().get_monitor()
Logger.log("WARNING MINIMIZED", monitor_id);
Logger.warn("WARNING MINIMIZED", this._monitors);
this._minimizedItems.set(winWrap.getWindowId(), winWrap); this._minimizedItems.set(winWrap.getWindowId(), winWrap);
this._monitors.get(monitor_id)?.removeWindow(winWrap); this._monitors.get(monitor_id)?.removeWindow(winWrap);
Logger.warn("WARNING MINIMIZED ITEMS", JSON.stringify(this._minimizedItems));
this._tileMonitors() this._tileMonitors()
} }
public handleWindowUnminimized(winWrap: WindowWrapper): void { public handleWindowUnminimized(winWrap: WindowWrapper): void {
Logger.log("WINDOW UNMINIMIZED");
Logger.log("WINDOW UNMINIMIZED", winWrap == null);
// Logger.log("WINDOW UNMINIMIZED", winWrap);
// Logger.log("WINDOW UNMINIMIZED", winWrap.getWindowId());
this._minimizedItems.delete(winWrap.getWindowId()); this._minimizedItems.delete(winWrap.getWindowId());
this._addWindowWrapperToMonitor(winWrap); this._addWindowWrapperToMonitor(winWrap);
this._tileMonitors() this._tileMonitors()
@@ -292,10 +286,8 @@ export default class WindowManager implements IWindowManager {
} }
public captureExistingWindows() { public captureExistingWindows() {
Logger.log("CAPTURING WINDOWS")
const workspace = global.workspace_manager.get_active_workspace(); const workspace = global.workspace_manager.get_active_workspace();
const windows = global.display.get_tab_list(Meta.TabList.NORMAL, workspace); const windows = global.display.get_tab_list(Meta.TabList.NORMAL, workspace);
Logger.log("WINDOWS", windows);
windows.forEach(window => { windows.forEach(window => {
if (this._isWindowTileable(window)) { if (this._isWindowTileable(window)) {
this.addWindowToMonitor(window); this.addWindowToMonitor(window);
@@ -343,9 +335,6 @@ export default class WindowManager implements IWindowManager {
} }
_addWindowWrapperToMonitor(winWrap: WindowWrapper) { _addWindowWrapperToMonitor(winWrap: WindowWrapper) {
Logger.log("Adding window", JSON.stringify(winWrap));
Logger.log("Adding window raw", JSON.stringify(winWrap.getWindow()));
Logger.log("Adding window raw", JSON.stringify(winWrap.getWindow().minimized));
if (winWrap.getWindow().minimized) { if (winWrap.getWindow().minimized) {
this._minimizedItems.set(winWrap.getWindow().get_id(), winWrap); this._minimizedItems.set(winWrap.getWindow().get_id(), winWrap);
} else { } else {
@@ -360,14 +349,35 @@ export default class WindowManager implements IWindowManager {
} }
} }
block_titles = [
"org.gnome.Shell.Extensions",
]
_isWindowTilingBlocked(window: Meta.Window) : boolean {
Logger.info("title", window.get_title());
Logger.info("description", window.get_description());
Logger.info("class", window.get_wm_class());
Logger.info("class", window.get_wm_class_instance());
return this.block_titles.some((title) => {
if (window.get_title() === title) {
Logger.log("WINDOW BLOCKED FROM TILING", window.get_title());
return true;
}
return false;
});
}
_isWindowTileable(window: Meta.Window) { _isWindowTileable(window: Meta.Window) {
if (!window || !window.get_compositor_private()) { if (!window || !window.get_compositor_private()) {
return false; return false;
} }
if (this._isWindowTilingBlocked(window)) {
return false;
}
const windowType = window.get_window_type(); const windowType = window.get_window_type();
Logger.log("WINDOW TYPE", windowType); Logger.log("WINDOW TILING CHECK",);
// Skip certain types of windows // Skip certain types of windows
return !window.is_skip_taskbar() && return !window.is_skip_taskbar() &&
windowType !== Meta.WindowType.DESKTOP && windowType !== Meta.WindowType.DESKTOP &&