Add signals for offscreen window embedding

3 signals are for offscreen windows
get-offscreen-parent: Get the parent window an offscreen is embedded in
to-parent: Convert coordinates from offscreen to parent
from-parent: Convert coordinates from parent to offscreen

1 signal is for the window embedding offscreens:
pick-offscreen-child: This picks what (if any) offscreen is at a specific position

The last signal is only used if you call gdk_window_set_has_offscreen_children
to tell gdk that the window has embedded offscreen children.
Add get-pointer signal for offscreen window pointer getting

Apps using offscreen windows can connect to get-pointer on offscreen
windows in order to make gdk_window_get_pointer() return correct
values.

Add get-offscreen-parent signal

Add signals for from-parent and to-parent coordinate mapping

Add pick-offscreen-child signal
This commit is contained in:
Alexander Larsson 2009-06-04 20:15:29 +02:00
parent 4720bbc15e
commit e1b52da0ab
6 changed files with 136 additions and 45 deletions

View File

@ -152,10 +152,10 @@ gdk_built_sources = \
gdkincludedir = $(includedir)/gtk-2.0/gdk
gdkinclude_HEADERS = $(gdk_public_h_sources) $(gdk_built_public_sources)
# gdkmarshalers.c is not here because it is currently an empty file
common_sources = \
$(gdk_c_sources) \
gdkenumtypes.c \
gdkmarshalers.c \
gdkmarshalers.h
libgdk_directfb_2_0_la_SOURCES = $(common_sources)

View File

@ -259,6 +259,7 @@ struct _GdkWindowObject
guint effective_visibility : 2;
guint visibility : 2; /* The visibility wrt the toplevel (i.e. based on clip_region) */
guint native_visibility : 2; /* the native visibility of a impl windows */
guint has_offscreen_children : 1;
GdkWindowPaint *implicit_paint;
GdkInputWindow *input_window; /* only set for impl windows */

View File

@ -1,2 +1,6 @@
VOID:OBJECT
VOID:BOOLEAN
VOID:POINTER,POINTER,POINTER
OBJECT:VOID
OBJECT:DOUBLE,DOUBLE
VOID:DOUBLE,DOUBLE,POINTER,POINTER

View File

@ -77,8 +77,8 @@ static void gdk_offscreen_window_impl_iface_init (GdkWindowImplIface
static void gdk_offscreen_window_hide (GdkWindow *window);
G_DEFINE_TYPE_WITH_CODE (GdkOffscreenWindow,
gdk_offscreen_window,
GDK_TYPE_DRAWABLE,
gdk_offscreen_window,
GDK_TYPE_DRAWABLE,
G_IMPLEMENT_INTERFACE (GDK_TYPE_WINDOW_IMPL,
gdk_offscreen_window_impl_iface_init));
@ -94,7 +94,7 @@ gdk_offscreen_window_finalize (GObject *object)
offscreen->cursor = NULL;
gdk_pixmap_unref (offscreen->pixmap);
G_OBJECT_CLASS (gdk_offscreen_window_parent_class)->finalize (object);
}
@ -122,7 +122,7 @@ gdk_offscreen_window_destroy (GdkWindow *window,
static gboolean
is_parent_of (GdkWindow *parent,
GdkWindow *child)
GdkWindow *child)
{
GdkWindow *w;
@ -161,18 +161,18 @@ gdk_offscreen_window_copy_to_image (GdkDrawable *drawable,
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);
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);
}
@ -258,7 +258,7 @@ add_damage (GdkOffscreenWindow *offscreen,
{
GdkRectangle rect;
GdkRegion *damage;
rect.x = x;
rect.y = y;
rect.width = w;
@ -291,7 +291,7 @@ gdk_offscreen_window_draw_drawable (GdkDrawable *drawable,
{
GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
GdkDrawable *real_drawable = get_real_drawable (offscreen);
gdk_draw_drawable (real_drawable, gc,
src, xsrc, ysrc,
xdest, ydest,
@ -316,7 +316,7 @@ gdk_offscreen_window_draw_rectangle (GdkDrawable *drawable,
gc, filled, x, y, width, height);
add_damage (offscreen, x, y, width, height);
}
static void
@ -354,7 +354,7 @@ gdk_offscreen_window_draw_polygon (GdkDrawable *drawable,
{
GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
GdkDrawable *real_drawable = get_real_drawable (offscreen);
gdk_draw_polygon (real_drawable,
gc,
filled,
@ -364,10 +364,10 @@ gdk_offscreen_window_draw_polygon (GdkDrawable *drawable,
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);
@ -375,7 +375,7 @@ gdk_offscreen_window_draw_polygon (GdkDrawable *drawable,
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);
@ -450,10 +450,10 @@ gdk_offscreen_window_draw_points (GdkDrawable *drawable,
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);
@ -461,7 +461,7 @@ gdk_offscreen_window_draw_points (GdkDrawable *drawable,
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);
@ -485,10 +485,10 @@ gdk_offscreen_window_draw_segments (GdkDrawable *drawable,
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);
@ -500,7 +500,7 @@ gdk_offscreen_window_draw_segments (GdkDrawable *drawable,
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);
@ -573,7 +573,7 @@ gdk_offscreen_window_draw_pixbuf (GdkDrawable *drawable,
{
GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
GdkDrawable *real_drawable = get_real_drawable (offscreen);
gdk_draw_pixbuf (real_drawable,
gc,
pixbuf,
@ -591,7 +591,7 @@ gdk_offscreen_window_draw_pixbuf (GdkDrawable *drawable,
}
void
void
_gdk_offscreen_window_new (GdkWindow *window,
GdkScreen *screen,
GdkVisual *visual,
@ -606,7 +606,7 @@ _gdk_offscreen_window_new (GdkWindow *window,
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))
@ -655,7 +655,7 @@ gdk_offscreen_window_reparent (GdkWindow *window,
/* 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;
@ -681,7 +681,7 @@ gdk_offscreen_window_reparent (GdkWindow *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;
}
@ -704,12 +704,7 @@ gdk_offscreen_window_get_pointer (GdkWindow *window,
gint *y,
GdkModifierType *mask)
{
*x = 0;
*y = 0;
*mask = 0;
/* TODO: Implement this by signal emission */
/* TODO: Base on signals */
return TRUE;
}
@ -728,12 +723,12 @@ 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;
}
@ -789,7 +784,7 @@ gdk_offscreen_window_move_resize_internal (GdkWindow *window,
{
private->width = width;
private->height = height;
old_pixmap = offscreen->pixmap;
offscreen->pixmap = gdk_pixmap_new (GDK_DRAWABLE (old_pixmap),
width,
@ -804,7 +799,7 @@ gdk_offscreen_window_move_resize_internal (GdkWindow *window,
-1, -1);
g_object_unref (old_pixmap);
}
if (GDK_WINDOW_IS_MAPPED (private))
{
// TODO: Only invalidate new area, i.e. for larger windows
@ -815,11 +810,11 @@ gdk_offscreen_window_move_resize_internal (GdkWindow *window,
static void
gdk_offscreen_window_move_resize (GdkWindow *window,
gboolean with_move,
gboolean with_move,
gint x,
gint y,
gint y,
gint width,
gint height)
gint height)
{
GdkWindowObject *private = (GdkWindowObject *)window;
GdkOffscreenWindow *offscreen;
@ -952,9 +947,9 @@ gdk_offscreen_window_set_back_pixmap (GdkWindow *window,
static void
gdk_offscreen_window_shape_combine_region (GdkWindow *window,
const GdkRegion *shape_region,
gint offset_x,
gint offset_y)
const GdkRegion *shape_region,
gint offset_x,
gint offset_y)
{
}

View File

@ -33,6 +33,7 @@
#include "gdkpixmap.h"
#include "gdkdrawable.h"
#include "gdkscreen.h"
#include "gdkmarshalers.h"
#include "gdkalias.h"
#undef DEBUG_WINDOW_PRINTING
@ -120,6 +121,14 @@
/* This adds a local value to the GdkVisibilityState enum */
#define GDK_VISIBILITY_NOT_VIEWABLE 3
enum {
GET_OFFSCREEN_PARENT,
PICK_OFFSCREEN_CHILD, /* only called if has_offscreen_children */
TO_PARENT,
FROM_PARENT,
LAST_SIGNAL
};
struct _GdkWindowPaint
{
GdkRegion *region;
@ -305,6 +314,8 @@ static void do_move_region_bits_on_impl (GdkWindowObject *private,
static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
static void move_native_children (GdkWindowObject *private);
static guint signals[LAST_SIGNAL] = { 0 };
static gpointer parent_class = NULL;
static const cairo_user_data_key_t gdk_window_cairo_key;
@ -376,6 +387,17 @@ gdk_window_init (GdkWindowObject *window)
window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
}
static gboolean
accumulate_get_parent (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer data)
{
g_value_copy (handler_return, return_accu);
/* Continue while returning NULL */
return g_value_get_pointer (handler_return) == NULL;
}
static GQuark quark_pointer_window = 0;
static void
@ -419,6 +441,54 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
drawable_class->get_source_drawable = gdk_window_get_source_drawable;
quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
signals[GET_OFFSCREEN_PARENT] =
g_signal_new (g_intern_static_string ("get-offscreen-parent"),
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
0,
accumulate_get_parent, NULL,
gdk_marshal_OBJECT__VOID,
GDK_TYPE_WINDOW,
0);
signals[PICK_OFFSCREEN_CHILD] =
g_signal_new (g_intern_static_string ("pick-offscreen-child"),
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
0,
accumulate_get_parent, NULL,
gdk_marshal_OBJECT__DOUBLE_DOUBLE,
GDK_TYPE_WINDOW,
2,
G_TYPE_DOUBLE,
G_TYPE_DOUBLE);
signals[TO_PARENT] =
g_signal_new (g_intern_static_string ("to-parent"),
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
G_TYPE_NONE,
4,
G_TYPE_DOUBLE,
G_TYPE_DOUBLE,
G_TYPE_POINTER,
G_TYPE_POINTER);
signals[FROM_PARENT] =
g_signal_new (g_intern_static_string ("from-parent"),
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
G_TYPE_NONE,
4,
G_TYPE_DOUBLE,
G_TYPE_DOUBLE,
G_TYPE_POINTER,
G_TYPE_POINTER);
}
static void
@ -8364,6 +8434,24 @@ _gdk_display_set_window_under_pointer (GdkDisplay *display,
_gdk_display_enable_motion_hints (display);
}
void
gdk_window_set_has_offscreen_children (GdkWindow *window,
gboolean has_offscreen_children)
{
GdkWindowObject *private = (GdkWindowObject *)window;
private->has_offscreen_children = !!has_offscreen_children;
}
gboolean
gdk_window_get_has_offscreen_children (GdkWindow *window)
{
GdkWindowObject *private = (GdkWindowObject *)window;
return private->has_offscreen_children;
}
void
_gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
{

View File

@ -656,6 +656,9 @@ GdkWindow *gdk_get_default_root_window (void);
/* Offscreen redirection */
GdkPixmap *gdk_window_get_offscreen_pixmap (GdkWindow *window);
void gdk_window_set_has_offscreen_children (GdkWindow *window,
gboolean has_offscreen_children);
gboolean gdk_window_get_has_offscreen_children (GdkWindow *window);
void gdk_window_redirect_to_drawable (GdkWindow *window,
GdkDrawable *drawable,