[gnome-control-center/meego-display: 2/2] display: add display-minimal as an option



commit 0347517f646de04adae579b617e48f585fb55d7c
Author: Ross Burton <ross linux intel com>
Date:   Wed Feb 17 17:09:34 2010 +0000

    display: add display-minimal as an option

 capplets/display/Makefile.am                      |   14 +-
 capplets/display/cc-display-minimal-page.c        |  758 +++++++++++++++++++++
 capplets/display/display-minimal.ui               |  168 +++++
 capplets/display/display-netbook-and-external.png |  Bin 0 -> 1175 bytes
 capplets/display/display-netbook-only.png         |  Bin 0 -> 1164 bytes
 5 files changed, 936 insertions(+), 4 deletions(-)
---
diff --git a/capplets/display/Makefile.am b/capplets/display/Makefile.am
index 435d598..ae565ba 100644
--- a/capplets/display/Makefile.am
+++ b/capplets/display/Makefile.am
@@ -8,6 +8,7 @@ INCLUDES = \
 	$(GNOMECC_CAPPLETS_CFLAGS)			\
 	-I$(top_srcdir)/libgnome-control-center-extension \
 	-DUIDIR="\"$(uidir)\""				\
+	-DPIXMAPDIR="\"$(pixmapdir)\""			\
 	-DGNOMELOCALEDIR="\"$(datadir)/locale\""	\
 	-DGNOMECC_DATA_DIR="\"$(pkgdatadir)\""		\
 	$(NULL)
@@ -29,7 +30,7 @@ ccmodules_LTLIBRARIES = libdisplay.la
 libdisplay_la_SOURCES =			\
 	display-module.c		\
 	cc-display-page.h		\
-	cc-display-page.c		\
+	cc-display-minimal-page.c		\
 	cc-display-panel.h		\
 	cc-display-panel.c		\
 	$(NULL)
@@ -39,11 +40,11 @@ libdisplay_la_LDFLAGS =			\
 	$(EXTENSION_LIBTOOL_FLAGS)	\
 	$(NULL)
 
+#	libdisplay-common.la
 libdisplay_la_LIBADD =			\
-	libdisplay-common.la		\
 	$(EXTENSION_LIBS)		\
 	$(EXTENSION_COMMON_LIBS)	\
-	$(LIBGNOMEKBDUI_LIBS)		\
+	$(DISPLAY_CAPPLET_LIBS)		\
 	$(NULL)
 
 libdisplay_la_CFLAGS =			\
@@ -78,12 +79,17 @@ dist_icons32_DATA = icons/32x32/gnome-display-properties.png
 iconssvgdir = $(datadir)/icons/hicolor/scalable/apps
 dist_iconssvg_DATA = icons/scalable/gnome-display-properties.svg
 
+icondir = $(pkgdatadir)/pixmaps
+dist_icon_DATA = \
+	display-netbook-and-external.png \
+	display-netbook-only.png 
+
 desktopdir = $(datadir)/applications
 Desktop_in_files = display-properties.desktop.in
 desktop_DATA = $(Desktop_in_files:.desktop.in=.desktop)
 
 uidir = $(pkgdatadir)/ui
-dist_ui_DATA = display-capplet.ui
+dist_ui_DATA = display-capplet.ui display-minimal.ui
 
 CLEANFILES = $(GNOMECC_CAPPLETS_CLEANFILES) $(Desktop_in_files) $(desktop_DATA)
 
diff --git a/capplets/display/cc-display-minimal-page.c b/capplets/display/cc-display-minimal-page.c
new file mode 100644
index 0000000..e8b4c44
--- /dev/null
+++ b/capplets/display/cc-display-minimal-page.c
@@ -0,0 +1,758 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 - 2010 Red Hat, Inc.
+ * Copyright (C) 2010 Intel Corp
+ *
+ * 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <mx/mx-gtk.h>
+#include <gconf/gconf-client.h>
+#include <dbus/dbus-glib.h>
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnomeui/gnome-rr.h>
+#include <libgnomeui/gnome-rr-config.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+
+#include "cc-display-page.h"
+
+#define CC_DISPLAY_PAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_DISPLAY_PAGE, CcDisplayPagePrivate))
+
+#define WID(s) GTK_WIDGET (gtk_builder_get_object (builder, s))
+
+typedef enum {
+        /* Internal display is on, no external */
+        INTERNAL,
+        /* Internal display is on, external is present */
+        INTERNAL_EXTERNAL_PRESENT,
+        /* Internal display off, external display is on */
+        EXTERNAL,
+} OutputMode;
+
+enum {
+  COL_MODE = 0,
+  COL_NAME = 1,
+  COL_END = -1
+};
+
+struct CcDisplayPagePrivate
+{
+        GnomeRRScreen   *screen;
+        GnomeRRConfig   *current_configuration;
+        GnomeOutputInfo *internal_output, *external_output;
+
+        GtkWidget       *monitor_icon;
+        GtkWidget       *toggle;
+        GtkTreeModel    *resolution_store;
+        GtkWidget       *resolution_combo;
+        GtkWidget       *resolution_box;
+        GtkWidget       *state_label;
+
+        /* We store the event timestamp when the Apply button is clicked */
+        GtkWidget       *apply_button;
+        guint32          apply_button_clicked_timestamp;
+
+        /* These are used while we are waiting for the ApplyConfiguration method to be executed over D-bus */
+        DBusGConnection *connection;
+        DBusGProxy      *proxy;
+        DBusGProxyCall  *proxy_call;
+
+        enum {
+                APPLYING_VERSION_1,
+                APPLYING_VERSION_2
+        } apply_configuration_state;
+};
+
+enum {
+        PROP_0,
+};
+
+static void     cc_display_page_class_init     (CcDisplayPageClass *klass);
+static void     cc_display_page_init           (CcDisplayPage      *display_page);
+static void     cc_display_page_finalize       (GObject             *object);
+
+static void     apply_configuration_returned_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, CcDisplayPage *page);
+
+G_DEFINE_TYPE (CcDisplayPage, cc_display_page, CC_TYPE_PAGE)
+
+
+typedef struct
+{
+    int grab_x;
+    int grab_y;
+    int output_x;
+    int output_y;
+} GrabInfo;
+
+static void
+error_message (CcDisplayPage *page,
+               const char    *primary_text,
+               const char    *secondary_text)
+{
+        GtkWidget *dialog;
+        GtkWidget *toplevel;
+
+        toplevel = gtk_widget_get_toplevel (GTK_WIDGET (page));
+        if (!GTK_WIDGET_TOPLEVEL (toplevel)) {
+                toplevel = NULL;
+        }
+
+        dialog = gtk_message_dialog_new ((toplevel) ? GTK_WINDOW (toplevel) : NULL,
+                                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                         GTK_MESSAGE_ERROR,
+                                         GTK_BUTTONS_CLOSE,
+                                         "%s", primary_text);
+
+        if (secondary_text != NULL)
+                gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                                          "%s", secondary_text);
+
+        gtk_dialog_run (GTK_DIALOG (dialog));
+        gtk_widget_destroy (dialog);
+}
+
+static void
+compute_virtual_size_for_configuration (GnomeRRConfig *config,
+                                        int           *ret_width,
+                                        int           *ret_height)
+{
+        int i;
+        int width;
+        int height;
+
+        width = height = 0;
+
+        for (i = 0; config->outputs[i] != NULL; i++) {
+                GnomeOutputInfo *output;
+
+                output = config->outputs[i];
+
+                if (output->on) {
+                        width = MAX (width, output->x + output->width);
+                        height = MAX (height, output->y + output->height);
+                }
+        }
+
+        *ret_width = width;
+        *ret_height = height;
+}
+
+static void
+check_required_virtual_size (CcDisplayPage *page)
+{
+        int req_width;
+        int req_height;
+        int min_width;
+        int max_width;
+        int min_height;
+        int max_height;
+
+        compute_virtual_size_for_configuration (page->priv->current_configuration,
+                                                &req_width,
+                                                &req_height);
+
+        gnome_rr_screen_get_ranges (page->priv->screen,
+                                    &min_width,
+                                    &max_width,
+                                    &min_height,
+                                    &max_height);
+
+#if 0
+        g_debug ("X Server supports:");
+        g_debug ("min_width = %d, max_width = %d", min_width, max_width);
+        g_debug ("min_height = %d, max_height = %d", min_height, max_height);
+
+        g_debug ("Requesting size of %dx%d", req_width, req_height);
+#endif
+
+        if (!(min_width <= req_width && req_width <= max_width
+              && min_height <= req_height && req_height <= max_height)) {
+                /* FIXME: present a useful dialog, maybe even before the user tries to Apply */
+#if 0
+                g_debug ("Your X server needs a larger Virtual size!");
+#endif
+        }
+}
+
+static void
+begin_version2_apply_configuration (CcDisplayPage *page,
+                                    GdkWindow     *parent_window,
+                                    guint32        timestamp)
+{
+        XID parent_window_xid;
+
+        parent_window_xid = GDK_WINDOW_XID (parent_window);
+
+        page->priv->proxy = dbus_g_proxy_new_for_name (page->priv->connection,
+                                                       "org.gnome.SettingsDaemon",
+                                                       "/org/gnome/SettingsDaemon/XRANDR",
+                                                       "org.gnome.SettingsDaemon.XRANDR_2");
+        g_assert (page->priv->proxy != NULL); /* that call does not fail unless we pass bogus names */
+
+        page->priv->apply_configuration_state = APPLYING_VERSION_2;
+        page->priv->proxy_call = dbus_g_proxy_begin_call (page->priv->proxy,
+                                                          "ApplyConfiguration",
+                                                          (DBusGProxyCallNotify) apply_configuration_returned_cb,
+                                                          page,
+                                                          NULL,
+                                                          G_TYPE_INT64,
+                                                          (gint64) parent_window_xid,
+                                                          G_TYPE_INT64,
+                                                          (gint64) timestamp,
+                                                          G_TYPE_INVALID,
+                                                          G_TYPE_INVALID);
+        /* FIXME: we don't check for page->priv->proxy_call == NULL, which could happen if
+         * the connection was disconnected.  This is left as an exercise for the
+         * reader.
+         */
+}
+
+static void
+begin_version1_apply_configuration (CcDisplayPage *page)
+{
+        page->priv->proxy = dbus_g_proxy_new_for_name (page->priv->connection,
+                                                "org.gnome.SettingsDaemon",
+                                                "/org/gnome/SettingsDaemon/XRANDR",
+                                                "org.gnome.SettingsDaemon.XRANDR");
+        g_assert (page->priv->proxy != NULL); /* that call does not fail unless we pass bogus names */
+
+        page->priv->apply_configuration_state = APPLYING_VERSION_1;
+        page->priv->proxy_call = dbus_g_proxy_begin_call (page->priv->proxy,
+                                                          "ApplyConfiguration",
+                                                          (DBusGProxyCallNotify) apply_configuration_returned_cb,
+                                                          page,
+                                                          NULL,
+                                                          G_TYPE_INVALID,
+                                                          G_TYPE_INVALID);
+        /* FIXME: we don't check for page->priv->proxy_call == NULL, which could happen if
+         * the connection was disconnected.  This is left as an exercise for the
+         * reader.
+         */
+}
+
+static void
+ensure_current_configuration_is_saved (void)
+{
+        GnomeRRScreen *rr_screen;
+        GnomeRRConfig *rr_config;
+
+        /* Normally, gnome_rr_config_save() creates a backup file based on the
+         * old monitors.xml.  However, if *that* file didn't exist, there is
+         * nothing from which to create a backup.  So, here we'll save the
+         * current/unchanged configuration and then let our caller call
+         * gnome_rr_config_save() again with the new/changed configuration, so
+         * that there *will* be a backup file in the end.
+         */
+
+        rr_screen = gnome_rr_screen_new (gdk_screen_get_default (),
+                                         NULL,
+                                         NULL,
+                                         NULL); /* NULL-GError */
+        if (!rr_screen)
+                return;
+
+        rr_config = gnome_rr_config_new_current (rr_screen);
+        gnome_rr_config_save (rr_config, NULL); /* NULL-GError */
+
+        gnome_rr_config_free (rr_config);
+        gnome_rr_screen_destroy (rr_screen);
+}
+
+/* Callback for dbus_g_proxy_begin_call() */
+static void
+apply_configuration_returned_cb (DBusGProxy     *proxy,
+                                 DBusGProxyCall *call_id,
+                                 CcDisplayPage  *page)
+{
+        gboolean success;
+        GError  *error;
+
+        g_assert (call_id == page->priv->proxy_call);
+
+        error = NULL;
+        success = dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID);
+
+        if (!success) {
+                if (page->priv->apply_configuration_state == APPLYING_VERSION_2
+                    && g_error_matches (error, DBUS_GERROR, DBUS_GERROR_UNKNOWN_METHOD)) {
+                        g_error_free (error);
+
+                        g_object_unref (page->priv->proxy);
+                        page->priv->proxy = NULL;
+
+                        begin_version1_apply_configuration (page);
+                        return;
+                } else {
+                        /* We don't pop up an error message; gnome-settings-daemon already does that
+                         * in case the selected RANDR configuration could not be applied.
+                         */
+                        g_error_free (error);
+                }
+        }
+
+        g_object_unref (page->priv->proxy);
+        page->priv->proxy = NULL;
+
+        dbus_g_connection_unref (page->priv->connection);
+        page->priv->connection = NULL;
+        page->priv->proxy_call = NULL;
+
+        gtk_widget_set_sensitive (GTK_WIDGET (page), TRUE);
+}
+
+static void
+apply (CcDisplayPage *page)
+{
+        GError    *error;
+        GtkWidget *toplevel;
+
+
+        gnome_rr_config_sanitize (page->priv->current_configuration);
+
+        check_required_virtual_size (page);
+
+        ensure_current_configuration_is_saved ();
+
+        error = NULL;
+        if (!gnome_rr_config_save (page->priv->current_configuration, &error)) {
+                error_message (page,
+                               _("Could not save the monitor configuration"),
+                               error->message);
+                g_error_free (error);
+                return;
+        }
+
+        g_assert (page->priv->connection == NULL);
+        g_assert (page->priv->proxy == NULL);
+        g_assert (page->priv->proxy_call == NULL);
+
+        page->priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+        if (page->priv->connection == NULL) {
+                error_message (page,
+                               _("Could not get session bus while applying display configuration"),
+                               error->message);
+                g_error_free (error);
+                return;
+        }
+
+        gtk_widget_set_sensitive (GTK_WIDGET (page), FALSE);
+
+        toplevel = gtk_widget_get_toplevel (GTK_WIDGET (page));
+        if (!GTK_WIDGET_TOPLEVEL (toplevel)) {
+                toplevel = GTK_WIDGET (page);
+        }
+
+        begin_version2_apply_configuration (page,
+                                            gtk_widget_get_window (toplevel),
+                                            page->priv->apply_button_clicked_timestamp);
+}
+
+static void
+on_apply_button_clicked (GtkButton     *button,
+                         CcDisplayPage *page)
+{
+        /* We simply store the timestamp at which the Apply button was clicked.
+         * We'll just wait for the dialog to return from gtk_dialog_run(), and
+         * *then* use the timestamp when applying the RANDR configuration.
+         */
+
+        page->priv->apply_button_clicked_timestamp = gtk_get_current_event_time ();
+
+        apply (page);
+}
+
+typedef struct {
+  GnomeRRMode *mode;
+  gboolean found;
+  GtkTreeIter iter;
+  GnomeRRMode *found_mode;
+} FindData;
+
+/*
+ * foreach helper to find the mode in @data->mode in @model.  If it exists,
+ * @data->found is TRUE and @data->iter/@data->found_mode are set.
+ */
+static gboolean
+find_mode (GtkTreeModel *model,
+           GtkTreePath *path,
+           GtkTreeIter *iter,
+           gpointer user_data)
+{
+  FindData *data = user_data;
+  GnomeRRMode *mode = NULL;
+  int width, height;
+
+  g_assert (data->mode);
+  g_assert (!data->found);
+
+  width = gnome_rr_mode_get_width (data->mode);
+  height = gnome_rr_mode_get_height (data->mode);
+
+  gtk_tree_model_get (model, iter, COL_MODE, &mode, COL_END);
+  g_assert (mode);
+
+  if (gnome_rr_mode_get_width (mode) == width &&
+      gnome_rr_mode_get_height (mode) == height) {
+    data->found = TRUE;
+    data->iter = *iter;
+    data->found_mode = mode;
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+static void
+update_resolutions (CcDisplayPage *page)
+{
+  GnomeRROutput *output;
+  GnomeRRMode **modes, *current_mode;
+  int i;
+
+  gtk_list_store_clear (GTK_LIST_STORE (page->priv->resolution_store));
+
+  output = gnome_rr_screen_get_output_by_name (page->priv->screen, page->priv->external_output->name);
+  modes = gnome_rr_output_list_modes (output);
+  current_mode = gnome_rr_output_get_current_mode (output);
+
+  for (i = 0; modes[i] != NULL; i++) {
+    GnomeRRMode *mode = modes[i];
+    char *s;
+    FindData data;
+
+    /* Skip modes that are too small for our UX */
+    if (gnome_rr_mode_get_width (mode) < 1024 ||
+        gnome_rr_mode_get_height (mode) < 576)
+      continue;
+
+    data.mode = mode;
+    data.found = FALSE;
+
+    /* See if this have this resolution already in the store */
+    gtk_tree_model_foreach (page->priv->resolution_store, find_mode, &data);
+    if (data.found) {
+      /* This resolution is already in the store.  If this mode is a higher
+         refresh than the one in the store, replace it */
+      if (gnome_rr_mode_get_freq (data.found_mode) <
+          gnome_rr_mode_get_freq (mode)) {
+        gtk_list_store_set (GTK_LIST_STORE (page->priv->resolution_store), &data.iter,
+                            COL_MODE, mode, COL_END);
+      }
+    } else {
+      /* This resolution isn't in the store, add it */
+      s = g_strdup_printf ("%dx%d",
+                           gnome_rr_mode_get_width (mode),
+                           gnome_rr_mode_get_height (mode));
+
+      gtk_list_store_insert_with_values (GTK_LIST_STORE (page->priv->resolution_store), &data.iter, -1,
+                                         COL_MODE, mode, COL_NAME, s, COL_END);
+      g_free (s);
+    }
+
+    /* If this mode is the current mode, active it */
+    if (mode == current_mode) {
+      gtk_combo_box_set_active_iter (GTK_COMBO_BOX (page->priv->resolution_combo), &data.iter);
+    }
+  }
+}
+
+static void
+update_ui (CcDisplayPage *page, OutputMode mode)
+{
+        switch (mode) {
+        case INTERNAL:
+                gtk_widget_set_sensitive (page->priv->toggle, FALSE);
+                mx_gtk_light_switch_set_active (MX_GTK_LIGHT_SWITCH (page->priv->toggle), FALSE);
+                gtk_label_set_text (GTK_LABEL (page->priv->state_label),
+                                    _("You are only showing your desktop on your computer's screen. "
+                                      "Plug in another display to share your view and then turn display sharing on above."));
+                gtk_widget_hide (page->priv->resolution_box);
+                gtk_image_set_from_file (GTK_IMAGE (page->priv->monitor_icon), PIXMAPDIR "/display-netbook-only.png");
+                break;
+        case INTERNAL_EXTERNAL_PRESENT:
+                gtk_widget_set_sensitive (page->priv->toggle, TRUE);
+                mx_gtk_light_switch_set_active (MX_GTK_LIGHT_SWITCH (page->priv->toggle), FALSE);
+                gtk_label_set_text (GTK_LABEL (page->priv->state_label),
+                                    _("You are only showing your desktop on your computer's screen. "
+                                      "Plug in another display to share your view and then turn display sharing on above."));
+                gtk_widget_hide (page->priv->resolution_box);
+                gtk_image_set_from_file (GTK_IMAGE (page->priv->monitor_icon), PIXMAPDIR "/display-netbook-only.png");
+                break;
+        case EXTERNAL:
+                gtk_widget_set_sensitive (page->priv->toggle, TRUE);
+                mx_gtk_light_switch_set_active (MX_GTK_LIGHT_SWITCH (page->priv->toggle), TRUE);
+                gtk_label_set_text (GTK_LABEL (page->priv->state_label),
+                                    _("You are showing your desktop on an external monitor or projector."));
+                gtk_widget_show (page->priv->resolution_box);
+                gtk_image_set_from_file (GTK_IMAGE (page->priv->monitor_icon), PIXMAPDIR "/display-netbook-and-external.png");
+
+                update_resolutions (page);
+                break;
+  }
+}
+
+static gboolean
+is_internal_screen (GnomeOutputInfo *output)
+{
+        g_return_val_if_fail (output, FALSE);
+
+        /* Really hope this is good enough */
+        return strncasecmp (output->name, "lvds", 4) == 0;
+}
+
+static void
+on_screen_changed (GnomeRRScreen *scr,
+                   CcDisplayPage *page)
+{
+        GnomeRRConfig *config;
+        int i;
+
+        if (page->priv->current_configuration)
+                gnome_rr_config_free (page->priv->current_configuration);
+
+        config = page->priv->current_configuration = gnome_rr_config_new_current (page->priv->screen);
+
+
+        page->priv->internal_output = NULL;
+        page->priv->external_output = NULL;
+
+        for (i = 0; config->outputs[i] != NULL; i++) {
+                GnomeOutputInfo *output = config->outputs[i];
+
+                if (is_internal_screen (output)) {
+                        page->priv->internal_output = output;
+                } else {
+                        if (output->connected)
+                                page->priv->external_output = output;
+                }
+        }
+
+        if (page->priv->internal_output->on &&
+            !page->priv->external_output)
+                update_ui (page, INTERNAL);
+        else if (page->priv->internal_output->on &&
+                 page->priv->external_output &&
+                 !page->priv->external_output->on)
+                update_ui (page, INTERNAL_EXTERNAL_PRESENT);
+        else if (page->priv->external_output)
+                update_ui (page, EXTERNAL);
+}
+
+static void
+activate_output (GnomeOutputInfo *info, GnomeRRMode *mode)
+{
+        g_return_if_fail (info);
+        g_return_if_fail (mode);
+
+        info->primary = TRUE;
+        info->on = TRUE;
+        info->width = gnome_rr_mode_get_width (mode);
+        info->height = gnome_rr_mode_get_height (mode);
+        info->rate = gnome_rr_mode_get_freq (mode);
+        info->rotation = GNOME_RR_ROTATION_0;
+}
+
+static void
+on_toggled (MxGtkLightSwitch *toggle, gboolean state, gpointer user_data)
+{
+        CcDisplayPage *page = CC_DISPLAY_PAGE (user_data);
+        GnomeRROutput *output;
+        GnomeRRMode *mode = NULL;
+
+        if (mx_gtk_light_switch_get_active (MX_GTK_LIGHT_SWITCH (toggle))) {
+                output = gnome_rr_screen_get_output_by_name (page->priv->screen, page->priv->external_output->name);
+                mode = gnome_rr_output_get_preferred_mode (output);
+                if (!mode)
+                        mode = gnome_rr_output_list_modes (output)[0];
+                activate_output (page->priv->external_output, mode);
+
+                page->priv->internal_output->on = FALSE;
+        } else {
+                output = gnome_rr_screen_get_output_by_name (page->priv->screen, page->priv->internal_output->name);
+                mode = gnome_rr_output_get_preferred_mode (output);
+                activate_output (page->priv->internal_output, mode);
+                page->priv->external_output->on = FALSE;
+        }
+
+        page->priv->apply_button_clicked_timestamp = gtk_get_current_event_time ();
+
+        apply (page);
+}
+
+static void
+setup_page (CcDisplayPage *page)
+{
+        GtkBuilder      *builder;
+        GtkWidget       *widget;
+        GtkCellRenderer *renderer;
+        GError          *error;
+
+        builder = gtk_builder_new ();
+
+        error = NULL;
+        gtk_builder_add_from_file (builder,
+                                   UIDIR
+                                   "/display-minimal.ui",
+                                   &error);
+        if (error != NULL) {
+                g_error (_("Could not load user interface file: %s"),
+                         error->message);
+                g_error_free (error);
+                return;
+        }
+
+        page->priv->monitor_icon = WID ("monitor_icon");
+        page->priv->state_label = WID ("state_label");
+        page->priv->resolution_box = WID ("resolution_box");
+        page->priv->resolution_combo = WID ("res_combo");
+        page->priv->resolution_store = GTK_TREE_MODEL (gtk_builder_get_object (builder, "mode_store"));
+        widget = WID ("apply_button");
+        g_signal_connect (widget, "clicked", G_CALLBACK (on_apply_button_clicked), page);
+
+        page->priv->toggle = mx_gtk_light_switch_new ();
+        g_signal_connect (page->priv->toggle, "switch-flipped", G_CALLBACK (on_toggled), page);
+        gtk_widget_show (page->priv->toggle);
+        widget = WID ("hbox");
+        gtk_box_pack_start (GTK_BOX (widget), page->priv->toggle, FALSE, FALSE, 0);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (page->priv->resolution_combo), renderer, TRUE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (page->priv->resolution_combo), renderer, "text", COL_NAME);
+
+        widget = WID ("topbox");
+        gtk_widget_reparent (widget, GTK_WIDGET (page));
+        gtk_widget_show (widget);
+
+        g_object_unref (builder);
+}
+
+static GObject *
+cc_display_page_constructor (GType                  type,
+                             guint                  n_construct_properties,
+                             GObjectConstructParam *construct_properties)
+{
+        CcDisplayPage      *display_page;
+        g_debug (__FUNCTION__);
+
+        display_page = CC_DISPLAY_PAGE (G_OBJECT_CLASS (cc_display_page_parent_class)->constructor (type,
+                                                                                                    n_construct_properties,
+                                                                                                    construct_properties));
+
+        g_object_set (display_page,
+                      "display-name", _("Displays and projectors"),
+                      "id", "general",
+                      NULL);
+
+        setup_page (display_page);
+
+        return G_OBJECT (display_page);
+}
+
+static void
+start_working (CcDisplayPage *page)
+{
+        GError *error = NULL;
+        g_debug (__FUNCTION__);
+        page->priv->screen = gnome_rr_screen_new (gdk_screen_get_default (),
+                                                  (GnomeRRScreenChanged) on_screen_changed,
+                                                  page,
+                                                  &error);
+        if (page->priv->screen == NULL) {
+                error_message (NULL,
+                               _("Could not get screen information"),
+                               error->message);
+                g_error_free (error);
+                return;
+        }
+        on_screen_changed (page->priv->screen, page);
+}
+
+static void
+stop_working (CcDisplayPage *page)
+{
+        gnome_rr_screen_destroy (page->priv->screen);
+        page->priv->screen = NULL;
+}
+
+static void
+cc_display_page_active_changed (CcPage  *base_page,
+                                gboolean is_active)
+{
+        CcDisplayPage *page = CC_DISPLAY_PAGE (base_page);
+        g_debug (__FUNCTION__);
+
+        if (is_active)
+                start_working (page);
+        else
+                stop_working (page);
+
+        CC_PAGE_CLASS (cc_display_page_parent_class)->active_changed (base_page, is_active);
+
+}
+
+static void
+cc_display_page_class_init (CcDisplayPageClass *klass)
+{
+        GObjectClass  *object_class = G_OBJECT_CLASS (klass);
+        CcPageClass   *page_class = CC_PAGE_CLASS (klass);
+
+        page_class->active_changed = cc_display_page_active_changed;
+
+        object_class->constructor = cc_display_page_constructor;
+        object_class->finalize = cc_display_page_finalize;
+
+        g_type_class_add_private (klass, sizeof (CcDisplayPagePrivate));
+}
+
+static void
+cc_display_page_init (CcDisplayPage *page)
+{
+        page->priv = CC_DISPLAY_PAGE_GET_PRIVATE (page);
+}
+
+static void
+cc_display_page_finalize (GObject *object)
+{
+        CcDisplayPage *page;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (CC_IS_DISPLAY_PAGE (object));
+
+        page = CC_DISPLAY_PAGE (object);
+
+        g_return_if_fail (page->priv != NULL);
+
+        stop_working (page);
+
+        G_OBJECT_CLASS (cc_display_page_parent_class)->finalize (object);
+}
+
+CcPage *
+cc_display_page_new (void)
+{
+        GObject *object;
+
+        object = g_object_new (CC_TYPE_DISPLAY_PAGE, NULL);
+
+        return CC_PAGE (object);
+}
diff --git a/capplets/display/display-minimal.ui b/capplets/display/display-minimal.ui
new file mode 100644
index 0000000..febab42
--- /dev/null
+++ b/capplets/display/display-minimal.ui
@@ -0,0 +1,168 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-requires mx 0.0 -->
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkWindow" id="window1">
+    <child>
+      <object class="GtkVBox" id="topbox">
+        <property name="visible">True</property>
+        <property name="border_width">8</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">8</property>
+        <child>
+          <object class="GtkLabel" id="banner">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">Displays and projectors</property>
+            <attributes>
+              <attribute name="weight" value="bold"/>
+              <attribute name="scale" value="2.000000"/>
+            </attributes>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <property name="spacing">8</property>
+            <child>
+              <object class="GtkImage" id="monitor_icon">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="yalign">0</property>
+                <property name="pixel_size">64</property>
+                <property name="icon_name">video-display</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkVBox" id="vbox2">
+                <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">12</property>
+                <child>
+                  <object class="GtkHBox" id="hbox">
+                    <property name="visible">True</property>
+                    <property name="spacing">8</property>
+                    <child>
+                      <object class="GtkLabel" id="label1">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">External display</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <!--
+                    <child>
+                      <object class="MxGtkLightSwitch" id="toggle">
+                        <property name="visible">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    -->
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="state_label">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">You are showing your desktop on an external monitor or projector.</property>
+                    <property name="wrap">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHBox" id="resolution_box">
+                    <property name="visible">True</property>
+                    <property name="spacing">8</property>
+                    <child>
+                      <object class="GtkLabel" id="label2">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">External display resolution</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkComboBox" id="res_combo">
+                        <property name="width_request">150</property>
+                        <property name="visible">True</property>
+                        <property name="model">mode_store</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="apply_button">
+                        <property name="label">gtk-apply</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="use_stock">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+  <object class="GtkListStore" id="mode_store">
+    <columns>
+      <!-- column-name mode -->
+      <column type="gpointer"/>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+</interface>
diff --git a/capplets/display/display-netbook-and-external.png b/capplets/display/display-netbook-and-external.png
new file mode 100644
index 0000000..cffc287
Binary files /dev/null and b/capplets/display/display-netbook-and-external.png differ
diff --git a/capplets/display/display-netbook-only.png b/capplets/display/display-netbook-only.png
new file mode 100644
index 0000000..eb73856
Binary files /dev/null and b/capplets/display/display-netbook-only.png differ



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]