Merge lp:~kalgasnik/lightdm-gtk-greeter/alternative_layouts_indicator into lp:~lightdm-gtk-greeter-team/lightdm-gtk-greeter/trunk

Proposed by Andrew P.
Status: Merged
Merged at revision: 286
Proposed branch: lp:~kalgasnik/lightdm-gtk-greeter/alternative_layouts_indicator
Merge into: lp:~lightdm-gtk-greeter-team/lightdm-gtk-greeter/trunk
Diff against target: 460 lines (+307/-19)
6 files modified
configure.ac (+9/-0)
src/Makefile.am (+14/-3)
src/lightdm-gtk-greeter-application.css (+4/-0)
src/lightdm-gtk-greeter-fallback.css (+12/-0)
src/lightdm-gtk-greeter.c (+254/-16)
src/lightdm-gtk-greeter.glade (+14/-0)
To merge this branch: bzr merge lp:~kalgasnik/lightdm-gtk-greeter/alternative_layouts_indicator
Reviewer Review Type Date Requested Status
LightDM Gtk+ Greeter Development Team Pending
Review via email: mp+221187@code.launchpad.net

Description of the change

New builtin indicator: layout

Two implementations:
1. Default - using LightDM API
2. "--with-libxklavier" configure option: using xklavier library directly.

CSS:
- application.css: loaded with APPLICATION priority
- fallback.css: loaded with FALLBACK priority of current theme do not have greeter support, with APPLICATION in other case.

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 'configure.ac'
2--- configure.ac 2014-05-04 11:59:11 +0000
3+++ configure.ac 2014-05-28 09:19:24 +0000
4@@ -105,6 +105,15 @@
5 AC_DEFINE([START_INDICATOR_SERVICES], [], [Try to start indicator-services])
6 ])
7
8+AC_ARG_WITH([libxklavier], AS_HELP_STRING([--with-libxklavier], [Use libxklavier to manage layouts (instead of LightDM API)]))
9+
10+AS_IF([test "x$with_libxklavier" = "xyes"],
11+ [
12+ PKG_CHECK_MODULES([LIBXKLAVIER], [libxklavier], [have_xklavier=yes])
13+ AC_DEFINE([HAVE_LIBXKLAVIER], [1], [Define if "libxklavier" is present])
14+ ],
15+ [])
16+
17 dnl ###########################################################################
18 dnl Internationalization
19 dnl ###########################################################################
20
21=== modified file 'src/Makefile.am'
22--- src/Makefile.am 2014-01-29 19:08:35 +0000
23+++ src/Makefile.am 2014-05-28 09:19:24 +0000
24@@ -1,7 +1,9 @@
25 sbin_PROGRAMS = lightdm-gtk-greeter
26
27 lightdm_gtk_greeter_built_sources = \
28- lightdm-gtk-greeter-ui.h
29+ lightdm-gtk-greeter-ui.h \
30+ lightdm-gtk-greeter-css-fallback.h \
31+ lightdm-gtk-greeter-css-application.h
32
33 lightdm_gtk_greeter_SOURCES = \
34 $(lightdm_gtk_greeter_built_sources) \
35@@ -34,13 +36,20 @@
36 $(LIGHTDMGOBJECT_LIBS) \
37 $(LIBX11_LIBS) \
38 $(LIBINDICATOR_LIBS) \
39- $(LIBIDO_LIBS)
40+ $(LIBIDO_LIBS) \
41+ $(LIBXKLAVIER_LIBS)
42
43 if MAINTAINER_MODE
44
45 lightdm-gtk-greeter-ui.h: $(srcdir)/lightdm-gtk-greeter.glade Makefile
46 $(AM_V_GEN) exo-csource --static --strip-comments --strip-content --name=lightdm_gtk_greeter_ui $< >$@
47
48+lightdm-gtk-greeter-css-fallback.h: $(srcdir)/lightdm-gtk-greeter-fallback.css Makefile
49+ $(AM_V_GEN) exo-csource --static --name=lightdm_gtk_greeter_css_fallback $< >$@
50+
51+lightdm-gtk-greeter-css-application.h: $(srcdir)/lightdm-gtk-greeter-application.css Makefile
52+ $(AM_V_GEN) exo-csource --static --name=lightdm_gtk_greeter_css_application $< >$@
53+
54 DISTCLEANFILES = \
55 $(lightdm_gtk_greeter_built_sources)
56
57@@ -50,4 +59,6 @@
58 endif
59
60 EXTRA_DIST = \
61- lightdm-gtk-greeter.glade
62+ lightdm-gtk-greeter.glade \
63+ lightdm-gtk-greeter-fallback.css \
64+ lightdm-gtk-greeter-application.css
65
66=== added file 'src/lightdm-gtk-greeter-application.css'
67--- src/lightdm-gtk-greeter-application.css 1970-01-01 00:00:00 +0000
68+++ src/lightdm-gtk-greeter-application.css 2014-05-28 09:19:24 +0000
69@@ -0,0 +1,4 @@
70+*
71+{
72+ -GtkWidget-window-dragging: false;
73+}
74
75=== added file 'src/lightdm-gtk-greeter-fallback.css'
76--- src/lightdm-gtk-greeter-fallback.css 1970-01-01 00:00:00 +0000
77+++ src/lightdm-gtk-greeter-fallback.css 2014-05-28 09:19:24 +0000
78@@ -0,0 +1,12 @@
79+#layout_menuitem>GtkLabel
80+{
81+ border: 1px solid alpha(@menu_fg_color, 0.8);
82+ border-radius: 0.5em;
83+ padding: 0px 0.25em;
84+ background: alpha(@menu_fg_color, 0.2);
85+}
86+
87+#layout_menuitem
88+{
89+ padding: 1px;
90+}
91
92=== modified file 'src/lightdm-gtk-greeter.c'
93--- src/lightdm-gtk-greeter.c 2014-05-10 00:31:27 +0000
94+++ src/lightdm-gtk-greeter.c 2014-05-28 09:19:24 +0000
95@@ -49,10 +49,19 @@
96 #include "libido/libido.h"
97 #endif
98
99+#ifdef HAVE_LIBXKLAVIER
100+#include <libxklavier/xklavier.h>
101+#endif
102+
103 #include <lightdm.h>
104
105 #include <src/lightdm-gtk-greeter-ui.h>
106
107+#if GTK_CHECK_VERSION (3, 0, 0)
108+#include <src/lightdm-gtk-greeter-css-fallback.h>
109+#include <src/lightdm-gtk-greeter-css-application.h>
110+#endif
111+
112 static LightDMGreeter *greeter;
113 static GKeyFile *state;
114 static gchar *state_filename;
115@@ -65,10 +74,11 @@
116 /* Panel Widgets */
117 static GtkWindow *panel_window;
118 static GtkWidget *clock_label;
119-static GtkWidget *menubar, *power_menuitem, *session_menuitem, *language_menuitem, *a11y_menuitem, *session_badge;
120+static GtkWidget *menubar, *power_menuitem, *session_menuitem, *language_menuitem, *a11y_menuitem,
121+ *layout_menuitem, *session_badge;
122 static GtkWidget *suspend_menuitem, *hibernate_menuitem, *restart_menuitem, *shutdown_menuitem;
123 static GtkWidget *keyboard_menuitem;
124-static GtkMenu *session_menu, *language_menu;
125+static GtkMenu *session_menu, *language_menu, *layout_menu;
126
127 /* Login Window Widgets */
128 static GtkWindow *login_window;
129@@ -135,11 +145,22 @@
130 DimensionPosition x, y;
131 } WindowPosition;
132
133-const WindowPosition CENTERED_WINDOW_POS = { .x = {50, +1, TRUE, 0}, .y = {50, +1, TRUE, 0} };
134-WindowPosition main_window_pos;
135-
136-GdkPixbuf* default_user_pixbuf = NULL;
137-gchar* default_user_icon = "avatar-default";
138+static const WindowPosition CENTERED_WINDOW_POS = { .x = {50, +1, TRUE, 0}, .y = {50, +1, TRUE, 0} };
139+static WindowPosition main_window_pos;
140+
141+static GdkPixbuf* default_user_pixbuf = NULL;
142+static gchar* default_user_icon = "avatar-default";
143+
144+static const gchar *LAYOUT_DATA_LABEL = "layout-label";
145+#ifdef HAVE_LIBXKLAVIER
146+static const gchar *LAYOUT_DATA_GROUP = "layout-group";
147+#else
148+static const gchar *LAYOUT_DATA_NAME = "layout-name";
149+#endif
150+
151+#ifdef HAVE_LIBXKLAVIER
152+static XklEngine *xkl_engine;
153+#endif
154
155 static void
156 pam_message_finalize (PAMConversationMessage *message)
157@@ -408,6 +429,7 @@
158 g_hash_table_insert (builtin_items, "~session", session_menuitem);
159 g_hash_table_insert (builtin_items, "~language", language_menuitem);
160 g_hash_table_insert (builtin_items, "~a11y", a11y_menuitem);
161+ g_hash_table_insert (builtin_items, "~layout", layout_menuitem);
162
163 g_hash_table_iter_init (&iter, builtin_items);
164 while (g_hash_table_iter_next (&iter, NULL, &iter_value))
165@@ -2231,6 +2253,180 @@
166 return GDK_FILTER_CONTINUE;
167 }
168
169+/* Layout functions and callbacks */
170+
171+static void
172+layout_selected_cb(GtkCheckMenuItem *menuitem, gpointer user_data)
173+{
174+ if (gtk_check_menu_item_get_active (menuitem))
175+ {
176+ #ifdef HAVE_LIBXKLAVIER
177+ gint group = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), LAYOUT_DATA_GROUP));
178+ xkl_engine_lock_group (xkl_engine, group);
179+ #else
180+ const gchar *name = g_object_get_data (G_OBJECT (menuitem), LAYOUT_DATA_NAME);
181+ GList *item;
182+ for (item = lightdm_get_layouts (); item; item = g_list_next (item))
183+ {
184+ if (g_strcmp0 (name, lightdm_layout_get_name (item->data)) == 0)
185+ {
186+ lightdm_set_layout (item->data);
187+ gtk_menu_item_set_label (GTK_MENU_ITEM (layout_menuitem),
188+ g_object_get_data (G_OBJECT (menuitem), LAYOUT_DATA_LABEL));
189+ break;
190+ }
191+ }
192+ #endif
193+ }
194+}
195+
196+static void
197+update_layouts_menu (void)
198+{
199+ #ifdef HAVE_LIBXKLAVIER
200+ XklConfigRegistry *registry;
201+ XklConfigRec *config;
202+ XklConfigItem *config_item;
203+ GSList *menu_group = NULL;
204+ gint i;
205+
206+ g_list_free_full (gtk_container_get_children (GTK_CONTAINER (layout_menu)),
207+ (GDestroyNotify)gtk_widget_destroy);
208+
209+ config = xkl_config_rec_new ();
210+ if (!xkl_config_rec_get_from_server (config, xkl_engine))
211+ {
212+ g_object_unref (config);
213+ g_warning ("Failed to get Xkl configuration from server");
214+ return;
215+ }
216+
217+ config_item = xkl_config_item_new ();
218+ registry = xkl_config_registry_get_instance (xkl_engine);
219+ xkl_config_registry_load (registry, FALSE);
220+
221+ for (i = 0; config->layouts[i] != NULL; ++i)
222+ {
223+ const gchar *layout = config->layouts[i] ? config->layouts[i] : "";
224+ const gchar *variant = config->variants[i] ? config->variants[i] : "";
225+ gchar *label = strlen (variant) > 0 ? g_strdup_printf ("%s_%s", layout, variant) : g_strdup (layout);
226+
227+ GtkWidget *menuitem = gtk_radio_menu_item_new (menu_group);
228+ menu_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
229+
230+ g_snprintf (config_item->name, sizeof (config_item->name), "%s", variant);
231+ if (xkl_config_registry_find_variant (registry, layout, config_item))
232+ gtk_menu_item_set_label (GTK_MENU_ITEM (menuitem), config_item->description);
233+ else
234+ {
235+ g_snprintf (config_item->name, sizeof (config_item->name), "%s", layout);
236+ if (xkl_config_registry_find_layout (registry, config_item))
237+ gtk_menu_item_set_label (GTK_MENU_ITEM (menuitem), config_item->description);
238+ else
239+ gtk_menu_item_set_label (GTK_MENU_ITEM (menuitem), label);
240+ }
241+
242+ g_object_set_data_full (G_OBJECT (menuitem), LAYOUT_DATA_LABEL, label, g_free);
243+ g_object_set_data (G_OBJECT (menuitem), LAYOUT_DATA_GROUP, GINT_TO_POINTER (i));
244+
245+ g_signal_connect (G_OBJECT (menuitem), "activate", G_CALLBACK (layout_selected_cb), NULL);
246+ gtk_menu_shell_append (GTK_MENU_SHELL (layout_menu), menuitem);
247+ gtk_widget_show (GTK_WIDGET (menuitem));
248+ }
249+
250+ g_object_unref (registry);
251+ g_object_unref (config_item);
252+ g_object_unref (config);
253+ #else
254+ GSList *menu_group = NULL;
255+ GList *item;
256+
257+ g_list_free_full (gtk_container_get_children (GTK_CONTAINER (layout_menu)),
258+ (GDestroyNotify)gtk_widget_destroy);
259+
260+ for (item = lightdm_get_layouts (); item; item = g_list_next (item))
261+ {
262+ LightDMLayout *layout = item->data;
263+ GtkWidget *menuitem = gtk_radio_menu_item_new (menu_group);
264+ menu_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
265+
266+ g_object_set_data_full (G_OBJECT (menuitem), LAYOUT_DATA_LABEL,
267+ g_strdelimit (g_strdup (lightdm_layout_get_name (layout)), "\t ", '_'), g_free);
268+ g_object_set_data_full (G_OBJECT (menuitem), LAYOUT_DATA_NAME,
269+ g_strdup (lightdm_layout_get_name (layout)), g_free);
270+
271+ g_signal_connect (G_OBJECT (menuitem), "activate", G_CALLBACK (layout_selected_cb), NULL);
272+ gtk_menu_item_set_label (GTK_MENU_ITEM (menuitem), lightdm_layout_get_description (layout));
273+ gtk_menu_shell_append (GTK_MENU_SHELL (layout_menu), menuitem);
274+ gtk_widget_show (GTK_WIDGET (menuitem));
275+ }
276+ #endif
277+}
278+
279+static void
280+update_layouts_menu_state (void)
281+{
282+ #ifdef HAVE_LIBXKLAVIER
283+ XklState *state = xkl_engine_get_current_state (xkl_engine);
284+ GList *menu_items = gtk_container_get_children (GTK_CONTAINER (layout_menu));
285+ GtkCheckMenuItem *menu_item = g_list_nth_data (menu_items, state->group);
286+
287+ if (menu_item)
288+ {
289+ gtk_menu_item_set_label (GTK_MENU_ITEM (layout_menuitem),
290+ g_object_get_data (G_OBJECT (menu_item), LAYOUT_DATA_LABEL));
291+ gtk_check_menu_item_set_active(menu_item, TRUE);
292+ }
293+ else
294+ gtk_menu_item_set_label (GTK_MENU_ITEM (layout_menuitem), "??");
295+ g_list_free (menu_items);
296+ #else
297+ LightDMLayout *layout = lightdm_get_layout ();
298+ g_return_if_fail (layout != NULL);
299+
300+ const gchar *name = lightdm_layout_get_name (layout);
301+ GList *menu_items = gtk_container_get_children (GTK_CONTAINER (layout_menu));
302+ GList *menu_iter;
303+ for (menu_iter = menu_items; menu_iter; menu_iter = g_list_next (menu_iter))
304+ {
305+ if (g_strcmp0 (name, g_object_get_data (G_OBJECT (menu_iter->data), LAYOUT_DATA_NAME)) == 0)
306+ {
307+ gtk_check_menu_item_set_active (menu_iter->data, TRUE);
308+ gtk_menu_item_set_label (GTK_MENU_ITEM (layout_menuitem),
309+ g_object_get_data (G_OBJECT (menu_iter->data), LAYOUT_DATA_LABEL));
310+ break;
311+ }
312+ }
313+ g_list_free (menu_items);
314+ #endif
315+}
316+
317+#ifdef HAVE_LIBXKLAVIER
318+static void
319+xkl_state_changed_cb (XklEngine *engine, XklEngineStateChange change, gint group,
320+ gboolean restore, gpointer user_data)
321+{
322+ if (change == GROUP_CHANGED)
323+ update_layouts_menu_state ();
324+}
325+
326+static void
327+xkl_config_changed_cb (XklEngine *engine, gpointer user_data)
328+{
329+ /* tip: xkl_config_rec_get_from_server() return old settings */
330+ update_layouts_menu ();
331+ update_layouts_menu_state ();
332+}
333+
334+static GdkFilterReturn
335+xkl_xevent_filter (GdkXEvent *xev, GdkEvent *event, gpointer data)
336+{
337+ XEvent *xevent = (XEvent *) xev;
338+ xkl_engine_filter_events (xkl_engine, xevent);
339+ return GDK_FILTER_CONTINUE;
340+}
341+#endif
342+
343 int
344 main (int argc, char **argv)
345 {
346@@ -2445,16 +2641,9 @@
347 gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "hostname_label")), lightdm_get_hostname ());
348 session_menu = GTK_MENU(gtk_builder_get_object (builder, "session_menu"));
349 language_menu = GTK_MENU(gtk_builder_get_object (builder, "language_menu"));
350+ layout_menu = GTK_MENU(gtk_builder_get_object (builder, "layout_menu"));
351 clock_label = GTK_WIDGET(gtk_builder_get_object (builder, "clock_label"));
352 menubar = GTK_WIDGET (gtk_builder_get_object (builder, "menubar"));
353- /* Never allow the panel-window to be moved via the menubar */
354-#if GTK_CHECK_VERSION (3, 0, 0)
355- css_provider = gtk_css_provider_new ();
356- gtk_css_provider_load_from_data (css_provider, "* { -GtkWidget-window-dragging: false; }", -1, NULL);
357- gtk_style_context_add_provider (GTK_STYLE_CONTEXT(gtk_widget_get_style_context(GTK_WIDGET(menubar))), GTK_STYLE_PROVIDER (css_provider), 800);
358-#endif
359-
360- keyboard_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "keyboard_menuitem"));
361
362 /* Login window */
363 login_window = GTK_WINDOW (gtk_builder_get_object (builder, "login_window"));
364@@ -2510,6 +2699,8 @@
365 language_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "language_menuitem"));
366 a11y_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "a11y_menuitem"));
367 power_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "power_menuitem"));
368+ layout_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "layout_menuitem"));
369+ keyboard_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "keyboard_menuitem"));
370
371 gtk_accel_map_add_entry ("<Login>/a11y/font", GDK_KEY_F1, 0);
372 gtk_accel_map_add_entry ("<Login>/a11y/contrast", GDK_KEY_F2, 0);
373@@ -2596,7 +2787,7 @@
374 label = g_strdup_printf ("%s - %s", lightdm_language_get_name (language), country);
375 else
376 label = g_strdup (lightdm_language_get_name (language));
377-
378+
379 code = lightdm_language_get_code (language);
380 gchar *modifier = strchr (code, '@');
381 if (modifier != NULL)
382@@ -2653,6 +2844,53 @@
383 g_signal_connect (G_OBJECT (power_menuitem),"activate", G_CALLBACK(power_menu_cb), NULL);
384 }
385
386+ /* Layout menu */
387+ if (gtk_widget_get_visible (layout_menuitem))
388+ {
389+ #ifdef HAVE_LIBXKLAVIER
390+ xkl_engine = xkl_engine_get_instance (XOpenDisplay (NULL));
391+ if (xkl_engine)
392+ {
393+ xkl_engine_start_listen (xkl_engine, XKLL_TRACK_KEYBOARD_STATE);
394+ g_signal_connect (xkl_engine, "X-state-changed",
395+ G_CALLBACK (xkl_state_changed_cb), NULL);
396+ g_signal_connect (xkl_engine, "X-config-changed",
397+ G_CALLBACK (xkl_config_changed_cb), NULL);
398+ gdk_window_add_filter (NULL, (GdkFilterFunc) xkl_xevent_filter, NULL);
399+
400+ /* refresh */
401+ XklConfigRec *config_rec = xkl_config_rec_new ();
402+ if (xkl_config_rec_get_from_server (config_rec, xkl_engine))
403+ xkl_config_rec_activate (config_rec, xkl_engine);
404+ g_object_unref (config_rec);
405+ }
406+ else
407+ {
408+ g_warning ("Failed to get XklEngine instance");
409+ gtk_widget_hide (layout_menuitem);
410+ }
411+ #endif
412+ update_layouts_menu ();
413+ update_layouts_menu_state ();
414+ }
415+
416+ #if GTK_CHECK_VERSION (3, 0, 0)
417+ /* A bit of CSS */
418+ css_provider = gtk_css_provider_new ();
419+ gtk_css_provider_load_from_data (css_provider, lightdm_gtk_greeter_css_application, lightdm_gtk_greeter_css_application_length, NULL);
420+ gtk_style_context_add_provider_for_screen(gdk_screen_get_default (), GTK_STYLE_PROVIDER (css_provider),
421+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
422+ css_provider = gtk_css_provider_new ();
423+ guint fallback_css_priority = GTK_STYLE_PROVIDER_PRIORITY_APPLICATION;
424+ if (gtk_style_context_lookup_color (gtk_widget_get_style_context (GTK_WIDGET (login_window)),
425+ "lightdm-gtk-greeter-override-defaults",
426+ &background_color))
427+ fallback_css_priority = GTK_STYLE_PROVIDER_PRIORITY_FALLBACK;
428+ gtk_css_provider_load_from_data (css_provider, lightdm_gtk_greeter_css_fallback, lightdm_gtk_greeter_css_fallback_length, NULL);
429+ gtk_style_context_add_provider_for_screen(gdk_screen_get_default (), GTK_STYLE_PROVIDER (css_provider),
430+ fallback_css_priority);
431+ #endif
432+
433 /* Users combobox */
434 renderer = gtk_cell_renderer_text_new();
435 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (user_combo), renderer, TRUE);
436
437=== modified file 'src/lightdm-gtk-greeter.glade'
438--- src/lightdm-gtk-greeter.glade 2014-02-23 12:13:12 +0000
439+++ src/lightdm-gtk-greeter.glade 2014-05-28 09:19:24 +0000
440@@ -165,6 +165,20 @@
441 </child>
442 </object>
443 </child>
444+ <child>
445+ <object class="GtkMenuItem" id="layout_menuitem">
446+ <property name="name">layout_menuitem</property>
447+ <property name="visible">True</property>
448+ <property name="can_focus">True</property>
449+ <property name="label">[layout]</property>
450+ <child type="submenu">
451+ <object class="GtkMenu" id="layout_menu">
452+ <property name="visible">True</property>
453+ <property name="can_focus">False</property>
454+ </object>
455+ </child>
456+ </object>
457+ </child>
458 </object>
459 <packing>
460 <property name="expand">False</property>

Subscribers

People subscribed via source and target branches