← Back to team overview

lightdm-gtk-greeter-team team mailing list archive

[Merge] lp:~lightdm-gtk-greeter-team/lightdm-gtk-greeter/one-window-layout into lp:lightdm-gtk-greeter

 

Andrew P. has proposed merging lp:~lightdm-gtk-greeter-team/lightdm-gtk-greeter/one-window-layout into lp:lightdm-gtk-greeter.

Requested reviews:
  LightDM Gtk+ Greeter Development Team (lightdm-gtk-greeter-team)

For more details, see:
https://code.launchpad.net/~lightdm-gtk-greeter-team/lightdm-gtk-greeter/one-window-layout/+merge/233644

One-window layout.
Each monitor have own GtkWindow, active monitor window have GtkOverlay as a child.
GtkOverlay contains all greeter controls. GtkEventBox used as subwindow (+ "background" style class for each subwindow).

Changes:
  - GtkOverlay widget name and class - "#screen.lightdm-gtk-greeter"
  - Power dialog: http://imgur.com/2qybtO1
  - Some functions have been rearranged (+ prototypes)
  - Hiding panel if there are no indicators (fixed)
  - New option:
    panel-position = top|bottom ("top" by default)
  - New option:
    keyboard-position = x y[;width height] ("50%,center -0;50% 25%" by default)

Issues:
  - Greybird, Xubuntu 14.04 (and 14.10): http://imgur.com/MQLz3eR
    Must be: http://imgur.com/FG3FeNy
    Reason:
    /usr/share/themes/Greybird/gtk-3.0/gtk-widgets.css: "* { background-color: inherit; }"

-- 
https://code.launchpad.net/~lightdm-gtk-greeter-team/lightdm-gtk-greeter/one-window-layout/+merge/233644
Your team LightDM Gtk+ Greeter Development Team is requested to review the proposed merge of lp:~lightdm-gtk-greeter-team/lightdm-gtk-greeter/one-window-layout into lp:lightdm-gtk-greeter.
=== modified file 'src/greeterbackground.c'
--- src/greeterbackground.c	2014-08-10 12:48:13 +0000
+++ src/greeterbackground.c	2014-09-07 14:49:59 +0000
@@ -105,19 +105,22 @@
 {
     GdkScreen* screen;
     gulong screen_monitors_changed_handler_id;
-    /* one-window-gtk3-only
-    GtkWindow* greeter_widget;
-    */
-    GSList* greeter_windows;
+
+    /* Widget to display on active monitor */
+    GtkWidget* child;
+    /* List of groups <GtkAccelGroup*> for greeter screens windows */
+    GSList* accel_groups;
 
     /* Mapping monitor name <gchar*> to its config <MonitorConfig*> */
     GHashTable* configs;
+
     /* Default config for unlisted monitors */
     MonitorConfig* default_config;
 
 	/* Array of configured monitors for current screen */
     Monitor* monitors;
     gsize monitors_size;
+
 	/* Name => <Monitor*>, "Number" => <Monitor*> */
     GHashTable* monitors_map;
 
@@ -239,9 +242,6 @@
 static gboolean monitor_window_draw_cb              (GtkWidget* widget,
                                                      cairo_t* cr,
                                                      const Monitor* monitor);
-static gboolean monitor_subwindow_draw_cb           (GtkWidget* widget,
-                                                     cairo_t* cr,
-                                                     GreeterBackground* background);
 static gboolean monitor_window_enter_notify_cb      (GtkWidget* widget,
                                                      GdkEventCrossing* event,
                                                      const Monitor* monitor);
@@ -284,7 +284,7 @@
     self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, GREETER_BACKGROUND_TYPE, GreeterBackgroundPrivate);
     self->priv->screen = NULL;
     self->priv->screen_monitors_changed_handler_id = 0;
-    self->priv->greeter_windows = NULL;
+    self->priv->accel_groups = NULL;
 
     self->priv->configs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)monitor_config_free);
     self->priv->default_config = monitor_config_copy(&DEFAULT_MONITOR_CONFIG, NULL);
@@ -303,9 +303,11 @@
 }
 
 GreeterBackground* 
-greeter_background_new(void)
+greeter_background_new(GtkWidget* child)
 {
-	return GREETER_BACKGROUND(g_object_new(greeter_background_get_type(), NULL));
+    GreeterBackground* background = GREETER_BACKGROUND(g_object_new(greeter_background_get_type(), NULL));
+    background->priv->child = child;
+	return background;
 }
 
 void
@@ -487,6 +489,10 @@
         monitor->window_draw_handler_id = g_signal_connect(G_OBJECT(monitor->window), "draw",
                                                            G_CALLBACK(monitor_window_draw_cb),
                                                            monitor);
+        GSList* item;
+        for(item = priv->accel_groups; item != NULL; item = g_slist_next(item))
+            gtk_window_add_accel_group(monitor->window, item->data);
+
         if(priv->follow_cursor)
             g_signal_connect(G_OBJECT(monitor->window), "enter-notify-event",
                              G_CALLBACK(monitor_window_enter_notify_cb), monitor);
@@ -640,6 +646,12 @@
         return;
 
     priv->active_monitor = active;
+
+    GtkWidget* old_parent = gtk_widget_get_parent(priv->child);
+    if(old_parent)
+        gtk_container_remove(GTK_CONTAINER(old_parent), priv->child);
+    gtk_container_add(GTK_CONTAINER(active->window), priv->child);
+
     g_debug("Active monitor changed to: %s #%d", active->name, active->number);
     g_signal_emit(background, background_signals[BACKGROUND_SIGNAL_ACTIVE_MONITOR_CHANGED], 0);
 
@@ -651,19 +663,6 @@
         greeter_background_set_cursor_position(background,
                                                active->geometry.x + active->geometry.width/2,
                                                active->geometry.y + active->geometry.height/2);
-
-    /* Update greeter windows */
-    GSList* iter;
-    for(iter = priv->greeter_windows; iter; iter = g_slist_next(iter))
-    {
-        gtk_window_set_screen(GTK_WINDOW(iter->data), priv->screen);
-        if(gtk_widget_get_visible(GTK_WIDGET(iter->data)))
-        {   /* Toggle window visibility to place window above of any 'background' windows */
-            gtk_widget_hide(GTK_WIDGET(iter->data));
-            gtk_widget_show(GTK_WIDGET(iter->data));
-            gtk_widget_queue_resize(GTK_WIDGET(iter->data));
-        }
-    }
 }
 
 static void
@@ -788,42 +787,6 @@
     greeter_background_connect(background, screen);
 }
 
-void greeter_background_add_subwindow(GreeterBackground* background,
-                                      GtkWindow* window)
-{
-    g_return_if_fail(GREETER_IS_BACKGROUND(background));
-    g_return_if_fail(GTK_IS_WINDOW(window));
-
-    GreeterBackgroundPrivate* priv = background->priv;
-
-    if(!g_slist_find(priv->greeter_windows, window))
-    {
-        priv->greeter_windows = g_slist_prepend(priv->greeter_windows, window);
-        g_signal_connect(G_OBJECT(window), "draw", G_CALLBACK(monitor_subwindow_draw_cb), background);
-    }
-
-    if(priv->screen)
-        gtk_window_set_screen(window, priv->screen);
-}
-
-void greeter_background_remove_subwindow(GreeterBackground* background,
-                                         GtkWindow* window)
-{
-    g_return_if_fail(GREETER_IS_BACKGROUND(background));
-    g_return_if_fail(GTK_IS_WINDOW(window));
-
-    GreeterBackgroundPrivate* priv = background->priv;
-
-    GSList* item = g_slist_find(priv->greeter_windows, window);
-    if(item)
-    {
-        g_object_disconnect(G_OBJECT(window),
-                            "any-signal", G_CALLBACK(monitor_subwindow_draw_cb), background,
-                            NULL);
-        priv->greeter_windows = g_slist_delete_link(priv->greeter_windows, item);
-    }
-}
-
 void
 greeter_background_set_custom_background(GreeterBackground* background,
                                          const gchar* value)
@@ -857,9 +820,6 @@
         g_hash_table_unref(images_cache);
     if(config.type != BACKGROUND_TYPE_INVALID)
         background_config_finalize(&config);
-
-    for(iter = priv->greeter_windows; iter; iter = g_slist_next(iter))
-        gtk_widget_queue_draw(GTK_WIDGET(iter->data));
 }
 
 void
@@ -899,6 +859,25 @@
     return priv->active_monitor ? &priv->active_monitor->geometry : NULL;
 }
 
+void
+greeter_background_add_accel_group(GreeterBackground* background,
+                                   GtkAccelGroup* group)
+{
+    g_return_if_fail(GREETER_IS_BACKGROUND(background));
+    g_return_if_fail(group != NULL);
+    GreeterBackgroundPrivate* priv = background->priv;
+
+    if(priv->monitors)
+    {
+        gint i;
+        for(i = 0; i < priv->monitors_size; ++i)
+            if(priv->monitors[i].window)
+                gtk_window_add_accel_group(priv->monitors[i].window, group);
+    }
+
+    priv->accel_groups = g_slist_append(priv->accel_groups, group);
+}
+
 static gboolean
 background_config_initialize(BackgroundConfig* config,
                              const gchar* value)
@@ -1054,26 +1033,6 @@
 }
 
 static gboolean
-monitor_subwindow_draw_cb(GtkWidget* widget,
-                          cairo_t* cr,
-                          GreeterBackground* background)
-{
-    g_return_val_if_fail(GREETER_IS_BACKGROUND(background), FALSE);
-    if(background->priv->active_monitor)
-    {
-        const GdkRectangle* geometry = &background->priv->active_monitor->geometry;
-        gint x = 0, y = 0;
-        gtk_window_get_position(GTK_WINDOW(widget), &x, &y);
-
-        cairo_save(cr);
-        cairo_translate(cr, geometry->x - x, geometry->y - y);
-        monitor_draw_background(background->priv->active_monitor, cr);
-        cairo_restore(cr);
-    }
-    return FALSE;
-}
-
-static gboolean
 monitor_window_enter_notify_cb(GtkWidget* widget,
                                GdkEventCrossing* event,
                                const Monitor* monitor)

=== modified file 'src/greeterbackground.h'
--- src/greeterbackground.h	2014-07-13 23:29:17 +0000
+++ src/greeterbackground.h	2014-09-07 14:49:59 +0000
@@ -17,7 +17,7 @@
 
 GType greeter_background_get_type(void) G_GNUC_CONST;
 
-GreeterBackground* greeter_background_new           (void);
+GreeterBackground* greeter_background_new           (GtkWidget* child);
 void greeter_background_set_active_monitor_config   (GreeterBackground* background,
                                                      const gchar* value);
 void greeter_background_set_default_config          (GreeterBackground* background,
@@ -34,14 +34,12 @@
 gchar** greeter_background_get_configured_monitors  (GreeterBackground* background);
 void greeter_background_connect                     (GreeterBackground* background,
                                                      GdkScreen* screen);
-void greeter_background_add_subwindow               (GreeterBackground* background,
-                                                     GtkWindow* window);
-void greeter_background_remove_subwindow            (GreeterBackground* background,
-                                                     GtkWindow* window);
 void greeter_background_set_custom_background       (GreeterBackground* background,
                                                      const gchar* path);
 void greeter_background_save_xroot                  (GreeterBackground* background);
 const GdkRectangle* greeter_background_get_active_monitor_geometry(GreeterBackground* background);
+void greeter_background_add_accel_group             (GreeterBackground* background,
+                                                     GtkAccelGroup* group);
 
 G_END_DECLS
 

=== modified file 'src/lightdm-gtk-greeter.c'
--- src/lightdm-gtk-greeter.c	2014-08-10 12:48:13 +0000
+++ src/lightdm-gtk-greeter.c	2014-09-07 14:49:59 +0000
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2010-2011 Robert Ancell.
  * Author: Robert Ancell <robert.ancell@xxxxxxxxxxxxx>
- * 
+ *
  * This program is free software: you can redistribute it and/or modify it under
  * the terms of the GNU General Public License as published by the Free Software
  * Foundation, either version 3 of the License, or (at your option) any later
@@ -53,6 +53,7 @@
 #include "src/lightdm-gtk-greeter-css-fallback.h"
 #include "src/lightdm-gtk-greeter-css-application.h"
 
+
 static LightDMGreeter *greeter;
 
 /* State file */
@@ -60,25 +61,41 @@
 static gchar *state_filename;
 static void save_state_file (void);
 
-/* Login Window Widgets */
-static GtkWindow *login_window;
-static GtkImage *user_image;
-static GtkComboBox *user_combo;
-static GtkEntry *username_entry, *password_entry;
-static GtkLabel *message_label;
-static GtkInfoBar *info_bar;
-static GtkButton *cancel_button, *login_button;
-
-/* Panel Widgets */
-static GtkWindow *panel_window;
-static GtkWidget *menubar;
-static GtkWidget *power_menuitem, *session_menuitem, *language_menuitem, *a11y_menuitem,
-                 *layout_menuitem, *clock_menuitem, *host_menuitem;
-static GtkWidget *suspend_menuitem, *hibernate_menuitem, *restart_menuitem, *shutdown_menuitem;
-static GtkWidget *contrast_menuitem, *font_menuitem, *keyboard_menuitem, *reader_menuitem;
-static GtkWidget *clock_label, *session_badge;
-static GtkMenu *session_menu, *language_menu, *layout_menu;
-
+/* Screen window */
+static GtkOverlay *screen_overlay;
+
+/* Login window */
+static GtkWidget    *login_window;
+static GtkImage     *user_image;
+static GtkComboBox  *user_combo;
+static GtkEntry     *username_entry, *password_entry;
+static GtkLabel     *message_label;
+static GtkInfoBar   *info_bar;
+static GtkButton    *cancel_button, *login_button;
+
+/* Panel */
+static GtkWidget    *panel_window, *menubar;
+static GtkWidget    *power_menuitem, *session_menuitem, *language_menuitem, *a11y_menuitem,
+                    *layout_menuitem, *clock_menuitem, *host_menuitem;
+static GtkWidget    *suspend_menuitem, *hibernate_menuitem, *restart_menuitem, *shutdown_menuitem;
+static GtkWidget    *contrast_menuitem, *font_menuitem, *keyboard_menuitem, *reader_menuitem;
+static GtkWidget    *clock_label, *session_badge;
+static GtkMenu      *session_menu, *language_menu, *layout_menu;
+
+/* Power window */
+static GtkWidget    *power_window;
+static GtkButton    *power_ok_button, *power_cancel_button;
+static GtkLabel     *power_title, *power_text;
+static GtkImage     *power_icon;
+
+static const gchar *POWER_WINDOW_DATA_LOOP = "power-window-loop";           /* <GMainLoop*> */
+static const gchar *POWER_WINDOW_DATA_RESPONSE = "power-window-response";   /* <GtkResponseType> */
+
+static gboolean show_power_prompt (const gchar *action, const gchar* icon, const gchar* title, const gchar* message);
+void power_button_clicked_cb (GtkButton *button, gpointer user_data);
+gboolean power_window_key_press_event_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
+
+/* Handling window position */
 typedef struct
 {
     gint value;
@@ -93,22 +110,40 @@
 typedef struct
 {
     DimensionPosition x, y;
+    /* Flag to use width and height fileds */
+    gboolean use_size;
+    DimensionPosition width, height;
 } WindowPosition;
 
+static WindowPosition* key_file_get_position (GKeyFile *key_file, const gchar *group_name, const gchar *key, const WindowPosition *default_value);
 /* Function translate user defined coordinates to absolute value */
 static gint get_absolute_position (const DimensionPosition *p, gint screen, gint window);
-static const WindowPosition WINDOW_POS_CENTER   = {.x = { 50, +1, TRUE,   0}, .y = { 50, +1, TRUE,   0}};
-static const WindowPosition WINDOW_POS_TOP_LEFT = {.x = {  0, +1, FALSE, -1}, .y = {  0, +1, FALSE, -1}};
-static const WindowPosition ONBOARD_WINDOW_POS  = {.x = { 50, +1, TRUE,   0}, .y = {  0, -1, FALSE, +1}};
-static const WindowPosition ONBOARD_WINDOW_SIZE = {.x = {610,  0, FALSE,  0}, .y = {210,  0, FALSE,  0}};
-static WindowPosition main_window_pos;
-static WindowPosition panel_window_pos;
-
-static gchar *default_font_name, *default_theme_name, *default_icon_theme_name;
+gboolean screen_overlay_get_child_position_cb (GtkWidget *overlay, GtkWidget *widget, GdkRectangle *allocation, gpointer user_data);
+
+static const gchar *WINDOW_DATA_POSITION = "window-position"; /* <WindowPosition*> */
+
+/* Some default positions */
+static const WindowPosition WINDOW_POS_CENTER   = {.x = { 50, +1, TRUE,   0}, .y = { 50, +1, TRUE,   0}, .use_size = FALSE};
+static const WindowPosition KEYBOARD_POSITION   = {.x = { 50, +1, TRUE,   0}, .y = {  0, -1, FALSE, +1}, .use_size = TRUE,
+                                                   .width = {50, 0, TRUE, 0}, .height = {25, 0, TRUE, 0}};
+
+/* Configuration */
+static gboolean key_file_get_boolean_extended (GKeyFile *key_file, const gchar *group_name, const gchar *key, gboolean default_value);
+
+/* Clock */
 static gchar *clock_format;
+static gboolean clock_timeout_thread (void);
+
+/* Message label */
+static gboolean message_label_is_empty (void);
+static void set_message_label (LightDMMessageType type, const gchar *text);
+
+/* User image */
 static GdkPixbuf *default_user_pixbuf = NULL;
 static gchar *default_user_icon = "avatar-default";
+static void set_user_image (const gchar *username);
 
+/* External command (keyboard, reader) */
 typedef struct
 {
     gchar **argv;
@@ -121,32 +156,42 @@
 
 static MenuCommand *menu_command_parse (const gchar *value, GtkWidget *menu_item);
 static MenuCommand *menu_command_parse_extended (const gchar *value, GtkWidget *menu_item,
-                                                       const gchar *xid_supported, const gchar *xid_arg,
-                                                       const WindowPosition *size);
+                                                 const gchar *xid_app, const gchar *xid_arg);
 static gboolean menu_command_run (MenuCommand *command);
 static gboolean menu_command_stop (MenuCommand *command);
-static void command_terminated_cb (GPid pid, gint status, MenuCommand *command);
+static void menu_command_terminated_cb (GPid pid, gint status, MenuCommand *command);
 
 static MenuCommand *a11y_keyboard_command;
 static MenuCommand *a11y_reader_command;
 
 static void a11y_menuitem_toggled_cb (GtkCheckMenuItem *item, const gchar* name);
 
-/* Pending Questions */
-static GSList *pending_questions = NULL;
-
-/* Current choices */
+/* Session */
 static gchar *current_session;
+static gboolean is_valid_session (GList* items, const gchar* session);
+static gchar* get_session (void);
+static void set_session (const gchar *session);
+void session_selected_cb (GtkMenuItem *menuitem, gpointer user_data);
+
+/* Sesion language */
 static gchar *current_language;
+static gchar* get_language (void);
+static void set_language (const gchar *language);
+void language_selected_cb (GtkMenuItem *menuitem, gpointer user_data);
 
 /* Screensaver values */
 static int timeout, interval, prefer_blanking, allow_exposures;
 
+/* Handling monitors backgrounds */
 static GreeterBackground *greeter_background;
 
+/* Authentication state */
 static gboolean cancelling = FALSE, prompted = FALSE;
 static gboolean prompt_active = FALSE, password_prompted = FALSE;
 
+/* Pending questions */
+static GSList *pending_questions = NULL;
+
 typedef struct
 {
     gboolean is_prompt;
@@ -158,18 +203,11 @@
     gchar *text;
 } PAMConversationMessage;
 
-static const gchar *LANGUAGE_DATA_CODE = "language-code";
-static const gchar *SESSION_DATA_KEY = "session-key";
-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
+static void pam_message_finalize (PAMConversationMessage *message);
+static void process_prompts (LightDMGreeter *greeter);
+static void show_prompt_cb (LightDMGreeter *greeter, const gchar *text, LightDMPromptType type);
 
-#ifdef HAVE_LIBXKLAVIER
-static XklEngine *xkl_engine;
-#endif
+/* Panel and indicators */
 
 typedef enum
 {
@@ -181,7 +219,7 @@
 
 static const gchar *PANEL_ITEM_STYLE = "panel-item";
 static const gchar *PANEL_ITEM_STYLE_HOVERED = "panel-item-hovered";
-static const gchar *PANEL_ITEM_STYLES[] = 
+static const gchar *PANEL_ITEM_STYLES[] =
 {
     "panel-item-indicator",
     "panel-item-spacer",
@@ -192,24 +230,62 @@
 static const gchar *PANEL_ITEM_DATA_INDEX = "panel-item-data-index";
 
 #ifdef HAVE_LIBINDICATOR
-static const gchar *INDICATOR_ITEM_DATA_OBJECT    = "indicator-item-data-object";
-static const gchar *INDICATOR_ITEM_DATA_ENTRY     = "indicator-item-data-entry";
-static const gchar *INDICATOR_ITEM_DATA_BOX       = "indicator-item-data-box";
-static const gchar *INDICATOR_DATA_MENUITEMS      = "indicator-data-menuitems";
-#endif
-
-static gboolean
-key_file_get_boolean_extended (GKeyFile *key_file, const gchar *group_name, const gchar *key, gboolean default_value)
-{
-    GError* error = NULL;
-    gboolean result = g_key_file_get_boolean (key_file, group_name, key, &error);
-    if (error)
-    {
-        g_clear_error (&error);
-        return default_value;
-    }
-    return result;
-}
+static const gchar *INDICATOR_ITEM_DATA_OBJECT = "indicator-item-data-object";  /* <IndicatorObject*> */
+static const gchar *INDICATOR_ITEM_DATA_ENTRY  = "indicator-item-data-entry";   /* <IndicatorObjectEntry*> */
+static const gchar *INDICATOR_ITEM_DATA_BOX    = "indicator-item-data-box";     /* <GtkBox*> */
+static const gchar *INDICATOR_DATA_MENUITEMS   = "indicator-data-menuitems";    /* <GHashTable*> */
+#endif
+
+static const gchar *LANGUAGE_DATA_CODE = "language-code";   /* <gchar*> e.g. "de_DE.UTF-8" */
+static const gchar *SESSION_DATA_KEY = "session-key";       /* <gchar*> session name */
+
+/* Layout indicator */
+#ifdef HAVE_LIBXKLAVIER
+static XklEngine *xkl_engine;
+static const gchar *LAYOUT_DATA_GROUP = "layout-group";     /* <gchar*> */
+#else
+static const gchar *LAYOUT_DATA_NAME = "layout-name";       /* <gchar*> */
+#endif
+static const gchar *LAYOUT_DATA_LABEL = "layout-label";     /* <gchar*> e.g. "English (US)" */
+
+static gboolean panel_item_enter_notify_cb (GtkWidget *widget, GdkEvent *event, gpointer enter);
+static void panel_add_item (GtkWidget *widget, gint index, GreeterPanelItemType item_type);
+static gboolean menu_item_accel_closure_cb (GtkAccelGroup *accel_group, GObject *acceleratable, guint keyval, GdkModifierType modifier, gpointer data);
+/* Maybe unnecessary (in future) trick to enable accelerators for hidden/detached menu items */
+static void reassign_menu_item_accel (GtkWidget *item);
+
+#ifdef START_INDICATOR_SERVICES
+static void init_indicators (GKeyFile* config, GPid* indicator_pid, GPid* spi_pid);
+#else
+static void init_indicators (GKeyFile* config);
+#endif
+
+static void layout_selected_cb (GtkCheckMenuItem *menuitem, gpointer user_data);
+static void update_layouts_menu (void);
+static void update_layouts_menu_state (void);
+#ifdef HAVE_LIBXKLAVIER
+static void xkl_state_changed_cb (XklEngine *engine, XklEngineStateChange change, gint group, gboolean restore, gpointer user_data);
+static void xkl_config_changed_cb (XklEngine *engine, gpointer user_data);
+static GdkFilterReturn xkl_xevent_filter (GdkXEvent *xev, GdkEvent *event, gpointer  data);
+#endif
+
+/* a11y indicator */
+static gchar *default_font_name,
+             *default_theme_name,
+             *default_icon_theme_name;
+void a11y_font_cb (GtkCheckMenuItem *item);
+void a11y_contrast_cb (GtkCheckMenuItem *item);
+void a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data);
+void a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data);
+
+/* Power indciator */
+static void power_menu_cb (GtkWidget *menuitem, gpointer userdata);
+void suspend_cb (GtkWidget *widget, LightDMGreeter *greeter);
+void hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter);
+void restart_cb (GtkWidget *widget, LightDMGreeter *greeter);
+void shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter);
+
+/* State file */
 
 static void
 save_state_file (void)
@@ -236,18 +312,341 @@
     }
 }
 
+/* Power window */
+
+static gboolean
+show_power_prompt (const gchar *action, const gchar* icon, const gchar* title, const gchar* message)
+{
+    gchar *new_message = NULL;
+
+    /* Check if there are still users logged in, count them and if so, display a warning */
+    gint logged_in_users = 0;
+    GList *items = lightdm_user_list_get_users (lightdm_user_list_get_instance ());
+    GList *item;
+    for (item = items; item; item = item->next)
+    {
+        LightDMUser *user = item->data;
+        if (lightdm_user_get_logged_in (user))
+            logged_in_users++;
+    }
+
+    if (logged_in_users > 0)
+    {
+        gchar *warning = g_strdup_printf (ngettext ("Warning: There is still %d user logged in.",
+                                                    "Warning: There are still %d users logged in.",
+                                                    logged_in_users),
+                                          logged_in_users);
+        message = new_message = g_markup_printf_escaped ("<b>%s</b>\n%s", warning, message);
+        g_free (warning);
+    }
+
+    gchar *dialog_name = g_strconcat (action, "_dialog", NULL);
+    gchar *button_name = g_strconcat (action, "_button", NULL);
+
+    gtk_widget_set_name (power_window, dialog_name);
+    gtk_widget_set_name (GTK_WIDGET (power_ok_button), button_name);
+    gtk_button_set_label (power_ok_button, title);
+    gtk_label_set_label (power_title, title);
+    gtk_label_set_markup (power_text, message);
+    gtk_image_set_from_icon_name (power_icon, icon, GTK_ICON_SIZE_DIALOG);
+
+    g_free (button_name);
+    g_free (dialog_name);
+    g_free (new_message);
+
+    GMainLoop *loop = g_main_loop_new (NULL, FALSE);
+    g_object_set_data (G_OBJECT (power_window), POWER_WINDOW_DATA_LOOP, loop);
+    g_object_set_data (G_OBJECT (power_window), POWER_WINDOW_DATA_RESPONSE, GINT_TO_POINTER (GTK_RESPONSE_CANCEL));
+
+    GtkWidget *focused = gtk_window_get_focus (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (screen_overlay))));
+    gboolean session_enabled = gtk_widget_get_sensitive (session_menuitem);
+    gboolean language_enabled = gtk_widget_get_sensitive (language_menuitem);
+
+    gtk_widget_set_sensitive (power_menuitem, FALSE);
+    gtk_widget_set_sensitive (session_menuitem, FALSE);
+    gtk_widget_set_sensitive (language_menuitem, FALSE);
+    gtk_widget_hide (login_window);
+    gtk_widget_show (power_window);
+    gtk_widget_grab_focus (GTK_WIDGET (power_ok_button));
+
+    g_main_loop_run (loop);
+    GtkResponseType response = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (power_window), POWER_WINDOW_DATA_RESPONSE));
+    g_main_loop_unref (loop);
+
+    gtk_widget_hide (power_window);
+    gtk_widget_show (login_window);
+    gtk_widget_set_sensitive (power_menuitem, TRUE);
+    gtk_widget_set_sensitive (session_menuitem, session_enabled);
+    gtk_widget_set_sensitive (language_menuitem, language_enabled);
+
+    if (focused)
+        gtk_widget_grab_focus (focused);
+
+    return response == GTK_RESPONSE_YES;
+}
+
+void
+power_button_clicked_cb (GtkButton *button, gpointer user_data)
+{
+    GMainLoop *loop = g_object_get_data (G_OBJECT (power_window), POWER_WINDOW_DATA_LOOP);
+    if (g_main_loop_is_running (loop))
+        g_main_loop_quit (loop);
+
+    g_object_set_data (G_OBJECT (power_window), POWER_WINDOW_DATA_RESPONSE,
+                       GINT_TO_POINTER (button == power_ok_button ? GTK_RESPONSE_YES : GTK_RESPONSE_CANCEL));
+}
+
+gboolean
+power_window_key_press_event_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
+{
+    if (event->keyval == GDK_KEY_Escape)
+    {
+        power_button_clicked_cb (power_cancel_button, NULL);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/* Handling window position */
+
+static gboolean
+read_position_from_str (const gchar *s, DimensionPosition *x)
+{
+    DimensionPosition p;
+    gchar *end = NULL;
+    gchar **parts = g_strsplit (s, ",", 2);
+    if (parts[0])
+    {
+        p.value = g_ascii_strtoll (parts[0], &end, 10);
+        p.percentage = end && end[0] == '%';
+        p.sign = (p.value < 0 || (p.value == 0 && parts[0][0] == '-')) ? -1 : +1;
+        if (p.value < 0)
+            p.value *= -1;
+        if (g_strcmp0(parts[1], "start") == 0)
+            p.anchor = -1;
+        else if (g_strcmp0(parts[1], "center") == 0)
+            p.anchor = 0;
+        else if (g_strcmp0(parts[1], "end") == 0)
+            p.anchor = +1;
+        else
+            p.anchor = p.sign > 0 ? -1 : +1;
+        *x = p;
+    }
+    else
+        x = NULL;
+    g_strfreev (parts);
+    return x != NULL;
+}
+
+static WindowPosition*
+key_file_get_position (GKeyFile *key_file, const gchar *group_name, const gchar *key, const WindowPosition *default_value)
+{
+    WindowPosition* pos = g_new0 (WindowPosition, 1);
+    gchar *value = g_key_file_get_value (key_file, group_name, key, NULL);
+
+    *pos = *default_value;
+
+    if (value)
+    {
+        gchar *x = value;
+        gchar *y = strchr (value, ' ');
+        if (y)
+            (y++)[0] = '\0';
+
+        if (read_position_from_str (x, &pos->x))
+            /* If there is no y-part then y = x */
+            if (!y || !read_position_from_str (y, &pos->y))
+                pos->y = pos->x;
+
+        gchar *size_delim = strchr (y ? y : x, ';');
+        if (size_delim)
+        {
+            gchar *x = size_delim + 1;
+            if (read_position_from_str (x, &pos->width))
+            {
+                y = strchr (x, ' ');
+                if (y)
+                    (y++)[0] = '\0';
+                if (!y || !read_position_from_str (y, &pos->height))
+                    if (!default_value->use_size)
+                        pos->height = pos->width;
+                pos->use_size = TRUE;
+            }
+        }
+
+        g_free (value);
+    }
+
+    return pos;
+}
+
+static gint
+get_absolute_position (const DimensionPosition *p, gint screen, gint window)
+{
+    gint x = p->percentage ? (screen*p->value)/100 : p->value;
+    x = p->sign < 0 ? screen - x : x;
+    if (p->anchor > 0)
+        x -= window;
+    else if (p->anchor == 0)
+        x -= window/2;
+
+    if (x < 0)                     /* Offscreen: left/top */
+        return 0;
+    else if (x + window > screen)  /* Offscreen: right/bottom */
+        return screen - window;
+    else
+        return x;
+}
+
+gboolean
+screen_overlay_get_child_position_cb (GtkWidget *overlay, GtkWidget *widget, GdkRectangle *allocation, gpointer user_data)
+{
+    const WindowPosition *pos = g_object_get_data (G_OBJECT (widget), WINDOW_DATA_POSITION);
+    if (!pos)
+        return FALSE;
+
+    gint screen_width = gtk_widget_get_allocated_width (overlay);
+    gint screen_height = gtk_widget_get_allocated_height (overlay);
+
+    if (pos->use_size)
+    {
+        allocation->width = get_absolute_position (&pos->width, screen_width, 0);
+        allocation->height = get_absolute_position (&pos->height, screen_height, 0);
+    }
+    else
+    {
+        gtk_widget_get_preferred_width (widget, NULL, &allocation->width);
+        gtk_widget_get_preferred_height (widget, NULL, &allocation->height);
+    }
+
+    allocation->x = get_absolute_position (&pos->x, screen_width, allocation->width);
+    allocation->y = get_absolute_position (&pos->y, screen_height, allocation->height);
+
+    /* Do not overlap panel window */
+    gint panel_height = gtk_widget_get_allocated_height (panel_window);
+    if (panel_height && gtk_widget_get_visible (panel_window))
+    {
+        GtkAlign valign = gtk_widget_get_valign (panel_window);
+        if (valign == GTK_ALIGN_START && allocation->y < panel_height)
+            allocation->y = panel_height;
+        else if (valign == GTK_ALIGN_END && screen_height - allocation->y - allocation->height < panel_height)
+            allocation->y = screen_height - allocation->height - panel_height;
+    }
+
+    return TRUE;
+}
+
+/* Configuration */
+
+static gboolean
+key_file_get_boolean_extended (GKeyFile *key_file, const gchar *group_name, const gchar *key, gboolean default_value)
+{
+    GError* error = NULL;
+    gboolean result = g_key_file_get_boolean (key_file, group_name, key, &error);
+    if (error)
+    {
+        g_clear_error (&error);
+        return default_value;
+    }
+    return result;
+}
+
+/* Clock */
+
+static gboolean
+clock_timeout_thread (void)
+{
+    time_t rawtime;
+    struct tm * timeinfo;
+    gchar time_str[50];
+    gchar *markup;
+
+    time (&rawtime);
+    timeinfo = localtime (&rawtime);
+
+    strftime (time_str, 50, clock_format, timeinfo);
+    markup = g_markup_printf_escaped ("<b>%s</b>", time_str);
+    if (g_strcmp0 (markup, gtk_label_get_label (GTK_LABEL (clock_label))) != 0)
+        gtk_label_set_markup (GTK_LABEL (clock_label), markup);
+    g_free (markup);
+
+    return TRUE;
+}
+
+/* Message label */
+
+static gboolean
+message_label_is_empty (void)
+{
+    return gtk_label_get_text (message_label)[0] == '\0';
+}
+
+static void
+set_message_label (LightDMMessageType type, const gchar *text)
+{
+    if (type == LIGHTDM_MESSAGE_TYPE_INFO)
+        gtk_info_bar_set_message_type (info_bar, GTK_MESSAGE_INFO);
+    else
+        gtk_info_bar_set_message_type (info_bar, GTK_MESSAGE_ERROR);
+    gtk_label_set_text (message_label, text);
+    gtk_widget_set_visible (GTK_WIDGET (info_bar), text && text[0]);
+}
+
+/* User image */
+
+static void
+set_user_image (const gchar *username)
+{
+    const gchar *path;
+    LightDMUser *user = NULL;
+    GdkPixbuf *image = NULL;
+    GError *error = NULL;
+
+    if (!gtk_widget_get_visible (GTK_WIDGET (user_image)))
+        return;
+
+    if (username)
+        user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
+
+    if (user)
+    {
+        path = lightdm_user_get_image (user);
+        if (path)
+        {
+            image = gdk_pixbuf_new_from_file_at_scale (path, 80, 80, FALSE, &error);
+            if (image)
+            {
+                gtk_image_set_from_pixbuf (GTK_IMAGE (user_image), image);
+                g_object_unref (image);
+                return;
+            }
+            else
+            {
+                g_warning ("Failed to load user image: %s", error->message);
+                g_clear_error (&error);
+            }
+        }
+    }
+
+    if (default_user_pixbuf)
+        gtk_image_set_from_pixbuf (GTK_IMAGE (user_image), default_user_pixbuf);
+    else
+        gtk_image_set_from_icon_name (GTK_IMAGE (user_image), default_user_icon, GTK_ICON_SIZE_DIALOG);
+}
+
 /* MenuCommand */
 
 static MenuCommand*
 menu_command_parse (const gchar *value, GtkWidget *menu_item)
 {
-    return menu_command_parse_extended (value, menu_item, NULL, NULL, NULL);
+    return menu_command_parse_extended (value, menu_item, NULL, NULL);
 }
 
 static MenuCommand*
-menu_command_parse_extended (const gchar *value, GtkWidget *menu_item,
-                             const gchar *xid_supported, const gchar *xid_arg,
-                             const WindowPosition *size)
+menu_command_parse_extended (const gchar *value,    /* String to parse */
+                             GtkWidget *menu_item,  /* Menu item to connect */
+                             const gchar *xid_app,  /* Program that have "xembed" mode support */
+                             const gchar *xid_arg)  /* Argument that must be added to command line */
 {
     if (!value)
         return NULL;
@@ -269,7 +668,7 @@
     command->argc = argc;
     command->argv = argv;
 
-    if (g_strcmp0 (argv[0], xid_supported) == 0)
+    if (g_strcmp0 (argv[0], xid_app) == 0)
     {
         gboolean have_xid_arg = FALSE;
         gint i;
@@ -301,15 +700,8 @@
 
         if (have_xid_arg)
         {
-            GdkRectangle screen;
-            command->widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-            gdk_screen_get_monitor_geometry (gdk_screen_get_default (),
-                                             /* must be replaced with background->active_monitor */
-                                             gdk_screen_get_primary_monitor (gdk_screen_get_default ()),
-                                             &screen);
-            gtk_widget_set_size_request (command->widget,
-                                         get_absolute_position (&size->x, screen.width, 0),
-                                         get_absolute_position (&size->y, screen.height, 0));
+            command->widget = gtk_event_box_new ();
+            gtk_overlay_add_overlay (screen_overlay, command->widget);
         }
     }
     return command;
@@ -350,7 +742,7 @@
                 else
                     g_warning ("Failed to get '%s' socket: unrecognized output", command->argv[0]);
 
-                g_free(text);
+                g_free (text);
             }
         }
     }
@@ -360,17 +752,17 @@
                                  G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
                                  NULL, NULL, &command->pid, &error);
         if (spawned)
-            g_child_watch_add (command->pid, (GChildWatchFunc)command_terminated_cb, command);
+            g_child_watch_add (command->pid, (GChildWatchFunc)menu_command_terminated_cb, command);
     }
 
-    if(!spawned)
+    if (!spawned)
     {
         if (error)
             g_warning ("Command spawning error: '%s'", error->message);
         command->pid = 0;
         gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (command->menu_item), FALSE);
     }
-    g_clear_error(&error);
+    g_clear_error (&error);
     return spawned;
 }
 
@@ -393,7 +785,7 @@
 }
 
 static void
-command_terminated_cb (GPid pid, gint status, MenuCommand *command)
+menu_command_terminated_cb (GPid pid, gint status, MenuCommand *command)
 {
     menu_command_stop (command);
 }
@@ -405,6 +797,185 @@
     save_state_file ();
 }
 
+/* Session */
+
+static gboolean
+is_valid_session (GList* items, const gchar* session)
+{
+    for (; items; items = g_list_next (items))
+        if (g_strcmp0 (session, lightdm_session_get_key (items->data)) == 0)
+            return TRUE;
+    return FALSE;
+}
+
+static gchar*
+get_session (void)
+{
+    return g_strdup (current_session);
+}
+
+static void
+set_session (const gchar *session)
+{
+    gchar *last_session = NULL;
+    GList *sessions = lightdm_get_sessions ();
+
+    /* Validation */
+    if (!session || !is_valid_session (sessions, session))
+    {
+        /* previous session */
+        last_session = g_key_file_get_value (state, "greeter", "last-session", NULL);
+        if (last_session && g_strcmp0 (session, last_session) != 0 &&
+            is_valid_session (sessions, last_session))
+            session = last_session;
+        else
+        {
+            /* default */
+            const gchar* default_session = lightdm_greeter_get_default_session_hint (greeter);
+            if (g_strcmp0 (session, default_session) != 0 &&
+                is_valid_session (sessions, default_session))
+                session = default_session;
+            /* first in the sessions list */
+            else if (sessions)
+                session = lightdm_session_get_key (sessions->data);
+            /* give up */
+            else
+                session = NULL;
+        }
+    }
+
+    if (gtk_widget_get_visible (session_menuitem))
+    {
+        GList *menu_iter = NULL;
+        GList *menu_items = gtk_container_get_children (GTK_CONTAINER (session_menu));
+        if (session)
+        {
+            for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next (menu_iter))
+                if (g_strcmp0 (session, g_object_get_data (G_OBJECT (menu_iter->data), SESSION_DATA_KEY)) == 0)
+                {
+                    /* Set menuitem-image to session-badge */
+                    GtkIconTheme *icon_theme = gtk_icon_theme_get_default ();
+                    gchar* session_name = g_ascii_strdown (session, -1);
+                    gchar* icon_name = g_strdup_printf ("%s_badge-symbolic", session_name);
+                    g_free (session_name);
+                    if (gtk_icon_theme_has_icon (icon_theme, icon_name))
+                        gtk_image_set_from_icon_name (GTK_IMAGE (session_badge), icon_name, GTK_ICON_SIZE_MENU);
+                    else
+                        gtk_image_set_from_icon_name (GTK_IMAGE (session_badge), "document-properties-symbolic", GTK_ICON_SIZE_MENU);
+                    g_free (icon_name);
+                    break;
+                }
+        }
+        if (!menu_iter)
+            menu_iter = menu_items;
+
+        if (menu_iter)
+	        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_iter->data), TRUE);
+    }
+
+    g_free (current_session);
+    current_session = g_strdup (session);
+    g_free (last_session);
+}
+
+void
+session_selected_cb (GtkMenuItem *menuitem, gpointer user_data)
+{
+    if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menuitem)))
+       set_session (g_object_get_data (G_OBJECT (menuitem), SESSION_DATA_KEY));
+}
+
+
+/* Session language */
+
+static gchar*
+get_language (void)
+{
+    GList *menu_items, *menu_iter;
+
+    /* if the user manually selected a language, use it */
+    if (current_language)
+        return g_strdup (current_language);
+
+    menu_items = gtk_container_get_children (GTK_CONTAINER (language_menu));
+    for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next (menu_iter))
+    {
+        if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menu_iter->data)))
+            return g_strdup (g_object_get_data (G_OBJECT (menu_iter->data), LANGUAGE_DATA_CODE));
+    }
+
+    return NULL;
+}
+
+static void
+set_language (const gchar *language)
+{
+    const gchar *default_language = NULL;
+    GList *menu_items, *menu_iter;
+
+    if (!gtk_widget_get_visible (language_menuitem))
+    {
+        g_free (current_language);
+        current_language = g_strdup (language);
+        return;
+    }
+
+    menu_items = gtk_container_get_children (GTK_CONTAINER (language_menu));
+
+    if (language)
+    {
+        for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next (menu_iter))
+        {
+            gchar *s;
+            gboolean matched;
+            s = g_strdup (g_object_get_data (G_OBJECT (menu_iter->data), LANGUAGE_DATA_CODE));
+            matched = g_strcmp0 (s, language) == 0;
+            g_free (s);
+            if (matched)
+            {
+                gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_iter->data), TRUE);
+                g_free (current_language);
+                current_language = g_strdup (language);
+                gtk_menu_item_set_label (GTK_MENU_ITEM (language_menuitem),language);
+                return;
+            }
+        }
+    }
+
+    /* If failed to find this language, then try the default */
+    if (lightdm_get_language ())
+    {
+        default_language = lightdm_language_get_code (lightdm_get_language ());
+        gtk_menu_item_set_label (GTK_MENU_ITEM (language_menuitem), default_language);
+    }
+    if (default_language && g_strcmp0 (default_language, language) != 0)
+        set_language (default_language);
+    /* If all else fails, just use the first language from the menu */
+    else
+    {
+        for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next (menu_iter))
+        {
+            if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menu_iter->data)))
+            {
+                gtk_menu_item_set_label (GTK_MENU_ITEM (language_menuitem), g_strdup (g_object_get_data (G_OBJECT (menu_iter->data), LANGUAGE_DATA_CODE)));
+                break;
+            }
+        }
+    }
+}
+
+void
+language_selected_cb (GtkMenuItem *menuitem, gpointer user_data)
+{
+    if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menuitem)))
+    {
+       gchar *language = g_object_get_data (G_OBJECT (menuitem), LANGUAGE_DATA_CODE);
+       set_language (language);
+    }
+}
+
+/* Pending questions */
+
 static void
 pam_message_finalize (PAMConversationMessage *message)
 {
@@ -412,6 +983,79 @@
     g_free (message);
 }
 
+static void
+process_prompts (LightDMGreeter *greeter)
+{
+    if (!pending_questions)
+        return;
+
+    /* always allow the user to change username again */
+    gtk_widget_set_sensitive (GTK_WIDGET (username_entry), TRUE);
+    gtk_widget_set_sensitive (GTK_WIDGET (password_entry), TRUE);
+
+    /* Special case: no user selected from list, so PAM asks us for the user
+     * via a prompt. For that case, use the username field */
+    if (!prompted && pending_questions && !pending_questions->next &&
+        ((PAMConversationMessage *) pending_questions->data)->is_prompt &&
+        ((PAMConversationMessage *) pending_questions->data)->type.prompt != LIGHTDM_PROMPT_TYPE_SECRET &&
+        gtk_widget_get_visible ((GTK_WIDGET (username_entry))) &&
+        lightdm_greeter_get_authentication_user (greeter) == NULL)
+    {
+        prompted = TRUE;
+        prompt_active = TRUE;
+        gtk_widget_grab_focus (GTK_WIDGET (username_entry));
+        gtk_widget_show (GTK_WIDGET (password_entry));
+        return;
+    }
+
+    while (pending_questions)
+    {
+        PAMConversationMessage *message = (PAMConversationMessage *) pending_questions->data;
+        pending_questions = g_slist_remove (pending_questions, (gconstpointer) message);
+
+        if (!message->is_prompt)
+        {
+            /* FIXME: this doesn't show multiple messages, but that was
+             * already the case before. */
+            set_message_label (message->type.message, message->text);
+            continue;
+        }
+
+        gtk_widget_show (GTK_WIDGET (password_entry));
+        gtk_widget_grab_focus (GTK_WIDGET (password_entry));
+        gtk_entry_set_text (password_entry, "");
+        gtk_entry_set_visibility (password_entry, message->type.prompt != LIGHTDM_PROMPT_TYPE_SECRET);
+        if (message_label_is_empty () && password_prompted)
+        {
+            /* No message was provided beforehand and this is not the
+             * first password prompt, so use the prompt as label,
+             * otherwise the user will be completely unclear of what
+             * is going on. Actually, the fact that prompt messages are
+             * not shown is problematic in general, especially if
+             * somebody uses a custom PAM module that wants to ask
+             * something different. */
+            gchar *str = message->text;
+            if (g_str_has_suffix (str, ": "))
+                str = g_strndup (str, strlen (str) - 2);
+            else if (g_str_has_suffix (str, ":"))
+                str = g_strndup (str, strlen (str) - 1);
+            set_message_label (LIGHTDM_MESSAGE_TYPE_INFO, str);
+            if (str != message->text)
+                g_free (str);
+        }
+        gtk_widget_grab_focus (GTK_WIDGET (password_entry));
+        prompted = TRUE;
+        password_prompted = TRUE;
+        prompt_active = TRUE;
+
+        /* If we have more stuff after a prompt, assume that other prompts are pending,
+         * so stop here. */
+        break;
+    }
+}
+
+/* Panel and indicators */
+
 static gboolean
 panel_item_enter_notify_cb (GtkWidget *widget, GdkEvent *event, gpointer enter)
 {
@@ -442,9 +1086,9 @@
     if (item_type == PANEL_ITEM_INDICATOR)
     {
         g_signal_connect (G_OBJECT (widget), "enter-notify-event",
-                          G_CALLBACK (panel_item_enter_notify_cb), GINT_TO_POINTER(TRUE));
+                          G_CALLBACK (panel_item_enter_notify_cb), GINT_TO_POINTER (TRUE));
         g_signal_connect (G_OBJECT (widget), "leave-notify-event",
-                          G_CALLBACK (panel_item_enter_notify_cb), GINT_TO_POINTER(FALSE));
+                          G_CALLBACK (panel_item_enter_notify_cb), GINT_TO_POINTER (FALSE));
     }
 
     gtk_widget_show (widget);
@@ -495,7 +1139,7 @@
     box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
     menuitem = gtk_menu_item_new ();
 
-    gtk_widget_add_events(GTK_WIDGET(menuitem), GDK_SCROLL_MASK);
+    gtk_widget_add_events (GTK_WIDGET (menuitem), GDK_SCROLL_MASK);
 
     g_object_set_data (G_OBJECT (menuitem), INDICATOR_ITEM_DATA_BOX, box);
     g_object_set_data (G_OBJECT (menuitem), INDICATOR_ITEM_DATA_OBJECT, io);
@@ -506,17 +1150,17 @@
     g_signal_connect (G_OBJECT (menuitem), "scroll-event", G_CALLBACK (indicator_entry_scrolled_cb), NULL);
 
     if (entry->image)
-        gtk_box_pack_start (GTK_BOX(box), GTK_WIDGET(entry->image), FALSE, FALSE, 1);
+        gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (entry->image), FALSE, FALSE, 1);
 
     if (entry->label)
-        gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(entry->label), FALSE, FALSE, 1);
+        gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (entry->label), FALSE, FALSE, 1);
 
     if (entry->menu)
         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), GTK_WIDGET (entry->menu));
 
     gtk_container_add (GTK_CONTAINER (menuitem), box);
     gtk_widget_show (box);
-    panel_add_item(menuitem, index, PANEL_ITEM_INDICATOR);
+    panel_add_item (menuitem, index, PANEL_ITEM_INDICATOR);
 
     return menuitem;
 }
@@ -832,170 +1476,286 @@
     }
 }
 
-static gboolean
-is_valid_session (GList* items, const gchar* session)
-{
-    for (; items; items = g_list_next (items))
-        if (g_strcmp0 (session, lightdm_session_get_key (items->data)) == 0)
-            return TRUE;
-    return FALSE;
-}
-
-static gchar *
-get_session (void)
-{
-    return g_strdup (current_session);
-}
-
-static void
-set_session (const gchar *session)
-{
-    gchar *last_session = NULL;
-    GList *sessions = lightdm_get_sessions ();
-
-    /* Validation */
-    if (!session || !is_valid_session (sessions, session))
-    {
-        /* previous session */
-        last_session = g_key_file_get_value (state, "greeter", "last-session", NULL);
-        if (last_session && g_strcmp0 (session, last_session) != 0 &&
-            is_valid_session (sessions, last_session))
-            session = last_session;
+/* Layout indicator */
+
+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
         {
-            /* default */
-            const gchar* default_session = lightdm_greeter_get_default_session_hint (greeter);
-            if (g_strcmp0 (session, default_session) != 0 &&
-                is_valid_session (sessions, default_session))
-                session = default_session;
-            /* first in the sessions list */
-            else if (sessions)
-                session = lightdm_session_get_key (sessions->data);
-            /* give up */
+            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
-                session = NULL;
-        }
-    }
-
-    if (gtk_widget_get_visible (session_menuitem))
-    {
-        GList *menu_iter = NULL;
-        GList *menu_items = gtk_container_get_children (GTK_CONTAINER (session_menu));
-        if (session)
-        {
-            for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
-                if (g_strcmp0 (session, g_object_get_data (G_OBJECT (menu_iter->data), SESSION_DATA_KEY)) == 0)
-                {
-                    /* Set menuitem-image to session-badge */
-                    GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
-                    gchar* session_name = g_ascii_strdown (session, -1);
-                    gchar* icon_name = g_strdup_printf ("%s_badge-symbolic", session_name);
-                    g_free (session_name);
-                    if (gtk_icon_theme_has_icon(icon_theme, icon_name))
-                        gtk_image_set_from_icon_name (GTK_IMAGE(session_badge), icon_name, GTK_ICON_SIZE_MENU);
-                    else
-                        gtk_image_set_from_icon_name (GTK_IMAGE(session_badge), "document-properties-symbolic", GTK_ICON_SIZE_MENU);
-                    g_free (icon_name);
-                    break;
-                }
-        }
-        if (!menu_iter)
-            menu_iter = menu_items;
-
-        if (menu_iter)
-	        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_iter->data), TRUE);
-    }
-
-    g_free (current_session);
-    current_session = g_strdup(session);
-    g_free (last_session);
-}
-
-static gchar *
-get_language (void)
-{
-    GList *menu_items, *menu_iter;
-
-    /* if the user manually selected a language, use it */
-    if (current_language)
-        return g_strdup (current_language);
-
-    menu_items = gtk_container_get_children(GTK_CONTAINER(language_menu));    
-    for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
-    {
-        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_iter->data)))
-            return g_strdup(g_object_get_data (G_OBJECT (menu_iter->data), LANGUAGE_DATA_CODE));
-    }
-
-    return NULL;
-}
-
-static void
-set_language (const gchar *language)
-{
-    const gchar *default_language = NULL;    
-    GList *menu_items, *menu_iter;
-
-    if (!gtk_widget_get_visible (language_menuitem))
-    {
-        g_free (current_language);
-        current_language = g_strdup (language);
-        return;
-    }
-
-    menu_items = gtk_container_get_children(GTK_CONTAINER(language_menu));
-
-    if (language)
-    {
-        for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
-        {
-            gchar *s;
-            gboolean matched;
-            s = g_strdup (g_object_get_data (G_OBJECT (menu_iter->data), LANGUAGE_DATA_CODE));
-            matched = g_strcmp0 (s, language) == 0;
-            g_free (s);
-            if (matched)
-            {
-                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_iter->data), TRUE);
-                g_free (current_language);
-                current_language = g_strdup(language);
-                gtk_menu_item_set_label(GTK_MENU_ITEM(language_menuitem),language);
-                return;
-            }
-        }
-    }
-
-    /* If failed to find this language, then try the default */
-    if (lightdm_get_language ())
-    {
-        default_language = lightdm_language_get_code (lightdm_get_language ());
-        gtk_menu_item_set_label(GTK_MENU_ITEM (language_menuitem), default_language);
-    }
-    if (default_language && g_strcmp0 (default_language, language) != 0)
-        set_language (default_language);
-    /* If all else fails, just use the first language from the menu */
-    else
-    {
-        for (menu_iter = menu_items; menu_iter != NULL; menu_iter = g_list_next(menu_iter))
-        {
-            if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_iter->data)))
-            {
-                gtk_menu_item_set_label (GTK_MENU_ITEM (language_menuitem), g_strdup (g_object_get_data (G_OBJECT (menu_iter->data), LANGUAGE_DATA_CODE)));
-                break;
-            }
-        }
-    }
-}
-
-static void
-set_message_label (LightDMMessageType type, const gchar *text)
-{
-    if (type == LIGHTDM_MESSAGE_TYPE_INFO)
-        gtk_info_bar_set_message_type (info_bar, GTK_MESSAGE_INFO);
-    else
-        gtk_info_bar_set_message_type (info_bar, GTK_MESSAGE_ERROR);
-    gtk_label_set_text (message_label, text);
-    gtk_widget_set_visible (GTK_WIDGET (info_bar), text && text[0]);
+                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
+
+/* a11y indciator */
+
+void
+a11y_font_cb (GtkCheckMenuItem *item)
+{
+    if (gtk_check_menu_item_get_active (item))
+    {
+        gchar *font_name, **tokens;
+        guint length;
+
+        g_object_get (gtk_settings_get_default (), "gtk-font-name", &font_name, NULL);
+        tokens = g_strsplit (font_name, " ", -1);
+        length = g_strv_length (tokens);
+        if (length > 1)
+        {
+            gint size = atoi (tokens[length - 1]);
+            if (size > 0)
+            {
+                g_free (tokens[length - 1]);
+                tokens[length - 1] = g_strdup_printf ("%d", size + 10);
+                g_free (font_name);
+                font_name = g_strjoinv (" ", tokens);
+            }
+        }
+        g_strfreev (tokens);
+
+        g_object_set (gtk_settings_get_default (), "gtk-font-name", font_name, NULL);
+    }
+    else
+    {
+        g_object_set (gtk_settings_get_default (), "gtk-font-name", default_font_name, NULL);
+    }
+}
+
+void
+a11y_contrast_cb (GtkCheckMenuItem *item)
+{
+    if (gtk_check_menu_item_get_active (item))
+    {
+        g_object_set (gtk_settings_get_default (), "gtk-theme-name", "HighContrast", NULL);
+        g_object_set (gtk_settings_get_default (), "gtk-icon-theme-name", "HighContrast", NULL);
+    }
+    else
+    {
+        g_object_set (gtk_settings_get_default (), "gtk-theme-name", default_theme_name, NULL);
+        g_object_set (gtk_settings_get_default (), "gtk-icon-theme-name", default_icon_theme_name, NULL);
+    }
+}
+
+void
+a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data)
+{
+    if (gtk_check_menu_item_get_active (item))
+        menu_command_run (a11y_keyboard_command);
+    else
+        menu_command_stop (a11y_keyboard_command);
+}
+
+void
+a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data)
+{
+    if (gtk_check_menu_item_get_active (item))
+        menu_command_run (a11y_reader_command);
+    else
+        menu_command_stop (a11y_reader_command);
+}
+
+/* Power indicator */
+
+static void
+power_menu_cb (GtkWidget *menuitem, gpointer userdata)
+{
+    gtk_widget_set_sensitive (suspend_menuitem, lightdm_get_can_suspend ());
+    gtk_widget_set_sensitive (hibernate_menuitem, lightdm_get_can_hibernate ());
+    gtk_widget_set_sensitive (restart_menuitem, lightdm_get_can_restart ());
+    gtk_widget_set_sensitive (shutdown_menuitem, lightdm_get_can_shutdown ());
+}
+
+void
+suspend_cb (GtkWidget *widget, LightDMGreeter *greeter)
+{
+    lightdm_suspend (NULL);
+}
+
+void
+hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter)
+{
+    lightdm_hibernate (NULL);
+}
+
+void
+restart_cb (GtkWidget *widget, LightDMGreeter *greeter)
+{
+    if (show_power_prompt ("restart", "view-refresh-symbolic",
+                           _("Restart"),
+                           _("Are you sure you want to close all programs and restart the computer?")))
+        lightdm_restart (NULL);
+}
+
+void
+shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter)
+{
+    if (show_power_prompt ("shutdown", "system-shutdown-symbolic",
+                           _("Shut Down"),
+                           _("Are you sure you want to close all programs and shut down the computer?")))
+        lightdm_shutdown (NULL);
 }
 
 static void
@@ -1032,98 +1792,6 @@
 }
 
 static void
-set_user_image (const gchar *username)
-{
-    const gchar *path;
-    LightDMUser *user = NULL;
-    GdkPixbuf *image = NULL;
-    GError *error = NULL;
-
-    if(!gtk_widget_get_visible (GTK_WIDGET (user_image)))
-        return;
-
-    if (username)
-        user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
-
-    if (user)
-    {
-        path = lightdm_user_get_image (user);
-        if (path)
-        {
-            image = gdk_pixbuf_new_from_file_at_scale (path, 80, 80, FALSE, &error);
-            if (image)
-            {
-                gtk_image_set_from_pixbuf (GTK_IMAGE (user_image), image);
-                g_object_unref (image);
-                return;
-            }
-            else
-            {
-                g_warning ("Failed to load user image: %s", error->message);
-                g_clear_error (&error);
-            }
-        }
-    }
-    
-    if (default_user_pixbuf)
-        gtk_image_set_from_pixbuf (GTK_IMAGE (user_image), default_user_pixbuf);
-    else
-        gtk_image_set_from_icon_name (GTK_IMAGE (user_image), default_user_icon, GTK_ICON_SIZE_DIALOG);
-}
-
-/* Function translate user defined coordinates to absolute value */
-static gint
-get_absolute_position (const DimensionPosition *p, gint screen, gint window)
-{
-    gint x = p->percentage ? (screen*p->value)/100 : p->value;
-    x = p->sign < 0 ? screen - x : x;
-    if (p->anchor > 0)
-        x -= window;
-    else if (p->anchor == 0)
-        x -= window/2;
-
-    if (x < 0)                     /* Offscreen: left/top */
-        return 0;
-    else if (x + window > screen)  /* Offscreen: right/bottom */
-        return screen - window;
-    else
-        return x;
-}
-
-static void
-center_window (GtkWindow *window, GtkAllocation *allocation, const WindowPosition *pos)
-{   
-    const GdkRectangle *monitor_geometry = greeter_background_get_active_monitor_geometry (greeter_background);
-    GtkAllocation *new_allocation = NULL;
-    if (!allocation)
-    {
-        allocation = new_allocation = g_new0 (GtkAllocation, 1);
-        gtk_widget_get_allocation (GTK_WIDGET (window), new_allocation);
-    }
-    if (monitor_geometry)
-        gtk_window_move (window,
-                         monitor_geometry->x + get_absolute_position (&pos->x, monitor_geometry->width, allocation->width),
-                         monitor_geometry->y + get_absolute_position (&pos->y, monitor_geometry->height, allocation->height));
-    g_free (new_allocation);
-}
-
-static void
-active_monitor_changed_cb (GreeterBackground *background, gpointer user_data)
-{
-    const GdkRectangle *monitor_geometry = greeter_background_get_active_monitor_geometry (greeter_background);
-    if (monitor_geometry)
-    {
-        GdkGeometry hints;
-        hints.min_width = monitor_geometry->width;
-        hints.max_width = monitor_geometry->width;
-        hints.min_height = -1;
-        hints.max_height = -1;
-        gtk_window_set_geometry_hints (panel_window, GTK_WIDGET(panel_window),
-                                       &hints, GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
-    }
-}
-
-static void
 start_authentication (const gchar *username)
 {
     cancelling = FALSE;
@@ -1243,38 +1911,6 @@
     g_free (session);
 }
 
-void
-session_selected_cb(GtkMenuItem *menuitem, gpointer user_data);
-G_MODULE_EXPORT
-void
-session_selected_cb(GtkMenuItem *menuitem, gpointer user_data)
-{
-    if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)))
-       set_session(g_object_get_data (G_OBJECT (menuitem), SESSION_DATA_KEY));
-}
-
-void
-language_selected_cb(GtkMenuItem *menuitem, gpointer user_data);
-G_MODULE_EXPORT
-void
-language_selected_cb(GtkMenuItem *menuitem, gpointer user_data)
-{
-    if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)))
-    {
-       gchar *language = g_object_get_data (G_OBJECT (menuitem), LANGUAGE_DATA_CODE);
-       set_language(language);
-    }
-}
-
-static void
-power_menu_cb (GtkWidget *menuitem, gpointer userdata)
-{
-    gtk_widget_set_sensitive (suspend_menuitem, lightdm_get_can_suspend());
-    gtk_widget_set_sensitive (hibernate_menuitem, lightdm_get_can_hibernate());
-    gtk_widget_set_sensitive (restart_menuitem, lightdm_get_can_restart());
-    gtk_widget_set_sensitive (shutdown_menuitem, lightdm_get_can_shutdown());
-}
-
 gboolean
 password_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
 G_MODULE_EXPORT
@@ -1282,7 +1918,7 @@
 password_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
 {
     if ((event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_Down) &&
-        gtk_widget_get_visible(GTK_WIDGET(user_combo)))
+        gtk_widget_get_visible (GTK_WIDGET (user_combo)))
     {
         gboolean available;
         GtkTreeIter iter;
@@ -1318,8 +1954,8 @@
 gboolean
 username_focus_out_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data)
 {
-    if (!g_strcmp0(gtk_entry_get_text(username_entry), "") == 0)
-        start_authentication(gtk_entry_get_text(username_entry));
+    if (!g_strcmp0(gtk_entry_get_text (username_entry), "") == 0)
+        start_authentication (gtk_entry_get_text (username_entry));
     return FALSE;
 }
 
@@ -1355,7 +1991,6 @@
     case GDK_KEY_F9: case GDK_KEY_F10:
     case GDK_KEY_F11: case GDK_KEY_F12:
         gtk_menu_shell_cancel (GTK_MENU_SHELL (menubar));
-        gtk_window_present (login_window);
         return TRUE;
     default:
         return FALSE;
@@ -1400,13 +2035,13 @@
     {
         gtk_widget_show (GTK_WIDGET (username_entry));
         gtk_widget_show (GTK_WIDGET (cancel_button));
-        user_tooltip = g_strdup(_("Other"));
+        user_tooltip = g_strdup (_("Other"));
     }
     else
     {
         gtk_widget_hide (GTK_WIDGET (username_entry));
         gtk_widget_hide (GTK_WIDGET (cancel_button));
-        user_tooltip = g_strdup(username);
+        user_tooltip = g_strdup (username);
     }
 
     /* At this moment we do not have information about possible prompts
@@ -1417,7 +2052,7 @@
 
     if (g_strcmp0 (username, "*guest") == 0)
     {
-        user_tooltip = g_strdup(_("Guest Session"));
+        user_tooltip = g_strdup (_("Guest Session"));
         gtk_widget_hide (GTK_WIDGET (password_entry));
         gtk_widget_grab_focus (GTK_WIDGET (user_combo));
     }
@@ -1454,90 +2089,13 @@
 
         gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &user, -1);
 
-        set_displayed_user(greeter, user);
+        set_displayed_user (greeter, user);
 
         g_free (user);
     }
     set_message_label (LIGHTDM_MESSAGE_TYPE_INFO, NULL);
 }
 
-static const gchar*
-get_message_label (void)
-{
-    return gtk_label_get_text (message_label);
-}
-
-static void
-process_prompts (LightDMGreeter *greeter)
-{
-    if (!pending_questions)
-        return;
-
-    /* always allow the user to change username again */
-    gtk_widget_set_sensitive (GTK_WIDGET (username_entry), TRUE);
-    gtk_widget_set_sensitive (GTK_WIDGET (password_entry), TRUE);
-
-    /* Special case: no user selected from list, so PAM asks us for the user
-     * via a prompt. For that case, use the username field */
-    if (!prompted && pending_questions && !pending_questions->next &&
-        ((PAMConversationMessage *) pending_questions->data)->is_prompt &&
-        ((PAMConversationMessage *) pending_questions->data)->type.prompt != LIGHTDM_PROMPT_TYPE_SECRET &&
-        gtk_widget_get_visible ((GTK_WIDGET (username_entry))) &&
-        lightdm_greeter_get_authentication_user (greeter) == NULL)
-    {
-        prompted = TRUE;
-        prompt_active = TRUE;
-        gtk_widget_grab_focus (GTK_WIDGET (username_entry));
-        gtk_widget_show (GTK_WIDGET (password_entry));
-        return;
-    }
-
-    while (pending_questions)
-    {
-        PAMConversationMessage *message = (PAMConversationMessage *) pending_questions->data;
-        pending_questions = g_slist_remove (pending_questions, (gconstpointer) message);
-
-        if (!message->is_prompt)
-        {
-            /* FIXME: this doesn't show multiple messages, but that was
-             * already the case before. */
-            set_message_label (message->type.message, message->text);
-            continue;
-        }
-
-        gtk_widget_show (GTK_WIDGET (password_entry));
-        gtk_widget_grab_focus (GTK_WIDGET (password_entry));
-        gtk_entry_set_text (password_entry, "");
-        gtk_entry_set_visibility (password_entry, message->type.prompt != LIGHTDM_PROMPT_TYPE_SECRET);
-        if (get_message_label()[0] == 0 && password_prompted)
-        {
-            /* No message was provided beforehand and this is not the
-             * first password prompt, so use the prompt as label,
-             * otherwise the user will be completely unclear of what
-             * is going on. Actually, the fact that prompt messages are
-             * not shown is problematic in general, especially if
-             * somebody uses a custom PAM module that wants to ask
-             * something different. */
-            gchar *str = message->text;
-            if (g_str_has_suffix (str, ": "))
-                str = g_strndup (str, strlen (str) - 2);
-            else if (g_str_has_suffix (str, ":"))
-                str = g_strndup (str, strlen (str) - 1);
-            set_message_label (LIGHTDM_MESSAGE_TYPE_INFO, str);
-            if (str != message->text)
-                g_free (str);
-        }
-        gtk_widget_grab_focus (GTK_WIDGET (password_entry));
-        prompted = TRUE;
-        password_prompted = TRUE;
-        prompt_active = TRUE;
-
-        /* If we have more stuff after a prompt, assume that other prompts are pending,
-         * so stop here. */
-        break;
-    }
-}
-
 void login_cb (GtkWidget *widget);
 G_MODULE_EXPORT
 void
@@ -1545,7 +2103,7 @@
 {
     /* Reset to default screensaver values */
     if (lightdm_greeter_get_lock_hint (greeter))
-        XSetScreenSaver(gdk_x11_display_get_xdisplay(gdk_display_get_default ()), timeout, interval, prefer_blanking, allow_exposures);        
+        XSetScreenSaver (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), timeout, interval, prefer_blanking, allow_exposures);
 
     gtk_widget_set_sensitive (GTK_WIDGET (username_entry), FALSE);
     gtk_widget_set_sensitive (GTK_WIDGET (password_entry), FALSE);
@@ -1659,7 +2217,7 @@
         /* If an error message is already printed we do not print it this statement
          * The error message probably comes from the PAM module that has a better knowledge
          * of the failure. */
-        gboolean have_pam_error = get_message_label()[0] &&
+        gboolean have_pam_error = !message_label_is_empty () &&
                                   gtk_info_bar_get_message_type (info_bar) != GTK_MESSAGE_ERROR;
         if (prompted)
         {
@@ -1676,110 +2234,6 @@
     }
 }
 
-void suspend_cb (GtkWidget *widget, LightDMGreeter *greeter);
-G_MODULE_EXPORT
-void
-suspend_cb (GtkWidget *widget, LightDMGreeter *greeter)
-{
-    lightdm_suspend (NULL);
-}
-
-void hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter);
-G_MODULE_EXPORT
-void
-hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter)
-{
-    lightdm_hibernate (NULL);
-}
-
-static gboolean
-show_power_prompt (const gchar* action, const gchar* message, const gchar* icon,
-                   const gchar* dialog_name, const gchar* button_name)
-{
-    GtkWidget *dialog;
-    GtkWidget *image;
-    GtkWidget *button;
-    gboolean   result;
-    const GList *items, *item;
-    gint logged_in_users = 0;
-    gchar *warning;
-    
-    /* Check if there are still users logged in, count them and if so, display a warning */
-    items = lightdm_user_list_get_users (lightdm_user_list_get_instance ());
-    for (item = items; item; item = item->next)
-    {
-        LightDMUser *user = item->data;
-        if (lightdm_user_get_logged_in (user))
-            logged_in_users++;
-    }
-    if (logged_in_users > 0)
-    {
-        if (logged_in_users > 1)
-            warning = g_strdup_printf (_("Warning: There are still %d users logged in."), logged_in_users);
-        else
-            warning = g_strdup_printf (_("Warning: There is still %d user logged in."), logged_in_users);
-        message = g_markup_printf_escaped ("<b>%s</b>\n%s", warning, message);
-        g_free (warning);
-    }
-
-    /* Prepare the dialog */
-    dialog = gtk_message_dialog_new (NULL,
-                                     GTK_DIALOG_MODAL,
-                                     GTK_MESSAGE_OTHER,
-                                     GTK_BUTTONS_NONE,
-                                     "%s", action);
-    gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", message);        
-    button = gtk_dialog_add_button(GTK_DIALOG (dialog), _("Cancel"), GTK_RESPONSE_CANCEL);
-    gtk_widget_set_name(button, "cancel_button");
-    button = gtk_dialog_add_button(GTK_DIALOG (dialog), action, GTK_RESPONSE_OK);
-    gtk_widget_set_name(button, button_name);
-
-    /* Add the icon */
-    image = gtk_image_new_from_icon_name(icon, GTK_ICON_SIZE_DIALOG);
-    gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(dialog), image);
-
-    /* Make the dialog themeable and attractive */
-    gtk_style_context_add_class (GTK_STYLE_CONTEXT (gtk_widget_get_style_context (GTK_WIDGET (dialog))), "lightdm-gtk-greeter");
-    gtk_widget_set_name (dialog, dialog_name);
-    gtk_container_set_border_width (GTK_CONTAINER (dialog), 18);
-
-    greeter_background_add_subwindow (greeter_background, GTK_WINDOW (dialog));
-
-    /* Hide the login window and show the dialog */
-    gtk_widget_hide (GTK_WIDGET (login_window));
-    gtk_widget_show_all (dialog);
-    center_window (GTK_WINDOW (dialog), NULL, &WINDOW_POS_CENTER);
-
-    result = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK;
-
-    greeter_background_remove_subwindow(greeter_background, GTK_WINDOW (dialog));
-    gtk_widget_destroy (dialog);
-    gtk_widget_show (GTK_WIDGET (login_window));
-    gtk_widget_queue_resize(GTK_WIDGET (login_window));
-
-    return result;
-}
-
-void restart_cb (GtkWidget *widget, LightDMGreeter *greeter);
-G_MODULE_EXPORT
-void
-restart_cb (GtkWidget *widget, LightDMGreeter *greeter)
-{
-    if (show_power_prompt(_("Restart"), _("Are you sure you want to close all programs and restart the computer?"),
-                          "view-refresh-symbolic", "restart_dialog", "restart_button"))
-        lightdm_restart (NULL);
-}
-
-void shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter);
-G_MODULE_EXPORT
-void
-shutdown_cb (GtkWidget *widget, LightDMGreeter *greeter)
-{
-    if (show_power_prompt(_("Shut Down"), _("Are you sure you want to close all programs and shut down the computer?"),
-                          "system-shutdown-symbolic", "shutdown_dialog", "shutdown_button"))
-        lightdm_shutdown (NULL);
-}
-
 static void
 user_added_cb (LightDMUserList *user_list, LightDMUser *user, LightDMGreeter *greeter)
 {
@@ -1856,79 +2310,6 @@
     gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
 }
 
-void a11y_font_cb (GtkCheckMenuItem *item);
-G_MODULE_EXPORT
-void
-a11y_font_cb (GtkCheckMenuItem *item)
-{
-    if (gtk_check_menu_item_get_active (item))
-    {
-        gchar *font_name, **tokens;
-        guint length;
-
-        g_object_get (gtk_settings_get_default (), "gtk-font-name", &font_name, NULL);
-        tokens = g_strsplit (font_name, " ", -1);
-        length = g_strv_length (tokens);
-        if (length > 1)
-        {
-            gint size = atoi (tokens[length - 1]);
-            if (size > 0)
-            {
-                g_free (tokens[length - 1]);
-                tokens[length - 1] = g_strdup_printf ("%d", size + 10);
-                g_free (font_name);
-                font_name = g_strjoinv (" ", tokens);
-            }
-        }
-        g_strfreev (tokens);
-
-        g_object_set (gtk_settings_get_default (), "gtk-font-name", font_name, NULL);
-    }
-    else
-    {
-        g_object_set (gtk_settings_get_default (), "gtk-font-name", default_font_name, NULL);
-    }
-}
-
-void a11y_contrast_cb (GtkCheckMenuItem *item);
-G_MODULE_EXPORT
-void
-a11y_contrast_cb (GtkCheckMenuItem *item)
-{
-    if (gtk_check_menu_item_get_active (item))
-    {
-        g_object_set (gtk_settings_get_default (), "gtk-theme-name", "HighContrast", NULL);
-        g_object_set (gtk_settings_get_default (), "gtk-icon-theme-name", "HighContrast", NULL);
-    }
-    else
-    {
-        g_object_set (gtk_settings_get_default (), "gtk-theme-name", default_theme_name, NULL);
-        g_object_set (gtk_settings_get_default (), "gtk-icon-theme-name", default_icon_theme_name, NULL);
-    }
-}
-
-void a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data);
-G_MODULE_EXPORT
-void
-a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data)
-{
-    if (gtk_check_menu_item_get_active (item))
-        menu_command_run (a11y_keyboard_command);
-    else
-        menu_command_stop (a11y_keyboard_command);
-}
-
-void a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data);
-G_MODULE_EXPORT
-void
-a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data)
-{
-    if (gtk_check_menu_item_get_active (item))
-        menu_command_run (a11y_reader_command);
-    else
-        menu_command_stop (a11y_reader_command);
-}
-
 static void
 load_user_list (void)
 {
@@ -1988,7 +2369,7 @@
     {
         gchar *name;
         gboolean matched = FALSE;
-        
+
         if (selected_user)
         {
             do
@@ -2009,64 +2390,15 @@
             gtk_tree_model_get_iter_first (model, &iter);
             gtk_tree_model_get (model, &iter, 0, &name, -1);
             gtk_combo_box_set_active_iter (user_combo, &iter);
-            set_displayed_user(greeter, name);
-            g_free(name);
+            set_displayed_user (greeter, name);
+            g_free (name);
         }
-        
+
     }
 
     g_free (last_user);
 }
 
-static gboolean
-clock_timeout_thread (void)
-{
-    time_t rawtime;
-    struct tm * timeinfo;
-    gchar time_str[50];
-    gchar *markup;
-    
-    time ( &rawtime );
-    timeinfo = localtime ( &rawtime );
-    
-    strftime(time_str, 50, clock_format, timeinfo);
-    markup = g_markup_printf_escaped("<b>%s</b>", time_str);
-    if (g_strcmp0(markup, gtk_label_get_label (GTK_LABEL (clock_label))) != 0)
-        gtk_label_set_markup (GTK_LABEL (clock_label), markup);
-    g_free(markup);
-    
-    return TRUE;
-}
-
-static gboolean
-read_position_from_str (const gchar *s, DimensionPosition *x)
-{
-    DimensionPosition p;
-    gchar *end = NULL;
-    gchar **parts = g_strsplit(s, ",", 2);
-    if (parts[0])
-    {
-        p.value = g_ascii_strtoll(parts[0], &end, 10);
-        p.percentage = end && end[0] == '%';
-        p.sign = (p.value < 0 || (p.value == 0 && parts[0][0] == '-')) ? -1 : +1;
-        if (p.value < 0)
-            p.value *= -1;
-        if (g_strcmp0(parts[1], "start") == 0)
-            p.anchor = -1;
-        else if (g_strcmp0(parts[1], "center") == 0)
-            p.anchor = 0;
-        else if (g_strcmp0(parts[1], "end") == 0)
-            p.anchor = +1;
-        else
-            p.anchor = p.sign > 0 ? -1 : +1;
-        *x = p;
-    }
-    else
-        x = NULL;
-    g_strfreev (parts);
-    return x != NULL;
-}
-
 static GdkFilterReturn
 focus_upon_map (GdkXEvent *gxevent, GdkEvent *event, gpointer  data)
 {
@@ -2112,180 +2444,6 @@
     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)
 {
@@ -2318,11 +2476,11 @@
     bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
     textdomain (GETTEXT_PACKAGE);
 
-    g_unix_signal_add(SIGTERM, (GSourceFunc)gtk_main_quit, NULL);
+    g_unix_signal_add (SIGTERM, (GSourceFunc)gtk_main_quit, NULL);
 
     /* init gtk */
     gtk_init (&argc, &argv);
-    
+
 #ifdef HAVE_LIBIDO
     ido_init ();
 #endif
@@ -2345,7 +2503,7 @@
     g_clear_error (&error);
 
     greeter = lightdm_greeter_new ();
-    g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL);  
+    g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL);
     g_signal_connect (greeter, "show-message", G_CALLBACK (show_message_cb), NULL);
     g_signal_connect (greeter, "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL);
     g_signal_connect (greeter, "autologin-timer-expired", G_CALLBACK (lightdm_greeter_authenticate_autologin), NULL);
@@ -2362,8 +2520,8 @@
     if (value)
         screensaver_timeout = g_ascii_strtoll (value, &end_ptr, 0);
     g_free (value);
-    
-    display = gdk_x11_display_get_xdisplay(gdk_display_get_default ());
+
+    display = gdk_x11_display_get_xdisplay (gdk_display_get_default ());
     if (lightdm_greeter_get_lock_hint (greeter))
     {
         XGetScreenSaver (display, &timeout, &interval, &prefer_blanking, &allow_exposures);
@@ -2400,10 +2558,10 @@
     }
     else
     {
-        value = g_strdup("Sans 10");
+        value = g_strdup ("Sans 10");
         g_object_set (gtk_settings_get_default (), "gtk-font-name", value, NULL);
     }
-    g_object_get (gtk_settings_get_default (), "gtk-font-name", &default_font_name, NULL);  
+    g_object_get (gtk_settings_get_default (), "gtk-font-name", &default_font_name, NULL);
     value = g_key_file_get_value (config, "greeter", "xft-dpi", NULL);
     if (value)
         g_object_set (gtk_settings_get_default (), "gtk-xft-dpi", (int) (1024 * atof (value)), NULL);
@@ -2429,9 +2587,12 @@
         return EXIT_FAILURE;
     }
     g_clear_error (&error);
-    
+
+    /* Screen window */
+    screen_overlay = GTK_OVERLAY (gtk_builder_get_object (builder, "screen_overlay"));
+
     /* Login window */
-    login_window = GTK_WINDOW (gtk_builder_get_object (builder, "login_window"));
+    login_window = GTK_WIDGET (gtk_builder_get_object (builder, "login_window"));
     user_image = GTK_IMAGE (gtk_builder_get_object (builder, "user_image"));
     user_combo = GTK_COMBO_BOX (gtk_builder_get_object (builder, "user_combobox"));
     username_entry = GTK_ENTRY (gtk_builder_get_object (builder, "username_entry"));
@@ -2441,8 +2602,8 @@
     cancel_button = GTK_BUTTON (gtk_builder_get_object (builder, "cancel_button"));
     login_button = GTK_BUTTON (gtk_builder_get_object (builder, "login_button"));
 
-    /* Panel */
-    panel_window = GTK_WINDOW (gtk_builder_get_object (builder, "panel_window"));
+    /* Panel window*/
+    panel_window = GTK_WIDGET (gtk_builder_get_object (builder, "panel_window"));
     menubar = GTK_WIDGET (gtk_builder_get_object (builder, "menubar"));
     session_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "session_menuitem"));
     session_menu = GTK_MENU (gtk_builder_get_object (builder, "session_menu"));
@@ -2455,10 +2616,22 @@
     reader_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "reader_menuitem"));
     power_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "power_menuitem"));
     layout_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "layout_menuitem"));
-    layout_menu = GTK_MENU(gtk_builder_get_object (builder, "layout_menu"));
+    layout_menu = GTK_MENU (gtk_builder_get_object (builder, "layout_menu"));
     clock_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "clock_menuitem"));
     host_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "host_menuitem"));
 
+    /* Power dialog */
+    power_window = GTK_WIDGET (gtk_builder_get_object (builder, "power_window"));
+    power_ok_button = GTK_BUTTON (gtk_builder_get_object (builder, "power_ok_button"));
+    power_cancel_button = GTK_BUTTON (gtk_builder_get_object (builder, "power_cancel_button"));
+    power_title = GTK_LABEL (gtk_builder_get_object (builder, "power_title"));
+    power_text = GTK_LABEL (gtk_builder_get_object (builder, "power_text"));
+    power_icon = GTK_IMAGE (gtk_builder_get_object (builder, "power_icon"));
+
+    gtk_overlay_add_overlay (screen_overlay, login_window);
+    gtk_overlay_add_overlay (screen_overlay, panel_window);
+    gtk_overlay_add_overlay (screen_overlay, power_window);
+
     gtk_accel_map_add_entry ("<Login>/a11y/font", GDK_KEY_F1, 0);
     gtk_accel_map_add_entry ("<Login>/a11y/contrast", GDK_KEY_F2, 0);
     gtk_accel_map_add_entry ("<Login>/a11y/keyboard", GDK_KEY_F3, 0);
@@ -2471,7 +2644,14 @@
     init_indicators (config);
 #endif
 
-    if (g_key_file_get_boolean(config, "greeter", "hide-user-image", NULL))
+    /* Hide empty panel */
+    GList *menubar_items = gtk_container_get_children (GTK_CONTAINER (menubar));
+    if (!menubar_items)
+        gtk_widget_hide (GTK_WIDGET (panel_window));
+    else
+        g_list_free (menubar_items);
+
+    if (g_key_file_get_boolean (config, "greeter", "hide-user-image", NULL))
     {
         gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (builder, "user_image_border")));
         gtk_widget_hide (GTK_WIDGET (user_image));  /* Hide to mark image is disabled */
@@ -2519,8 +2699,8 @@
             radiomenuitem = gtk_radio_menu_item_new_with_label (sessions, lightdm_session_get_name (session));
             g_object_set_data (G_OBJECT (radiomenuitem), SESSION_DATA_KEY, (gpointer) lightdm_session_get_key (session));
             sessions = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (radiomenuitem));
-            g_signal_connect(G_OBJECT(radiomenuitem), "activate", G_CALLBACK(session_selected_cb), NULL);
-            gtk_menu_shell_append (GTK_MENU_SHELL(session_menu), radiomenuitem);
+            g_signal_connect (G_OBJECT (radiomenuitem), "activate", G_CALLBACK (session_selected_cb), NULL);
+            gtk_menu_shell_append (GTK_MENU_SHELL (session_menu), radiomenuitem);
             gtk_widget_show (GTK_WIDGET (radiomenuitem));
         }
         set_session (NULL);
@@ -2556,8 +2736,8 @@
             radiomenuitem = gtk_radio_menu_item_new_with_label (languages, label);
             g_object_set_data (G_OBJECT (radiomenuitem), LANGUAGE_DATA_CODE, (gpointer) code);
             languages = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (radiomenuitem));
-            g_signal_connect(G_OBJECT(radiomenuitem), "activate", G_CALLBACK(language_selected_cb), NULL);
-            gtk_menu_shell_append (GTK_MENU_SHELL(language_menu), radiomenuitem);
+            g_signal_connect (G_OBJECT (radiomenuitem), "activate", G_CALLBACK (language_selected_cb), NULL);
+            gtk_menu_shell_append (GTK_MENU_SHELL (language_menu), radiomenuitem);
             gtk_widget_show (GTK_WIDGET (radiomenuitem));
         }
         set_language (NULL);
@@ -2566,7 +2746,7 @@
     /* a11y menu */
     if (gtk_widget_get_visible (a11y_menuitem))
     {
-        if (gtk_icon_theme_has_icon(icon_theme, "preferences-desktop-accessibility-symbolic"))
+        if (gtk_icon_theme_has_icon (icon_theme, "preferences-desktop-accessibility-symbolic"))
             image = gtk_image_new_from_icon_name ("preferences-desktop-accessibility-symbolic", GTK_ICON_SIZE_MENU);
         else
             image = gtk_image_new_from_icon_name ("preferences-desktop-accessibility", GTK_ICON_SIZE_MENU);
@@ -2575,13 +2755,10 @@
     }
 
     value = g_key_file_get_value (config, "greeter", "keyboard", NULL);
-    a11y_keyboard_command = menu_command_parse_extended (value, keyboard_menuitem, "onboard", "--xid",
-                                                         &ONBOARD_WINDOW_SIZE);
+    a11y_keyboard_command = menu_command_parse_extended (value, keyboard_menuitem, "onboard", "--xid");
     g_free (value);
 
     gtk_widget_set_visible (keyboard_menuitem, a11y_keyboard_command != NULL);
-    if (a11y_keyboard_command)
-        g_signal_connect (a11y_keyboard_command->widget, "size-allocate", G_CALLBACK (center_window), (gpointer)&ONBOARD_WINDOW_POS);
 
     value = g_key_file_get_value (config, "greeter", "reader", NULL);
     a11y_reader_command = menu_command_parse (value, reader_menuitem);
@@ -2591,7 +2768,7 @@
     /* Power menu */
     if (gtk_widget_get_visible (power_menuitem))
     {
-        if (gtk_icon_theme_has_icon(icon_theme, "system-shutdown-symbolic"))
+        if (gtk_icon_theme_has_icon (icon_theme, "system-shutdown-symbolic"))
             image = gtk_image_new_from_icon_name ("system-shutdown-symbolic", GTK_ICON_SIZE_MENU);
         else
             image = gtk_image_new_from_icon_name ("system-shutdown", GTK_ICON_SIZE_MENU);
@@ -2603,7 +2780,7 @@
         restart_menuitem = (GTK_WIDGET (gtk_builder_get_object (builder, "restart_menuitem")));
         shutdown_menuitem = (GTK_WIDGET (gtk_builder_get_object (builder, "shutdown_menuitem")));
 
-        g_signal_connect (G_OBJECT (power_menuitem),"activate", G_CALLBACK(power_menu_cb), NULL);
+        g_signal_connect (G_OBJECT (power_menuitem),"activate", G_CALLBACK (power_menu_cb), NULL);
     }
 
     /* Layout menu */
@@ -2656,8 +2833,8 @@
     GdkRGBA lightdm_gtk_greeter_override_defaults;
     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);
+    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)),
@@ -2665,11 +2842,11 @@
                                         &lightdm_gtk_greeter_override_defaults))
         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);
+    gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), GTK_STYLE_PROVIDER (css_provider),
+                                               fallback_css_priority);
 
     /* Background */
-    greeter_background = greeter_background_new ();
+    greeter_background = greeter_background_new (GTK_WIDGET (screen_overlay));
 
     value = g_key_file_get_value (config, "greeter", "active-monitor", NULL);
     greeter_background_set_active_monitor_config (greeter_background, value ? value : "#cursor");
@@ -2688,7 +2865,7 @@
     {
         if (!g_str_has_prefix (*config_group, CONFIG_MONITOR_PREFIX))
             continue;
-        const gchar *name = *config_group + sizeof(CONFIG_MONITOR_PREFIX);
+        const gchar *name = *config_group + sizeof (CONFIG_MONITOR_PREFIX);
         while (*name && g_ascii_isspace (*name))
             ++name;
         g_debug ("Monitor configuration found: '%s'", name);
@@ -2708,9 +2885,9 @@
     }
     g_strfreev (config_groups);
 
-    g_signal_connect (G_OBJECT (greeter_background), "active-monitor-changed", G_CALLBACK (active_monitor_changed_cb), NULL);
-    greeter_background_add_subwindow (greeter_background, login_window);
-    greeter_background_add_subwindow (greeter_background, panel_window);
+    greeter_background_add_accel_group (greeter_background, GTK_ACCEL_GROUP (gtk_builder_get_object (builder, "a11y_accelgroup")));
+    greeter_background_add_accel_group (greeter_background, GTK_ACCEL_GROUP (gtk_builder_get_object (builder, "power_accelgroup")));
+
     greeter_background_connect (greeter_background, gdk_screen_get_default ());
 
     if (lightdm_greeter_get_hide_users_hint (greeter))
@@ -2726,34 +2903,19 @@
     }
 
     /* Windows positions */
-    main_window_pos = WINDOW_POS_CENTER;
-    value = g_key_file_get_value (config, "greeter", "position", NULL);
-    if (value)
-    {
-        gchar *x = value;
-        gchar *y = strchr(value, ' ');
-        if (y)
-            (y++)[0] = '\0';
-        
-        if (read_position_from_str (x, &main_window_pos.x))
-            /* If there is no y-part then y = x */
-            if (!y || !read_position_from_str (y, &main_window_pos.y))
-                main_window_pos.y = main_window_pos.x;
-
-        g_free (value);
-    }
-    panel_window_pos = WINDOW_POS_TOP_LEFT;
-
-    gtk_builder_connect_signals(builder, greeter);
-
-    gtk_widget_show (GTK_WIDGET (panel_window));
-    center_window (panel_window, NULL, &panel_window_pos);
-    g_signal_connect (GTK_WIDGET (panel_window), "size-allocate", G_CALLBACK (center_window), &panel_window_pos);
-
-    gtk_widget_show (GTK_WIDGET (login_window));
-    center_window (login_window, NULL, &main_window_pos);
-    g_signal_connect (GTK_WIDGET (login_window), "size-allocate", G_CALLBACK (center_window), &main_window_pos);
-    gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (login_window)), GDK_CURRENT_TIME);
+    g_object_set_data_full (G_OBJECT (login_window), WINDOW_DATA_POSITION,
+                            key_file_get_position (config, "greeter", "position", &WINDOW_POS_CENTER), g_free);
+
+    value = g_key_file_get_value (config, "greeter", "panel-position", NULL);
+    if (g_strcmp0 (value, "bottom") == 0)
+        gtk_widget_set_valign (panel_window, GTK_ALIGN_END);
+    g_free (value);
+
+    if (a11y_keyboard_command)
+        g_object_set_data_full (G_OBJECT (a11y_keyboard_command->widget), WINDOW_DATA_POSITION,
+                                key_file_get_position (config, "greeter", "keyboard-position", &KEYBOARD_POSITION), g_free);
+
+    gtk_builder_connect_signals (builder, greeter);
 
     values = g_key_file_get_string_list (config, "greeter", "a11y-states", NULL, NULL);
     if (values && *values)
@@ -2799,6 +2961,8 @@
     gdk_window_set_events (root_window, gdk_window_get_events (root_window) | GDK_SUBSTRUCTURE_MASK);
     gdk_window_add_filter (root_window, focus_upon_map, NULL);
 
+    gtk_widget_show (GTK_WIDGET (screen_overlay));
+
     gtk_main ();
 
 #ifdef START_INDICATOR_SERVICES

=== modified file 'src/lightdm-gtk-greeter.glade'
--- src/lightdm-gtk-greeter.glade	2014-08-10 12:48:13 +0000
+++ src/lightdm-gtk-greeter.glade	2014-09-07 14:49:59 +0000
@@ -1,30 +1,27 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.16.1 -->
+<!-- Generated with glade 3.18.3 -->
 <interface>
   <requires lib="gtk+" version="3.4"/>
-  <!-- interface-requires greeter_menu_bar 1.0 -->
+  <requires lib="greeter_menu_bar" version="1.0"/>
   <object class="GtkAccelGroup" id="a11y_accelgroup"/>
   <object class="GtkAccelGroup" id="power_accelgroup"/>
-  <object class="GtkWindow" id="panel_window">
+  <object class="GtkEventBox" id="panel_window">
     <property name="name">panel_window</property>
+    <property name="visible">True</property>
     <property name="can_focus">False</property>
-    <property name="decorated">False</property>
-    <accel-groups>
-      <group name="a11y_accelgroup"/>
-      <group name="power_accelgroup"/>
-    </accel-groups>
+    <property name="valign">start</property>
     <child>
       <object class="GreeterMenuBar" id="menubar">
         <property name="name">menubar</property>
         <property name="visible">True</property>
-        <property name="can_focus">True</property>
+        <property name="can_focus">False</property>
         <property name="pack_direction">rtl</property>
         <signal name="key-press-event" handler="menubar_key_press_cb" swapped="no"/>
         <child>
           <object class="GtkMenuItem" id="power_menuitem">
             <property name="name">power_menuitem</property>
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
+            <property name="can_focus">False</property>
             <child type="submenu">
               <object class="GtkMenu" id="power_menu">
                 <property name="visible">True</property>
@@ -72,7 +69,7 @@
           <object class="GtkMenuItem" id="a11y_menuitem">
             <property name="name">a11y_menuitem</property>
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
+            <property name="can_focus">False</property>
             <child type="submenu">
               <object class="GtkMenu" id="a11y_menu">
                 <property name="visible">True</property>
@@ -128,7 +125,7 @@
           <object class="GtkMenuItem" id="language_menuitem">
             <property name="name">language_menuitem</property>
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
+            <property name="can_focus">False</property>
             <property name="label">[language_code]</property>
             <child type="submenu">
               <object class="GtkMenu" id="language_menu">
@@ -142,7 +139,7 @@
           <object class="GtkMenuItem" id="session_menuitem">
             <property name="name">session_menuitem</property>
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
+            <property name="can_focus">False</property>
             <child type="submenu">
               <object class="GtkMenu" id="session_menu">
                 <property name="visible">True</property>
@@ -155,7 +152,7 @@
           <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="can_focus">False</property>
             <property name="label">[layout]</property>
             <child type="submenu">
               <object class="GtkMenu" id="layout_menu">
@@ -180,8 +177,169 @@
       </object>
     </child>
     <style>
+      <class name="background"/>
+      <class name="panel"/>
+    </style>
+  </object>
+  <object class="GtkEventBox" id="power_window">
+    <property name="name">power_window</property>
+    <property name="can_focus">False</property>
+    <property name="halign">center</property>
+    <property name="valign">center</property>
+    <signal name="key-press-event" handler="power_window_key_press_event_cb" swapped="no"/>
+    <child>
+      <object class="GtkBox" id="box3">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkEventBox" id="power_content_frame">
+            <property name="name">content_frame</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkGrid" id="grid2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_left">24</property>
+                <property name="margin_right">24</property>
+                <property name="margin_top">24</property>
+                <property name="margin_bottom">24</property>
+                <property name="row_spacing">6</property>
+                <property name="column_spacing">6</property>
+                <child>
+                  <object class="GtkImage" id="power_icon">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="margin_left">6</property>
+                    <property name="margin_right">12</property>
+                    <property name="margin_top">6</property>
+                    <property name="margin_bottom">6</property>
+                    <property name="stock">gtk-missing-image</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
+                    <property name="height">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="power_title">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">start</property>
+                    <property name="margin_bottom">6</property>
+                    <property name="hexpand">True</property>
+                    <property name="label">[title]</property>
+                    <attributes>
+                      <attribute name="weight" value="semibold"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="power_text">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">start</property>
+                    <property name="hexpand">True</property>
+                    <property name="label">[text]</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEventBox" id="power_buttonbox_frame">
+            <property name="name">buttonbox_frame</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkButtonBox" id="buttonbox1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_left">24</property>
+                <property name="margin_right">24</property>
+                <property name="margin_top">24</property>
+                <property name="margin_bottom">24</property>
+                <property name="spacing">6</property>
+                <property name="layout_style">end</property>
+                <child>
+                  <object class="GtkButton" id="power_cancel_button">
+                    <property name="label" translatable="yes">Cancel</property>
+                    <property name="name">cancel_button</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <signal name="clicked" handler="power_button_clicked_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="power_ok_button">
+                    <property name="label" translatable="yes">OK</property>
+                    <property name="name">power_ok_button</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <signal name="clicked" handler="power_button_clicked_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <style>
+      <class name="background"/>
+    </style>
+  </object>
+  <object class="GtkOverlay" id="screen_overlay">
+    <property name="name">screen</property>
+    <property name="can_focus">False</property>
+    <property name="hexpand">True</property>
+    <property name="vexpand">True</property>
+    <signal name="get-child-position" handler="screen_overlay_get_child_position_cb" swapped="no"/>
+    <child>
+      <object class="GtkBox" id="screen-child">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+    </child>
+    <style>
       <class name="lightdm-gtk-greeter"/>
-      <class name="menubar"/>
     </style>
   </object>
   <object class="GtkListStore" id="user_liststore">
@@ -194,18 +352,15 @@
       <column type="gint"/>
     </columns>
   </object>
-  <object class="GtkWindow" id="login_window">
+  <object class="GtkEventBox" id="login_window">
     <property name="name">login_window</property>
+    <property name="visible">True</property>
     <property name="can_focus">False</property>
-    <property name="resizable">False</property>
-    <property name="decorated">False</property>
-    <accel-groups>
-      <group name="a11y_accelgroup"/>
-      <group name="power_accelgroup"/>
-    </accel-groups>
-    <signal name="key-press-event" handler="login_window_key_press_cb" swapped="no"/>
+    <property name="halign">start</property>
+    <property name="valign">start</property>
     <child>
-      <object class="GtkBox" id="box1">
+      <object class="GtkBox" id="login_box">
+        <property name="name">login_box</property>
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="orientation">vertical</property>
@@ -247,7 +402,6 @@
                   <packing>
                     <property name="left_attach">0</property>
                     <property name="top_attach">0</property>
-                    <property name="width">1</property>
                     <property name="height">3</property>
                   </packing>
                 </child>
@@ -273,8 +427,6 @@
                   <packing>
                     <property name="left_attach">1</property>
                     <property name="top_attach">0</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
                   </packing>
                 </child>
                 <child>
@@ -291,8 +443,6 @@
                   <packing>
                     <property name="left_attach">1</property>
                     <property name="top_attach">1</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
                   </packing>
                 </child>
                 <child>
@@ -314,8 +464,6 @@
                   <packing>
                     <property name="left_attach">1</property>
                     <property name="top_attach">2</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
                   </packing>
                 </child>
               </object>
@@ -336,7 +484,7 @@
             <property name="app_paintable">True</property>
             <property name="can_focus">False</property>
             <child internal-child="action_area">
-              <object class="GtkButtonBox" id="infobar-action_area1">
+              <object class="GtkButtonBox" id="infobar-action_area">
                 <property name="can_focus">False</property>
                 <property name="layout_style">end</property>
                 <child>
@@ -346,11 +494,11 @@
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">False</property>
-                <property name="position">0</property>
+                <property name="position">-1</property>
               </packing>
             </child>
             <child internal-child="content_area">
-              <object class="GtkBox" id="infobar-content_area1">
+              <object class="GtkBox" id="infobar-content_area">
                 <property name="can_focus">False</property>
                 <child>
                   <object class="GtkLabel" id="message_label">
@@ -367,8 +515,8 @@
               </object>
               <packing>
                 <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
+                <property name="fill">True</property>
+                <property name="position">-1</property>
               </packing>
             </child>
           </object>
@@ -438,7 +586,7 @@
       </object>
     </child>
     <style>
-      <class name="lightdm-gtk-greeter"/>
+      <class name="background"/>
     </style>
   </object>
 </interface>


Follow ups