123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 |
- /*
- * This file is part of the Forge extension for GNOME
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- // Gnome imports
- import GObject from "gi://GObject";
- import Meta from "gi://Meta";
- import Shell from "gi://Shell";
- // Gnome Shell imports
- import * as Main from "resource:///org/gnome/shell/ui/main.js";
- // Shared state
- import { Logger } from "../shared/logger.js";
- export class Keybindings extends GObject.Object {
- static {
- GObject.registerClass(this);
- }
- /** @type {import('./extension.js').default} */
- ext;
- constructor(ext) {
- super();
- Logger.debug(`created keybindings`);
- this._grabbers = new Map();
- // this._bindSignals();
- this.ext = ext;
- this.extWm = ext.extWm;
- this.kbdSettings = ext.kbdSettings;
- this.settings = ext.settings;
- this.buildBindingDefinitions();
- }
- // @deprecated
- _acceleratorActivate(action) {
- let grabber = this._grabbers.get(action);
- if (grabber) {
- Logger.debug(`Firing accelerator ${grabber.accelerator} : ${grabber.name}`);
- grabber.callback();
- } else {
- Logger.error(`No listeners [action={${action}}]`);
- }
- }
- // @deprecated
- _bindSignals() {
- global.display.connect("accelerator-activated", (_display, action, _deviceId, _timestamp) => {
- this._acceleratorActivate(action);
- });
- }
- enable() {
- let keybindings = this._bindings;
- for (const key in keybindings) {
- Main.wm.addKeybinding(
- key,
- this.kbdSettings,
- Meta.KeyBindingFlags.NONE,
- Shell.ActionMode.NORMAL,
- keybindings[key]
- );
- }
- Logger.debug(`keybindings:enable`);
- }
- disable() {
- let keybindings = this._bindings;
- for (const key in keybindings) {
- Main.wm.removeKeybinding(key);
- }
- Logger.debug(`keybindings:disable`);
- }
- // @deprecated
- enableListenForBindings() {
- windowConfig.forEach((config) => {
- config.shortcut.forEach((shortcut) => {
- this.listenFor(shortcut, () => {
- config.actions.forEach((action) => {
- this.extWm.command(action);
- });
- });
- });
- });
- }
- // @deprecated
- disableListenForBindings() {
- // The existing grabber items are from the custom config by
- // this extension.
- this._grabbers.forEach((grabber) => {
- global.display.ungrab_accelerator(grabber.action);
- Main.wm.allowKeybinding(grabber.name, Shell.ActionMode.NONE);
- });
- this._grabbers.clear();
- }
- /**
- * API for quick binding of keys to function. This is going to be useful with SpaceMode
- *
- * @param {String} accelerator - keybinding combinations
- * @param {Function} callback - function to call when the accelerator is invoked
- *
- * Credits:
- * - https://superuser.com/a/1182899
- * - Adapted based on current Gnome-shell API or syntax
- */
- listenFor(accelerator, callback) {
- let grabFlags = Meta.KeyBindingFlags.NONE;
- let action = global.display.grab_accelerator(accelerator, grabFlags);
- if (action == Meta.KeyBindingAction.NONE) {
- Logger.error(`Unable to grab accelerator [binding={${accelerator}}]`);
- // TODO - check the gnome keybindings for conflicts and notify the user
- } else {
- let name = Meta.external_binding_name_for_action(action);
- Logger.debug(`Requesting WM to allow binding [name={${name}}]`);
- Main.wm.allowKeybinding(name, Shell.ActionMode.ALL);
- this._grabbers.set(action, {
- name: name,
- accelerator: accelerator,
- callback: callback,
- action: action,
- });
- }
- }
- get modifierState() {
- const [_x, _y, state] = this.extWm.getPointer();
- return state;
- }
- allowDragDropTile() {
- const tileModifier = this.kbdSettings.get_string("mod-mask-mouse-tile");
- const modState = this.modifierState;
- // Using Clutter.ModifierType values and also testing for pointer
- // being grabbed (256). E.g. grabbed + pressing Super = 256 + 64 = 320
- // See window.js#_handleMoving() - an overlay preview is shown.
- // See window.js#_handleGrabOpEnd() - when the drag has been dropped
- switch (tileModifier) {
- case "Super":
- return modState === 64 || modState === 320;
- case "Alt":
- return modState === 8 || modState === 264;
- case "Ctrl":
- return modState === 4 || modState === 260;
- case "None":
- return true;
- }
- return false;
- }
- buildBindingDefinitions() {
- this._bindings = {
- "window-toggle-float": () => {
- let actions = [
- {
- name: "FloatToggle",
- mode: "float",
- x: "center",
- y: "center",
- width: 0.65,
- height: 0.75,
- },
- ];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "window-toggle-always-float": () => {
- let action = {
- name: "FloatClassToggle",
- mode: "float",
- x: "center",
- y: "center",
- width: 0.65,
- height: 0.75,
- };
- this.extWm.command(action);
- },
- "window-focus-left": () => {
- let actions = [
- {
- name: "Focus",
- direction: "Left",
- },
- ];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "window-focus-down": () => {
- let actions = [
- {
- name: "Focus",
- direction: "Down",
- },
- ];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "window-focus-up": () => {
- let actions = [
- {
- name: "Focus",
- direction: "Up",
- },
- ];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "window-focus-right": () => {
- let actions = [
- {
- name: "Focus",
- direction: "Right",
- },
- ];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "window-swap-left": () => {
- let actions = [
- {
- name: "Swap",
- direction: "Left",
- },
- ];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "window-swap-down": () => {
- let actions = [
- {
- name: "Swap",
- direction: "Down",
- },
- ];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "window-swap-up": () => {
- let actions = [
- {
- name: "Swap",
- direction: "Up",
- },
- ];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "window-swap-right": () => {
- let actions = [
- {
- name: "Swap",
- direction: "Right",
- },
- ];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "window-move-left": () => {
- let actions = [
- {
- name: "Move",
- direction: "Left",
- },
- ];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "window-move-down": () => {
- let actions = [
- {
- name: "Move",
- direction: "Down",
- },
- ];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "window-move-up": () => {
- let actions = [
- {
- name: "Move",
- direction: "Up",
- },
- ];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "window-move-right": () => {
- let actions = [
- {
- name: "Move",
- direction: "Right",
- },
- ];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "con-split-layout-toggle": () => {
- let actions = [{ name: "LayoutToggle" }];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "con-split-vertical": () => {
- let actions = [{ name: "Split", orientation: "vertical" }];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "con-split-horizontal": () => {
- let actions = [{ name: "Split", orientation: "horizontal" }];
- actions.forEach((action) => {
- this.extWm.command(action);
- });
- },
- "con-stacked-layout-toggle": () => {
- let action = { name: "LayoutStackedToggle" };
- this.extWm.command(action);
- },
- "con-tabbed-layout-toggle": () => {
- let action = { name: "LayoutTabbedToggle" };
- this.extWm.command(action);
- },
- "con-tabbed-showtab-decoration-toggle": () => {
- let action = { name: "ShowTabDecorationToggle" };
- this.extWm.command(action);
- },
- "focus-border-toggle": () => {
- let action = { name: "FocusBorderToggle" };
- this.extWm.command(action);
- },
- "prefs-tiling-toggle": () => {
- let action = { name: "TilingModeToggle" };
- this.extWm.command(action);
- },
- "window-gap-size-increase": () => {
- let action = { name: "GapSize", amount: 1 };
- this.extWm.command(action);
- },
- "window-gap-size-decrease": () => {
- let action = { name: "GapSize", amount: -1 };
- this.extWm.command(action);
- },
- "workspace-active-tile-toggle": () => {
- let action = { name: "WorkspaceActiveTileToggle" };
- this.extWm.command(action);
- },
- "prefs-open": () => {
- let action = { name: "PrefsOpen" };
- this.extWm.command(action);
- },
- "window-swap-last-active": () => {
- let action = {
- name: "WindowSwapLastActive",
- };
- this.extWm.command(action);
- },
- "window-snap-one-third-right": () => {
- let action = {
- name: "SnapLayoutMove",
- direction: "Right",
- amount: 1 / 3,
- };
- this.extWm.command(action);
- },
- "window-snap-two-third-right": () => {
- let action = {
- name: "SnapLayoutMove",
- direction: "Right",
- amount: 2 / 3,
- };
- this.extWm.command(action);
- },
- "window-snap-one-third-left": () => {
- let action = {
- name: "SnapLayoutMove",
- direction: "Left",
- amount: 1 / 3,
- };
- this.extWm.command(action);
- },
- "window-snap-two-third-left": () => {
- let action = {
- name: "SnapLayoutMove",
- direction: "Left",
- amount: 2 / 3,
- };
- this.extWm.command(action);
- },
- "window-snap-center": () => {
- let action = {
- name: "SnapLayoutMove",
- direction: "Center",
- };
- this.extWm.command(action);
- },
- "window-resize-top-increase": () => {
- let action = {
- name: "WindowResizeTop",
- amount: this.settings.get_uint("resize-amount"),
- };
- this.extWm.command(action);
- },
- "window-resize-top-decrease": () => {
- let action = {
- name: "WindowResizeTop",
- amount: -1 * this.settings.get_uint("resize-amount"),
- };
- this.extWm.command(action);
- },
- "window-resize-bottom-increase": () => {
- let action = {
- name: "WindowResizeBottom",
- amount: this.settings.get_uint("resize-amount"),
- };
- this.extWm.command(action);
- },
- "window-resize-bottom-decrease": () => {
- let action = {
- name: "WindowResizeBottom",
- amount: -1 * this.settings.get_uint("resize-amount"),
- };
- this.extWm.command(action);
- },
- "window-resize-left-increase": () => {
- let action = {
- name: "WindowResizeLeft",
- amount: this.settings.get_uint("resize-amount"),
- };
- this.extWm.command(action);
- },
- "window-resize-left-decrease": () => {
- let action = {
- name: "WindowResizeLeft",
- amount: -1 * this.settings.get_uint("resize-amount"),
- };
- this.extWm.command(action);
- },
- "window-resize-right-increase": () => {
- let action = {
- name: "WindowResizeRight",
- amount: this.settings.get_uint("resize-amount"),
- };
- this.extWm.command(action);
- },
- "window-resize-right-decrease": () => {
- let action = {
- name: "WindowResizeRight",
- amount: -1 * this.settings.get_uint("resize-amount"),
- };
- this.extWm.command(action);
- },
- };
- }
- }
|