From 42b1c4b642f26defadf49b15bcb073ed84715458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 8 Oct 2024 18:40:25 -0700 Subject: [PATCH 1/5] KeyboardLayout: list from xkbregistry --- meson.build | 1 + src/Objects/KeyboardLayout.vala | 51 +++-------- src/meson.build | 1 + vapi/xkbregistry.vapi | 147 ++++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+), 38 deletions(-) create mode 100644 vapi/xkbregistry.vapi diff --git a/meson.build b/meson.build index e85533499..0b34239e2 100644 --- a/meson.build +++ b/meson.build @@ -21,6 +21,7 @@ granite_dep = dependency('granite-7', version: '>=7.4.0') adw_dep = dependency('libadwaita-1', version: '>=1.4.0') json_glib_dep = dependency('json-glib-1.0') xml2_dep = dependency('libxml-2.0') +xkbregistry_dep = dependency('xkbregistry') pwquality_dep = dependency('pwquality') systemd_dep = dependency('systemd') diff --git a/src/Objects/KeyboardLayout.vala b/src/Objects/KeyboardLayout.vala index d9a3be6e0..a91f13111 100644 --- a/src/Objects/KeyboardLayout.vala +++ b/src/Objects/KeyboardLayout.vala @@ -259,54 +259,29 @@ public class Installer.KeyboardLayout : GLib.Object { public static GLib.ListStore get_all () { var layout_store = new GLib.ListStore (typeof (KeyboardLayout)); - unowned Xml.Doc* doc = Xml.Parser.read_file (get_xml_rules_file_path ()); - Xml.XPath.Context cntx = new Xml.XPath.Context (doc); - unowned Xml.XPath.Object* res = cntx.eval_expression ("/xkbConfigRegistry/layoutList/layout"); - if (res == null) { - delete doc; - critical ("Unable to parse 'base.xml'"); - return layout_store; - } - - if (res->type != Xml.XPath.ObjectType.NODESET || res->nodesetval == null) { - delete res; - delete doc; - critical ("No layouts found in 'base.xml'"); - return layout_store; - } + var xkb_context = new Rxkb.Context (NO_FLAGS); + xkb_context.parse_default_ruleset (); - for (int i = 0; i < res->nodesetval->length (); i++) { - unowned Xml.Node* layout_node = res->nodesetval->item (i); - unowned Xml.Node* config_node = get_xml_node_by_name (layout_node, "configItem"); - unowned Xml.Node* variant_node = get_xml_node_by_name (layout_node, "variantList"); - unowned Xml.Node* description_node = get_xml_node_by_name (config_node, "description"); - unowned Xml.Node* name_node = get_xml_node_by_name (config_node, "name"); - if (name_node == null || description_node == null) { + var xkb_layout = xkb_context.get_first_layout (); + while (xkb_layout != null) { + if (xkb_layout.get_variant () != null) { continue; } - var layout = new KeyboardLayout (name_node->children->content, description_node->children->content); + var layout = new KeyboardLayout (xkb_layout.get_name (), xkb_layout.get_description ()); layout_store.insert_sorted (layout, (GLib.CompareDataFunc) KeyboardLayout.compare); - if (variant_node != null) { - for (unowned Xml.Node* variant_iter = variant_node->children; variant_iter != null; variant_iter = variant_iter->next) { - if (variant_iter->name == "variant") { - unowned Xml.Node* variant_config_node = get_xml_node_by_name (variant_iter, "configItem"); - if (variant_config_node != null) { - unowned Xml.Node* variant_description_node = get_xml_node_by_name (variant_config_node, "description"); - unowned Xml.Node* variant_name_node = get_xml_node_by_name (variant_config_node, "name"); - if (variant_description_node != null && variant_name_node != null) { - layout.add_variant (variant_name_node->children->content, variant_description_node->children->content); - } - } - } - } + var next_layout = xkb_layout.next (); + while (next_layout != null && next_layout.get_variant () != null) { + layout.add_variant (next_layout.get_variant (), next_layout.get_description ()); + + next_layout = next_layout.next (); } + + xkb_layout = next_layout; } - delete res; - delete doc; return layout_store; } diff --git a/src/meson.build b/src/meson.build index 13bf7e43a..44161cda6 100644 --- a/src/meson.build +++ b/src/meson.build @@ -65,6 +65,7 @@ gui_dependencies = [ adw_dep, json_glib_dep, pwquality_dep, + xkbregistry_dep, xml2_dep ] diff --git a/vapi/xkbregistry.vapi b/vapi/xkbregistry.vapi new file mode 100644 index 000000000..bb4dfdd15 --- /dev/null +++ b/vapi/xkbregistry.vapi @@ -0,0 +1,147 @@ +/* + * Vala bindings for xkbregistry + * Copyright 2022 Corentin Noël + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +[CCode (cheader_filename = "xkbcommon/xkbregistry.h", cprefix = "rxkb_", lower_case_cprefix = "rxkb_")] +namespace Rxkb { + [CCode (cname = "struct rxkb_context", ref_function = "rxkb_context_ref", unref_function = "rxkb_context_unref", has_type_id = false)] + [Compact] + public class Context { + public Context (Rxkb.ContextFlags flags); + public void set_log_level (Rxkb.LogLevel level); + public Rxkb.LogLevel get_log_level (); + public bool parse (string ruleset); + public bool parse_default_ruleset (); + public bool include_path_append (string path); + public bool include_path_append_default (); + public void set_log_fn (LogFn log_fn); + public void set_user_data (void* user_data); + public void* get_user_data (); + [CCode (cname = "rxkb_model_first")] + public unowned Rxkb.Model? get_first_model (); + [CCode (cname = "rxkb_layout_first")] + public unowned Rxkb.Layout? get_first_layout (); + [CCode (cname = "rxkb_option_group_first")] + public unowned Rxkb.OptionGroup? get_first_option_group (); + public unowned Rxkb.Context @ref (); + public void unref (); + } + + [CCode (cname = "struct rxkb_model", ref_function = "rxkb_model_ref", unref_function = "rxkb_model_unref", has_type_id = false)] + [Compact] + public class Model { + public unowned Rxkb.Model? next (); + public unowned string get_name (); + public unowned string? get_description (); + public unowned string? get_vendor (); + public Rxkb.Popularity get_popularity (); + public unowned Rxkb.Model @ref (); + public void unref (); + } + + [CCode (cname = "struct rxkb_layout", ref_function = "rxkb_layout_ref", unref_function = "rxkb_layout_unref", has_type_id = false)] + [Compact] + public class Layout { + public unowned Rxkb.Layout? next (); + public unowned string get_name (); + public unowned string? get_description (); + public unowned string? get_variant (); + public unowned string? get_brief (); + [CCode (cname = "rxkb_layout_get_iso639_first")] + public unowned Rxkb.Iso639Code? get_first_iso639 (); + [CCode (cname = "rxkb_layout_get_iso3166_first")] + public unowned Rxkb.Iso3166Code? get_first_iso3166 (); + public unowned Rxkb.Layout @ref (); + public void unref (); + } + + [CCode (cname = "struct rxkb_option_group", ref_function = "rxkb_option_group_ref", unref_function = "rxkb_option_group_unref", has_type_id = false)] + [Compact] + public class OptionGroup { + public unowned Rxkb.OptionGroup? next (); + public unowned string get_name (); + public unowned string? get_description (); + public bool allows_multiple (); + public Rxkb.Popularity get_popularity (); + [CCode (cname = "rxkb_option_first")] + public unowned Rxkb.Option? get_first_option (); + public unowned Rxkb.OptionGroup @ref (); + public void unref (); + } + + [CCode (cname = "struct rxkb_option", ref_function = "rxkb_option_ref", unref_function = "rxkb_option_unref", has_type_id = false)] + [Compact] + public class Option { + public unowned Rxkb.Option? next (); + public unowned string get_name (); + public unowned string? get_description (); + public unowned string? get_brief (); + public Rxkb.Popularity get_popularity (); + public unowned Rxkb.Option @ref (); + public void unref (); + } + + [CCode (cname = "struct rxkb_iso639_code", ref_function = "rxkb_iso639_code_ref", unref_function = "rxkb_iso639_code_unref", has_type_id = false)] + [Compact] + public class Iso639Code { + public unowned Rxkb.Iso639Code? next (); + public unowned string get_code (); + public unowned Rxkb.Iso639Code @ref (); + public void unref (); + } + + [CCode (cname = "struct rxkb_iso3166_code", ref_function = "rxkb_iso3166_code_ref", unref_function = "rxkb_iso3166_code_unref", has_type_id = false)] + [Compact] + public class Iso3166Code { + public unowned Rxkb.Iso3166Code? next (); + public unowned string get_code (); + public unowned Rxkb.Iso3166Code @ref (); + public void unref (); + } + + [CCode (cname = "enum rxkb_context_flags", cprefix = "RXKB_CONTEXT_", has_type_id = false)] + [Flags] + public enum ContextFlags { + NO_FLAGS, + NO_DEFAULT_INCLUDES, + LOAD_EXOTIC_RULES + } + + [CCode (cname = "enum rxkb_popularity", cprefix = "RXKB_POPULARITY_", has_type_id = false)] + public enum Popularity { + STANDARD, + EXOTIC + } + + [CCode (cname = "enum rxkb_log_level", cprefix = "RXKB_LOG_LEVEL_", has_type_id = false)] + public enum LogLevel { + CRITICAL, + ERROR, + WARNING, + INFO, + DEBUG + } + + [CCode (has_target = false, has_typedef = false)] + public delegate void LogFn (Rxkb.Context ctx, Rxkb.LogLevel level, string format, va_list args); +} From 171f0bc21c752e0ed55165586d323588a885fb0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 8 Oct 2024 18:43:33 -0700 Subject: [PATCH 2/5] Remove XML dep, update README, CI --- .github/workflows/ci.yml | 2 +- README.md | 3 +-- meson.build | 1 - src/Objects/KeyboardLayout.vala | 23 ----------------------- src/meson.build | 3 +-- 5 files changed, 3 insertions(+), 29 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 359b907fb..14e886320 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: - name: Install Dependencies run: | apt update - apt install -y desktop-file-utils gettext libadwaita-1-dev libdistinst-dev libgee-0.8-dev libgranite-7-dev libgtk-4-dev libxml2-dev libjson-glib-dev libpwquality-dev libxml2-utils meson valac + apt install -y desktop-file-utils gettext libadwaita-1-dev libdistinst-dev libgee-0.8-dev libgranite-7-dev libgtk-4-dev libxkbregistry-dev libjson-glib-dev libpwquality-dev libxml2-utils meson valac - name: Build and Test env: DESTDIR: out diff --git a/README.md b/README.md index 4c4f4c751..9d2bb648c 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,7 @@ You'll need the following dependencies: - libadwaita-1-dev >=1.4.0 - libjson-glib-dev - libpwquality-dev - - libxml2-dev - - libxml2-utils + - libxkbregistry-dev - [distinst](https://github.com/pop-os/distinst/) - valac diff --git a/meson.build b/meson.build index 0b34239e2..3f1c858cc 100644 --- a/meson.build +++ b/meson.build @@ -20,7 +20,6 @@ gio_dep = dependency('gio-2.0') granite_dep = dependency('granite-7', version: '>=7.4.0') adw_dep = dependency('libadwaita-1', version: '>=1.4.0') json_glib_dep = dependency('json-glib-1.0') -xml2_dep = dependency('libxml-2.0') xkbregistry_dep = dependency('xkbregistry') pwquality_dep = dependency('pwquality') systemd_dep = dependency('systemd') diff --git a/src/Objects/KeyboardLayout.vala b/src/Objects/KeyboardLayout.vala index a91f13111..6223bdce0 100644 --- a/src/Objects/KeyboardLayout.vala +++ b/src/Objects/KeyboardLayout.vala @@ -246,17 +246,6 @@ public class Installer.KeyboardLayout : GLib.Object { return a.display_name.collate (b.display_name); } - private const string XKB_RULES_FILE = "base.xml"; - - private static string get_xml_rules_file_path () { - unowned string? base_path = GLib.Environment.get_variable ("XKB_CONFIG_ROOT"); - if (base_path == null) { - base_path = Build.XKB_BASE; - } - - return Path.build_filename (base_path, "rules", XKB_RULES_FILE); - } - public static GLib.ListStore get_all () { var layout_store = new GLib.ListStore (typeof (KeyboardLayout)); @@ -284,16 +273,4 @@ public class Installer.KeyboardLayout : GLib.Object { return layout_store; } - - private static unowned Xml.Node* get_xml_node_by_name (Xml.Node* root, string name) { - for (unowned Xml.Node* iter = root->children; iter != null; iter = iter->next) { - if (iter->type == Xml.ElementType.ELEMENT_NODE) { - if (iter->name == name) { - return iter; - } - } - } - - return null; - } } diff --git a/src/meson.build b/src/meson.build index 44161cda6..3bcba8d65 100644 --- a/src/meson.build +++ b/src/meson.build @@ -65,8 +65,7 @@ gui_dependencies = [ adw_dep, json_glib_dep, pwquality_dep, - xkbregistry_dep, - xml2_dep + xkbregistry_dep ] executable(meson.project_name(), vala_files, config_file, From df1222245eb82dbc58df4440c8ab304dfa9b98f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Thu, 10 Oct 2024 10:41:10 -0700 Subject: [PATCH 3/5] Update KeyboardLayout.vala --- src/Objects/KeyboardLayout.vala | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Objects/KeyboardLayout.vala b/src/Objects/KeyboardLayout.vala index 6223bdce0..e4ce0972f 100644 --- a/src/Objects/KeyboardLayout.vala +++ b/src/Objects/KeyboardLayout.vala @@ -254,10 +254,6 @@ public class Installer.KeyboardLayout : GLib.Object { var xkb_layout = xkb_context.get_first_layout (); while (xkb_layout != null) { - if (xkb_layout.get_variant () != null) { - continue; - } - var layout = new KeyboardLayout (xkb_layout.get_name (), xkb_layout.get_description ()); layout_store.insert_sorted (layout, (GLib.CompareDataFunc) KeyboardLayout.compare); From 8262d3c3c165b86af51f36c629e003fd78dbf131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Fri, 11 Oct 2024 10:30:55 -0700 Subject: [PATCH 4/5] Update .github/workflows/ci.yml Co-authored-by: Ryo Nakano --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14e886320..db99c7221 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: - name: Install Dependencies run: | apt update - apt install -y desktop-file-utils gettext libadwaita-1-dev libdistinst-dev libgee-0.8-dev libgranite-7-dev libgtk-4-dev libxkbregistry-dev libjson-glib-dev libpwquality-dev libxml2-utils meson valac + apt install -y desktop-file-utils gettext libadwaita-1-dev libdistinst-dev libgee-0.8-dev libgranite-7-dev libgtk-4-dev libxkbregistry-dev libjson-glib-dev libpwquality-dev meson valac - name: Build and Test env: DESTDIR: out From 697dad34da1319a63111e57c2b10ab32903c043d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Fri, 11 Oct 2024 10:33:08 -0700 Subject: [PATCH 5/5] Remove XKB_BASE constnat --- src/Config.vala.in | 1 - src/meson.build | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/Config.vala.in b/src/Config.vala.in index a9f6c8bd6..247c2d825 100644 --- a/src/Config.vala.in +++ b/src/Config.vala.in @@ -3,6 +3,5 @@ namespace Build { public const string LANG_LIST = "@LANG_LIST@"; public const string LOCALEDIR = @LOCALEDIR@; public const string PREFERRED_LANG_LIST = "@PREFERRED_LANG_LIST@"; - public const string XKB_BASE = "@XKB_BASE@"; public const string ISO_CODES_LOCATION = "@ISO_CODES_LOCATION@"; } diff --git a/src/meson.build b/src/meson.build index 3bcba8d65..39df2156f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -39,10 +39,6 @@ configuration_data.set('GETTEXT_PACKAGE', meson.project_name()) configuration_data.set('LANG_LIST', get_option('supported_languages')) configuration_data.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir')) -xkbconf = dependency('xkeyboard-config') -xkb_base = xkbconf.get_pkgconfig_variable('xkb_base') -configuration_data.set('XKB_BASE', xkb_base) - isocodes = dependency('iso-codes') isocodes_prefix = isocodes.get_pkgconfig_variable('prefix') isocodes_location = join_paths(isocodes_prefix, get_option('datadir'), 'iso-codes', 'json')