// Gnome imports import Adw from "gi://Adw"; import GObject from "gi://GObject"; import Gtk from "gi://Gtk"; // Extension Imports import { gettext as _ } from "resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js"; // Prefs UI import { EntryRow, PreferencesPage, RadioRow } from "./widgets.js"; import { Logger } from "../shared/logger.js"; export class KeyboardPage extends PreferencesPage { static { GObject.registerClass(this); } constructor({ kbdSettings }) { super({ title: _("Keyboard"), icon_name: "input-keyboard-symbolic" }); const description = `${_("Syntax")}: <Super>h, <Shift>g, <Shift><Super>h ${_("Legend")}: <Super> - ${_("Windows key")}, <Primary> - ${_("Control key")} ${_("Delete text to unset. Press Return key to accept. Focus out to ignore.")} ${_( "Resets" )} ${_("to previous value when invalid")}`; this.add_group({ title: _("Update Shortcuts"), description, children: Object.entries({ window: "Window Shortcuts", workspace: "Workspace Shortcuts", con: "Container Shortcuts", focus: "Focus Shortcuts", prefs: "Other Shortcuts", }).map(([prefix, gettextKey]) => KeyboardPage.makeKeygroupExpander(prefix, gettextKey, kbdSettings) ), }); this.add_group({ title: _("Drag-Drop Tiling Modifier Key Options"), description: `${_( "Change the modifier for tiling windows via mouse/drag-drop" )} ${_("Select None to always tile immediately by default")}`, children: [ new RadioRow({ title: _("Tile Modifier"), settings: kbdSettings, bind: "mod-mask-mouse-tile", options: { Super: _("Super"), Ctrl: _("Ctrl"), Alt: _("Alt"), None: _("None"), }, }), ], }); } static makeKeygroupExpander(prefix, gettextKey, settings) { const expander = new Adw.ExpanderRow({ title: _(gettextKey) }); KeyboardPage.createKeyList(settings, prefix).forEach((key) => expander.add_row( new EntryRow({ title: key, settings, bind: key, map: { from(settings, bind) { return settings.get_strv(bind).join(","); }, to(settings, bind, value) { if (!!value) { const mappings = value.split(",").map((x) => { const [, key, mods] = Gtk.accelerator_parse(x); return Gtk.accelerator_valid(key, mods) && Gtk.accelerator_name(key, mods); }); if (mappings.every((x) => !!x)) { Logger.info("setting", bind, "to", mappings); settings.set_strv(bind, mappings); } } else { // If value deleted, unset the mapping settings.set_strv(bind, []); } }, }, }) ) ); return expander; } static createKeyList(settings, categoryName) { return settings .list_keys() .filter((keyName) => !!keyName && !!categoryName && keyName.startsWith(categoryName)) .sort((a, b) => { const aUp = a.toUpperCase(); const bUp = b.toUpperCase(); if (aUp < bUp) return -1; if (aUp > bUp) return 1; return 0; }); } }