Add Gtk+-3 support
authorHugo Villeneuve <hugo@hugovil.com>
Sun, 21 Dec 2014 23:32:35 +0000 (18:32 -0500)
committerHugo Villeneuve <hugo@hugovil.com>
Sun, 24 Apr 2016 22:31:09 +0000 (18:31 -0400)
configure.ac
src/clock.c
src/dockapp.c

index 28892cc..85b50b0 100644 (file)
@@ -33,8 +33,67 @@ dnl Checking for X11 library.
 AC_CHECK_LIB(X11, XOpenDisplay, LIBS="${LIBS} -lX11",
              echo "Can't find X11 library" ; exit 1, "${X_LIBS}")
 
-dnl Checks for Gtk+-2.0
-PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.8, CFLAGS="${CFLAGS} -DGDK_PIXBUF_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED")
+dnl --with-gtk3 option
+with_gtk3=no
+
+dnl Checks for Gtk+ (version 3 or 2)
+GTK_TOOLKIT=
+check_gtk2=no
+gtk3_pkg_errors=
+
+dnl First test if Gtk+-3 is available
+GLIB_REQUIRED=2.28
+GTK_REQUIRED=3.10
+GTK_MODULES="gtk+-3.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED"
+PKG_CHECK_MODULES(GTK3, $GTK_MODULES, pkg_check_gtk=yes, pkg_check_gtk=no)
+
+if test "$pkg_check_gtk" = "no" && test "$with_gtk3" = "yes"; then
+    dnl Error if Gtk+-3 was explicitely requested, but is not found
+    AC_MSG_ERROR($GTK3_PKG_ERRORS)
+fi
+if test "$pkg_check_gtk" = "yes"; then
+    AC_DEFINE(HAVE_GTK3, 1, [Define to 1 if using GTK 3 or later.])
+    GTK_TOOLKIT="GTK3"
+    if test "x$ac_enable_gtk_deprecation_warnings" = x; then
+    AC_DEFINE([GDK_DISABLE_DEPRECATION_WARNINGS], [1],
+        [Define to 1 to disable GTK+/GDK deprecation warnings.])
+    AC_DEFINE([GLIB_DISABLE_DEPRECATION_WARNINGS], [1],
+        [Define to 1 to disable Glib deprecation warnings.])
+    fi
+else
+    dnl Gtk+-3 was not found, try to find Gtk+-2
+    check_gtk2=yes
+    gtk3_pkg_errors="$GTK3_PKG_ERRORS "
+fi
+
+if test "${with_gtk2}" = "yes" || test "$check_gtk2" = "yes"; then
+    dnl Test if Gtk+-2 is available
+    GLIB_REQUIRED=2.10
+    GTK_REQUIRED=2.8
+    GTK_MODULES="gtk+-2.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED"
+    PKG_CHECK_MODULES(GTK2, $GTK_MODULES, pkg_check_gtk=yes, pkg_check_gtk=no)
+    if test "$pkg_check_gtk" = "no" && test "$with_gtk2" = "yes"; then
+      AC_MSG_ERROR($gtk3_pkg_errors$GTK2_PKG_ERRORS)
+    fi
+    if test "$pkg_check_gtk" = "yes"; then
+        AC_DEFINE(HAVE_GTK2, 1, [Define to 1 if using GTK 2.])
+        GTK_TOOLKIT="GTK2"
+    fi
+fi
+
+if test "${GTK_TOOLKIT}" = "GTK3"; then
+    GTK_CFLAGS=$GTK3_CFLAGS
+    GTK_LIBS=$GTK3_LIBS
+else
+if test "${GTK_TOOLKIT}" = "GTK2"; then
+    GTK_CFLAGS=$GTK2_CFLAGS
+    GTK_LIBS=$GTK2_LIBS
+else
+    dnl Error, no Gtk+-3 or Gtk+-2 was found
+    AC_MSG_ERROR([No suitable Gtk+ version found])
+fi
+fi
+
 AC_SUBST(GTK_CFLAGS)
 AC_SUBST(GTK_LIBS)
 
index 05964b5..3fa1d36 100644 (file)
 /* Starting mode is clock mode */
 static int hvclock_mode = CLOCK_MODE;
 
+#if defined (HAVE_GTK2)
 /* In preparation for Gtk+-3 support. */
 #define gtk_widget_get_allocated_width(_widget_) _widget_->allocation.width
 #define gtk_widget_get_allocated_height(_widget_) _widget_->allocation.height
+#endif
 
 static double
 get_clock_face_radius(GtkWidget *clock)
@@ -377,16 +379,32 @@ draw_calendar(GtkWidget *clock, cairo_t *cr)
 }
 
 static gboolean
+#if defined (HAVE_GTK2)
 hvclock_expose(GtkWidget *clock, GdkEventExpose *event)
+#elif defined (HAVE_GTK3)
+draw_handler(GtkWidget *clock, cairo_t *cr, gpointer d G_GNUC_UNUSED)
+#endif
 {
+#if defined (HAVE_GTK2)
        cairo_t *cr;
+#elif defined (HAVE_GTK3)
+       GdkRectangle rect;
+#endif
 
+#if defined (HAVE_GTK2)
        /* Get a cairo_t */
        cr = gdk_cairo_create(gtk_widget_get_window(clock));
 
        cairo_rectangle(cr, event->area.x, event->area.y,
-                       event->area.width, event->area.height);
+               event->area.width, event->area.height);
+#elif defined (HAVE_GTK3)
+       gdk_cairo_get_clip_rectangle(cr, &rect);
+       printf("Redrawing (%d,%d+%d+%d)\n", rect.x, rect.y,
+              rect.width, rect.height);
+
+       cairo_rectangle(cr, rect.x, rect.y, rect.width, rect.height);
        cairo_clip(cr);
+#endif
 
        if (hvclock_mode == CLOCK_MODE) {
                dockapp_set_mask(clock, clock_mask_xpm);
@@ -397,25 +415,36 @@ hvclock_expose(GtkWidget *clock, GdkEventExpose *event)
                draw_calendar(clock, cr);
        }
 
-       cairo_destroy(cr);
-
        return TRUE;
 }
 
 static void
 hvclock_redraw_canvas(GtkWidget *widget)
 {
+#if defined (HAVE_GTK2)
        GdkRegion *region;
+#elif defined (HAVE_GTK3)
+       cairo_region_t *region;
+#endif
 
        if (!gtk_widget_get_window(widget))
                return;
 
+#if defined (HAVE_GTK2)
        region = gdk_drawable_get_clip_region(gtk_widget_get_window(widget));
+#elif defined (HAVE_GTK3)
+       region = gdk_window_get_clip_region(gtk_widget_get_window(widget));
+#endif
+
        /* redraw the cairo canvas completely by exposing it */
        gdk_window_invalidate_region(gtk_widget_get_window(widget), region, TRUE);
        gdk_window_process_updates(gtk_widget_get_window(widget), TRUE);
 
+#if defined (HAVE_GTK2)
        gdk_region_destroy(region);
+#elif defined (HAVE_GTK3)
+       cairo_region_destroy(region);
+#endif
 }
 
 static gboolean
@@ -481,9 +510,13 @@ hvclock_init(GtkWidget *win)
                              GDK_BUTTON_RELEASE_MASK |
                              GDK_POINTER_MOTION_MASK);
 
+#if defined (HAVE_GTK2)
        g_signal_connect(G_OBJECT(win), "expose-event",
                         G_CALLBACK(hvclock_expose), NULL);
-
+#elif defined (HAVE_GTK3)
+       g_signal_connect(G_OBJECT(win), "draw",
+                        G_CALLBACK(draw_handler), NULL);
+#endif
        g_signal_connect(G_OBJECT(win), "button-press-event",
                         G_CALLBACK(hvclock_button_release), NULL);
        g_signal_connect(G_OBJECT(win), "button-release-event",
index 8ded719..f01c9f9 100644 (file)
 #ifdef GTK_WITHDRAWN_HACK
 
 static void
-dockapp_set_withdrawn_state(Display *d, Window w)
+dockapp_set_withdrawn_state(Display *d, Window mw, Window iw)
 {
        XWMHints *hints;
 
-       hints = XGetWMHints(d, w);
-       hints->flags |= StateHint;
-       hints->initial_state = WithdrawnState;
-       XSetWMHints(d, w, hints);
+       hints = XGetWMHints(d, mw);
+       if (!hints) {
+               hints = XAllocWMHints();
+       }
+       hints->flags |= IconWindowHint;
+        hints->icon_window = iw;
+       XSetWMHints(d, mw, hints);
        XFree(hints);
 }
 
@@ -68,22 +71,22 @@ dockapp_gtk_withdrawn_hack(GtkWidget *dockwin, GtkWidget *iconwin)
        unsigned int nchildren;
        Window win_temp;
        Window win_orig;
-
-       (void) iconwin; /* Unused parameter. */
+        Window iw;
 
        d = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
        win_orig = GDK_WINDOW_XID(gtk_widget_get_window(dockwin));
+       iw = GDK_WINDOW_XID(gtk_widget_get_window(iconwin));
 
        XQueryTree(d, win_orig, &root, &p, &children, &nchildren);
-
        if (children)
                XFree(children);
 
        win_temp = XCreateSimpleWindow(d, p, 0, 0, 1, 1, 0, 0, 0);
        XReparentWindow(d, win_orig, win_temp, 0, 0);
        gtk_widget_show(dockwin);
+        gtk_widget_show(iconwin);
 
-       dockapp_set_withdrawn_state(d, win_orig);
+       dockapp_set_withdrawn_state(d, win_orig, iw);
 
        XReparentWindow(d, win_orig, p, 0, 0);
        XDestroyWindow(d, win_temp);
@@ -95,15 +98,22 @@ void
 dockapp_set_mask(GtkWidget *iconwin, char **xpm)
 {
        GdkPixbuf *pixbuf;
+#if defined (HAVE_GTK2)
        GdkPixmap *pixmap;
        GdkBitmap *mask;
+#elif defined (HAVE_GTK3)
+       cairo_surface_t *surface;
+       cairo_region_t *shape;
+#endif
 
        pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)xpm);
+       if (!pixbuf) {
+               fprintf(stderr, "Could not load pixbuf\n");
+               exit(1);
+       }
 
+#if defined (HAVE_GTK2)
        gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap, &mask, 127);
-
-       g_object_unref(pixbuf);
-
        if (!pixmap) {
                fprintf(stderr, "Could not load pixmap\n");
                exit(1);
@@ -112,6 +122,16 @@ dockapp_set_mask(GtkWidget *iconwin, char **xpm)
        gtk_widget_shape_combine_mask(iconwin, mask, 0, 0);
        g_object_unref(mask);
        g_object_unref(pixmap);
+#elif defined (HAVE_GTK3)
+       surface = gdk_cairo_surface_create_from_pixbuf(
+               pixbuf, 0,
+               gtk_widget_get_window(iconwin));
+       shape = gdk_cairo_region_create_from_surface(surface);
+       cairo_surface_destroy(surface);
+       gtk_widget_shape_combine_region(iconwin, shape);
+       cairo_region_destroy(shape);
+#endif
+       g_object_unref(pixbuf);
 }
 
 static GtkWidget *
@@ -146,7 +166,10 @@ dockapp_init(int argc, char *argv[])
        g_signal_connect(dockwin, "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
        /* Sets the icon of dockwin as iconwin. */
-       gdk_window_set_icon(gtk_widget_get_window(dockwin), gtk_widget_get_window(iconwin), NULL, NULL);
+#if defined (HAVE_GTK2)
+       gdk_window_set_icon(gtk_widget_get_window(dockwin),
+                           gtk_widget_get_window(iconwin), NULL, NULL);
+#endif
 
        hvclock_init(iconwin);
        gtk_widget_show(iconwin);