macos: Queue events during drag

By passing the events during a (midal-ish) drag operation to the main loop,
we're able to keep up with what's happening. This allows the internal
drag state (GtkDragSource) to be updated and be done when the drag is
done.
This commit is contained in:
Arjan Molenaar 2023-01-16 14:47:49 +01:00
parent 1d8a23e97b
commit 1bc63eeadb
3 changed files with 24 additions and 17 deletions

View File

@ -30,6 +30,7 @@
#include "gdkmacosdisplay-private.h" #include "gdkmacosdisplay-private.h"
#include "gdkmacosdrag-private.h" #include "gdkmacosdrag-private.h"
#include "gdkmacosdrop-private.h" #include "gdkmacosdrop-private.h"
#include "gdkmacoseventsource-private.h"
#include "gdkmacosmonitor-private.h" #include "gdkmacosmonitor-private.h"
#include "gdkmacospasteboard-private.h" #include "gdkmacospasteboard-private.h"
#include "gdkmacossurface-private.h" #include "gdkmacossurface-private.h"
@ -701,6 +702,8 @@ typedef NSString *CALayerContentsGravity;
GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number); GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
int x, y; int x, y;
_gdk_macos_event_source_queue_event ([NSApp currentEvent]);
_gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display), screenPoint.x, screenPoint.y, &x, &y); _gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display), screenPoint.x, screenPoint.y, &x, &y);
_gdk_macos_drag_surface_move (GDK_MACOS_DRAG (drag), x, y); _gdk_macos_drag_surface_move (GDK_MACOS_DRAG (drag), x, y);
} }
@ -711,6 +714,8 @@ typedef NSString *CALayerContentsGravity;
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface)); GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number); GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
_gdk_macos_event_source_queue_event ([NSApp currentEvent]);
if (gdk_drag_get_selected_action (drag) != 0) if (gdk_drag_get_selected_action (drag) != 0)
g_signal_emit_by_name (drag, "drop-performed"); g_signal_emit_by_name (drag, "drop-performed");
else else

View File

@ -34,6 +34,7 @@ typedef enum
GSource *_gdk_macos_event_source_new (GdkMacosDisplay *display); GSource *_gdk_macos_event_source_new (GdkMacosDisplay *display);
NSEvent *_gdk_macos_event_source_get_pending (void); NSEvent *_gdk_macos_event_source_get_pending (void);
gboolean _gdk_macos_event_source_check_pending (void); gboolean _gdk_macos_event_source_check_pending (void);
void _gdk_macos_event_source_queue_event (NSEvent *event);
G_END_DECLS G_END_DECLS

View File

@ -640,6 +640,23 @@ _gdk_macos_event_source_get_pending (void)
return event; return event;
} }
void
_gdk_macos_event_source_queue_event (NSEvent *event)
{
/* Just used to wake us up; if an event and a FD arrived at the same
* time; could have come from a previous iteration in some cases,
* but the spurious wake up is harmless if a little inefficient.
*/
if (!event ||
([event type] == NSEventTypeApplicationDefined &&
[event subtype] == GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP))
return;
if (!current_events)
current_events = g_queue_new ();
g_queue_push_head (current_events, [event retain]);
}
static gboolean static gboolean
gdk_macos_event_source_prepare (GSource *source, gdk_macos_event_source_prepare (GSource *source,
int *timeout) int *timeout)
@ -782,23 +799,7 @@ poll_func (GPollFD *ufds,
if (last_ufds == ufds && n_ready < 0) if (last_ufds == ufds && n_ready < 0)
n_ready = select_thread_collect_poll (ufds, nfds); n_ready = select_thread_collect_poll (ufds, nfds);
if (event && _gdk_macos_event_source_queue_event (event);
[event type] == NSEventTypeApplicationDefined &&
[event subtype] == GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP)
{
/* Just used to wake us up; if an event and a FD arrived at the same
* time; could have come from a previous iteration in some cases,
* but the spurious wake up is harmless if a little inefficient.
*/
event = NULL;
}
if (event)
{
if (!current_events)
current_events = g_queue_new ();
g_queue_push_head (current_events, [event retain]);
}
return n_ready; return n_ready;
} }