Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock

Please consider unblocking of not-yet-uploaded package mate-desktop

This version will fix observed problems with solid background colors
currently existing in Debian 9's MATE desktop.

This unblock is needed for getting last minute caja/1.16.6-1 fixes in.
See: https://bugs.debian.org/863791 for further details.

unblock mate-desktop/1.16.2-1

-- System Information:
Debian Release: 9.0
  APT prefers testing
  APT policy: (990, 'testing')
Architecture: amd64
 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.9.0-2-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
diff -Nru mate-desktop-1.16.1/configure.ac mate-desktop-1.16.2/configure.ac
--- mate-desktop-1.16.1/configure.ac    2016-10-18 14:36:21.000000000 +0200
+++ mate-desktop-1.16.2/configure.ac    2017-03-25 22:30:16.000000000 +0100
@@ -1,6 +1,6 @@
 m4_define([mate_platform], [1])
 m4_define([mate_minor], [16])
-m4_define([mate_micro], [1])
+m4_define([mate_micro], [2])
 
 m4_define(mate_version, [mate_platform.mate_minor.mate_micro]),
 
diff -Nru mate-desktop-1.16.1/debian/changelog 
mate-desktop-1.16.2/debian/changelog
--- mate-desktop-1.16.1/debian/changelog        2016-10-20 13:19:38.000000000 
+0200
+++ mate-desktop-1.16.2/debian/changelog        2017-04-28 22:28:53.000000000 
+0200
@@ -1,3 +1,11 @@
+mate-desktop (1.16.2-1) unstable; urgency=medium
+
+  * New upstream release.
+    - Fix desktops look'n'feel with solid background color. (Closes:
+      #856027).
+
+ -- Mike Gabriel <sunwea...@debian.org>  Fri, 28 Apr 2017 22:28:53 +0200
+
 mate-desktop (1.16.1-1) unstable; urgency=medium
 
   * New upstream release.
diff -Nru mate-desktop-1.16.1/libmate-desktop/mate-aboutdialog.c 
mate-desktop-1.16.2/libmate-desktop/mate-aboutdialog.c
--- mate-desktop-1.16.1/libmate-desktop/mate-aboutdialog.c      2016-10-18 
14:36:21.000000000 +0200
+++ mate-desktop-1.16.2/libmate-desktop/mate-aboutdialog.c      2017-03-25 
22:30:16.000000000 +0100
@@ -537,7 +537,7 @@
   priv->website_label = button = gtk_label_new ("");
   gtk_widget_set_no_show_all (button, TRUE);
   gtk_label_set_selectable (GTK_LABEL (button), TRUE);
-  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, FALSE, 0);
   g_signal_connect_swapped (button, "activate-link",
                             G_CALLBACK (mate_about_dialog_activate_link), 
about);
 
diff -Nru mate-desktop-1.16.1/libmate-desktop/mate-bg.c 
mate-desktop-1.16.2/libmate-desktop/mate-bg.c
--- mate-desktop-1.16.1/libmate-desktop/mate-bg.c       2016-10-18 
14:36:21.000000000 +0200
+++ mate-desktop-1.16.2/libmate-desktop/mate-bg.c       2017-03-25 
22:30:16.000000000 +0100
@@ -49,15 +49,6 @@
 
 #if GTK_CHECK_VERSION (3, 0, 0)
 # include <cairo-xlib.h>
-#else
-#define cairo_surface_t                GdkPixmap
-#define cairo_create           gdk_cairo_create
-#define cairo_surface_destroy  g_object_unref
-#define cairo_xlib_surface_get_drawable        GDK_DRAWABLE_XID
-#define gdk_error_trap_pop_ignored     gdk_error_trap_pop
-#define mate_bg_get_surface_from_root          mate_bg_get_pixmap_from_root
-#define mate_bg_crossfade_set_start_surface    
mate_bg_crossfade_set_start_pixmap
-#define mate_bg_crossfade_set_end_surface      mate_bg_crossfade_set_end_pixmap
 #endif
 
 #define MATE_BG_CACHE_DIR "mate/background"
@@ -879,9 +870,9 @@
        case MATE_BG_COLOR_SOLID:
                /* not really a big deal to ignore the area of interest */
 #if GTK_CHECK_VERSION (3, 0, 0)
-               pixel = (((guint) bg->primary.red * 65535) >> 8) << 24      |
-                       (((guint) bg->primary.green * 65535) >> 8) << 24    |
-                       (((guint) bg->primary.blue * 65535) >> 8) << 24      |
+               pixel = ((guint) (bg->primary.red * 0xff) << 24)   |
+                       ((guint) (bg->primary.green * 0xff) << 16) |
+                       ((guint) (bg->primary.blue * 0xff) << 8)   |
 #else
                pixel = ((bg->primary.red >> 8) << 24)      |
                        ((bg->primary.green >> 8) << 16)    |
@@ -1219,7 +1210,11 @@
 {
        int pm_width, pm_height;
 
+#if GTK_CHECK_VERSION (3, 0, 0)
        cairo_surface_t *surface;
+#else
+       GdkPixmap *pixmap;
+#endif
        cairo_t *cr;
 
        g_return_val_if_fail (bg != NULL, NULL);
@@ -1238,19 +1233,27 @@
 
        if (root)
        {
+#if GTK_CHECK_VERSION (3, 0, 0)
                surface = make_root_pixmap (window, pm_width, pm_height);
+#else
+               pixmap = make_root_pixmap (window, pm_width, pm_height);
+#endif
        }
        else
        {
-#  if GTK_CHECK_VERSION (3, 0, 0)
+#if GTK_CHECK_VERSION (3, 0, 0)
                surface = gdk_window_create_similar_surface (window, 
CAIRO_CONTENT_COLOR,
                                                             pm_width, 
pm_height);
-#  else
-               surface = gdk_pixmap_new (window, pm_width, pm_height, -1);
-#  endif
+#else
+               pixmap = gdk_pixmap_new (window, pm_width, pm_height, -1);
+#endif
        }
 
+#if GTK_CHECK_VERSION (3, 0, 0)
        cr = cairo_create (surface);
+#else
+       cr = gdk_cairo_create (pixmap);
+#endif
        if (!bg->filename && bg->color_type == MATE_BG_COLOR_SOLID) {
 #if GTK_CHECK_VERSION (3, 0, 0)
                gdk_cairo_set_source_rgba (cr, &(bg->primary));
@@ -1273,7 +1276,11 @@
 
        cairo_destroy (cr);
 
+#if GTK_CHECK_VERSION (3, 0, 0)
        return surface;
+#else
+       return pixmap;
+#endif
 }
 
 
@@ -1355,7 +1362,11 @@
        char *disp_name = DisplayString (GDK_WINDOW_XDISPLAY (window));
        Display *display;
        Pixmap xpixmap;
+#if GTK_CHECK_VERSION (3, 0, 0)
        cairo_surface_t *surface;
+#else
+       GdkPixmap *pixmap;
+#endif
        int depth;
 
        /* Desktop background pixmap should be created from dummy X client 
since most
@@ -1376,16 +1387,18 @@
        XSetCloseDownMode (display, RetainPermanent);
        XCloseDisplay (display);
 
-#  if GTK_CHECK_VERSION (3, 0, 0)
+#if GTK_CHECK_VERSION (3, 0, 0)
        surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (screen), 
xpixmap,
                                              GDK_VISUAL_XVISUAL 
(gdk_screen_get_system_visual (screen)),
                                             width, height);
-#  else
-       surface = gdk_pixmap_foreign_new_for_screen (screen, xpixmap, width, 
height, depth);
-       gdk_drawable_set_colormap (surface, gdk_drawable_get_colormap (window));
-#  endif
 
        return surface;
+#else
+       pixmap = gdk_pixmap_foreign_new_for_screen (screen, xpixmap, width, 
height, depth);
+       gdk_drawable_set_colormap (pixmap, gdk_drawable_get_colormap (window));
+
+       return pixmap;
+#endif
 }
 
 static gboolean
@@ -1527,8 +1540,13 @@
        Atom type;
        Display *display;
        int screen_num;
+#if GTK_CHECK_VERSION (3, 0, 0)
        cairo_surface_t *surface;
        cairo_surface_t *source_pixmap;
+#else
+       GdkPixmap *pixmap;
+       GdkPixmap *source_pixmap;
+#endif
        int width, height;
        cairo_t *cr;
 
@@ -1541,7 +1559,11 @@
                                     0L, 1L, False, XA_PIXMAP,
                                     &type, &format, &nitems, &bytes_after,
                                     &data);
+#if GTK_CHECK_VERSION (3, 0, 0)
        surface = NULL;
+#else
+       pixmap = NULL;
+#endif
        source_pixmap = NULL;
 
        if (result != Success || type != XA_PIXMAP ||
@@ -1551,14 +1573,14 @@
        }
 
        if (data != NULL) {
-               gdk_error_trap_push ();
-
 #  if GTK_CHECK_VERSION (3, 0, 0)
                Pixmap xpixmap = *(Pixmap *) data;
                Window root_return;
                int x_ret, y_ret;
                unsigned int w_ret, h_ret, bw_ret, depth_ret;
 
+               gdk_error_trap_push ();
+
                if (XGetGeometry (GDK_SCREEN_XDISPLAY (screen),
                                  xpixmap,
                                  &root_return,
@@ -1572,6 +1594,7 @@
 
                gdk_error_trap_pop_ignored ();
 #  else
+               gdk_error_trap_push ();
                source_pixmap = gdk_pixmap_foreign_new (*(Pixmap *) data);
                gdk_error_trap_pop ();
 
@@ -1608,15 +1631,19 @@
                                                             
CAIRO_CONTENT_COLOR,
                                                             width, height);
        }
+
+       if (source_pixmap != NULL)
+               cairo_surface_destroy (source_pixmap);
 #  else
-       surface = gdk_pixmap_new (source_pixmap != NULL? source_pixmap :
+       pixmap = gdk_pixmap_new (source_pixmap != NULL? source_pixmap :
                                 gdk_screen_get_root_window (screen),
                                 width, height, -1);
 
-       cr = gdk_cairo_create (surface);
+       cr = gdk_cairo_create (pixmap);
        if (source_pixmap != NULL) {
+               cairo_pattern_t *pattern;
                gdk_cairo_set_source_pixmap (cr, source_pixmap, 0, 0);
-               cairo_pattern_t *pattern = cairo_get_source (cr);
+               pattern = cairo_get_source (cr);
                cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
        } else {
                cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
@@ -1624,19 +1651,23 @@
        cairo_paint (cr);
 
        if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
-               g_object_unref (surface);
-               surface = NULL;
+               g_object_unref (pixmap);
+               pixmap = NULL;
        }
        cairo_destroy (cr);
-#  endif
 
        if (source_pixmap != NULL)
-               cairo_surface_destroy (source_pixmap);
+               g_object_unref (source_pixmap);
+#  endif
 
        if (data != NULL)
                XFree (data);
 
+#if GTK_CHECK_VERSION (3, 0, 0)
        return surface;
+#else
+       return pixmap;
+#endif
 }
 
 /* Sets the "ESETROOT_PMAP_ID" property to later be used to free the pixmap,
@@ -1651,7 +1682,7 @@
        Atom     atoms[G_N_ELEMENTS(atom_names)] = {0};
 
        Atom     type;
-       int      format;
+       int      format, result;
        unsigned long nitems, after;
        unsigned char *data_root, *data_esetroot;
 
@@ -1659,20 +1690,24 @@
         * This method is to avoid multiple round-trips to Xserver
         */
        if (XInternAtoms (display, atom_names, G_N_ELEMENTS(atom_names), True, 
atoms) &&
-           atoms[0] != None && atoms[1] != None)
-       {
-               XGetWindowProperty (display, xroot, atoms[0], 0L, 1L, False, 
AnyPropertyType,
-                                   &type, &format, &nitems, &after, 
&data_root);
-               if (data_root && type == XA_PIXMAP && format == 32 && nitems == 
1)
-               {
-                       XGetWindowProperty (display, xroot, atoms[1], 0L, 1L, 
False, AnyPropertyType,
-                                           &type, &format, &nitems, &after, 
&data_esetroot);
-                       if (data_esetroot && type == XA_PIXMAP && format == 32 
&& nitems == 1)
-                       {
+           atoms[0] != None && atoms[1] != None) {
+               result = XGetWindowProperty (display, xroot, atoms[0], 0L, 1L,
+                                            False, AnyPropertyType,
+                                            &type, &format, &nitems, &after,
+                                            &data_root);
+
+               if (data_root != NULL && result == Success &&
+                   type == XA_PIXMAP && format == 32 && nitems == 1) {
+                       result = XGetWindowProperty (display, xroot, atoms[1],
+                                                    0L, 1L, False,
+                                                    AnyPropertyType,
+                                                    &type, &format, &nitems,
+                                                    &after, &data_esetroot);
+
+                       if (data_esetroot != NULL && result == Success &&
+                           type == XA_PIXMAP && format == 32 && nitems == 1) {
                                Pixmap xrootpmap = *((Pixmap *) data_root);
                                Pixmap esetrootpmap = *((Pixmap *) 
data_esetroot);
-                               XFree (data_root);
-                               XFree (data_esetroot);
 
                                gdk_error_trap_push ();
                                if (xrootpmap && xrootpmap == esetrootpmap) {
@@ -1681,12 +1716,20 @@
                                if (esetrootpmap && esetrootpmap != xrootpmap) {
                                        XKillClient (display, esetrootpmap);
                                }
-#                          if !GTK_CHECK_VERSION (3, 0, 0)
-                               XSync (display, False);
-#                          endif
+#if GTK_CHECK_VERSION (3, 0, 0)
                                gdk_error_trap_pop_ignored ();
+#else
+                               XSync (display, False);
+                               gdk_error_trap_pop ();
+#endif
+                       }
+                       if (data_esetroot != NULL) {
+                               XFree (data_esetroot);
                        }
                }
+               if (data_root != NULL) {
+                       XFree (data_root);
+               }
        }
 
        /* Get atoms for both properties in an array, create them if needed.
@@ -1723,21 +1766,25 @@
 #if GTK_CHECK_VERSION (3, 0, 0)
 mate_bg_set_surface_as_root (GdkScreen *screen, cairo_surface_t *surface)
 #else
-mate_bg_set_pixmap_as_root  (GdkScreen *screen, GdkPixmap *surface)
+mate_bg_set_pixmap_as_root  (GdkScreen *screen, GdkPixmap *pixmap)
 #endif
 {
        g_return_if_fail (screen != NULL);
 #  if GTK_CHECK_VERSION (3, 0, 0)
        g_return_if_fail (cairo_surface_get_type (surface) == 
CAIRO_SURFACE_TYPE_XLIB);
 #  else
-       g_return_if_fail (surface != NULL);
+       g_return_if_fail (pixmap != NULL);
 #  endif
 
        /* Desktop background pixmap should be created from dummy X client 
since most
         * applications will try to kill it with XKillClient later when 
changing pixmap
         */
        Display    *display      = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display 
(screen));
+#if GTK_CHECK_VERSION (3, 0, 0)
        Pixmap      pixmap_id    = cairo_xlib_surface_get_drawable (surface);
+#else
+       Pixmap      pixmap_id    = GDK_DRAWABLE_XID (pixmap);
+#endif
        Window      xroot        = RootWindow (display, gdk_screen_get_number 
(screen));
 
        XGrabServer (display);
@@ -1768,32 +1815,65 @@
                                            cairo_surface_t *surface)
 #else
 mate_bg_set_pixmap_as_root_with_crossfade (GdkScreen *screen,
-                                          GdkPixmap *surface)
+                                          GdkPixmap *pixmap)
 #endif
 {
+       GdkWindow       *root_window;
+       int              width, height;
+       MateBGCrossfade *fade;
+       cairo_t         *cr;
+#if GTK_CHECK_VERSION (3, 0, 0)
+       cairo_surface_t *old_surface;
+#else
+       GdkPixmap       *old_pixmap;
+#endif
+
        g_return_val_if_fail (screen != NULL, NULL);
+#if GTK_CHECK_VERSION (3, 0, 0)
        g_return_val_if_fail (surface != NULL, NULL);
+#else
+       g_return_val_if_fail (pixmap != NULL, NULL);
+#endif
 
-       GdkWindow  *root_window  = gdk_screen_get_root_window (screen);
-       int         width        = gdk_screen_get_width (screen);
-       int         height       = gdk_screen_get_height (screen);
-
-       MateBGCrossfade *fade    = mate_bg_crossfade_new (width, height);
+       root_window = gdk_screen_get_root_window (screen);
+       width       = gdk_window_get_width (root_window);
+       height      = gdk_window_get_height (root_window);
+       fade        = mate_bg_crossfade_new (width, height);
+#if GTK_CHECK_VERSION (3, 0, 0)
+       old_surface = mate_bg_get_surface_from_root (screen);
 
-       Display    *display      = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display 
(screen));
-       Pixmap      pixmap_id    = cairo_xlib_surface_get_drawable (surface);
+       mate_bg_crossfade_set_start_surface (fade, old_surface);
+       mate_bg_crossfade_set_end_surface (fade, surface);
+#else
+       old_pixmap = mate_bg_get_pixmap_from_root (screen);
 
-       XGrabServer (display);
-       cairo_surface_t *old_surface = mate_bg_get_surface_from_root (screen);
-       mate_bg_set_root_pixmap_id (screen, display, pixmap_id);
+       mate_bg_crossfade_set_start_pixmap (fade, old_pixmap);
+       mate_bg_crossfade_set_end_pixmap (fade, pixmap);
+#endif
 
-       mate_bg_crossfade_set_start_surface (fade, old_surface);
+       /* Before setting the surface as a root pixmap, let's have it draw
+        * the old stuff, just so it won't be noticable
+        * (crossfade will later get it back)
+        */
+#if GTK_CHECK_VERSION (3, 0, 0)
+       cr = cairo_create (surface);
+       cairo_set_source_surface (cr, old_surface, 0, 0);
+#else
+       cr = gdk_cairo_create (pixmap);
+       gdk_cairo_set_source_pixmap (cr, old_pixmap, 0, 0);
+#endif
+       cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
+       cairo_paint (cr);
+       cairo_destroy (cr);
+#if GTK_CHECK_VERSION (3, 0, 0)
        cairo_surface_destroy (old_surface);
-       mate_bg_crossfade_set_end_surface (fade, surface);
 
-       XFlush (display);
-       XUngrabServer (display);
+       mate_bg_set_surface_as_root (screen, surface);
+#else
+       g_object_unref (old_pixmap);
 
+       mate_bg_set_pixmap_as_root (screen, pixmap);
+#endif
        mate_bg_crossfade_start (fade, root_window);
 
        return fade;
diff -Nru mate-desktop-1.16.1/libmate-desktop/mate-bg-crossfade.c 
mate-desktop-1.16.2/libmate-desktop/mate-bg-crossfade.c
--- mate-desktop-1.16.1/libmate-desktop/mate-bg-crossfade.c     2016-10-18 
14:36:21.000000000 +0200
+++ mate-desktop-1.16.2/libmate-desktop/mate-bg-crossfade.c     2017-03-25 
22:30:16.000000000 +0100
@@ -38,19 +38,14 @@
 #include <mate-bg.h>
 #include "mate-bg-crossfade.h"
 
-#if !GTK_CHECK_VERSION(3, 0, 0)
-#define cairo_surface_t GdkPixmap
-#define cairo_create gdk_cairo_create
-#define cairo_set_source_surface gdk_cairo_set_source_pixmap
-#define cairo_surface_destroy g_object_unref
-#endif
-
 struct _MateBGCrossfadePrivate
 {
        GdkWindow       *window;
+       GtkWidget       *widget;
        int              width;
        int              height;
        cairo_surface_t *fading_surface;
+       cairo_surface_t *start_surface;
        cairo_surface_t *end_surface;
        gdouble          start_time;
        gdouble          total_duration;
@@ -143,6 +138,11 @@
                fade->priv->fading_surface = NULL;
        }
 
+       if (fade->priv->start_surface != NULL) {
+               cairo_surface_destroy (fade->priv->start_surface);
+               fade->priv->start_surface = NULL;
+       }
+
        if (fade->priv->end_surface != NULL) {
                cairo_surface_destroy (fade->priv->end_surface);
                fade->priv->end_surface = NULL;
@@ -210,7 +210,10 @@
 {
        fade->priv = MATE_BG_CROSSFADE_GET_PRIVATE (fade);
 
+       fade->priv->window = NULL;
+       fade->priv->widget = NULL;
        fade->priv->fading_surface = NULL;
+       fade->priv->start_surface = NULL;
        fade->priv->end_surface = NULL;
        fade->priv->timeout_id = 0;
 }
@@ -245,7 +248,6 @@
        cairo_surface_t *copy;
        cairo_t *cr;
 
-#if GTK_CHECK_VERSION (3, 0, 0)
        if (surface == NULL)
        {
                copy = gdk_window_create_similar_surface 
(gdk_get_default_root_window (),
@@ -258,9 +260,6 @@
                                                     cairo_surface_get_content 
(surface),
                                                     width, height);
        }
-#else
-       copy = gdk_pixmap_new(surface, width, height, surface == NULL? 24 : -1);
-#endif
 
        cr = cairo_create (copy);
 
@@ -303,6 +302,48 @@
        return copy;
 }
 
+#if !GTK_CHECK_VERSION (3, 0, 0)
+static cairo_surface_t *
+tile_pixmap (GdkPixmap *pixmap,
+             int        width,
+             int        height)
+{
+       cairo_surface_t *copy;
+       cairo_t *cr;
+
+       copy = gdk_window_create_similar_surface (gdk_get_default_root_window 
(),
+                                                 CAIRO_CONTENT_COLOR,
+                                                 width, height);
+       cr = cairo_create (copy);
+
+       if (pixmap != NULL)
+       {
+               cairo_pattern_t *pattern;
+               gdk_cairo_set_source_pixmap (cr, pixmap, 0.0, 0.0);
+               pattern = cairo_get_source (cr);
+               cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+       }
+       else
+       {
+               GtkStyle *style;
+               style = gtk_widget_get_default_style ();
+               gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]);
+       }
+
+       cairo_paint (cr);
+
+       if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
+       {
+               cairo_surface_destroy (copy);
+               copy = NULL;
+       }
+
+       cairo_destroy(cr);
+
+       return copy;
+}
+#endif
+
 /**
  * mate_bg_crossfade_set_start_surface:
  * @fade: a #MateBGCrossfade
@@ -319,22 +360,26 @@
 #if GTK_CHECK_VERSION(3, 0, 0)
 mate_bg_crossfade_set_start_surface (MateBGCrossfade* fade, cairo_surface_t 
*surface)
 #else
-mate_bg_crossfade_set_start_pixmap (MateBGCrossfade* fade, GdkPixmap *surface)
+mate_bg_crossfade_set_start_pixmap (MateBGCrossfade* fade, GdkPixmap *pixmap)
 #endif
 {
        g_return_val_if_fail (MATE_IS_BG_CROSSFADE (fade), FALSE);
 
-       if (fade->priv->fading_surface != NULL)
+       if (fade->priv->start_surface != NULL)
        {
-               cairo_surface_destroy (fade->priv->fading_surface);
-               fade->priv->fading_surface = NULL;
+               cairo_surface_destroy (fade->priv->start_surface);
+               fade->priv->start_surface = NULL;
        }
 
-       fade->priv->fading_surface = tile_surface (surface,
-                                                  fade->priv->width,
-                                                  fade->priv->height);
+#if GTK_CHECK_VERSION(3, 0, 0)
+       fade->priv->start_surface = tile_surface (surface,
+#else
+       fade->priv->start_surface = tile_pixmap  (pixmap,
+#endif
+                                                 fade->priv->width,
+                                                 fade->priv->height);
 
-       return fade->priv->fading_surface != NULL;
+       return fade->priv->start_surface != NULL;
 }
 
 static gdouble
@@ -368,7 +413,7 @@
 #if GTK_CHECK_VERSION(3, 0, 0)
 mate_bg_crossfade_set_end_surface (MateBGCrossfade* fade, cairo_surface_t 
*surface)
 #else
-mate_bg_crossfade_set_end_pixmap (MateBGCrossfade* fade, GdkPixmap *surface)
+mate_bg_crossfade_set_end_pixmap (MateBGCrossfade* fade, GdkPixmap *pixmap)
 #endif
 {
        g_return_val_if_fail (MATE_IS_BG_CROSSFADE (fade), FALSE);
@@ -378,9 +423,13 @@
                fade->priv->end_surface = NULL;
        }
 
+#if GTK_CHECK_VERSION(3, 0, 0)
        fade->priv->end_surface = tile_surface (surface,
-                                               fade->priv->width,
-                                               fade->priv->height);
+#else
+       fade->priv->end_surface = tile_pixmap  (pixmap,
+#endif
+                                               fade->priv->width,
+                                               fade->priv->height);
 
        /* Reset timer in case we're called while animating
         */
@@ -407,23 +456,114 @@
 }
 
 static void
+send_root_property_change_notification (MateBGCrossfade *fade)
+{
+        long zero_length_pixmap = 0;
+
+        /* We do a zero length append to force a change notification,
+         * without changing the value */
+        XChangeProperty (GDK_WINDOW_XDISPLAY (fade->priv->window),
+                         GDK_WINDOW_XID (fade->priv->window),
+                         gdk_x11_get_xatom_by_name ("_XROOTPMAP_ID"),
+                         XA_PIXMAP, 32, PropModeAppend,
+                         (unsigned char *) &zero_length_pixmap, 0);
+}
+
+static void
 draw_background (MateBGCrossfade *fade)
 {
-       if (gdk_window_get_window_type (fade->priv->window) == GDK_WINDOW_ROOT) 
{
-               XClearArea (GDK_WINDOW_XDISPLAY (fade->priv->window),
-                           GDK_WINDOW_XID (fade->priv->window),
-                           0, 0,
-                           gdk_window_get_width (fade->priv->window),
-                           gdk_window_get_height (fade->priv->window),
-                           False);
-               gdk_flush ();
-       } else {
+       if (fade->priv->widget != NULL) {
+               gtk_widget_queue_draw (fade->priv->widget);
+       } else if (gdk_window_get_window_type (fade->priv->window) != 
GDK_WINDOW_ROOT) {
+#if GTK_CHECK_VERSION (3, 22, 0)
+               cairo_t           *cr;
+               cairo_region_t    *region;
+               GdkDrawingContext *draw_context;
+
+               region = gdk_window_get_visible_region (fade->priv->window);
+               draw_context = gdk_window_begin_draw_frame (fade->priv->window,
+                                                           region);
+               cr = gdk_drawing_context_get_cairo_context (draw_context);
+               cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+               cairo_set_source_surface (cr, fade->priv->fading_surface, 0, 0);
+               cairo_paint (cr);
+               gdk_window_end_draw_frame (fade->priv->window, draw_context);
+               cairo_region_destroy (region);
+#elif GTK_CHECK_VERSION (3, 0, 0)
+               cairo_pattern_t *pattern;
+
+               pattern =
+                 cairo_pattern_create_for_surface (fade->priv->fading_surface);
+               gdk_window_set_background_pattern (fade->priv->window, pattern);
+               cairo_pattern_destroy (pattern);
                gdk_window_invalidate_rect (fade->priv->window, NULL, FALSE);
                gdk_window_process_updates (fade->priv->window, FALSE);
+#else
+               cairo_t   *cr;
+               GdkPixmap *pixmap;
+
+               pixmap = gdk_pixmap_new (fade->priv->window,
+                                        fade->priv->width, fade->priv->height,
+                                        -1);
+               cr = gdk_cairo_create (pixmap);
+               cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+               cairo_set_source_surface (cr, fade->priv->fading_surface, 0, 0);
+               cairo_paint (cr);
+               cairo_destroy (cr);
+               gdk_window_set_back_pixmap (fade->priv->window, pixmap, FALSE);
+               g_object_unref (pixmap);
+               gdk_window_invalidate_rect (fade->priv->window, NULL, FALSE);
+               gdk_window_process_updates (fade->priv->window, FALSE);
+#endif
+       } else {
+               Display *xdisplay = GDK_WINDOW_XDISPLAY (fade->priv->window);
+               gdk_error_trap_push ();
+               XGrabServer (xdisplay);
+               XClearWindow (xdisplay, GDK_WINDOW_XID (fade->priv->window));
+               send_root_property_change_notification (fade);
+               XFlush (xdisplay);
+               XUngrabServer (xdisplay);
+#if GTK_CHECK_VERSION (3, 0, 0)
+               gdk_error_trap_pop_ignored ();
+#else
+               gdk_error_trap_pop ();
+#endif
        }
 }
 
 static gboolean
+on_widget_draw (GtkWidget       *widget,
+#if GTK_CHECK_VERSION (3, 0, 0)
+                cairo_t         *cr,
+#else
+                GdkEventExpose  *event,
+#endif
+                MateBGCrossfade *fade)
+{
+#if !GTK_CHECK_VERSION (3, 0, 0)
+       cairo_t *cr;
+
+#endif
+       g_assert (fade->priv->fading_surface != NULL);
+
+#if !GTK_CHECK_VERSION (3, 0, 0)
+       cr = gdk_cairo_create (event->window);
+
+       gdk_cairo_rectangle (cr, &event->area);
+       cairo_clip (cr);
+
+#endif
+       cairo_set_source_surface (cr, fade->priv->fading_surface, 0, 0);
+       cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
+       cairo_paint (cr);
+
+#if !GTK_CHECK_VERSION (3, 0, 0)
+       cairo_destroy (cr);
+#endif
+       return FALSE;
+}
+
+static gboolean
 on_tick (MateBGCrossfade *fade)
 {
        gdouble now, percent_done;
@@ -447,7 +587,8 @@
                return on_tick (fade);
        }
 
-       if (fade->priv->fading_surface == NULL) {
+       if (fade->priv->fading_surface == NULL ||
+           fade->priv->end_surface == NULL) {
                return FALSE;
        }
 
@@ -481,60 +622,175 @@
 static void
 on_finished (MateBGCrossfade *fade)
 {
+       cairo_t *cr;
+
        if (fade->priv->timeout_id == 0)
                return;
 
+       g_assert (fade->priv->fading_surface != NULL);
        g_assert (fade->priv->end_surface != NULL);
 
-#if GTK_CHECK_VERSION (3, 0, 0)
-       cairo_pattern_t *pattern;
-       pattern = cairo_pattern_create_for_surface (fade->priv->end_surface);
-       gdk_window_set_background_pattern (fade->priv->window, pattern);
-       cairo_pattern_destroy (pattern);
-#else
-       gdk_window_set_back_pixmap (fade->priv->window,
-                                   fade->priv->end_surface,
-                                   FALSE);
-#endif
+       cr = cairo_create (fade->priv->fading_surface);
+       cairo_set_source_surface (cr, fade->priv->end_surface, 0, 0);
+       cairo_paint (cr);
+       cairo_destroy (cr);
        draw_background (fade);
 
+       cairo_surface_destroy (fade->priv->fading_surface);
+       fade->priv->fading_surface = NULL;
+
        cairo_surface_destroy (fade->priv->end_surface);
        fade->priv->end_surface = NULL;
 
-       g_assert (fade->priv->fading_surface != NULL);
+       g_assert (fade->priv->start_surface != NULL);
 
-       cairo_surface_destroy (fade->priv->fading_surface);
-       fade->priv->fading_surface = NULL;
+       cairo_surface_destroy (fade->priv->start_surface);
+       fade->priv->start_surface = NULL;
+
+       if (fade->priv->widget != NULL) {
+               g_signal_handlers_disconnect_by_func (fade->priv->widget,
+                                                     (GCallback) 
on_widget_draw,
+                                                     fade);
+       }
+       fade->priv->widget = NULL;
 
        fade->priv->timeout_id = 0;
        g_signal_emit (fade, signals[FINISHED], 0, fade->priv->window);
 }
 
+/* This function queries the _XROOTPMAP_ID property from the root window
+ * to determine the current root window background pixmap and returns a
+ * surface to draw directly to it.
+ * If _XROOTPMAP_ID is not set, then NULL returned.
+ */
+static cairo_surface_t *
+get_root_pixmap_id_surface (GdkDisplay *display)
+{
+       GdkScreen       *screen;
+       Display         *xdisplay;
+       Visual          *xvisual;
+       Window           xroot;
+       Atom             type;
+       int              format, result;
+       unsigned long    nitems, bytes_after;
+       unsigned char   *data;
+       cairo_surface_t *surface = NULL;
+
+       g_return_val_if_fail (display != NULL, NULL);
+
+       screen   = gdk_display_get_default_screen (display);
+       xdisplay = GDK_DISPLAY_XDISPLAY (display);
+       xvisual  = GDK_VISUAL_XVISUAL (gdk_screen_get_system_visual (screen));
+       xroot    = RootWindow (xdisplay, GDK_SCREEN_XNUMBER (screen));
+
+       result = XGetWindowProperty (xdisplay, xroot,
+                                    gdk_x11_get_xatom_by_name 
("_XROOTPMAP_ID"),
+                                    0L, 1L, False, XA_PIXMAP,
+                                    &type, &format, &nitems, &bytes_after,
+                                    &data);
+
+       if (result != Success || type != XA_PIXMAP ||
+           format != 32 || nitems != 1) {
+               XFree (data);
+               data = NULL;
+       }
+
+       if (data != NULL) {
+               Pixmap pixmap = *(Pixmap *) data;
+               Window root_ret;
+               int x_ret, y_ret;
+               unsigned int w_ret, h_ret, bw_ret, depth_ret;
+
+               gdk_error_trap_push ();
+               if (XGetGeometry (xdisplay, pixmap, &root_ret,
+                                 &x_ret, &y_ret, &w_ret, &h_ret,
+                                 &bw_ret, &depth_ret))
+               {
+                       surface = cairo_xlib_surface_create (xdisplay,
+                                                            pixmap, xvisual,
+                                                            w_ret, h_ret);
+               }
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+               gdk_error_trap_pop_ignored ();
+#else
+               gdk_error_trap_pop ();
+#endif
+               XFree (data);
+       }
+
+       gdk_display_flush (display);
+       return surface;
+}
+
 /**
  * mate_bg_crossfade_start:
  * @fade: a #MateBGCrossfade
  * @window: The #GdkWindow to draw crossfade on
  *
  * This function initiates a quick crossfade between two surfaces on
- * the background of @window.  Before initiating the crossfade both
- * mate_bg_crossfade_start() and mate_bg_crossfade_end() need to
- * be called. If animations are disabled, the crossfade is skipped,
- * and the window background is set immediately to the end surface.
+ * the background of @window. Before initiating the crossfade both
+ * mate_bg_crossfade_set_start_surface() and
+ * mate_bg_crossfade_set_end_surface() need to be called. If animations
+ * are disabled, the crossfade is skipped, and the window background is
+ * set immediately to the end surface.
  **/
 void
 mate_bg_crossfade_start (MateBGCrossfade *fade,
-                         GdkWindow        *window)
+                         GdkWindow        *window)
 {
        GSource *source;
        GMainContext *context;
 
        g_return_if_fail (MATE_IS_BG_CROSSFADE (fade));
        g_return_if_fail (window != NULL);
-       g_return_if_fail (fade->priv->fading_surface != NULL);
+       g_return_if_fail (fade->priv->start_surface != NULL);
        g_return_if_fail (fade->priv->end_surface != NULL);
        g_return_if_fail (!mate_bg_crossfade_is_started (fade));
        g_return_if_fail (gdk_window_get_window_type (window) != 
GDK_WINDOW_FOREIGN);
 
+       /* If drawing is done on the root window,
+        * it is essential to have the root pixmap.
+        */
+       if (gdk_window_get_window_type (window) == GDK_WINDOW_ROOT) {
+               GdkDisplay *display = gdk_window_get_display (window);
+               cairo_surface_t *surface = get_root_pixmap_id_surface (display);
+
+               g_return_if_fail (surface != NULL);
+               cairo_surface_destroy (surface);
+       }
+
+       if (fade->priv->fading_surface != NULL) {
+               cairo_surface_destroy (fade->priv->fading_surface);
+               fade->priv->fading_surface = NULL;
+       }
+
+       fade->priv->window = window;
+       if (gdk_window_get_window_type (fade->priv->window) != GDK_WINDOW_ROOT) 
{
+               fade->priv->fading_surface = tile_surface 
(fade->priv->start_surface,
+                                                          fade->priv->width,
+                                                          fade->priv->height);
+               if (fade->priv->widget != NULL) {
+#if GTK_CHECK_VERSION (3, 0, 0)
+                       g_signal_connect (fade->priv->widget, "draw",
+                                         (GCallback) on_widget_draw, fade);
+#else
+                       g_signal_connect (fade->priv->widget, "expose-event",
+                                         (GCallback) on_widget_draw, fade);
+#endif
+               }
+       } else {
+               cairo_t   *cr;
+               GdkDisplay *display = gdk_window_get_display 
(fade->priv->window);
+
+               fade->priv->fading_surface = get_root_pixmap_id_surface 
(display);
+               cr = cairo_create (fade->priv->fading_surface);
+               cairo_set_source_surface (cr, fade->priv->start_surface, 0, 0);
+               cairo_paint (cr);
+               cairo_destroy (cr);
+       }
+       draw_background (fade);
+
        source = g_timeout_source_new (1000 / 60.0);
        g_source_set_callback (source,
                               (GSourceFunc) on_tick,
@@ -544,24 +800,38 @@
        fade->priv->timeout_id = g_source_attach (source, context);
        g_source_unref (source);
 
-       fade->priv->window = window;
-#if GTK_CHECK_VERSION (3, 0, 0)
-       cairo_pattern_t *pattern;
-       pattern = cairo_pattern_create_for_surface (fade->priv->fading_surface);
-       gdk_window_set_background_pattern (fade->priv->window, pattern);
-       cairo_pattern_destroy (pattern);
-#else
-       gdk_window_set_back_pixmap (fade->priv->window,
-                                   fade->priv->fading_surface,
-                                   FALSE);
-#endif
-       draw_background (fade);
-
        fade->priv->is_first_frame = TRUE;
        fade->priv->total_duration = .75;
        fade->priv->start_time = get_current_time ();
 }
 
+/**
+ * mate_bg_crossfade_start_widget:
+ * @fade: a #MateBGCrossfade
+ * @widget: The #GtkWidget to draw crossfade on
+ *
+ * This function initiates a quick crossfade between two surfaces on
+ * the background of @widget. Before initiating the crossfade both
+ * mate_bg_crossfade_set_start_surface() and
+ * mate_bg_crossfade_set_end_surface() need to be called. If animations
+ * are disabled, the crossfade is skipped, and the window background is
+ * set immediately to the end surface.
+ **/
+void
+mate_bg_crossfade_start_widget (MateBGCrossfade *fade,
+                                GtkWidget       *widget)
+{
+       GdkWindow *window;
+
+       g_return_if_fail (MATE_IS_BG_CROSSFADE (fade));
+       g_return_if_fail (widget != NULL);
+
+       fade->priv->widget = widget;
+       gtk_widget_realize (fade->priv->widget);
+       window = gtk_widget_get_window (fade->priv->widget);
+
+       mate_bg_crossfade_start (fade, window);
+}
 
 /**
  * mate_bg_crossfade_is_started:
diff -Nru mate-desktop-1.16.1/libmate-desktop/mate-bg-crossfade.h 
mate-desktop-1.16.2/libmate-desktop/mate-bg-crossfade.h
--- mate-desktop-1.16.1/libmate-desktop/mate-bg-crossfade.h     2016-10-18 
14:36:21.000000000 +0200
+++ mate-desktop-1.16.2/libmate-desktop/mate-bg-crossfade.h     2017-03-25 
22:30:16.000000000 +0100
@@ -77,7 +77,9 @@
 #endif
 
 void              mate_bg_crossfade_start (MateBGCrossfade *fade,
-                                            GdkWindow        *window);
+                                           GdkWindow       *window);
+void              mate_bg_crossfade_start_widget (MateBGCrossfade *fade,
+                                                  GtkWidget       *widget);
 gboolean          mate_bg_crossfade_is_started (MateBGCrossfade *fade);
 void              mate_bg_crossfade_stop (MateBGCrossfade *fade);
 
diff -Nru mate-desktop-1.16.1/NEWS mate-desktop-1.16.2/NEWS
--- mate-desktop-1.16.1/NEWS    2016-10-18 14:36:21.000000000 +0200
+++ mate-desktop-1.16.2/NEWS    2017-03-25 22:30:16.000000000 +0100
@@ -1,3 +1,11 @@
+mate-desktop 1.16.2
+
+  * Background: fix crossfade issues with recent GTK+3 versions
+  * Background: fix more graphics issues to allow Caja to use background
+    for directory windows in GTK+3 build
+  * Background: fix memleaks and other misc issues
+  * mate-about: fix URL centering in GTK+3 build
+
 mate-desktop 1.16.1
 
   * mate-bg: fix regression that caused font color in Caja to be

Reply via email to