diff --git a/figures/highlightedKeyboardLayouts.png b/figures/highlightedKeyboardLayouts.png index 08d9a86..aef038c 100644 Binary files a/figures/highlightedKeyboardLayouts.png and b/figures/highlightedKeyboardLayouts.png differ diff --git a/figures/keyboard-gnome-irish.png b/figures/keyboard-gnome-irish.png new file mode 100644 index 0000000..a7d12fa Binary files /dev/null and b/figures/keyboard-gnome-irish.png differ diff --git a/figures/keyboard-reset-irish.png b/figures/keyboard-reset-irish.png new file mode 100644 index 0000000..06d741e Binary files /dev/null and b/figures/keyboard-reset-irish.png differ diff --git a/files/bibliography.yml b/files/bibliography.yml index af46ae8..7e6596d 100644 --- a/files/bibliography.yml +++ b/files/bibliography.yml @@ -348,4 +348,8 @@ flatpak-web: gio: type: web title: "GIO" - url: https://crates.io/crates/gio \ No newline at end of file + url: https://crates.io/crates/gio +gtk-css: + type: web + title: "GTK CSS properties" + url: https://docs.gtk.org/gtk4/css-properties.html \ No newline at end of file diff --git a/sections/plugin_implementation/keyboard.typ b/sections/plugin_implementation/keyboard.typ index a296029..88d8869 100644 --- a/sections/plugin_implementation/keyboard.typ +++ b/sections/plugin_implementation/keyboard.typ @@ -72,11 +72,12 @@ input { )], ) -ReSet has to know where the input config is located which has to be provided by the user. -This path can be provided in the local config folder of a user in a file called Reset.toml. -This file contains ReSet relevant configuration. The user has to provide the path to the input -config there like @reset-keyboard-config-hyprland or else ReSet wouldn't know where to write -the changes to. If the file does not exist, a new one will be created. +ReSet has to know where the input config is located which has to be provided by +the user. This path can be provided in the local config folder of a user in a +file called Reset.toml. This file contains ReSet relevant configuration. The +user has to provide the path to the input config there like +@reset-keyboard-config-hyprland or else ReSet wouldn't know where to write the +changes to. If the file does not exist, a new one will be created. #let code = " [Keyboard] @@ -133,11 +134,11 @@ Command::new(\"dconf\") Therefore dconf_rs was replaced by gio. The advantages have already been discussed in @GNOME. Gio provides very convenient bindings to the GSettings API. In @gnome-gio-get-input-config the layouts are fetched and its type is checked. If the -layout_variant isn't an array of two strings an empty array will be returned. Otherwise -a generic get function is called with type Vec<(String, String)>> to parse it into -desired structure. This solution is a lot more elegant than the Regex because it is more -human readable and better performant wise as regex processing can be slower due to its -pattern matching which involves operations like backtracking. +layout_variant isn't an array of two strings an empty array will be returned. +Otherwise a generic get function is called with type Vec<(String, String)>> to parse +it into desired structure. This solution is a lot more elegant than the Regex because +it is more human readable and better performant wise as regex processing can be slower +due to its pattern matching which involves operations like backtracking. #let code = " let input_sources = gtk::gio::Settings::new(\"org.gnome.desktop.input-sources\"); @@ -157,7 +158,8 @@ let layouts = layout_variant.get::>().unwrap(); )], ) -In @gnome-gio-set-input-config the code for writing the new keyboard layouts can be seen. +In @gnome-gio-set-input-config the code for writing the new keyboard layouts can be +seen. #let code = " let variant = Variant::from(all_layouts); @@ -173,11 +175,12 @@ input_sources.set(\"sources\", variant).expect(\"failed to write layouts\"); ) #subsubsubsection("KDE Implementation") -To read the keyboard layouts and variants in KDE, kreadconfig6 has to be used. Unfortunately -there is no library that provides bindings so reading and writing using rust commands was -necessary. In @kde-get-input-config the command with all its argument can be seen. Writing -to the kxkbrc file works exactly the same as writing with the only difference of adding -the new keyboard layout string as an additional argument and using kwriteconfig6. +To read the keyboard layouts and variants in KDE, kreadconfig6 has to be used. +Unfortunately there is no library that provides bindings so reading and writing +using rust commands was necessary. In @kde-get-input-config the command with all +its argument can be seen. Writing to the kxkbrc file works exactly the same as +writing with the only difference of adding the new keyboard layout string as an +additional argument and using kwriteconfig6. #let code = " let output = Command::new(\"kreadconfig6\") @@ -205,7 +208,8 @@ let kb_variant = parse_setting(output); #align( left, [#figure( - sourcecode(raw(code, lang: "rs")), kind: "code", supplement: "Listing", caption: [Read KDE keyboard layouts], + sourcecode(raw(code, lang: "rs")), kind: "code", supplement: "Listing", + caption: [Read KDE keyboard layouts], )], ) @@ -220,41 +224,140 @@ is not deprecated. A quality-of-life feature to makes adding keyboard layouts easier is the addition of nested listing. There are many keyboard variants for the same layout, for example, German (US), German (Dvorak) etc. which can grouped -together into single entry in the list marked with an arrow symbol because not -all languages have variants. +together into single entry in the list marked with an arrow symbol because +not all languages have variants. An example on how this looks can be seen +in @nested-listing. \ + #align( center, [#figure( - img("keyboardAddLayout.png", width: 75%, extension: "figures"), caption: [Keyboard layouts with variants], + img("keyboardAddLayout.png", width: 75%, extension: "figures"), + caption: [Keyboard layouts with variants], )], ) +In Gnome control setting, every keyboard layout with its variations are +shown in an alphabetically sorted list. The problem with this approach is +that there are variants for layouts that have a very different name where +it's not obvious to which layout it belongs to as seen in an example in +@comparison-reset-gnome-irish. + +#align( + center, [#figure([ + #columns(2, [ + #img("keyboard-reset-irish.png", width: 100%, extension: "figures") + #colbreak() + #img("keyboard-gnome-irish.png", width: 100%, extension: "figures") + ]) + ], caption: [Irish keyboard layouts comparison (ReSet left, Gnome right)])], +) + This feature reduces the list by a significant amount and helps the user to narrow down the desired language first before looking more detailed for the specific variant. Clicking on such an entry removes all other keyboard layouts -and only shows the variants for that language. +and only shows the variants for that language as seen in @keyboard-layout-variants. #align( center, [#figure( - img("keyboardAddLayoutVariants.png", width: 80%, extension: "figures"), caption: [Keyboard layouts with variants], + img("keyboardAddLayoutVariants.png", width: 80%, extension: "figures"), + caption: [Keyboard layouts with variants], )], ) +To achieve this, a layout that has variants needs to have some code that removes +all other layouts and only show its variants and a button to show all layouts +again. This is shown in the on click event listener in @keyboard-show-variants. +The back button removes every element in the list and inserts all layouts back +to the list. + +#let code = " +layout_row.connect_activate(clone!(@strong keyboard_layouts, @weak list, @strong back_row => move |_| { + // add variants to list + for keyboard_layout in keyboard_layouts.clone() { + let layout_row = create_layout_row(keyboard_layout.description.clone()); + list.append(&layout_row); + } + + list.prepend(&back_row); + + let mut last_row = list.last_child(); + let mut skip = keyboard_layouts.len(); + + // remove all but first + while last_row != None { + // if we're at top of list, prevent selecting the back button and break + if list.first_child() == last_row { + list.grab_focus(); + break; + } + // skip rows because it's a variant we want to show + if skip > 0 { + last_row = last_row.unwrap().prev_sibling(); + skip -= 1; + continue; + } + // remove row from list + let temp = last_row.clone().unwrap().prev_sibling(); + list.remove(&last_row.unwrap()); + last_row = temp; + } +})); +"; + +#align( + left, [#figure( + sourcecode(raw(code, lang: "rs")), kind: "code", supplement: "Listing", + caption: [Code to only show variants of selected layout], + )], +) + +#subsubsubsection("Highlight active layouts") +To show users that limitation visually, the first few rows are highlighted, +while the rest have system colors. This number is set depending on the desktop +environment because some don't use XKB and therefore could allow more than four +keyboard layouts. To further clarify it a subtitle for this setting group that +explains the highlight is added. \ + +#align( + center, [#figure( + img("highlightedKeyboardLayouts.png", width: 75%, extension: "figures"), + caption: [First few keyboard layouts are colored differently], + )], +) + +Because there are users that use many different themes, it is not possible to +hardcode a single color because it might not fit with other themes. A GTK +theme is defined in a css file that contains a list of key-value like pairs +of name and a color as can be seen in @gtk-theme-definition. These can be +accessed from ReSet with an \@css-name like @keyboard-css-highlight. Because +using the color definition as is is bound to clash with other UI elements with +the same coloring, color expressions can be used to slightly change a color +without having to hardcode it. @gtk-css -#subsubsubsection("Testing") -// todo +#let code = " +@define-color accent_color #a9b1d6; +@define-color accent_bg_color #a9b1d6; +@define-color accent_fg_color rgba(0, 0, 0, 0.87); +@define-color destructive_color #F28B82; +/* many more colors */ +"; +#align( + left, [#figure( + sourcecode(raw(code, lang: "css")), kind: "code", supplement: "Listing", + caption: [Excerpt from GTK default dark theme], + )], +) -// moved from existing plugin fucntionality -// todo somehow integrate this somewhere -//To show users that limitation visually, the first few rows are highlighted, -//while the rest have system colors. This number is set depending on the desktop -//environment because some don't use XKB and therefore could allow more than four -//keyboard layouts. +#let code = " +row.activeLanguage { + background-color: darker(darker(darker(@window_fg_color))); +} +"; -// #align( -// center, [#figure( -// img("highlightedKeyboardLayouts.png", width: 75%, extension: "figures"), -// caption: [First four keyboard layouts are colored differently], -// )], -//) \ No newline at end of file +#align( + left, [#figure( + sourcecode(raw(code, lang: "css")), kind: "code", supplement: "Listing", + caption: [Setting the highlight color], + )], +) \ No newline at end of file