Merge lp:~robert-ancell/unity-greeter/end-session-dialog into lp:unity-greeter

Proposed by Robert Ancell
Status: Merged
Approved by: Michael Terry
Approved revision: 1031
Merged at revision: 1013
Proposed branch: lp:~robert-ancell/unity-greeter/end-session-dialog
Merge into: lp:unity-greeter
Diff against target: 820 lines (+575/-17)
12 files modified
configure.ac (+1/-1)
data/Makefile.am (+13/-0)
debian/changelog (+7/-0)
po/POTFILES.in (+1/-1)
po/POTFILES.skip (+1/-0)
src/Makefile.am (+1/-0)
src/fixes.vapi (+6/-0)
src/main-window.vala (+75/-14)
src/settings-daemon.vala (+36/-0)
src/shutdown-dialog.vala (+381/-0)
src/unity-greeter.vala (+51/-0)
tests/Makefile.am (+2/-1)
To merge this branch: bzr merge lp:~robert-ancell/unity-greeter/end-session-dialog
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Michael Terry (community) Approve
Review via email: mp+193880@code.launchpad.net

This proposal supersedes a proposal from 2013-10-21.

Commit message

Use Unity style shutdown dialogs
Handle hardware power button in greeter

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Michael Terry (mterry) wrote : Posted in a previous version of this proposal

So we talked about this on IRC. Sounds like it needs at least keyboard navigation before landing. Also mentioned was the use of a well-known DBus name vs unique.

Revision history for this message
Michael Terry (mterry) wrote : Posted in a previous version of this proposal

Whoops, forgot to set status.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Robert Ancell (robert-ancell) wrote :

Should be good now - can you re-review?

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1031
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~robert-ancell/unity-greeter/end-session-dialog/+merge/193880/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/unity-greeter-ci/22/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-greeter-trusty-amd64-ci/5
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-greeter-trusty-armhf-ci/5

Click here to trigger a rebuild:
http://10.97.0.26:8080/job/unity-greeter-ci/22/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michael Terry (mterry) wrote :

Works better for me now, thanks!

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configure.ac'
2--- configure.ac 2013-10-02 17:46:49 +0000
3+++ configure.ac 2013-11-05 04:29:38 +0000
4@@ -2,7 +2,7 @@
5
6 dnl Process this file with autoconf to produce a configure script.
7
8-AC_INIT(unity-greeter, 13.10.3)
9+AC_INIT(unity-greeter, 14.04.0)
10 AC_CONFIG_MACRO_DIR(m4)
11 AM_INIT_AUTOMAKE
12 AM_PROG_CC_C_O
13
14=== modified file 'data/Makefile.am'
15--- data/Makefile.am 2012-10-18 14:45:57 +0000
16+++ data/Makefile.am 2013-11-05 04:29:38 +0000
17@@ -9,13 +9,26 @@
18 arrow_left.png \
19 arrow_right.png \
20 cof.png \
21+ dialog_close_highlight.png \
22+ dialog_close.png \
23 gnome_badge.png \
24+ hibernate_highlight.png \
25+ hibernate.png \
26 kde_badge.png \
27 logo.png \
28 message.png \
29 recovery_console_badge.png \
30 remote_login_help.png \
31+ restart_highlight.png \
32+ restart.png \
33 shadow.png \
34+ shutdown_highlight.png \
35+ shutdown.png \
36+ suspend_highlight.png \
37+ suspend.png \
38+ switcher_corner.png \
39+ switcher_left.png \
40+ switcher_top.png \
41 ubuntu_badge.png \
42 unknown_badge.png
43
44
45=== added file 'data/dialog_close.png'
46Binary files data/dialog_close.png 1970-01-01 00:00:00 +0000 and data/dialog_close.png 2013-11-05 04:29:38 +0000 differ
47=== added file 'data/dialog_close_highlight.png'
48Binary files data/dialog_close_highlight.png 1970-01-01 00:00:00 +0000 and data/dialog_close_highlight.png 2013-11-05 04:29:38 +0000 differ
49=== added file 'data/hibernate.png'
50Binary files data/hibernate.png 1970-01-01 00:00:00 +0000 and data/hibernate.png 2013-11-05 04:29:38 +0000 differ
51=== added file 'data/hibernate_highlight.png'
52Binary files data/hibernate_highlight.png 1970-01-01 00:00:00 +0000 and data/hibernate_highlight.png 2013-11-05 04:29:38 +0000 differ
53=== added file 'data/restart.png'
54Binary files data/restart.png 1970-01-01 00:00:00 +0000 and data/restart.png 2013-11-05 04:29:38 +0000 differ
55=== added file 'data/restart_highlight.png'
56Binary files data/restart_highlight.png 1970-01-01 00:00:00 +0000 and data/restart_highlight.png 2013-11-05 04:29:38 +0000 differ
57=== added file 'data/shutdown.png'
58Binary files data/shutdown.png 1970-01-01 00:00:00 +0000 and data/shutdown.png 2013-11-05 04:29:38 +0000 differ
59=== added file 'data/shutdown_highlight.png'
60Binary files data/shutdown_highlight.png 1970-01-01 00:00:00 +0000 and data/shutdown_highlight.png 2013-11-05 04:29:38 +0000 differ
61=== added file 'data/suspend.png'
62Binary files data/suspend.png 1970-01-01 00:00:00 +0000 and data/suspend.png 2013-11-05 04:29:38 +0000 differ
63=== added file 'data/suspend_highlight.png'
64Binary files data/suspend_highlight.png 1970-01-01 00:00:00 +0000 and data/suspend_highlight.png 2013-11-05 04:29:38 +0000 differ
65=== added file 'data/switcher_corner.png'
66Binary files data/switcher_corner.png 1970-01-01 00:00:00 +0000 and data/switcher_corner.png 2013-11-05 04:29:38 +0000 differ
67=== added file 'data/switcher_left.png'
68Binary files data/switcher_left.png 1970-01-01 00:00:00 +0000 and data/switcher_left.png 2013-11-05 04:29:38 +0000 differ
69=== added file 'data/switcher_top.png'
70Binary files data/switcher_top.png 1970-01-01 00:00:00 +0000 and data/switcher_top.png 2013-11-05 04:29:38 +0000 differ
71=== modified file 'debian/changelog'
72--- debian/changelog 2013-10-03 13:59:34 +0000
73+++ debian/changelog 2013-11-05 04:29:38 +0000
74@@ -1,3 +1,10 @@
75+unity-greeter (14.04.0-0ubuntu1) UNRELEASED; urgency=low
76+
77+ * Use Unity style shutdown dialogs
78+ * Handle hardware power button in greeter
79+
80+ -- Robert Ancell <robert.ancell@canonical.com> Mon, 21 Oct 2013 17:15:38 +1300
81+
82 unity-greeter (13.10.3-0ubuntu1) saucy; urgency=low
83
84 [ William Hua ]
85
86=== modified file 'po/POTFILES.in'
87--- po/POTFILES.in 2012-11-08 15:48:14 +0000
88+++ po/POTFILES.in 2013-11-05 04:29:38 +0000
89@@ -19,8 +19,8 @@
90 src/session-list.vala
91 src/settings-daemon.vala
92 src/settings.vala
93+src/shutdown-dialog.vala
94 src/toggle-box.vala
95 src/unity-greeter.vala
96 src/user-list.vala
97 src/user-prompt-box.vala
98-
99
100=== modified file 'po/POTFILES.skip'
101--- po/POTFILES.skip 2012-11-08 15:48:14 +0000
102+++ po/POTFILES.skip 2013-11-05 04:29:38 +0000
103@@ -17,6 +17,7 @@
104 src/session-list.c
105 src/settings-daemon.c
106 src/settings.c
107+src/shutdown-dialog.c
108 src/toggle-box.c
109 src/unity-greeter.c
110 src/user-list.c
111
112=== modified file 'src/Makefile.am'
113--- src/Makefile.am 2013-10-17 22:09:16 +0000
114+++ src/Makefile.am 2013-11-05 04:29:38 +0000
115@@ -27,6 +27,7 @@
116 remote-login-service.vala \
117 settings.vala \
118 settings-daemon.vala \
119+ shutdown-dialog.vala \
120 toggle-box.vala \
121 unity-greeter.vala \
122 user-list.vala \
123
124=== modified file 'src/fixes.vapi'
125--- src/fixes.vapi 2013-10-24 12:27:03 +0000
126+++ src/fixes.vapi 2013-11-05 04:29:38 +0000
127@@ -33,12 +33,16 @@
128 public const int KEY_Page_Down;
129 public const int KEY_Up;
130 public const int KEY_Down;
131+ public const int KEY_Left;
132+ public const int KEY_Right;
133 public const int KEY_KP_Home;
134 public const int KEY_KP_End;
135 public const int KEY_KP_Page_Up;
136 public const int KEY_KP_Page_Down;
137 public const int KEY_KP_Up;
138 public const int KEY_KP_Down;
139+ public const int KEY_KP_Left;
140+ public const int KEY_KP_Right;
141 public const int KEY_F10;
142 public const int KEY_0;
143 public const int KEY_g;
144@@ -47,10 +51,12 @@
145 public const int KEY_m;
146 public const int KEY_M;
147 public const int KEY_s;
148+ public const int KEY_z;
149 public const int KEY_plus;
150 public const int KEY_minus;
151 public const int KEY_equal;
152 public const int CONTROL_MASK;
153+ public const int KEY_PowerOff;
154 }
155
156 namespace Gtk
157
158=== modified file 'src/main-window.vala'
159--- src/main-window.vala 2013-02-08 15:53:16 +0000
160+++ src/main-window.vala 2013-11-05 04:29:38 +0000
161@@ -24,10 +24,12 @@
162 public MenuBar menubar;
163
164 private List<Monitor> monitors;
165+ private Monitor active_monitor;
166 private Background background;
167 private Gtk.Box login_box;
168 private Gtk.Box hbox;
169 private Gtk.Button back_button;
170+ private ShutdownDialog? shutdown_dialog = null;
171
172 public ListStack stack;
173
174@@ -245,9 +247,16 @@
175
176 private void move_to_monitor (Monitor monitor)
177 {
178+ active_monitor = monitor;
179 login_box.set_size_request (monitor.width, monitor.height);
180 background.set_active_monitor (monitor);
181 background.move (login_box, monitor.x, monitor.y);
182+
183+ if (shutdown_dialog != null)
184+ {
185+ shutdown_dialog.set_size_request (monitor.width, monitor.height);
186+ background.move (shutdown_dialog, monitor.x, monitor.y);
187+ }
188 }
189
190 private void add_user_list ()
191@@ -266,36 +275,88 @@
192 switch (event.keyval)
193 {
194 case Gdk.KEY_Escape:
195- top.cancel_authentication ();
196- break;
197+ if (login_box.sensitive)
198+ top.cancel_authentication ();
199+ if (shutdown_dialog != null)
200+ shutdown_dialog.cancel ();
201+ return true;
202 case Gdk.KEY_Page_Up:
203 case Gdk.KEY_KP_Page_Up:
204- top.scroll (GreeterList.ScrollTarget.START);
205- break;
206+ if (login_box.sensitive)
207+ top.scroll (GreeterList.ScrollTarget.START);
208+ return true;
209 case Gdk.KEY_Page_Down:
210 case Gdk.KEY_KP_Page_Down:
211- top.scroll (GreeterList.ScrollTarget.END);
212- break;
213+ if (login_box.sensitive)
214+ top.scroll (GreeterList.ScrollTarget.END);
215+ return true;
216 case Gdk.KEY_Up:
217 case Gdk.KEY_KP_Up:
218- top.scroll (GreeterList.ScrollTarget.UP);
219- break;
220+ if (login_box.sensitive)
221+ top.scroll (GreeterList.ScrollTarget.UP);
222+ return true;
223 case Gdk.KEY_Down:
224 case Gdk.KEY_KP_Down:
225- top.scroll (GreeterList.ScrollTarget.DOWN);
226- break;
227+ if (login_box.sensitive)
228+ top.scroll (GreeterList.ScrollTarget.DOWN);
229+ return true;
230+ case Gdk.KEY_Left:
231+ case Gdk.KEY_KP_Left:
232+ if (shutdown_dialog != null)
233+ shutdown_dialog.focus_prev ();
234+ return true;
235+ case Gdk.KEY_Right:
236+ case Gdk.KEY_KP_Right:
237+ if (shutdown_dialog != null)
238+ shutdown_dialog.focus_next ();
239+ return true;
240 case Gdk.KEY_F10:
241- menubar.select_first (false);
242+ if (login_box.sensitive)
243+ menubar.select_first (false);
244+ return true;
245+ case Gdk.KEY_PowerOff:
246+ show_shutdown_dialog (ShutdownDialogType.SHUTDOWN);
247+ return true;
248+ case Gdk.KEY_z:
249+ if (UnityGreeter.singleton.test_mode && (event.state & Gdk.ModifierType.MOD1_MASK) != 0)
250+ {
251+ show_shutdown_dialog (ShutdownDialogType.SHUTDOWN);
252+ return true;
253+ }
254 break;
255- default:
256- return base.key_press_event (event);
257 }
258
259- return true;
260+ return base.key_press_event (event);
261 }
262
263 public void set_keyboard_state ()
264 {
265 menubar.set_keyboard_state ();
266 }
267+
268+ public void show_shutdown_dialog (ShutdownDialogType type)
269+ {
270+ if (shutdown_dialog != null)
271+ shutdown_dialog.destroy ();
272+
273+ /* Stop input to login box */
274+ login_box.sensitive = false;
275+
276+ shutdown_dialog = new ShutdownDialog (type);
277+ shutdown_dialog.visible = true;
278+ shutdown_dialog.close.connect (close_shutdown_dialog);
279+ background.add (shutdown_dialog);
280+ move_to_monitor (active_monitor);
281+ }
282+
283+ public void close_shutdown_dialog ()
284+ {
285+ if (shutdown_dialog == null)
286+ return;
287+
288+ shutdown_dialog.destroy ();
289+ shutdown_dialog = null;
290+
291+ login_box.sensitive = true;
292+ }
293 }
294
295=== modified file 'src/settings-daemon.vala'
296--- src/settings-daemon.vala 2013-01-30 20:31:38 +0000
297+++ src/settings-daemon.vala 2013-11-05 04:29:38 +0000
298@@ -19,6 +19,8 @@
299
300 public class SettingsDaemon : Object
301 {
302+ private int logind_inhibit_fd = -1;
303+
304 public async void start ()
305 {
306 configure ();
307@@ -64,6 +66,40 @@
308 require gnome-session and it's Presence DBus interface to be run. */
309 GLib.Bus.own_name (GLib.BusType.SESSION, "org.gnome.ScreenSaver",
310 GLib.BusNameOwnerFlags.NONE);
311+
312+ /* The media-keys plugin inhibits the power key, but we don't want
313+ all the other keys doing things. So inhibit it ourselves */
314+ /* NOTE: We are using the synchronous method here since there is a bug in Vala/GLib in that
315+ * g_dbus_connection_call_with_unix_fd_list_finish and g_dbus_proxy_call_with_unix_fd_list_finish
316+ * don't have the GAsyncResult as the second argument.
317+ * https://bugzilla.gnome.org/show_bug.cgi?id=688907
318+ */
319+ try
320+ {
321+ var b = Bus.get_sync (BusType.SYSTEM);
322+ UnixFDList fd_list;
323+ var result = b.call_with_unix_fd_list_sync ("org.freedesktop.login1",
324+ "/org/freedesktop/login1",
325+ "org.freedesktop.login1.Manager",
326+ "Inhibit",
327+ new Variant ("(ssss)",
328+ "handle-power-key",
329+ Environment.get_user_name (),
330+ "Unity Greeter handling keypresses",
331+ "block"),
332+ new VariantType ("(h)"),
333+ DBusCallFlags.NONE,
334+ -1,
335+ null,
336+ out fd_list);
337+ int32 index = -1;
338+ result.get ("(h)", &index);
339+ logind_inhibit_fd = fd_list.get (index);
340+ }
341+ catch (Error e)
342+ {
343+ warning ("Failed to inhibit power keys: %s", e.message);
344+ }
345 }
346
347 private void set_plugin_enabled (string schema_name, bool enabled)
348
349=== added file 'src/shutdown-dialog.vala'
350--- src/shutdown-dialog.vala 1970-01-01 00:00:00 +0000
351+++ src/shutdown-dialog.vala 2013-11-05 04:29:38 +0000
352@@ -0,0 +1,381 @@
353+/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*-
354+ *
355+ * Copyright (C) 2013 Canonical Ltd
356+ *
357+ * This program is free software: you can redistribute it and/or modify
358+ * it under the terms of the GNU General Public License version 3 as
359+ * published by the Free Software Foundation.
360+ *
361+ * This program is distributed in the hope that it will be useful,
362+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
363+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
364+ * GNU General Public License for more details.
365+ *
366+ * You should have received a copy of the GNU General Public License
367+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
368+ *
369+ * Authors: Robert Ancell <robert.ancell@canonical.com>
370+ */
371+
372+public enum ShutdownDialogType
373+{
374+ LOGOUT,
375+ SHUTDOWN,
376+ RESTART
377+}
378+
379+public class ShutdownDialog : Gtk.Fixed
380+{
381+ public signal void close ();
382+
383+ private Cairo.ImageSurface? corner_surface = null;
384+ private Cairo.ImageSurface? left_surface = null;
385+ private Cairo.ImageSurface? top_surface = null;
386+ private Cairo.Pattern? corner_pattern = null;
387+ private Cairo.Pattern? left_pattern = null;
388+ private Cairo.Pattern? top_pattern = null;
389+
390+ private const int BORDER_SIZE = 30;
391+ private const int CLOSE_OFFSET = 3;
392+
393+ private Gtk.Box vbox;
394+ private DialogButton close_button;
395+ private Gtk.Box button_box;
396+
397+ public ShutdownDialog (ShutdownDialogType type)
398+ {
399+ vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 10);
400+ vbox.visible = true;
401+ add (vbox);
402+
403+ vbox.border_width = 20;
404+
405+ var title_label = new Gtk.Label (_("Shutdown"));
406+ title_label.override_font (Pango.FontDescription.from_string ("Ubuntu Light 15"));
407+ title_label.override_color (Gtk.StateFlags.NORMAL, { 1.0f, 1.0f, 1.0f, 1.0f });
408+ title_label.set_alignment (0.0f, 0.5f);
409+ vbox.pack_start (title_label, false, false, 0);
410+
411+ string text;
412+ if (type == ShutdownDialogType.SHUTDOWN)
413+ text = _("Goodbye. Would you like to…");
414+ else
415+ {
416+ text = _("Are you sure you want to shut down the computer?");
417+ title_label.visible = true;
418+ }
419+ var label = new Gtk.Label (text);
420+ label.set_line_wrap (true);
421+ label.override_font (Pango.FontDescription.from_string ("Ubuntu Light 12"));
422+ label.override_color (Gtk.StateFlags.NORMAL, { 1.0f, 1.0f, 1.0f, 1.0f });
423+ label.set_alignment (0.0f, 0.5f);
424+ label.visible = true;
425+ vbox.pack_start (label, false, false, 0);
426+
427+ button_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 20);
428+ button_box.visible = true;
429+ vbox.pack_start (button_box, false, false, 0);
430+
431+ if (type == ShutdownDialogType.SHUTDOWN)
432+ {
433+ if (LightDM.get_can_suspend ())
434+ {
435+ var button = add_button (_("Suspend"), Path.build_filename (Config.PKGDATADIR, "suspend.png"), Path.build_filename (Config.PKGDATADIR, "suspend_highlight.png"));
436+ button.clicked.connect (() =>
437+ {
438+ try
439+ {
440+ LightDM.suspend ();
441+ close ();
442+ }
443+ catch (Error e)
444+ {
445+ warning ("Failed to suspend: %s", e.message);
446+ }
447+ });
448+ }
449+
450+ if (LightDM.get_can_hibernate ())
451+ {
452+ var button = add_button (_("Hibernate"), Path.build_filename (Config.PKGDATADIR, "hibernate.png"), Path.build_filename (Config.PKGDATADIR, "hibernate_highlight.png"));
453+ button.clicked.connect (() =>
454+ {
455+ try
456+ {
457+ LightDM.hibernate ();
458+ close ();
459+ }
460+ catch (Error e)
461+ {
462+ warning ("Failed to hibernate: %s", e.message);
463+ }
464+ });
465+ }
466+ }
467+
468+ if (LightDM.get_can_restart ())
469+ {
470+ var button = add_button (_("Restart"), Path.build_filename (Config.PKGDATADIR, "restart.png"), Path.build_filename (Config.PKGDATADIR, "restart_highlight.png"));
471+ button.clicked.connect (() =>
472+ {
473+ try
474+ {
475+ LightDM.restart ();
476+ close ();
477+ }
478+ catch (Error e)
479+ {
480+ warning ("Failed to restart: %s", e.message);
481+ }
482+ });
483+ }
484+
485+ if (LightDM.get_can_shutdown ())
486+ {
487+ var button = add_button (_("Shutdown"), Path.build_filename (Config.PKGDATADIR, "shutdown.png"), Path.build_filename (Config.PKGDATADIR, "shutdown_highlight.png"));
488+ button.clicked.connect (() =>
489+ {
490+ try
491+ {
492+ LightDM.shutdown ();
493+ close ();
494+ }
495+ catch (Error e)
496+ {
497+ warning ("Failed to shutdown: %s", e.message);
498+ }
499+ });
500+ }
501+
502+ close_button = new DialogButton (Path.build_filename (Config.PKGDATADIR, "dialog_close.png"), Path.build_filename (Config.PKGDATADIR, "dialog_close_highlight.png"));
503+ close_button.can_focus = false;
504+ close_button.clicked.connect (() => { close (); });
505+ close_button.visible = true;
506+ add (close_button);
507+ }
508+
509+ public void focus_next ()
510+ {
511+ (get_toplevel () as Gtk.Window).move_focus (Gtk.DirectionType.TAB_FORWARD);
512+ }
513+
514+ public void focus_prev ()
515+ {
516+ (get_toplevel () as Gtk.Window).move_focus (Gtk.DirectionType.TAB_BACKWARD);
517+ }
518+
519+ public void cancel ()
520+ {
521+ var widget = (get_toplevel () as Gtk.Window).get_focus ();
522+ if (widget is DialogButton)
523+ (get_toplevel () as Gtk.Window).set_focus (null);
524+ else
525+ close ();
526+ }
527+
528+ public override void size_allocate (Gtk.Allocation allocation)
529+ {
530+ base.size_allocate (allocation);
531+
532+ var content_allocation = Gtk.Allocation ();
533+ int minimum_width, natural_width, minimum_height, natural_height;
534+ vbox.get_preferred_width (out minimum_width, out natural_width);
535+ vbox.get_preferred_height_for_width (minimum_width, out minimum_height, out natural_height);
536+ content_allocation.x = allocation.x + (allocation.width - minimum_width) / 2;
537+ content_allocation.y = allocation.y + (allocation.height - minimum_height) / 2;
538+ content_allocation.width = minimum_width;
539+ content_allocation.height = minimum_height;
540+ vbox.size_allocate (content_allocation);
541+
542+ var a = Gtk.Allocation ();
543+ close_button.get_preferred_width (out minimum_width, out natural_width);
544+ close_button.get_preferred_height (out minimum_height, out natural_height);
545+ a.x = content_allocation.x - BORDER_SIZE + CLOSE_OFFSET;
546+ a.y = content_allocation.y - BORDER_SIZE + CLOSE_OFFSET;
547+ a.width = minimum_width;
548+ a.height = minimum_height;
549+ close_button.size_allocate (a);
550+ }
551+
552+ public override bool draw (Cairo.Context c)
553+ {
554+ if (corner_surface == null)
555+ {
556+ corner_surface = new Cairo.ImageSurface.from_png (Path.build_filename (Config.PKGDATADIR, "switcher_corner.png"));
557+ left_surface = new Cairo.ImageSurface.from_png (Path.build_filename (Config.PKGDATADIR, "switcher_left.png"));
558+ top_surface = new Cairo.ImageSurface.from_png (Path.build_filename (Config.PKGDATADIR, "switcher_top.png"));
559+ corner_pattern = new Cairo.Pattern.for_surface (corner_surface);
560+ left_pattern = new Cairo.Pattern.for_surface (left_surface);
561+ left_pattern.set_extend (Cairo.Extend.REPEAT);
562+ top_pattern = new Cairo.Pattern.for_surface (top_surface);
563+ top_pattern.set_extend (Cairo.Extend.REPEAT);
564+ }
565+
566+ var width = vbox.get_allocated_width () + 20 * 2 + BORDER_SIZE * 2;
567+ var height = vbox.get_allocated_height () + 20 * 2 + BORDER_SIZE * 2;
568+
569+ /* Darken background */
570+ c.set_source_rgba (0, 0, 0, 0.25);
571+ c.paint ();
572+
573+ /* Draw dialog */
574+ c.save ();
575+ c.translate ((get_allocated_width () - width) * 0.5, (get_allocated_height () - height) * 0.5);
576+
577+ /* Top left */
578+ var m = Cairo.Matrix.identity ();
579+ corner_pattern.set_matrix (m);
580+ c.set_source (corner_pattern);
581+ c.rectangle (0, 0, BORDER_SIZE, BORDER_SIZE);
582+ c.fill ();
583+
584+ /* Top right */
585+ m = Cairo.Matrix.identity ();
586+ m.translate (width, 0);
587+ m.scale (-1, 1);
588+ corner_pattern.set_matrix (m);
589+ c.set_source (corner_pattern);
590+ c.rectangle (width - BORDER_SIZE, 0, BORDER_SIZE, BORDER_SIZE);
591+ c.fill ();
592+
593+ /* Bottom left */
594+ m = Cairo.Matrix.identity ();
595+ m.translate (0, height);
596+ m.scale (1, -1);
597+ corner_pattern.set_matrix (m);
598+ c.set_source (corner_pattern);
599+ c.rectangle (0, height - BORDER_SIZE, BORDER_SIZE, BORDER_SIZE);
600+ c.fill ();
601+
602+ /* Bottom right */
603+ m = Cairo.Matrix.identity ();
604+ m.translate (width, height);
605+ m.scale (-1, -1);
606+ corner_pattern.set_matrix (m);
607+ c.set_source (corner_pattern);
608+ c.rectangle (width - BORDER_SIZE, height - BORDER_SIZE, BORDER_SIZE, BORDER_SIZE);
609+ c.fill ();
610+
611+ /* Left */
612+ m = Cairo.Matrix.identity ();
613+ left_pattern.set_matrix (m);
614+ c.set_source (left_pattern);
615+ c.rectangle (0, BORDER_SIZE, BORDER_SIZE, height - BORDER_SIZE * 2);
616+ c.fill ();
617+
618+ /* Right */
619+ m = Cairo.Matrix.identity ();
620+ m.translate (width, 0);
621+ m.scale (-1, 1);
622+ left_pattern.set_matrix (m);
623+ c.set_source (left_pattern);
624+ c.rectangle (width - BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, height - BORDER_SIZE * 2);
625+ c.fill ();
626+
627+ /* Top */
628+ m = Cairo.Matrix.identity ();
629+ top_pattern.set_matrix (m);
630+ c.set_source (top_pattern);
631+ c.rectangle (BORDER_SIZE, 0, width - BORDER_SIZE * 2, BORDER_SIZE);
632+ c.fill ();
633+
634+ /* Right */
635+ m = Cairo.Matrix.identity ();
636+ m.translate (0, height);
637+ m.scale (1, -1);
638+ top_pattern.set_matrix (m);
639+ c.set_source (top_pattern);
640+ c.rectangle (BORDER_SIZE, height - BORDER_SIZE, width - BORDER_SIZE * 2, BORDER_SIZE);
641+ c.fill ();
642+
643+ /* Background */
644+ DashBox.cairo_rounded_rectangle (c, 20, 20, width - 40, height - 40, 5);
645+ c.set_source_rgba (0, 0, 0, 0.75);
646+ c.fill ();
647+
648+ c.restore ();
649+
650+ return base.draw (c);
651+ }
652+
653+ public override bool button_press_event (Gdk.EventButton event)
654+ {
655+ /* Close when selecting the background */
656+ // FIXME: Broken..
657+ close ();
658+ return true;
659+ }
660+
661+ private DialogButton add_button (string text, string inactive_filename, string active_filename)
662+ {
663+ var b = new Gtk.Box (Gtk.Orientation.VERTICAL, 9);
664+ b.visible = true;
665+ button_box.pack_start (b, false, false, 0);
666+
667+ var label = new Gtk.Label (text);
668+ label.visible = true;
669+ label.override_font (Pango.FontDescription.from_string ("Ubuntu Light 12"));
670+ label.override_color (Gtk.StateFlags.NORMAL, { 1.0f, 1.0f, 1.0f, 0.0f });
671+ var button = new DialogButton (inactive_filename, active_filename, label);
672+ button.visible = true;
673+
674+ b.pack_start (button, false, false, 0);
675+ b.pack_start (label, false, false, 0);
676+
677+ return button;
678+ }
679+}
680+
681+private class DialogButton : Gtk.Button
682+{
683+ private string inactive_filename;
684+ private string active_filename;
685+ private Gtk.Image i;
686+ private Gtk.Label? l;
687+
688+ public DialogButton (string inactive_filename, string active_filename, Gtk.Label? label = null)
689+ {
690+ this.inactive_filename = inactive_filename;
691+ this.active_filename = active_filename;
692+ l = label;
693+ relief = Gtk.ReliefStyle.NONE;
694+ focus_on_click = false;
695+ i = new Gtk.Image.from_file (inactive_filename);
696+ i.visible = true;
697+ add (i);
698+ }
699+
700+ public override bool enter_notify_event (Gdk.EventCrossing event)
701+ {
702+ grab_focus ();
703+ return base.enter_notify_event (event);
704+ }
705+
706+ public override bool leave_notify_event (Gdk.EventCrossing event)
707+ {
708+ (get_toplevel () as Gtk.Window).set_focus (null);
709+ return base.leave_notify_event (event);
710+ }
711+
712+ public override bool focus_in_event (Gdk.EventFocus event)
713+ {
714+ i.set_from_file (active_filename);
715+ if (l != null)
716+ l.override_color (Gtk.StateFlags.NORMAL, { 1.0f, 1.0f, 1.0f, 1.0f });
717+ return base.focus_in_event (event);
718+ }
719+
720+ public override bool focus_out_event (Gdk.EventFocus event)
721+ {
722+ i.set_from_file (inactive_filename);
723+ if (l != null)
724+ l.override_color (Gtk.StateFlags.NORMAL, { 1.0f, 1.0f, 1.0f, 0.0f });
725+ return base.focus_out_event (event);
726+ }
727+
728+ public override bool draw (Cairo.Context c)
729+ {
730+ i.draw (c);
731+ return true;
732+ }
733+}
734
735=== modified file 'src/unity-greeter.vala'
736--- src/unity-greeter.vala 2013-10-02 17:46:49 +0000
737+++ src/unity-greeter.vala 2013-11-05 04:29:38 +0000
738@@ -46,6 +46,8 @@
739
740 private static Timer log_timer;
741
742+ private DialogDBusInterface dbus_object;
743+
744 private UnityGreeter (bool test_mode_)
745 {
746 singleton = this;
747@@ -98,6 +100,38 @@
748
749 main_window = new MainWindow ();
750
751+ dbus_object = new DialogDBusInterface ();
752+ dbus_object.open_dialog.connect ((type) =>
753+ {
754+ ShutdownDialogType dialog_type;
755+ switch (type)
756+ {
757+ default:
758+ case 1:
759+ dialog_type = ShutdownDialogType.LOGOUT;
760+ break;
761+ case 2:
762+ dialog_type = ShutdownDialogType.RESTART;
763+ break;
764+ }
765+ main_window.show_shutdown_dialog (dialog_type);
766+ });
767+ dbus_object.close_dialog.connect ((type) => { main_window.close_shutdown_dialog (); });
768+ Bus.own_name (BusType.SESSION, "com.canonical.Unity", BusNameOwnerFlags.NONE,
769+ (c) =>
770+ {
771+ try
772+ {
773+ c.register_object ("/org/gnome/SessionManager/EndSessionDialog", dbus_object);
774+ }
775+ catch (Error e)
776+ {
777+ warning ("Failed to register /org/gnome/SessionManager/EndSessionDialog: %s", e.message);
778+ }
779+ },
780+ null,
781+ () => debug ("Failed to acquire name com.canonical.Unity"));
782+
783 start_fake_wm ();
784 Gdk.threads_add_idle (ready_cb);
785 }
786@@ -535,3 +569,20 @@
787 return Posix.EXIT_SUCCESS;
788 }
789 }
790+
791+[DBus (name="org.gnome.SessionManager.EndSessionDialog")]
792+public class DialogDBusInterface : Object
793+{
794+ public signal void open_dialog (uint32 type);
795+ public signal void close_dialog ();
796+
797+ public void open (uint32 type, uint32 timestamp, uint32 seconds_to_stay_open, ObjectPath[] inhibitor_object_paths)
798+ {
799+ open_dialog (type);
800+ }
801+
802+ public void close ()
803+ {
804+ close_dialog ();
805+ }
806+}
807
808=== modified file 'tests/Makefile.am'
809--- tests/Makefile.am 2013-10-17 22:09:16 +0000
810+++ tests/Makefile.am 2013-11-05 04:29:38 +0000
811@@ -34,7 +34,8 @@
812 ../src/session-list.vala \
813 ../src/main-window.vala \
814 ../src/list-stack.vala \
815- ../src/settings.vala
816+ ../src/settings.vala \
817+ ../src/shutdown-dialog.vala
818
819
820 unity_greeter_test_CFLAGS = \

Subscribers

People subscribed via source and target branches