mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-05 16:20:10 +00:00
New approach to motion event handling
This commit is contained in:
parent
afc81c9e64
commit
b771c9924d
237
gdk/gdkdisplay.c
237
gdk/gdkdisplay.c
@ -491,7 +491,7 @@ gdk_display_real_get_window_at_pointer (GdkDisplay *display,
|
||||
GdkWindow *window;
|
||||
gint x, y;
|
||||
|
||||
window = _gdk_windowing_window_at_pointer (display, &x, &y);
|
||||
window = _gdk_windowing_window_at_pointer (display, &x, &y, NULL);
|
||||
|
||||
/* This might need corrections, as the native window returned
|
||||
may contain client side children */
|
||||
@ -737,6 +737,17 @@ generate_grab_broken_event (GdkWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_window_under_pointer (GdkDisplay *display,
|
||||
GdkWindow *window)
|
||||
{
|
||||
if (display->pointer_info.window_under_pointer)
|
||||
g_object_unref (display->pointer_info.window_under_pointer);
|
||||
display->pointer_info.window_under_pointer = window;
|
||||
if (window)
|
||||
g_object_ref (window);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_display_set_has_pointer_grab (GdkDisplay *display,
|
||||
GdkWindow *window,
|
||||
@ -747,51 +758,89 @@ _gdk_display_set_has_pointer_grab (GdkDisplay *display,
|
||||
guint32 time,
|
||||
gboolean implicit)
|
||||
{
|
||||
int wx, wy;
|
||||
GdkWindow *pointer_window, *src_toplevel, *dest_toplevel, *src_window;
|
||||
|
||||
/* Normal GRAB events are sent by listening for enter and leave
|
||||
* events on the native event window, which is then proxied
|
||||
* into the virtual windows when the events are seen.
|
||||
* However, there are two cases where X will not send these events:
|
||||
* * When there is already a grab on the native parent of the
|
||||
* virtual grab window
|
||||
* * When there is no grab, but the pointer is already in the
|
||||
* native parent of the virtual grab window
|
||||
* In the first case we send the right GRAB events from the grab, but
|
||||
* in the second case we need to generate our own UNGRAB crossing events.
|
||||
*/
|
||||
if (display->pointer_grab.window != NULL &&
|
||||
display->pointer_grab.window != window)
|
||||
{
|
||||
generate_grab_broken_event (GDK_WINDOW (display->pointer_grab.window),
|
||||
FALSE, display->pointer_grab.implicit,
|
||||
window);
|
||||
|
||||
/* Re-grabbing. Pretend we have no grab for now so that
|
||||
the GRAB events get delivered */
|
||||
display->pointer_grab.window = NULL;
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
display->pointer_grab.window,
|
||||
window,
|
||||
GDK_CROSSING_GRAB,
|
||||
/* These may be stale... */
|
||||
display->pointer_info.toplevel_x,
|
||||
display->pointer_info.toplevel_y,
|
||||
display->pointer_info.state,
|
||||
time, TRUE, TRUE);
|
||||
}
|
||||
else if (_gdk_windowing_window_at_pointer (display, &wx, &wy) == native_window)
|
||||
|
||||
/* We need to generate crossing events for the grab.
|
||||
* However, there are never any crossing events for implicit grabs
|
||||
* TODO: ... Actually, this could happen if the pointer window doesn't have button mask so a parent gets the event...
|
||||
*/
|
||||
if (!implicit)
|
||||
{
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
display->pointer_info.window_under_pointer,
|
||||
window,
|
||||
GDK_CROSSING_GRAB,
|
||||
/* These may be stale... */
|
||||
display->pointer_info.toplevel_x,
|
||||
display->pointer_info.toplevel_y,
|
||||
display->pointer_info.state,
|
||||
time, TRUE, TRUE);
|
||||
GdkScreen *screen;
|
||||
GdkWindowObject *w;
|
||||
int x, y;
|
||||
GdkModifierType state;
|
||||
|
||||
/* We send GRAB crossing events from the window under the pointer to the
|
||||
grab window. Except if there is an old grab then we start from that */
|
||||
if (display->pointer_grab.window)
|
||||
src_window = display->pointer_grab.window;
|
||||
else
|
||||
src_window = display->pointer_info.window_under_pointer;
|
||||
|
||||
/* Unset any current grab to make sure we send the events */
|
||||
display->pointer_grab.window = NULL;
|
||||
|
||||
if (src_window != window)
|
||||
{
|
||||
/* _gdk_syntesize_crossing_events only works inside one toplevel, split into two calls if needed */
|
||||
if (src_window)
|
||||
src_toplevel = gdk_window_get_toplevel (src_window);
|
||||
else
|
||||
src_toplevel = NULL;
|
||||
dest_toplevel = gdk_window_get_toplevel (window);
|
||||
|
||||
if (src_toplevel == NULL ||
|
||||
src_toplevel == dest_toplevel)
|
||||
{
|
||||
_gdk_windowing_window_get_pointer (display,
|
||||
dest_toplevel,
|
||||
&x, &y, &state);
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
src_window,
|
||||
window,
|
||||
GDK_CROSSING_GRAB,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gdk_windowing_window_get_pointer (display,
|
||||
src_toplevel,
|
||||
&x, &y, &state);
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
src_window,
|
||||
NULL,
|
||||
GDK_CROSSING_GRAB,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL, FALSE);
|
||||
_gdk_windowing_window_get_pointer (display,
|
||||
dest_toplevel,
|
||||
&x, &y, &state);
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
NULL,
|
||||
window,
|
||||
GDK_CROSSING_GRAB,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* !owner_event Grabbing a window that we're not inside, current status is
|
||||
now NULL (i.e. outside grabbed window) */
|
||||
if (!owner_events && display->pointer_info.window_under_pointer != window)
|
||||
set_window_under_pointer (display, NULL);
|
||||
}
|
||||
|
||||
display->pointer_grab.window = window;
|
||||
@ -810,10 +859,12 @@ _gdk_display_unset_has_pointer_grab (GdkDisplay *display,
|
||||
gboolean do_grab_one_pointer_release_event,
|
||||
guint32 time)
|
||||
{
|
||||
int wx, wy;
|
||||
GdkWindow *pointer_window, *src_toplevel, *dest_toplevel;
|
||||
GdkWindow *old_grab_window;
|
||||
GdkWindow *old_native_grab_window;
|
||||
|
||||
int x, y;
|
||||
GdkModifierType state;
|
||||
GdkWindowObject *w;
|
||||
|
||||
old_grab_window = display->pointer_grab.window;
|
||||
old_native_grab_window = display->pointer_grab.native_window;
|
||||
@ -821,35 +872,99 @@ _gdk_display_unset_has_pointer_grab (GdkDisplay *display,
|
||||
if (do_grab_one_pointer_release_event)
|
||||
display->pointer_grab.grab_one_pointer_release_event = display->pointer_grab.window;
|
||||
|
||||
/* We need to set this to null befor syntesizing events to make sure they get
|
||||
delivered to anything but the grab window */
|
||||
/* Set first so crossing events get sent */
|
||||
display->pointer_grab.window = NULL;
|
||||
|
||||
/* Normal UNGRAB events are sent by listening for enter and leave
|
||||
* events on the native event window, which is then proxied
|
||||
* into the virtual windows when the events are seen.
|
||||
* However, there are two cases where X will not send these events:
|
||||
* * When this ungrab is due to a new grab on the native window that
|
||||
* is a parent of the currently grabbed virtual window
|
||||
* * When there is no new grab, and the pointer is already in the
|
||||
* grabbed virtual windows parent native window
|
||||
* In the first case we send the right GRAB events from the grab, but
|
||||
* in the second case we need to generate our own UNGRAB crossing events.
|
||||
*/
|
||||
pointer_window = _gdk_windowing_window_at_pointer (display, &x, &y, &state);
|
||||
|
||||
if (pointer_window != NULL &&
|
||||
(GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
|
||||
GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
|
||||
pointer_window = NULL;
|
||||
|
||||
if (_gdk_windowing_window_at_pointer (display, &wx, &wy) == old_native_grab_window)
|
||||
/* We force checked what window we're in, so we need to
|
||||
* update the toplevel_under_pointer info, as that won't get told of
|
||||
* this change.
|
||||
*/
|
||||
if (display->pointer_info.toplevel_under_pointer)
|
||||
g_object_unref (display->pointer_info.toplevel_under_pointer);
|
||||
display->pointer_info.toplevel_under_pointer = NULL;
|
||||
|
||||
if (pointer_window)
|
||||
{
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
old_grab_window,
|
||||
display->pointer_info.window_under_pointer,
|
||||
GDK_CROSSING_UNGRAB,
|
||||
/* These may be stale... */
|
||||
display->pointer_info.toplevel_x,
|
||||
display->pointer_info.toplevel_y,
|
||||
display->pointer_info.state,
|
||||
time, TRUE, TRUE);
|
||||
/* Convert to toplevel */
|
||||
w = (GdkWindowObject *)pointer_window;
|
||||
while (w->parent->window_type != GDK_WINDOW_ROOT)
|
||||
{
|
||||
x += w->x;
|
||||
y += w->y;
|
||||
w = w->parent;
|
||||
}
|
||||
|
||||
/* w is now toplevel and x,y in toplevel coords */
|
||||
|
||||
display->pointer_info.toplevel_under_pointer = g_object_ref (w);
|
||||
|
||||
/* Find child window */
|
||||
pointer_window =
|
||||
_gdk_window_find_descendant_at ((GdkWindow *)w,
|
||||
x, y,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (pointer_window == NULL)
|
||||
{
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
old_grab_window,
|
||||
NULL,
|
||||
GDK_CROSSING_UNGRAB,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pointer_window != old_grab_window)
|
||||
{
|
||||
/* _gdk_syntesize_crossing_events only works inside one toplevel, split into two calls if needed */
|
||||
src_toplevel = gdk_window_get_toplevel (old_grab_window);
|
||||
dest_toplevel = gdk_window_get_toplevel (pointer_window);
|
||||
|
||||
if (src_toplevel == dest_toplevel)
|
||||
{
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
display->pointer_info.window_under_pointer,
|
||||
pointer_window,
|
||||
GDK_CROSSING_UNGRAB,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: We're reporting the wrong coords here. They are in pointer_window toplevel coords */
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
display->pointer_info.window_under_pointer,
|
||||
NULL,
|
||||
GDK_CROSSING_UNGRAB,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL, FALSE);
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
NULL,
|
||||
pointer_window,
|
||||
GDK_CROSSING_UNGRAB,
|
||||
x, y, state,
|
||||
time,
|
||||
NULL, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We're now ungrabbed, update the window_under_pointer */
|
||||
set_window_under_pointer (display, pointer_window);
|
||||
|
||||
if (implicit)
|
||||
generate_grab_broken_event (old_grab_window,
|
||||
FALSE, implicit,
|
||||
|
@ -58,14 +58,18 @@ typedef struct
|
||||
GdkWindow *grab_one_pointer_release_event;
|
||||
} GdkPointerGrabInfo;
|
||||
|
||||
/* Tracks information about which window the pointer is in and
|
||||
* at what position the mouse is. This is useful when we need
|
||||
* to synthesize events later.
|
||||
/* Tracks information about which window and position the pointer last was in.
|
||||
* This is useful when we need to synthesize events later.
|
||||
* Note that we track toplevel_under_pointer using enter/leave events,
|
||||
* so in the case of a grab, either with owner_events==FALSE or with the
|
||||
* pointer in no clients window the x/y coordinates may actually be outside
|
||||
* the window.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
GdkWindow *window_under_pointer;
|
||||
gdouble toplevel_x, toplevel_y;
|
||||
GdkWindow *toplevel_under_pointer; /* The toplevel window with mouse inside, tracked via native events */
|
||||
GdkWindow *window_under_pointer; /* The window that last got sent a normal enter event */
|
||||
gdouble toplevel_x, toplevel_y;
|
||||
guint32 state;
|
||||
} GdkPointerWindowInfo;
|
||||
|
||||
|
@ -345,7 +345,12 @@ GdkWindow* _gdk_windowing_window_get_pointer (GdkDisplay *display,
|
||||
GdkModifierType *mask);
|
||||
GdkWindow* _gdk_windowing_window_at_pointer (GdkDisplay *display,
|
||||
gint *win_x,
|
||||
gint *win_y);
|
||||
gint *win_y,
|
||||
GdkModifierType *mask);
|
||||
void _gdk_windowing_got_event (GdkDisplay *display,
|
||||
GList *event_link,
|
||||
GdkEvent *event);
|
||||
|
||||
|
||||
/* Return the number of bits-per-pixel for images of the specified depth. */
|
||||
gint _gdk_windowing_get_bits_for_depth (GdkDisplay *display,
|
||||
@ -521,8 +526,8 @@ void _gdk_syntesize_crossing_events (GdkDisplay *display,
|
||||
gint toplevel_y,
|
||||
GdkModifierType mask,
|
||||
guint32 time_,
|
||||
gboolean do_first,
|
||||
gboolean do_last);
|
||||
GdkEvent *event_in_queue,
|
||||
gboolean before_event);
|
||||
|
||||
void _gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window);
|
||||
|
||||
|
720
gdk/gdkwindow.c
720
gdk/gdkwindow.c
@ -1159,6 +1159,7 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
|
||||
GdkWindowObject *temp_private;
|
||||
GdkWindow *temp_window;
|
||||
GdkScreen *screen;
|
||||
GdkDisplay *display;
|
||||
GList *children;
|
||||
GList *tmp;
|
||||
|
||||
@ -1169,11 +1170,13 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
|
||||
if (GDK_WINDOW_DESTROYED (window))
|
||||
return;
|
||||
|
||||
display = gdk_drawable_get_display (GDK_DRAWABLE (window));
|
||||
screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
|
||||
temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
|
||||
if (temp_window == window)
|
||||
g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
|
||||
|
||||
|
||||
switch (GDK_WINDOW_TYPE (window))
|
||||
{
|
||||
case GDK_WINDOW_ROOT:
|
||||
@ -1284,6 +1287,12 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
|
||||
gdk_window_redirect_free (private->redirect);
|
||||
|
||||
private->redirect = NULL;
|
||||
|
||||
if (display->pointer_info.toplevel_under_pointer == window)
|
||||
{
|
||||
g_object_unref (display->pointer_info.toplevel_under_pointer);
|
||||
display->pointer_info.toplevel_under_pointer = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -6615,13 +6624,9 @@ static gboolean
|
||||
point_in_window (GdkWindowObject *window,
|
||||
double x, double y)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
|
||||
|
||||
return
|
||||
x >= 0 && x < w &&
|
||||
y >= 0 && y < h;
|
||||
x >= 0 && x < window->width &&
|
||||
y >= 0 && y < window->height;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -6856,22 +6861,22 @@ is_motion_type (GdkEventType type)
|
||||
type == GDK_LEAVE_NOTIFY;
|
||||
}
|
||||
|
||||
static GdkWindow *
|
||||
find_common_ancestor (GdkWindow *win1,
|
||||
GdkWindow *win2)
|
||||
static GdkWindowObject *
|
||||
find_common_ancestor (GdkWindowObject *win1,
|
||||
GdkWindowObject *win2)
|
||||
{
|
||||
GdkWindowObject *tmp;
|
||||
GList *path1 = NULL, *path2 = NULL;
|
||||
GList *list1, *list2;
|
||||
|
||||
tmp = GDK_WINDOW_OBJECT (win1);
|
||||
tmp = win1;
|
||||
while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
|
||||
{
|
||||
path1 = g_list_prepend (path1, tmp);
|
||||
tmp = tmp->parent;
|
||||
}
|
||||
|
||||
tmp = GDK_WINDOW_OBJECT (win2);
|
||||
tmp = win2;
|
||||
while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
|
||||
{
|
||||
path2 = g_list_prepend (path2, tmp);
|
||||
@ -6890,7 +6895,7 @@ find_common_ancestor (GdkWindow *win1,
|
||||
g_list_free (path1);
|
||||
g_list_free (path2);
|
||||
|
||||
return GDK_WINDOW (tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
GdkEvent *
|
||||
@ -6995,6 +7000,54 @@ _gdk_make_event (GdkWindow *window,
|
||||
return event;
|
||||
}
|
||||
|
||||
static void
|
||||
send_crossing_event (GdkDisplay *display,
|
||||
GdkWindowObject *toplevel,
|
||||
GdkWindowObject *window,
|
||||
GdkEventType type,
|
||||
GdkCrossingMode mode,
|
||||
GdkNotifyType notify_type,
|
||||
GdkWindow *subwindow,
|
||||
gint toplevel_x,
|
||||
gint toplevel_y,
|
||||
GdkModifierType mask,
|
||||
guint32 time_,
|
||||
GdkEvent *event_in_queue,
|
||||
gboolean before_event)
|
||||
{
|
||||
GdkEvent *event;
|
||||
guint32 event_mask;
|
||||
|
||||
if (display->pointer_grab.window != NULL &&
|
||||
!display->pointer_grab.owner_events &&
|
||||
(GdkWindow *)window != display->pointer_grab.window)
|
||||
return;
|
||||
|
||||
if (type == GDK_LEAVE_NOTIFY)
|
||||
event_mask = GDK_LEAVE_NOTIFY_MASK;
|
||||
else
|
||||
event_mask = GDK_ENTER_NOTIFY_MASK;
|
||||
|
||||
if (window->event_mask & event_mask)
|
||||
{
|
||||
event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, before_event);
|
||||
event->crossing.time = time_;
|
||||
event->crossing.subwindow = subwindow;
|
||||
if (subwindow)
|
||||
g_object_ref (subwindow);
|
||||
convert_toplevel_coords_to_window ((GdkWindow *)window,
|
||||
toplevel_x, toplevel_y,
|
||||
&event->crossing.x, &event->crossing.y);
|
||||
event->crossing.x_root = toplevel_x + toplevel->x;
|
||||
event->crossing.y_root = toplevel_y + toplevel->y;
|
||||
event->crossing.mode = mode;
|
||||
event->crossing.detail = notify_type;
|
||||
event->crossing.focus = FALSE;
|
||||
event->crossing.state = mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The coordinates are in the toplevel window that src/dest are in.
|
||||
* src and dest are always (if != NULL) in the same toplevel, as
|
||||
* we get a leave-notify and set the window_under_pointer to null
|
||||
@ -7009,159 +7062,134 @@ _gdk_syntesize_crossing_events (GdkDisplay *display,
|
||||
gint toplevel_y,
|
||||
GdkModifierType mask,
|
||||
guint32 time_,
|
||||
gboolean do_first,
|
||||
gboolean do_last)
|
||||
GdkEvent *event_in_queue,
|
||||
gboolean before_event)
|
||||
{
|
||||
GdkWindow *c;
|
||||
GdkWindow *win, *last, *next;
|
||||
GdkEvent *event;
|
||||
GdkWindowObject *c;
|
||||
GdkWindowObject *win, *last, *next;
|
||||
GList *path, *list;
|
||||
gboolean non_linear;
|
||||
GdkWindow *a;
|
||||
GdkWindow *b;
|
||||
GdkWindow *event_win;
|
||||
GdkWindowObject *a;
|
||||
GdkWindowObject *b;
|
||||
GdkWindowObject *toplevel;
|
||||
GdkNotifyType notify_type;
|
||||
|
||||
/* TODO: Don't send events to toplevel, as we get those from the windowing system */
|
||||
|
||||
a = src;
|
||||
b = dest;
|
||||
a = (GdkWindowObject *)src;
|
||||
b = (GdkWindowObject *)dest;
|
||||
if (a == b)
|
||||
return; /* No crossings generated between src and dest */
|
||||
|
||||
c = find_common_ancestor (a, b);
|
||||
|
||||
non_linear = (c != a) && (c != b);
|
||||
|
||||
if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
|
||||
{
|
||||
toplevel = (GdkWindowObject *)gdk_window_get_toplevel (a);
|
||||
toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
|
||||
|
||||
/* Traverse up from a to (excluding) c sending leave events */
|
||||
|
||||
event_win = get_target_window_for_pointer_event (display, a, GDK_LEAVE_NOTIFY, mask);
|
||||
if (do_first && event_win)
|
||||
{
|
||||
event = _gdk_make_event (event_win, GDK_LEAVE_NOTIFY, NULL, FALSE);
|
||||
event->crossing.time = time_;
|
||||
event->crossing.subwindow = NULL;
|
||||
convert_toplevel_coords_to_window (event_win,
|
||||
toplevel_x, toplevel_y,
|
||||
&event->crossing.x, &event->crossing.y);
|
||||
event->crossing.x_root = toplevel_x + toplevel->x;
|
||||
event->crossing.y_root = toplevel_y + toplevel->y;
|
||||
event->crossing.mode = mode;
|
||||
if (non_linear)
|
||||
event->crossing.detail = GDK_NOTIFY_NONLINEAR;
|
||||
else if (c == a)
|
||||
event->crossing.detail = GDK_NOTIFY_INFERIOR;
|
||||
else
|
||||
event->crossing.detail = GDK_NOTIFY_ANCESTOR;
|
||||
event->crossing.focus = FALSE;
|
||||
event->crossing.state = mask;
|
||||
}
|
||||
|
||||
if (non_linear)
|
||||
notify_type = GDK_NOTIFY_NONLINEAR;
|
||||
else if (c == a)
|
||||
notify_type = GDK_NOTIFY_INFERIOR;
|
||||
else
|
||||
notify_type = GDK_NOTIFY_ANCESTOR;
|
||||
send_crossing_event (display, toplevel,
|
||||
a, GDK_LEAVE_NOTIFY,
|
||||
mode,
|
||||
notify_type,
|
||||
NULL,
|
||||
toplevel_x, toplevel_y,
|
||||
mask, time_,
|
||||
event_in_queue, before_event);
|
||||
|
||||
if (c != a)
|
||||
{
|
||||
if (non_linear)
|
||||
notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
|
||||
else
|
||||
notify_type = GDK_NOTIFY_VIRTUAL;
|
||||
|
||||
last = a;
|
||||
win = GDK_WINDOW (GDK_WINDOW_OBJECT (a)->parent);
|
||||
win = a->parent;
|
||||
while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
|
||||
{
|
||||
event_win = get_target_window_for_pointer_event (display, win, GDK_LEAVE_NOTIFY, mask);
|
||||
if (event_win)
|
||||
{
|
||||
event = _gdk_make_event (event_win, GDK_LEAVE_NOTIFY, NULL, FALSE);
|
||||
event->crossing.time = time_;
|
||||
event->crossing.subwindow = g_object_ref (last);
|
||||
convert_toplevel_coords_to_window (event_win,
|
||||
toplevel_x, toplevel_y,
|
||||
&event->crossing.x, &event->crossing.y);
|
||||
event->crossing.x_root = toplevel_x + toplevel->x;
|
||||
event->crossing.y_root = toplevel_y + toplevel->y;
|
||||
event->crossing.mode = mode;
|
||||
if (non_linear)
|
||||
event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
|
||||
else
|
||||
event->crossing.detail = GDK_NOTIFY_VIRTUAL;
|
||||
event->crossing.focus = FALSE;
|
||||
event->crossing.state = mask;
|
||||
}
|
||||
send_crossing_event (display, toplevel,
|
||||
win, GDK_LEAVE_NOTIFY,
|
||||
mode,
|
||||
notify_type,
|
||||
(GdkWindow *)last,
|
||||
toplevel_x, toplevel_y,
|
||||
mask, time_,
|
||||
event_in_queue, before_event);
|
||||
|
||||
last = win;
|
||||
win = GDK_WINDOW (GDK_WINDOW_OBJECT (win)->parent);
|
||||
win = win->parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (b) /* Might not be a dest, e.g. if we're moving out of the window */
|
||||
{
|
||||
toplevel = (GdkWindowObject *)gdk_window_get_toplevel (b);
|
||||
toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
|
||||
|
||||
/* Traverse down from c to b */
|
||||
if (c != b)
|
||||
{
|
||||
path = NULL;
|
||||
win = GDK_WINDOW (GDK_WINDOW_OBJECT (b)->parent);
|
||||
win = b->parent;
|
||||
while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
|
||||
{
|
||||
path = g_list_prepend (path, win);
|
||||
win = GDK_WINDOW( GDK_WINDOW_OBJECT (win)->parent);
|
||||
win = win->parent;
|
||||
}
|
||||
|
||||
if (non_linear)
|
||||
notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
|
||||
else
|
||||
notify_type = GDK_NOTIFY_VIRTUAL;
|
||||
|
||||
list = path;
|
||||
while (list)
|
||||
{
|
||||
win = (GdkWindow *)list->data;
|
||||
win = (GdkWindowObject *)list->data;
|
||||
list = g_list_next (list);
|
||||
if (list)
|
||||
next = (GdkWindow *)list->data;
|
||||
next = (GdkWindowObject *)list->data;
|
||||
else
|
||||
next = b;
|
||||
|
||||
event_win = get_target_window_for_pointer_event (display, win, GDK_ENTER_NOTIFY, mask);
|
||||
if (event_win)
|
||||
{
|
||||
event = _gdk_make_event (event_win, GDK_ENTER_NOTIFY, NULL, FALSE);
|
||||
event->crossing.time = time_;
|
||||
event->crossing.subwindow = g_object_ref (next);
|
||||
convert_toplevel_coords_to_window (event_win,
|
||||
toplevel_x, toplevel_y,
|
||||
&event->crossing.x, &event->crossing.y);
|
||||
event->crossing.x_root = toplevel_x + toplevel->x;
|
||||
event->crossing.y_root = toplevel_y + toplevel->y;
|
||||
event->crossing.mode = mode;
|
||||
if (non_linear)
|
||||
event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
|
||||
else
|
||||
event->crossing.detail = GDK_NOTIFY_VIRTUAL;
|
||||
event->crossing.focus = FALSE;
|
||||
event->crossing.state = mask;
|
||||
}
|
||||
|
||||
send_crossing_event (display, toplevel,
|
||||
win, GDK_ENTER_NOTIFY,
|
||||
mode,
|
||||
notify_type,
|
||||
(GdkWindow *)next,
|
||||
toplevel_x, toplevel_y,
|
||||
mask, time_,
|
||||
event_in_queue, before_event);
|
||||
}
|
||||
g_list_free (path);
|
||||
}
|
||||
|
||||
event_win = get_target_window_for_pointer_event (display, b, GDK_ENTER_NOTIFY, mask);
|
||||
if (do_last && event_win)
|
||||
{
|
||||
event = _gdk_make_event (event_win, GDK_ENTER_NOTIFY, NULL, FALSE);
|
||||
event->crossing.time = time_;
|
||||
event->crossing.subwindow = NULL;
|
||||
convert_toplevel_coords_to_window (event_win,
|
||||
toplevel_x, toplevel_y,
|
||||
&event->crossing.x, &event->crossing.y);
|
||||
event->crossing.x_root = toplevel_x + toplevel->x;
|
||||
event->crossing.y_root = toplevel_y + toplevel->y;
|
||||
event->crossing.mode = mode;
|
||||
if (non_linear)
|
||||
event->crossing.detail = GDK_NOTIFY_NONLINEAR;
|
||||
else if (c == a)
|
||||
event->crossing.detail = GDK_NOTIFY_ANCESTOR;
|
||||
else
|
||||
event->crossing.detail = GDK_NOTIFY_INFERIOR;
|
||||
event->crossing.focus = FALSE;
|
||||
event->crossing.state = mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (non_linear)
|
||||
notify_type = GDK_NOTIFY_NONLINEAR;
|
||||
else if (c == a)
|
||||
notify_type = GDK_NOTIFY_ANCESTOR;
|
||||
else
|
||||
notify_type = GDK_NOTIFY_INFERIOR;
|
||||
|
||||
send_crossing_event (display, toplevel,
|
||||
b, GDK_ENTER_NOTIFY,
|
||||
mode,
|
||||
notify_type,
|
||||
NULL,
|
||||
toplevel_x, toplevel_y,
|
||||
mask, time_,
|
||||
event_in_queue, before_event);
|
||||
}
|
||||
}
|
||||
|
||||
static GdkWindow *
|
||||
@ -7176,146 +7204,182 @@ get_toplevel (GdkWindow *w)
|
||||
return GDK_WINDOW (private);
|
||||
}
|
||||
|
||||
/* Returns the window inside the event window with the pointer in it
|
||||
* at the specified coordinates, or NULL if its not in any child of
|
||||
* the toplevel. It also takes into account !owner_events grabs.
|
||||
*/
|
||||
static GdkWindow *
|
||||
get_pointer_window (GdkDisplay *display,
|
||||
GdkWindow *event_window,
|
||||
gdouble toplevel_x,
|
||||
gdouble toplevel_y)
|
||||
{
|
||||
GdkWindow *pointer_window;
|
||||
|
||||
if (event_window == display->pointer_info.toplevel_under_pointer)
|
||||
pointer_window =
|
||||
_gdk_window_find_descendant_at (event_window,
|
||||
toplevel_x, toplevel_y,
|
||||
NULL, NULL);
|
||||
else
|
||||
pointer_window = NULL;
|
||||
|
||||
if (display->pointer_grab.window != NULL &&
|
||||
!display->pointer_grab.owner_events &&
|
||||
pointer_window != display->pointer_grab.window)
|
||||
pointer_window = NULL;
|
||||
|
||||
return pointer_window;
|
||||
}
|
||||
|
||||
static void
|
||||
set_window_under_pointer (GdkDisplay *display,
|
||||
GdkWindow *window)
|
||||
{
|
||||
if (display->pointer_info.window_under_pointer)
|
||||
g_object_unref (display->pointer_info.window_under_pointer);
|
||||
display->pointer_info.window_under_pointer = window;
|
||||
if (window)
|
||||
g_object_ref (window);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkWindow *changed_toplevel;
|
||||
GdkWindow *pointer_toplevel;
|
||||
GdkWindow *pointer_toplevel, *grab_toplevel;
|
||||
GdkWindow *new_window_under_pointer;
|
||||
|
||||
changed_toplevel = get_toplevel (changed_window);
|
||||
|
||||
display = gdk_drawable_get_display (changed_window);
|
||||
if (display->pointer_info.window_under_pointer)
|
||||
if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
|
||||
{
|
||||
pointer_toplevel = get_toplevel (display->pointer_info.window_under_pointer);
|
||||
|
||||
if (pointer_toplevel == changed_toplevel)
|
||||
new_window_under_pointer =
|
||||
get_pointer_window (display, changed_toplevel,
|
||||
display->pointer_info.toplevel_x,
|
||||
display->pointer_info.toplevel_y);
|
||||
if (new_window_under_pointer !=
|
||||
display->pointer_info.window_under_pointer)
|
||||
{
|
||||
new_window_under_pointer =
|
||||
_gdk_window_find_descendant_at (pointer_toplevel,
|
||||
display->pointer_info.toplevel_x,
|
||||
display->pointer_info.toplevel_y,
|
||||
NULL, NULL);
|
||||
if (new_window_under_pointer !=
|
||||
display->pointer_info.window_under_pointer)
|
||||
{
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
display->pointer_info.window_under_pointer,
|
||||
new_window_under_pointer,
|
||||
GDK_CROSSING_NORMAL,
|
||||
display->pointer_info.toplevel_x,
|
||||
display->pointer_info.toplevel_y,
|
||||
display->pointer_info.state,
|
||||
GDK_CURRENT_TIME,
|
||||
TRUE, TRUE);
|
||||
|
||||
if (display->pointer_info.window_under_pointer)
|
||||
g_object_unref (display->pointer_info.window_under_pointer);
|
||||
display->pointer_info.window_under_pointer = NULL;
|
||||
if (new_window_under_pointer)
|
||||
display->pointer_info.window_under_pointer = g_object_ref (new_window_under_pointer);
|
||||
}
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
display->pointer_info.window_under_pointer,
|
||||
new_window_under_pointer,
|
||||
GDK_CROSSING_NORMAL,
|
||||
display->pointer_info.toplevel_x,
|
||||
display->pointer_info.toplevel_y,
|
||||
display->pointer_info.state,
|
||||
GDK_CURRENT_TIME,
|
||||
NULL, FALSE);
|
||||
set_window_under_pointer (display, new_window_under_pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't use for crossing events */
|
||||
static GdkWindow *
|
||||
get_event_window (GdkDisplay *display,
|
||||
GdkWindow *pointer_window,
|
||||
GdkEventType type,
|
||||
GdkModifierType mask)
|
||||
{
|
||||
guint evmask;
|
||||
GdkWindow *grab_window;
|
||||
GdkWindowObject *w;
|
||||
|
||||
if ((display->pointer_grab.window != NULL && !display->pointer_grab.owner_events) ||
|
||||
(type == GDK_BUTTON_RELEASE && display->pointer_grab.grab_one_pointer_release_event))
|
||||
{
|
||||
evmask = display->pointer_grab.event_mask;
|
||||
evmask = update_evmask_for_button_motion (evmask, mask);
|
||||
|
||||
if (type == GDK_BUTTON_RELEASE &&
|
||||
display->pointer_grab.grab_one_pointer_release_event)
|
||||
{
|
||||
grab_window = display->pointer_grab.grab_one_pointer_release_event;
|
||||
display->pointer_grab.grab_one_pointer_release_event = NULL;
|
||||
}
|
||||
else
|
||||
grab_window = display->pointer_grab.window;
|
||||
|
||||
if (evmask & type_masks[type])
|
||||
return grab_window;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
w = (GdkWindowObject *)pointer_window;
|
||||
while (w != NULL)
|
||||
{
|
||||
evmask = w->event_mask;
|
||||
evmask = update_evmask_for_button_motion (evmask, mask);
|
||||
|
||||
if (evmask & type_masks[type])
|
||||
return (GdkWindow *)w;
|
||||
|
||||
w = w->parent;
|
||||
}
|
||||
|
||||
if (display->pointer_grab.window != NULL &&
|
||||
display->pointer_grab.owner_events)
|
||||
{
|
||||
evmask = display->pointer_grab.event_mask;
|
||||
evmask = update_evmask_for_button_motion (evmask, mask);
|
||||
|
||||
if (evmask & type_masks[type])
|
||||
return display->pointer_grab.window;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
proxy_pointer_event (GdkDisplay *display,
|
||||
GdkWindow *pointer_window,
|
||||
gdouble toplevel_x,
|
||||
gdouble toplevel_y,
|
||||
GdkEvent *source_event)
|
||||
{
|
||||
GdkWindow *event_window;
|
||||
GdkWindow *event_win, *cursor_window;
|
||||
gboolean crossing_event;
|
||||
GdkWindow *toplevel_window;
|
||||
GdkWindow *pointer_window;
|
||||
GdkWindow *cursor_window;
|
||||
gboolean sent_motion;
|
||||
GdkEvent *event;
|
||||
guint state;
|
||||
gdouble toplevel_x, toplevel_y;
|
||||
guint32 time_;
|
||||
|
||||
event_window = source_event->any.window;
|
||||
|
||||
toplevel_window = source_event->any.window;
|
||||
gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
|
||||
gdk_event_get_state (source_event, &state);
|
||||
time_ = gdk_event_get_time (source_event);
|
||||
|
||||
crossing_event =
|
||||
source_event->type == GDK_ENTER_NOTIFY ||
|
||||
source_event->type == GDK_LEAVE_NOTIFY;
|
||||
|
||||
if (crossing_event)
|
||||
pointer_window = get_pointer_window (display, toplevel_window, toplevel_x, toplevel_y);
|
||||
if (display->pointer_info.window_under_pointer != pointer_window)
|
||||
{
|
||||
GdkEventCrossing *crossing = &source_event->crossing;
|
||||
/* Either a toplevel crossing notify that ended up inside a child window,
|
||||
or a motion notify that got into another child window */
|
||||
/* Different than last time, send crossing events */
|
||||
|
||||
if (crossing->mode == GDK_CROSSING_GRAB)
|
||||
{
|
||||
if (crossing->type == GDK_LEAVE_NOTIFY &&
|
||||
display->pointer_info.window_under_pointer != NULL)
|
||||
{
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
display->pointer_info.window_under_pointer,
|
||||
event_window,
|
||||
GDK_CROSSING_GRAB,
|
||||
toplevel_x, toplevel_y, state, time_,
|
||||
TRUE, FALSE);
|
||||
}
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
display->pointer_info.window_under_pointer,
|
||||
pointer_window,
|
||||
GDK_CROSSING_NORMAL,
|
||||
toplevel_x, toplevel_y,
|
||||
state, time_,
|
||||
source_event, source_event->type == GDK_LEAVE_NOTIFY);
|
||||
|
||||
if (crossing->type == GDK_ENTER_NOTIFY &&
|
||||
display->pointer_grab.window != NULL)
|
||||
{
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
event_window,
|
||||
display->pointer_grab.window,
|
||||
GDK_CROSSING_GRAB,
|
||||
toplevel_x, toplevel_y, state, time_,
|
||||
FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (crossing->mode == GDK_CROSSING_UNGRAB)
|
||||
{
|
||||
if (crossing->type == GDK_LEAVE_NOTIFY &&
|
||||
display->pointer_grab.window != NULL)
|
||||
{
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
display->pointer_grab.window,
|
||||
event_window,
|
||||
GDK_CROSSING_UNGRAB,
|
||||
toplevel_x, toplevel_y, state, time_,
|
||||
TRUE, FALSE);
|
||||
}
|
||||
|
||||
if (crossing->type == GDK_ENTER_NOTIFY &&
|
||||
display->pointer_info.window_under_pointer != NULL)
|
||||
{
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
event_window,
|
||||
display->pointer_info.window_under_pointer,
|
||||
GDK_CROSSING_UNGRAB,
|
||||
toplevel_x, toplevel_y, state, time_,
|
||||
FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
set_window_under_pointer (display, pointer_window);
|
||||
}
|
||||
|
||||
cursor_window = pointer_window;
|
||||
if (display->pointer_grab.window &&
|
||||
(pointer_window == NULL ||
|
||||
!is_parent_of (display->pointer_grab.window, pointer_window)))
|
||||
cursor_window = display->pointer_grab.window;
|
||||
|
||||
/* TODO: set cursor from cursor_window, or grab cursor */
|
||||
|
||||
sent_motion = FALSE;
|
||||
if (!crossing_event &&
|
||||
(display->pointer_info.window_under_pointer == pointer_window ||
|
||||
(display->pointer_grab.window != NULL &&
|
||||
!display->pointer_grab.owner_events)))
|
||||
else if (source_event->type == GDK_MOTION_NOTIFY)
|
||||
{
|
||||
/* send motion events */
|
||||
event_win = get_target_window_for_pointer_event (display, pointer_window, GDK_MOTION_NOTIFY, state);
|
||||
GdkWindow *event_win;
|
||||
|
||||
event_win = get_event_window (display,
|
||||
pointer_window,
|
||||
source_event->type,
|
||||
state);
|
||||
|
||||
if (event_win)
|
||||
{
|
||||
sent_motion = TRUE;
|
||||
@ -7334,43 +7398,52 @@ proxy_pointer_event (GdkDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
_gdk_syntesize_crossing_events (display,
|
||||
display->pointer_info.window_under_pointer,
|
||||
pointer_window,
|
||||
GDK_CROSSING_NORMAL,
|
||||
toplevel_x, toplevel_y,
|
||||
state, time_,
|
||||
TRUE, TRUE);
|
||||
/* TODO: set cursor from cursor_window, or grab cursor */
|
||||
cursor_window = pointer_window;
|
||||
if (display->pointer_grab.window &&
|
||||
(pointer_window == NULL ||
|
||||
!is_parent_of (display->pointer_grab.window, pointer_window)))
|
||||
cursor_window = display->pointer_grab.window;
|
||||
/* Actually, this should probably happen in synthesize crossing so it works with geometry changes */
|
||||
|
||||
/* unlink move event from parent if we sent a motion event */
|
||||
return source_event->type == GDK_MOTION_NOTIFY && sent_motion;
|
||||
|
||||
/* unlink all move events from queue.
|
||||
We handle our own, including our emulated masks. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
proxy_button_event (GdkWindow *pointer_window,
|
||||
gdouble toplevel_x,
|
||||
gdouble toplevel_y,
|
||||
GdkEvent *source_event)
|
||||
proxy_button_event (GdkEvent *source_event)
|
||||
{
|
||||
GdkWindow *toplevel_window;
|
||||
GdkWindow *event_win;
|
||||
GdkWindow *pointer_window;
|
||||
GdkEvent *event;
|
||||
guint state;
|
||||
guint32 time_;
|
||||
GdkEventType type;
|
||||
gdouble toplevel_x, toplevel_y;
|
||||
GdkDisplay *display;
|
||||
|
||||
type = source_event->any.type;
|
||||
toplevel_window = source_event->any.window;
|
||||
gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
|
||||
gdk_event_get_state (source_event, &state);
|
||||
time_ = gdk_event_get_time (source_event);
|
||||
display = gdk_drawable_get_display (source_event->any.window);
|
||||
|
||||
|
||||
if ((type == GDK_BUTTON_PRESS || type == GDK_SCROLL) &&
|
||||
pointer_window != NULL &&
|
||||
display->pointer_grab.window == source_event->any.window &&
|
||||
display->pointer_grab.implicit &&
|
||||
!display->pointer_grab.converted_implicit)
|
||||
{
|
||||
if (pointer_window != source_event->any.window)
|
||||
pointer_window =
|
||||
_gdk_window_find_descendant_at (toplevel_window,
|
||||
toplevel_x, toplevel_y,
|
||||
NULL, NULL);
|
||||
|
||||
if (pointer_window != NULL &&
|
||||
pointer_window != source_event->any.window)
|
||||
_gdk_display_set_has_pointer_grab (display,
|
||||
pointer_window,
|
||||
display->pointer_grab.native_window,
|
||||
@ -7382,57 +7455,51 @@ proxy_button_event (GdkWindow *pointer_window,
|
||||
display->pointer_grab.converted_implicit = TRUE;
|
||||
}
|
||||
|
||||
event_win = get_target_window_for_pointer_event (display,
|
||||
pointer_window,
|
||||
type,
|
||||
state);
|
||||
pointer_window = get_pointer_window (display, toplevel_window, toplevel_x, toplevel_y);
|
||||
|
||||
event_win = get_event_window (display,
|
||||
pointer_window,
|
||||
type,
|
||||
state);
|
||||
|
||||
if (event_win == NULL)
|
||||
return TRUE;
|
||||
|
||||
if (event_win != source_event->any.window)
|
||||
event = _gdk_make_event (event_win, type, source_event, FALSE);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
event = _gdk_make_event (event_win, type, source_event, FALSE);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GDK_BUTTON_PRESS:
|
||||
case GDK_BUTTON_RELEASE:
|
||||
event->button.button = source_event->button.button;
|
||||
convert_toplevel_coords_to_window (event_win,
|
||||
toplevel_x, toplevel_y,
|
||||
&event->button.x, &event->button.y);
|
||||
event->button.x_root = source_event->button.x_root;
|
||||
event->button.y_root = source_event->button.y_root;
|
||||
event->button.state = state;
|
||||
event->button.device = source_event->button.device;
|
||||
|
||||
if (type == GDK_BUTTON_PRESS)
|
||||
_gdk_event_button_generate (display, event);
|
||||
return TRUE;
|
||||
|
||||
case GDK_SCROLL:
|
||||
event->scroll.direction = source_event->scroll.direction;
|
||||
convert_toplevel_coords_to_window (event_win,
|
||||
toplevel_x, toplevel_y,
|
||||
&event->scroll.x, &event->scroll.y);
|
||||
event->scroll.x_root = source_event->scroll.x_root;
|
||||
event->scroll.y_root = source_event->scroll.y_root;
|
||||
event->scroll.state = state;
|
||||
event->scroll.device = source_event->scroll.device;
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Same window as original window, keep the event */
|
||||
if (source_event->type == GDK_BUTTON_PRESS)
|
||||
_gdk_event_button_generate (display, source_event);
|
||||
case GDK_BUTTON_PRESS:
|
||||
case GDK_BUTTON_RELEASE:
|
||||
event->button.button = source_event->button.button;
|
||||
convert_toplevel_coords_to_window (event_win,
|
||||
toplevel_x, toplevel_y,
|
||||
&event->button.x, &event->button.y);
|
||||
event->button.x_root = source_event->button.x_root;
|
||||
event->button.y_root = source_event->button.y_root;
|
||||
event->button.state = state;
|
||||
event->button.device = source_event->button.device;
|
||||
|
||||
if (type == GDK_BUTTON_PRESS)
|
||||
_gdk_event_button_generate (display, event);
|
||||
return TRUE;
|
||||
|
||||
case GDK_SCROLL:
|
||||
event->scroll.direction = source_event->scroll.direction;
|
||||
convert_toplevel_coords_to_window (event_win,
|
||||
toplevel_x, toplevel_y,
|
||||
&event->scroll.x, &event->scroll.y);
|
||||
event->scroll.x_root = source_event->scroll.x_root;
|
||||
event->scroll.y_root = source_event->scroll.y_root;
|
||||
event->scroll.state = state;
|
||||
event->scroll.device = source_event->scroll.device;
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE; /* Always unlink original, we want to obey the emulated event mask */
|
||||
}
|
||||
|
||||
void
|
||||
@ -7441,9 +7508,8 @@ _gdk_windowing_got_event (GdkDisplay *display,
|
||||
GdkEvent *event)
|
||||
{
|
||||
GdkWindow *event_window;
|
||||
GdkWindow *pointer_window;
|
||||
GdkWindowObject *event_private;
|
||||
gdouble x, y, child_x, child_y;
|
||||
gdouble x, y;
|
||||
gboolean unlink_event;
|
||||
|
||||
event_window = event->any.window;
|
||||
@ -7466,40 +7532,78 @@ _gdk_windowing_got_event (GdkDisplay *display,
|
||||
event_private->window_type);
|
||||
|
||||
/* We should only get these events on toplevel windows */
|
||||
g_warning ("got unexpected event of type %s on non-toplevel window (type %s)",
|
||||
g_warning ("got unexpected event of type %s on non-toplevel window (gtype %s, type %d)",
|
||||
event_type_value->value_name,
|
||||
window_type_value->value_name);
|
||||
window_type_value->value_name,
|
||||
GDK_WINDOW_TYPE (event_window));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((event->type == GDK_ENTER_NOTIFY ||
|
||||
event->type == GDK_LEAVE_NOTIFY) &&
|
||||
(event->crossing.mode == GDK_CROSSING_GRAB ||
|
||||
event->crossing.mode == GDK_CROSSING_UNGRAB))
|
||||
{
|
||||
/* We synthesize all crossing events due to grabs are synthesized,
|
||||
* so we ignore the native ones. This is partly to get easier non-X
|
||||
* portability, and because of problems with race conditions due to
|
||||
* the cached state in the client and the real state in the xserver
|
||||
* when grabbing.
|
||||
*/
|
||||
|
||||
/* Some grab in another window (by perhaps another client) did a grab.
|
||||
* The pointer is still in this window, but we won't get told if it
|
||||
* moves out, so NULL this now and set it back to the right value at
|
||||
* ungrab time.
|
||||
*/
|
||||
if (event->type == GDK_LEAVE_NOTIFY &&
|
||||
event->crossing.mode == GDK_CROSSING_GRAB)
|
||||
{
|
||||
g_assert (display->pointer_info.toplevel_under_pointer == event_window);
|
||||
g_object_unref (display->pointer_info.toplevel_under_pointer);
|
||||
display->pointer_info.toplevel_under_pointer = NULL;
|
||||
}
|
||||
|
||||
/* We ended up in this window after some (perhaps other clients)
|
||||
grab, so update the toplevel_under_window state */
|
||||
if (event->type == GDK_ENTER_NOTIFY &&
|
||||
event->crossing.mode == GDK_CROSSING_UNGRAB)
|
||||
{
|
||||
if (display->pointer_info.toplevel_under_pointer)
|
||||
g_object_unref (display->pointer_info.toplevel_under_pointer);
|
||||
display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gdk_event_get_coords (event, &x, &y);
|
||||
pointer_window = _gdk_window_find_descendant_at (event_window, x, y,
|
||||
&child_x,
|
||||
&child_y);
|
||||
unlink_event = FALSE;
|
||||
if (is_motion_type (event->type))
|
||||
unlink_event = proxy_pointer_event (display,
|
||||
pointer_window,
|
||||
x, y,
|
||||
event);
|
||||
else if (is_button_type (event->type))
|
||||
unlink_event = proxy_button_event (pointer_window, x, y,
|
||||
event);
|
||||
|
||||
/* Store last pointer window and position/state */
|
||||
if (event->type == GDK_ENTER_NOTIFY &&
|
||||
event->crossing.detail != GDK_NOTIFY_INFERIOR)
|
||||
{
|
||||
g_assert (display->pointer_info.toplevel_under_pointer == NULL);
|
||||
display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
|
||||
}
|
||||
else if (event->type == GDK_LEAVE_NOTIFY &&
|
||||
event->crossing.detail != GDK_NOTIFY_INFERIOR)
|
||||
{
|
||||
g_assert (display->pointer_info.toplevel_under_pointer == event_window);
|
||||
g_object_unref (display->pointer_info.toplevel_under_pointer);
|
||||
display->pointer_info.toplevel_under_pointer = NULL;
|
||||
}
|
||||
|
||||
gdk_event_get_coords (event, &x, &y);
|
||||
display->pointer_info.toplevel_x = x;
|
||||
display->pointer_info.toplevel_y = y;
|
||||
gdk_event_get_state (event, &display->pointer_info.state);
|
||||
|
||||
|
||||
if (pointer_window != display->pointer_info.window_under_pointer)
|
||||
{
|
||||
if (display->pointer_info.window_under_pointer)
|
||||
g_object_unref (display->pointer_info.window_under_pointer);
|
||||
display->pointer_info.window_under_pointer = NULL;
|
||||
if (pointer_window)
|
||||
display->pointer_info.window_under_pointer = g_object_ref (pointer_window);
|
||||
}
|
||||
unlink_event = FALSE;
|
||||
if (is_motion_type (event->type))
|
||||
unlink_event = proxy_pointer_event (display,
|
||||
event);
|
||||
else if (is_button_type (event->type))
|
||||
unlink_event = proxy_button_event (event);
|
||||
|
||||
if (unlink_event)
|
||||
{
|
||||
|
@ -987,7 +987,7 @@ gdk_event_translate (GdkDisplay *display,
|
||||
display_x11->keyboard_xgrab_window != NULL &&
|
||||
(
|
||||
/* The window is not a descendant of the grabbed window */
|
||||
!is_parent_of (display_x11->keyboard_xgrab_window, window) ||
|
||||
!is_parent_of ((GdkWindow *)display_x11->keyboard_xgrab_window, window) ||
|
||||
/* Or owner event is false */
|
||||
!display_x11->keyboard_xgrab_owner_events
|
||||
)
|
||||
|
@ -3185,7 +3185,8 @@ gdk_display_warp_pointer (GdkDisplay *display,
|
||||
GdkWindow*
|
||||
_gdk_windowing_window_at_pointer (GdkDisplay *display,
|
||||
gint *win_x,
|
||||
gint *win_y)
|
||||
gint *win_y,
|
||||
GdkModifierType *mask)
|
||||
{
|
||||
GdkWindow *window;
|
||||
GdkScreen *screen;
|
||||
@ -3294,7 +3295,9 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
|
||||
window = gdk_window_lookup_for_display (display, xwindow_last);
|
||||
*win_x = window ? winx : -1;
|
||||
*win_y = window ? winy : -1;
|
||||
|
||||
if (mask)
|
||||
*mask = xmask;
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user