prefs.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. 'use strict';
  2. import Adw from 'gi://Adw';
  3. import Gtk from 'gi://Gtk';
  4. import Gdk from 'gi://Gdk';
  5. import GLib from 'gi://GLib';
  6. import { ExtensionPreferences, gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
  7. import * as Config from 'resource:///org/gnome/Shell/Extensions/js/misc/config.js'
  8. const [major, minor] = Config.PACKAGE_VERSION.split('.').map(s => Number(s));
  9. export default class GjsOskPreferences extends ExtensionPreferences {
  10. fillPreferencesWindow(window) {
  11. const UIFolderPath = this.dir.get_child('ui').get_path();
  12. let iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default());
  13. iconTheme.add_search_path(UIFolderPath + `/icons`);
  14. const settings = this.getSettings('org.gnome.shell.extensions.gjsosk');
  15. const page1 = new Adw.PreferencesPage({
  16. title: _("General"),
  17. icon_name: "general-symbolic"
  18. });
  19. const behaviorGroup = new Adw.PreferencesGroup({
  20. title: _("Behavior")
  21. });
  22. page1.add(behaviorGroup);
  23. const layoutRow = new Adw.ExpanderRow({
  24. title: _('Layout')
  25. });
  26. behaviorGroup.add(layoutRow);
  27. const layoutLandscapeRow = new Adw.ActionRow({
  28. title: _('Landscape Layout')
  29. });
  30. layoutRow.add_row(layoutLandscapeRow);
  31. let layouts;
  32. let [okL, contentsL] = GLib.file_get_contents(this.path + '/physicalLayouts.json');
  33. if (okL) {
  34. layouts = JSON.parse(contentsL);
  35. }
  36. let layoutList = Object.keys(layouts);
  37. let layoutLandscapeDrop = Gtk.DropDown.new_from_strings(layoutList);
  38. layoutLandscapeDrop.valign = Gtk.Align.CENTER;
  39. layoutLandscapeDrop.selected = settings.get_int("layout-landscape");
  40. layoutLandscapeRow.add_suffix(layoutLandscapeDrop);
  41. layoutLandscapeRow.activatable_widget = layoutLandscapeDrop;
  42. const layoutPortraitRow = new Adw.ActionRow({
  43. title: _('Portrait Layout')
  44. });
  45. layoutRow.add_row(layoutPortraitRow);
  46. let layoutPortraitDrop = Gtk.DropDown.new_from_strings(layoutList);
  47. layoutPortraitDrop.valign = Gtk.Align.CENTER;
  48. layoutPortraitDrop.selected = settings.get_int("layout-portrait");
  49. layoutPortraitRow.add_suffix(layoutPortraitDrop);
  50. layoutPortraitRow.activatable_widget = layoutPortraitDrop;
  51. const enableDragRow = new Adw.ActionRow({
  52. title: _('Enable Dragging')
  53. });
  54. behaviorGroup.add(enableDragRow);
  55. const dragEnableDT = new Gtk.Switch({
  56. active: settings.get_boolean('enable-drag'),
  57. valign: Gtk.Align.CENTER,
  58. });
  59. enableDragRow.add_suffix(dragEnableDT);
  60. enableDragRow.activatable_widget = dragEnableDT;
  61. const indEnabledRow = new Adw.ActionRow({
  62. title: _('Enable Panel Indicator')
  63. });
  64. behaviorGroup.add(indEnabledRow);
  65. const indEnabled = new Gtk.Switch({
  66. active: settings.get_boolean("indicator-enabled"),
  67. valign: Gtk.Align.CENTER,
  68. });
  69. indEnabledRow.add_suffix(indEnabled);
  70. indEnabledRow.activatable_widget = indEnabled;
  71. const row1t5 = new Adw.ActionRow({
  72. title: _('Open upon clicking in a text field')
  73. });
  74. behaviorGroup.add(row1t5);
  75. let dragOptList = [_("Never"), _("Only on Touch"), _("Always")];
  76. let dragOpt = Gtk.DropDown.new_from_strings(dragOptList);
  77. dragOpt.valign = Gtk.Align.CENTER;
  78. dragOpt.selected = settings.get_int("enable-tap-gesture");
  79. row1t5.add_suffix(dragOpt);
  80. row1t5.activatable_widget = dragOpt;
  81. const portraitSizing = new Adw.ExpanderRow({
  82. title: _('Portrait Sizing')
  83. });
  84. behaviorGroup.add(portraitSizing);
  85. let pW = new Adw.ActionRow({
  86. title: _('Width (%)')
  87. })
  88. let pH = new Adw.ActionRow({
  89. title: _('Height (%)')
  90. })
  91. let numChanger_pW = Gtk.SpinButton.new_with_range(0, 100, 5);
  92. numChanger_pW.value = settings.get_int('portrait-width-percent');
  93. numChanger_pW.valign = Gtk.Align.CENTER;
  94. pW.add_suffix(numChanger_pW);
  95. pW.activatable_widget = numChanger_pW;
  96. let numChanger_pH = Gtk.SpinButton.new_with_range(0, 100, 5);
  97. numChanger_pH.value = settings.get_int('portrait-height-percent');
  98. numChanger_pH.valign = Gtk.Align.CENTER;
  99. pH.add_suffix(numChanger_pH);
  100. pH.activatable_widget = numChanger_pH;
  101. portraitSizing.add_row(pW);
  102. portraitSizing.add_row(pH);
  103. const landscapeSizing = new Adw.ExpanderRow({
  104. title: _('Landscape Sizing')
  105. });
  106. behaviorGroup.add(landscapeSizing);
  107. let lW = new Adw.ActionRow({
  108. title: _('Width (%)')
  109. });
  110. let lH = new Adw.ActionRow({
  111. title: _('Height (%)')
  112. });
  113. let numChanger_lW = Gtk.SpinButton.new_with_range(0, 100, 5);
  114. numChanger_lW.value = settings.get_int('landscape-width-percent');
  115. numChanger_lW.valign = Gtk.Align.CENTER;
  116. lW.add_suffix(numChanger_lW);
  117. lW.activatable_widget = numChanger_lW;
  118. let numChanger_lH = Gtk.SpinButton.new_with_range(0, 100, 5);
  119. numChanger_lH.value = settings.get_int('landscape-height-percent');
  120. numChanger_lH.valign = Gtk.Align.CENTER;
  121. lH.add_suffix(numChanger_lH);
  122. lH.activatable_widget = numChanger_lH;
  123. landscapeSizing.add_row(lW);
  124. landscapeSizing.add_row(lH);
  125. const defaultMonitor = new Adw.ActionRow({
  126. title: _('Default Monitor')
  127. })
  128. behaviorGroup.add(defaultMonitor);
  129. let monitors = [];
  130. const display = Gdk.Display.get_default();
  131. if (display && "get_monitors" in display) {
  132. const monitorsAvailable = display.get_monitors();
  133. for (let idx = 0; idx < monitorsAvailable.get_n_items(); idx++) {
  134. const monitor = monitorsAvailable.get_item(idx);
  135. monitors.push(monitor);
  136. }
  137. }
  138. let monitorDrop = Gtk.DropDown.new_from_strings(monitors.map(m => m.get_model()))
  139. monitorDrop.valign = Gtk.Align.CENTER;
  140. let currentMonitorMap = {};
  141. let currentMonitors;
  142. if (settings.get_string("default-monitor").includes(";")) {
  143. currentMonitors = settings.get_string("default-monitor").split(";")
  144. } else {
  145. currentMonitors = [("1:" + monitors[0].get_connector())]
  146. }
  147. for (var i of currentMonitors) {
  148. let tmp = i.split(":");
  149. currentMonitorMap[tmp[0]] = tmp[1] + "";
  150. }
  151. if (!Object.keys(currentMonitorMap).includes(monitors.length + "")) {
  152. let allConfigs = Object.keys(currentMonitorMap).map(Number.parseInt).sort();
  153. currentMonitorMap[monitors.length + ""] = allConfigs[allConfigs.length - 1];
  154. }
  155. let index = monitors.map(m => { return m.get_connector() }).indexOf(currentMonitorMap[monitors.length + ""]);
  156. if (index == -1) {
  157. index = 0
  158. }
  159. monitorDrop.selected = index;
  160. defaultMonitor.add_suffix(monitorDrop);
  161. defaultMonitor.activatable_widget = monitorDrop;
  162. const defaultPosition = new Adw.ActionRow({
  163. title: _('Default Position')
  164. });
  165. behaviorGroup.add(defaultPosition);
  166. let posList = [
  167. _("Top Left"), _("Top Center"), _("Top Right"),
  168. _("Center Left"), _("Center"), _("Center Right"),
  169. _("Bottom Left"), _("Bottom Center"), _("Bottom Right")
  170. ];
  171. let snapDrop = Gtk.DropDown.new_from_strings(posList);
  172. snapDrop.valign = Gtk.Align.CENTER;
  173. snapDrop.selected = settings.get_int("default-snap");
  174. defaultPosition.add_suffix(snapDrop);
  175. defaultPosition.activatable_widget = snapDrop;
  176. const soundPlayRow = new Adw.ActionRow({
  177. title: _('Play sound')
  178. });
  179. behaviorGroup.add(soundPlayRow);
  180. const soundPlayDT = new Gtk.Switch({
  181. active: settings.get_boolean('play-sound'),
  182. valign: Gtk.Align.CENTER,
  183. });
  184. soundPlayRow.add_suffix(soundPlayDT);
  185. soundPlayRow.activatable_widget = soundPlayDT;
  186. const appearanceGroup = new Adw.PreferencesGroup({
  187. title: _("Appearance")
  188. });
  189. page1.add(appearanceGroup);
  190. const colorRow = new Adw.ExpanderRow({
  191. title: _("Color")
  192. })
  193. appearanceGroup.add(colorRow);
  194. const lightCol = new Adw.ActionRow({
  195. title: _('Light Mode')
  196. });
  197. colorRow.add_row(lightCol)
  198. let rgba = new Gdk.RGBA();
  199. rgba.parse("rgba(" + settings.get_double("background-r") + ", " + settings.get_double("background-g") + ", " + settings.get_double("background-b") + ", " + settings.get_double("background-a") + ")");
  200. let colorButton = new Gtk.ColorButton({
  201. rgba: rgba,
  202. use_alpha: true,
  203. valign: Gtk.Align.CENTER
  204. });
  205. lightCol.add_suffix(colorButton);
  206. lightCol.activatable_widget = colorButton;
  207. const darkCol = new Adw.ActionRow({
  208. title: _('Dark Mode')
  209. });
  210. colorRow.add_row(darkCol)
  211. let rgba_d = new Gdk.RGBA();
  212. rgba_d.parse("rgba(" + settings.get_double("background-r-dark") + ", " + settings.get_double("background-g-dark") + ", " + settings.get_double("background-b-dark") + ", " + settings.get_double("background-a-dark") + ")");
  213. let colorButton_d = new Gtk.ColorButton({
  214. rgba: rgba_d,
  215. use_alpha: true,
  216. valign: Gtk.Align.CENTER
  217. });
  218. darkCol.add_suffix(colorButton_d);
  219. darkCol.activatable_widget = colorButton_d;
  220. const systemAccCol = new Adw.ActionRow({
  221. title: _("Use System Accent Color")
  222. })
  223. colorRow.add_row(systemAccCol)
  224. const systemAccColEnabled = new Gtk.Switch({
  225. active: settings.get_boolean("system-accent-col"),
  226. valign: Gtk.Align.CENTER
  227. })
  228. systemAccCol.add_suffix(systemAccColEnabled)
  229. systemAccCol.activatable_widget = systemAccColEnabled
  230. systemAccCol.set_sensitive(major >= 47)
  231. lightCol.set_sensitive(!settings.get_boolean("system-accent-col"));
  232. darkCol.set_sensitive(!settings.get_boolean("system-accent-col"));
  233. let fontSize = new Adw.ActionRow({
  234. title: _('Font Size (px)')
  235. });
  236. appearanceGroup.add(fontSize);
  237. let numChanger_font = Gtk.SpinButton.new_with_range(0, 100, 1);
  238. numChanger_font.value = settings.get_int('font-size-px');
  239. numChanger_font.valign = Gtk.Align.CENTER;
  240. fontSize.add_suffix(numChanger_font);
  241. fontSize.activatable_widget = numChanger_font;
  242. const fontBoldRow = new Adw.ActionRow({
  243. title: _("Bold Font")
  244. })
  245. appearanceGroup.add(fontBoldRow)
  246. const fontBoldEnabled = new Gtk.Switch({
  247. active: settings.get_boolean("font-bold"),
  248. valign: Gtk.Align.CENTER
  249. })
  250. fontBoldRow.add_suffix(fontBoldEnabled)
  251. fontBoldRow.activatable_widget = fontBoldEnabled
  252. let borderSpacing = new Adw.ActionRow({
  253. title: _('Border Spacing (px)')
  254. });
  255. appearanceGroup.add(borderSpacing);
  256. let numChanger_bord = Gtk.SpinButton.new_with_range(0, 10, 1);
  257. numChanger_bord.value = settings.get_int('border-spacing-px');
  258. numChanger_bord.valign = Gtk.Align.CENTER;
  259. borderSpacing.add_suffix(numChanger_bord);
  260. borderSpacing.activatable_widget = numChanger_bord;
  261. let outerSpacing = new Adw.ActionRow({
  262. title: _('Outer Spacing (px)')
  263. });
  264. appearanceGroup.add(outerSpacing);
  265. let numChanger_outer = Gtk.SpinButton.new_with_range(0, 30, 1);
  266. numChanger_outer.value = settings.get_int('outer-spacing-px');
  267. numChanger_outer.valign = Gtk.Align.CENTER;
  268. outerSpacing.add_suffix(numChanger_outer);
  269. outerSpacing.activatable_widget = numChanger_outer;
  270. let snapSpacing = new Adw.ActionRow({
  271. title: _('Drag snap spacing (px)')
  272. });
  273. appearanceGroup.add(snapSpacing);
  274. let numChanger_snap = Gtk.SpinButton.new_with_range(0, 50, 5);
  275. numChanger_snap.value = settings.get_int('snap-spacing-px');
  276. numChanger_snap.valign = Gtk.Align.CENTER;
  277. snapSpacing.add_suffix(numChanger_snap);
  278. snapSpacing.activatable_widget = numChanger_snap;
  279. const roundCorners = new Adw.ActionRow({
  280. title: _('Round Corners')
  281. });
  282. appearanceGroup.add(roundCorners);
  283. const roundKeyCDT = new Gtk.Switch({
  284. active: settings.get_boolean('round-key-corners'),
  285. valign: Gtk.Align.CENTER,
  286. });
  287. roundCorners.add_suffix(roundKeyCDT);
  288. roundCorners.activatable_widget = roundKeyCDT;
  289. const showIcon = new Adw.ActionRow({
  290. title: _('Show Special Key Icons')
  291. });
  292. appearanceGroup.add(showIcon);
  293. const showIconDT = new Gtk.Switch({
  294. active: settings.get_boolean('show-icons'),
  295. valign: Gtk.Align.CENTER,
  296. });
  297. showIcon.add_suffix(showIconDT);
  298. showIcon.activatable_widget = showIconDT;
  299. window.add(page1);
  300. let page2 = new Adw.PreferencesPage({
  301. title: _("About"),
  302. icon_name: 'info-symbolic',
  303. });
  304. let contribute_icon_pref_group = new Adw.PreferencesGroup();
  305. let icon_box = new Gtk.Box({
  306. orientation: Gtk.Orientation.VERTICAL,
  307. margin_top: 24,
  308. margin_bottom: 24,
  309. spacing: 18,
  310. });
  311. let icon_image = new Gtk.Image({
  312. icon_name: "input-keyboard-symbolic",
  313. pixel_size: 128,
  314. });
  315. let label_box = new Gtk.Box({
  316. orientation: Gtk.Orientation.VERTICAL,
  317. spacing: 6,
  318. });
  319. let label = new Gtk.Label({
  320. label: "GJS OSK",
  321. wrap: true,
  322. });
  323. let context = label.get_style_context();
  324. context.add_class("title-1");
  325. let another_label = new Gtk.Label({
  326. label: _("Autorelease ") + `776e35f`
  327. });
  328. let links_pref_group = new Adw.PreferencesGroup();
  329. let code_row = new Adw.ActionRow({
  330. icon_name: "code-symbolic",
  331. title: _("More Information, submit feedback, and get help")
  332. });
  333. let github_link = new Gtk.LinkButton({
  334. label: "Github",
  335. uri: "https://github.com/Vishram1123/gjs-osk",
  336. });
  337. let icons_credit = new Adw.ActionRow({
  338. icon_name: "app-icon-design-symbolic",
  339. title: _("Icons sourced from")
  340. });
  341. let remixicon_link = new Gtk.LinkButton({
  342. label: "RemixIcon",
  343. uri: "https://remixicon.com/",
  344. });
  345. code_row.add_suffix(github_link);
  346. code_row.set_activatable_widget(github_link);
  347. links_pref_group.add(code_row);
  348. icons_credit.add_suffix(remixicon_link);
  349. icons_credit.set_activatable_widget(remixicon_link);
  350. links_pref_group.add(icons_credit);
  351. label_box.append(label);
  352. label_box.append(another_label);
  353. icon_box.append(icon_image);
  354. icon_box.append(label_box);
  355. contribute_icon_pref_group.add(icon_box);
  356. page2.add(contribute_icon_pref_group);
  357. page2.add(links_pref_group);
  358. window.add(page2);
  359. settings.bind("layout-landscape", layoutLandscapeDrop, "selected", 0);
  360. settings.bind("layout-portrait", layoutPortraitDrop, "selected", 0);
  361. settings.bind("enable-drag", dragEnableDT, "active", 0);
  362. settings.bind("enable-tap-gesture", dragOpt, "selected", 0);
  363. settings.bind("indicator-enabled", indEnabled, "active", 0);
  364. settings.bind("portrait-width-percent", numChanger_pW, "value", 0);
  365. settings.bind("portrait-height-percent", numChanger_pH, "value", 0);
  366. settings.bind("landscape-width-percent", numChanger_lW, "value", 0);
  367. settings.bind("landscape-height-percent", numChanger_lH, "value", 0);
  368. colorButton.connect("color-set", () => {
  369. settings.set_double("background-r", Math.round(colorButton.get_rgba().red * 255));
  370. settings.set_double("background-g", Math.round(colorButton.get_rgba().green * 255));
  371. settings.set_double("background-b", Math.round(colorButton.get_rgba().blue * 255));
  372. settings.set_double("background-a", colorButton.get_rgba().alpha);
  373. })
  374. colorButton_d.connect("color-set", () => {
  375. settings.set_double("background-r-dark", Math.round(colorButton_d.get_rgba().red * 255));
  376. settings.set_double("background-g-dark", Math.round(colorButton_d.get_rgba().green * 255));
  377. settings.set_double("background-b-dark", Math.round(colorButton_d.get_rgba().blue * 255));
  378. settings.set_double("background-a-dark", colorButton_d.get_rgba().alpha);
  379. })
  380. settings.bind("font-size-px", numChanger_font, "value", 0);
  381. settings.bind("font-bold", fontBoldEnabled, "active", 0)
  382. settings.bind("border-spacing-px", numChanger_bord, "value", 0);
  383. settings.bind("outer-spacing-px", numChanger_outer, "value", 0);
  384. settings.bind("snap-spacing-px", numChanger_snap, "value", 0)
  385. settings.bind("round-key-corners", roundKeyCDT, "active", 0);
  386. settings.bind("play-sound", soundPlayDT, "active", 0);
  387. settings.bind("show-icons", showIconDT, "active", 0)
  388. settings.bind("default-snap", snapDrop, "selected", 0);
  389. monitorDrop.connect("notify::selected", () => {
  390. currentMonitorMap[monitors.length + ""] = monitors.map(m => { return m.get_connector() })[monitorDrop.selected];
  391. let representation = [];
  392. for (var k of Object.keys(currentMonitorMap)) {
  393. representation.push(k + ":" + currentMonitorMap[k])
  394. }
  395. settings.set_string("default-monitor", representation.join(";"))
  396. })
  397. systemAccColEnabled.connect("state-set", () => {
  398. settings.set_boolean("system-accent-col", systemAccColEnabled.active)
  399. lightCol.set_sensitive(!settings.get_boolean("system-accent-col"));
  400. darkCol.set_sensitive(!settings.get_boolean("system-accent-col"));
  401. })
  402. window.connect("close-request", () => {
  403. settings.set_int("layout-landscape", layoutLandscapeDrop.selected);
  404. settings.set_int("layout-portrait", layoutPortraitDrop.selected);
  405. settings.set_boolean("enable-drag", dragEnableDT.active);
  406. settings.set_int("enable-tap-gesture", dragOpt.selected);
  407. settings.set_boolean("indicator-enabled", indEnabled.active);
  408. settings.set_int("portrait-width-percent", numChanger_pW.value);
  409. settings.set_int("portrait-height-percent", numChanger_pH.value);
  410. settings.set_int("landscape-width-percent", numChanger_lW.value);
  411. settings.set_int("landscape-height-percent", numChanger_lH.value);
  412. settings.set_double("background-r", Math.round(colorButton.get_rgba().red * 255));
  413. settings.set_double("background-g", Math.round(colorButton.get_rgba().green * 255));
  414. settings.set_double("background-b", Math.round(colorButton.get_rgba().blue * 255));
  415. settings.set_double("background-a", colorButton.get_rgba().alpha);
  416. settings.set_double("background-r-dark", Math.round(colorButton_d.get_rgba().red * 255));
  417. settings.set_double("background-g-dark", Math.round(colorButton_d.get_rgba().green * 255));
  418. settings.set_double("background-b-dark", Math.round(colorButton_d.get_rgba().blue * 255));
  419. settings.set_double("background-a-dark", colorButton_d.get_rgba().alpha);
  420. settings.set_int("font-size-px", numChanger_font.value);
  421. settings.set_boolean("font-bold", fontBoldEnabled.active)
  422. settings.set_int("border-spacing-px", numChanger_bord.value);
  423. settings.set_int("outer-spacing-px", numChanger_outer.value);
  424. settings.set_int("snap-spacing-px", numChanger_snap.value)
  425. settings.set_boolean("round-key-corners", roundKeyCDT.active);
  426. settings.set_boolean("play-sound", soundPlayDT.active);
  427. settings.set_boolean("show-icons", showIconDT.active)
  428. settings.set_int("default-snap", snapDrop.selected);
  429. currentMonitorMap[monitors.length + ""] = monitors.map(m => { return m.get_connector() })[monitorDrop.selected];
  430. let representation = [];
  431. for (var k of Object.keys(currentMonitorMap)) {
  432. representation.push(k + ":" + currentMonitorMap[k])
  433. }
  434. settings.set_string("default-monitor", representation.join(";"))
  435. settings.set_boolean("system-accent-col", systemAccColEnabled.active)
  436. })
  437. }
  438. };