Merge lp:~mterry/lightdm/keyboards into lp:lightdm
- keyboards
- Merge into trunk
Proposed by
Michael Terry
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 1394 | ||||||||||||
Proposed branch: | lp:~mterry/lightdm/keyboards | ||||||||||||
Merge into: | lp:lightdm | ||||||||||||
Diff against target: |
962 lines (+607/-26) (has conflicts) 15 files modified
liblightdm-gobject/layout.c (+88/-11) liblightdm-gobject/user.c (+10/-1) tests/Makefile.am (+2/-0) tests/scripts/default-keyboard-layout.conf (+40/-0) tests/scripts/keyboard-layout.conf (+11/-0) tests/scripts/keyboard-variants.conf (+52/-0) tests/scripts/no-keyboard-layout.conf (+4/-0) tests/src/Makefile.am (+1/-1) tests/src/X.c (+3/-0) tests/src/test-gobject-greeter.c (+92/-0) tests/src/test-runner.c (+27/-12) tests/src/x-server.c (+271/-1) tests/src/x-server.h (+2/-0) tests/test-default-keyboard-layout (+2/-0) tests/test-keyboard-variants (+2/-0) Text conflict in tests/scripts/keyboard-layout.conf Text conflict in tests/scripts/no-keyboard-layout.conf Text conflict in tests/src/test-gobject-greeter.c |
||||||||||||
To merge this branch: | bzr merge lp:~mterry/lightdm/keyboards | ||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Robert Ancell | Needs Fixing | ||
Review via email: mp+91907@code.launchpad.net |
Commit message
Description of the change
This branch fixes the outstanding keyboard issues:
1) It grabs the default keyboard layout from the system
2) It lists variants in its giant list of layouts
3) It knows to ask accountsservice about "XKeyboardLayout" a new property I will add to accountsservice to expose the user's layout/variant. The X in this instance means "extension", i.e. not official.
And of course, new or augmented tests for all this.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'liblightdm-gobject/layout.c' |
2 | --- liblightdm-gobject/layout.c 2011-12-20 16:29:17 +0000 |
3 | +++ liblightdm-gobject/layout.c 2012-02-07 19:30:57 +0000 |
4 | @@ -1,4 +1,5 @@ |
5 | -/* |
6 | +/* -*- Mode: C; indent-tabs-mode:nil; tab-width:4 -*- |
7 | + * |
8 | * Copyright (C) 2010 Robert Ancell. |
9 | * Author: Robert Ancell <robert.ancell@canonical.com> |
10 | * |
11 | @@ -36,6 +37,55 @@ |
12 | static XklEngine *xkl_engine = NULL; |
13 | static XklConfigRec *xkl_config = NULL; |
14 | static GList *layouts = NULL; |
15 | +static LightDMLayout *default_layout = NULL; |
16 | + |
17 | +static gchar * |
18 | +make_layout_string (const gchar *layout, const gchar *variant) |
19 | +{ |
20 | + if (!layout || layout[0] == 0) |
21 | + return NULL; |
22 | + else if (!variant || variant[0] == 0) |
23 | + return g_strdup (layout); |
24 | + else |
25 | + return g_strdup_printf ("%s\t%s", layout, variant); |
26 | +} |
27 | + |
28 | +static void |
29 | +parse_layout_string (const gchar *name, gchar **layout, gchar **variant) |
30 | +{ |
31 | + gchar **split; |
32 | + |
33 | + *layout = NULL; |
34 | + *variant = NULL; |
35 | + |
36 | + if (!name) |
37 | + return; |
38 | + |
39 | + split = g_strsplit (name, "\t", 2); |
40 | + if (split[0]) |
41 | + { |
42 | + *layout = g_strdup (split[0]); |
43 | + if (split[1]) |
44 | + *variant = g_strdup (split[1]); |
45 | + } |
46 | + g_strfreev (split); |
47 | +} |
48 | + |
49 | +static void |
50 | +variant_cb (XklConfigRegistry *config, |
51 | + const XklConfigItem *item, |
52 | + gpointer data) |
53 | +{ |
54 | + LightDMLayout *layout; |
55 | + gchar *full_name; |
56 | + |
57 | + full_name = make_layout_string (data, item->name); |
58 | + |
59 | + layout = g_object_new (LIGHTDM_TYPE_LAYOUT, "name", full_name, "short-description", item->short_description, "description", item->description, NULL); |
60 | + layouts = g_list_append (layouts, layout); |
61 | + |
62 | + g_free (full_name); |
63 | +} |
64 | |
65 | static void |
66 | layout_cb (XklConfigRegistry *config, |
67 | @@ -46,6 +96,8 @@ |
68 | |
69 | layout = g_object_new (LIGHTDM_TYPE_LAYOUT, "name", item->name, "short-description", item->short_description, "description", item->description, NULL); |
70 | layouts = g_list_append (layouts, layout); |
71 | + |
72 | + xkl_config_registry_foreach_layout_variant (config, item->name, variant_cb, (gpointer) item->name); |
73 | } |
74 | |
75 | /** |
76 | @@ -86,19 +138,25 @@ |
77 | * Set the layout for this session. |
78 | **/ |
79 | void |
80 | -lightdm_set_layout (LightDMLayout *layout) |
81 | +lightdm_set_layout (LightDMLayout *dmlayout) |
82 | { |
83 | XklConfigRec *config; |
84 | - |
85 | - g_return_if_fail (layout != NULL); |
86 | - |
87 | - g_debug ("Setting keyboard layout to %s", lightdm_layout_get_name (layout)); |
88 | + gchar *layout, *variant; |
89 | + |
90 | + g_return_if_fail (dmlayout != NULL); |
91 | + |
92 | + g_debug ("Setting keyboard layout to '%s'", lightdm_layout_get_name (dmlayout)); |
93 | + |
94 | + parse_layout_string (lightdm_layout_get_name (dmlayout), &layout, &variant); |
95 | |
96 | config = xkl_config_rec_new (); |
97 | config->layouts = g_malloc (sizeof (gchar *) * 2); |
98 | + config->variants = g_malloc (sizeof (gchar *) * 2); |
99 | config->model = g_strdup (xkl_config->model); |
100 | - config->layouts[0] = g_strdup (lightdm_layout_get_name (layout)); |
101 | + config->layouts[0] = layout; |
102 | config->layouts[1] = NULL; |
103 | + config->variants[0] = variant; |
104 | + config->variants[1] = NULL; |
105 | if (!xkl_config_rec_activate (config, xkl_engine)) |
106 | g_warning ("Failed to activate XKL config"); |
107 | g_object_unref (config); |
108 | @@ -115,10 +173,29 @@ |
109 | lightdm_get_layout (void) |
110 | { |
111 | lightdm_get_layouts (); |
112 | - if (layouts) |
113 | - return (LightDMLayout *) g_list_first (layouts)->data; |
114 | - else |
115 | - return NULL; |
116 | + |
117 | + if (layouts && xkl_config && !default_layout) |
118 | + { |
119 | + gchar *full_name; |
120 | + GList *item; |
121 | + |
122 | + full_name = make_layout_string (xkl_config->layouts ? xkl_config->layouts[0] : NULL, |
123 | + xkl_config->variants ? xkl_config->variants[0] : NULL); |
124 | + |
125 | + for (item = layouts; item; item = item->next) |
126 | + { |
127 | + LightDMLayout *iter_layout = (LightDMLayout *) item->data; |
128 | + if (g_strcmp0 (lightdm_layout_get_name (iter_layout), full_name) == 0) |
129 | + { |
130 | + default_layout = iter_layout; |
131 | + break; |
132 | + } |
133 | + } |
134 | + |
135 | + g_free (full_name); |
136 | + } |
137 | + |
138 | + return default_layout; |
139 | } |
140 | |
141 | /** |
142 | |
143 | === modified file 'liblightdm-gobject/user.c' |
144 | --- liblightdm-gobject/user.c 2012-01-24 05:26:39 +0000 |
145 | +++ liblightdm-gobject/user.c 2012-02-07 19:30:57 +0000 |
146 | @@ -1,4 +1,5 @@ |
147 | -/* |
148 | +/* -*- Mode: C; indent-tabs-mode:nil; tab-width:4 -*- |
149 | + * |
150 | * Copyright (C) 2010 Robert Ancell. |
151 | * Author: Robert Ancell <robert.ancell@canonical.com> |
152 | * |
153 | @@ -1196,6 +1197,7 @@ |
154 | LightDMUserListPrivate *list_priv = GET_LIST_PRIVATE (priv->user_list); |
155 | UserAccountObject *account = NULL; |
156 | GList *iter; |
157 | + gchar *value; |
158 | |
159 | /* First, find AccountObject proxy */ |
160 | for (iter = list_priv->user_account_objects; iter; iter = iter->next) |
161 | @@ -1218,6 +1220,13 @@ |
162 | g_free (priv->session); |
163 | priv->session = get_string_property (account->proxy, "XSession"); |
164 | |
165 | + value = get_string_property (account->proxy, "XKeyboardLayout"); |
166 | + if (value) |
167 | + { |
168 | + g_free (priv->layout); |
169 | + priv->layout = value; |
170 | + } |
171 | + |
172 | return TRUE; |
173 | } |
174 | |
175 | |
176 | === modified file 'tests/Makefile.am' |
177 | --- tests/Makefile.am 2012-02-06 05:28:06 +0000 |
178 | +++ tests/Makefile.am 2012-02-07 19:30:57 +0000 |
179 | @@ -19,6 +19,8 @@ |
180 | test-autologin-guest-logout \ |
181 | test-keyboard-layout \ |
182 | test-no-keyboard-layout \ |
183 | + test-default-keyboard-layout \ |
184 | + test-keyboard-variants \ |
185 | test-language \ |
186 | test-no-language \ |
187 | test-language-no-accounts-service \ |
188 | |
189 | === added file 'tests/scripts/default-keyboard-layout.conf' |
190 | --- tests/scripts/default-keyboard-layout.conf 1970-01-01 00:00:00 +0000 |
191 | +++ tests/scripts/default-keyboard-layout.conf 2012-02-07 19:30:57 +0000 |
192 | @@ -0,0 +1,40 @@ |
193 | +# |
194 | +# Check returns correct layout for a user |
195 | +# |
196 | + |
197 | +[LightDM] |
198 | +minimum-display-number=50 |
199 | + |
200 | +[test-xserver-config] |
201 | +keyboard-layout=ara |
202 | +keyboard-variant=azerty |
203 | + |
204 | +[test-greeter-config] |
205 | +log-keyboard-layout=%DEFAULT% |
206 | + |
207 | +#?RUNNER DAEMON-START |
208 | + |
209 | +# X server starts |
210 | +#?XSERVER :50 START |
211 | +#?XSERVER :50 INDICATE-READY |
212 | + |
213 | +# LightDM connects to X server |
214 | +#?XSERVER :50 ACCEPT-CONNECT |
215 | + |
216 | +# Greeter starts |
217 | +#?GREETER :50 START |
218 | +#?XSERVER :50 ACCEPT-CONNECT |
219 | +#?GREETER :50 CONNECT-XSERVER |
220 | +#?GREETER :50 CONNECT-TO-DAEMON |
221 | +#?GREETER :50 CONNECTED-TO-DAEMON |
222 | + |
223 | +# Correct layout is found |
224 | +#?XSERVER :50 ACCEPT-CONNECT |
225 | +#?GREETER :50 GET-LAYOUT USERNAME=%DEFAULT% LAYOUT='ara azerty' |
226 | + |
227 | +# Cleanup |
228 | +#?*STOP-DAEMON |
229 | +# Don't know what order they will terminate |
230 | +#?(GREETER :50 TERMINATE SIGNAL=15|XSERVER :50 TERMINATE SIGNAL=15) |
231 | +#?(GREETER :50 TERMINATE SIGNAL=15|XSERVER :50 TERMINATE SIGNAL=15) |
232 | +#?RUNNER DAEMON-EXIT STATUS=0 |
233 | |
234 | === modified file 'tests/scripts/keyboard-layout.conf' |
235 | --- tests/scripts/keyboard-layout.conf 2012-02-02 23:40:27 +0000 |
236 | +++ tests/scripts/keyboard-layout.conf 2012-02-07 19:30:57 +0000 |
237 | @@ -5,6 +5,12 @@ |
238 | [LightDM] |
239 | minimum-display-number=50 |
240 | |
241 | +<<<<<<< TREE |
242 | +======= |
243 | +[test-greeter-config] |
244 | +log-keyboard-layout=bob,carol |
245 | + |
246 | +>>>>>>> MERGE-SOURCE |
247 | #?RUNNER DAEMON-START |
248 | |
249 | # X server starts |
250 | @@ -22,8 +28,13 @@ |
251 | #?GREETER :50 CONNECTED-TO-DAEMON |
252 | |
253 | # Correct layout is found |
254 | +<<<<<<< TREE |
255 | #?*GREETER :50 LOG-LAYOUT USERNAME=bob |
256 | #?GREETER :50 LOG-LAYOUT USERNAME=bob LAYOUT=us |
257 | +======= |
258 | +#?GREETER :50 GET-LAYOUT USERNAME=bob LAYOUT='us' |
259 | +#?GREETER :50 GET-LAYOUT USERNAME=carol LAYOUT='fr oss' |
260 | +>>>>>>> MERGE-SOURCE |
261 | |
262 | # Cleanup |
263 | #?*STOP-DAEMON |
264 | |
265 | === added file 'tests/scripts/keyboard-variants.conf' |
266 | --- tests/scripts/keyboard-variants.conf 1970-01-01 00:00:00 +0000 |
267 | +++ tests/scripts/keyboard-variants.conf 2012-02-07 19:30:57 +0000 |
268 | @@ -0,0 +1,52 @@ |
269 | +# |
270 | +# Check returns variants as well as normal layouts |
271 | +# |
272 | + |
273 | +[LightDM] |
274 | +minimum-display-number=50 |
275 | + |
276 | +[test-greeter-config] |
277 | +log-keyboard-layouts=fr |
278 | + |
279 | +#?RUNNER DAEMON-START |
280 | + |
281 | +# X server starts |
282 | +#?XSERVER :50 START |
283 | +#?XSERVER :50 INDICATE-READY |
284 | + |
285 | +# LightDM connects to X server |
286 | +#?XSERVER :50 ACCEPT-CONNECT |
287 | + |
288 | +# Greeter starts |
289 | +#?GREETER :50 START |
290 | +#?XSERVER :50 ACCEPT-CONNECT |
291 | +#?GREETER :50 CONNECT-XSERVER |
292 | +#?GREETER :50 CONNECT-TO-DAEMON |
293 | +#?GREETER :50 CONNECTED-TO-DAEMON |
294 | + |
295 | +# Correct layouts are found |
296 | +#?XSERVER :50 ACCEPT-CONNECT |
297 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr' |
298 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr nodeadkeys' |
299 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr sundeadkeys' |
300 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr oss' |
301 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr oss_latin9' |
302 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr oss_nodeadkeys' |
303 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr oss_sundeadkeys' |
304 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr latin9' |
305 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr latin9_nodeadkeys' |
306 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr latin9_sundeadkeys' |
307 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr bepo' |
308 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr bepo_latin9' |
309 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr dvorak' |
310 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr mac' |
311 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr bre' |
312 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr oci' |
313 | +#?GREETER :50 GET-LAYOUTS LAYOUT='fr geo' |
314 | + |
315 | +# Cleanup |
316 | +#?*STOP-DAEMON |
317 | +# Don't know what order they will terminate |
318 | +#?(GREETER :50 TERMINATE SIGNAL=15|XSERVER :50 TERMINATE SIGNAL=15) |
319 | +#?(GREETER :50 TERMINATE SIGNAL=15|XSERVER :50 TERMINATE SIGNAL=15) |
320 | +#?RUNNER DAEMON-EXIT STATUS=0 |
321 | |
322 | === modified file 'tests/scripts/no-keyboard-layout.conf' |
323 | --- tests/scripts/no-keyboard-layout.conf 2012-02-02 23:40:27 +0000 |
324 | +++ tests/scripts/no-keyboard-layout.conf 2012-02-07 19:30:57 +0000 |
325 | @@ -22,8 +22,12 @@ |
326 | #?GREETER :50 CONNECTED-TO-DAEMON |
327 | |
328 | # Correct layout is found |
329 | +<<<<<<< TREE |
330 | #?*GREETER :50 LOG-LAYOUT USERNAME=alice |
331 | #?GREETER :50 LOG-LAYOUT USERNAME=alice LAYOUT= |
332 | +======= |
333 | +#?GREETER :50 GET-LAYOUT USERNAME=alice LAYOUT='' |
334 | +>>>>>>> MERGE-SOURCE |
335 | |
336 | # Cleanup |
337 | #?*STOP-DAEMON |
338 | |
339 | === modified file 'tests/src/Makefile.am' |
340 | --- tests/src/Makefile.am 2012-02-02 05:00:01 +0000 |
341 | +++ tests/src/Makefile.am 2012-02-07 19:30:57 +0000 |
342 | @@ -4,7 +4,7 @@ |
343 | |
344 | libsystem_la_SOURCES = libsystem.c |
345 | libsystem_la_CFLAGS = $(GLIB_CFLAGS) |
346 | -libsystem_la_LIBADD = -ldl |
347 | +libsystem_la_LIBADD = -ldl $(GLIB_LIBS) |
348 | |
349 | # This is required to have autotools generate a library that is not installed |
350 | # but produces a shared library (instead of just a static library) |
351 | |
352 | === modified file 'tests/src/X.c' |
353 | --- tests/src/X.c 2012-02-02 07:09:27 +0000 |
354 | +++ tests/src/X.c 2012-02-07 19:30:57 +0000 |
355 | @@ -339,6 +339,9 @@ |
356 | x_server_set_listen_unix (xserver, listen_unix); |
357 | x_server_set_listen_tcp (xserver, listen_tcp); |
358 | |
359 | + /* Add fake screen so that libx11 calls don't freak out when they can't find a screen */ |
360 | + x_server_add_screen (xserver, 0xffffff, 0x000000, 0, 1024, 768, 1000, 1000); |
361 | + |
362 | status_notify ("XSERVER :%d START", display_number); |
363 | |
364 | config = g_key_file_new (); |
365 | |
366 | === modified file 'tests/src/test-gobject-greeter.c' |
367 | --- tests/src/test-gobject-greeter.c 2012-02-02 23:40:27 +0000 |
368 | +++ tests/src/test-gobject-greeter.c 2012-02-07 19:30:57 +0000 |
369 | @@ -1,3 +1,5 @@ |
370 | +/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*- */ |
371 | + |
372 | #include <stdlib.h> |
373 | #include <stdio.h> |
374 | #include <string.h> |
375 | @@ -122,6 +124,11 @@ |
376 | main (int argc, char **argv) |
377 | { |
378 | GMainLoop *main_loop; |
379 | +<<<<<<< TREE |
380 | +======= |
381 | + LightDMGreeter *greeter; |
382 | + gchar *layout_username, *language_username, *layout_prefix; |
383 | +>>>>>>> MERGE-SOURCE |
384 | |
385 | signal (SIGINT, signal_cb); |
386 | signal (SIGTERM, signal_cb); |
387 | @@ -169,6 +176,91 @@ |
388 | |
389 | status_notify ("GREETER %s CONNECTED-TO-DAEMON", getenv ("DISPLAY")); |
390 | |
391 | +<<<<<<< TREE |
392 | +======= |
393 | + layout_username = g_key_file_get_string (config, "test-greeter-config", "log-keyboard-layout", NULL); |
394 | + if (layout_username) |
395 | + { |
396 | + gchar **users; |
397 | + int i; |
398 | + |
399 | + users = g_strsplit (layout_username, ",", 0); |
400 | + |
401 | + for (i = 0; users[i]; i++) |
402 | + { |
403 | + LightDMUser *user; |
404 | + const gchar *layout; |
405 | + |
406 | + if (g_strcmp0 (users[i], "%DEFAULT%") == 0) /* Grab system default layout */ |
407 | + layout = lightdm_layout_get_name (lightdm_get_layout ()); |
408 | + else |
409 | + { |
410 | + user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), users[i]); |
411 | + layout = lightdm_user_get_layout (user); |
412 | + } |
413 | + |
414 | + status_notify ("GREETER %s GET-LAYOUT USERNAME=%s LAYOUT='%s'", getenv ("DISPLAY"), users[i], layout ? layout : ""); |
415 | + } |
416 | + |
417 | + g_strfreev (users); |
418 | + } |
419 | + |
420 | + layout_prefix = g_key_file_get_string (config, "test-greeter-config", "log-keyboard-layouts", NULL); |
421 | + if (layout_prefix) |
422 | + { |
423 | + GList *layouts, *iter; |
424 | + |
425 | + layouts = lightdm_get_layouts (); |
426 | + |
427 | + for (iter = layouts; iter; iter = iter->next) |
428 | + { |
429 | + LightDMLayout *layout; |
430 | + const gchar *name; |
431 | + |
432 | + layout = (LightDMLayout *) iter->data; |
433 | + name = lightdm_layout_get_name (layout); |
434 | + |
435 | + if (g_str_has_prefix (name, layout_prefix)) |
436 | + { |
437 | + status_notify ("GREETER %s GET-LAYOUTS LAYOUT='%s'", getenv ("DISPLAY"), name); |
438 | + } |
439 | + } |
440 | + } |
441 | + |
442 | + language_username = g_key_file_get_string (config, "test-greeter-config", "log-language", NULL); |
443 | + if (language_username) |
444 | + { |
445 | + LightDMUser *user; |
446 | + const gchar *language; |
447 | + |
448 | + user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), language_username); |
449 | + language = lightdm_user_get_language (user); |
450 | + |
451 | + status_notify ("GREETER %s GET-LANGUAGE USERNAME=%s LANGUAGE=%s", getenv ("DISPLAY"), language_username, language ? language : ""); |
452 | + } |
453 | + |
454 | + if (g_key_file_get_boolean (config, "test-greeter-config", "crash-xserver", NULL)) |
455 | + { |
456 | + gchar *crash_lock; |
457 | + FILE *f; |
458 | + |
459 | + crash_lock = g_build_filename (g_getenv ("LIGHTDM_TEST_HOME_DIR"), ".greeter-crashed-xserver", NULL); |
460 | + f = fopen (crash_lock, "r"); |
461 | + |
462 | + if (f == NULL) |
463 | + { |
464 | + const gchar *name = "SIGSEGV"; |
465 | + status_notify ("GREETER %s CRASH-XSERVER", getenv ("DISPLAY")); |
466 | + xcb_intern_atom (connection, FALSE, strlen (name), name); |
467 | + xcb_flush (connection); |
468 | + |
469 | + /* Write lock to stop repeatedly logging in */ |
470 | + f = fopen (crash_lock, "w"); |
471 | + fclose (f); |
472 | + } |
473 | + } |
474 | + |
475 | +>>>>>>> MERGE-SOURCE |
476 | /* Automatically log in as requested user */ |
477 | if (lightdm_greeter_get_select_user_hint (greeter)) |
478 | status_notify ("GREETER %s SELECT-USER-HINT USERNAME=%s", getenv ("DISPLAY"), lightdm_greeter_get_select_user_hint (greeter)); |
479 | |
480 | === modified file 'tests/src/test-runner.c' |
481 | --- tests/src/test-runner.c 2012-02-06 05:17:12 +0000 |
482 | +++ tests/src/test-runner.c 2012-02-07 19:30:57 +0000 |
483 | @@ -4,6 +4,7 @@ |
484 | #include <ctype.h> |
485 | #include <errno.h> |
486 | #include <glib.h> |
487 | +#include <glib/gstdio.h> |
488 | #include <glib-unix.h> |
489 | #include <gio/gio.h> |
490 | #include <gio/gunixsocketaddress.h> |
491 | @@ -48,6 +49,7 @@ |
492 | guint id; |
493 | gchar *language; |
494 | gchar *xsession; |
495 | + gchar *layout; |
496 | } AccountsUser; |
497 | static GList *accounts_users = NULL; |
498 | static void handle_user_call (GDBusConnection *connection, |
499 | @@ -771,6 +773,7 @@ |
500 | *c = '\0'; |
501 | } |
502 | user->xsession = g_key_file_get_string (dmrc_file, "Desktop", "Session", NULL); |
503 | + user->layout = g_key_file_get_string (dmrc_file, "X-Accounts", "Layout", NULL); |
504 | user->path = g_strdup_printf ("/org/freedesktop/Accounts/User%d", uid); |
505 | user->id = g_dbus_connection_register_object (accounts_connection, |
506 | user->path, |
507 | @@ -895,6 +898,8 @@ |
508 | return g_variant_new_string (user->language ? user->language : ""); |
509 | else if (strcmp (property_name, "XSession") == 0) |
510 | return g_variant_new_string (user->xsession ? user->xsession : ""); |
511 | + else if (strcmp (property_name, "XKeyboardLayout") == 0) |
512 | + return g_variant_new_string (user->layout ? user->layout : ""); |
513 | |
514 | return NULL; |
515 | } |
516 | @@ -932,6 +937,7 @@ |
517 | " <property name='BackgroundFile' type='s' access='read'/>" |
518 | " <property name='Language' type='s' access='read'/>" |
519 | " <property name='XSession' type='s' access='read'/>" |
520 | + " <property name='XKeyboardLayout' type='s' access='read'/>" |
521 | " </interface>" |
522 | "</node>"; |
523 | GError *error = NULL; |
524 | @@ -1143,12 +1149,13 @@ |
525 | g_source_attach (status_source, NULL); |
526 | |
527 | /* Run from a temporary directory */ |
528 | - temp_dir = g_build_filename (cwd, "lightdm-test-XXXXXX", NULL); |
529 | + temp_dir = g_build_filename (g_get_tmp_dir (), "lightdm-test-XXXXXX", NULL); |
530 | if (!mkdtemp (temp_dir)) |
531 | { |
532 | g_warning ("Error creating temporary directory: %s", strerror (errno)); |
533 | quit (EXIT_FAILURE); |
534 | } |
535 | + g_chmod (temp_dir, 0755); |
536 | |
537 | /* Set up a skeleton file system */ |
538 | g_mkdir_with_parents (g_strdup_printf ("%s/etc", temp_dir), 0755); |
539 | @@ -1182,18 +1189,19 @@ |
540 | gboolean have_home_dir; |
541 | gchar *real_name; |
542 | gchar *xsession; |
543 | - gchar *layout; |
544 | + gchar *dmrc_layout; |
545 | + gchar *dbus_layout; |
546 | gchar *language; |
547 | gint uid; |
548 | } users[] = |
549 | { |
550 | - {"root", "", TRUE, "root", NULL, NULL, NULL, 0}, |
551 | - {"lightdm", "", TRUE, "", NULL, NULL, NULL, 100}, |
552 | - {"alice", "password", TRUE, "Alice User", NULL, NULL, NULL, 1000}, |
553 | - {"bob", "", TRUE, "Bob User", NULL, "us", "en_AU.utf8", 1001}, |
554 | - {"carol", "", TRUE, "Carol User", "alternative", "fr", "fr_FR.UTF-8", 1002}, |
555 | - {"dave", "", FALSE, "Dave User", NULL, NULL, NULL, 1003}, |
556 | - {NULL, NULL, FALSE, NULL, NULL, NULL, NULL, 0} |
557 | + {"root", "", TRUE, "root", NULL, NULL, NULL, NULL, 0}, |
558 | + {"lightdm", "", TRUE, "", NULL, NULL, NULL, NULL, 100}, |
559 | + {"alice", "password", TRUE, "Alice User", NULL, NULL, NULL, NULL, 1000}, |
560 | + {"bob", "", TRUE, "Bob User", NULL, "us", NULL, "en_AU.utf8", 1001}, |
561 | + {"carol", "", TRUE, "Carol User", "alternative", "ru", "fr\toss", "fr_FR.UTF-8", 1002}, |
562 | + {"dave", "", FALSE, "Dave User", NULL, NULL, NULL, NULL, 1003}, |
563 | + {NULL, NULL, FALSE, NULL, NULL, NULL, NULL, NULL, 0} |
564 | }; |
565 | passwd_data = g_string_new (""); |
566 | int i; |
567 | @@ -1206,6 +1214,8 @@ |
568 | { |
569 | path = g_build_filename (home_dir, users[i].user_name, NULL); |
570 | g_mkdir_with_parents (path, 0755); |
571 | + if (chown (path, users[i].uid, users[i].uid) < 0) |
572 | + g_debug ("chown (%s) failed: %s", path, strerror (errno)); |
573 | g_free (path); |
574 | } |
575 | |
576 | @@ -1215,9 +1225,14 @@ |
577 | g_key_file_set_string (dmrc_file, "Desktop", "Session", users[i].xsession); |
578 | save_dmrc = TRUE; |
579 | } |
580 | - if (users[i].layout) |
581 | - { |
582 | - g_key_file_set_string (dmrc_file, "Desktop", "Layout", users[i].layout); |
583 | + if (users[i].dmrc_layout) |
584 | + { |
585 | + g_key_file_set_string (dmrc_file, "Desktop", "Layout", users[i].dmrc_layout); |
586 | + save_dmrc = TRUE; |
587 | + } |
588 | + if (users[i].dbus_layout) |
589 | + { |
590 | + g_key_file_set_string (dmrc_file, "X-Accounts", "Layout", users[i].dbus_layout); |
591 | save_dmrc = TRUE; |
592 | } |
593 | if (users[i].language) |
594 | |
595 | === modified file 'tests/src/x-server.c' |
596 | --- tests/src/x-server.c 2012-02-02 07:09:27 +0000 |
597 | +++ tests/src/x-server.c 2012-02-07 19:30:57 +0000 |
598 | @@ -1,9 +1,12 @@ |
599 | +/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*- */ |
600 | + |
601 | #include <stdlib.h> |
602 | #include <stdio.h> |
603 | #include <string.h> |
604 | #include <errno.h> |
605 | #include <sys/types.h> |
606 | #include <sys/socket.h> |
607 | +#include <glib.h> |
608 | #include <gio/gio.h> |
609 | #include <gio/gunixsocketaddress.h> |
610 | |
611 | @@ -26,9 +29,24 @@ |
612 | |
613 | enum |
614 | { |
615 | + Error = 0, |
616 | Reply = 1, |
617 | }; |
618 | |
619 | +enum |
620 | +{ |
621 | + InternAtom = 16, |
622 | + GetProperty = 20, |
623 | + QueryExtension = 98, |
624 | + kbUseExtension = 200 |
625 | +}; |
626 | + |
627 | +enum |
628 | +{ |
629 | + BadAtom = 5, |
630 | + BadImplementation = 17 |
631 | +}; |
632 | + |
633 | enum { |
634 | X_SERVER_CLIENT_CONNECTED, |
635 | X_SERVER_CLIENT_DISCONNECTED, |
636 | @@ -78,6 +96,7 @@ |
637 | guint8 byte_order; |
638 | gboolean connected; |
639 | guint16 sequence_number; |
640 | + GHashTable *atoms; |
641 | }; |
642 | |
643 | struct XScreenPrivate |
644 | @@ -272,6 +291,23 @@ |
645 | } |
646 | |
647 | void |
648 | +x_client_send_error (XClient *client, int type, int major, int minor) |
649 | +{ |
650 | + guint8 buffer[MAXIMUM_REQUEST_LENGTH]; |
651 | + gsize n_written = 0; |
652 | + |
653 | + write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, Error, &n_written); |
654 | + write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, type, &n_written); |
655 | + write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, client->priv->sequence_number, &n_written); |
656 | + write_card32 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* resourceID */ |
657 | + write_card16 (buffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, minor, &n_written); |
658 | + write_card8 (buffer, MAXIMUM_REQUEST_LENGTH, major, &n_written); |
659 | + write_padding (buffer, MAXIMUM_REQUEST_LENGTH, 21, &n_written); |
660 | + |
661 | + send (g_io_channel_unix_get_fd (client->priv->channel), buffer, n_written, 0); |
662 | +} |
663 | + |
664 | +void |
665 | x_client_disconnect (XClient *client) |
666 | { |
667 | g_io_channel_shutdown (client->priv->channel, TRUE, NULL); |
668 | @@ -282,11 +318,16 @@ |
669 | { |
670 | client->priv = G_TYPE_INSTANCE_GET_PRIVATE (client, x_client_get_type (), XClientPrivate); |
671 | client->priv->sequence_number = 1; |
672 | + client->priv->atoms = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); |
673 | } |
674 | |
675 | static void |
676 | x_client_finalize (GObject *object) |
677 | { |
678 | + XClient *client = (XClient *) object; |
679 | + |
680 | + g_hash_table_unref (client->priv->atoms); |
681 | + client->priv->atoms = NULL; |
682 | } |
683 | |
684 | static void |
685 | @@ -425,6 +466,214 @@ |
686 | } |
687 | |
688 | static void |
689 | +process_intern_atom (XClient *client, const guint8 *buffer, gssize buffer_length) |
690 | +{ |
691 | + /* Decode */ |
692 | + |
693 | + gsize offset = 0; |
694 | + guint8 onlyIfExists; |
695 | + guint16 n; |
696 | + gchar *name; |
697 | + int atom; |
698 | + |
699 | + read_padding (1, &offset); /* reqType */ |
700 | + onlyIfExists = read_card8 (buffer, buffer_length, &offset); |
701 | + read_padding (2, &offset); /* length */ |
702 | + n = read_card16 (buffer, buffer_length, client->priv->byte_order, &offset); |
703 | + read_padding (2, &offset); |
704 | + name = read_padded_string (buffer, buffer_length, n, &offset); |
705 | + |
706 | + /* Process */ |
707 | + |
708 | + atom = g_str_hash (name); |
709 | + |
710 | + if (onlyIfExists) |
711 | + { |
712 | + g_free (name); |
713 | + if (!g_hash_table_contains (client->priv->atoms, GINT_TO_POINTER (atom))) |
714 | + { |
715 | + x_client_send_error (client, BadAtom, InternAtom, 0); |
716 | + return; |
717 | + } |
718 | + } |
719 | + else |
720 | + g_hash_table_insert (client->priv->atoms, GINT_TO_POINTER (atom), name); |
721 | + |
722 | + /* Reply */ |
723 | + |
724 | + guint8 outBuffer[MAXIMUM_REQUEST_LENGTH]; |
725 | + gsize n_written = 0; |
726 | + |
727 | + write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, Reply, &n_written); |
728 | + write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, 1, &n_written); |
729 | + write_card16 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, client->priv->sequence_number, &n_written); |
730 | + write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* length */ |
731 | + write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, atom, &n_written); |
732 | + write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, 20, &n_written); |
733 | + |
734 | + send (g_io_channel_unix_get_fd (client->priv->channel), outBuffer, n_written, 0); |
735 | +} |
736 | + |
737 | +static void |
738 | +process_get_property (XClient *client, const guint8 *buffer, gssize buffer_length) |
739 | +{ |
740 | + /* Decode */ |
741 | + |
742 | + gsize offset = 0; |
743 | + guint8 delete; |
744 | + guint32 property; |
745 | + guint32 type; |
746 | + |
747 | + read_padding (1, &offset); /* reqType */ |
748 | + delete = read_card8 (buffer, buffer_length, &offset); |
749 | + read_padding (2, &offset); /* length */ |
750 | + read_padding (4, &offset); /* window */ |
751 | + property = read_card32 (buffer, buffer_length, client->priv->byte_order, &offset); |
752 | + type = read_card32 (buffer, buffer_length, client->priv->byte_order, &offset); |
753 | + read_padding (4, &offset); /* longOffset */ |
754 | + read_padding (4, &offset); /* longLength */ |
755 | + |
756 | + /* Process */ |
757 | + |
758 | + gchar *name = g_hash_table_lookup (client->priv->atoms, GINT_TO_POINTER (property)); |
759 | + GString *reply = NULL; |
760 | + guint8 format = 8; |
761 | + |
762 | + if (g_strcmp0 (name, "_XKB_RULES_NAMES") == 0) |
763 | + { |
764 | + GKeyFile *config; |
765 | + |
766 | + config = g_key_file_new (); |
767 | + if (g_getenv ("LIGHTDM_TEST_CONFIG")) |
768 | + g_key_file_load_from_file (config, g_getenv ("LIGHTDM_TEST_CONFIG"), G_KEY_FILE_NONE, NULL); |
769 | + |
770 | + reply = g_string_new (""); |
771 | + |
772 | + g_string_append (reply, "evdev"); /* rules file */ |
773 | + g_string_append_c (reply, 0); /* embedded null byte */ |
774 | + |
775 | + g_string_append (reply, "pc105"); /* model name */ |
776 | + g_string_append_c (reply, 0); /* embedded null byte */ |
777 | + |
778 | + if (g_key_file_has_key (config, "test-xserver-config", "keyboard-layout", NULL)) |
779 | + g_string_append (reply, g_key_file_get_string (config, "test-xserver-config", "keyboard-layout", NULL)); |
780 | + else |
781 | + g_string_append (reply, "us"); |
782 | + g_string_append_c (reply, 0); /* embedded null byte */ |
783 | + |
784 | + if (g_key_file_has_key (config, "test-xserver-config", "keyboard-variant", NULL)) |
785 | + g_string_append (reply, g_key_file_get_string (config, "test-xserver-config", "keyboard-variant", NULL)); |
786 | + g_string_append_c (reply, 0); /* embedded null byte */ |
787 | + |
788 | + /* no xkb options */ |
789 | + g_string_append_c (reply, 0); /* embedded null byte */ |
790 | + |
791 | + g_key_file_free (config); |
792 | + } |
793 | + |
794 | + if (name && delete) |
795 | + g_hash_table_remove (client->priv->atoms, GINT_TO_POINTER (property)); |
796 | + |
797 | + /* Reply */ |
798 | + |
799 | + if (!reply) |
800 | + { |
801 | + x_client_send_error (client, BadImplementation, GetProperty, 0); |
802 | + return; |
803 | + } |
804 | + |
805 | + guint8 outBuffer[MAXIMUM_REQUEST_LENGTH]; |
806 | + gsize n_written = 0, length_offset, packet_start; |
807 | + |
808 | + write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, Reply, &n_written); |
809 | + write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, format, &n_written); |
810 | + write_card16 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, client->priv->sequence_number, &n_written); |
811 | + length_offset = n_written; |
812 | + write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* length */ |
813 | + write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, type, &n_written); |
814 | + write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* bytesAfter */ |
815 | + write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, reply->len, &n_written); |
816 | + write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, 12, &n_written); |
817 | + packet_start = n_written; |
818 | + |
819 | + write_string8 (outBuffer, MAXIMUM_REQUEST_LENGTH, (guint8 *) reply->str, reply->len, &n_written); |
820 | + write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, pad (reply->len), &n_written); |
821 | + |
822 | + write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, (n_written - packet_start) / 4, &length_offset); |
823 | + |
824 | + send (g_io_channel_unix_get_fd (client->priv->channel), outBuffer, n_written, 0); |
825 | + |
826 | + /* Cleanup */ |
827 | + |
828 | + g_string_free (reply, TRUE); |
829 | +} |
830 | + |
831 | +static void |
832 | +process_query_extension (XClient *client, const guint8 *buffer, gssize buffer_length) |
833 | +{ |
834 | + /* Decode */ |
835 | + |
836 | + gsize offset = 0; |
837 | + guint8 n; |
838 | + gchar *name; |
839 | + |
840 | + read_padding (1, &offset); /* reqType */ |
841 | + read_padding (1, &offset); /* pad */ |
842 | + read_padding (2, &offset); /* length */ |
843 | + n = read_card16 (buffer, buffer_length, client->priv->byte_order, &offset); |
844 | + read_padding (2, &offset); /* pad */ |
845 | + name = read_padded_string (buffer, buffer_length, n, &offset); |
846 | + |
847 | + /* Process */ |
848 | + |
849 | + guint8 present = 0; |
850 | + if (g_strcmp0 (name, "XKEYBOARD") == 0) |
851 | + present = 1; |
852 | + |
853 | + /* Reply */ |
854 | + |
855 | + guint8 outBuffer[MAXIMUM_REQUEST_LENGTH]; |
856 | + gsize n_written = 0; |
857 | + |
858 | + write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, Reply, &n_written); |
859 | + write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, 1, &n_written); |
860 | + write_card16 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, client->priv->sequence_number, &n_written); |
861 | + write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* length */ |
862 | + write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, present, &n_written); |
863 | + write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, kbUseExtension, &n_written); /* major_opcode */ |
864 | + write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, 0, &n_written); /* first_event */ |
865 | + write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, 0, &n_written); /* first_error */ |
866 | + write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, 20, &n_written); |
867 | + |
868 | + send (g_io_channel_unix_get_fd (client->priv->channel), outBuffer, n_written, 0); |
869 | + |
870 | + /* Cleanup */ |
871 | + |
872 | + g_free (name); |
873 | +} |
874 | + |
875 | +static void |
876 | +process_kb_use_extension (XClient *client, const guint8 *buffer, gssize buffer_length) |
877 | +{ |
878 | + /* Nothing to decode, we don't care about parameters */ |
879 | + |
880 | + /* Reply */ |
881 | + |
882 | + guint8 outBuffer[MAXIMUM_REQUEST_LENGTH]; |
883 | + gsize n_written = 0; |
884 | + |
885 | + write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, Reply, &n_written); |
886 | + write_card8 (outBuffer, MAXIMUM_REQUEST_LENGTH, 1, &n_written); /* supported */ |
887 | + write_card16 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, client->priv->sequence_number, &n_written); |
888 | + write_card32 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* length */ |
889 | + write_card16 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 1, &n_written); /* serverMajor */ |
890 | + write_card16 (outBuffer, MAXIMUM_REQUEST_LENGTH, client->priv->byte_order, 0, &n_written); /* serverMinor */ |
891 | + write_padding (outBuffer, MAXIMUM_REQUEST_LENGTH, 20, &n_written); |
892 | + |
893 | + send (g_io_channel_unix_get_fd (client->priv->channel), outBuffer, n_written, 0); |
894 | +} |
895 | + |
896 | +static void |
897 | decode_request (XClient *client, const guint8 *buffer, gssize buffer_length) |
898 | { |
899 | int opcode; |
900 | @@ -436,13 +685,34 @@ |
901 | guint16 length; |
902 | |
903 | start_offset = offset; |
904 | - client->priv->sequence_number++; |
905 | opcode = read_card8 (buffer, buffer_length, &offset); |
906 | read_card8 (buffer, buffer_length, &offset); |
907 | length = read_card16 (buffer, buffer_length, client->priv->byte_order, &offset) * 4; |
908 | |
909 | g_debug ("Got opcode=%d length=%d", opcode, length); |
910 | offset = start_offset + length; |
911 | + |
912 | + switch (opcode) |
913 | + { |
914 | + case InternAtom: |
915 | + process_intern_atom (client, buffer + start_offset, length); |
916 | + break; |
917 | + case GetProperty: |
918 | + process_get_property (client, buffer + start_offset, length); |
919 | + break; |
920 | + case QueryExtension: |
921 | + process_query_extension (client, buffer + start_offset, length); |
922 | + break; |
923 | + case kbUseExtension: |
924 | + process_kb_use_extension (client, buffer + start_offset, length); |
925 | + break; |
926 | + default: |
927 | + /* Send an error because we don't understand the opcode yet */ |
928 | + x_client_send_error (client, BadImplementation, opcode, 0); |
929 | + break; |
930 | + } |
931 | + |
932 | + client->priv->sequence_number++; |
933 | } |
934 | } |
935 | |
936 | |
937 | === modified file 'tests/src/x-server.h' |
938 | --- tests/src/x-server.h 2012-02-02 07:09:27 +0000 |
939 | +++ tests/src/x-server.h 2012-02-07 19:30:57 +0000 |
940 | @@ -106,6 +106,8 @@ |
941 | |
942 | void x_client_send_success (XClient *client); |
943 | |
944 | +void x_client_send_error (XClient *client, int type, int major, int minor); |
945 | + |
946 | void x_client_disconnect (XClient *client); |
947 | |
948 | G_END_DECLS |
949 | |
950 | === added file 'tests/test-default-keyboard-layout' |
951 | --- tests/test-default-keyboard-layout 1970-01-01 00:00:00 +0000 |
952 | +++ tests/test-default-keyboard-layout 2012-02-07 19:30:57 +0000 |
953 | @@ -0,0 +1,2 @@ |
954 | +#!/bin/sh |
955 | +./src/dbus-env ./src/test-runner default-keyboard-layout test-gobject-greeter |
956 | |
957 | === added file 'tests/test-keyboard-variants' |
958 | --- tests/test-keyboard-variants 1970-01-01 00:00:00 +0000 |
959 | +++ tests/test-keyboard-variants 2012-02-07 19:30:57 +0000 |
960 | @@ -0,0 +1,2 @@ |
961 | +#!/bin/sh |
962 | +./src/dbus-env ./src/test-runner keyboard-variants test-gobject-greeter |
Seems to be some merge conflicts (see script files)?
Apart from that looks great, loving the regression test work. :)