Add Gtk+-3 support
authorHugo Villeneuve <hugo@hugovil.com>
Sat, 28 Feb 2015 22:06:58 +0000 (17:06 -0500)
committerHugo Villeneuve <hugo@hugovil.com>
Sun, 2 Jan 2022 22:43:17 +0000 (17:43 -0500)
configure.ac
src/batmon.c
src/batmon.h
src/dockapp.c

index 592d971..9482b8b 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 e8b3d73..c8781e1 100644 (file)
@@ -221,7 +221,7 @@ display_capacity(cairo_t *cr)
 }
 
 static void
-draw_background(GtkWidget *clock, cairo_t *cr)
+draw_background(cairo_t *cr)
 {
        int y_start;
        int height;
@@ -284,20 +284,34 @@ draw_background(GtkWidget *clock, cairo_t *cr)
 }
 
 static gboolean
-batmon_expose(GtkWidget *clock, GdkEventExpose *event)
+#if defined (HAVE_GTK2)
+batmon_expose(GtkWidget *w, GdkEventExpose *event)
+#elif defined (HAVE_GTK3)
+batmon_handler(GtkWidget *w, 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(clock->window);
+       cr = gdk_cairo_create(gtk_widget_get_window(w));
 
        cairo_rectangle(cr, event->area.x, event->area.y,
-                       event->area.width, event->area.height);
-       cairo_clip(cr);
+               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);
 
-       draw_background(clock, cr);
+       cairo_rectangle(cr, rect.x, rect.y, rect.width, rect.height);
+       cairo_clip(cr);
+#endif
 
-       cairo_destroy(cr);
+       draw_background(cr);
 
        return TRUE;
 }
@@ -319,8 +333,11 @@ batmon_redraw_canvas(GtkWidget *widget)
 }
 
 static gboolean
-batmon_button_release(GtkWidget *clock, GdkEventButton *event)
+batmon_button_release(GtkWidget *w, GdkEventButton *event)
 {
+       (void) event; /* Unused parameter. */
+       (void) w; /* Unused parameter. */
+
        if (batmon_infos.debug)
                printf("%s: button released\n", PACKAGE_NAME);
 
@@ -330,41 +347,36 @@ batmon_button_release(GtkWidget *clock, GdkEventButton *event)
 static gboolean
 dockapp_update(gpointer data)
 {
-       GtkWidget *clock = GTK_WIDGET(data);
+       GtkWidget *w = GTK_WIDGET(data);
 
-       batmon_redraw_canvas(clock);
+       batmon_redraw_canvas(w);
 
        return TRUE; /* keep running this event */
 }
 
 void
-batmon_init(GtkWidget *dockwin, GtkWidget *iconwin)
+batmon_init(GtkWidget *win)
 {
-       gtk_widget_add_events(dockwin, GDK_BUTTON_PRESS_MASK |
-                             GDK_BUTTON_RELEASE_MASK |
-                             GDK_POINTER_MOTION_MASK);
-       gtk_widget_add_events(iconwin, GDK_BUTTON_PRESS_MASK |
+       gtk_widget_add_events(win, GDK_BUTTON_PRESS_MASK |
                              GDK_BUTTON_RELEASE_MASK |
                              GDK_POINTER_MOTION_MASK);
 
-       g_signal_connect(G_OBJECT(dockwin), "expose-event",
-                        G_CALLBACK(batmon_expose), NULL);
-       g_signal_connect(G_OBJECT(iconwin), "expose-event",
+#if defined (HAVE_GTK2)
+       g_signal_connect(G_OBJECT(win), "expose-event",
                         G_CALLBACK(batmon_expose), NULL);
-
-       g_signal_connect(G_OBJECT(dockwin), "button-press-event",
-                        G_CALLBACK(batmon_button_release), NULL);
-       g_signal_connect(G_OBJECT(iconwin), "button-press-event",
-                        G_CALLBACK(batmon_button_release), NULL);
-       g_signal_connect(G_OBJECT(dockwin), "button-release-event",
+#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(batmon_button_release), NULL);
-       g_signal_connect(G_OBJECT(iconwin), "button-release-event",
+       g_signal_connect(G_OBJECT(win), "button-release-event",
                         G_CALLBACK(batmon_button_release), NULL);
 
-       dockapp_set_mask(iconwin, dockapp_mask_xpm);
+       dockapp_set_mask(win, dockapp_mask_xpm);
 
        /* update the battery status once per second */
-       g_timeout_add(1000, dockapp_update, iconwin);
+       g_timeout_add(1000, dockapp_update, win);
 
-       batmon_redraw_canvas(iconwin);
+       batmon_redraw_canvas(win);
 }
index 0bc56ec..aa4734d 100644 (file)
@@ -12,6 +12,6 @@
 #include <gtk/gtk.h>
 
 void
-batmon_init(GtkWidget *dockwin, GtkWidget *iconwin);
+batmon_init(GtkWidget *win);
 
 #endif /* BATMON_H */
index 98450d3..0ab272b 100644 (file)
 /* Width and height in pixels of Window Maker icons. */
 #define ICON_SIZE 64
 
+#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);
 }
 
@@ -66,44 +71,79 @@ dockapp_gtk_withdrawn_hack(GtkWidget *dockwin, GtkWidget *iconwin)
        unsigned int nchildren;
        Window win_temp;
        Window win_orig;
+        Window iw;
 
        d = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
-       win_orig = GDK_WINDOW_XID(dockwin->window);
+       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);
 }
 
+#endif /* GTK_WITHDRAWN_HACK */
+
 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) {
-               printf("Could not load pixmap\n");
+               fprintf(stderr, "Could not load pixmap\n");
                exit(1);
        }
 
        gtk_widget_shape_combine_mask(iconwin, mask, 0, 0);
+#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 *
+dockapp_win_init(GtkWindowType window_type)
+{
+       GtkWidget *win;
+
+       win = gtk_window_new(window_type);
+       gtk_window_set_wmclass(GTK_WINDOW(win), g_get_prgname(), "DockApp");
+       gtk_widget_set_size_request(win, ICON_SIZE, ICON_SIZE);
+       gtk_widget_set_app_paintable(win, true);
+       gtk_widget_realize(win);
+
+       return win;
 }
 
 /*******************************************************************************
@@ -117,33 +157,25 @@ dockapp_init(int argc, char *argv[])
 
        gtk_init(&argc, &argv);
 
-       dockwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-       iconwin = gtk_window_new(GTK_WINDOW_POPUP);
-
-       gtk_window_set_wmclass(GTK_WINDOW(dockwin), g_get_prgname(), "DockApp");
-       gtk_window_set_wmclass(GTK_WINDOW(iconwin), g_get_prgname(), "DockApp");
-
-       gtk_widget_set_size_request(dockwin, ICON_SIZE, ICON_SIZE);
-       gtk_widget_set_size_request(iconwin, ICON_SIZE, ICON_SIZE);
-       gtk_widget_set_app_paintable(dockwin, TRUE);
-       gtk_widget_set_app_paintable(iconwin, TRUE);
+       dockwin = dockapp_win_init(GTK_WINDOW_TOPLEVEL);
+       iconwin = dockapp_win_init(GTK_WINDOW_POPUP);
 
        gtk_window_set_default_size(GTK_WINDOW(dockwin), ICON_SIZE, ICON_SIZE);
-
        g_signal_connect(dockwin, "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
-       gtk_widget_realize(dockwin);
-       gtk_widget_realize(iconwin);
-       gdk_window_set_icon(dockwin->window, iconwin->window, NULL, NULL);
-
-       batmon_init(dockwin, iconwin);
+       /* Sets the icon of dockwin as iconwin. */
+#if defined (HAVE_GTK2)
+       gdk_window_set_icon(gtk_widget_get_window(dockwin),
+                           gtk_widget_get_window(iconwin), NULL, NULL);
+#endif
 
+       batmon_init(iconwin);
        gtk_widget_show(iconwin);
 
 #ifdef GTK_WITHDRAWN_HACK
        dockapp_gtk_withdrawn_hack(dockwin, iconwin);
 #else
        gtk_widget_show(dockwin);
-       gdk_window_withdraw(dockwin->window);
+       gdk_window_withdraw(gtk_widget_get_window(dockwin));
 #endif
 }