Ken Thomases : winemac: Take control over when a window can become focused away from Cocoa.
Alexandre Julliard
julliard at winehq.org
Mon Jan 28 13:43:19 CST 2013
Module: wine
Branch: master
Commit: 6cde62ac18c9845c6f339b273a821135f7bf6794
URL: http://source.winehq.org/git/wine.git/?a=commit;h=6cde62ac18c9845c6f339b273a821135f7bf6794
Author: Ken Thomases <ken at 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
More information about the wine-cvs
mailing list