Advertisement
Ancurio

Gtk3 widgets with background image

Jan 9th, 2012
1,036
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.94 KB | None | 0 0
  1.  
  2. #include <gtk/gtk.h>
  3. #include <cairo.h>
  4.  
  5. #define WINDOW_W 200
  6. #define WINDOW_H 200
  7.  
  8.  
  9. static cairo_surface_t *scale_surface
  10. ( cairo_surface_t *old_surface, gdouble new_w, gdouble new_h,
  11.   gboolean smooth )
  12. {
  13.     gint old_width = cairo_image_surface_get_width(old_surface);
  14.     gint old_height = cairo_image_surface_get_height(old_surface);
  15.  
  16.     cairo_surface_t *new_surface = cairo_surface_create_similar
  17.         (old_surface, CAIRO_CONTENT_COLOR_ALPHA,
  18.         (gint)(new_w), (gint)(new_h));
  19.     cairo_t *cr = cairo_create (new_surface);
  20.  
  21.     cairo_scale (cr, new_w/old_width, new_h/old_height);
  22.     cairo_set_source_surface (cr, old_surface, 0, 0);
  23.  
  24.     if (!smooth)
  25.     {
  26.         cairo_pattern_set_filter
  27.             (cairo_get_source(cr), CAIRO_FILTER_NEAREST);
  28.     }
  29.     cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
  30.     cairo_paint (cr);
  31.     cairo_destroy (cr);
  32.  
  33.     return new_surface;
  34. }
  35.  
  36.  
  37. /* The expose event handler for the window.
  38.  *
  39.  * This function performs the actual compositing of the event box onto
  40.  * the already-existing background of the window at 70% normal opacity.
  41.  */
  42. static gboolean
  43. window_draw_event   (GtkWidget      *widget,
  44.                      cairo_t        *cr,
  45.                      gpointer        data)
  46. {
  47.   GtkWidget *child;
  48.   /* get our child (in this case, the event box) */
  49.   child = gtk_bin_get_child (GTK_BIN (widget));
  50.   /* draw the background image first */
  51.   cairo_set_source_surface
  52.     (cr, (cairo_surface_t*)data, 0, 0);
  53.   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
  54.   cairo_paint(cr);
  55.   /* now draw the event box */
  56.   gint border_width =
  57.     gtk_container_get_border_width(GTK_CONTAINER(widget));
  58.   gdk_cairo_set_source_window (cr, gtk_widget_get_window(child),
  59.                                border_width,
  60.                                border_width);
  61.   /* composite, with a 70% opacity */
  62.   cairo_paint_with_alpha (cr, 0.7);
  63.   /* we're done */
  64.   return FALSE;
  65. }
  66. int
  67. main (int argc, char **argv)
  68. {
  69.   GtkWidget *window, *event, *button1, *button2, *checkbox, *box;
  70.   GdkScreen *screen;
  71.   GdkRGBA transparent = { 0, 0, 0, 0 };
  72.  
  73.   gtk_init (&argc, &argv);
  74.  
  75.   cairo_surface_t *bg_image =
  76.     cairo_image_surface_create_from_png("background.png");
  77.   cairo_surface_t *bg_scaled_image
  78.     = scale_surface(bg_image, WINDOW_W, WINDOW_H, TRUE);
  79.   cairo_surface_destroy(bg_image);
  80.   /* Make the widgets */
  81.   button1 = gtk_button_new_with_label ("Label");
  82.   button2 = gtk_button_new_from_stock (GTK_STOCK_ABOUT);
  83.   checkbox = gtk_check_button_new_with_label ("Checkbox");
  84.  
  85.   box = gtk_vbox_new(FALSE, 8);
  86.   gtk_box_pack_start(GTK_BOX(box), button1, FALSE, FALSE, 8);
  87.   gtk_box_pack_start(GTK_BOX(box), button2, FALSE, FALSE, 8);
  88.   gtk_box_pack_start(GTK_BOX(box), checkbox, FALSE, FALSE, 8);
  89.  
  90.   event = gtk_event_box_new ();
  91.   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  92.   screen = gtk_widget_get_screen (event);
  93.   gtk_widget_override_background_color(event, 0, &transparent);
  94.   /* Put them inside one another */
  95.   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
  96.   gtk_container_add (GTK_CONTAINER (window), event);
  97.   gtk_container_add (GTK_CONTAINER (event), box);
  98.   /* Since rescaling the background is expensive, you better fix the widget size */
  99.   gtk_widget_set_size_request(window, WINDOW_W, WINDOW_H);
  100.   gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
  101.   /* Realise and show everything */
  102.   gtk_widget_show_all (window);
  103.  
  104.   /* Set the event box GdkWindow to be composited.
  105.    * Obviously must be performed after event box is realised.
  106.    */
  107.   gdk_window_set_composited (gtk_widget_get_window(event), TRUE);
  108.   /* Set up the compositing handler.
  109.    * Note that we do _after_ so that the normal (red) background is drawn
  110.    * by gtk before our compositing occurs.
  111.    */
  112.   g_signal_connect_after (window, "draw",
  113.                           G_CALLBACK (window_draw_event), bg_scaled_image);
  114.   g_signal_connect_swapped(G_OBJECT(window), "destroy",
  115.         G_CALLBACK(gtk_main_quit), G_OBJECT(window));
  116.  
  117.   gtk_main ();
  118.   return 0;
  119. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement