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