~ubuntu-branches/ubuntu/saucy/totem/saucy

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Iain Lane
  • Date: 2012-11-29 17:11:44 UTC
  • mfrom: (1.11.16)
  • Revision ID: package-import@ubuntu.com-20121129171144-oboortekh89o15z5
Tags: 3.6.3-0ubuntu1
* New upstream release
  - Really stop using the soundpitch plugin
  - Fix playback of some audio types failing
* Add patch to use scaletempo from -good (this is an Ubuntu-local patch as
  this move has not yet happened in upstream gstreamer). Remove gstreamer
  -bad BD and dep accordingly.
* Remove Grilo until MIRed

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
 
}