~ubuntu-branches/ubuntu/oneiric/gnome-panel/oneiric

« back to all changes in this revision

Viewing changes to gnome-panel/button-widget.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2011-05-30 11:04:49 UTC
  • mfrom: (1.3.4 upstream)
  • mto: This revision was merged to the branch mainline in revision 204.
  • Revision ID: james.westby@ubuntu.com-20110530110449-ut1tc5t61rpvf9e3
Tags: upstream-3.0.2
ImportĀ upstreamĀ versionĀ 3.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
#include "panel-widget.h"
12
12
#include "panel-types.h"
13
13
#include "panel-util.h"
14
 
#include "panel-config-global.h"
15
14
#include "panel-marshal.h"
16
15
#include "panel-typebuiltins.h"
17
16
#include "panel-globals.h"
113
112
static void
114
113
button_widget_realize(GtkWidget *widget)
115
114
{
116
 
        GtkAllocation allocation;
117
 
        GdkWindowAttr attributes;
118
 
        gint attributes_mask;
119
 
        GtkButton *button;
120
 
 
121
 
        g_return_if_fail (widget != NULL);
122
 
        g_return_if_fail (BUTTON_IS_WIDGET (widget));
123
 
 
124
 
        button = GTK_BUTTON (widget);
125
 
 
126
 
        gtk_widget_set_realized (widget, TRUE);
127
 
 
128
 
        gtk_widget_get_allocation (widget, &allocation);
129
 
 
130
 
        attributes.window_type = GDK_WINDOW_CHILD;
131
 
        attributes.x = allocation.x;
132
 
        attributes.y = allocation.y;
133
 
        attributes.width = allocation.width;
134
 
        attributes.height = allocation.height;
135
 
        attributes.wclass = GDK_INPUT_ONLY;
136
 
        attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
137
 
                                 GDK_BUTTON_RELEASE_MASK |
138
 
                                 GDK_POINTER_MOTION_MASK |
139
 
                                 GDK_POINTER_MOTION_HINT_MASK |
140
 
                                 GDK_KEY_PRESS_MASK |
141
 
                                 GDK_ENTER_NOTIFY_MASK |
142
 
                                 GDK_LEAVE_NOTIFY_MASK);
143
 
        attributes_mask = GDK_WA_X | GDK_WA_Y;
144
 
 
145
 
        gtk_widget_set_window (widget, gtk_widget_get_parent_window (widget));
146
 
        g_object_ref (gtk_widget_get_window (widget));
147
 
      
148
 
        button->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
149
 
                                               &attributes,
150
 
                                               attributes_mask);
151
 
        gdk_window_set_user_data (button->event_window, widget);
152
 
 
153
 
        widget->style = gtk_style_attach (widget->style, gtk_widget_get_window (widget));
 
115
        // FIXMEchpe why?
 
116
        gtk_widget_add_events (widget, GDK_POINTER_MOTION_MASK |
 
117
                                       GDK_POINTER_MOTION_HINT_MASK |
 
118
                                       GDK_KEY_PRESS_MASK);
 
119
 
 
120
        GTK_WIDGET_CLASS (button_widget_parent_class)->realize (widget);
154
121
 
155
122
        BUTTON_WIDGET (widget)->priv->icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
156
123
        g_signal_connect_object (BUTTON_WIDGET (widget)->priv->icon_theme,
157
124
                                 "changed",
158
125
                                 G_CALLBACK (button_widget_icon_theme_changed),
159
 
                                 button,
 
126
                                 widget,
160
127
                                 G_CONNECT_SWAPPED);
161
128
 
162
129
        button_widget_reload_pixbuf (BUTTON_WIDGET (widget));
165
132
static void
166
133
button_widget_unrealize (GtkWidget *widget)
167
134
{
168
 
        GtkButton *button;
169
 
 
170
 
        g_return_if_fail (widget != NULL);
171
 
        g_return_if_fail (BUTTON_IS_WIDGET (widget));
172
 
 
173
 
        button = GTK_BUTTON (widget);
174
 
 
175
 
        if (button->event_window != NULL) {
176
 
                gdk_window_set_user_data (button->event_window, NULL);
177
 
                gdk_window_destroy (button->event_window);
178
 
                button->event_window = NULL;
179
 
        }
 
135
        g_signal_handlers_disconnect_by_func (BUTTON_WIDGET (widget)->priv->icon_theme,
 
136
                                              G_CALLBACK (button_widget_icon_theme_changed),
 
137
                                              widget);
180
138
 
181
139
        GTK_WIDGET_CLASS (button_widget_parent_class)->unrealize (widget);
182
140
}
215
173
                if (error) {
216
174
                        //FIXME: this is not rendered at button->priv->size
217
175
                        button->priv->pixbuf =
218
 
                                gtk_widget_render_icon (GTK_WIDGET (button),
219
 
                                                        GTK_STOCK_MISSING_IMAGE,
220
 
                                                        (GtkIconSize) -1, NULL);
 
176
                                gtk_widget_render_icon_pixbuf (GTK_WIDGET (button),
 
177
                                                               GTK_STOCK_MISSING_IMAGE,
 
178
                                                               (GtkIconSize) -1);
221
179
                        g_free (error);
222
180
                }
 
181
 
 
182
                gtk_button_set_image (GTK_BUTTON (button), gtk_image_new_from_pixbuf (button->priv->pixbuf));
223
183
        }
224
184
 
225
185
        button->priv->pixbuf_hc = make_hc_pixbuf (button->priv->pixbuf);
255
215
{
256
216
        ButtonWidget *button;
257
217
 
258
 
        g_return_if_fail (BUTTON_IS_WIDGET (object));
259
 
 
260
218
        button = BUTTON_WIDGET (object);
261
219
 
262
220
        switch (prop_id) {
292
250
{
293
251
        ButtonWidget *button;
294
252
 
295
 
        g_return_if_fail (BUTTON_IS_WIDGET (object));
296
 
 
297
253
        button = BUTTON_WIDGET (object);
298
254
 
299
255
        switch (prop_id) {
327
283
            int               button_height,
328
284
            int              *x,
329
285
            int              *y,
330
 
            int              *width,
331
 
            int              *height)
 
286
            gdouble          *angle,
 
287
            gdouble          *size)
332
288
{
333
289
        GtkArrowType retval = GTK_ARROW_UP;
334
290
        double scale;
335
291
 
336
292
        scale = (orientation & PANEL_HORIZONTAL_MASK ? button_height : button_width) / 48.0;
337
293
 
338
 
        *width  = 12 * scale;
339
 
        *height = 12 * scale;
 
294
        *size = 12 * scale;
 
295
        *angle = 0;
340
296
 
341
297
        switch (orientation) {
342
298
        case PANEL_ORIENTATION_TOP:
343
299
                *x     = scale * 3;
344
300
                *y     = scale * (48 - 13);
 
301
                *angle = G_PI;
345
302
                retval = GTK_ARROW_DOWN;
346
303
                break;
347
304
        case PANEL_ORIENTATION_BOTTOM:
348
305
                *x     = scale * (48 - 13);
349
306
                *y     = scale * 1;
 
307
                *angle = 0;
350
308
                retval = GTK_ARROW_UP;
351
309
                break;
352
310
        case PANEL_ORIENTATION_LEFT:
353
311
                *x     = scale * (48 - 13);
354
312
                *y     = scale * 3;
 
313
                *angle = G_PI / 2;
355
314
                retval = GTK_ARROW_RIGHT;
356
315
                break;
357
316
        case PANEL_ORIENTATION_RIGHT:
358
317
                *x     = scale * 1;
359
318
                *y     = scale * 3;
 
319
                *angle = 3 * (G_PI / 2);
360
320
                retval = GTK_ARROW_LEFT;
361
321
                break;
362
322
        }
365
325
}
366
326
 
367
327
static gboolean
368
 
button_widget_expose (GtkWidget         *widget,
369
 
                      GdkEventExpose    *event)
 
328
button_widget_draw (GtkWidget *widget,
 
329
                    cairo_t   *cr)
370
330
{
371
 
        ButtonWidget *button_widget;
372
 
        GtkButton *button;
373
 
        GdkWindow *window;
374
 
        GtkAllocation allocation;
375
 
        GdkRectangle area, image_bound;
376
 
        GtkStyle *style;
 
331
        ButtonWidget *button_widget = BUTTON_WIDGET (widget);
 
332
        GtkStyleContext *context;
 
333
        GtkStateFlags state_flags;
 
334
        gboolean hover_highlight;
377
335
        int off;
378
 
        int x, y, w, h;
 
336
        int width, height;
 
337
        int x, y, w, h;
379
338
        GdkPixbuf *pb = NULL;
380
 
  
381
 
        g_return_val_if_fail (BUTTON_IS_WIDGET (widget), FALSE);
382
 
        g_return_val_if_fail (event != NULL, FALSE);
383
 
 
384
 
        if (!gtk_widget_get_visible (widget) || !gtk_widget_get_mapped (widget))
385
 
                return FALSE;
386
 
 
387
 
        button_widget = BUTTON_WIDGET (widget);
388
339
 
389
340
        if (!button_widget->priv->pixbuf_hc && !button_widget->priv->pixbuf)
390
341
                return FALSE;
391
342
 
392
 
        button = GTK_BUTTON (widget);
393
 
        window = gtk_widget_get_window (widget);
394
 
        gtk_widget_get_allocation (widget, &allocation);
 
343
        width = gtk_widget_get_allocated_width (widget);
 
344
        height = gtk_widget_get_allocated_height (widget);
395
345
 
396
346
        /* offset for pressed buttons */
397
 
        off = (button_widget->priv->activatable &&
398
 
               button->in_button && button->button_down) ?
399
 
                BUTTON_WIDGET_DISPLACEMENT * allocation.height / 48.0 : 0;
400
 
 
 
347
        state_flags = gtk_widget_get_state_flags (widget);
 
348
        gtk_widget_style_get (widget, "hover-highlight", &hover_highlight, NULL);
 
349
 
 
350
        off = (button_widget->priv->activatable && (state_flags & GTK_STATE_FLAG_PRELIGHT) &&
 
351
               (state_flags & GTK_STATE_FLAG_ACTIVE)) ?
 
352
                BUTTON_WIDGET_DISPLACEMENT * height / 48.0 : 0;
 
353
 
 
354
        /* FIXMEchpe replace this by cairo ops too! */
401
355
        if (!button_widget->priv->activatable) {
402
356
                pb = gdk_pixbuf_copy (button_widget->priv->pixbuf);
403
357
                gdk_pixbuf_saturate_and_pixelate (button_widget->priv->pixbuf,
404
358
                                                  pb,
405
359
                                                  0.8,
406
360
                                                  TRUE);
407
 
        } else if (panel_global_config_get_highlight_when_over () && 
408
 
                   (button->in_button || gtk_widget_has_focus (widget)))
 
361
        } else if (hover_highlight &&
 
362
                   (state_flags & GTK_STATE_FLAG_PRELIGHT || gtk_widget_has_focus (widget)))
409
363
                pb = g_object_ref (button_widget->priv->pixbuf_hc);
410
364
        else
411
365
                pb = g_object_ref (button_widget->priv->pixbuf);
414
368
 
415
369
        w = gdk_pixbuf_get_width (pb);
416
370
        h = gdk_pixbuf_get_height (pb);
417
 
        x = allocation.x + off + (allocation.width - w)/2;
418
 
        y = allocation.y + off + (allocation.height - h)/2;
419
 
        
420
 
        image_bound.x = x;
421
 
        image_bound.y = y;      
422
 
        image_bound.width = w;
423
 
        image_bound.height = h;
424
 
        
425
 
        area = event->area;
 
371
        x = off + (width - w)/2;
 
372
        y = off + (height - h)/2;
426
373
 
427
 
        if (gdk_rectangle_intersect (&area, &allocation, &area) &&
428
 
            gdk_rectangle_intersect (&image_bound, &area, &image_bound))
429
 
                gdk_draw_pixbuf (window, NULL, pb,
430
 
                                 image_bound.x - x, image_bound.y - y,
431
 
                                 image_bound.x, image_bound.y,
432
 
                                 image_bound.width, image_bound.height,
433
 
                                 GDK_RGB_DITHER_NORMAL,
434
 
                                 0, 0);
 
374
        cairo_save (cr);
 
375
        gdk_cairo_set_source_pixbuf (cr, pb, x, y);
 
376
        cairo_paint (cr);
 
377
        cairo_restore (cr);
435
378
 
436
379
        g_object_unref (pb);
437
380
 
438
 
        style = gtk_widget_get_style (widget);
 
381
        context = gtk_widget_get_style_context (widget);
439
382
 
440
383
        if (button_widget->priv->arrow) {
441
384
                GtkArrowType arrow_type;
442
 
                int          x, y, width, height;
 
385
                gdouble angle, size;
443
386
 
444
 
                x = y = width = height = -1;
 
387
                gtk_style_context_save (context);
 
388
                gtk_style_context_set_state (context, state_flags);
445
389
 
446
390
                arrow_type = calc_arrow (button_widget->priv->orientation,
447
 
                                         allocation.width,
448
 
                                         allocation.height,
449
 
                                         &x,
450
 
                                         &y,
451
 
                                         &width,
452
 
                                         &height);
453
 
 
454
 
                gtk_paint_arrow (style,
455
 
                                 window,
456
 
                                 GTK_STATE_NORMAL,
457
 
                                 GTK_SHADOW_NONE,
458
 
                                 NULL,
459
 
                                 widget,
460
 
                                 "panel-button",
461
 
                                 arrow_type,
462
 
                                 TRUE,
463
 
                                 allocation.x + x,
464
 
                                 allocation.y + y,
465
 
                                 width,
466
 
                                 height);
 
391
                                         width, height,
 
392
                                         &x, &y,
 
393
                                         &angle, &size);
 
394
 
 
395
                cairo_save (cr);
 
396
                gtk_render_arrow (context, cr, angle, x, y, size);
 
397
                cairo_restore (cr);
 
398
 
 
399
                gtk_style_context_restore (context);
467
400
        }
468
401
 
469
402
        if (button_widget->priv->dnd_highlight) {
470
 
                gdk_draw_rectangle(window, style->black_gc, FALSE,
471
 
                                   allocation.x, allocation.y,
472
 
                                   allocation.width - 1,
473
 
                                   allocation.height - 1);
 
403
                cairo_save (cr);
 
404
                cairo_set_line_width (cr, 1);
 
405
                cairo_set_source_rgb (cr, 0., 0., 0.);
 
406
                cairo_rectangle (cr, 0.5, 0.5, width - 1, height - 1);
 
407
                cairo_stroke (cr);
 
408
                cairo_restore (cr);
474
409
        }
475
410
 
476
411
        if (gtk_widget_has_focus (widget)) {
477
 
                gint focus_width, focus_pad;
478
 
                gint x, y, width, height;
 
412
                gint focus_pad;
 
413
 
 
414
                gtk_style_context_save (context);
 
415
                gtk_style_context_set_state (context, state_flags);
479
416
 
480
417
                gtk_widget_style_get (widget,
481
 
                                      "focus-line-width", &focus_width,
482
418
                                      "focus-padding", &focus_pad,
483
419
                                      NULL);
484
 
                x = allocation.x + focus_pad;
485
 
                y = allocation.y + focus_pad;
486
 
                width = allocation.width -  2 * focus_pad;
487
 
                height = allocation.height - 2 * focus_pad;
488
 
                gtk_paint_focus (style, window,
489
 
                                 GTK_STATE_NORMAL,
490
 
                                 &event->area, widget, "button",
491
 
                                 x, y, width, height);
 
420
                x = focus_pad;
 
421
                y = focus_pad;
 
422
                w = width -  2 * focus_pad;
 
423
                h = height - 2 * focus_pad;
 
424
 
 
425
                cairo_save (cr);
 
426
                gtk_render_focus (context, cr, x, y, w, h);
 
427
                cairo_restore (cr);
 
428
 
 
429
                gtk_style_context_restore (context);
492
430
        }
493
431
        
494
432
        return FALSE;
495
433
}
496
434
 
497
435
static void
498
 
button_widget_size_request (GtkWidget      *widget,
499
 
                            GtkRequisition *requisition)
500
 
{
501
 
        ButtonWidget *button_widget = BUTTON_WIDGET (widget);
502
 
 
503
 
        if (button_widget->priv->pixbuf) {
504
 
                requisition->width  = gdk_pixbuf_get_width  (button_widget->priv->pixbuf);
505
 
                requisition->height = gdk_pixbuf_get_height (button_widget->priv->pixbuf);
506
 
        }
507
 
}
 
436
button_widget_get_preferred_width (GtkWidget *widget,
 
437
                                   gint *minimal_width,
 
438
                                   gint *natural_width)
 
439
{
 
440
        ButtonWidget *button_widget = BUTTON_WIDGET (widget);
 
441
        GtkWidget *parent;
 
442
        int size;
 
443
 
 
444
        parent = gtk_widget_get_parent (widget);
 
445
 
 
446
        if (button_widget->priv->orientation & PANEL_HORIZONTAL_MASK)
 
447
                size = gtk_widget_get_allocated_height (parent);
 
448
        else
 
449
                size = gtk_widget_get_allocated_width (parent);
 
450
 
 
451
        *minimal_width = *natural_width = size;
 
452
}
 
453
 
 
454
static void
 
455
button_widget_get_preferred_height (GtkWidget *widget,
 
456
                                    gint *minimal_height,
 
457
                                    gint *natural_height)
 
458
{
 
459
        ButtonWidget *button_widget = BUTTON_WIDGET (widget);
 
460
        GtkWidget *parent;
 
461
        int size;
 
462
 
 
463
        parent = gtk_widget_get_parent (widget);
 
464
 
 
465
        if (button_widget->priv->orientation & PANEL_HORIZONTAL_MASK)
 
466
                size = gtk_widget_get_allocated_height (parent);
 
467
        else
 
468
                size = gtk_widget_get_allocated_width (parent);
 
469
 
 
470
        *minimal_height = *natural_height = size;
 
471
}
 
472
 
508
473
 
509
474
static void
510
475
button_widget_size_allocate (GtkWidget     *widget,
511
476
                             GtkAllocation *allocation)
512
477
{
513
478
        ButtonWidget *button_widget = BUTTON_WIDGET (widget);
514
 
        GtkButton    *button = GTK_BUTTON (widget);
515
479
        int           size;
516
480
 
 
481
        GTK_WIDGET_CLASS (button_widget_parent_class)->size_allocate (widget, allocation);
 
482
 
517
483
        if (button_widget->priv->orientation & PANEL_HORIZONTAL_MASK)
518
484
                size = allocation->height;
519
485
        else
535
501
 
536
502
                button_widget_reload_pixbuf (button_widget);
537
503
        }
538
 
 
539
 
        gtk_widget_set_allocation (widget, allocation);
540
 
 
541
 
        if (gtk_widget_get_realized (widget)) {
542
 
                gdk_window_move_resize (button->event_window, 
543
 
                                        allocation->x,
544
 
                                        allocation->y,
545
 
                                        allocation->width,
546
 
                                        allocation->height);
547
 
        }
548
504
}
549
505
 
550
506
static void
577
533
static gboolean
578
534
button_widget_enter_notify (GtkWidget *widget, GdkEventCrossing *event)
579
535
{
 
536
        GtkStateFlags state_flags;
580
537
        gboolean in_button;
 
538
        gboolean hover_highlight;
581
539
 
582
540
        g_return_val_if_fail (BUTTON_IS_WIDGET (widget), FALSE);
583
541
 
584
 
        in_button = GTK_BUTTON (widget)->in_button;
 
542
        state_flags = gtk_widget_get_state_flags (widget);
 
543
        in_button = state_flags & GTK_STATE_FLAG_PRELIGHT;
 
544
 
585
545
        GTK_WIDGET_CLASS (button_widget_parent_class)->enter_notify_event (widget, event);
586
 
        if (in_button != GTK_BUTTON (widget)->in_button &&
587
 
            panel_global_config_get_highlight_when_over ())
 
546
 
 
547
        state_flags = gtk_widget_get_state_flags (widget);
 
548
        gtk_widget_style_get (widget, "hover-highlight", &hover_highlight, NULL);
 
549
 
 
550
        if (in_button != (state_flags & GTK_STATE_FLAG_PRELIGHT) &&
 
551
            hover_highlight)
588
552
                gtk_widget_queue_draw (widget);
589
553
 
590
554
        return FALSE;
593
557
static gboolean
594
558
button_widget_leave_notify (GtkWidget *widget, GdkEventCrossing *event)
595
559
{
 
560
        GtkStateFlags state_flags;
596
561
        gboolean in_button;
 
562
        gboolean hover_highlight;
597
563
 
598
564
        g_return_val_if_fail (BUTTON_IS_WIDGET (widget), FALSE);
599
565
 
600
 
        in_button = GTK_BUTTON (widget)->in_button;
 
566
        state_flags = gtk_widget_get_state_flags (widget);
 
567
        in_button = state_flags & GTK_STATE_FLAG_PRELIGHT;
 
568
 
601
569
        GTK_WIDGET_CLASS (button_widget_parent_class)->leave_notify_event (widget, event);
602
 
        if (in_button != GTK_BUTTON (widget)->in_button &&
603
 
            panel_global_config_get_highlight_when_over ())
 
570
 
 
571
        state_flags = gtk_widget_get_state_flags (widget);
 
572
        gtk_widget_style_get (widget, "hover-highlight", &hover_highlight, NULL);
 
573
 
 
574
        if (in_button != (state_flags & GTK_STATE_FLAG_PRELIGHT) &&
 
575
            hover_highlight)
604
576
                gtk_widget_queue_draw (widget);
605
577
 
606
578
        return FALSE;
640
612
 
641
613
        g_type_class_add_private (klass, sizeof (ButtonWidgetPrivate));
642
614
          
643
 
        widget_class->realize            = button_widget_realize;
644
 
        widget_class->unrealize          = button_widget_unrealize;
645
 
        widget_class->size_allocate      = button_widget_size_allocate;
646
 
        widget_class->size_request       = button_widget_size_request;
647
 
        widget_class->button_press_event = button_widget_button_press;
648
 
        widget_class->enter_notify_event = button_widget_enter_notify;
649
 
        widget_class->leave_notify_event = button_widget_leave_notify;
650
 
        widget_class->expose_event       = button_widget_expose;
 
615
        widget_class->realize              = button_widget_realize;
 
616
        widget_class->unrealize            = button_widget_unrealize;
 
617
        widget_class->size_allocate        = button_widget_size_allocate;
 
618
        widget_class->get_preferred_width  = button_widget_get_preferred_width;
 
619
        widget_class->get_preferred_height = button_widget_get_preferred_height;
 
620
        widget_class->button_press_event   = button_widget_button_press;
 
621
        widget_class->enter_notify_event   = button_widget_enter_notify;
 
622
        widget_class->leave_notify_event   = button_widget_leave_notify;
 
623
        widget_class->draw                 = button_widget_draw;
651
624
 
652
625
        button_class->activate = button_widget_activate;
653
626
 
705
678
                                             "The desired icon for the ButtonWidget",
706
679
                                             NULL,
707
680
                                             G_PARAM_READWRITE));
 
681
 
 
682
        gtk_widget_class_install_style_property (
 
683
                        widget_class,
 
684
                        g_param_spec_boolean ("hover-highlight",
 
685
                                              "Highlight on hover",
 
686
                                              "Whether to highlight the button on mouse over",
 
687
                                              TRUE,
 
688
                                              G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
689
 
708
690
}
709
691
 
710
692
GtkWidget *