Merge lp:~hikiko/unity-control-center/unity-control-center.per-monitor-fonts-scale-factor-slider into lp:unity-control-center

Proposed by Robert Ancell
Status: Merged
Approved by: Sebastien Bacher
Approved revision: no longer in the source branch.
Merged at revision: 12714
Proposed branch: lp:~hikiko/unity-control-center/unity-control-center.per-monitor-fonts-scale-factor-slider
Merge into: lp:unity-control-center
Diff against target: 631 lines (+240/-44)
3 files modified
debian/control (+1/-0)
panels/display/cc-display-panel.c (+132/-0)
panels/display/display-capplet.ui (+107/-44)
To merge this branch: bzr merge lp:~hikiko/unity-control-center/unity-control-center.per-monitor-fonts-scale-factor-slider
Reviewer Review Type Date Requested Status
Sebastien Bacher Needs Fixing
Matthew Paul Thomas (community) design Needs Fixing
Robert Ancell Needs Fixing
PS Jenkins bot (community) continuous-integration Approve
Brandon Schaefer (community) Approve
Review via email: mp+205227@code.launchpad.net

Commit message

Add a slider that can change the fonts-scale-factor gsetting (per monitor text scaling factor)

Description of the change

added a slider that can change the fonts-scale-factor gsetting (per monitor text scaling factor)
here's a way to test it:
http://paste.ubuntu.com/6873091/

To post a comment you must log in.
Revision history for this message
Robert Ancell (robert-ancell) :
review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Eleni Maria Stea (hikiko) wrote :

This MP was moved so the previous reviews (http://paste.ubuntu.com/6891211/) had been deleted. Some comments on the changes I've made:

---

Change #1: fixed a bug

Robert Ancell (robert-ancell) wrote 21 hours ago: #
> I think this is a bug:
+ if (self->priv->config_string)
+ cfgstr_destroy (self->priv->config_string)
> Shouldn't self->priv->config_string be set to NULL otherwise it might be destroyed twice?

Thanks, it was actually a bug, so I fixed it.

---

Change #2: added glib dependency, replaced the linked list in ConfigString with a GHashTable and strip_whitespaces with g_strstrip

Robert Ancell (robert-ancell) wrote 20 hours ago: #
> As far as I can tell ConfigString is just a hash table, i.e. you need to map the scaling factor (a float) to each
> monitor (with a string name).
> So you should something like:
> table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);

I didn't use a hash table because the keys are monitor names which means that they usually are 1 or 2 and they can't exceed 6. Using a hash table instead of a simple linked list in this case is pointless as an optimization, and actually degrades performance as we introduce the overhead of calculating hash functions for every lookup and modification.

Nevertheless, the difference is negligible, so since you insist, I've changed it for consistency with the rest of the code.

Robert Ancell (robert-ancell) wrote 21 hours ago: #
> you should use g_strstrip() instead of strip_whitespace()

I wasn't using glib anywhere else so, there was no point in introducing glib just to strip whitespaces, fixed now.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

LGTM.

So to add a bit more to what the purpose of this is. We need sliders for each monitor hooked up to control each monitors scale DPI setting. This way we can scale things up accordingly in unity, or any application. The information we are storing/getting is based off

S -> <MonitorName>=<ScaleValue>;S | <MonitorName=<ScaleValue>

So the only valid strings (settings) must be in some form of S.

Just some more information!

review: Approve
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

S -> <MonitorName>=<ScaleValue>;S | <MonitorName>=<ScaleValue>

Revision history for this message
Eleni Maria Stea (hikiko) wrote :

new requirements, so I've changed the status to work in progress!

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Robert Ancell (robert-ancell) wrote :

This code should be removed:

56 +/* DEBUG */
57 +/*
58 +static void
59 +print_dict_entries (GVariant *dict)

review: Needs Fixing
Revision history for this message
Robert Ancell (robert-ancell) wrote :

You should return FALSE here - the return value is a gboolean, not an integer.

+ return 0; /* gtk should still process this event */

review: Needs Fixing
Revision history for this message
Robert Ancell (robert-ancell) wrote :

gtk_adjustment_get_value() returns a double, not an integer. Also, you can just use gtk_range_get_value().

195 + GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE(ui_scale));
196 + int value = gtk_adjustment_get_value (adj);

review: Needs Fixing
Revision history for this message
Robert Ancell (robert-ancell) wrote :

Where is the com.ubuntu.desktop schema? We need to depend on it otherwise the panel crashes.

Revision history for this message
Robert Ancell (robert-ancell) wrote :

The GVariant dictionary modification code is quite complicated, but that seems unavoidable with the current API. There's new API landing in the next release that makes this a lot simpler. We should shift to using that when it is available. (probably a second MP).

Revision history for this message
Eleni Maria Stea (hikiko) wrote :

Hey Robert, thanks for the review! I agree about the GVariant overcomplication, but the Unity8 people need it to be done this way because it's more convenient for them. I should definately do a second MP at a later point.

About the dependency: the gsetting is in the gsettings-ubuntu-touch-schemas package that will be renamed by the Gnome people, probably today, so, I will add the dependency right after this. (Sorry I forgot to mention it in a comment :))

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Sebastien Bacher (seb128) wrote :

the gsettings schemas is in https://launchpad.net/~ci-train-ppa-service/+archive/landing-008/

I want to rename the binary to drop -touch since it's not specific to touch, but we are going to have a transitional binary anyway, so feel free to start by using the old name and we can rename later in the week once the new binary is uploaded

Revision history for this message
Robert Ancell (robert-ancell) wrote :

> the gsettings schemas is in https://launchpad.net/~ci-train-ppa-
> service/+archive/landing-008/
>
> I want to rename the binary to drop -touch since it's not specific to touch,
> but we are going to have a transitional binary anyway, so feel free to start
> by using the old name and we can rename later in the week once the new binary
> is uploaded

You could also drop the gsettings- from the prefix. That's a bit odd...

Revision history for this message
Robert Ancell (robert-ancell) wrote :

> > the gsettings schemas is in https://launchpad.net/~ci-train-ppa-
> > service/+archive/landing-008/
> >
> > I want to rename the binary to drop -touch since it's not specific to touch,
> > but we are going to have a transitional binary anyway, so feel free to start
> > by using the old name and we can rename later in the week once the new
> binary
> > is uploaded
>
> You could also drop the gsettings- from the prefix. That's a bit odd...

Also, gsettings-ubuntu-touch-schemas has the following depends:
Depends: dconf-gsettings-backend | gsettings-backend, ubuntu-touch-sounds
which drags in 11M of sound files for no apparent reason.

Revision history for this message
Robert Ancell (robert-ancell) wrote :

Eleni, the only thing that's blocking this is you need to make unity-control-center depend on gsettings-ubuntu-touch-schemas with at least the version that adds the com.ubuntu.desktop schema. This is done in debian/control.

Revision history for this message
Robert Ancell (robert-ancell) wrote :

OK, so now I can run it I can see some problems.

1. The font scale control is on the right of the dialog, why is it not in the vertical list with the other controls (Resolution, Rotation, Launcher placement, Sticky edges)? I would expect it to be there.

2. When starting it up with no font scale set it shows the scale set to "0.981". I would expect this should be 1 right?

3. The units of the scale are unclear, is this a percentage? If so, it should probably say "100%".

4. If I drag the slider and look at the gsetting value in dconf-editor it appears to be an integer. So when the dialog says "1.94" the setting is 19. Is this correct? If so, then you're only storing one decimal place but showing two in the interface. That's confusing.

5. It doesn't seem possible to drag the scale to 1.0 - You should add a mark with gtk_scale_add_mark () so this can be easily done (and also hint what the default is).

review: Needs Fixing
Revision history for this message
Robert Ancell (robert-ancell) wrote :

All these variables seem to be unused:

174 + GVariant *dict;
175 + GVariant *dict_entry;
176 + GVariant *tmp;
177 + int foo;

Revision history for this message
Robert Ancell (robert-ancell) wrote :

This is what the dialog looks like when first used:
http://imgur.com/cVlLyV0

Revision history for this message
Eleni Maria Stea (hikiko) wrote :

1. We put it on the right side because it's not part of the XRand settings and there was plenty of space :) It's easy to move it on the left though if designers don't like it :)

2. Well, here's the problem we had: the unity8/qml-apps people required that the scale factor is an integer from 4-30 (and they might change it later to 2-30) and that it's stored like an integer. In unity7 we needed a float value from 0.5 to 3.0 (similar to the text-scaling-factor gnome setting). At the same time, the Unity8/QML people required that the setting appears to be a decimal number so that it doesn't confuse the user...

So, in cc-display-panel.c I map the Unity8 integer values that are in [FONTS_SCALE_MIN, FONTS_SDALE_MAX] interval,
#define FONTS_SCALE_MIN 4.0
#define FONTS_SCALE_MAX 30.0

to floating values in the [FONTS_SCALE_MIN_DISP, FONTS_SCALE_MAX_DISP] interval using interpolation...
#define FONTS_SCALE_MIN_DISP 0.5
#define FONTS_SCALE_MAX_DISP 3.0

Then, in unity7, I get the integer value and I convert it to float using the reverse calculation... Ideally, we could use a different gsetting for each DE but there was a requirement that we have only one factor for all aps in all desktops.

3. It's not a percentage, for the unity7 people that's a value that means: <desired_dpi> / 96.0 like the text-scaling-factor in Gnome, for the Unity8 people it's just a decimal number, that looks better than 4, 5, ... , 30

4. Yes, it's correct, we should store the 19 and show the 1.94 because the 19 is the real value in the [4, 30] interval and the 1.94 is the equivalent floating number in the [0.5, 3.0] (I know it's overcomplicated but that's in the requirements...) You can check the static gchar* on_ui_scale_format_value (GtkScale *ui_scale, gdouble value) function to see how I do the conversion.

5. It's not possible because the slider is an integer scale... It can only allow the values 4, 5, ..., 30 and it shows the decimal equivalent value in [0.5, 3.0] so if none of the integer values 4-30 is mapped to 1.0 you can't select the 1.0 (you have to change the FONTS_SCALE_* to find another interval probably)

I think Kaleo could explain you better why they need the integers in QML/Unity8 and the discrete values in the slider. The other idea was to have a slider with floating numbers and just round to the closest integer (eg: 1.05 would be converted to a float in [4, 30] and then rounded in the closest integer in this interval), but they told me to only allow the (4, 5,..., 30) to be selected and use discrete values because it's more convenient for Unity8/QML apps. We had a discussion on that because the integer values are a restriction for Unity7 and decided to use the design that the Unity8/QML people had proposed...

Revision history for this message
Matthew Paul Thomas (mpt) wrote :

> We put it on the right side because it's not part of the XRand settings and there was plenty of space :) It's easy to move it on the left though if designers don't like it :)

Most users have never heard of XRand, so they don't care which piece of plumbing is powering each setting. Please do put the slider immediately below the "Rotation" menu. Thanks!

Agreed with Robert's other comments as well. If the default is "0.981", people will think they've nudged the slider accidentally. If the default can't be "100%", then show actual dpi values, even if the underlying setting uses different units.

review: Needs Fixing (design)
Revision history for this message
Eleni Maria Stea (hikiko) wrote :

Sure, I'll move it to the left. The rest should be discussed with the Unity8/QML people. They only need to change their intervals to fix this I think.

Revision history for this message
Sebastien Bacher (seb128) wrote :

the schemas is being renamed gsettings-ubuntu-schemas in https://code.launchpad.net/~laney/gsettings-ubuntu-touch-schemas/rename-packages/+merge/207179 , can you change the depends to that (you can version to (>= 0.0.1+14.04.20140219))

Revision history for this message
Sebastien Bacher (seb128) wrote :

thanks for the update, trying to current version (r12724) I see those issues:

- the slider goes to much on the left, it should have the same left margin that the elements stacked on top of it

- the default value is "0.5", shouldn't it be "1"?

review: Needs Fixing
Revision history for this message
Sebastien Bacher (seb128) wrote :

Thanks for the updates, we are getting there ;-)

The UI could still use some tweaking, the label "UI scale: " should probably don't have a ":" (the others in that dialog don't) and be right aligned on the ones on top, the slider should match take the same space as the combos as well I think

The feature freeze is coming and we should get things rolling (we can fix minor issues later) so I've started a landing for that change, combined with the schemas package rename/new key, the result is in https://launchpad.net/~ci-train-ppa-service/+archive/landing-008 for those who want to test

I'm going to go forward with the landing tomorrow, we can kick a rebuild if the vcs gets some change in between though

review: Approve
Revision history for this message
Sebastien Bacher (seb128) wrote :

("UI scale: " shouldn't have a space either)

review: Needs Fixing
Revision history for this message
Sebastien Bacher (seb128) wrote :

getting there, can you change the label to have the same styling as the other ones? just add that to the .ui in the label section

<style>
  <class name="dim-label"/>
</style>

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2014-02-19 02:34:13 +0000
3+++ debian/control 2014-02-20 10:15:57 +0000
4@@ -13,6 +13,7 @@
5 gnome-pkg-tools (>= 0.10),
6 gnome-settings-daemon-dev (>= 3.8.4),
7 gsettings-desktop-schemas-dev (>= 3.7.2.2),
8+ gsettings-ubuntu-schemas (>= 0.0.1+14.04.20140219),
9 hardening-wrapper,
10 intltool (>= 0.37.1),
11 libcanberra-gtk3-dev,
12
13=== modified file 'panels/display/cc-display-panel.c'
14--- panels/display/cc-display-panel.c 2014-02-17 22:45:08 +0000
15+++ panels/display/cc-display-panel.c 2014-02-20 10:15:57 +0000
16@@ -27,6 +27,7 @@
17 #include "cc-display-panel.h"
18
19 #include <gtk/gtk.h>
20+#include <glib.h>
21 #include "scrollarea.h"
22 #define GNOME_DESKTOP_USE_UNSTABLE_API
23 #include <libgnome-desktop/gnome-rr.h>
24@@ -62,6 +63,11 @@
25 #define UNITY2D_GSETTINGS_MAIN "com.canonical.Unity2d"
26 #define UNITY2D_GSETTINGS_LAUNCHER "com.canonical.Unity2d.Launcher"
27
28+#define DESKTOP_GSETTINGS_SCHEMA "com.ubuntu.user-interface"
29+
30+#define UI_SCALE_MIN 4.0
31+#define UI_SCALE_MAX 32.0
32+
33 enum {
34 TEXT_COL,
35 WIDTH_COL,
36@@ -83,6 +89,7 @@
37 GSettings *unity_settings;
38 GSettings *unity2d_settings_main;
39 GSettings *unity2d_settings_launcher;
40+ GSettings *desktop_settings;
41 GtkBuilder *builder;
42 guint focus_id;
43
44@@ -96,6 +103,8 @@
45 GtkWidget *clone_checkbox;
46 GtkWidget *clone_label;
47 GtkWidget *show_icon_checkbox;
48+ GtkWidget *ui_scale;
49+ double ui_prev_scale;
50
51 /* We store the event timestamp when the Apply button is clicked */
52 guint32 apply_button_clicked_timestamp;
53@@ -187,6 +196,8 @@
54 g_object_unref (self->priv->unity2d_settings_launcher);
55 if (self->priv->unity_settings != NULL)
56 g_object_unref (self->priv->unity_settings);
57+ if (self->priv->desktop_settings != NULL)
58+ g_object_unref (self->priv->desktop_settings);
59
60 shell = cc_panel_get_shell (CC_PANEL (self));
61 if (shell != NULL)
62@@ -552,6 +563,82 @@
63 gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->rotation_combo), 0);
64 }
65
66+static GVariant*
67+add_dict_entry (GVariant *dict, const char *key, int value)
68+{
69+ GVariant *dict_entry;
70+ GVariant **dict_entries;
71+ GVariant *tmp;
72+ GVariant *pair[2];
73+ GVariantIter iter;
74+ unsigned long sz;
75+ char str[512];
76+ int i = 0;
77+
78+ pair[0] = g_variant_new_string (key);
79+ pair[1] = g_variant_new_int32 (value);
80+ dict_entry = g_variant_new_dict_entry (pair[0], pair[1]);
81+
82+ if (!dict)
83+ {
84+ dict = g_variant_new_array (G_VARIANT_TYPE_DICT_ENTRY, &dict_entry, 1);
85+ return dict;
86+ }
87+
88+ sz = g_variant_n_children (dict);
89+ dict_entries = malloc (sizeof(GVariant*) * (sz + 1));
90+
91+ g_variant_iter_init (&iter, dict);
92+ while (tmp = g_variant_iter_next_value (&iter))
93+ {
94+ int val = 0; char *str;
95+ g_variant_get_child (tmp, 0, "s", &str);
96+ if (!str)
97+ {
98+ fprintf (stderr, "Invalid dictionary entry\n");
99+ break;
100+ }
101+
102+ if (strcmp (str, key) != 0)
103+ {
104+ dict_entries[i++] = tmp;
105+ }
106+ g_free(str);
107+ }
108+ dict_entries[i++] = dict_entry;
109+ dict = g_variant_new_array (NULL, dict_entries, i);
110+
111+ return dict;
112+}
113+
114+static void
115+rebuild_ui_scale (CcDisplayPanel *self)
116+{
117+ int value;
118+ float t;
119+
120+ GVariant *dict;
121+
122+ const char *monitor_name = gnome_rr_output_info_get_name (self->priv->current_output);
123+
124+ GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE(self->priv->ui_scale));
125+
126+ gtk_adjustment_set_upper (adj, UI_SCALE_MAX);
127+ gtk_adjustment_set_lower (adj, UI_SCALE_MIN);
128+
129+ gtk_scale_set_digits (GTK_SCALE(self->priv->ui_scale), 0);
130+
131+ g_settings_get (self->priv->desktop_settings, "scale-factor", "@a{si}", &dict);
132+ if (!g_variant_lookup (dict, monitor_name, "i", &value))
133+ {
134+ value = 8;
135+ self->priv->ui_prev_scale = value;
136+ }
137+ add_dict_entry (dict, monitor_name, value);
138+ g_settings_set (self->priv->desktop_settings, "scale-factor", "@a{si}", dict);
139+ gtk_adjustment_set_value (adj, value);
140+}
141+
142 static int
143 count_active_outputs (CcDisplayPanel *self)
144 {
145@@ -884,6 +971,7 @@
146 rebuild_on_off_radios (self);
147 rebuild_resolution_combo (self);
148 rebuild_rotation_combo (self);
149+ rebuild_ui_scale (self);
150 refresh_unity_launcher_placement (self);
151
152 self->priv->ignore_gui_changes = FALSE;
153@@ -939,6 +1027,41 @@
154 foo_scroll_area_invalidate (FOO_SCROLL_AREA (self->priv->area));
155 }
156
157+static gboolean
158+on_ui_scale_button_press (GtkWidget *ui_scale, GdkEvent *ev, gpointer data)
159+{
160+ CcDisplayPanel *self = data;
161+ self->priv->ui_prev_scale = gtk_range_get_value (GTK_RANGE(ui_scale));
162+
163+ return FALSE; /* gtk should still process this event */
164+}
165+
166+static gboolean
167+on_ui_scale_button_release (GtkWidget *ui_scale, GdkEvent *ev, gpointer data)
168+{
169+ const char *monitor_name;
170+ CcDisplayPanel *self = data;
171+ int value = (int)gtk_range_get_value (GTK_RANGE(ui_scale));
172+
173+ if (value != self->priv->ui_prev_scale)
174+ {
175+ GVariant *dict;
176+
177+ monitor_name = gnome_rr_output_info_get_name (self->priv->current_output);
178+ g_settings_get (self->priv->desktop_settings, "scale-factor", "@a{si}", &dict);
179+ dict = add_dict_entry (dict, monitor_name, value);
180+ g_settings_set (self->priv->desktop_settings, "scale-factor", "@a{si}", dict);
181+ }
182+
183+ return FALSE; /* gtk should still process this event */
184+}
185+
186+static gchar*
187+on_ui_scale_format_value (GtkScale *ui_scale, gdouble value)
188+{
189+ return g_strdup_printf ("%.3g", value / 8.0);
190+}
191+
192 static void
193 select_resolution_for_current_output (CcDisplayPanel *self)
194 {
195@@ -2893,6 +3016,7 @@
196 }
197
198 self->priv->clock_settings = g_settings_new (CLOCK_SCHEMA);
199+ self->priv->desktop_settings = g_settings_new (DESKTOP_GSETTINGS_SCHEMA);
200
201 shell = cc_panel_get_shell (CC_PANEL (self));
202 toplevel = cc_shell_get_toplevel (shell);
203@@ -2918,6 +3042,14 @@
204 g_signal_connect (self->priv->rotation_combo, "changed",
205 G_CALLBACK (on_rotation_changed), self);
206
207+ self->priv->ui_scale = WID ("ui_scale");
208+ g_signal_connect (self->priv->ui_scale, "button-press-event",
209+ G_CALLBACK (on_ui_scale_button_press), self);
210+ g_signal_connect (self->priv->ui_scale, "button-release-event",
211+ G_CALLBACK (on_ui_scale_button_release), self);
212+ g_signal_connect (self->priv->ui_scale, "format-value",
213+ G_CALLBACK (on_ui_scale_format_value), self);
214+
215 self->priv->clone_checkbox = WID ("clone_checkbox");
216 g_signal_connect (self->priv->clone_checkbox, "toggled",
217 G_CALLBACK (on_clone_changed), self);
218
219=== modified file 'panels/display/display-capplet.ui'
220--- panels/display/display-capplet.ui 2013-11-28 04:26:08 +0000
221+++ panels/display/display-capplet.ui 2014-02-20 10:15:57 +0000
222@@ -1,6 +1,6 @@
223 <?xml version="1.0"?>
224 <interface>
225- <requires lib="gtk+" version="2.16"/>
226+ <requires lib="gtk+" version="3.0"/>
227 <object class="GtkListStore" id="available_launcher_placement_store">
228 <columns>
229 <!-- column-name MONITOR_PREVIEW -->
230@@ -11,42 +11,50 @@
231 </object>
232 <!-- interface-naming-policy toplevel-contextual -->
233 <object class="GtkWindow" id="window1">
234+ <property name="can_focus">False</property>
235 <child>
236 <object class="GtkVBox" id="display-panel">
237 <property name="visible">True</property>
238+ <property name="can_focus">False</property>
239 <property name="border_width">10</property>
240- <property name="orientation">vertical</property>
241 <property name="spacing">12</property>
242 <child>
243 <object class="GtkAlignment" id="align">
244 <property name="visible">True</property>
245+ <property name="can_focus">False</property>
246 <child>
247 <placeholder/>
248 </child>
249 </object>
250 <packing>
251+ <property name="expand">True</property>
252+ <property name="fill">True</property>
253 <property name="position">0</property>
254 </packing>
255 </child>
256 <child>
257 <object class="GtkHBox" id="hbox1">
258 <property name="visible">True</property>
259+ <property name="can_focus">False</property>
260 <property name="spacing">12</property>
261 <child>
262 <object class="GtkVBox" id="vbox1">
263 <property name="visible">True</property>
264- <property name="orientation">vertical</property>
265+ <property name="can_focus">False</property>
266 <property name="spacing">12</property>
267 <child>
268 <object class="GtkHBox" id="hbox3">
269 <property name="visible">True</property>
270+ <property name="can_focus">False</property>
271 <property name="spacing">12</property>
272 <child>
273 <object class="GtkEventBox" id="current_monitor_event_box">
274 <property name="visible">True</property>
275+ <property name="can_focus">False</property>
276 <child>
277 <object class="GtkLabel" id="current_monitor_label">
278 <property name="visible">True</property>
279+ <property name="can_focus">False</property>
280 <property name="xalign">0</property>
281 <property name="xpad">10</property>
282 <property name="ypad">5</property>
283@@ -66,12 +74,12 @@
284 <child>
285 <object class="GtkHBox" id="hbox2">
286 <property name="visible">True</property>
287+ <property name="can_focus">False</property>
288 <property name="spacing">12</property>
289 <child>
290 <object class="GtkSwitch" id="monitor_switch">
291 <property name="visible">True</property>
292 <property name="can_focus">True</property>
293- <property name="receives_default">False</property>
294 <property name="active">True</property>
295 </object>
296 <packing>
297@@ -98,19 +106,22 @@
298 <child>
299 <object class="GtkAlignment" id="alignment1">
300 <property name="visible">True</property>
301+ <property name="can_focus">False</property>
302 <property name="xalign">0</property>
303 <property name="yalign">0</property>
304 <property name="left_padding">12</property>
305 <child>
306 <object class="GtkTable" id="table1">
307 <property name="visible">True</property>
308- <property name="n_rows">5</property>
309+ <property name="can_focus">False</property>
310+ <property name="n_rows">6</property>
311 <property name="n_columns">2</property>
312 <property name="column_spacing">12</property>
313 <property name="row_spacing">6</property>
314 <child>
315 <object class="GtkLabel" id="label2">
316 <property name="visible">True</property>
317+ <property name="can_focus">False</property>
318 <property name="xalign">1</property>
319 <property name="label" translatable="yes">_Resolution</property>
320 <property name="use_underline">True</property>
321@@ -121,16 +132,17 @@
322 </object>
323 <packing>
324 <property name="x_options">GTK_FILL</property>
325- <property name="y_options"></property>
326+ <property name="y_options"/>
327 </packing>
328 </child>
329 <child>
330 <object class="GtkLabel" id="label5">
331 <property name="visible">True</property>
332+ <property name="can_focus">False</property>
333 <property name="xalign">1</property>
334 <property name="label" translatable="yes">R_otation</property>
335+ <property name="use_underline">True</property>
336 <property name="mnemonic_widget">rotation_combo</property>
337- <property name="use_underline">True</property>
338 <style>
339 <class name="dim-label"/>
340 </style>
341@@ -139,29 +151,30 @@
342 <property name="top_attach">1</property>
343 <property name="bottom_attach">2</property>
344 <property name="x_options">GTK_FILL</property>
345- <property name="y_options"></property>
346+ <property name="y_options"/>
347 </packing>
348 </child>
349 <child>
350 <object class="GtkSeparator" id="unity_launcher_placement_sep">
351 <property name="visible">True</property>
352+ <property name="can_focus">False</property>
353 </object>
354 <packing>
355+ <property name="right_attach">2</property>
356 <property name="top_attach">2</property>
357 <property name="bottom_attach">3</property>
358- <property name="left_attach">0</property>
359- <property name="right_attach">2</property>
360 <property name="x_options">GTK_FILL</property>
361- <property name="y_options"></property>
362+ <property name="y_options"/>
363 </packing>
364 </child>
365 <child>
366 <object class="GtkLabel" id="launcher_placement_label">
367 <property name="visible">True</property>
368+ <property name="can_focus">False</property>
369 <property name="xalign">1</property>
370 <property name="label" translatable="yes">L_auncher placement</property>
371+ <property name="use_underline">True</property>
372 <property name="mnemonic_widget">launcher_placement_combo</property>
373- <property name="use_underline">True</property>
374 <style>
375 <class name="dim-label"/>
376 </style>
377@@ -170,16 +183,17 @@
378 <property name="top_attach">3</property>
379 <property name="bottom_attach">4</property>
380 <property name="x_options">GTK_FILL</property>
381- <property name="y_options"></property>
382+ <property name="y_options"/>
383 </packing>
384 </child>
385 <child>
386 <object class="GtkLabel" id="sticky_edge_label">
387 <property name="visible">True</property>
388+ <property name="can_focus">False</property>
389 <property name="xalign">1</property>
390 <property name="label" translatable="yes">S_ticky edges</property>
391+ <property name="use_underline">True</property>
392 <property name="mnemonic_widget">stickyedge_switch</property>
393- <property name="use_underline">True</property>
394 <style>
395 <class name="dim-label"/>
396 </style>
397@@ -188,22 +202,24 @@
398 <property name="top_attach">4</property>
399 <property name="bottom_attach">5</property>
400 <property name="x_options">GTK_FILL</property>
401- <property name="y_options"></property>
402+ <property name="y_options"/>
403 </packing>
404 </child>
405 <child>
406 <object class="GtkComboBox" id="resolution_combo">
407 <property name="visible">True</property>
408+ <property name="can_focus">False</property>
409 </object>
410 <packing>
411 <property name="left_attach">1</property>
412 <property name="right_attach">2</property>
413- <property name="y_options"></property>
414+ <property name="y_options"/>
415 </packing>
416 </child>
417 <child>
418 <object class="GtkComboBox" id="rotation_combo">
419 <property name="visible">True</property>
420+ <property name="can_focus">False</property>
421 <child>
422 <object class="GtkCellRendererText" id="cellrenderertext1"/>
423 <attributes>
424@@ -216,7 +232,7 @@
425 <property name="right_attach">2</property>
426 <property name="top_attach">1</property>
427 <property name="bottom_attach">2</property>
428- <property name="y_options"></property>
429+ <property name="y_options"/>
430 </packing>
431 </child>
432 <child>
433@@ -243,18 +259,19 @@
434 <property name="right_attach">2</property>
435 <property name="top_attach">3</property>
436 <property name="bottom_attach">4</property>
437- <property name="y_options"></property>
438+ <property name="y_options"/>
439 </packing>
440 </child>
441 <child>
442 <object class="GtkHBox" id="hbox4">
443 <property name="visible">True</property>
444+ <property name="can_focus">False</property>
445+ <property name="margin_bottom">1</property>
446 <property name="spacing">12</property>
447 <child>
448 <object class="GtkSwitch" id="stickyedge_switch">
449 <property name="visible">True</property>
450 <property name="can_focus">True</property>
451- <property name="receives_default">False</property>
452 <property name="active">True</property>
453 </object>
454 <packing>
455@@ -270,43 +287,82 @@
456 <property name="right_attach">2</property>
457 <property name="top_attach">4</property>
458 <property name="bottom_attach">5</property>
459- <property name="y_options"></property>
460- <property name="expand">False</property>
461- <property name="fill">False</property>
462- <property name="position">0</property>
463- </packing>
464- </child>
465- <child>
466- <placeholder/>
467+ <property name="y_options"/>
468+ </packing>
469+ </child>
470+ <child>
471+ <object class="GtkLabel" id="ui_label">
472+ <property name="visible">True</property>
473+ <property name="can_focus">False</property>
474+ <property name="xalign">1</property>
475+ <property name="yalign">1</property>
476+ <property name="xpad">3</property>
477+ <property name="ypad">3</property>
478+ <property name="label" translatable="yes">UI scale</property>
479+ <style>
480+ <class name="dim-label"/>
481+ </style>
482+ </object>
483+ <packing>
484+ <property name="top_attach">5</property>
485+ <property name="bottom_attach">6</property>
486+ </packing>
487+ </child>
488+ <child>
489+ <object class="GtkHScale" id="ui_scale">
490+ <property name="visible">True</property>
491+ <property name="can_focus">True</property>
492+ <property name="digits">2</property>
493+ <child internal-child="accessible">
494+ <object class="AtkObject" id="ui_scale-atkobject">
495+ <property name="AtkObject::accessible-description" translatable="yes">Cursor blink speed</property>
496+ </object>
497+ </child>
498+ </object>
499+ <packing>
500+ <property name="left_attach">1</property>
501+ <property name="right_attach">2</property>
502+ <property name="top_attach">5</property>
503+ <property name="bottom_attach">6</property>
504+ </packing>
505 </child>
506 </object>
507 </child>
508 </object>
509 <packing>
510 <property name="expand">False</property>
511+ <property name="fill">True</property>
512 <property name="position">1</property>
513 </packing>
514 </child>
515+ <child>
516+ <placeholder/>
517+ </child>
518 </object>
519 <packing>
520+ <property name="expand">True</property>
521+ <property name="fill">True</property>
522 <property name="position">0</property>
523 </packing>
524 </child>
525 <child>
526 <object class="GtkAlignment" id="alignment2">
527 <property name="visible">True</property>
528+ <property name="can_focus">False</property>
529 <child>
530 <placeholder/>
531 </child>
532 </object>
533 <packing>
534+ <property name="expand">True</property>
535+ <property name="fill">True</property>
536 <property name="position">1</property>
537 </packing>
538 </child>
539 <child>
540 <object class="GtkVBox" id="vbox2">
541 <property name="visible">True</property>
542- <property name="orientation">vertical</property>
543+ <property name="can_focus">False</property>
544 <child>
545 <object class="GtkCheckButton" id="clone_checkbox">
546 <property name="label" translatable="yes" comments="Note that mirror is a verb in this string">_Mirror displays</property>
547@@ -314,6 +370,7 @@
548 <property name="can_focus">True</property>
549 <property name="receives_default">False</property>
550 <property name="use_underline">True</property>
551+ <property name="xalign">0.5</property>
552 <property name="draw_indicator">True</property>
553 </object>
554 <packing>
555@@ -325,6 +382,7 @@
556 <child>
557 <object class="GtkLabel" id="clone_resolution_warning_label">
558 <property name="visible">True</property>
559+ <property name="can_focus">False</property>
560 <property name="xalign">0</property>
561 <property name="label" translatable="yes">Note: may limit resolution options</property>
562 <attributes>
563@@ -346,24 +404,45 @@
564 </object>
565 <packing>
566 <property name="expand">False</property>
567+ <property name="fill">True</property>
568 <property name="position">2</property>
569 </packing>
570 </child>
571 </object>
572 <packing>
573+ <property name="expand">True</property>
574+ <property name="fill">True</property>
575 <property name="position">1</property>
576 </packing>
577 </child>
578 <child>
579 <object class="GtkAlignment" id="alignment3">
580 <property name="visible">True</property>
581+ <property name="can_focus">False</property>
582 <property name="top_padding">10</property>
583 <child>
584 <object class="GtkHButtonBox" id="hbuttonbox1">
585 <property name="visible">True</property>
586+ <property name="can_focus">False</property>
587 <property name="spacing">6</property>
588 <property name="layout_style">end</property>
589 <child>
590+ <object class="GtkButton" id="detect_displays_button">
591+ <property name="label" translatable="yes">_Detect Displays</property>
592+ <property name="visible">True</property>
593+ <property name="can_focus">True</property>
594+ <property name="receives_default">True</property>
595+ <property name="use_underline">True</property>
596+ </object>
597+ <packing>
598+ <property name="expand">False</property>
599+ <property name="fill">False</property>
600+ <property name="pack_type">end</property>
601+ <property name="position">0</property>
602+ <property name="secondary">True</property>
603+ </packing>
604+ </child>
605+ <child>
606 <object class="GtkButton" id="apply_button">
607 <property name="label">gtk-apply</property>
608 <property name="visible">True</property>
609@@ -378,22 +457,6 @@
610 <property name="position">1</property>
611 </packing>
612 </child>
613- <child>
614- <object class="GtkButton" id="detect_displays_button">
615- <property name="label" translatable="yes">_Detect Displays</property>
616- <property name="visible">True</property>
617- <property name="can_focus">True</property>
618- <property name="receives_default">True</property>
619- <property name="use_underline">True</property>
620- </object>
621- <packing>
622- <property name="expand">False</property>
623- <property name="fill">False</property>
624- <property name="pack_type">end</property>
625- <property name="position">0</property>
626- <property name="secondary">True</property>
627- </packing>
628- </child>
629 </object>
630 </child>
631 </object>

Subscribers

People subscribed via source and target branches