[gnome-control-center] display: initial implementation of the new design
- From: Thomas Wood <thos src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center] display: initial implementation of the new design
- Date: Tue, 20 Aug 2013 17:30:58 +0000 (UTC)
commit b4a16be646b3c2f7b5b2eb8c4ceeed9dc84d7c8e
Author: Thomas Wood <thomas wood intel com>
Date: Tue Aug 20 14:48:04 2013 +0100
display: initial implementation of the new design
Add an initial implementation of the new design for the display panel. The
display previews and presentation mode are not yet fully implemented.
https://bugzilla.gnome.org/show_bug.cgi?id=706115
configure.ac | 2 +-
panels/display/cc-display-panel.c | 2442 +++++++++++++++----------------------
panels/display/cc-display-panel.h | 3 +
panels/display/cc-rr-labeler.c | 152 +--
panels/display/cc-rr-labeler.h | 2 -
panels/display/display-capplet.ui | 578 ++++++---
6 files changed, 1393 insertions(+), 1786 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 799df81..6a04dba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -94,7 +94,7 @@ NETWORK_MANAGER_REQUIRED_VERSION=0.9.8
NETWORK_MANAGER_APPLET_REQUIRED_VERSION=0.9.7.995
MODEM_MANAGER_REQUIRED_VERSION=0.7
LIBNOTIFY_REQUIRED_VERSION=0.7.3
-GNOME_DESKTOP_REQUIRED_VERSION=3.9.0
+GNOME_DESKTOP_REQUIRED_VERSION=3.9.90
SCHEMAS_REQUIRED_VERSION=3.7.2.2
LIBWACOM_REQUIRED_VERSION=0.7
CLUTTER_REQUIRED_VERSION=1.11.3
diff --git a/panels/display/cc-display-panel.c b/panels/display/cc-display-panel.c
index ff585e2..2424037 100644
--- a/panels/display/cc-display-panel.c
+++ b/panels/display/cc-display-panel.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007, 2008 Red Hat, Inc.
+ * Copyright (C) 2013 Intel, 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
@@ -13,17 +14,10 @@
*
* 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.
- *
- * Author: Soren Sandmann <sandmann redhat com>
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
-#include <config.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/wait.h>
-
#include "cc-display-panel.h"
#include "cc-display-resources.h"
@@ -32,10 +26,10 @@
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <libgnome-desktop/gnome-rr.h>
#include <libgnome-desktop/gnome-rr-config.h>
-#include <gdk/gdkx.h>
-#include <X11/Xlib.h>
#include <glib/gi18n.h>
+#include <stdlib.h>
#include <gdesktop-enums.h>
+#include <math.h>
#include "cc-rr-labeler.h"
#include <libupower-glib/upower.h>
@@ -49,52 +43,38 @@ CC_PANEL_REGISTER (CcDisplayPanel, cc_display_panel)
#define TOP_BAR_HEIGHT 10
-#define CLOCK_SCHEMA "org.gnome.desktop.interface"
-#define CLOCK_FORMAT_KEY "clock-format"
-
/* The minimum supported size for the panel, see:
* http://live.gnome.org/Design/SystemSettings */
#define MINIMUM_WIDTH 675
#define MINIMUM_HEIGHT 530
-enum {
- TEXT_COL,
- WIDTH_COL,
- HEIGHT_COL,
- RATE_COL,
- SORT_COL,
- ROTATION_COL,
- NUM_COLS
+
+#define DISPLAY_PREVIEW_SETUP_HEIGHT 140
+#define DISPLAY_PREVIEW_LIST_HEIGHT 55
+
+enum
+{
+ DISPLAY_MODE_PRIMARY,
+ DISPLAY_MODE_SECONDARY,
+ /* DISPLAY_MODE_PRESENTATION, */
+ DISPLAY_MODE_MIRROR
};
struct _CcDisplayPanelPrivate
{
- GnomeRRScreen *screen;
- GnomeRRConfig *current_configuration;
- CcRRLabeler *labeler;
- GnomeRROutputInfo *current_output;
+ GnomeRRScreen *screen;
+ GnomeRRConfig *current_configuration;
+ CcRRLabeler *labeler;
+ GnomeRROutputInfo *current_output;
- GSettings *clock_settings;
- GtkBuilder *builder;
guint focus_id;
+ guint screen_changed_handler_id;
- GtkWidget *panel;
- GtkWidget *current_monitor_event_box;
- GtkWidget *current_monitor_label;
- GtkWidget *monitor_switch;
- GtkListStore *resolution_store;
- GtkWidget *resolution_combo;
- GtkWidget *rotation_combo;
- GtkWidget *clone_checkbox;
- GtkWidget *clone_label;
- GtkWidget *show_icon_checkbox;
-
- /* We store the event timestamp when the Apply button is clicked */
- guint32 apply_button_clicked_timestamp;
-
- GtkWidget *area;
- gboolean ignore_gui_changes;
- gboolean dragging_top_bar;
+ GtkWidget *displays_listbox;
+ GtkWidget *arrange_button;
+ GtkWidget *res_combo;
+ GtkWidget *rotate_left_button;
+ GtkWidget *rotate_right_button;
UpClient *up_client;
gboolean lid_is_closed;
@@ -108,85 +88,52 @@ typedef struct
int output_y;
} GrabInfo;
-static void rebuild_gui (CcDisplayPanel *self);
-static void on_clone_changed (GtkWidget *box, gpointer data);
-static gboolean output_overlaps (GnomeRROutputInfo *output, GnomeRRConfig *config);
-static void select_current_output_from_dialog_position (CcDisplayPanel *self);
-static void monitor_switch_active_cb (GObject *object, GParamSpec *pspec, gpointer data);
-static void get_geometry (GnomeRROutputInfo *output, int *w, int *h);
-static gboolean get_clone_size (GnomeRRScreen *screen, int *width, int *height);
-static gboolean output_info_supports_mode (CcDisplayPanel *self, GnomeRROutputInfo *info, int width, int
height);
-static char *make_resolution_string (int width, int height);
-static GObject *cc_display_panel_constructor (GType gtype,
- guint n_properties,
- GObjectConstructParam *properties);
-static void on_screen_changed (GnomeRRScreen *scr, gpointer data);
-
-static void
-cc_display_panel_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id)
- {
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
+static GHashTable *output_ids;
-static void
-cc_display_panel_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+gint
+cc_display_panel_get_output_id (GnomeRROutputInfo *output)
{
- switch (property_id)
- {
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
+ if (output_ids)
+ return GPOINTER_TO_INT (g_hash_table_lookup (output_ids, output));
+ else
+ return 0;
}
static void
cc_display_panel_dispose (GObject *object)
{
CcDisplayPanelPrivate *priv = CC_DISPLAY_PANEL (object)->priv;
-
- g_clear_object (&priv->up_client);
-
- G_OBJECT_CLASS (cc_display_panel_parent_class)->dispose (object);
-}
-
-static void
-cc_display_panel_finalize (GObject *object)
-{
- CcDisplayPanel *self;
CcShell *shell;
GtkWidget *toplevel;
- self = CC_DISPLAY_PANEL (object);
-
- g_signal_handlers_disconnect_by_func (self->priv->screen, on_screen_changed, self);
- g_object_unref (self->priv->screen);
- g_object_unref (self->priv->builder);
-
- if (self->priv->clock_settings != NULL)
- g_object_unref (self->priv->clock_settings);
+ if (output_ids)
+ {
+ g_hash_table_destroy (output_ids);
+ output_ids = NULL;
+ }
- shell = cc_panel_get_shell (CC_PANEL (self));
- if (shell != NULL)
+ if (priv->focus_id)
{
+ shell = cc_panel_get_shell (CC_PANEL (object));
toplevel = cc_shell_get_toplevel (shell);
if (toplevel != NULL)
g_signal_handler_disconnect (G_OBJECT (toplevel),
- self->priv->focus_id);
+ priv->focus_id);
+ cc_rr_labeler_hide (priv->labeler);
+ priv->focus_id = 0;
}
+ g_clear_object (&priv->labeler);
- cc_rr_labeler_hide (self->priv->labeler);
- g_object_unref (self->priv->labeler);
+ if (priv->screen_changed_handler_id)
+ {
+ g_signal_handler_disconnect (priv->screen, priv->screen_changed_handler_id);
+ priv->screen_changed_handler_id = 0;
+ }
+
+ g_clear_object (&priv->screen);
+ g_clear_object (&priv->up_client);
- G_OBJECT_CLASS (cc_display_panel_parent_class)->finalize (object);
+ G_OBJECT_CLASS (cc_display_panel_parent_class)->dispose (object);
}
static const char *
@@ -205,35 +152,7 @@ cc_display_panel_class_init (CcDisplayPanelClass *klass)
panel_class->get_help_uri = cc_display_panel_get_help_uri;
- object_class->constructor = cc_display_panel_constructor;
- object_class->get_property = cc_display_panel_get_property;
- object_class->set_property = cc_display_panel_set_property;
object_class->dispose = cc_display_panel_dispose;
- object_class->finalize = cc_display_panel_finalize;
-}
-
-static void
-error_message (CcDisplayPanel *self, const char *primary_text, const char *secondary_text)
-{
- GtkWidget *toplevel;
- GtkWidget *dialog;
-
- if (self && self->priv->panel)
- toplevel = gtk_widget_get_toplevel (self->priv->panel);
- else
- toplevel = NULL;
-
- dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- "%s", primary_text);
-
- if (secondary_text)
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", secondary_text);
-
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
}
static gboolean
@@ -250,33 +169,6 @@ should_show_resolution (gint output_width,
return FALSE;
}
-static void
-on_screen_changed (GnomeRRScreen *scr,
- gpointer data)
-{
- GnomeRRConfig *current;
- CcDisplayPanel *self = data;
-
- current = gnome_rr_config_new_current (self->priv->screen, NULL);
- gnome_rr_config_ensure_primary (current);
-
- if (self->priv->current_configuration)
- g_object_unref (self->priv->current_configuration);
-
- self->priv->current_configuration = current;
- self->priv->current_output = NULL;
-
- if (self->priv->labeler) {
- cc_rr_labeler_hide (self->priv->labeler);
- g_object_unref (self->priv->labeler);
- }
-
- self->priv->labeler = cc_rr_labeler_new (self->priv->current_configuration);
- if (gtk_widget_has_focus (self->priv->panel))
- cc_rr_labeler_show (self->priv->labeler);
-
- select_current_output_from_dialog_position (self);
-}
static void
on_viewport_changed (FooScrollArea *scroll_area,
@@ -291,693 +183,274 @@ on_viewport_changed (FooScrollArea *scroll_area,
}
static void
-layout_set_font (PangoLayout *layout, const char *font)
+paint_output (cairo_t *cr,
+ GnomeRRConfig *configuration,
+ GnomeRROutputInfo *output,
+ gint num,
+ gint allocated_width,
+ gint allocated_height)
{
- PangoFontDescription *desc =
- pango_font_description_from_string (font);
-
- if (desc)
+ GnomeRRRotation rotation;
+ cairo_text_extents_t extents;
+ gint x, y, width, height;
+ gint max_extent;
+ gboolean active;
+
+ active = gnome_rr_output_info_is_active (output);
+ if (active)
+ gnome_rr_output_info_get_geometry (output, NULL, NULL, &width, &height);
+ else
{
- pango_layout_set_font_description (layout, desc);
-
- pango_font_description_free (desc);
+ width = gnome_rr_output_info_get_preferred_width (output);
+ height = gnome_rr_output_info_get_preferred_height (output);
}
-}
-
-static void
-clear_combo (GtkWidget *widget)
-{
- GtkComboBox *box = GTK_COMBO_BOX (widget);
- GtkTreeModel *model = gtk_combo_box_get_model (box);
- GtkListStore *store = GTK_LIST_STORE (model);
-
- gtk_list_store_clear (store);
-}
-typedef struct
-{
- const char *text;
- gboolean found;
- GtkTreeIter iter;
-} ForeachInfo;
+ rotation = gnome_rr_output_info_get_rotation (output);
-static gboolean
-foreach (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
-{
- ForeachInfo *info = data;
- char *text = NULL;
+ x = y = 0;
- gtk_tree_model_get (model, iter, TEXT_COL, &text, -1);
+ if ((rotation & GNOME_RR_ROTATION_90) || (rotation & GNOME_RR_ROTATION_270))
+ {
+ gint tmp;
- g_assert (text != NULL);
+ /* swap width and height */
+ tmp = width;
+ width = height;
+ height = tmp;
+ }
- if (strcmp (info->text, text) == 0)
+ /* scale to fit allocation */
+ if (width / (double) height < allocated_width / (double) allocated_height)
{
- info->found = TRUE;
- info->iter = *iter;
- return TRUE;
+ width = allocated_height * (width / (double) height);
+ height = allocated_height;
+ }
+ else
+ {
+ height = allocated_width * (height / (double) width);
+ width = allocated_width;
}
- return FALSE;
-}
-
-static void
-add_key (GtkTreeModel *model,
- const char *text,
- gboolean preferred,
- int width, int height, int rate,
- GnomeRRRotation rotation)
-{
- ForeachInfo info;
-
- info.text = text;
- info.found = FALSE;
- gtk_tree_model_foreach (model, foreach, &info);
+ x = (allocated_width / 2.0) - (width / 2.0);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_rectangle (cr, x, y, width, height);
+ cairo_fill (cr);
- if (!info.found)
+ if (gnome_rr_output_info_get_primary (output)
+ || gnome_rr_config_get_clone (configuration))
{
- GtkTreeIter iter;
- g_debug ("adding %s with rate %d Hz", text, rate);
- gtk_list_store_insert_with_values (GTK_LIST_STORE (model), &iter, -1,
- TEXT_COL, text,
- WIDTH_COL, width,
- HEIGHT_COL, height,
- RATE_COL, rate,
- SORT_COL, width * 10000 + height,
- ROTATION_COL, rotation,
- -1);
- return;
- }
+ gint top_bar_height;
- /* Look, the preferred output, replace the old one */
- if (preferred)
- {
- g_debug ("replacing %s with rate %d Hz (preferred mode)", text, rate);
- gtk_list_store_set (GTK_LIST_STORE (model), &info.iter,
- RATE_COL, rate,
- -1);
- return;
- }
+ top_bar_height = height / 12;
- {
- int old_rate;
+ y += top_bar_height;
+ height -= top_bar_height;
+ }
- gtk_tree_model_get (model, &info.iter,
- RATE_COL, &old_rate,
- -1);
+ cairo_set_source_rgb (cr, 0.7, 0.7, 0.7);
+ cairo_rectangle (cr, x + 1, y + 1, width - 2, height - 2);
+ cairo_fill (cr);
- /* Higher refresh rate */
- if (rate > old_rate)
+ if (num > 0)
{
- g_debug ("replacing %s with rate %d Hz (old rate: %d)", text, rate, old_rate);
- gtk_list_store_set (GTK_LIST_STORE (model), &info.iter,
- RATE_COL, rate,
- -1);
- return;
- }
- }
+ gchar *number_str;
- g_debug ("not adding %s with rate %d Hz (higher rate already there)", text, rate);
-}
+ number_str = g_strdup_printf ("%d", num);
+ cairo_text_extents (cr, number_str, &extents);
-static void
-add_mode (CcDisplayPanel *self,
- GnomeRRMode *mode,
- gint output_width,
- gint output_height,
- guint preferred_id)
-{
- int width, height, rate;
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ max_extent = MAX (extents.width, extents.height);
+ cairo_rectangle (cr, x + 5, y + 5, max_extent + 10, max_extent + 10);
+ cairo_fill (cr);
- width = gnome_rr_mode_get_width (mode);
- height = gnome_rr_mode_get_height (mode);
- rate = gnome_rr_mode_get_freq (mode);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_move_to (cr, x + 10, y + 10 + extents.height);
+ cairo_show_text (cr, number_str);
- if (should_show_resolution (output_width, output_height, width, height))
- {
- char *text;
- gboolean preferred;
-
- preferred = (gnome_rr_mode_get_id (mode) == preferred_id);
- text = make_resolution_string (width, height);
- add_key (gtk_combo_box_get_model (GTK_COMBO_BOX (self->priv->resolution_combo)),
- text, preferred, width, height, rate, -1);
- g_free (text);
+ g_free (number_str);
}
}
-
-
static gboolean
-combo_select (GtkWidget *widget, const char *text)
+display_preview_draw (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer data)
{
- GtkComboBox *box = GTK_COMBO_BOX (widget);
- GtkTreeModel *model = gtk_combo_box_get_model (box);
- ForeachInfo info;
+ GnomeRROutputInfo *output;
+ GnomeRRConfig *config;
+ gint num, width, height;
- info.text = text;
- info.found = FALSE;
+ output = g_object_get_data (G_OBJECT (widget), "output");
+ config = g_object_get_data (G_OBJECT (widget), "config");
+ num = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "number"));
- gtk_tree_model_foreach (model, foreach, &info);
+ width = gtk_widget_get_allocated_width (widget);
+ height = gtk_widget_get_allocated_height (widget);
- if (!info.found)
- return FALSE;
+ paint_output (cr, config, output, num, width, height);
- gtk_combo_box_set_active_iter (box, &info.iter);
return TRUE;
}
-static GnomeRRMode **
-get_current_modes (CcDisplayPanel *self)
+static GtkWidget*
+display_preview_new (GnomeRROutputInfo *output,
+ GnomeRRConfig *config,
+ gint num,
+ gint base_height)
{
- GnomeRROutput *output;
+ GtkWidget *area;
+ gint width, height, x, y;
+ gboolean active;
- if (gnome_rr_config_get_clone (self->priv->current_configuration))
- {
- return gnome_rr_screen_list_clone_modes (self->priv->screen);
- }
+ active = gnome_rr_output_info_is_active (output);
+ if (active)
+ gnome_rr_output_info_get_geometry (output, &x, &y, &width, &height);
else
{
- if (!self->priv->current_output)
- return NULL;
-
- output = gnome_rr_screen_get_output_by_name (self->priv->screen,
- gnome_rr_output_info_get_name
(self->priv->current_output));
-
- if (!output)
- return NULL;
-
- return gnome_rr_output_list_modes (output);
- }
-}
-
-static void
-rebuild_rotation_combo (CcDisplayPanel *self)
-{
- typedef struct
- {
- GnomeRRRotation rotation;
- const char * name;
- } RotationInfo;
- static const RotationInfo rotations[] = {
- { GNOME_RR_ROTATION_0, NC_("display panel, rotation", "Normal") },
- { GNOME_RR_ROTATION_90, NC_("display panel, rotation", "Counterclockwise") },
- { GNOME_RR_ROTATION_270, NC_("display panel, rotation", "Clockwise") },
- { GNOME_RR_ROTATION_180, NC_("display panel, rotation", "180 Degrees") },
- };
- const char *selection;
- GnomeRRRotation current;
- int i;
-
- clear_combo (self->priv->rotation_combo);
-
- gtk_widget_set_sensitive (self->priv->rotation_combo,
- self->priv->current_output && gnome_rr_output_info_is_active
(self->priv->current_output));
-
- if (!self->priv->current_output)
- return;
-
- current = gnome_rr_output_info_get_rotation (self->priv->current_output);
-
- selection = NULL;
- for (i = 0; i < G_N_ELEMENTS (rotations); ++i)
- {
- const RotationInfo *info = &(rotations[i]);
-
- gnome_rr_output_info_set_rotation (self->priv->current_output, info->rotation);
-
- /* NULL-GError --- FIXME: we should say why this rotation is not available! */
- if (gnome_rr_config_applicable (self->priv->current_configuration, self->priv->screen, NULL))
- {
- add_key (gtk_combo_box_get_model (GTK_COMBO_BOX (self->priv->rotation_combo)), g_dpgettext2 (NULL,
"display panel, rotation", info->name), FALSE, 0, 0, 0, info->rotation);
-
- if (info->rotation == current)
- selection = g_dpgettext2 (NULL, "display panel, rotation", info->name);
- }
- }
-
- gnome_rr_output_info_set_rotation (self->priv->current_output, current);
-
- if (!(selection && combo_select (self->priv->rotation_combo, selection)))
- gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->rotation_combo), 0);
-}
-
-static int
-count_active_outputs (CcDisplayPanel *self)
-{
- int i, count = 0;
- GnomeRROutputInfo **outputs = gnome_rr_config_get_outputs (self->priv->current_configuration);
-
- for (i = 0; outputs[i] != NULL; ++i)
- {
- if (gnome_rr_output_info_is_active (outputs[i]))
- count++;
+ width = gnome_rr_output_info_get_preferred_width (output);
+ height = gnome_rr_output_info_get_preferred_height (output);
}
- return count;
-}
-
-#if 0
-static int
-count_all_outputs (GnomeRRConfig *config)
-{
- int i;
- GnomeRROutputInfo **outputs = gnome_rr_config_get_outputs (config);
-
- for (i = 0; outputs[i] != NULL; i++)
- ;
-
- return i;
-}
-#endif
+ area = gtk_drawing_area_new ();
+ g_signal_connect (area, "draw", G_CALLBACK (display_preview_draw), NULL);
-/* Computes whether "Mirror displays" (clone mode) is supported based on these criteria:
- *
- * 1. There is an available size for cloning.
- *
- * 2. There are 2 or more connected outputs that support that size.
- */
-static gboolean
-mirror_screens_is_supported (CcDisplayPanel *self)
-{
- int clone_width, clone_height;
- gboolean have_clone_size;
- gboolean mirror_is_supported;
+ gtk_widget_set_size_request (area, base_height * (width / (gdouble) height), base_height);
- mirror_is_supported = FALSE;
+ gtk_widget_set_valign (area, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (area, GTK_ALIGN_CENTER);
- have_clone_size = get_clone_size (self->priv->screen, &clone_width, &clone_height);
+ g_object_set_data (G_OBJECT (area), "output", output);
+ g_object_set_data (G_OBJECT (area), "config", config);
+ g_object_set_data (G_OBJECT (area), "number", GINT_TO_POINTER (num));
- if (have_clone_size) {
- int i;
- int num_outputs_with_clone_size;
- GnomeRROutputInfo **outputs = gnome_rr_config_get_outputs (self->priv->current_configuration);
-
- num_outputs_with_clone_size = 0;
-
- for (i = 0; outputs[i] != NULL; i++)
- {
- /* We count the connected outputs that support the clone size. It
- * doesn't matter if those outputs aren't actually On currently; we
- * will turn them on in on_clone_changed().
- */
- if (gnome_rr_output_info_is_connected (outputs[i]) && output_info_supports_mode (self, outputs[i],
clone_width, clone_height))
- num_outputs_with_clone_size++;
- }
-
- if (num_outputs_with_clone_size >= 2)
- mirror_is_supported = TRUE;
- }
-
- return mirror_is_supported;
+ return area;
}
static void
-rebuild_mirror_screens (CcDisplayPanel *self)
+on_screen_changed (CcDisplayPanel *panel)
{
- gboolean mirror_is_active;
- gboolean mirror_is_supported;
-
- g_signal_handlers_block_by_func (self->priv->clone_checkbox, G_CALLBACK (on_clone_changed), self);
-
- mirror_is_active = self->priv->current_configuration && gnome_rr_config_get_clone
(self->priv->current_configuration);
-
- /* If mirror_is_active, then it *must* be possible to turn mirroring off */
- mirror_is_supported = mirror_is_active || mirror_screens_is_supported (self);
-
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->priv->clone_checkbox), mirror_is_active);
- gtk_widget_set_sensitive (self->priv->clone_checkbox, mirror_is_supported);
- gtk_widget_set_sensitive (self->priv->clone_label, mirror_is_supported);
-
- g_signal_handlers_unblock_by_func (self->priv->clone_checkbox, G_CALLBACK (on_clone_changed), self);
-}
+ GnomeRRConfig *current;
+ CcDisplayPanelPrivate *priv = panel->priv;
+ GnomeRROutputInfo **outputs;
+ gint i, num_active_outputs = 0, num_connected_outputs = 0, number = 0;
+ gboolean clone, combined = FALSE;
+ GtkSizeGroup *sizegroup;
-static char *
-mirror_monitor_name (void)
-{
- /* Keep this string in sync with gnome-desktop/libgnome-desktop/gnome-rr-labeler.c */
+ gnome_rr_screen_refresh (priv->screen, NULL);
- /* Translators: this is the feature where what you see on your laptop's
- * screen is the same as your external projector. Here, "Mirrored" is being
- * used as an adjective. For example, the Spanish translation could be
- * "Pantallas en Espejo".
- */
- return g_strdup (_("Mirrored Displays"));
-}
+ current = gnome_rr_config_new_current (priv->screen, NULL);
+ gnome_rr_config_ensure_primary (current);
-static void
-rebuild_current_monitor_label (CcDisplayPanel *self)
-{
- char *str, *tmp;
- GdkRGBA color;
- gboolean use_color;
+ gtk_container_foreach (GTK_CONTAINER (priv->displays_listbox),
+ (GtkCallback) gtk_widget_destroy, NULL);
- if (self->priv->current_output)
- {
- if (gnome_rr_config_get_clone (self->priv->current_configuration))
- tmp = mirror_monitor_name ();
- else
- tmp = g_strdup (gnome_rr_output_info_get_display_name (self->priv->current_output));
+ if (priv->current_configuration)
+ g_object_unref (priv->current_configuration);
- str = g_strdup_printf ("<b>%s</b>", tmp);
- cc_rr_labeler_get_rgba_for_output (self->priv->labeler, self->priv->current_output, &color);
- use_color = TRUE;
- g_free (tmp);
- }
- else
- {
- str = g_strdup_printf ("<b>%s</b>", _("Monitor"));
- use_color = FALSE;
- }
+ priv->current_configuration = current;
- gtk_label_set_markup (GTK_LABEL (self->priv->current_monitor_label), str);
- g_free (str);
+ clone = gnome_rr_config_get_clone (current);
- if (use_color)
- {
- GdkRGBA black = { 0, 0, 0, 1.0 };
+ outputs = gnome_rr_config_get_outputs (current);
- gtk_widget_override_background_color (self->priv->current_monitor_event_box,
- gtk_widget_get_state_flags
(self->priv->current_monitor_event_box),
- &color);
+ g_hash_table_remove_all (output_ids);
- /* Make the label explicitly black. We don't want it to follow the
- * theme's colors, since the label is always shown against a light
- * pastel background. See bgo#556050
- */
- gtk_widget_override_color (self->priv->current_monitor_label,
- gtk_widget_get_state_flags (self->priv->current_monitor_label),
- &black);
- }
- else
+ /* count the number of active and connected outputs */
+ for (i = 0; outputs[i]; i++)
{
- /* Remove any modifications we did on the label's color */
- gtk_widget_override_color (self->priv->current_monitor_label,
- gtk_widget_get_state_flags (self->priv->current_monitor_label),
- NULL);
+ if (gnome_rr_output_info_is_active (outputs[i]))
+ num_active_outputs++;
+ num_connected_outputs++;
}
- gtk_event_box_set_visible_window (GTK_EVENT_BOX (self->priv->current_monitor_event_box), use_color);
-}
-
-static void
-rebuild_on_off_radios (CcDisplayPanel *self)
-{
- gboolean sensitive;
- gboolean on_active;
-
- g_signal_handlers_block_by_func (self->priv->monitor_switch, G_CALLBACK (monitor_switch_active_cb), self);
+ sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
- sensitive = FALSE;
- on_active = FALSE;
-
- if (!gnome_rr_config_get_clone (self->priv->current_configuration) && self->priv->current_output)
+ for (i = 0; outputs[i]; i++)
{
+ GtkWidget *row, *item, *preview, *label;
+ gboolean primary, active;
+ gint x, y, width, height;
+ const gchar *status;
gboolean display_closed = FALSE;
- if (self->priv->lid_is_closed)
+ if (priv->lid_is_closed)
{
GnomeRROutput *output;
- output = gnome_rr_screen_get_output_by_name (self->priv->screen,
- gnome_rr_output_info_get_name
(self->priv->current_output));
+ output = gnome_rr_screen_get_output_by_name (priv->screen,
+ gnome_rr_output_info_get_name (outputs[i]));
display_closed = gnome_rr_output_is_builtin_display (output);
}
- if ((count_active_outputs (self) > 1 || !gnome_rr_output_info_is_active (self->priv->current_output))
- && !display_closed)
- sensitive = TRUE;
- else
- sensitive = FALSE;
-
- on_active = gnome_rr_output_info_is_active (self->priv->current_output);
- }
-
- gtk_widget_set_sensitive (self->priv->monitor_switch, sensitive);
-
- gtk_switch_set_active (GTK_SWITCH (self->priv->monitor_switch), on_active);
-
- g_signal_handlers_unblock_by_func (self->priv->monitor_switch, G_CALLBACK (monitor_switch_active_cb),
self);
-}
-
-static char *
-make_resolution_string (int width, int height)
-{
- int ratio;
- const char *aspect = NULL;
-
- /* We use a number of Unicode characters below:
- * ∶ is U+2236 RATIO
- * is U+2009 THIN SPACE,
- * × is U+00D7 MULTIPLICATION SIGN
- */
- if (width && height) {
- if (width > height)
- ratio = width * 10 / height;
- else
- ratio = height * 10 / width;
-
- switch (ratio) {
- case 13:
- aspect = "4∶3";
- break;
- case 16:
- aspect = "16∶10";
- break;
- case 17:
- aspect = "16∶9";
- break;
- case 23:
- aspect = "21∶9";
- break;
- case 12:
- aspect = "5∶4";
- break;
- /* This catches 1.5625 as well (1600x1024) when maybe it shouldn't. */
- case 15:
- aspect = "3∶2";
- break;
- case 18:
- aspect = "9∶5";
- break;
- case 10:
- aspect = "1∶1";
- break;
- }
- }
-
- if (aspect != NULL)
- return g_strdup_printf ("%d × %d (%s)", width, height, aspect);
- else
- return g_strdup_printf ("%d × %d", width, height);
-}
-
-static void
-find_best_mode (GnomeRRMode **modes, int *out_width, int *out_height)
-{
- int i;
+ row = gtk_list_box_row_new ();
+ item = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (item), 12);
- *out_width = 0;
- *out_height = 0;
+ active = gnome_rr_output_info_is_active (outputs[i]);
- for (i = 0; modes[i] != NULL; i++)
- {
- int w, h;
+ gnome_rr_output_info_get_geometry (outputs[i], &x, &y, &width, &height);
- w = gnome_rr_mode_get_width (modes[i]);
- h = gnome_rr_mode_get_height (modes[i]);
-
- if (w * h > *out_width * *out_height)
+ if (!active)
{
- *out_width = w;
- *out_height = h;
+ width = gnome_rr_output_info_get_preferred_width (outputs[i]);
+ height = gnome_rr_output_info_get_preferred_height (outputs[i]);
}
- }
-}
-
-static void
-rebuild_resolution_combo (CcDisplayPanel *self)
-{
- int i;
- GnomeRRMode **modes;
- GnomeRRMode *mode;
- char *current;
- int output_width, output_height;
- guint32 preferred_id;
- GnomeRROutput *output;
-
- clear_combo (self->priv->resolution_combo);
-
- if (!(modes = get_current_modes (self))
- || !self->priv->current_output
- || !gnome_rr_output_info_is_active (self->priv->current_output))
- {
- gtk_widget_set_sensitive (self->priv->resolution_combo, FALSE);
- return;
- }
-
- g_assert (self->priv->current_output != NULL);
-
- gnome_rr_output_info_get_geometry (self->priv->current_output, NULL, NULL, &output_width, &output_height);
- g_assert (output_width != 0 && output_height != 0);
-
- gtk_widget_set_sensitive (self->priv->resolution_combo, TRUE);
-
- output = gnome_rr_screen_get_output_by_name (self->priv->screen,
- gnome_rr_output_info_get_name (self->priv->current_output));
- mode = gnome_rr_output_get_preferred_mode (output);
- preferred_id = gnome_rr_mode_get_id (mode);
-
- for (i = 0; modes[i] != NULL; ++i)
- add_mode (self, modes[i], output_width, output_height, preferred_id);
-
- /* And force the preferred mode in the drop-down (when not in clone mode)
- * https://bugzilla.gnome.org/show_bug.cgi?id=680969 */
- if (!gnome_rr_config_get_clone (self->priv->current_configuration))
- add_mode (self, mode, output_width, output_height, preferred_id);
-
- current = make_resolution_string (output_width, output_height);
- if (!combo_select (self->priv->resolution_combo, current))
- {
- int best_w, best_h;
- char *str;
-
- find_best_mode (modes, &best_w, &best_h);
- str = make_resolution_string (best_w, best_h);
- combo_select (self->priv->resolution_combo, str);
- g_free (str);
- }
-
- g_free (current);
-}
-
-static void
-rebuild_gui (CcDisplayPanel *self)
-{
- /* We would break spectacularly if we recursed, so
- * just assert if that happens
- */
- g_assert (self->priv->ignore_gui_changes == FALSE);
-
- self->priv->ignore_gui_changes = TRUE;
-
- rebuild_mirror_screens (self);
- rebuild_current_monitor_label (self);
- rebuild_on_off_radios (self);
- rebuild_resolution_combo (self);
- rebuild_rotation_combo (self);
-
- self->priv->ignore_gui_changes = FALSE;
-}
-
-static gboolean
-get_mode (GtkWidget *widget, int *width, int *height, int *rate, GnomeRRRotation *rot)
-{
- GtkTreeIter iter;
- GtkTreeModel *model;
- GtkComboBox *box = GTK_COMBO_BOX (widget);
- int dummy;
-
- if (!gtk_combo_box_get_active_iter (box, &iter))
- return FALSE;
-
- if (!width)
- width = &dummy;
-
- if (!height)
- height = &dummy;
-
- if (!rate)
- rate = &dummy;
-
- if (!rot)
- rot = (GnomeRRRotation *)&dummy;
-
- model = gtk_combo_box_get_model (box);
- gtk_tree_model_get (model, &iter,
- WIDTH_COL, width,
- HEIGHT_COL, height,
- RATE_COL, rate,
- ROTATION_COL, rot,
- -1);
-
- return TRUE;
+ preview = display_preview_new (outputs[i], current, ++number,
+ DISPLAY_PREVIEW_LIST_HEIGHT);
+ gtk_size_group_add_widget (sizegroup, preview);
-}
+ if (display_closed)
+ gtk_widget_set_sensitive (row, FALSE);
-static void
-on_rotation_changed (GtkComboBox *box, gpointer data)
-{
- CcDisplayPanel *self = data;
- GnomeRRRotation rotation;
+ g_hash_table_insert (output_ids, outputs[i], GINT_TO_POINTER (number));
- if (!self->priv->current_output)
- return;
+ gtk_container_add (GTK_CONTAINER (item), preview);
- if (get_mode (self->priv->rotation_combo, NULL, NULL, NULL, &rotation))
- gnome_rr_output_info_set_rotation (self->priv->current_output, rotation);
+ label = gtk_label_new (gnome_rr_output_info_get_display_name (outputs[i]));
+ gtk_container_add (GTK_CONTAINER (item), label);
- foo_scroll_area_invalidate (FOO_SCROLL_AREA (self->priv->area));
-}
+ primary = gnome_rr_output_info_get_primary (outputs[i]);
+ active = gnome_rr_output_info_is_active (outputs[i]);
-static void
-select_resolution_for_current_output (CcDisplayPanel *self)
-{
- GnomeRRMode **modes;
- int width, height;
- int x,y;
- gnome_rr_output_info_get_geometry (self->priv->current_output, &x, &y, NULL, NULL);
+ if (num_connected_outputs > 1)
+ {
+ if (display_closed)
+ status = _("Lid Closed");
+ else if (clone)
+ /* translators: "Mirrored" describes when both displays show the same view */
+ status = _("Mirrored");
+ else if (primary)
+ status = _("Primary");
+ else if (!active)
+ status = _("Off");
+ else
+ {
+ status = _("Secondary");
+ combined = TRUE;
+ }
- width = gnome_rr_output_info_get_preferred_width (self->priv->current_output);
- height = gnome_rr_output_info_get_preferred_height (self->priv->current_output);
+ label = gtk_label_new (status);
+ gtk_widget_set_hexpand (label, TRUE);
+ gtk_widget_set_halign (label, GTK_ALIGN_END);
+ gtk_container_add (GTK_CONTAINER (item), label);
+ }
- if (width != 0 && height != 0)
- {
- gnome_rr_output_info_set_geometry (self->priv->current_output, x, y, width, height);
- return;
+ g_object_set_data (G_OBJECT (row), "gnome-rr-output", outputs[i]);
+ gtk_container_add (GTK_CONTAINER (row), item);
+ gtk_container_add (GTK_CONTAINER (priv->displays_listbox), row);
+ gtk_widget_show_all (row);
}
- modes = get_current_modes (self);
- if (!modes)
- return;
-
- find_best_mode (modes, &width, &height);
-
- gnome_rr_output_info_set_geometry (self->priv->current_output, x, y, width, height);
-}
-
-static void
-monitor_switch_active_cb (GObject *object,
- GParamSpec *pspec,
- gpointer data)
-{
- CcDisplayPanel *self = data;
- gboolean value;
-
- if (!self->priv->current_output)
- return;
-
- value = gtk_switch_get_active (GTK_SWITCH (object));
-
- if (value)
- {
- gnome_rr_output_info_set_active (self->priv->current_output, TRUE);
- select_resolution_for_current_output (self);
- }
+ if (combined)
+ gtk_widget_show (priv->arrange_button);
else
- {
- gnome_rr_output_info_set_active (self->priv->current_output, FALSE);
- gnome_rr_config_ensure_primary (self->priv->current_configuration);
- }
+ gtk_widget_hide (priv->arrange_button);
- rebuild_gui (self);
- foo_scroll_area_invalidate (FOO_SCROLL_AREA (self->priv->area));
+ g_clear_object (&priv->labeler);
+ priv->labeler = cc_rr_labeler_new (priv->current_configuration);
}
static void
@@ -1035,37 +508,6 @@ realign_outputs_after_resolution_change (CcDisplayPanel *self, GnomeRROutputInfo
}
static void
-on_resolution_changed (GtkComboBox *box, gpointer data)
-{
- CcDisplayPanel *self = data;
- int old_width, old_height;
- int x,y;
- int width;
- int height;
-
- if (!self->priv->current_output)
- return;
-
- gnome_rr_output_info_get_geometry (self->priv->current_output, &x, &y, &old_width, &old_height);
-
- if (get_mode (self->priv->resolution_combo, &width, &height, NULL, NULL))
- {
- gnome_rr_output_info_set_geometry (self->priv->current_output, x, y, width, height);
-
- if (width == 0 || height == 0)
- gnome_rr_output_info_set_active (self->priv->current_output, FALSE);
- else
- gnome_rr_output_info_set_active (self->priv->current_output, TRUE);
- }
-
- realign_outputs_after_resolution_change (self, self->priv->current_output, old_width, old_height);
-
- rebuild_rotation_combo (self);
-
- foo_scroll_area_invalidate (FOO_SCROLL_AREA (self->priv->area));
-}
-
-static void
lay_out_outputs_horizontally (CcDisplayPanel *self)
{
int i;
@@ -1108,116 +550,6 @@ lay_out_outputs_horizontally (CcDisplayPanel *self)
}
-/* FIXME: this function is copied from gnome-settings-daemon/plugins/xrandr/gsd-xrandr-manager.c.
- * Do we need to put this function in gnome-desktop for public use?
- */
-static gboolean
-get_clone_size (GnomeRRScreen *screen, int *width, int *height)
-{
- GnomeRRMode **modes = gnome_rr_screen_list_clone_modes (screen);
- int best_w, best_h;
- int i;
-
- best_w = 0;
- best_h = 0;
-
- for (i = 0; modes[i] != NULL; ++i) {
- GnomeRRMode *mode = modes[i];
- int w, h;
-
- w = gnome_rr_mode_get_width (mode);
- h = gnome_rr_mode_get_height (mode);
-
- if (w * h > best_w * best_h) {
- best_w = w;
- best_h = h;
- }
- }
-
- if (best_w > 0 && best_h > 0) {
- if (width)
- *width = best_w;
- if (height)
- *height = best_h;
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-output_info_supports_mode (CcDisplayPanel *self, GnomeRROutputInfo *info, int width, int height)
-{
- GnomeRROutput *output;
- GnomeRRMode **modes;
- int i;
-
- if (!gnome_rr_output_info_is_connected (info))
- return FALSE;
-
- output = gnome_rr_screen_get_output_by_name (self->priv->screen, gnome_rr_output_info_get_name (info));
- if (!output)
- return FALSE;
-
- modes = gnome_rr_output_list_modes (output);
-
- for (i = 0; modes[i]; i++) {
- if (gnome_rr_mode_get_width (modes[i]) == width
- && gnome_rr_mode_get_height (modes[i]) == height)
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-on_clone_changed (GtkWidget *box, gpointer data)
-{
- CcDisplayPanel *self = data;
-
- gnome_rr_config_set_clone (self->priv->current_configuration, gtk_toggle_button_get_active
(GTK_TOGGLE_BUTTON (self->priv->clone_checkbox)));
-
- if (gnome_rr_config_get_clone (self->priv->current_configuration))
- {
- int i;
- int width, height;
- GnomeRROutputInfo **outputs = gnome_rr_config_get_outputs (self->priv->current_configuration);
-
- for (i = 0; outputs[i]; ++i)
- {
- if (gnome_rr_output_info_is_connected (outputs[i]))
- {
- self->priv->current_output = outputs[i];
- break;
- }
- }
-
- /* Turn on all the connected screens that support the best clone mode.
- * The user may hit "Mirror displays", but he shouldn't have to turn on
- * all the required outputs as well.
- */
-
- get_clone_size (self->priv->screen, &width, &height);
-
- for (i = 0; outputs[i]; i++) {
- int x, y;
- if (output_info_supports_mode (self, outputs[i], width, height)) {
- gnome_rr_output_info_set_active (outputs[i], TRUE);
- gnome_rr_output_info_get_geometry (outputs[i], &x, &y, NULL, NULL);
- gnome_rr_output_info_set_geometry (outputs[i], x, y, width, height);
- }
- }
- }
- else
- {
- if (output_overlaps (self->priv->current_output, self->priv->current_configuration))
- lay_out_outputs_horizontally (self);
- }
-
- rebuild_gui (self);
-}
-
static void
apply_rotation_to_geometry (GnomeRROutputInfo *output, int *w, int *h)
{
@@ -1298,7 +630,7 @@ get_n_connected (CcDisplayPanel *self)
}
static double
-compute_scale (CcDisplayPanel *self)
+compute_scale (CcDisplayPanel *self, FooScrollArea *area)
{
int available_w, available_h;
int total_w, total_h;
@@ -1306,7 +638,7 @@ compute_scale (CcDisplayPanel *self)
GdkRectangle viewport;
GList *connected_outputs;
- foo_scroll_area_get_viewport (FOO_SCROLL_AREA (self->priv->area), &viewport);
+ foo_scroll_area_get_viewport (area, &viewport);
connected_outputs = list_connected_outputs (self, &total_w, &total_h);
@@ -1688,89 +1020,6 @@ set_cursor (GtkWidget *widget, GdkCursorType type)
}
static void
-set_top_bar_tooltip (CcDisplayPanel *self, gboolean is_dragging)
-{
- const char *text;
-
- if (is_dragging)
- text = NULL;
- else
- text = _("Drag to change primary display.");
-
- gtk_widget_set_tooltip_text (self->priv->area, text);
-}
-
-static void
-on_top_bar_event (FooScrollArea *area,
- FooScrollAreaEvent *event,
- CcDisplayPanel *self)
-{
- /* Ignore drops */
- if (event->type == FOO_DROP)
- return;
-
- /* If the mouse is inside the top bar, set the cursor to "you can move me". See
- * on_canvas_event() for where we reset the cursor to the default if it
- * exits the outputs' area.
- */
- if (!gnome_rr_config_get_clone (self->priv->current_configuration) && get_n_connected (self) > 1)
- set_cursor (GTK_WIDGET (area), GDK_HAND1);
-
- if (event->type == FOO_BUTTON_PRESS)
- {
- rebuild_gui (self);
- set_top_bar_tooltip (self, TRUE);
-
- if (!gnome_rr_config_get_clone (self->priv->current_configuration) && get_n_connected (self) > 1)
- {
- self->priv->dragging_top_bar = TRUE;
- foo_scroll_area_begin_grab (area, (FooScrollAreaEventFunc) on_top_bar_event, self);
- }
-
- foo_scroll_area_invalidate (area);
- }
- else
- {
- if (foo_scroll_area_is_grabbed (area))
- {
- if (event->type == FOO_BUTTON_RELEASE)
- {
- foo_scroll_area_end_grab (area, event);
- self->priv->dragging_top_bar = FALSE;
- set_top_bar_tooltip (self, FALSE);
- }
-
- foo_scroll_area_invalidate (area);
- }
- }
-}
-
-static void
-set_monitors_tooltip (CcDisplayPanel *self, gboolean is_dragging)
-{
- const char *text;
-
- if (is_dragging)
- text = NULL;
- else
- text = _("Select a monitor to change its properties; drag it to rearrange its placement.");
-
- gtk_widget_set_tooltip_text (self->priv->area, text);
-}
-
-static void
-set_primary_output (CcDisplayPanel *self,
- GnomeRROutputInfo *output)
-{
- int i;
- GnomeRROutputInfo **outputs;
-
- outputs = gnome_rr_config_get_outputs (self->priv->current_configuration);
- for (i = 0; outputs[i] != NULL; ++i)
- gnome_rr_output_info_set_primary (outputs[i], outputs[i] == output);
-}
-
-static void
grab_weak_ref_notify (gpointer area,
GObject *object)
{
@@ -1787,8 +1036,6 @@ on_output_event (FooScrollArea *area,
if (event->type == FOO_DRAG_HOVER)
{
- if (gnome_rr_output_info_is_active (output) && self->priv->dragging_top_bar)
- set_primary_output (self, output);
return;
}
if (event->type == FOO_DROP)
@@ -1810,8 +1057,6 @@ on_output_event (FooScrollArea *area,
self->priv->current_output = output;
- rebuild_gui (self);
- set_monitors_tooltip (self, TRUE);
if (!gnome_rr_config_get_clone (self->priv->current_configuration) && get_n_connected (self) > 1)
{
@@ -1836,7 +1081,7 @@ on_output_event (FooScrollArea *area,
if (foo_scroll_area_is_grabbed (area))
{
GrabInfo *info = g_object_get_data (G_OBJECT (output), "grab-info");
- double scale = compute_scale (self);
+ double scale = compute_scale (self, area);
int old_x, old_y;
int width, height;
int new_x, new_y;
@@ -1888,7 +1133,6 @@ on_output_event (FooScrollArea *area,
if (event->type == FOO_BUTTON_RELEASE)
{
foo_scroll_area_end_grab (area, event);
- set_monitors_tooltip (self, FALSE);
g_free (g_object_get_data (G_OBJECT (output), "grab-info"));
g_object_set_data (G_OBJECT (output), "grab-info", NULL);
@@ -1916,25 +1160,6 @@ on_canvas_event (FooScrollArea *area,
set_cursor (GTK_WIDGET (area), GDK_BLANK_CURSOR);
}
-static PangoLayout *
-get_display_name (CcDisplayPanel *self,
- GnomeRROutputInfo *output)
-{
- PangoLayout *layout;
- char *text;
-
- if (gnome_rr_config_get_clone (self->priv->current_configuration))
- text = mirror_monitor_name ();
- else
- text = g_strdup (gnome_rr_output_info_get_display_name (output));
-
- layout = gtk_widget_create_pango_layout (GTK_WIDGET (self->priv->area), text);
- g_free (text);
- pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
-
- return layout;
-}
-
static void
paint_background (FooScrollArea *area,
cairo_t *cr)
@@ -1975,217 +1200,6 @@ paint_background (FooScrollArea *area,
}
static void
-color_shade (double *r,
- double *g,
- double *b,
- double k)
-{
- double h, s, v;
-
- gtk_rgb_to_hsv (*r, *g, *b, &h, &s, &v);
-
- s *= k;
- if (s > 1.0)
- s = 1.0;
- else if (s < 0.0)
- s = 0.0;
-
- v *= k;
- if (v > 1.0)
- v = 1.0;
- else if (v < 0.0)
- v = 0.0;
-
- gtk_hsv_to_rgb (h, s, v, r, g, b);
-}
-
-static void
-paint_output (CcDisplayPanel *self, cairo_t *cr, int i)
-{
- int w, h;
- double scale = compute_scale (self);
- double x, y;
- int output_x, output_y;
- GnomeRRRotation rotation;
- int total_w, total_h;
- GList *connected_outputs = list_connected_outputs (self, &total_w, &total_h);
- GnomeRROutputInfo *output = g_list_nth (connected_outputs, i)->data;
- PangoLayout *layout = get_display_name (self, output);
- PangoRectangle ink_extent, log_extent;
- GdkRectangle viewport;
- GdkRGBA output_color;
- double r, g, b;
- double available_w;
- double factor;
-
- cairo_save (cr);
-
- foo_scroll_area_get_viewport (FOO_SCROLL_AREA (self->priv->area), &viewport);
- get_geometry (output, &w, &h);
-
-#if 0
- g_debug ("%s (%p) geometry %d %d %d primary=%d", output->name, output->name,
- w, h, output->rate, output->primary);
-#endif
-
- viewport.height -= 2 * MARGIN;
- viewport.width -= 2 * MARGIN;
-
- gnome_rr_output_info_get_geometry (output, &output_x, &output_y, NULL, NULL);
- x = output_x * scale + MARGIN + (viewport.width - total_w * scale) / 2.0;
- y = output_y * scale + MARGIN + (viewport.height - total_h * scale) / 2.0;
-
-#if 0
- g_debug ("scaled: %f %f", x, y);
-
- g_debug ("scale: %f", scale);
-
- g_debug ("%f %f %f %f", x, y, w * scale + 0.5, h * scale + 0.5);
-#endif
-
- cairo_translate (cr,
- x + (w * scale + 0.5) / 2,
- y + (h * scale + 0.5) / 2);
-
- /* rotation is already applied in get_geometry */
-
- rotation = gnome_rr_output_info_get_rotation (output);
- if (rotation & GNOME_RR_REFLECT_X)
- cairo_scale (cr, -1, 1);
-
- if (rotation & GNOME_RR_REFLECT_Y)
- cairo_scale (cr, 1, -1);
-
- cairo_translate (cr,
- - x - (w * scale + 0.5) / 2,
- - y - (h * scale + 0.5) / 2);
-
- if (output == self->priv->current_output)
- {
- GtkStyleContext *context;
- GdkRGBA color;
-
- context = gtk_widget_get_style_context (self->priv->area);
- gtk_style_context_get_background_color (context, GTK_STATE_FLAG_SELECTED, &color);
-
- cairo_rectangle (cr, x - 2, y - 2, w * scale + 0.5 + 4, h * scale + 0.5 + 4);
-
- cairo_set_line_width (cr, 4);
- cairo_set_source_rgba (cr, color.red, color.green, color.blue, 0.5);
- cairo_stroke (cr);
- }
-
- cairo_rectangle (cr, x, y, w * scale + 0.5, h * scale + 0.5);
- cairo_clip_preserve (cr);
-
- cc_rr_labeler_get_rgba_for_output (self->priv->labeler, output, &output_color);
- r = output_color.red;
- g = output_color.green;
- b = output_color.blue;
-
- if (!gnome_rr_output_info_is_active (output))
- {
- /* If the output is turned off, just darken the selected color */
- color_shade (&r, &g, &b, 0.4);
- }
-
- cairo_set_source_rgba (cr, r, g, b, 1.0);
-
- foo_scroll_area_add_input_from_fill (FOO_SCROLL_AREA (self->priv->area),
- cr, on_output_event, output);
- cairo_fill (cr);
-
- cairo_rectangle (cr, x + 0.5, y + 0.5, w * scale + 0.5 - 1, h * scale + 0.5 - 1);
-
- cairo_set_line_width (cr, 1);
- cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
-
- cairo_stroke (cr);
- cairo_set_line_width (cr, 2);
-
- cairo_save (cr);
-
- layout_set_font (layout, "Sans 10");
- pango_layout_get_pixel_extents (layout, &ink_extent, &log_extent);
-
- available_w = w * scale + 0.5 - 6; /* Same as the inner rectangle's width, minus 1 pixel of padding on
each side */
- if (available_w < ink_extent.width)
- factor = available_w / ink_extent.width;
- else
- factor = 1.0;
-
- cairo_move_to (cr,
- x + ((w * scale + 0.5) - factor * log_extent.width) / 2,
- y + ((h * scale + 0.5) - factor * log_extent.height) / 2);
-
- cairo_scale (cr, factor, factor);
- if (gnome_rr_output_info_is_active (output))
- cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
- else
- cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
-
- pango_cairo_show_layout (cr, layout);
- g_object_unref (layout);
- cairo_restore (cr);
-
- if (gnome_rr_output_info_get_primary (output))
- {
- const char *clock_format;
- char *text;
- gboolean use_24;
- GDateTime *dt;
- GDesktopClockFormat value;
-
- /* top bar */
- cairo_rectangle (cr, x, y, w * scale + 0.5, TOP_BAR_HEIGHT);
- cairo_set_source_rgb (cr, 0, 0, 0);
- foo_scroll_area_add_input_from_fill (FOO_SCROLL_AREA (self->priv->area),
- cr,
- (FooScrollAreaEventFunc) on_top_bar_event,
- self);
-
- cairo_fill (cr);
-
- /* clock */
- value = g_settings_get_enum (self->priv->clock_settings, CLOCK_FORMAT_KEY);
- use_24 = value == G_DESKTOP_CLOCK_FORMAT_24H;
- if (use_24)
- clock_format = _("%a %R");
- else
- clock_format = _("%a %l:%M %p");
-
- dt = g_date_time_new_now_local ();
- text = g_date_time_format (dt, clock_format);
- g_date_time_unref (dt);
-
- layout = gtk_widget_create_pango_layout (GTK_WIDGET (self->priv->area), text);
- g_free (text);
- pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
-
- layout_set_font (layout, "Sans 4");
- pango_layout_get_pixel_extents (layout, &ink_extent, &log_extent);
-
- if (available_w < ink_extent.width)
- factor = available_w / ink_extent.width;
- else
- factor = 1.0;
-
- cairo_move_to (cr,
- x + ((w * scale + 0.5) - factor * log_extent.width) / 2,
- y + (TOP_BAR_HEIGHT - factor * log_extent.height) / 2);
-
- cairo_scale (cr, factor, factor);
-
- cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
-
- pango_cairo_show_layout (cr, layout);
- g_object_unref (layout);
- }
-
- cairo_restore (cr);
-}
-
-static void
on_area_paint (FooScrollArea *area,
cairo_t *cr,
gpointer data)
@@ -2203,43 +1217,45 @@ on_area_paint (FooScrollArea *area,
for (list = connected_outputs; list != NULL; list = list->next)
{
- paint_output (self, cr, g_list_position (connected_outputs, list));
+ int w, h;
+ double scale = compute_scale (self, area);
+ double x, y;
+ int output_x, output_y;
+ int total_w, total_h;
+ GList *connected_outputs;
+ GnomeRROutputInfo *output = list->data;
+ GdkRectangle viewport;
- if (gnome_rr_config_get_clone (self->priv->current_configuration))
- break;
- }
-}
+ cairo_save (cr);
-static void
-make_text_combo (GtkWidget *widget, int sort_column)
-{
- GtkComboBox *box = GTK_COMBO_BOX (widget);
- GtkListStore *store = gtk_list_store_new (
- NUM_COLS,
- G_TYPE_STRING, /* Text */
- G_TYPE_INT, /* Width */
- G_TYPE_INT, /* Height */
- G_TYPE_INT, /* Frequency */
- G_TYPE_INT, /* Width * Height */
- G_TYPE_INT); /* Rotation */
+ connected_outputs = list_connected_outputs (self, &total_w, &total_h);
+ g_list_free (connected_outputs);
- GtkCellRenderer *cell;
+ foo_scroll_area_get_viewport (area, &viewport);
+ get_geometry (output, &w, &h);
- gtk_cell_layout_clear (GTK_CELL_LAYOUT (widget));
+ viewport.height -= 2 * MARGIN;
+ viewport.width -= 2 * MARGIN;
- gtk_combo_box_set_model (box, GTK_TREE_MODEL (store));
+ gnome_rr_output_info_get_geometry (output, &output_x, &output_y, NULL, NULL);
+ x = output_x * scale + MARGIN + (viewport.width - total_w * scale) / 2.0;
+ y = output_y * scale + MARGIN + (viewport.height - total_h * scale) / 2.0;
- cell = gtk_cell_renderer_text_new ();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (box), cell, TRUE);
- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (box), cell,
- "text", 0,
- NULL);
- if (sort_column != -1)
- {
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
- sort_column,
- GTK_SORT_DESCENDING);
+ cairo_set_source_rgba (cr, 0, 0, 0, 0);
+ cairo_rectangle (cr, x, y, w * scale + 0.5, h * scale + 0.5);
+ foo_scroll_area_add_input_from_fill (area, cr, on_output_event, output);
+ cairo_fill (cr);
+
+ cairo_translate (cr, x, y);
+ paint_output (cr, self->priv->current_configuration, list->data,
+ cc_display_panel_get_output_id (list->data),
+ w * scale, h * scale);
+
+ cairo_restore (cr);
+
+ if (gnome_rr_config_get_clone (self->priv->current_configuration))
+ break;
}
}
@@ -2298,166 +1314,288 @@ check_required_virtual_size (CcDisplayPanel *self)
}
static void
-sanitize_configuration (CcDisplayPanel *self)
+apply_current_configuration (CcDisplayPanel *self)
{
+ GError *error = NULL;
+
gnome_rr_config_sanitize (self->priv->current_configuration);
gnome_rr_config_ensure_primary (self->priv->current_configuration);
check_required_virtual_size (self);
- foo_scroll_area_invalidate (FOO_SCROLL_AREA (self->priv->area));
+ gnome_rr_config_apply_persistent (self->priv->current_configuration,
+ self->priv->screen, &error);
+
+ /* re-read the configuration */
+ on_screen_changed (self);
+
+ if (error)
+ {
+ g_warning ("Error applying configuration: %s", error->message);
+ g_clear_error (&error);
+ }
}
static void
-apply (CcDisplayPanel *self)
+show_arrange_displays_dialog (GtkButton *button,
+ CcDisplayPanel *panel)
+{
+ GtkWidget *dialog, *content_area, *area, *vbox, *label;
+
+ dialog = gtk_dialog_new_with_buttons (_("Arrange Combined Displays"),
+ GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL
(panel)))),
+ GTK_DIALOG_MODAL,
+ _("_Cancel"), GTK_RESPONSE_REJECT,
+ _("_Apply"), GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ area = (GtkWidget *) foo_scroll_area_new ();
+ g_object_set_data (G_OBJECT (area), "panel", panel);
+
+ foo_scroll_area_set_min_size (FOO_SCROLL_AREA (area), 520, 290);
+ gtk_widget_set_margin_right (area, 12);
+ gtk_widget_set_margin_left (area, 12);
+ gtk_widget_set_size_request (area, 520, 290);
+ g_signal_connect (area, "paint",
+ G_CALLBACK (on_area_paint), panel);
+ g_signal_connect (area, "viewport_changed",
+ G_CALLBACK (on_viewport_changed), panel);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_container_add (GTK_CONTAINER (vbox), area);
+
+ label = gtk_label_new (_("Drag displays to rearrange them"));
+ gtk_widget_set_margin_top (label, 12);
+ gtk_widget_set_margin_bottom (label, 12);
+ gtk_container_add (GTK_CONTAINER (vbox), label);
+ gtk_style_context_add_class (gtk_widget_get_style_context (label), GTK_STYLE_CLASS_DIM_LABEL);
+
+ gtk_widget_show_all (vbox);
+ gtk_container_add (GTK_CONTAINER (content_area), vbox);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ apply_current_configuration (panel);
+ else
+ {
+ /* re-read the previous configuration */
+ on_screen_changed (panel);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static const gchar *
+make_aspect_string (gint width,
+ gint height)
{
- GError *error;
- gboolean ok;
+ int ratio;
+ const gchar *aspect = NULL;
+
+ /* We use a number of Unicode characters below:
+ * ∶ is U+2236 RATIO
+ * is U+2009 THIN SPACE,
+ * × is U+00D7 MULTIPLICATION SIGN
+ */
+ if (width && height) {
+ if (width > height)
+ ratio = width * 10 / height;
+ else
+ ratio = height * 10 / width;
- self->priv->apply_button_clicked_timestamp = gtk_get_current_event_time ();
+ switch (ratio) {
+ case 13:
+ aspect = "4∶3";
+ break;
+ case 16:
+ aspect = "16∶10";
+ break;
+ case 17:
+ aspect = "16∶9";
+ break;
+ case 23:
+ aspect = "21∶9";
+ break;
+ case 12:
+ aspect = "5∶4";
+ break;
+ /* This catches 1.5625 as well (1600x1024) when maybe it shouldn't. */
+ case 15:
+ aspect = "3∶2";
+ break;
+ case 18:
+ aspect = "9∶5";
+ break;
+ case 10:
+ aspect = "1∶1";
+ break;
+ }
+ }
- sanitize_configuration (self);
+ return aspect;
+}
- error = NULL;
- ok = gnome_rr_config_apply_persistent (self->priv->current_configuration,
- self->priv->screen, &error);
+static char *
+make_resolution_string (gint width,
+ gint height)
+{
+ const char *aspect = make_aspect_string (width, height);
- if (!ok)
- error_message (self, _("Failed to apply configuration"), error->message);
- g_clear_error (&error);
+ if (aspect != NULL)
+ return g_strdup_printf ("%d × %d (%s)", width, height, aspect);
+ else
+ return g_strdup_printf ("%d × %d", width, height);
}
-#if 0
-/* Returns whether the graphics driver doesn't advertise RANDR 1.2 features, and just 1.0 */
-static gboolean
-driver_is_randr_10 (GnomeRRConfig *config)
-{
- /* In the Xorg code, see xserver/randr/rrinfo.c:RRScanOldConfig(). It gets
- * called when the graphics driver doesn't support RANDR 1.2 yet, just 1.0.
- * In that case, the X server's base code (which supports RANDR 1.2) will
- * simulate having a single output called "default". For drivers that *do*
- * support RANDR 1.2, the separate outputs will be named differently, we
- * hope.
- *
- * This heuristic is courtesy of Dirk Mueller <dmueller suse de>
- *
- * FIXME: however, we don't even check for XRRQueryVersion() returning 1.2, neither
- * here nor in gnome-desktop/libgnomedesktop*.c. Do we need to check for that,
- * or is gnome_rr_screen_new()'s return value sufficient?
- */
+static GtkWidget *
+list_box_item (const gchar *title,
+ const gchar *subtitle)
+{
+ GtkWidget *item, *label, *row;
+
+ row = gtk_list_box_row_new ();
+
+ item = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (item), 12);
+
+ label = gtk_label_new (title);
+ gtk_container_add (GTK_CONTAINER (item), label);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
+ gtk_widget_set_size_request (label, 230, -1);
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+
+ label = gtk_label_new (subtitle);
+ gtk_container_add (GTK_CONTAINER (item), label);
+ gtk_style_context_add_class (gtk_widget_get_style_context (label), GTK_STYLE_CLASS_DIM_LABEL);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
+ gtk_widget_set_size_request (label, 230, -1);
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
- return (count_all_outputs (config) == 1 && strcmp (gnome_rr_output_info_get_name
(gnome_rr_config_get_outputs (config)[0]), "default") == 0);
+ gtk_container_add (GTK_CONTAINER (row), item);
+
+ return row;
}
-#endif
static void
-on_detect_displays (GtkWidget *widget, gpointer data)
+cc_display_panel_list_box_update_header (GtkListBoxRow *row,
+ GtkListBoxRow *before,
+ gpointer user_data)
{
- CcDisplayPanel *self = data;
- GError *error;
+ GtkWidget *current;
- error = NULL;
- if (!gnome_rr_screen_refresh (self->priv->screen, &error)) {
- if (error) {
- error_message (self, _("Could not detect displays"), error->message);
- g_error_free (error);
+ if (before == NULL)
+ return;
+
+ current = gtk_list_box_row_get_header (row);
+ if (current == NULL)
+ {
+ current = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+ gtk_widget_show (current);
+ gtk_list_box_row_set_header (row, current);
}
- }
}
-static GnomeRROutputInfo *
-get_nearest_output (GnomeRRConfig *configuration, int x, int y)
+static void
+setup_resolution_combo_box (CcDisplayPanel *panel,
+ GnomeRRMode **modes,
+ GnomeRRMode *current_mode)
{
- int i;
- int nearest_index;
- int nearest_dist;
- GnomeRROutputInfo **outputs;
+ CcDisplayPanelPrivate *priv = panel->priv;
+ GtkTreeModel *res_model;
+ GHashTable *resolutions;
+ gint i;
- nearest_index = -1;
- nearest_dist = G_MAXINT;
+ res_model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->res_combo));
+ gtk_list_store_clear (GTK_LIST_STORE (res_model));
- outputs = gnome_rr_config_get_outputs (configuration);
- for (i = 0; outputs[i] != NULL; i++)
+ resolutions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ for (i = 0; modes[i] != NULL; i++)
{
- int dist_x, dist_y;
- int output_x, output_y, output_width, output_height;
+ gchar *res;
+ gboolean present;
+ gint output_width, output_height, mode_width, mode_height;
- if (!(gnome_rr_output_info_is_connected (outputs[i]) && gnome_rr_output_info_is_active (outputs[i])))
- continue;
+ if (!current_mode)
+ current_mode = modes[i];
- gnome_rr_output_info_get_geometry (outputs[i], &output_x, &output_y, &output_width, &output_height);
+ mode_width = gnome_rr_mode_get_width (modes[i]);
+ mode_height = gnome_rr_mode_get_height (modes[i]);
- if (x < output_x)
- dist_x = output_x - x;
- else if (x >= output_x + output_width)
- dist_x = x - (output_x + output_width) + 1;
- else
- dist_x = 0;
+ output_width = gnome_rr_output_info_get_preferred_width (priv->current_output);
+ output_height = gnome_rr_output_info_get_preferred_height (priv->current_output);
- if (y < output_y)
- dist_y = output_y - y;
- else if (y >= output_y + output_height)
- dist_y = y - (output_y + output_height) + 1;
- else
- dist_y = 0;
+ if (!should_show_resolution (output_width, output_height, mode_width,
+ mode_height))
+ continue;
- if (MIN (dist_x, dist_y) < nearest_dist)
- {
- nearest_dist = MIN (dist_x, dist_y);
- nearest_index = i;
- }
+ res = make_resolution_string (gnome_rr_mode_get_width (modes[i]),
+ gnome_rr_mode_get_height (modes[i]));
+ present = GPOINTER_TO_INT (g_hash_table_lookup (resolutions, res));
+ if (!present)
+ {
+ GtkTreeIter iter;
+
+ g_hash_table_insert (resolutions, g_strdup (res),
+ GINT_TO_POINTER (TRUE));
+
+ gtk_list_store_insert_with_values (GTK_LIST_STORE (res_model), &iter,
+ -1, 0, res, 1, modes[i], -1);
+
+ /* select the current mode in the combo box */
+ if (gnome_rr_mode_get_width (modes[i]) == gnome_rr_mode_get_width (current_mode)
+ && gnome_rr_mode_get_height (modes[i]) == gnome_rr_mode_get_height (current_mode))
+ {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->res_combo),
+ &iter);
+ }
+ }
+ g_free (res);
}
- if (nearest_index != -1)
- return outputs[nearest_index];
- else
- return NULL;
+ /* ensure a resolution is selected by default */
+ if (gtk_combo_box_get_active (GTK_COMBO_BOX (priv->res_combo)) == -1)
+ gtk_combo_box_set_active (GTK_COMBO_BOX (priv->res_combo), 0);
+
+ g_hash_table_destroy (resolutions);
}
-/* Gets the output that contains the largest intersection with the window.
- * Logic stolen from gdk_screen_get_monitor_at_window().
- */
-static GnomeRROutputInfo *
-get_output_for_window (GnomeRRConfig *configuration, GdkWindow *window)
-{
- GdkRectangle win_rect;
- int i;
- int largest_area;
- int largest_index;
- GnomeRROutputInfo **outputs;
- gdk_window_get_geometry (window, &win_rect.x, &win_rect.y, &win_rect.width, &win_rect.height);
- gdk_window_get_origin (window, &win_rect.x, &win_rect.y);
+static void
+setup_listbox_row_activated (GtkListBox *list_box,
+ GtkListBoxRow *row,
+ CcDisplayPanel *panel)
+{
+ CcDisplayPanelPrivate *priv = panel->priv;
+ GnomeRRMode **modes;
+ gint index;
+ GnomeRROutput *output;
- largest_area = 0;
- largest_index = -1;
+ if (!row)
+ return;
- outputs = gnome_rr_config_get_outputs (configuration);
- for (i = 0; outputs[i] != NULL; i++)
- {
- GdkRectangle output_rect, intersection;
+ index = gtk_list_box_row_get_index (row);
- gnome_rr_output_info_get_geometry (outputs[i], &output_rect.x, &output_rect.y, &output_rect.width,
&output_rect.height);
+ output = gnome_rr_screen_get_output_by_name (priv->screen,
+ gnome_rr_output_info_get_name (priv->current_output));
- if (gnome_rr_output_info_is_connected (outputs[i]) && gdk_rectangle_intersect (&win_rect,
&output_rect, &intersection))
- {
- int area;
+ if (index == DISPLAY_MODE_MIRROR)
+ {
+ modes = gnome_rr_screen_list_clone_modes (priv->screen);
+ gnome_rr_config_set_clone (priv->current_configuration, TRUE);
+ }
+ else
+ {
+ gnome_rr_output_info_set_primary (priv->current_output,
+ (index == DISPLAY_MODE_PRIMARY));
+ gnome_rr_config_set_clone (priv->current_configuration, FALSE);
- area = intersection.width * intersection.height;
- if (area > largest_area)
- {
- largest_area = area;
- largest_index = i;
- }
- }
+ modes = gnome_rr_output_list_modes (output);
}
- if (largest_index != -1)
- return outputs[largest_index];
- else
- return get_nearest_output (configuration,
- win_rect.x + win_rect.width / 2,
- win_rect.y + win_rect.height / 2);
+ setup_resolution_combo_box (panel, modes,
+ gnome_rr_output_get_current_mode (output));
}
static void
@@ -2473,174 +1611,528 @@ dialog_toplevel_focus_changed (GtkWindow *window,
cc_rr_labeler_hide (self->priv->labeler);
}
+
static void
-on_toplevel_realized (GtkWidget *widget,
- CcDisplayPanel *self)
+rotate_left_clicked (GtkButton *button,
+ CcDisplayPanel *panel)
{
- self->priv->current_output = get_output_for_window (self->priv->current_configuration,
- gtk_widget_get_window (widget));
- rebuild_gui (self);
+ CcDisplayPanelPrivate *priv = panel->priv;
+ GnomeRRRotation rotation;
+
+ rotation = gnome_rr_output_info_get_rotation (priv->current_output);
+
+ if (rotation & GNOME_RR_ROTATION_0)
+ {
+ rotation = GNOME_RR_ROTATION_90;
+ gtk_widget_set_sensitive (priv->rotate_left_button, FALSE);
+ }
+ else
+ {
+ rotation = GNOME_RR_ROTATION_0;
+ gtk_widget_set_sensitive (priv->rotate_right_button, TRUE);
+ }
+
+ gnome_rr_output_info_set_rotation (priv->current_output, rotation);
}
-/* We select the current output, i.e. select the one being edited, based on
- * which output is showing the configuration dialog.
- */
static void
-select_current_output_from_dialog_position (CcDisplayPanel *self)
+rotate_right_clicked (GtkButton *button,
+ CcDisplayPanel *panel)
{
- GtkWidget *toplevel;
+ CcDisplayPanelPrivate *priv = panel->priv;
+ GnomeRRRotation rotation;
- toplevel = gtk_widget_get_toplevel (self->priv->panel);
+ rotation = gnome_rr_output_info_get_rotation (priv->current_output);
- if (gtk_widget_get_realized (toplevel)) {
- self->priv->current_output = get_output_for_window (self->priv->current_configuration,
- gtk_widget_get_window (toplevel));
- rebuild_gui (self);
- } else {
- g_signal_connect (toplevel, "realize", G_CALLBACK (on_toplevel_realized), self);
- self->priv->current_output = NULL;
- }
+ if (rotation & GNOME_RR_ROTATION_0)
+ {
+ rotation = GNOME_RR_ROTATION_270;
+ gtk_widget_set_sensitive (priv->rotate_right_button, FALSE);
+ }
+ else
+ {
+ rotation = GNOME_RR_ROTATION_0;
+ gtk_widget_set_sensitive (priv->rotate_left_button, TRUE);
+ }
+
+ gnome_rr_output_info_set_rotation (priv->current_output, rotation);
}
-/* This is a GtkWidget::map-event handler. We wait for the display-properties
- * dialog to be mapped, and then we select the output which corresponds to the
- * monitor on which the dialog is being shown.
- */
-static gboolean
-dialog_map_event_cb (GtkWidget *widget, GdkEventAny *event, gpointer data)
+static const double known_diagonals[] = {
+ 12.1,
+ 13.3,
+ 15.6
+};
+
+static char *
+diagonal_to_str (double d)
{
- CcDisplayPanel *self = data;
+ int i;
- select_current_output_from_dialog_position (self);
- return FALSE;
+ for (i = 0; i < G_N_ELEMENTS (known_diagonals); i++)
+ {
+ double delta;
+
+ delta = fabs(known_diagonals[i] - d);
+ if (delta < 0.1)
+ return g_strdup_printf ("%0.1lf\"", known_diagonals[i]);
+ }
+
+ return g_strdup_printf ("%d\"", (int) (d + 0.5));
}
-static void
-cc_display_panel_init (CcDisplayPanel *self)
+static char *
+make_display_size_string (int width_mm,
+ int height_mm)
{
- g_resources_register (cc_display_get_resource ());
+ char *inches = NULL;
+
+ if (width_mm > 0 && height_mm > 0)
+ {
+ double d = sqrt (width_mm * width_mm + height_mm * height_mm);
+
+ inches = diagonal_to_str (d / 25.4);
+ }
+
+ return inches;
}
static void
-cc_display_panel_up_client_changed (UpClient *client,
- CcDisplayPanel *self)
+res_combo_changed (GtkComboBox *combo,
+ CcDisplayPanel *panel)
{
- CcDisplayPanelPrivate *priv = self->priv;
- gboolean lid_is_closed;
+ CcDisplayPanelPrivate *priv = panel->priv;
+ GtkTreeModel *res_model;
+ GtkTreeIter iter;
+ GnomeRRMode *mode;
+ gint x, y, width, height;
- lid_is_closed = up_client_get_lid_is_closed (client);
+ res_model = gtk_combo_box_get_model (combo);
- if (lid_is_closed != priv->lid_is_closed)
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter))
{
- priv->lid_is_closed = lid_is_closed;
+ gtk_tree_model_get (GTK_TREE_MODEL (res_model), &iter, 1, &mode, -1);
+
+ gnome_rr_output_info_get_geometry (priv->current_output, &x, &y, NULL, NULL);
- rebuild_on_off_radios (self);
+ width = gnome_rr_mode_get_width (mode);
+ height = gnome_rr_mode_get_height (mode);
+
+ gnome_rr_output_info_set_geometry (priv->current_output, x, y, width, height);
}
}
-static GObject *
-cc_display_panel_constructor (GType gtype,
- guint n_properties,
- GObjectConstructParam *properties)
+static void
+show_setup_dialog (CcDisplayPanel *panel)
{
- GtkBuilder *builder;
- GtkWidget *align;
- GError *error;
- GObject *obj;
- CcDisplayPanel *self;
- CcShell *shell;
- GtkWidget *toplevel;
- gchar *objects[] = {"display-panel", NULL};
+ CcDisplayPanelPrivate *priv = panel->priv;
+ GtkWidget *dialog, *listbox, *content_area, *item, *box, *frame, *preview;
+ GtkWidget *label, *rotate_box, *grid;
+ gint i, width_mm, height_mm, old_width, old_height;
+ GnomeRROutput *output;
+ gchar *str;
+ gboolean clone, was_clone, primary, was_primary, active;
+ GtkListStore *res_model;
+ GtkCellRenderer *renderer;
+ GnomeRRRotation rotation;
- obj = G_OBJECT_CLASS (cc_display_panel_parent_class)->constructor (gtype, n_properties, properties);
- self = CC_DISPLAY_PANEL (obj);
- self->priv = DISPLAY_PANEL_PRIVATE (self);
+ output = gnome_rr_screen_get_output_by_name (priv->screen,
+ gnome_rr_output_info_get_name (priv->current_output));
+
+
+ dialog = gtk_dialog_new_with_buttons (gnome_rr_output_info_get_display_name (priv->current_output),
+ GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL
(panel)))),
+ GTK_DIALOG_MODAL,
+ _("_Cancel"), GTK_RESPONSE_REJECT,
+ _("_Apply"), GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+ gtk_widget_set_margin_left (box, 12);
+ gtk_widget_set_margin_right (box, 12);
+ gtk_widget_set_margin_top (box, 6);
+ gtk_widget_set_margin_bottom (box, 12);
+ gtk_container_add (GTK_CONTAINER (content_area), box);
+
+ /* configuration grid */
+ grid = gtk_grid_new ();
+ gtk_widget_set_margin_left (grid, 36);
+ gtk_widget_set_margin_right (grid, 36);
+ gtk_widget_set_margin_bottom (grid, 6);
+ gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
+ gtk_grid_set_row_spacing (GTK_GRID (grid), 12);
+
+ /* preview */
+ preview = display_preview_new (priv->current_output,
+ priv->current_configuration,
+ cc_display_panel_get_output_id (priv->current_output),
+ DISPLAY_PREVIEW_SETUP_HEIGHT);
+ gtk_grid_attach (GTK_GRID (grid), preview, 0, 0, 2, 1);
+
+ /* rotation */
+ rotation = gnome_rr_output_info_get_rotation (priv->current_output);
+ rotate_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_set_margin_bottom (rotate_box, 12);
+ gtk_style_context_add_class (gtk_widget_get_style_context (rotate_box),
+ GTK_STYLE_CLASS_LINKED);
+ gtk_grid_attach (GTK_GRID (grid), rotate_box, 0, 1, 2, 1);
+ gtk_widget_set_halign (rotate_box, GTK_ALIGN_CENTER);
+
+ priv->rotate_left_button = gtk_button_new ();
+ if (rotation == GNOME_RR_ROTATION_90)
+ gtk_widget_set_sensitive (priv->rotate_left_button, FALSE);
+ g_signal_connect (priv->rotate_left_button, "clicked",
+ G_CALLBACK (rotate_left_clicked), panel);
+ g_signal_connect_swapped (priv->rotate_left_button, "clicked",
+ G_CALLBACK (gtk_widget_queue_draw), preview);
+ gtk_container_add (GTK_CONTAINER (priv->rotate_left_button),
+ gtk_image_new_from_icon_name ("object-rotate-left-symbolic",
+ GTK_ICON_SIZE_BUTTON));
+ gtk_widget_set_halign (priv->rotate_left_button, GTK_ALIGN_END);
+ gtk_container_add (GTK_CONTAINER (rotate_box), priv->rotate_left_button);
+
+ priv->rotate_right_button = gtk_button_new ();
+ if (rotation == GNOME_RR_ROTATION_270)
+ gtk_widget_set_sensitive (priv->rotate_right_button, FALSE);
+ g_signal_connect (priv->rotate_right_button, "clicked",
+ G_CALLBACK (rotate_right_clicked), panel);
+ g_signal_connect_swapped (priv->rotate_right_button, "clicked",
+ G_CALLBACK (gtk_widget_queue_draw), preview);
+ gtk_container_add (GTK_CONTAINER (priv->rotate_right_button),
+ gtk_image_new_from_icon_name ("object-rotate-right-symbolic",
+ GTK_ICON_SIZE_BUTTON));
+ gtk_widget_set_halign (priv->rotate_right_button, GTK_ALIGN_START);
+ gtk_container_add (GTK_CONTAINER (rotate_box), priv->rotate_right_button);
+
+ /* size */
+ label = gtk_label_new (_("Size"));
+ gtk_style_context_add_class (gtk_widget_get_style_context (label),
+ GTK_STYLE_CLASS_DIM_LABEL);
+ gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1);
+ gtk_widget_set_halign (label, GTK_ALIGN_END);
+
+
+ gnome_rr_output_get_physical_size (output, &width_mm, &height_mm);
+ str = make_display_size_string (width_mm, height_mm);
+ label = gtk_label_new (str);
+ gtk_grid_attach (GTK_GRID (grid), label, 1, 2, 1, 1);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ g_free (str);
+
+ /* aspect ratio */
+ label = gtk_label_new (_("Aspect Ratio"));
+ gtk_style_context_add_class (gtk_widget_get_style_context (label),
+ GTK_STYLE_CLASS_DIM_LABEL);
+ gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1);
+ gtk_widget_set_halign (label, GTK_ALIGN_END);
+ label = gtk_label_new (make_aspect_string (gnome_rr_output_info_get_preferred_width (priv->current_output),
+ gnome_rr_output_info_get_preferred_height
(priv->current_output)));
+ gtk_grid_attach (GTK_GRID (grid), label, 1, 3, 1, 1);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+
+ /* resolution combo box */
+ res_model = gtk_list_store_new (2, G_TYPE_STRING, GNOME_TYPE_RR_MODE);
+ renderer = gtk_cell_renderer_text_new ();
+ priv->res_combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (res_model));
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->res_combo), renderer, TRUE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->res_combo), renderer, "text", 0);
+ g_signal_connect (priv->res_combo, "changed", G_CALLBACK (res_combo_changed),
+ panel);
+ g_signal_connect_swapped (priv->res_combo, "changed",
+ G_CALLBACK (gtk_widget_queue_draw), preview);
+
+ label = gtk_label_new (_("Resolution"));
+ gtk_style_context_add_class (gtk_widget_get_style_context (label),
+ GTK_STYLE_CLASS_DIM_LABEL);
+ gtk_grid_attach (GTK_GRID (grid), label, 0, 4, 1, 1);
+ gtk_grid_attach (GTK_GRID (grid), priv->res_combo, 1, 4, 1, 1);
+
+ gtk_widget_set_halign (label, GTK_ALIGN_END);
+ gtk_widget_set_halign (priv->res_combo, GTK_ALIGN_START);
+
+ was_clone = clone = gnome_rr_config_get_clone (priv->current_configuration);
+ was_primary = primary = gnome_rr_output_info_get_primary (priv->current_output);
+ active = gnome_rr_output_info_is_active (priv->current_output);
+
+ if (g_hash_table_size (output_ids) > 1)
+ {
+ frame = gtk_frame_new (NULL);
+ gtk_container_add (GTK_CONTAINER (box), frame);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+
+ listbox = gtk_list_box_new ();
+ gtk_container_add (GTK_CONTAINER (frame), listbox);
+ gtk_list_box_set_header_func (GTK_LIST_BOX (listbox),
+ cc_display_panel_list_box_update_header,
+ NULL, NULL);
+ g_signal_connect (listbox, "row-selected",
+ G_CALLBACK (setup_listbox_row_activated), panel);
+ g_signal_connect_swapped (listbox, "row-selected",
+ G_CALLBACK (gtk_widget_queue_draw), preview);
+ gtk_widget_show (listbox);
+
+ item = list_box_item (_("Primary"),
+ _("Show the top bar and Activities Overview on this display"));
+ gtk_container_add (GTK_CONTAINER (listbox), item);
+ if (primary)
+ gtk_list_box_select_row (GTK_LIST_BOX (listbox),
+ GTK_LIST_BOX_ROW (item));
+
+ item = list_box_item (_("Secondary Display"),
+ _("Join this display with another to create an extra workspace"));
+ gtk_container_add (GTK_CONTAINER (listbox), item);
+ if (!primary && !clone)
+ gtk_list_box_select_row (GTK_LIST_BOX (listbox),
+ GTK_LIST_BOX_ROW (item));
- error = NULL;
- self->priv->builder = builder = gtk_builder_new ();
+#if 0
+ item = list_box_item (_("Presentation"),
+ _("Show slideshows and media only"));
+ gtk_container_add (GTK_CONTAINER (listbox), item);
+#endif
- if (!gtk_builder_add_objects_from_resource (builder,
"/org/gnome/control-center/display/display-capplet.ui", objects, &error))
+ /* translators: "Mirror" describes when both displays show the same view */
+ item = list_box_item (_("Mirror"),
+ _("Show your existing view on both displays"));
+ gtk_container_add (GTK_CONTAINER (listbox), item);
+ if (clone && active)
+ gtk_list_box_select_row (GTK_LIST_BOX (listbox),
+ GTK_LIST_BOX_ROW (item));
+ }
+ else
{
- g_warning ("Could not parse UI definition: %s", error->message);
- g_error_free (error);
- g_object_unref (builder);
- return obj;
+ GnomeRRMode **modes;
+
+ modes = gnome_rr_output_list_modes (output);
+ setup_resolution_combo_box (panel, modes,
+ gnome_rr_output_get_current_mode (output));
}
- self->priv->screen = gnome_rr_screen_new (gdk_screen_get_default (), &error);
- g_signal_connect (self->priv->screen, "changed", G_CALLBACK (on_screen_changed), self);
- if (!self->priv->screen)
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+ gtk_container_add (GTK_CONTAINER (box), grid);
+ gtk_widget_show_all (box);
+
+ gnome_rr_output_info_get_geometry (priv->current_output, NULL, NULL,
+ &old_width, &old_height);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
{
- error_message (NULL, _("Could not get screen information"), error->message);
- g_error_free (error);
- g_object_unref (builder);
- return obj;
+ GnomeRROutputInfo **outputs;
+ GtkListBoxRow *row;
+ GnomeRRRotation rotation;
+
+ if (g_hash_table_size (output_ids) > 1)
+ {
+ gint new_width, new_height;
+
+ outputs = gnome_rr_config_get_outputs (priv->current_configuration);
+
+ gnome_rr_output_info_get_geometry (priv->current_output, NULL, NULL,
+ &new_width, &new_height);
+
+ row = gtk_list_box_get_selected_row (GTK_LIST_BOX (listbox));
+
+ switch (gtk_list_box_row_get_index (row))
+ {
+ case DISPLAY_MODE_PRIMARY:
+ primary = TRUE;
+ clone = FALSE;
+ break;
+
+#if 0
+ case DISPLAY_MODE_PRESENTATION:
+ gnome_rr_config_set_clone (priv->current_configuration, FALSE);
+ primary = FALSE;
+ clone = FALSE;
+ break;
+#endif
+
+ case DISPLAY_MODE_MIRROR:
+ clone = TRUE;
+ break;
+
+ case DISPLAY_MODE_SECONDARY:
+ primary = FALSE;
+ clone = FALSE;
+ break;
+ }
+
+ gnome_rr_output_info_set_active (priv->current_output, TRUE);
+ gnome_rr_output_info_set_primary (priv->current_output, primary);
+ gnome_rr_config_set_clone (priv->current_configuration, clone);
+
+ for (i = 0; outputs[i]; i++)
+ {
+ if (!gnome_rr_output_info_is_active (outputs[i]))
+ continue;
+
+ if (clone)
+ {
+ /* set all active outputs to the same size and position when
+ * cloning */
+ gnome_rr_output_info_set_geometry (outputs[i], 0, 0,
+ new_width, new_height);
+ }
+ else if (outputs[i] != priv->current_output)
+ {
+ /* ensure no other outputs are primary if this output is now
+ * primary, or find another output to set as primary if this
+ * output is no longer primary */
+
+ gnome_rr_output_info_set_primary (outputs[i], !primary);
+ if (!was_primary)
+ break;
+ }
+ }
+
+ /* if the display was previously in clone mode, ensure the outputs
+ * are arranged correctly */
+ if ((was_clone && !clone))
+ lay_out_outputs_horizontally (panel);
+
+ if (!clone)
+ realign_outputs_after_resolution_change (panel,
+ priv->current_output,
+ old_width, old_height);
+ }
+
+ /* check rotation */
+ rotation = gnome_rr_output_info_get_rotation (priv->current_output);
+
+ /* other options such as reflection are not supported */
+ rotation &= (GNOME_RR_ROTATION_0 | GNOME_RR_ROTATION_90
+ | GNOME_RR_ROTATION_180 | GNOME_RR_ROTATION_270);
+ if (rotation == 0)
+ rotation = GNOME_RR_ROTATION_0;
+ gnome_rr_output_info_set_rotation (priv->current_output, rotation);
+
+ apply_current_configuration (panel);
+ }
+ else
+ {
+ /* changes cancelled, so re-read the current configuration */
+ on_screen_changed (panel);
}
- self->priv->clock_settings = g_settings_new (CLOCK_SCHEMA);
+ priv->rotate_left_button = NULL;
+ priv->rotate_right_button = NULL;
+ priv->res_combo = NULL;
+ gtk_widget_destroy (dialog);
+}
+
+static void
+cc_display_panel_box_row_activated (GtkListBox *listbox,
+ GtkWidget *row,
+ CcDisplayPanel *panel)
+{
+ CcDisplayPanelPrivate *priv = panel->priv;
+ GnomeRROutputInfo *output_info;
+
+ gtk_list_box_select_row (listbox, NULL);
+
+ output_info = g_object_get_data (G_OBJECT (row), "gnome-rr-output");
+
+ if (!output_info)
+ return;
+
+ priv->current_output = output_info;
+
+ show_setup_dialog (panel);
+}
+
+static void
+mapped_cb (CcDisplayPanel *panel)
+{
+ CcDisplayPanelPrivate *priv = panel->priv;
+ CcShell *shell;
+ GtkWidget *toplevel;
- shell = cc_panel_get_shell (CC_PANEL (self));
+ shell = cc_panel_get_shell (CC_PANEL (panel));
toplevel = cc_shell_get_toplevel (shell);
- self->priv->focus_id = g_signal_connect (toplevel, "notify::has-toplevel-focus",
- G_CALLBACK (dialog_toplevel_focus_changed), self);
+ if (toplevel)
+ priv->focus_id = g_signal_connect (toplevel, "notify::has-toplevel-focus",
+ G_CALLBACK (dialog_toplevel_focus_changed), panel);
+}
- self->priv->panel = WID ("display-panel");
- g_signal_connect_after (self->priv->panel, "show",
- G_CALLBACK (dialog_map_event_cb), self);
+static void
+cc_display_panel_up_client_changed (UpClient *client,
+ CcDisplayPanel *self)
+{
+ CcDisplayPanelPrivate *priv = self->priv;
+ gboolean lid_is_closed;
- self->priv->current_monitor_event_box = WID ("current_monitor_event_box");
- self->priv->current_monitor_label = WID ("current_monitor_label");
+ lid_is_closed = up_client_get_lid_is_closed (client);
- self->priv->monitor_switch = WID ("monitor_switch");
- g_signal_connect (self->priv->monitor_switch, "notify::active",
- G_CALLBACK (monitor_switch_active_cb), self);
+ if (lid_is_closed != priv->lid_is_closed)
+ {
+ priv->lid_is_closed = lid_is_closed;
- self->priv->resolution_combo = WID ("resolution_combo");
- g_signal_connect (self->priv->resolution_combo, "changed",
- G_CALLBACK (on_resolution_changed), self);
+ on_screen_changed (self);
+ }
+}
- self->priv->rotation_combo = WID ("rotation_combo");
- g_signal_connect (self->priv->rotation_combo, "changed",
- G_CALLBACK (on_rotation_changed), self);
+static void
+cc_display_panel_init (CcDisplayPanel *self)
+{
+ CcDisplayPanelPrivate *priv;
+ GtkWidget *frame, *vbox;
+ GError *error = NULL;
- self->priv->clone_checkbox = WID ("clone_checkbox");
- g_signal_connect (self->priv->clone_checkbox, "toggled",
- G_CALLBACK (on_clone_changed), self);
+ g_resources_register (cc_display_get_resource ());
- self->priv->clone_label = WID ("clone_resolution_warning_label");
+ priv = self->priv = DISPLAY_PANEL_PRIVATE (self);
- g_signal_connect (WID ("detect_displays_button"),
- "clicked", G_CALLBACK (on_detect_displays), self);
+ priv->screen = gnome_rr_screen_new (gdk_screen_get_default (), &error);
+ if (!priv->screen)
+ {
+ gtk_container_add (GTK_CONTAINER (self),
+ gtk_label_new (_("Could not get screen information")));
+ g_error_free (error);
- make_text_combo (self->priv->resolution_combo, 4);
- make_text_combo (self->priv->rotation_combo, -1);
+ gtk_widget_show_all (GTK_WIDGET (self));
- /* Scroll Area */
- self->priv->area = (GtkWidget *)foo_scroll_area_new ();
+ return;
+ }
- g_object_set_data (G_OBJECT (self->priv->area), "panel", self);
+ output_ids = g_hash_table_new (g_direct_hash, g_direct_equal);
- set_monitors_tooltip (self, FALSE);
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+ gtk_container_add (GTK_CONTAINER (self), vbox);
- /* FIXME: this should be computed dynamically */
- foo_scroll_area_set_min_size (FOO_SCROLL_AREA (self->priv->area), 0, 200);
- gtk_widget_show (self->priv->area);
- g_signal_connect (self->priv->area, "paint",
- G_CALLBACK (on_area_paint), self);
- g_signal_connect (self->priv->area, "viewport_changed",
- G_CALLBACK (on_viewport_changed), self);
+ frame = gtk_frame_new (NULL);
+ gtk_widget_set_margin_left (vbox, 134);
+ gtk_widget_set_margin_right (vbox, 134);
+ gtk_widget_set_margin_top (vbox, 22);
+ gtk_widget_set_margin_bottom (vbox, 22);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (vbox), frame);
- align = WID ("align");
+ priv->displays_listbox = gtk_list_box_new ();
+ gtk_list_box_set_header_func (GTK_LIST_BOX (priv->displays_listbox),
+ cc_display_panel_list_box_update_header, NULL,
+ NULL);
+ g_signal_connect (priv->displays_listbox, "row-activated",
+ G_CALLBACK (cc_display_panel_box_row_activated),
+ self);
+ gtk_container_add (GTK_CONTAINER (frame), priv->displays_listbox);
- gtk_container_add (GTK_CONTAINER (align), self->priv->area);
- on_screen_changed (self->priv->screen, self);
+ priv->arrange_button = gtk_button_new_with_mnemonic (_("_Arrange Combined Displays"));
+ g_signal_connect (priv->arrange_button, "clicked",
+ G_CALLBACK (show_arrange_displays_dialog), self);
+ gtk_widget_set_halign (priv->arrange_button, GTK_ALIGN_CENTER);
- g_signal_connect_swapped (WID ("apply_button"),
- "clicked", G_CALLBACK (apply), self);
+ gtk_container_add (GTK_CONTAINER (vbox), priv->arrange_button);
+ gtk_widget_show_all (vbox);
- gtk_widget_show (self->priv->panel);
- gtk_container_add (GTK_CONTAINER (self), self->priv->panel);
+ on_screen_changed (self);
+ priv->screen_changed_handler_id = g_signal_connect_swapped (priv->screen,
+ "changed",
+ G_CALLBACK (on_screen_changed),
+ self);
self->priv->up_client = up_client_new ();
if (up_client_get_lid_is_present (self->priv->up_client))
@@ -2658,5 +2150,5 @@ cc_display_panel_constructor (GType gtype,
else
g_clear_object (&self->priv->up_client);
- return obj;
+ g_signal_connect (self, "map", G_CALLBACK (mapped_cb), NULL);
}
diff --git a/panels/display/cc-display-panel.h b/panels/display/cc-display-panel.h
index dd02c2b..881d203 100644
--- a/panels/display/cc-display-panel.h
+++ b/panels/display/cc-display-panel.h
@@ -24,6 +24,8 @@
#define _CC_DISPLAY_PANEL_H
#include <shell/cc-panel.h>
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-rr-config.h>
G_BEGIN_DECLS
@@ -66,6 +68,7 @@ struct _CcDisplayPanelClass
};
GType cc_display_panel_get_type (void) G_GNUC_CONST;
+gint cc_display_panel_get_output_id (GnomeRROutputInfo *output);
G_END_DECLS
diff --git a/panels/display/cc-rr-labeler.c b/panels/display/cc-rr-labeler.c
index ea8a7fd..646b112 100644
--- a/panels/display/cc-rr-labeler.c
+++ b/panels/display/cc-rr-labeler.c
@@ -38,13 +38,13 @@
#endif
#include "cc-rr-labeler.h"
+#include "cc-display-panel.h"
struct _CcRRLabelerPrivate {
GnomeRRConfig *config;
int num_outputs;
- GdkRGBA *palette;
GtkWidget **windows;
GdkScreen *screen;
@@ -179,8 +179,6 @@ cc_rr_labeler_finalize (GObject *object)
g_free (labeler->priv->windows);
}
- g_free (labeler->priv->palette);
-
G_OBJECT_CLASS (cc_rr_labeler_parent_class)->finalize (object);
}
@@ -197,45 +195,6 @@ count_outputs (GnomeRRConfig *config)
}
static void
-make_palette (CcRRLabeler *labeler)
-{
- /* The idea is that we go around an hue color wheel. We want to start
- * at red, go around to green/etc. and stop at blue --- because magenta
- * is evil. Eeeeek, no magenta, please!
- *
- * Purple would be nice, though. Remember that we are watered down
- * (i.e. low saturation), so that would be like Like berries with cream.
- * Mmmmm, berries.
- */
- double start_hue;
- double end_hue;
- int i;
-
- g_assert (labeler->priv->num_outputs > 0);
-
- labeler->priv->palette = g_new (GdkRGBA, labeler->priv->num_outputs);
-
- start_hue = 0.0; /* red */
- end_hue = 2.0/3; /* blue */
-
- for (i = 0; i < labeler->priv->num_outputs; i++) {
- double h, s, v;
- double r, g, b;
-
- h = start_hue + (end_hue - start_hue) / labeler->priv->num_outputs * i;
- s = 1.0 / 3;
- v = 1.0;
-
- gtk_hsv_to_rgb (h, s, v, &r, &g, &b);
-
- labeler->priv->palette[i].red = r;
- labeler->priv->palette[i].green = g;
- labeler->priv->palette[i].blue = b;
- labeler->priv->palette[i].alpha = 1.0;
- }
-}
-
-static void
rounded_rectangle (cairo_t *cr,
gint x,
gint y,
@@ -274,7 +233,9 @@ rounded_rectangle (cairo_t *cr,
cairo_close_path (cr);
}
-#define LABEL_WINDOW_EDGE_THICKNESS 2
+#define LABEL_WINDOW_SIZE 80
+#define LABEL_WINDOW_MARGIN 14
+#define LABEL_WINDOW_EDGE_THICKNESS 1
#define LABEL_WINDOW_PADDING 12
/* Look for panel-corner in:
* http://git.gnome.org/browse/gnome-shell/tree/data/theme/gnome-shell.css
@@ -285,10 +246,9 @@ static void
label_draw_background_and_frame (GtkWidget *widget, cairo_t *cr, gboolean for_shape)
{
GdkRGBA shape_color = { 0, 0, 0, 1 };
- GdkRGBA *rgba;
+ GdkRGBA black = { 0, 0, 0, 0.75 };
GtkAllocation allocation;
- rgba = g_object_get_data (G_OBJECT (widget), "rgba");
gtk_widget_get_allocation (widget, &allocation);
cairo_save (cr);
@@ -298,7 +258,7 @@ label_draw_background_and_frame (GtkWidget *widget, cairo_t *cr, gboolean for_sh
if (for_shape)
gdk_cairo_set_source_rgba (cr, &shape_color);
else
- cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
+ cairo_set_source_rgba (cr, 0.75, 0.75, 0.75, 0.75);
rounded_rectangle (cr,
LABEL_WINDOW_EDGE_THICKNESS / 2.0,
@@ -313,8 +273,7 @@ label_draw_background_and_frame (GtkWidget *widget, cairo_t *cr, gboolean for_sh
if (for_shape) {
gdk_cairo_set_source_rgba (cr, &shape_color);
} else {
- rgba->alpha = 0.75;
- gdk_cairo_set_source_rgba (cr, rgba);
+ gdk_cairo_set_source_rgba (cr, &black);
}
rounded_rectangle (cr,
@@ -362,7 +321,8 @@ position_window (CcRRLabeler *labeler,
&monitor);
gdk_rectangle_intersect (&monitor, &workarea, &workarea);
- gtk_window_move (GTK_WINDOW (window), workarea.x, workarea.y);
+ gtk_window_move (GTK_WINDOW (window), workarea.x + LABEL_WINDOW_MARGIN,
+ workarea.y + LABEL_WINDOW_MARGIN);
}
static void
@@ -386,17 +346,21 @@ label_window_composited_changed_cb (GtkWidget *widget, CcRRLabeler *labeler)
}
static GtkWidget *
-create_label_window (CcRRLabeler *labeler, GnomeRROutputInfo *output, GdkRGBA *rgba)
+create_label_window (CcRRLabeler *labeler, GnomeRROutputInfo *output)
{
GtkWidget *window;
GtkWidget *widget;
char *str;
- const char *display_name;
- GdkRGBA black = { 0, 0, 0, 1.0 };
- int x, y;
+ GdkRGBA white = { 1, 1, 1, 1 };
+ int x, y, display_num;
GdkScreen *screen;
GdkVisual *visual;
+ display_num = cc_display_panel_get_output_id (output);
+
+ if (display_num == 0)
+ return NULL;
+
window = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_TOOLTIP);
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
@@ -407,13 +371,8 @@ create_label_window (CcRRLabeler *labeler, GnomeRROutputInfo *output, GdkRGBA *r
if (visual != NULL)
gtk_widget_set_visual (window, visual);
- gtk_container_set_border_width (GTK_CONTAINER (window), LABEL_WINDOW_PADDING +
LABEL_WINDOW_EDGE_THICKNESS);
-
- /* This is semi-dangerous. The color is part of the labeler->palette
- * array. Note that in cc_rr_labeler_finalize(), we are careful to
- * free the palette only after we free the windows.
- */
- g_object_set_data (G_OBJECT (window), "rgba", rgba);
+ gtk_widget_set_size_request (window, LABEL_WINDOW_SIZE,
+ LABEL_WINDOW_SIZE);
g_signal_connect (window, "draw",
G_CALLBACK (label_window_draw_event_cb), labeler);
@@ -422,30 +381,18 @@ create_label_window (CcRRLabeler *labeler, GnomeRROutputInfo *output, GdkRGBA *r
g_signal_connect (window, "composited-changed",
G_CALLBACK (label_window_composited_changed_cb), labeler);
- if (gnome_rr_config_get_clone (labeler->priv->config)) {
- /* Keep this string in sync with
gnome-control-center/capplets/display/xrandr-capplet.c:get_display_name() */
-
- /* Translators: this is the feature where what you see on your
- * laptop's screen is the same as your external projector.
- * Here, "Mirrored" is being used as an adjective. For example,
- * the Spanish translation could be "Pantallas en Espejo".
- */
- display_name = _("Mirrored Displays");
- } else
- display_name = gnome_rr_output_info_get_display_name (output);
-
- str = g_strdup_printf ("<b>%s</b>", display_name);
+ str = g_strdup_printf ("<span size='xx-large' font-weight='bold'>%d</span>", display_num);
widget = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (widget), str);
g_free (str);
- /* Make the label explicitly black. We don't want it to follow the
- * theme's colors, since the label is always shown against a light
- * pastel background. See bgo#556050
+ /* Make the label explicitly white. We don't want it to follow the
+ * theme's colors, since the label is always shown against a black
+ * background. See bgo#556050
*/
gtk_widget_override_color (widget,
gtk_widget_get_state_flags (widget),
- &black);
+ &white);
gtk_container_add (GTK_CONTAINER (window), widget);
@@ -463,8 +410,6 @@ setup_from_config (CcRRLabeler *labeler)
{
labeler->priv->num_outputs = count_outputs (labeler->priv->config);
- make_palette (labeler);
-
cc_rr_labeler_show (labeler);
}
@@ -497,7 +442,6 @@ void
cc_rr_labeler_show (CcRRLabeler *labeler)
{
int i;
- gboolean created_window_for_clone;
GnomeRROutputInfo **outputs;
g_return_if_fail (GNOME_IS_RR_LABELER (labeler));
@@ -505,18 +449,16 @@ cc_rr_labeler_show (CcRRLabeler *labeler)
if (labeler->priv->windows != NULL)
return;
- labeler->priv->windows = g_new (GtkWidget *, labeler->priv->num_outputs);
-
- created_window_for_clone = FALSE;
+ if (gnome_rr_config_get_clone (labeler->priv->config))
+ return;
outputs = gnome_rr_config_get_outputs (labeler->priv->config);
- for (i = 0; i < labeler->priv->num_outputs; i++) {
- if (!created_window_for_clone && gnome_rr_output_info_is_active (outputs[i])) {
- labeler->priv->windows[i] = create_label_window (labeler, outputs[i],
labeler->priv->palette + i);
+ labeler->priv->windows = g_new (GtkWidget *, labeler->priv->num_outputs);
- if (gnome_rr_config_get_clone (labeler->priv->config))
- created_window_for_clone = TRUE;
+ for (i = 0; i < labeler->priv->num_outputs; i++) {
+ if (gnome_rr_output_info_is_active (outputs[i])) {
+ labeler->priv->windows[i] = create_label_window (labeler, outputs[i]);
} else
labeler->priv->windows[i] = NULL;
}
@@ -549,37 +491,3 @@ cc_rr_labeler_hide (CcRRLabeler *labeler)
g_free (priv->windows);
priv->windows = NULL;
}
-
-/**
- * cc_rr_labeler_get_rgba_for_output:
- * @labeler: A #CcRRLabeler
- * @output: Output device (i.e. monitor) to query
- * @rgba_out: (out): Color of selected monitor.
- *
- * Get the color used for the label on a given output (monitor).
- */
-void
-cc_rr_labeler_get_rgba_for_output (CcRRLabeler *labeler, GnomeRROutputInfo *output, GdkRGBA *rgba_out)
-{
- int i;
- GnomeRROutputInfo **outputs;
-
- g_return_if_fail (GNOME_IS_RR_LABELER (labeler));
- g_return_if_fail (GNOME_IS_RR_OUTPUT_INFO (output));
- g_return_if_fail (rgba_out != NULL);
-
- outputs = gnome_rr_config_get_outputs (labeler->priv->config);
-
- for (i = 0; i < labeler->priv->num_outputs; i++)
- if (outputs[i] == output) {
- *rgba_out = labeler->priv->palette[i];
- return;
- }
-
- g_warning ("trying to get the color for unknown GnomeOutputInfo %p; returning magenta!", output);
-
- rgba_out->red = 1.0;
- rgba_out->green = 0;
- rgba_out->blue = 1.0;
- rgba_out->alpha = 1.0;
-}
diff --git a/panels/display/cc-rr-labeler.h b/panels/display/cc-rr-labeler.h
index fdecf29..860accf 100644
--- a/panels/display/cc-rr-labeler.h
+++ b/panels/display/cc-rr-labeler.h
@@ -59,6 +59,4 @@ void cc_rr_labeler_show (CcRRLabeler *labeler);
void cc_rr_labeler_hide (CcRRLabeler *labeler);
-void cc_rr_labeler_get_rgba_for_output (CcRRLabeler *labeler, GnomeRROutputInfo *output, GdkRGBA *rgba_out);
-
#endif
diff --git a/panels/display/display-capplet.ui b/panels/display/display-capplet.ui
index 6906e5d..386bd3b 100644
--- a/panels/display/display-capplet.ui
+++ b/panels/display/display-capplet.ui
@@ -1,312 +1,518 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="2.16"/>
- <!-- interface-naming-policy toplevel-contextual -->
+ <!-- interface-requires gtk+ 3.10 -->
<object class="GtkWindow" id="window1">
+ <property name="can_focus">False</property>
<child>
- <object class="GtkVBox" id="display-panel">
+ <object class="GtkFrame" id="frame1">
<property name="visible">True</property>
- <property name="border_width">10</property>
- <property name="orientation">vertical</property>
- <property name="spacing">12</property>
- <property name="margin-left">6</property>
- <property name="margin-right">6</property>
- <property name="margin-top">6</property>
- <property name="margin-bottom">6</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">134</property>
+ <property name="margin_right">134</property>
+ <property name="margin_top">22</property>
+ <property name="margin_bottom">22</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">in</property>
<child>
- <object class="GtkAlignment" id="align">
+ <object class="GtkListBox" id="listbox1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<child>
- <placeholder/>
+ <object class="GtkListBoxRow" id="listboxrow1">
+ <property name="can_focus">False</property>
+ <property name="margin_bottom">67</property>
+ </object>
</child>
</object>
- <packing>
- <property name="position">0</property>
- </packing>
</child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkWindow" id="window2">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
<child>
- <object class="GtkHBox" id="hbox1">
+ <object class="GtkFrame" id="frame2">
<property name="visible">True</property>
- <property name="spacing">12</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">39</property>
+ <property name="margin_right">39</property>
+ <property name="margin_top">22</property>
+ <property name="margin_bottom">22</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">in</property>
<child>
- <object class="GtkVBox" id="vbox1">
+ <object class="GtkListBox" id="listbox2">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">12</property>
+ <property name="can_focus">False</property>
<child>
- <object class="GtkHBox" id="hbox3">
+ <object class="GtkListBoxRow" id="listboxrow3">
+ <property name="width_request">100</property>
+ <property name="height_request">80</property>
<property name="visible">True</property>
- <property name="spacing">12</property>
+ <property name="can_focus">True</property>
<child>
- <object class="GtkEventBox" id="current_monitor_event_box">
+ <object class="GtkBox" id="box2">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkLabel" id="current_monitor_label">
+ <object class="GtkLabel" id="label3">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">10</property>
- <property name="ypad">5</property>
- <property name="label" translatable="yes">Monitor</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Primary</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="width_request">260</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Show the top bar and Activities
Overview on this display</property>
+ <property name="wrap">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</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>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBoxRow" id="listboxrow2">
+ <property name="width_request">100</property>
+ <property name="height_request">80</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
<child>
- <object class="GtkHBox" id="hbox2">
+ <object class="GtkBox" id="box3">
<property name="visible">True</property>
- <property name="spacing">12</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkSwitch" id="monitor_switch">
+ <object class="GtkLabel" id="label5">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="active">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Presentation</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
</object>
<packing>
<property name="expand">False</property>
- <property name="fill">False</property>
+ <property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="width_request">260</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Show slideshows and media
only</property>
+ <property name="wrap">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</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="GtkAlignment" id="alignment1">
+ <object class="GtkListBoxRow" id="listboxrow4">
+ <property name="width_request">100</property>
+ <property name="height_request">80</property>
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="yalign">0</property>
- <property name="left_padding">12</property>
+ <property name="can_focus">True</property>
<child>
- <object class="GtkTable" id="table1">
+ <object class="GtkBox" id="box4">
<property name="visible">True</property>
- <property name="n_rows">3</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">12</property>
- <property name="row_spacing">6</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkAlignment" id="alignment4">
+ <object class="GtkLabel" id="label7">
<property name="visible">True</property>
- <child>
- <placeholder/>
- </child>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Mirror</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
</object>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options"></property>
- <property name="y_options"></property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="label2">
+ <object class="GtkLabel" id="label8">
+ <property name="width_request">260</property>
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Resolution</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">resolution_combo</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Show your primary display on this
screen also</property>
+ <property name="wrap">True</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBoxRow" id="listboxrow5">
+ <property name="width_request">100</property>
+ <property name="height_request">80</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkBox" id="box5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkLabel" id="label5">
+ <object class="GtkLabel" id="label9">
<property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">R_otation</property>
- <property name="mnemonic_widget">rotation_combo</property>
- <property name="use_underline">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Combine</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label10">
+ <property name="width_request">260</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Join with the primary display to
create an extra space</property>
+ <property name="wrap">True</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBoxRow" id="listboxrow6">
+ <property name="width_request">100</property>
+ <property name="height_request">80</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkBox" id="box6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkComboBox" id="resolution_combo">
+ <object class="GtkLabel" id="label11">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Turn Off</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
</object>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="y_options"></property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkComboBox" id="rotation_combo">
+ <object class="GtkLabel" id="label12">
+ <property name="width_request">260</property>
<property name="visible">True</property>
- <child>
- <object class="GtkCellRendererText" id="cellrenderertext1"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
- </child>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Don't use the display</property>
+ <property name="wrap">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
</object>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options"></property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
- <child>
- <placeholder/>
- </child>
</object>
</child>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
</child>
</object>
- <packing>
- <property name="position">0</property>
- </packing>
</child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">67</property>
+ <property name="margin_right">67</property>
+ <property name="margin_top">22</property>
+ <property name="margin_bottom">22</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">12</property>
<child>
- <object class="GtkAlignment" id="alignment2">
+ <object class="GtkDrawingArea" id="drawingarea1">
+ <property name="height_request">100</property>
<property name="visible">True</property>
- <child>
- <placeholder/>
- </child>
+ <property name="can_focus">False</property>
</object>
<packing>
- <property name="position">1</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ <property name="height">1</property>
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox2">
+ <object class="GtkBox" id="box8">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="can_focus">False</property>
+ <style>
+ <class name="linked"/>
+ </style>
<child>
- <object class="GtkCheckButton" id="clone_checkbox">
- <property name="label" translatable="yes" comments="Note that mirror is a verb in this
string">_Mirror displays</property>
+ <object class="GtkButton" id="button2">
+ <property name="name">rotate-left-button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">object-rotate-left-symbolic</property>
+ </object>
+ </child>
</object>
<packing>
<property name="expand">False</property>
- <property name="fill">False</property>
+ <property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="clone_resolution_warning_label">
+ <object class="GtkButton" id="button3">
+ <property name="name">rotate-right-button</property>
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Note: may limit resolution options</property>
- <attributes>
- <attribute name="style" value="italic"/>
- </attributes>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">object-rotate-right-symbolic</property>
+ </object>
+ </child>
</object>
<packing>
<property name="expand">False</property>
- <property name="fill">False</property>
+ <property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="position">2</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ <property name="height">1</property>
</packing>
</child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkAlignment" id="alignment3">
- <property name="visible">True</property>
- <property name="top_padding">10</property>
<child>
- <object class="GtkHButtonBox" id="hbuttonbox1">
+ <object class="GtkLabel" id="label13">
<property name="visible">True</property>
- <property name="spacing">6</property>
- <property name="layout_style">end</property>
- <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="can_default">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">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="detect_displays_button">
- <property name="label" translatable="yes">_Detect Displays</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- <property name="secondary">True</property>
- </packing>
- </child>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Model</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label14">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Aspect Ratio</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label15">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Resolution</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
</object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label16">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Refresh Rate</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="model-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="aspect-ratio-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="resolution-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="refresh-rate-comboboxtext">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">5</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
</child>
</object>
<packing>
<property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
</object>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]