Merge branch 'wip/chergert/for-main' into 'main'

macos: various fixes

See merge request GNOME/gtk!4543
This commit is contained in:
Matthias Clasen 2022-03-02 13:37:06 +00:00
commit eaf0353205
10 changed files with 173 additions and 99 deletions

View File

@ -20,7 +20,7 @@
#include "config.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacosmonitor.h"
#include "gdkmacosmonitor-private.h"
#include "gdkmacossurface-private.h"
#include "gdkmacostoplevelsurface-private.h"
@ -36,47 +36,28 @@ _gdk_macos_display_position_toplevel_with_parent (GdkMacosDisplay *self,
{
GdkRectangle surface_rect;
GdkRectangle parent_rect;
GdkRectangle workarea;
GdkMonitor *monitor;
g_assert (GDK_IS_MACOS_DISPLAY (self));
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (surface));
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (parent));
/* If x/y is set, we should place relative to parent */
if (GDK_SURFACE (surface)->x != 0 || GDK_SURFACE (surface)->y != 0)
{
*x = parent->root_x + GDK_SURFACE (surface)->x;
*y = parent->root_y + GDK_SURFACE (surface)->y;
return;
}
monitor = _gdk_macos_surface_get_best_monitor (parent);
/* Try to center on top of the parent but also try to make the whole thing
* visible in case that lands us under the topbar/panel/etc.
*/
surface_rect.x = surface->root_x + surface->shadow_left;
surface_rect.y = surface->root_y + surface->shadow_top;
parent_rect.x = parent->root_x + parent->shadow_left;
parent_rect.y = parent->root_y + parent->shadow_top;
parent_rect.width = GDK_SURFACE (parent)->width - parent->shadow_left - parent->shadow_right;
parent_rect.height = GDK_SURFACE (parent)->height - parent->shadow_top - parent->shadow_bottom;
surface_rect.width = GDK_SURFACE (surface)->width - surface->shadow_left - surface->shadow_right;
surface_rect.height = GDK_SURFACE (surface)->height - surface->shadow_top - surface->shadow_bottom;
parent_rect.x = parent->root_x + surface->shadow_left;
parent_rect.y = parent->root_y + surface->shadow_top;
parent_rect.width = GDK_SURFACE (parent)->width - surface->shadow_left - surface->shadow_right;
parent_rect.height = GDK_SURFACE (parent)->height - surface->shadow_top - surface->shadow_bottom;
/* Try to place centered atop parent */
surface_rect.x = parent_rect.x + ((parent_rect.width - surface_rect.width) / 2);
surface_rect.y = parent_rect.y + ((parent_rect.height - surface_rect.height) / 2);
/* Now make sure that we don't overlap the top-bar */
monitor = _gdk_macos_surface_get_best_monitor (parent);
gdk_macos_monitor_get_workarea (monitor, &workarea);
if (surface_rect.x < workarea.x)
surface_rect.x = workarea.x;
if (surface_rect.y < workarea.y)
surface_rect.y = workarea.y;
_gdk_macos_monitor_clamp (GDK_MACOS_MONITOR (monitor), &surface_rect);
*x = surface_rect.x - surface->shadow_left;
*y = surface_rect.y - surface->shadow_top;
@ -123,11 +104,7 @@ _gdk_macos_display_position_toplevel (GdkMacosDisplay *self,
surface_rect.x = workarea.x + ((workarea.width - surface_rect.width) / 2);
surface_rect.y = workarea.y + ((workarea.height - surface_rect.height) / 2);
if (surface_rect.x < workarea.x)
surface_rect.x = workarea.x;
if (surface_rect.y < workarea.y)
surface_rect.y = workarea.y;
_gdk_macos_monitor_clamp (GDK_MACOS_MONITOR (surface->best_monitor), &surface_rect);
*x = surface_rect.x - surface->shadow_left;
*y = surface_rect.y - surface->shadow_top;

View File

@ -156,6 +156,10 @@ gdk_macos_display_update_bounds (GdkMacosDisplay *self)
self->width = self->max_x - self->min_x;
self->height = self->max_y - self->min_y;
GDK_NOTE (MISC,
g_message ("Displays reconfigured to bounds %d,%d %dx%d",
self->min_x, self->min_y, self->width, self->height));
GDK_END_MACOS_ALLOC_POOL;
}

View File

@ -38,8 +38,6 @@ struct _GdkMacosGLContext
{
GdkGLContext parent_instance;
cairo_region_t *damage;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
CGLContextObj cgl_context;
G_GNUC_END_IGNORE_DEPRECATIONS

View File

@ -469,6 +469,7 @@ gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
buffer = _gdk_macos_surface_get_buffer (GDK_MACOS_SURFACE (surface));
_gdk_macos_buffer_set_flipped (buffer, TRUE);
_gdk_macos_buffer_set_damage (buffer, region);
/* Create our render target and bind it */
gdk_gl_context_make_current (GDK_GL_CONTEXT (self));
@ -476,9 +477,6 @@ gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->begin_frame (context, prefers_high_depth, region);
g_clear_pointer (&self->damage, cairo_region_destroy);
self->damage = g_steal_pointer (&copy);
gdk_gl_context_make_current (GDK_GL_CONTEXT (self));
CHECK_GL (NULL, glBindFramebuffer (GL_FRAMEBUFFER, self->fbo));
}
@ -531,8 +529,6 @@ gdk_macos_gl_context_surface_resized (GdkDrawContext *draw_context)
g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
g_clear_pointer (&self->damage, cairo_region_destroy);
if (self->cgl_context != NULL)
CGLUpdateContext (self->cgl_context);
}
@ -587,9 +583,16 @@ static cairo_region_t *
gdk_macos_gl_context_get_damage (GdkGLContext *context)
{
GdkMacosGLContext *self = (GdkMacosGLContext *)context;
const cairo_region_t *damage;
GdkMacosBuffer *buffer;
GdkSurface *surface;
if (self->damage)
return cairo_region_copy (self->damage);
g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
if ((surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context))) &&
(buffer = GDK_MACOS_SURFACE (surface)->front) &&
(damage = _gdk_macos_buffer_get_damage (buffer)))
return cairo_region_copy (damage);
return GDK_GL_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->get_damage (context);
}
@ -619,8 +622,6 @@ gdk_macos_gl_context_dispose (GObject *gobject)
CGLDestroyContext (cgl_context);
}
g_clear_pointer (&self->damage, cairo_region_destroy);
G_OBJECT_CLASS (gdk_macos_gl_context_parent_class)->dispose (gobject);
}

View File

@ -41,6 +41,8 @@ void _gdk_macos_monitor_add_frame_callback (GdkMacosMonitor *
GdkMacosSurface *surface);
void _gdk_macos_monitor_remove_frame_callback (GdkMacosMonitor *self,
GdkMacosSurface *surface);
void _gdk_macos_monitor_clamp (GdkMacosMonitor *self,
GdkRectangle *area);
G_END_DECLS

View File

@ -431,3 +431,29 @@ _gdk_macos_monitor_remove_frame_callback (GdkMacosMonitor *self,
gdk_display_link_source_pause (self->display_link);
}
}
void
_gdk_macos_monitor_clamp (GdkMacosMonitor *self,
GdkRectangle *area)
{
GdkRectangle workarea;
GdkRectangle geom;
g_return_if_fail (GDK_IS_MACOS_MONITOR (self));
g_return_if_fail (area != NULL);
gdk_macos_monitor_get_workarea (GDK_MONITOR (self), &workarea);
gdk_monitor_get_geometry (GDK_MONITOR (self), &geom);
if (area->x + area->width > workarea.x + workarea.width)
area->x = workarea.x + workarea.width - area->width;
if (area->x < workarea.x)
area->x = workarea.x;
if (area->y + area->height > workarea.y + workarea.height)
area->y = workarea.y + workarea.height - area->height;
if (area->y < workarea.y)
area->y = workarea.y;
}

View File

@ -275,7 +275,7 @@ _gdk_macos_popup_surface_class_init (GdkMacosPopupSurfaceClass *klass)
object_class->get_property = _gdk_macos_popup_surface_get_property;
object_class->set_property = _gdk_macos_popup_surface_set_property;
gdk_popup_install_properties (object_class, 1);
gdk_popup_install_properties (object_class, LAST_PROP);
}
static void

View File

@ -75,6 +75,7 @@ struct _GdkMacosSurface
guint geometry_dirty : 1;
guint next_frame_set : 1;
guint show_on_next_swap : 1;
guint in_change_monitor : 1;
guint in_frame : 1;
guint awaiting_frame : 1;
};

View File

@ -72,9 +72,12 @@ _gdk_macos_surface_request_frame (GdkMacosSurface *self)
if (self->awaiting_frame)
return;
self->awaiting_frame = TRUE;
_gdk_macos_monitor_add_frame_callback (GDK_MACOS_MONITOR (self->best_monitor), self);
gdk_surface_freeze_updates (GDK_SURFACE (self));
if (self->best_monitor != NULL)
{
self->awaiting_frame = TRUE;
_gdk_macos_monitor_add_frame_callback (GDK_MACOS_MONITOR (self->best_monitor), self);
gdk_surface_freeze_updates (GDK_SURFACE (self));
}
}
static void
@ -85,9 +88,12 @@ _gdk_macos_surface_cancel_frame (GdkMacosSurface *self)
if (!self->awaiting_frame)
return;
self->awaiting_frame = FALSE;
_gdk_macos_monitor_remove_frame_callback (GDK_MACOS_MONITOR (self->best_monitor), self);
gdk_surface_thaw_updates (GDK_SURFACE (self));
if (self->best_monitor != NULL)
{
self->awaiting_frame = FALSE;
_gdk_macos_monitor_remove_frame_callback (GDK_MACOS_MONITOR (self->best_monitor), self);
gdk_surface_thaw_updates (GDK_SURFACE (self));
}
}
void
@ -152,9 +158,6 @@ _gdk_macos_surface_reposition_children (GdkMacosSurface *self)
if (GDK_IS_MACOS_POPUP_SURFACE (child))
_gdk_macos_popup_surface_reposition (GDK_MACOS_POPUP_SURFACE (child));
}
if (GDK_IS_POPUP (self) && self->did_initial_present)
gdk_surface_request_layout (GDK_SURFACE (self));
}
static void
@ -199,7 +202,9 @@ gdk_macos_surface_hide (GdkSurface *surface)
self->show_on_next_swap = FALSE;
was_mapped = GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self));
_gdk_macos_surface_cancel_frame (self);
was_mapped = GDK_SURFACE_IS_MAPPED (surface);
was_key = [self->window isKeyWindow];
seat = gdk_display_get_default_seat (surface->display);
@ -222,13 +227,6 @@ gdk_macos_surface_hide (GdkSurface *surface)
[parentWindow showAndMakeKey:YES];
}
}
if (self->awaiting_frame)
{
self->awaiting_frame = FALSE;
_gdk_macos_monitor_remove_frame_callback (GDK_MACOS_MONITOR (self->best_monitor), self);
gdk_surface_freeze_updates (surface);
}
}
static int
@ -469,16 +467,8 @@ gdk_macos_surface_destroy (GdkSurface *surface,
GdkMacosWindow *window = g_steal_pointer (&self->window);
GdkFrameClock *frame_clock;
if (self->best_monitor)
{
if (self->awaiting_frame)
{
_gdk_macos_monitor_remove_frame_callback (GDK_MACOS_MONITOR (self->best_monitor), self);
self->awaiting_frame = FALSE;
}
g_clear_object (&self->best_monitor);
}
_gdk_macos_surface_cancel_frame (self);
g_clear_object (&self->best_monitor);
if ((frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self))))
{
@ -636,7 +626,10 @@ _gdk_macos_surface_new (GdkMacosDisplay *display,
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
frame_clock = _gdk_frame_clock_idle_new ();
if (parent != NULL)
frame_clock = g_object_ref (parent->frame_clock);
else
frame_clock = _gdk_frame_clock_idle_new ();
switch (surface_type)
{
@ -844,8 +837,9 @@ _gdk_macos_surface_update_fullscreen_state (GdkMacosSurface *self)
void
_gdk_macos_surface_configure (GdkMacosSurface *self)
{
GdkMacosDisplay *display;
GdkSurface *surface = (GdkSurface *)self;
GdkMacosDisplay *display;
GdkMacosSurface *parent;
NSRect frame_rect;
NSRect content_rect;
@ -854,6 +848,13 @@ _gdk_macos_surface_configure (GdkMacosSurface *self)
if (GDK_SURFACE_DESTROYED (self))
return;
if (surface->parent != NULL)
parent = GDK_MACOS_SURFACE (surface->parent);
else if (surface->transient_for != NULL)
parent = GDK_MACOS_SURFACE (surface->transient_for);
else
parent = NULL;
display = GDK_MACOS_DISPLAY (GDK_SURFACE (self)->display);
frame_rect = [self->window frame];
content_rect = [self->window contentRectForFrameRect:frame_rect];
@ -863,10 +864,10 @@ _gdk_macos_surface_configure (GdkMacosSurface *self)
content_rect.origin.y + content_rect.size.height,
&self->root_x, &self->root_y);
if (surface->parent != NULL)
if (parent != NULL)
{
surface->x = self->root_x - GDK_MACOS_SURFACE (surface->parent)->root_x;
surface->y = self->root_y - GDK_MACOS_SURFACE (surface->parent)->root_y;
surface->x = self->root_x - parent->root_x;
surface->y = self->root_y - parent->root_y;
}
else
{
@ -884,7 +885,6 @@ _gdk_macos_surface_configure (GdkMacosSurface *self)
g_clear_object (&self->front);
_gdk_surface_update_size (surface);
gdk_surface_request_layout (surface);
gdk_surface_invalidate_rect (surface, NULL);
}
@ -910,6 +910,7 @@ _gdk_macos_surface_show (GdkMacosSurface *self)
{
gdk_surface_set_is_mapped (GDK_SURFACE (self), TRUE);
gdk_surface_request_layout (GDK_SURFACE (self));
gdk_surface_invalidate_rect (GDK_SURFACE (self), NULL);
gdk_surface_thaw_updates (GDK_SURFACE (self));
}
}
@ -965,13 +966,27 @@ _gdk_macos_surface_move_resize (GdkMacosSurface *self,
NSRect frame_rect;
gboolean ignore_move;
gboolean ignore_size;
GdkRectangle current;
g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
ignore_move = (x == -1 || (x == self->root_x)) &&
(y == -1 || (y == self->root_y));
ignore_size = (width == -1 || (width == surface->width)) &&
(height == -1 || (height == surface->height));
/* Query for up-to-date values in case we're racing against
* an incoming frame notify which could be queued behind whatever
* we're processing right now.
*/
frame_rect = [self->window frame];
content_rect = [self->window contentRectForFrameRect:frame_rect];
_gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (GDK_SURFACE (self)->display),
content_rect.origin.x, content_rect.origin.y,
&current.x, &current.y);
current.width = content_rect.size.width;
current.height = content_rect.size.height;
/* Check if we can ignore the operation all together */
ignore_move = (x == -1 || (x == current.x)) &&
(y == -1 || (y == current.y));
ignore_size = (width == -1 || (width == current.width)) &&
(height == -1 || (height == current.height));
if (ignore_move && ignore_size)
return;
@ -979,23 +994,21 @@ _gdk_macos_surface_move_resize (GdkMacosSurface *self,
display = gdk_surface_get_display (surface);
if (width == -1)
width = surface->width;
width = current.width;
if (height == -1)
height = surface->height;
height = current.height;
if (x == -1)
x = self->root_x;
x = current.x;
if (y == -1)
y = self->root_y;
y = current.y;
_gdk_macos_display_to_display_coords (GDK_MACOS_DISPLAY (display),
x, y + height,
&x, &y);
content_rect = [self->window contentRectForFrameRect:[self->window frame]];
if (!ignore_move)
content_rect.origin = NSMakePoint (x, y);
@ -1003,7 +1016,7 @@ _gdk_macos_surface_move_resize (GdkMacosSurface *self,
content_rect.size = NSMakeSize (width, height);
frame_rect = [self->window frameRectForContentRect:content_rect];
[self->window setFrame:frame_rect display:YES];
[self->window setFrame:frame_rect display:NO];
}
void
@ -1068,7 +1081,13 @@ _gdk_macos_surface_monitor_changed (GdkMacosSurface *self)
g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
if (self->in_change_monitor)
return;
self->in_change_monitor = TRUE;
_gdk_macos_surface_cancel_frame (self);
_gdk_macos_surface_configure (self);
rect.x = self->root_x;
rect.y = self->root_y;
@ -1132,11 +1151,42 @@ _gdk_macos_surface_monitor_changed (GdkMacosSurface *self)
g_message ("Surface \"%s\" moved to monitor \"%s\"",
self->title ? self->title : "unknown",
gdk_monitor_get_connector (best)));
_gdk_macos_surface_configure (self);
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self)))
{
_gdk_macos_surface_request_frame (self);
gdk_surface_request_layout (GDK_SURFACE (self));
}
for (const GList *iter = GDK_SURFACE (self)->children;
iter != NULL;
iter = iter->next)
{
GdkMacosSurface *child = iter->data;
GdkRectangle area;
g_set_object (&child->best_monitor, best);
area.x = self->root_x + GDK_SURFACE (child)->x + child->shadow_left;
area.y = self->root_y + GDK_SURFACE (child)->y + child->shadow_top;
area.width = GDK_SURFACE (child)->width - child->shadow_left - child->shadow_right;
area.height = GDK_SURFACE (child)->height - child->shadow_top - child->shadow_bottom;
_gdk_macos_monitor_clamp (GDK_MACOS_MONITOR (best), &area);
area.x -= child->shadow_left;
area.y -= child->shadow_top;
_gdk_macos_surface_move (child, area.x, area.y);
gdk_surface_invalidate_rect (GDK_SURFACE (child), NULL);
}
}
_gdk_macos_surface_configure (self);
gdk_surface_invalidate_rect (GDK_SURFACE (self), NULL);
_gdk_macos_surface_request_frame (self);
self->in_change_monitor = FALSE;
}
GdkMonitor *
@ -1220,11 +1270,15 @@ _gdk_macos_surface_get_buffer (GdkMacosSurface *self)
static void
_gdk_macos_surface_do_delayed_show (GdkMacosSurface *self)
{
GdkSurface *surface = (GdkSurface *)self;
g_assert (GDK_IS_MACOS_SURFACE (self));
self->show_on_next_swap = FALSE;
[self->window showAndMakeKey:YES];
gdk_surface_request_motion (GDK_SURFACE (self));
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
gdk_surface_request_motion (surface);
}
void

View File

@ -648,10 +648,10 @@ _gdk_macos_toplevel_surface_new (GdkMacosDisplay *display,
GdkMacosWindow *window;
GdkMacosSurface *self;
NSScreen *screen;
NSUInteger style_mask;
NSRect content_rect;
NSRect screen_rect;
NSRect visible_frame;
NSScreen *screen;
int nx;
int ny;
@ -664,14 +664,17 @@ _gdk_macos_toplevel_surface_new (GdkMacosDisplay *display,
NSWindowStyleMaskMiniaturizable |
NSWindowStyleMaskResizable);
_gdk_macos_display_to_display_coords (display, x, y, &nx, &ny);
if (parent != NULL)
{
x += GDK_MACOS_SURFACE (parent)->root_x;
y += GDK_MACOS_SURFACE (parent)->root_y;
}
_gdk_macos_display_to_display_coords (display, x, y + height, &nx, &ny);
screen = _gdk_macos_display_get_screen_at_display_coords (display, nx, ny);
screen_rect = [screen visibleFrame];
nx -= screen_rect.origin.x;
ny -= screen_rect.origin.y;
content_rect = NSMakeRect (nx, ny - height, width, height);
visible_frame = [screen visibleFrame];
content_rect = NSMakeRect (nx - visible_frame.origin.x, ny - visible_frame.origin.y, width, height);
window = [[GdkMacosWindow alloc] initWithContentRect:content_rect
styleMask:style_mask
backing:NSBackingStoreBuffered
@ -707,13 +710,21 @@ _gdk_macos_toplevel_surface_attach_to_parent (GdkMacosToplevelSurface *self)
{
NSWindow *parent = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface->transient_for));
NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
int x, y;
[parent addChildWindow:window ordered:NSWindowAbove];
if (GDK_SURFACE (self)->modal_hint)
[window setLevel:NSModalPanelWindowLevel];
surface->x = 0;
surface->y = 0;
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
_gdk_macos_display_position_surface (GDK_MACOS_DISPLAY (surface->display),
GDK_MACOS_SURFACE (surface),
&x, &y);
_gdk_macos_surface_move (GDK_MACOS_SURFACE (surface), x, y);
}
}