lightdm-gtk-greeter-team team mailing list archive
-
lightdm-gtk-greeter-team team
-
Mailing list archive
-
Message #00503
[Merge] lp:~kalgasnik/lightdm-gtk-greeter/alternative_layouts_indicator into lp:lightdm-gtk-greeter
Andrew P. has proposed merging lp:~kalgasnik/lightdm-gtk-greeter/alternative_layouts_indicator into lp:lightdm-gtk-greeter.
Requested reviews:
LightDM Gtk+ Greeter Development Team (lightdm-gtk-greeter-team)
For more details, see:
https://code.launchpad.net/~kalgasnik/lightdm-gtk-greeter/alternative_layouts_indicator/+merge/221187
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.
--
https://code.launchpad.net/~kalgasnik/lightdm-gtk-greeter/alternative_layouts_indicator/+merge/221187
Your team LightDM Gtk+ Greeter Development Team is requested to review the proposed merge of lp:~kalgasnik/lightdm-gtk-greeter/alternative_layouts_indicator into lp:lightdm-gtk-greeter.
=== modified file 'configure.ac'
--- configure.ac 2014-05-04 11:59:11 +0000
+++ configure.ac 2014-05-28 09:19:24 +0000
@@ -105,6 +105,15 @@
AC_DEFINE([START_INDICATOR_SERVICES], [], [Try to start indicator-services])
])
+AC_ARG_WITH([libxklavier], AS_HELP_STRING([--with-libxklavier], [Use libxklavier to manage layouts (instead of LightDM API)]))
+
+AS_IF([test "x$with_libxklavier" = "xyes"],
+ [
+ PKG_CHECK_MODULES([LIBXKLAVIER], [libxklavier], [have_xklavier=yes])
+ AC_DEFINE([HAVE_LIBXKLAVIER], [1], [Define if "libxklavier" is present])
+ ],
+ [])
+
dnl ###########################################################################
dnl Internationalization
dnl ###########################################################################
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2014-01-29 19:08:35 +0000
+++ src/Makefile.am 2014-05-28 09:19:24 +0000
@@ -1,7 +1,9 @@
sbin_PROGRAMS = lightdm-gtk-greeter
lightdm_gtk_greeter_built_sources = \
- lightdm-gtk-greeter-ui.h
+ lightdm-gtk-greeter-ui.h \
+ lightdm-gtk-greeter-css-fallback.h \
+ lightdm-gtk-greeter-css-application.h
lightdm_gtk_greeter_SOURCES = \
$(lightdm_gtk_greeter_built_sources) \
@@ -34,13 +36,20 @@
$(LIGHTDMGOBJECT_LIBS) \
$(LIBX11_LIBS) \
$(LIBINDICATOR_LIBS) \
- $(LIBIDO_LIBS)
+ $(LIBIDO_LIBS) \
+ $(LIBXKLAVIER_LIBS)
if MAINTAINER_MODE
lightdm-gtk-greeter-ui.h: $(srcdir)/lightdm-gtk-greeter.glade Makefile
$(AM_V_GEN) exo-csource --static --strip-comments --strip-content --name=lightdm_gtk_greeter_ui $< >$@
+lightdm-gtk-greeter-css-fallback.h: $(srcdir)/lightdm-gtk-greeter-fallback.css Makefile
+ $(AM_V_GEN) exo-csource --static --name=lightdm_gtk_greeter_css_fallback $< >$@
+
+lightdm-gtk-greeter-css-application.h: $(srcdir)/lightdm-gtk-greeter-application.css Makefile
+ $(AM_V_GEN) exo-csource --static --name=lightdm_gtk_greeter_css_application $< >$@
+
DISTCLEANFILES = \
$(lightdm_gtk_greeter_built_sources)
@@ -50,4 +59,6 @@
endif
EXTRA_DIST = \
- lightdm-gtk-greeter.glade
+ lightdm-gtk-greeter.glade \
+ lightdm-gtk-greeter-fallback.css \
+ lightdm-gtk-greeter-application.css
=== added file 'src/lightdm-gtk-greeter-application.css'
--- src/lightdm-gtk-greeter-application.css 1970-01-01 00:00:00 +0000
+++ src/lightdm-gtk-greeter-application.css 2014-05-28 09:19:24 +0000
@@ -0,0 +1,4 @@
+*
+{
+ -GtkWidget-window-dragging: false;
+}
=== added file 'src/lightdm-gtk-greeter-fallback.css'
--- src/lightdm-gtk-greeter-fallback.css 1970-01-01 00:00:00 +0000
+++ src/lightdm-gtk-greeter-fallback.css 2014-05-28 09:19:24 +0000
@@ -0,0 +1,12 @@
+#layout_menuitem>GtkLabel
+{
+ border: 1px solid alpha(@menu_fg_color, 0.8);
+ border-radius: 0.5em;
+ padding: 0px 0.25em;
+ background: alpha(@menu_fg_color, 0.2);
+}
+
+#layout_menuitem
+{
+ padding: 1px;
+}
=== modified file 'src/lightdm-gtk-greeter.c'
--- src/lightdm-gtk-greeter.c 2014-05-10 00:31:27 +0000
+++ src/lightdm-gtk-greeter.c 2014-05-28 09:19:24 +0000
@@ -49,10 +49,19 @@
#include "libido/libido.h"
#endif
+#ifdef HAVE_LIBXKLAVIER
+#include <libxklavier/xklavier.h>
+#endif
+
#include <lightdm.h>
#include <src/lightdm-gtk-greeter-ui.h>
+#if GTK_CHECK_VERSION (3, 0, 0)
+#include <src/lightdm-gtk-greeter-css-fallback.h>
+#include <src/lightdm-gtk-greeter-css-application.h>
+#endif
+
static LightDMGreeter *greeter;
static GKeyFile *state;
static gchar *state_filename;
@@ -65,10 +74,11 @@
/* Panel Widgets */
static GtkWindow *panel_window;
static GtkWidget *clock_label;
-static GtkWidget *menubar, *power_menuitem, *session_menuitem, *language_menuitem, *a11y_menuitem, *session_badge;
+static GtkWidget *menubar, *power_menuitem, *session_menuitem, *language_menuitem, *a11y_menuitem,
+ *layout_menuitem, *session_badge;
static GtkWidget *suspend_menuitem, *hibernate_menuitem, *restart_menuitem, *shutdown_menuitem;
static GtkWidget *keyboard_menuitem;
-static GtkMenu *session_menu, *language_menu;
+static GtkMenu *session_menu, *language_menu, *layout_menu;
/* Login Window Widgets */
static GtkWindow *login_window;
@@ -135,11 +145,22 @@
DimensionPosition x, y;
} WindowPosition;
-const WindowPosition CENTERED_WINDOW_POS = { .x = {50, +1, TRUE, 0}, .y = {50, +1, TRUE, 0} };
-WindowPosition main_window_pos;
-
-GdkPixbuf* default_user_pixbuf = NULL;
-gchar* default_user_icon = "avatar-default";
+static const WindowPosition CENTERED_WINDOW_POS = { .x = {50, +1, TRUE, 0}, .y = {50, +1, TRUE, 0} };
+static WindowPosition main_window_pos;
+
+static GdkPixbuf* default_user_pixbuf = NULL;
+static gchar* default_user_icon = "avatar-default";
+
+static const gchar *LAYOUT_DATA_LABEL = "layout-label";
+#ifdef HAVE_LIBXKLAVIER
+static const gchar *LAYOUT_DATA_GROUP = "layout-group";
+#else
+static const gchar *LAYOUT_DATA_NAME = "layout-name";
+#endif
+
+#ifdef HAVE_LIBXKLAVIER
+static XklEngine *xkl_engine;
+#endif
static void
pam_message_finalize (PAMConversationMessage *message)
@@ -408,6 +429,7 @@
g_hash_table_insert (builtin_items, "~session", session_menuitem);
g_hash_table_insert (builtin_items, "~language", language_menuitem);
g_hash_table_insert (builtin_items, "~a11y", a11y_menuitem);
+ g_hash_table_insert (builtin_items, "~layout", layout_menuitem);
g_hash_table_iter_init (&iter, builtin_items);
while (g_hash_table_iter_next (&iter, NULL, &iter_value))
@@ -2231,6 +2253,180 @@
return GDK_FILTER_CONTINUE;
}
+/* Layout functions and callbacks */
+
+static void
+layout_selected_cb(GtkCheckMenuItem *menuitem, gpointer user_data)
+{
+ if (gtk_check_menu_item_get_active (menuitem))
+ {
+ #ifdef HAVE_LIBXKLAVIER
+ gint group = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), LAYOUT_DATA_GROUP));
+ xkl_engine_lock_group (xkl_engine, group);
+ #else
+ const gchar *name = g_object_get_data (G_OBJECT (menuitem), LAYOUT_DATA_NAME);
+ GList *item;
+ for (item = lightdm_get_layouts (); item; item = g_list_next (item))
+ {
+ if (g_strcmp0 (name, lightdm_layout_get_name (item->data)) == 0)
+ {
+ lightdm_set_layout (item->data);
+ gtk_menu_item_set_label (GTK_MENU_ITEM (layout_menuitem),
+ g_object_get_data (G_OBJECT (menuitem), LAYOUT_DATA_LABEL));
+ break;
+ }
+ }
+ #endif
+ }
+}
+
+static void
+update_layouts_menu (void)
+{
+ #ifdef HAVE_LIBXKLAVIER
+ XklConfigRegistry *registry;
+ XklConfigRec *config;
+ XklConfigItem *config_item;
+ GSList *menu_group = NULL;
+ gint i;
+
+ g_list_free_full (gtk_container_get_children (GTK_CONTAINER (layout_menu)),
+ (GDestroyNotify)gtk_widget_destroy);
+
+ config = xkl_config_rec_new ();
+ if (!xkl_config_rec_get_from_server (config, xkl_engine))
+ {
+ g_object_unref (config);
+ g_warning ("Failed to get Xkl configuration from server");
+ return;
+ }
+
+ config_item = xkl_config_item_new ();
+ registry = xkl_config_registry_get_instance (xkl_engine);
+ xkl_config_registry_load (registry, FALSE);
+
+ for (i = 0; config->layouts[i] != NULL; ++i)
+ {
+ const gchar *layout = config->layouts[i] ? config->layouts[i] : "";
+ const gchar *variant = config->variants[i] ? config->variants[i] : "";
+ gchar *label = strlen (variant) > 0 ? g_strdup_printf ("%s_%s", layout, variant) : g_strdup (layout);
+
+ GtkWidget *menuitem = gtk_radio_menu_item_new (menu_group);
+ menu_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
+
+ g_snprintf (config_item->name, sizeof (config_item->name), "%s", variant);
+ if (xkl_config_registry_find_variant (registry, layout, config_item))
+ gtk_menu_item_set_label (GTK_MENU_ITEM (menuitem), config_item->description);
+ else
+ {
+ g_snprintf (config_item->name, sizeof (config_item->name), "%s", layout);
+ if (xkl_config_registry_find_layout (registry, config_item))
+ gtk_menu_item_set_label (GTK_MENU_ITEM (menuitem), config_item->description);
+ else
+ gtk_menu_item_set_label (GTK_MENU_ITEM (menuitem), label);
+ }
+
+ g_object_set_data_full (G_OBJECT (menuitem), LAYOUT_DATA_LABEL, label, g_free);
+ g_object_set_data (G_OBJECT (menuitem), LAYOUT_DATA_GROUP, GINT_TO_POINTER (i));
+
+ g_signal_connect (G_OBJECT (menuitem), "activate", G_CALLBACK (layout_selected_cb), NULL);
+ gtk_menu_shell_append (GTK_MENU_SHELL (layout_menu), menuitem);
+ gtk_widget_show (GTK_WIDGET (menuitem));
+ }
+
+ g_object_unref (registry);
+ g_object_unref (config_item);
+ g_object_unref (config);
+ #else
+ GSList *menu_group = NULL;
+ GList *item;
+
+ g_list_free_full (gtk_container_get_children (GTK_CONTAINER (layout_menu)),
+ (GDestroyNotify)gtk_widget_destroy);
+
+ for (item = lightdm_get_layouts (); item; item = g_list_next (item))
+ {
+ LightDMLayout *layout = item->data;
+ GtkWidget *menuitem = gtk_radio_menu_item_new (menu_group);
+ menu_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
+
+ g_object_set_data_full (G_OBJECT (menuitem), LAYOUT_DATA_LABEL,
+ g_strdelimit (g_strdup (lightdm_layout_get_name (layout)), "\t ", '_'), g_free);
+ g_object_set_data_full (G_OBJECT (menuitem), LAYOUT_DATA_NAME,
+ g_strdup (lightdm_layout_get_name (layout)), g_free);
+
+ g_signal_connect (G_OBJECT (menuitem), "activate", G_CALLBACK (layout_selected_cb), NULL);
+ gtk_menu_item_set_label (GTK_MENU_ITEM (menuitem), lightdm_layout_get_description (layout));
+ gtk_menu_shell_append (GTK_MENU_SHELL (layout_menu), menuitem);
+ gtk_widget_show (GTK_WIDGET (menuitem));
+ }
+ #endif
+}
+
+static void
+update_layouts_menu_state (void)
+{
+ #ifdef HAVE_LIBXKLAVIER
+ XklState *state = xkl_engine_get_current_state (xkl_engine);
+ GList *menu_items = gtk_container_get_children (GTK_CONTAINER (layout_menu));
+ GtkCheckMenuItem *menu_item = g_list_nth_data (menu_items, state->group);
+
+ if (menu_item)
+ {
+ gtk_menu_item_set_label (GTK_MENU_ITEM (layout_menuitem),
+ g_object_get_data (G_OBJECT (menu_item), LAYOUT_DATA_LABEL));
+ gtk_check_menu_item_set_active(menu_item, TRUE);
+ }
+ else
+ gtk_menu_item_set_label (GTK_MENU_ITEM (layout_menuitem), "??");
+ g_list_free (menu_items);
+ #else
+ LightDMLayout *layout = lightdm_get_layout ();
+ g_return_if_fail (layout != NULL);
+
+ const gchar *name = lightdm_layout_get_name (layout);
+ GList *menu_items = gtk_container_get_children (GTK_CONTAINER (layout_menu));
+ GList *menu_iter;
+ for (menu_iter = menu_items; menu_iter; menu_iter = g_list_next (menu_iter))
+ {
+ if (g_strcmp0 (name, g_object_get_data (G_OBJECT (menu_iter->data), LAYOUT_DATA_NAME)) == 0)
+ {
+ gtk_check_menu_item_set_active (menu_iter->data, TRUE);
+ gtk_menu_item_set_label (GTK_MENU_ITEM (layout_menuitem),
+ g_object_get_data (G_OBJECT (menu_iter->data), LAYOUT_DATA_LABEL));
+ break;
+ }
+ }
+ g_list_free (menu_items);
+ #endif
+}
+
+#ifdef HAVE_LIBXKLAVIER
+static void
+xkl_state_changed_cb (XklEngine *engine, XklEngineStateChange change, gint group,
+ gboolean restore, gpointer user_data)
+{
+ if (change == GROUP_CHANGED)
+ update_layouts_menu_state ();
+}
+
+static void
+xkl_config_changed_cb (XklEngine *engine, gpointer user_data)
+{
+ /* tip: xkl_config_rec_get_from_server() return old settings */
+ update_layouts_menu ();
+ update_layouts_menu_state ();
+}
+
+static GdkFilterReturn
+xkl_xevent_filter (GdkXEvent *xev, GdkEvent *event, gpointer data)
+{
+ XEvent *xevent = (XEvent *) xev;
+ xkl_engine_filter_events (xkl_engine, xevent);
+ return GDK_FILTER_CONTINUE;
+}
+#endif
+
int
main (int argc, char **argv)
{
@@ -2445,16 +2641,9 @@
gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "hostname_label")), lightdm_get_hostname ());
session_menu = GTK_MENU(gtk_builder_get_object (builder, "session_menu"));
language_menu = GTK_MENU(gtk_builder_get_object (builder, "language_menu"));
+ layout_menu = GTK_MENU(gtk_builder_get_object (builder, "layout_menu"));
clock_label = GTK_WIDGET(gtk_builder_get_object (builder, "clock_label"));
menubar = GTK_WIDGET (gtk_builder_get_object (builder, "menubar"));
- /* Never allow the panel-window to be moved via the menubar */
-#if GTK_CHECK_VERSION (3, 0, 0)
- css_provider = gtk_css_provider_new ();
- gtk_css_provider_load_from_data (css_provider, "* { -GtkWidget-window-dragging: false; }", -1, NULL);
- gtk_style_context_add_provider (GTK_STYLE_CONTEXT(gtk_widget_get_style_context(GTK_WIDGET(menubar))), GTK_STYLE_PROVIDER (css_provider), 800);
-#endif
-
- keyboard_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "keyboard_menuitem"));
/* Login window */
login_window = GTK_WINDOW (gtk_builder_get_object (builder, "login_window"));
@@ -2510,6 +2699,8 @@
language_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "language_menuitem"));
a11y_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "a11y_menuitem"));
power_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "power_menuitem"));
+ layout_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "layout_menuitem"));
+ keyboard_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "keyboard_menuitem"));
gtk_accel_map_add_entry ("<Login>/a11y/font", GDK_KEY_F1, 0);
gtk_accel_map_add_entry ("<Login>/a11y/contrast", GDK_KEY_F2, 0);
@@ -2596,7 +2787,7 @@
label = g_strdup_printf ("%s - %s", lightdm_language_get_name (language), country);
else
label = g_strdup (lightdm_language_get_name (language));
-
+
code = lightdm_language_get_code (language);
gchar *modifier = strchr (code, '@');
if (modifier != NULL)
@@ -2653,6 +2844,53 @@
g_signal_connect (G_OBJECT (power_menuitem),"activate", G_CALLBACK(power_menu_cb), NULL);
}
+ /* Layout menu */
+ if (gtk_widget_get_visible (layout_menuitem))
+ {
+ #ifdef HAVE_LIBXKLAVIER
+ xkl_engine = xkl_engine_get_instance (XOpenDisplay (NULL));
+ if (xkl_engine)
+ {
+ xkl_engine_start_listen (xkl_engine, XKLL_TRACK_KEYBOARD_STATE);
+ g_signal_connect (xkl_engine, "X-state-changed",
+ G_CALLBACK (xkl_state_changed_cb), NULL);
+ g_signal_connect (xkl_engine, "X-config-changed",
+ G_CALLBACK (xkl_config_changed_cb), NULL);
+ gdk_window_add_filter (NULL, (GdkFilterFunc) xkl_xevent_filter, NULL);
+
+ /* refresh */
+ XklConfigRec *config_rec = xkl_config_rec_new ();
+ if (xkl_config_rec_get_from_server (config_rec, xkl_engine))
+ xkl_config_rec_activate (config_rec, xkl_engine);
+ g_object_unref (config_rec);
+ }
+ else
+ {
+ g_warning ("Failed to get XklEngine instance");
+ gtk_widget_hide (layout_menuitem);
+ }
+ #endif
+ update_layouts_menu ();
+ update_layouts_menu_state ();
+ }
+
+ #if GTK_CHECK_VERSION (3, 0, 0)
+ /* A bit of CSS */
+ css_provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_data (css_provider, lightdm_gtk_greeter_css_application, lightdm_gtk_greeter_css_application_length, NULL);
+ gtk_style_context_add_provider_for_screen(gdk_screen_get_default (), GTK_STYLE_PROVIDER (css_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ css_provider = gtk_css_provider_new ();
+ guint fallback_css_priority = GTK_STYLE_PROVIDER_PRIORITY_APPLICATION;
+ if (gtk_style_context_lookup_color (gtk_widget_get_style_context (GTK_WIDGET (login_window)),
+ "lightdm-gtk-greeter-override-defaults",
+ &background_color))
+ fallback_css_priority = GTK_STYLE_PROVIDER_PRIORITY_FALLBACK;
+ gtk_css_provider_load_from_data (css_provider, lightdm_gtk_greeter_css_fallback, lightdm_gtk_greeter_css_fallback_length, NULL);
+ gtk_style_context_add_provider_for_screen(gdk_screen_get_default (), GTK_STYLE_PROVIDER (css_provider),
+ fallback_css_priority);
+ #endif
+
/* Users combobox */
renderer = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (user_combo), renderer, TRUE);
=== modified file 'src/lightdm-gtk-greeter.glade'
--- src/lightdm-gtk-greeter.glade 2014-02-23 12:13:12 +0000
+++ src/lightdm-gtk-greeter.glade 2014-05-28 09:19:24 +0000
@@ -165,6 +165,20 @@
</child>
</object>
</child>
+ <child>
+ <object class="GtkMenuItem" id="layout_menuitem">
+ <property name="name">layout_menuitem</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">[layout]</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="layout_menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ </object>
+ </child>
</object>
<packing>
<property name="expand">False</property>
Follow ups