ScrapExplorer - win32_monitor.c

Home / ext / glfw / src Lines: 1 | Size: 17073 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1//======================================================================== 2// GLFW 3.5 Win32 - www.glfw.org 3//------------------------------------------------------------------------ 4// Copyright (c) 2002-2006 Marcus Geelnard 5// Copyright (c) 2006-2019 Camilla Löwy <[email protected]> 6// 7// This software is provided 'as-is', without any express or implied 8// warranty. In no event will the authors be held liable for any damages 9// arising from the use of this software. 10// 11// Permission is granted to anyone to use this software for any purpose, 12// including commercial applications, and to alter it and redistribute it 13// freely, subject to the following restrictions: 14// 15// 1. The origin of this software must not be misrepresented; you must not 16// claim that you wrote the original software. If you use this software 17// in a product, an acknowledgment in the product documentation would 18// be appreciated but is not required. 19// 20// 2. Altered source versions must be plainly marked as such, and must not 21// be misrepresented as being the original software. 22// 23// 3. This notice may not be removed or altered from any source 24// distribution. 25// 26//======================================================================== 27 28#include "internal.h" 29 30#if defined(_GLFW_WIN32) 31 32#include <stdlib.h> 33#include <string.h> 34#include <limits.h> 35#include <wchar.h> 36#include <assert.h> 37 38 39// Callback for EnumDisplayMonitors in createMonitor 40// 41static BOOL CALLBACK monitorCallback(HMONITOR handle, 42 HDC dc, 43 RECT* rect, 44 LPARAM data) 45{ 46 MONITORINFOEXW mi; 47 ZeroMemory(&mi, sizeof(mi)); 48 mi.cbSize = sizeof(mi); 49 50 if (GetMonitorInfoW(handle, (MONITORINFO*) &mi)) 51 { 52 _GLFWmonitor* monitor = (_GLFWmonitor*) data; 53 if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0) 54 monitor->win32.handle = handle; 55 } 56 57 return TRUE; 58} 59 60// Create monitor from an adapter and (optionally) a display 61// 62static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter, 63 DISPLAY_DEVICEW* display) 64{ 65 _GLFWmonitor* monitor; 66 int widthMM, heightMM; 67 char* name; 68 HDC dc; 69 DEVMODEW dm; 70 RECT rect; 71 72 if (display) 73 name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString); 74 else 75 name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString); 76 if (!name) 77 return NULL; 78 79 ZeroMemory(&dm, sizeof(dm)); 80 dm.dmSize = sizeof(dm); 81 EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm); 82 83 dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL); 84 85 if (IsWindows8Point1OrGreater()) 86 { 87 widthMM = GetDeviceCaps(dc, HORZSIZE); 88 heightMM = GetDeviceCaps(dc, VERTSIZE); 89 } 90 else 91 { 92 widthMM = (int) (dm.dmPelsWidth * 25.4f / GetDeviceCaps(dc, LOGPIXELSX)); 93 heightMM = (int) (dm.dmPelsHeight * 25.4f / GetDeviceCaps(dc, LOGPIXELSY)); 94 } 95 96 DeleteDC(dc); 97 98 monitor = _glfwAllocMonitor(name, widthMM, heightMM); 99 _glfw_free(name); 100 101 if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED) 102 monitor->win32.modesPruned = GLFW_TRUE; 103 104 wcscpy(monitor->win32.adapterName, adapter->DeviceName); 105 WideCharToMultiByte(CP_UTF8, 0, 106 adapter->DeviceName, -1, 107 monitor->win32.publicAdapterName, 108 sizeof(monitor->win32.publicAdapterName), 109 NULL, NULL); 110 111 if (display) 112 { 113 wcscpy(monitor->win32.displayName, display->DeviceName); 114 WideCharToMultiByte(CP_UTF8, 0, 115 display->DeviceName, -1, 116 monitor->win32.publicDisplayName, 117 sizeof(monitor->win32.publicDisplayName), 118 NULL, NULL); 119 } 120 121 rect.left = dm.dmPosition.x; 122 rect.top = dm.dmPosition.y; 123 rect.right = dm.dmPosition.x + dm.dmPelsWidth; 124 rect.bottom = dm.dmPosition.y + dm.dmPelsHeight; 125 126 EnumDisplayMonitors(NULL, &rect, monitorCallback, (LPARAM) monitor); 127 return monitor; 128} 129 130 131////////////////////////////////////////////////////////////////////////// 132////// GLFW internal API ////// 133////////////////////////////////////////////////////////////////////////// 134 135// Poll for changes in the set of connected monitors 136// 137void _glfwPollMonitorsWin32(void) 138{ 139 int i, disconnectedCount; 140 _GLFWmonitor** disconnected = NULL; 141 DWORD adapterIndex, displayIndex; 142 DISPLAY_DEVICEW adapter, display; 143 _GLFWmonitor* monitor; 144 145 disconnectedCount = _glfw.monitorCount; 146 if (disconnectedCount) 147 { 148 disconnected = _glfw_calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*)); 149 memcpy(disconnected, 150 _glfw.monitors, 151 _glfw.monitorCount * sizeof(_GLFWmonitor*)); 152 } 153 154 for (adapterIndex = 0; ; adapterIndex++) 155 { 156 int type = _GLFW_INSERT_LAST; 157 158 ZeroMemory(&adapter, sizeof(adapter)); 159 adapter.cb = sizeof(adapter); 160 161 if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0)) 162 break; 163 164 if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE)) 165 continue; 166 167 if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) 168 type = _GLFW_INSERT_FIRST; 169 170 for (displayIndex = 0; ; displayIndex++) 171 { 172 ZeroMemory(&display, sizeof(display)); 173 display.cb = sizeof(display); 174 175 if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0)) 176 break; 177 178 if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE)) 179 continue; 180 181 for (i = 0; i < disconnectedCount; i++) 182 { 183 if (disconnected[i] && 184 wcscmp(disconnected[i]->win32.displayName, 185 display.DeviceName) == 0) 186 { 187 disconnected[i] = NULL; 188 // handle may have changed, update 189 EnumDisplayMonitors(NULL, NULL, monitorCallback, (LPARAM) _glfw.monitors[i]); 190 break; 191 } 192 } 193 194 if (i < disconnectedCount) 195 continue; 196 197 monitor = createMonitor(&adapter, &display); 198 if (!monitor) 199 { 200 _glfw_free(disconnected); 201 return; 202 } 203 204 _glfwInputMonitor(monitor, GLFW_CONNECTED, type); 205 206 type = _GLFW_INSERT_LAST; 207 } 208 209 // HACK: If an active adapter does not have any display devices 210 // (as sometimes happens), add it directly as a monitor 211 if (displayIndex == 0) 212 { 213 for (i = 0; i < disconnectedCount; i++) 214 { 215 if (disconnected[i] && 216 wcscmp(disconnected[i]->win32.adapterName, 217 adapter.DeviceName) == 0) 218 { 219 disconnected[i] = NULL; 220 break; 221 } 222 } 223 224 if (i < disconnectedCount) 225 continue; 226 227 monitor = createMonitor(&adapter, NULL); 228 if (!monitor) 229 { 230 _glfw_free(disconnected); 231 return; 232 } 233 234 _glfwInputMonitor(monitor, GLFW_CONNECTED, type); 235 } 236 } 237 238 for (i = 0; i < disconnectedCount; i++) 239 { 240 if (disconnected[i]) 241 _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0); 242 } 243 244 _glfw_free(disconnected); 245} 246 247// Change the current video mode 248// 249void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired) 250{ 251 GLFWvidmode current; 252 const GLFWvidmode* best; 253 DEVMODEW dm; 254 LONG result; 255 256 best = _glfwChooseVideoMode(monitor, desired); 257 _glfwGetVideoModeWin32(monitor, &current); 258 if (_glfwCompareVideoModes(&current, best) == 0) 259 return; 260 261 ZeroMemory(&dm, sizeof(dm)); 262 dm.dmSize = sizeof(dm); 263 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | 264 DM_DISPLAYFREQUENCY; 265 dm.dmPelsWidth = best->width; 266 dm.dmPelsHeight = best->height; 267 dm.dmBitsPerPel = best->redBits + best->greenBits + best->blueBits; 268 dm.dmDisplayFrequency = best->refreshRate; 269 270 if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24) 271 dm.dmBitsPerPel = 32; 272 273 result = ChangeDisplaySettingsExW(monitor->win32.adapterName, 274 &dm, 275 NULL, 276 CDS_FULLSCREEN, 277 NULL); 278 if (result == DISP_CHANGE_SUCCESSFUL) 279 monitor->win32.modeChanged = GLFW_TRUE; 280 else 281 { 282 const char* description = "Unknown error"; 283 284 if (result == DISP_CHANGE_BADDUALVIEW) 285 description = "The system uses DualView"; 286 else if (result == DISP_CHANGE_BADFLAGS) 287 description = "Invalid flags"; 288 else if (result == DISP_CHANGE_BADMODE) 289 description = "Graphics mode not supported"; 290 else if (result == DISP_CHANGE_BADPARAM) 291 description = "Invalid parameter"; 292 else if (result == DISP_CHANGE_FAILED) 293 description = "Graphics mode failed"; 294 else if (result == DISP_CHANGE_NOTUPDATED) 295 description = "Failed to write to registry"; 296 else if (result == DISP_CHANGE_RESTART) 297 description = "Computer restart required"; 298 299 _glfwInputError(GLFW_PLATFORM_ERROR, 300 "Win32: Failed to set video mode: %s", 301 description); 302 } 303} 304 305// Restore the previously saved (original) video mode 306// 307void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor) 308{ 309 if (monitor->win32.modeChanged) 310 { 311 ChangeDisplaySettingsExW(monitor->win32.adapterName, 312 NULL, NULL, CDS_FULLSCREEN, NULL); 313 monitor->win32.modeChanged = GLFW_FALSE; 314 } 315} 316 317void _glfwGetHMONITORContentScaleWin32(HMONITOR handle, float* xscale, float* yscale) 318{ 319 UINT xdpi, ydpi; 320 321 if (xscale) 322 *xscale = 0.f; 323 if (yscale) 324 *yscale = 0.f; 325 326 if (IsWindows8Point1OrGreater()) 327 { 328 if (GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi) != S_OK) 329 { 330 _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to query monitor DPI"); 331 return; 332 } 333 } 334 else 335 { 336 const HDC dc = GetDC(NULL); 337 xdpi = GetDeviceCaps(dc, LOGPIXELSX); 338 ydpi = GetDeviceCaps(dc, LOGPIXELSY); 339 ReleaseDC(NULL, dc); 340 } 341 342 if (xscale) 343 *xscale = xdpi / (float) USER_DEFAULT_SCREEN_DPI; 344 if (yscale) 345 *yscale = ydpi / (float) USER_DEFAULT_SCREEN_DPI; 346} 347 348 349////////////////////////////////////////////////////////////////////////// 350////// GLFW platform API ////// 351////////////////////////////////////////////////////////////////////////// 352 353void _glfwFreeMonitorWin32(_GLFWmonitor* monitor) 354{ 355} 356 357void _glfwGetMonitorPosWin32(_GLFWmonitor* monitor, int* xpos, int* ypos) 358{ 359 DEVMODEW dm; 360 ZeroMemory(&dm, sizeof(dm)); 361 dm.dmSize = sizeof(dm); 362 363 EnumDisplaySettingsExW(monitor->win32.adapterName, 364 ENUM_CURRENT_SETTINGS, 365 &dm, 366 EDS_ROTATEDMODE); 367 368 if (xpos) 369 *xpos = dm.dmPosition.x; 370 if (ypos) 371 *ypos = dm.dmPosition.y; 372} 373 374void _glfwGetMonitorContentScaleWin32(_GLFWmonitor* monitor, 375 float* xscale, float* yscale) 376{ 377 _glfwGetHMONITORContentScaleWin32(monitor->win32.handle, xscale, yscale); 378} 379 380void _glfwGetMonitorWorkareaWin32(_GLFWmonitor* monitor, 381 int* xpos, int* ypos, 382 int* width, int* height) 383{ 384 MONITORINFO mi = { sizeof(mi) }; 385 GetMonitorInfoW(monitor->win32.handle, &mi); 386 387 if (xpos) 388 *xpos = mi.rcWork.left; 389 if (ypos) 390 *ypos = mi.rcWork.top; 391 if (width) 392 *width = mi.rcWork.right - mi.rcWork.left; 393 if (height) 394 *height = mi.rcWork.bottom - mi.rcWork.top; 395} 396 397GLFWvidmode* _glfwGetVideoModesWin32(_GLFWmonitor* monitor, int* count) 398{ 399 int modeIndex = 0, size = 0; 400 GLFWvidmode* result = NULL; 401 402 *count = 0; 403 404 for (;;) 405 { 406 int i; 407 GLFWvidmode mode; 408 DEVMODEW dm; 409 410 ZeroMemory(&dm, sizeof(dm)); 411 dm.dmSize = sizeof(dm); 412 413 if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm)) 414 break; 415 416 modeIndex++; 417 418 // Skip modes with less than 15 BPP 419 if (dm.dmBitsPerPel < 15) 420 continue; 421 422 mode.width = dm.dmPelsWidth; 423 mode.height = dm.dmPelsHeight; 424 mode.refreshRate = dm.dmDisplayFrequency; 425 _glfwSplitBPP(dm.dmBitsPerPel, 426 &mode.redBits, 427 &mode.greenBits, 428 &mode.blueBits); 429 430 for (i = 0; i < *count; i++) 431 { 432 if (_glfwCompareVideoModes(result + i, &mode) == 0) 433 break; 434 } 435 436 // Skip duplicate modes 437 if (i < *count) 438 continue; 439 440 if (monitor->win32.modesPruned) 441 { 442 // Skip modes not supported by the connected displays 443 if (ChangeDisplaySettingsExW(monitor->win32.adapterName, 444 &dm, 445 NULL, 446 CDS_TEST, 447 NULL) != DISP_CHANGE_SUCCESSFUL) 448 { 449 continue; 450 } 451 } 452 453 if (*count == size) 454 { 455 size += 128; 456 result = (GLFWvidmode*) _glfw_realloc(result, size * sizeof(GLFWvidmode)); 457 } 458 459 (*count)++; 460 result[*count - 1] = mode; 461 } 462 463 if (!*count) 464 { 465 // HACK: Report the current mode if no valid modes were found 466 result = _glfw_calloc(1, sizeof(GLFWvidmode)); 467 _glfwGetVideoModeWin32(monitor, result); 468 *count = 1; 469 } 470 471 return result; 472} 473 474GLFWbool _glfwGetVideoModeWin32(_GLFWmonitor* monitor, GLFWvidmode* mode) 475{ 476 DEVMODEW dm; 477 ZeroMemory(&dm, sizeof(dm)); 478 dm.dmSize = sizeof(dm); 479 480 if (!EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm)) 481 { 482 _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to query display settings"); 483 return GLFW_FALSE; 484 } 485 486 mode->width = dm.dmPelsWidth; 487 mode->height = dm.dmPelsHeight; 488 mode->refreshRate = dm.dmDisplayFrequency; 489 _glfwSplitBPP(dm.dmBitsPerPel, 490 &mode->redBits, 491 &mode->greenBits, 492 &mode->blueBits); 493 494 return GLFW_TRUE; 495} 496 497GLFWbool _glfwGetGammaRampWin32(_GLFWmonitor* monitor, GLFWgammaramp* ramp) 498{ 499 HDC dc; 500 WORD values[3][256]; 501 502 dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL); 503 GetDeviceGammaRamp(dc, values); 504 DeleteDC(dc); 505 506 _glfwAllocGammaArrays(ramp, 256); 507 508 memcpy(ramp->red, values[0], sizeof(values[0])); 509 memcpy(ramp->green, values[1], sizeof(values[1])); 510 memcpy(ramp->blue, values[2], sizeof(values[2])); 511 512 return GLFW_TRUE; 513} 514 515void _glfwSetGammaRampWin32(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) 516{ 517 HDC dc; 518 WORD values[3][256]; 519 520 if (ramp->size != 256) 521 { 522 _glfwInputError(GLFW_PLATFORM_ERROR, 523 "Win32: Gamma ramp size must be 256"); 524 return; 525 } 526 527 memcpy(values[0], ramp->red, sizeof(values[0])); 528 memcpy(values[1], ramp->green, sizeof(values[1])); 529 memcpy(values[2], ramp->blue, sizeof(values[2])); 530 531 dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL); 532 SetDeviceGammaRamp(dc, values); 533 DeleteDC(dc); 534} 535 536 537////////////////////////////////////////////////////////////////////////// 538////// GLFW native API ////// 539////////////////////////////////////////////////////////////////////////// 540 541GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle) 542{ 543 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 544 545 if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32) 546 { 547 _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "Win32: Platform not initialized"); 548 return NULL; 549 } 550 551 _GLFWmonitor* monitor = (_GLFWmonitor*) handle; 552 assert(monitor != NULL); 553 554 return monitor->win32.publicAdapterName; 555} 556 557GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle) 558{ 559 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 560 561 if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32) 562 { 563 _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "Win32: Platform not initialized"); 564 return NULL; 565 } 566 567 _GLFWmonitor* monitor = (_GLFWmonitor*) handle; 568 assert(monitor != NULL); 569 570 return monitor->win32.publicDisplayName; 571} 572 573#endif // _GLFW_WIN32 574 575
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.