chiark / gitweb /
GTK 3 port: use GdkRGBA for the window background colour.
[sgt-puzzles.git] / gtk.c
diff --git a/gtk.c b/gtk.c
index 0b2805bbadf295c068069a9b4ecc01ae55779ffa..c3c10a5af611e931f5267d84604966d2e8e3475a 100644 (file)
--- a/gtk.c
+++ b/gtk.c
@@ -39,7 +39,7 @@
 #endif
 #if GTK_CHECK_VERSION(2,8,0)
 # define USE_CAIRO
-# if defined(GDK_DISABLE_DEPRECATED)
+# if GTK_CHECK_VERSION(3,0,0) || defined(GDK_DISABLE_DEPRECATED)
 #  define USE_CAIRO_WITHOUT_PIXMAP
 # endif
 #endif
@@ -156,13 +156,15 @@ struct frontend {
 #ifdef OLD_FILESEL
     char *filesel_name;
 #endif
-    int drawing_area_shrink_pending;
     GSList *preset_radio;
     int n_preset_menu_items;
     int preset_threaded;
     GtkWidget *preset_custom;
     GtkWidget *copy_menu_item;
+#if !GTK_CHECK_VERSION(3,0,0)
+    int drawing_area_shrink_pending;
     int menubar_is_local;
+#endif
 };
 
 struct blitter {
@@ -184,10 +186,26 @@ void get_random_seed(void **randseed, int *randseedsize)
 
 void frontend_default_colour(frontend *fe, float *output)
 {
+#if !GTK_CHECK_VERSION(3,0,0)
+    /*
+     * Use the widget style's default background colour as the
+     * background for the puzzle drawing area.
+     */
     GdkColor col = gtk_widget_get_style(fe->window)->bg[GTK_STATE_NORMAL];
     output[0] = col.red / 65535.0;
     output[1] = col.green / 65535.0;
     output[2] = col.blue / 65535.0;
+#else
+    /*
+     * GTK 3 has decided that there's no such thing as a 'default
+     * background colour' any more, because widget styles might set
+     * the background to something more complicated like a background
+     * image. We don't want to get into overlaying our entire puzzle
+     * on an arbitrary background image, so we'll just make up a
+     * reasonable shade of grey.
+     */
+    output[0] = output[1] = output[2] = 0.9F;
+#endif
 }
 
 void gtk_status_bar(void *handle, char *text)
@@ -250,6 +268,15 @@ static void set_colour(frontend *fe, int colour)
 
 static void set_window_background(frontend *fe, int colour)
 {
+#if GTK_CHECK_VERSION(3,0,0)
+    GdkRGBA rgba;
+    rgba.red = fe->colours[3*colour + 0];
+    rgba.green = fe->colours[3*colour + 1];
+    rgba.blue = fe->colours[3*colour + 2];
+    rgba.alpha = 1.0;
+    gdk_window_set_background_rgba(gtk_widget_get_window(fe->area), &rgba);
+    gdk_window_set_background_rgba(gtk_widget_get_window(fe->window), &rgba);
+#else
     GdkColormap *colmap;
 
     colmap = gdk_colormap_get_system();
@@ -265,6 +292,7 @@ static void set_window_background(frontend *fe, int colour)
                               &fe->background);
     gdk_window_set_background(gtk_widget_get_window(fe->window),
                               &fe->background);
+#endif
 }
 
 static PangoLayout *make_pango_layout(frontend *fe)
@@ -1198,6 +1226,21 @@ static gint motion_event(GtkWidget *widget, GdkEventMotion *event,
     return TRUE;
 }
 
+#if GTK_CHECK_VERSION(3,0,0)
+static gint draw_area(GtkWidget *widget, cairo_t *cr, gpointer data)
+{
+    frontend *fe = (frontend *)data;
+    GdkRectangle dirtyrect;
+
+    gdk_cairo_get_clip_rectangle(cr, &dirtyrect);
+    cairo_set_source_surface(cr, fe->image, fe->ox, fe->oy);
+    cairo_rectangle(cr, dirtyrect.x, dirtyrect.y,
+                    dirtyrect.width, dirtyrect.height);
+    cairo_fill(cr);
+
+    return TRUE;
+}
+#else
 static gint expose_area(GtkWidget *widget, GdkEventExpose *event,
                         gpointer data)
 {
@@ -1219,6 +1262,7 @@ static gint expose_area(GtkWidget *widget, GdkEventExpose *event,
     }
     return TRUE;
 }
+#endif
 
 static gint map_window(GtkWidget *widget, GdkEvent *event,
                       gpointer data)
@@ -1505,7 +1549,11 @@ static int get_config(frontend *fe, int which)
     g_signal_connect(G_OBJECT(w), "clicked",
                      G_CALLBACK(config_ok_button_clicked), fe);
 
+#if GTK_CHECK_VERSION(3,0,0)
+    table = gtk_grid_new();
+#else
     table = gtk_table_new(1, 2, FALSE);
+#endif
     y = 0;
     gtk_box_pack_start
         (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(fe->cfgbox))),
@@ -1513,7 +1561,9 @@ static int get_config(frontend *fe, int which)
     gtk_widget_show(table);
 
     for (i = fe->cfg; i->type != C_END; i++) {
+#if !GTK_CHECK_VERSION(3,0,0)
        gtk_table_resize(GTK_TABLE(table), y+1, 2);
+#endif
 
        switch (i->type) {
          case C_STRING:
@@ -1523,17 +1573,26 @@ static int get_config(frontend *fe, int which)
 
            w = gtk_label_new(i->name);
            gtk_misc_set_alignment(GTK_MISC(w), 0.0, 0.5);
+#if GTK_CHECK_VERSION(3,0,0)
+            gtk_grid_attach(GTK_GRID(table), w, 0, y, 1, 1);
+#else
            gtk_table_attach(GTK_TABLE(table), w, 0, 1, y, y+1,
                             GTK_SHRINK | GTK_FILL,
                             GTK_EXPAND | GTK_SHRINK | GTK_FILL,
                             3, 3);
+#endif
            gtk_widget_show(w);
 
            w = gtk_entry_new();
+#if GTK_CHECK_VERSION(3,0,0)
+            gtk_grid_attach(GTK_GRID(table), w, 1, y, 1, 1);
+            g_object_set(G_OBJECT(w), "hexpand", TRUE, (const char *)NULL);
+#else
            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);
+#endif
            gtk_entry_set_text(GTK_ENTRY(w), i->sval);
            g_signal_connect(G_OBJECT(w), "changed",
                              G_CALLBACK(editbox_changed), i);
@@ -1550,10 +1609,15 @@ static int get_config(frontend *fe, int which)
             w = gtk_check_button_new_with_label(i->name);
            g_signal_connect(G_OBJECT(w), "toggled",
                              G_CALLBACK(button_toggled), i);
+#if GTK_CHECK_VERSION(3,0,0)
+            gtk_grid_attach(GTK_GRID(table), w, 0, y, 2, 1);
+            g_object_set(G_OBJECT(w), "hexpand", TRUE, (const char *)NULL);
+#else
            gtk_table_attach(GTK_TABLE(table), w, 0, 2, y, y+1,
                             GTK_EXPAND | GTK_SHRINK | GTK_FILL,
                             GTK_EXPAND | GTK_SHRINK | GTK_FILL,
                             3, 3);
+#endif
            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), i->ival);
            gtk_widget_show(w);
            break;
@@ -1565,10 +1629,14 @@ static int get_config(frontend *fe, int which)
 
            w = gtk_label_new(i->name);
            gtk_misc_set_alignment(GTK_MISC(w), 0.0, 0.5);
+#if GTK_CHECK_VERSION(3,0,0)
+            gtk_grid_attach(GTK_GRID(table), w, 0, y, 1, 1);
+#else
            gtk_table_attach(GTK_TABLE(table), w, 0, 1, y, y+1,
                             GTK_SHRINK | GTK_FILL,
                             GTK_EXPAND | GTK_SHRINK | GTK_FILL ,
                             3, 3);
+#endif
            gtk_widget_show(w);
 
             {
@@ -1613,10 +1681,15 @@ static int get_config(frontend *fe, int which)
                                 G_CALLBACK(droplist_sel), i);
             }
 
+#if GTK_CHECK_VERSION(3,0,0)
+            gtk_grid_attach(GTK_GRID(table), w, 1, y, 1, 1);
+            g_object_set(G_OBJECT(w), "hexpand", TRUE, (const char *)NULL);
+#else
            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);
+#endif
            gtk_widget_show(w);
            break;
        }
@@ -1718,6 +1791,7 @@ static void changed_preset(frontend *fe)
     }
 }
 
+#if !GTK_CHECK_VERSION(3,0,0)
 static gboolean not_size_allocated_yet(GtkWidget *w)
 {
     /*
@@ -1766,18 +1840,21 @@ static void try_shrink_drawing_area(frontend *fe)
         fe->drawing_area_shrink_pending = FALSE;
     }
 }
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
 
 static gint configure_window(GtkWidget *widget,
                              GdkEventConfigure *event, gpointer data)
 {
-    frontend *fe = (frontend *)data;
+#if !GTK_CHECK_VERSION(3,0,0)
     /*
      * When the main puzzle window changes size, it might be because
      * the menu bar or status bar has turned up after starting off
      * absent, in which case we should have another go at enacting a
      * pending shrink of the drawing area.
      */
+    frontend *fe = (frontend *)data;
     try_shrink_drawing_area(fe);
+#endif
     return FALSE;
 }
 
@@ -1786,6 +1863,10 @@ static void resize_fe(frontend *fe)
     int x, y;
 
     get_size(fe, &x, &y);
+
+#if GTK_CHECK_VERSION(3,0,0)
+    gtk_window_resize_to_geometry(GTK_WINDOW(fe->window), x, y);
+#else
     fe->w = x;
     fe->h = y;
     fe->drawing_area_shrink_pending = FALSE;
@@ -1797,6 +1878,7 @@ static void resize_fe(frontend *fe)
     }
     fe->drawing_area_shrink_pending = TRUE;
     try_shrink_drawing_area(fe);
+#endif
 }
 
 static void menu_preset_event(GtkMenuItem *menuitem, gpointer data)
@@ -2226,6 +2308,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
        midend_new_game(fe->me);
     }
 
+#if !GTK_CHECK_VERSION(3,0,0)
     {
         /*
          * try_shrink_drawing_area() will do some fiddling with the
@@ -2252,6 +2335,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
             fe->menubar_is_local = !unity_mode;
         }
     }
+#endif
 
     fe->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
     gtk_window_set_title(GTK_WINDOW(fe->window), thegame.name);
@@ -2469,9 +2553,19 @@ static frontend *new_window(char *arg, int argtype, char **error)
 #if GTK_CHECK_VERSION(2,0,0)
     gtk_widget_set_double_buffered(fe->area, FALSE);
 #endif
+    {
+        GdkGeometry geom;
+        geom.base_width = geom.base_height = 0;
+        gtk_window_set_geometry_hints(GTK_WINDOW(fe->window), fe->area,
+                                      &geom, GDK_HINT_BASE_SIZE);
+    }
     get_size(fe, &x, &y);
+#if GTK_CHECK_VERSION(3,0,0)
+    gtk_window_set_default_geometry(GTK_WINDOW(fe->window), x, y);
+#else
     fe->drawing_area_shrink_pending = FALSE;
     gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y);
+#endif
     fe->w = x;
     fe->h = y;
 
@@ -2498,8 +2592,13 @@ static frontend *new_window(char *arg, int argtype, char **error)
                      G_CALLBACK(selection_get), fe);
     g_signal_connect(G_OBJECT(fe->area), "selection_clear_event",
                      G_CALLBACK(selection_clear), fe);
+#if GTK_CHECK_VERSION(3,0,0)
+    g_signal_connect(G_OBJECT(fe->area), "draw",
+                     G_CALLBACK(draw_area), fe);
+#else
     g_signal_connect(G_OBJECT(fe->area), "expose_event",
                      G_CALLBACK(expose_area), fe);
+#endif
     g_signal_connect(G_OBJECT(fe->window), "map_event",
                      G_CALLBACK(map_window), fe);
     g_signal_connect(G_OBJECT(fe->area), "configure_event",
@@ -2531,8 +2630,11 @@ static frontend *new_window(char *arg, int argtype, char **error)
     gtk_widget_show(fe->area);
     gtk_widget_show(fe->window);
 
+#if !GTK_CHECK_VERSION(3,0,0)
     fe->drawing_area_shrink_pending = TRUE;
     try_shrink_drawing_area(fe);
+#endif
+
     set_window_background(fe, 0);
 
     return fe;