summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libmate-desktop/mate-bg-crossfade.c385
-rw-r--r--libmate-desktop/mate-bg-crossfade.h4
-rw-r--r--libmate-desktop/mate-bg.c164
3 files changed, 440 insertions, 113 deletions
diff --git a/libmate-desktop/mate-bg-crossfade.c b/libmate-desktop/mate-bg-crossfade.c
index 970b567..b7cc993 100644
--- a/libmate-desktop/mate-bg-crossfade.c
+++ b/libmate-desktop/mate-bg-crossfade.c
@@ -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 @@ mate_bg_crossfade_finalize (GObject *object)
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 @@ mate_bg_crossfade_init (MateBGCrossfade *fade)
{
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 @@ tile_surface (cairo_surface_t *surface,
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 @@ tile_surface (cairo_surface_t *surface,
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 @@ tile_surface (cairo_surface_t *surface,
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 @@ gboolean
#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 @@ gboolean
#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 @@ mate_bg_crossfade_set_end_pixmap (MateBGCrossfade* fade, GdkPixmap *surface)
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
*/
@@ -423,22 +472,98 @@ send_root_property_change_notification (MateBGCrossfade *fade)
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);
- send_root_property_change_notification (fade);
- 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;
@@ -462,7 +587,8 @@ on_tick (MateBGCrossfade *fade)
return on_tick (fade);
}
- if (fade->priv->fading_surface == NULL) {
+ if (fade->priv->fading_surface == NULL ||
+ fade->priv->end_surface == NULL) {
return FALSE;
}
@@ -496,60 +622,175 @@ on_tick (MateBGCrossfade *fade)
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,
@@ -559,24 +800,38 @@ mate_bg_crossfade_start (MateBGCrossfade *fade,
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 --git a/libmate-desktop/mate-bg-crossfade.h b/libmate-desktop/mate-bg-crossfade.h
index f4674fd..893592c 100644
--- a/libmate-desktop/mate-bg-crossfade.h
+++ b/libmate-desktop/mate-bg-crossfade.h
@@ -77,7 +77,9 @@ gboolean mate_bg_crossfade_set_end_pixmap (MateBGCrossfade *fade,
#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 --git a/libmate-desktop/mate-bg.c b/libmate-desktop/mate-bg.c
index 4a0b563..b852e57 100644
--- a/libmate-desktop/mate-bg.c
+++ b/libmate-desktop/mate-bg.c
@@ -49,15 +49,6 @@ Authors: Soren Sandmann <[email protected]>
#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"
@@ -1219,7 +1210,11 @@ mate_bg_create_pixmap (MateBG *bg,
{
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 @@ mate_bg_create_pixmap (MateBG *bg,
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 @@ mate_bg_create_pixmap (MateBG *bg,
cairo_destroy (cr);
+#if GTK_CHECK_VERSION (3, 0, 0)
return surface;
+#else
+ return pixmap;
+#endif
}
@@ -1355,7 +1362,11 @@ make_root_pixmap (GdkWindow *window, gint width, gint height)
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 @@ make_root_pixmap (GdkWindow *window, gint width, gint height)
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 @@ mate_bg_get_pixmap_from_root (GdkScreen *screen)
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 @@ mate_bg_get_pixmap_from_root (GdkScreen *screen)
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 @@ mate_bg_get_pixmap_from_root (GdkScreen *screen)
}
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 @@ mate_bg_get_pixmap_from_root (GdkScreen *screen)
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 @@ mate_bg_get_pixmap_from_root (GdkScreen *screen)
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 @@ mate_bg_get_pixmap_from_root (GdkScreen *screen)
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,
@@ -1685,10 +1716,12 @@ mate_bg_set_root_pixmap_id (GdkScreen *screen,
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);
@@ -1733,21 +1766,25 @@ void
#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);
@@ -1778,32 +1815,65 @@ mate_bg_set_surface_as_root_with_crossfade (GdkScreen *screen,
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;