Base pointer grab on get-offscreen-parent

This commit is contained in:
Alexander Larsson
2009-06-05 14:50:58 +02:00
parent f195fbc221
commit 904f0ccb7c
4 changed files with 131 additions and 82 deletions

View File

@@ -69,7 +69,6 @@ gdk_get_use_xshm
gdk_set_use_xshm
#endif
gdk_keyboard_grab
gdk_pointer_grab
#endif
#endif
@@ -715,6 +714,7 @@ gdk_window_set_user_data
gdk_window_thaw_toplevel_updates_libgtk_only
gdk_window_thaw_updates
gdk_window_set_composited
gdk_pointer_grab
#endif
#endif

View File

@@ -453,6 +453,13 @@ GdkWindow* _gdk_windowing_window_at_pointer (GdkDisplay *display,
gint *win_x,
gint *win_y,
GdkModifierType *mask);
GdkGrabStatus _gdk_windowing_pointer_grab (GdkWindow *window,
GdkWindow *native,
gboolean owner_events,
GdkEventMask event_mask,
GdkWindow *confine_to,
GdkCursor *cursor,
guint32 time);
void _gdk_windowing_got_event (GdkDisplay *display,
GList *event_link,
GdkEvent *event,

View File

@@ -8434,6 +8434,112 @@ _gdk_display_set_window_under_pointer (GdkDisplay *display,
_gdk_display_enable_motion_hints (display);
}
static GdkWindow *
gdk_window_get_offscreen_parent (GdkWindow *window)
{
GdkWindowObject *private = (GdkWindowObject *)window;
GdkWindow *res;
res = NULL;
g_signal_emit_by_name (private->impl_window,
"get-offscreen-parent",
&res);
return res;
}
/*
*--------------------------------------------------------------
* gdk_pointer_grab
*
* Grabs the pointer to a specific window
*
* Arguments:
* "window" is the window which will receive the grab
* "owner_events" specifies whether events will be reported as is,
* or relative to "window"
* "event_mask" masks only interesting events
* "confine_to" limits the cursor movement to the specified window
* "cursor" changes the cursor for the duration of the grab
* "time" specifies the time
*
* Results:
*
* Side effects:
* requires a corresponding call to gdk_pointer_ungrab
*
*--------------------------------------------------------------
*/
GdkGrabStatus
gdk_pointer_grab (GdkWindow * window,
gboolean owner_events,
GdkEventMask event_mask,
GdkWindow * confine_to,
GdkCursor * cursor,
guint32 time)
{
GdkWindow *native;
GdkDisplay *display;
GdkGrabStatus res;
gulong serial;
g_return_val_if_fail (window != NULL, 0);
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
/* We need a native window for confine to to work, ensure we have one */
if (confine_to)
{
if (!gdk_window_ensure_native (confine_to))
{
g_warning ("Can't confine to grabbed window, not native");
confine_to = NULL;
}
}
/* Non-viewable client side window => fail */
if (!_gdk_window_has_impl (window) &&
!gdk_window_is_viewable (window))
return GDK_GRAB_NOT_VIEWABLE;
native = gdk_window_get_toplevel (window);
while (gdk_window_is_offscreen ((GdkWindowObject *)native))
{
native = gdk_window_get_offscreen_parent (native);
if (native == NULL ||
(!_gdk_window_has_impl (native) &&
!gdk_window_is_viewable (native)))
return GDK_GRAB_NOT_VIEWABLE;
native = gdk_window_get_toplevel (native);
}
display = gdk_drawable_get_display (window);
serial = _gdk_windowing_window_get_next_serial (display);
res = _gdk_windowing_pointer_grab (window,
native,
owner_events,
event_mask,
confine_to,
cursor,
time);
if (res == GDK_GRAB_SUCCESS)
_gdk_display_add_pointer_grab (display,
window,
native,
owner_events,
event_mask,
serial,
time,
FALSE);
return res;
}
void
gdk_window_set_has_offscreen_children (GdkWindow *window,
gboolean has_offscreen_children)

View File

@@ -138,16 +138,6 @@ gdk_x11_convert_grab_status (gint status)
return 0;
}
struct XPointerGrabInfo {
GdkDisplay *display;
GdkWindow *window;
GdkWindow *native_window;
gboolean owner_events;
gulong serial;
guint event_mask;
guint32 time;
};
static void
has_pointer_grab_callback (GdkDisplay *display,
gpointer data,
@@ -156,81 +146,38 @@ has_pointer_grab_callback (GdkDisplay *display,
_gdk_display_pointer_grab_update (display, serial);
}
/*
*--------------------------------------------------------------
* gdk_pointer_grab
*
* Grabs the pointer to a specific window
*
* Arguments:
* "window" is the window which will receive the grab
* "owner_events" specifies whether events will be reported as is,
* or relative to "window"
* "event_mask" masks only interesting events
* "confine_to" limits the cursor movement to the specified window
* "cursor" changes the cursor for the duration of the grab
* "time" specifies the time
*
* Results:
*
* Side effects:
* requires a corresponding call to gdk_pointer_ungrab
*
*--------------------------------------------------------------
*/
GdkGrabStatus
gdk_pointer_grab (GdkWindow * window,
gboolean owner_events,
GdkEventMask event_mask,
GdkWindow * confine_to,
GdkCursor * cursor,
guint32 time)
_gdk_windowing_pointer_grab (GdkWindow *window,
GdkWindow *native,
gboolean owner_events,
GdkEventMask event_mask,
GdkWindow *confine_to,
GdkCursor *cursor,
guint32 time)
{
gint return_val;
GdkCursorPrivate *cursor_private;
GdkWindow *native;
GdkDisplayX11 *display_x11;
guint xevent_mask;
Window xwindow;
Window xconfine_to;
Cursor xcursor;
unsigned long serial;
int i;
g_return_val_if_fail (window != NULL, 0);
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
native = gdk_window_get_toplevel (window);
/* We need a native window for confine to to work, ensure we have one */
if (confine_to)
gdk_window_ensure_native (confine_to);
/* TODO: What do we do for offscreens and their children? We need to proxy the grab somehow */
if (!GDK_IS_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (native)->impl))
return GDK_GRAB_SUCCESS;
if (!_gdk_window_has_impl (window) &&
!gdk_window_is_viewable (window))
return GDK_GRAB_NOT_VIEWABLE;
if (confine_to)
confine_to = _gdk_window_get_impl_window (confine_to);
display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
cursor_private = (GdkCursorPrivate*) cursor;
xwindow = GDK_WINDOW_XID (native);
serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
xconfine_to = None;
else
xconfine_to = GDK_WINDOW_XID (confine_to);
if (!cursor)
xcursor = None;
else
@@ -238,7 +185,7 @@ gdk_pointer_grab (GdkWindow * window,
_gdk_x11_cursor_update_theme (cursor);
xcursor = cursor_private->xcursor;
}
xevent_mask = 0;
for (i = 0; i < _gdk_nenvent_masks; i++)
{
@@ -250,7 +197,7 @@ gdk_pointer_grab (GdkWindow * window,
* hints. If we set a native one we just wouldn't get any events.
*/
xevent_mask &= ~PointerMotionHintMask;
return_val = _gdk_input_grab_pointer (window,
native,
owner_events,
@@ -258,7 +205,7 @@ gdk_pointer_grab (GdkWindow * window,
confine_to,
time);
if (return_val == GrabSuccess ||
if (return_val == GrabSuccess ||
G_UNLIKELY (!display_x11->trusted_client && return_val == AlreadyGrabbed))
{
if (!GDK_WINDOW_DESTROYED (native))
@@ -280,22 +227,11 @@ gdk_pointer_grab (GdkWindow * window,
else
return_val = AlreadyGrabbed;
}
if (return_val == GrabSuccess)
{
_gdk_display_add_pointer_grab (GDK_DISPLAY_OBJECT (display_x11),
window,
native,
owner_events,
event_mask,
serial,
time,
FALSE);
_gdk_x11_roundtrip_async (GDK_DISPLAY_OBJECT (display_x11),
has_pointer_grab_callback,
NULL);
}
if (return_val == GrabSuccess)
_gdk_x11_roundtrip_async (GDK_DISPLAY_OBJECT (display_x11),
has_pointer_grab_callback,
NULL);
return gdk_x11_convert_grab_status (return_val);
}