~mniess/ubuntu/trusty/totem/fix-lp1292262

« back to all changes in this revision

Viewing changes to src/gsd-osd-window.c

  • Committer: Bazaar Package Importer
  • Author(s): Raphaël Hertzog
  • Date: 2011-04-10 18:12:25 UTC
  • mfrom: (1.1.14 upstream)
  • mto: (1.5.7 upstream)
  • mto: This revision was merged to the branch mainline in revision 19.
  • Revision ID: james.westby@ubuntu.com-20110410181225-u3x8yhsscjoe8ony
Tags: upstream-3.0.0
Import upstream version 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * On-screen-display (OSD) window for gnome-settings-daemon's plugins
 
4
 *
 
5
 * Copyright (C) 2006-2007 William Jon McCann <mccann@jhu.edu> 
 
6
 * Copyright (C) 2009 Novell, Inc
 
7
 *
 
8
 * Authors:
 
9
 *   William Jon McCann <mccann@jhu.edu>
 
10
 *   Federico Mena-Quintero <federico@novell.com>
 
11
 *
 
12
 * This program is free software; you can redistribute it and/or
 
13
 * modify it under the terms of the GNU Lesser General Public
 
14
 * License as published by the Free Software Foundation; either
 
15
 * version 2, or (at your option) any later version.
 
16
 *
 
17
 * This program is distributed in the hope that it will be
 
18
 * useful, but WITHOUT ANY WARRANTY; without even the implied
 
19
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 
20
 * PURPOSE.  See the GNU Lesser General Public License for more
 
21
 * details.
 
22
 *
 
23
 * You should have received a copy of the GNU Lesser General
 
24
 * Public License along with this program; if not, write to the
 
25
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
26
 * Boston, MA 02111-1307, USA.
 
27
 *
 
28
 */
 
29
 
 
30
#include "config.h"
 
31
 
 
32
#include <stdlib.h>
 
33
#include <string.h>
 
34
#include <math.h>
 
35
#include <glib.h>
 
36
#include <glib/gi18n.h>
 
37
#include <gtk/gtk.h>
 
38
#include <gdk-pixbuf/gdk-pixbuf.h>
 
39
 
 
40
#include "gsd-osd-window.h"
 
41
 
 
42
#define DIALOG_TIMEOUT 2000     /* dialog timeout in ms */
 
43
#define DIALOG_FADE_TIMEOUT 1500 /* timeout before fade starts */
 
44
#define FADE_TIMEOUT 10        /* timeout in ms between each frame of the fade */
 
45
 
 
46
#define BG_ALPHA 0.75
 
47
 
 
48
#define GSD_OSD_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_OSD_WINDOW, GsdOsdWindowPrivate))
 
49
 
 
50
struct GsdOsdWindowPrivate
 
51
{
 
52
        guint                    is_composited : 1;
 
53
        guint                    hide_timeout_id;
 
54
        guint                    fade_timeout_id;
 
55
        double                   fade_out_alpha;
 
56
};
 
57
 
 
58
enum {
 
59
        DRAW_WHEN_COMPOSITED,
 
60
        LAST_SIGNAL
 
61
};
 
62
 
 
63
static guint signals[LAST_SIGNAL] = { 0 };
 
64
 
 
65
G_DEFINE_TYPE (GsdOsdWindow, gsd_osd_window, GTK_TYPE_WINDOW)
 
66
 
 
67
static gboolean
 
68
fade_timeout (GsdOsdWindow *window)
 
69
{
 
70
        if (window->priv->fade_out_alpha <= 0.0) {
 
71
                gtk_widget_hide (GTK_WIDGET (window));
 
72
 
 
73
                /* Reset it for the next time */
 
74
                window->priv->fade_out_alpha = 1.0;
 
75
                window->priv->fade_timeout_id = 0;
 
76
 
 
77
                return FALSE;
 
78
        } else {
 
79
                GdkRectangle rect;
 
80
                GtkWidget *win = GTK_WIDGET (window);
 
81
                GtkAllocation allocation;
 
82
 
 
83
                window->priv->fade_out_alpha -= 0.10;
 
84
 
 
85
                rect.x = 0;
 
86
                rect.y = 0;
 
87
                gtk_widget_get_allocation (win, &allocation);
 
88
                rect.width = allocation.width;
 
89
                rect.height = allocation.height;
 
90
 
 
91
                gtk_widget_realize (win);
 
92
                gdk_window_invalidate_rect (gtk_widget_get_window (win), &rect, FALSE);
 
93
        }
 
94
 
 
95
        return TRUE;
 
96
}
 
97
 
 
98
static gboolean
 
99
hide_timeout (GsdOsdWindow *window)
 
100
{
 
101
        if (window->priv->is_composited) {
 
102
                window->priv->hide_timeout_id = 0;
 
103
                window->priv->fade_timeout_id = g_timeout_add (FADE_TIMEOUT,
 
104
                                                               (GSourceFunc) fade_timeout,
 
105
                                                               window);
 
106
        } else {
 
107
                gtk_widget_hide (GTK_WIDGET (window));
 
108
        }
 
109
 
 
110
        return FALSE;
 
111
}
 
112
 
 
113
static void
 
114
remove_hide_timeout (GsdOsdWindow *window)
 
115
{
 
116
        if (window->priv->hide_timeout_id != 0) {
 
117
                g_source_remove (window->priv->hide_timeout_id);
 
118
                window->priv->hide_timeout_id = 0;
 
119
        }
 
120
 
 
121
        if (window->priv->fade_timeout_id != 0) {
 
122
                g_source_remove (window->priv->fade_timeout_id);
 
123
                window->priv->fade_timeout_id = 0;
 
124
                window->priv->fade_out_alpha = 1.0;
 
125
        }
 
126
}
 
127
 
 
128
static void
 
129
add_hide_timeout (GsdOsdWindow *window)
 
130
{
 
131
        int timeout;
 
132
 
 
133
        if (window->priv->is_composited) {
 
134
                timeout = DIALOG_FADE_TIMEOUT;
 
135
        } else {
 
136
                timeout = DIALOG_TIMEOUT;
 
137
        }
 
138
        window->priv->hide_timeout_id = g_timeout_add (timeout,
 
139
                                                       (GSourceFunc) hide_timeout,
 
140
                                                       window);
 
141
}
 
142
 
 
143
void
 
144
gsd_osd_window_draw_rounded_rectangle (cairo_t* cr,
 
145
                                       gdouble  aspect,
 
146
                                       gdouble  x,
 
147
                                       gdouble  y,
 
148
                                       gdouble  corner_radius,
 
149
                                       gdouble  width,
 
150
                                       gdouble  height)
 
151
{
 
152
        gdouble radius = corner_radius / aspect;
 
153
 
 
154
        cairo_move_to (cr, x + radius, y);
 
155
 
 
156
        cairo_line_to (cr,
 
157
                       x + width - radius,
 
158
                       y);
 
159
        cairo_arc (cr,
 
160
                   x + width - radius,
 
161
                   y + radius,
 
162
                   radius,
 
163
                   -90.0f * G_PI / 180.0f,
 
164
                   0.0f * G_PI / 180.0f);
 
165
        cairo_line_to (cr,
 
166
                       x + width,
 
167
                       y + height - radius);
 
168
        cairo_arc (cr,
 
169
                   x + width - radius,
 
170
                   y + height - radius,
 
171
                   radius,
 
172
                   0.0f * G_PI / 180.0f,
 
173
                   90.0f * G_PI / 180.0f);
 
174
        cairo_line_to (cr,
 
175
                       x + radius,
 
176
                       y + height);
 
177
        cairo_arc (cr,
 
178
                   x + radius,
 
179
                   y + height - radius,
 
180
                   radius,
 
181
                   90.0f * G_PI / 180.0f,
 
182
                   180.0f * G_PI / 180.0f);
 
183
        cairo_line_to (cr,
 
184
                       x,
 
185
                       y + radius);
 
186
        cairo_arc (cr,
 
187
                   x + radius,
 
188
                   y + radius,
 
189
                   radius,
 
190
                   180.0f * G_PI / 180.0f,
 
191
                   270.0f * G_PI / 180.0f);
 
192
        cairo_close_path (cr);
 
193
}
 
194
 
 
195
static void
 
196
rgb_to_hls (gdouble *r,
 
197
            gdouble *g,
 
198
            gdouble *b)
 
199
{
 
200
        gdouble min;
 
201
        gdouble max;
 
202
        gdouble red;
 
203
        gdouble green;
 
204
        gdouble blue;
 
205
        gdouble h, l, s;
 
206
        gdouble delta;
 
207
 
 
208
        red = *r;
 
209
        green = *g;
 
210
        blue = *b;
 
211
 
 
212
        if (red > green)
 
213
        {
 
214
                if (red > blue)
 
215
                        max = red;
 
216
                else
 
217
                        max = blue;
 
218
 
 
219
                if (green < blue)
 
220
                        min = green;
 
221
                else
 
222
                        min = blue;
 
223
        }
 
224
        else
 
225
        {
 
226
                if (green > blue)
 
227
                        max = green;
 
228
                else
 
229
                        max = blue;
 
230
 
 
231
                if (red < blue)
 
232
                        min = red;
 
233
                else
 
234
                        min = blue;
 
235
        }
 
236
 
 
237
        l = (max + min) / 2;
 
238
        s = 0;
 
239
        h = 0;
 
240
 
 
241
        if (max != min)
 
242
        {
 
243
                if (l <= 0.5)
 
244
                        s = (max - min) / (max + min);
 
245
                else
 
246
                        s = (max - min) / (2 - max - min);
 
247
 
 
248
                delta = max -min;
 
249
                if (red == max)
 
250
                        h = (green - blue) / delta;
 
251
                else if (green == max)
 
252
                        h = 2 + (blue - red) / delta;
 
253
                else if (blue == max)
 
254
                        h = 4 + (red - green) / delta;
 
255
 
 
256
                h *= 60;
 
257
                if (h < 0.0)
 
258
                        h += 360;
 
259
        }
 
260
 
 
261
        *r = h;
 
262
        *g = l;
 
263
        *b = s;
 
264
}
 
265
 
 
266
static void
 
267
hls_to_rgb (gdouble *h,
 
268
            gdouble *l,
 
269
            gdouble *s)
 
270
{
 
271
        gdouble hue;
 
272
        gdouble lightness;
 
273
        gdouble saturation;
 
274
        gdouble m1, m2;
 
275
        gdouble r, g, b;
 
276
 
 
277
        lightness = *l;
 
278
        saturation = *s;
 
279
 
 
280
        if (lightness <= 0.5)
 
281
                m2 = lightness * (1 + saturation);
 
282
        else
 
283
                m2 = lightness + saturation - lightness * saturation;
 
284
        m1 = 2 * lightness - m2;
 
285
 
 
286
        if (saturation == 0)
 
287
        {
 
288
                *h = lightness;
 
289
                *l = lightness;
 
290
                *s = lightness;
 
291
        }
 
292
        else
 
293
        {
 
294
                hue = *h + 120;
 
295
                while (hue > 360)
 
296
                        hue -= 360;
 
297
                while (hue < 0)
 
298
                        hue += 360;
 
299
 
 
300
                if (hue < 60)
 
301
                        r = m1 + (m2 - m1) * hue / 60;
 
302
                else if (hue < 180)
 
303
                        r = m2;
 
304
                else if (hue < 240)
 
305
                        r = m1 + (m2 - m1) * (240 - hue) / 60;
 
306
                else
 
307
                        r = m1;
 
308
 
 
309
                hue = *h;
 
310
                while (hue > 360)
 
311
                        hue -= 360;
 
312
                while (hue < 0)
 
313
                        hue += 360;
 
314
 
 
315
                if (hue < 60)
 
316
                        g = m1 + (m2 - m1) * hue / 60;
 
317
                else if (hue < 180)
 
318
                        g = m2;
 
319
                else if (hue < 240)
 
320
                        g = m1 + (m2 - m1) * (240 - hue) / 60;
 
321
                else
 
322
                        g = m1;
 
323
 
 
324
                hue = *h - 120;
 
325
                while (hue > 360)
 
326
                        hue -= 360;
 
327
                while (hue < 0)
 
328
                        hue += 360;
 
329
 
 
330
                if (hue < 60)
 
331
                        b = m1 + (m2 - m1) * hue / 60;
 
332
                else if (hue < 180)
 
333
                        b = m2;
 
334
                else if (hue < 240)
 
335
                        b = m1 + (m2 - m1) * (240 - hue) / 60;
 
336
                else
 
337
                        b = m1;
 
338
 
 
339
                *h = r;
 
340
                *l = g;
 
341
                *s = b;
 
342
        }
 
343
}
 
344
 
 
345
void
 
346
gsd_osd_window_color_shade (GdkRGBA *a,
 
347
                            gdouble   k)
 
348
{
 
349
        gdouble red;
 
350
        gdouble green;
 
351
        gdouble blue;
 
352
 
 
353
        red = a->red;
 
354
        green = a->green;
 
355
        blue = a->blue;
 
356
 
 
357
        rgb_to_hls (&red, &green, &blue);
 
358
 
 
359
        green *= k;
 
360
        if (green > 1.0)
 
361
                green = 1.0;
 
362
        else if (green < 0.0)
 
363
                green = 0.0;
 
364
 
 
365
        blue *= k;
 
366
        if (blue > 1.0)
 
367
                blue = 1.0;
 
368
        else if (blue < 0.0)
 
369
                blue = 0.0;
 
370
 
 
371
        hls_to_rgb (&red, &green, &blue);
 
372
 
 
373
        a->red = red;
 
374
        a->green = green;
 
375
        a->blue = blue;
 
376
}
 
377
 
 
378
 
 
379
void
 
380
gsd_osd_window_color_reverse (GdkRGBA *a)
 
381
{
 
382
        gdouble red;
 
383
        gdouble green;
 
384
        gdouble blue;
 
385
        gdouble h;
 
386
        gdouble s;
 
387
        gdouble v;
 
388
 
 
389
        red = a->red;
 
390
        green = a->green;
 
391
        blue = a->blue;
 
392
 
 
393
        gtk_rgb_to_hsv (red, green, blue, &h, &s, &v);
 
394
 
 
395
        v = 0.5 + (0.5 - v);
 
396
        if (v > 1.0)
 
397
                v = 1.0;
 
398
        else if (v < 0.0)
 
399
                v = 0.0;
 
400
 
 
401
        gtk_hsv_to_rgb (h, s, v, &red, &green, &blue);
 
402
 
 
403
        a->red = red;
 
404
        a->green = green;
 
405
        a->blue = blue;
 
406
}
 
407
 
 
408
/* This is our draw handler when the window is in a compositing manager.
 
409
 * We draw everything by hand, using Cairo, so that we can have a nice
 
410
 * transparent/rounded look.
 
411
 */
 
412
static void
 
413
draw_when_composited (GtkWidget *widget, cairo_t *orig_cr)
 
414
{
 
415
        GsdOsdWindow    *window;
 
416
        cairo_t         *cr;
 
417
        cairo_surface_t *surface;
 
418
        int              width;
 
419
        int              height;
 
420
        GtkStyleContext *context;
 
421
        GdkRGBA          acolor;
 
422
 
 
423
        window = GSD_OSD_WINDOW (widget);
 
424
 
 
425
        context = gtk_widget_get_style_context (widget);
 
426
        cairo_set_operator (orig_cr, CAIRO_OPERATOR_SOURCE);
 
427
        gtk_window_get_size (GTK_WINDOW (widget), &width, &height);
 
428
 
 
429
        surface = cairo_surface_create_similar (cairo_get_target (orig_cr),
 
430
                                                CAIRO_CONTENT_COLOR_ALPHA,
 
431
                                                width,
 
432
                                                height);
 
433
 
 
434
        if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) {
 
435
                goto done;
 
436
        }
 
437
 
 
438
        cr = cairo_create (surface);
 
439
        if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
 
440
                goto done;
 
441
        }
 
442
        cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0);
 
443
        cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
 
444
        cairo_paint (cr);
 
445
 
 
446
        /* draw a box */
 
447
        gsd_osd_window_draw_rounded_rectangle (cr, 1.0, 0.5, 0.5, height / 10, width-1, height-1);
 
448
        gtk_style_context_get_background_color (context, GTK_STATE_NORMAL, &acolor);
 
449
        gsd_osd_window_color_reverse (&acolor);
 
450
        acolor.alpha = BG_ALPHA;
 
451
        gdk_cairo_set_source_rgba (cr, &acolor);
 
452
        cairo_fill_preserve (cr);
 
453
 
 
454
        /* FIXME use &style->text_aa[GTK_STATE_NORMAL] instead? */
 
455
        gtk_style_context_get_color (context, GTK_STATE_NORMAL, &acolor);
 
456
        gsd_osd_window_color_reverse (&acolor);
 
457
        acolor.alpha = BG_ALPHA / 2;
 
458
        gdk_cairo_set_source_rgba (cr, &acolor);
 
459
        cairo_set_line_width (cr, 1);
 
460
        cairo_stroke (cr);
 
461
 
 
462
        g_signal_emit (window, signals[DRAW_WHEN_COMPOSITED], 0, cr);
 
463
 
 
464
        cairo_destroy (cr);
 
465
 
 
466
        /* Make sure we have a transparent background */
 
467
        cairo_rectangle (orig_cr, 0, 0, width, height);
 
468
        cairo_set_source_rgba (orig_cr, 0.0, 0.0, 0.0, 0.0);
 
469
        cairo_fill (orig_cr);
 
470
 
 
471
        cairo_set_source_surface (orig_cr, surface, 0, 0);
 
472
        cairo_paint_with_alpha (orig_cr, window->priv->fade_out_alpha);
 
473
 
 
474
 done:
 
475
        if (surface != NULL) {
 
476
                cairo_surface_destroy (surface);
 
477
        }
 
478
}
 
479
 
 
480
/* This is our draw handler when the window is *not* in a compositing manager.
 
481
 * We just draw a rectangular frame by hand.  We do this with hardcoded drawing code,
 
482
 * instead of GtkFrame, to avoid changing the window's internal widget hierarchy:  in
 
483
 * either case (composited or non-composited), callers can assume that this works
 
484
 * identically to a GtkWindow without any intermediate widgetry.
 
485
 */
 
486
static void
 
487
draw_when_not_composited (GtkWidget *widget, cairo_t *cr)
 
488
{
 
489
        GtkStyleContext *context;
 
490
        int width;
 
491
        int height;
 
492
 
 
493
        width = gtk_widget_get_allocated_width (widget);
 
494
        height = gtk_widget_get_allocated_width (widget);
 
495
        context = gtk_widget_get_style_context (widget);
 
496
 
 
497
        gtk_style_context_set_state (context, GTK_STATE_FLAG_ACTIVE);
 
498
        gtk_render_frame (context,
 
499
                          cr,
 
500
                          0,
 
501
                          0,
 
502
                          width,
 
503
                          height);
 
504
}
 
505
 
 
506
static gboolean
 
507
gsd_osd_window_draw (GtkWidget *widget,
 
508
                     cairo_t   *cr)
 
509
{
 
510
        GsdOsdWindow *window;
 
511
        GtkWidget *child;
 
512
 
 
513
        window = GSD_OSD_WINDOW (widget);
 
514
 
 
515
        if (window->priv->is_composited)
 
516
                draw_when_composited (widget, cr);
 
517
        else
 
518
                draw_when_not_composited (widget, cr);
 
519
 
 
520
        child = gtk_bin_get_child (GTK_BIN (window));
 
521
        if (child)
 
522
                gtk_container_propagate_draw (GTK_CONTAINER (window), child, cr);
 
523
 
 
524
        return FALSE;
 
525
}
 
526
 
 
527
static void
 
528
gsd_osd_window_real_show (GtkWidget *widget)
 
529
{
 
530
        GsdOsdWindow *window;
 
531
 
 
532
        if (GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->show) {
 
533
                GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->show (widget);
 
534
        }
 
535
 
 
536
        window = GSD_OSD_WINDOW (widget);
 
537
        remove_hide_timeout (window);
 
538
        add_hide_timeout (window);
 
539
}
 
540
 
 
541
static void
 
542
gsd_osd_window_real_hide (GtkWidget *widget)
 
543
{
 
544
        GsdOsdWindow *window;
 
545
 
 
546
        if (GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->hide) {
 
547
                GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->hide (widget);
 
548
        }
 
549
 
 
550
        window = GSD_OSD_WINDOW (widget);
 
551
        remove_hide_timeout (window);
 
552
}
 
553
 
 
554
static void
 
555
gsd_osd_window_real_realize (GtkWidget *widget)
 
556
{
 
557
        cairo_region_t *region;
 
558
        GdkScreen *screen;
 
559
        GdkVisual *visual;
 
560
 
 
561
        screen = gtk_widget_get_screen (widget);
 
562
        visual = gdk_screen_get_rgba_visual (screen);
 
563
        if (visual == NULL) {
 
564
                visual = gdk_screen_get_system_visual (screen);
 
565
        }
 
566
 
 
567
        gtk_widget_set_visual (widget, visual);
 
568
 
 
569
        if (GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->realize) {
 
570
                GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->realize (widget);
 
571
        }
 
572
 
 
573
        /* make the whole window ignore events */
 
574
        region = cairo_region_create ();
 
575
        gtk_widget_input_shape_combine_region (widget, region);
 
576
        cairo_region_destroy (region);
 
577
}
 
578
 
 
579
static void
 
580
gsd_osd_window_style_updated (GtkWidget *widget)
 
581
{
 
582
        GtkStyleContext *context;
 
583
        GtkBorder padding;
 
584
 
 
585
        GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->style_updated (widget);
 
586
 
 
587
        /* We set our border width to 12 (per the GNOME standard), plus the
 
588
         * thickness of the frame that we draw in our draw handler.  This will
 
589
         * make our child be 12 pixels away from the frame.
 
590
         */
 
591
 
 
592
        context = gtk_widget_get_style_context (widget);
 
593
        gtk_style_context_get_padding (context, GTK_STATE_NORMAL, &padding);
 
594
        gtk_container_set_border_width (GTK_CONTAINER (widget), 12 + MAX (padding.left, padding.top));
 
595
}
 
596
 
 
597
static void
 
598
gsd_osd_window_get_preferred_width (GtkWidget *widget,
 
599
                                    gint      *minimum,
 
600
                                    gint      *natural)
 
601
{
 
602
        GtkStyleContext *context;
 
603
        GtkBorder padding;
 
604
 
 
605
        GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->get_preferred_width (widget, minimum, natural);
 
606
 
 
607
        /* See the comment in gsd_osd_window_style_updated() for why we add the padding here */
 
608
 
 
609
        context = gtk_widget_get_style_context (widget);
 
610
        gtk_style_context_get_padding (context, GTK_STATE_NORMAL, &padding);
 
611
 
 
612
        *minimum += padding.left;
 
613
        *natural += padding.left;
 
614
}
 
615
 
 
616
static void
 
617
gsd_osd_window_get_preferred_height (GtkWidget *widget,
 
618
                                     gint      *minimum,
 
619
                                     gint      *natural)
 
620
{
 
621
        GtkStyleContext *context;
 
622
        GtkBorder padding;
 
623
 
 
624
        GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->get_preferred_height (widget, minimum, natural);
 
625
 
 
626
        /* See the comment in gsd_osd_window_style_updated() for why we add the padding here */
 
627
 
 
628
        context = gtk_widget_get_style_context (widget);
 
629
        gtk_style_context_get_padding (context, GTK_STATE_NORMAL, &padding);
 
630
 
 
631
        *minimum += padding.top;
 
632
        *natural += padding.top;
 
633
}
 
634
 
 
635
static GObject *
 
636
gsd_osd_window_constructor (GType                  type,
 
637
                            guint                  n_construct_properties,
 
638
                            GObjectConstructParam *construct_params)
 
639
{
 
640
        GObject *object;
 
641
 
 
642
        object = G_OBJECT_CLASS (gsd_osd_window_parent_class)->constructor (type, n_construct_properties, construct_params);
 
643
 
 
644
        g_object_set (object,
 
645
                      "type", GTK_WINDOW_POPUP,
 
646
                      "type-hint", GDK_WINDOW_TYPE_HINT_NOTIFICATION,
 
647
                      "skip-taskbar-hint", TRUE,
 
648
                      "skip-pager-hint", TRUE,
 
649
                      "focus-on-map", FALSE,
 
650
                      NULL);
 
651
 
 
652
        return object;
 
653
}
 
654
 
 
655
static void
 
656
gsd_osd_window_class_init (GsdOsdWindowClass *klass)
 
657
{
 
658
        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
659
        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
660
 
 
661
        gobject_class->constructor = gsd_osd_window_constructor;
 
662
 
 
663
        widget_class->show = gsd_osd_window_real_show;
 
664
        widget_class->hide = gsd_osd_window_real_hide;
 
665
        widget_class->realize = gsd_osd_window_real_realize;
 
666
        widget_class->style_updated = gsd_osd_window_style_updated;
 
667
        widget_class->get_preferred_width = gsd_osd_window_get_preferred_width;
 
668
        widget_class->get_preferred_height = gsd_osd_window_get_preferred_height;
 
669
        widget_class->draw = gsd_osd_window_draw;
 
670
 
 
671
        signals[DRAW_WHEN_COMPOSITED] = g_signal_new ("draw-when-composited",
 
672
                                                      G_TYPE_FROM_CLASS (gobject_class),
 
673
                                                      G_SIGNAL_RUN_FIRST,
 
674
                                                      G_STRUCT_OFFSET (GsdOsdWindowClass, draw_when_composited),
 
675
                                                      NULL, NULL,
 
676
                                                      g_cclosure_marshal_VOID__POINTER,
 
677
                                                      G_TYPE_NONE, 1,
 
678
                                                      G_TYPE_POINTER);
 
679
 
 
680
        g_type_class_add_private (klass, sizeof (GsdOsdWindowPrivate));
 
681
}
 
682
 
 
683
/*
 
684
 * gsd_osd_window_is_composited:
 
685
 * @window: a #GsdOsdWindow
 
686
 *
 
687
 * Return value: whether the window was created on a composited screen.
 
688
 */
 
689
gboolean
 
690
gsd_osd_window_is_composited (GsdOsdWindow *window)
 
691
{
 
692
        return window->priv->is_composited;
 
693
}
 
694
 
 
695
/*
 
696
 * gsd_osd_window_is_valid:
 
697
 * @window: a #GsdOsdWindow
 
698
 *
 
699
 * Return value: TRUE if the @window's idea of being composited matches whether
 
700
 * its current screen is actually composited.
 
701
 */
 
702
gboolean
 
703
gsd_osd_window_is_valid (GsdOsdWindow *window)
 
704
{
 
705
        GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (window));
 
706
        return gdk_screen_is_composited (screen) == window->priv->is_composited;
 
707
}
 
708
 
 
709
static void
 
710
gsd_osd_window_init (GsdOsdWindow *window)
 
711
{
 
712
        GdkScreen *screen;
 
713
 
 
714
        window->priv = GSD_OSD_WINDOW_GET_PRIVATE (window);
 
715
 
 
716
        screen = gtk_widget_get_screen (GTK_WIDGET (window));
 
717
 
 
718
        window->priv->is_composited = gdk_screen_is_composited (screen);
 
719
 
 
720
        if (window->priv->is_composited) {
 
721
                gdouble scalew, scaleh, scale;
 
722
                gint size;
 
723
 
 
724
                gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
 
725
                gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
 
726
 
 
727
                /* assume 130x130 on a 640x480 display and scale from there */
 
728
                scalew = gdk_screen_get_width (screen) / 640.0;
 
729
                scaleh = gdk_screen_get_height (screen) / 480.0;
 
730
                scale = MIN (scalew, scaleh);
 
731
                size = 130 * MAX (1, scale);
 
732
 
 
733
                gtk_window_set_default_size (GTK_WINDOW (window), size, size);
 
734
 
 
735
                window->priv->fade_out_alpha = 1.0;
 
736
        } else {
 
737
                gtk_container_set_border_width (GTK_CONTAINER (window), 12);
 
738
        }
 
739
}
 
740
 
 
741
GtkWidget *
 
742
gsd_osd_window_new (void)
 
743
{
 
744
        return g_object_new (GSD_TYPE_OSD_WINDOW, NULL);
 
745
}
 
746
 
 
747
/**
 
748
 * gsd_osd_window_update_and_hide:
 
749
 * @window: a #GsdOsdWindow
 
750
 *
 
751
 * Queues the @window for immediate drawing, and queues a timer to hide the window.
 
752
 */
 
753
void
 
754
gsd_osd_window_update_and_hide (GsdOsdWindow *window)
 
755
{
 
756
        remove_hide_timeout (window);
 
757
        add_hide_timeout (window);
 
758
 
 
759
        if (window->priv->is_composited) {
 
760
                gtk_widget_queue_draw (GTK_WIDGET (window));
 
761
        }
 
762
}