2 * System parameters functions
4 * Copyright 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
38 #include "wine/wingdi16.h"
46 #include "user_private.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(system
);
53 DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_GPU_LUID
, 0xca085853, 0x16ce, 0x48aa, 0xb1, 0x14, 0xde, 0x9c, 0x72, 0x33, 0x42, 0x23, 1);
54 DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_OUTPUT_ID
, 0xca085853, 0x16ce, 0x48aa, 0xb1, 0x14, 0xde, 0x9c, 0x72, 0x33, 0x42, 0x23, 2);
56 /* Wine specific monitor properties */
57 DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_STATEFLAGS
, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 2);
58 DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_ADAPTERNAME
, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 5);
61 static HDC display_dc
;
62 static CRITICAL_SECTION display_dc_section
;
63 static CRITICAL_SECTION_DEBUG critsect_debug
=
65 0, 0, &display_dc_section
,
66 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
67 0, 0, { (DWORD_PTR
)(__FILE__
": display_dc_section") }
69 static CRITICAL_SECTION display_dc_section
= { &critsect_debug
, -1 ,0, 0, 0, 0 };
72 /* System parameters storage */
73 static UINT system_dpi
;
75 static void SYSPARAMS_LogFont32WTo32A( const LOGFONTW
* font32W
, LPLOGFONTA font32A
)
77 font32A
->lfHeight
= font32W
->lfHeight
;
78 font32A
->lfWidth
= font32W
->lfWidth
;
79 font32A
->lfEscapement
= font32W
->lfEscapement
;
80 font32A
->lfOrientation
= font32W
->lfOrientation
;
81 font32A
->lfWeight
= font32W
->lfWeight
;
82 font32A
->lfItalic
= font32W
->lfItalic
;
83 font32A
->lfUnderline
= font32W
->lfUnderline
;
84 font32A
->lfStrikeOut
= font32W
->lfStrikeOut
;
85 font32A
->lfCharSet
= font32W
->lfCharSet
;
86 font32A
->lfOutPrecision
= font32W
->lfOutPrecision
;
87 font32A
->lfClipPrecision
= font32W
->lfClipPrecision
;
88 font32A
->lfQuality
= font32W
->lfQuality
;
89 font32A
->lfPitchAndFamily
= font32W
->lfPitchAndFamily
;
90 WideCharToMultiByte( CP_ACP
, 0, font32W
->lfFaceName
, -1, font32A
->lfFaceName
, LF_FACESIZE
, NULL
, NULL
);
91 font32A
->lfFaceName
[LF_FACESIZE
-1] = 0;
94 static void SYSPARAMS_LogFont32ATo32W( const LOGFONTA
* font32A
, LPLOGFONTW font32W
)
96 font32W
->lfHeight
= font32A
->lfHeight
;
97 font32W
->lfWidth
= font32A
->lfWidth
;
98 font32W
->lfEscapement
= font32A
->lfEscapement
;
99 font32W
->lfOrientation
= font32A
->lfOrientation
;
100 font32W
->lfWeight
= font32A
->lfWeight
;
101 font32W
->lfItalic
= font32A
->lfItalic
;
102 font32W
->lfUnderline
= font32A
->lfUnderline
;
103 font32W
->lfStrikeOut
= font32A
->lfStrikeOut
;
104 font32W
->lfCharSet
= font32A
->lfCharSet
;
105 font32W
->lfOutPrecision
= font32A
->lfOutPrecision
;
106 font32W
->lfClipPrecision
= font32A
->lfClipPrecision
;
107 font32W
->lfQuality
= font32A
->lfQuality
;
108 font32W
->lfPitchAndFamily
= font32A
->lfPitchAndFamily
;
109 MultiByteToWideChar( CP_ACP
, 0, font32A
->lfFaceName
, -1, font32W
->lfFaceName
, LF_FACESIZE
);
110 font32W
->lfFaceName
[LF_FACESIZE
-1] = 0;
113 static void SYSPARAMS_NonClientMetrics32WTo32A( const NONCLIENTMETRICSW
* lpnm32W
, LPNONCLIENTMETRICSA lpnm32A
)
115 lpnm32A
->iBorderWidth
= lpnm32W
->iBorderWidth
;
116 lpnm32A
->iScrollWidth
= lpnm32W
->iScrollWidth
;
117 lpnm32A
->iScrollHeight
= lpnm32W
->iScrollHeight
;
118 lpnm32A
->iCaptionWidth
= lpnm32W
->iCaptionWidth
;
119 lpnm32A
->iCaptionHeight
= lpnm32W
->iCaptionHeight
;
120 SYSPARAMS_LogFont32WTo32A( &lpnm32W
->lfCaptionFont
, &lpnm32A
->lfCaptionFont
);
121 lpnm32A
->iSmCaptionWidth
= lpnm32W
->iSmCaptionWidth
;
122 lpnm32A
->iSmCaptionHeight
= lpnm32W
->iSmCaptionHeight
;
123 SYSPARAMS_LogFont32WTo32A( &lpnm32W
->lfSmCaptionFont
, &lpnm32A
->lfSmCaptionFont
);
124 lpnm32A
->iMenuWidth
= lpnm32W
->iMenuWidth
;
125 lpnm32A
->iMenuHeight
= lpnm32W
->iMenuHeight
;
126 SYSPARAMS_LogFont32WTo32A( &lpnm32W
->lfMenuFont
, &lpnm32A
->lfMenuFont
);
127 SYSPARAMS_LogFont32WTo32A( &lpnm32W
->lfStatusFont
, &lpnm32A
->lfStatusFont
);
128 SYSPARAMS_LogFont32WTo32A( &lpnm32W
->lfMessageFont
, &lpnm32A
->lfMessageFont
);
129 if (lpnm32A
->cbSize
> FIELD_OFFSET(NONCLIENTMETRICSA
, iPaddedBorderWidth
))
131 if (lpnm32W
->cbSize
> FIELD_OFFSET(NONCLIENTMETRICSW
, iPaddedBorderWidth
))
132 lpnm32A
->iPaddedBorderWidth
= lpnm32W
->iPaddedBorderWidth
;
134 lpnm32A
->iPaddedBorderWidth
= 0;
138 static void SYSPARAMS_NonClientMetrics32ATo32W( const NONCLIENTMETRICSA
* lpnm32A
, LPNONCLIENTMETRICSW lpnm32W
)
140 lpnm32W
->iBorderWidth
= lpnm32A
->iBorderWidth
;
141 lpnm32W
->iScrollWidth
= lpnm32A
->iScrollWidth
;
142 lpnm32W
->iScrollHeight
= lpnm32A
->iScrollHeight
;
143 lpnm32W
->iCaptionWidth
= lpnm32A
->iCaptionWidth
;
144 lpnm32W
->iCaptionHeight
= lpnm32A
->iCaptionHeight
;
145 SYSPARAMS_LogFont32ATo32W( &lpnm32A
->lfCaptionFont
, &lpnm32W
->lfCaptionFont
);
146 lpnm32W
->iSmCaptionWidth
= lpnm32A
->iSmCaptionWidth
;
147 lpnm32W
->iSmCaptionHeight
= lpnm32A
->iSmCaptionHeight
;
148 SYSPARAMS_LogFont32ATo32W( &lpnm32A
->lfSmCaptionFont
, &lpnm32W
->lfSmCaptionFont
);
149 lpnm32W
->iMenuWidth
= lpnm32A
->iMenuWidth
;
150 lpnm32W
->iMenuHeight
= lpnm32A
->iMenuHeight
;
151 SYSPARAMS_LogFont32ATo32W( &lpnm32A
->lfMenuFont
, &lpnm32W
->lfMenuFont
);
152 SYSPARAMS_LogFont32ATo32W( &lpnm32A
->lfStatusFont
, &lpnm32W
->lfStatusFont
);
153 SYSPARAMS_LogFont32ATo32W( &lpnm32A
->lfMessageFont
, &lpnm32W
->lfMessageFont
);
154 if (lpnm32W
->cbSize
> FIELD_OFFSET(NONCLIENTMETRICSW
, iPaddedBorderWidth
))
156 if (lpnm32A
->cbSize
> FIELD_OFFSET(NONCLIENTMETRICSA
, iPaddedBorderWidth
))
157 lpnm32W
->iPaddedBorderWidth
= lpnm32A
->iPaddedBorderWidth
;
159 lpnm32W
->iPaddedBorderWidth
= 0;
164 /* Helper functions to retrieve monitors info */
166 static BOOL CALLBACK
get_virtual_screen_proc( HMONITOR monitor
, HDC hdc
, LPRECT rect
, LPARAM lp
)
168 RECT
*virtual_rect
= (RECT
*)lp
;
170 UnionRect( virtual_rect
, virtual_rect
, rect
);
174 RECT
get_virtual_screen_rect(void)
178 NtUserEnumDisplayMonitors( 0, NULL
, get_virtual_screen_proc
, (LPARAM
)&rect
);
182 static BOOL CALLBACK
get_primary_monitor_proc( HMONITOR monitor
, HDC hdc
, LPRECT rect
, LPARAM lp
)
184 RECT
*primary_rect
= (RECT
*)lp
;
186 if (!rect
->top
&& !rect
->left
&& rect
->right
&& rect
->bottom
)
188 *primary_rect
= *rect
;
195 RECT
get_primary_monitor_rect(void)
199 NtUserEnumDisplayMonitors( 0, NULL
, get_primary_monitor_proc
, (LPARAM
)&rect
);
203 HDC
get_display_dc(void)
205 EnterCriticalSection( &display_dc_section
);
210 LeaveCriticalSection( &display_dc_section
);
211 dc
= CreateDCW( L
"DISPLAY", NULL
, NULL
, NULL
);
212 EnterCriticalSection( &display_dc_section
);
221 void release_display_dc( HDC hdc
)
223 LeaveCriticalSection( &display_dc_section
);
226 static HANDLE
get_display_device_init_mutex( void )
228 HANDLE mutex
= CreateMutexW( NULL
, FALSE
, L
"display_device_init" );
230 WaitForSingleObject( mutex
, INFINITE
);
234 static void release_display_device_init_mutex( HANDLE mutex
)
236 ReleaseMutex( mutex
);
237 CloseHandle( mutex
);
240 /* Wait until graphics driver is loaded by explorer */
241 void wait_graphics_driver_ready(void)
243 static BOOL ready
= FALSE
;
247 SendMessageW( GetDesktopWindow(), WM_NULL
, 0, 0 );
252 /***********************************************************************
255 void SYSPARAMS_Init(void)
257 system_dpi
= NtUserGetSystemDpiForProcess( NULL
);
260 static BOOL
update_desktop_wallpaper(void)
264 if (GetWindowThreadProcessId( GetDesktopWindow(), &pid
) && pid
== GetCurrentProcessId())
266 WCHAR wallpaper
[MAX_PATH
], pattern
[256];
268 if (NtUserSystemParametersInfo( SPI_GETDESKWALLPAPER
, ARRAYSIZE(wallpaper
), wallpaper
, 0 ) &&
269 NtUserCallOneParam( (ULONG_PTR
)pattern
, NtUserGetDeskPattern
))
271 update_wallpaper( wallpaper
, pattern
);
274 else SendMessageW( GetDesktopWindow(), WM_SETTINGCHANGE
, SPI_SETDESKWALLPAPER
, 0 );
279 /***********************************************************************
280 * SystemParametersInfoForDpi (USER32.@)
282 BOOL WINAPI
SystemParametersInfoForDpi( UINT action
, UINT val
, PVOID ptr
, UINT winini
, UINT dpi
)
284 BOOL ret
= NtUserSystemParametersInfoForDpi( action
, val
, ptr
, winini
, dpi
);
285 if (ret
&& (action
== SPI_SETDESKWALLPAPER
|| action
== SPI_SETDESKPATTERN
))
286 ret
= update_desktop_wallpaper();
291 /***********************************************************************
292 * SystemParametersInfoW (USER32.@)
294 BOOL WINAPI
SystemParametersInfoW( UINT action
, UINT val
, void *ptr
, UINT winini
)
296 BOOL ret
= NtUserSystemParametersInfo( action
, val
, ptr
, winini
);
297 if (ret
&& (action
== SPI_SETDESKWALLPAPER
|| action
== SPI_SETDESKPATTERN
))
298 ret
= update_desktop_wallpaper();
303 /***********************************************************************
304 * SystemParametersInfoA (USER32.@)
306 BOOL WINAPI
SystemParametersInfoA( UINT uiAction
, UINT uiParam
,
307 PVOID pvParam
, UINT fuWinIni
)
311 TRACE("(%u, %u, %p, %u)\n", uiAction
, uiParam
, pvParam
, fuWinIni
);
315 case SPI_SETDESKWALLPAPER
: /* 20 */
316 case SPI_SETDESKPATTERN
: /* 21 */
320 if (!MultiByteToWideChar( CP_ACP
, 0, pvParam
, -1, buffer
, ARRAY_SIZE( buffer
)))
321 buffer
[ARRAY_SIZE(buffer
)-1] = 0;
322 ret
= SystemParametersInfoW( uiAction
, uiParam
, pvParam
? buffer
: NULL
, fuWinIni
);
326 case SPI_GETICONTITLELOGFONT
: /* 31 */
329 ret
= SystemParametersInfoW( uiAction
, uiParam
, pvParam
? &tmp
: NULL
, fuWinIni
);
331 SYSPARAMS_LogFont32WTo32A( &tmp
, pvParam
);
335 case SPI_GETNONCLIENTMETRICS
: /* 41 WINVER >= 0x400 */
337 NONCLIENTMETRICSW tmp
;
338 LPNONCLIENTMETRICSA lpnmA
= pvParam
;
339 if (lpnmA
&& (lpnmA
->cbSize
== sizeof(NONCLIENTMETRICSA
) ||
340 lpnmA
->cbSize
== FIELD_OFFSET(NONCLIENTMETRICSA
, iPaddedBorderWidth
)))
342 tmp
.cbSize
= sizeof(NONCLIENTMETRICSW
);
343 ret
= SystemParametersInfoW( uiAction
, uiParam
, &tmp
, fuWinIni
);
345 SYSPARAMS_NonClientMetrics32WTo32A( &tmp
, lpnmA
);
352 case SPI_SETNONCLIENTMETRICS
: /* 42 WINVER >= 0x400 */
354 NONCLIENTMETRICSW tmp
;
355 LPNONCLIENTMETRICSA lpnmA
= pvParam
;
356 if (lpnmA
&& (lpnmA
->cbSize
== sizeof(NONCLIENTMETRICSA
) ||
357 lpnmA
->cbSize
== FIELD_OFFSET(NONCLIENTMETRICSA
, iPaddedBorderWidth
)))
359 tmp
.cbSize
= sizeof(NONCLIENTMETRICSW
);
360 SYSPARAMS_NonClientMetrics32ATo32W( lpnmA
, &tmp
);
361 ret
= SystemParametersInfoW( uiAction
, uiParam
, &tmp
, fuWinIni
);
368 case SPI_GETICONMETRICS
: /* 45 WINVER >= 0x400 */
371 LPICONMETRICSA lpimA
= pvParam
;
372 if (lpimA
&& lpimA
->cbSize
== sizeof(ICONMETRICSA
))
374 tmp
.cbSize
= sizeof(ICONMETRICSW
);
375 ret
= SystemParametersInfoW( uiAction
, uiParam
, &tmp
, fuWinIni
);
378 lpimA
->iHorzSpacing
= tmp
.iHorzSpacing
;
379 lpimA
->iVertSpacing
= tmp
.iVertSpacing
;
380 lpimA
->iTitleWrap
= tmp
.iTitleWrap
;
381 SYSPARAMS_LogFont32WTo32A( &tmp
.lfFont
, &lpimA
->lfFont
);
389 case SPI_SETICONMETRICS
: /* 46 WINVER >= 0x400 */
392 LPICONMETRICSA lpimA
= pvParam
;
393 if (lpimA
&& lpimA
->cbSize
== sizeof(ICONMETRICSA
))
395 tmp
.cbSize
= sizeof(ICONMETRICSW
);
396 tmp
.iHorzSpacing
= lpimA
->iHorzSpacing
;
397 tmp
.iVertSpacing
= lpimA
->iVertSpacing
;
398 tmp
.iTitleWrap
= lpimA
->iTitleWrap
;
399 SYSPARAMS_LogFont32ATo32W( &lpimA
->lfFont
, &tmp
.lfFont
);
400 ret
= SystemParametersInfoW( uiAction
, uiParam
, &tmp
, fuWinIni
);
407 case SPI_GETHIGHCONTRAST
: /* 66 WINVER >= 0x400 */
410 LPHIGHCONTRASTA lphcA
= pvParam
;
411 if (lphcA
&& lphcA
->cbSize
== sizeof(HIGHCONTRASTA
))
413 tmp
.cbSize
= sizeof(HIGHCONTRASTW
);
414 ret
= SystemParametersInfoW( uiAction
, uiParam
, &tmp
, fuWinIni
);
417 lphcA
->dwFlags
= tmp
.dwFlags
;
418 lphcA
->lpszDefaultScheme
= NULL
; /* FIXME? */
426 case SPI_GETDESKWALLPAPER
: /* 115 */
428 WCHAR buffer
[MAX_PATH
];
429 ret
= (SystemParametersInfoW( SPI_GETDESKWALLPAPER
, uiParam
, buffer
, fuWinIni
) &&
430 WideCharToMultiByte(CP_ACP
, 0, buffer
, -1, pvParam
, uiParam
, NULL
, NULL
));
435 ret
= SystemParametersInfoW( uiAction
, uiParam
, pvParam
, fuWinIni
);
442 /***********************************************************************
443 * GetSystemMetrics (USER32.@)
445 INT WINAPI
GetSystemMetrics( INT index
)
447 return NtUserCallOneParam( index
, NtUserGetSystemMetrics
);
451 /***********************************************************************
452 * GetSystemMetricsForDpi (USER32.@)
454 INT WINAPI
GetSystemMetricsForDpi( INT index
, UINT dpi
)
456 return NtUserCallTwoParam( index
, dpi
, NtUserGetSystemMetricsForDpi
);
460 /***********************************************************************
461 * SwapMouseButton (USER32.@)
462 * Reverse or restore the meaning of the left and right mouse buttons
463 * fSwap [I ] TRUE - reverse, FALSE - original
467 BOOL WINAPI
SwapMouseButton( BOOL fSwap
)
469 BOOL prev
= GetSystemMetrics(SM_SWAPBUTTON
);
470 SystemParametersInfoW(SPI_SETMOUSEBUTTONSWAP
, fSwap
, 0, 0);
475 /**********************************************************************
476 * SetDoubleClickTime (USER32.@)
478 BOOL WINAPI
SetDoubleClickTime( UINT interval
)
480 return SystemParametersInfoW(SPI_SETDOUBLECLICKTIME
, interval
, 0, 0);
484 /*************************************************************************
485 * GetSysColor (USER32.@)
487 COLORREF WINAPI DECLSPEC_HOTPATCH
GetSysColor( INT index
)
489 return NtUserCallOneParam( index
, NtUserGetSysColor
);
493 /*************************************************************************
494 * SetSysColorsTemp (USER32.@)
496 DWORD_PTR WINAPI
SetSysColorsTemp( const COLORREF
*pPens
, const HBRUSH
*pBrushes
, DWORD_PTR n
)
498 FIXME( "no longer supported\n" );
503 /***********************************************************************
504 * GetSysColorBrush (USER32.@)
506 HBRUSH WINAPI DECLSPEC_HOTPATCH
GetSysColorBrush( INT index
)
508 return UlongToHandle( NtUserCallOneParam( index
, NtUserGetSysColorBrush
));
512 /***********************************************************************
515 HPEN
SYSCOLOR_GetPen( INT index
)
517 return UlongToHandle( NtUserCallOneParam( index
, NtUserGetSysColorPen
));
521 /***********************************************************************
522 * SYSCOLOR_Get55AABrush
524 HBRUSH
SYSCOLOR_Get55AABrush(void)
526 return UlongToHandle( NtUserCallOneParam( COLOR_55AA_BRUSH
, NtUserGetSysColorBrush
));
529 /***********************************************************************
530 * ChangeDisplaySettingsA (USER32.@)
532 LONG WINAPI
ChangeDisplaySettingsA( LPDEVMODEA devmode
, DWORD flags
)
534 if (devmode
) devmode
->dmDriverExtra
= 0;
536 return ChangeDisplaySettingsExA(NULL
,devmode
,NULL
,flags
,NULL
);
540 /***********************************************************************
541 * ChangeDisplaySettingsW (USER32.@)
543 LONG WINAPI
ChangeDisplaySettingsW( LPDEVMODEW devmode
, DWORD flags
)
545 if (devmode
) devmode
->dmDriverExtra
= 0;
547 return ChangeDisplaySettingsExW(NULL
,devmode
,NULL
,flags
,NULL
);
551 /***********************************************************************
552 * ChangeDisplaySettingsExA (USER32.@)
554 LONG WINAPI
ChangeDisplaySettingsExA( LPCSTR devname
, LPDEVMODEA devmode
, HWND hwnd
,
555 DWORD flags
, LPVOID lparam
)
558 UNICODE_STRING nameW
;
560 if (devname
) RtlCreateUnicodeStringFromAsciiz(&nameW
, devname
);
561 else nameW
.Buffer
= NULL
;
567 devmodeW
= GdiConvertToDevmodeW(devmode
);
570 ret
= ChangeDisplaySettingsExW(nameW
.Buffer
, devmodeW
, hwnd
, flags
, lparam
);
571 HeapFree(GetProcessHeap(), 0, devmodeW
);
574 ret
= DISP_CHANGE_SUCCESSFUL
;
578 ret
= ChangeDisplaySettingsExW(nameW
.Buffer
, NULL
, hwnd
, flags
, lparam
);
581 if (devname
) RtlFreeUnicodeString(&nameW
);
586 /***********************************************************************
587 * ChangeDisplaySettingsExW (USER32.@)
589 LONG WINAPI
ChangeDisplaySettingsExW( LPCWSTR devname
, LPDEVMODEW devmode
, HWND hwnd
,
590 DWORD flags
, LPVOID lparam
)
593 RtlInitUnicodeString( &str
, devname
);
594 return NtUserChangeDisplaySettings( &str
, devmode
, hwnd
, flags
, lparam
);
598 /***********************************************************************
599 * EnumDisplaySettingsW (USER32.@)
602 * TRUE if nth setting exists found (described in the LPDEVMODEW struct)
603 * FALSE if we do not have the nth setting
605 BOOL WINAPI
EnumDisplaySettingsW( LPCWSTR name
, DWORD n
, LPDEVMODEW devmode
)
607 return EnumDisplaySettingsExW(name
, n
, devmode
, 0);
611 /***********************************************************************
612 * EnumDisplaySettingsA (USER32.@)
614 BOOL WINAPI
EnumDisplaySettingsA(LPCSTR name
,DWORD n
,LPDEVMODEA devmode
)
616 return EnumDisplaySettingsExA(name
, n
, devmode
, 0);
620 /***********************************************************************
621 * EnumDisplaySettingsExA (USER32.@)
623 BOOL WINAPI
EnumDisplaySettingsExA(LPCSTR lpszDeviceName
, DWORD iModeNum
,
624 LPDEVMODEA lpDevMode
, DWORD dwFlags
)
628 UNICODE_STRING nameW
;
630 if (lpszDeviceName
) RtlCreateUnicodeStringFromAsciiz(&nameW
, lpszDeviceName
);
631 else nameW
.Buffer
= NULL
;
633 memset(&devmodeW
, 0, sizeof(devmodeW
));
634 devmodeW
.dmSize
= sizeof(devmodeW
);
635 ret
= EnumDisplaySettingsExW(nameW
.Buffer
,iModeNum
,&devmodeW
,dwFlags
);
638 lpDevMode
->dmSize
= FIELD_OFFSET(DEVMODEA
, dmICMMethod
);
639 lpDevMode
->dmSpecVersion
= devmodeW
.dmSpecVersion
;
640 lpDevMode
->dmDriverVersion
= devmodeW
.dmDriverVersion
;
641 WideCharToMultiByte(CP_ACP
, 0, devmodeW
.dmDeviceName
, -1,
642 (LPSTR
)lpDevMode
->dmDeviceName
, CCHDEVICENAME
, NULL
, NULL
);
643 lpDevMode
->dmDriverExtra
= 0; /* FIXME */
644 lpDevMode
->dmBitsPerPel
= devmodeW
.dmBitsPerPel
;
645 lpDevMode
->dmPelsHeight
= devmodeW
.dmPelsHeight
;
646 lpDevMode
->dmPelsWidth
= devmodeW
.dmPelsWidth
;
647 lpDevMode
->u2
.dmDisplayFlags
= devmodeW
.u2
.dmDisplayFlags
;
648 lpDevMode
->dmDisplayFrequency
= devmodeW
.dmDisplayFrequency
;
649 lpDevMode
->dmFields
= devmodeW
.dmFields
;
651 lpDevMode
->u1
.s2
.dmPosition
.x
= devmodeW
.u1
.s2
.dmPosition
.x
;
652 lpDevMode
->u1
.s2
.dmPosition
.y
= devmodeW
.u1
.s2
.dmPosition
.y
;
653 lpDevMode
->u1
.s2
.dmDisplayOrientation
= devmodeW
.u1
.s2
.dmDisplayOrientation
;
654 lpDevMode
->u1
.s2
.dmDisplayFixedOutput
= devmodeW
.u1
.s2
.dmDisplayFixedOutput
;
656 if (lpszDeviceName
) RtlFreeUnicodeString(&nameW
);
661 /***********************************************************************
662 * EnumDisplaySettingsExW (USER32.@)
664 BOOL WINAPI
EnumDisplaySettingsExW( const WCHAR
*device
, DWORD mode
,
665 DEVMODEW
*dev_mode
, DWORD flags
)
668 RtlInitUnicodeString( &str
, device
);
669 return NtUserEnumDisplaySettings( &str
, mode
, dev_mode
, flags
);
672 /**********************************************************************
675 UINT
get_monitor_dpi( HMONITOR monitor
)
677 /* FIXME: use the monitor DPI instead */
681 /**********************************************************************
682 * get_win_monitor_dpi
684 UINT
get_win_monitor_dpi( HWND hwnd
)
686 /* FIXME: use the monitor DPI instead */
690 /**********************************************************************
693 UINT
get_thread_dpi(void)
695 switch (GetAwarenessFromDpiAwarenessContext( GetThreadDpiAwarenessContext() ))
697 case DPI_AWARENESS_UNAWARE
: return USER_DEFAULT_SCREEN_DPI
;
698 case DPI_AWARENESS_SYSTEM_AWARE
: return system_dpi
;
699 default: return 0; /* no scaling */
703 /**********************************************************************
706 POINT
map_dpi_point( POINT pt
, UINT dpi_from
, UINT dpi_to
)
708 if (dpi_from
&& dpi_to
&& dpi_from
!= dpi_to
)
710 pt
.x
= MulDiv( pt
.x
, dpi_to
, dpi_from
);
711 pt
.y
= MulDiv( pt
.y
, dpi_to
, dpi_from
);
716 /**********************************************************************
717 * point_win_to_phys_dpi
719 POINT
point_win_to_phys_dpi( HWND hwnd
, POINT pt
)
721 return map_dpi_point( pt
, GetDpiForWindow( hwnd
), get_win_monitor_dpi( hwnd
) );
724 /**********************************************************************
725 * point_phys_to_win_dpi
727 POINT
point_phys_to_win_dpi( HWND hwnd
, POINT pt
)
729 return map_dpi_point( pt
, get_win_monitor_dpi( hwnd
), GetDpiForWindow( hwnd
));
732 /**********************************************************************
733 * point_win_to_thread_dpi
735 POINT
point_win_to_thread_dpi( HWND hwnd
, POINT pt
)
737 UINT dpi
= get_thread_dpi();
738 if (!dpi
) dpi
= get_win_monitor_dpi( hwnd
);
739 return map_dpi_point( pt
, GetDpiForWindow( hwnd
), dpi
);
742 /**********************************************************************
743 * point_thread_to_win_dpi
745 POINT
point_thread_to_win_dpi( HWND hwnd
, POINT pt
)
747 UINT dpi
= get_thread_dpi();
748 if (!dpi
) dpi
= get_win_monitor_dpi( hwnd
);
749 return map_dpi_point( pt
, dpi
, GetDpiForWindow( hwnd
));
752 /**********************************************************************
755 RECT
map_dpi_rect( RECT rect
, UINT dpi_from
, UINT dpi_to
)
757 if (dpi_from
&& dpi_to
&& dpi_from
!= dpi_to
)
759 rect
.left
= MulDiv( rect
.left
, dpi_to
, dpi_from
);
760 rect
.top
= MulDiv( rect
.top
, dpi_to
, dpi_from
);
761 rect
.right
= MulDiv( rect
.right
, dpi_to
, dpi_from
);
762 rect
.bottom
= MulDiv( rect
.bottom
, dpi_to
, dpi_from
);
767 /**********************************************************************
768 * rect_win_to_thread_dpi
770 RECT
rect_win_to_thread_dpi( HWND hwnd
, RECT rect
)
772 UINT dpi
= get_thread_dpi();
773 if (!dpi
) dpi
= get_win_monitor_dpi( hwnd
);
774 return map_dpi_rect( rect
, GetDpiForWindow( hwnd
), dpi
);
777 /**********************************************************************
778 * rect_thread_to_win_dpi
780 RECT
rect_thread_to_win_dpi( HWND hwnd
, RECT rect
)
782 UINT dpi
= get_thread_dpi();
783 if (!dpi
) dpi
= get_win_monitor_dpi( hwnd
);
784 return map_dpi_rect( rect
, dpi
, GetDpiForWindow( hwnd
) );
787 /**********************************************************************
788 * SetProcessDpiAwarenessContext (USER32.@)
790 BOOL WINAPI
SetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT context
)
794 switch (GetAwarenessFromDpiAwarenessContext( context
))
796 case DPI_AWARENESS_UNAWARE
:
797 awareness
= NTUSER_DPI_UNAWARE
;
799 case DPI_AWARENESS_SYSTEM_AWARE
:
800 awareness
= NTUSER_DPI_SYSTEM_AWARE
;
802 case DPI_AWARENESS_PER_MONITOR_AWARE
:
803 awareness
= context
== DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
804 ? NTUSER_DPI_PER_MONITOR_AWARE_V2
: NTUSER_DPI_PER_MONITOR_AWARE
;
807 SetLastError( ERROR_INVALID_PARAMETER
);
811 if (!NtUserSetProcessDpiAwarenessContext( awareness
, 0 ))
813 SetLastError( ERROR_ACCESS_DENIED
);
817 TRACE( "set to %p\n", context
);
821 /**********************************************************************
822 * GetProcessDpiAwarenessInternal (USER32.@)
824 BOOL WINAPI
GetProcessDpiAwarenessInternal( HANDLE process
, DPI_AWARENESS
*awareness
)
826 *awareness
= NtUserGetProcessDpiAwarenessContext( process
) & 3;
830 /**********************************************************************
831 * SetProcessDpiAwarenessInternal (USER32.@)
833 BOOL WINAPI
SetProcessDpiAwarenessInternal( DPI_AWARENESS awareness
)
835 static const DPI_AWARENESS_CONTEXT contexts
[3] = { DPI_AWARENESS_CONTEXT_UNAWARE
,
836 DPI_AWARENESS_CONTEXT_SYSTEM_AWARE
,
837 DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
};
839 if (awareness
< DPI_AWARENESS_UNAWARE
|| awareness
> DPI_AWARENESS_PER_MONITOR_AWARE
)
841 SetLastError( ERROR_INVALID_PARAMETER
);
844 return SetProcessDpiAwarenessContext( contexts
[awareness
] );
847 /***********************************************************************
848 * AreDpiAwarenessContextsEqual (USER32.@)
850 BOOL WINAPI
AreDpiAwarenessContextsEqual( DPI_AWARENESS_CONTEXT ctx1
, DPI_AWARENESS_CONTEXT ctx2
)
852 DPI_AWARENESS aware1
= GetAwarenessFromDpiAwarenessContext( ctx1
);
853 DPI_AWARENESS aware2
= GetAwarenessFromDpiAwarenessContext( ctx2
);
854 return aware1
!= DPI_AWARENESS_INVALID
&& aware1
== aware2
;
857 /***********************************************************************
858 * GetAwarenessFromDpiAwarenessContext (USER32.@)
860 DPI_AWARENESS WINAPI
GetAwarenessFromDpiAwarenessContext( DPI_AWARENESS_CONTEXT context
)
862 switch ((ULONG_PTR
)context
)
870 return (ULONG_PTR
)context
& 3;
871 case (ULONG_PTR
)DPI_AWARENESS_CONTEXT_UNAWARE
:
872 case (ULONG_PTR
)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE
:
873 case (ULONG_PTR
)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
:
874 return ~(ULONG_PTR
)context
;
876 return DPI_AWARENESS_INVALID
;
880 /***********************************************************************
881 * IsValidDpiAwarenessContext (USER32.@)
883 BOOL WINAPI
IsValidDpiAwarenessContext( DPI_AWARENESS_CONTEXT context
)
885 return GetAwarenessFromDpiAwarenessContext( context
) != DPI_AWARENESS_INVALID
;
888 /***********************************************************************
889 * SetProcessDPIAware (USER32.@)
891 BOOL WINAPI
SetProcessDPIAware(void)
894 NtUserSetProcessDpiAwarenessContext( NTUSER_DPI_SYSTEM_AWARE
, 0 );
898 /***********************************************************************
899 * IsProcessDPIAware (USER32.@)
901 BOOL WINAPI
IsProcessDPIAware(void)
903 return GetAwarenessFromDpiAwarenessContext( GetThreadDpiAwarenessContext() ) != DPI_AWARENESS_UNAWARE
;
906 /**********************************************************************
907 * EnableNonClientDpiScaling (USER32.@)
909 BOOL WINAPI
EnableNonClientDpiScaling( HWND hwnd
)
911 FIXME("(%p): stub\n", hwnd
);
912 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
916 /***********************************************************************
917 * GetDpiForSystem (USER32.@)
919 UINT WINAPI
GetDpiForSystem(void)
921 if (!IsProcessDPIAware()) return USER_DEFAULT_SCREEN_DPI
;
925 /**********************************************************************
926 * GetThreadDpiAwarenessContext (USER32.@)
928 DPI_AWARENESS_CONTEXT WINAPI
GetThreadDpiAwarenessContext(void)
930 struct user_thread_info
*info
= get_user_thread_info();
932 if (info
->dpi_awareness
) return ULongToHandle( info
->dpi_awareness
);
933 return UlongToHandle( (NtUserGetProcessDpiAwarenessContext( GetCurrentProcess() ) & 3 ) | 0x10 );
936 /**********************************************************************
937 * SetThreadDpiAwarenessContext (USER32.@)
939 DPI_AWARENESS_CONTEXT WINAPI
SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT context
)
941 struct user_thread_info
*info
= get_user_thread_info();
942 DPI_AWARENESS prev
, val
= GetAwarenessFromDpiAwarenessContext( context
);
944 if (val
== DPI_AWARENESS_INVALID
)
946 SetLastError( ERROR_INVALID_PARAMETER
);
949 if (!(prev
= info
->dpi_awareness
))
951 prev
= NtUserGetProcessDpiAwarenessContext( GetCurrentProcess() ) & 3;
952 prev
|= 0x80000010; /* restore to process default */
954 if (((ULONG_PTR
)context
& ~(ULONG_PTR
)0x13) == 0x80000000) info
->dpi_awareness
= 0;
955 else info
->dpi_awareness
= val
| 0x10;
956 return ULongToHandle( prev
);
959 /**********************************************************************
960 * LogicalToPhysicalPointForPerMonitorDPI (USER32.@)
962 BOOL WINAPI
LogicalToPhysicalPointForPerMonitorDPI( HWND hwnd
, POINT
*pt
)
966 if (!GetWindowRect( hwnd
, &rect
)) return FALSE
;
967 if (pt
->x
< rect
.left
|| pt
->y
< rect
.top
|| pt
->x
> rect
.right
|| pt
->y
> rect
.bottom
) return FALSE
;
968 *pt
= point_win_to_phys_dpi( hwnd
, *pt
);
972 /**********************************************************************
973 * PhysicalToLogicalPointForPerMonitorDPI (USER32.@)
975 BOOL WINAPI
PhysicalToLogicalPointForPerMonitorDPI( HWND hwnd
, POINT
*pt
)
977 DPI_AWARENESS_CONTEXT context
;
981 context
= SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
);
982 if (GetWindowRect( hwnd
, &rect
) &&
983 pt
->x
>= rect
.left
&& pt
->y
>= rect
.top
&& pt
->x
<= rect
.right
&& pt
->y
<= rect
.bottom
)
985 *pt
= point_phys_to_win_dpi( hwnd
, *pt
);
988 SetThreadDpiAwarenessContext( context
);
992 struct monitor_enum_info
1002 /* helper callback for MonitorFromRect */
1003 static BOOL CALLBACK
monitor_enum( HMONITOR monitor
, HDC hdc
, LPRECT rect
, LPARAM lp
)
1005 struct monitor_enum_info
*info
= (struct monitor_enum_info
*)lp
;
1008 if (IntersectRect( &intersect
, rect
, &info
->rect
))
1010 /* check for larger intersecting area */
1011 UINT area
= (intersect
.right
- intersect
.left
) * (intersect
.bottom
- intersect
.top
);
1012 if (area
> info
->max_area
)
1014 info
->max_area
= area
;
1015 info
->ret
= monitor
;
1018 else if (!info
->max_area
) /* if not intersecting, check for min distance */
1023 if (info
->rect
.right
<= rect
->left
) x
= rect
->left
- info
->rect
.right
;
1024 else if (rect
->right
<= info
->rect
.left
) x
= info
->rect
.left
- rect
->right
;
1026 if (info
->rect
.bottom
<= rect
->top
) y
= rect
->top
- info
->rect
.bottom
;
1027 else if (rect
->bottom
<= info
->rect
.top
) y
= info
->rect
.top
- rect
->bottom
;
1029 distance
= x
* x
+ y
* y
;
1030 if (distance
< info
->min_distance
)
1032 info
->min_distance
= distance
;
1033 info
->nearest
= monitor
;
1038 MONITORINFO mon_info
;
1039 mon_info
.cbSize
= sizeof(mon_info
);
1040 GetMonitorInfoW( monitor
, &mon_info
);
1041 if (mon_info
.dwFlags
& MONITORINFOF_PRIMARY
) info
->primary
= monitor
;
1046 /***********************************************************************
1047 * MonitorFromRect (USER32.@)
1049 HMONITOR WINAPI
MonitorFromRect( const RECT
*rect
, DWORD flags
)
1051 struct monitor_enum_info info
;
1055 info
.min_distance
= ~0u;
1060 if (IsRectEmpty(&info
.rect
))
1062 info
.rect
.right
= info
.rect
.left
+ 1;
1063 info
.rect
.bottom
= info
.rect
.top
+ 1;
1066 if (!NtUserEnumDisplayMonitors( 0, NULL
, monitor_enum
, (LPARAM
)&info
)) return 0;
1069 if (flags
& MONITOR_DEFAULTTOPRIMARY
) info
.ret
= info
.primary
;
1070 else if (flags
& MONITOR_DEFAULTTONEAREST
) info
.ret
= info
.nearest
;
1073 TRACE( "%s flags %x returning %p\n", wine_dbgstr_rect(rect
), flags
, info
.ret
);
1077 /***********************************************************************
1078 * MonitorFromPoint (USER32.@)
1080 HMONITOR WINAPI
MonitorFromPoint( POINT pt
, DWORD flags
)
1084 SetRect( &rect
, pt
.x
, pt
.y
, pt
.x
+ 1, pt
.y
+ 1 );
1085 return MonitorFromRect( &rect
, flags
);
1088 /***********************************************************************
1089 * MonitorFromWindow (USER32.@)
1091 HMONITOR WINAPI
MonitorFromWindow(HWND hWnd
, DWORD dwFlags
)
1096 TRACE("(%p, 0x%08x)\n", hWnd
, dwFlags
);
1098 wp
.length
= sizeof(wp
);
1099 if (IsIconic(hWnd
) && GetWindowPlacement(hWnd
, &wp
))
1100 return MonitorFromRect( &wp
.rcNormalPosition
, dwFlags
);
1102 if (GetWindowRect( hWnd
, &rect
))
1103 return MonitorFromRect( &rect
, dwFlags
);
1105 if (!(dwFlags
& (MONITOR_DEFAULTTOPRIMARY
|MONITOR_DEFAULTTONEAREST
))) return 0;
1106 /* retrieve the primary */
1107 SetRect( &rect
, 0, 0, 1, 1 );
1108 return MonitorFromRect( &rect
, dwFlags
);
1111 /***********************************************************************
1112 * GetMonitorInfoA (USER32.@)
1114 BOOL WINAPI
GetMonitorInfoA( HMONITOR monitor
, LPMONITORINFO info
)
1119 if (info
->cbSize
== sizeof(MONITORINFO
)) return GetMonitorInfoW( monitor
, info
);
1120 if (info
->cbSize
!= sizeof(MONITORINFOEXA
)) return FALSE
;
1122 miW
.cbSize
= sizeof(miW
);
1123 ret
= GetMonitorInfoW( monitor
, (MONITORINFO
*)&miW
);
1126 MONITORINFOEXA
*miA
= (MONITORINFOEXA
*)info
;
1127 miA
->rcMonitor
= miW
.rcMonitor
;
1128 miA
->rcWork
= miW
.rcWork
;
1129 miA
->dwFlags
= miW
.dwFlags
;
1130 WideCharToMultiByte(CP_ACP
, 0, miW
.szDevice
, -1, miA
->szDevice
, sizeof(miA
->szDevice
), NULL
, NULL
);
1135 /***********************************************************************
1136 * GetMonitorInfoW (USER32.@)
1138 BOOL WINAPI
GetMonitorInfoW( HMONITOR monitor
, LPMONITORINFO info
)
1140 return NtUserCallTwoParam( HandleToUlong(monitor
), (ULONG_PTR
)info
, NtUserGetMonitorInfo
);
1144 /* Some apps pass a non-stdcall callback to EnumDisplayMonitors,
1145 * so we need a small assembly wrapper to call it.
1147 extern BOOL
enum_mon_callback_wrapper( void *proc
, HMONITOR monitor
, HDC hdc
, RECT
*rect
, LPARAM lparam
);
1148 __ASM_GLOBAL_FUNC( enum_mon_callback_wrapper
,
1150 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
1151 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
1152 "movl %esp,%ebp\n\t"
1153 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
1155 "pushl 24(%ebp)\n\t" /* lparam */
1156 /* MJ's Help Diagnostic expects that %ecx contains the address to the rect. */
1157 "movl 20(%ebp),%ecx\n\t" /* rect */
1159 "pushl 16(%ebp)\n\t" /* hdc */
1160 "pushl 12(%ebp)\n\t" /* monitor */
1161 "movl 8(%ebp),%eax\n" /* proc */
1164 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
1165 __ASM_CFI(".cfi_same_value %ebp\n\t")
1167 #endif /* __i386__ */
1169 BOOL WINAPI
User32CallEnumDisplayMonitor( struct enum_display_monitor_params
*params
, ULONG size
)
1172 return enum_mon_callback_wrapper( params
->proc
, params
->monitor
, params
->hdc
,
1173 ¶ms
->rect
, params
->lparam
);
1175 return params
->proc( params
->monitor
, params
->hdc
, ¶ms
->rect
, params
->lparam
);
1179 /***********************************************************************
1180 * EnumDisplayDevicesA (USER32.@)
1182 BOOL WINAPI
EnumDisplayDevicesA( LPCSTR device
, DWORD index
, DISPLAY_DEVICEA
*info
, DWORD flags
)
1184 UNICODE_STRING deviceW
;
1185 DISPLAY_DEVICEW ddW
;
1189 RtlCreateUnicodeStringFromAsciiz( &deviceW
, device
);
1191 deviceW
.Buffer
= NULL
;
1193 ddW
.cb
= sizeof(ddW
);
1194 ret
= EnumDisplayDevicesW( deviceW
.Buffer
, index
, &ddW
, flags
);
1195 RtlFreeUnicodeString( &deviceW
);
1200 WideCharToMultiByte( CP_ACP
, 0, ddW
.DeviceName
, -1, info
->DeviceName
, sizeof(info
->DeviceName
), NULL
, NULL
);
1201 WideCharToMultiByte( CP_ACP
, 0, ddW
.DeviceString
, -1, info
->DeviceString
, sizeof(info
->DeviceString
), NULL
, NULL
);
1202 info
->StateFlags
= ddW
.StateFlags
;
1204 if (info
->cb
>= offsetof(DISPLAY_DEVICEA
, DeviceID
) + sizeof(info
->DeviceID
))
1205 WideCharToMultiByte( CP_ACP
, 0, ddW
.DeviceID
, -1, info
->DeviceID
, sizeof(info
->DeviceID
), NULL
, NULL
);
1206 if (info
->cb
>= offsetof(DISPLAY_DEVICEA
, DeviceKey
) + sizeof(info
->DeviceKey
))
1207 WideCharToMultiByte( CP_ACP
, 0, ddW
.DeviceKey
, -1, info
->DeviceKey
, sizeof(info
->DeviceKey
), NULL
, NULL
);
1212 /***********************************************************************
1213 * EnumDisplayDevicesW (USER32.@)
1215 BOOL WINAPI
EnumDisplayDevicesW( LPCWSTR device
, DWORD index
, DISPLAY_DEVICEW
*info
, DWORD flags
)
1218 RtlInitUnicodeString( &str
, device
);
1219 return NT_SUCCESS(NtUserEnumDisplayDevices( &str
, index
, info
, flags
));
1222 /**********************************************************************
1223 * GetAutoRotationState [USER32.@]
1225 BOOL WINAPI
GetAutoRotationState( AR_STATE
*state
)
1227 TRACE("(%p)\n", state
);
1231 SetLastError(ERROR_INVALID_PARAMETER
);
1235 *state
= AR_NOSENSOR
;
1239 /**********************************************************************
1240 * GetDisplayAutoRotationPreferences [USER32.@]
1242 BOOL WINAPI
GetDisplayAutoRotationPreferences( ORIENTATION_PREFERENCE
*orientation
)
1244 FIXME("(%p): stub\n", orientation
);
1245 *orientation
= ORIENTATION_PREFERENCE_NONE
;
1249 /* physical<->logical mapping functions from win8 that are nops in later versions */
1251 /***********************************************************************
1252 * GetPhysicalCursorPos (USER32.@)
1254 BOOL WINAPI
GetPhysicalCursorPos( POINT
*point
)
1256 return GetCursorPos( point
);
1259 /***********************************************************************
1260 * SetPhysicalCursorPos (USER32.@)
1262 BOOL WINAPI
SetPhysicalCursorPos( INT x
, INT y
)
1264 return SetCursorPos( x
, y
);
1267 /***********************************************************************
1268 * WindowFromPhysicalPoint (USER32.@)
1270 HWND WINAPI
WindowFromPhysicalPoint( POINT pt
)
1272 return WindowFromPoint( pt
);
1275 /***********************************************************************
1276 * LogicalToPhysicalPoint (USER32.@)
1278 BOOL WINAPI
LogicalToPhysicalPoint( HWND hwnd
, POINT
*point
)
1283 /***********************************************************************
1284 * PhysicalToLogicalPoint (USER32.@)
1286 BOOL WINAPI
PhysicalToLogicalPoint( HWND hwnd
, POINT
*point
)
1291 static DISPLAYCONFIG_ROTATION
get_dc_rotation(const DEVMODEW
*devmode
)
1293 if (devmode
->dmFields
& DM_DISPLAYORIENTATION
)
1294 return devmode
->u1
.s2
.dmDisplayOrientation
+ 1;
1296 return DISPLAYCONFIG_ROTATION_IDENTITY
;
1299 static DISPLAYCONFIG_SCANLINE_ORDERING
get_dc_scanline_ordering(const DEVMODEW
*devmode
)
1301 if (!(devmode
->dmFields
& DM_DISPLAYFLAGS
))
1302 return DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED
;
1303 else if (devmode
->u2
.dmDisplayFlags
& DM_INTERLACED
)
1304 return DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED
;
1306 return DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE
;
1309 static DISPLAYCONFIG_PIXELFORMAT
get_dc_pixelformat(DWORD dmBitsPerPel
)
1311 if ((dmBitsPerPel
== 8) || (dmBitsPerPel
== 16) ||
1312 (dmBitsPerPel
== 24) || (dmBitsPerPel
== 32))
1313 return dmBitsPerPel
/ 8;
1315 return DISPLAYCONFIG_PIXELFORMAT_NONGDI
;
1318 static void set_mode_target_info(DISPLAYCONFIG_MODE_INFO
*info
, const LUID
*gpu_luid
, UINT32 target_id
,
1319 UINT32 flags
, const DEVMODEW
*devmode
)
1321 DISPLAYCONFIG_TARGET_MODE
*mode
= &(info
->u
.targetMode
);
1323 info
->infoType
= DISPLAYCONFIG_MODE_INFO_TYPE_TARGET
;
1324 info
->adapterId
= *gpu_luid
;
1325 info
->id
= target_id
;
1327 /* FIXME: Populate pixelRate/hSyncFreq/totalSize with real data */
1328 mode
->targetVideoSignalInfo
.pixelRate
= devmode
->dmDisplayFrequency
* devmode
->dmPelsWidth
* devmode
->dmPelsHeight
;
1329 mode
->targetVideoSignalInfo
.hSyncFreq
.Numerator
= devmode
->dmDisplayFrequency
* devmode
->dmPelsWidth
;
1330 mode
->targetVideoSignalInfo
.hSyncFreq
.Denominator
= 1;
1331 mode
->targetVideoSignalInfo
.vSyncFreq
.Numerator
= devmode
->dmDisplayFrequency
;
1332 mode
->targetVideoSignalInfo
.vSyncFreq
.Denominator
= 1;
1333 mode
->targetVideoSignalInfo
.activeSize
.cx
= devmode
->dmPelsWidth
;
1334 mode
->targetVideoSignalInfo
.activeSize
.cy
= devmode
->dmPelsHeight
;
1335 if (flags
& QDC_DATABASE_CURRENT
)
1337 mode
->targetVideoSignalInfo
.totalSize
.cx
= 0;
1338 mode
->targetVideoSignalInfo
.totalSize
.cy
= 0;
1342 mode
->targetVideoSignalInfo
.totalSize
.cx
= devmode
->dmPelsWidth
;
1343 mode
->targetVideoSignalInfo
.totalSize
.cy
= devmode
->dmPelsHeight
;
1345 mode
->targetVideoSignalInfo
.u
.videoStandard
= D3DKMDT_VSS_OTHER
;
1346 mode
->targetVideoSignalInfo
.scanLineOrdering
= get_dc_scanline_ordering(devmode
);
1349 static void set_path_target_info(DISPLAYCONFIG_PATH_TARGET_INFO
*info
, const LUID
*gpu_luid
,
1350 UINT32 target_id
, UINT32 mode_index
, const DEVMODEW
*devmode
)
1352 info
->adapterId
= *gpu_luid
;
1353 info
->id
= target_id
;
1354 info
->u
.modeInfoIdx
= mode_index
;
1355 info
->outputTechnology
= DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL
;
1356 info
->rotation
= get_dc_rotation(devmode
);
1357 info
->scaling
= DISPLAYCONFIG_SCALING_IDENTITY
;
1358 info
->refreshRate
.Numerator
= devmode
->dmDisplayFrequency
;
1359 info
->refreshRate
.Denominator
= 1;
1360 info
->scanLineOrdering
= get_dc_scanline_ordering(devmode
);
1361 info
->targetAvailable
= TRUE
;
1362 info
->statusFlags
= DISPLAYCONFIG_TARGET_IN_USE
;
1365 static void set_mode_source_info(DISPLAYCONFIG_MODE_INFO
*info
, const LUID
*gpu_luid
,
1366 UINT32 source_id
, const DEVMODEW
*devmode
)
1368 DISPLAYCONFIG_SOURCE_MODE
*mode
= &(info
->u
.sourceMode
);
1370 info
->infoType
= DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE
;
1371 info
->adapterId
= *gpu_luid
;
1372 info
->id
= source_id
;
1374 mode
->width
= devmode
->dmPelsWidth
;
1375 mode
->height
= devmode
->dmPelsHeight
;
1376 mode
->pixelFormat
= get_dc_pixelformat(devmode
->dmBitsPerPel
);
1377 if (devmode
->dmFields
& DM_POSITION
)
1379 mode
->position
= devmode
->u1
.s2
.dmPosition
;
1383 mode
->position
.x
= 0;
1384 mode
->position
.y
= 0;
1388 static void set_path_source_info(DISPLAYCONFIG_PATH_SOURCE_INFO
*info
, const LUID
*gpu_luid
,
1389 UINT32 source_id
, UINT32 mode_index
)
1391 info
->adapterId
= *gpu_luid
;
1392 info
->id
= source_id
;
1393 info
->u
.modeInfoIdx
= mode_index
;
1394 info
->statusFlags
= DISPLAYCONFIG_SOURCE_IN_USE
;
1397 static BOOL
source_mode_exists(const DISPLAYCONFIG_MODE_INFO
*modeinfo
, UINT32 num_modes
,
1398 UINT32 source_id
, UINT32
*found_mode_index
)
1402 for (i
= 0; i
< num_modes
; i
++)
1404 if (modeinfo
[i
].infoType
== DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE
&&
1405 modeinfo
[i
].id
== source_id
)
1407 *found_mode_index
= i
;
1414 /***********************************************************************
1415 * QueryDisplayConfig (USER32.@)
1417 LONG WINAPI
QueryDisplayConfig(UINT32 flags
, UINT32
*numpathelements
, DISPLAYCONFIG_PATH_INFO
*pathinfo
,
1418 UINT32
*numinfoelements
, DISPLAYCONFIG_MODE_INFO
*modeinfo
,
1419 DISPLAYCONFIG_TOPOLOGY_ID
*topologyid
)
1421 LONG adapter_index
, ret
;
1424 SP_DEVINFO_DATA device_data
= {sizeof(device_data
)};
1425 DWORD monitor_index
= 0, state_flags
, type
;
1426 UINT32 output_id
, source_mode_index
, path_index
= 0, mode_index
= 0;
1428 WCHAR device_name
[CCHDEVICENAME
];
1431 FIXME("(%08x %p %p %p %p %p): semi-stub\n", flags
, numpathelements
, pathinfo
, numinfoelements
, modeinfo
, topologyid
);
1433 if (!numpathelements
|| !numinfoelements
)
1434 return ERROR_INVALID_PARAMETER
;
1436 if (!*numpathelements
|| !*numinfoelements
)
1437 return ERROR_INVALID_PARAMETER
;
1439 if (flags
!= QDC_ALL_PATHS
&&
1440 flags
!= QDC_ONLY_ACTIVE_PATHS
&&
1441 flags
!= QDC_DATABASE_CURRENT
)
1442 return ERROR_INVALID_PARAMETER
;
1444 if (((flags
== QDC_DATABASE_CURRENT
) && !topologyid
) ||
1445 ((flags
!= QDC_DATABASE_CURRENT
) && topologyid
))
1446 return ERROR_INVALID_PARAMETER
;
1448 if (flags
!= QDC_ONLY_ACTIVE_PATHS
)
1449 FIXME("only returning active paths\n");
1453 FIXME("setting toplogyid to DISPLAYCONFIG_TOPOLOGY_INTERNAL\n");
1454 *topologyid
= DISPLAYCONFIG_TOPOLOGY_INTERNAL
;
1457 wait_graphics_driver_ready();
1458 mutex
= get_display_device_init_mutex();
1460 /* Iterate through "targets"/monitors.
1461 * Each target corresponds to a path, and each path corresponds to one or two unique modes.
1463 devinfo
= SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR
, L
"DISPLAY", NULL
, DIGCF_PRESENT
);
1464 if (devinfo
== INVALID_HANDLE_VALUE
)
1466 ret
= ERROR_GEN_FAILURE
;
1470 ret
= ERROR_GEN_FAILURE
;
1471 while (SetupDiEnumDeviceInfo(devinfo
, monitor_index
++, &device_data
))
1473 /* Only count active monitors */
1474 if (!SetupDiGetDevicePropertyW(devinfo
, &device_data
, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS
,
1475 &type
, (BYTE
*)&state_flags
, sizeof(state_flags
), NULL
, 0))
1477 if (!(state_flags
& DISPLAY_DEVICE_ACTIVE
))
1480 if (!SetupDiGetDevicePropertyW(devinfo
, &device_data
, &DEVPROPKEY_MONITOR_GPU_LUID
,
1481 &type
, (BYTE
*)&gpu_luid
, sizeof(gpu_luid
), NULL
, 0))
1484 if (!SetupDiGetDevicePropertyW(devinfo
, &device_data
, &DEVPROPKEY_MONITOR_OUTPUT_ID
,
1485 &type
, (BYTE
*)&output_id
, sizeof(output_id
), NULL
, 0))
1488 if (!SetupDiGetDevicePropertyW(devinfo
, &device_data
, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME
,
1489 &type
, (BYTE
*)device_name
, sizeof(device_name
), NULL
, 0))
1492 memset(&devmode
, 0, sizeof(devmode
));
1493 devmode
.dmSize
= sizeof(devmode
);
1494 if (!EnumDisplaySettingsW(device_name
, ENUM_CURRENT_SETTINGS
, &devmode
))
1497 /* Extract the adapter index from device_name to use as the source ID */
1498 adapter_index
= wcstol(device_name
+ lstrlenW(L
"\\\\.\\DISPLAY"), NULL
, 10);
1501 if (path_index
== *numpathelements
|| mode_index
== *numinfoelements
)
1503 ret
= ERROR_INSUFFICIENT_BUFFER
;
1507 pathinfo
[path_index
].flags
= DISPLAYCONFIG_PATH_ACTIVE
;
1508 set_mode_target_info(&modeinfo
[mode_index
], &gpu_luid
, output_id
, flags
, &devmode
);
1509 set_path_target_info(&(pathinfo
[path_index
].targetInfo
), &gpu_luid
, output_id
, mode_index
, &devmode
);
1512 if (mode_index
== *numinfoelements
)
1514 ret
= ERROR_INSUFFICIENT_BUFFER
;
1518 /* Multiple targets can be driven by the same source, ensure a mode
1519 * hasn't already been added for this source.
1521 if (!source_mode_exists(modeinfo
, mode_index
, adapter_index
, &source_mode_index
))
1523 set_mode_source_info(&modeinfo
[mode_index
], &gpu_luid
, adapter_index
, &devmode
);
1524 source_mode_index
= mode_index
;
1527 set_path_source_info(&(pathinfo
[path_index
].sourceInfo
), &gpu_luid
, adapter_index
, source_mode_index
);
1531 *numpathelements
= path_index
;
1532 *numinfoelements
= mode_index
;
1533 ret
= ERROR_SUCCESS
;
1536 SetupDiDestroyDeviceInfoList(devinfo
);
1537 release_display_device_init_mutex(mutex
);
1541 /***********************************************************************
1542 * DisplayConfigGetDeviceInfo (USER32.@)
1544 LONG WINAPI
DisplayConfigGetDeviceInfo(DISPLAYCONFIG_DEVICE_INFO_HEADER
*packet
)
1546 LONG ret
= ERROR_GEN_FAILURE
;
1549 SP_DEVINFO_DATA device_data
= {sizeof(device_data
)};
1550 DWORD index
= 0, type
;
1553 TRACE("(%p)\n", packet
);
1555 if (!packet
|| packet
->size
< sizeof(*packet
))
1556 return ERROR_GEN_FAILURE
;
1557 wait_graphics_driver_ready();
1559 switch (packet
->type
)
1561 case DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME
:
1563 DISPLAYCONFIG_SOURCE_DEVICE_NAME
*source_name
= (DISPLAYCONFIG_SOURCE_DEVICE_NAME
*)packet
;
1564 WCHAR device_name
[CCHDEVICENAME
];
1567 TRACE("DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME\n");
1569 if (packet
->size
< sizeof(*source_name
))
1570 return ERROR_INVALID_PARAMETER
;
1572 mutex
= get_display_device_init_mutex();
1573 devinfo
= SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR
, L
"DISPLAY", NULL
, DIGCF_PRESENT
);
1574 if (devinfo
== INVALID_HANDLE_VALUE
)
1576 release_display_device_init_mutex(mutex
);
1580 while (SetupDiEnumDeviceInfo(devinfo
, index
++, &device_data
))
1582 if (!SetupDiGetDevicePropertyW(devinfo
, &device_data
, &DEVPROPKEY_MONITOR_GPU_LUID
,
1583 &type
, (BYTE
*)&gpu_luid
, sizeof(gpu_luid
), NULL
, 0))
1586 if ((source_name
->header
.adapterId
.LowPart
!= gpu_luid
.LowPart
) ||
1587 (source_name
->header
.adapterId
.HighPart
!= gpu_luid
.HighPart
))
1590 /* QueryDisplayConfig() derives the source ID from the adapter name. */
1591 if (!SetupDiGetDevicePropertyW(devinfo
, &device_data
, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME
,
1592 &type
, (BYTE
*)device_name
, sizeof(device_name
), NULL
, 0))
1595 source_id
= wcstol(device_name
+ lstrlenW(L
"\\\\.\\DISPLAY"), NULL
, 10);
1597 if (source_name
->header
.id
!= source_id
)
1600 lstrcpyW(source_name
->viewGdiDeviceName
, device_name
);
1601 ret
= ERROR_SUCCESS
;
1604 SetupDiDestroyDeviceInfoList(devinfo
);
1605 release_display_device_init_mutex(mutex
);
1608 case DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME
:
1610 DISPLAYCONFIG_TARGET_DEVICE_NAME
*target_name
= (DISPLAYCONFIG_TARGET_DEVICE_NAME
*)packet
;
1612 FIXME("DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME: stub\n");
1614 if (packet
->size
< sizeof(*target_name
))
1615 return ERROR_INVALID_PARAMETER
;
1617 return ERROR_NOT_SUPPORTED
;
1619 case DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE
:
1621 DISPLAYCONFIG_TARGET_PREFERRED_MODE
*preferred_mode
= (DISPLAYCONFIG_TARGET_PREFERRED_MODE
*)packet
;
1623 FIXME("DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE: stub\n");
1625 if (packet
->size
< sizeof(*preferred_mode
))
1626 return ERROR_INVALID_PARAMETER
;
1628 return ERROR_NOT_SUPPORTED
;
1630 case DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME
:
1632 DISPLAYCONFIG_ADAPTER_NAME
*adapter_name
= (DISPLAYCONFIG_ADAPTER_NAME
*)packet
;
1634 FIXME("DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME: stub\n");
1636 if (packet
->size
< sizeof(*adapter_name
))
1637 return ERROR_INVALID_PARAMETER
;
1639 return ERROR_NOT_SUPPORTED
;
1641 case DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE
:
1642 case DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE
:
1643 case DISPLAYCONFIG_DEVICE_INFO_GET_SUPPORT_VIRTUAL_RESOLUTION
:
1644 case DISPLAYCONFIG_DEVICE_INFO_SET_SUPPORT_VIRTUAL_RESOLUTION
:
1645 case DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO
:
1646 case DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE
:
1647 case DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL
:
1649 FIXME("Unimplemented packet type: %u\n", packet
->type
);
1650 return ERROR_INVALID_PARAMETER
;
1654 /***********************************************************************
1655 * SetDisplayConfig (USER32.@)
1657 LONG WINAPI
SetDisplayConfig(UINT32 path_info_count
, DISPLAYCONFIG_PATH_INFO
*path_info
, UINT32 mode_info_count
,
1658 DISPLAYCONFIG_MODE_INFO
*mode_info
, UINT32 flags
)
1660 FIXME("path_info_count %u, path_info %p, mode_info_count %u, mode_info %p, flags %#x stub.\n",
1661 path_info_count
, path_info
, mode_info_count
, mode_info
, flags
);
1663 return ERROR_SUCCESS
;