keyboard.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // Gnome imports
  2. import Adw from "gi://Adw";
  3. import GObject from "gi://GObject";
  4. import Gtk from "gi://Gtk";
  5. // Extension Imports
  6. import { gettext as _ } from "resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js";
  7. // Prefs UI
  8. import { EntryRow, PreferencesPage, RadioRow } from "./widgets.js";
  9. import { Logger } from "../shared/logger.js";
  10. export class KeyboardPage extends PreferencesPage {
  11. static {
  12. GObject.registerClass(this);
  13. }
  14. constructor({ kbdSettings }) {
  15. super({ title: _("Keyboard"), icon_name: "input-keyboard-symbolic" });
  16. const description = `${_("Syntax")}: <Super>h, <Shift>g, <Shift><Super>h
  17. ${_("Legend")}: <Super> - ${_("Windows key")}, <Primary> - ${_("Control key")}
  18. ${_("Delete text to unset. Press Return key to accept. Focus out to ignore.")} <i>${_(
  19. "Resets"
  20. )}</i> ${_("to previous value when invalid")}`;
  21. this.add_group({
  22. title: _("Update Shortcuts"),
  23. description,
  24. children: Object.entries({
  25. window: "Window Shortcuts",
  26. workspace: "Workspace Shortcuts",
  27. con: "Container Shortcuts",
  28. focus: "Focus Shortcuts",
  29. prefs: "Other Shortcuts",
  30. }).map(([prefix, gettextKey]) =>
  31. KeyboardPage.makeKeygroupExpander(prefix, gettextKey, kbdSettings)
  32. ),
  33. });
  34. this.add_group({
  35. title: _("Drag-Drop Tiling Modifier Key Options"),
  36. description: `<i>${_(
  37. "Change the modifier for <b>tiling</b> windows via mouse/drag-drop"
  38. )}</i> ${_("Select <i>None</i> to <u>always tile immediately</u> by default")}`,
  39. children: [
  40. new RadioRow({
  41. title: _("Tile Modifier"),
  42. settings: kbdSettings,
  43. bind: "mod-mask-mouse-tile",
  44. options: {
  45. Super: _("Super"),
  46. Ctrl: _("Ctrl"),
  47. Alt: _("Alt"),
  48. None: _("None"),
  49. },
  50. }),
  51. ],
  52. });
  53. }
  54. static makeKeygroupExpander(prefix, gettextKey, settings) {
  55. const expander = new Adw.ExpanderRow({ title: _(gettextKey) });
  56. KeyboardPage.createKeyList(settings, prefix).forEach((key) =>
  57. expander.add_row(
  58. new EntryRow({
  59. title: key,
  60. settings,
  61. bind: key,
  62. map: {
  63. from(settings, bind) {
  64. return settings.get_strv(bind).join(",");
  65. },
  66. to(settings, bind, value) {
  67. if (!!value) {
  68. const mappings = value.split(",").map((x) => {
  69. const [, key, mods] = Gtk.accelerator_parse(x);
  70. return Gtk.accelerator_valid(key, mods) && Gtk.accelerator_name(key, mods);
  71. });
  72. if (mappings.every((x) => !!x)) {
  73. Logger.info("setting", bind, "to", mappings);
  74. settings.set_strv(bind, mappings);
  75. }
  76. } else {
  77. // If value deleted, unset the mapping
  78. settings.set_strv(bind, []);
  79. }
  80. },
  81. },
  82. })
  83. )
  84. );
  85. return expander;
  86. }
  87. static createKeyList(settings, categoryName) {
  88. return settings
  89. .list_keys()
  90. .filter((keyName) => !!keyName && !!categoryName && keyName.startsWith(categoryName))
  91. .sort((a, b) => {
  92. const aUp = a.toUpperCase();
  93. const bUp = b.toUpperCase();
  94. if (aUp < bUp) return -1;
  95. if (aUp > bUp) return 1;
  96. return 0;
  97. });
  98. }
  99. }