~noskcaj/ubuntu/trusty/xfce4-power-manager/systemd

« back to all changes in this revision

Viewing changes to .pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/gsd-media-keys-window.c

  • Committer: Package Import Robot
  • Author(s): Jackson Doak
  • Date: 2013-08-13 06:56:35 UTC
  • mfrom: (6.2.13 sid)
  • Revision ID: package-import@ubuntu.com-20130813065635-gu2mh06aw8n2id6w
Tags: 1.2.0-2ubuntu1
* Merged from debian unstable. Remaining changes:
  - 06_fix-suspend-auth-check.patch: added, correctly check for suspend
    permissions before disabling the corresponding drop-down menu item.
    lp #929537
  - 08_show_preferences_lxde.patch: Hide settings menu only on desktop
    environment which have another power manager.
  - xubuntu_fix-status-icon-other-devices.patch: fix broken status icons
    for other devices (phone, wireless kbd, mouse, etc.).
  - Switch to using logind for session tracking. Depend on systemd-services
  instead of consolekit recommends, and add libsystemd-login-dev build
  dependency.

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
 * Copyright (C) 2006-2007 William Jon McCann <mccann@jhu.edu>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 *
 
19
 */
 
20
 
 
21
#include "config.h"
 
22
 
 
23
#include <stdlib.h>
 
24
#include <string.h>
 
25
#include <math.h>
 
26
#include <glib.h>
 
27
#include <glib/gi18n.h>
 
28
#include <gtk/gtk.h>
 
29
 
 
30
#include "gsd-media-keys-window.h"
 
31
 
 
32
#include "data/interfaces/acme_ui.h"
 
33
 
 
34
#define DIALOG_TIMEOUT 2000     /* dialog timeout in ms */
 
35
#define DIALOG_FADE_TIMEOUT 1500 /* timeout before fade starts */
 
36
#define FADE_TIMEOUT 10        /* timeout in ms between each frame of the fade */
 
37
 
 
38
#define BG_ALPHA 0.75
 
39
#define FG_ALPHA 1.00
 
40
 
 
41
#define GSD_MEDIA_KEYS_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_MEDIA_KEYS_WINDOW, GsdMediaKeysWindowPrivate))
 
42
 
 
43
struct GsdMediaKeysWindowPrivate
 
44
{
 
45
        guint                    is_composited : 1;
 
46
        guint                    hide_timeout_id;
 
47
        guint                    fade_timeout_id;
 
48
        double                   fade_out_alpha;
 
49
        GsdMediaKeysWindowAction action;
 
50
        char                    *icon_name;
 
51
        gboolean                 show_level;
 
52
 
 
53
        guint                    volume_muted : 1;
 
54
        int                      volume_level;
 
55
 
 
56
        GtkImage                *image;
 
57
        GtkWidget               *progress;
 
58
};
 
59
 
 
60
G_DEFINE_TYPE (GsdMediaKeysWindow, gsd_media_keys_window, GTK_TYPE_WINDOW)
 
61
 
 
62
static gboolean
 
63
fade_timeout (GsdMediaKeysWindow *window)
 
64
{
 
65
        if (window->priv->fade_out_alpha <= 0.0) {
 
66
                gtk_widget_hide (GTK_WIDGET (window));
 
67
 
 
68
                /* Reset it for the next time */
 
69
                window->priv->fade_out_alpha = 1.0;
 
70
                window->priv->fade_timeout_id = 0;
 
71
 
 
72
                return FALSE;
 
73
        } else {
 
74
                GdkRectangle rect;
 
75
                GtkWidget *win = GTK_WIDGET (window);
 
76
                GtkAllocation allocation;
 
77
 
 
78
                window->priv->fade_out_alpha -= 0.10;
 
79
 
 
80
                rect.x = 0;
 
81
                rect.y = 0;
 
82
                gtk_widget_get_allocation (win, &allocation);
 
83
                rect.width = allocation.width;
 
84
                rect.height = allocation.height;
 
85
 
 
86
                gtk_widget_realize (win);
 
87
                gdk_window_invalidate_rect (gtk_widget_get_window (win), &rect, FALSE);
 
88
        }
 
89
 
 
90
        return TRUE;
 
91
}
 
92
 
 
93
static gboolean
 
94
hide_timeout (GsdMediaKeysWindow *window)
 
95
{
 
96
        if (window->priv->is_composited) {
 
97
                window->priv->hide_timeout_id = 0;
 
98
                window->priv->fade_timeout_id = g_timeout_add (FADE_TIMEOUT,
 
99
                                                               (GSourceFunc) fade_timeout,
 
100
                                                               window);
 
101
        } else {
 
102
                gtk_widget_hide (GTK_WIDGET (window));
 
103
        }
 
104
 
 
105
        return FALSE;
 
106
}
 
107
 
 
108
static void
 
109
remove_hide_timeout (GsdMediaKeysWindow *window)
 
110
{
 
111
        if (window->priv->hide_timeout_id != 0) {
 
112
                g_source_remove (window->priv->hide_timeout_id);
 
113
                window->priv->hide_timeout_id = 0;
 
114
        }
 
115
 
 
116
        if (window->priv->fade_timeout_id != 0) {
 
117
                g_source_remove (window->priv->fade_timeout_id);
 
118
                window->priv->fade_timeout_id = 0;
 
119
                window->priv->fade_out_alpha = 1.0;
 
120
        }
 
121
}
 
122
 
 
123
static void
 
124
add_hide_timeout (GsdMediaKeysWindow *window)
 
125
{
 
126
        int timeout;
 
127
 
 
128
        if (window->priv->is_composited) {
 
129
                timeout = DIALOG_FADE_TIMEOUT;
 
130
        } else {
 
131
                timeout = DIALOG_TIMEOUT;
 
132
        }
 
133
        window->priv->hide_timeout_id = g_timeout_add (timeout,
 
134
                                                       (GSourceFunc) hide_timeout,
 
135
                                                       window);
 
136
}
 
137
 
 
138
static void
 
139
update_window (GsdMediaKeysWindow *window)
 
140
{
 
141
        remove_hide_timeout (window);
 
142
        add_hide_timeout (window);
 
143
 
 
144
        if (window->priv->is_composited) {
 
145
                gtk_widget_queue_draw (GTK_WIDGET (window));
 
146
        }
 
147
}
 
148
 
 
149
static void
 
150
volume_controls_set_visible (GsdMediaKeysWindow *window,
 
151
                             gboolean            visible)
 
152
{
 
153
        if (window->priv->progress == NULL)
 
154
                return;
 
155
 
 
156
        if (visible) {
 
157
                gtk_widget_show (window->priv->progress);
 
158
        } else {
 
159
                gtk_widget_hide (window->priv->progress);
 
160
        }
 
161
}
 
162
 
 
163
static void
 
164
window_set_icon_name (GsdMediaKeysWindow *window,
 
165
                      const char         *name)
 
166
{
 
167
        if (window->priv->image == NULL)
 
168
                return;
 
169
 
 
170
        gtk_image_set_from_icon_name (window->priv->image,
 
171
                                      name, GTK_ICON_SIZE_DIALOG);
 
172
}
 
173
 
 
174
static void
 
175
action_changed (GsdMediaKeysWindow *window)
 
176
{
 
177
        if (! window->priv->is_composited) {
 
178
                switch (window->priv->action) {
 
179
                case GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME:
 
180
                        volume_controls_set_visible (window, TRUE);
 
181
 
 
182
                        if (window->priv->volume_muted) {
 
183
                                window_set_icon_name (window, "audio-volume-muted");
 
184
                        } else {
 
185
                                window_set_icon_name (window, "audio-volume-high");
 
186
                        }
 
187
 
 
188
                        break;
 
189
                case GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM:
 
190
                        volume_controls_set_visible (window, window->priv->show_level);
 
191
                        window_set_icon_name (window, window->priv->icon_name);
 
192
                        break;
 
193
                default:
 
194
                        g_assert_not_reached ();
 
195
                        break;
 
196
                }
 
197
        }
 
198
 
 
199
        update_window (window);
 
200
}
 
201
 
 
202
static void
 
203
volume_level_changed (GsdMediaKeysWindow *window)
 
204
{
 
205
        update_window (window);
 
206
 
 
207
        if (!window->priv->is_composited && window->priv->progress != NULL) {
 
208
                double fraction;
 
209
 
 
210
                fraction = (double) window->priv->volume_level / 100.0;
 
211
 
 
212
                gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->priv->progress),
 
213
                                               fraction);
 
214
        }
 
215
}
 
216
 
 
217
static void
 
218
volume_muted_changed (GsdMediaKeysWindow *window)
 
219
{
 
220
        update_window (window);
 
221
 
 
222
        if (! window->priv->is_composited) {
 
223
                if (window->priv->volume_muted) {
 
224
                        window_set_icon_name (window, "audio-volume-muted");
 
225
                } else {
 
226
                        window_set_icon_name (window, "audio-volume-high");
 
227
                }
 
228
        }
 
229
}
 
230
 
 
231
void
 
232
gsd_media_keys_window_set_action (GsdMediaKeysWindow      *window,
 
233
                                  GsdMediaKeysWindowAction action)
 
234
{
 
235
        g_return_if_fail (GSD_IS_MEDIA_KEYS_WINDOW (window));
 
236
        g_return_if_fail (action == GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME);
 
237
 
 
238
        if (window->priv->action != action) {
 
239
                window->priv->action = action;
 
240
                action_changed (window);
 
241
        } else {
 
242
                update_window (window);
 
243
        }
 
244
}
 
245
 
 
246
void
 
247
gsd_media_keys_window_set_action_custom (GsdMediaKeysWindow      *window,
 
248
                                         const char              *icon_name,
 
249
                                         gboolean                 show_level)
 
250
{
 
251
        g_return_if_fail (GSD_IS_MEDIA_KEYS_WINDOW (window));
 
252
        g_return_if_fail (icon_name != NULL);
 
253
 
 
254
        if (window->priv->action != GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM ||
 
255
            g_strcmp0 (window->priv->icon_name, icon_name) != 0 ||
 
256
            window->priv->show_level != show_level) {
 
257
                window->priv->action = GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM;
 
258
                g_free (window->priv->icon_name);
 
259
                window->priv->icon_name = g_strdup (icon_name);
 
260
                window->priv->show_level = show_level;
 
261
                action_changed (window);
 
262
        } else {
 
263
                update_window (window);
 
264
        }
 
265
}
 
266
 
 
267
void
 
268
gsd_media_keys_window_set_volume_muted (GsdMediaKeysWindow *window,
 
269
                                        gboolean            muted)
 
270
{
 
271
        g_return_if_fail (GSD_IS_MEDIA_KEYS_WINDOW (window));
 
272
 
 
273
        if (window->priv->volume_muted != muted) {
 
274
                window->priv->volume_muted = muted;
 
275
                volume_muted_changed (window);
 
276
        }
 
277
}
 
278
 
 
279
void
 
280
gsd_media_keys_window_set_volume_level (GsdMediaKeysWindow *window,
 
281
                                        int                 level)
 
282
{
 
283
        g_return_if_fail (GSD_IS_MEDIA_KEYS_WINDOW (window));
 
284
 
 
285
        if (window->priv->volume_level != level) {
 
286
                window->priv->volume_level = level;
 
287
                volume_level_changed (window);
 
288
        }
 
289
}
 
290
 
 
291
static void
 
292
rounded_rectangle (cairo_t* cr,
 
293
                   gdouble  aspect,
 
294
                   gdouble  x,
 
295
                   gdouble  y,
 
296
                   gdouble  corner_radius,
 
297
                   gdouble  width,
 
298
                   gdouble  height)
 
299
{
 
300
        gdouble radius = corner_radius / aspect;
 
301
 
 
302
        cairo_move_to (cr, x + radius, y);
 
303
 
 
304
        cairo_line_to (cr,
 
305
                       x + width - radius,
 
306
                       y);
 
307
        cairo_arc (cr,
 
308
                   x + width - radius,
 
309
                   y + radius,
 
310
                   radius,
 
311
                   -90.0f * G_PI / 180.0f,
 
312
                   0.0f * G_PI / 180.0f);
 
313
        cairo_line_to (cr,
 
314
                       x + width,
 
315
                       y + height - radius);
 
316
        cairo_arc (cr,
 
317
                   x + width - radius,
 
318
                   y + height - radius,
 
319
                   radius,
 
320
                   0.0f * G_PI / 180.0f,
 
321
                   90.0f * G_PI / 180.0f);
 
322
        cairo_line_to (cr,
 
323
                       x + radius,
 
324
                       y + height);
 
325
        cairo_arc (cr,
 
326
                   x + radius,
 
327
                   y + height - radius,
 
328
                   radius,
 
329
                   90.0f * G_PI / 180.0f,
 
330
                   180.0f * G_PI / 180.0f);
 
331
        cairo_line_to (cr,
 
332
                       x,
 
333
                       y + radius);
 
334
        cairo_arc (cr,
 
335
                   x + radius,
 
336
                   y + radius,
 
337
                   radius,
 
338
                   180.0f * G_PI / 180.0f,
 
339
                   270.0f * G_PI / 180.0f);
 
340
        cairo_close_path (cr);
 
341
}
 
342
 
 
343
static GdkPixbuf *
 
344
load_pixbuf (GsdMediaKeysWindow *window,
 
345
             const char         *name,
 
346
             int                 icon_size)
 
347
{
 
348
        GtkIconTheme *theme;
 
349
        GdkPixbuf    *pixbuf;
 
350
 
 
351
        if (window != NULL && gtk_widget_has_screen (GTK_WIDGET (window))) {
 
352
                theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
 
353
        } else {
 
354
                theme = gtk_icon_theme_get_default ();
 
355
        }
 
356
 
 
357
        pixbuf = gtk_icon_theme_load_icon (theme,
 
358
                                           name,
 
359
                                           icon_size,
 
360
                                           GTK_ICON_LOOKUP_FORCE_SVG,
 
361
                                           NULL);
 
362
 
 
363
        /* make sure the pixbuf is close to the requested size
 
364
         * this is necessary because GTK_ICON_LOOKUP_FORCE_SVG
 
365
         * seems to be broken */
 
366
        if (pixbuf != NULL) {
 
367
                int width;
 
368
 
 
369
                width = gdk_pixbuf_get_width (pixbuf);
 
370
                if (width < (float)icon_size * 0.75) {
 
371
                        g_object_unref (pixbuf);
 
372
                        pixbuf = NULL;
 
373
                }
 
374
        }
 
375
 
 
376
        return pixbuf;
 
377
}
 
378
 
 
379
static void
 
380
draw_eject (cairo_t *cr,
 
381
            double   _x0,
 
382
            double   _y0,
 
383
            double   width,
 
384
            double   height)
 
385
{
 
386
        int box_height;
 
387
        int tri_height;
 
388
        int separation;
 
389
 
 
390
        box_height = height * 0.2;
 
391
        separation = box_height / 3;
 
392
        tri_height = height - box_height - separation;
 
393
 
 
394
        cairo_rectangle (cr, _x0, _y0 + height - box_height, width, box_height);
 
395
 
 
396
        cairo_move_to (cr, _x0, _y0 + tri_height);
 
397
        cairo_rel_line_to (cr, width, 0);
 
398
        cairo_rel_line_to (cr, -width / 2, -tri_height);
 
399
        cairo_rel_line_to (cr, -width / 2, tri_height);
 
400
        cairo_close_path (cr);
 
401
        cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, FG_ALPHA);
 
402
        cairo_fill_preserve (cr);
 
403
 
 
404
        cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, FG_ALPHA / 2);
 
405
        cairo_set_line_width (cr, 2);
 
406
        cairo_stroke (cr);
 
407
}
 
408
 
 
409
static void
 
410
draw_waves (cairo_t *cr,
 
411
            double   cx,
 
412
            double   cy,
 
413
            double   max_radius,
 
414
            int      volume_level)
 
415
{
 
416
        const int n_waves = 3;
 
417
        int last_wave;
 
418
        int i;
 
419
 
 
420
        last_wave = n_waves * volume_level / 100;
 
421
 
 
422
        for (i = 0; i < n_waves; i++) {
 
423
                double angle1;
 
424
                double angle2;
 
425
                double radius;
 
426
                double alpha;
 
427
 
 
428
                angle1 = -M_PI / 4;
 
429
                angle2 = M_PI / 4;
 
430
 
 
431
                if (i < last_wave)
 
432
                        alpha = 1.0;
 
433
                else if (i > last_wave)
 
434
                        alpha = 0.1;
 
435
                else alpha = 0.1 + 0.9 * (n_waves * volume_level % 100) / 100.0;
 
436
 
 
437
                radius = (i + 1) * (max_radius / n_waves);
 
438
                cairo_arc (cr, cx, cy, radius, angle1, angle2);
 
439
                cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, alpha / 2);
 
440
                cairo_set_line_width (cr, 14);
 
441
                cairo_set_line_cap  (cr, CAIRO_LINE_CAP_ROUND);
 
442
                cairo_stroke_preserve (cr);
 
443
 
 
444
                cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, alpha);
 
445
                cairo_set_line_width (cr, 10);
 
446
                cairo_set_line_cap  (cr, CAIRO_LINE_CAP_ROUND);
 
447
                cairo_stroke (cr);
 
448
        }
 
449
}
 
450
 
 
451
static void
 
452
draw_cross (cairo_t *cr,
 
453
            double   cx,
 
454
            double   cy,
 
455
            double   size)
 
456
{
 
457
        cairo_move_to (cr, cx, cy - size/2.0);
 
458
        cairo_rel_line_to (cr, size, size);
 
459
 
 
460
        cairo_move_to (cr, cx, cy + size/2.0);
 
461
        cairo_rel_line_to (cr, size, -size);
 
462
 
 
463
        cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, FG_ALPHA / 2);
 
464
        cairo_set_line_width (cr, 14);
 
465
        cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
 
466
        cairo_stroke_preserve (cr);
 
467
 
 
468
        cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, FG_ALPHA);
 
469
        cairo_set_line_width (cr, 10);
 
470
        cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
 
471
        cairo_stroke (cr);
 
472
}
 
473
 
 
474
static void
 
475
draw_speaker (cairo_t *cr,
 
476
              double   cx,
 
477
              double   cy,
 
478
              double   width,
 
479
              double   height)
 
480
{
 
481
        double box_width;
 
482
        double box_height;
 
483
        double _x0;
 
484
        double _y0;
 
485
 
 
486
        box_width = width / 3;
 
487
        box_height = height / 3;
 
488
 
 
489
        _x0 = cx - (width / 2) + box_width;
 
490
        _y0 = cy - box_height / 2;
 
491
 
 
492
        cairo_move_to (cr, _x0, _y0);
 
493
        cairo_rel_line_to (cr, - box_width, 0);
 
494
        cairo_rel_line_to (cr, 0, box_height);
 
495
        cairo_rel_line_to (cr, box_width, 0);
 
496
 
 
497
        cairo_line_to (cr, cx + box_width, cy + height / 2);
 
498
        cairo_rel_line_to (cr, 0, -height);
 
499
        cairo_line_to (cr, _x0, _y0);
 
500
        cairo_close_path (cr);
 
501
 
 
502
        cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, FG_ALPHA);
 
503
        cairo_fill_preserve (cr);
 
504
 
 
505
        cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, FG_ALPHA / 2);
 
506
        cairo_set_line_width (cr, 2);
 
507
        cairo_stroke (cr);
 
508
}
 
509
 
 
510
static gboolean
 
511
render_speaker (GsdMediaKeysWindow *window,
 
512
                cairo_t            *cr,
 
513
                double              _x0,
 
514
                double              _y0,
 
515
                double              width,
 
516
                double              height)
 
517
{
 
518
        GdkPixbuf         *pixbuf;
 
519
        int                icon_size;
 
520
        int                n;
 
521
        static const char *icon_names[] = {
 
522
                "audio-volume-muted",
 
523
                "audio-volume-low",
 
524
                "audio-volume-medium",
 
525
                "audio-volume-high",
 
526
                NULL
 
527
        };
 
528
 
 
529
        if (window->priv->volume_muted) {
 
530
                n = 0;
 
531
        } else {
 
532
                /* select image */
 
533
                n = 3 * window->priv->volume_level / 100 + 1;
 
534
                if (n < 1) {
 
535
                        n = 1;
 
536
                } else if (n > 3) {
 
537
                        n = 3;
 
538
                }
 
539
        }
 
540
 
 
541
        icon_size = (int)width;
 
542
 
 
543
        pixbuf = load_pixbuf (window, icon_names[n], icon_size);
 
544
 
 
545
        if (pixbuf == NULL) {
 
546
                return FALSE;
 
547
        }
 
548
 
 
549
        gdk_cairo_set_source_pixbuf (cr, pixbuf, _x0, _y0);
 
550
        cairo_paint_with_alpha (cr, FG_ALPHA);
 
551
 
 
552
        g_object_unref (pixbuf);
 
553
 
 
554
        return TRUE;
 
555
}
 
556
 
 
557
static void
 
558
color_reverse (const GdkColor *a,
 
559
               GdkColor       *b)
 
560
{
 
561
        gdouble red;
 
562
        gdouble green;
 
563
        gdouble blue;
 
564
        gdouble h;
 
565
        gdouble s;
 
566
        gdouble v;
 
567
 
 
568
        red = (gdouble) a->red / 65535.0;
 
569
        green = (gdouble) a->green / 65535.0;
 
570
        blue = (gdouble) a->blue / 65535.0;
 
571
 
 
572
        gtk_rgb_to_hsv (red, green, blue, &h, &s, &v);
 
573
 
 
574
        v = 0.5 + (0.5 - v);
 
575
        if (v > 1.0)
 
576
                v = 1.0;
 
577
        else if (v < 0.0)
 
578
                v = 0.0;
 
579
 
 
580
        gtk_hsv_to_rgb (h, s, v, &red, &green, &blue);
 
581
 
 
582
        b->red = red * 65535.0;
 
583
        b->green = green * 65535.0;
 
584
        b->blue = blue * 65535.0;
 
585
}
 
586
 
 
587
static void
 
588
draw_volume_boxes (GsdMediaKeysWindow *window,
 
589
                   cairo_t            *cr,
 
590
                   double              percentage,
 
591
                   double              _x0,
 
592
                   double              _y0,
 
593
                   double              width,
 
594
                   double              height)
 
595
{
 
596
        gdouble   x1;
 
597
        GdkColor  color;
 
598
        double    r, g, b;
 
599
        GtkStyle *style;
 
600
 
 
601
        _x0 += 0.5;
 
602
        _y0 += 0.5;
 
603
        height = round (height) - 1;
 
604
        width = round (width) - 1;
 
605
        x1 = round ((width - 1) * percentage);
 
606
        style = gtk_widget_get_style (GTK_WIDGET (window));
 
607
 
 
608
        /* bar background */
 
609
        color_reverse (&style->dark[GTK_STATE_NORMAL], &color);
 
610
        r = (float)color.red / 65535.0;
 
611
        g = (float)color.green / 65535.0;
 
612
        b = (float)color.blue / 65535.0;
 
613
        rounded_rectangle (cr, 1.0, _x0, _y0, height / 6, width, height);
 
614
        cairo_set_source_rgba (cr, r, g, b, FG_ALPHA / 2);
 
615
        cairo_fill_preserve (cr);
 
616
 
 
617
        /* bar border */
 
618
        color_reverse (&style->light[GTK_STATE_NORMAL], &color);
 
619
        r = (float)color.red / 65535.0;
 
620
        g = (float)color.green / 65535.0;
 
621
        b = (float)color.blue / 65535.0;
 
622
        cairo_set_source_rgba (cr, r, g, b, FG_ALPHA / 2);
 
623
        cairo_set_line_width (cr, 1);
 
624
        cairo_stroke (cr);
 
625
 
 
626
        /* bar progress */
 
627
        if (percentage < 0.01)
 
628
                return;
 
629
        color = style->bg[GTK_STATE_NORMAL];
 
630
        r = (float)color.red / 65535.0;
 
631
        g = (float)color.green / 65535.0;
 
632
        b = (float)color.blue / 65535.0;
 
633
        rounded_rectangle (cr, 1.0, _x0 + 0.5, _y0 + 0.5, height / 6 - 0.5, x1, height - 1);
 
634
        cairo_set_source_rgba (cr, r, g, b, FG_ALPHA);
 
635
        cairo_fill (cr);
 
636
}
 
637
 
 
638
static void
 
639
draw_action_volume (GsdMediaKeysWindow *window,
 
640
                    cairo_t            *cr)
 
641
{
 
642
        int window_width;
 
643
        int window_height;
 
644
        double icon_box_width;
 
645
        double icon_box_height;
 
646
        double icon_box_x0;
 
647
        double icon_box_y0;
 
648
        double volume_box_x0;
 
649
        double volume_box_y0;
 
650
        double volume_box_width;
 
651
        double volume_box_height;
 
652
        gboolean res;
 
653
 
 
654
        gtk_window_get_size (GTK_WINDOW (window), &window_width, &window_height);
 
655
 
 
656
        icon_box_width = round (window_width * 0.65);
 
657
        icon_box_height = round (window_height * 0.65);
 
658
        volume_box_width = icon_box_width;
 
659
        volume_box_height = round (window_height * 0.05);
 
660
 
 
661
        icon_box_x0 = (window_width - icon_box_width) / 2;
 
662
        icon_box_y0 = (window_height - icon_box_height - volume_box_height) / 2;
 
663
        volume_box_x0 = round (icon_box_x0);
 
664
        volume_box_y0 = round (icon_box_height + icon_box_y0);
 
665
 
 
666
#if 0
 
667
        g_message ("icon box: w=%f h=%f _x0=%f _y0=%f",
 
668
                   icon_box_width,
 
669
                   icon_box_height,
 
670
                   icon_box_x0,
 
671
                   icon_box_y0);
 
672
        g_message ("volume box: w=%f h=%f _x0=%f _y0=%f",
 
673
                   volume_box_width,
 
674
                   volume_box_height,
 
675
                   volume_box_x0,
 
676
                   volume_box_y0);
 
677
#endif
 
678
 
 
679
        res = render_speaker (window,
 
680
                              cr,
 
681
                              icon_box_x0, icon_box_y0,
 
682
                              icon_box_width, icon_box_height);
 
683
        if (! res) {
 
684
                double speaker_width;
 
685
                double speaker_height;
 
686
                double speaker_cx;
 
687
                double speaker_cy;
 
688
 
 
689
                speaker_width = icon_box_width * 0.5;
 
690
                speaker_height = icon_box_height * 0.75;
 
691
                speaker_cx = icon_box_x0 + speaker_width / 2;
 
692
                speaker_cy = icon_box_y0 + speaker_height / 2;
 
693
 
 
694
#if 0
 
695
                g_message ("speaker box: w=%f h=%f cx=%f cy=%f",
 
696
                           speaker_width,
 
697
                           speaker_height,
 
698
                           speaker_cx,
 
699
                           speaker_cy);
 
700
#endif
 
701
 
 
702
                /* draw speaker symbol */
 
703
                draw_speaker (cr, speaker_cx, speaker_cy, speaker_width, speaker_height);
 
704
 
 
705
                if (! window->priv->volume_muted) {
 
706
                        /* draw sound waves */
 
707
                        double wave_x0;
 
708
                        double wave_y0;
 
709
                        double wave_radius;
 
710
 
 
711
                        wave_x0 = window_width / 2;
 
712
                        wave_y0 = speaker_cy;
 
713
                        wave_radius = icon_box_width / 2;
 
714
 
 
715
                        draw_waves (cr, wave_x0, wave_y0, wave_radius, window->priv->volume_level);
 
716
                } else {
 
717
                        /* draw 'mute' cross */
 
718
                        double cross_x0;
 
719
                        double cross_y0;
 
720
                        double cross_size;
 
721
 
 
722
                        cross_size = speaker_width * 3 / 4;
 
723
                        cross_x0 = icon_box_x0 + icon_box_width - cross_size;
 
724
                        cross_y0 = speaker_cy;
 
725
 
 
726
                        draw_cross (cr, cross_x0, cross_y0, cross_size);
 
727
                }
 
728
        }
 
729
 
 
730
        /* draw volume meter */
 
731
        draw_volume_boxes (window,
 
732
                           cr,
 
733
                           (double)window->priv->volume_level / 100.0,
 
734
                           volume_box_x0,
 
735
                           volume_box_y0,
 
736
                           volume_box_width,
 
737
                           volume_box_height);
 
738
}
 
739
 
 
740
static gboolean
 
741
render_custom (GsdMediaKeysWindow *window,
 
742
               cairo_t            *cr,
 
743
               double              _x0,
 
744
               double              _y0,
 
745
               double              width,
 
746
               double              height)
 
747
{
 
748
        GdkPixbuf         *pixbuf;
 
749
        int                icon_size;
 
750
 
 
751
        icon_size = (int)width;
 
752
 
 
753
        pixbuf = load_pixbuf (window, window->priv->icon_name, icon_size);
 
754
 
 
755
        if (pixbuf == NULL) {
 
756
                char *name;
 
757
                if (gtk_widget_get_direction (GTK_WIDGET (window)) == GTK_TEXT_DIR_RTL)
 
758
                        name = g_strdup_printf ("%s-rtl", window->priv->icon_name);
 
759
                else
 
760
                        name = g_strdup_printf ("%s-ltr", window->priv->icon_name);
 
761
                pixbuf = load_pixbuf (window, name, icon_size);
 
762
                g_free (name);
 
763
                if (pixbuf == NULL)
 
764
                        return FALSE;
 
765
        }
 
766
 
 
767
        gdk_cairo_set_source_pixbuf (cr, pixbuf, _x0, _y0);
 
768
        cairo_paint_with_alpha (cr, FG_ALPHA);
 
769
 
 
770
        g_object_unref (pixbuf);
 
771
 
 
772
        return TRUE;
 
773
}
 
774
 
 
775
static void
 
776
draw_action_custom (GsdMediaKeysWindow *window,
 
777
                    cairo_t            *cr)
 
778
{
 
779
        int window_width;
 
780
        int window_height;
 
781
        double icon_box_width;
 
782
        double icon_box_height;
 
783
        double icon_box_x0;
 
784
        double icon_box_y0;
 
785
        double bright_box_x0;
 
786
        double bright_box_y0;
 
787
        double bright_box_width;
 
788
        double bright_box_height;
 
789
        gboolean res;
 
790
 
 
791
        gtk_window_get_size (GTK_WINDOW (window), &window_width, &window_height);
 
792
 
 
793
        icon_box_width = round (window_width * 0.65);
 
794
        icon_box_height = round (window_height * 0.65);
 
795
        bright_box_width = round (icon_box_width);
 
796
        bright_box_height = round (window_height * 0.05);
 
797
 
 
798
        icon_box_x0 = (window_width - icon_box_width) / 2;
 
799
        icon_box_y0 = (window_height - icon_box_height - bright_box_height) / 2;
 
800
        bright_box_x0 = round (icon_box_x0);
 
801
        bright_box_y0 = round (icon_box_height + icon_box_y0);
 
802
 
 
803
#if 0
 
804
        g_message ("icon box: w=%f h=%f _x0=%f _y0=%f",
 
805
                   icon_box_width,
 
806
                   icon_box_height,
 
807
                   icon_box_x0,
 
808
                   icon_box_y0);
 
809
        g_message ("brightness box: w=%f h=%f _x0=%f _y0=%f",
 
810
                   bright_box_width,
 
811
                   bright_box_height,
 
812
                   bright_box_x0,
 
813
                   bright_box_y0);
 
814
#endif
 
815
 
 
816
        res = render_custom (window,
 
817
                             cr,
 
818
                             icon_box_x0, icon_box_y0,
 
819
                             icon_box_width, icon_box_height);
 
820
        if (! res && g_strcmp0 (window->priv->icon_name, "media-eject") == 0) {
 
821
                /* draw eject symbol */
 
822
                draw_eject (cr,
 
823
                            icon_box_x0, icon_box_y0,
 
824
                            icon_box_width, icon_box_height);
 
825
        }
 
826
 
 
827
        if (window->priv->show_level != FALSE) {
 
828
                /* draw volume meter */
 
829
                draw_volume_boxes (window,
 
830
                                   cr,
 
831
                                   (double)window->priv->volume_level / 100.0,
 
832
                                   bright_box_x0,
 
833
                                   bright_box_y0,
 
834
                                   bright_box_width,
 
835
                                   bright_box_height);
 
836
        }
 
837
}
 
838
 
 
839
static void
 
840
draw_action (GsdMediaKeysWindow *window,
 
841
             cairo_t            *cr)
 
842
{
 
843
        switch (window->priv->action) {
 
844
        case GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME:
 
845
                draw_action_volume (window, cr);
 
846
                break;
 
847
        case GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM:
 
848
                draw_action_custom (window, cr);
 
849
                break;
 
850
        default:
 
851
                break;
 
852
        }
 
853
}
 
854
 
 
855
static gboolean
 
856
on_expose_event (GtkWidget          *widget,
 
857
                 GdkEventExpose     *event,
 
858
                 GsdMediaKeysWindow *window)
 
859
{
 
860
        cairo_t         *context;
 
861
        cairo_t         *cr;
 
862
        cairo_surface_t *surface;
 
863
        int              width;
 
864
        int              height;
 
865
        GtkStyle        *style;
 
866
        GdkColor         color;
 
867
        double           r, g, b;
 
868
 
 
869
        context = gdk_cairo_create (gtk_widget_get_window (widget));
 
870
 
 
871
        style = gtk_widget_get_style (widget);
 
872
        cairo_set_operator (context, CAIRO_OPERATOR_SOURCE);
 
873
        gtk_window_get_size (GTK_WINDOW (widget), &width, &height);
 
874
 
 
875
        surface = cairo_surface_create_similar (cairo_get_target (context),
 
876
                                                CAIRO_CONTENT_COLOR_ALPHA,
 
877
                                                width,
 
878
                                                height);
 
879
 
 
880
        if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) {
 
881
                goto done;
 
882
        }
 
883
 
 
884
        cr = cairo_create (surface);
 
885
        if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
 
886
                goto done;
 
887
        }
 
888
        cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0);
 
889
        cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
 
890
        cairo_paint (cr);
 
891
 
 
892
        /* draw a box */
 
893
        rounded_rectangle (cr, 1.0, 0.5, 0.5, height / 10, width-1, height-1);
 
894
        color_reverse (&style->bg[GTK_STATE_NORMAL], &color);
 
895
        r = (float)color.red / 65535.0;
 
896
        g = (float)color.green / 65535.0;
 
897
        b = (float)color.blue / 65535.0;
 
898
        cairo_set_source_rgba (cr, r, g, b, BG_ALPHA);
 
899
        cairo_fill_preserve (cr);
 
900
 
 
901
        color_reverse (&style->text_aa[GTK_STATE_NORMAL], &color);
 
902
        r = (float)color.red / 65535.0;
 
903
        g = (float)color.green / 65535.0;
 
904
        b = (float)color.blue / 65535.0;
 
905
        cairo_set_source_rgba (cr, r, g, b, BG_ALPHA / 2);
 
906
        cairo_set_line_width (cr, 1);
 
907
        cairo_stroke (cr);
 
908
 
 
909
        /* draw action */
 
910
        draw_action (window, cr);
 
911
 
 
912
        cairo_destroy (cr);
 
913
 
 
914
        /* Make sure we have a transparent background */
 
915
        cairo_rectangle (context, 0, 0, width, height);
 
916
        cairo_set_source_rgba (context, 0.0, 0.0, 0.0, 0.0);
 
917
        cairo_fill (context);
 
918
 
 
919
        cairo_set_source_surface (context, surface, 0, 0);
 
920
        cairo_paint_with_alpha (context, window->priv->fade_out_alpha);
 
921
 
 
922
 done:
 
923
        if (surface != NULL) {
 
924
                cairo_surface_destroy (surface);
 
925
        }
 
926
        cairo_destroy (context);
 
927
 
 
928
        return FALSE;
 
929
}
 
930
 
 
931
static void
 
932
gsd_media_keys_window_real_show (GtkWidget *widget)
 
933
{
 
934
        GsdMediaKeysWindow *window;
 
935
 
 
936
        if (GTK_WIDGET_CLASS (gsd_media_keys_window_parent_class)->show) {
 
937
                GTK_WIDGET_CLASS (gsd_media_keys_window_parent_class)->show (widget);
 
938
        }
 
939
 
 
940
        window = GSD_MEDIA_KEYS_WINDOW (widget);
 
941
        remove_hide_timeout (window);
 
942
        add_hide_timeout (window);
 
943
}
 
944
 
 
945
static void
 
946
gsd_media_keys_window_real_hide (GtkWidget *widget)
 
947
{
 
948
        GsdMediaKeysWindow *window;
 
949
 
 
950
        if (GTK_WIDGET_CLASS (gsd_media_keys_window_parent_class)->hide) {
 
951
                GTK_WIDGET_CLASS (gsd_media_keys_window_parent_class)->hide (widget);
 
952
        }
 
953
 
 
954
        window = GSD_MEDIA_KEYS_WINDOW (widget);
 
955
        remove_hide_timeout (window);
 
956
}
 
957
 
 
958
static void
 
959
gsd_media_keys_window_real_realize (GtkWidget *widget)
 
960
{
 
961
        GdkColormap *colormap;
 
962
        GtkAllocation allocation;
 
963
        GdkBitmap *mask;
 
964
        cairo_t *cr;
 
965
 
 
966
        colormap = gdk_screen_get_rgba_colormap (gtk_widget_get_screen (widget));
 
967
 
 
968
        if (colormap != NULL) {
 
969
                gtk_widget_set_colormap (widget, colormap);
 
970
        }
 
971
 
 
972
        if (GTK_WIDGET_CLASS (gsd_media_keys_window_parent_class)->realize) {
 
973
                GTK_WIDGET_CLASS (gsd_media_keys_window_parent_class)->realize (widget);
 
974
        }
 
975
 
 
976
        gtk_widget_get_allocation (widget, &allocation);
 
977
        mask = gdk_pixmap_new (gtk_widget_get_window (widget),
 
978
                               allocation.width,
 
979
                               allocation.height,
 
980
                               1);
 
981
        cr = gdk_cairo_create (mask);
 
982
 
 
983
        cairo_set_source_rgba (cr, 1., 1., 1., 0.);
 
984
        cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 
985
        cairo_paint (cr);
 
986
 
 
987
        /* make the whole window ignore events */
 
988
        gdk_window_input_shape_combine_mask (gtk_widget_get_window (widget), mask, 0, 0);
 
989
        g_object_unref (mask);
 
990
        cairo_destroy (cr);
 
991
}
 
992
 
 
993
static void
 
994
gsd_media_keys_window_class_init (GsdMediaKeysWindowClass *klass)
 
995
{
 
996
        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
997
 
 
998
        widget_class->show = gsd_media_keys_window_real_show;
 
999
        widget_class->hide = gsd_media_keys_window_real_hide;
 
1000
        widget_class->realize = gsd_media_keys_window_real_realize;
 
1001
 
 
1002
        g_type_class_add_private (klass, sizeof (GsdMediaKeysWindowPrivate));
 
1003
}
 
1004
 
 
1005
gboolean
 
1006
gsd_media_keys_window_is_valid (GsdMediaKeysWindow *window)
 
1007
{
 
1008
        GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (window));
 
1009
        return gdk_screen_is_composited (screen) == window->priv->is_composited;
 
1010
}
 
1011
 
 
1012
static void
 
1013
gsd_media_keys_window_init (GsdMediaKeysWindow *window)
 
1014
{
 
1015
        GdkScreen *screen;
 
1016
 
 
1017
        window->priv = GSD_MEDIA_KEYS_WINDOW_GET_PRIVATE (window);
 
1018
 
 
1019
        screen = gtk_widget_get_screen (GTK_WIDGET (window));
 
1020
 
 
1021
        window->priv->is_composited = gdk_screen_is_composited (screen);
 
1022
 
 
1023
        if (window->priv->is_composited) {
 
1024
                gdouble scalew, scaleh, scale;
 
1025
                gint size;
 
1026
 
 
1027
                gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
 
1028
                gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
 
1029
 
 
1030
                /* assume 130x130 on a 640x480 display and scale from there */
 
1031
                scalew = gdk_screen_get_width (screen) / 640.0;
 
1032
                scaleh = gdk_screen_get_height (screen) / 480.0;
 
1033
                scale = MIN (scalew, scaleh);
 
1034
                size = 130 * MAX (1, scale);
 
1035
 
 
1036
                gtk_window_set_default_size (GTK_WINDOW (window), size, size);
 
1037
                g_signal_connect (window, "expose-event", G_CALLBACK (on_expose_event), window);
 
1038
 
 
1039
                window->priv->fade_out_alpha = 1.0;
 
1040
        } else {
 
1041
                GtkBuilder *builder;
 
1042
                const gchar *objects[] = {"acme_frame", NULL};
 
1043
                GtkWidget *frame;
 
1044
 
 
1045
                builder = gtk_builder_new ();
 
1046
                gtk_builder_add_objects_from_string (builder, acme_ui, acme_ui_length, (char **)objects, NULL);
 
1047
 
 
1048
                window->priv->image = GTK_IMAGE (gtk_builder_get_object (builder, "acme_image"));
 
1049
                window->priv->progress = GTK_WIDGET (gtk_builder_get_object (builder, "acme_volume_progressbar"));
 
1050
                frame = GTK_WIDGET (gtk_builder_get_object (builder,
 
1051
                                                            "acme_frame"));
 
1052
 
 
1053
                if (frame != NULL) {
 
1054
                        gtk_container_add (GTK_CONTAINER (window), frame);
 
1055
                        gtk_widget_show_all (frame);
 
1056
                }
 
1057
 
 
1058
                /* The builder needs to stay alive until the window
 
1059
                   takes ownership of the frame (and its children)  */
 
1060
                g_object_unref (builder);
 
1061
        }
 
1062
}
 
1063
 
 
1064
GtkWidget *
 
1065
gsd_media_keys_window_new (void)
 
1066
{
 
1067
        GObject *object;
 
1068
 
 
1069
        object = g_object_new (GSD_TYPE_MEDIA_KEYS_WINDOW,
 
1070
                               "type", GTK_WINDOW_POPUP,
 
1071
                               "type-hint", GDK_WINDOW_TYPE_HINT_NOTIFICATION,
 
1072
                               "skip-taskbar-hint", TRUE,
 
1073
                               "skip-pager-hint", TRUE,
 
1074
                               "focus-on-map", FALSE,
 
1075
                               NULL);
 
1076
 
 
1077
        return GTK_WIDGET (object);
 
1078
}