Ken Thomases : winemac: Implement DISPLAYS_CHANGED event for when display configuration has changed .

Alexandre Julliard julliard at winehq.org
Mon Feb 18 13:27:05 CST 2013


Module: wine
Branch: master
Commit: bc75a9baffd889deef00a2acfdb19ae4bdce29ca
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=bc75a9baffd889deef00a2acfdb19ae4bdce29ca

Author: Ken Thomases <ken at codeweavers.com>
Date:   Sun Feb 17 19:28:34 2013 -0600

winemac: Implement DISPLAYS_CHANGED event for when display configuration has changed.

---

 dlls/winemac.drv/cocoa_app.m    |   15 +++++++++
 dlls/winemac.drv/display.c      |   65 ++++++++++++++++++++++++++++++++++++++-
 dlls/winemac.drv/event.c        |    5 +++
 dlls/winemac.drv/gdi.c          |   10 +++++-
 dlls/winemac.drv/macdrv.h       |    6 +++
 dlls/winemac.drv/macdrv_cocoa.h |    1 +
 dlls/winemac.drv/window.c       |   33 ++++++++++++++++++++
 7 files changed, 133 insertions(+), 2 deletions(-)

diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m
index 2651cfc..479b4d0 100644
--- a/dlls/winemac.drv/cocoa_app.m
+++ b/dlls/winemac.drv/cocoa_app.m
@@ -312,6 +312,20 @@ int macdrv_err_on;
         }
     }
 
+    - (void) sendDisplaysChanged
+    {
+        macdrv_event event;
+        WineEventQueue* queue;
+
+        event.type = DISPLAYS_CHANGED;
+        event.window = NULL;
+
+        [eventQueuesLock lock];
+        for (queue in eventQueues)
+            [queue postEvent:&event];
+        [eventQueuesLock unlock];
+    }
+
 
     /*
      * ---------- NSApplication method overrides ----------
@@ -340,6 +354,7 @@ int macdrv_err_on;
     - (void)applicationDidChangeScreenParameters:(NSNotification *)notification
     {
         primaryScreenHeightValid = FALSE;
+        [self sendDisplaysChanged];
     }
 
     - (void)applicationDidResignActive:(NSNotification *)notification
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c
index a1bea38..2a96631 100644
--- a/dlls/winemac.drv/display.c
+++ b/dlls/winemac.drv/display.c
@@ -2,7 +2,7 @@
  * MACDRV display settings
  *
  * Copyright 2003 Alexander James Pasadyn
- * Copyright 2011, 2012 Ken Thomases for CodeWeavers Inc.
+ * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -38,6 +38,42 @@ static inline CGDirectDisplayID monitor_to_display_id(HMONITOR handle)
 }
 
 
+static int display_mode_bits_per_pixel(CGDisplayModeRef display_mode)
+{
+    CFStringRef pixel_encoding;
+    int bits_per_pixel = 0;
+
+    pixel_encoding = CGDisplayModeCopyPixelEncoding(display_mode);
+    if (pixel_encoding)
+    {
+        if (CFEqual(pixel_encoding, CFSTR(kIO32BitFloatPixels)))
+            bits_per_pixel = 128;
+        else if (CFEqual(pixel_encoding, CFSTR(kIO16BitFloatPixels)))
+            bits_per_pixel = 64;
+        else if (CFEqual(pixel_encoding, CFSTR(kIO64BitDirectPixels)))
+            bits_per_pixel = 64;
+        else if (CFEqual(pixel_encoding, CFSTR(kIO30BitDirectPixels)))
+            bits_per_pixel = 30;
+        else if (CFEqual(pixel_encoding, CFSTR(IO32BitDirectPixels)))
+            bits_per_pixel = 32;
+        else if (CFEqual(pixel_encoding, CFSTR(IO16BitDirectPixels)))
+            bits_per_pixel = 16;
+        else if (CFEqual(pixel_encoding, CFSTR(IO8BitIndexedPixels)))
+            bits_per_pixel = 8;
+        else if (CFEqual(pixel_encoding, CFSTR(IO4BitIndexedPixels)))
+            bits_per_pixel = 4;
+        else if (CFEqual(pixel_encoding, CFSTR(IO2BitIndexedPixels)))
+            bits_per_pixel = 2;
+        else if (CFEqual(pixel_encoding, CFSTR(IO1BitIndexedPixels)))
+            bits_per_pixel = 1;
+
+        CFRelease(pixel_encoding);
+    }
+
+    return bits_per_pixel;
+}
+
+
 /***********************************************************************
  *              EnumDisplayMonitors  (MACDRV.@)
  */
@@ -156,3 +192,30 @@ BOOL CDECL macdrv_GetMonitorInfo(HMONITOR monitor, LPMONITORINFO info)
     macdrv_free_displays(displays);
     return (i < num_displays);
 }
+
+
+/***********************************************************************
+ *              macdrv_displays_changed
+ *
+ * Handler for DISPLAYS_CHANGED events.
+ */
+void macdrv_displays_changed(const macdrv_event *event)
+{
+    HWND hwnd = GetDesktopWindow();
+
+    /* A system display change will get delivered to all GUI-attached threads,
+       so the desktop-window-owning thread will get it and all others should
+       ignore it. */
+    if (GetWindowThreadProcessId(hwnd, NULL) == GetCurrentThreadId())
+    {
+        CGDirectDisplayID mainDisplay = CGMainDisplayID();
+        CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay);
+        size_t width = CGDisplayModeGetWidth(mode);
+        size_t height = CGDisplayModeGetHeight(mode);
+        int mode_bpp = display_mode_bits_per_pixel(mode);
+
+        CGDisplayModeRelease(mode);
+        SendMessageW(hwnd, WM_MACDRV_UPDATE_DESKTOP_RECT, mode_bpp,
+                     MAKELPARAM(width, height));
+    }
+}
diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c
index f03fef4..b9131f7 100644
--- a/dlls/winemac.drv/event.c
+++ b/dlls/winemac.drv/event.c
@@ -33,6 +33,7 @@ static const char *dbgstr_event(int type)
 {
     static const char * const event_names[] = {
         "APP_DEACTIVATED",
+        "DISPLAYS_CHANGED",
         "KEY_PRESS",
         "KEY_RELEASE",
         "KEYBOARD_CHANGED",
@@ -84,6 +85,7 @@ static macdrv_event_mask get_event_mask(DWORD mask)
     if (mask & QS_POSTMESSAGE)
     {
         event_mask |= event_mask_for_type(APP_DEACTIVATED);
+        event_mask |= event_mask_for_type(DISPLAYS_CHANGED);
         event_mask |= event_mask_for_type(WINDOW_CLOSE_REQUESTED);
         event_mask |= event_mask_for_type(WINDOW_DID_MINIMIZE);
         event_mask |= event_mask_for_type(WINDOW_DID_UNMINIMIZE);
@@ -116,6 +118,9 @@ void macdrv_handle_event(macdrv_event *event)
     case APP_DEACTIVATED:
         macdrv_app_deactivated();
         break;
+    case DISPLAYS_CHANGED:
+        macdrv_displays_changed(event);
+        break;
     case KEY_PRESS:
     case KEY_RELEASE:
         macdrv_key_event(hwnd, event);
diff --git a/dlls/winemac.drv/gdi.c b/dlls/winemac.drv/gdi.c
index 333cb0c..6ded900 100644
--- a/dlls/winemac.drv/gdi.c
+++ b/dlls/winemac.drv/gdi.c
@@ -2,7 +2,7 @@
  * Mac graphics driver initialisation functions
  *
  * Copyright 1996 Alexandre Julliard
- * Copyright 2011, 2012 Ken Thomases for CodeWeavers, Inc.
+ * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -200,6 +200,14 @@ static void device_init(void)
 }
 
 
+void macdrv_reset_device_metrics(void)
+{
+    EnterCriticalSection(&device_data_section);
+    device_data_valid = FALSE;
+    LeaveCriticalSection(&device_data_section);
+}
+
+
 static MACDRV_PDEVICE *create_mac_physdev(void)
 {
     MACDRV_PDEVICE *physDev;
diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h
index 8c4ce54..113cda1 100644
--- a/dlls/winemac.drv/macdrv.h
+++ b/dlls/winemac.drv/macdrv.h
@@ -68,6 +68,7 @@ static inline const char *wine_dbgstr_cgrect(CGRect cgrect)
  */
 
 extern CGRect macdrv_get_desktop_rect(void) DECLSPEC_HIDDEN;
+extern void macdrv_reset_device_metrics(void) DECLSPEC_HIDDEN;
 
 
 /**************************************************************************
@@ -78,6 +79,9 @@ extern CGRect macdrv_get_desktop_rect(void) DECLSPEC_HIDDEN;
 enum macdrv_window_messages
 {
     WM_MACDRV_SET_WIN_REGION = 0x80001000,
+    WM_MACDRV_UPDATE_DESKTOP_RECT,
+    WM_MACDRV_RESET_DEVICE_METRICS,
+    WM_MACDRV_DISPLAYCHANGE,
 };
 
 struct macdrv_thread_data
@@ -142,4 +146,6 @@ extern void macdrv_compute_keyboard_layout(struct macdrv_thread_data *thread_dat
 extern void macdrv_keyboard_changed(const macdrv_event *event) DECLSPEC_HIDDEN;
 extern void macdrv_key_event(HWND hwnd, const macdrv_event *event) DECLSPEC_HIDDEN;
 
+extern void macdrv_displays_changed(const macdrv_event *event) DECLSPEC_HIDDEN;
+
 #endif  /* __WINE_MACDRV_H */
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index 23f0edf..5ffd7c7 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -126,6 +126,7 @@ extern void macdrv_free_displays(struct macdrv_display* displays) DECLSPEC_HIDDE
 /* event */
 enum {
     APP_DEACTIVATED,
+    DISPLAYS_CHANGED,
     KEY_PRESS,
     KEY_RELEASE,
     KEYBOARD_CHANGED,
diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c
index 65f7955..c7513f0 100644
--- a/dlls/winemac.drv/window.c
+++ b/dlls/winemac.drv/window.c
@@ -1192,6 +1192,39 @@ LRESULT CDECL macdrv_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
             release_win_data(data);
         }
         return 0;
+    case WM_MACDRV_UPDATE_DESKTOP_RECT:
+        if (hwnd == GetDesktopWindow())
+        {
+            CGRect new_desktop_rect;
+            RECT current_desktop_rect;
+
+            macdrv_reset_device_metrics();
+            new_desktop_rect = macdrv_get_desktop_rect();
+            if (!GetWindowRect(hwnd, &current_desktop_rect) ||
+                !CGRectEqualToRect(cgrect_from_rect(current_desktop_rect), new_desktop_rect))
+            {
+                SendMessageTimeoutW(HWND_BROADCAST, WM_MACDRV_RESET_DEVICE_METRICS, 0, 0,
+                                    SMTO_ABORTIFHUNG, 2000, NULL);
+                SetWindowPos(hwnd, 0, CGRectGetMinX(new_desktop_rect), CGRectGetMinY(new_desktop_rect),
+                             CGRectGetWidth(new_desktop_rect), CGRectGetHeight(new_desktop_rect),
+                             SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE);
+                SendMessageTimeoutW(HWND_BROADCAST, WM_MACDRV_DISPLAYCHANGE, wp, lp,
+                                    SMTO_ABORTIFHUNG, 2000, NULL);
+            }
+        }
+        return 0;
+    case WM_MACDRV_RESET_DEVICE_METRICS:
+        macdrv_reset_device_metrics();
+        return 0;
+    case WM_MACDRV_DISPLAYCHANGE:
+        if ((data = get_win_data(hwnd)))
+        {
+            if (data->cocoa_window && data->on_screen)
+                sync_window_position(data, SWP_NOZORDER | SWP_NOACTIVATE);
+            release_win_data(data);
+        }
+        SendMessageW(hwnd, WM_DISPLAYCHANGE, wp, lp);
+        return 0;
     }
 
     FIXME("unrecognized window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, wp, lp);




More information about the wine-cvs mailing list