2 * MACDRV display settings
4 * Copyright 2003 Alexander James Pasadyn
5 * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 WINE_DEFAULT_DEBUG_CHANNEL(display
);
32 BOOL CDECL
macdrv_EnumDisplaySettingsEx(LPCWSTR devname
, DWORD mode
, LPDEVMODEW devmode
, DWORD flags
);
35 static CFArrayRef modes
;
36 static BOOL modes_has_8bpp
, modes_has_16bpp
;
37 static int default_mode_bpp
;
38 static CRITICAL_SECTION modes_section
;
39 static CRITICAL_SECTION_DEBUG critsect_debug
=
42 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
43 0, 0, { (DWORD_PTR
)(__FILE__
": modes_section") }
45 static CRITICAL_SECTION modes_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
48 static inline HMONITOR
display_id_to_monitor(CGDirectDisplayID display_id
)
50 return (HMONITOR
)(UINT_PTR
)display_id
;
53 static inline CGDirectDisplayID
monitor_to_display_id(HMONITOR handle
)
55 return (CGDirectDisplayID
)(UINT_PTR
)handle
;
59 static BOOL
get_display_device_reg_key(char *key
, unsigned len
)
61 static const char display_device_guid_prop
[] = "__wine_display_device_guid";
62 static const char video_path
[] = "System\\CurrentControlSet\\Control\\Video\\{";
63 static const char display0
[] = "}\\0000";
66 assert(len
>= sizeof(video_path
) + sizeof(display0
) + 40);
68 guid_atom
= HandleToULong(GetPropA(GetDesktopWindow(), display_device_guid_prop
));
69 if (!guid_atom
) return FALSE
;
71 memcpy(key
, video_path
, sizeof(video_path
));
73 if (!GlobalGetAtomNameA(guid_atom
, key
+ strlen(key
), 40))
76 strcat(key
, display0
);
78 TRACE("display device key %s\n", wine_dbgstr_a(key
));
83 static BOOL
read_registry_settings(DEVMODEW
*dm
)
85 char wine_mac_reg_key
[128];
92 if (!get_display_device_reg_key(wine_mac_reg_key
, sizeof(wine_mac_reg_key
)))
95 if (RegOpenKeyExA(HKEY_CURRENT_CONFIG
, wine_mac_reg_key
, 0, KEY_READ
, &hkey
))
98 #define query_value(name, data) \
99 size = sizeof(DWORD); \
100 if (RegQueryValueExA(hkey, name, 0, &type, (LPBYTE)(data), &size) || \
101 type != REG_DWORD || size != sizeof(DWORD)) \
104 query_value("DefaultSettings.BitsPerPel", &dm
->dmBitsPerPel
);
105 dm
->dmFields
|= DM_BITSPERPEL
;
106 query_value("DefaultSettings.XResolution", &dm
->dmPelsWidth
);
107 dm
->dmFields
|= DM_PELSWIDTH
;
108 query_value("DefaultSettings.YResolution", &dm
->dmPelsHeight
);
109 dm
->dmFields
|= DM_PELSHEIGHT
;
110 query_value("DefaultSettings.VRefresh", &dm
->dmDisplayFrequency
);
111 dm
->dmFields
|= DM_DISPLAYFREQUENCY
;
112 query_value("DefaultSettings.Flags", &dm
->dmDisplayFlags
);
113 dm
->dmFields
|= DM_DISPLAYFLAGS
;
114 query_value("DefaultSettings.XPanning", &dm
->dmPosition
.x
);
115 query_value("DefaultSettings.YPanning", &dm
->dmPosition
.y
);
116 query_value("DefaultSettings.Orientation", &dm
->dmDisplayOrientation
);
117 query_value("DefaultSettings.FixedOutput", &dm
->dmDisplayFixedOutput
);
126 static BOOL
write_registry_settings(const DEVMODEW
*dm
)
128 char wine_mac_reg_key
[128];
132 if (!get_display_device_reg_key(wine_mac_reg_key
, sizeof(wine_mac_reg_key
)))
135 if (RegCreateKeyExA(HKEY_CURRENT_CONFIG
, wine_mac_reg_key
, 0, NULL
,
136 REG_OPTION_VOLATILE
, KEY_WRITE
, NULL
, &hkey
, NULL
))
139 #define set_value(name, data) \
140 if (RegSetValueExA(hkey, name, 0, REG_DWORD, (const BYTE*)(data), sizeof(DWORD))) \
143 set_value("DefaultSettings.BitsPerPel", &dm
->dmBitsPerPel
);
144 set_value("DefaultSettings.XResolution", &dm
->dmPelsWidth
);
145 set_value("DefaultSettings.YResolution", &dm
->dmPelsHeight
);
146 set_value("DefaultSettings.VRefresh", &dm
->dmDisplayFrequency
);
147 set_value("DefaultSettings.Flags", &dm
->dmDisplayFlags
);
148 set_value("DefaultSettings.XPanning", &dm
->dmPosition
.x
);
149 set_value("DefaultSettings.YPanning", &dm
->dmPosition
.y
);
150 set_value("DefaultSettings.Orientation", &dm
->dmDisplayOrientation
);
151 set_value("DefaultSettings.FixedOutput", &dm
->dmDisplayFixedOutput
);
160 static int display_mode_bits_per_pixel(CGDisplayModeRef display_mode
)
162 CFStringRef pixel_encoding
;
163 int bits_per_pixel
= 0;
165 pixel_encoding
= CGDisplayModeCopyPixelEncoding(display_mode
);
168 if (CFEqual(pixel_encoding
, CFSTR(kIO32BitFloatPixels
)))
169 bits_per_pixel
= 128;
170 else if (CFEqual(pixel_encoding
, CFSTR(kIO16BitFloatPixels
)))
172 else if (CFEqual(pixel_encoding
, CFSTR(kIO64BitDirectPixels
)))
174 else if (CFEqual(pixel_encoding
, CFSTR(kIO30BitDirectPixels
)))
176 else if (CFEqual(pixel_encoding
, CFSTR(IO32BitDirectPixels
)))
178 else if (CFEqual(pixel_encoding
, CFSTR(IO16BitDirectPixels
)))
180 else if (CFEqual(pixel_encoding
, CFSTR(IO8BitIndexedPixels
)))
182 else if (CFEqual(pixel_encoding
, CFSTR(IO4BitIndexedPixels
)))
184 else if (CFEqual(pixel_encoding
, CFSTR(IO2BitIndexedPixels
)))
186 else if (CFEqual(pixel_encoding
, CFSTR(IO1BitIndexedPixels
)))
189 CFRelease(pixel_encoding
);
192 return bits_per_pixel
;
196 static int get_default_bpp(void)
200 EnterCriticalSection(&modes_section
);
202 if (!default_mode_bpp
)
204 CGDisplayModeRef mode
= CGDisplayCopyDisplayMode(kCGDirectMainDisplay
);
207 default_mode_bpp
= display_mode_bits_per_pixel(mode
);
211 if (!default_mode_bpp
)
212 default_mode_bpp
= 32;
215 ret
= default_mode_bpp
;
217 LeaveCriticalSection(&modes_section
);
219 TRACE(" -> %d\n", ret
);
224 /***********************************************************************
225 * ChangeDisplaySettingsEx (MACDRV.@)
228 LONG CDECL
macdrv_ChangeDisplaySettingsEx(LPCWSTR devname
, LPDEVMODEW devmode
,
229 HWND hwnd
, DWORD flags
, LPVOID lpvoid
)
231 LONG ret
= DISP_CHANGE_BADMODE
;
234 BOOL def_mode
= TRUE
;
235 struct macdrv_display
*displays
;
237 CFArrayRef display_modes
;
238 CFIndex count
, i
, safe
, best
;
239 CGDisplayModeRef best_display_mode
;
240 uint32_t best_io_flags
;
242 TRACE("%s %p %p 0x%08x %p\n", debugstr_w(devname
), devmode
, hwnd
, flags
, lpvoid
);
246 /* this is the minimal dmSize that XP accepts */
247 if (devmode
->dmSize
< FIELD_OFFSET(DEVMODEW
, dmFields
))
248 return DISP_CHANGE_FAILED
;
250 if (devmode
->dmSize
>= FIELD_OFFSET(DEVMODEW
, dmFields
) + sizeof(devmode
->dmFields
))
252 if (((devmode
->dmFields
& DM_BITSPERPEL
) && devmode
->dmBitsPerPel
) ||
253 ((devmode
->dmFields
& DM_PELSWIDTH
) && devmode
->dmPelsWidth
) ||
254 ((devmode
->dmFields
& DM_PELSHEIGHT
) && devmode
->dmPelsHeight
) ||
255 ((devmode
->dmFields
& DM_DISPLAYFREQUENCY
) && devmode
->dmDisplayFrequency
))
262 if (!macdrv_EnumDisplaySettingsEx(devname
, ENUM_REGISTRY_SETTINGS
, &dm
, 0))
264 ERR("Default mode not found!\n");
265 return DISP_CHANGE_BADMODE
;
268 TRACE("Return to original display mode\n");
272 if ((devmode
->dmFields
& (DM_PELSWIDTH
| DM_PELSHEIGHT
)) != (DM_PELSWIDTH
| DM_PELSHEIGHT
))
274 WARN("devmode doesn't specify the resolution: %04x\n", devmode
->dmFields
);
275 return DISP_CHANGE_BADMODE
;
278 if (macdrv_get_displays(&displays
, &num_displays
))
279 return DISP_CHANGE_FAILED
;
281 display_modes
= CGDisplayCopyAllDisplayModes(displays
[0].displayID
, NULL
);
284 macdrv_free_displays(displays
);
285 return DISP_CHANGE_FAILED
;
288 bpp
= get_default_bpp();
289 if ((devmode
->dmFields
& DM_BITSPERPEL
) && devmode
->dmBitsPerPel
!= bpp
)
290 TRACE("using default %d bpp instead of caller's request %d bpp\n", bpp
, devmode
->dmBitsPerPel
);
292 TRACE("looking for %dx%dx%dbpp @%d Hz",
293 (devmode
->dmFields
& DM_PELSWIDTH
? devmode
->dmPelsWidth
: 0),
294 (devmode
->dmFields
& DM_PELSHEIGHT
? devmode
->dmPelsHeight
: 0),
296 (devmode
->dmFields
& DM_DISPLAYFREQUENCY
? devmode
->dmDisplayFrequency
: 0));
297 if (devmode
->dmFields
& DM_DISPLAYFIXEDOUTPUT
)
298 TRACE(" %sstretched", devmode
->dmDisplayFixedOutput
== DMDFO_STRETCH
? "" : "un");
299 if (devmode
->dmFields
& DM_DISPLAYFLAGS
)
300 TRACE(" %sinterlaced", devmode
->dmDisplayFlags
& DM_INTERLACED
? "" : "non-");
304 best_display_mode
= NULL
;
305 count
= CFArrayGetCount(display_modes
);
306 for (i
= 0; i
< count
; i
++)
308 CGDisplayModeRef display_mode
= (CGDisplayModeRef
)CFArrayGetValueAtIndex(display_modes
, i
);
309 uint32_t io_flags
= CGDisplayModeGetIOFlags(display_mode
);
310 int mode_bpp
= display_mode_bits_per_pixel(display_mode
);
311 size_t width
= CGDisplayModeGetWidth(display_mode
);
312 size_t height
= CGDisplayModeGetHeight(display_mode
);
314 if (!(io_flags
& kDisplayModeValidFlag
) || !(io_flags
& kDisplayModeSafeFlag
))
322 if (devmode
->dmFields
& DM_PELSWIDTH
)
324 if (devmode
->dmPelsWidth
!= width
)
327 if (devmode
->dmFields
& DM_PELSHEIGHT
)
329 if (devmode
->dmPelsHeight
!= height
)
332 if ((devmode
->dmFields
& DM_DISPLAYFREQUENCY
) && devmode
->dmDisplayFrequency
!= 0)
334 double refresh_rate
= CGDisplayModeGetRefreshRate(display_mode
);
337 if (devmode
->dmDisplayFrequency
!= (DWORD
)refresh_rate
)
340 if (devmode
->dmFields
& DM_DISPLAYFLAGS
)
342 if (!(devmode
->dmDisplayFlags
& DM_INTERLACED
) != !(io_flags
& kDisplayModeInterlacedFlag
))
345 else if (best_display_mode
)
347 if (io_flags
& kDisplayModeInterlacedFlag
&& !(best_io_flags
& kDisplayModeInterlacedFlag
))
349 else if (!(io_flags
& kDisplayModeInterlacedFlag
) && best_io_flags
& kDisplayModeInterlacedFlag
)
352 if (devmode
->dmFields
& DM_DISPLAYFIXEDOUTPUT
)
354 if (!(devmode
->dmDisplayFixedOutput
== DMDFO_STRETCH
) != !(io_flags
& kDisplayModeStretchedFlag
))
357 else if (best_display_mode
)
359 if (io_flags
& kDisplayModeStretchedFlag
&& !(best_io_flags
& kDisplayModeStretchedFlag
))
361 else if (!(io_flags
& kDisplayModeStretchedFlag
) && best_io_flags
& kDisplayModeStretchedFlag
)
365 if (best_display_mode
)
369 best_display_mode
= display_mode
;
371 best_io_flags
= io_flags
;
374 if (best_display_mode
)
376 /* we have a valid mode */
377 TRACE("Requested display settings match mode %ld\n", best
);
379 if ((flags
& CDS_UPDATEREGISTRY
) && !write_registry_settings(devmode
))
381 WARN("Failed to update registry\n");
382 ret
= DISP_CHANGE_NOTUPDATED
;
384 else if (flags
& (CDS_TEST
| CDS_NORESET
))
385 ret
= DISP_CHANGE_SUCCESSFUL
;
386 else if (macdrv_set_display_mode(&displays
[0], best_display_mode
))
388 int mode_bpp
= display_mode_bits_per_pixel(best_display_mode
);
389 size_t width
= CGDisplayModeGetWidth(best_display_mode
);
390 size_t height
= CGDisplayModeGetHeight(best_display_mode
);
392 SendMessageW(GetDesktopWindow(), WM_MACDRV_UPDATE_DESKTOP_RECT
, mode_bpp
,
393 MAKELPARAM(width
, height
));
394 ret
= DISP_CHANGE_SUCCESSFUL
;
398 WARN("Failed to set display mode\n");
399 ret
= DISP_CHANGE_FAILED
;
404 /* no valid modes found */
405 ERR("No matching mode found %ux%ux%d @%u!\n", devmode
->dmPelsWidth
, devmode
->dmPelsHeight
,
406 bpp
, devmode
->dmDisplayFrequency
);
409 CFRelease(display_modes
);
410 macdrv_free_displays(displays
);
416 /***********************************************************************
417 * EnumDisplayMonitors (MACDRV.@)
419 BOOL CDECL
macdrv_EnumDisplayMonitors(HDC hdc
, LPRECT rect
, MONITORENUMPROC proc
, LPARAM lparam
)
421 struct macdrv_display
*displays
;
426 TRACE("%p, %s, %p, %#lx\n", hdc
, wine_dbgstr_rect(rect
), proc
, lparam
);
433 if (!GetDCOrgEx(hdc
, &origin
)) return FALSE
;
434 if (GetClipBox(hdc
, &limit
) == ERROR
) return FALSE
;
436 if (rect
&& !IntersectRect(&limit
, &limit
, rect
)) return TRUE
;
438 if (macdrv_get_displays(&displays
, &num_displays
))
441 for (i
= 0; i
< num_displays
; i
++)
443 RECT monrect
= rect_from_cgrect(displays
[i
].frame
);
444 OffsetRect(&monrect
, -origin
.x
, -origin
.y
);
445 if (IntersectRect(&monrect
, &monrect
, &limit
))
447 HMONITOR monitor
= display_id_to_monitor(displays
[i
].displayID
);
448 TRACE("monitor %d handle %p @ %s\n", i
, monitor
, wine_dbgstr_rect(&monrect
));
449 if (!proc(monitor
, hdc
, &monrect
, lparam
))
459 if (macdrv_get_displays(&displays
, &num_displays
))
462 for (i
= 0; i
< num_displays
; i
++)
464 RECT monrect
= rect_from_cgrect(displays
[i
].frame
);
466 if (!rect
|| IntersectRect(&unused
, &monrect
, rect
))
468 HMONITOR monitor
= display_id_to_monitor(displays
[i
].displayID
);
469 TRACE("monitor %d handle %p @ %s\n", i
, monitor
, wine_dbgstr_rect(&monrect
));
470 if (!proc(monitor
, 0, &monrect
, lparam
))
479 macdrv_free_displays(displays
);
485 /***********************************************************************
486 * EnumDisplaySettingsEx (MACDRV.@)
489 BOOL CDECL
macdrv_EnumDisplaySettingsEx(LPCWSTR devname
, DWORD mode
,
490 LPDEVMODEW devmode
, DWORD flags
)
492 static const WCHAR dev_name
[CCHDEVICENAME
] =
493 { 'W','i','n','e',' ','M','a','c',' ','d','r','i','v','e','r',0 };
494 struct macdrv_display
*displays
= NULL
;
496 CGDisplayModeRef display_mode
;
497 int display_mode_bpp
;
498 BOOL synthesized
= FALSE
;
502 TRACE("%s, %u, %p + %hu, %08x\n", debugstr_w(devname
), mode
, devmode
, devmode
->dmSize
, flags
);
504 memcpy(devmode
->dmDeviceName
, dev_name
, sizeof(dev_name
));
505 devmode
->dmSpecVersion
= DM_SPECVERSION
;
506 devmode
->dmDriverVersion
= DM_SPECVERSION
;
507 devmode
->dmSize
= FIELD_OFFSET(DEVMODEW
, dmICMMethod
);
508 devmode
->dmDriverExtra
= 0;
509 memset(&devmode
->dmFields
, 0, devmode
->dmSize
- FIELD_OFFSET(DEVMODEW
, dmFields
));
511 if (mode
== ENUM_REGISTRY_SETTINGS
)
513 TRACE("mode %d (registry) -- getting default mode\n", mode
);
514 return read_registry_settings(devmode
);
517 if (macdrv_get_displays(&displays
, &num_displays
))
520 if (mode
== ENUM_CURRENT_SETTINGS
)
522 TRACE("mode %d (current) -- getting current mode\n", mode
);
523 display_mode
= CGDisplayCopyDisplayMode(displays
[0].displayID
);
524 display_mode_bpp
= display_mode_bits_per_pixel(display_mode
);
530 EnterCriticalSection(&modes_section
);
532 if (mode
== 0 || !modes
)
534 if (modes
) CFRelease(modes
);
535 modes
= CGDisplayCopyAllDisplayModes(displays
[0].displayID
, NULL
);
536 modes_has_8bpp
= modes_has_16bpp
= FALSE
;
540 count
= CFArrayGetCount(modes
);
541 for (i
= 0; i
< count
&& !(modes_has_8bpp
&& modes_has_16bpp
); i
++)
543 CGDisplayModeRef mode
= (CGDisplayModeRef
)CFArrayGetValueAtIndex(modes
, i
);
544 int bpp
= display_mode_bits_per_pixel(mode
);
546 modes_has_8bpp
= TRUE
;
548 modes_has_16bpp
= TRUE
;
556 int default_bpp
= get_default_bpp();
557 DWORD seen_modes
= 0;
559 count
= CFArrayGetCount(modes
);
560 for (i
= 0; i
< count
; i
++)
562 CGDisplayModeRef candidate
= (CGDisplayModeRef
)CFArrayGetValueAtIndex(modes
, i
);
564 io_flags
= CGDisplayModeGetIOFlags(candidate
);
565 if (!(flags
& EDS_RAWMODE
) &&
566 (!(io_flags
& kDisplayModeValidFlag
) || !(io_flags
& kDisplayModeSafeFlag
)))
570 if (seen_modes
> mode
)
572 display_mode
= (CGDisplayModeRef
)CFRetain(candidate
);
573 display_mode_bpp
= display_mode_bits_per_pixel(display_mode
);
577 /* We only synthesize modes from those having the default bpp. */
578 if (display_mode_bits_per_pixel(candidate
) != default_bpp
)
584 if (seen_modes
> mode
)
586 display_mode
= (CGDisplayModeRef
)CFRetain(candidate
);
587 display_mode_bpp
= 8;
593 if (!modes_has_16bpp
)
596 if (seen_modes
> mode
)
598 display_mode
= (CGDisplayModeRef
)CFRetain(candidate
);
599 display_mode_bpp
= 16;
607 LeaveCriticalSection(&modes_section
);
613 /* We currently only report modes for the primary display, so it's at (0, 0). */
614 devmode
->dmPosition
.x
= 0;
615 devmode
->dmPosition
.y
= 0;
616 devmode
->dmFields
|= DM_POSITION
;
618 rotation
= CGDisplayRotation(displays
[0].displayID
);
619 devmode
->dmDisplayOrientation
= ((int)((rotation
/ 90) + 0.5)) % 4;
620 devmode
->dmFields
|= DM_DISPLAYORIENTATION
;
622 io_flags
= CGDisplayModeGetIOFlags(display_mode
);
623 if (io_flags
& kDisplayModeStretchedFlag
)
624 devmode
->dmDisplayFixedOutput
= DMDFO_STRETCH
;
626 devmode
->dmDisplayFixedOutput
= DMDFO_CENTER
;
627 devmode
->dmFields
|= DM_DISPLAYFIXEDOUTPUT
;
629 devmode
->dmBitsPerPel
= display_mode_bpp
;
630 if (devmode
->dmBitsPerPel
)
631 devmode
->dmFields
|= DM_BITSPERPEL
;
633 devmode
->dmPelsWidth
= CGDisplayModeGetWidth(display_mode
);
634 devmode
->dmPelsHeight
= CGDisplayModeGetHeight(display_mode
);
635 devmode
->dmFields
|= DM_PELSWIDTH
| DM_PELSHEIGHT
;
637 devmode
->dmDisplayFlags
= 0;
638 if (io_flags
& kDisplayModeInterlacedFlag
)
639 devmode
->dmDisplayFlags
|= DM_INTERLACED
;
640 devmode
->dmFields
|= DM_DISPLAYFLAGS
;
642 devmode
->dmDisplayFrequency
= CGDisplayModeGetRefreshRate(display_mode
);
643 if (!devmode
->dmDisplayFrequency
)
644 devmode
->dmDisplayFrequency
= 60;
645 devmode
->dmFields
|= DM_DISPLAYFREQUENCY
;
647 CFRelease(display_mode
);
648 macdrv_free_displays(displays
);
650 TRACE("mode %d -- %dx%dx%dbpp @%d Hz", mode
,
651 devmode
->dmPelsWidth
, devmode
->dmPelsHeight
, devmode
->dmBitsPerPel
,
652 devmode
->dmDisplayFrequency
);
653 if (devmode
->dmDisplayOrientation
)
654 TRACE(" rotated %u degrees", devmode
->dmDisplayOrientation
* 90);
655 if (devmode
->dmDisplayFixedOutput
== DMDFO_STRETCH
)
657 if (devmode
->dmDisplayFlags
& DM_INTERLACED
)
658 TRACE(" interlaced");
660 TRACE(" (synthesized)");
666 TRACE("mode %d -- not present\n", mode
);
667 if (displays
) macdrv_free_displays(displays
);
668 SetLastError(ERROR_NO_MORE_FILES
);
673 /***********************************************************************
674 * GetDeviceGammaRamp (MACDRV.@)
676 BOOL
macdrv_GetDeviceGammaRamp(PHYSDEV dev
, LPVOID ramp
)
679 DDGAMMARAMP
*r
= ramp
;
680 struct macdrv_display
*displays
;
682 uint32_t mac_entries
;
683 int win_entries
= sizeof(r
->red
) / sizeof(r
->red
[0]);
684 CGGammaValue
*red
, *green
, *blue
;
688 TRACE("dev %p ramp %p\n", dev
, ramp
);
690 if (macdrv_get_displays(&displays
, &num_displays
))
692 WARN("failed to get Mac displays\n");
696 mac_entries
= CGDisplayGammaTableCapacity(displays
[0].displayID
);
697 red
= HeapAlloc(GetProcessHeap(), 0, mac_entries
* sizeof(red
[0]) * 3);
700 green
= red
+ mac_entries
;
701 blue
= green
+ mac_entries
;
703 err
= CGGetDisplayTransferByTable(displays
[0].displayID
, mac_entries
, red
, green
,
705 if (err
!= kCGErrorSuccess
)
707 WARN("failed to get Mac gamma table: %d\n", err
);
711 if (mac_entries
== win_entries
)
713 for (win_entry
= 0; win_entry
< win_entries
; win_entry
++)
715 r
->red
[win_entry
] = red
[win_entry
] * 65535 + 0.5;
716 r
->green
[win_entry
] = green
[win_entry
] * 65535 + 0.5;
717 r
->blue
[win_entry
] = blue
[win_entry
] * 65535 + 0.5;
722 for (win_entry
= 0; win_entry
< win_entries
; win_entry
++)
724 double mac_pos
= win_entry
* (mac_entries
- 1) / (double)(win_entries
- 1);
725 int mac_entry
= mac_pos
;
726 double red_value
, green_value
, blue_value
;
728 if (mac_entry
== mac_entries
- 1)
730 red_value
= red
[mac_entry
];
731 green_value
= green
[mac_entry
];
732 blue_value
= blue
[mac_entry
];
736 double distance
= mac_pos
- mac_entry
;
738 red_value
= red
[mac_entry
] * (1 - distance
) + red
[mac_entry
+ 1] * distance
;
739 green_value
= green
[mac_entry
] * (1 - distance
) + green
[mac_entry
+ 1] * distance
;
740 blue_value
= blue
[mac_entry
] * (1 - distance
) + blue
[mac_entry
+ 1] * distance
;
743 r
->red
[win_entry
] = red_value
* 65535 + 0.5;
744 r
->green
[win_entry
] = green_value
* 65535 + 0.5;
745 r
->blue
[win_entry
] = blue_value
* 65535 + 0.5;
752 HeapFree(GetProcessHeap(), 0, red
);
753 macdrv_free_displays(displays
);
758 /***********************************************************************
759 * GetMonitorInfo (MACDRV.@)
761 BOOL CDECL
macdrv_GetMonitorInfo(HMONITOR monitor
, LPMONITORINFO info
)
763 static const WCHAR adapter_name
[] = { '\\','\\','.','\\','D','I','S','P','L','A','Y','1',0 };
764 struct macdrv_display
*displays
;
766 CGDirectDisplayID display_id
;
769 TRACE("%p, %p\n", monitor
, info
);
771 if (macdrv_get_displays(&displays
, &num_displays
))
773 ERR("couldn't get display list\n");
774 SetLastError(ERROR_GEN_FAILURE
);
778 display_id
= monitor_to_display_id(monitor
);
779 for (i
= 0; i
< num_displays
; i
++)
781 if (displays
[i
].displayID
== display_id
)
785 if (i
< num_displays
)
787 info
->rcMonitor
= rect_from_cgrect(displays
[i
].frame
);
788 info
->rcWork
= rect_from_cgrect(displays
[i
].work_frame
);
790 info
->dwFlags
= (i
== 0) ? MONITORINFOF_PRIMARY
: 0;
792 if (info
->cbSize
>= sizeof(MONITORINFOEXW
))
793 lstrcpyW(((MONITORINFOEXW
*)info
)->szDevice
, adapter_name
);
795 TRACE(" -> rcMonitor %s rcWork %s dwFlags %08x\n", wine_dbgstr_rect(&info
->rcMonitor
),
796 wine_dbgstr_rect(&info
->rcWork
), info
->dwFlags
);
800 ERR("invalid monitor handle\n");
801 SetLastError(ERROR_INVALID_HANDLE
);
804 macdrv_free_displays(displays
);
805 return (i
< num_displays
);
809 /***********************************************************************
810 * SetDeviceGammaRamp (MACDRV.@)
812 BOOL
macdrv_SetDeviceGammaRamp(PHYSDEV dev
, LPVOID ramp
)
814 DDGAMMARAMP
*r
= ramp
;
815 struct macdrv_display
*displays
;
817 int win_entries
= sizeof(r
->red
) / sizeof(r
->red
[0]);
818 CGGammaValue
*red
, *green
, *blue
;
820 CGError err
= kCGErrorFailure
;
822 TRACE("dev %p ramp %p\n", dev
, ramp
);
824 if (!allow_set_gamma
)
826 TRACE("disallowed by registry setting\n");
830 if (macdrv_get_displays(&displays
, &num_displays
))
832 WARN("failed to get Mac displays\n");
836 red
= HeapAlloc(GetProcessHeap(), 0, win_entries
* sizeof(red
[0]) * 3);
839 green
= red
+ win_entries
;
840 blue
= green
+ win_entries
;
842 for (i
= 0; i
< win_entries
; i
++)
844 red
[i
] = r
->red
[i
] / 65535.0;
845 green
[i
] = r
->green
[i
] / 65535.0;
846 blue
[i
] = r
->blue
[i
] / 65535.0;
849 err
= CGSetDisplayTransferByTable(displays
[0].displayID
, win_entries
, red
, green
, blue
);
850 if (err
!= kCGErrorSuccess
)
851 WARN("failed to set display gamma table: %d\n", err
);
854 HeapFree(GetProcessHeap(), 0, red
);
855 macdrv_free_displays(displays
);
856 return (err
== kCGErrorSuccess
);
860 /***********************************************************************
861 * macdrv_displays_changed
863 * Handler for DISPLAYS_CHANGED events.
865 void macdrv_displays_changed(const macdrv_event
*event
)
867 HWND hwnd
= GetDesktopWindow();
869 /* A system display change will get delivered to all GUI-attached threads,
870 so the desktop-window-owning thread will get it and all others should
871 ignore it. A synthesized display change event due to activation
872 will only get delivered to the activated process. So, it needs to
873 process it (by sending it to the desktop window). */
874 if (event
->displays_changed
.activating
||
875 GetWindowThreadProcessId(hwnd
, NULL
) == GetCurrentThreadId())
877 CGDirectDisplayID mainDisplay
= CGMainDisplayID();
878 CGDisplayModeRef mode
= CGDisplayCopyDisplayMode(mainDisplay
);
879 size_t width
= CGDisplayModeGetWidth(mode
);
880 size_t height
= CGDisplayModeGetHeight(mode
);
881 int mode_bpp
= display_mode_bits_per_pixel(mode
);
883 CGDisplayModeRelease(mode
);
884 SendMessageW(hwnd
, WM_MACDRV_UPDATE_DESKTOP_RECT
, mode_bpp
,
885 MAKELPARAM(width
, height
));