Merge lp:~3v1n0/unity-greeter/shutdown-blurred-bg into lp:unity-greeter
- shutdown-blurred-bg
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Robert Ancell | ||||
Approved revision: | 1048 | ||||
Merged at revision: | 1022 | ||||
Proposed branch: | lp:~3v1n0/unity-greeter/shutdown-blurred-bg | ||||
Merge into: | lp:unity-greeter | ||||
Prerequisite: | lp:~3v1n0/unity-greeter/shutdown-average-color-bg | ||||
Diff against target: |
651 lines (+353/-66) 10 files modified
configure.ac (+1/-0) debian/changelog (+8/-0) debian/control (+1/-0) src/Makefile.am (+2/-0) src/background.vala (+9/-1) src/cairo-utils.vala (+238/-0) src/dash-box.vala (+1/-19) src/main-window.vala (+2/-2) src/shutdown-dialog.vala (+89/-42) src/toggle-box.vala (+2/-2) |
||||
To merge this branch: | bzr merge lp:~3v1n0/unity-greeter/shutdown-blurred-bg | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Robert Ancell | Approve | ||
Review via email: mp+194792@code.launchpad.net |
Commit message
ShutdownDialog: blur the background under the dialog
This is done by copying the the area under the dialog into a new ImageSurface
before drawing over it, then we apply some blur on it (only when it changes) and
finally we fill the dialog rectangle with it.
Description of the change
Moved some Cairo utility functions inside the CairoUtils namespace, added Gaussian and Exponential blur implementations based on Nux code and using them to blur the window area below the dialog.
Also fixed the spelling of "Shut Down" labels so that it matches unity.
Final result: http://
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Just merged this one with previous branch in queue, removed the signal as the background average color is now a property, and using notify instead.
- 1049. By Marco Trevisan (Treviño)
-
Merging with trunk
- 1050. By Marco Trevisan (Treviño)
-
ShutdownDialog: fix background margin for good (hopefully)
But now we've buttons with no border or paddings, it should be enough.
- 1051. By Marco Trevisan (Treviño)
-
debian/control: build-depends on libpixman-1-dev
Preview Diff
1 | === modified file 'configure.ac' |
2 | --- configure.ac 2013-10-21 04:38:12 +0000 |
3 | +++ configure.ac 2013-11-13 05:34:24 +0000 |
4 | @@ -26,6 +26,7 @@ |
5 | freetype2 |
6 | cairo-ft |
7 | libcanberra |
8 | + pixman-1 |
9 | x11 |
10 | ]) |
11 | |
12 | |
13 | === modified file 'debian/changelog' |
14 | --- debian/changelog 2013-11-11 04:21:48 +0000 |
15 | +++ debian/changelog 2013-11-13 05:34:24 +0000 |
16 | @@ -1,3 +1,11 @@ |
17 | +unity-greeter (14.04.0-0ubuntu2) UNRELEASED; urgency=low |
18 | + |
19 | + * debian/control: |
20 | + - build-depends on libpixman-1-dev |
21 | + - Improved Unity style shutdown dialogs with blurred bg |
22 | + |
23 | + -- Marco Trevisan <marco@ubuntu.com> Wed, 13 Nov 2013 06:32:17 +0100 |
24 | + |
25 | unity-greeter (14.04.0-0ubuntu1) trusty; urgency=low |
26 | |
27 | * New upstream release: |
28 | |
29 | === modified file 'debian/control' |
30 | --- debian/control 2013-09-20 18:11:17 +0000 |
31 | +++ debian/control 2013-11-13 05:34:24 +0000 |
32 | @@ -15,6 +15,7 @@ |
33 | libindicator3-dev, |
34 | libido3-0.1-dev (>= 13.10.0), |
35 | liblightdm-gobject-1-dev (>= 1.4.0), |
36 | + libpixman-1-dev, |
37 | valac (>= 0.20.0), |
38 | xvfb, |
39 | Homepage: https://launchpad.net/unity-greeter |
40 | |
41 | === modified file 'src/Makefile.am' |
42 | --- src/Makefile.am 2013-11-05 02:46:46 +0000 |
43 | +++ src/Makefile.am 2013-11-13 05:34:24 +0000 |
44 | @@ -9,6 +9,7 @@ |
45 | animate-timer.vala \ |
46 | background.vala \ |
47 | cached-image.vala \ |
48 | + cairo-utils.vala \ |
49 | email-autocompleter.vala \ |
50 | dash-box.vala \ |
51 | dash-button.vala \ |
52 | @@ -52,6 +53,7 @@ |
53 | --pkg liblightdm-gobject-1 \ |
54 | --pkg libcanberra \ |
55 | --pkg gio-2.0 \ |
56 | + --pkg pixman-1 \ |
57 | --target-glib 2.32 |
58 | |
59 | unity_greeter_LDADD = \ |
60 | |
61 | === modified file 'src/background.vala' |
62 | --- src/background.vala 2013-11-13 03:43:29 +0000 |
63 | +++ src/background.vala 2013-11-13 05:34:24 +0000 |
64 | @@ -374,6 +374,14 @@ |
65 | this.width = width; |
66 | this.height = height; |
67 | } |
68 | + |
69 | + public bool equals (Monitor? other) |
70 | + { |
71 | + if (other != null) |
72 | + return (x == other.x && y == other.y && width == other.width && height == other.height); |
73 | + |
74 | + return false; |
75 | + } |
76 | } |
77 | |
78 | public class Background : Gtk.Fixed |
79 | @@ -574,7 +582,6 @@ |
80 | private void animate_cb (double progress) |
81 | { |
82 | alpha = progress; |
83 | - |
84 | queue_draw (); |
85 | |
86 | /* Stop when we get there */ |
87 | @@ -681,6 +688,7 @@ |
88 | |
89 | void publish_average_color () |
90 | { |
91 | + notify_property ("average-color"); |
92 | var rgba = current.average_color.to_string (); |
93 | var root = get_screen ().get_root_window (); |
94 | |
95 | |
96 | === added file 'src/cairo-utils.vala' |
97 | --- src/cairo-utils.vala 1970-01-01 00:00:00 +0000 |
98 | +++ src/cairo-utils.vala 2013-11-13 05:34:24 +0000 |
99 | @@ -0,0 +1,238 @@ |
100 | +/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*- |
101 | + * |
102 | + * Copyright (C) 2013 Canonical Ltd |
103 | + * |
104 | + * This program is free software: you can redistribute it and/or modify |
105 | + * it under the terms of the GNU General Public License version 3 as |
106 | + * published by the Free Software Foundation. |
107 | + * |
108 | + * This program is distributed in the hope that it will be useful, |
109 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
110 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
111 | + * GNU General Public License for more details. |
112 | + * |
113 | + * You should have received a copy of the GNU General Public License |
114 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
115 | + * |
116 | + * Authors: Marco Trevisan <marco.trevisan@canonical.com> |
117 | + * Mirco "MacSlow" Mueller <mirco.mueller@canonical.com> |
118 | + */ |
119 | + |
120 | +namespace CairoUtils |
121 | +{ |
122 | + |
123 | +public void rounded_rectangle (Cairo.Context c, double x, double y, |
124 | + double width, double height, double radius) |
125 | +{ |
126 | + var w = width - radius * 2; |
127 | + var h = height - radius * 2; |
128 | + var kappa = 0.5522847498 * radius; |
129 | + c.move_to (x + radius, y); |
130 | + c.rel_line_to (w, 0); |
131 | + c.rel_curve_to (kappa, 0, radius, radius - kappa, radius, radius); |
132 | + c.rel_line_to (0, h); |
133 | + c.rel_curve_to (0, kappa, kappa - radius, radius, -radius, radius); |
134 | + c.rel_line_to (-w, 0); |
135 | + c.rel_curve_to (-kappa, 0, -radius, kappa - radius, -radius, -radius); |
136 | + c.rel_line_to (0, -h); |
137 | + c.rel_curve_to (0, -kappa, radius - kappa, -radius, radius, -radius); |
138 | +} |
139 | + |
140 | +class GaussianBlur |
141 | +{ |
142 | + /* Gaussian Blur, based on Mirco Mueller work on notify-osd */ |
143 | + |
144 | + public static void surface (Cairo.ImageSurface surface, uint radius, double sigma = 0.0f) |
145 | + { |
146 | + if (surface.get_format () != Cairo.Format.ARGB32) |
147 | + { |
148 | + warning ("Impossible to blur a non ARGB32-formatted ImageSurface"); |
149 | + return; |
150 | + } |
151 | + |
152 | + surface.flush (); |
153 | + |
154 | + double radiusf = Math.fabs (radius) + 1.0f; |
155 | + |
156 | + if (sigma == 0.0f) |
157 | + sigma = Math.sqrt (-(radiusf * radiusf) / (2.0f * Math.log (1.0f / 255.0f))); |
158 | + |
159 | + int w = surface.get_width (); |
160 | + int h = surface.get_height (); |
161 | + int s = surface.get_stride (); |
162 | + |
163 | + // create pixman image for cairo image surface |
164 | + unowned uchar[] p = surface.get_data (); |
165 | + var src = new Pixman.Image.bits (Pixman.Format.A8R8G8B8, w, h, p, s); |
166 | + |
167 | + // attach gaussian kernel to pixman image |
168 | + var params = create_gaussian_blur_kernel ((int) radius, sigma); |
169 | + src.set_filter (Pixman.Filter.CONVOLUTION, params); |
170 | + |
171 | + // render blured image to new pixman image |
172 | + Pixman.Image.composite (Pixman.Operation.SRC, src, null, src, |
173 | + 0, 0, 0, 0, 0, 0, (uint16) w, (uint16) h); |
174 | + |
175 | + surface.mark_dirty (); |
176 | + } |
177 | + |
178 | + private static Pixman.Fixed[] create_gaussian_blur_kernel (int radius, double sigma) |
179 | + { |
180 | + double scale2 = 2.0f * sigma * sigma; |
181 | + double scale1 = 1.0f / (Math.PI * scale2); |
182 | + int size = 2 * radius + 1; |
183 | + int n_params = size * size; |
184 | + double sum = 0; |
185 | + |
186 | + var tmp = new double[n_params]; |
187 | + |
188 | + // caluclate gaussian kernel in floating point format |
189 | + for (int i = 0, x = -radius; x <= radius; ++x) |
190 | + { |
191 | + for (int y = -radius; y <= radius; ++y, ++i) |
192 | + { |
193 | + double u = x * x; |
194 | + double v = y * y; |
195 | + |
196 | + tmp[i] = scale1 * Math.exp (-(u+v)/scale2); |
197 | + |
198 | + sum += tmp[i]; |
199 | + } |
200 | + } |
201 | + |
202 | + // normalize gaussian kernel and convert to fixed point format |
203 | + var params = new Pixman.Fixed[n_params + 2]; |
204 | + |
205 | + params[0] = Pixman.Fixed.int (size); |
206 | + params[1] = Pixman.Fixed.int (size); |
207 | + |
208 | + for (int i = 2; i < params.length; ++i) |
209 | + params[i] = Pixman.Fixed.double (tmp[i] / sum); |
210 | + |
211 | + return params; |
212 | + } |
213 | +} |
214 | + |
215 | +class ExponentialBlur |
216 | +{ |
217 | + /* Exponential Blur, based on the Nux version */ |
218 | + |
219 | + const int APREC = 16; |
220 | + const int ZPREC = 7; |
221 | + |
222 | + public static void surface (Cairo.ImageSurface surface, int radius) |
223 | + { |
224 | + if (radius < 1) |
225 | + return; |
226 | + |
227 | + // before we mess with the surface execute any pending drawing |
228 | + surface.flush (); |
229 | + |
230 | + unowned uchar[] pixels = surface.get_data (); |
231 | + var width = surface.get_width (); |
232 | + var height = surface.get_height (); |
233 | + var format = surface.get_format (); |
234 | + |
235 | + switch (format) |
236 | + { |
237 | + case Cairo.Format.ARGB32: |
238 | + blur (pixels, width, height, 4, radius); |
239 | + break; |
240 | + |
241 | + case Cairo.Format.RGB24: |
242 | + blur (pixels, width, height, 3, radius); |
243 | + break; |
244 | + |
245 | + case Cairo.Format.A8: |
246 | + blur (pixels, width, height, 1, radius); |
247 | + break; |
248 | + |
249 | + default : |
250 | + // do nothing |
251 | + break; |
252 | + } |
253 | + |
254 | + // inform cairo we altered the surfaces contents |
255 | + surface.mark_dirty (); |
256 | + } |
257 | + |
258 | + static void blur (uchar[] pixels, int width, int height, int channels, int radius) |
259 | + { |
260 | + // calculate the alpha such that 90% of |
261 | + // the kernel is within the radius. |
262 | + // (Kernel extends to infinity) |
263 | + |
264 | + int alpha = (int) ((1 << APREC) * (1.0f - Math.expf(-2.3f / (radius + 1.0f)))); |
265 | + |
266 | + for (int row = 0; row < height; ++row) |
267 | + blurrow (pixels, width, height, channels, row, alpha); |
268 | + |
269 | + for (int col = 0; col < width; ++col) |
270 | + blurcol (pixels, width, height, channels, col, alpha); |
271 | + } |
272 | + |
273 | + static void blurrow (uchar[] pixels, int width, int height, int channels, int line, int alpha) |
274 | + { |
275 | + var scanline = &(pixels[line * width * channels]); |
276 | + |
277 | + int zR = *scanline << ZPREC; |
278 | + int zG = *(scanline + 1) << ZPREC; |
279 | + int zB = *(scanline + 2) << ZPREC; |
280 | + int zA = *(scanline + 3) << ZPREC; |
281 | + |
282 | + for (int index = 0; index < width; ++index) |
283 | + { |
284 | + blurinner (&scanline[index * channels], alpha, ref zR, ref zG, ref zB, ref zA); |
285 | + } |
286 | + |
287 | + for (int index = width - 2; index >= 0; --index) |
288 | + { |
289 | + blurinner (&scanline[index * channels], alpha, ref zR, ref zG, ref zB, ref zA); |
290 | + } |
291 | + } |
292 | + |
293 | + static void blurcol (uchar[] pixels, int width, int height, int channels, int x, int alpha) |
294 | + { |
295 | + var ptr = &(pixels[x * channels]); |
296 | + |
297 | + int zR = *ptr << ZPREC; |
298 | + int zG = *(ptr + 1) << ZPREC; |
299 | + int zB = *(ptr + 2) << ZPREC; |
300 | + int zA = *(ptr + 3) << ZPREC; |
301 | + |
302 | + for (int index = width; index < (height - 1) * width; index += width) |
303 | + { |
304 | + blurinner (&ptr[index * channels], alpha, ref zR, ref zG, ref zB, ref zA); |
305 | + } |
306 | + |
307 | + for (int index = (height - 2) * width; index >= 0; index -= width) |
308 | + { |
309 | + blurinner (&ptr[index * channels], alpha, ref zR, ref zG, ref zB, ref zA); |
310 | + } |
311 | + } |
312 | + |
313 | + static void blurinner (uchar *pixel, int alpha, ref int zR, ref int zG, ref int zB, ref int zA) |
314 | + { |
315 | + int R; |
316 | + int G; |
317 | + int B; |
318 | + uchar A; |
319 | + |
320 | + R = *pixel; |
321 | + G = *(pixel + 1); |
322 | + B = *(pixel + 2); |
323 | + A = *(pixel + 3); |
324 | + |
325 | + zR += (alpha * ((R << ZPREC) - zR)) >> APREC; |
326 | + zG += (alpha * ((G << ZPREC) - zG)) >> APREC; |
327 | + zB += (alpha * ((B << ZPREC) - zB)) >> APREC; |
328 | + zA += (alpha * ((A << ZPREC) - zA)) >> APREC; |
329 | + |
330 | + *pixel = zR >> ZPREC; |
331 | + *(pixel + 1) = zG >> ZPREC; |
332 | + *(pixel + 2) = zB >> ZPREC; |
333 | + *(pixel + 3) = zA >> ZPREC; |
334 | + } |
335 | +} |
336 | + |
337 | +} |
338 | |
339 | === modified file 'src/dash-box.vala' |
340 | --- src/dash-box.vala 2012-10-23 20:01:56 +0000 |
341 | +++ src/dash-box.vala 2013-11-13 05:34:24 +0000 |
342 | @@ -214,7 +214,7 @@ |
343 | |
344 | c.save (); |
345 | |
346 | - cairo_rounded_rectangle (c, 0, box_y, box_w, box_h, box_r); |
347 | + CairoUtils.rounded_rectangle (c, 0, box_y, box_w, box_h, box_r); |
348 | |
349 | c.set_source_rgba (0.1, 0.1, 0.1, 0.4); |
350 | c.fill_preserve (); |
351 | @@ -227,22 +227,4 @@ |
352 | |
353 | return base.draw (c); |
354 | } |
355 | - |
356 | - public static void cairo_rounded_rectangle (Cairo.Context c, double x, |
357 | - double y, double width, |
358 | - double height, double radius) |
359 | - { |
360 | - var w = width - radius * 2; |
361 | - var h = height - radius * 2; |
362 | - var kappa = 0.5522847498 * radius; |
363 | - c.move_to (x + radius, y); |
364 | - c.rel_line_to (w, 0); |
365 | - c.rel_curve_to (kappa, 0, radius, radius - kappa, radius, radius); |
366 | - c.rel_line_to (0, h); |
367 | - c.rel_curve_to (0, kappa, kappa - radius, radius, -radius, radius); |
368 | - c.rel_line_to (-w, 0); |
369 | - c.rel_curve_to (-kappa, 0, -radius, kappa - radius, -radius, -radius); |
370 | - c.rel_line_to (0, -h); |
371 | - c.rel_curve_to (0, -kappa, radius - kappa, -radius, radius, -radius); |
372 | - } |
373 | } |
374 | |
375 | === modified file 'src/main-window.vala' |
376 | --- src/main-window.vala 2013-11-13 03:32:25 +0000 |
377 | +++ src/main-window.vala 2013-11-13 05:34:24 +0000 |
378 | @@ -254,7 +254,7 @@ |
379 | |
380 | if (shutdown_dialog != null) |
381 | { |
382 | - shutdown_dialog.set_size_request (monitor.width, monitor.height); |
383 | + shutdown_dialog.set_active_monitor (monitor); |
384 | background.move (shutdown_dialog, monitor.x, monitor.y); |
385 | } |
386 | } |
387 | @@ -342,7 +342,7 @@ |
388 | /* Stop input to login box */ |
389 | login_box.sensitive = false; |
390 | |
391 | - shutdown_dialog = new ShutdownDialog (type, background.average_color); |
392 | + shutdown_dialog = new ShutdownDialog (type, background); |
393 | shutdown_dialog.visible = true; |
394 | shutdown_dialog.close.connect (close_shutdown_dialog); |
395 | background.add (shutdown_dialog); |
396 | |
397 | === modified file 'src/shutdown-dialog.vala' |
398 | --- src/shutdown-dialog.vala 2013-11-13 05:23:57 +0000 |
399 | +++ src/shutdown-dialog.vala 2013-11-13 05:34:24 +0000 |
400 | @@ -15,6 +15,7 @@ |
401 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
402 | * |
403 | * Authors: Robert Ancell <robert.ancell@canonical.com> |
404 | + * Marco Trevisan <marco.trevisan@canonical.com> |
405 | */ |
406 | |
407 | public enum ShutdownDialogType |
408 | @@ -28,6 +29,7 @@ |
409 | { |
410 | public signal void close (); |
411 | |
412 | + private Cairo.ImageSurface? bg_surface = null; |
413 | private Cairo.ImageSurface? corner_surface = null; |
414 | private Cairo.ImageSurface? left_surface = null; |
415 | private Cairo.ImageSurface? top_surface = null; |
416 | @@ -36,22 +38,27 @@ |
417 | private Cairo.Pattern? top_pattern = null; |
418 | |
419 | private const int BORDER_SIZE = 30; |
420 | + private const int BORDER_INTERNAL_SIZE = 10; |
421 | + private const int BORDER_EXTERNAL_SIZE = BORDER_SIZE - BORDER_INTERNAL_SIZE; |
422 | private const int CLOSE_OFFSET = 3; |
423 | private const int BUTTON_TEXT_SPACE = 9; |
424 | - private const int VBOX_EXTERNAL_PADDING = 10; |
425 | + private const int BLUR_RADIUS = 4; |
426 | + |
427 | + private Monitor monitor; |
428 | + private weak Background background; |
429 | |
430 | private Gtk.Box vbox; |
431 | private DialogButton close_button; |
432 | private Gtk.Box button_box; |
433 | - |
434 | private Gtk.EventBox monitor_events; |
435 | private Gtk.EventBox vbox_events; |
436 | |
437 | - private Gdk.RGBA avg_color; |
438 | |
439 | - public ShutdownDialog (ShutdownDialogType type, Gdk.RGBA average_color) |
440 | + public ShutdownDialog (ShutdownDialogType type, Background bg) |
441 | { |
442 | - this.avg_color = average_color; |
443 | + background = bg; |
444 | + background.notify["alpha"].connect (rebuild_background); |
445 | + background.notify["average-color"].connect (rebuild_background); |
446 | |
447 | // This event box covers the monitor size, and closes the dialog on click. |
448 | monitor_events = new Gtk.EventBox (); |
449 | @@ -66,12 +73,12 @@ |
450 | |
451 | vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 10); |
452 | vbox.visible = true; |
453 | - add (vbox); |
454 | |
455 | - vbox.margin_top = 10; |
456 | - vbox.margin_left = 22; |
457 | - vbox.margin_right = 18; |
458 | - vbox.margin_bottom = 0; |
459 | + vbox.margin = BORDER_INTERNAL_SIZE; |
460 | + vbox.margin_top += 10; |
461 | + vbox.margin_left += 20; |
462 | + vbox.margin_right += 20; |
463 | + vbox.margin_bottom += 0; |
464 | |
465 | // This event box consumes the click events inside the vbox |
466 | vbox_events = new Gtk.EventBox(); |
467 | @@ -79,24 +86,27 @@ |
468 | vbox_events.set_visible_window (false); |
469 | vbox_events.events |= Gdk.EventMask.BUTTON_PRESS_MASK; |
470 | vbox_events.button_press_event.connect (() => { return true; }); |
471 | + vbox_events.add (vbox); |
472 | monitor_events.add (vbox_events); |
473 | |
474 | - var title_label = new Gtk.Label (_("Shutdown")); |
475 | - title_label.override_font (Pango.FontDescription.from_string ("Ubuntu Light 15")); |
476 | - title_label.override_color (Gtk.StateFlags.NORMAL, { 1.0f, 1.0f, 1.0f, 1.0f }); |
477 | - title_label.set_alignment (0.0f, 0.5f); |
478 | - vbox.pack_start (title_label, false, false, 0); |
479 | - |
480 | string text; |
481 | + |
482 | if (type == ShutdownDialogType.SHUTDOWN) |
483 | { |
484 | text = _("Goodbye. Would you like to…"); |
485 | } |
486 | else |
487 | { |
488 | + var title_label = new Gtk.Label (_("Shut Down")); |
489 | + title_label.visible = true; |
490 | + title_label.override_font (Pango.FontDescription.from_string ("Ubuntu Light 15")); |
491 | + title_label.override_color (Gtk.StateFlags.NORMAL, { 1.0f, 1.0f, 1.0f, 1.0f }); |
492 | + title_label.set_alignment (0.0f, 0.5f); |
493 | + vbox.pack_start (title_label, false, false, 0); |
494 | + |
495 | text = _("Are you sure you want to shut down the computer?"); |
496 | - title_label.visible = true; |
497 | } |
498 | + |
499 | var label = new Gtk.Label (text); |
500 | label.set_line_wrap (true); |
501 | label.override_font (Pango.FontDescription.from_string ("Ubuntu Light 12")); |
502 | @@ -165,7 +175,7 @@ |
503 | |
504 | if (LightDM.get_can_shutdown ()) |
505 | { |
506 | - var button = add_button (_("Shutdown"), Path.build_filename (Config.PKGDATADIR, "shutdown.png"), Path.build_filename (Config.PKGDATADIR, "shutdown_highlight.png")); |
507 | + var button = add_button (_("Shut Down"), Path.build_filename (Config.PKGDATADIR, "shutdown.png"), Path.build_filename (Config.PKGDATADIR, "shutdown_highlight.png")); |
508 | button.clicked.connect (() => |
509 | { |
510 | try |
511 | @@ -187,6 +197,22 @@ |
512 | add (close_button); |
513 | } |
514 | |
515 | + private void rebuild_background () |
516 | + { |
517 | + bg_surface = null; |
518 | + queue_draw (); |
519 | + } |
520 | + |
521 | + public void set_active_monitor (Monitor m) |
522 | + { |
523 | + if (m == this.monitor || m.equals (this.monitor)) |
524 | + return; |
525 | + |
526 | + monitor = m; |
527 | + rebuild_background (); |
528 | + set_size_request (monitor.width, monitor.height); |
529 | + } |
530 | + |
531 | public void focus_next () |
532 | { |
533 | (get_toplevel () as Gtk.Window).move_focus (Gtk.DirectionType.TAB_FORWARD); |
534 | @@ -213,26 +239,19 @@ |
535 | |
536 | var content_allocation = Gtk.Allocation (); |
537 | int minimum_width, natural_width, minimum_height, natural_height; |
538 | - vbox.get_preferred_width (out minimum_width, out natural_width); |
539 | - vbox.get_preferred_height_for_width (minimum_width, out minimum_height, out natural_height); |
540 | + vbox_events.get_preferred_width (out minimum_width, out natural_width); |
541 | + vbox_events.get_preferred_height_for_width (minimum_width, out minimum_height, out natural_height); |
542 | content_allocation.x = allocation.x + (allocation.width - minimum_width) / 2; |
543 | content_allocation.y = allocation.y + (allocation.height - minimum_height) / 2; |
544 | content_allocation.width = minimum_width; |
545 | content_allocation.height = minimum_height; |
546 | - vbox.size_allocate (content_allocation); |
547 | - |
548 | - var events_allocation = content_allocation; |
549 | - events_allocation.x -= VBOX_EXTERNAL_PADDING; |
550 | - events_allocation.y -= VBOX_EXTERNAL_PADDING; |
551 | - events_allocation.width += VBOX_EXTERNAL_PADDING * 2; |
552 | - events_allocation.height += VBOX_EXTERNAL_PADDING * 2; |
553 | - vbox_events.size_allocate (events_allocation); |
554 | + vbox_events.size_allocate (content_allocation); |
555 | |
556 | var a = Gtk.Allocation (); |
557 | close_button.get_preferred_width (out minimum_width, out natural_width); |
558 | close_button.get_preferred_height (out minimum_height, out natural_height); |
559 | - a.x = content_allocation.x - BORDER_SIZE + CLOSE_OFFSET; |
560 | - a.y = content_allocation.y - BORDER_SIZE + CLOSE_OFFSET; |
561 | + a.x = content_allocation.x - BORDER_EXTERNAL_SIZE + CLOSE_OFFSET; |
562 | + a.y = content_allocation.y - BORDER_EXTERNAL_SIZE + CLOSE_OFFSET; |
563 | a.width = minimum_width; |
564 | a.height = minimum_height; |
565 | close_button.size_allocate (a); |
566 | @@ -252,16 +271,51 @@ |
567 | top_pattern.set_extend (Cairo.Extend.REPEAT); |
568 | } |
569 | |
570 | - var width = vbox.get_allocated_width () + BORDER_SIZE * 2 + vbox.margin_left + vbox.margin_right; |
571 | - var height = vbox.get_allocated_height () + BORDER_SIZE * 2 + vbox.margin_top + vbox.margin_bottom; |
572 | + int width = vbox_events.get_allocated_width (); |
573 | + int height = vbox_events.get_allocated_height (); |
574 | + int x = (get_allocated_width () - width) / 2; |
575 | + int y = (get_allocated_height () - height) / 2; |
576 | |
577 | /* Darken background */ |
578 | c.set_source_rgba (0, 0, 0, 0.25); |
579 | c.paint (); |
580 | |
581 | - /* Draw dialog */ |
582 | - c.save (); |
583 | - c.translate ((get_allocated_width () - width) * 0.5, (get_allocated_height () - height) * 0.5); |
584 | + if (bg_surface == null) |
585 | + { |
586 | + /* Create a new blurred surface of the current surface */ |
587 | + bg_surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, width, height); |
588 | + var bg_cr = new Cairo.Context (bg_surface); |
589 | + |
590 | + bg_cr.set_source_surface (c.get_target (), -x - monitor.x, -y - monitor.y); |
591 | + bg_cr.rectangle (0, 0, width, height); |
592 | + bg_cr.fill (); |
593 | + |
594 | + CairoUtils.ExponentialBlur.surface (bg_surface, BLUR_RADIUS); |
595 | + } |
596 | + |
597 | + /* Background */ |
598 | + c.save (); |
599 | + c.translate (x, y); |
600 | + |
601 | + var avg_color = background.average_color; |
602 | + CairoUtils.rounded_rectangle (c, 0, 0, width, height, 4); |
603 | + c.set_source_surface (bg_surface, 0, 0); |
604 | + c.fill_preserve (); |
605 | + c.set_source_rgba (0.0, 0.0, 0.0, 0.55f); |
606 | + c.fill_preserve (); |
607 | + c.set_source_rgba (avg_color.red, avg_color.green, avg_color.blue, 0.35); |
608 | + c.fill (); |
609 | + |
610 | + c.restore(); |
611 | + |
612 | + /* Draw borders */ |
613 | + x -= BORDER_EXTERNAL_SIZE; |
614 | + y -= BORDER_EXTERNAL_SIZE; |
615 | + width += BORDER_EXTERNAL_SIZE * 2; |
616 | + height += BORDER_EXTERNAL_SIZE * 2; |
617 | + |
618 | + c.save (); |
619 | + c.translate (x, y); |
620 | |
621 | /* Top left */ |
622 | var m = Cairo.Matrix.identity (); |
623 | @@ -329,13 +383,6 @@ |
624 | c.rectangle (BORDER_SIZE, height - BORDER_SIZE, width - BORDER_SIZE * 2, BORDER_SIZE); |
625 | c.fill (); |
626 | |
627 | - /* Background */ |
628 | - DashBox.cairo_rounded_rectangle (c, 20, 20, width - 40, height - 40, 4); |
629 | - c.set_source_rgba (0.0, 0.0, 0.0, 0.75f); |
630 | - c.fill_preserve (); |
631 | - c.set_source_rgba (avg_color.red, avg_color.green, avg_color.blue, 0.35); |
632 | - c.fill (); |
633 | - |
634 | c.restore (); |
635 | |
636 | return base.draw (c); |
637 | |
638 | === modified file 'src/toggle-box.vala' |
639 | --- src/toggle-box.vala 2012-10-23 20:01:56 +0000 |
640 | +++ src/toggle-box.vala 2013-11-13 05:34:24 +0000 |
641 | @@ -54,8 +54,8 @@ |
642 | Gtk.Allocation allocation; |
643 | get_allocation (out allocation); |
644 | |
645 | - DashBox.cairo_rounded_rectangle (c, 0, 0, allocation.width, |
646 | - allocation.height, 0.1 * grid_size); |
647 | + CairoUtils.rounded_rectangle (c, 0, 0, allocation.width, |
648 | + allocation.height, 0.1 * grid_size); |
649 | c.set_source_rgba (0.5, 0.5, 0.5, 0.5); |
650 | c.set_line_width (1); |
651 | c.stroke (); |
This was in my too-hard-basket :) Works well here!