diff --git a/ChangeLog b/ChangeLog index 59f004ba4b..174dcf73bb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2008-01-10 Richard Hult + + Merged from trunk: + + * gdk/quartz/gdkwindow-quartz.c: (show_window_internal), + (gdk_window_hide), (move_resize_window_internal): Move the + tracking rect workaround from here... + + * gdk/quartz/GdkQuartzWindow.c: + * gdk/quartz/GdkQuartzWindow.h: ...to here, and ignore window + movements during showing/hiding operations. Fixes bug #508516. + 2008-01-10 Kristian Rietveld Merge from trunk: diff --git a/gdk/quartz/GdkQuartzWindow.c b/gdk/quartz/GdkQuartzWindow.c index b5c751d443..d1ecbfdfa9 100644 --- a/gdk/quartz/GdkQuartzWindow.c +++ b/gdk/quartz/GdkQuartzWindow.c @@ -136,6 +136,14 @@ GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); GdkEvent *event; + /* Ignore new position during showing/hiding the window, otherwise we + * would get the off-screen position that is used for hidden windows to + * get reliable MouseEntered events when showing them again. See comments + * in show() and hide(). + */ + if (inShowOrHide) + return; + private->x = content_rect.origin.x; private->y = _gdk_quartz_window_get_inverted_screen_y (content_rect.origin.y + content_rect.size.height); @@ -257,6 +265,63 @@ return YES; } +- (void)showAndMakeKey:(BOOL)makeKey +{ + GdkWindow *window = [[self contentView] gdkWindow]; + GdkWindowObject *private = (GdkWindowObject *)window; + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); + + inShowOrHide = YES; + + if (!GDK_WINDOW_IS_MAPPED (window)) + { + NSRect content_rect; + NSRect frame_rect; + + /* We move the window in place if it's not mapped. See comment in + * hide(). + */ + content_rect = + NSMakeRect (private->x, + _gdk_quartz_window_get_inverted_screen_y (private->y) - impl->height, + impl->width, impl->height); + frame_rect = [impl->toplevel frameRectForContentRect:content_rect]; + [impl->toplevel setFrame:frame_rect display:NO]; + } + + if (makeKey) + [impl->toplevel makeKeyAndOrderFront:impl->toplevel]; + else + [impl->toplevel orderFront:nil]; + + inShowOrHide = NO; +} + +- (void)hide +{ + GdkWindow *window = [[self contentView] gdkWindow]; + GdkWindowObject *private = (GdkWindowObject *)window; + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); + NSRect content_rect; + NSRect frame_rect; + + inShowOrHide = YES; + + /* We move the window away when hiding, to make it possible to move it in + * place when showing to get reliable tracking rect events (which are used + * to generate crossing events). We have to do this, probably a bug in + * quartz. + */ + content_rect = NSMakeRect (-500 - impl->width, -500 - impl->height, + impl->width, impl->height); + frame_rect = [impl->toplevel frameRectForContentRect:content_rect]; + [impl->toplevel setFrame:frame_rect display:NO]; + + [impl->toplevel orderOut:nil]; + + inShowOrHide = NO; +} + - (BOOL)trackManualMove { NSPoint currentLocation; diff --git a/gdk/quartz/GdkQuartzWindow.h b/gdk/quartz/GdkQuartzWindow.h index 37271790aa..e6d1b4e155 100644 --- a/gdk/quartz/GdkQuartzWindow.h +++ b/gdk/quartz/GdkQuartzWindow.h @@ -23,7 +23,8 @@ #include @interface GdkQuartzWindow : NSWindow { - BOOL inMove; + BOOL inMove; + BOOL inShowOrHide; /* Manually triggered move/resize (not by the window manager) */ BOOL inManualMove; @@ -39,6 +40,8 @@ -(BOOL)trackManualMove; -(void)beginManualResize; -(BOOL)trackManualResize; +-(void)showAndMakeKey:(BOOL)makeKey; +-(void)hide; @end diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c index b687d2a5c1..e740790d82 100644 --- a/gdk/quartz/gdkwindow-quartz.c +++ b/gdk/quartz/gdkwindow-quartz.c @@ -962,30 +962,15 @@ show_window_internal (GdkWindow *window, if (impl->toplevel) { + gboolean make_key; + /* Move the window into place, to guarantee that we get the * initial MouseEntered event. */ - if (!GDK_WINDOW_IS_MAPPED (window)) - { - NSRect content_rect; - NSRect frame_rect; + make_key = (private->accept_focus && focus_on_map && raise && + private->window_type != GDK_WINDOW_TEMP); - content_rect = - NSMakeRect (private->x, - _gdk_quartz_window_get_inverted_screen_y (private->y) - impl->height, - impl->width, impl->height); - frame_rect = [impl->toplevel frameRectForContentRect:content_rect]; - [impl->toplevel setFrame:frame_rect display:NO]; - } - - /* We should make the window not raise for !raise, but at least - * this will keep it from getting focused in that case. - */ - if (private->accept_focus && focus_on_map && raise && - private->window_type != GDK_WINDOW_TEMP) - [impl->toplevel makeKeyAndOrderFront:impl->toplevel]; - else - [impl->toplevel orderFront:nil]; + [(GdkQuartzWindow*)impl->toplevel showAndMakeKey:make_key]; } else { @@ -1110,16 +1095,7 @@ gdk_window_hide (GdkWindow *window) if (impl->transient_for) _gdk_quartz_window_detach_from_parent (window); - /* Big hack in gdk_window_new() and show_window_internal() - * continued. Move the window away when hidden so that we can - * move it back before showing it. - */ - content_rect = NSMakeRect (-500 - impl->width, -500 - impl->height, - impl->width, impl->height); - frame_rect = [impl->toplevel frameRectForContentRect:content_rect]; - [impl->toplevel setFrame:frame_rect display:NO]; - - [impl->toplevel orderOut:nil]; + [(GdkQuartzWindow*)impl->toplevel hide]; } else if (impl->view) { @@ -1214,12 +1190,19 @@ move_resize_window_internal (GdkWindow *window, NSRect content_rect; NSRect frame_rect; - content_rect = NSMakeRect (private->x, - _gdk_quartz_window_get_inverted_screen_y (private->y + impl->height), - impl->width, impl->height); - - frame_rect = [impl->toplevel frameRectForContentRect:content_rect]; - [impl->toplevel setFrame:frame_rect display:YES]; + /* We don't update the NSWindow while unmapped, since we move windows + * off-screen when hiding in order for MouseEntered to be triggered + * reliably when showing windows and they appear under the mouse. + */ + if (GDK_WINDOW_IS_MAPPED (window)) + { + content_rect = NSMakeRect (private->x, + _gdk_quartz_window_get_inverted_screen_y (private->y + impl->height), + impl->width, impl->height); + + frame_rect = [impl->toplevel frameRectForContentRect:content_rect]; + [impl->toplevel setFrame:frame_rect display:YES]; + } } else {