diff --git a/ChangeLog b/ChangeLog index bb6dabd02a..f5c7b5ad4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2008-03-28 Richard Hult + + * gdk/quartz/gdkevents-quartz.c: (gdk_event_translate), + (_gdk_quartz_events_trigger_crossing_events): Defer the generated + event to the mainloop and don't generate one at all if the + toplevel didn't change. Use the actual window and not the toplevel + as event window. These changes make the generated crossing events + match the X11 behavior and fixes issues with e.g. tooltips, + comboboxes and menus. + + * gdk/quartz/GdkQuartzView.c: Don't update the tracking rect if + the view has no window, it will be updated as soon as it's put + inside a window. + + * gdk/quartz/gdkwindow-quartz.c: + (_gdk_quartz_window_debug_highlight): Make it possible to track + multiple windows with debug highlighting. + (show_window_internal): Remove workaround for tooltips and popups + that is no longer needed with the above changes. + 2008-03-26 Federico Mena Quintero * gtk/gtkfilechooserentry.c (commit_completion_and_refresh): New diff --git a/gdk/quartz/GdkQuartzView.c b/gdk/quartz/GdkQuartzView.c index 1063e7bfb9..843df50e47 100644 --- a/gdk/quartz/GdkQuartzView.c +++ b/gdk/quartz/GdkQuartzView.c @@ -179,7 +179,9 @@ -(void)setFrame:(NSRect)frame { [super setFrame:frame]; - [self updateTrackingRect]; + + if ([self window]) + [self updateTrackingRect]; } @end diff --git a/gdk/quartz/gdkevents-quartz.c b/gdk/quartz/gdkevents-quartz.c index dc7701b6fd..912fdec898 100644 --- a/gdk/quartz/gdkevents-quartz.c +++ b/gdk/quartz/gdkevents-quartz.c @@ -888,7 +888,7 @@ _gdk_quartz_events_update_mouse_window (GdkWindow *window) #ifdef G_ENABLE_DEBUG if (_gdk_debug_flags & GDK_DEBUG_EVENTS) - _gdk_quartz_window_debug_highlight (window); + _gdk_quartz_window_debug_highlight (window, 0); #endif /* G_ENABLE_DEBUG */ if (window) @@ -1092,18 +1092,34 @@ find_mouse_window_for_ns_event (NSEvent *nsevent, * window. */ void -_gdk_quartz_events_trigger_crossing_events (void) +_gdk_quartz_events_trigger_crossing_events (gboolean defer_to_mainloop) { NSPoint point; - gint x; - gint y; + gint x, y; + gint x_toplevel, y_toplevel; GdkWindow *mouse_window; + GdkWindow *toplevel; GdkWindowImplQuartz *impl; guint flags = 0; NSTimeInterval timestamp = 0; NSEvent *current_event; NSEvent *nsevent; + if (defer_to_mainloop) + { + nsevent = [NSEvent otherEventWithType:NSApplicationDefined + location:NSZeroPoint + modifierFlags:0 + timestamp:0 + windowNumber:0 + context:nil + subtype:GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING + data1:0 + data2:0]; + [NSApp postEvent:nsevent atStart:NO]; + return; + } + point = [NSEvent mouseLocation]; x = point.x; y = _gdk_quartz_window_get_inverted_screen_y (point.y); @@ -1112,16 +1128,24 @@ _gdk_quartz_events_trigger_crossing_events (void) if (!mouse_window || mouse_window == _gdk_root) return; - /* NSMouseEntered always happens on the toplevel. */ - mouse_window = gdk_window_get_toplevel (mouse_window); + toplevel = gdk_window_get_toplevel (mouse_window); + + /* We ignore crossing within the same toplevel since that is already + * handled elsewhere. + */ + if (toplevel == gdk_window_get_toplevel (current_mouse_window)) + return; + + get_converted_window_coordinates (_gdk_root, + x, y, + toplevel, + &x_toplevel, &y_toplevel); 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) @@ -1130,8 +1154,12 @@ _gdk_quartz_events_trigger_crossing_events (void) timestamp = [current_event timestamp]; } + if (timestamp == 0) + timestamp = GetCurrentEventTime (); + + impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl); nsevent = [NSEvent otherEventWithType:NSApplicationDefined - location:NSMakePoint(x, impl->height - y) + location:NSMakePoint (x_toplevel, impl->height - y_toplevel) modifierFlags:flags timestamp:timestamp windowNumber:[impl->toplevel windowNumber] @@ -1141,7 +1169,7 @@ _gdk_quartz_events_trigger_crossing_events (void) data2:0]; #ifdef G_ENABLE_DEBUG - /*_gdk_quartz_window_debug_highlight (mouse_window);*/ + /*_gdk_quartz_window_debug_highlight (mouse_window, 0);*/ #endif synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, x, y); @@ -1702,6 +1730,14 @@ gdk_event_translate (NSEvent *nsevent) } } + /* Handle our generated "fake" crossing events. */ + if ([nsevent type] == NSApplicationDefined && + [nsevent subtype] == GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING) + { + _gdk_quartz_events_trigger_crossing_events (FALSE); + return TRUE; + } + /* Keep track of button state, since we don't get that information * for key events. */ diff --git a/gdk/quartz/gdkprivate-quartz.h b/gdk/quartz/gdkprivate-quartz.h index 39696ec11d..859a802b88 100644 --- a/gdk/quartz/gdkprivate-quartz.h +++ b/gdk/quartz/gdkprivate-quartz.h @@ -144,7 +144,8 @@ void _gdk_quartz_window_attach_to_parent (GdkWindow *window); void _gdk_quartz_window_detach_from_parent (GdkWindow *window); void _gdk_quartz_window_did_become_main (GdkWindow *window); void _gdk_quartz_window_did_resign_main (GdkWindow *window); -void _gdk_quartz_window_debug_highlight (GdkWindow *window); +void _gdk_quartz_window_debug_highlight (GdkWindow *window, + gint number); /* Events */ typedef enum { @@ -159,7 +160,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); +void _gdk_quartz_events_trigger_crossing_events(gboolean defer_to_mainloop); 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 ddf2e81cdc..997e90db6c 100644 --- a/gdk/quartz/gdkwindow-quartz.c +++ b/gdk/quartz/gdkwindow-quartz.c @@ -538,22 +538,31 @@ get_ancestor_coordinates_from_child (GdkWindow *child_window, } void -_gdk_quartz_window_debug_highlight (GdkWindow *window) +_gdk_quartz_window_debug_highlight (GdkWindow *window, gint number) { GdkWindowObject *private = GDK_WINDOW_OBJECT (window); GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); gint x, y; GdkWindow *toplevel; gint tx, ty; - static NSWindow *debug_window; - static NSRect old_rect; + static NSWindow *debug_window[10]; + static NSRect old_rect[10]; NSRect rect; + NSColor *color; + + g_return_if_fail (number >= 0 && number <= 9); if (window == _gdk_root) return; if (window == NULL) - return; + { + if (debug_window[number]) + [debug_window[number] close]; + debug_window[number] = NULL; + + return; + } toplevel = gdk_window_get_toplevel (window); get_ancestor_coordinates_from_child (window, 0, 0, toplevel, &x, &y); @@ -562,37 +571,56 @@ _gdk_quartz_window_debug_highlight (GdkWindow *window) x += tx; y += ty; - rect = NSMakeRect (x, - _gdk_quartz_window_get_inverted_screen_y (y + impl->height), - impl->width, impl->height); + rect = NSMakeRect (x, + _gdk_quartz_window_get_inverted_screen_y (y + impl->height), + impl->width, impl->height); - if (debug_window && - rect.origin.x == old_rect.origin.x && - rect.origin.y == old_rect.origin.y && - rect.size.width == old_rect.size.width && - rect.size.height == old_rect.size.height) + if (debug_window[number] && NSEqualRects (rect, old_rect[number])) + return; + + old_rect[number] = rect; + + if (debug_window[number]) + [debug_window[number] close]; + + debug_window[number] = [[NSWindow alloc] initWithContentRect:rect + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + + switch (number) { - return; + case 0: + color = [NSColor redColor]; + break; + case 1: + color = [NSColor blueColor]; + break; + case 2: + color = [NSColor greenColor]; + break; + case 3: + color = [NSColor yellowColor]; + break; + case 4: + color = [NSColor brownColor]; + break; + case 5: + color = [NSColor purpleColor]; + break; + default: + color = [NSColor blackColor]; + break; } - old_rect = rect; + [debug_window[number] setBackgroundColor:color]; + [debug_window[number] setAlphaValue:0.4]; + [debug_window[number] setOpaque:NO]; + [debug_window[number] setReleasedWhenClosed:YES]; + [debug_window[number] setIgnoresMouseEvents:YES]; + [debug_window[number] setLevel:NSFloatingWindowLevel]; - if (debug_window) - [debug_window close]; - - debug_window = [[NSWindow alloc] initWithContentRect:rect - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:NO]; - - [debug_window setBackgroundColor:[NSColor redColor]]; - [debug_window setAlphaValue:0.4]; - [debug_window setOpaque:NO]; - [debug_window setReleasedWhenClosed:YES]; - [debug_window setIgnoresMouseEvents:YES]; - [debug_window setLevel:NSFloatingWindowLevel]; - - [debug_window orderFront:nil]; + [debug_window[number] orderFront:nil]; } gboolean @@ -1137,11 +1165,11 @@ show_window_internal (GdkWindow *window, if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for)) _gdk_quartz_window_attach_to_parent (window); - /* Create a crossing event for managed windows that pop up under the - * mouse. Part of the workarounds for problems with the tracking rect API. + /* Create a crossing event for windows that pop up under the mouse. Part + * of the workarounds for problems with the tracking rect API. */ - if (impl->toplevel && private->window_type != GDK_WINDOW_TEMP) - _gdk_quartz_events_trigger_crossing_events (); + if (impl->toplevel) + _gdk_quartz_events_trigger_crossing_events (TRUE); GDK_QUARTZ_RELEASE_POOL; }