Merge lp:~mterry/unity-greeter/grid-fixes-plus-refactor into lp:unity-greeter
- grid-fixes-plus-refactor
- Merge into trunk
Proposed by
Michael Terry
Status: | Merged |
---|---|
Approved by: | Robert Ancell |
Approved revision: | 250 |
Merged at revision: | 250 |
Proposed branch: | lp:~mterry/unity-greeter/grid-fixes-plus-refactor |
Merge into: | lp:unity-greeter |
Diff against target: |
1871 lines (+896/-748) 6 files modified
src/Makefile.am (+2/-0) src/background.vala (+357/-0) src/dash-box.vala (+17/-0) src/menubar.vala (+466/-0) src/unity-greeter.vala (+20/-14) src/user-list.vala (+34/-734) |
To merge this branch: | bzr merge lp:~mterry/unity-greeter/grid-fixes-plus-refactor |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Robert Ancell | Approve | ||
Review via email: mp+88602@code.launchpad.net |
Commit message
Description of the change
(This branch is lacking in history because I accidentally blew it away when I deleted my checkout. Thankfully I had the source files open in gedit and didn't lose the work, but I did lose the bzr history.)
This branch's primary purpose was to enable hiding the grid dots behind the login box and the menubar. But along the way, I refactored the background and menubar code out of UserList and fixed the logo to align with the grid better.
To post a comment you must log in.
Revision history for this message
Robert Ancell (robert-ancell) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'data/logo.png' |
2 | Binary files data/logo.png 2012-01-12 16:38:55 +0000 and data/logo.png 2012-01-15 10:29:23 +0000 differ |
3 | === modified file 'src/Makefile.am' |
4 | --- src/Makefile.am 2012-01-12 13:17:02 +0000 |
5 | +++ src/Makefile.am 2012-01-15 10:29:23 +0000 |
6 | @@ -7,7 +7,9 @@ |
7 | fixes.vapi \ |
8 | indicator.vapi \ |
9 | animate-timer.vala \ |
10 | + background.vala \ |
11 | dash-box.vala \ |
12 | + menubar.vala \ |
13 | settings-daemon.vala \ |
14 | unity-greeter.vala \ |
15 | user-list.vala |
16 | |
17 | === added file 'src/background.vala' |
18 | --- src/background.vala 1970-01-01 00:00:00 +0000 |
19 | +++ src/background.vala 2012-01-15 10:29:23 +0000 |
20 | @@ -0,0 +1,357 @@ |
21 | +/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*- |
22 | + * |
23 | + * Copyright (C) 2011,2012 Canonical Ltd |
24 | + * |
25 | + * This program is free software: you can redistribute it and/or modify |
26 | + * it under the terms of the GNU General Public License version 3 as |
27 | + * published by the Free Software Foundation. |
28 | + * |
29 | + * This program is distributed in the hope that it will be useful, |
30 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
31 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
32 | + * GNU General Public License for more details. |
33 | + * |
34 | + * You should have received a copy of the GNU General Public License |
35 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
36 | + * |
37 | + * Authors: Robert Ancell <robert.ancell@canonical.com> |
38 | + * Michael Terry <michael.terry@canonical.com> |
39 | + */ |
40 | + |
41 | +class BackgroundLoader |
42 | +{ |
43 | + public string filename {get; private set;} |
44 | + public Cairo.Surface logo {get; set;} |
45 | + |
46 | + private int width; |
47 | + private int height; |
48 | + private bool draw_grid; |
49 | + private unowned Thread<Cairo.Pattern?> thread; |
50 | + private bool finished; |
51 | + private uint ready_id; |
52 | + |
53 | + public Cairo.Pattern? pattern = null; |
54 | + |
55 | + public signal void loaded (); |
56 | + |
57 | + public BackgroundLoader (string filename, int width, int height, bool draw_grid) |
58 | + { |
59 | + this.filename = filename; |
60 | + this.width = width; |
61 | + this.height = height; |
62 | + this.draw_grid = draw_grid; |
63 | + } |
64 | + |
65 | + public bool load () |
66 | + { |
67 | + /* Already loaded */ |
68 | + if (finished) |
69 | + return true; |
70 | + |
71 | + /* Currently loading */ |
72 | + if (thread != null) |
73 | + return false; |
74 | + |
75 | + debug ("Making background %s at %dx%d", filename, width, height); |
76 | + try |
77 | + { |
78 | + thread = Thread<Cairo.Pattern?>.create<Cairo.Pattern?> (render, true); |
79 | + } |
80 | + catch (ThreadError e) |
81 | + { |
82 | + finished = true; |
83 | + return true; |
84 | + } |
85 | + |
86 | + return false; |
87 | + } |
88 | + |
89 | + ~Background () |
90 | + { |
91 | + if (ready_id > 0) |
92 | + Source.remove (ready_id); |
93 | + ready_id = 0; |
94 | + } |
95 | + |
96 | + private bool ready_cb () |
97 | + { |
98 | + debug ("Render of background %s at %dx%d complete", filename, width, height); |
99 | + |
100 | + pattern = thread.join (); |
101 | + thread = null; |
102 | + finished = true; |
103 | + |
104 | + loaded (); |
105 | + |
106 | + return false; |
107 | + } |
108 | + |
109 | + private Cairo.Pattern? render () |
110 | + { |
111 | + Gdk.Color color; |
112 | + Gdk.Pixbuf orig_image = null; |
113 | + if (!Gdk.Color.parse (filename, out color)) |
114 | + { |
115 | + try |
116 | + { |
117 | + orig_image = new Gdk.Pixbuf.from_file (filename); |
118 | + } |
119 | + catch (Error e) |
120 | + { |
121 | + debug ("Error loading background: %s", e.message); |
122 | + ready_id = Gdk.threads_add_idle (ready_cb); |
123 | + return null; |
124 | + } |
125 | + } |
126 | + |
127 | + Gdk.Pixbuf? image = null; |
128 | + if (orig_image != null) |
129 | + { |
130 | + var target_aspect = (double) width / height; |
131 | + var aspect = (double) orig_image.width / orig_image.height; |
132 | + double scale, offset_x = 0, offset_y = 0; |
133 | + if (aspect > target_aspect) |
134 | + { |
135 | + /* Fit height and trim sides */ |
136 | + scale = (double) height / orig_image.height; |
137 | + offset_x = (orig_image.width * scale - width) / 2; |
138 | + } |
139 | + else |
140 | + { |
141 | + /* Fit width and trim top and bottom */ |
142 | + scale = (double) width / orig_image.width; |
143 | + offset_y = (orig_image.height * scale - height) / 2; |
144 | + } |
145 | + |
146 | + image = new Gdk.Pixbuf (orig_image.colorspace, orig_image.has_alpha, orig_image.bits_per_sample, width, height); |
147 | + orig_image.scale (image, 0, 0, width, height, -offset_x, -offset_y, scale, scale, Gdk.InterpType.BILINEAR); |
148 | + } |
149 | + |
150 | + var grid_x_offset = get_grid_offset (width); |
151 | + var grid_y_offset = get_grid_offset (height); |
152 | + |
153 | + /* Create background */ |
154 | + var surface = new Cairo.ImageSurface (Cairo.Format.RGB24, width, height); |
155 | + var bc = new Cairo.Context (surface); |
156 | + if (image != null) |
157 | + Gdk.cairo_set_source_pixbuf (bc, image, 0, 0); |
158 | + else |
159 | + Gdk.cairo_set_source_color (bc, color); |
160 | + bc.paint (); |
161 | + |
162 | + /* Draw logo */ |
163 | + if (logo != null) |
164 | + { |
165 | + bc.save (); |
166 | + var y = (int) (height / grid_size - 2) * grid_size + grid_y_offset; |
167 | + bc.translate (grid_x_offset, y); |
168 | + bc.set_source_surface (logo, 0, 0); |
169 | + bc.paint_with_alpha (0.5); |
170 | + bc.restore (); |
171 | + } |
172 | + |
173 | + var pattern = new Cairo.Pattern.for_surface (surface); |
174 | + pattern.set_extend (Cairo.Extend.REPEAT); |
175 | + |
176 | + ready_id = Gdk.threads_add_idle (ready_cb); |
177 | + |
178 | + return pattern; |
179 | + } |
180 | +} |
181 | + |
182 | +public class Background : Gtk.Box |
183 | +{ |
184 | + public enum DrawFlags |
185 | + { |
186 | + NONE, |
187 | + GRID, |
188 | + } |
189 | + |
190 | + public string default_background {get; set; default = "#2C001E";} |
191 | + public string? current_background {get; set; default = null;} |
192 | + public bool draw_grid {get; set; default = true;} |
193 | + public double alpha {get; private set; default = 1.0;} |
194 | + |
195 | + public void set_logo (string logo_path) |
196 | + { |
197 | + if (FileUtils.test (logo_path, FileTest.EXISTS)) |
198 | + { |
199 | + logo_surface = new Cairo.ImageSurface.from_png (logo_path); |
200 | + } |
201 | + else |
202 | + { |
203 | + debug ("Can't use logo %s, it does not exist", logo_path); |
204 | + logo_surface = null; |
205 | + } |
206 | + } |
207 | + |
208 | + public override void size_allocate (Gtk.Allocation allocation) |
209 | + { |
210 | + var resized = allocation.height != get_allocated_height () || allocation.width != get_allocated_width (); |
211 | + |
212 | + base.size_allocate (allocation); |
213 | + |
214 | + /* Regenerate backgrounds */ |
215 | + if (resized) |
216 | + { |
217 | + debug ("Regenerating backgrounds"); |
218 | + loaders.remove_all (); |
219 | + load_background (null); |
220 | + reload (); |
221 | + } |
222 | + } |
223 | + |
224 | + public override bool draw (Cairo.Context c) |
225 | + { |
226 | + var flags = DrawFlags.NONE; |
227 | + if (draw_grid) |
228 | + flags |= DrawFlags.GRID; |
229 | + draw_full (c, flags); |
230 | + return base.draw (c); |
231 | + } |
232 | + |
233 | + public void draw_full (Cairo.Context c, DrawFlags flags) |
234 | + { |
235 | + c.save (); |
236 | + |
237 | + /* Test whether we ran into an error loading this background */ |
238 | + if (current == null || (current.load () && current.pattern == null)) |
239 | + { |
240 | + /* We couldn't load it, so swap it out for the default background |
241 | + and remember that choice */ |
242 | + var new_background = load_background (null); |
243 | + if (current != null) |
244 | + loaders.insert (current.filename, new_background); |
245 | + if (old == current) |
246 | + old = new_background; |
247 | + current = new_background; |
248 | + } |
249 | + |
250 | + /* Fade to this background when loaded */ |
251 | + if (current.load () && current != old && !timer.is_running) |
252 | + { |
253 | + alpha = 0.0; |
254 | + timer.reset (); |
255 | + } |
256 | + |
257 | + c.set_source_rgba (0.0, 0.0, 0.0, 0.0); |
258 | + var old_painted = false; |
259 | + |
260 | + /* Draw old background */ |
261 | + if (old != null && old.load () && (alpha < 1.0 || !current.load ())) |
262 | + { |
263 | + c.set_source (old.pattern); |
264 | + c.paint (); |
265 | + old_painted = true; |
266 | + } |
267 | + |
268 | + /* Draw new background */ |
269 | + if (current.load () && alpha > 0.0) |
270 | + { |
271 | + c.set_source (current.pattern); |
272 | + c.paint_with_alpha (old_painted ? alpha : 1.0); |
273 | + } |
274 | + |
275 | + c.restore (); |
276 | + |
277 | + if ((flags & DrawFlags.GRID) != 0) |
278 | + overlay_grid (c); |
279 | + } |
280 | + |
281 | + private AnimateTimer timer; |
282 | + |
283 | + private BackgroundLoader current; |
284 | + private BackgroundLoader old; |
285 | + |
286 | + private HashTable<string, BackgroundLoader> loaders; |
287 | + |
288 | + private Cairo.Surface? logo_surface = null; |
289 | + |
290 | + construct |
291 | + { |
292 | + orientation = Gtk.Orientation.VERTICAL; |
293 | + |
294 | + timer = new AnimateTimer (AnimateTimer.Speed.INSTANT); |
295 | + timer.animate.connect (animate_cb); |
296 | + |
297 | + loaders = new HashTable<string?, BackgroundLoader> (str_hash, str_equal); |
298 | + |
299 | + notify["current-background"].connect (() => {reload ();}); |
300 | + } |
301 | + |
302 | + private void animate_cb (double progress) |
303 | + { |
304 | + alpha = progress; |
305 | + |
306 | + queue_draw (); |
307 | + |
308 | + /* Stop when we get there */ |
309 | + if (alpha >= 1.0) |
310 | + old = current; |
311 | + } |
312 | + |
313 | + private void reload () |
314 | + { |
315 | + if (get_realized ()) |
316 | + { |
317 | + var new_background = load_background (current_background); |
318 | + |
319 | + if (current != new_background) |
320 | + { |
321 | + old = current; |
322 | + current = new_background; |
323 | + } |
324 | + |
325 | + queue_draw (); |
326 | + } |
327 | + } |
328 | + |
329 | + private BackgroundLoader load_background (string? filename) |
330 | + { |
331 | + if (filename == null) |
332 | + filename = default_background; |
333 | + |
334 | + var b = loaders.lookup (filename); |
335 | + if (b == null) |
336 | + { |
337 | + b = new BackgroundLoader (filename, get_allocated_width (), |
338 | + get_allocated_height (), draw_grid); |
339 | + b.logo = logo_surface; |
340 | + b.loaded.connect (() => {reload();}); |
341 | + b.load (); |
342 | + loaders.insert (filename, b); |
343 | + } |
344 | + |
345 | + return b; |
346 | + } |
347 | + |
348 | + private void overlay_grid (Cairo.Context c) |
349 | + { |
350 | + var width = get_allocated_width (); |
351 | + var height = get_allocated_height (); |
352 | + var grid_x_offset = get_grid_offset (width); |
353 | + var grid_y_offset = get_grid_offset (height); |
354 | + |
355 | + /* Overlay grid */ |
356 | + var overlay_surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, grid_size, grid_size); |
357 | + var oc = new Cairo.Context (overlay_surface); |
358 | + oc.rectangle (0, 0, 1, 1); |
359 | + oc.rectangle (grid_size - 1, 0, 1, 1); |
360 | + oc.rectangle (0, grid_size - 1, 1, 1); |
361 | + oc.rectangle (grid_size - 1, grid_size - 1, 1, 1); |
362 | + oc.set_source_rgba (1.0, 1.0, 1.0, 0.25); |
363 | + oc.fill (); |
364 | + var overlay = new Cairo.Pattern.for_surface (overlay_surface); |
365 | + var matrix = Cairo.Matrix.identity (); |
366 | + matrix.translate (-grid_x_offset, -grid_y_offset); |
367 | + overlay.set_matrix (matrix); |
368 | + overlay.set_extend (Cairo.Extend.REPEAT); |
369 | + |
370 | + /* Draw overlay */ |
371 | + c.save (); |
372 | + c.set_source (overlay); |
373 | + c.rectangle (0, 0, width, height); |
374 | + c.fill (); |
375 | + c.restore (); |
376 | + } |
377 | +} |
378 | |
379 | === modified file 'src/dash-box.vala' |
380 | --- src/dash-box.vala 2012-01-12 12:03:25 +0000 |
381 | +++ src/dash-box.vala 2012-01-15 10:29:23 +0000 |
382 | @@ -19,6 +19,13 @@ |
383 | |
384 | public class DashBox : Gtk.Box |
385 | { |
386 | + public Background? background {get; construct; default = null;} |
387 | + |
388 | + public DashBox (Background bg) |
389 | + { |
390 | + Object (background: bg); |
391 | + } |
392 | + |
393 | construct |
394 | { |
395 | orientation = Gtk.Orientation.VERTICAL; |
396 | @@ -26,6 +33,16 @@ |
397 | |
398 | public override bool draw (Cairo.Context c) |
399 | { |
400 | + if (background != null) |
401 | + { |
402 | + int x, y; |
403 | + background.translate_coordinates (this, 0, 0, out x, out y); |
404 | + c.save (); |
405 | + c.translate (x, y); |
406 | + background.draw_full (c, Background.DrawFlags.NONE); |
407 | + c.restore (); |
408 | + } |
409 | + |
410 | c.save (); |
411 | |
412 | Gtk.Allocation allocation; |
413 | |
414 | === added file 'src/menubar.vala' |
415 | --- src/menubar.vala 1970-01-01 00:00:00 +0000 |
416 | +++ src/menubar.vala 2012-01-15 10:29:23 +0000 |
417 | @@ -0,0 +1,466 @@ |
418 | +/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*- |
419 | + * |
420 | + * Copyright (C) 2011,2012 Canonical Ltd |
421 | + * |
422 | + * This program is free software: you can redistribute it and/or modify |
423 | + * it under the terms of the GNU General Public License version 3 as |
424 | + * published by the Free Software Foundation. |
425 | + * |
426 | + * This program is distributed in the hope that it will be useful, |
427 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
428 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
429 | + * GNU General Public License for more details. |
430 | + * |
431 | + * You should have received a copy of the GNU General Public License |
432 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
433 | + * |
434 | + * Authors: Robert Ancell <robert.ancell@canonical.com> |
435 | + * Michael Terry <michael.terry@canonical.com> |
436 | + */ |
437 | + |
438 | +private class IndicatorMenuItem : Gtk.MenuItem |
439 | +{ |
440 | + public unowned Indicator.ObjectEntry entry; |
441 | + private Gtk.HBox hbox; |
442 | + |
443 | + public IndicatorMenuItem (Indicator.ObjectEntry entry) |
444 | + { |
445 | + this.entry = entry; |
446 | + this.hbox = new Gtk.HBox (false, 3); |
447 | + this.add (this.hbox); |
448 | + this.hbox.show (); |
449 | + |
450 | + if (entry.label != null) |
451 | + { |
452 | + entry.label.show.connect (this.visibility_changed_cb); |
453 | + entry.label.hide.connect (this.visibility_changed_cb); |
454 | + hbox.pack_start (entry.label, false, false, 0); |
455 | + } |
456 | + if (entry.image != null) |
457 | + { |
458 | + entry.image.show.connect (visibility_changed_cb); |
459 | + entry.image.hide.connect (visibility_changed_cb); |
460 | + hbox.pack_start (entry.image, false, false, 0); |
461 | + } |
462 | + if (entry.accessible_desc != null) |
463 | + get_accessible ().set_name (entry.accessible_desc); |
464 | + if (entry.menu != null) |
465 | + submenu = entry.menu; |
466 | + |
467 | + if (has_visible_child ()) |
468 | + show (); |
469 | + } |
470 | + |
471 | + public bool has_visible_child () |
472 | + { |
473 | + return (entry.image != null && entry.image.get_visible ()) || |
474 | + (entry.label != null && entry.label.get_visible ()); |
475 | + } |
476 | + |
477 | + public void visibility_changed_cb (Gtk.Widget widget) |
478 | + { |
479 | + visible = has_visible_child (); |
480 | + } |
481 | +} |
482 | + |
483 | +public class MenuBar : Gtk.MenuBar |
484 | +{ |
485 | + public Background? background {get; construct; default = null;} |
486 | + public bool high_contrast {get; private set; default = false;} |
487 | + |
488 | + public MenuBar (Background bg) |
489 | + { |
490 | + Object (background: bg); |
491 | + } |
492 | + |
493 | + public void set_layout (LightDM.Layout? layout) |
494 | + { |
495 | + if (layout == null) |
496 | + layout = LightDM.get_layout (); /* default layout */ |
497 | + |
498 | + var item = layout.get_data<Gtk.RadioMenuItem> ("unity-greeter-radio"); |
499 | + if (item != null) |
500 | + item.active = true; /* will trigger callback to do rest of work */ |
501 | + } |
502 | + |
503 | + public override bool draw (Cairo.Context c) |
504 | + { |
505 | + if (background != null) |
506 | + { |
507 | + int x, y; |
508 | + background.translate_coordinates (this, 0, 0, out x, out y); |
509 | + c.save (); |
510 | + c.translate (x, y); |
511 | + background.draw_full (c, Background.DrawFlags.NONE); |
512 | + c.restore (); |
513 | + } |
514 | + |
515 | + c.set_source_rgb (0, 0, 0); |
516 | + c.paint_with_alpha (0.5); |
517 | + |
518 | + foreach (var child in get_children ()) |
519 | + { |
520 | + propagate_draw (child, c); |
521 | + } |
522 | + |
523 | + return false; |
524 | + } |
525 | + |
526 | + private string default_theme_name; |
527 | + private List<Indicator.Object> indicator_objects; |
528 | + private Gtk.CheckMenuItem high_contrast_item; |
529 | + private Gtk.Label keyboard_label = null; |
530 | + private Pid keyboard_pid = 0; |
531 | + private Gtk.Window? keyboard_window = null; |
532 | + |
533 | + construct |
534 | + { |
535 | + Gtk.Settings.get_default ().get ("gtk-theme-name", out default_theme_name); |
536 | + |
537 | + pack_direction = Gtk.PackDirection.RTL; |
538 | + |
539 | + var label = new Gtk.Label (Posix.utsname ().nodename); |
540 | + label.show (); |
541 | + var hostname_item = new Gtk.MenuItem (); |
542 | + hostname_item.add (label); |
543 | + hostname_item.sensitive = false; |
544 | + hostname_item.right_justified = true; |
545 | + hostname_item.show (); |
546 | + append (hostname_item); |
547 | + |
548 | + /* Hack to get a label showing on the menubar */ |
549 | + label.ensure_style (); |
550 | + label.modify_fg (Gtk.StateType.INSENSITIVE, label.get_style ().fg[Gtk.StateType.NORMAL]); |
551 | + |
552 | + setup_indicators (); |
553 | + } |
554 | + |
555 | + ~MenuBar () |
556 | + { |
557 | + if (keyboard_pid != 0) |
558 | + { |
559 | + Posix.kill (keyboard_pid, Posix.SIGKILL); |
560 | + int status; |
561 | + Posix.waitpid (keyboard_pid, out status, 0); |
562 | + keyboard_pid = 0; |
563 | + } |
564 | + } |
565 | + |
566 | + private void greeter_set_env (string key, string val) |
567 | + { |
568 | + GLib.Environment.set_variable (key, val, true); |
569 | + |
570 | + /* And also set it in the DBus activation environment so that any |
571 | + * indicator services pick it up. */ |
572 | + try |
573 | + { |
574 | + var proxy = new GLib.DBusProxy.for_bus_sync (GLib.BusType.SESSION, |
575 | + GLib.DBusProxyFlags.NONE, null, |
576 | + "org.freedesktop.DBus", |
577 | + "/org/freedesktop/DBus", |
578 | + "org.freedesktop.DBus", |
579 | + null); |
580 | + |
581 | + var builder = new GLib.VariantBuilder (GLib.VariantType.ARRAY); |
582 | + builder.add ("{ss}", key, val); |
583 | + |
584 | + proxy.call ("UpdateActivationEnvironment", new GLib.Variant ("(a{ss})", builder), GLib.DBusCallFlags.NONE, -1, null); |
585 | + } |
586 | + catch (Error e) |
587 | + { |
588 | + warning ("Could not get set environment for indicators: %s", e.message); |
589 | + return; |
590 | + } |
591 | + } |
592 | + |
593 | + private Gtk.Widget make_a11y_indicator () |
594 | + { |
595 | + var a11y_item = new Gtk.MenuItem (); |
596 | + var hbox = new Gtk.HBox (false, 3); |
597 | + hbox.show (); |
598 | + a11y_item.add (hbox); |
599 | + var image = new Gtk.Image.from_file (Path.build_filename (Config.PKGDATADIR, "a11y.svg")); |
600 | + image.show (); |
601 | + hbox.add (image); |
602 | + a11y_item.show (); |
603 | + a11y_item.submenu = new Gtk.Menu (); |
604 | + var item = new Gtk.CheckMenuItem.with_label (_("Onscreen keyboard")); |
605 | + item.toggled.connect (keyboard_toggled_cb); |
606 | + item.show (); |
607 | + a11y_item.submenu.append (item); |
608 | + high_contrast_item = new Gtk.CheckMenuItem.with_label (_("High Contrast")); |
609 | + high_contrast_item.toggled.connect (high_contrast_toggled_cb); |
610 | + high_contrast_item.show (); |
611 | + a11y_item.submenu.append (high_contrast_item); |
612 | + item = new Gtk.CheckMenuItem.with_label (_("Screen Reader")); |
613 | + item.toggled.connect (screen_reader_toggled_cb); |
614 | + item.show (); |
615 | + a11y_item.submenu.append (item); |
616 | + return a11y_item; |
617 | + } |
618 | + |
619 | + private void layout_toggled_cb (Gtk.CheckMenuItem item) |
620 | + { |
621 | + if (!item.active) |
622 | + return; |
623 | + |
624 | + var layout = item.get_data<LightDM.Layout> ("unity-greeter-layout"); |
625 | + if (layout == null) |
626 | + return; |
627 | + |
628 | + keyboard_label.label = layout.short_description; |
629 | + LightDM.set_layout (layout); |
630 | + } |
631 | + |
632 | + private static int cmp_layout (LightDM.Layout? a, LightDM.Layout? b) |
633 | + { |
634 | + if (a == null && b == null) |
635 | + return 0; |
636 | + else if (a == null) |
637 | + return 1; |
638 | + else if (b == null) |
639 | + return -1; |
640 | + else |
641 | + { |
642 | + /* Use a dumb, ascii comparison for now. If it turns out that some |
643 | + descriptions can be in unicode, we'll have to use libicu's collation |
644 | + algorithms. */ |
645 | + return strcmp (a.description, b.description); |
646 | + } |
647 | + } |
648 | + |
649 | + private Gtk.Widget make_keyboard_indicator () |
650 | + { |
651 | + var keyboard_item = new Gtk.MenuItem (); |
652 | + var hbox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 3); |
653 | + hbox.show (); |
654 | + keyboard_item.add (hbox); |
655 | + var image = new Gtk.Image.from_icon_name ("keyboard", Gtk.IconSize.LARGE_TOOLBAR); |
656 | + image.show (); |
657 | + hbox.add (image); |
658 | + keyboard_label = new Gtk.Label (""); |
659 | + keyboard_label.width_chars = 2; |
660 | + keyboard_label.show (); |
661 | + hbox.add (keyboard_label); |
662 | + keyboard_item.show (); |
663 | + |
664 | + var submenu = new Gtk.Menu (); |
665 | + keyboard_item.set_submenu (submenu); |
666 | + |
667 | + var layouts = LightDM.get_layouts ().copy (); |
668 | + layouts.sort (cmp_layout); |
669 | + |
670 | + Gtk.RadioMenuItem? last_item = null; |
671 | + foreach (var layout in layouts) |
672 | + { |
673 | + var item = new Gtk.RadioMenuItem.with_label (last_item == null ? null : last_item.get_group (), layout.description); |
674 | + last_item = item; |
675 | + |
676 | + item.show (); |
677 | + |
678 | + /* LightDM does not change its layout list during its lifetime, so this is safe */ |
679 | + item.set_data ("unity-greeter-layout", layout); |
680 | + layout.set_data ("unity-greeter-radio", item); |
681 | + |
682 | + item.toggled.connect (layout_toggled_cb); |
683 | + |
684 | + submenu.append (item); |
685 | + } |
686 | + |
687 | + return keyboard_item; |
688 | + } |
689 | + |
690 | + private void setup_indicators () |
691 | + { |
692 | + /* Set indicators to run with reduced functionality */ |
693 | + greeter_set_env ("INDICATOR_GREETER_MODE", "1"); |
694 | + |
695 | + /* Don't allow virtual file systems? */ |
696 | + greeter_set_env ("GIO_USE_VFS", "local"); |
697 | + greeter_set_env ("GVFS_DISABLE_FUSE", "1"); |
698 | + |
699 | + /* Hint to have gnome-settings-daemon run in greeter mode */ |
700 | + greeter_set_env ("RUNNING_UNDER_GDM", "1"); |
701 | + |
702 | + var keyboard_item = make_keyboard_indicator (); |
703 | + insert (keyboard_item, (int) get_children ().length () - 1); |
704 | + |
705 | + var a11y_item = make_a11y_indicator (); |
706 | + insert (a11y_item, (int) get_children ().length () - 1); |
707 | + |
708 | + debug ("LANG=%s LANGUAGE=%s", Environment.get_variable ("LANG"), Environment.get_variable ("LANGUAGE")); |
709 | + string[] filenames = {"/usr/lib/indicators3/6/libsession.so", |
710 | + "/usr/lib/indicators3/6/libdatetime.so", |
711 | + "/usr/lib/indicators3/6/libpower.so", |
712 | + "/usr/lib/indicators3/6/libsoundmenu.so"}; |
713 | + foreach (var filename in filenames) |
714 | + { |
715 | + var io = new Indicator.Object.from_file (filename); |
716 | + indicator_objects.append (io); |
717 | + io.entry_added.connect (indicator_added_cb); |
718 | + io.entry_removed.connect (indicator_removed_cb); |
719 | + foreach (var entry in io.get_entries ()) |
720 | + indicator_added_cb (io, entry); |
721 | + } |
722 | + debug ("LANG=%s LANGUAGE=%s", Environment.get_variable ("LANG"), Environment.get_variable ("LANGUAGE")); |
723 | + } |
724 | + |
725 | + private void keyboard_toggled_cb (Gtk.CheckMenuItem item) |
726 | + { |
727 | + /* FIXME: The below would be sufficient if gnome-session were running |
728 | + * to notice and run a screen keyboard in /etc/xdg/autostart... But |
729 | + * since we're not running gnome-session, we hardcode onboard here. */ |
730 | + /* var settings = new Settings ("org.gnome.desktop.a11y.applications");*/ |
731 | + /*settings.set_boolean ("screen-keyboard-enabled", item.active);*/ |
732 | + |
733 | + if (keyboard_window == null) |
734 | + { |
735 | + int id; |
736 | + |
737 | + try |
738 | + { |
739 | + string[] argv; |
740 | + int onboard_stdout_fd; |
741 | + |
742 | + Shell.parse_argv ("onboard --xid", out argv); |
743 | + Process.spawn_async_with_pipes (null, |
744 | + argv, |
745 | + null, |
746 | + SpawnFlags.SEARCH_PATH, |
747 | + null, |
748 | + out keyboard_pid, |
749 | + null, |
750 | + out onboard_stdout_fd, |
751 | + null); |
752 | + var f = FileStream.fdopen (onboard_stdout_fd, "r"); |
753 | + var stdout_text = new char[1024]; |
754 | + f.gets (stdout_text); |
755 | + id = int.parse ((string) stdout_text); |
756 | + |
757 | + } |
758 | + catch (Error e) |
759 | + { |
760 | + warning ("Error setting up keyboard: %s", e.message); |
761 | + return; |
762 | + } |
763 | + |
764 | + var keyboard_socket = new Gtk.Socket (); |
765 | + keyboard_socket.show (); |
766 | + keyboard_window = new Gtk.Window (); |
767 | + keyboard_window.accept_focus = false; |
768 | + keyboard_window.focus_on_map = false; |
769 | + keyboard_window.add (keyboard_socket); |
770 | + Gtk.socket_add_id (keyboard_socket, id); |
771 | + |
772 | + /* Put keyboard at the bottom of the screen */ |
773 | + var screen = get_screen (); |
774 | + var monitor = screen.get_monitor_at_window (get_window ()); |
775 | + Gdk.Rectangle geom; |
776 | + screen.get_monitor_geometry (monitor, out geom); |
777 | + keyboard_window.move (geom.x, geom.y + geom.height - 200); |
778 | + keyboard_window.resize (geom.width, 200); |
779 | + } |
780 | + |
781 | + keyboard_window.visible = item.active; |
782 | + } |
783 | + |
784 | + private void high_contrast_toggled_cb (Gtk.CheckMenuItem item) |
785 | + { |
786 | + var settings = Gtk.Settings.get_default (); |
787 | + if (item.active) |
788 | + settings.set ("gtk-theme-name", "HighContrastInverse"); |
789 | + else |
790 | + settings.set ("gtk-theme-name", default_theme_name); |
791 | + high_contrast = item.active; |
792 | + } |
793 | + |
794 | + private void screen_reader_toggled_cb (Gtk.CheckMenuItem item) |
795 | + { |
796 | + /* FIXME: The below would be sufficient if gnome-session were running |
797 | + * to notice and run a screen reader in /etc/xdg/autostart... But |
798 | + * since we're not running gnome-session, we hardcode orca here. |
799 | + /*var settings = new Settings ("org.gnome.desktop.a11y.applications");*/ |
800 | + /*settings.set_boolean ("screen-reader-enabled", item.active);*/ |
801 | + |
802 | + /* Hardcoded orca: */ |
803 | + try |
804 | + { |
805 | + if (item.active) |
806 | + Process.spawn_command_line_async ("orca --replace --no-setup --disable=splash-window --disable=main-window"); |
807 | + else |
808 | + Process.spawn_command_line_async ("orca --quit"); |
809 | + } |
810 | + catch (Error e) |
811 | + { |
812 | + warning ("Failed to run Orca: %s", e.message); |
813 | + } |
814 | + } |
815 | + |
816 | + private uint get_indicator_index (Indicator.Object object) |
817 | + { |
818 | + uint index = 0; |
819 | + |
820 | + foreach (var io in indicator_objects) |
821 | + { |
822 | + if (io == object) |
823 | + return index; |
824 | + index++; |
825 | + } |
826 | + |
827 | + return index; |
828 | + } |
829 | + |
830 | + private Indicator.Object? get_indicator_object_from_entry (Indicator.ObjectEntry entry) |
831 | + { |
832 | + foreach (var io in indicator_objects) |
833 | + { |
834 | + foreach (var e in io.get_entries ()) |
835 | + { |
836 | + if (e == entry) |
837 | + return io; |
838 | + } |
839 | + } |
840 | + |
841 | + return null; |
842 | + } |
843 | + |
844 | + private void indicator_added_cb (Indicator.Object object, Indicator.ObjectEntry entry) |
845 | + { |
846 | + var index = get_indicator_index (object); |
847 | + var pos = 0; |
848 | + foreach (var child in get_children ()) |
849 | + { |
850 | + if (!(child is IndicatorMenuItem)) |
851 | + break; |
852 | + |
853 | + var menuitem = (IndicatorMenuItem) child; |
854 | + var child_object = get_indicator_object_from_entry (menuitem.entry); |
855 | + var child_index = get_indicator_index (child_object); |
856 | + if (child_index > index) |
857 | + break; |
858 | + pos++; |
859 | + } |
860 | + |
861 | + debug ("Adding indicator object %p at position %d", entry, pos); |
862 | + |
863 | + var menuitem = new IndicatorMenuItem (entry); |
864 | + insert (menuitem, pos); |
865 | + } |
866 | + |
867 | + private void indicator_removed_cb (Indicator.Object object, Indicator.ObjectEntry entry) |
868 | + { |
869 | + debug ("Removing indicator object %p", entry); |
870 | + |
871 | + foreach (var child in get_children ()) |
872 | + { |
873 | + var menuitem = (IndicatorMenuItem) child; |
874 | + if (menuitem.entry == entry) |
875 | + { |
876 | + remove (child); |
877 | + return; |
878 | + } |
879 | + } |
880 | + |
881 | + warning ("Indicator object %p not in menubar", entry); |
882 | + } |
883 | +} |
884 | |
885 | === modified file 'src/unity-greeter.vala' |
886 | --- src/unity-greeter.vala 2012-01-12 13:17:02 +0000 |
887 | +++ src/unity-greeter.vala 2012-01-15 10:29:23 +0000 |
888 | @@ -120,11 +120,11 @@ |
889 | } |
890 | |
891 | user_list = new UserList (); |
892 | + user_list.background.draw_grid = get_config_value ("greeter", "draw-grid", "true") == "true"; |
893 | + user_list.background.default_background = get_config_value ("greeter", "background", "#2C001E"); |
894 | + user_list.background.set_logo (get_config_value ("greeter", "logo", Path.build_filename (Config.PKGDATADIR, "logo.png", null))); |
895 | + user_list.show (); |
896 | main_window.add (user_list); |
897 | - user_list.set_logo (get_config_value ("greeter", "logo", Path.build_filename (Config.PKGDATADIR, "logo.png", null))); |
898 | - user_list.draw_grid = get_config_value ("greeter", "draw-grid", "true") == "true"; |
899 | - user_list.default_background = get_config_value ("greeter", "background", "#2C001E"); |
900 | - user_list.show (); |
901 | |
902 | foreach (var session in LightDM.get_sessions ()) |
903 | { |
904 | @@ -295,12 +295,20 @@ |
905 | user_list.show_prompt (text, type == LightDM.PromptType.SECRET); |
906 | } |
907 | |
908 | - private void background_loaded_cb (Background background) |
909 | + private void background_loaded_cb (ParamSpec pspec) |
910 | + { |
911 | + if (user_list.background.alpha == 1.0) |
912 | + { |
913 | + user_list.background.notify["alpha"].disconnect (background_loaded_cb); |
914 | + start_session (); |
915 | + } |
916 | + } |
917 | + |
918 | + private void start_session () |
919 | { |
920 | /* Set the background */ |
921 | var c = new Cairo.Context (background_surface); |
922 | - c.set_source (background.pattern); |
923 | - c.paint (); |
924 | + user_list.background.draw (c); |
925 | c = null; |
926 | refresh_background (Gdk.Screen.get_default ()); |
927 | |
928 | @@ -331,14 +339,12 @@ |
929 | if (prompted) |
930 | { |
931 | user_list.login_complete (); |
932 | - if (test_mode) |
933 | - user_list.login_complete (); |
934 | - else |
935 | + if (!test_mode) |
936 | { |
937 | - var background = user_list.get_background (); |
938 | - background.loaded.connect (background_loaded_cb); |
939 | - if (background.load ()) |
940 | - background_loaded_cb (background); |
941 | + if (user_list.background.alpha == 1.0) |
942 | + start_session (); |
943 | + else |
944 | + user_list.background.notify["alpha"].connect (background_loaded_cb); |
945 | } |
946 | } |
947 | else |
948 | |
949 | === modified file 'src/user-list.vala' |
950 | --- src/user-list.vala 2012-01-12 13:17:02 +0000 |
951 | +++ src/user-list.vala 2012-01-15 10:29:23 +0000 |
952 | @@ -1,6 +1,6 @@ |
953 | /* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*- |
954 | * |
955 | - * Copyright (C) 2011 Canonical Ltd |
956 | + * Copyright (C) 2011,2012 Canonical Ltd |
957 | * |
958 | * This program is free software: you can redistribute it and/or modify |
959 | * it under the terms of the GNU General Public License version 3 as |
960 | @@ -14,11 +14,10 @@ |
961 | * You should have received a copy of the GNU General Public License |
962 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
963 | * |
964 | - * Authored by: Robert Ancell <robert.ancell@canonical.com> |
965 | + * Authors: Robert Ancell <robert.ancell@canonical.com> |
966 | + * Michael Terry <michael.terry@canonical.com> |
967 | */ |
968 | |
969 | -private Cairo.Surface? logo_surface = null; |
970 | - |
971 | private int get_grid_offset (int size) |
972 | { |
973 | return (int) (size % grid_size) / 2; |
974 | @@ -42,222 +41,17 @@ |
975 | public LightDM.Layout keyboard_layout; |
976 | } |
977 | |
978 | -private class IndicatorMenuItem : Gtk.MenuItem |
979 | -{ |
980 | - public unowned Indicator.ObjectEntry entry; |
981 | - private Gtk.HBox hbox; |
982 | - |
983 | - public IndicatorMenuItem (Indicator.ObjectEntry entry) |
984 | - { |
985 | - this.entry = entry; |
986 | - this.hbox = new Gtk.HBox (false, 3); |
987 | - this.add (this.hbox); |
988 | - this.hbox.show (); |
989 | - |
990 | - if (entry.label != null) |
991 | - { |
992 | - entry.label.show.connect (this.visibility_changed_cb); |
993 | - entry.label.hide.connect (this.visibility_changed_cb); |
994 | - hbox.pack_start (entry.label, false, false, 0); |
995 | - } |
996 | - if (entry.image != null) |
997 | - { |
998 | - entry.image.show.connect (visibility_changed_cb); |
999 | - entry.image.hide.connect (visibility_changed_cb); |
1000 | - hbox.pack_start (entry.image, false, false, 0); |
1001 | - } |
1002 | - if (entry.accessible_desc != null) |
1003 | - get_accessible ().set_name (entry.accessible_desc); |
1004 | - if (entry.menu != null) |
1005 | - submenu = entry.menu; |
1006 | - |
1007 | - if (has_visible_child ()) |
1008 | - show(); |
1009 | - } |
1010 | - |
1011 | - public bool has_visible_child () |
1012 | - { |
1013 | - return (entry.image != null && entry.image.get_visible ()) || |
1014 | - (entry.label != null && entry.label.get_visible ()); |
1015 | - } |
1016 | - |
1017 | - public void visibility_changed_cb (Gtk.Widget widget) |
1018 | - { |
1019 | - visible = has_visible_child (); |
1020 | - } |
1021 | -} |
1022 | - |
1023 | private class SessionMenuItem : Gtk.RadioMenuItem |
1024 | { |
1025 | public string session_name; |
1026 | } |
1027 | |
1028 | -public class Background |
1029 | -{ |
1030 | - public string filename {get; private set;} |
1031 | - private int width; |
1032 | - private int height; |
1033 | - private bool draw_grid; |
1034 | - private unowned Thread<Cairo.Pattern?> thread; |
1035 | - private bool finished; |
1036 | - |
1037 | - public Cairo.Pattern? pattern = null; |
1038 | - |
1039 | - public signal void loaded (); |
1040 | - |
1041 | - public Background (string filename, int width, int height, bool draw_grid) |
1042 | - { |
1043 | - this.filename = filename; |
1044 | - this.width = width; |
1045 | - this.height = height; |
1046 | - this.draw_grid = draw_grid; |
1047 | - } |
1048 | - |
1049 | - public bool load () |
1050 | - { |
1051 | - /* Already loaded */ |
1052 | - if (finished) |
1053 | - return true; |
1054 | - |
1055 | - /* Currently loading */ |
1056 | - if (thread != null) |
1057 | - return false; |
1058 | - |
1059 | - debug ("Making background %s at %dx%d", filename, width, height); |
1060 | - try |
1061 | - { |
1062 | - thread = Thread<Cairo.Pattern?>.create<Cairo.Pattern?> (render, true); |
1063 | - } |
1064 | - catch (ThreadError e) |
1065 | - { |
1066 | - finished = true; |
1067 | - return true; |
1068 | - } |
1069 | - |
1070 | - return false; |
1071 | - } |
1072 | - |
1073 | - private bool ready_cb () |
1074 | - { |
1075 | - debug ("Render of background %s at %dx%d complete", filename, width, height); |
1076 | - |
1077 | - pattern = thread.join (); |
1078 | - thread = null; |
1079 | - finished = true; |
1080 | - |
1081 | - loaded (); |
1082 | - |
1083 | - return false; |
1084 | - } |
1085 | - |
1086 | - private Cairo.Pattern? render () |
1087 | - { |
1088 | - Gdk.Color color; |
1089 | - Gdk.Pixbuf orig_image = null; |
1090 | - if (!Gdk.Color.parse (filename, out color)) |
1091 | - { |
1092 | - try |
1093 | - { |
1094 | - orig_image = new Gdk.Pixbuf.from_file (filename); |
1095 | - } |
1096 | - catch (Error e) |
1097 | - { |
1098 | - debug ("Error loading background: %s", e.message); |
1099 | - Gdk.threads_add_idle (ready_cb); |
1100 | - return null; |
1101 | - } |
1102 | - } |
1103 | - |
1104 | - Gdk.Pixbuf? image = null; |
1105 | - if (orig_image != null) |
1106 | - { |
1107 | - var target_aspect = (double) width / height; |
1108 | - var aspect = (double) orig_image.width / orig_image.height; |
1109 | - double scale, offset_x = 0, offset_y = 0; |
1110 | - if (aspect > target_aspect) |
1111 | - { |
1112 | - /* Fit height and trim sides */ |
1113 | - scale = (double) height / orig_image.height; |
1114 | - offset_x = (orig_image.width * scale - width) / 2; |
1115 | - } |
1116 | - else |
1117 | - { |
1118 | - /* Fit width and trim top and bottom */ |
1119 | - scale = (double) width / orig_image.width; |
1120 | - offset_y = (orig_image.height * scale - height) / 2; |
1121 | - } |
1122 | - |
1123 | - image = new Gdk.Pixbuf (orig_image.colorspace, orig_image.has_alpha, orig_image.bits_per_sample, width, height); |
1124 | - orig_image.scale (image, 0, 0, width, height, -offset_x, -offset_y, scale, scale, Gdk.InterpType.BILINEAR); |
1125 | - } |
1126 | - |
1127 | - var grid_x_offset = get_grid_offset (width); |
1128 | - var grid_y_offset = get_grid_offset (height); |
1129 | - |
1130 | - /* Overlay grid */ |
1131 | - var overlay_surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, grid_size, grid_size); |
1132 | - var oc = new Cairo.Context (overlay_surface); |
1133 | - oc.rectangle (0, 0, 1, 1); |
1134 | - oc.rectangle (grid_size - 1, 0, 1, 1); |
1135 | - oc.rectangle (0, grid_size - 1, 1, 1); |
1136 | - oc.rectangle (grid_size - 1, grid_size - 1, 1, 1); |
1137 | - oc.set_source_rgba (1.0, 1.0, 1.0, 0.25); |
1138 | - oc.fill (); |
1139 | - var overlay = new Cairo.Pattern.for_surface (overlay_surface); |
1140 | - var matrix = Cairo.Matrix.identity (); |
1141 | - matrix.translate (-grid_x_offset, -grid_y_offset); |
1142 | - overlay.set_matrix (matrix); |
1143 | - overlay.set_extend (Cairo.Extend.REPEAT); |
1144 | - |
1145 | - /* Create background */ |
1146 | - var surface = new Cairo.ImageSurface (Cairo.Format.RGB24, width, height); |
1147 | - var bc = new Cairo.Context (surface); |
1148 | - if (image != null) |
1149 | - Gdk.cairo_set_source_pixbuf (bc, image, 0, 0); |
1150 | - else |
1151 | - Gdk.cairo_set_source_color (bc, color); |
1152 | - bc.paint (); |
1153 | - |
1154 | - /* Draw overlay */ |
1155 | - if (draw_grid) |
1156 | - { |
1157 | - bc.set_source (overlay); |
1158 | - bc.rectangle (0, 0, width, height); |
1159 | - bc.fill (); |
1160 | - } |
1161 | - |
1162 | - /* Draw logo */ |
1163 | - if (logo_surface != null) |
1164 | - { |
1165 | - bc.save (); |
1166 | - var y = (int) (height / grid_size - 2) * grid_size + grid_y_offset; |
1167 | - bc.translate (grid_x_offset, y); |
1168 | - bc.set_source_surface (logo_surface, 0, 0); |
1169 | - bc.paint_with_alpha (0.5); |
1170 | - bc.restore (); |
1171 | - } |
1172 | - |
1173 | - var pattern = new Cairo.Pattern.for_surface (surface); |
1174 | - pattern.set_extend (Cairo.Extend.REPEAT); |
1175 | - |
1176 | - Gdk.threads_add_idle (ready_cb); |
1177 | - |
1178 | - return pattern; |
1179 | - } |
1180 | -} |
1181 | - |
1182 | public class UserList : Gtk.Container |
1183 | { |
1184 | - private string default_theme_name; |
1185 | - |
1186 | private int frame_count = 0; |
1187 | - |
1188 | - private HashTable<string, Background> backgrounds; |
1189 | - private Background background; |
1190 | - private Background old_background; |
1191 | + |
1192 | + public Background background; |
1193 | private uint change_background_timeout = 0; |
1194 | - public string default_background = "#2C001E"; |
1195 | - public bool draw_grid = true; |
1196 | |
1197 | private List<UserEntry> entries = null; |
1198 | private UserEntry? selected_entry = null; |
1199 | @@ -269,20 +63,9 @@ |
1200 | |
1201 | private AnimateTimer scroll_timer; |
1202 | |
1203 | - private AnimateTimer background_timer; |
1204 | - private double background_alpha; |
1205 | - |
1206 | private List<Gtk.Widget> children; |
1207 | |
1208 | - private Gtk.MenuBar menubar; |
1209 | - private Cairo.Context menubar_cairo_context; |
1210 | - public List<Indicator.Object> indicator_objects; |
1211 | - private Gtk.CheckMenuItem high_contrast_item; |
1212 | - |
1213 | - private Gtk.Label keyboard_label = null; |
1214 | - |
1215 | - private Pid keyboard_pid = 0; |
1216 | - private Gtk.Window? keyboard_window = null; |
1217 | + private MenuBar menubar; |
1218 | |
1219 | private string? error; |
1220 | private string? message; |
1221 | @@ -356,30 +139,17 @@ |
1222 | public UserList () |
1223 | { |
1224 | can_focus = false; |
1225 | - background_alpha = 1.0; |
1226 | - |
1227 | - Gtk.Settings.get_default ().get ("gtk-theme-name", out default_theme_name); |
1228 | - |
1229 | - menubar = new Gtk.MenuBar (); |
1230 | - menubar.draw.connect_after (menubar_draw_cb); |
1231 | - menubar.pack_direction = Gtk.PackDirection.RTL; |
1232 | + |
1233 | + background = new Background (); |
1234 | + background.show (); |
1235 | + add (background); |
1236 | + |
1237 | + menubar = new MenuBar (background); |
1238 | + menubar.notify["high-contrast"].connect (() => {change_background ();}); |
1239 | menubar.show (); |
1240 | add (menubar); |
1241 | |
1242 | - var label = new Gtk.Label (Posix.utsname ().nodename); |
1243 | - label.show (); |
1244 | - var hostname_item = new Gtk.MenuItem (); |
1245 | - hostname_item.add (label); |
1246 | - hostname_item.sensitive = false; |
1247 | - hostname_item.right_justified = true; |
1248 | - hostname_item.show (); |
1249 | - menubar.append (hostname_item); |
1250 | - |
1251 | - /* Hack to get a label showing on the menubar */ |
1252 | - label.ensure_style (); |
1253 | - label.modify_fg (Gtk.StateType.INSENSITIVE, label.get_style ().fg[Gtk.StateType.NORMAL]); |
1254 | - |
1255 | - login_box = new DashBox (); |
1256 | + login_box = new DashBox (background); |
1257 | login_box.show (); |
1258 | add (login_box); |
1259 | |
1260 | @@ -396,7 +166,7 @@ |
1261 | add (prompt_entry); |
1262 | |
1263 | login_button = new Gtk.Button (); |
1264 | - label = new Gtk.Label ("<span font_size=\"large\">%s</span>".printf (/* 'Log In' here is the button for logging in. */ |
1265 | + var label = new Gtk.Label ("<span font_size=\"large\">%s</span>".printf (/* 'Log In' here is the button for logging in. */ |
1266 | _("Log In"))); |
1267 | label.use_markup = true; |
1268 | label.show (); |
1269 | @@ -424,275 +194,8 @@ |
1270 | |
1271 | options_menu = new Gtk.Menu (); |
1272 | |
1273 | - backgrounds = new HashTable<string?, Background> (str_hash, str_equal); |
1274 | - |
1275 | scroll_timer = new AnimateTimer (AnimateTimer.Speed.FAST); |
1276 | scroll_timer.animate.connect (scroll_animate_cb); |
1277 | - background_timer = new AnimateTimer (AnimateTimer.Speed.INSTANT); |
1278 | - background_timer.animate.connect (background_animate_cb); |
1279 | - |
1280 | - setup_indicators (); |
1281 | - } |
1282 | - |
1283 | - public void set_logo (string logo_path) |
1284 | - { |
1285 | - if (FileUtils.test (logo_path, FileTest.EXISTS)) |
1286 | - { |
1287 | - debug ("Using logo %s", logo_path); |
1288 | - logo_surface = new Cairo.ImageSurface.from_png (logo_path); |
1289 | - } |
1290 | - else |
1291 | - { |
1292 | - debug ("Can't use logo %s, it does not exist", logo_path); |
1293 | - logo_surface = null; |
1294 | - } |
1295 | - } |
1296 | - |
1297 | - private void draw_child_cb (Gtk.Widget child) |
1298 | - { |
1299 | - menubar.propagate_draw (child, menubar_cairo_context); |
1300 | - } |
1301 | - |
1302 | - private bool menubar_draw_cb (Cairo.Context c) |
1303 | - { |
1304 | - draw_background (c); |
1305 | - |
1306 | - c.set_source_rgb (0, 0, 0); |
1307 | - c.paint_with_alpha (0.5); |
1308 | - |
1309 | - menubar_cairo_context = c; |
1310 | - menubar.forall (draw_child_cb); |
1311 | - |
1312 | - return false; |
1313 | - } |
1314 | - |
1315 | - void greeter_set_env (string key, string val) |
1316 | - { |
1317 | - GLib.Environment.set_variable (key, val, true); |
1318 | - |
1319 | - /* And also set it in the DBus activation environment so that any |
1320 | - * indicator services pick it up. */ |
1321 | - try |
1322 | - { |
1323 | - var proxy = new GLib.DBusProxy.for_bus_sync (GLib.BusType.SESSION, |
1324 | - GLib.DBusProxyFlags.NONE, null, |
1325 | - "org.freedesktop.DBus", |
1326 | - "/org/freedesktop/DBus", |
1327 | - "org.freedesktop.DBus", |
1328 | - null); |
1329 | - |
1330 | - var builder = new GLib.VariantBuilder (GLib.VariantType.ARRAY); |
1331 | - builder.add ("{ss}", key, val); |
1332 | - |
1333 | - proxy.call ("UpdateActivationEnvironment", new GLib.Variant ("(a{ss})", builder), GLib.DBusCallFlags.NONE, -1, null); |
1334 | - } |
1335 | - catch (Error e) |
1336 | - { |
1337 | - warning ("Could not get set environment for indicators: %s", e.message); |
1338 | - return; |
1339 | - } |
1340 | - } |
1341 | - |
1342 | - Gtk.Widget make_a11y_indicator () |
1343 | - { |
1344 | - var a11y_item = new Gtk.MenuItem (); |
1345 | - var hbox = new Gtk.HBox (false, 3); |
1346 | - hbox.show (); |
1347 | - a11y_item.add (hbox); |
1348 | - var image = new Gtk.Image.from_file (Path.build_filename (Config.PKGDATADIR, "a11y.svg")); |
1349 | - image.show (); |
1350 | - hbox.add (image); |
1351 | - a11y_item.show (); |
1352 | - a11y_item.submenu = new Gtk.Menu (); |
1353 | - var item = new Gtk.CheckMenuItem.with_label (_("Onscreen keyboard")); |
1354 | - item.toggled.connect (keyboard_toggled_cb); |
1355 | - item.show (); |
1356 | - a11y_item.submenu.append (item); |
1357 | - high_contrast_item = new Gtk.CheckMenuItem.with_label (_("High Contrast")); |
1358 | - high_contrast_item.toggled.connect (high_contrast_toggled_cb); |
1359 | - high_contrast_item.show (); |
1360 | - a11y_item.submenu.append (high_contrast_item); |
1361 | - item = new Gtk.CheckMenuItem.with_label (_("Screen Reader")); |
1362 | - item.toggled.connect (screen_reader_toggled_cb); |
1363 | - item.show (); |
1364 | - a11y_item.submenu.append (item); |
1365 | - return a11y_item; |
1366 | - } |
1367 | - |
1368 | - void set_layout (LightDM.Layout? layout) |
1369 | - { |
1370 | - if (layout == null) |
1371 | - layout = LightDM.get_layout (); /* default layout */ |
1372 | - |
1373 | - var item = layout.get_data<Gtk.RadioMenuItem> ("unity-greeter-radio"); |
1374 | - if (item != null) |
1375 | - item.active = true; /* will trigger callback to do rest of work */ |
1376 | - } |
1377 | - |
1378 | - void layout_toggled_cb (Gtk.CheckMenuItem item) |
1379 | - { |
1380 | - if (!item.active) |
1381 | - return; |
1382 | - |
1383 | - var layout = item.get_data<LightDM.Layout> ("unity-greeter-layout"); |
1384 | - if (layout == null) |
1385 | - return; |
1386 | - |
1387 | - keyboard_label.label = layout.short_description; |
1388 | - LightDM.set_layout (layout); |
1389 | - } |
1390 | - |
1391 | - static int cmp_layout (LightDM.Layout? a, LightDM.Layout? b) |
1392 | - { |
1393 | - if (a == null && b == null) |
1394 | - return 0; |
1395 | - else if (a == null) |
1396 | - return 1; |
1397 | - else if (b == null) |
1398 | - return -1; |
1399 | - else |
1400 | - { |
1401 | - /* Use a dumb, ascii comparison for now. If it turns out that some |
1402 | - descriptions can be in unicode, we'll have to use libicu's collation |
1403 | - algorithms. */ |
1404 | - return strcmp (a.description, b.description); |
1405 | - } |
1406 | - } |
1407 | - |
1408 | - Gtk.Widget make_keyboard_indicator () |
1409 | - { |
1410 | - var keyboard_item = new Gtk.MenuItem (); |
1411 | - var hbox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 3); |
1412 | - hbox.show (); |
1413 | - keyboard_item.add (hbox); |
1414 | - var image = new Gtk.Image.from_icon_name ("keyboard", Gtk.IconSize.LARGE_TOOLBAR); |
1415 | - image.show (); |
1416 | - hbox.add (image); |
1417 | - keyboard_label = new Gtk.Label (""); |
1418 | - keyboard_label.width_chars = 2; |
1419 | - keyboard_label.show (); |
1420 | - hbox.add (keyboard_label); |
1421 | - keyboard_item.show (); |
1422 | - |
1423 | - var submenu = new Gtk.Menu (); |
1424 | - keyboard_item.set_submenu (submenu); |
1425 | - |
1426 | - var layouts = LightDM.get_layouts ().copy (); |
1427 | - layouts.sort (cmp_layout); |
1428 | - |
1429 | - Gtk.RadioMenuItem? last_item = null; |
1430 | - foreach (var layout in layouts) |
1431 | - { |
1432 | - var item = new Gtk.RadioMenuItem.with_label (last_item == null ? null : last_item.get_group (), layout.description); |
1433 | - last_item = item; |
1434 | - |
1435 | - item.show (); |
1436 | - |
1437 | - /* LightDM does not change its layout list during its lifetime, so this is safe */ |
1438 | - item.set_data ("unity-greeter-layout", layout); |
1439 | - layout.set_data ("unity-greeter-radio", item); |
1440 | - |
1441 | - item.toggled.connect (layout_toggled_cb); |
1442 | - |
1443 | - submenu.append (item); |
1444 | - } |
1445 | - |
1446 | - return keyboard_item; |
1447 | - } |
1448 | - |
1449 | - void setup_indicators () |
1450 | - { |
1451 | - /* Set indicators to run with reduced functionality */ |
1452 | - greeter_set_env ("INDICATOR_GREETER_MODE", "1"); |
1453 | - |
1454 | - /* Don't allow virtual file systems? */ |
1455 | - greeter_set_env ("GIO_USE_VFS", "local"); |
1456 | - greeter_set_env ("GVFS_DISABLE_FUSE", "1"); |
1457 | - |
1458 | - /* Hint to have gnome-settings-daemon run in greeter mode */ |
1459 | - greeter_set_env ("RUNNING_UNDER_GDM", "1"); |
1460 | - |
1461 | - var keyboard_item = make_keyboard_indicator (); |
1462 | - menubar.insert (keyboard_item, (int) menubar.get_children ().length () - 1); |
1463 | - |
1464 | - var a11y_item = make_a11y_indicator (); |
1465 | - menubar.insert (a11y_item, (int) menubar.get_children ().length () - 1); |
1466 | - |
1467 | - debug ("LANG=%s LANGUAGE=%s", Environment.get_variable ("LANG"), Environment.get_variable ("LANGUAGE")); |
1468 | - string[] filenames = {"/usr/lib/indicators3/6/libsession.so", |
1469 | - "/usr/lib/indicators3/6/libdatetime.so", |
1470 | - "/usr/lib/indicators3/6/libpower.so", |
1471 | - "/usr/lib/indicators3/6/libsoundmenu.so"}; |
1472 | - foreach (var filename in filenames) |
1473 | - { |
1474 | - var io = new Indicator.Object.from_file (filename); |
1475 | - indicator_objects.append (io); |
1476 | - io.entry_added.connect (indicator_added_cb); |
1477 | - io.entry_removed.connect (indicator_removed_cb); |
1478 | - foreach (var entry in io.get_entries ()) |
1479 | - indicator_added_cb (io, entry); |
1480 | - } |
1481 | - debug ("LANG=%s LANGUAGE=%s", Environment.get_variable ("LANG"), Environment.get_variable ("LANGUAGE")); |
1482 | - } |
1483 | - |
1484 | - private void keyboard_toggled_cb (Gtk.CheckMenuItem item) |
1485 | - { |
1486 | - /* FIXME: The below would be sufficient if gnome-session were running |
1487 | - * to notice and run a screen keyboard in /etc/xdg/autostart... But |
1488 | - * since we're not running gnome-session, we hardcode onboard here. */ |
1489 | - /* var settings = new Settings ("org.gnome.desktop.a11y.applications");*/ |
1490 | - /*settings.set_boolean ("screen-keyboard-enabled", item.active);*/ |
1491 | - |
1492 | - if (keyboard_window == null) |
1493 | - { |
1494 | - int id; |
1495 | - |
1496 | - try |
1497 | - { |
1498 | - string[] argv; |
1499 | - int onboard_stdout_fd; |
1500 | - |
1501 | - Shell.parse_argv ("onboard --xid", out argv); |
1502 | - Process.spawn_async_with_pipes (null, |
1503 | - argv, |
1504 | - null, |
1505 | - SpawnFlags.SEARCH_PATH, |
1506 | - null, |
1507 | - out keyboard_pid, |
1508 | - null, |
1509 | - out onboard_stdout_fd, |
1510 | - null); |
1511 | - var f = FileStream.fdopen (onboard_stdout_fd, "r"); |
1512 | - var stdout_text = new char[1024]; |
1513 | - f.gets (stdout_text); |
1514 | - id = int.parse ((string) stdout_text); |
1515 | - |
1516 | - } |
1517 | - catch (Error e) |
1518 | - { |
1519 | - warning ("Error setting up keyboard: %s", e.message); |
1520 | - return; |
1521 | - } |
1522 | - |
1523 | - var keyboard_socket = new Gtk.Socket (); |
1524 | - keyboard_socket.show (); |
1525 | - keyboard_window = new Gtk.Window (); |
1526 | - keyboard_window.accept_focus = false; |
1527 | - keyboard_window.focus_on_map = false; |
1528 | - keyboard_window.add (keyboard_socket); |
1529 | - Gtk.socket_add_id (keyboard_socket, id); |
1530 | - |
1531 | - /* Put keyboard at the bottom of the screen */ |
1532 | - keyboard_window.move (0, get_allocated_height () - 200); |
1533 | - keyboard_window.resize (get_allocated_width (), 200); |
1534 | - } |
1535 | - |
1536 | - keyboard_window.visible = item.active; |
1537 | - } |
1538 | - |
1539 | - private void redraw_background () |
1540 | - { |
1541 | - queue_draw (); |
1542 | } |
1543 | |
1544 | private void redraw_user_list () |
1545 | @@ -707,39 +210,6 @@ |
1546 | queue_draw_area (box_x, box_y, box_width * grid_size, box_height * grid_size); |
1547 | } |
1548 | |
1549 | - private void high_contrast_toggled_cb (Gtk.CheckMenuItem item) |
1550 | - { |
1551 | - var settings = Gtk.Settings.get_default (); |
1552 | - if (item.active) |
1553 | - settings.set ("gtk-theme-name", "HighContrastInverse"); |
1554 | - else |
1555 | - settings.set ("gtk-theme-name", default_theme_name); |
1556 | - change_background (); |
1557 | - redraw_background (); |
1558 | - } |
1559 | - |
1560 | - private void screen_reader_toggled_cb (Gtk.CheckMenuItem item) |
1561 | - { |
1562 | - /* FIXME: The below would be sufficient if gnome-session were running |
1563 | - * to notice and run a screen reader in /etc/xdg/autostart... But |
1564 | - * since we're not running gnome-session, we hardcode orca here. |
1565 | - /*var settings = new Settings ("org.gnome.desktop.a11y.applications");*/ |
1566 | - /*settings.set_boolean ("screen-reader-enabled", item.active);*/ |
1567 | - |
1568 | - /* Hardcoded orca: */ |
1569 | - try |
1570 | - { |
1571 | - if (item.active) |
1572 | - Process.spawn_command_line_async ("orca --replace --no-setup --disable=splash-window --disable=main-window"); |
1573 | - else |
1574 | - Process.spawn_command_line_async ("orca --quit"); |
1575 | - } |
1576 | - catch (Error e) |
1577 | - { |
1578 | - warning ("Failed to run Orca: %s", e.message); |
1579 | - } |
1580 | - } |
1581 | - |
1582 | public void show_message (string text, bool error = false) |
1583 | { |
1584 | message = text; |
1585 | @@ -807,74 +277,6 @@ |
1586 | redraw_login_box (); |
1587 | } |
1588 | |
1589 | - private uint get_indicator_index (Indicator.Object object) |
1590 | - { |
1591 | - uint index = 0; |
1592 | - |
1593 | - foreach (var io in indicator_objects) |
1594 | - { |
1595 | - if (io == object) |
1596 | - return index; |
1597 | - index++; |
1598 | - } |
1599 | - |
1600 | - return index; |
1601 | - } |
1602 | - |
1603 | - private Indicator.Object? get_indicator_object_from_entry (Indicator.ObjectEntry entry) |
1604 | - { |
1605 | - foreach (var io in indicator_objects) |
1606 | - { |
1607 | - foreach (var e in io.get_entries ()) |
1608 | - { |
1609 | - if (e == entry) |
1610 | - return io; |
1611 | - } |
1612 | - } |
1613 | - |
1614 | - return null; |
1615 | - } |
1616 | - |
1617 | - private void indicator_added_cb (Indicator.Object object, Indicator.ObjectEntry entry) |
1618 | - { |
1619 | - var index = get_indicator_index (object); |
1620 | - var pos = 0; |
1621 | - foreach (var child in menubar.get_children ()) |
1622 | - { |
1623 | - if (!(child is IndicatorMenuItem)) |
1624 | - break; |
1625 | - |
1626 | - var menuitem = (IndicatorMenuItem) child; |
1627 | - var child_object = get_indicator_object_from_entry (menuitem.entry); |
1628 | - var child_index = get_indicator_index (child_object); |
1629 | - if (child_index > index) |
1630 | - break; |
1631 | - pos++; |
1632 | - } |
1633 | - |
1634 | - debug ("Adding indicator object %p at position %d", entry, pos); |
1635 | - |
1636 | - var menuitem = new IndicatorMenuItem (entry); |
1637 | - menubar.insert (menuitem, pos); |
1638 | - } |
1639 | - |
1640 | - private void indicator_removed_cb (Indicator.Object object, Indicator.ObjectEntry entry) |
1641 | - { |
1642 | - debug ("Removing indicator object %p", entry); |
1643 | - |
1644 | - foreach (var child in menubar.get_children ()) |
1645 | - { |
1646 | - var menuitem = (IndicatorMenuItem) child; |
1647 | - if (menuitem.entry == entry) |
1648 | - { |
1649 | - menubar.remove (child); |
1650 | - return; |
1651 | - } |
1652 | - } |
1653 | - |
1654 | - warning ("Indicator object %p not in menubar", entry); |
1655 | - } |
1656 | - |
1657 | public void add_session (string name, string label) |
1658 | { |
1659 | var item = new SessionMenuItem (); |
1660 | @@ -908,7 +310,7 @@ |
1661 | } |
1662 | e.layout = create_pango_layout (label); |
1663 | e.layout.set_font_description (Pango.FontDescription.from_string ("Ubuntu 16")); |
1664 | - e.background = background != null ? background : default_background; |
1665 | + e.background = background; |
1666 | e.keyboard_layout = keyboard_layout; |
1667 | e.is_active = is_active; |
1668 | |
1669 | @@ -1003,33 +405,15 @@ |
1670 | finished_animating (); |
1671 | } |
1672 | |
1673 | - private void background_animate_cb (double progress) |
1674 | - { |
1675 | - background_alpha = progress; |
1676 | - |
1677 | - redraw_background (); |
1678 | - |
1679 | - /* Stop when we get there */ |
1680 | - if (background_alpha >= 1.0) |
1681 | - old_background = background; |
1682 | - } |
1683 | - |
1684 | private bool change_background_timeout_cb () |
1685 | { |
1686 | - Background new_background; |
1687 | - if (high_contrast_item.active) |
1688 | - new_background = make_background (default_background); |
1689 | + string new_background_file; |
1690 | + if (menubar.high_contrast) |
1691 | + new_background_file = null; |
1692 | else |
1693 | - new_background = make_background (selected_entry.background); |
1694 | + new_background_file = selected_entry.background; |
1695 | |
1696 | - if (background != new_background) |
1697 | - { |
1698 | - if (frame_count > 0) |
1699 | - background_alpha = 0.0; |
1700 | - old_background = background; |
1701 | - background = new_background; |
1702 | - redraw_background (); |
1703 | - } |
1704 | + background.current_background = new_background_file; |
1705 | |
1706 | change_background_timeout = 0; |
1707 | return false; |
1708 | @@ -1082,7 +466,7 @@ |
1709 | user_selected (selected_entry.name); |
1710 | } |
1711 | |
1712 | - set_layout (selected_entry.keyboard_layout); |
1713 | + menubar.set_layout (selected_entry.keyboard_layout); |
1714 | } |
1715 | } |
1716 | |
1717 | @@ -1108,7 +492,6 @@ |
1718 | |
1719 | public override void realize () |
1720 | { |
1721 | - background = old_background = make_background (default_background); |
1722 | change_background (); |
1723 | |
1724 | set_realized (true); |
1725 | @@ -1161,15 +544,18 @@ |
1726 | if (resized) |
1727 | debug ("Resized to %dx%d", get_allocated_width (), get_allocated_height ()); |
1728 | |
1729 | - Gtk.Requisition natural_size; |
1730 | - menubar.get_preferred_size (null, out natural_size); |
1731 | var child_allocation = Gtk.Allocation (); |
1732 | - natural_size.height = 32; |
1733 | - natural_size.width = get_allocated_width (); |
1734 | - child_allocation.x = 0; |
1735 | - child_allocation.y = 0; |
1736 | - child_allocation.width = natural_size.width; |
1737 | - child_allocation.height = natural_size.height; |
1738 | + |
1739 | + child_allocation.x = 0; |
1740 | + child_allocation.y = 0; |
1741 | + child_allocation.width = allocation.width; |
1742 | + child_allocation.height = allocation.height; |
1743 | + background.size_allocate (child_allocation); |
1744 | + |
1745 | + child_allocation.x = 0; |
1746 | + child_allocation.y = 0; |
1747 | + child_allocation.width = allocation.width; |
1748 | + child_allocation.height = 32; |
1749 | menubar.size_allocate (child_allocation); |
1750 | |
1751 | child_allocation.x = box_x + 6; |
1752 | @@ -1191,21 +577,13 @@ |
1753 | child_allocation.width = grid_size; |
1754 | child_allocation.height = grid_size; |
1755 | options_button.size_allocate (child_allocation); |
1756 | - |
1757 | - /* Regenerate backgrounds */ |
1758 | - if (resized) |
1759 | - { |
1760 | - debug ("Regenerating backgrounds"); |
1761 | - backgrounds.remove_all (); |
1762 | - change_background (); |
1763 | - } |
1764 | } |
1765 | |
1766 | private void draw_entry (Cairo.Context c, UserEntry entry, double alpha = 0.5, bool in_box = false) |
1767 | { |
1768 | c.save (); |
1769 | |
1770 | - if (high_contrast_item.active || in_box) |
1771 | + if (menubar.high_contrast || in_box) |
1772 | alpha = 1.0; |
1773 | |
1774 | if (entry.is_active) |
1775 | @@ -1257,72 +635,6 @@ |
1776 | } |
1777 | } |
1778 | |
1779 | - private void background_loaded_cb (Background b) |
1780 | - { |
1781 | - change_background (); |
1782 | - redraw_background (); |
1783 | - } |
1784 | - |
1785 | - private Background make_background (string filename) |
1786 | - { |
1787 | - var b = backgrounds.lookup (filename); |
1788 | - if (b == null) |
1789 | - { |
1790 | - b = new Background (filename, get_allocated_width (), get_allocated_height (), this.draw_grid); |
1791 | - b.loaded.connect (background_loaded_cb); |
1792 | - backgrounds.insert (filename, b); |
1793 | - } |
1794 | - |
1795 | - return b; |
1796 | - } |
1797 | - |
1798 | - public Background get_background () |
1799 | - { |
1800 | - if (selected_entry != null) |
1801 | - return make_background (selected_entry.background); |
1802 | - else |
1803 | - return make_background (default_background); |
1804 | - } |
1805 | - |
1806 | - private void draw_background (Cairo.Context c) |
1807 | - { |
1808 | - /* Test whether we ran into an error loading this background */ |
1809 | - if (background.load () && background.pattern == null) |
1810 | - { |
1811 | - /* We couldn't load it, so swap it out for the default background |
1812 | - and remember that choice */ |
1813 | - var new_background = make_background (default_background); |
1814 | - backgrounds.insert (background.filename, new_background); |
1815 | - if (old_background == background) |
1816 | - old_background = new_background; |
1817 | - background = new_background; |
1818 | - } |
1819 | - |
1820 | - /* Fade to this background when loaded */ |
1821 | - if (background.load () && background != old_background && !background_timer.is_running) |
1822 | - background_timer.reset (); |
1823 | - |
1824 | - c.set_source_rgb (0x2C, 0x00, 0x1E); |
1825 | - var old_not_loaded = false; |
1826 | - |
1827 | - /* Draw old background */ |
1828 | - if (background_alpha < 1.0) |
1829 | - { |
1830 | - if (old_background.load ()) |
1831 | - c.set_source (old_background.pattern); |
1832 | - else |
1833 | - old_not_loaded = true; |
1834 | - c.paint (); |
1835 | - } |
1836 | - |
1837 | - /* Draw new background */ |
1838 | - if (background.load () && background_alpha > 0.0) |
1839 | - { |
1840 | - c.set_source (background.pattern); |
1841 | - c.paint_with_alpha (old_not_loaded ? 1.0 : background_alpha); |
1842 | - } |
1843 | - } |
1844 | - |
1845 | private void draw_entry_at_position (Cairo.Context c, UserEntry entry, |
1846 | double position, bool in_box = false) |
1847 | { |
1848 | @@ -1344,8 +656,6 @@ |
1849 | |
1850 | frame_count++; |
1851 | |
1852 | - draw_background (c); |
1853 | - |
1854 | foreach (var child in children) |
1855 | propagate_draw (child, c); |
1856 | |
1857 | @@ -1548,14 +858,4 @@ |
1858 | |
1859 | return false; |
1860 | } |
1861 | - |
1862 | - public override void unrealize () |
1863 | - { |
1864 | - if (keyboard_pid != 0) |
1865 | - { |
1866 | - Posix.kill (keyboard_pid, Posix.SIGKILL); |
1867 | - int status; |
1868 | - Posix.waitpid (keyboard_pid, out status, 0); |
1869 | - } |
1870 | - } |
1871 | } |