/* GDK - The GIMP Drawing Kit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* * Modified by the GTK+ Team and others 1997-2005. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #include #include #include "gdk.h" #include "gdkwindow.h" #include "gdkinternals.h" #include "gdkwindowimpl.h" #include "gdkpixmap.h" #include "gdkdrawable.h" #include "gdktypes.h" #include "gdkscreen.h" #include "gdkgc.h" #include "gdkcolor.h" #include "gdkcursor.h" #include "gdkalias.h" /* LIMITATIONS: * * Offscreen windows can't be the child of a foreign window, * nor contain foreign windows * GDK_POINTER_MOTION_HINT_MASK isn't effective */ typedef struct _GdkOffscreenWindow GdkOffscreenWindow; typedef struct _GdkOffscreenWindowClass GdkOffscreenWindowClass; struct _GdkOffscreenWindow { GdkDrawable parent_instance; GdkWindow *wrapper; GdkCursor *cursor; GdkColormap *colormap; GdkScreen *screen; GdkPixmap *pixmap; }; struct _GdkOffscreenWindowClass { GdkDrawableClass parent_class; }; #define GDK_TYPE_OFFSCREEN_WINDOW (gdk_offscreen_window_get_type()) #define GDK_OFFSCREEN_WINDOW(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindow)) #define GDK_IS_OFFSCREEN_WINDOW(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_OFFSCREEN_WINDOW)) #define GDK_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass)) #define GDK_IS_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_OFFSCREEN_WINDOW)) #define GDK_OFFSCREEN_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass)) static void gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface); static void gdk_offscreen_window_hide (GdkWindow *window); static void gdk_offscreen_window_clear_area (GdkWindow *window, gint x, gint y, gint width, gint height, gboolean send_expose); G_DEFINE_TYPE_WITH_CODE (GdkOffscreenWindow, gdk_offscreen_window, GDK_TYPE_DRAWABLE, G_IMPLEMENT_INTERFACE (GDK_TYPE_WINDOW_IMPL, gdk_offscreen_window_impl_iface_init)); static void gdk_offscreen_window_finalize (GObject *object) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (object); if (offscreen->cursor) gdk_cursor_unref (offscreen->cursor); offscreen->cursor = NULL; gdk_pixmap_unref (offscreen->pixmap); G_OBJECT_CLASS (gdk_offscreen_window_parent_class)->finalize (object); } static void gdk_offscreen_window_init (GdkOffscreenWindow *window) { } void _gdk_offscreen_window_destroy (GdkWindow *window, gboolean recursing) { GdkWindowObject *private = GDK_WINDOW_OBJECT (window); GdkOffscreenWindow *offscreen; offscreen = GDK_OFFSCREEN_WINDOW (private->impl); if (!recursing) gdk_offscreen_window_hide (window); g_object_unref (offscreen->colormap); offscreen->colormap = NULL; } static gboolean is_parent_of (GdkWindow *parent, GdkWindow *child) { GdkWindow *w; w = child; while (w != NULL) { if (w == parent) return TRUE; w = gdk_window_get_parent (w); } return FALSE; } static GdkGC * gdk_offscreen_window_create_gc (GdkDrawable *drawable, GdkGCValues *values, GdkGCValuesMask values_mask) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); return gdk_gc_new_with_values (offscreen->pixmap, values, values_mask); } static GdkImage* gdk_offscreen_window_copy_to_image (GdkDrawable *drawable, GdkImage *image, gint src_x, gint src_y, gint dest_x, gint dest_y, gint width, gint height) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); return gdk_drawable_copy_to_image (offscreen->pixmap, image, src_x, src_y, dest_x, dest_y, width, height); } static cairo_surface_t * gdk_offscreen_window_ref_cairo_surface (GdkDrawable *drawable) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); return _gdk_drawable_ref_cairo_surface (offscreen->pixmap); } static GdkColormap* gdk_offscreen_window_get_colormap (GdkDrawable *drawable) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); return offscreen->colormap; } static void gdk_offscreen_window_set_colormap (GdkDrawable *drawable, GdkColormap*colormap) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); if (colormap && GDK_WINDOW_DESTROYED (offscreen->wrapper)) return; if (offscreen->colormap == colormap) return; if (offscreen->colormap) g_object_unref (offscreen->colormap); offscreen->colormap = colormap; if (offscreen->colormap) g_object_ref (offscreen->colormap); } static gint gdk_offscreen_window_get_depth (GdkDrawable *drawable) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); return gdk_drawable_get_depth (offscreen->wrapper); } static GdkDrawable * gdk_offscreen_window_get_source_drawable (GdkDrawable *drawable) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); return _gdk_drawable_get_source_drawable (offscreen->pixmap); } static GdkDrawable * gdk_offscreen_window_get_composite_drawable (GdkDrawable *drawable, gint x, gint y, gint width, gint height, gint *composite_x_offset, gint *composite_y_offset) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); return g_object_ref (offscreen->pixmap); } static GdkScreen* gdk_offscreen_window_get_screen (GdkDrawable *drawable) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); return offscreen->screen; } static GdkVisual* gdk_offscreen_window_get_visual (GdkDrawable *drawable) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); return gdk_drawable_get_visual (offscreen->wrapper); } static void add_damage (GdkOffscreenWindow *offscreen, int x, int y, int w, int h) { GdkRectangle rect; GdkRegion *damage; rect.x = x; rect.y = y; rect.width = w; rect.height = h; damage = gdk_region_rectangle (&rect); _gdk_window_add_damage (offscreen->wrapper, damage); gdk_region_destroy (damage); } static void gdk_offscreen_window_draw_drawable (GdkDrawable *drawable, GdkGC *gc, GdkPixmap *src, gint xsrc, gint ysrc, gint xdest, gint ydest, gint width, gint height) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap); gdk_draw_drawable (real_drawable, gc, src, xsrc, ysrc, xdest, ydest, width, height); add_damage (offscreen, xdest, ydest, width, height); } static void gdk_offscreen_window_draw_rectangle (GdkDrawable *drawable, GdkGC *gc, gboolean filled, gint x, gint y, gint width, gint height) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap); gdk_draw_rectangle (real_drawable, gc, filled, x, y, width, height); add_damage (offscreen, x, y, width, height); } static void gdk_offscreen_window_draw_arc (GdkDrawable *drawable, GdkGC *gc, gboolean filled, gint x, gint y, gint width, gint height, gint angle1, gint angle2) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap); gdk_draw_arc (real_drawable, gc, filled, x, y, width, height, angle1, angle2); add_damage (offscreen, x, y, width, height); } static void gdk_offscreen_window_draw_polygon (GdkDrawable *drawable, GdkGC *gc, gboolean filled, GdkPoint *points, gint npoints) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap); gdk_draw_polygon (real_drawable, gc, filled, points, npoints); if (npoints > 0) { int min_x, min_y, max_x, max_y, i; min_x = max_x = points[0].x; min_y = max_y = points[0].y; for (i = 1; i < npoints; i++) { min_x = MIN (min_x, points[i].x); max_x = MAX (max_x, points[i].x); min_y = MIN (min_y, points[i].y); max_y = MAX (max_y, points[i].y); } add_damage (offscreen, min_x, min_y, max_x - min_x, max_y - min_y); } } static void gdk_offscreen_window_draw_text (GdkDrawable *drawable, GdkFont *font, GdkGC *gc, gint x, gint y, const gchar *text, gint text_length) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap); GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper); gdk_draw_text (real_drawable, font, gc, x, y, text, text_length); /* Hard to compute the minimal size, not that often used anyway. */ add_damage (offscreen, 0, 0, private->width, private->height); } static void gdk_offscreen_window_draw_text_wc (GdkDrawable *drawable, GdkFont *font, GdkGC *gc, gint x, gint y, const GdkWChar *text, gint text_length) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap); GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper); gdk_draw_text_wc (real_drawable, font, gc, x, y, text, text_length); /* Hard to compute the minimal size, not that often used anyway. */ add_damage (offscreen, 0, 0, private->width, private->height); } static void gdk_offscreen_window_draw_points (GdkDrawable *drawable, GdkGC *gc, GdkPoint *points, gint npoints) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap); gdk_draw_points (real_drawable, gc, points, npoints); if (npoints > 0) { int min_x, min_y, max_x, max_y, i; min_x = max_x = points[0].x; min_y = max_y = points[0].y; for (i = 1; i < npoints; i++) { min_x = MIN (min_x, points[i].x); max_x = MAX (max_x, points[i].x); min_y = MIN (min_y, points[i].y); max_y = MAX (max_y, points[i].y); } add_damage (offscreen, min_x, min_y, max_x - min_x, max_y - min_y); } } static void gdk_offscreen_window_draw_segments (GdkDrawable *drawable, GdkGC *gc, GdkSegment *segs, gint nsegs) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap); gdk_draw_segments (real_drawable, gc, segs, nsegs); if (nsegs > 0) { int min_x, min_y, max_x, max_y, i; min_x = max_x = segs[0].x1; min_y = max_y = segs[0].y1; for (i = 1; i < nsegs; i++) { min_x = MIN (min_x, segs[i].x1); max_x = MAX (max_x, segs[i].x1); min_x = MIN (min_x, segs[i].x2); max_x = MAX (max_x, segs[i].x2); min_y = MIN (min_y, segs[i].y1); max_y = MAX (max_y, segs[i].y1); min_y = MIN (min_y, segs[i].y2); max_y = MAX (max_y, segs[i].y2); } add_damage (offscreen, min_x, min_y, max_x - min_x, max_y - min_y); } } static void gdk_offscreen_window_draw_lines (GdkDrawable *drawable, GdkGC *gc, GdkPoint *points, gint npoints) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap); GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper); gdk_draw_lines (real_drawable, gc, points, npoints); /* Hard to compute the minimal size, as we don't know the line width, and since joins are hard to calculate. Its not that often used anyway, damage it all */ add_damage (offscreen, 0, 0, private->width, private->height); } static void gdk_offscreen_window_draw_image (GdkDrawable *drawable, GdkGC *gc, GdkImage *image, gint xsrc, gint ysrc, gint xdest, gint ydest, gint width, gint height) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap); gdk_draw_image (real_drawable, gc, image, xsrc, ysrc, xdest, ydest, width, height); add_damage (offscreen, xdest, ydest, width, height); } static void gdk_offscreen_window_draw_pixbuf (GdkDrawable *drawable, GdkGC *gc, GdkPixbuf *pixbuf, gint src_x, gint src_y, gint dest_x, gint dest_y, gint width, gint height, GdkRgbDither dither, gint x_dither, gint y_dither) { GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable); GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap); gdk_draw_pixbuf (real_drawable, gc, pixbuf, src_x, src_y, dest_x, dest_y, width, height, dither, x_dither, y_dither); add_damage (offscreen, dest_x, dest_y, width, height); } void _gdk_offscreen_window_new (GdkWindow *window, GdkScreen *screen, GdkVisual *visual, GdkWindowAttr *attributes, gint attributes_mask) { GdkWindowObject *parent_private; GdkWindowObject *private; GdkOffscreenWindow *offscreen; g_return_if_fail (attributes != NULL); if (attributes->wclass != GDK_INPUT_OUTPUT) return; /* Can't support input only offscreens */ private = (GdkWindowObject *)window; if (private->parent != NULL && GDK_WINDOW_DESTROYED (private->parent)) return; parent_private = (GdkWindowObject*) private->parent; private->impl = g_object_new (GDK_TYPE_OFFSCREEN_WINDOW, NULL); offscreen = GDK_OFFSCREEN_WINDOW (private->impl); offscreen->wrapper = window; offscreen->screen = screen; if (attributes_mask & GDK_WA_COLORMAP) offscreen->colormap = g_object_ref (attributes->colormap); else { if (gdk_screen_get_system_visual (screen) == visual) { offscreen->colormap = gdk_screen_get_system_colormap (screen); g_object_ref (offscreen->colormap); } else offscreen->colormap = gdk_colormap_new (visual, FALSE); } offscreen->pixmap = gdk_pixmap_new ((GdkDrawable *)private->parent, private->width, private->height, private->depth); } static gboolean gdk_offscreen_window_reparent (GdkWindow *window, GdkWindow *new_parent, gint x, gint y) { GdkWindowObject *private = (GdkWindowObject *)window; GdkWindowObject *new_parent_private = (GdkWindowObject *)new_parent; GdkWindowObject *old_parent; GdkOffscreenWindow *offscreen; gboolean was_mapped; if (new_parent) { /* No input-output children of input-only windows */ if (new_parent_private->input_only && !private->input_only) return FALSE; /* Don't create loops in hierarchy */ if (is_parent_of (window, new_parent)) return FALSE; } offscreen = GDK_OFFSCREEN_WINDOW (private->impl); was_mapped = GDK_WINDOW_IS_MAPPED (window); gdk_window_hide (window); if (private->parent) private->parent->children = g_list_remove (private->parent->children, window); old_parent = private->parent; private->parent = new_parent_private; private->x = x; private->y = y; if (new_parent_private) private->parent->children = g_list_prepend (private->parent->children, window); _gdk_syntesize_crossing_events_for_geometry_change (window); if (old_parent) _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (old_parent)); return was_mapped; } static gint gdk_offscreen_window_get_origin (GdkWindow *window, gint *x, gint *y) { if (x) *x = 0; if (y) *y = 0; return TRUE; } /** * gdk_window_get_offscreen_pixmap: * @window: a #GdkWindow * * Gets the offscreen pixmap that an offscreen window renders into. If * you need to keep this around over window resizes, you need to add a * reference to it. * * Returns: The offscreen pixmap, or NULL if not offscreen **/ GdkPixmap * gdk_window_get_offscreen_pixmap (GdkWindow *window) { GdkWindowObject *private = (GdkWindowObject *)window; GdkOffscreenWindow *offscreen; g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE); if (!GDK_IS_OFFSCREEN_WINDOW (private->impl)) return NULL; offscreen = GDK_OFFSCREEN_WINDOW (private->impl); return offscreen->pixmap; } static void gdk_offscreen_window_raise (GdkWindow *window) { /* gdk_window_raise already changed the stacking order */ _gdk_syntesize_crossing_events_for_geometry_change (window); } static void gdk_offscreen_window_lower (GdkWindow *window) { /* gdk_window_lower already changed the stacking order */ _gdk_syntesize_crossing_events_for_geometry_change (window); } static void gdk_offscreen_window_move_resize_internal (GdkWindow *window, gint x, gint y, gint width, gint height, gboolean send_expose_events) { GdkWindowObject *private = (GdkWindowObject *)window; GdkOffscreenWindow *offscreen; gint dx, dy, dw, dh; GdkGC *gc; GdkPixmap *old_pixmap; offscreen = GDK_OFFSCREEN_WINDOW (private->impl); if (width < 1) width = 1; if (height < 1) height = 1; if (private->destroyed) return; dx = x - private->x; dy = y - private->y; dw = width - private->width; dh = height - private->height; private->x = x; private->y = y; if (private->width != width || private->height != height) { private->width = width; private->height = height; old_pixmap = offscreen->pixmap; offscreen->pixmap = gdk_pixmap_new (GDK_DRAWABLE (old_pixmap), width, height, private->depth); gc = _gdk_drawable_get_scratch_gc (offscreen->pixmap, FALSE); gdk_draw_drawable (offscreen->pixmap, gc, old_pixmap, 0,0, 0, 0, -1, -1); g_object_unref (old_pixmap); } if (GDK_WINDOW_IS_MAPPED (private)) { // TODO: Only invalidate new area, i.e. for larger windows gdk_window_invalidate_rect (window, NULL, TRUE); _gdk_syntesize_crossing_events_for_geometry_change (window); } } static void gdk_offscreen_window_move_resize (GdkWindow *window, gboolean with_move, gint x, gint y, gint width, gint height) { GdkWindowObject *private = (GdkWindowObject *)window; GdkOffscreenWindow *offscreen; offscreen = GDK_OFFSCREEN_WINDOW (private->impl); if (!with_move) { x = private->x; y = private->y; } if (width < 0) width = private->width; if (height < 0) height = private->height; gdk_offscreen_window_move_resize_internal (window, x, y, width, height, TRUE); } static void gdk_offscreen_window_show (GdkWindow *window, gboolean raise) { GdkWindowObject *private = (GdkWindowObject *)window; GdkOffscreenWindow *offscreen; if (GDK_WINDOW_IS_MAPPED (window)) return; offscreen = GDK_OFFSCREEN_WINDOW (private->impl); private->state = 0; /* gdk_window_show already changed the stacking order if needed */ if (private->event_mask & GDK_STRUCTURE_MASK) _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE); if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK) _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE); if (gdk_window_is_viewable (window)) _gdk_syntesize_crossing_events_for_geometry_change (window); gdk_window_clear_area_e (window, 0, 0, private->width, private->height); } static void gdk_offscreen_window_hide (GdkWindow *window) { GdkWindowObject *private; GdkOffscreenWindow *offscreen; GdkDisplay *display; g_return_if_fail (window != NULL); private = (GdkWindowObject*) window; offscreen = GDK_OFFSCREEN_WINDOW (private->impl); if (!GDK_WINDOW_IS_MAPPED (private)) return; /* May need to break grabs on children */ display = gdk_drawable_get_display (window); if (display->pointer_grab.window != NULL) { if (is_parent_of (window, display->pointer_grab.window)) { /* Call this ourselves, even though gdk_display_pointer_ungrab does so too, since we want to pass implicit == TRUE so the broken grab event is generated */ _gdk_display_unset_has_pointer_grab (display, TRUE, FALSE, GDK_CURRENT_TIME); gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME); } } if (private->event_mask & GDK_STRUCTURE_MASK) _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE); if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK) _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE); private->state = GDK_WINDOW_STATE_WITHDRAWN; _gdk_syntesize_crossing_events_for_geometry_change (window); } static void gdk_offscreen_window_withdraw (GdkWindow *window) { } static GdkEventMask gdk_offscreen_window_get_events (GdkWindow *window) { return 0; } static void gdk_offscreen_window_set_events (GdkWindow *window, GdkEventMask event_mask) { } static GdkGC * setup_backing_rect_gc (GdkWindow *window, int x_offset, int y_offset) { GdkWindowObject *private = (GdkWindowObject *)window; GdkGC *gc; if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent) { x_offset += private->x; y_offset += private->y; return setup_backing_rect_gc (GDK_WINDOW (private->parent), x_offset, y_offset); } else if (private->bg_pixmap && private->bg_pixmap != GDK_PARENT_RELATIVE_BG && private->bg_pixmap != GDK_NO_BG) { guint gc_mask; GdkGCValues gc_values; gc_values.fill = GDK_TILED; gc_values.tile = private->bg_pixmap; gc_values.ts_x_origin = -x_offset; gc_values.ts_y_origin = -y_offset; gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN; return gdk_gc_new_with_values (window, &gc_values, gc_mask); } else { gc = _gdk_drawable_get_scratch_gc (window, FALSE); g_object_ref (gc); gdk_gc_set_foreground (gc, &private->bg_color); return gc; } } static void gdk_offscreen_window_clear_area (GdkWindow *window, gint x, gint y, gint width, gint height, gboolean send_expose) { GdkGC *gc; if (GDK_WINDOW_DESTROYED (window)) return; /* Actual drawing is done by gdkwindow.c */ gc = setup_backing_rect_gc (window, 0, 0); gdk_draw_rectangle (window, gc, TRUE, x, y, width, height); g_object_unref (gc); if (send_expose) { GdkRectangle visible, rect; visible.x = visible.y = 0; gdk_drawable_get_size (GDK_DRAWABLE (window), &visible.width, &visible.height); rect.x = x; rect.y = x; rect.width = width; rect.height = height; gdk_rectangle_intersect (&rect, &visible, &rect); gdk_window_invalidate_rect (window, &rect, TRUE); } } static void gdk_offscreen_window_set_background (GdkWindow *window, const GdkColor *color) { GdkWindowObject *private = (GdkWindowObject *)window; GdkColormap *colormap = gdk_drawable_get_colormap (window); private->bg_color = *color; gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color); if (private->bg_pixmap && private->bg_pixmap != GDK_PARENT_RELATIVE_BG && private->bg_pixmap != GDK_NO_BG) g_object_unref (private->bg_pixmap); private->bg_pixmap = NULL; } static void gdk_offscreen_window_set_back_pixmap (GdkWindow *window, GdkPixmap *pixmap) { GdkWindowObject *private = (GdkWindowObject *)window; if (pixmap && private->bg_pixmap != GDK_PARENT_RELATIVE_BG && private->bg_pixmap != GDK_NO_BG && !gdk_drawable_get_colormap (pixmap)) { g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap"); return; } if (private->bg_pixmap && private->bg_pixmap != GDK_PARENT_RELATIVE_BG && private->bg_pixmap != GDK_NO_BG) g_object_unref (private->bg_pixmap); private->bg_pixmap = pixmap; if (pixmap && private->bg_pixmap != GDK_PARENT_RELATIVE_BG && private->bg_pixmap != GDK_NO_BG) g_object_ref (pixmap); } static void gdk_offscreen_window_shape_combine_mask (GdkWindow *window, GdkBitmap *mask, gint x, gint y) { } static void gdk_offscreen_window_shape_combine_region (GdkWindow *window, const GdkRegion *shape_region, gint offset_x, gint offset_y) { } static void gdk_offscreen_window_set_child_shapes (GdkWindow *window) { } static void gdk_offscreen_window_merge_child_shapes (GdkWindow *window) { } static gboolean gdk_offscreen_window_set_static_gravities (GdkWindow *window, gboolean use_static) { return TRUE; } static void gdk_offscreen_window_set_cursor (GdkWindow *window, GdkCursor *cursor) { GdkWindowObject *private = (GdkWindowObject *)window; GdkOffscreenWindow *offscreen; offscreen = GDK_OFFSCREEN_WINDOW (private->impl); if (offscreen->cursor) { gdk_cursor_unref (offscreen->cursor); offscreen->cursor = NULL; } if (cursor) offscreen->cursor = gdk_cursor_ref (cursor); /* TODO: The cursor is never actually used... */ } static void gdk_offscreen_window_get_geometry (GdkWindow *window, gint *x, gint *y, gint *width, gint *height, gint *depth) { GdkWindowObject *private = (GdkWindowObject *)window; GdkOffscreenWindow *offscreen; offscreen = GDK_OFFSCREEN_WINDOW (private->impl); g_return_if_fail (window == NULL || GDK_IS_WINDOW (window)); if (!GDK_WINDOW_DESTROYED (window)) { if (x) *x = private->x; if (y) *y = private->y; if (width) *width = private->width; if (height) *height = private->height; if (depth) *depth = private->depth; } } /** * gdk_window_set_offscreen_hooks: * @offscreen_window: a offscreen #GdkWindow * @hooks: a table of pointers to functions for handling offscreen * window coordinates translations * * Sets the parent-to-offscreen-child and offscreen-child-to-parent coordinate * translation functions for offscreen windows. * * This function is useful for complex widgets employing * offscreen windows. * * Since: 2.16 */ void gdk_window_set_offscreen_hooks (GdkWindow *offscreen_window, const GdkOffscreenChildHooks *hooks) { GdkWindowObject *private; g_return_if_fail (GDK_IS_WINDOW (offscreen_window)); g_return_if_fail (hooks != NULL); private = (GdkWindowObject *) offscreen_window; private->offscreen_hooks = hooks; } static gboolean gdk_offscreen_window_queue_antiexpose (GdkWindow *window, GdkRegion *area) { return FALSE; } static void gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass) { GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gdk_offscreen_window_finalize; drawable_class->create_gc = gdk_offscreen_window_create_gc; drawable_class->_copy_to_image = gdk_offscreen_window_copy_to_image; drawable_class->ref_cairo_surface = gdk_offscreen_window_ref_cairo_surface; drawable_class->set_colormap = gdk_offscreen_window_set_colormap; drawable_class->get_colormap = gdk_offscreen_window_get_colormap; drawable_class->get_depth = gdk_offscreen_window_get_depth; drawable_class->get_screen = gdk_offscreen_window_get_screen; drawable_class->get_visual = gdk_offscreen_window_get_visual; drawable_class->get_source_drawable = gdk_offscreen_window_get_source_drawable; drawable_class->get_composite_drawable = gdk_offscreen_window_get_composite_drawable; drawable_class->draw_rectangle = gdk_offscreen_window_draw_rectangle; drawable_class->draw_arc = gdk_offscreen_window_draw_arc; drawable_class->draw_polygon = gdk_offscreen_window_draw_polygon; drawable_class->draw_text = gdk_offscreen_window_draw_text; drawable_class->draw_text_wc = gdk_offscreen_window_draw_text_wc; drawable_class->draw_drawable = gdk_offscreen_window_draw_drawable; drawable_class->draw_points = gdk_offscreen_window_draw_points; drawable_class->draw_segments = gdk_offscreen_window_draw_segments; drawable_class->draw_lines = gdk_offscreen_window_draw_lines; drawable_class->draw_image = gdk_offscreen_window_draw_image; drawable_class->draw_pixbuf = gdk_offscreen_window_draw_pixbuf; } static void gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface) { iface->show = gdk_offscreen_window_show; iface->hide = gdk_offscreen_window_hide; iface->withdraw = gdk_offscreen_window_withdraw; iface->raise = gdk_offscreen_window_raise; iface->lower = gdk_offscreen_window_lower; iface->move_resize = gdk_offscreen_window_move_resize; iface->set_background = gdk_offscreen_window_set_background; iface->set_back_pixmap = gdk_offscreen_window_set_back_pixmap; iface->get_events = gdk_offscreen_window_get_events; iface->set_events = gdk_offscreen_window_set_events; iface->clear_area = gdk_offscreen_window_clear_area; iface->reparent = gdk_offscreen_window_reparent; iface->set_cursor = gdk_offscreen_window_set_cursor; iface->get_geometry = gdk_offscreen_window_get_geometry; iface->shape_combine_mask = gdk_offscreen_window_shape_combine_mask; iface->shape_combine_region = gdk_offscreen_window_shape_combine_region; iface->set_child_shapes = gdk_offscreen_window_set_child_shapes; iface->merge_child_shapes = gdk_offscreen_window_merge_child_shapes; iface->set_static_gravities = gdk_offscreen_window_set_static_gravities; iface->queue_antiexpose = gdk_offscreen_window_queue_antiexpose; iface->get_origin = gdk_offscreen_window_get_origin; } #define __GDK_OFFSCREEN_WINDOW_C__ #include "gdkaliasdef.c"