Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Meego:Netbook:1.1
gnome-control-center-netbook
0005-Add-minimal-display-capplet.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0005-Add-minimal-display-capplet.patch of Package gnome-control-center-netbook
From 968d0f93e846cd262e1048025ffc51076835d933 Mon Sep 17 00:00:00 2001 From: Thomas Wood <thomas.wood@intel.com> Date: Thu, 26 Aug 2010 16:04:37 +0100 Subject: [PATCH 05/13] Add minimal display capplet --- capplets/display/Makefile.am | 33 ++- capplets/display/cc-display-minimal-page.c | 768 ++++++++++++++++++++++++++++ capplets/display/cc-display-page.h | 55 ++ capplets/display/cc-display-panel.c | 177 +++++++ capplets/display/cc-display-panel.h | 54 ++ capplets/display/display-minimal.ui | 168 ++++++ capplets/display/display-module.c | 42 ++ configure.ac | 19 +- po/POTFILES.in | 3 + 9 files changed, 1316 insertions(+), 3 deletions(-) create mode 100644 capplets/display/cc-display-minimal-page.c create mode 100644 capplets/display/cc-display-page.h create mode 100644 capplets/display/cc-display-panel.c create mode 100644 capplets/display/cc-display-panel.h create mode 100644 capplets/display/display-minimal.ui create mode 100644 capplets/display/display-module.c diff --git a/capplets/display/Makefile.am b/capplets/display/Makefile.am index 86226db..9bfd715 100644 --- a/capplets/display/Makefile.am +++ b/capplets/display/Makefile.am @@ -2,7 +2,7 @@ cappletname = display uidir = $(pkgdatadir)/ui -dist_ui_DATA = display-capplet.ui +dist_ui_DATA = display-capplet.ui display-minimal.ui bin_PROGRAMS = gnome-display-properties @@ -18,6 +18,37 @@ gnome_display_properties_LDADD = \ $(GNOMECC_CAPPLETS_LIBS) \ $(DISPLAY_CAPPLET_LIBS) + +ccmodulesdir = $(EXTENSIONSDIR) +ccmodules_LTLIBRARIES = libdisplay.la + +libdisplay_la_SOURCES = \ + display-module.c \ + cc-display-page.h \ + cc-display-minimal-page.c \ + cc-display-panel.h \ + cc-display-panel.c \ + $(NULL) + + +libdisplay_la_LDFLAGS = \ + $(EXTENSION_LIBTOOL_FLAGS) \ + $(NULL) + +libdisplay_la_LIBADD = \ + $(EXTENSION_LIBS) \ + $(EXTENSION_COMMON_LIBS) \ + $(DISPLAY_CAPPLET_LIBS) \ + $(NULL) + +libdisplay_la_CFLAGS = \ + -DPIXMAPDIR="\"$(pixmapdir)\"" \ + $(EXTENSION_CFLAGS) \ + $(EXTENSION_COMMON_CFLAGS) \ + $(NULL) + +libdisplay_la_LIBTOOLFLAGS = --tag=disable-static + @INTLTOOL_DESKTOP_RULE@ icons16dir = $(datadir)/icons/hicolor/16x16/apps diff --git a/capplets/display/cc-display-minimal-page.c b/capplets/display/cc-display-minimal-page.c new file mode 100644 index 0000000..0a0a7ff --- /dev/null +++ b/capplets/display/cc-display-minimal-page.c @@ -0,0 +1,768 @@ +/* -*- 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) + +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 +on_resolution_changed (GtkComboBox *combo, gpointer user_data) +{ + CcDisplayPage *page = CC_DISPLAY_PAGE (user_data); + GtkTreeModel *model; + GtkTreeIter iter; + GnomeRRMode *mode; + + if (!gtk_combo_box_get_active_iter (combo, &iter)) + return; + + model = gtk_combo_box_get_model (combo); + gtk_tree_model_get (model, &iter, COL_MODE, &mode, COL_END); + g_assert (mode); + + page->priv->external_output->width = gnome_rr_mode_get_width (mode); + page->priv->external_output->height = gnome_rr_mode_get_height (mode); +} + +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"); + g_signal_connect (page->priv->resolution_combo, "changed", G_CALLBACK (on_resolution_changed), page); + 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; + + 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/cc-display-page.h b/capplets/display/cc-display-page.h new file mode 100644 index 0000000..81e9759 --- /dev/null +++ b/capplets/display/cc-display-page.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Red Hat, Inc. + * + * 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. + * + */ + +#ifndef __CC_DISPLAY_PAGE_H +#define __CC_DISPLAY_PAGE_H + +#include <gtk/gtk.h> +#include "cc-page.h" + +G_BEGIN_DECLS + +#define CC_TYPE_DISPLAY_PAGE (cc_display_page_get_type ()) +#define CC_DISPLAY_PAGE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CC_TYPE_DISPLAY_PAGE, CcDisplayPage)) +#define CC_DISPLAY_PAGE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CC_TYPE_DISPLAY_PAGE, CcDisplayPageClass)) +#define CC_IS_DISPLAY_PAGE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CC_TYPE_DISPLAY_PAGE)) +#define CC_IS_DISPLAY_PAGE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CC_TYPE_DISPLAY_PAGE)) +#define CC_DISPLAY_PAGE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CC_TYPE_DISPLAY_PAGE, CcDisplayPageClass)) + +typedef struct CcDisplayPagePrivate CcDisplayPagePrivate; + +typedef struct +{ + CcPage parent; + CcDisplayPagePrivate *priv; +} CcDisplayPage; + +typedef struct +{ + CcPageClass parent_class; +} CcDisplayPageClass; + +GType cc_display_page_get_type (void); + +CcPage * cc_display_page_new (void); + +G_END_DECLS + +#endif /* __CC_DISPLAY_PAGE_H */ diff --git a/capplets/display/cc-display-panel.c b/capplets/display/cc-display-panel.c new file mode 100644 index 0000000..f64e594 --- /dev/null +++ b/capplets/display/cc-display-panel.c @@ -0,0 +1,177 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Red Hat, Inc. + * + * 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 <stdlib.h> +#include <stdio.h> + +#include <gtk/gtk.h> +#include <gio/gio.h> +#include <glib/gi18n-lib.h> + +#include <gconf/gconf-client.h> + +#include "cc-display-panel.h" +#include "cc-display-page.h" + +#define CC_DISPLAY_PANEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_DISPLAY_PANEL, CcDisplayPanelPrivate)) + +#define WID(s) GTK_WIDGET (gtk_builder_get_object (builder, s)) + +struct CcDisplayPanelPrivate +{ + GtkWidget *notebook; + CcPage *display_page; +}; + +enum { + PROP_0, +}; + +static void cc_display_panel_class_init (CcDisplayPanelClass *klass); +static void cc_display_panel_init (CcDisplayPanel *display_panel); +static void cc_display_panel_finalize (GObject *object); + +G_DEFINE_DYNAMIC_TYPE (CcDisplayPanel, cc_display_panel, CC_TYPE_PANEL) + +static void +cc_display_panel_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +cc_display_panel_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +setup_panel (CcDisplayPanel *panel) +{ + GtkWidget *label; + char *display_name; + + panel->priv->notebook = gtk_notebook_new (); + gtk_container_add (GTK_CONTAINER (panel), panel->priv->notebook); + gtk_widget_show (panel->priv->notebook); + + panel->priv->display_page = cc_display_page_new (); + g_object_get (panel->priv->display_page, + "display-name", &display_name, + NULL); + label = gtk_label_new (display_name); + g_free (display_name); + gtk_notebook_append_page (GTK_NOTEBOOK (panel->priv->notebook), + GTK_WIDGET (panel->priv->display_page), + label); + gtk_widget_show (GTK_WIDGET (panel->priv->display_page)); + + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (panel->priv->notebook), + FALSE); + + g_object_set (panel, + "current-page", panel->priv->display_page, + NULL); +} + +static GObject * +cc_display_panel_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + CcDisplayPanel *display_panel; + + display_panel = CC_DISPLAY_PANEL (G_OBJECT_CLASS (cc_display_panel_parent_class)->constructor (type, + n_construct_properties, + construct_properties)); + g_object_set (display_panel, + "display-name", _("Display"), + "id", "display-properties.desktop", + NULL); + + setup_panel (display_panel); + + return G_OBJECT (display_panel); +} + +static void +cc_display_panel_class_init (CcDisplayPanelClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = cc_display_panel_get_property; + object_class->set_property = cc_display_panel_set_property; + object_class->constructor = cc_display_panel_constructor; + object_class->finalize = cc_display_panel_finalize; + + g_type_class_add_private (klass, sizeof (CcDisplayPanelPrivate)); +} + +static void +cc_display_panel_class_finalize (CcDisplayPanelClass *klass) +{ +} + +static void +cc_display_panel_init (CcDisplayPanel *panel) +{ + panel->priv = CC_DISPLAY_PANEL_GET_PRIVATE (panel); +} + +static void +cc_display_panel_finalize (GObject *object) +{ + CcDisplayPanel *display_panel; + + g_return_if_fail (object != NULL); + g_return_if_fail (CC_IS_DISPLAY_PANEL (object)); + + display_panel = CC_DISPLAY_PANEL (object); + + g_return_if_fail (display_panel->priv != NULL); + + G_OBJECT_CLASS (cc_display_panel_parent_class)->finalize (object); +} + +void +cc_display_panel_register (GIOModule *module) +{ + cc_display_panel_register_type (G_TYPE_MODULE (module)); + g_io_extension_point_implement (CC_PANEL_EXTENSION_POINT_NAME, + CC_TYPE_DISPLAY_PANEL, + "display", + 10); +} diff --git a/capplets/display/cc-display-panel.h b/capplets/display/cc-display-panel.h new file mode 100644 index 0000000..0f92dbe --- /dev/null +++ b/capplets/display/cc-display-panel.h @@ -0,0 +1,54 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Red Hat, Inc. + * + * 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. + * + */ + +#ifndef __CC_DISPLAY_PANEL_H +#define __CC_DISPLAY_PANEL_H + +#include <gtk/gtk.h> +#include "cc-panel.h" + +G_BEGIN_DECLS + +#define CC_TYPE_DISPLAY_PANEL (cc_display_panel_get_type ()) +#define CC_DISPLAY_PANEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CC_TYPE_DISPLAY_PANEL, CcDisplayPanel)) +#define CC_DISPLAY_PANEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CC_TYPE_DISPLAY_PANEL, CcDisplayPanelClass)) +#define CC_IS_DISPLAY_PANEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CC_TYPE_DISPLAY_PANEL)) +#define CC_IS_DISPLAY_PANEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CC_TYPE_DISPLAY_PANEL)) +#define CC_DISPLAY_PANEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CC_TYPE_DISPLAY_PANEL, CcDisplayPanelClass)) + +typedef struct CcDisplayPanelPrivate CcDisplayPanelPrivate; + +typedef struct +{ + CcPanel parent; + CcDisplayPanelPrivate *priv; +} CcDisplayPanel; + +typedef struct +{ + CcPanelClass parent_class; +} CcDisplayPanelClass; + +GType cc_display_panel_get_type (void); +void cc_display_panel_register (GIOModule *module); + +G_END_DECLS + +#endif /* __CC_DISPLAY_PANEL_H */ 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-module.c b/capplets/display/display-module.c new file mode 100644 index 0000000..4291743 --- /dev/null +++ b/capplets/display/display-module.c @@ -0,0 +1,42 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Red Hat, Inc. + * + * 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.h> +#include <glib/gi18n-lib.h> +#include <gmodule.h> +#include <gio/gio.h> + +#include "cc-display-panel.h" + +void +g_io_module_load (GIOModule *module) +{ + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + + cc_display_panel_register (module); +} + +void +g_io_module_unload (GIOModule *module) +{ +} diff --git a/configure.ac b/configure.ac index 1278b56..3d072e4 100644 --- a/configure.ac +++ b/configure.ac @@ -171,8 +171,23 @@ PKG_CHECK_MODULES(FONT_VIEWER, $COMMON_MODULES $xft_modules) PKG_CHECK_MODULES(AT_CAPPLET, $COMMON_MODULES) -PKG_CHECK_MODULES(DISPLAY_CAPPLET, $COMMON_MODULES) -DISPLAY_CAPPLET_LIBS="$DISPLAY_CAPPLET_LIBS" +dnl +dnl Check for XRandR, needed for display capplet +dnl + +have_randr=no +AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration, + [AC_CHECK_HEADER(X11/extensions/Xrandr.h, + have_randr=yes + RANDR_LIBS="-lXrandr -lXrender" + AC_DEFINE(HAVE_RANDR, 1, [Define if Xrandr extension is available]), + :, [#include <X11/Xlib.h>])], : , + -lXrandr -lXrender $x_libs) +AM_CONDITIONAL(HAVE_RANDR, [test $have_randr = yes]) + +PKG_CHECK_MODULES(DISPLAY_CAPPLET, $COMMON_MODULES mx-gtk-1.0) + +DISPLAY_CAPPLET_LIBS="$DISPLAY_CAPPLET_LIBS $RANDR_LIBS $DBUS_LIBS" CAPPLET_LIBS="$CAPPLET_LIBS $x_libs" GNOMECC_LIBS="$GNOMECC_LIBS $x_libs" diff --git a/po/POTFILES.in b/po/POTFILES.in index 4296e9d..7903006 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -41,6 +41,9 @@ capplets/default-applications/gnome-at-session.desktop.in.in capplets/default-applications/gnome-da-capplet.c [type: gettext/glade]capplets/default-applications/gnome-default-applications-properties.ui capplets/default-applications/gnome-default-applications.xml.in +capplets/display/cc-display-minimal-page.c +capplets/display/cc-display-panel.c +capplets/display/display-minimal.ui [type: gettext/glade]capplets/display/display-capplet.ui capplets/display/display-properties.desktop.in.in capplets/display/xrandr-capplet.c -- 1.7.2.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor