forked from AuroraMiddleware/gtk
eabac453e6
The history before this was kind of twisted as several different approaches were tested, so that was all squashed into this initial commit to hide the uninteresting changes and files that were later removed.
1218 lines
32 KiB
C
1218 lines
32 KiB
C
/* 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 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"
|