Control: tags -1 + patch

Please find attached a patch which I tested as much as I can.  I
considered switching from Xft to Pango and doing the drawing with
PangoCairo but its API does not allow access to some features
(autohinting, subpixel smoothing, etc.) so that would reduce the
program's functionality.

The patch also fixes some other issues:

  * Missing sentinels in some fontconfig variadic functions
  * Some memory leaks
  * Duplicate font families in the fonts combobox
  * Garbage value as first item in the styles combobox
Description: Port to GTK 3.
Bug-Debian: https://bugs.debian.org/967509
Author: Yavor Doganov <[email protected]>
Forwarded: no
Last-Update: 2026-01-14
---

--- gwaterfall.orig/configure.ac
+++ gwaterfall/configure.ac
@@ -21,8 +21,7 @@
 AC_PROG_CC
 AC_PROG_LIBTOOL
 
-# no need to check for fontconfig, xft brings it in
-PKG_CHECK_MODULES(WATERFALL, gtk+-2.0 >= 2.2.0 xft >= 2.0.0)
+PKG_CHECK_MODULES(WATERFALL, gtk+-3.0 cairo-xlib fontconfig xft >= 2.0.0)
 
 AC_SUBST(WATERFALL_CFLAGS)
 AC_SUBST(WATERFALL_LIBS)
--- gwaterfall.orig/src/main.c
+++ gwaterfall/src/main.c
@@ -33,16 +33,16 @@
   FcObjectSet *set;
   FcPattern *pattern;
   FcFontSet *list;
-  GList *styles = NULL;
-  FcChar8 *style;
+  GList *l, *styles = NULL;
+  FcChar8 *style = NULL;
   gint i;
 
   if (style_combo == NULL)
     return;
 
-  set = FcObjectSetBuild (FC_STYLE, 0);
+  set = FcObjectSetBuild (FC_STYLE, NULL);
   pattern = FcPatternBuild (0, FC_FAMILY, FcTypeString, 
-                            waterfall_get_font_family (waterfall), 0);
+                            waterfall_get_font_family (waterfall), NULL);
   g_assert (pattern != NULL);
 
   list = FcFontList (0, pattern, set);
@@ -51,41 +51,51 @@
   for (i = 0;  i < list->nfont;  i++)
     {
       FcPatternGetString (list->fonts[i], FC_STYLE, 0, &style);
-      styles = g_list_append (styles, style);
+      if (style)
+        styles = g_list_append (styles, style);
     }
 
   if (styles)
-    gtk_combo_set_popdown_strings (GTK_COMBO (style_combo), styles);
+    for (l = styles; l; l = l->next)
+        gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (style_combo),
+                                        l->data);
+
+  gtk_combo_box_set_active (GTK_COMBO_BOX (style_combo), 0);
+  g_list_free (styles);
   FcFontSetDestroy (list);
 }
 
 
 static void
-family_changed (GtkEntry *entry,
+family_changed (GtkComboBox *combo,
                 Waterfall *waterfall)
 {
-  const gchar *new_family = gtk_entry_get_text (entry);
+  gchar *new_family
+    = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combo));
 
   /* ignore empty string (it sends these a lot) */
   if (new_family[0] == '\0')
     return;
 
   waterfall_set_font_family (waterfall, new_family);
+  g_free (new_family);
   set_style_choices (waterfall);
 }
 
 
 static void
-style_changed (GtkEntry *entry,
+style_changed (GtkComboBox *combo,
                Waterfall *waterfall)
 {
-  const gchar *new_style = gtk_entry_get_text (entry);
+  gchar *new_style
+    = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combo));
 
   /* ignore empty string (it sends these a lot) */
   if (new_style[0] == '\0')
     return;
 
   waterfall_set_font_style (waterfall, new_style);
+  g_free (new_style);
 }
 
 
@@ -94,17 +104,16 @@
 {
   GtkWidget *combo;
   FcFontSet *list;
-  FcObjectSet *set = FcObjectSetBuild (FC_FAMILY, 0);
+  FcObjectSet *set = FcObjectSetBuild (FC_FAMILY, NULL);
   FcPattern *pattern = FcPatternCreate ();
-  GList *family_names = NULL;
+  GList *l, *family_names = NULL;
   FcChar8 *family_name;
   int i;
 
-  combo = gtk_combo_new ();
+  combo = gtk_combo_box_text_new ();
   gtk_widget_show (combo);
-  gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO (combo)->entry), FALSE);
 
-  g_signal_connect (GTK_COMBO (combo)->entry, "changed",
+  g_signal_connect (combo, "changed",
                     G_CALLBACK (family_changed), waterfall);
 
   list = FcFontList (0, pattern, set);
@@ -115,7 +124,9 @@
   for (i = 0;  i < list->nfont;  i++)
     {
       FcPatternGetString (list->fonts[i], FC_FAMILY, 0, &family_name);
-      family_names = g_list_append (family_names, family_name);
+      if (!g_list_find_custom (family_names, family_name,
+                               (GCompareFunc) FcStrCmpIgnoreCase))
+        family_names = g_list_append (family_names, family_name);
     }
   /*
   family_names = g_list_append (family_names, "Serif");
@@ -124,8 +135,11 @@
   */
 
   family_names = g_list_sort (family_names, (GCompareFunc) FcStrCmpIgnoreCase);
-  gtk_combo_set_popdown_strings (GTK_COMBO (combo), family_names);
+  for (l = family_names; l; l = l->next)
+    gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo),
+                                    l->data);
 
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
   g_list_free (family_names);
   FcFontSetDestroy (list);
 
@@ -136,12 +150,10 @@
 static GtkWidget *
 construct_font_style_chooser (Waterfall *waterfall)
 {
-  style_combo = gtk_combo_new ();
+  style_combo = gtk_combo_box_text_new ();
   gtk_widget_show (style_combo);
-  gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO (style_combo)->entry), 
-                             FALSE);
 
-  g_signal_connect (GTK_COMBO (style_combo)->entry, "changed",
+  g_signal_connect (style_combo, "changed",
                     G_CALLBACK (style_changed), waterfall);
 
   set_style_choices (waterfall);
@@ -219,11 +231,11 @@
 construct_size_bar (Waterfall *waterfall)
 {
   GtkWidget *hbox;
-  GtkObject *adjustment;
+  GtkAdjustment *adjustment;
   GtkWidget *spin_button;
   GtkWidget *label;
 
-  hbox = gtk_hbox_new (FALSE, 12);
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
   gtk_widget_show (hbox);
 
   label = gtk_label_new ("Smallest:");
@@ -270,11 +282,11 @@
 construct_aspect_bar (Waterfall *waterfall)
 {
   GtkWidget *hbox;
-  GtkObject *adjustment;
+  GtkAdjustment *adjustment;
   GtkWidget *spin_button;
   GtkWidget *label;
 
-  hbox = gtk_hbox_new (FALSE, 6);
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
   gtk_widget_show (hbox);
 
   label = gtk_label_new ("Aspect:");
@@ -388,7 +400,7 @@
   GtkWidget *hbox;
   GtkWidget *button;
 
-  hbox = gtk_hbox_new (FALSE, 3);
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
   gtk_widget_show (hbox);
 
   button = gtk_button_new_with_label (" <<< ");
@@ -444,42 +456,30 @@
 
 
 static void
-set_rgba_none (GtkMenuItem *menu_item,
-               Waterfall *waterfall)
-{
-  waterfall_set_rgba (waterfall, FC_RGBA_NONE);
-}
-
-
-static void
-set_rgba_rgb (GtkMenuItem *menu_item,
-              Waterfall *waterfall)
+set_rgba (GtkComboBox *combo,
+          Waterfall *waterfall)
 {
-  waterfall_set_rgba (waterfall, FC_RGBA_RGB);
-}
-
-
-static void
-set_rgba_bgr (GtkMenuItem *menu_item,
-              Waterfall *waterfall)
-{
-  waterfall_set_rgba (waterfall, FC_RGBA_BGR);
-}
-
-
-static void
-set_rgba_vrgb (GtkMenuItem *menu_item,
-               Waterfall *waterfall)
-{
-  waterfall_set_rgba (waterfall, FC_RGBA_VRGB);
-}
-
+  switch (gtk_combo_box_get_active (combo))
+    {
+    case 0:
+      waterfall_set_rgba (waterfall, FC_RGBA_NONE);
+      break;
+    case 1:
+      waterfall_set_rgba (waterfall, FC_RGBA_RGB);
+      break;
+    case 2:
+      waterfall_set_rgba (waterfall, FC_RGBA_BGR);
+      break;
+    case 3:
+      waterfall_set_rgba (waterfall, FC_RGBA_VRGB);
+      break;
+    case 4:
+      waterfall_set_rgba (waterfall, FC_RGBA_VBGR);
+      break;
 
-static void
-set_rgba_vbgr (GtkMenuItem *menu_item,
-               Waterfall *waterfall)
-{
-  waterfall_set_rgba (waterfall, FC_RGBA_VBGR);
+    default:
+      break;
+    }
 }
 
 
@@ -487,54 +487,27 @@
 construct_rgba_menu (Waterfall *waterfall)
 {
   GtkWidget *option_menu;
-  GtkWidget *menu;
-  GtkWidget *menu_item;
   GtkWidget *label;
 
-  rgba_hbox = gtk_hbox_new (FALSE, 6);
+  rgba_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
   gtk_widget_show (rgba_hbox);
 
   label = gtk_label_new ("Subpixel smoothing:");
   gtk_widget_show (label);
   gtk_box_pack_start (GTK_BOX (rgba_hbox), label, FALSE, FALSE, 0);
 
-  menu = gtk_menu_new ();
-  gtk_widget_show (menu);
+  option_menu = gtk_combo_box_text_new ();
+
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (option_menu), "None");
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (option_menu), "RGB");
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (option_menu), "BGR");
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (option_menu), "VRGB");
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (option_menu), "VBGR");
+  gtk_combo_box_set_active (GTK_COMBO_BOX (option_menu), 0);
+  g_signal_connect (option_menu, "changed", G_CALLBACK (set_rgba), waterfall);
 
-  menu_item = gtk_menu_item_new_with_label ("None");
-  gtk_widget_show (menu_item);
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
-  g_signal_connect (menu_item, "activate", 
-                    G_CALLBACK (set_rgba_none), waterfall);
-  
-  menu_item = gtk_menu_item_new_with_label ("RGB");
-  gtk_widget_show (menu_item);
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
-  g_signal_connect (menu_item, "activate", 
-                    G_CALLBACK (set_rgba_rgb), waterfall);
-  
-  menu_item = gtk_menu_item_new_with_label ("BGR");
-  gtk_widget_show (menu_item);
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
-  g_signal_connect (menu_item, "activate", 
-                    G_CALLBACK (set_rgba_bgr), waterfall);
-  
-  menu_item = gtk_menu_item_new_with_label ("VRGB");
-  gtk_widget_show (menu_item);
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
-  g_signal_connect (menu_item, "activate", 
-                    G_CALLBACK (set_rgba_vrgb), waterfall);
-  
-  menu_item = gtk_menu_item_new_with_label ("VBGR");
-  gtk_widget_show (menu_item);
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
-  g_signal_connect (menu_item, "activate", 
-                    G_CALLBACK (set_rgba_vbgr), waterfall);
-  
-  option_menu = gtk_option_menu_new ();
   gtk_widget_show (option_menu);
   gtk_box_pack_start (GTK_BOX (rgba_hbox), option_menu, FALSE, FALSE, 0);
-  gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
 
   gtk_widget_set_sensitive (rgba_hbox,
                             waterfall_get_antialias (waterfall));
@@ -551,10 +524,10 @@
   GtkWidget *check_button;
   GtkWidget *separator;
 
-  vbox = gtk_vbox_new (FALSE, 6);
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
   gtk_widget_show (vbox);
 
-  hbox = gtk_hbox_new (FALSE, 12);
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
   gtk_widget_show (hbox);
 
   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
@@ -567,7 +540,7 @@
                       construct_font_style_chooser (waterfall), 
                       FALSE, FALSE, 0);
 
-  separator = gtk_vseparator_new ();
+  separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
   gtk_widget_show (separator);
   gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, FALSE, 0);
 
@@ -589,7 +562,7 @@
   g_signal_connect (G_OBJECT (autohint_check_button), "toggled",
                     G_CALLBACK (autohint_toggled), waterfall);
 
-  separator = gtk_vseparator_new ();
+  separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
   gtk_widget_show (separator);
   gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, FALSE, 0);
 
@@ -604,21 +577,21 @@
   gtk_box_pack_start (GTK_BOX (hbox), construct_rgba_menu (waterfall), 
                       FALSE, FALSE, 0);
 
-  separator = gtk_vseparator_new ();
+  separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
   gtk_widget_show (separator);
   gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, FALSE, 0);
 
   gtk_box_pack_start (GTK_BOX (hbox), construct_aspect_bar (waterfall), 
                       FALSE, FALSE, 0);
 
-  hbox = gtk_hbox_new (FALSE, 12);
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
   gtk_widget_show (hbox);
   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
 
   gtk_box_pack_start (GTK_BOX (hbox), construct_size_bar (waterfall), 
                       FALSE, FALSE, 0);
 
-  separator = gtk_vseparator_new ();
+  separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
   gtk_widget_show (separator);
   gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, FALSE, 0);
 
@@ -636,7 +609,11 @@
   GtkWidget *vbox;
   GtkWidget *waterfall;
   GtkWidget *scrolled_window;
+  GtkCssProvider *css;
+  GdkMonitor *monitor;
   GdkScreen *screen;
+  GdkRectangle geom;
+  const char *css_data = "viewport * { background-color: @theme_bg_color }";
 
   gtk_init (&argc, &argv);
 
@@ -645,22 +622,31 @@
   g_signal_connect (G_OBJECT (window), "destroy",
                     G_CALLBACK (gtk_main_quit), NULL);
 
+  gtk_widget_realize (window);
   screen = gtk_window_get_screen (GTK_WINDOW (window));
+  monitor = gdk_display_get_monitor_at_window(gdk_screen_get_display (screen),
+                                              gtk_widget_get_window (window));
+  gdk_monitor_get_geometry (monitor, &geom);
   gtk_window_set_default_size (GTK_WINDOW (window),
-                               gdk_screen_get_width (screen) * 3/4,
-                               gdk_screen_get_height (screen) * 3/4);
+                               geom.width * 3/4, geom.height * 3/4);
 
-  vbox = gtk_vbox_new (FALSE, 6);
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
   gtk_widget_show (vbox);
   gtk_container_add (GTK_CONTAINER (window), vbox);
 
   waterfall = waterfall_new ();
   gtk_widget_show (waterfall);
 
+  css = gtk_css_provider_new ();
+  gtk_css_provider_load_from_data (css, css_data, -1, NULL);
+  gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (css),
+                                             GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_overlay_scrolling (GTK_SCROLLED_WINDOW
+                                             (scrolled_window), FALSE);
   gtk_widget_show (scrolled_window);
-  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window),
-                                         waterfall);
+  gtk_container_add (GTK_CONTAINER (scrolled_window), waterfall);
 
   gtk_box_pack_start (GTK_BOX (vbox), 
                       construct_options_bar (WATERFALL (waterfall)), 
--- gwaterfall.orig/src/waterfall.c
+++ gwaterfall/src/waterfall.c
@@ -18,6 +18,7 @@
 
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
+#include <cairo-xlib.h>
 #include <X11/Xft/Xft.h>
 #include <string.h>
 #include "waterfall.h"
@@ -29,6 +30,7 @@
 
 enum { BUFFER = 12 };
 
+static void queue_redraw (Waterfall *waterfall);
 
 /* buf should have at least WATERFALL_PAGE_SIZE slots */
 static void
@@ -82,15 +84,16 @@
   FcPatternAddInteger (pattern, FC_RGBA, waterfall->rgba);
   FcPatternAddDouble (pattern, FC_ASPECT, waterfall->aspect);
 
-  match = XftFontMatch (GDK_DISPLAY (), gdk_x11_get_default_screen (), 
-                        pattern, &result);
+  match = XftFontMatch (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+                        gdk_x11_get_default_screen (), pattern, &result);
 
   FcPatternDestroy (pattern);
 
   if (!match)
     return NULL;
 
-  font = XftFontOpenPattern (GDK_DISPLAY (), match);
+  font = XftFontOpenPattern (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+                             match);
   if (!font)
     FcPatternDestroy (match);
 
@@ -103,25 +106,33 @@
               gint *width,
               gint *height)
 {
+  Display *dpy;
   XGlyphInfo extents;
   gdouble lines;
   XftFont *big_font, *small_font, *theme_font;
-  gchar *buf;
+  GtkStyleContext *ctxt;
+  PangoFontDescription *desc = NULL;
+  gchar *buf, *font;
   gunichar ucs[128];
   gint ucs_len;
 
+  ctxt = gtk_widget_get_style_context (GTK_WIDGET (waterfall));
+  gtk_style_context_get (ctxt, gtk_style_context_get_state (ctxt),
+                         GTK_STYLE_PROPERTY_FONT, &desc, NULL);
+  font = pango_font_description_to_string (desc);
+  pango_font_description_free (desc);
   small_font = open_font (waterfall, waterfall->min_size);
   big_font = open_font (waterfall, waterfall->max_size);
-  theme_font = XftFontOpenName (GDK_DISPLAY (), gdk_x11_get_default_screen (), 
-                                pango_font_description_to_string (
-                                    GTK_WIDGET (waterfall)->style->font_desc));
+  dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+  theme_font = XftFontOpenName (dpy, gdk_x11_get_default_screen (), font);
+  g_free (font);
 
   get_string_for_page (waterfall, ucs, &ucs_len);
-  XftTextExtents32 (GDK_DISPLAY (), big_font, ucs, ucs_len, &extents);
+  XftTextExtents32 (dpy, big_font, ucs, ucs_len, &extents);
   *width = extents.width + BUFFER;
 
   buf = g_strdup_printf ("%5.1f", waterfall->max_size);
-  XftTextExtentsUtf8 (GDK_DISPLAY (), theme_font, buf, strlen (buf), &extents);
+  XftTextExtentsUtf8 (dpy, theme_font, buf, strlen (buf), &extents);
   *width += extents.width + BUFFER;
   g_free (buf);
 
@@ -141,9 +152,9 @@
       *height = 3000;
     }
 
-  XftFontClose (GDK_DISPLAY (), big_font);
-  XftFontClose (GDK_DISPLAY (), small_font);
-  XftFontClose (GDK_DISPLAY (), theme_font);
+  XftFontClose (dpy, big_font);
+  XftFontClose (dpy, small_font);
+  XftFontClose (dpy, theme_font);
 }
 
 
@@ -151,50 +162,65 @@
 draw_pixmap (Waterfall *waterfall)
 {
   Colormap colormap;
+  Display *dpy;
   Drawable drawable;
   Visual *visual;
+  Window w;
   gint width, height;
   XGlyphInfo extents;
   XftFont *theme_font;
-  XftColor fg;
+  XftColor fg, bg;
   XftFont *font;
   XftDraw *xftdraw;
+  GtkStyleContext *ctxt;
+  GdkRGBA *fg_rgba = NULL, *bg_rgba = NULL;
+  PangoFontDescription *desc = NULL;
   gdouble size;
   gint y;
   gint size_width; /* width allotted to "12.0", etc */
-  gchar *buf;
+  gchar *buf, *font_str;
   gunichar ucs[128];
   gint ucs_len;
+  int screen_nr;
 
-  width = GTK_WIDGET (waterfall)->allocation.width;
-  height = GTK_WIDGET (waterfall)->allocation.height;
+  ctxt = gtk_widget_get_style_context (GTK_WIDGET (waterfall));
+  width = gtk_widget_get_allocated_width (GTK_WIDGET (waterfall));
+  height = gtk_widget_get_allocated_height (GTK_WIDGET (waterfall));
+
+  gtk_style_context_get (ctxt, gtk_style_context_get_state (ctxt),
+                         GTK_STYLE_PROPERTY_FONT, &desc,
+                         GTK_STYLE_PROPERTY_COLOR, &fg_rgba,
+                         GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &bg_rgba,
+                         NULL);
+  font_str = pango_font_description_to_string (desc);
+  pango_font_description_free (desc);
+  dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+  screen_nr = gdk_x11_get_default_screen ();
+  theme_font = XftFontOpenName (dpy, screen_nr, font_str);
+  g_free (font_str);
 
-  theme_font = XftFontOpenName (GDK_DISPLAY (), gdk_x11_get_default_screen (), 
-                                pango_font_description_to_string (
-                                    GTK_WIDGET (waterfall)->style->font_desc));
-
-  waterfall->pixmap = gdk_pixmap_new (GTK_WIDGET (waterfall)->window,
-                                      width, height, -1);
-
-  gdk_draw_rectangle (GDK_DRAWABLE (waterfall->pixmap),
-                      GTK_WIDGET (waterfall)->style->base_gc[GTK_STATE_NORMAL], 
-                      TRUE, 0, 0, width, height);
-
-  colormap = gdk_x11_colormap_get_xcolormap (
-          gdk_drawable_get_colormap (GTK_WIDGET (waterfall)->window));
-  drawable = gdk_x11_drawable_get_xid (GDK_DRAWABLE (waterfall->pixmap));
+  colormap = DefaultColormap (dpy, screen_nr);
   visual = gdk_x11_visual_get_xvisual (
           gtk_widget_get_visual (GTK_WIDGET (waterfall)));
+  w = gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (waterfall)));
+  drawable = XCreatePixmap (dpy, w, width, height,
+                            DefaultDepth (dpy, screen_nr));
+  xftdraw = XftDrawCreate (dpy, drawable, visual, colormap);
+
+  fg.color.red = (int) (0.5 + CLAMP (fg_rgba->red, 0., 1.) * 65535.);
+  fg.color.green = (int) (0.5 + CLAMP (fg_rgba->green, 0., 1.) * 65535.);
+  fg.color.blue = (int) (0.5 + CLAMP (fg_rgba->blue, 0., 1.) * 65535.);
+  fg.color.alpha = (int) (0.5 + CLAMP (fg_rgba->alpha, 0., 1.) * 65535.);
+
+  bg.color.red = (int) (0.5 + CLAMP (bg_rgba->red, 0., 1.) * 65535.);
+  bg.color.green = (int) (0.5 + CLAMP (bg_rgba->green, 0., 1.) * 65535.);
+  bg.color.blue = (int) (0.5 + CLAMP (bg_rgba->blue, 0., 1.) * 65535.);
+  bg.color.alpha = (int) (0.5 + CLAMP (bg_rgba->alpha, 0., 1.) * 65535.);
 
-  xftdraw = XftDrawCreate (GDK_DISPLAY (), drawable, visual, colormap);
-
-  fg.color.red = GTK_WIDGET (waterfall)->style->fg[GTK_STATE_NORMAL].red;
-  fg.color.green = GTK_WIDGET (waterfall)->style->fg[GTK_STATE_NORMAL].green;
-  fg.color.blue = GTK_WIDGET (waterfall)->style->fg[GTK_STATE_NORMAL].blue;
-  fg.color.alpha = 0xffff;
+  XftDrawRect (xftdraw, &bg, 0, 0, width, height);
 
   buf = g_strdup_printf ("%5.1f", waterfall->max_size);
-  XftTextExtentsUtf8 (GDK_DISPLAY (), theme_font, buf, strlen (buf), &extents);
+  XftTextExtentsUtf8 (dpy, theme_font, buf, strlen (buf), &extents);
   size_width = extents.width + BUFFER;
   g_free (buf);
 
@@ -211,29 +237,27 @@
       get_string_for_page (waterfall, ucs, &ucs_len);
       XftDrawString32(xftdraw, &fg, font, size_width, y, ucs, ucs_len);
 
-      XftFontClose (GDK_DISPLAY (), font);
+      XftFontClose (dpy, font);
     }
 
-  XftFontClose (GDK_DISPLAY (), theme_font);
+  waterfall->pixmap = cairo_xlib_surface_create (dpy, drawable, visual,
+                                                 width, height);
+
+  XftFontClose (dpy, theme_font);
   XftDrawDestroy (xftdraw);
+  XFreeColormap (dpy, colormap);
 }
 
 
 static gint
-expose_event (Waterfall *waterfall,
-              GdkEventExpose *event)
+draw (Waterfall *waterfall,
+      cairo_t *cr)
 {
-  gdk_window_set_back_pixmap (GTK_WIDGET (waterfall)->window, NULL, FALSE);
-
   if (waterfall->pixmap == NULL)
     draw_pixmap (waterfall);
 
-  gdk_draw_drawable (GTK_WIDGET (waterfall)->window,
-                     GTK_WIDGET (waterfall)->style->fg_gc[GTK_STATE_NORMAL],
-                     waterfall->pixmap,
-                     event->area.x, event->area.y,
-                     event->area.x, event->area.y,
-                     event->area.width, event->area.height);
+  cairo_set_source_surface (cr, waterfall->pixmap, 0, 0);
+  cairo_paint (cr);
 
   return FALSE;
 }
@@ -243,6 +267,8 @@
 size_allocate (GtkWidget *widget,
                GtkAllocation *allocation)
 {
+  /* Trigger a full redraw if the window is resized.  */
+  queue_redraw (WATERFALL (widget));
 }
 
 
@@ -262,8 +288,8 @@
   waterfall->page = -1;
 
   gtk_widget_set_events (GTK_WIDGET (waterfall), GDK_EXPOSURE_MASK);
-  g_signal_connect (G_OBJECT (waterfall), "expose-event", 
-                    G_CALLBACK (expose_event), NULL);
+  g_signal_connect (G_OBJECT (waterfall), "draw",
+                    G_CALLBACK (draw), NULL);
   g_signal_connect (G_OBJECT (waterfall), "size-allocate",
                     G_CALLBACK (size_allocate), NULL);
 }
@@ -311,7 +337,7 @@
 
   if (waterfall->pixmap)
     {
-      g_object_unref (waterfall->pixmap);
+      cairo_surface_destroy (waterfall->pixmap);
       waterfall->pixmap = NULL;
     }
 
@@ -330,7 +356,8 @@
     g_free (waterfall->font_family);
 
   if (waterfall->font)
-    XftFontClose (GDK_DISPLAY (), waterfall->font);
+    XftFontClose (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+                  waterfall->font);
 
   waterfall->font_family = g_strdup (new_family);
   waterfall->font = open_font (waterfall, waterfall->min_size);
@@ -354,7 +381,8 @@
     g_free (waterfall->font_style);
 
   if (waterfall->font)
-    XftFontClose (GDK_DISPLAY (), waterfall->font);
+    XftFontClose (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+                  waterfall->font);
 
   waterfall->font_style = g_strdup (new_style);
   waterfall->font = open_font (waterfall, waterfall->min_size);
--- gwaterfall.orig/src/waterfall.h
+++ gwaterfall/src/waterfall.h
@@ -42,7 +42,7 @@
 {
   GtkDrawingArea parent;
 
-  GdkPixmap *pixmap;
+  cairo_surface_t *pixmap;
   XftDraw *xftdraw;
 
   gchar *font_family;

Reply via email to