mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-24 12:41:16 +00:00
Rework coordinate transformation to be based on root window
The root window contains all the monitors attached to a Mac. The coordinate transformation now both translates the x and y coordinate, translating it from the Cocoa monitor coordinate space to the GDK coordinate space. How monitors are laid out in the root window differs between Cocoa and GDK, which is why it is important to translate based on the root window to get multi monitor setups to work properly. We have replaced the old y coordinate transformation function with new functions that translate both the x and y coordinate. When creating new toplevels, we have to determine the Cocoa screen on which the toplevel should appear and translate the coordinates according to that screen. This change also fixes event handling in case there is a monitor left of the screen containing the menu bar. In such a case all coordinates on the left monitor are negative. Event handling broke, because of _gdk_quartz_window_find_child() checking bounds. Now that coordinates are always properly translated to GDK coordinate space, in which negative coordinates do never occur, the checks here will work properly.
This commit is contained in:
parent
d26dd103b2
commit
8846012c6d
@ -144,8 +144,9 @@
|
||||
GdkWindowObject *private = (GdkWindowObject *)window;
|
||||
GdkEvent *event;
|
||||
|
||||
private->x = content_rect.origin.x;
|
||||
private->y = _gdk_quartz_window_get_inverted_screen_y (content_rect.origin.y + content_rect.size.height);
|
||||
_gdk_quartz_window_xy_to_gdk_xy (content_rect.origin.x,
|
||||
content_rect.origin.y + content_rect.size.height,
|
||||
&private->x, &private->y);
|
||||
|
||||
/* Synthesize a configure event */
|
||||
event = gdk_event_new (GDK_CONFIGURE);
|
||||
@ -183,12 +184,13 @@
|
||||
_gdk_event_queue_append (gdk_display_get_default (), event);
|
||||
}
|
||||
|
||||
-(id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag
|
||||
-(id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag screen:(NSScreen *)screen
|
||||
{
|
||||
self = [super initWithContentRect:contentRect
|
||||
styleMask:styleMask
|
||||
backing:backingType
|
||||
defer:flag];
|
||||
defer:flag
|
||||
screen:screen];
|
||||
|
||||
[self setAcceptsMouseMovedEvents:YES];
|
||||
[self setDelegate:self];
|
||||
@ -506,16 +508,18 @@ update_context_from_dragging_info (id <NSDraggingInfo> sender)
|
||||
NSPoint point = [sender draggingLocation];
|
||||
NSPoint screen_point = [self convertBaseToScreen:point];
|
||||
GdkEvent event;
|
||||
int gx, gy;
|
||||
|
||||
update_context_from_dragging_info (sender);
|
||||
_gdk_quartz_window_nspoint_to_gdk_xy (screen_point, &gx, &gy);
|
||||
|
||||
event.dnd.type = GDK_DRAG_MOTION;
|
||||
event.dnd.window = g_object_ref ([[self contentView] gdkWindow]);
|
||||
event.dnd.send_event = FALSE;
|
||||
event.dnd.context = current_context;
|
||||
event.dnd.time = GDK_CURRENT_TIME;
|
||||
event.dnd.x_root = screen_point.x;
|
||||
event.dnd.y_root = _gdk_quartz_window_get_inverted_screen_y (screen_point.y);
|
||||
event.dnd.x_root = gx;
|
||||
event.dnd.y_root = gy;
|
||||
|
||||
(*_gdk_event_func) (&event, _gdk_event_data);
|
||||
|
||||
@ -529,16 +533,18 @@ update_context_from_dragging_info (id <NSDraggingInfo> sender)
|
||||
NSPoint point = [sender draggingLocation];
|
||||
NSPoint screen_point = [self convertBaseToScreen:point];
|
||||
GdkEvent event;
|
||||
int gy, gx;
|
||||
|
||||
update_context_from_dragging_info (sender);
|
||||
_gdk_quartz_window_nspoint_to_gdk_xy (screen_point, &gx, &gy);
|
||||
|
||||
event.dnd.type = GDK_DROP_START;
|
||||
event.dnd.window = g_object_ref ([[self contentView] gdkWindow]);
|
||||
event.dnd.send_event = FALSE;
|
||||
event.dnd.context = current_context;
|
||||
event.dnd.time = GDK_CURRENT_TIME;
|
||||
event.dnd.x_root = screen_point.x;
|
||||
event.dnd.y_root = _gdk_quartz_window_get_inverted_screen_y (screen_point.y);
|
||||
event.dnd.x_root = gx;
|
||||
event.dnd.y_root = gy;
|
||||
|
||||
(*_gdk_event_func) (&event, _gdk_event_data);
|
||||
|
||||
|
@ -465,8 +465,7 @@ find_window_for_ns_event (NSEvent *nsevent,
|
||||
*x = point.x;
|
||||
*y = private->height - point.y;
|
||||
|
||||
*x_root = screen_point.x;
|
||||
*y_root = _gdk_quartz_window_get_inverted_screen_y (screen_point.y);
|
||||
_gdk_quartz_window_nspoint_to_gdk_xy (screen_point, x_root, y_root);
|
||||
|
||||
event_type = [nsevent type];
|
||||
|
||||
|
@ -138,7 +138,17 @@ void _gdk_quartz_colormap_get_rgba_from_pixel (GdkColormap *colormap,
|
||||
/* Window */
|
||||
gboolean _gdk_quartz_window_is_ancestor (GdkWindow *ancestor,
|
||||
GdkWindow *window);
|
||||
gint _gdk_quartz_window_get_inverted_screen_y (gint y);
|
||||
void _gdk_quartz_window_gdk_xy_to_xy (gint gdk_x,
|
||||
gint gdk_y,
|
||||
gint *ns_x,
|
||||
gint *ns_y);
|
||||
void _gdk_quartz_window_xy_to_gdk_xy (gint ns_x,
|
||||
gint ns_y,
|
||||
gint *gdk_x,
|
||||
gint *gdk_y);
|
||||
void _gdk_quartz_window_nspoint_to_gdk_xy (NSPoint point,
|
||||
gint *x,
|
||||
gint *y);
|
||||
GdkWindow *_gdk_quartz_window_find_child (GdkWindow *window,
|
||||
gint x,
|
||||
gint y);
|
||||
|
@ -129,6 +129,8 @@ gdk_screen_quartz_calculate_layout (GdkScreenQuartz *screen)
|
||||
*/
|
||||
screen->width = 0;
|
||||
screen->height = 0;
|
||||
screen->min_x = 0;
|
||||
screen->min_y = 0;
|
||||
|
||||
for (i = 0; i < [array count]; i++)
|
||||
{
|
||||
@ -136,6 +138,8 @@ gdk_screen_quartz_calculate_layout (GdkScreenQuartz *screen)
|
||||
|
||||
screen->width += rect.size.width;
|
||||
screen->height = MAX (screen->height, rect.size.height);
|
||||
screen->min_x = MIN (screen->min_x, rect.origin.x);
|
||||
screen->min_y = MIN (screen->min_y, rect.origin.y);
|
||||
}
|
||||
|
||||
screen->n_screens = [array count];
|
||||
@ -162,7 +166,7 @@ gdk_screen_quartz_calculate_layout (GdkScreenQuartz *screen)
|
||||
nsscreen = [array objectAtIndex:i];
|
||||
rect = [nsscreen frame];
|
||||
|
||||
screen->screen_rects[i].x = rect.origin.x;
|
||||
screen->screen_rects[i].x = rect.origin.x - screen->min_x;
|
||||
screen->screen_rects[i].width = rect.size.width;
|
||||
screen->screen_rects[i].height = rect.size.height;
|
||||
|
||||
|
@ -40,6 +40,10 @@ struct _GdkScreenQuartz
|
||||
GdkDisplay *display;
|
||||
GdkColormap *default_colormap;
|
||||
|
||||
/* Origin of "root window" in Cocoa coordinates */
|
||||
gint min_x;
|
||||
gint min_y;
|
||||
|
||||
gint width;
|
||||
gint height;
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "gdk.h"
|
||||
#include "gdkwindowimpl.h"
|
||||
#include "gdkprivate-quartz.h"
|
||||
#include "gdkscreen-quartz.h"
|
||||
#include "gdkinputprivate.h"
|
||||
|
||||
static gpointer parent_class;
|
||||
@ -557,6 +558,7 @@ _gdk_quartz_window_debug_highlight (GdkWindow *window, gint number)
|
||||
{
|
||||
GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
|
||||
gint x, y;
|
||||
gint gx, gy;
|
||||
GdkWindow *toplevel;
|
||||
gint tx, ty;
|
||||
static NSWindow *debug_window[10];
|
||||
@ -585,9 +587,10 @@ _gdk_quartz_window_debug_highlight (GdkWindow *window, gint number)
|
||||
x += tx;
|
||||
y += ty;
|
||||
|
||||
rect = NSMakeRect (x,
|
||||
_gdk_quartz_window_get_inverted_screen_y (y + private->height),
|
||||
private->width, private->height);
|
||||
_gdk_quartz_window_gdk_xy_to_xy (x, y + private->height,
|
||||
&gx, &gy);
|
||||
|
||||
rect = NSMakeRect (gx, gy, private->width, private->height);
|
||||
|
||||
if (debug_window[number] && NSEqualRects (rect, old_rect[number]))
|
||||
return;
|
||||
@ -649,22 +652,44 @@ _gdk_quartz_window_is_ancestor (GdkWindow *ancestor,
|
||||
gdk_window_get_parent (window)));
|
||||
}
|
||||
|
||||
/* FIXME: It would be nice to have one function that takes an NSPoint
|
||||
* and flips the coords for any window.
|
||||
*/
|
||||
gint
|
||||
_gdk_quartz_window_get_inverted_screen_y (gint y)
|
||||
|
||||
void
|
||||
_gdk_quartz_window_gdk_xy_to_xy (gint gdk_x,
|
||||
gint gdk_y,
|
||||
gint *ns_x,
|
||||
gint *ns_y)
|
||||
{
|
||||
int index;
|
||||
GdkRectangle gdk_rect;
|
||||
NSScreen *main_screen = [NSScreen mainScreen];
|
||||
NSRect rect = [main_screen frame];
|
||||
GdkScreenQuartz *screen_quartz = GDK_SCREEN_QUARTZ (_gdk_screen);
|
||||
|
||||
index = [[NSScreen screens] indexOfObject:main_screen];
|
||||
if (ns_y)
|
||||
*ns_y = screen_quartz->height - gdk_y + screen_quartz->min_y;
|
||||
|
||||
gdk_screen_get_monitor_geometry (_gdk_screen, index, &gdk_rect);
|
||||
if (ns_x)
|
||||
*ns_x = gdk_x + screen_quartz->min_x;
|
||||
}
|
||||
|
||||
return gdk_rect.height - y + rect.origin.y + gdk_rect.y;
|
||||
void
|
||||
_gdk_quartz_window_xy_to_gdk_xy (gint ns_x,
|
||||
gint ns_y,
|
||||
gint *gdk_x,
|
||||
gint *gdk_y)
|
||||
{
|
||||
GdkScreenQuartz *screen_quartz = GDK_SCREEN_QUARTZ (_gdk_screen);
|
||||
|
||||
if (gdk_y)
|
||||
*gdk_y = screen_quartz->height - ns_y + screen_quartz->min_y;
|
||||
|
||||
if (gdk_x)
|
||||
*gdk_x = ns_x - screen_quartz->min_x;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_quartz_window_nspoint_to_gdk_xy (NSPoint point,
|
||||
gint *x,
|
||||
gint *y)
|
||||
{
|
||||
_gdk_quartz_window_xy_to_gdk_xy (point.x, point.y,
|
||||
x, y);
|
||||
}
|
||||
|
||||
static GdkWindow *
|
||||
@ -780,8 +805,7 @@ generate_motion_event (GdkWindow *window)
|
||||
|
||||
screen_point = [NSEvent mouseLocation];
|
||||
|
||||
x_root = screen_point.x;
|
||||
y_root = _gdk_quartz_window_get_inverted_screen_y (screen_point.y);
|
||||
_gdk_quartz_window_nspoint_to_gdk_xy (screen_point, &x_root, &y_root);
|
||||
|
||||
point = [nswindow convertScreenToBase:screen_point];
|
||||
|
||||
@ -860,6 +884,32 @@ _gdk_quartz_window_did_resign_main (GdkWindow *window)
|
||||
clear_toplevel_order ();
|
||||
}
|
||||
|
||||
static NSScreen *
|
||||
get_nsscreen_for_x (gint x)
|
||||
{
|
||||
int i;
|
||||
NSArray *screens;
|
||||
|
||||
GDK_QUARTZ_ALLOC_POOL;
|
||||
|
||||
screens = [NSScreen screens];
|
||||
|
||||
for (i = 0; i < [screens count]; i++)
|
||||
{
|
||||
NSRect rect = [[screens objectAtIndex:i] frame];
|
||||
|
||||
/* FIXME: Only horizontal layouts supported for now. Also
|
||||
* see comments in gdkscreen-quartz.c
|
||||
*/
|
||||
if (x >= rect.origin.x && x <= rect.origin.x + rect.size.width)
|
||||
return [screens objectAtIndex:i];
|
||||
}
|
||||
|
||||
GDK_QUARTZ_RELEASE_POOL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_window_impl_new (GdkWindow *window,
|
||||
GdkWindow *real_parent,
|
||||
@ -944,12 +994,26 @@ _gdk_window_impl_new (GdkWindow *window,
|
||||
case GDK_WINDOW_DIALOG:
|
||||
case GDK_WINDOW_TEMP:
|
||||
{
|
||||
NSScreen *screen;
|
||||
NSRect screen_rect;
|
||||
NSRect content_rect;
|
||||
int style_mask;
|
||||
int nx, ny;
|
||||
const char *title;
|
||||
|
||||
content_rect = NSMakeRect (private->x,
|
||||
_gdk_quartz_window_get_inverted_screen_y (private->y) - private->height,
|
||||
/* initWithContentRect will place on the mainScreen by default.
|
||||
* We want to select the screen to place on ourselves. We need
|
||||
* to find the screen the window will be on and correct the
|
||||
* content_rect coordinates to be relative to that screen.
|
||||
*/
|
||||
_gdk_quartz_window_gdk_xy_to_xy (private->x, private->y, &nx, &ny);
|
||||
|
||||
screen = get_nsscreen_for_x (nx);
|
||||
screen_rect = [screen frame];
|
||||
nx -= screen_rect.origin.x;
|
||||
ny -= screen_rect.origin.y;
|
||||
|
||||
content_rect = NSMakeRect (nx, ny - private->height,
|
||||
private->width,
|
||||
private->height);
|
||||
|
||||
@ -969,7 +1033,8 @@ _gdk_window_impl_new (GdkWindow *window,
|
||||
impl->toplevel = [[GdkQuartzWindow alloc] initWithContentRect:content_rect
|
||||
styleMask:style_mask
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO];
|
||||
defer:NO
|
||||
screen:screen];
|
||||
|
||||
if (attributes_mask & GDK_WA_TITLE)
|
||||
title = attributes->title;
|
||||
@ -1323,10 +1388,12 @@ move_resize_window_internal (GdkWindow *window,
|
||||
{
|
||||
NSRect content_rect;
|
||||
NSRect frame_rect;
|
||||
gint gx, gy;
|
||||
|
||||
content_rect = NSMakeRect (private->x,
|
||||
_gdk_quartz_window_get_inverted_screen_y (private->y + private->height),
|
||||
private->width, private->height);
|
||||
_gdk_quartz_window_gdk_xy_to_xy (private->x, private->y + private->height,
|
||||
&gx, &gy);
|
||||
|
||||
content_rect = NSMakeRect (gx, gy, private->width, private->height);
|
||||
|
||||
frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
|
||||
[impl->toplevel setFrame:frame_rect display:YES];
|
||||
@ -1714,10 +1781,9 @@ gdk_window_quartz_get_geometry (GdkWindow *window,
|
||||
*/
|
||||
if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
|
||||
{
|
||||
if (x)
|
||||
*x = ns_rect.origin.x;
|
||||
if (y)
|
||||
*y = _gdk_quartz_window_get_inverted_screen_y (ns_rect.origin.y + ns_rect.size.height);
|
||||
_gdk_quartz_window_xy_to_gdk_xy (ns_rect.origin.x,
|
||||
ns_rect.origin.y + ns_rect.size.height,
|
||||
x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1790,8 +1856,12 @@ gdk_window_quartz_get_root_coords (GdkWindow *window,
|
||||
|
||||
content_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
|
||||
|
||||
tmp_x = x + content_rect.origin.x;
|
||||
tmp_y = y + _gdk_quartz_window_get_inverted_screen_y (content_rect.origin.y + content_rect.size.height);
|
||||
_gdk_quartz_window_xy_to_gdk_xy (content_rect.origin.x,
|
||||
content_rect.origin.y + content_rect.size.height,
|
||||
&tmp_x, &tmp_y);
|
||||
|
||||
tmp_x += x;
|
||||
tmp_y += y;
|
||||
|
||||
while (private != GDK_WINDOW_OBJECT (toplevel))
|
||||
{
|
||||
@ -1870,8 +1940,7 @@ gdk_window_quartz_get_pointer_helper (GdkWindow *window,
|
||||
if (window == _gdk_root)
|
||||
{
|
||||
point = [NSEvent mouseLocation];
|
||||
x_tmp = point.x;
|
||||
y_tmp = _gdk_quartz_window_get_inverted_screen_y (point.y);
|
||||
_gdk_quartz_window_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2525,8 +2594,10 @@ gdk_window_get_frame_extents (GdkWindow *window,
|
||||
|
||||
ns_rect = [impl->toplevel frame];
|
||||
|
||||
rect->x = ns_rect.origin.x;
|
||||
rect->y = _gdk_quartz_window_get_inverted_screen_y (ns_rect.origin.y + ns_rect.size.height);
|
||||
_gdk_quartz_window_xy_to_gdk_xy (ns_rect.origin.x,
|
||||
ns_rect.origin.y + ns_rect.size.height,
|
||||
&rect->x, &rect->y);
|
||||
|
||||
rect->width = ns_rect.size.width;
|
||||
rect->height = ns_rect.size.height;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user