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

macos: fit'n'finish fixes for main

See merge request GNOME/gtk!4564
This commit is contained in:
Matthias Clasen 2022-03-12 19:07:41 +00:00
commit 8186cb8bee
9 changed files with 167 additions and 57 deletions

View File

@ -24,6 +24,7 @@
#import "GdkMacosLayer.h" #import "GdkMacosLayer.h"
#import "GdkMacosView.h" #import "GdkMacosView.h"
#import "GdkMacosWindow.h"
@implementation GdkMacosView @implementation GdkMacosView
@ -56,6 +57,19 @@
return NO; return NO;
} }
-(void)mouseDown:(NSEvent *)nsevent
{
if ([(GdkMacosWindow *)[self window] needsMouseDownQuirk])
/* We should only hit this when we are trying to click through
* the shadow of a window into another window. Just request
* that the application not activate this window on mouseUp.
* See gdkmacosdisplay-translate.c for the other half of this.
*/
[NSApp preventWindowOrdering];
else
[super mouseDown:nsevent];
}
-(void)setFrame:(NSRect)rect -(void)setFrame:(NSRect)rect
{ {
[super setFrame:rect]; [super setFrame:rect];

View File

@ -262,9 +262,12 @@ typedef NSString *CALayerContentsGravity;
inShowOrHide = YES; inShowOrHide = YES;
if (makeKey && [self canBecomeKeyWindow]) if (makeKey && [self canBecomeKeyWindow])
[self makeKeyAndOrderFront:nil]; [self makeKeyAndOrderFront:self];
else else
[self orderFront:nil]; [self orderFront:self];
if (makeKey && [self canBecomeMainWindow])
[self makeMainWindow];
inShowOrHide = NO; inShowOrHide = NO;
@ -374,9 +377,17 @@ typedef NSString *CALayerContentsGravity;
_gdk_macos_surface_configure ([self gdkSurface]); _gdk_macos_surface_configure ([self gdkSurface]);
} }
- (void)windowDidResize:(NSNotification *)notification -(void)windowDidResize:(NSNotification *)notification
{ {
_gdk_macos_surface_configure ([self gdkSurface]); _gdk_macos_surface_configure (gdk_surface);
/* If we're using server-side decorations, this notification is coming
* in from a display-side change. We need to request a layout in
* addition to the configure event.
*/
if (GDK_IS_MACOS_TOPLEVEL_SURFACE (gdk_surface) &&
GDK_MACOS_TOPLEVEL_SURFACE (gdk_surface)->decorated)
gdk_surface_request_layout (GDK_SURFACE (gdk_surface));
} }
/* Used by gdkmacosdisplay-translate.c to decide if our sendEvent() handler /* Used by gdkmacosdisplay-translate.c to decide if our sendEvent() handler
@ -819,4 +830,10 @@ typedef NSString *CALayerContentsGravity;
[(GdkMacosView *)[self contentView] swapBuffer:buffer withDamage:damage]; [(GdkMacosView *)[self contentView] swapBuffer:buffer withDamage:damage];
} }
-(BOOL)needsMouseDownQuirk
{
return GDK_IS_MACOS_TOPLEVEL_SURFACE (gdk_surface) &&
!GDK_MACOS_TOPLEVEL_SURFACE (gdk_surface)->decorated;
}
@end @end

View File

@ -69,5 +69,6 @@
-(BOOL)trackManualResize; -(BOOL)trackManualResize;
-(void)setDecorated:(BOOL)decorated; -(void)setDecorated:(BOOL)decorated;
-(void)swapBuffer:(GdkMacosBuffer *)buffer withDamage:(const cairo_region_t *)damage; -(void)swapBuffer:(GdkMacosBuffer *)buffer withDamage:(const cairo_region_t *)damage;
-(BOOL)needsMouseDownQuirk;
@end @end

View File

@ -43,6 +43,8 @@ G_BEGIN_DECLS
#define GIC_FILTER_PASSTHRU 0 #define GIC_FILTER_PASSTHRU 0
#define GIC_FILTER_FILTERED 1 #define GIC_FILTER_FILTERED 1
#define GDK_MACOS_EVENT_DROP (GdkEvent *)GSIZE_TO_POINTER(1)
struct _GdkMacosDisplay struct _GdkMacosDisplay
{ {
GdkDisplay parent_instance; GdkDisplay parent_instance;
@ -82,6 +84,14 @@ struct _GdkMacosDisplay
int min_y; int min_y;
int max_x; int max_x;
int max_y; int max_y;
/* A GSource to select a new main/key window */
guint select_key_in_idle;
/* Note if we have a key window that is not a GdkMacosWindow
* such as a NSPanel used for native dialogs.
*/
guint key_window_is_foregin : 1;
}; };
struct _GdkMacosDisplayClass struct _GdkMacosDisplayClass

View File

@ -628,7 +628,7 @@ fill_scroll_event (GdkMacosDisplay *self,
* handle those internally. * handle those internally.
*/ */
if (phase == 0 && momentumPhase != 0) if (phase == 0 && momentumPhase != 0)
return NULL; return GDK_MACOS_EVENT_DROP;
seat = gdk_display_get_default_seat (GDK_DISPLAY (self)); seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
pointer = gdk_seat_get_pointer (seat); pointer = gdk_seat_get_pointer (seat);
@ -1086,6 +1086,7 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
GdkMacosSurface *surface; GdkMacosSurface *surface;
GdkMacosWindow *window; GdkMacosWindow *window;
NSEventType event_type; NSEventType event_type;
NSWindow *event_window;
GdkEvent *ret = NULL; GdkEvent *ret = NULL;
int x; int x;
int y; int y;
@ -1128,6 +1129,15 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
return NULL; return NULL;
} }
/* If the event was delivered to NSWindow that is foreign (or rather,
* Cocoa native), then we should pass the event along to that window.
*/
if ((event_window = [nsevent window]) && !GDK_IS_MACOS_WINDOW (event_window))
return NULL;
/* If we can't find a GdkSurface to deliver the event to, then we
* should pass it along to the NSApp.
*/
if (!(surface = find_surface_for_ns_event (self, nsevent, &x, &y))) if (!(surface = find_surface_for_ns_event (self, nsevent, &x, &y)))
return NULL; return NULL;
@ -1159,15 +1169,31 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
if (test_resize (nsevent, surface, x, y)) if (test_resize (nsevent, surface, x, y))
return NULL; return NULL;
if ((event_type == NSEventTypeRightMouseDown || if (event_type == NSEventTypeRightMouseDown ||
event_type == NSEventTypeOtherMouseDown || event_type == NSEventTypeOtherMouseDown ||
event_type == NSEventTypeLeftMouseDown)) event_type == NSEventTypeLeftMouseDown)
{ {
if (![NSApp isActive]) if (![NSApp isActive])
[NSApp activateIgnoringOtherApps:YES]; [NSApp activateIgnoringOtherApps:YES];
if (![window isKeyWindow]) if (![window isKeyWindow])
[window makeKeyWindow]; {
NSWindow *orig_window = [nsevent window];
/* To get NSApp to supress activating the window we might
* have clicked through the shadow of, we need to dispatch
* the event and handle it in GdkMacosView:mouseDown to call
* [NSApp preventWindowOrdering]. Calling it here will not
* do anything as the event is not registered.
*/
if (orig_window &&
GDK_IS_MACOS_WINDOW (orig_window) &&
[(GdkMacosWindow *)orig_window needsMouseDownQuirk])
[NSApp sendEvent:nsevent];
[window showAndMakeKey:YES];
_gdk_macos_display_clear_sorting (self);
}
} }
switch ((int)event_type) switch ((int)event_type)
@ -1200,7 +1226,11 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
GdkDevice *pointer = gdk_seat_get_pointer (seat); GdkDevice *pointer = gdk_seat_get_pointer (seat);
GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (GDK_DISPLAY (self), pointer); GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (GDK_DISPLAY (self), pointer);
if (grab == NULL) if ([(GdkMacosWindow *)window isInManualResizeOrMove])
{
ret = GDK_MACOS_EVENT_DROP;
}
else if (grab == NULL)
{ {
if (event_type == NSEventTypeMouseExited) if (event_type == NSEventTypeMouseExited)
[[NSCursor arrowCursor] set]; [[NSCursor arrowCursor] set];

View File

@ -310,11 +310,15 @@ gdk_macos_display_queue_events (GdkDisplay *display)
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self)); g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
if ((nsevent = _gdk_macos_event_source_get_pending ())) while ((nsevent = _gdk_macos_event_source_get_pending ()))
{ {
GdkEvent *event = _gdk_macos_display_translate (self, nsevent); GdkEvent *event = _gdk_macos_display_translate (self, nsevent);
if (event != NULL) if (event == GDK_MACOS_EVENT_DROP)
{
[nsevent release];
}
else if (event != NULL)
{ {
push_nsevent (event, nsevent); push_nsevent (event, nsevent);
_gdk_windowing_got_event (GDK_DISPLAY (self), _gdk_windowing_got_event (GDK_DISPLAY (self),
@ -409,6 +413,38 @@ _gdk_macos_display_surface_became_key (GdkMacosDisplay *self,
gdk_surface_request_motion (GDK_SURFACE (surface)); gdk_surface_request_motion (GDK_SURFACE (surface));
} }
static gboolean
select_key_in_idle_cb (gpointer data)
{
GdkMacosDisplay *self = data;
g_assert (GDK_IS_MACOS_DISPLAY (self));
self->select_key_in_idle = 0;
/* Don't steal focus from NSPanel, etc */
if (self->key_window_is_foregin)
return G_SOURCE_REMOVE;
if (self->keyboard_surface == NULL)
{
const GList *surfaces = _gdk_macos_display_get_surfaces (self);
for (const GList *iter = surfaces; iter; iter = iter->next)
{
GdkMacosSurface *surface = iter->data;
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (surface)))
{
[surface->window showAndMakeKey:YES];
break;
}
}
}
return G_SOURCE_REMOVE;
}
void void
_gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self, _gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self,
GdkMacosSurface *surface) GdkMacosSurface *surface)
@ -453,6 +489,9 @@ _gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self,
} }
_gdk_macos_display_clear_sorting (self); _gdk_macos_display_clear_sorting (self);
if (self->select_key_in_idle == 0)
self->select_key_in_idle = g_idle_add (select_key_in_idle_cb, self);
} }
/* Raises a transient window. /* Raises a transient window.
@ -491,8 +530,6 @@ void
_gdk_macos_display_surface_resigned_main (GdkMacosDisplay *self, _gdk_macos_display_surface_resigned_main (GdkMacosDisplay *self,
GdkMacosSurface *surface) GdkMacosSurface *surface)
{ {
GdkMacosSurface *new_surface = NULL;
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self)); g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
g_return_if_fail (GDK_IS_MACOS_SURFACE (surface)); g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
@ -500,40 +537,6 @@ _gdk_macos_display_surface_resigned_main (GdkMacosDisplay *self,
g_queue_unlink (&self->main_surfaces, &surface->main); g_queue_unlink (&self->main_surfaces, &surface->main);
_gdk_macos_display_clear_sorting (self); _gdk_macos_display_clear_sorting (self);
if (GDK_SURFACE (surface)->transient_for &&
gdk_surface_get_mapped (GDK_SURFACE (surface)->transient_for))
{
new_surface = GDK_MACOS_SURFACE (GDK_SURFACE (surface)->transient_for);
}
else
{
const GList *surfaces = _gdk_macos_display_get_surfaces (self);
for (const GList *iter = surfaces; iter; iter = iter->next)
{
GdkMacosSurface *item = iter->data;
g_assert (GDK_IS_MACOS_SURFACE (item));
if (item == surface)
continue;
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (item)))
{
new_surface = item;
break;
}
}
}
if (new_surface != NULL)
{
NSWindow *nswindow = _gdk_macos_surface_get_native (new_surface);
[nswindow makeKeyAndOrderFront:nswindow];
}
_gdk_macos_display_clear_sorting (self);
} }
static GdkSurface * static GdkSurface *
@ -596,6 +599,7 @@ gdk_macos_display_finalize (GObject *object)
_gdk_macos_display_feedback_destroy (self); _gdk_macos_display_feedback_destroy (self);
g_clear_handle_id (&self->select_key_in_idle, g_source_remove);
g_clear_pointer (&self->active_drags, g_hash_table_unref); g_clear_pointer (&self->active_drags, g_hash_table_unref);
g_clear_pointer (&self->active_drops, g_hash_table_unref); g_clear_pointer (&self->active_drops, g_hash_table_unref);
g_clear_object (&GDK_DISPLAY (self)->clipboard); g_clear_object (&GDK_DISPLAY (self)->clipboard);
@ -960,11 +964,16 @@ _gdk_macos_display_get_surfaces (GdkMacosDisplay *self)
NSArray *array = [NSApp orderedWindows]; NSArray *array = [NSApp orderedWindows];
GQueue sorted = G_QUEUE_INIT; GQueue sorted = G_QUEUE_INIT;
self->key_window_is_foregin = FALSE;
for (id obj in array) for (id obj in array)
{ {
NSWindow *nswindow = (NSWindow *)obj; NSWindow *nswindow = (NSWindow *)obj;
GdkMacosSurface *surface; GdkMacosSurface *surface;
if ([nswindow isKeyWindow])
self->key_window_is_foregin = !GDK_IS_MACOS_WINDOW (nswindow);
if (!GDK_IS_MACOS_WINDOW (nswindow)) if (!GDK_IS_MACOS_WINDOW (nswindow))
continue; continue;

View File

@ -34,6 +34,7 @@ struct _GdkMacosPopupSurface
{ {
GdkMacosSurface parent_instance; GdkMacosSurface parent_instance;
GdkPopupLayout *layout; GdkPopupLayout *layout;
guint attached : 1;
}; };
struct _GdkMacosPopupSurfaceClass struct _GdkMacosPopupSurfaceClass
@ -138,6 +139,9 @@ gdk_macos_popup_surface_present (GdkPopup *popup,
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self))) if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self)))
return TRUE; return TRUE;
if (!self->attached && GDK_SURFACE (self)->parent != NULL)
_gdk_macos_popup_surface_attach_to_parent (self);
if (GDK_SURFACE (self)->autohide) if (GDK_SURFACE (self)->autohide)
{ {
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (popup)); GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (popup));
@ -203,6 +207,19 @@ enum {
LAST_PROP, LAST_PROP,
}; };
static void
_gdk_macos_popup_surface_hide (GdkSurface *surface)
{
GdkMacosPopupSurface *self = (GdkMacosPopupSurface *)surface;
g_assert (GDK_IS_MACOS_POPUP_SURFACE (self));
if (self->attached)
_gdk_macos_popup_surface_detach_from_parent (self);
GDK_SURFACE_CLASS (_gdk_macos_popup_surface_parent_class)->hide (surface);
}
static void static void
_gdk_macos_popup_surface_finalize (GObject *object) _gdk_macos_popup_surface_finalize (GObject *object)
{ {
@ -270,11 +287,14 @@ static void
_gdk_macos_popup_surface_class_init (GdkMacosPopupSurfaceClass *klass) _gdk_macos_popup_surface_class_init (GdkMacosPopupSurfaceClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkSurfaceClass *surface_class = GDK_SURFACE_CLASS (klass);
object_class->finalize = _gdk_macos_popup_surface_finalize; object_class->finalize = _gdk_macos_popup_surface_finalize;
object_class->get_property = _gdk_macos_popup_surface_get_property; object_class->get_property = _gdk_macos_popup_surface_get_property;
object_class->set_property = _gdk_macos_popup_surface_set_property; object_class->set_property = _gdk_macos_popup_surface_set_property;
surface_class->hide = _gdk_macos_popup_surface_hide;
gdk_popup_install_properties (object_class, LAST_PROP); gdk_popup_install_properties (object_class, LAST_PROP);
} }
@ -326,14 +346,8 @@ _gdk_macos_popup_surface_new (GdkMacosDisplay *display,
[window setOpaque:NO]; [window setOpaque:NO];
[window setBackgroundColor:[NSColor clearColor]]; [window setBackgroundColor:[NSColor clearColor]];
[window setDecorated:NO]; [window setDecorated:NO];
[window setExcludedFromWindowsMenu:YES];
#if 0
/* NOTE: We could set these to be popup level, but then
* [NSApp orderedWindows] would not give us the windows
* back with the stacking order applied.
*/
[window setLevel:NSPopUpMenuWindowLevel]; [window setLevel:NSPopUpMenuWindowLevel];
#endif
self = g_object_new (GDK_TYPE_MACOS_POPUP_SURFACE, self = g_object_new (GDK_TYPE_MACOS_POPUP_SURFACE,
"display", display, "display", display,
@ -364,6 +378,8 @@ _gdk_macos_popup_surface_attach_to_parent (GdkMacosPopupSurface *self)
[parent addChildWindow:window ordered:NSWindowAbove]; [parent addChildWindow:window ordered:NSWindowAbove];
self->attached = TRUE;
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display)); _gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
} }
} }
@ -385,6 +401,8 @@ _gdk_macos_popup_surface_detach_from_parent (GdkMacosPopupSurface *self)
[parent removeChildWindow:window]; [parent removeChildWindow:window];
self->attached = FALSE;
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display)); _gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
} }
} }

View File

@ -219,10 +219,17 @@ gdk_macos_surface_hide (GdkSurface *surface)
if (was_key) if (was_key)
{ {
GdkSurface *parent;
if (GDK_IS_TOPLEVEL (surface))
parent = surface->transient_for;
else
parent = surface->parent;
/* Return key input to the parent window if necessary */ /* Return key input to the parent window if necessary */
if (surface->parent != NULL && GDK_SURFACE_IS_MAPPED (surface->parent)) if (parent != NULL && GDK_SURFACE_IS_MAPPED (parent))
{ {
GdkMacosWindow *parentWindow = GDK_MACOS_SURFACE (surface->parent)->window; GdkMacosWindow *parentWindow = GDK_MACOS_SURFACE (parent)->window;
[parentWindow showAndMakeKey:YES]; [parentWindow showAndMakeKey:YES];
} }

View File

@ -39,6 +39,7 @@
#include "gtkfilefilterprivate.h" #include "gtkfilefilterprivate.h"
#include "macos/gdkmacos.h" #include "macos/gdkmacos.h"
#include "macos/gdkmacosdisplay-private.h"
#include "macos/gdkmacossurface-private.h" #include "macos/gdkmacossurface-private.h"
typedef struct { typedef struct {
@ -368,6 +369,9 @@ filechooser_quartz_launch (FileChooserQuartzData *data)
[data->key_window makeKeyAndOrderFront:nil]; [data->key_window makeKeyAndOrderFront:nil];
} }
/* Need to clear our cached copy of ordered windows */
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (gdk_display_get_default ()));
if (!data->skip_response) if (!data->skip_response)
{ {
g_slist_free_full (self->custom_files, g_object_unref); g_slist_free_full (self->custom_files, g_object_unref);