405
405
<div class="example">
406
406
<a name="composited-window-example"></a><p class="title"><b>Example 7. Composited windows</b></p>
407
<div class="example-contents">
408
<table class="listing_frame" border="0" cellpadding="0" cellspacing="0">
411
<td class="listing_lines" align="right"><pre>1
524
<td class="listing_code"><pre class="programlisting"><span class="preproc">#include </span><span class="number"><gtk/gtk.h></span>
525
<span class="comment">/*</span><span class="comment"> The expose event handler for the event box.</span>
526
<span class="comment"> *</span>
527
<span class="comment"> * This function simply draws a transparency onto a widget on the area</span>
528
<span class="comment"> * for which it receives expose events. This is intended to give the</span>
529
<span class="comment"> * event box a "transparent" background.</span>
530
<span class="comment"> *</span>
531
<span class="comment"> * In order for this to work properly, the widget must have an RGBA</span>
532
<span class="comment"> * colourmap. The widget should also be set as app-paintable since it</span>
533
<span class="comment"> * doesn't make sense for GTK+ to draw a background if we are drawing it</span>
534
<span class="comment"> * (and because GTK+ might actually replace our transparency with its</span>
535
<span class="comment"> * default background colour).</span>
536
<span class="comment"> </span><span class="comment">*/</span>
537
<span class="type">static</span> gboolean
407
<div class="example-contents"><pre class="programlisting">
408
#include <gtk/gtk.h>
409
/* The expose event handler for the event box.
411
* This function simply draws a transparency onto a widget on the area
412
* for which it receives expose events. This is intended to give the
413
* event box a "transparent" background.
415
* In order for this to work properly, the widget must have an RGBA
416
* colourmap. The widget should also be set as app-paintable since it
417
* doesn't make sense for GTK+ to draw a background if we are drawing it
418
* (and because GTK+ might actually replace our transparency with its
419
* default background colour).
538
422
transparent_expose (GtkWidget *widget,
539
423
GdkEventExpose *event)
544
428
gdk_cairo_region (cr, event->region);
546
430
cairo_destroy (cr);
547
<span class="keyword">return</span> FALSE;
549
<span class="comment">/*</span><span class="comment"> The expose event handler for the window.</span>
550
<span class="comment"> *</span>
551
<span class="comment"> * This function performs the actual compositing of the event box onto</span>
552
<span class="comment"> * the already-existing background of the window at 50% normal opacity.</span>
553
<span class="comment"> *</span>
554
<span class="comment"> * In this case we do not want app-paintable to be set on the widget</span>
555
<span class="comment"> * since we want it to draw its own (red) background. Because of this,</span>
556
<span class="comment"> * however, we must ensure that we use g_signal_connect_after so that</span>
557
<span class="comment"> * this handler is called after the red has been drawn. If it was</span>
558
<span class="comment"> * called before then GTK would just blindly paint over our work.</span>
559
<span class="comment"> *</span>
560
<span class="comment"> * Note: if the child window has children, then you need a cairo 1.6</span>
561
<span class="comment"> * feature to make this work correctly.</span>
562
<span class="comment"> </span><span class="comment">*/</span>
563
<span class="type">static</span> gboolean
433
/* The expose event handler for the window.
435
* This function performs the actual compositing of the event box onto
436
* the already-existing background of the window at 50% normal opacity.
438
* In this case we do not want app-paintable to be set on the widget
439
* since we want it to draw its own (red) background. Because of this,
440
* however, we must ensure that we use g_signal_connect_after so that
441
* this handler is called after the red has been drawn. If it was
442
* called before then GTK would just blindly paint over our work.
444
* Note: if the child window has children, then you need a cairo 1.6
445
* feature to make this work correctly.
564
448
window_expose_event (GtkWidget *widget,
565
449
GdkEventExpose *event)
567
451
GdkRegion *region;
568
452
GtkWidget *child;
570
<span class="comment">/*</span><span class="comment"> get our child (in this case, the event box) </span><span class="comment">*/</span>
454
/* get our child (in this case, the event box) */
571
455
child = gtk_bin_get_child (GTK_BIN (widget));
572
<span class="comment">/*</span><span class="comment"> create a cairo context to draw to the window </span><span class="comment">*/</span>
456
/* create a cairo context to draw to the window */
573
457
cr = gdk_cairo_create (widget->window);
574
<span class="comment">/*</span><span class="comment"> the source data is the (composited) event box </span><span class="comment">*/</span>
458
/* the source data is the (composited) event box */
575
459
gdk_cairo_set_source_pixmap (cr, child->window,
576
460
child->allocation.x,
577
461
child->allocation.y);
578
<span class="comment">/*</span><span class="comment"> draw no more than our expose event intersects our child </span><span class="comment">*/</span>
462
/* draw no more than our expose event intersects our child */
579
463
region = gdk_region_rectangle (&child->allocation);
580
464
gdk_region_intersect (region, event->region);
581
465
gdk_cairo_region (cr, region);
583
<span class="comment">/*</span><span class="comment"> composite, with a 50% opacity </span><span class="comment">*/</span>
467
/* composite, with a 50% opacity */
584
468
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
585
cairo_paint_with_alpha (cr, <span class="number">0.5</span>);
586
<span class="comment">/*</span><span class="comment"> we're done </span><span class="comment">*/</span>
469
cairo_paint_with_alpha (cr, 0.5);
587
471
cairo_destroy (cr);
588
<span class="keyword">return</span> FALSE;
590
<span class="type">int</span>
591
main (<span class="type">int</span> argc, <span class="type">char</span> **argv)
475
main (int argc, char **argv)
593
477
GtkWidget *window, *event, *button;
594
478
GdkScreen *screen;
595
479
GdkColormap *rgba;
597
481
gtk_init (&argc, &argv);
598
<span class="comment">/*</span><span class="comment"> Make the widgets </span><span class="comment">*/</span>
599
button = gtk_button_new_with_label (<span class="number">"A Button"</span>);
482
/* Make the widgets */
483
button = gtk_button_new_with_label ("A Button");
600
484
event = gtk_event_box_new ();
601
485
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
602
<span class="comment">/*</span><span class="comment"> Put a red background on the window </span><span class="comment">*/</span>
603
gdk_color_parse (<span class="number">"red"</span>, &red);
486
/* Put a red background on the window */
487
gdk_color_parse ("red", &red);
604
488
gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &red);
605
<span class="comment">/*</span><span class="comment"> Set the colourmap for the event box.</span>
606
<span class="comment"> * Must be done before the event box is realised.</span>
607
<span class="comment"> </span><span class="comment">*/</span>
489
/* Set the colourmap for the event box.
490
* Must be done before the event box is realised.
608
492
screen = gtk_widget_get_screen (event);
609
493
rgba = gdk_screen_get_rgba_colormap (screen);
610
494
gtk_widget_set_colormap (event, rgba);
611
<span class="comment">/*</span><span class="comment"> Set our event box to have a fully-transparent background</span>
612
<span class="comment"> * drawn on it. Currently there is no way to simply tell GTK+</span>
613
<span class="comment"> * that "transparency" is the background colour for a widget.</span>
614
<span class="comment"> </span><span class="comment">*/</span>
495
/* Set our event box to have a fully-transparent background
496
* drawn on it. Currently there is no way to simply tell GTK+
497
* that "transparency" is the background colour for a widget.
615
499
gtk_widget_set_app_paintable (GTK_WIDGET (event), TRUE);
616
g_signal_connect (event, <span class="number">"expose-event"</span>,
617
G_CALLBACK (transparent_expose), <span class="number">NULL</span>);
618
<span class="comment">/*</span><span class="comment"> Put them inside one another </span><span class="comment">*/</span>
619
gtk_container_set_border_width (GTK_CONTAINER (window), <span class="number">10</span>);
500
g_signal_connect (event, "expose-event",
501
G_CALLBACK (transparent_expose), NULL);
502
/* Put them inside one another */
503
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
620
504
gtk_container_add (GTK_CONTAINER (window), event);
621
505
gtk_container_add (GTK_CONTAINER (event), button);
622
<span class="comment">/*</span><span class="comment"> Realise and show everything </span><span class="comment">*/</span>
506
/* Realise and show everything */
623
507
gtk_widget_show_all (window);
624
<span class="comment">/*</span><span class="comment"> Set the event box GdkWindow to be composited.</span>
625
<span class="comment"> * Obviously must be performed after event box is realised.</span>
626
<span class="comment"> </span><span class="comment">*/</span>
508
/* Set the event box GdkWindow to be composited.
509
* Obviously must be performed after event box is realised.
627
511
gdk_window_set_composited (event->window, TRUE);
628
<span class="comment">/*</span><span class="comment"> Set up the compositing handler.</span>
629
<span class="comment"> * Note that we do _after_ so that the normal (red) background is drawn</span>
630
<span class="comment"> * by gtk before our compositing occurs.</span>
631
<span class="comment"> </span><span class="comment">*/</span>
632
g_signal_connect_after (window, <span class="number">"expose-event"</span>,
633
G_CALLBACK (window_expose_event), <span class="number">NULL</span>);
512
/* Set up the compositing handler.
513
* Note that we do _after_ so that the normal (red) background is drawn
514
* by gtk before our compositing occurs.
516
g_signal_connect_after (window, "expose-event",
517
G_CALLBACK (window_expose_event), NULL);
635
<span class="keyword">return</span> <span class="number">0</span>;
643
524
<br class="example-break"><p>
644
525
In the example <a class="xref" href="gdk-Windows.html#composited-window-example" title="Example 7. Composited windows">Example 7, “Composited windows”</a>, a button is