Index: gdm-2.24.0/gui/simple-greeter/Makefile.am
===================================================================
--- gdm-2.24.0.orig/gui/simple-greeter/Makefile.am
+++ gdm-2.24.0/gui/simple-greeter/Makefile.am
@@ -195,6 +195,7 @@ test_language_chooser_SOURCES = 	\
 
 test_language_chooser_LDADD =	\
 	$(GTK_LIBS)		\
+	$(GCONF_LIBS)		\
 	$(NULL)
 
 test_layout_chooser_SOURCES = 	\
@@ -218,6 +219,7 @@ test_layout_chooser_SOURCES = 	\
 test_layout_chooser_LDADD =		\
 	$(GTK_LIBS)			\
 	$(LIBXKLAVIER_LIBS)		\
+	$(GCONF_LIBS)		\
 	$(NULL)
 
 test_languages_SOURCES = 		\
Index: gdm-2.24.0/gui/simple-greeter/gdm-chooser-widget.c
===================================================================
--- gdm-2.24.0.orig/gui/simple-greeter/gdm-chooser-widget.c
+++ gdm-2.24.0/gui/simple-greeter/gdm-chooser-widget.c
@@ -36,6 +36,8 @@
 #include <glib/gstdio.h>
 #include <gtk/gtk.h>
 
+#include <gconf/gconf-client.h>
+
 #include "gdm-chooser-widget.h"
 #include "gdm-scrollable-widget.h"
 #include "gdm-cell-renderer-timer.h"
@@ -93,12 +95,18 @@ struct GdmChooserWidgetPrivate
         guint32                  should_hide_inactive_items : 1;
         guint32                  emit_activated_after_resize_animation : 1;
         guint32                  was_fully_grown : 1;
+        guint32                  show_inactive_items : 1;
 
         GdmChooserWidgetPosition separator_position;
         GdmChooserWidgetState    state;
 
         double                   active_row_normalized_position;
         int                      height_when_grown;
+
+        GConfClient             *gconf_client;
+        char                    *filter_regex_gconf_key;
+        guint                    notification_id;
+        GRegex                  *filter_regex;
 };
 
 enum {
@@ -602,9 +610,22 @@ update_chooser_visibility (GdmChooserWid
         }
 }
 
+static gboolean
+id_passes_filter (GdmChooserWidget *widget, const char *id)
+{
+        gboolean passed_filter = TRUE;
+
+        if (strcmp (id, "-") &&
+            !g_str_has_prefix (id, "__") &&
+            widget->priv->filter_regex &&
+            !g_regex_match (widget->priv->filter_regex, id, 0, NULL))
+                passed_filter = FALSE;
+
+        return passed_filter;
+}
+
 static void
-set_inactive_items_visible (GdmChooserWidget *widget,
-                            gboolean          should_show)
+update_row_visibility (GdmChooserWidget *widget)
 {
         GtkTreeModel *model;
         char         *active_item_id;
@@ -620,34 +641,34 @@ set_inactive_items_visible (GdmChooserWi
         active_item_id = get_active_item_id (widget, &active_item_iter);
 
         do {
+                char *id;
+
                 gboolean is_active;
+                gboolean passed_filter;
+                gboolean visibility;
 
                 is_active = FALSE;
-                if (active_item_id != NULL) {
-                        char *id;
 
-                        gtk_tree_model_get (model, &iter,
-                                            CHOOSER_ID_COLUMN, &id, -1);
+                gtk_tree_model_get (model, &iter,
+                                    CHOOSER_ID_COLUMN, &id, -1);
 
+                if (active_item_id != NULL) {
                         if (strcmp (active_item_id, id) == 0) {
                                 is_active = TRUE;
                                 g_free (active_item_id);
                                 active_item_id = NULL;
                         }
-                        g_free (id);
                 }
+                
+                passed_filter = id_passes_filter (widget, id);
+                visibility = is_active || (passed_filter && widget->priv->show_inactive_items);
 
-                if (!is_active) {
-                        gtk_list_store_set (widget->priv->list_store,
-                                            &iter,
-                                            CHOOSER_ITEM_IS_VISIBLE_COLUMN, should_show,
-                                            -1);
-                } else {
-                        gtk_list_store_set (widget->priv->list_store,
-                                            &iter,
-                                            CHOOSER_ITEM_IS_VISIBLE_COLUMN, TRUE,
-                                            -1);
-                }
+                g_free (id);
+
+                gtk_list_store_set (widget->priv->list_store,
+                                    &iter,
+                                    CHOOSER_ITEM_IS_VISIBLE_COLUMN, visibility,
+                                    -1);
         } while (gtk_tree_model_iter_next (model, &iter));
 
         g_free (active_item_id);
@@ -656,6 +677,14 @@ set_inactive_items_visible (GdmChooserWi
 }
 
 static void
+set_inactive_items_visible (GdmChooserWidget *widget,
+                            gboolean          should_show)
+{
+        widget->priv->show_inactive_items = should_show;
+        update_row_visibility (widget);
+}
+
+static void
 on_shrink_animation_complete (GdmScrollableWidget *scrollable_widget,
                               GdmChooserWidget    *widget)
 {
@@ -1613,6 +1642,15 @@ update_column_visibility (GdmChooserWidg
         return FALSE;
 }
 
+static gboolean
+update_visibility (GdmChooserWidget *widget)
+{
+        update_column_visibility (widget);
+        update_row_visibility (widget);
+
+        return FALSE;
+}
+
 static void
 clear_canceled_visibility_update (GdmChooserWidget *widget)
 {
@@ -1620,13 +1658,13 @@ clear_canceled_visibility_update (GdmCho
 }
 
 static void
-queue_column_visibility_update (GdmChooserWidget *widget)
+queue_visibility_update (GdmChooserWidget *widget)
 {
         if (widget->priv->update_idle_id == 0) {
                 widget->priv->update_idle_id =
                         g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
                                          (GSourceFunc)
-                                         update_column_visibility, widget,
+                                         update_visibility, widget,
                                          (GDestroyNotify)
                                          clear_canceled_visibility_update);
         }
@@ -1638,7 +1676,7 @@ on_row_changed (GtkTreeModel     *model,
                 GtkTreeIter      *iter,
                 GdmChooserWidget *widget)
 {
-        queue_column_visibility_update (widget);
+        queue_visibility_update (widget);
 }
 
 static void
@@ -1775,6 +1813,8 @@ gdm_chooser_widget_init (GdmChooserWidge
         GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
 
         widget->priv->height_when_grown = get_height_of_screen (widget);
+        widget->priv->show_inactive_items = TRUE;
+        widget->priv->gconf_client = gconf_client_get_default ();
 
         gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 0, 0);
 
@@ -1908,7 +1948,7 @@ gdm_chooser_widget_init (GdmChooserWidge
 
         add_separator (widget);
 
-        queue_column_visibility_update (widget);
+        queue_visibility_update (widget);
         gdm_chooser_widget_grow (widget);
 }
 
@@ -1927,6 +1967,23 @@ gdm_chooser_widget_finalize (GObject *ob
         g_hash_table_destroy (widget->priv->rows_with_timers);
         widget->priv->rows_with_timers = NULL;
 
+        if (widget->priv->notification_id != 0) {
+                gconf_client_notify_remove (widget->priv->gconf_client,
+                                            widget->priv->notification_id);
+
+                widget->priv->notification_id = 0;
+        }
+
+        if (widget->priv->filter_regex) {
+                g_regex_unref (widget->priv->filter_regex);
+                widget->priv->filter_regex = NULL;
+        }
+
+        g_free (widget->priv->filter_regex_gconf_key);
+        widget->priv->filter_regex_gconf_key = NULL;
+
+        g_object_unref (widget->priv->gconf_client);
+
         G_OBJECT_CLASS (gdm_chooser_widget_parent_class)->finalize (object);
 }
 
@@ -1981,7 +2038,7 @@ gdm_chooser_widget_update_item (GdmChoos
                 } else if (image != NULL && new_image == NULL) {
                         widget->priv->number_of_rows_with_images--;
                 }
-                queue_column_visibility_update (widget);
+                queue_visibility_update (widget);
         }
         if (image != NULL) {
                 g_object_unref (image);
@@ -1993,7 +2050,7 @@ gdm_chooser_widget_update_item (GdmChoos
                 } else {
                         widget->priv->number_of_rows_with_status--;
                 }
-                queue_column_visibility_update (widget);
+                queue_visibility_update (widget);
         }
 
         if (is_separate != new_is_separate) {
@@ -2041,15 +2098,15 @@ gdm_chooser_widget_add_item (GdmChooserW
 
         if (in_use) {
                 widget->priv->number_of_rows_with_status++;
-                queue_column_visibility_update (widget);
+                queue_visibility_update (widget);
         }
 
         if (image != NULL) {
                 widget->priv->number_of_rows_with_images++;
-                queue_column_visibility_update (widget);
+                queue_visibility_update (widget);
         }
 
-        is_visible = widget->priv->active_row == NULL;
+        is_visible = widget->priv->active_row == NULL && id_passes_filter (widget, id);
 
         gtk_list_store_insert_with_values (widget->priv->list_store,
                                            NULL, 0,
@@ -2101,7 +2158,7 @@ gdm_chooser_widget_remove_item (GdmChoos
 
         if (is_in_use) {
                 widget->priv->number_of_rows_with_status--;
-                queue_column_visibility_update (widget);
+                queue_visibility_update (widget);
         }
 
         if (is_separate) {
@@ -2195,7 +2252,7 @@ gdm_chooser_widget_set_item_in_use (GdmC
                 } else {
                         widget->priv->number_of_rows_with_status--;
                 }
-                queue_column_visibility_update (widget);
+                queue_visibility_update (widget);
 
                 gtk_list_store_set (widget->priv->list_store,
                                     &iter,
@@ -2387,7 +2444,7 @@ update_timer_from_time (GdmChooserWidget
                 g_free (id);
 
                 widget->priv->number_of_rows_with_status--;
-                queue_column_visibility_update (widget);
+                queue_visibility_update (widget);
         }
 }
 
@@ -2442,7 +2499,7 @@ gdm_chooser_widget_set_item_timer (GdmCh
                                      g_strdup (id), row);
 
                 widget->priv->number_of_rows_with_status++;
-                queue_column_visibility_update (widget);
+                queue_visibility_update (widget);
         }
 
         start_timer (widget, row, timeout / 1000.0);
@@ -2517,3 +2574,131 @@ gdm_chooser_widget_loaded (GdmChooserWid
 {
         g_signal_emit (widget, signals[LOADED], 0);
 }
+
+static gboolean
+set_filter_regex (GdmChooserWidget *widget, const char *pattern, GError **error)
+{
+        GError *local_error = NULL;
+
+        if (widget->priv->filter_regex) {
+                g_regex_unref (widget->priv->filter_regex);
+                widget->priv->filter_regex = NULL;
+        }
+
+        if (pattern) {
+                widget->priv->filter_regex = g_regex_new (pattern,
+                                                          G_REGEX_OPTIMIZE,
+                                                          0,
+                                                          &local_error);
+        }
+
+        update_row_visibility (widget);
+
+        if (local_error != NULL) {
+                g_propagate_error (error, local_error);
+                return FALSE;
+        }
+
+        return TRUE;
+}
+
+static gboolean
+sync_items_from_gconf (GdmChooserWidget *widget, GError **error)
+{
+        GConfValue *value;
+        GError     *local_error;
+        const char *pattern;
+
+        local_error = NULL;
+        value = gconf_client_get (widget->priv->gconf_client,
+                                  widget->priv->filter_regex_gconf_key,
+                                  &local_error);
+
+        if (local_error != NULL) {
+                g_warning ("could not get gconf key '%s': %s",
+                           widget->priv->filter_regex_gconf_key,
+                           local_error->message);
+                g_propagate_error (error, local_error);
+                return FALSE;
+        }
+
+        if (value == NULL) {
+                g_warning ("gconf key '%s' is unset",
+                           widget->priv->filter_regex_gconf_key);
+                return FALSE;
+        }
+
+        if (value->type != GCONF_VALUE_STRING) {
+                g_warning ("gconf key is not a string");
+                return FALSE;
+        }
+
+        pattern = gconf_value_get_string (value);
+        set_filter_regex (widget, pattern, &local_error);
+
+        gconf_value_free (value);
+        
+        if (local_error != NULL) {
+                g_propagate_error (error, local_error);
+                return FALSE;
+        }
+        
+        return TRUE;
+}
+
+static void
+gconf_notify_func (GConfClient *client,
+                   guint        connection_id,
+                   GConfEntry  *entry,
+                   gpointer     user_data)
+{
+        sync_items_from_gconf (GDM_CHOOSER_WIDGET (user_data), NULL);
+}
+
+gboolean
+gdm_chooser_widget_set_filter_regex_gconf_key (GdmChooserWidget          *widget,
+                                               const char                *gconf_key,
+                                               GError                   **error)
+{
+        GError *local_error;
+
+        if (widget->priv->filter_regex_gconf_key != NULL &&
+            gconf_key != NULL &&
+            strcmp (widget->priv->filter_regex_gconf_key, gconf_key) == 0) {
+                return TRUE;
+        }
+
+        if (widget->priv->notification_id != 0) {
+                gconf_client_notify_remove (widget->priv->gconf_client,
+                                            widget->priv->notification_id);
+
+                widget->priv->notification_id = 0;
+        }
+
+        g_free (widget->priv->filter_regex_gconf_key);
+        widget->priv->filter_regex_gconf_key = NULL;
+
+        if (gconf_key) {
+                widget->priv->filter_regex_gconf_key = g_strdup (gconf_key);
+
+                local_error = NULL;
+                sync_items_from_gconf (widget, &local_error);
+                if (local_error != NULL) {
+                        g_propagate_error (error, local_error);
+                        return FALSE;
+                }
+
+                local_error = NULL;
+                widget->priv->notification_id = gconf_client_notify_add (widget->priv->gconf_client,
+                                                                         gconf_key,
+                                                                         (GConfClientNotifyFunc) gconf_notify_func,
+                                                                         widget, NULL, &local_error);
+                if (local_error != NULL) {
+                        g_propagate_error (error, local_error);
+                        return FALSE;
+                }
+        }
+
+        return TRUE;
+}
+
Index: gdm-2.24.0/gui/simple-greeter/gdm-chooser-widget.h
===================================================================
--- gdm-2.24.0.orig/gui/simple-greeter/gdm-chooser-widget.h
+++ gdm-2.24.0/gui/simple-greeter/gdm-chooser-widget.h
@@ -140,6 +140,10 @@ void           gdm_chooser_widget_propag
 
 void           gdm_chooser_widget_loaded                       (GdmChooserWidget          *widget);
 
+gboolean       gdm_chooser_widget_set_filter_regex_gconf_key   (GdmChooserWidget          *widget,
+                                                                const char                *gconf_key,
+                                                                GError                   **error);
+
 G_END_DECLS
 
 #endif /* __GDM_CHOOSER_WIDGET_H */
Index: gdm-2.24.0/gui/simple-greeter/gdm-domain-chooser-widget.c
===================================================================
--- gdm-2.24.0.orig/gui/simple-greeter/gdm-domain-chooser-widget.c
+++ gdm-2.24.0/gui/simple-greeter/gdm-domain-chooser-widget.c
@@ -209,6 +209,10 @@ gdm_domain_chooser_widget_init (GdmDomai
 
         gdm_chooser_widget_set_separator_position (GDM_CHOOSER_WIDGET (domain_chooser_widget),
                                                    GDM_CHOOSER_WIDGET_POSITION_TOP);
+
+        gdm_chooser_widget_set_filter_regex_gconf_key (GDM_CHOOSER_WIDGET (domain_chooser_widget),
+                                                       "/apps/gdm/simple-greeter/domain_filter_regexp",
+                                                       NULL);
 }
 
 static void
Index: gdm-2.24.0/gui/simple-greeter/gdm-language-chooser-widget.c
===================================================================
--- gdm-2.24.0.orig/gui/simple-greeter/gdm-language-chooser-widget.c
+++ gdm-2.24.0/gui/simple-greeter/gdm-language-chooser-widget.c
@@ -246,6 +246,10 @@ gdm_language_chooser_widget_init (GdmLan
 
         gdm_chooser_widget_set_separator_position (GDM_CHOOSER_WIDGET (widget),
                                                    GDM_CHOOSER_WIDGET_POSITION_TOP);
+
+        gdm_chooser_widget_set_filter_regex_gconf_key (GDM_CHOOSER_WIDGET (widget),
+                                                       "/apps/gdm/simple-greeter/language_filter_regexp",
+                                                       NULL);
 }
 
 static void
Index: gdm-2.24.0/gui/simple-greeter/gdm-layout-chooser-widget.c
===================================================================
--- gdm-2.24.0.orig/gui/simple-greeter/gdm-layout-chooser-widget.c
+++ gdm-2.24.0/gui/simple-greeter/gdm-layout-chooser-widget.c
@@ -174,6 +174,10 @@ gdm_layout_chooser_widget_init (GdmLayou
 
         gdm_chooser_widget_set_separator_position (GDM_CHOOSER_WIDGET (widget),
                                                    GDM_CHOOSER_WIDGET_POSITION_TOP);
+
+        gdm_chooser_widget_set_filter_regex_gconf_key (GDM_CHOOSER_WIDGET (widget),
+                                                       "/apps/gdm/simple-greeter/layout_filter_regexp",
+                                                       NULL);
 }
 
 static void
Index: gdm-2.24.0/gui/simple-greeter/gdm-simple-greeter.schemas.in
===================================================================
--- gdm-2.24.0.orig/gui/simple-greeter/gdm-simple-greeter.schemas.in
+++ gdm-2.24.0/gui/simple-greeter/gdm-simple-greeter.schemas.in
@@ -68,6 +68,39 @@
       </locale>
     </schema>
     <schema>
+      <key>/schemas/apps/gdm/simple-greeter/domain_filter_regexp</key>
+      <applyto>/apps/gdm/simple-greeter/domain_filter_regexp</applyto>
+      <owner>gdm-simple-greeter</owner>
+      <type>string</type>
+      <default></default>
+      <locale name="C">
+        <short>Regexp filter for domain list</short>
+        <long>Set to a regexp limiting the list of domains to show in the domain chooser.</long>
+      </locale>
+    </schema>
+    <schema>
+      <key>/schemas/apps/gdm/simple-greeter/language_filter_regexp</key>
+      <applyto>/apps/gdm/simple-greeter/language_filter_regexp</applyto>
+      <owner>gdm-simple-greeter</owner>
+      <type>string</type>
+      <default></default>
+      <locale name="C">
+        <short>Regexp filter for language list</short>
+        <long>Set to a regexp limiting the list of languages to show in the language chooser.</long>
+      </locale>
+    </schema>
+    <schema>
+      <key>/schemas/apps/gdm/simple-greeter/layout_filter_regexp</key>
+      <applyto>/apps/gdm/simple-greeter/layout_filter_regexp</applyto>
+      <owner>gdm-simple-greeter</owner>
+      <type>string</type>
+      <default></default>
+      <locale name="C">
+        <short>Regexp filter for keyboard layout list</short>
+        <long>Set to a regexp limiting the list of keyboard layouts to show in the layout chooser.</long>
+      </locale>
+    </schema>
+    <schema>
       <key>/schemas/apps/gdm/simple-greeter/recent-languages</key>
       <applyto>/apps/gdm/simple-greeter/recent-languages</applyto>
       <owner>gdm-simple-greeter</owner>
