Merge lp:~davidmhewitt/switchboard-plug-keyboard/fix-1650986-load-xml-config into lp:~elementary-pantheon/switchboard-plug-keyboard/trunk

Proposed by David Hewitt
Status: Merged
Approved by: Danielle Foré
Approved revision: 519
Merged at revision: 523
Proposed branch: lp:~davidmhewitt/switchboard-plug-keyboard/fix-1650986-load-xml-config
Merge into: lp:~elementary-pantheon/switchboard-plug-keyboard/trunk
Diff against target: 176 lines (+81/-53)
2 files modified
src/CMakeLists.txt (+2/-1)
src/Layout/Handler.vala (+79/-52)
To merge this branch: bzr merge lp:~davidmhewitt/switchboard-plug-keyboard/fix-1650986-load-xml-config
Reviewer Review Type Date Requested Status
Santiago (community) code Approve
elementary Pantheon team Pending
Leonardo Lemos Pending
Review via email: mp+317412@code.launchpad.net

Commit message

Load XKB keymaps from evdev.xml instead of evdev.lst

Description of the change

The list of keyboard configurations was being read from evdev.lst. All documentation online about how to create keyboard maps refers to creating them in the XML files.

I checked and both files contain the exact same base configurations for every language and keymap. But, it's likely that any custom or new keyboard maps will be added to the XML files.

To post a comment you must log in.
517. By David Hewitt

Fixed double-free crash?

518. By David Hewitt

Improved code based on Santiago's suggestions

519. By David Hewitt

Ooops, missed some improvements from last commit

Revision history for this message
Santiago (santileortiz) wrote :

This and the branch on the keyboard indicator should allow users to more easily use custom keyboard layouts, I've been running them both for several days and they seem fine. Code looks good to me too.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2017-02-12 02:46:10 +0000
+++ src/CMakeLists.txt 2017-02-25 18:17:51 +0000
@@ -1,7 +1,7 @@
1find_package (PkgConfig)1find_package (PkgConfig)
22
3# Add all your dependencies to the list below3# Add all your dependencies to the list below
4pkg_check_modules (DEPS REQUIRED gthread-2.0 gtk+-3.0>=3.10 switchboard-2.0 granite)4pkg_check_modules (DEPS REQUIRED gthread-2.0 gtk+-3.0>=3.10 switchboard-2.0 granite libxml-2.0)
55
6add_definitions (${DEPS_CFLAGS})6add_definitions (${DEPS_CFLAGS})
7link_directories (${DEPS_LIBRARY_DIRS})7link_directories (${DEPS_LIBRARY_DIRS})
@@ -47,6 +47,7 @@
47 gtk+-3.047 gtk+-3.0
48 switchboard-2.048 switchboard-2.0
49 granite49 granite
50 libxml-2.0
50OPTIONS51OPTIONS
51 --thread52 --thread
52)53)
5354
=== modified file 'src/Layout/Handler.vala'
--- src/Layout/Handler.vala 2017-02-12 02:46:10 +0000
+++ src/Layout/Handler.vala 2017-02-25 18:17:51 +0000
@@ -8,73 +8,100 @@
8 construct {8 construct {
9 languages = new HashTable<string, string> (str_hash, str_equal);9 languages = new HashTable<string, string> (str_hash, str_equal);
10 }10 }
1111
12 private void parse_layouts () {12 private void parse_layouts () {
13 var file = File.new_for_path ("/usr/share/X11/xkb/rules/evdev.lst");13 Xml.Doc* doc = Xml.Parser.parse_file ("/usr/share/X11/xkb/rules/evdev.xml");
1414 if (doc == null) {
15 if (!file.query_exists ()) {15 critical ("'evdev.xml' not found or permissions missing\n");
16 critical ("File '%s' doesn't exist.", file.get_path ());16 return;
17 return;17 }
18 }18
1919 Xml.XPath.Context cntx = new Xml.XPath.Context (doc);
20 try {20 Xml.XPath.Object* res = cntx.eval_expression ("/xkbConfigRegistry/layoutList/layout/configItem");
21 var dis = new DataInputStream (file.read ());21
22 string line;22 if (res == null) {
23 bool layout_found = false;23 delete doc;
24 while ((line = dis.read_line (null)) != null) {24 critical ("Unable to parse 'evdev.xml'");
25 if (layout_found) {25 return;
26 if ("!" in line || line == "") {26 }
27 break;27
28 }28 if (res->type != Xml.XPath.ObjectType.NODESET || res->nodesetval == null) {
29 29 delete res;
30 var parts = line.chug ().split (" ", 2);30 delete doc;
31 languages.set (parts[0], dgettext ("xkeyboard-config", parts[1].chug ()));31 critical ("No layouts found in 'evdev.xml'");
32 } else {32 return;
33 if ("!" in line && "layout" in line) {33 }
34 layout_found = true;34
35 for (int i = 0; i < res->nodesetval->length (); i++) {
36 Xml.Node* node = res->nodesetval->item (i);
37 string? name = null;
38 string? description = null;
39 for (Xml.Node* iter = node->children; iter != null; iter = iter->next) {
40 if (iter->type == Xml.ElementType.ELEMENT_NODE) {
41 if (iter->name == "name") {
42 name = iter->get_content ();
43 } else if (iter->name == "description") {
44 description = dgettext ("xkeyboard-config", iter->get_content ());
35 }45 }
36 }46 }
37 }47 }
38 } catch (Error e) {48 if (name != null && description != null) {
39 error (e.message);49 languages.set (name, description);
50 }
40 }51 }
52
53 delete res;
54 delete doc;
41 }55 }
4256
43 public HashTable<string, string> get_variants_for_language (string language) {57 public HashTable<string, string> get_variants_for_language (string language) {
44 var returned_table = new HashTable<string, string> (str_hash, str_equal);58 var returned_table = new HashTable<string, string> (str_hash, str_equal);
45 returned_table.set ("", _("Default"));59 returned_table.set ("", _("Default"));
46 var file = File.new_for_path ("/usr/share/X11/xkb/rules/evdev.lst");60 Xml.Doc* doc = Xml.Parser.parse_file ("/usr/share/X11/xkb/rules/evdev.xml");
4761 if (doc == null) {
48 if (!file.query_exists ()) {62 critical ("'evdev.xml' not found or permissions incorrect\n");
49 critical ("File '%s' doesn't exist.", file.get_path ());63 return returned_table;
50 return returned_table;64 }
51 }65
5266 Xml.XPath.Context cntx = new Xml.XPath.Context (doc);
53 try {67 var xpath = @"/xkbConfigRegistry/layoutList/layout/configItem/name[text()='$language']/../../variantList/variant/configItem";
54 var dis = new DataInputStream (file.read ());68 Xml.XPath.Object* res = cntx.eval_expression (xpath);
55 string line;69
56 bool variant_found = false;70 if (res == null) {
57 while ((line = dis.read_line (null)) != null) {71 delete doc;
58 if (variant_found) {72 critical ("Unable to parse 'evdev.xml'");
59 if ("!" in line || line == "") {73 return returned_table;
60 break;74 }
61 }75
62 76 if (res->type != Xml.XPath.ObjectType.NODESET || res->nodesetval == null) {
63 var parts = line.chug ().split (" ", 2);77 delete res;
64 var subparts = parts[1].chug ().split (":", 2);78 delete doc;
65 if (subparts[0] == language) {79 warning (@"No variants for $language found in 'evdev.xml'");
66 returned_table.set (parts[0], dgettext ("xkeyboard-config", subparts[1].chug ()));80 return returned_table;
67 }81 }
68 } else {82
69 if ("!" in line && "variant" in line) {83 for (int i = 0; i < res->nodesetval->length (); i++) {
70 variant_found = true;84 Xml.Node* node = res->nodesetval->item (i);
85
86 string? name = null;
87 string? description = null;
88 for (Xml.Node* iter = node->children; iter != null; iter = iter->next) {
89 if (iter->type == Xml.ElementType.ELEMENT_NODE) {
90 if (iter->name == "name") {
91 name = iter->get_content ();
92 } else if (iter->name == "description") {
93 description = dgettext ("xkeyboard-config", iter->get_content ());
71 }94 }
72 }95 }
73 }96 }
74 } catch (Error e) {97 if (name != null && description != null) {
75 error (e.message);98 returned_table.set (name, description);
99 }
76 }100 }
77101
102 delete res;
103 delete doc;
104
78 return returned_table;105 return returned_table;
79 }106 }
80107

Subscribers

People subscribed via source and target branches

to all changes: