mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-13 05:50:10 +00:00
More refactoring of the event handling: Extract synthesizing of crossing
2007-06-17 Richard Hult <richard@imendio.com> * gdk/quartz/gdkevents-quartz.c (gdk_event_translate) (synthesize_crossing_events_for_ns_event) (find_window_for_ns_event): More refactoring of the event handling: Extract synthesizing of crossing events from find_window_for_ns_event so that it doesn't have any side effects, and call the new function from gdk_event_translate instead. svn path=/trunk/; revision=18176
This commit is contained in:
parent
cd03a9e977
commit
33ec37ee9e
@ -1,3 +1,12 @@
|
||||
2007-06-17 Richard Hult <richard@imendio.com>
|
||||
|
||||
* gdk/quartz/gdkevents-quartz.c (gdk_event_translate)
|
||||
(synthesize_crossing_events_for_ns_event)
|
||||
(find_window_for_ns_event): More refactoring of the event
|
||||
handling: Extract synthesizing of crossing events from
|
||||
find_window_for_ns_event so that it doesn't have any side effects,
|
||||
and call the new function from gdk_event_translate instead.
|
||||
|
||||
2007-06-16 Richard Hult <richard@imendio.com>
|
||||
|
||||
* gdk/quartz/gdkevents-quartz.c: (find_window_for_ns_event),
|
||||
|
@ -789,6 +789,13 @@ synthesize_crossing_events (GdkWindow *window,
|
||||
}
|
||||
|
||||
_gdk_quartz_events_update_mouse_window (window);
|
||||
|
||||
/* FIXME: This does't work when someone calls gdk_window_set_cursor
|
||||
* during a grab. The right behavior is that the cursor doesn't
|
||||
* change when a grab is in effect, but in that case it does.
|
||||
*/
|
||||
if (window && !_gdk_quartz_pointer_grab_window)
|
||||
_gdk_quartz_events_update_cursor (window);
|
||||
}
|
||||
|
||||
void
|
||||
@ -845,15 +852,16 @@ _gdk_quartz_events_update_cursor (GdkWindow *window)
|
||||
GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
|
||||
NSCursor *nscursor = nil;
|
||||
|
||||
while (private) {
|
||||
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
||||
while (private)
|
||||
{
|
||||
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
||||
|
||||
nscursor = impl->nscursor;
|
||||
if (nscursor)
|
||||
break;
|
||||
nscursor = impl->nscursor;
|
||||
if (nscursor)
|
||||
break;
|
||||
|
||||
private = private->parent;
|
||||
}
|
||||
private = private->parent;
|
||||
}
|
||||
|
||||
if (!nscursor)
|
||||
nscursor = [NSCursor arrowCursor];
|
||||
@ -1025,6 +1033,134 @@ find_mouse_window_for_ns_event (NSEvent *nsevent,
|
||||
return mouse_window;
|
||||
}
|
||||
|
||||
/* Synthesizes crossing events if necessary, based on the passed in
|
||||
* NSEvent. Uses NSMouseEntered and NSMouseExisted for toplevels and
|
||||
* the mouse moved/dragged events for child windows, to see if the
|
||||
* mouse window has changed.
|
||||
*/
|
||||
static void
|
||||
synthesize_crossing_events_for_ns_event (NSEvent *nsevent)
|
||||
{
|
||||
NSEventType event_type;
|
||||
GdkWindow *mouse_window;
|
||||
gint x;
|
||||
gint y;
|
||||
|
||||
event_type = [nsevent type];
|
||||
|
||||
switch (event_type)
|
||||
{
|
||||
case NSMouseMoved:
|
||||
case NSLeftMouseDragged:
|
||||
case NSRightMouseDragged:
|
||||
case NSOtherMouseDragged:
|
||||
mouse_window = find_mouse_window_for_ns_event (nsevent, &x, &y);
|
||||
|
||||
/* We don't need to handle the case where we don't find a mouse
|
||||
* window (i.e. after leaving a GDK toplevel and not entering a
|
||||
* new one) here, it's covered by NSMouseExited events.
|
||||
*/
|
||||
if (mouse_window && mouse_window != current_mouse_window)
|
||||
synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, x, y);
|
||||
|
||||
break;
|
||||
|
||||
case NSMouseEntered:
|
||||
{
|
||||
GdkWindow *event_toplevel;
|
||||
NSPoint point;
|
||||
|
||||
event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
|
||||
point = [nsevent locationInWindow];
|
||||
|
||||
x = point.x;
|
||||
|
||||
/* Flip the y coordinate. */
|
||||
if (event_toplevel == _gdk_root)
|
||||
y = _gdk_quartz_window_get_inverted_screen_y (point.y);
|
||||
else
|
||||
{
|
||||
GdkWindowImplQuartz *impl;
|
||||
|
||||
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (event_toplevel)->impl);
|
||||
y = impl->height - point.y;
|
||||
}
|
||||
|
||||
/* This is the only case where we actually use the window from
|
||||
* the event since we need to know which toplevel we entered
|
||||
* so it can be tracked properly.
|
||||
*/
|
||||
mouse_window = _gdk_quartz_window_find_child (event_toplevel, x, y);
|
||||
|
||||
/* Treat unknown windows (including title bar/buttons,
|
||||
* desktop) as the root.
|
||||
*/
|
||||
if (!mouse_window)
|
||||
mouse_window = _gdk_root;
|
||||
|
||||
if (mouse_window != event_toplevel)
|
||||
get_converted_window_coordinates (event_toplevel,
|
||||
x, y,
|
||||
mouse_window,
|
||||
&x, &y);
|
||||
|
||||
synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, x, y);
|
||||
}
|
||||
break;
|
||||
|
||||
case NSMouseExited:
|
||||
{
|
||||
GdkWindow *event_toplevel;
|
||||
NSPoint point;
|
||||
gint x_orig, y_orig;
|
||||
|
||||
/* We get mouse exited when leaving toplevels. We only use
|
||||
* this when leaving from a window to the root window. The
|
||||
* other case is handled above by checking the motion/button
|
||||
* events, or getting a MouseEntered for another GDK window.
|
||||
*
|
||||
* The reason we don't use MouseExited for other windows is
|
||||
* that quartz first delivers the entered event and then the
|
||||
* exited which is the opposite from what we need.
|
||||
*/
|
||||
|
||||
event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
|
||||
point = [nsevent locationInWindow];
|
||||
|
||||
x = point.x;
|
||||
|
||||
/* Flip the y coordinate. */
|
||||
if (event_toplevel == _gdk_root)
|
||||
y = _gdk_quartz_window_get_inverted_screen_y (point.y);
|
||||
else
|
||||
{
|
||||
GdkWindowImplQuartz *impl;
|
||||
|
||||
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (event_toplevel)->impl);
|
||||
y = impl->height - point.y;
|
||||
}
|
||||
|
||||
if (gdk_window_get_origin (event_toplevel, &x_orig, &y_orig))
|
||||
{
|
||||
x += x_orig;
|
||||
y += y_orig;
|
||||
}
|
||||
|
||||
/* Check if the root window has a child at this position, if
|
||||
* so ignore the event since it means we didn't exit to the
|
||||
* root.
|
||||
*/
|
||||
mouse_window = _gdk_quartz_window_find_child (_gdk_root, x, y);
|
||||
if (mouse_window == _gdk_root)
|
||||
synthesize_crossing_events (_gdk_root, GDK_CROSSING_NORMAL, nsevent, x, y);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function finds the correct window to send an event to, taking
|
||||
* into account grabs, event propagation, and event masks.
|
||||
*/
|
||||
@ -1037,35 +1173,6 @@ find_window_for_ns_event (NSEvent *nsevent,
|
||||
|
||||
event_type = [nsevent type];
|
||||
|
||||
/* Synthesize crossing events when moving between child
|
||||
* windows. Toplevels are handled with NSMouseEntered and
|
||||
* NSMouseExited in the switch below.
|
||||
*/
|
||||
if (event_type == NSMouseMoved ||
|
||||
event_type == NSLeftMouseDragged ||
|
||||
event_type == NSRightMouseDragged ||
|
||||
event_type == NSOtherMouseDragged)
|
||||
{
|
||||
GdkWindow *mouse_window;
|
||||
|
||||
mouse_window = find_mouse_window_for_ns_event (nsevent, x, y);
|
||||
|
||||
/* We don't need to handle the case where we don't find a mouse
|
||||
* window (i.e. after leaving a gdk toplevel and not entering a
|
||||
* new one) here, it's covered by NSMouseExited events.
|
||||
*/
|
||||
if (mouse_window && mouse_window != current_mouse_window)
|
||||
synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, *x, *y);
|
||||
|
||||
/* FIXME: Does this check really work as intended? It seems like
|
||||
* we sometimes get a cursor update when we shouldn't, for
|
||||
* example during an implicit grab on a GtkButton, and dragging
|
||||
* the mouse over a link button.
|
||||
*/
|
||||
if (mouse_window && !_gdk_quartz_pointer_grab_window)
|
||||
_gdk_quartz_events_update_cursor (mouse_window);
|
||||
}
|
||||
|
||||
switch (event_type)
|
||||
{
|
||||
case NSLeftMouseDown:
|
||||
@ -1165,91 +1272,8 @@ find_window_for_ns_event (NSEvent *nsevent,
|
||||
break;
|
||||
|
||||
case NSMouseEntered:
|
||||
{
|
||||
GdkWindow *event_toplevel;
|
||||
GdkWindow *mouse_window;
|
||||
NSPoint point;
|
||||
gint x_tmp, y_tmp;
|
||||
|
||||
event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
|
||||
point = [nsevent locationInWindow];
|
||||
|
||||
x_tmp = point.x;
|
||||
|
||||
/* Flip the y coordinate. */
|
||||
if (event_toplevel == _gdk_root)
|
||||
y_tmp = _gdk_quartz_window_get_inverted_screen_y (point.y);
|
||||
else
|
||||
{
|
||||
GdkWindowImplQuartz *impl;
|
||||
|
||||
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (event_toplevel)->impl);
|
||||
y_tmp = impl->height - point.y;
|
||||
}
|
||||
|
||||
/* This is the only case where we actually use the window from
|
||||
* the event since we need to know which toplevel we entered
|
||||
* so it can be tracked properly.
|
||||
*/
|
||||
mouse_window = _gdk_quartz_window_find_child (event_toplevel, x_tmp, y_tmp);
|
||||
|
||||
/* Treat unknown windows (including title bar/buttons,
|
||||
* desktop) as the root.
|
||||
*/
|
||||
if (!mouse_window)
|
||||
mouse_window = _gdk_root;
|
||||
|
||||
synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, *x, *y);
|
||||
}
|
||||
break;
|
||||
|
||||
case NSMouseExited:
|
||||
{
|
||||
GdkWindow *event_toplevel;
|
||||
GdkWindow *mouse_window;
|
||||
NSPoint point;
|
||||
gint x_tmp, y_tmp;
|
||||
gint x_orig, y_orig;
|
||||
|
||||
/* We get mouse exited when leaving toplevels. We only use
|
||||
* this when leaving from a window to the root window. The
|
||||
* other case is handled above by checking the motion/button
|
||||
* events, or getting a MouseEntered for another GDK window.
|
||||
*
|
||||
* The reason we don't use MouseExited for other windows is
|
||||
* that quartz first delivers the entered event and then the
|
||||
* exited which is the opposite from what we need.
|
||||
*/
|
||||
|
||||
/* Check if the root window has a child at this position, if
|
||||
* so ignore the event.
|
||||
*/
|
||||
event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
|
||||
point = [nsevent locationInWindow];
|
||||
|
||||
x_tmp = point.x;
|
||||
|
||||
/* Flip the y coordinate. */
|
||||
if (event_toplevel == _gdk_root)
|
||||
y_tmp = _gdk_quartz_window_get_inverted_screen_y (point.y);
|
||||
else
|
||||
{
|
||||
GdkWindowImplQuartz *impl;
|
||||
|
||||
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (event_toplevel)->impl);
|
||||
y_tmp = impl->height - point.y;
|
||||
}
|
||||
|
||||
if (gdk_window_get_origin (event_toplevel, &x_orig, &y_orig))
|
||||
{
|
||||
x_tmp += x_orig;
|
||||
y_tmp += y_orig;
|
||||
}
|
||||
|
||||
mouse_window = _gdk_quartz_window_find_child (_gdk_root, x_tmp, y_tmp);
|
||||
if (mouse_window == _gdk_root)
|
||||
synthesize_crossing_events (_gdk_root, GDK_CROSSING_NORMAL, nsevent, *x, *y);
|
||||
}
|
||||
/* Already handled in synthesize_crossing_events_for_ns_event. */
|
||||
break;
|
||||
|
||||
case NSKeyDown:
|
||||
@ -1522,7 +1546,12 @@ gdk_event_translate (NSEvent *nsevent)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Find the right gdk window to send the event to, taking grabs and
|
||||
/* Take care of NSMouseEntered/Exited events and mouse movements
|
||||
* events and emit the right GDK crossing events.
|
||||
*/
|
||||
synthesize_crossing_events_for_ns_event (nsevent);
|
||||
|
||||
/* Find the right GDK window to send the event to, taking grabs and
|
||||
* event masks into consideration.
|
||||
*/
|
||||
window = find_window_for_ns_event (nsevent, &x, &y);
|
||||
|
Loading…
Reference in New Issue
Block a user