[gtk/wip/chergert/quartz4u] macos: improve coordinate positioning and edge snapping
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/quartz4u] macos: improve coordinate positioning and edge snapping
- Date: Mon, 18 May 2020 18:59:56 +0000 (UTC)
commit 76bcf5eddd853f726be14837acd854036bc9cb78
Author: Christian Hergert <chergert redhat com>
Date: Mon May 18 10:48:39 2020 -0700
macos: improve coordinate positioning and edge snapping
This adds a little helper so that we can try to snap edges for CSD
windows more similar to how quartz does for opaque/titled
windows.
gdk/macos/GdkMacosWindow.c | 169 ++++++++++++++-------------
gdk/macos/GdkMacosWindow.h | 5 +-
gdk/macos/edgesnapping.c | 223 ++++++++++++++++++++++++++++++++++++
gdk/macos/edgesnapping.h | 50 ++++++++
gdk/macos/gdkmacosdisplay-private.h | 2 +
gdk/macos/gdkmacosdisplay.c | 21 ++--
gdk/macos/gdkmacosmonitor.c | 99 ++++++++--------
gdk/macos/gdkmacossurface.c | 4 +-
gdk/macos/meson.build | 2 +
9 files changed, 426 insertions(+), 149 deletions(-)
---
diff --git a/gdk/macos/GdkMacosWindow.c b/gdk/macos/GdkMacosWindow.c
index 6a5f4abddf..36e8611996 100644
--- a/gdk/macos/GdkMacosWindow.c
+++ b/gdk/macos/GdkMacosWindow.c
@@ -310,92 +310,79 @@
-(BOOL)trackManualMove
{
- NSRect workarea;
- NSRect geometry;
NSRect windowFrame;
- NSRect withoutShadow;
- NSRect newFrame;
NSPoint currentLocation;
+ GdkMonitor *monitor;
+ GdkRectangle geometry;
+ GdkRectangle workarea;
int shadow_top = 0;
int shadow_left = 0;
int shadow_right = 0;
int shadow_bottom = 0;
- int thresh_top;
- int thresh_left;
- int thresh_right;
- int thresh_bottom;
+ GdkRectangle window_gdk;
+ GdkPoint pointer_position;
+ GdkPoint new_origin;
if (!inManualMove)
return NO;
- workarea = [[self screen] visibleFrame];
- geometry = [[self screen] frame];
- windowFrame = [self frame];
-
- _gdk_macos_surface_get_shadow (gdk_surface, &shadow_top, &shadow_right, &shadow_bottom, &shadow_left);
-
- currentLocation = [self convertPointToScreen:[self mouseLocationOutsideOfEventStream]];
- windowFrame.origin.x = currentLocation.x - initialMoveLocation.x;
- windowFrame.origin.y = currentLocation.y - initialMoveLocation.y;
-
- if (currentLocation.y > lastMoveLocation.y)
- {
- thresh_bottom = 5;
- thresh_top = 10;
- }
- else
- {
- thresh_bottom = 10;
- thresh_top = 10;
- }
-
- if (currentLocation.x > lastMoveLocation.x)
- {
- thresh_right = 20;
- thresh_left = 10;
- }
- else
- {
- thresh_right = 10;
- thresh_left = 20;
- }
-
- withoutShadow = NSMakeRect (windowFrame.origin.x + shadow_left,
- windowFrame.origin.y + shadow_bottom,
- windowFrame.size.width - shadow_left - shadow_right,
- windowFrame.size.height - shadow_top - shadow_bottom);
-
- newFrame = [self constrainFrameRect:withoutShadow
- toScreen:[self screen]];
-
- if (newFrame.origin.x < workarea.origin.x &&
- newFrame.origin.x > (workarea.origin.x - thresh_left))
- newFrame.origin.x = workarea.origin.x;
-
- if (newFrame.origin.x + newFrame.size.width > workarea.origin.x + workarea.size.width &&
- newFrame.origin.x + newFrame.size.width < workarea.origin.x + workarea.size.width + thresh_right)
- newFrame.origin.x = workarea.origin.x + workarea.size.width - newFrame.size.width;
-
- if (newFrame.origin.y < workarea.origin.y &&
- newFrame.origin.y > workarea.origin.y - thresh_bottom)
- newFrame.origin.y = workarea.origin.y;
-
- if (newFrame.origin.y < geometry.origin.y &&
- newFrame.origin.y > geometry.origin.y - thresh_bottom)
- newFrame.origin.y = geometry.origin.y;
+ /* Get our shadow so we can adjust the window position sans-shadow */
+ _gdk_macos_surface_get_shadow (gdk_surface,
+ &shadow_top,
+ &shadow_right,
+ &shadow_bottom,
+ &shadow_left);
- if (newFrame.origin.y + newFrame.size.height > workarea.origin.y + workarea.size.height &&
- newFrame.origin.y + newFrame.size.height < workarea.origin.y + workarea.size.height + thresh_top)
- newFrame.origin.y = workarea.origin.y + workarea.size.height - newFrame.size.height;
-
- newFrame.origin.x -= shadow_left;
- newFrame.origin.y -= shadow_bottom;
- newFrame.size.width += shadow_left + shadow_right;
- newFrame.size.height += shadow_bottom + shadow_top;
-
- lastMoveLocation = currentLocation;
-
- [self setFrameOrigin:newFrame.origin];
+ windowFrame = [self frame];
+ currentLocation = [NSEvent mouseLocation];
+
+ /* Update the snapping geometry to match the current monitor */
+ monitor = _gdk_macos_display_get_monitor_at_display_coords ([self gdkDisplay],
+ currentLocation.x,
+ currentLocation.y);
+ gdk_monitor_get_geometry (monitor, &geometry);
+ gdk_monitor_get_workarea (monitor, &workarea);
+ _edge_snapping_set_monitor (&self->snapping, &geometry, &workarea);
+
+ /* Convert origins to GDK coordinates */
+ _gdk_macos_display_from_display_coords ([self gdkDisplay],
+ currentLocation.x,
+ currentLocation.y,
+ &pointer_position.x,
+ &pointer_position.y);
+ _gdk_macos_display_from_display_coords ([self gdkDisplay],
+ windowFrame.origin.x,
+ windowFrame.origin.y + windowFrame.size.height,
+ &window_gdk.x,
+ &window_gdk.y);
+ window_gdk.width = windowFrame.size.width;
+ window_gdk.height = windowFrame.size.height;
+
+ /* Subtract our shadowin from the window */
+ window_gdk.x += shadow_left;
+ window_gdk.y += shadow_top;
+ window_gdk.width = window_gdk.width - shadow_left - shadow_right;
+ window_gdk.height = window_gdk.height - shadow_top - shadow_bottom;
+
+ /* Now place things on the monitor */
+ _edge_snapping_motion (&self->snapping, &pointer_position, &window_gdk);
+
+ /* And add our shadow back to the frame */
+ window_gdk.x -= shadow_left;
+ window_gdk.y -= shadow_top;
+ window_gdk.width += shadow_left + shadow_right;
+ window_gdk.height += shadow_top + shadow_bottom;
+
+ /* Convert to quartz coordiantes */
+ _gdk_macos_display_to_display_coords ([self gdkDisplay],
+ window_gdk.x,
+ window_gdk.y + window_gdk.height,
+ &new_origin.x, &new_origin.y);
+ windowFrame.origin.x = new_origin.x;
+ windowFrame.origin.y = new_origin.y;
+
+ /* And now apply the frame to the window */
+ [self setFrameOrigin:NSMakePoint(new_origin.x, new_origin.y)];
return YES;
}
@@ -411,18 +398,40 @@
-(void)beginManualMove
{
- NSRect frame = [self frame];
+ NSPoint initialMoveLocation;
+ GdkPoint point;
+ GdkMonitor *monitor;
+ GdkRectangle geometry;
+ GdkRectangle area;
+ GdkRectangle workarea;
if (inMove || inManualMove || inManualResize)
return;
inManualMove = YES;
- initialMoveLocation = [self convertPointToScreen:[self mouseLocationOutsideOfEventStream]];
- initialMoveLocation.x -= frame.origin.x;
- initialMoveLocation.y -= frame.origin.y;
+ monitor = _gdk_macos_surface_get_best_monitor ([self gdkSurface]);
+ gdk_monitor_get_geometry (monitor, &geometry);
+ gdk_monitor_get_workarea (monitor, &workarea);
+
+ initialMoveLocation = [NSEvent mouseLocation];
+
+ _gdk_macos_display_from_display_coords ([self gdkDisplay],
+ initialMoveLocation.x,
+ initialMoveLocation.y,
+ &point.x,
+ &point.y);
+
+ area.x = GDK_SURFACE (gdk_surface)->x;
+ area.y = GDK_SURFACE (gdk_surface)->y;
+ area.width = GDK_SURFACE (gdk_surface)->width;
+ area.height = GDK_SURFACE (gdk_surface)->height;
- lastMoveLocation = initialMoveLocation;
+ _edge_snapping_init (&self->snapping,
+ &geometry,
+ &workarea,
+ &point,
+ &area);
}
-(BOOL)trackManualResize
diff --git a/gdk/macos/GdkMacosWindow.h b/gdk/macos/GdkMacosWindow.h
index 664cc22b9b..61f546a78b 100644
--- a/gdk/macos/GdkMacosWindow.h
+++ b/gdk/macos/GdkMacosWindow.h
@@ -26,6 +26,7 @@
#include "gdkmacosdisplay.h"
#include "gdkmacossurface.h"
+#include "edgesnapping.h"
#define GDK_IS_MACOS_WINDOW(obj) ([obj isKindOfClass:[GdkMacosWindow class]])
@@ -40,12 +41,12 @@
BOOL inManualMove;
BOOL inManualResize;
BOOL inTrackManualResize;
- NSPoint initialMoveLocation;
- NSPoint lastMoveLocation;
NSPoint initialResizeLocation;
NSRect initialResizeFrame;
GdkSurfaceEdge resizeEdge;
+ EdgeSnapping snapping;
+
NSRect lastUnmaximizedFrame;
NSRect lastMaximizedFrame;
NSRect lastUnfullscreenFrame;
diff --git a/gdk/macos/edgesnapping.c b/gdk/macos/edgesnapping.c
new file mode 100644
index 0000000000..e81b29626c
--- /dev/null
+++ b/gdk/macos/edgesnapping.c
@@ -0,0 +1,223 @@
+/* edgesnapping.c
+ *
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gdkrectangle.h"
+#include "edgesnapping.h"
+
+#define LEAVE_THRESHOLD 3.0
+#define ENTER_THRESHOLD 2.0
+
+#define X1(r) ((r)->x)
+#define X2(r) ((r)->x + (r)->width)
+#define Y1(r) ((r)->y)
+#define Y2(r) ((r)->y + (r)->height)
+
+void
+_edge_snapping_init (EdgeSnapping *self,
+ const GdkRectangle *geometry,
+ const GdkRectangle *workarea,
+ const GdkPoint *pointer_position,
+ const GdkRectangle *window)
+{
+ g_assert (self != NULL);
+ g_assert (geometry != NULL);
+ g_assert (workarea != NULL);
+ g_assert (pointer_position != NULL);
+
+ self->geometry = *geometry;
+ self->workarea = *workarea;
+ self->last_pointer_position = *pointer_position;
+ self->pointer_offset_in_window.x = pointer_position->x - window->x;
+ self->pointer_offset_in_window.y = pointer_position->y - window->y;
+}
+
+static void
+edge_snapping_constrain_left (EdgeSnapping *self,
+ int change,
+ const GdkRectangle *geometry,
+ GdkRectangle *window)
+{
+ if (change < 0)
+ {
+ if (X1 (window) < X1 (geometry) &&
+ X1 (window) > X1 (geometry) - LEAVE_THRESHOLD &&
+ ABS (change) < LEAVE_THRESHOLD)
+ window->x = geometry->x;
+ }
+
+ /* We don't constrain when returning from left edge */
+}
+
+static void
+edge_snapping_constrain_right (EdgeSnapping *self,
+ int change,
+ const GdkRectangle *geometry,
+ GdkRectangle *window)
+{
+ if (change > 0)
+ {
+ if (X2 (window) > X2 (geometry) &&
+ X2 (window) < X2 (geometry) + LEAVE_THRESHOLD &&
+ ABS (change) < LEAVE_THRESHOLD)
+ window->x = X2 (geometry) - window->width;
+ }
+
+ /* We don't constrain when returning from right edge */
+}
+
+static void
+edge_snapping_constrain_top (EdgeSnapping *self,
+ int change,
+ const GdkRectangle *geometry,
+ GdkRectangle *window)
+{
+ if (change < 0)
+ {
+ if (Y1 (window) < Y1 (geometry))
+ window->y = geometry->y;
+ }
+
+ /* We don't constrain when returning from top edge */
+}
+
+static void
+edge_snapping_constrain_bottom (EdgeSnapping *self,
+ int change,
+ const GdkRectangle *geometry,
+ GdkRectangle *window)
+{
+ if (change > 0)
+ {
+ if (Y2 (window) > Y2 (geometry) &&
+ Y2 (window) < Y2 (geometry) + LEAVE_THRESHOLD &&
+ ABS (change) < LEAVE_THRESHOLD)
+ window->y = Y2 (geometry) - window->height;
+ }
+ else if (change < 0)
+ {
+ if (Y2 (window) < Y2 (geometry) &&
+ Y2 (window) > Y2 (geometry) - ENTER_THRESHOLD &&
+ ABS (change) < ENTER_THRESHOLD)
+ window->y = Y2 (geometry) - window->height;
+ }
+
+}
+
+static void
+edge_snapping_constrain_horizontal (EdgeSnapping *self,
+ int change,
+ const GdkRectangle *geometry,
+ GdkRectangle *window)
+{
+ g_assert (self != NULL);
+ g_assert (geometry != NULL);
+ g_assert (window != NULL);
+ g_assert (change != 0);
+
+ if (ABS (X1 (geometry) - X1 (window)) < ABS (X2 (geometry)) - ABS (X2 (window)))
+ edge_snapping_constrain_left (self, change, geometry, window);
+ else
+ edge_snapping_constrain_right (self, change, geometry, window);
+}
+
+static void
+edge_snapping_constrain_vertical (EdgeSnapping *self,
+ int change,
+ const GdkRectangle *geometry,
+ GdkRectangle *window,
+ gboolean bottom_only)
+{
+ g_assert (self != NULL);
+ g_assert (geometry != NULL);
+ g_assert (window != NULL);
+ g_assert (change != 0);
+
+ if (!bottom_only &&
+ ABS (Y1 (geometry) - Y1 (window)) < ABS (Y2 (geometry)) - ABS (Y2 (window)))
+ edge_snapping_constrain_top (self, change, geometry, window);
+ else
+ edge_snapping_constrain_bottom (self, change, geometry, window);
+}
+
+void
+_edge_snapping_motion (EdgeSnapping *self,
+ const GdkPoint *pointer_position,
+ GdkRectangle *window)
+{
+ GdkRectangle new_window;
+ GdkRectangle overlap;
+ GdkPoint change;
+
+ g_assert (self != NULL);
+ g_assert (pointer_position != NULL);
+
+ change.x = pointer_position->x - self->last_pointer_position.x;
+ change.y = pointer_position->y - self->last_pointer_position.y;
+
+ self->last_pointer_position = *pointer_position;
+
+ window->x += change.x;
+ window->y += change.y;
+
+ new_window = *window;
+
+ /* First constrain horizontal */
+ if (change.x)
+ {
+ edge_snapping_constrain_horizontal (self, change.x, &self->workarea, &new_window);
+ if (gdk_rectangle_equal (&new_window, window))
+ edge_snapping_constrain_horizontal (self, change.x, &self->geometry, &new_window);
+ }
+
+ /* Now constrain veritcally */
+ if (change.y)
+ {
+ edge_snapping_constrain_vertical (self, change.y, &self->workarea, &new_window, FALSE);
+ if (new_window.y == window->y)
+ edge_snapping_constrain_vertical (self, change.y, &self->geometry, &new_window, TRUE);
+ }
+
+ /* If the window is not placed in the monitor at all, then we need to
+ * just move the window onto the new screen using the original offset
+ * of the pointer within the window.
+ */
+ if (!gdk_rectangle_intersect (&self->geometry, &new_window, &overlap))
+ {
+ new_window.x = pointer_position->x - self->pointer_offset_in_window.x;
+ new_window.y = pointer_position->y - self->pointer_offset_in_window.y;
+ }
+
+ *window = new_window;
+}
+
+void
+_edge_snapping_set_monitor (EdgeSnapping *self,
+ const GdkRectangle *geometry,
+ const GdkRectangle *workarea)
+{
+ g_assert (self != NULL);
+ g_assert (geometry != NULL);
+ g_assert (workarea != NULL);
+
+ self->geometry = *geometry;
+ self->workarea = *workarea;
+}
diff --git a/gdk/macos/edgesnapping.h b/gdk/macos/edgesnapping.h
new file mode 100644
index 0000000000..8769ea7e47
--- /dev/null
+++ b/gdk/macos/edgesnapping.h
@@ -0,0 +1,50 @@
+/* edgesnapping.h
+ *
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __EDGE_SNAPPING_H__
+#define __EDGE_SNAPPING_H__
+
+#include "gdktypes.h"
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ GdkRectangle geometry;
+ GdkRectangle workarea;
+ GdkPoint last_pointer_position;
+ GdkPoint pointer_offset_in_window;
+} EdgeSnapping;
+
+void _edge_snapping_init (EdgeSnapping *self,
+ const GdkRectangle *geometry,
+ const GdkRectangle *workarea,
+ const GdkPoint *pointer_position,
+ const GdkRectangle *window);
+void _edge_snapping_motion (EdgeSnapping *self,
+ const GdkPoint *pointer_position,
+ GdkRectangle *window);
+void _edge_snapping_set_monitor (EdgeSnapping *self,
+ const GdkRectangle *geometry,
+ const GdkRectangle *workarea);
+
+G_END_DECLS
+
+#endif /* __EDGE_SNAPPING_H__ */
diff --git a/gdk/macos/gdkmacosdisplay-private.h b/gdk/macos/gdkmacosdisplay-private.h
index c9089f0f52..d731f8dce8 100644
--- a/gdk/macos/gdkmacosdisplay-private.h
+++ b/gdk/macos/gdkmacosdisplay-private.h
@@ -72,6 +72,8 @@ struct _GdkMacosDisplay
int height;
int min_x;
int min_y;
+ int max_x;
+ int max_y;
};
struct _GdkMacosDisplayClass
diff --git a/gdk/macos/gdkmacosdisplay.c b/gdk/macos/gdkmacosdisplay.c
index 8aedcee9ed..58740aa2d9 100644
--- a/gdk/macos/gdkmacosdisplay.c
+++ b/gdk/macos/gdkmacosdisplay.c
@@ -184,30 +184,26 @@ gdk_macos_display_update_bounds (GdkMacosDisplay *self)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
- int max_x = G_MININT;
- int max_y = G_MININT;
-
g_assert (GDK_IS_MACOS_DISPLAY (self));
self->min_x = G_MAXINT;
self->min_y = G_MAXINT;
+ self->max_x = G_MININT;
+ self->max_y = G_MININT;
+
for (id obj in [NSScreen screens])
{
- CGDirectDisplayID screen_id;
- CGRect geom;
-
- screen_id = [[[obj deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
- geom = CGDisplayBounds (screen_id);
+ NSRect geom = [(NSScreen *)obj frame];
self->min_x = MIN (self->min_x, geom.origin.x);
self->min_y = MIN (self->min_y, geom.origin.y);
- max_x = MAX (max_x, geom.origin.x + geom.size.width);
- max_y = MAX (max_y, geom.origin.y + geom.size.height);
+ self->max_x = MAX (self->max_x, geom.origin.x + geom.size.width);
+ self->max_y = MAX (self->max_y, geom.origin.y + geom.size.height);
}
- self->width = max_x - self->min_x;
- self->height = max_y - self->min_y;
+ self->width = self->max_x - self->min_x;
+ self->height = self->max_y - self->min_y;
GDK_END_MACOS_ALLOC_POOL;
}
@@ -819,6 +815,7 @@ _gdk_macos_display_get_monitor_at_display_coords (GdkMacosDisplay *self,
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
_gdk_macos_display_from_display_coords (self, x, y, &x, &y);
+
return _gdk_macos_display_get_monitor_at_coords (self, x, y);
}
diff --git a/gdk/macos/gdkmacosmonitor.c b/gdk/macos/gdkmacosmonitor.c
index 0333872e03..2c3d53b742 100644
--- a/gdk/macos/gdkmacosmonitor.c
+++ b/gdk/macos/gdkmacosmonitor.c
@@ -30,6 +30,7 @@ struct _GdkMacosMonitor
{
GdkMonitor parent_instance;
CGDirectDisplayID screen_id;
+ NSRect workarea;
guint has_opengl : 1;
};
@@ -47,36 +48,22 @@ gdk_macos_monitor_get_workarea (GdkMonitor *monitor,
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkMacosMonitor *self = (GdkMacosMonitor *)monitor;
+ int x, y;
g_assert (GDK_IS_MACOS_MONITOR (self));
g_assert (geometry != NULL);
- *geometry = monitor->geometry;
+ x = self->workarea.origin.x;
+ y = self->workarea.origin.y + self->workarea.size.height;
- for (id obj in [NSScreen screens])
- {
- CGDirectDisplayID screen_id;
-
- screen_id = [[[obj deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
-
- if (screen_id == self->screen_id)
- {
- NSScreen *screen = (NSScreen *)obj;
- NSRect visibleFrame = [screen visibleFrame];
- int x = visibleFrame.origin.x;
- int y = visibleFrame.origin.y + visibleFrame.size.height;
+ _gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (monitor->display),
+ x, y,
+ &x, &y);
- _gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (monitor->display),
- x, y, &x, &y);
-
- geometry->x = x;
- geometry->y = y;
- geometry->width = visibleFrame.size.width;
- geometry->height = visibleFrame.size.height;
-
- break;
- }
- }
+ geometry->x = x;
+ geometry->y = y;
+ geometry->width = self->workarea.size.width;
+ geometry->height = self->workarea.size.height;
GDK_END_MACOS_ALLOC_POOL;
}
@@ -148,23 +135,17 @@ GetSubpixelLayout (CGDirectDisplayID screen_id)
}
static char *
-GetLocalizedName (CGDirectDisplayID screen_id)
+GetLocalizedName (NSScreen *screen)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
- char *name = NULL;
+ NSString *str;
+ char *name;
- for (id obj in [NSScreen screens])
- {
- CGDirectDisplayID this_id = [[[obj deviceDescription] objectForKey:@"NSScreenNumber"]
unsignedIntValue];
+ g_assert (screen);
- if (screen_id == this_id)
- {
- NSString *str = [(NSScreen *)obj localizedName];
- name = g_strdup ([str UTF8String]);
- break;
- }
- }
+ str = [screen localizedName];
+ name = g_strdup ([str UTF8String]);
GDK_END_MACOS_ALLOC_POOL;
@@ -178,17 +159,38 @@ GetConnectorName (CGDirectDisplayID screen_id)
return g_strdup_printf ("unit-%u", unit);
}
+static NSScreen *
+find_screen (CGDirectDisplayID screen_id)
+{
+ GDK_BEGIN_MACOS_ALLOC_POOL;
+
+ NSScreen *screen = NULL;
+
+ for (id obj in [NSScreen screens])
+ {
+ if (screen_id == [[[obj deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue])
+ {
+ screen = (NSScreen *)obj;
+ break;
+ }
+ }
+
+ GDK_END_MACOS_ALLOC_POOL;
+
+ return screen;
+}
+
gboolean
_gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
{
GdkSubpixelLayout subpixel_layout;
CGDisplayModeRef mode;
GdkMacosDisplay *display;
+ NSScreen *screen;
GdkRectangle geom;
gboolean has_opengl;
CGSize size;
CGRect bounds;
- CGRect main_bounds;
size_t width;
size_t pixel_width;
gchar *connector;
@@ -202,17 +204,17 @@ _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
display = GDK_MACOS_DISPLAY (GDK_MONITOR (self)->display);
- if (!(mode = CGDisplayCopyDisplayMode (self->screen_id)))
+ if (!(screen = find_screen (self->screen_id)) ||
+ !(mode = CGDisplayCopyDisplayMode (self->screen_id)))
return FALSE;
size = CGDisplayScreenSize (self->screen_id);
- bounds = CGDisplayBounds (self->screen_id);
- main_bounds = CGDisplayBounds (CGMainDisplayID ());
+ bounds = [screen frame];
width = CGDisplayModeGetWidth (mode);
pixel_width = CGDisplayModeGetPixelWidth (mode);
has_opengl = CGDisplayUsesOpenGLAcceleration (self->screen_id);
subpixel_layout = GetSubpixelLayout (self->screen_id);
- name = GetLocalizedName (self->screen_id);
+ name = GetLocalizedName (screen);
connector = GetConnectorName (self->screen_id);
if (width != 0 && pixel_width != 0)
@@ -221,19 +223,8 @@ _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
width_mm = size.width;
height_mm = size.height;
- /* This requires that the display bounds have been updated before the monitor
- * is reconfigured. Note that the result from CGDisplayBounds() is not exactly
- * the same as display coordinates.
- *
- * As the docs say:
- *
- * Returns the bounds of a display in the global display coordinate space.
- *
- * The bounds of the display, expressed as a rectangle in the global display
- * coordinate space (relative to the upper-left corner of the main display).
- */
geom.x = bounds.origin.x - display->min_x;
- geom.y = bounds.origin.y - display->min_y;
+ geom.y = display->height - bounds.origin.y - bounds.size.height + display->min_y;
geom.width = bounds.size.width;
geom.height = bounds.size.height;
@@ -253,6 +244,8 @@ _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
gdk_monitor_set_refresh_rate (GDK_MONITOR (self), refresh_rate);
gdk_monitor_set_subpixel_layout (GDK_MONITOR (self), GDK_SUBPIXEL_LAYOUT_UNKNOWN);
+ self->workarea = [screen visibleFrame];
+
/* We might be able to use this at some point to change which GSK renderer
* we use for surfaces on this monitor. For example, it might be better
* to use cairo if we cannot use OpenGL (or it would be software) anyway.
diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c
index ce84d36d9f..019fa14de1 100644
--- a/gdk/macos/gdkmacossurface.c
+++ b/gdk/macos/gdkmacossurface.c
@@ -25,6 +25,7 @@
#import "GdkMacosCairoView.h"
+#include "gdkdisplay.h"
#include "gdkframeclockidleprivate.h"
#include "gdkinternals.h"
#include "gdksurfaceprivate.h"
@@ -895,7 +896,7 @@ _gdk_macos_surface_monitor_changed (GdkMacosSurface *self)
GdkMonitor *
_gdk_macos_surface_get_best_monitor (GdkMacosSurface *self)
{
- GdkMonitor *best;
+ GdkMonitor *best = NULL;
GdkDisplay *display;
GdkRectangle rect;
guint n_monitors;
@@ -911,7 +912,6 @@ _gdk_macos_surface_get_best_monitor (GdkMacosSurface *self)
rect.width = GDK_SURFACE (self)->width;
rect.height = GDK_SURFACE (self)->height;
- best = gdk_display_get_monitor (display, 0);
for (guint i = 0; i < n_monitors; i++)
{
diff --git a/gdk/macos/meson.build b/gdk/macos/meson.build
index c10a3bb5b8..cecbdbe97f 100644
--- a/gdk/macos/meson.build
+++ b/gdk/macos/meson.build
@@ -1,4 +1,6 @@
gdk_macos_sources = files([
+ 'edgesnapping.c',
+
'gdkdisplaylinksource.c',
'GdkMacosWindow.c',
'gdkmacoscairocontext.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]