Files
dotfiles/gnome/.local/share/gnome-shell/extensions/grimble@lmt.github.io/settingsHandlers/keybindingHandler.js

198 lines
7.9 KiB
JavaScript

/**
* © gnome-shell-extension-tiling-assistant
* Source: https://git.launchpad.net/ubuntu/+source/gnome-shell-extension-tiling-assistant/tree/tiling-assistant@leleat-on-github/src/prefs/shortcutListener.js
*
* This code is partially reused from Ubuntu tiling assistant extension (GPL-2.0).
*
* enableArrowBinding and disableArrowBinding are new methods.
* Other methods are modified for our use case.
*/
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import Meta from 'gi://Meta';
import Shell from 'gi://Shell';
import GLib from 'gi://GLib';
import {Shortcut} from '../common.js';
import {Direction} from '../tileWindowManager.js';
const MAX_RESIZE_GAP = 50;
const MIN_RESIZE_GAP = 10;
/**
* Class to handle the keyboard shortcuts (on the extension side) except the
* ones related to the Layouts. For those, see layoutsManager.js.
*/
export default class KeybindingHandler {
_keyBindings;
_windowManager;
_extensionObject = null;
_settings;
_waitingAction;
_enableArrow = false;
_prevArrowTyped;
constructor(windowManager, extension) {
this._extensionObject = extension;
this._settings = extension.getSettings();
this._windowManager = windowManager;
this._prevArrowTyped = [Direction.North, 0];
this._keyBindings = Shortcut.getShortcuts();
this._keyBindings.forEach(key => {
Main.wm.addKeybinding(key, this._settings, Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, Shell.ActionMode.NORMAL, this._onCustomKeybindingPressed.bind(this, key));
});
}
destroy() {
this._keyBindings.forEach(key => Main.wm.removeKeybinding(key));
this.disableArrowBinding();
}
enableArrowBinding() {
let bindings = ['arrow-up', 'arrow-down', 'arrow-left', 'arrow-right', 'key-escape'];
bindings.forEach(key => {
Main.wm.addKeybinding(key, this._settings, Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, Shell.ActionMode.NORMAL, this._onCustomKeybindingPressed.bind(this, key));
});
}
disableArrowBinding() {
let bindings = ['arrow-up', 'arrow-down', 'arrow-left', 'arrow-right', 'key-escape'];
bindings.forEach(key => Main.wm.removeKeybinding(key));
}
compute_gap(direction) {
const t = GLib.get_real_time();
const dir = this._prevArrowTyped[0];
const time = Math.min(Math.max(t - this._prevArrowTyped[1], 150000), 300000) - 150000;
this._prevArrowTyped = [direction, t];
let gap = dir === direction
? MAX_RESIZE_GAP - ((time * (MAX_RESIZE_GAP - MIN_RESIZE_GAP) / 150000))
: MIN_RESIZE_GAP;
return gap;
}
/**
* @param {string} shortcutName
*/
_onCustomKeybindingPressed(shortcutName) {
switch (shortcutName) {
case 'keybinding-close':
global.display.get_focus_window().delete(global.get_current_time());
break;
case 'keybinding-open-settings':
this._extensionObject?.openPreferences();
break;
case 'keybinding-rotation':
this._windowManager.rotateWindow(global.display.get_focus_window());
break;
case 'keybinding-maximize':
this._windowManager.maximizeTile(global.display.get_focus_window());
break;
case 'keybinding-search':
this._windowManager.createSearchBar();
break;
case 'keybinding-refresh':
// Unused
this._windowManager.refresh();
break;
case 'keybinding-move-left':
this._windowManager.moveTile(Direction.West);
break;
case 'keybinding-move-right':
this._windowManager.moveTile(Direction.East);
break;
case 'keybinding-move-top':
this._windowManager.moveTile(Direction.North);
break;
case 'keybinding-move-bottom':
this._windowManager.moveTile(Direction.South);
break;
case 'keybinding-move':
this._waitingAction = shortcutName;
this.enableArrowBinding();
break;
case 'keybinding-resize':
this._waitingAction = shortcutName;
this.enableArrowBinding();
break;
case 'keybinding-resize-left':
this._windowManager.resizeFocusedWindow(Meta.GrabOp.RESIZING_W);
break;
case 'keybinding-resize-right':
this._windowManager.resizeFocusedWindow(Meta.GrabOp.RESIZING_E);
break;
case 'keybinding-resize-top':
this._windowManager.resizeFocusedWindow(Meta.GrabOp.RESIZING_N);
break;
case 'keybinding-resize-bottom':
this._windowManager.resizeFocusedWindow(Meta.GrabOp.RESIZING_S);
break;
case 'keybinding-focus':
this._waitingAction = shortcutName;
this.enableArrowBinding();
break;
case 'keybinding-focus-left':
this._windowManager.changeFocus(Direction.West);
break;
case 'keybinding-focus-right':
this._windowManager.changeFocus(Direction.East);
break;
case 'keybinding-focus-top':
this._windowManager.changeFocus(Direction.North);
break;
case 'keybinding-focus-bottom':
this._windowManager.changeFocus(Direction.South);
break;
case 'keybinding-next-workspace':
this._windowManager.moveToWorkspace(true);
break;
case 'keybinding-previous-workspace':
this._windowManager.moveToWorkspace(false);
break;
case 'keybinding-next-monitor':
this._windowManager.moveToNextMonitor();
break;
case 'arrow-up':
if (this._waitingAction === 'keybinding-move') {
this._windowManager.moveTile(Direction.North);
this.disableArrowBinding();
} else if (this._waitingAction === 'keybinding-resize') {
this._windowManager.resizeFocusedWindow(Meta.GrabOp.RESIZING_N, this.compute_gap(Direction.North));
} else if (this._waitingAction === 'keybinding-focus') {
this._windowManager.changeFocus(Direction.North);
}
break;
case 'arrow-down':
if (this._waitingAction === 'keybinding-move') {
this._windowManager.moveTile(Direction.South);
this.disableArrowBinding();
} else if (this._waitingAction === 'keybinding-resize') {
this._windowManager.resizeFocusedWindow(Meta.GrabOp.RESIZING_S, this.compute_gap(Direction.South));
} else if (this._waitingAction === 'keybinding-focus') {
this._windowManager.changeFocus(Direction.South);
}
break;
case 'arrow-left':
if (this._waitingAction === 'keybinding-move') {
this._windowManager.moveTile(Direction.West);
this.disableArrowBinding();
} else if (this._waitingAction === 'keybinding-resize') {
this._windowManager.resizeFocusedWindow(Meta.GrabOp.RESIZING_W, this.compute_gap(Direction.West));
} else if (this._waitingAction === 'keybinding-focus') {
this._windowManager.changeFocus(Direction.West);
}
break;
case 'arrow-right':
if (this._waitingAction === 'keybinding-move') {
this._windowManager.moveTile(Direction.East);
this.disableArrowBinding();
} else if (this._waitingAction === 'keybinding-resize') {
this._windowManager.resizeFocusedWindow(Meta.GrabOp.RESIZING_E, this.compute_gap(Direction.East));
} else if (this._waitingAction === 'keybinding-focus') {
this._windowManager.changeFocus(Direction.East);
}
break;
case 'key-escape':
this.disableArrowBinding();
break;
default:
break;
}
}
}