1 /* Volume Button / popup widget
2 * (c) copyright 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
28 #include <glib/gi18n.h>
30 #include <gdk/gdkkeysyms.h>
31 #include "bacon-volume.h"
33 #define SCALE_SIZE 100
34 #define CLICK_TIMEOUT 250
41 static void bacon_volume_button_class_init (BaconVolumeButtonClass
* klass
);
42 static void bacon_volume_button_init (BaconVolumeButton
* button
);
43 static void bacon_volume_button_dispose (GObject
* object
);
45 static gboolean
bacon_volume_button_scroll (GtkWidget
* widget
,
46 GdkEventScroll
* event
);
47 static gboolean
bacon_volume_button_press (GtkWidget
* widget
,
48 GdkEventButton
* event
);
49 static gboolean
bacon_volume_key_release (GtkWidget
* widget
,
51 static void bacon_volume_button_style_set (GtkWidget
*widget
,
52 GtkStyle
*previous_style
);
53 static gboolean
cb_dock_button_press (GtkWidget
* widget
,
54 GdkEventButton
* event
,
56 static gboolean
cb_dock_key_release (GtkWidget
* widget
,
59 static gboolean
cb_dock_key_press (GtkWidget
* widget
,
63 static gboolean
cb_button_press (GtkWidget
* widget
,
64 GdkEventButton
* event
,
66 static gboolean
cb_button_release (GtkWidget
* widget
,
67 GdkEventButton
* event
,
69 static void bacon_volume_button_update_icon (BaconVolumeButton
*button
);
70 static void bacon_volume_scale_value_changed(GtkRange
* range
);
71 static void bacon_volume_button_load_icons (GtkWidget
* widget
);
73 /* see below for scale definitions */
74 static GtkWidget
*bacon_volume_scale_new (BaconVolumeButton
* button
,
78 static GtkButtonClass
*parent_class
= NULL
;
79 static guint signals
[NUM_SIGNALS
] = { 0 };
82 bacon_volume_button_get_type (void)
84 static GType bacon_volume_button_type
= 0;
86 if (G_UNLIKELY (bacon_volume_button_type
== 0)) {
87 const GTypeInfo bacon_volume_button_info
= {
88 sizeof (BaconVolumeButtonClass
),
91 (GClassInitFunc
) bacon_volume_button_class_init
,
94 sizeof (BaconVolumeButton
),
96 (GInstanceInitFunc
) bacon_volume_button_init
,
100 bacon_volume_button_type
=
101 g_type_register_static (GTK_TYPE_BUTTON
,
103 &bacon_volume_button_info
, 0);
106 return bacon_volume_button_type
;
110 bacon_volume_button_class_init (BaconVolumeButtonClass
*klass
)
112 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
113 GtkWidgetClass
*gtkwidget_class
= GTK_WIDGET_CLASS (klass
);
115 parent_class
= g_type_class_peek_parent (klass
);
118 gobject_class
->dispose
= bacon_volume_button_dispose
;
119 gtkwidget_class
->button_press_event
= bacon_volume_button_press
;
120 gtkwidget_class
->key_release_event
= bacon_volume_key_release
;
121 gtkwidget_class
->scroll_event
= bacon_volume_button_scroll
;
122 gtkwidget_class
->style_set
= bacon_volume_button_style_set
;
125 signals
[SIGNAL_VALUE_CHANGED
] = g_signal_new ("value-changed",
126 G_TYPE_FROM_CLASS (klass
), G_SIGNAL_RUN_LAST
,
127 G_STRUCT_OFFSET (BaconVolumeButtonClass
, value_changed
),
128 NULL
, NULL
, g_cclosure_marshal_VOID__VOID
, G_TYPE_NONE
, 0);
132 bacon_volume_button_init (BaconVolumeButton
*button
)
134 button
->timeout
= FALSE
;
135 button
->click_id
= 0;
136 button
->dock
= button
->scale
= NULL
;
140 bacon_volume_button_dispose (GObject
*object
)
142 BaconVolumeButton
*button
= BACON_VOLUME_BUTTON (object
);
146 gtk_widget_destroy (button
->dock
);
150 if (button
->click_id
!= 0) {
151 g_source_remove (button
->click_id
);
152 button
->click_id
= 0;
154 for (i
= 0; i
< 4; i
++) {
155 if (button
->icon
[i
] != NULL
) {
156 g_object_unref (button
->icon
[i
]);
157 button
->icon
[i
] = NULL
;
161 G_OBJECT_CLASS (parent_class
)->dispose (object
);
169 bacon_volume_button_new (GtkIconSize size
,
170 float min
, float max
,
173 BaconVolumeButton
*button
;
174 GtkWidget
*frame
, *box
;
176 button
= g_object_new (BACON_TYPE_VOLUME_BUTTON
, NULL
);
177 atk_object_set_name (gtk_widget_get_accessible (GTK_WIDGET (button
)),
180 gtk_button_set_relief (GTK_BUTTON (button
), GTK_RELIEF_NONE
);
181 gtk_button_set_focus_on_click (GTK_BUTTON (button
), FALSE
);
184 button
->image
= gtk_image_new ();
185 gtk_container_add (GTK_CONTAINER (button
), button
->image
);
186 gtk_widget_show_all (button
->image
);
189 button
->dock
= gtk_window_new (GTK_WINDOW_POPUP
);
190 g_signal_connect (button
->dock
, "button-press-event",
191 G_CALLBACK (cb_dock_button_press
), button
);
192 g_signal_connect (button
->dock
, "key-release-event",
193 G_CALLBACK (cb_dock_key_release
), button
);
194 g_signal_connect (button
->dock
, "key-press-event",
195 G_CALLBACK (cb_dock_key_press
), button
);
196 gtk_window_set_decorated (GTK_WINDOW (button
->dock
), FALSE
);
199 frame
= gtk_frame_new (NULL
);
200 gtk_frame_set_shadow_type (GTK_FRAME (frame
), GTK_SHADOW_OUT
);
201 gtk_container_add (GTK_CONTAINER (button
->dock
), frame
);
202 box
= gtk_vbox_new (FALSE
, 0);
203 gtk_container_add (GTK_CONTAINER (frame
), box
);
206 button
->plus
= gtk_button_new_with_label (_("+"));
207 atk_object_set_name (gtk_widget_get_accessible (button
->plus
),
209 gtk_button_set_relief (GTK_BUTTON (button
->plus
), GTK_RELIEF_NONE
);
210 g_signal_connect (button
->plus
, "button-press-event",
211 G_CALLBACK (cb_button_press
), button
);
212 g_signal_connect (button
->plus
, "button-release-event",
213 G_CALLBACK (cb_button_release
), button
);
214 gtk_box_pack_start (GTK_BOX (box
), button
->plus
, TRUE
, FALSE
, 0);
217 button
->scale
= bacon_volume_scale_new (button
, min
, max
, step
);
218 gtk_widget_set_size_request (button
->scale
, -1, SCALE_SIZE
);
219 gtk_scale_set_draw_value (GTK_SCALE (button
->scale
), FALSE
);
220 gtk_range_set_inverted (GTK_RANGE (button
->scale
), TRUE
);
221 gtk_box_pack_start (GTK_BOX (box
), button
->scale
, TRUE
, FALSE
, 0);
224 button
->min
= gtk_button_new_with_label (_("-"));
225 atk_object_set_name (gtk_widget_get_accessible (button
->min
),
227 gtk_button_set_relief (GTK_BUTTON (button
->min
), GTK_RELIEF_NONE
);
228 g_signal_connect (button
->min
, "button-press-event",
229 G_CALLBACK (cb_button_press
), button
);
230 g_signal_connect (button
->min
, "button-release-event",
231 G_CALLBACK (cb_button_release
), button
);
232 gtk_box_pack_start (GTK_BOX (box
), button
->min
, TRUE
, FALSE
, 0);
234 /* set button text */
235 bacon_volume_button_update_icon (button
);
237 return GTK_WIDGET (button
);
241 bacon_volume_button_get_value (BaconVolumeButton
* button
)
243 g_return_val_if_fail (button
!= NULL
, 0);
245 return gtk_range_get_value (GTK_RANGE (button
->scale
));
249 bacon_volume_button_set_value (BaconVolumeButton
* button
,
252 g_return_if_fail (button
!= NULL
);
254 gtk_range_set_value (GTK_RANGE (button
->scale
), value
);
262 bacon_volume_button_style_set (GtkWidget
*widget
,
263 GtkStyle
*previous_style
)
265 GTK_WIDGET_CLASS (parent_class
)->style_set (widget
, previous_style
);
267 bacon_volume_button_load_icons (widget
);
271 bacon_volume_button_scroll (GtkWidget
* widget
,
272 GdkEventScroll
* event
)
274 BaconVolumeButton
*button
= BACON_VOLUME_BUTTON (widget
);
275 GtkAdjustment
*adj
= gtk_range_get_adjustment (GTK_RANGE (button
->scale
));
278 if (event
->type
!= GDK_SCROLL
)
281 d
= bacon_volume_button_get_value (button
);
282 if (event
->direction
== GDK_SCROLL_UP
) {
283 d
+= adj
->step_increment
;
287 d
-= adj
->step_increment
;
291 bacon_volume_button_set_value (button
, d
);
297 bacon_volume_button_press (GtkWidget
* widget
,
298 GdkEventButton
* event
)
300 BaconVolumeButton
*button
= BACON_VOLUME_BUTTON (widget
);
301 GtkAdjustment
*adj
= gtk_range_get_adjustment (GTK_RANGE (button
->scale
));
302 gint x
, y
, m
, dx
, dy
, sx
, sy
, ystartoff
, mouse_y
;
308 display
= gtk_widget_get_display (widget
);
309 screen
= gtk_widget_get_screen (widget
);
311 /* position roughly */
312 gtk_window_set_screen (GTK_WINDOW (button
->dock
), screen
);
314 gdk_window_get_origin (widget
->window
, &x
, &y
);
315 x
+= widget
->allocation
.x
;
316 y
+= widget
->allocation
.y
;
317 gtk_window_move (GTK_WINDOW (button
->dock
), x
, y
- (SCALE_SIZE
/ 2));
318 gtk_widget_show_all (button
->dock
);
319 gdk_window_get_origin (button
->dock
->window
, &dx
, &dy
);
320 dy
+= button
->dock
->allocation
.y
;
321 gdk_window_get_origin (button
->scale
->window
, &sx
, &sy
);
322 sy
+= button
->scale
->allocation
.y
;
325 button
->timeout
= TRUE
;
327 /* position (needs widget to be shown already) */
328 v
= bacon_volume_button_get_value (button
) / (adj
->upper
- adj
->lower
);
329 x
+= (widget
->allocation
.width
- button
->dock
->allocation
.width
) / 2;
331 y
-= GTK_RANGE (button
->scale
)->min_slider_size
/ 2;
332 m
= button
->scale
->allocation
.height
-
333 GTK_RANGE (button
->scale
)->min_slider_size
;
336 gtk_window_move (GTK_WINDOW (button
->dock
), x
, y
);
337 gdk_window_get_origin (button
->scale
->window
, &sx
, &sy
);
339 GTK_WIDGET_CLASS (parent_class
)->button_press_event (widget
, event
);
342 gtk_grab_add (button
->dock
);
344 if (gdk_pointer_grab (button
->dock
->window
, TRUE
,
345 GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
|
346 GDK_POINTER_MOTION_MASK
, NULL
, NULL
, event
->time
)
347 != GDK_GRAB_SUCCESS
) {
348 gtk_grab_remove (button
->dock
);
349 gtk_widget_hide (button
->dock
);
353 if (gdk_keyboard_grab (button
->dock
->window
, TRUE
, event
->time
) != GDK_GRAB_SUCCESS
) {
354 gdk_display_pointer_ungrab (display
, event
->time
);
355 gtk_grab_remove (button
->dock
);
356 gtk_widget_hide (button
->dock
);
360 gtk_widget_grab_focus (button
->dock
);
362 /* forward event to the slider */
363 e
= (GdkEventButton
*) gdk_event_copy ((GdkEvent
*) event
);
364 e
->window
= button
->scale
->window
;
366 /* position: the X position isn't relevant, halfway will work just fine.
367 * The vertical position should be *exactly* in the middle of the slider
368 * of the scale; if we don't do that correctly, it'll move from its current
369 * position, which means a position change on-click, which is bad. */
370 e
->x
= button
->scale
->allocation
.width
/ 2;
371 m
= button
->scale
->allocation
.height
-
372 GTK_RANGE (button
->scale
)->min_slider_size
;
373 e
->y
= ((1.0 - v
) * m
) + GTK_RANGE (button
->scale
)->min_slider_size
/ 2;
374 gtk_widget_event (button
->scale
, (GdkEvent
*) e
);
375 e
->window
= event
->window
;
376 gdk_event_free ((GdkEvent
*) e
);
378 button
->pop_time
= event
->time
;
384 bacon_volume_key_release (GtkWidget
* widget
,
387 BaconVolumeButton
*button
= BACON_VOLUME_BUTTON (widget
);
388 GtkAdjustment
*adj
= gtk_range_get_adjustment (GTK_RANGE (button
->scale
));
389 gint x
, y
, m
, dx
, dy
, sx
, sy
, ystartoff
;
394 if (event
->keyval
!= GDK_space
&& event
->keyval
!= GDK_Return
)
397 display
= gtk_widget_get_display (widget
);
398 screen
= gtk_widget_get_screen (widget
);
400 /* position roughly */
401 gtk_window_set_screen (GTK_WINDOW (button
->dock
), screen
);
403 gdk_window_get_origin (widget
->window
, &x
, &y
);
404 x
+= widget
->allocation
.x
;
405 y
+= widget
->allocation
.y
;
406 gtk_window_move (GTK_WINDOW (button
->dock
), x
, y
- (SCALE_SIZE
/ 2));
407 gtk_widget_show_all (button
->dock
);
408 gdk_window_get_origin (button
->dock
->window
, &dx
, &dy
);
409 dy
+= button
->dock
->allocation
.y
;
410 gdk_window_get_origin (button
->scale
->window
, &sx
, &sy
);
411 sy
+= button
->scale
->allocation
.y
;
413 button
->timeout
= TRUE
;
415 /* position (needs widget to be shown already) */
416 v
= bacon_volume_button_get_value (button
) / (adj
->upper
- adj
->lower
);
417 x
+= (widget
->allocation
.width
- button
->dock
->allocation
.width
) / 2;
419 y
-= GTK_RANGE (button
->scale
)->min_slider_size
/ 2;
420 m
= button
->scale
->allocation
.height
-
421 GTK_RANGE (button
->scale
)->min_slider_size
;
423 gtk_window_move (GTK_WINDOW (button
->dock
), x
, y
);
424 gdk_window_get_origin (button
->scale
->window
, &sx
, &sy
);
427 gtk_grab_add (button
->dock
);
429 if (gdk_pointer_grab (button
->dock
->window
, TRUE
,
430 GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
| GDK_POINTER_MOTION_MASK
,
431 NULL
, NULL
, event
->time
)
432 != GDK_GRAB_SUCCESS
) {
433 gtk_grab_remove (button
->dock
);
434 gtk_widget_hide (button
->dock
);
438 if (gdk_keyboard_grab (button
->dock
->window
, TRUE
, event
->time
) != GDK_GRAB_SUCCESS
) {
439 gdk_display_pointer_ungrab (display
, event
->time
);
440 gtk_grab_remove (button
->dock
);
441 gtk_widget_hide (button
->dock
);
445 gtk_widget_grab_focus (button
->scale
);
447 button
->pop_time
= event
->time
;
453 * +/- button callbacks.
457 cb_button_timeout (gpointer data
)
459 BaconVolumeButton
*button
= BACON_VOLUME_BUTTON (data
);
460 GtkAdjustment
*adj
= gtk_range_get_adjustment (GTK_RANGE (button
->scale
));
464 if (button
->click_id
== 0)
467 val
= bacon_volume_button_get_value (button
);
468 val
+= button
->direction
;
469 if (val
<= adj
->lower
) {
472 } else if (val
> adj
->upper
) {
476 bacon_volume_button_set_value (button
, val
);
479 g_source_remove (button
->click_id
);
480 button
->click_id
= 0;
487 cb_button_press (GtkWidget
* widget
,
488 GdkEventButton
* event
,
491 BaconVolumeButton
*button
= BACON_VOLUME_BUTTON (data
);
492 GtkAdjustment
*adj
= gtk_range_get_adjustment (GTK_RANGE (button
->scale
));
494 if (button
->click_id
!= 0)
495 g_source_remove (button
->click_id
);
496 button
->direction
= (widget
== button
->plus
) ?
497 fabs (adj
->page_increment
) : - fabs (adj
->page_increment
);
498 button
->click_id
= g_timeout_add (CLICK_TIMEOUT
,
499 (GSourceFunc
) cb_button_timeout
, button
);
500 cb_button_timeout (button
);
506 cb_button_release (GtkWidget
* widget
,
507 GdkEventButton
* event
,
510 BaconVolumeButton
*button
= BACON_VOLUME_BUTTON (data
);
512 if (button
->click_id
!= 0) {
513 g_source_remove (button
->click_id
);
514 button
->click_id
= 0;
525 bacon_volume_release_grab (BaconVolumeButton
*button
,
526 GdkEventButton
* event
)
532 display
= gtk_widget_get_display (GTK_WIDGET (button
));
533 gdk_display_keyboard_ungrab (display
, event
->time
);
534 gdk_display_pointer_ungrab (display
, event
->time
);
535 gtk_grab_remove (button
->dock
);
538 gtk_widget_hide (button
->dock
);
539 button
->timeout
= FALSE
;
541 e
= (GdkEventButton
*) gdk_event_copy ((GdkEvent
*) event
);
542 e
->window
= GTK_WIDGET (button
)->window
;
543 e
->type
= GDK_BUTTON_RELEASE
;
544 gtk_widget_event (GTK_WIDGET (button
), (GdkEvent
*) e
);
545 e
->window
= event
->window
;
546 gdk_event_free ((GdkEvent
*) e
);
550 cb_dock_button_press (GtkWidget
* widget
,
551 GdkEventButton
* event
,
554 //GtkWidget *ewidget = gtk_get_event_widget ((GdkEvent *) event);
555 BaconVolumeButton
*button
= BACON_VOLUME_BUTTON (data
);
557 if (/*ewidget == button->dock &&*/ event
->type
== GDK_BUTTON_PRESS
) {
558 bacon_volume_release_grab (button
, event
);
566 cb_dock_key_release (GtkWidget
* widget
,
570 BaconVolumeButton
*button
= BACON_VOLUME_BUTTON (data
);
572 if (event
->keyval
== GDK_Escape
) {
576 display
= gtk_widget_get_display (widget
);
577 gdk_display_keyboard_ungrab (display
, event
->time
);
578 gdk_display_pointer_ungrab (display
, event
->time
);
581 gtk_widget_hide (button
->dock
);
582 button
->timeout
= FALSE
;
590 cb_dock_key_press (GtkWidget
* widget
,
594 if (event
->keyval
== GDK_Escape
) {
604 #define BACON_TYPE_VOLUME_SCALE \
605 (bacon_volume_scale_get_type ())
606 #define BACON_VOLUME_SCALE(obj) \
607 (G_TYPE_CHECK_INSTANCE_CAST ((obj), BACON_TYPE_VOLUME_SCALE, \
610 typedef struct _BaconVolumeScale
{
612 BaconVolumeButton
*button
;
615 static GType
bacon_volume_scale_get_type (void);
617 static void bacon_volume_scale_class_init (GtkVScaleClass
* klass
);
619 static gboolean
bacon_volume_scale_press (GtkWidget
* widget
,
620 GdkEventButton
* event
);
621 static gboolean
bacon_volume_scale_release (GtkWidget
* widget
,
622 GdkEventButton
* event
);
624 static GtkVScaleClass
*scale_parent_class
= NULL
;
627 bacon_volume_scale_get_type (void)
629 static GType bacon_volume_scale_type
= 0;
631 if (G_UNLIKELY (bacon_volume_scale_type
== 0)) {
632 const GTypeInfo bacon_volume_scale_info
= {
633 sizeof (GtkVScaleClass
),
636 (GClassInitFunc
) bacon_volume_scale_class_init
,
639 sizeof (BaconVolumeScale
),
645 bacon_volume_scale_type
=
646 g_type_register_static (GTK_TYPE_VSCALE
,
648 &bacon_volume_scale_info
, 0);
651 return bacon_volume_scale_type
;
655 bacon_volume_scale_class_init (GtkVScaleClass
* klass
)
657 GtkWidgetClass
*gtkwidget_class
= GTK_WIDGET_CLASS (klass
);
658 GtkRangeClass
*gtkrange_class
= GTK_RANGE_CLASS (klass
);
660 scale_parent_class
= g_type_class_peek_parent (klass
);
662 gtkwidget_class
->button_press_event
= bacon_volume_scale_press
;
663 gtkwidget_class
->button_release_event
= bacon_volume_scale_release
;
664 gtkrange_class
->value_changed
= bacon_volume_scale_value_changed
;
668 bacon_volume_scale_new (BaconVolumeButton
* button
,
669 float min
, float max
,
672 BaconVolumeScale
*scale
= g_object_new (BACON_TYPE_VOLUME_SCALE
, NULL
);
675 adj
= gtk_adjustment_new (min
, min
, max
, step
, 10 * step
, 0);
676 gtk_range_set_adjustment (GTK_RANGE (scale
), GTK_ADJUSTMENT (adj
));
677 scale
->button
= button
;
679 return GTK_WIDGET (scale
);
683 bacon_volume_scale_press (GtkWidget
* widget
,
684 GdkEventButton
* event
)
686 BaconVolumeScale
*scale
= BACON_VOLUME_SCALE (widget
);
687 BaconVolumeButton
*button
= scale
->button
;
689 /* the scale will grab input; if we have input grabbed, all goes
690 * horribly wrong, so let's not do that. */
691 gtk_grab_remove (button
->dock
);
693 return GTK_WIDGET_CLASS (scale_parent_class
)->button_press_event (widget
, event
);
697 bacon_volume_scale_release (GtkWidget
* widget
,
698 GdkEventButton
* event
)
700 BaconVolumeScale
*scale
= BACON_VOLUME_SCALE (widget
);
701 BaconVolumeButton
*button
= scale
->button
;
704 if (button
->timeout
) {
705 /* if we did a quick click, leave the window open; else, hide it */
706 if (event
->time
> button
->pop_time
+ CLICK_TIMEOUT
) {
707 bacon_volume_release_grab (button
, event
);
708 GTK_WIDGET_CLASS (scale_parent_class
)->button_release_event (widget
, event
);
711 button
->timeout
= FALSE
;
714 res
= GTK_WIDGET_CLASS (scale_parent_class
)->button_release_event (widget
, event
);
716 /* the scale will release input; right after that, we *have to* grab
717 * it back so we can catch out-of-scale clicks and hide the popup,
718 * so I basically want a g_signal_connect_after_always(), but I can't
719 * find that, so we do this complex 'first-call-parent-then-do-actual-
720 * action' thingy... */
721 gtk_grab_add (button
->dock
);
727 bacon_volume_button_update_icon (BaconVolumeButton
*button
)
729 GtkRange
*range
= GTK_RANGE (button
->scale
);
730 float val
= gtk_range_get_value (range
);
735 adj
= gtk_range_get_adjustment (range
);
736 step
= (adj
->upper
- adj
->lower
) / 4;
738 if (val
== adj
->lower
)
739 pixbuf
= button
->icon
[0];
740 else if (val
> adj
->lower
&& val
<= adj
->lower
+ step
)
741 pixbuf
= button
->icon
[1];
742 else if (val
> adj
->lower
+ step
&& val
<= adj
->lower
+ step
* 2)
743 pixbuf
= button
->icon
[2];
745 pixbuf
= button
->icon
[3];
747 gtk_image_set_from_pixbuf (GTK_IMAGE (button
->image
), pixbuf
);
751 bacon_volume_scale_value_changed (GtkRange
* range
)
753 BaconVolumeScale
*scale
= BACON_VOLUME_SCALE (range
);
754 BaconVolumeButton
*button
= scale
->button
;
756 bacon_volume_button_update_icon (button
);
759 g_signal_emit (button
, signals
[SIGNAL_VALUE_CHANGED
], 0);
763 bacon_volume_button_load_icons (GtkWidget
*widget
)
765 BaconVolumeButton
*button
= BACON_VOLUME_BUTTON (widget
);
770 const char *icon_name
[] = {"audio-volume-muted", "audio-volume-low",
771 "audio-volume-medium", "audio-volume-high"};
772 const char *fallback_icon_name
[] = {"stock_volume-0", "stock_volume-min",
773 "stock_volume-med", "stock_volume-max"};
775 screen
= gtk_widget_get_screen (widget
);
776 theme
= gtk_icon_theme_get_for_screen (screen
);
778 gtk_icon_size_lookup (button
->size
, &w
, &h
);
780 for (i
= 0; i
< 4; i
++) {
781 GError
*error
= NULL
;
782 if (button
->icon
[i
] != NULL
) {
783 g_object_unref (button
->icon
[i
]);
784 button
->icon
[i
] = NULL
;
786 button
->icon
[i
] = gtk_icon_theme_load_icon (theme
, icon_name
[i
], w
, 0, &error
);
788 g_print ("Couldn't load themed icon '%s': %s\n", icon_name
[i
], error
->message
);
789 g_clear_error (&error
);
791 button
->icon
[i
] = gtk_icon_theme_load_icon (theme
, fallback_icon_name
[i
], w
, 0, &error
);
793 g_print ("Couldn't load themed icon '%s': %s\n", icon_name
[i
], error
->message
);
794 g_clear_error (&error
);
799 /* Apply the new icons */
800 bacon_volume_button_update_icon (button
);
804 * vim: sw=2 ts=8 cindent noai bs=2