From 78f2c7dcd99f6b9c774155df3f91fb6fba66b254 Mon Sep 17 00:00:00 2001 From: Fmstrat Date: Fri, 22 Nov 2024 17:13:32 -0500 Subject: [PATCH] proper multi-GNOME version support, updates from fork, bugfixes, co-exist with Ubuntu tiler extension --- .gitignore | 3 +- build.sh | 74 +++++++++++++++++++++++++- build/.gitkeep | 0 extension.js | 136 ++++++++++++++++++++++++++--------------------- keybindings.js | 16 +++--- metadata-45.json | 13 +++++ metadata.json | 8 +-- package.json | 6 +-- prefs.js | 88 ++++++++++++++++++------------ settings.ui | 2 +- 10 files changed, 234 insertions(+), 112 deletions(-) create mode 100644 build/.gitkeep create mode 100644 metadata-45.json diff --git a/.gitignore b/.gitignore index a7970b9..e6edfcb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ -wintile@nowsci.com.zip +build/* node_modules/ package-lock.json package.json +dist diff --git a/build.sh b/build.sh index 59f18c5..2f0ad23 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,77 @@ #!/bin/bash -rm wintile@nowsci.com.zip +G45() { + local FILE="${1}" + IN_NON_G45=0 + IN_G45=0 + while IFS= read -r LINE; do + if [[ "${LINE}" = *"/* END NON-G45 */"* ]]; then + IN_NON_G45=0 + elif [[ "${LINE}" = *"/* END G45 */"* ]]; then + IN_G45=0 + fi + if (( IN_G45 == 1 )); then + echo "${LINE}" | sed -E 's|^(\s+)?// |\1|' + elif (( IN_NON_G45 == 1 )) && ! [[ ${LINE} =~ ^[[:space:]]*// ]]; then + echo "${LINE}" | sed -E 's|^(\s+)?|\1// |' + else + echo "${LINE}" + fi + if [[ "${LINE}" = *"/* BEGIN NON-G45 */"* ]]; then + IN_NON_G45=1 + elif [[ "${LINE}" = *"/* BEGIN G45 */"* ]]; then + IN_G45=1 + fi + done < "${FILE}" +} + +NON_G45() { + local FILE="${1}" + IN_NON_G45=0 + IN_G45=0 + while IFS= read -r LINE; do + if [[ "${LINE}" = *"/* END NON-G45 */"* ]]; then + IN_NON_G45=0 + elif [[ "${LINE}" = *"/* END G45 */"* ]]; then + IN_G45=0 + fi + if (( IN_G45 == 1 )) && ! [[ ${LINE} =~ ^[[:space:]]*// ]]; then + echo "${LINE}" | sed -E 's|^(\s+)?|\1// |' + elif (( IN_NON_G45 == 1 )); then + echo "${LINE}" | sed -E 's|^(\s+)?// |\1|' + else + echo "${LINE}" + fi + if [[ "${LINE}" = *"/* BEGIN NON-G45 */"* ]]; then + IN_NON_G45=1 + elif [[ "${LINE}" = *"/* BEGIN G45 */"* ]]; then + IN_G45=1 + fi + done < "${FILE}" +} + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +cd "${SCRIPT_DIR}" + +rm -rf dist +mkdir -p dist/G43/build +mkdir -p dist/G45/build + glib-compile-schemas schemas/ + +FILES="extension.js keybindings.js prefs.js" +for FILE in ${FILES}; do + NON_G45 ${FILE} > dist/G43/build/${FILE} + G45 ${FILE} > dist/G45/build/${FILE} +done +cp -a settings.ui schemas dist/G43/build/ +cp -a settings.ui schemas dist/G45/build/ +cp -a metadata.json dist/G43/build/metadata.json +cp -a metadata-45.json dist/G45/build/metadata.json + +cd dist/G43/build +zip -r9 wintile@nowsci.com.zip extension.js keybindings.js metadata.json prefs.js settings.ui schemas +mv wintile@nowsci.com.zip .. +cd ../../G45/build zip -r9 wintile@nowsci.com.zip extension.js keybindings.js metadata.json prefs.js settings.ui schemas +mv wintile@nowsci.com.zip .. diff --git a/build/.gitkeep b/build/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/extension.js b/extension.js index 2c97e74..88fd496 100644 --- a/extension.js +++ b/extension.js @@ -1,28 +1,32 @@ /* global global */ + /* BEGIN NON-G45 */ -// const Meta = imports.gi.Meta; -// const Main = imports.ui.main; -// const Gio = imports.gi.Gio; -// const GLib = imports.gi.GLib; -// const ExtensionUtils = imports.misc.extensionUtils; -// const Clutter = imports.gi.Clutter; -// const St = imports.gi.St; -// const Config = imports.misc.config; -// const SHELL_VERSION = parseFloat(Config.PACKAGE_VERSION); +const Meta = imports.gi.Meta; +const Main = imports.ui.main; +const Gio = imports.gi.Gio; +const GLib = imports.gi.GLib; +const Extension = imports.misc.extensionUtils.getCurrentExtension(); +const Clutter = imports.gi.Clutter; +const St = imports.gi.St; +const Config = imports.misc.config; +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); +const KeyBindingsManager = Me.imports.keybindings.KeyBindingsManager; +const SHELL_VERSION = parseFloat(Config.PACKAGE_VERSION); /* END NON-G45 */ /* BEGIN G45 */ -import Meta from 'gi://Meta'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; -import Clutter from 'gi://Clutter'; -import St from 'gi://St'; -import {PACKAGE_VERSION} from 'resource:///org/gnome/shell/misc/config.js'; -import KeyBindingsManager from './keybindings.js'; -const SHELL_VERSION = parseFloat(PACKAGE_VERSION); +// import Meta from 'gi://Meta'; +// import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +// import Gio from 'gi://Gio'; +// import GLib from 'gi://GLib'; +// import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; +// import Clutter from 'gi://Clutter'; +// import St from 'gi://St'; +// import {PACKAGE_VERSION} from 'resource:///org/gnome/shell/misc/config.js'; +// import KeyBindingsManager from './keybindings.js'; +// const SHELL_VERSION = parseFloat(PACKAGE_VERSION); /* END G45 */ let onWindowGrabBegin, onWindowGrabEnd; @@ -42,7 +46,7 @@ journalctl -qf | grep -i -e Wintile -e 'js error' */ function _log(message) { if (config.debug) - log('[WinTile]', message); + console.log('[Wintile]', message); } let config = { @@ -83,16 +87,6 @@ function updateSettings() { _log(JSON.stringify(config)); } -/* BEGIN NON-G45 */ -// const wintile = { -// extdatadir: imports.misc.extensionUtils.getCurrentExtension().path, -// shell_version: parseInt(Config.PACKAGE_VERSION.split('.')[1], 10), -// }; -// imports.searchPath.unshift(wintile.extdatadir); - -// const KeyBindings = imports.keybindings; -/* END NON-G45 */ - let keyManager = null; var oldbindings = { unmaximize: [], @@ -329,6 +323,10 @@ function sendMove(direction, ctrlPressed = false) { _log('---'); _log(`sendMove) ${direction} ctrl: ${ctrlPressed}`); var app = global.display.focus_window; + if (!app) { + _log('no window selected'); + return; + } var monitorIndex = app.get_monitor(); var curMonitor = getMonitorInfo(monitorIndex); @@ -712,6 +710,7 @@ function windowGrabEnd(metaWindow, metaGrabOp) { */ function changeBinding(settingsObject, key, oldBinding, newBinding) { var binding = oldbindings[key.replace(/-/g, '_')]; + if (!binding) binding = oldbindings[key]; var _newbindings = []; for (var i = 0; i < binding.length; i++) { let currentbinding = binding[i]; @@ -1074,22 +1073,24 @@ function getMonitorInfo(monitorIndex) { */ /* BEGIN NON-G45 */ -// class WintileExtension { +var WintileExtension = class WintileExtension { /* END NON-G45 */ /* BEGIN G45 */ -export default class WintileExtension extends Extension { +// export default class WintileExtension extends Extension { /* END G45 */ + enable() { _log('enable) Keymanager is being defined'); + /* BEGIN NON-G45 */ + keyManager = new KeyBindingsManager(`${Me.path}/schemas`); + /* END NON-G45 */ + /* BEGIN G45 */ - keyManager = new KeyBindingsManager(); + // keyManager = new KeyBindingsManager(); /* END G45 */ - /* BEGIN NON-G45 */ - // keyManager = new KeyBindings.Manager(); - /* END NON-G45 */ let desktopSettings = new Gio.Settings({schema_id: 'org.gnome.desktop.wm.keybindings'}); let mutterKeybindingSettings = new Gio.Settings({schema_id: 'org.gnome.mutter.keybindings'}); let mutterSettings = new Gio.Settings({schema_id: 'org.gnome.mutter'}); @@ -1108,6 +1109,19 @@ export default class WintileExtension extends Extension { changeBinding(mutterKeybindingSettings, 'toggle-tiled-left', 'Left', 'Left'); changeBinding(mutterKeybindingSettings, 'toggle-tiled-right', 'Right', 'Right'); mutterSettings.set_boolean('edge-tiling', false); + try { + let tilingAssistantSettings = new Gio.Settings({schema_id: 'org.gnome.shell.extensions.tiling-assistant'}); + oldbindings['restore-window'] = tilingAssistantSettings.get_strv('restore-window'); + oldbindings['tile-left-half'] = tilingAssistantSettings.get_strv('tile-left-half'); + oldbindings['tile-maximize'] = tilingAssistantSettings.get_strv('tile-maximize'); + oldbindings['tile-right-half'] = tilingAssistantSettings.get_strv('tile-right-half'); + changeBinding(tilingAssistantSettings, 'restore-window', 'Down', 'Down'); + changeBinding(tilingAssistantSettings, 'tile-left-half', 'Left', 'Left'); + changeBinding(tilingAssistantSettings, 'tile-maximize', 'Up', 'Up'); + changeBinding(tilingAssistantSettings, 'tile-right-half', 'Right', 'Right'); + } catch (error) { + _log('enable) org.gnome.shell.extensions.tiling-assistant does not exist'); + } keyManagerTimer = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 3000, () => { keyManager.add('left', () => { requestMove('left', true); @@ -1135,19 +1149,11 @@ export default class WintileExtension extends Extension { }); }); - // Since GNOME 40 the metaDisplay argument isn't passed anymore to these callbacks. - // We "translate" the parameters here so that things work on both GNOME 3 and 40. - onWindowGrabBegin = global.display.connect('grab-op-begin', (metaDisplay, metaScreen, metaWindow, metaGrabOp, _gpointer) => { - if (SHELL_VERSION >= 40) - windowGrabBegin(metaScreen, metaWindow); - else - windowGrabBegin(metaWindow, metaGrabOp); + onWindowGrabBegin = global.display.connect('grab-op-begin', (metaDisplay, metaScreen, metaWindow, _metaGrabOp, _gpointer) => { + windowGrabBegin(metaScreen, metaWindow); }); - onWindowGrabEnd = global.display.connect('grab-op-end', (metaDisplay, metaScreen, metaWindow, metaGrabOp, _gpointer) => { - if (SHELL_VERSION >= 40) - windowGrabEnd(metaScreen, metaWindow); - else - windowGrabEnd(metaWindow, metaGrabOp); + onWindowGrabEnd = global.display.connect('grab-op-end', (metaDisplay, metaScreen, metaWindow, _metaGrabOp, _gpointer) => { + windowGrabEnd(metaScreen, metaWindow); }); // Create a new gsettings object @@ -1155,15 +1161,19 @@ export default class WintileExtension extends Extension { style_class: 'tile-preview', visible: false, }); - Main.uiGroup.add_actor(preview); + if (SHELL_VERSION < 46.0) + Main.uiGroup.add_actor(preview); + else + Main.uiGroup.add_child(preview); + + /* BEGIN NON-G45 */ + gsettings = ExtensionUtils.getSettings(); + /* END NON-G45 */ /* BEGIN G45 */ - gsettings = this.getSettings(); + // gsettings = this.getSettings(); /* END G45 */ - /* BEGIN NON-G45 */ - // gsettings = ExtensionUtils.getSettings(); - /* END NON-G45 */ updateSettings(); // Watch the gsettings for changes @@ -1195,6 +1205,16 @@ export default class WintileExtension extends Extension { mutterKeybindingSettings = null; mutterSettings.reset('edge-tiling'); mutterSettings = null; + try { + let tilingAssistantSettings = new Gio.Settings({schema_id: 'org.gnome.shell.extensions.tiling-assistant'}); + tilingAssistantSettings.reset('restore-window'); + tilingAssistantSettings.reset('tile-left-half'); + tilingAssistantSettings.reset('tile-maximize'); + tilingAssistantSettings.reset('tile-right-half'); + tilingAssistantSettings = null; + } catch (error) { + _log('disable) org.gnome.shell.extensions.tiling-assistant does not exist'); + } global.display.disconnect(onWindowGrabBegin); global.display.disconnect(onWindowGrabEnd); onWindowGrabBegin = null; @@ -1212,11 +1232,7 @@ export default class WintileExtension extends Extension { } /* BEGIN NON-G45 */ -// /** -// * -// * @param {object} _meta = standard meta object -// */ -// function init(_meta) { -// return new WintileExtension(); -// } +function init() { + return new WintileExtension(); +} /* END NON-G45 */ diff --git a/keybindings.js b/keybindings.js index 14b4634..8562d01 100644 --- a/keybindings.js +++ b/keybindings.js @@ -2,15 +2,15 @@ /* global global */ /* BEGIN NON-G45 */ -// const Main = imports.ui.main; -// const Meta = imports.gi.Meta; -// const Shell = imports.gi.Shell; +const Main = imports.ui.main; +const Meta = imports.gi.Meta; +const Shell = imports.gi.Shell; /* END NON-G45 */ /* BEGIN G45 */ -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import Meta from 'gi://Meta'; -import Shell from 'gi://Shell'; +// import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +// import Meta from 'gi://Meta'; +// import Shell from 'gi://Shell'; /* END G45 */ /** @@ -29,10 +29,10 @@ import Shell from 'gi://Shell'; * https://gitlab.gnome.org/GNOME/gnome-shell/blob/master/js/ui/windowManager.js#L1093-1112 */ /* BEGIN NON-G45 */ -// var Manager = class Manager { +var KeyBindingsManager = class KeyBindingsManager { /* END NON-G45 */ /* BEGIN G45 */ -export default class KeyBindingsManager { +// export default class KeyBindingsManager { /* END G45 */ constructor() { this._keybindings = new Map(); diff --git a/metadata-45.json b/metadata-45.json new file mode 100644 index 0000000..6ea15f3 --- /dev/null +++ b/metadata-45.json @@ -0,0 +1,13 @@ +{ + "name": "WinTile", + "description": "WinTile is a hotkey driven window tiling system for GNOME that imitates the standard Win-Arrow keys of Windows 10, allowing you to maximize, maximize to sides, or 1/4 sized to corner across a single or multiple monitors using just Super+Arrow.\n\nWinTile also supports:\n- 1-5 columns and 1-5 rows for standard or ultrawide monitors\n- Top/bottom half support\n- Mouse preview and snapping for placing windows\n- 'Maximize' mode, which adds/removes GNOME animations\n- 'Ultrawide-only' mode, to allow standard screens to have different cols/row than ultrawides\n- Portrait screens will automatically swap columns and rows\n- Add gaps around tiles to avoid the 'crowded elevator' feeling'\n- Ctrl+Super+Arrow to grow a tile in that direction if space is available\n- Ctrl+drag to drop a tile in a specific spot\n- Ctrl+Super+drag to draw a grid for the new tile", + "uuid": "wintile@nowsci.com", + "url": "https://nowsci.com/wintile/", + "settings-schema":"org.gnome.shell.extensions.wintile", + "shell-version": [ + "45", + "46", + "47" + ], + "version": 19 +} diff --git a/metadata.json b/metadata.json index 66739c3..7762cb1 100644 --- a/metadata.json +++ b/metadata.json @@ -1,11 +1,11 @@ { "name": "WinTile", - "description": "WinTile is a hotkey driven window tiling system for GNOME that imitates the standard Win-Arrow keys of Windows 10, allowing you to maximize, maximize to sides, or 1/4 sized to corner across a single or multiple monitors using just Super+Arrow.\n\nAs of v17, WinTile also supports:\n- 1-5 columns and 1-5 rows for standard or ultrawide monitors\n- Top/bottom half support\n- Mouse preview and snapping for placing windows\n- 'Maximize' mode, which adds/removes GNOME animations\n- 'Ultrawide-only' mode, to allow standard screens to have different cols/row than ultrawides\n- Portrait screens will automatically swap columns and rows\n- Add gaps around tiles to avoid the 'crowded elevator' feeling'\n- Ctrl+Super+Arrow to grow a tile in that direction if space is available\n- Ctrl+drag to drop a tile in a specific spot\n- Ctrl+Super+drag to draw a grid for the new tile", + "description": "WinTile is a hotkey driven window tiling system for GNOME that imitates the standard Win-Arrow keys of Windows 10, allowing you to maximize, maximize to sides, or 1/4 sized to corner across a single or multiple monitors using just Super+Arrow.\n\nWinTile also supports:\n- 1-5 columns and 1-5 rows for standard or ultrawide monitors\n- Top/bottom half support\n- Mouse preview and snapping for placing windows\n- 'Maximize' mode, which adds/removes GNOME animations\n- 'Ultrawide-only' mode, to allow standard screens to have different cols/row than ultrawides\n- Portrait screens will automatically swap columns and rows\n- Add gaps around tiles to avoid the 'crowded elevator' feeling'\n- Ctrl+Super+Arrow to grow a tile in that direction if space is available\n- Ctrl+drag to drop a tile in a specific spot\n- Ctrl+Super+drag to draw a grid for the new tile", "uuid": "wintile@nowsci.com", - "url": "https://github.com/fmstrat/wintile", + "url": "https://nowsci.com/wintile/", "settings-schema":"org.gnome.shell.extensions.wintile", "shell-version": [ - "45" + "43" ], - "version": 17 + "version": 18 } diff --git a/package.json b/package.json index 14cad24..e1d3297 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wintile", - "version": "11.0.0", + "version": "19.0.0", "description": "WinTile: Windows 10 window tiling for GNOME =========================================== WinTile is a hotkey driven window tiling system for GNOME that imitates the standard `Win-Arrow` keys of Windows 10, allowing you to maximize, maximize to sides, or 1/4 sized to corner a window using just ``+``.", "main": "extension.js", "scripts": { @@ -15,9 +15,9 @@ "bugs": { "url": "https://github.com/Fmstrat/wintile/issues" }, - "homepage": "https://github.com/Fmstrat/wintile#readme", + "homepage": "https://nowsci.com/wintile/", "devDependencies": { - "eslint": "^8.44.0", + "eslint": "^8.57.0", "eslint-plugin-jsdoc": "^45.0.0" } } diff --git a/prefs.js b/prefs.js index ec63586..2d53584 100644 --- a/prefs.js +++ b/prefs.js @@ -1,52 +1,60 @@ 'use strict'; /* BEGIN NON-G45 */ -// const Gio = imports.gi.Gio; -// const Gtk = imports.gi.Gtk; - -// const ExtensionUtils = imports.misc.extensionUtils; -// const Me = ExtensionUtils.getCurrentExtension(); - -// const Gettext = imports.gettext; -// const _ = Gettext.domain('wintile').gettext; +const Gio = imports.gi.Gio; +const Gtk = imports.gi.Gtk; +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); +/* END NON-G45 */ -// const gsettings = ExtensionUtils.getSettings(); +/* BEGIN G45 */ +// import Gio from 'gi://Gio'; +// import Gtk from 'gi://Gtk'; +// import {ExtensionPreferences} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; +/* END G45 */ -// /** -// * -// */ -// function init() { -// // empty -// } +/* BEGIN NON-G45 */ +function buildPrefsWidget() { /* END NON-G45 */ /* BEGIN G45 */ -import Gio from 'gi://Gio'; -import Gtk from 'gi://Gtk'; -import {ExtensionPreferences} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -export default class WinTileExtensionPreferences extends ExtensionPreferences { +// export default class WinTileExtensionPreferences extends ExtensionPreferences { +// fillPreferencesWindow(window) { /* END G45 */ - /** - * - * @param {object} window - Don't worry about this. Gnome handles it for you. - */ - /* BEGIN G45 */ - fillPreferencesWindow(window) { - /* END G45 */ - /* BEGIN NON-G45 */ - // function fillPreferencesWindow(window) { - /* END NON-G45 */ + let builder = Gtk.Builder.new(); - builder.add_from_file(`${this.path}/settings.ui`); + + /* BEGIN NON-G45 */ + builder.add_from_file(`${Me.path}/settings.ui`); + /* END NON-G45 */ + + /* BEGIN G45 */ + // builder.add_from_file(`${this.path}/settings.ui`); + /* END G45 */ + let gridPage = builder.get_object('gridPage'); let behaviorPage = builder.get_object('behaviorPage'); - window.add(gridPage); - window.add(behaviorPage); + + /* BEGIN NON-G45 */ + let window = new Gtk.Box({ + orientation: Gtk.Orientation.VERTICAL, + spacing: 10, + margin_top: 20, + margin_bottom: 20, + margin_start: 20, + margin_end: 20 + }); + window.append(gridPage); + window.append(behaviorPage); + let gsettings = ExtensionUtils.getSettings(); + /* END NON-G45 */ /* BEGIN G45 */ - let gsettings = this.getSettings(); + // window.add(gridPage); + // window.add(behaviorPage); + // let gsettings = this.getSettings(); /* END G45 */ + const bindSettings = (key, input) => { key.value = gsettings.get_value(input).deep_unpack(); gsettings.bind(input, key, 'active', Gio.SettingsBindFlags.DEFAULT); @@ -92,5 +100,17 @@ export default class WinTileExtensionPreferences extends ExtensionPreferences { // make sure that the non-ultrawide menu is hidden unless it's enabled toggleUltrawide(); + + /* BEGIN NON-G45 */ + return window; + /* END NON-G45 */ } +/* BEGIN G45 */ +// } +/* END G45 */ + +/* BEGIN NON-G45 */ +function init() { + console.log('init'); } +/* END NON-G45 */ diff --git a/settings.ui b/settings.ui index 1fce634..3a9aa10 100644 --- a/settings.ui +++ b/settings.ui @@ -8,7 +8,7 @@ Grid size - Configure the rows and columns of YourExtensionName + Configure the rows and columns of Wintile