Break out code that was repeated into separate functions and call them

2007-05-28  Richard Hult  <richard@imendio.com>

	* gdk/quartz/gdkevents-quartz.c (get_child_coordinates_from_ancestor)
	(get_ancestor_coordinates_from_child): Break out code that was
	repeated into separate functions and call them instead.
	(find_window_for_mouse_nsevent): Break out this from
	find_window_for_nsevent to make the code clearer.
	(find_window_for_nsevent): Use the above and fix the returned
	coordinates in the process so that they are always relative the
	found window, both for the normal case and during grabs. Still
	needs fixing for the case where we get nsevents for a window other
	than than grab window during grabs.

svn path=/trunk/; revision=17971
This commit is contained in:
Richard Hult 2007-05-28 21:11:55 +00:00 committed by Richard Hult
parent d36c24a8b9
commit f2f1be4e4f
2 changed files with 189 additions and 55 deletions

View File

@ -1,3 +1,16 @@
2007-05-28 Richard Hult <richard@imendio.com>
* gdk/quartz/gdkevents-quartz.c (get_child_coordinates_from_ancestor)
(get_ancestor_coordinates_from_child): Break out code that was
repeated into separate functions and call them instead.
(find_window_for_mouse_nsevent): Break out this from
find_window_for_nsevent to make the code clearer.
(find_window_for_nsevent): Use the above and fix the returned
coordinates in the process so that they are always relative the
found window, both for the normal case and during grabs. Still
needs fixing for the case where we get nsevents for a window other
than than grab window during grabs.
2007-05-28 Richard Hult <richard@imendio.com>
* gdk/quartz/gdkevents-quartz.c (gdk_event_translate): Fix typo,

View File

@ -785,33 +785,136 @@ _gdk_quartz_events_update_cursor (GdkWindow *window)
[nscursor set];
}
/* This function finds the correct window to send an event to,
* taking into account grabs (FIXME: not done yet), event propagation,
* and event masks.
/* Translates coordinates from an ancestor window + coords, to
* coordinates that are relative the child window.
*/
static void
get_child_coordinates_from_ancestor (GdkWindow *ancestor_window,
gint ancestor_x,
gint ancestor_y,
GdkWindow *child_window,
gint *child_x,
gint *child_y)
{
GdkWindowObject *ancestor_private = GDK_WINDOW_OBJECT (ancestor_window);
GdkWindowObject *child_private = GDK_WINDOW_OBJECT (child_window);
while (child_private != ancestor_private)
{
ancestor_x -= child_private->x;
ancestor_y -= child_private->y;
child_private = child_private->parent;
}
*child_x = ancestor_x;
*child_y = ancestor_y;
}
/* Translates coordinates from a child window + coords, to
* coordinates that are relative the ancestor window.
*/
static void
get_ancestor_coordinates_from_child (GdkWindow *child_window,
gint child_x,
gint child_y,
GdkWindow *ancestor_window,
gint *ancestor_x,
gint *ancestor_y)
{
GdkWindowObject *child_private = GDK_WINDOW_OBJECT (child_window);
GdkWindowObject *ancestor_private = GDK_WINDOW_OBJECT (ancestor_window);
while (child_private != ancestor_private)
{
child_x += child_private->x;
child_y += child_private->y;
child_private = child_private->parent;
}
*ancestor_x = child_x;
*ancestor_y = child_y;
}
/* Given a mouse NSEvent, returns the window in which the pointer
* position from the event is. The returned coordinates are relative
* to the found window, and normal GDK coordinates, not Quartz.
*/
static GdkWindow *
find_window_for_event (NSEvent *nsevent, gint *x, gint *y)
find_window_for_mouse_nsevent (NSEvent *nsevent,
gint *x_ret,
gint *y_ret)
{
NSWindow *nswindow;
GdkWindow *toplevel;
NSPoint point;
gint x_tmp, y_tmp;
GdkWindow *found_window;
nswindow = [nsevent window];
toplevel = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
point = [nsevent locationInWindow];
x_tmp = point.x;
/* Flip the y coordinate. */
if (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 (toplevel)->impl);
y_tmp = impl->height - point.y;
}
found_window = _gdk_quartz_window_find_child (toplevel, x_tmp, y_tmp);
/* Translate the coordinates so they are relative to the found
* window.
*/
if (found_window)
get_child_coordinates_from_ancestor (toplevel,
x_tmp, y_tmp,
found_window,
&x_tmp, &y_tmp);
*x_ret = x_tmp;
*y_ret = y_tmp;
return found_window;
}
/* This function finds the correct window to send an event to, taking
* into account grabs, event propagation, and event masks.
*/
static GdkWindow *
find_window_for_nsevent (NSEvent *nsevent, gint *x, gint *y)
{
NSWindow *nswindow = [nsevent window];
NSEventType event_type = [nsevent type];
if (!nswindow)
return NULL;
/* Window where not created by GDK so the event should be handled by Quartz */
/* Window was not created by GDK so the event should be handled by Quartz. */
if (![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
return NULL;
/* 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 *toplevel = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
NSPoint point = [nsevent locationInWindow];
GdkWindow *mouse_window;
mouse_window = _gdk_quartz_window_find_child_by_point (toplevel, point.x, point.y, x, y);
mouse_window = find_window_for_mouse_nsevent (nsevent, x, y);
if (!mouse_window)
mouse_window = _gdk_root;
@ -826,7 +929,6 @@ find_window_for_event (NSEvent *nsevent, gint *x, gint *y)
if (current_mouse_window != mouse_window)
{
synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, *x, *y);
_gdk_quartz_events_update_cursor (mouse_window);
}
}
@ -846,73 +948,92 @@ find_window_for_event (NSEvent *nsevent, gint *x, gint *y)
case NSRightMouseDragged:
case NSOtherMouseDragged:
{
GdkWindow *toplevel = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
NSPoint point = [nsevent locationInWindow];
GdkWindow *mouse_window;
GdkEventMask event_mask;
GdkWindow *real_window;
if (_gdk_quartz_pointer_grab_window && !pointer_grab_owner_events)
/* From the docs for XGrabPointer:
*
* If owner_events is True and if a generated pointer event
* would normally be reported to this client, it is reported
* as usual. Otherwise, the event is reported with respect to
* the grab_window and is reported only if selected by
* event_mask. For either value of owner_events, unreported
* events are discarded.
*
* This means we first try the owner, then the grab window,
* then give up.
*/
if (_gdk_quartz_pointer_grab_window)
{
if (pointer_grab_owner_events)
{
mouse_window = find_window_for_mouse_nsevent (nsevent, x, y);
event_mask = get_event_mask_from_ns_event (nsevent);
real_window = find_window_interested_in_event_mask (mouse_window, event_mask, TRUE);
if (mouse_window && real_window && mouse_window != real_window)
get_ancestor_coordinates_from_child (mouse_window,
*x, *y,
real_window,
x, y);
if (real_window)
return real_window;
}
/* FIXME: This part needs some fixing, it doesn't return
* the right coordinates if the nsevent happens for a
* different window than the grab window.
*/
if (pointer_grab_event_mask & get_event_mask_from_ns_event (nsevent))
{
int tempx, tempy;
GdkWindowObject *w;
GdkWindowObject *grab_toplevel;
GdkWindow *grab_toplevel;
NSPoint point;
int x_tmp, y_tmp;
w = GDK_WINDOW_OBJECT (_gdk_quartz_pointer_grab_window);
grab_toplevel = GDK_WINDOW_OBJECT (gdk_window_get_toplevel (_gdk_quartz_pointer_grab_window));
grab_toplevel = gdk_window_get_toplevel (_gdk_quartz_pointer_grab_window);
point = [nsevent locationInWindow];
tempx = point.x;
tempy = GDK_WINDOW_IMPL_QUARTZ (grab_toplevel->impl)->height -
point.y;
x_tmp = point.x;
y_tmp = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (grab_toplevel)->impl)->height - point.y;
while (w != grab_toplevel)
{
tempx -= w->x;
tempy -= w->y;
w = w->parent;
}
*x = tempx;
*y = tempy;
get_child_coordinates_from_ancestor (grab_toplevel,
x_tmp, y_tmp,
_gdk_quartz_pointer_grab_window,
x, y);
return _gdk_quartz_pointer_grab_window;
}
else
{
return NULL;
}
}
if (!nswindow)
{
mouse_window = _gdk_root;
return NULL;
}
else
else
{
mouse_window = _gdk_quartz_window_find_child_by_point (toplevel, point.x, point.y, x, y);
}
/* The non-grabbed case. */
mouse_window = find_window_for_mouse_nsevent (nsevent, x, y);
event_mask = get_event_mask_from_ns_event (nsevent);
real_window = find_window_interested_in_event_mask (mouse_window, event_mask, TRUE);
/* We have to translate the coordinates if the actual
* window is different from the mouse window.
*/
if (mouse_window && real_window && mouse_window != real_window)
get_ancestor_coordinates_from_child (mouse_window,
*x, *y,
real_window,
x, y);
event_mask = get_event_mask_from_ns_event (nsevent);
real_window = find_window_interested_in_event_mask (mouse_window, event_mask, TRUE);
return real_window;
return real_window;
}
}
break;
case NSMouseEntered:
{
NSPoint point;
GdkWindow *toplevel;
GdkWindow *mouse_window;
point = [nsevent locationInWindow];
toplevel = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
mouse_window = _gdk_quartz_window_find_child_by_point (toplevel, point.x, point.y, x, y);
mouse_window = find_window_for_mouse_nsevent (nsevent, x, y);
synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, *x, *y);
}
break;
@ -1179,7 +1300,7 @@ gdk_event_translate (NSEvent *nsevent)
}
}
window = find_window_for_event (nsevent, &x, &y);
window = find_window_for_nsevent (nsevent, &x, &y);
/* FIXME: During owner_event grabs, we don't find a window when there is a
* click on a no-window widget, which makes popups etc still stay up. Need