diff options
-rw-r--r-- | libmate-desktop/mate-bg-crossfade.c | 385 | ||||
-rw-r--r-- | libmate-desktop/mate-bg-crossfade.h | 4 | ||||
-rw-r--r-- | libmate-desktop/mate-bg.c | 164 |
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; |