Merge lp:~mterry/lightdm/keyboards into lp:lightdm

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
Reviewer Review Type Date Requested Status
Robert Ancell Needs Fixing
Review via email: mp+91907@code.launchpad.net

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.
Revision history for this message
Robert Ancell (robert-ancell) wrote :

Seems to be some merge conflicts (see script files)?

Apart from that looks great, loving the regression test work. :)

review: Needs Fixing

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

Subscribers

People subscribed via source and target branches