Bug#863792: unblock: mate-desktop/1.16.2-1

Mike Gabriel mike.gabriel at das-netzwerkteam.de
Wed May 31 09:26:00 UTC 2017


Package: release.debian.org
Severity: normal
User: release.debian.org at 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)
-------------- next part --------------
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 <sunweaver at 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


More information about the pkg-mate-team mailing list