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
;
240 TRACE("%s %p %p 0x%08x %p\n", debugstr_w(devname
), devmode
, hwnd
, flags
, lpvoid
);
244 /* this is the minimal dmSize that XP accepts */
245 if (devmode
->dmSize
< FIELD_OFFSET(DEVMODEW
, dmFields
))
246 return DISP_CHANGE_FAILED
;
248 if (devmode
->dmSize
>= FIELD_OFFSET(DEVMODEW
, dmFields
) + sizeof(devmode
->dmFields
))
250 if (((devmode
->dmFields
& DM_BITSPERPEL
) && devmode
->dmBitsPerPel
) ||
251 ((devmode
->dmFields
& DM_PELSWIDTH
) && devmode
->dmPelsWidth
) ||
252 ((devmode
->dmFields
& DM_PELSHEIGHT
) && devmode
->dmPelsHeight
) ||
253 ((devmode
->dmFields
& DM_DISPLAYFREQUENCY
) && devmode
->dmDisplayFrequency
))
260 if (!macdrv_EnumDisplaySettingsEx(devname
, ENUM_REGISTRY_SETTINGS
, &dm
, 0))
262 ERR("Default mode not found!\n");
263 return DISP_CHANGE_BADMODE
;
266 TRACE("Return to original display mode\n");
270 if ((devmode
->dmFields
& (DM_PELSWIDTH
| DM_PELSHEIGHT
)) != (DM_PELSWIDTH
| DM_PELSHEIGHT
))
272 WARN("devmode doesn't specify the resolution: %04x\n", devmode
->dmFields
);
273 return DISP_CHANGE_BADMODE
;
276 if (macdrv_get_displays(&displays
, &num_displays
))
277 return DISP_CHANGE_FAILED
;
279 display_modes
= CGDisplayCopyAllDisplayModes(displays
[0].displayID
, NULL
);
282 macdrv_free_displays(displays
);
283 return DISP_CHANGE_FAILED
;
286 bpp
= get_default_bpp();
287 if ((devmode
->dmFields
& DM_BITSPERPEL
) && devmode
->dmBitsPerPel
!= bpp
)
288 TRACE("using default %d bpp instead of caller's request %d bpp\n", bpp
, devmode
->dmBitsPerPel
);
290 TRACE("looking for %dx%dx%dbpp @%d Hz",
291 (devmode
->dmFields
& DM_PELSWIDTH
? devmode
->dmPelsWidth
: 0),
292 (devmode
->dmFields
& DM_PELSHEIGHT
? devmode
->dmPelsHeight
: 0),
294 (devmode
->dmFields
& DM_DISPLAYFREQUENCY
? devmode
->dmDisplayFrequency
: 0));
295 if (devmode
->dmFields
& DM_DISPLAYFIXEDOUTPUT
)
296 TRACE(" %sstretched", devmode
->dmDisplayFixedOutput
== DMDFO_STRETCH
? "" : "un");
297 if (devmode
->dmFields
& DM_DISPLAYFLAGS
)
298 TRACE(" %sinterlaced", devmode
->dmDisplayFlags
& DM_INTERLACED
? "" : "non-");
302 count
= CFArrayGetCount(display_modes
);
303 for (i
= 0; i
< count
; i
++)
305 CGDisplayModeRef display_mode
= (CGDisplayModeRef
)CFArrayGetValueAtIndex(display_modes
, i
);
306 uint32_t io_flags
= CGDisplayModeGetIOFlags(display_mode
);
307 int mode_bpp
= display_mode_bits_per_pixel(display_mode
);
308 size_t width
= CGDisplayModeGetWidth(display_mode
);
309 size_t height
= CGDisplayModeGetHeight(display_mode
);
311 if (!(io_flags
& kDisplayModeValidFlag
) || !(io_flags
& kDisplayModeSafeFlag
))
319 if (devmode
->dmFields
& DM_PELSWIDTH
)
321 if (devmode
->dmPelsWidth
!= width
)
324 if (devmode
->dmFields
& DM_PELSHEIGHT
)
326 if (devmode
->dmPelsHeight
!= height
)
329 if ((devmode
->dmFields
& DM_DISPLAYFREQUENCY
) && devmode
->dmDisplayFrequency
!= 0)
331 double refresh_rate
= CGDisplayModeGetRefreshRate(display_mode
);
334 if (devmode
->dmDisplayFrequency
!= (DWORD
)refresh_rate
)
337 if (devmode
->dmFields
& DM_DISPLAYFIXEDOUTPUT
)
339 if (!(devmode
->dmDisplayFixedOutput
== DMDFO_STRETCH
) != !(io_flags
& kDisplayModeStretchedFlag
))
342 if (devmode
->dmFields
& DM_DISPLAYFLAGS
)
344 if (!(devmode
->dmDisplayFlags
& DM_INTERLACED
) != !(io_flags
& kDisplayModeInterlacedFlag
))
348 /* we have a valid mode */
349 TRACE("Requested display settings match mode %ld\n", safe
);
351 if ((flags
& CDS_UPDATEREGISTRY
) && !write_registry_settings(devmode
))
353 WARN("Failed to update registry\n");
354 ret
= DISP_CHANGE_NOTUPDATED
;
358 if (flags
& (CDS_TEST
| CDS_NORESET
))
359 ret
= DISP_CHANGE_SUCCESSFUL
;
362 if (macdrv_set_display_mode(&displays
[0], display_mode
))
364 SendMessageW(GetDesktopWindow(), WM_MACDRV_UPDATE_DESKTOP_RECT
, mode_bpp
,
365 MAKELPARAM(width
, height
));
366 ret
= DISP_CHANGE_SUCCESSFUL
;
370 WARN("Failed to set display mode\n");
371 ret
= DISP_CHANGE_FAILED
;
378 CFRelease(display_modes
);
379 macdrv_free_displays(displays
);
383 /* no valid modes found */
384 ERR("No matching mode found %ux%ux%d @%u!\n", devmode
->dmPelsWidth
, devmode
->dmPelsHeight
,
385 bpp
, devmode
->dmDisplayFrequency
);
392 /***********************************************************************
393 * EnumDisplayMonitors (MACDRV.@)
395 BOOL CDECL
macdrv_EnumDisplayMonitors(HDC hdc
, LPRECT rect
, MONITORENUMPROC proc
, LPARAM lparam
)
397 struct macdrv_display
*displays
;
402 TRACE("%p, %s, %p, %#lx\n", hdc
, wine_dbgstr_rect(rect
), proc
, lparam
);
409 if (!GetDCOrgEx(hdc
, &origin
)) return FALSE
;
410 if (GetClipBox(hdc
, &limit
) == ERROR
) return FALSE
;
412 if (rect
&& !IntersectRect(&limit
, &limit
, rect
)) return TRUE
;
414 if (macdrv_get_displays(&displays
, &num_displays
))
417 for (i
= 0; i
< num_displays
; i
++)
419 RECT monrect
= rect_from_cgrect(displays
[i
].frame
);
420 OffsetRect(&monrect
, -origin
.x
, -origin
.y
);
421 if (IntersectRect(&monrect
, &monrect
, &limit
))
423 HMONITOR monitor
= display_id_to_monitor(displays
[i
].displayID
);
424 TRACE("monitor %d handle %p @ %s\n", i
, monitor
, wine_dbgstr_rect(&monrect
));
425 if (!proc(monitor
, hdc
, &monrect
, lparam
))
435 if (macdrv_get_displays(&displays
, &num_displays
))
438 for (i
= 0; i
< num_displays
; i
++)
440 RECT monrect
= rect_from_cgrect(displays
[i
].frame
);
442 if (!rect
|| IntersectRect(&unused
, &monrect
, rect
))
444 HMONITOR monitor
= display_id_to_monitor(displays
[i
].displayID
);
445 TRACE("monitor %d handle %p @ %s\n", i
, monitor
, wine_dbgstr_rect(&monrect
));
446 if (!proc(monitor
, 0, &monrect
, lparam
))
455 macdrv_free_displays(displays
);
461 /***********************************************************************
462 * EnumDisplaySettingsEx (MACDRV.@)
465 BOOL CDECL
macdrv_EnumDisplaySettingsEx(LPCWSTR devname
, DWORD mode
,
466 LPDEVMODEW devmode
, DWORD flags
)
468 static const WCHAR dev_name
[CCHDEVICENAME
] =
469 { 'W','i','n','e',' ','M','a','c',' ','d','r','i','v','e','r',0 };
470 struct macdrv_display
*displays
= NULL
;
472 CGDisplayModeRef display_mode
;
473 int display_mode_bpp
;
474 BOOL synthesized
= FALSE
;
478 TRACE("%s, %u, %p + %hu, %08x\n", debugstr_w(devname
), mode
, devmode
, devmode
->dmSize
, flags
);
480 memcpy(devmode
->dmDeviceName
, dev_name
, sizeof(dev_name
));
481 devmode
->dmSpecVersion
= DM_SPECVERSION
;
482 devmode
->dmDriverVersion
= DM_SPECVERSION
;
483 devmode
->dmSize
= FIELD_OFFSET(DEVMODEW
, dmICMMethod
);
484 devmode
->dmDriverExtra
= 0;
485 memset(&devmode
->dmFields
, 0, devmode
->dmSize
- FIELD_OFFSET(DEVMODEW
, dmFields
));
487 if (mode
== ENUM_REGISTRY_SETTINGS
)
489 TRACE("mode %d (registry) -- getting default mode\n", mode
);
490 return read_registry_settings(devmode
);
493 if (macdrv_get_displays(&displays
, &num_displays
))
496 if (mode
== ENUM_CURRENT_SETTINGS
)
498 TRACE("mode %d (current) -- getting current mode\n", mode
);
499 display_mode
= CGDisplayCopyDisplayMode(displays
[0].displayID
);
500 display_mode_bpp
= display_mode_bits_per_pixel(display_mode
);
506 EnterCriticalSection(&modes_section
);
508 if (mode
== 0 || !modes
)
510 if (modes
) CFRelease(modes
);
511 modes
= CGDisplayCopyAllDisplayModes(displays
[0].displayID
, NULL
);
512 modes_has_8bpp
= modes_has_16bpp
= FALSE
;
516 count
= CFArrayGetCount(modes
);
517 for (i
= 0; i
< count
&& !(modes_has_8bpp
&& modes_has_16bpp
); i
++)
519 CGDisplayModeRef mode
= (CGDisplayModeRef
)CFArrayGetValueAtIndex(modes
, i
);
520 int bpp
= display_mode_bits_per_pixel(mode
);
522 modes_has_8bpp
= TRUE
;
524 modes_has_16bpp
= TRUE
;
532 int default_bpp
= get_default_bpp();
533 DWORD seen_modes
= 0;
535 count
= CFArrayGetCount(modes
);
536 for (i
= 0; i
< count
; i
++)
538 CGDisplayModeRef candidate
= (CGDisplayModeRef
)CFArrayGetValueAtIndex(modes
, i
);
540 io_flags
= CGDisplayModeGetIOFlags(candidate
);
541 if (!(flags
& EDS_RAWMODE
) &&
542 (!(io_flags
& kDisplayModeValidFlag
) || !(io_flags
& kDisplayModeSafeFlag
)))
546 if (seen_modes
> mode
)
548 display_mode
= (CGDisplayModeRef
)CFRetain(candidate
);
549 display_mode_bpp
= display_mode_bits_per_pixel(display_mode
);
553 /* We only synthesize modes from those having the default bpp. */
554 if (display_mode_bits_per_pixel(candidate
) != default_bpp
)
560 if (seen_modes
> mode
)
562 display_mode
= (CGDisplayModeRef
)CFRetain(candidate
);
563 display_mode_bpp
= 8;
569 if (!modes_has_16bpp
)
572 if (seen_modes
> mode
)
574 display_mode
= (CGDisplayModeRef
)CFRetain(candidate
);
575 display_mode_bpp
= 16;
583 LeaveCriticalSection(&modes_section
);
589 /* We currently only report modes for the primary display, so it's at (0, 0). */
590 devmode
->dmPosition
.x
= 0;
591 devmode
->dmPosition
.y
= 0;
592 devmode
->dmFields
|= DM_POSITION
;
594 rotation
= CGDisplayRotation(displays
[0].displayID
);
595 devmode
->dmDisplayOrientation
= ((int)((rotation
/ 90) + 0.5)) % 4;
596 devmode
->dmFields
|= DM_DISPLAYORIENTATION
;
598 io_flags
= CGDisplayModeGetIOFlags(display_mode
);
599 if (io_flags
& kDisplayModeStretchedFlag
)
600 devmode
->dmDisplayFixedOutput
= DMDFO_STRETCH
;
602 devmode
->dmDisplayFixedOutput
= DMDFO_CENTER
;
603 devmode
->dmFields
|= DM_DISPLAYFIXEDOUTPUT
;
605 devmode
->dmBitsPerPel
= display_mode_bpp
;
606 if (devmode
->dmBitsPerPel
)
607 devmode
->dmFields
|= DM_BITSPERPEL
;
609 devmode
->dmPelsWidth
= CGDisplayModeGetWidth(display_mode
);
610 devmode
->dmPelsHeight
= CGDisplayModeGetHeight(display_mode
);
611 devmode
->dmFields
|= DM_PELSWIDTH
| DM_PELSHEIGHT
;
613 devmode
->dmDisplayFlags
= 0;
614 if (io_flags
& kDisplayModeInterlacedFlag
)
615 devmode
->dmDisplayFlags
|= DM_INTERLACED
;
616 devmode
->dmFields
|= DM_DISPLAYFLAGS
;
618 devmode
->dmDisplayFrequency
= CGDisplayModeGetRefreshRate(display_mode
);
619 if (!devmode
->dmDisplayFrequency
)
620 devmode
->dmDisplayFrequency
= 60;
621 devmode
->dmFields
|= DM_DISPLAYFREQUENCY
;
623 CFRelease(display_mode
);
624 macdrv_free_displays(displays
);
626 TRACE("mode %d -- %dx%dx%dbpp @%d Hz", mode
,
627 devmode
->dmPelsWidth
, devmode
->dmPelsHeight
, devmode
->dmBitsPerPel
,
628 devmode
->dmDisplayFrequency
);
629 if (devmode
->dmDisplayOrientation
)
630 TRACE(" rotated %u degrees", devmode
->dmDisplayOrientation
* 90);
631 if (devmode
->dmDisplayFixedOutput
== DMDFO_STRETCH
)
633 if (devmode
->dmDisplayFlags
& DM_INTERLACED
)
634 TRACE(" interlaced");
636 TRACE(" (synthesized)");
642 TRACE("mode %d -- not present\n", mode
);
643 if (displays
) macdrv_free_displays(displays
);
644 SetLastError(ERROR_NO_MORE_FILES
);
649 /***********************************************************************
650 * GetDeviceGammaRamp (MACDRV.@)
652 BOOL
macdrv_GetDeviceGammaRamp(PHYSDEV dev
, LPVOID ramp
)
655 DDGAMMARAMP
*r
= ramp
;
656 struct macdrv_display
*displays
;
658 uint32_t mac_entries
;
659 int win_entries
= sizeof(r
->red
) / sizeof(r
->red
[0]);
660 CGGammaValue
*red
, *green
, *blue
;
664 TRACE("dev %p ramp %p\n", dev
, ramp
);
666 if (macdrv_get_displays(&displays
, &num_displays
))
668 WARN("failed to get Mac displays\n");
672 mac_entries
= CGDisplayGammaTableCapacity(displays
[0].displayID
);
673 red
= HeapAlloc(GetProcessHeap(), 0, mac_entries
* sizeof(red
[0]) * 3);
676 green
= red
+ mac_entries
;
677 blue
= green
+ mac_entries
;
679 err
= CGGetDisplayTransferByTable(displays
[0].displayID
, mac_entries
, red
, green
,
681 if (err
!= kCGErrorSuccess
)
683 WARN("failed to get Mac gamma table: %d\n", err
);
687 if (mac_entries
== win_entries
)
689 for (win_entry
= 0; win_entry
< win_entries
; win_entry
++)
691 r
->red
[win_entry
] = red
[win_entry
] * 65535 + 0.5;
692 r
->green
[win_entry
] = green
[win_entry
] * 65535 + 0.5;
693 r
->blue
[win_entry
] = blue
[win_entry
] * 65535 + 0.5;
698 for (win_entry
= 0; win_entry
< win_entries
; win_entry
++)
700 double mac_pos
= win_entry
* (mac_entries
- 1) / (double)(win_entries
- 1);
701 int mac_entry
= mac_pos
;
702 double red_value
, green_value
, blue_value
;
704 if (mac_entry
== mac_entries
- 1)
706 red_value
= red
[mac_entry
];
707 green_value
= green
[mac_entry
];
708 blue_value
= blue
[mac_entry
];
712 double distance
= mac_pos
- mac_entry
;
714 red_value
= red
[mac_entry
] * (1 - distance
) + red
[mac_entry
+ 1] * distance
;
715 green_value
= green
[mac_entry
] * (1 - distance
) + green
[mac_entry
+ 1] * distance
;
716 blue_value
= blue
[mac_entry
] * (1 - distance
) + blue
[mac_entry
+ 1] * distance
;
719 r
->red
[win_entry
] = red_value
* 65535 + 0.5;
720 r
->green
[win_entry
] = green_value
* 65535 + 0.5;
721 r
->blue
[win_entry
] = blue_value
* 65535 + 0.5;
728 HeapFree(GetProcessHeap(), 0, red
);
729 macdrv_free_displays(displays
);
734 /***********************************************************************
735 * GetMonitorInfo (MACDRV.@)
737 BOOL CDECL
macdrv_GetMonitorInfo(HMONITOR monitor
, LPMONITORINFO info
)
739 static const WCHAR adapter_name
[] = { '\\','\\','.','\\','D','I','S','P','L','A','Y','1',0 };
740 struct macdrv_display
*displays
;
742 CGDirectDisplayID display_id
;
745 TRACE("%p, %p\n", monitor
, info
);
747 if (macdrv_get_displays(&displays
, &num_displays
))
749 ERR("couldn't get display list\n");
750 SetLastError(ERROR_GEN_FAILURE
);
754 display_id
= monitor_to_display_id(monitor
);
755 for (i
= 0; i
< num_displays
; i
++)
757 if (displays
[i
].displayID
== display_id
)
761 if (i
< num_displays
)
763 info
->rcMonitor
= rect_from_cgrect(displays
[i
].frame
);
764 info
->rcWork
= rect_from_cgrect(displays
[i
].work_frame
);
766 info
->dwFlags
= (i
== 0) ? MONITORINFOF_PRIMARY
: 0;
768 if (info
->cbSize
>= sizeof(MONITORINFOEXW
))
769 lstrcpyW(((MONITORINFOEXW
*)info
)->szDevice
, adapter_name
);
771 TRACE(" -> rcMonitor %s rcWork %s dwFlags %08x\n", wine_dbgstr_rect(&info
->rcMonitor
),
772 wine_dbgstr_rect(&info
->rcWork
), info
->dwFlags
);
776 ERR("invalid monitor handle\n");
777 SetLastError(ERROR_INVALID_HANDLE
);
780 macdrv_free_displays(displays
);
781 return (i
< num_displays
);
785 /***********************************************************************
786 * SetDeviceGammaRamp (MACDRV.@)
788 BOOL
macdrv_SetDeviceGammaRamp(PHYSDEV dev
, LPVOID ramp
)
790 DDGAMMARAMP
*r
= ramp
;
791 struct macdrv_display
*displays
;
793 int win_entries
= sizeof(r
->red
) / sizeof(r
->red
[0]);
794 CGGammaValue
*red
, *green
, *blue
;
796 CGError err
= kCGErrorFailure
;
798 TRACE("dev %p ramp %p\n", dev
, ramp
);
800 if (macdrv_get_displays(&displays
, &num_displays
))
802 WARN("failed to get Mac displays\n");
806 red
= HeapAlloc(GetProcessHeap(), 0, win_entries
* sizeof(red
[0]) * 3);
809 green
= red
+ win_entries
;
810 blue
= green
+ win_entries
;
812 for (i
= 0; i
< win_entries
; i
++)
814 red
[i
] = r
->red
[i
] / 65535.0;
815 green
[i
] = r
->green
[i
] / 65535.0;
816 blue
[i
] = r
->blue
[i
] / 65535.0;
819 err
= CGSetDisplayTransferByTable(displays
[0].displayID
, win_entries
, red
, green
, blue
);
820 if (err
!= kCGErrorSuccess
)
821 WARN("failed to set display gamma table: %d\n", err
);
824 HeapFree(GetProcessHeap(), 0, red
);
825 macdrv_free_displays(displays
);
826 return (err
== kCGErrorSuccess
);
830 /***********************************************************************
831 * macdrv_displays_changed
833 * Handler for DISPLAYS_CHANGED events.
835 void macdrv_displays_changed(const macdrv_event
*event
)
837 HWND hwnd
= GetDesktopWindow();
839 /* A system display change will get delivered to all GUI-attached threads,
840 so the desktop-window-owning thread will get it and all others should
841 ignore it. A synthesized display change event due to activation
842 will only get delivered to the activated process. So, it needs to
843 process it (by sending it to the desktop window). */
844 if (event
->displays_changed
.activating
||
845 GetWindowThreadProcessId(hwnd
, NULL
) == GetCurrentThreadId())
847 CGDirectDisplayID mainDisplay
= CGMainDisplayID();
848 CGDisplayModeRef mode
= CGDisplayCopyDisplayMode(mainDisplay
);
849 size_t width
= CGDisplayModeGetWidth(mode
);
850 size_t height
= CGDisplayModeGetHeight(mode
);
851 int mode_bpp
= display_mode_bits_per_pixel(mode
);
853 CGDisplayModeRelease(mode
);
854 SendMessageW(hwnd
, WM_MACDRV_UPDATE_DESKTOP_RECT
, mode_bpp
,
855 MAKELPARAM(width
, height
));