chiark / gitweb /
GTK 3 prep: make the server-side backing pixmap optional.
[sgt-puzzles.git] / gtk.c
diff --git a/gtk.c b/gtk.c
index 9860ed66f121cb10316127da10b8ea42ba6ca896..29c757ce14d8ece683cf7de3eb939fb96a46e104 100644 (file)
--- a/gtk.c
+++ b/gtk.c
@@ -39,6 +39,9 @@
 #endif
 #if GTK_CHECK_VERSION(2,8,0)
 # define USE_CAIRO
+# if defined(GDK_DISABLE_DEPRECATED)
+#  define USE_CAIRO_WITHOUT_PIXMAP
+# endif
 #endif
 
 /* #undef USE_CAIRO */
@@ -126,7 +129,9 @@ struct frontend {
     const float *colours;
     cairo_t *cr;
     cairo_surface_t *image;
+#ifndef USE_CAIRO_WITHOUT_PIXMAP
     GdkPixmap *pixmap;
+#endif
     GdkColor background;              /* for painting outside puzzle area */
 #else
     GdkPixmap *pixmap;
@@ -212,20 +217,22 @@ static void setup_drawing(frontend *fe)
 
 static void teardown_drawing(frontend *fe)
 {
-    cairo_t *cr;
-
     cairo_destroy(fe->cr);
     fe->cr = NULL;
 
-    cr = gdk_cairo_create(fe->pixmap);
-    cairo_set_source_surface(cr, fe->image, 0, 0);
-    cairo_rectangle(cr,
-                   fe->bbox_l - 1,
-                   fe->bbox_u - 1,
-                   fe->bbox_r - fe->bbox_l + 2,
-                   fe->bbox_d - fe->bbox_u + 2);
-    cairo_fill(cr);
-    cairo_destroy(cr);
+#ifndef USE_CAIRO_WITHOUT_PIXMAP
+    {
+        cairo_t *cr = gdk_cairo_create(fe->pixmap);
+        cairo_set_source_surface(cr, fe->image, 0, 0);
+        cairo_rectangle(cr,
+                        fe->bbox_l - 1,
+                        fe->bbox_u - 1,
+                        fe->bbox_r - fe->bbox_l + 2,
+                        fe->bbox_d - fe->bbox_u + 2);
+        cairo_fill(cr);
+        cairo_destroy(cr);
+    }
+#endif
 }
 
 static void snaffle_colours(frontend *fe)
@@ -382,28 +389,28 @@ static void clear_backing_store(frontend *fe)
     fe->image = NULL;
 }
 
-static void setup_backing_store(frontend *fe)
+static void wipe_and_destroy_cairo(frontend *fe, cairo_t *cr)
 {
-    cairo_t *cr;
-    int i;
+    cairo_set_source_rgb(cr, fe->colours[0], fe->colours[1], fe->colours[2]);
+    cairo_paint(cr);
+    cairo_destroy(cr);
+}
 
+static void setup_backing_store(frontend *fe)
+{
+#ifndef USE_CAIRO_WITHOUT_PIXMAP
     fe->pixmap = gdk_pixmap_new(gtk_widget_get_window(fe->area),
                                 fe->pw, fe->ph, -1);
+#endif
     fe->image = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
                                           fe->pw, fe->ph);
 
-    for (i = 0; i < 3; i++) {
-       switch (i) {
-           case 0: cr = cairo_create(fe->image); break;
-           case 1: cr = gdk_cairo_create(fe->pixmap); break;
-           case 2: cr = gdk_cairo_create(gtk_widget_get_window(fe->area));
-              break;
-       }
-       cairo_set_source_rgb(cr,
-                            fe->colours[0], fe->colours[1], fe->colours[2]);
-       cairo_paint(cr);
-       cairo_destroy(cr);
-    }
+    wipe_and_destroy_cairo(fe, cairo_create(fe->image));
+#ifndef USE_CAIRO_WITHOUT_PIXMAP
+    wipe_and_destroy_cairo(fe, gdk_cairo_create(fe->pixmap));
+#endif
+    wipe_and_destroy_cairo(fe, gdk_cairo_create
+                           (gtk_widget_get_window(fe->area)));
 }
 
 static int backing_store_ok(frontend *fe)
@@ -414,7 +421,9 @@ static int backing_store_ok(frontend *fe)
 static void teardown_backing_store(frontend *fe)
 {
     cairo_surface_destroy(fe->image);
+#ifndef USE_CAIRO_WITHOUT_PIXMAP
     gdk_pixmap_unref(fe->pixmap);
+#endif
     fe->image = NULL;
 }
 
@@ -668,6 +677,7 @@ static void teardown_backing_store(frontend *fe)
 
 #endif
 
+#ifndef USE_CAIRO_WITHOUT_PIXMAP
 static void repaint_rectangle(frontend *fe, GtkWidget *widget,
                              int x, int y, int w, int h)
 {
@@ -703,6 +713,7 @@ static void repaint_rectangle(frontend *fe, GtkWidget *widget,
                    x - fe->ox, y - fe->oy, x, y, w, h);
     gdk_gc_unref(gc);
 }
+#endif
 
 /* ----------------------------------------------------------------------
  * Pango font functions.
@@ -983,11 +994,19 @@ void gtk_end_draw(void *handle)
     teardown_drawing(fe);
 
     if (fe->bbox_l < fe->bbox_r && fe->bbox_u < fe->bbox_d) {
+#ifdef USE_CAIRO_WITHOUT_PIXMAP
+        gtk_widget_queue_draw_area(fe->area,
+                                   fe->bbox_l - 1 + fe->ox,
+                                   fe->bbox_u - 1 + fe->oy,
+                                   fe->bbox_r - fe->bbox_l + 2,
+                                   fe->bbox_d - fe->bbox_u + 2);
+#else
        repaint_rectangle(fe, fe->area,
                          fe->bbox_l - 1 + fe->ox,
                          fe->bbox_u - 1 + fe->oy,
                          fe->bbox_r - fe->bbox_l + 2,
                          fe->bbox_d - fe->bbox_u + 2);
+#endif
     }
 }
 
@@ -1185,9 +1204,18 @@ static gint expose_area(GtkWidget *widget, GdkEventExpose *event,
     frontend *fe = (frontend *)data;
 
     if (backing_store_ok(fe)) {
+#ifdef USE_CAIRO_WITHOUT_PIXMAP
+        cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(widget));
+        cairo_set_source_surface(cr, fe->image, fe->ox, fe->oy);
+        cairo_rectangle(cr, event->area.x, event->area.y,
+                        event->area.width, event->area.height);
+        cairo_fill(cr);
+        cairo_destroy(cr);
+#else
        repaint_rectangle(fe, widget,
                          event->area.x, event->area.y,
                          event->area.width, event->area.height);
+#endif
     }
     return TRUE;
 }
@@ -1436,11 +1464,11 @@ static void button_toggled(GtkToggleButton *tb, gpointer data)
     i->ival = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tb));
 }
 
-static void droplist_sel(GtkMenuItem *item, gpointer data)
+static void droplist_sel(GtkComboBox *combo, gpointer data)
 {
     config_item *i = (config_item *)data;
 
-    i->ival = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item), "user-data"));
+    i->ival = gtk_combo_box_get_active(combo);
 }
 
 static int get_config(frontend *fe, int which)
@@ -1532,7 +1560,7 @@ static int get_config(frontend *fe, int which)
 
          case C_CHOICES:
            /*
-            * Drop-down list (GtkOptionMenu).
+            * Drop-down list (GtkComboBox).
             */
 
            w = gtk_label_new(i->name);
@@ -1543,24 +1571,17 @@ static int get_config(frontend *fe, int which)
                             3, 3);
            gtk_widget_show(w);
 
-           w = gtk_option_menu_new();
-           gtk_table_attach(GTK_TABLE(table), w, 1, 2, y, y+1,
-                            GTK_EXPAND | GTK_SHRINK | GTK_FILL,
-                            GTK_EXPAND | GTK_SHRINK | GTK_FILL,
-                            3, 3);
-           gtk_widget_show(w);
-
-           {
-               int c, val;
+            {
+               int c;
                char *p, *q, *name;
-               GtkWidget *menuitem;
-               GtkWidget *menu = gtk_menu_new();
+                GtkListStore *model;
+               GtkCellRenderer *cr;
+                GtkTreeIter iter;
 
-               gtk_option_menu_set_menu(GTK_OPTION_MENU(w), menu);
+                model = gtk_list_store_new(1, G_TYPE_STRING);
 
                c = *i->sval;
                p = i->sval+1;
-               val = 0;
 
                while (*p) {
                    q = p;
@@ -1573,22 +1594,30 @@ static int get_config(frontend *fe, int which)
 
                    if (*q) q++;       /* eat delimiter */
 
-                   menuitem = gtk_menu_item_new_with_label(name);
-                   gtk_container_add(GTK_CONTAINER(menu), menuitem);
-                   g_object_set_data(G_OBJECT(menuitem), "user-data",
-                                      GINT_TO_POINTER(val));
-                   g_signal_connect(G_OBJECT(menuitem), "activate",
-                                     G_CALLBACK(droplist_sel), i);
-                   gtk_widget_show(menuitem);
-
-                   val++;
+                    gtk_list_store_append(model, &iter);
+                    gtk_list_store_set(model, &iter, 0, name, -1);
 
                    p = q;
                }
 
-               gtk_option_menu_set_history(GTK_OPTION_MENU(w), i->ival);
-           }
+                w = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
+
+               gtk_combo_box_set_active(GTK_COMBO_BOX(w), i->ival);
+
+               cr = gtk_cell_renderer_text_new();
+               gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(w), cr, TRUE);
+               gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(w), cr,
+                                              "text", 0, NULL);
+
+               g_signal_connect(G_OBJECT(w), "changed",
+                                G_CALLBACK(droplist_sel), i);
+            }
 
+           gtk_table_attach(GTK_TABLE(table), w, 1, 2, y, y+1,
+                            GTK_EXPAND | GTK_SHRINK | GTK_FILL,
+                            GTK_EXPAND | GTK_SHRINK | GTK_FILL,
+                            3, 3);
+           gtk_widget_show(w);
            break;
        }
 
@@ -2298,7 +2327,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
            menuitem =
                gtk_radio_menu_item_new_with_label(fe->preset_radio, name);
            fe->preset_radio =
-               gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(menuitem));
+               gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem));
            fe->n_preset_menu_items++;
             gtk_container_add(GTK_CONTAINER(submenu), menuitem);
             g_object_set_data(G_OBJECT(menuitem), "user-data", params);
@@ -2312,7 +2341,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
                gtk_radio_menu_item_new_with_label(fe->preset_radio,
                                                   "Custom...");
            fe->preset_radio =
-               gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(menuitem));
+               gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem));
             gtk_container_add(GTK_CONTAINER(submenu), menuitem);
             g_object_set_data(G_OBJECT(menuitem), "user-data",
                               GINT_TO_POINTER(CFG_SETTINGS));