gtk2/gdk/gdkoffscreenwindow.c
Alexander Larsson 864649157d Move _gdk_gc_remove_drawable_clip from after each time its set to before each pixmap set and when adding a new different region
This means we can avoid changing the clip if we're drawing with the same gc to the same clip region
2009-04-02 10:14:06 +02:00

1226 lines
32 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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 <config.h>
#include <math.h>
#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 GdkDrawable *
get_real_drawable (GdkOffscreenWindow *offscreen)
{
GdkPixmapObject *pixmap;
pixmap = (GdkPixmapObject *) offscreen->pixmap;
return GDK_DRAWABLE (pixmap->impl);
}
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 = get_real_drawable (offscreen);
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 = get_real_drawable (offscreen);
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 = get_real_drawable (offscreen);
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 = get_real_drawable (offscreen);
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 = get_real_drawable (offscreen);
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 = get_real_drawable (offscreen);
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 = get_real_drawable (offscreen);
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 = get_real_drawable (offscreen);
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 = get_real_drawable (offscreen);
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 = get_real_drawable (offscreen);
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 = get_real_drawable (offscreen);
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"