Merge lp:~mterry/unity-greeter/session-chooser into lp:unity-greeter

Proposed by Michael Terry
Status: Merged
Approved by: Robert Ancell
Approved revision: 321
Merged at revision: 316
Proposed branch: lp:~mterry/unity-greeter/session-chooser
Merge into: lp:unity-greeter
Diff against target: 1154 lines (+466/-215) (has conflicts)
10 files modified
data/Makefile.am (+2/-1)
src/Makefile.am (+2/-0)
src/animate-timer.vala (+1/-0)
src/dash-button.vala (+1/-1)
src/dash-entry.vala (+1/-1)
src/fadable-box.vala (+40/-0)
src/fadable.vala (+8/-0)
src/session-chooser.vala (+156/-0)
src/unity-greeter.vala (+14/-69)
src/user-list.vala (+241/-143)
Text conflict in src/unity-greeter.vala
To merge this branch: bzr merge lp:~mterry/unity-greeter/session-chooser
Reviewer Review Type Date Requested Status
Robert Ancell Approve
Review via email: mp+94031@code.launchpad.net

Description of the change

Here's a branch to implement the design changes for bug 932169. It's not the best of code, but it works. :)

One thing I noticed is that alt-tabbing/keyboard navigation does not seem to work among the UserList controls (including this new session chooser). I don't think that's specific to this branch, and it is something we can fix post-UI-freeze, so I'm going to do that as a separate branch.

Next I'll work on menus from the main menubar looking right. This branch and that one are the last Unity Greeter changes I wanted to push in before Thursday.

To post a comment you must log in.
Revision history for this message
Robert Ancell (robert-ancell) wrote :

Missing src/session-chooser.vala

review: Needs Fixing
321. By Michael Terry

add missing file

Revision history for this message
Michael Terry (mterry) wrote :

Updated with the missing file. Doh!

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

Nice, works well for me. I wish design would drop the back button as it's completely pointless and ugly but I'll leave that one for them to decide :)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/Makefile.am'
2--- data/Makefile.am 2012-02-20 23:12:50 +0000
3+++ data/Makefile.am 2012-02-22 04:29:17 +0000
4@@ -5,7 +5,8 @@
5
6 dist_pkgdata_DATA = \
7 a11y.svg \
8- arrow.png \
9+ arrow_left.png \
10+ arrow_right.png \
11 cof.png \
12 logo.png \
13 message.png \
14
15=== added file 'data/arrow_left.png'
16Binary files data/arrow_left.png 1970-01-01 00:00:00 +0000 and data/arrow_left.png 2012-02-22 04:29:17 +0000 differ
17=== renamed file 'data/arrow.png' => 'data/arrow_right.png'
18Binary files data/arrow.png 2012-02-16 01:45:32 +0000 and data/arrow_right.png 2012-02-22 04:29:17 +0000 differ
19=== added file 'data/gnome_badge.png'
20Binary files data/gnome_badge.png 1970-01-01 00:00:00 +0000 and data/gnome_badge.png 2012-02-22 04:29:17 +0000 differ
21=== renamed file 'data/gnome_badge.png' => 'data/gnome_badge.png.moved'
22=== added file 'data/kde_badge.png'
23Binary files data/kde_badge.png 1970-01-01 00:00:00 +0000 and data/kde_badge.png 2012-02-22 04:29:17 +0000 differ
24=== renamed file 'data/kde_badge.png' => 'data/kde_badge.png.moved'
25=== added file 'data/recovery_console_badge.png'
26Binary files data/recovery_console_badge.png 1970-01-01 00:00:00 +0000 and data/recovery_console_badge.png 2012-02-22 04:29:17 +0000 differ
27=== renamed file 'data/recovery_console_badge.png' => 'data/recovery_console_badge.png.moved'
28=== added file 'data/ubuntu_badge.png'
29Binary files data/ubuntu_badge.png 1970-01-01 00:00:00 +0000 and data/ubuntu_badge.png 2012-02-22 04:29:17 +0000 differ
30=== renamed file 'data/ubuntu_badge.png' => 'data/ubuntu_badge.png.moved'
31=== added file 'data/unknown_badge.png'
32Binary files data/unknown_badge.png 1970-01-01 00:00:00 +0000 and data/unknown_badge.png 2012-02-22 04:29:17 +0000 differ
33=== renamed file 'data/unknown_badge.png' => 'data/unknown_badge.png.moved'
34=== modified file 'src/Makefile.am'
35--- src/Makefile.am 2012-02-15 11:26:39 +0000
36+++ src/Makefile.am 2012-02-22 04:29:17 +0000
37@@ -12,9 +12,11 @@
38 dash-button.vala \
39 dash-entry.vala \
40 fadable.vala \
41+ fadable-box.vala \
42 main-window.vala \
43 menu.vala \
44 menubar.vala \
45+ session-chooser.vala \
46 settings.vala \
47 settings-daemon.vala \
48 unity-greeter.vala \
49
50=== modified file 'src/animate-timer.vala'
51--- src/animate-timer.vala 2012-01-30 17:49:07 +0000
52+++ src/animate-timer.vala 2012-02-22 04:29:17 +0000
53@@ -46,6 +46,7 @@
54 stop ();
55
56 timeout = Timeout.add (16, animate_cb);
57+ progress = 0;
58 start_time = 0;
59 extra_time = 0;
60 extra_progress = 0;
61
62=== modified file 'src/dash-button.vala'
63--- src/dash-button.vala 2012-02-16 21:31:19 +0000
64+++ src/dash-button.vala 2012-02-22 04:29:17 +0000
65@@ -47,7 +47,7 @@
66 hbox.add (label);
67
68 // add chevron
69- var image = new Gtk.Image.from_file (Path.build_filename (Config.PKGDATADIR, "arrow.png", null));
70+ var image = new Gtk.Image.from_file (Path.build_filename (Config.PKGDATADIR, "arrow_right.png", null));
71 sizes.add_widget (image);
72 hbox.add (image);
73
74
75=== modified file 'src/dash-entry.vala'
76--- src/dash-entry.vala 2012-02-16 21:31:19 +0000
77+++ src/dash-entry.vala 2012-02-22 04:29:17 +0000
78@@ -87,7 +87,7 @@
79 {
80 if (enabled)
81 {
82- var file = File.new_for_path (Path.build_filename (Config.PKGDATADIR, "arrow.png", null));
83+ var file = File.new_for_path (Path.build_filename (Config.PKGDATADIR, "arrow_right.png", null));
84 var icon = new FileIcon (file);
85 set_icon_from_gicon (Gtk.EntryIconPosition.SECONDARY, icon);
86 }
87
88=== added file 'src/fadable-box.vala'
89--- src/fadable-box.vala 1970-01-01 00:00:00 +0000
90+++ src/fadable-box.vala 2012-02-22 04:29:17 +0000
91@@ -0,0 +1,40 @@
92+/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*-
93+ *
94+ * Copyright (C) 2011,2012 Canonical Ltd
95+ *
96+ * This program is free software: you can redistribute it and/or modify
97+ * it under the terms of the GNU General Public License version 3 as
98+ * published by the Free Software Foundation.
99+ *
100+ * This program is distributed in the hope that it will be useful,
101+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
102+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
103+ * GNU General Public License for more details.
104+ *
105+ * You should have received a copy of the GNU General Public License
106+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
107+ *
108+ * Authored by: Michael Terry <michael.terry@canonical.com>
109+ */
110+
111+public class FadableBox : Gtk.Box, Fadable
112+{
113+ public signal void fade_done ();
114+
115+ protected FadeTracker fade_tracker {get; protected set;}
116+
117+ construct
118+ {
119+ fade_tracker = new FadeTracker (this);
120+ fade_tracker.done.connect (() => {fade_done ();});
121+ }
122+
123+ public override bool draw (Cairo.Context c)
124+ {
125+ c.push_group ();
126+ base.draw (c);
127+ c.pop_group_to_source ();
128+ c.paint_with_alpha (fade_tracker.alpha);
129+ return false;
130+ }
131+}
132
133=== modified file 'src/fadable.vala'
134--- src/fadable.vala 2012-01-30 17:40:41 +0000
135+++ src/fadable.vala 2012-02-22 04:29:17 +0000
136@@ -19,6 +19,8 @@
137
138 public class FadeTracker : Object
139 {
140+ public signal void done ();
141+
142 public double alpha {get; private set; default = 1.0;}
143 public Gtk.Widget widget {get; construct;}
144
145@@ -56,13 +58,19 @@
146 {
147 alpha = progress;
148 if (progress == 1.0)
149+ {
150 widget.grab_focus ();
151+ done ();
152+ }
153 }
154 else
155 {
156 alpha = 1.0 - progress;
157 if (progress == 1.0)
158+ {
159 widget.hide (); /* finish the job */
160+ done ();
161+ }
162 }
163
164 widget.queue_draw ();
165
166=== added file 'src/session-chooser.vala'
167--- src/session-chooser.vala 1970-01-01 00:00:00 +0000
168+++ src/session-chooser.vala 2012-02-22 04:29:17 +0000
169@@ -0,0 +1,156 @@
170+/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*-
171+ *
172+ * Copyright (C) 2012 Canonical Ltd
173+ *
174+ * This program is free software: you can redistribute it and/or modify
175+ * it under the terms of the GNU General Public License version 3 as
176+ * published by the Free Software Foundation.
177+ *
178+ * This program is distributed in the hope that it will be useful,
179+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
180+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
181+ * GNU General Public License for more details.
182+ *
183+ * You should have received a copy of the GNU General Public License
184+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
185+ *
186+ * Authors: Michael Terry <michael.terry@canonical.com>
187+ */
188+
189+public class SessionChooser : FadableBox
190+{
191+ public signal void session_clicked (string? session);
192+
193+ construct
194+ {
195+ orientation = Gtk.Orientation.VERTICAL;
196+ border_width = 6;
197+
198+ var back = build_back_button ();
199+ pack_start (back, false, false, 0);
200+
201+ if (UnityGreeter.test_mode)
202+ {
203+ add_session ("gnome", "Ubuntu");
204+ add_session ("gnome-shell", "GNOME");
205+ add_session ("kde", "KDE");
206+ }
207+ else
208+ {
209+ foreach (var session in LightDM.get_sessions ())
210+ {
211+ debug ("Adding session %s (%s)", session.key, session.name);
212+ add_session (session.key, session.name);
213+ }
214+ }
215+ }
216+
217+ private Gtk.Widget build_back_button ()
218+ {
219+ var align = new Gtk.Alignment (0.0f, 0.5f, 0.0f, 1.0f);
220+
221+ var back = new Gtk.Button ();
222+ UnityGreeter.add_style_class (back);
223+ back.clicked.connect (() => {session_clicked (null);});
224+ align.add (back);
225+
226+ var hbox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6);
227+ back.add (hbox);
228+
229+ var image = new Gtk.Image.from_file (Path.build_filename (Config.PKGDATADIR, "arrow_left.png", null));
230+ hbox.pack_start (image, false, false, 0);
231+
232+ var label = new Gtk.Label.with_mnemonic (_("_Back"));
233+ label.mnemonic_widget = back;
234+ label.halign = Gtk.Align.START;
235+ hbox.pack_start (label, false, false, 0);
236+
237+ align.show_all ();
238+ return align;
239+ }
240+
241+ private void add_session (string key, string name)
242+ {
243+ var item = new Gtk.Button ();
244+ item.clicked.connect (() => {session_clicked (key);});
245+ UnityGreeter.add_style_class (item);
246+
247+ var hbox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6);
248+
249+ var pixbuf = get_badge (key);
250+ if (pixbuf != null)
251+ {
252+ var image = new Gtk.Image.from_pixbuf (pixbuf);
253+ hbox.pack_start (image, false, false, 0);
254+ }
255+
256+ var label = new Gtk.Label (name);
257+ label.halign = Gtk.Align.START;
258+ hbox.pack_start (label, true, true, 0);
259+
260+ item.relief = Gtk.ReliefStyle.NONE;
261+ item.add (hbox);
262+ item.show_all ();
263+
264+ try
265+ {
266+ /* Tighten padding on buttons to not be so large */
267+ var style = new Gtk.CssProvider ();
268+ style.load_from_data ("* {padding: 3px;}", -1);
269+ item.get_style_context ().add_provider (style, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
270+ }
271+ catch (Error e)
272+ {
273+ debug ("Internal error loading session chooser style: %s", e.message);
274+ }
275+
276+ add (item);
277+ }
278+
279+ private static string get_badge_name (string session)
280+ {
281+ switch (session)
282+ {
283+ case "ubuntu":
284+ case "ubuntu-2d":
285+ /* NOTE: For legacy reasons 'gnome' is actually Ubuntu */
286+ case "gnome":
287+ return "ubuntu_badge.png";
288+ case "gnome-classic":
289+ case "gnome-fallback":
290+ case "gnome-shell":
291+ return "gnome_badge.png";
292+ case "kde":
293+ return "kde_badge.png";
294+ case "xterm":
295+ return "recovery_console_badge.png";
296+ default:
297+ return "unknown_badge.png";
298+ }
299+ }
300+
301+ private static HashTable<string, Gdk.Pixbuf> badges; /* cache of badges */
302+ public static Gdk.Pixbuf? get_badge (string session)
303+ {
304+ var name = get_badge_name (session);
305+
306+ if (badges == null)
307+ badges = new HashTable<string, Gdk.Pixbuf> (str_hash, str_equal);
308+
309+ var pixbuf = badges.lookup (name);
310+ if (pixbuf == null)
311+ {
312+ try
313+ {
314+ pixbuf = new Gdk.Pixbuf.from_file (Path.build_filename (Config.PKGDATADIR, name, null));
315+ badges.insert (name, pixbuf);
316+ }
317+ catch (Error e)
318+ {
319+ debug ("Error loading badge %s: %s", name, e.message);
320+ }
321+ }
322+
323+ return pixbuf;
324+ }
325+}
326
327=== modified file 'src/unity-greeter.vala'
328--- src/unity-greeter.vala 2012-02-21 22:36:02 +0000
329+++ src/unity-greeter.vala 2012-02-22 04:29:17 +0000
330@@ -48,7 +48,6 @@
331
332 private LightDM.Greeter greeter;
333 private bool prompted = false;
334- private bool have_session = false;
335
336 /* User to authenticate against */
337 private string ?authenticate_user = null;
338@@ -105,35 +104,30 @@
339 main_window = new MainWindow ();
340 user_list = main_window.user_list;
341
342- foreach (var session in LightDM.get_sessions ())
343- {
344- debug ("Adding session %s (%s)", session.key, session.name);
345- user_list.add_session (session.key, session.name);
346- }
347-
348 if (test_mode)
349 {
350+<<<<<<< TREE
351 user_list.add_entry ("alice", "가나다라마", "#dd4814", make_layout_list ("kr"), true);
352 user_list.add_entry ("chris", "Christopher Halse Rogers!!!!!!!!!!!!!!!", "/usr/share/backgrounds/Darkening_Clockwork_by_Matt_Katzenberger.jpg", null, true, true);
353+=======
354+ user_list.add_entry ("alice", "가나다라마", "/usr/share/backgrounds/Darkening_Clockwork_by_Matt_Katzenberger.jpg", make_layout_list ("kr"), true, false, "gnome");
355+ user_list.add_entry ("chris", "Christopher Halse Rogers!!!!!!!!!!!!!!!", "/usr/share/backgrounds/Darkening_Clockwork_by_Matt_Katzenberger.jpg", null, true, true, "kde");
356+>>>>>>> MERGE-SOURCE
357 user_list.add_entry ("jorge", "Jorge O Castro", "/usr/share/backgrounds/PurpleDancers_by_Emilio_Merlino.jpg", make_layout_list ("us"));
358 user_list.add_entry ("ken", "Ken VanDine", "/usr/share/backgrounds/Small_flowers_by_Dariusz_Duma.jpg", make_layout_list ("uk;us"));
359 user_list.add_entry ("matthew", "Matthew Paul Thomas", "/usr/share/backgrounds/Not_Alone_by_Deacon_MacMillan.jpg", make_layout_list ("gb"), false, true);
360 user_list.add_entry ("otto", "Otto Greenslade", "/usr/share/backgrounds/Mount_Snowdon,_Wales_by_Adam_Vellender.jpg", make_layout_list ("gb"));
361 user_list.add_entry ("pitti", "Martin Pitt", "/usr/share/backgrounds/Stalking_Ocelot_by_Sayantan_Chaudhuri.jpg", make_layout_list ("de\tdvorak;us"));
362- user_list.add_entry ("desrt", "Ryan Lortie", "/usr/share/backgrounds/Power_of_Words_by_Antonio_Litterio.jpg", make_layout_list ("ca"), false, true);
363+ user_list.add_entry ("desrt", "Ryan Lortie", "/usr/share/backgrounds/Power_of_Words_by_Antonio_Litterio.jpg", make_layout_list ("ca"), false, true, "gnome-shell");
364 user_list.add_entry ("*guest", _("Guest Session"), null, null, true);
365
366- user_list.add_session ("gnome", "Ubuntu");
367- user_list.add_session ("gnome-shell", "GNOME");
368- user_list.add_session ("kde", "KDE");
369-
370 if (last_user != null)
371 user_list.set_active_entry (last_user);
372 }
373 else
374 {
375 if (greeter.hide_users_hint)
376- user_list.add_entry ("*other", _("Login"), null, null);
377+ user_list.add_entry ("*other", _("Login"), null, null, false, false, greeter.default_session_hint);
378 else
379 {
380 var users = LightDM.UserList.get_instance ();
381@@ -147,7 +141,7 @@
382 if (greeter.has_guest_account_hint)
383 {
384 debug ("Adding guest account entry");
385- user_list.add_entry ("*guest", _("Guest Session"), null, null);
386+ user_list.add_entry ("*guest", _("Guest Session"), null, null, false, false, greeter.default_session_hint);
387 }
388
389 if (greeter.select_user_hint != null)
390@@ -220,6 +214,10 @@
391 if (user.real_name == "")
392 label = user.name;
393
394+ var session = user.session;
395+ if (session == null)
396+ session = greeter.default_session_hint;
397+
398 var layouts = new List <LightDM.Layout> ();
399 foreach (var name in user.get_layouts ())
400 {
401@@ -228,7 +226,7 @@
402 layouts.append (layout);
403 }
404
405- user_list.add_entry (user.name, label, user.background, layouts, user.logged_in, user.has_messages);
406+ user_list.add_entry (user.name, label, user.background, layouts, user.logged_in, user.has_messages, session);
407 }
408
409 private void user_removed_cb (LightDM.User user)
410@@ -244,59 +242,13 @@
411 main_window.get_window ().focus (Gdk.CURRENT_TIME);
412 }
413
414- private void update_session ()
415- {
416- if (have_session)
417- return;
418-
419- if (test_mode)
420- {
421- if (test_username == null)
422- return;
423-
424- switch (test_username)
425- {
426- case "alice":
427- user_list.session = "ubuntu";
428- break;
429- case "bob":
430- user_list.session = "gnome-shell";
431- break;
432- case "carol":
433- user_list.session = "kde";
434- break;
435- default:
436- return;
437- }
438- have_session = true;
439- return;
440- }
441- else
442- {
443- if (greeter.authentication_user == null)
444- return;
445-
446- var user = LightDM.UserList.get_instance ().get_user_by_name (greeter.authentication_user);
447- if (user == null)
448- {
449- user_list.session = greeter.default_session_hint;
450- return;
451- }
452-
453- user_list.session = user.session;
454- have_session = true;
455- }
456- }
457-
458 private void show_message_cb (string text, LightDM.MessageType type)
459 {
460- update_session ();
461 user_list.show_message (text, type == LightDM.MessageType.ERROR);
462 }
463
464 private void show_prompt_cb (string text, LightDM.PromptType type)
465 {
466- update_session ();
467 update_other_label ();
468
469 prompted = true;
470@@ -336,7 +288,6 @@
471
472 private void authentication_complete_cb ()
473 {
474- update_session ();
475 update_other_label ();
476
477 bool is_authenticated;
478@@ -394,10 +345,6 @@
479 }
480
481 user_list.set_error (null);
482- if (test_mode)
483- user_list.session = "ubuntu";
484- else
485- user_list.session = greeter.default_session_hint;
486 start_authentication ();
487 }
488
489@@ -418,13 +365,12 @@
490 text = greeter.authentication_user;
491 }
492
493- user_list.add_entry ("*other", text, null, null);
494+ user_list.add_entry ("*other", text, null, null, false, false, greeter.default_session_hint);
495 }
496
497 private void start_authentication ()
498 {
499 prompted = false;
500- have_session = false;
501
502 if (test_mode)
503 {
504@@ -472,7 +418,6 @@
505 greeter.authenticate (user_list.selected);
506 }
507
508- update_session ();
509 update_other_label ();
510 }
511
512
513=== modified file 'src/user-list.vala'
514--- src/user-list.vala 2012-02-21 05:21:02 +0000
515+++ src/user-list.vala 2012-02-22 04:29:17 +0000
516@@ -42,11 +42,9 @@
517
518 /* Keyboard layouts to use for this user by default */
519 public List <LightDM.Layout> keyboard_layouts;
520-}
521
522-private class SessionMenuItem : Gtk.RadioMenuItem
523-{
524- public string session_name;
525+ /* Default session for this user */
526+ public string session;
527 }
528
529 public class UserList : Gtk.EventBox
530@@ -76,14 +74,18 @@
531 private Fadable prompt_widget_to_show;
532 private Gtk.Button session_button;
533 private Gtk.Image session_image;
534- private Menu session_menu;
535- private Gdk.Pixbuf unknown_badge_pixbuf;
536- private Gdk.Pixbuf gnome_badge_pixbuf;
537- private Gdk.Pixbuf kde_badge_pixbuf;
538- private Gdk.Pixbuf recovery_console_badge_pixbuf;
539- private Gdk.Pixbuf ubuntu_badge_pixbuf;
540-
541- unowned GLib.SList<SessionMenuItem> session_group = null;
542+ private SessionChooser session_chooser;
543+
544+ private enum Mode
545+ {
546+ LOGIN,
547+ TRANSFORM_TO_LOGIN_HIDE,
548+ TRANSFORM_TO_LOGIN_SHOW,
549+ SCROLLING,
550+ SESSIONS,
551+ TRANSFORM_TO_SESSIONS_HIDE,
552+ }
553+ private Mode mode = Mode.LOGIN;
554
555 private bool complete = false;
556
557@@ -120,55 +122,9 @@
558 get { if (selected_entry == null) return null; return selected_entry.name; }
559 }
560
561- public string? session
562- {
563- get
564- {
565- foreach (var item in session_group)
566- {
567- if (item.active)
568- return item.session_name;
569- }
570- return null;
571- }
572- set
573- {
574- foreach (var item in session_group)
575- {
576- if (item.session_name == value)
577- {
578- item.active = true;
579- return;
580- }
581- }
582- }
583- }
584+ public string? session {get; private set;}
585
586 private Gdk.Pixbuf? last_session_badge = null;
587- private Gdk.Pixbuf? session_badge
588- {
589- get
590- {
591- switch (session)
592- {
593- case "ubuntu":
594- case "ubuntu-2d":
595- /* NOTE: For legacy reasons 'gnome' is actually Ubuntu */
596- case "gnome":
597- return ubuntu_badge_pixbuf;
598- case "gnome-classic":
599- case "gnome-fallback":
600- case "gnome-shell":
601- return gnome_badge_pixbuf;
602- case "kde":
603- return kde_badge_pixbuf;
604- case "xterm":
605- return recovery_console_badge_pixbuf;
606- default:
607- return unknown_badge_pixbuf;
608- }
609- }
610- }
611
612 public UserList (Background bg, MenuBar mb)
613 {
614@@ -185,6 +141,12 @@
615 login_box.show ();
616 add_with_class (login_box);
617
618+ session_chooser = new SessionChooser ();
619+ session_chooser.session_clicked.connect (session_clicked_cb);
620+ session_chooser.fade_done.connect (session_fade_done_cb);
621+ session_chooser.show ();
622+ UnityGreeter.add_style_class (session_chooser);
623+
624 prompt_entry = new DashEntry ();
625 prompt_entry.caps_lock_warning = true;
626
627@@ -204,23 +166,10 @@
628 debug ("Error loading message image: %s", e.message);
629 }
630
631- try
632- {
633- unknown_badge_pixbuf = new Gdk.Pixbuf.from_file (Path.build_filename (Config.PKGDATADIR, "unknown_badge.png", null));
634- gnome_badge_pixbuf = new Gdk.Pixbuf.from_file (Path.build_filename (Config.PKGDATADIR, "gnome_badge.png"));
635- kde_badge_pixbuf = new Gdk.Pixbuf.from_file (Path.build_filename (Config.PKGDATADIR, "kde_badge.png"));
636- recovery_console_badge_pixbuf = new Gdk.Pixbuf.from_file (Path.build_filename (Config.PKGDATADIR, "recovery_console_badge.png"));
637- ubuntu_badge_pixbuf = new Gdk.Pixbuf.from_file (Path.build_filename (Config.PKGDATADIR, "ubuntu_badge.png"));
638- }
639- catch (Error e)
640- {
641- debug ("Error loading image: %s", e.message);
642- }
643-
644 session_button = new Gtk.Button ();
645 session_button.focus_on_click = false;
646 session_button.get_accessible ().set_name (_("Session Options"));
647- session_image = new Gtk.Image.from_pixbuf (session_badge);
648+ session_image = new Gtk.Image.from_pixbuf (SessionChooser.get_badge (session));
649 session_image.show ();
650 session_button.relief = Gtk.ReliefStyle.NONE;
651 session_button.add (session_image);
652@@ -228,9 +177,6 @@
653 session_button.show ();
654 add_with_class (session_button);
655
656- session_menu = new Menu (background);
657- UnityGreeter.add_style_class (session_menu);
658-
659 scroll_timer = new AnimateTimer (AnimateTimer.FAST);
660 scroll_timer.animate.connect (scroll_animate_cb);
661 }
662@@ -245,6 +191,9 @@
663
664 public void scroll (ScrollTarget target)
665 {
666+ if (mode != Mode.LOGIN && mode != Mode.SCROLLING)
667+ return;
668+
669 switch (target)
670 {
671 case ScrollTarget.START:
672@@ -286,8 +235,8 @@
673 private void redraw_login_box ()
674 {
675 Gtk.Allocation allocation;
676- get_allocation (out allocation);
677- queue_draw_area (allocation.x + box_x, allocation.y + box_y, box_width * grid_size, box_height * grid_size);
678+ login_box.get_allocation (out allocation);
679+ queue_draw_area (allocation.x, allocation.y, allocation.width, allocation.height);
680 }
681
682 public void show_message (string text, bool error = false)
683@@ -320,7 +269,7 @@
684 prompt_entry.text = "";
685 prompt_entry.sensitive = true;
686 prompt_entry.visibility = !secret;
687- if (scroll_timer.is_running)
688+ if (mode == Mode.SCROLLING)
689 prompt_widget_to_show = prompt_entry;
690 else
691 prompt_entry.show ();
692@@ -343,7 +292,7 @@
693 prompt_entry.hide ();
694 login_button.hide ();
695 message = "";
696- if (scroll_timer.is_running)
697+ if (mode == Mode.SCROLLING)
698 prompt_widget_to_show = login_button;
699 else
700 login_button.show();
701@@ -373,26 +322,6 @@
702 redraw_login_box ();
703 }
704
705- public void add_session (string name, string label)
706- {
707- var item = new SessionMenuItem ();
708- item.set_group (session_group);
709- item.session_name = name;
710- item.label = label;
711- item.show ();
712- item.toggled.connect (session_changed_cb);
713- session_menu.append (item);
714- session_group = (GLib.SList<SessionMenuItem>) item.get_group ();
715- }
716-
717- private void session_changed_cb (Gtk.CheckMenuItem item)
718- {
719- if (!item.active)
720- return;
721-
722- session_image.set_from_pixbuf (session_badge);
723- }
724-
725 private UserEntry? find_entry (string name)
726 {
727 foreach (var entry in entries)
728@@ -404,7 +333,7 @@
729 return null;
730 }
731
732- public void add_entry (string name, string label, string? background, List <LightDM.Layout>? keyboard_layouts, bool is_active = false, bool has_messages = false)
733+ public void add_entry (string name, string label, string? background, List <LightDM.Layout>? keyboard_layouts, bool is_active = false, bool has_messages = false, string? session = null)
734 {
735 var e = find_entry (name);
736 if (e == null)
737@@ -419,6 +348,7 @@
738 e.keyboard_layouts = keyboard_layouts.copy ();
739 e.is_active = is_active;
740 e.has_messages = has_messages;
741+ e.session = (session == null) ? "ubuntu" : session;
742
743 if (selected_entry == null)
744 select_entry (e, 1.0);
745@@ -467,24 +397,99 @@
746 start_session ();
747 }
748
749- private void session_menu_position_cb (Gtk.Menu menu, out int x, out int y, out bool push_in)
750- {
751- Gtk.Allocation button_allocation;
752- session_button.get_allocation (out button_allocation);
753-
754- get_window ().get_origin (out x, out y);
755- x += button_allocation.x;
756- y += button_allocation.y + button_allocation.height;
757- push_in = true;
758- }
759-
760 private void session_button_clicked_cb ()
761 {
762- session_menu.popup (null, null, session_menu_position_cb, 0, Gtk.get_current_event_time ());
763+ return_if_fail (mode == Mode.LOGIN);
764+ mode = Mode.TRANSFORM_TO_SESSIONS_HIDE;
765+ scroll_timer.reset (AnimateTimer.INSTANT);
766+ }
767+
768+ private void change_session (string session)
769+ {
770+ this.session = session;
771+ session_image.set_from_pixbuf (SessionChooser.get_badge (session));
772+ }
773+
774+ private void session_clicked_cb (string? session)
775+ {
776+ return_if_fail (mode == Mode.SESSIONS);
777+
778+ mode = Mode.TRANSFORM_TO_LOGIN_HIDE;
779+ session_chooser.fade_out ();
780+
781+ if (session != null)
782+ change_session (session);
783+ }
784+
785+ private void session_fade_done_cb ()
786+ {
787+ /* Either a fade in into SESSIONS mode or a fade out from SESSIONS mode */
788+ if (mode == Mode.TRANSFORM_TO_LOGIN_HIDE)
789+ {
790+ login_box.remove (session_chooser);
791+ mode = Mode.TRANSFORM_TO_LOGIN_SHOW;
792+ scroll_timer.reset (AnimateTimer.INSTANT);
793+
794+ if (prompt_entry.visible)
795+ prompt_entry.grab_focus ();
796+ else if (login_button.visible)
797+ login_button.grab_focus ();
798+ }
799 }
800
801 private void scroll_animate_cb (double progress)
802 {
803+ switch (mode)
804+ {
805+ case Mode.SCROLLING:
806+ animate_scrolling (progress);
807+ break;
808+ case Mode.TRANSFORM_TO_SESSIONS_HIDE:
809+ animate_to_sessions_hide (progress);
810+ break;
811+ case Mode.TRANSFORM_TO_LOGIN_SHOW:
812+ animate_to_login (progress);
813+ break;
814+ }
815+ }
816+
817+ private void animate_to_sessions_hide (double progress)
818+ {
819+ allocate_login_box ();
820+
821+ /* Stop when we get there */
822+ if (progress >= 1.0)
823+ finished_to_sessions_hide ();
824+
825+ redraw_user_list ();
826+ }
827+
828+ private void finished_to_sessions_hide ()
829+ {
830+ login_box.add (session_chooser);
831+ session_chooser.grab_focus ();
832+ session_chooser.fade_in ();
833+ mode = Mode.SESSIONS;
834+ }
835+
836+ private void animate_to_login (double progress)
837+ {
838+ allocate_login_box ();
839+
840+ /* Stop when we get there */
841+ if (progress >= 1.0)
842+ finished_to_login ();
843+
844+ redraw_user_list ();
845+ }
846+
847+ private void finished_to_login ()
848+ {
849+ mode = Mode.LOGIN;
850+ }
851+
852+ private void animate_scrolling (double progress)
853+ {
854 /* Total height of list */
855 var h = entries.length ();
856
857@@ -508,10 +513,10 @@
858
859 /* Stop when we get there */
860 if (progress >= 1.0)
861- finished_animating ();
862+ finished_scrolling ();
863 }
864
865- private void finished_animating ()
866+ private void finished_scrolling ()
867 {
868 if (prompt_widget_to_show != null)
869 {
870@@ -520,16 +525,18 @@
871 }
872 session_button.show ();
873 user_displayed ();
874+ mode = Mode.LOGIN;
875 }
876
877 private void select_entry (UserEntry entry, double direction)
878 {
879- last_session_badge = session_badge;
880+ last_session_badge = SessionChooser.get_badge (session);
881
882 if (!get_realized ())
883 {
884 /* Just note it for the future if we haven't been realized yet */
885 selected_entry = entry;
886+ change_session (entry.session);
887 return;
888 }
889
890@@ -538,15 +545,15 @@
891 var old_target = scroll_target_location;
892 var new_target = entries.index (entry);
893 var new_direction = direction;
894- var new_start = scroll_timer.is_running ? scroll_start_location : scroll_location;
895+ var new_start = (mode == Mode.SCROLLING) ? scroll_start_location : scroll_location;
896
897- if (scroll_timer.is_running && scroll_direction != new_direction)
898+ if (mode == Mode.SCROLLING && scroll_direction != new_direction)
899 return; /* ignore requests when we're already scrolling the opposite way */
900
901 if (scroll_location != new_target)
902 {
903 var new_distance = new_direction * (new_target - new_start);
904- if (scroll_timer.is_running)
905+ if (mode == Mode.SCROLLING)
906 {
907 var old_distance = new_direction * (old_target - new_start);
908 if (!scroll_timer.extend ((new_distance - old_distance) / old_distance))
909@@ -565,6 +572,8 @@
910 prompt_entry.hide ();
911 login_button.hide ();
912 session_button.hide ();
913+
914+ mode = Mode.SCROLLING;
915 }
916
917 scroll_target_location = new_target;
918@@ -575,9 +584,10 @@
919 if (selected_entry != entry)
920 {
921 selected_entry = entry;
922+ change_session (entry.session);
923 user_selected (selected_entry.name);
924
925- if (!scroll_timer.is_running)
926+ if (mode == Mode.LOGIN)
927 user_displayed (); /* didn't need to move, make sure we trigger side effects */
928 }
929 }
930@@ -591,20 +601,64 @@
931 select_entry (saved_entry, 1);
932 }
933
934- public override void size_allocate (Gtk.Allocation allocation)
935+ private int round_up_to_grid_size (int size)
936 {
937- base.size_allocate (allocation);
938+ if (size % grid_size == 0)
939+ return size;
940+ else
941+ return (size / grid_size + 1) * grid_size;
942+ }
943
944- if (!get_realized ())
945- return;
946+ private void allocate_login_box ()
947+ {
948+ Gtk.Allocation allocation;
949+ get_allocation (out allocation);
950
951 var child_allocation = Gtk.Allocation ();
952-
953 child_allocation.x = allocation.x + box_x + 6;
954 child_allocation.y = allocation.y + box_y + 6;
955 child_allocation.width = grid_size * box_width - 12;
956- child_allocation.height = grid_size * box_height - 12;
957+ child_allocation.height = grid_size * box_height - 6;
958+
959+ Gtk.Requisition session_request;
960+ session_chooser.get_preferred_size (null, out session_request);
961+ var session_height = round_up_to_grid_size (session_request.height + 12);
962+ if ((session_height / grid_size) % 2 == 0)
963+ session_height += grid_size; /* make sure we expand equally top and bottom */
964+ session_height -= 12;
965+ session_height = int.max (session_height, child_allocation.height);
966+ var session_distance = session_height - child_allocation.height;
967+
968+ switch (mode)
969+ {
970+ case Mode.TRANSFORM_TO_SESSIONS_HIDE:
971+ child_allocation.height += (int) (scroll_timer.progress * session_distance);
972+ child_allocation.y -= (int) (scroll_timer.progress * session_distance) / 2;
973+ break;
974+ case Mode.SESSIONS:
975+ case Mode.TRANSFORM_TO_LOGIN_HIDE:
976+ child_allocation.height = session_height;
977+ child_allocation.y -= session_distance / 2;
978+ break;
979+ case Mode.TRANSFORM_TO_LOGIN_SHOW:
980+ child_allocation.height = session_height - (int) (scroll_timer.progress * session_distance);
981+ child_allocation.y -= (int) ((1.0 - scroll_timer.progress) * session_distance) / 2;
982+ break;
983+ }
984+
985 login_box.size_allocate (child_allocation);
986+ }
987+
988+ public override void size_allocate (Gtk.Allocation allocation)
989+ {
990+ base.size_allocate (allocation);
991+
992+ if (!get_realized ())
993+ return;
994+
995+ allocate_login_box ();
996+
997+ var child_allocation = Gtk.Allocation ();
998
999 /* Put prompt entry and login button inside login box */
1000 child_allocation.x = allocation.x + box_x + grid_size / 2;
1001@@ -673,7 +727,7 @@
1002 c.restore ();
1003
1004 /* Now draw session button if we're animating in the box */
1005- if (in_box && scroll_timer.is_running && badge != null)
1006+ if (in_box && mode == Mode.SCROLLING && badge != null)
1007 {
1008 c.save ();
1009 var xpadding = (grid_size - badge.width) / 2;
1010@@ -701,12 +755,44 @@
1011
1012 public override bool draw (Cairo.Context c)
1013 {
1014+ var max_alpha = 1.0;
1015+ if (mode == Mode.TRANSFORM_TO_SESSIONS_HIDE)
1016+ max_alpha = 1.0 - scroll_timer.progress;
1017+ else if (mode == Mode.TRANSFORM_TO_LOGIN_SHOW)
1018+ max_alpha = scroll_timer.progress;
1019+
1020 c.save ();
1021- base.draw (c);
1022+ fixed.propagate_draw (login_box, c); /* Always full alpha */
1023 c.restore ();
1024
1025+ if (mode == Mode.LOGIN ||
1026+ mode == Mode.SCROLLING ||
1027+ mode == Mode.TRANSFORM_TO_SESSIONS_HIDE ||
1028+ mode == Mode.TRANSFORM_TO_LOGIN_SHOW)
1029+ {
1030+ c.save ();
1031+ c.push_group ();
1032+
1033+ draw_names (c, NameLocation.OUTSIDE_BOX);
1034+ draw_box_contents (c);
1035+ draw_names (c, NameLocation.INSIDE_BOX);
1036+
1037+ c.pop_group_to_source ();
1038+ c.paint_with_alpha (max_alpha);
1039+ c.restore ();
1040+ }
1041+
1042+ return false;
1043+ }
1044+
1045+ private enum NameLocation
1046+ {
1047+ INSIDE_BOX,
1048+ OUTSIDE_BOX,
1049+ }
1050+ private void draw_names (Cairo.Context c, NameLocation where)
1051+ {
1052 c.save ();
1053-
1054 c.translate (box_x, box_y);
1055
1056 var index = 0;
1057@@ -715,7 +801,7 @@
1058 var position = index - scroll_location;
1059
1060 /* Draw entries above the box */
1061- if (position < 0)
1062+ if (where == NameLocation.OUTSIDE_BOX && position < 0)
1063 {
1064 var h_above = (double) (n_above + 1) * grid_size;
1065 c.save ();
1066@@ -728,7 +814,7 @@
1067 }
1068
1069 /* Draw entries in the box */
1070- if (position > -1 && position < 1 && scroll_timer.is_running)
1071+ if (where == NameLocation.INSIDE_BOX && position > -1 && position < 1 && mode == Mode.SCROLLING)
1072 {
1073 c.save ();
1074 c.translate (0, border);
1075@@ -737,7 +823,7 @@
1076
1077 var badge = last_session_badge;
1078 if (entry == selected_entry)
1079- badge = session_badge;
1080+ badge = SessionChooser.get_badge (session);
1081
1082 if (position <= 0) /* top of box, normal pace */
1083 draw_entry_at_position (c, entry, position, true, badge);
1084@@ -748,7 +834,7 @@
1085 }
1086
1087 /* Draw entries below the box */
1088- if (position > 0)
1089+ if (where == NameLocation.OUTSIDE_BOX && position > 0)
1090 {
1091 var h_below = (double) (n_below + 1) * grid_size;
1092 c.save ();
1093@@ -763,24 +849,35 @@
1094 index++;
1095 }
1096
1097+ c.restore ();
1098+ }
1099+
1100+ private void draw_box_contents (Cairo.Context c)
1101+ {
1102+ foreach (var child in fixed.get_children ())
1103+ {
1104+ if (child != login_box)
1105+ fixed.propagate_draw (child, c);
1106+ }
1107+
1108+ c.save ();
1109+
1110+ c.translate (box_x, box_y);
1111+
1112 /* Selected item */
1113- if (selected_entry != null && !scroll_timer.is_running)
1114+ if (selected_entry != null && mode != Mode.SCROLLING)
1115 {
1116- var text_y = border;
1117+ c.save ();
1118
1119- c.save ();
1120 c.rectangle (border, border, box_width * grid_size - border * 2, box_height * grid_size - border * 2);
1121 c.clip ();
1122-
1123- c.save ();
1124- c.translate (0, text_y);
1125+ c.translate (0, border);
1126 draw_entry (c, selected_entry, 1.0, true);
1127- c.restore ();
1128
1129 c.restore ();
1130 }
1131
1132- if ((error != null || message != null) && !scroll_timer.is_running)
1133+ if ((error != null || message != null) && mode != Mode.SCROLLING)
1134 {
1135 string text;
1136 if (error == null)
1137@@ -818,8 +915,6 @@
1138 }
1139
1140 c.restore ();
1141-
1142- return false;
1143 }
1144
1145 private bool inside_entry (double x, double y, double entry_y, UserEntry entry)
1146@@ -839,6 +934,9 @@
1147
1148 public override bool button_release_event (Gdk.EventButton event)
1149 {
1150+ if (mode != Mode.LOGIN)
1151+ return false;
1152+
1153 var x = event.x - box_x;
1154 var y = event.y - box_y;
1155

Subscribers

People subscribed via source and target branches