Use consistent coordinates in get_toplevel_from_ns_event.
[NSView frame] returns a rectangle in the superview's coordinates, and the superview of an NSWindow's content view (which is the only NSView that GdkQuartz instantiates) is an undocumented NSThemeFrame. While it happens to have the same origin as the content view and the same size as the window's frame this isn't documented and so could change without notice. Convert the window frame coordinates to the view's coordinate system to ensure consistency. Use the view's bounds instead of its frame: The bounds rectangle is in the view's coordinate system. Use the parent NSWindow's frame instead of the private NSThemeFrame's. This ensures that all coordinate comparisons have the same reference. Finally, the macOS coordinate systems origin is at the bottom left, so the title bar is between the content view's height and the window's height, not in negative y in the view's coordinates. Adjust the y comparisons accordingly. Fixes #6297
This commit is contained in:
@@ -417,12 +417,13 @@ get_toplevel_from_ns_event (NSEvent *nsevent,
|
||||
gint *y)
|
||||
{
|
||||
GdkWindow *toplevel = NULL;
|
||||
NSWindow* nswindow = [nsevent window];
|
||||
|
||||
if ([nsevent window])
|
||||
if (nswindow)
|
||||
{
|
||||
GdkQuartzView *view;
|
||||
NSPoint point, view_point;
|
||||
NSRect view_frame;
|
||||
NSRect view_bounds;
|
||||
|
||||
view = (GdkQuartzView *)[[nsevent window] contentView];
|
||||
|
||||
@@ -430,7 +431,7 @@ get_toplevel_from_ns_event (NSEvent *nsevent,
|
||||
|
||||
point = [nsevent locationInWindow];
|
||||
view_point = [view convertPoint:point fromView:nil];
|
||||
view_frame = [view frame];
|
||||
view_bounds = [view bounds];
|
||||
|
||||
/* NSEvents come in with a window set, but with window coordinates
|
||||
* out of window bounds. For e.g. moved events this is fine, we use
|
||||
@@ -445,10 +446,10 @@ get_toplevel_from_ns_event (NSEvent *nsevent,
|
||||
* toplevel window below.
|
||||
*/
|
||||
if (is_mouse_button_press_event ([nsevent type]) &&
|
||||
(view_point.x < view_frame.origin.x ||
|
||||
view_point.x >= view_frame.origin.x + view_frame.size.width ||
|
||||
view_point.y < view_frame.origin.y ||
|
||||
view_point.y >= view_frame.origin.y + view_frame.size.height))
|
||||
(view_point.x < view_bounds.origin.x ||
|
||||
view_point.x >= view_bounds.origin.x + view_bounds.size.width ||
|
||||
view_point.y < view_bounds.origin.y ||
|
||||
view_point.y >= view_bounds.origin.y + view_bounds.size.height))
|
||||
{
|
||||
toplevel = NULL;
|
||||
|
||||
@@ -468,27 +469,22 @@ get_toplevel_from_ns_event (NSEvent *nsevent,
|
||||
* fallback path, which could match the window that is
|
||||
* directly under the titlebar.
|
||||
*/
|
||||
if (view_point.y < 0 &&
|
||||
view_point.x >= view_frame.origin.x &&
|
||||
view_point.x < view_frame.origin.x + view_frame.size.width)
|
||||
if (view_point.y > view_bounds.origin.y + view_bounds.size.height &&
|
||||
view_point.x >= view_bounds.origin.x &&
|
||||
view_point.x < view_bounds.origin.x + view_bounds.size.width)
|
||||
{
|
||||
NSView *superview = [view superview];
|
||||
if (superview)
|
||||
NSRect window_frame = [view convertRect: [nswindow frame]
|
||||
fromView: nil];
|
||||
if (view_point.y <=
|
||||
view_bounds.origin.y + window_frame.size.height)
|
||||
{
|
||||
NSRect superview_frame = [superview frame];
|
||||
int titlebar_height = superview_frame.size.height -
|
||||
view_frame.size.height;
|
||||
|
||||
if (titlebar_height > 0 && view_point.y >= -titlebar_height)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*screen_point = [(GdkQuartzNSWindow*)[nsevent window] convertPointToScreen:point];
|
||||
*screen_point = [(GdkQuartzNSWindow*)nswindow convertPointToScreen:point];
|
||||
*x = point.x;
|
||||
*y = toplevel->height - point.y;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user