From 4dbd9d23d7a924d1335487ebe76d18a376c143c7 Mon Sep 17 00:00:00 2001 From: Richard Hult Date: Sun, 24 Feb 2008 17:45:29 +0000 Subject: [PATCH] Use the subtype field for the custom event that is used to wake up the 2008-02-24 Richard Hult * gdk/quartz/gdkprivate-quartz.h: * gdk/quartz/gdkeventloop-quartz.c: (got_fd_activity), (poll_func): Use the subtype field for the custom event that is used to wake up the mainloop so we can have other custom event types. * gdk/quartz/gdkevents-quartz.c: (_gdk_quartz_events_trigger_crossing_events): * gdk/quartz/gdkwindow-quartz.c: (show_window_internal): Create crossing events after showing a window if necessary, to work around problems with the tracking rect API. svn path=/trunk/; revision=19637 --- ChangeLog | 13 +++++++ gdk/quartz/gdkeventloop-quartz.c | 5 ++- gdk/quartz/gdkevents-quartz.c | 63 ++++++++++++++++++++++++++++++++ gdk/quartz/gdkprivate-quartz.h | 6 +++ gdk/quartz/gdkwindow-quartz.c | 3 ++ 5 files changed, 88 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 200ce17bcc..b13f6487da 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2008-02-24 Richard Hult + + * gdk/quartz/gdkprivate-quartz.h: + * gdk/quartz/gdkeventloop-quartz.c: (got_fd_activity), (poll_func): + Use the subtype field for the custom event that is used to wake up + the mainloop so we can have other custom event types. + + * gdk/quartz/gdkevents-quartz.c: + (_gdk_quartz_events_trigger_crossing_events): + * gdk/quartz/gdkwindow-quartz.c: (show_window_internal): Create + crossing events after showing a window if necessary, to work + around problems with the tracking rect API. + 2008-02-22 Dominic Lachowicz * demos/gtk-demo/printing.c (do_printing): gtk-demo printing gives diff --git a/gdk/quartz/gdkeventloop-quartz.c b/gdk/quartz/gdkeventloop-quartz.c index bb14a13f32..dcc8c9ca91 100644 --- a/gdk/quartz/gdkeventloop-quartz.c +++ b/gdk/quartz/gdkeventloop-quartz.c @@ -139,7 +139,7 @@ got_fd_activity (void *info) timestamp: 0 windowNumber: 0 context: nil - subtype: 0 + subtype: GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP data1: 0 data2: 0]; @@ -253,7 +253,8 @@ poll_func (GPollFD *ufds, guint nfds, gint timeout_) if (event) { - if ([event type] == NSApplicationDefined) + if ([event type] == NSApplicationDefined && + [event subtype] == GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP) { pthread_mutex_lock (&pollfd_mutex); diff --git a/gdk/quartz/gdkevents-quartz.c b/gdk/quartz/gdkevents-quartz.c index 5bc0367fdf..af37e91dc4 100644 --- a/gdk/quartz/gdkevents-quartz.c +++ b/gdk/quartz/gdkevents-quartz.c @@ -650,6 +650,7 @@ create_crossing_event (GdkWindow *window, point = [nsevent locationInWindow]; toplevel = [(GdkQuartzView *)[nswindow contentView] gdkWindow]; + impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl); x_tmp = point.x; @@ -1084,6 +1085,68 @@ find_mouse_window_for_ns_event (NSEvent *nsevent, return mouse_window; } +/* Trigger crossing events if necessary. This is used when showing a new + * window, since the tracking rect API doesn't work reliably when a window + * shows up under the mouse cursor. It's done by finding the topmost window + * under the mouse pointer and synthesizing crossing events into that + * window. + */ +void +_gdk_quartz_events_trigger_crossing_events (void) +{ + NSPoint point; + gint x; + gint y; + GdkWindow *mouse_window; + GdkWindowImplQuartz *impl; + NSUInteger flags = 0; + NSTimeInterval timestamp = 0; + NSEvent *current_event; + NSEvent *nsevent; + + point = [NSEvent mouseLocation]; + x = point.x; + y = _gdk_quartz_window_get_inverted_screen_y (point.y); + + mouse_window = _gdk_quartz_window_find_child (_gdk_root, x, y); + if (mouse_window == _gdk_root) + return; + + /* NSMouseEntered always happens on the toplevel. */ + mouse_window = gdk_window_get_toplevel (mouse_window); + + get_converted_window_coordinates (_gdk_root, + x, y, + mouse_window, + &x, &y); + + impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (mouse_window)->impl); + + /* Fix up the event to be less fake if possible. */ + current_event = [NSApp currentEvent]; + if (current_event) + { + flags = [current_event modifierFlags]; + timestamp = [current_event timestamp]; + } + + nsevent = [NSEvent otherEventWithType:NSApplicationDefined + location:NSMakePoint(x, impl->height - y) + modifierFlags:flags + timestamp:timestamp + windowNumber:[impl->toplevel windowNumber] + context:nil + subtype:GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING + data1:0 + data2:0]; + +#ifdef G_ENABLE_DEBUG + /*_gdk_quartz_window_debug_highlight (mouse_window);*/ +#endif + + synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, x, y); +} + /* Synthesizes crossing events if necessary, based on the passed in * NSEvent. Uses NSMouseEntered and NSMouseExisted for toplevels and * the mouse moved/dragged events for child windows, to see if the diff --git a/gdk/quartz/gdkprivate-quartz.h b/gdk/quartz/gdkprivate-quartz.h index b79663baa6..39696ec11d 100644 --- a/gdk/quartz/gdkprivate-quartz.h +++ b/gdk/quartz/gdkprivate-quartz.h @@ -147,6 +147,11 @@ void _gdk_quartz_window_did_resign_main (GdkWindow *window); void _gdk_quartz_window_debug_highlight (GdkWindow *window); /* Events */ +typedef enum { + GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP, + GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING +} GdkQuartzEventSubType; + void _gdk_quartz_events_update_focus_window (GdkWindow *new_window, gboolean got_focus); GdkWindow * _gdk_quartz_events_get_mouse_window (gboolean consider_grabs); @@ -154,6 +159,7 @@ void _gdk_quartz_events_update_mouse_window (GdkWindow *window); void _gdk_quartz_events_update_cursor (GdkWindow *window); void _gdk_quartz_events_send_map_events (GdkWindow *window); GdkEventMask _gdk_quartz_events_get_current_event_mask (void); +void _gdk_quartz_events_trigger_crossing_events(void); extern GdkWindow *_gdk_quartz_keyboard_grab_window; extern GdkWindow *_gdk_quartz_pointer_grab_window; diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c index 54238235b3..d585f1d604 100644 --- a/gdk/quartz/gdkwindow-quartz.c +++ b/gdk/quartz/gdkwindow-quartz.c @@ -1101,6 +1101,9 @@ show_window_internal (GdkWindow *window, if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for)) _gdk_quartz_window_attach_to_parent (window); + if (impl->toplevel) + _gdk_quartz_events_trigger_crossing_events (); + GDK_QUARTZ_RELEASE_POOL; }