Module: wine Branch: master Commit: 6cde62ac18c9845c6f339b273a821135f7bf6794 URL: http://source.winehq.org/git/wine.git/?a=commit;h=6cde62ac18c9845c6f339b273a...
Author: Ken Thomases ken@codeweavers.com Date: Sun Jan 27 16:19:41 2013 -0600
winemac: Take control over when a window can become focused away from Cocoa.
---
dlls/winemac.drv/cocoa_window.h | 2 + dlls/winemac.drv/cocoa_window.m | 56 ++++++++++++++++++++++++++++++++++++- dlls/winemac.drv/macdrv_cocoa.h | 1 + dlls/winemac.drv/window.c | 34 ++++++++++++++++++++++ dlls/winemac.drv/winemac.drv.spec | 1 + 5 files changed, 93 insertions(+), 1 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.h b/dlls/winemac.drv/cocoa_window.h index 1f81cc6..7708fa6 100644 --- a/dlls/winemac.drv/cocoa_window.h +++ b/dlls/winemac.drv/cocoa_window.h @@ -45,6 +45,8 @@ CGFloat colorKeyRed, colorKeyGreen, colorKeyBlue;
BOOL usePerPixelAlpha; + + BOOL causing_becomeKeyWindow; }
@end diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 402db30..c1f90d2 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -440,14 +440,52 @@ static BOOL frame_intersects_screens(NSRect frame, NSArray* screens) [queue postEvent:&event]; }
+ - (void) makeFocused + { + NSArray* screens; + + [NSApp transformProcessToForeground]; + + /* If a borderless window is offscreen, orderFront: won't move + it onscreen like it would for a titled window. Do that ourselves. */ + screens = [NSScreen screens]; + if (!([self styleMask] & NSTitledWindowMask) && ![self isVisible] && + !frame_intersects_screens([self frame], screens)) + { + NSScreen* primaryScreen = [screens objectAtIndex:0]; + NSRect frame = [primaryScreen frame]; + [self setFrameTopLeftPoint:NSMakePoint(NSMinX(frame), NSMaxY(frame))]; + frame = [self constrainFrameRect:[self frame] toScreen:primaryScreen]; + [self setFrame:frame display:YES]; + } + + [self orderFront:nil]; + causing_becomeKeyWindow = TRUE; + [self makeKeyWindow]; + causing_becomeKeyWindow = FALSE; + if (latentParentWindow) + { + [latentParentWindow addChildWindow:self ordered:NSWindowAbove]; + self.latentParentWindow = nil; + } + if (![self isExcludedFromWindowsMenu]) + [NSApp addWindowsItem:self title:[self title] filename:NO]; + + /* Cocoa may adjust the frame when the window is ordered onto the screen. + Generate a frame-changed event just in case. The back end will ignore + it if nothing actually changed. */ + [self windowDidResize:nil]; + } +
/* * ---------- NSWindow method overrides ---------- */ - (BOOL) canBecomeKeyWindow { + if (causing_becomeKeyWindow) return YES; if (self.disabled || self.noActivate) return NO; - return YES; + return [self isKeyWindow]; }
- (BOOL) canBecomeMainWindow @@ -841,3 +879,19 @@ void macdrv_window_use_per_pixel_alpha(macdrv_window w, int use_per_pixel_alpha)
[pool release]; } + +/*********************************************************************** + * macdrv_give_cocoa_window_focus + * + * Makes the Cocoa window "key" (gives it keyboard focus). This also + * orders it front and, if its frame was not within the desktop bounds, + * Cocoa will typically move it on-screen. + */ +void macdrv_give_cocoa_window_focus(macdrv_window w) +{ + WineWindow* window = (WineWindow*)w; + + OnMainThread(^{ + [window makeFocused]; + }); +} diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index 4827d40..4b7de10 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -205,5 +205,6 @@ extern void macdrv_set_window_color_key(macdrv_window w, CGFloat keyRed, CGFloat CGFloat keyBlue) DECLSPEC_HIDDEN; extern void macdrv_clear_window_color_key(macdrv_window w) DECLSPEC_HIDDEN; extern void macdrv_window_use_per_pixel_alpha(macdrv_window w, int use_per_pixel_alpha) DECLSPEC_HIDDEN; +extern void macdrv_give_cocoa_window_focus(macdrv_window w) DECLSPEC_HIDDEN;
#endif /* __WINE_MACDRV_COCOA_H */ diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index a08e896..74894e9 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -43,6 +43,9 @@ static CRITICAL_SECTION win_data_section = { &critsect_debug, -1, 0, 0, 0, 0 }; static CFMutableDictionaryRef win_datas;
+void CDECL macdrv_SetFocus(HWND hwnd); + + /*********************************************************************** * get_cocoa_window_features */ @@ -154,6 +157,12 @@ static void show_window(struct macdrv_win_data *data) TRACE("win %p/%p\n", data->hwnd, data->cocoa_window);
data->on_screen = macdrv_order_cocoa_window(data->cocoa_window, NULL, NULL); + if (data->on_screen) + { + HWND hwndFocus = GetFocus(); + if (hwndFocus && (data->hwnd == hwndFocus || IsChild(data->hwnd, hwndFocus))) + macdrv_SetFocus(hwndFocus); + } }
@@ -820,6 +829,31 @@ void CDECL macdrv_DestroyWindow(HWND hwnd) }
+/***************************************************************** + * SetFocus (MACDRV.@) + * + * Set the Mac focus. + */ +void CDECL macdrv_SetFocus(HWND hwnd) +{ + struct macdrv_win_data *data; + + TRACE("%p\n", hwnd); + + if (!(hwnd = GetAncestor(hwnd, GA_ROOT))) return; + if (!(data = get_win_data(hwnd))) return; + + if (data->cocoa_window) + { + /* Set Mac focus */ + macdrv_give_cocoa_window_focus(data->cocoa_window); + data->on_screen = TRUE; + } + + release_win_data(data); +} + + /*********************************************************************** * SetLayeredWindowAttributes (MACDRV.@) * diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec index 73e78ca..a0e1ab8 100644 --- a/dlls/winemac.drv/winemac.drv.spec +++ b/dlls/winemac.drv/winemac.drv.spec @@ -10,6 +10,7 @@ @ cdecl EnumDisplayMonitors(long ptr ptr long) macdrv_EnumDisplayMonitors @ cdecl GetMonitorInfo(long ptr) macdrv_GetMonitorInfo @ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) macdrv_MsgWaitForMultipleObjectsEx +@ cdecl SetFocus(long) macdrv_SetFocus @ cdecl SetLayeredWindowAttributes(long long long long) macdrv_SetLayeredWindowAttributes @ cdecl SetParent(long long long) macdrv_SetParent @ cdecl SetWindowRgn(long long long) macdrv_SetWindowRgn