twitchapon-anim

Basic Twitchapon Receiver/Visuals
git clone git://bsandro.tech/twitchapon-anim
Log | Files | Refs | README | LICENSE

win32_monitor.c (16204B)


      1 //========================================================================
      2 // GLFW 3.3 Win32 - www.glfw.org
      3 //------------------------------------------------------------------------
      4 // Copyright (c) 2002-2006 Marcus Geelnard
      5 // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
      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 // Please use C89 style variable declarations in this file because VS 2010
     28 //========================================================================
     29 
     30 #include "internal.h"
     31 
     32 #include <stdlib.h>
     33 #include <string.h>
     34 #include <limits.h>
     35 #include <malloc.h>
     36 #include <wchar.h>
     37 
     38 
     39 // Callback for EnumDisplayMonitors in createMonitor
     40 //
     41 static 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 //
     62 static _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     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 //
    137 void _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 = 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                     break;
    189                 }
    190             }
    191 
    192             if (i < disconnectedCount)
    193                 continue;
    194 
    195             monitor = createMonitor(&adapter, &display);
    196             if (!monitor)
    197             {
    198                 free(disconnected);
    199                 return;
    200             }
    201 
    202             _glfwInputMonitor(monitor, GLFW_CONNECTED, type);
    203 
    204             type = _GLFW_INSERT_LAST;
    205         }
    206 
    207         // HACK: If an active adapter does not have any display devices
    208         //       (as sometimes happens), add it directly as a monitor
    209         if (displayIndex == 0)
    210         {
    211             for (i = 0;  i < disconnectedCount;  i++)
    212             {
    213                 if (disconnected[i] &&
    214                     wcscmp(disconnected[i]->win32.adapterName,
    215                            adapter.DeviceName) == 0)
    216                 {
    217                     disconnected[i] = NULL;
    218                     break;
    219                 }
    220             }
    221 
    222             if (i < disconnectedCount)
    223                 continue;
    224 
    225             monitor = createMonitor(&adapter, NULL);
    226             if (!monitor)
    227             {
    228                 free(disconnected);
    229                 return;
    230             }
    231 
    232             _glfwInputMonitor(monitor, GLFW_CONNECTED, type);
    233         }
    234     }
    235 
    236     for (i = 0;  i < disconnectedCount;  i++)
    237     {
    238         if (disconnected[i])
    239             _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
    240     }
    241 
    242     free(disconnected);
    243 }
    244 
    245 // Change the current video mode
    246 //
    247 void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
    248 {
    249     GLFWvidmode current;
    250     const GLFWvidmode* best;
    251     DEVMODEW dm;
    252     LONG result;
    253 
    254     best = _glfwChooseVideoMode(monitor, desired);
    255     _glfwPlatformGetVideoMode(monitor, &current);
    256     if (_glfwCompareVideoModes(&current, best) == 0)
    257         return;
    258 
    259     ZeroMemory(&dm, sizeof(dm));
    260     dm.dmSize = sizeof(dm);
    261     dm.dmFields           = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL |
    262                             DM_DISPLAYFREQUENCY;
    263     dm.dmPelsWidth        = best->width;
    264     dm.dmPelsHeight       = best->height;
    265     dm.dmBitsPerPel       = best->redBits + best->greenBits + best->blueBits;
    266     dm.dmDisplayFrequency = best->refreshRate;
    267 
    268     if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
    269         dm.dmBitsPerPel = 32;
    270 
    271     result = ChangeDisplaySettingsExW(monitor->win32.adapterName,
    272                                       &dm,
    273                                       NULL,
    274                                       CDS_FULLSCREEN,
    275                                       NULL);
    276     if (result == DISP_CHANGE_SUCCESSFUL)
    277         monitor->win32.modeChanged = GLFW_TRUE;
    278     else
    279     {
    280         const char* description = "Unknown error";
    281 
    282         if (result == DISP_CHANGE_BADDUALVIEW)
    283             description = "The system uses DualView";
    284         else if (result == DISP_CHANGE_BADFLAGS)
    285             description = "Invalid flags";
    286         else if (result == DISP_CHANGE_BADMODE)
    287             description = "Graphics mode not supported";
    288         else if (result == DISP_CHANGE_BADPARAM)
    289             description = "Invalid parameter";
    290         else if (result == DISP_CHANGE_FAILED)
    291             description = "Graphics mode failed";
    292         else if (result == DISP_CHANGE_NOTUPDATED)
    293             description = "Failed to write to registry";
    294         else if (result == DISP_CHANGE_RESTART)
    295             description = "Computer restart required";
    296 
    297         _glfwInputError(GLFW_PLATFORM_ERROR,
    298                         "Win32: Failed to set video mode: %s",
    299                         description);
    300     }
    301 }
    302 
    303 // Restore the previously saved (original) video mode
    304 //
    305 void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
    306 {
    307     if (monitor->win32.modeChanged)
    308     {
    309         ChangeDisplaySettingsExW(monitor->win32.adapterName,
    310                                  NULL, NULL, CDS_FULLSCREEN, NULL);
    311         monitor->win32.modeChanged = GLFW_FALSE;
    312     }
    313 }
    314 
    315 void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale)
    316 {
    317     UINT xdpi, ydpi;
    318 
    319     if (IsWindows8Point1OrGreater())
    320         GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
    321     else
    322     {
    323         const HDC dc = GetDC(NULL);
    324         xdpi = GetDeviceCaps(dc, LOGPIXELSX);
    325         ydpi = GetDeviceCaps(dc, LOGPIXELSY);
    326         ReleaseDC(NULL, dc);
    327     }
    328 
    329     if (xscale)
    330         *xscale = xdpi / (float) USER_DEFAULT_SCREEN_DPI;
    331     if (yscale)
    332         *yscale = ydpi / (float) USER_DEFAULT_SCREEN_DPI;
    333 }
    334 
    335 
    336 //////////////////////////////////////////////////////////////////////////
    337 //////                       GLFW platform API                      //////
    338 //////////////////////////////////////////////////////////////////////////
    339 
    340 void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
    341 {
    342 }
    343 
    344 void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
    345 {
    346     DEVMODEW dm;
    347     ZeroMemory(&dm, sizeof(dm));
    348     dm.dmSize = sizeof(dm);
    349 
    350     EnumDisplaySettingsExW(monitor->win32.adapterName,
    351                            ENUM_CURRENT_SETTINGS,
    352                            &dm,
    353                            EDS_ROTATEDMODE);
    354 
    355     if (xpos)
    356         *xpos = dm.dmPosition.x;
    357     if (ypos)
    358         *ypos = dm.dmPosition.y;
    359 }
    360 
    361 void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
    362                                          float* xscale, float* yscale)
    363 {
    364     _glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale);
    365 }
    366 
    367 void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
    368                                      int* xpos, int* ypos,
    369                                      int* width, int* height)
    370 {
    371     MONITORINFO mi = { sizeof(mi) };
    372     GetMonitorInfo(monitor->win32.handle, &mi);
    373 
    374     if (xpos)
    375         *xpos = mi.rcWork.left;
    376     if (ypos)
    377         *ypos = mi.rcWork.top;
    378     if (width)
    379         *width = mi.rcWork.right - mi.rcWork.left;
    380     if (height)
    381         *height = mi.rcWork.bottom - mi.rcWork.top;
    382 }
    383 
    384 GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
    385 {
    386     int modeIndex = 0, size = 0;
    387     GLFWvidmode* result = NULL;
    388 
    389     *count = 0;
    390 
    391     for (;;)
    392     {
    393         int i;
    394         GLFWvidmode mode;
    395         DEVMODEW dm;
    396 
    397         ZeroMemory(&dm, sizeof(dm));
    398         dm.dmSize = sizeof(dm);
    399 
    400         if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm))
    401             break;
    402 
    403         modeIndex++;
    404 
    405         // Skip modes with less than 15 BPP
    406         if (dm.dmBitsPerPel < 15)
    407             continue;
    408 
    409         mode.width  = dm.dmPelsWidth;
    410         mode.height = dm.dmPelsHeight;
    411         mode.refreshRate = dm.dmDisplayFrequency;
    412         _glfwSplitBPP(dm.dmBitsPerPel,
    413                       &mode.redBits,
    414                       &mode.greenBits,
    415                       &mode.blueBits);
    416 
    417         for (i = 0;  i < *count;  i++)
    418         {
    419             if (_glfwCompareVideoModes(result + i, &mode) == 0)
    420                 break;
    421         }
    422 
    423         // Skip duplicate modes
    424         if (i < *count)
    425             continue;
    426 
    427         if (monitor->win32.modesPruned)
    428         {
    429             // Skip modes not supported by the connected displays
    430             if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
    431                                          &dm,
    432                                          NULL,
    433                                          CDS_TEST,
    434                                          NULL) != DISP_CHANGE_SUCCESSFUL)
    435             {
    436                 continue;
    437             }
    438         }
    439 
    440         if (*count == size)
    441         {
    442             size += 128;
    443             result = (GLFWvidmode*) realloc(result, size * sizeof(GLFWvidmode));
    444         }
    445 
    446         (*count)++;
    447         result[*count - 1] = mode;
    448     }
    449 
    450     if (!*count)
    451     {
    452         // HACK: Report the current mode if no valid modes were found
    453         result = calloc(1, sizeof(GLFWvidmode));
    454         _glfwPlatformGetVideoMode(monitor, result);
    455         *count = 1;
    456     }
    457 
    458     return result;
    459 }
    460 
    461 void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
    462 {
    463     DEVMODEW dm;
    464     ZeroMemory(&dm, sizeof(dm));
    465     dm.dmSize = sizeof(dm);
    466 
    467     EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm);
    468 
    469     mode->width  = dm.dmPelsWidth;
    470     mode->height = dm.dmPelsHeight;
    471     mode->refreshRate = dm.dmDisplayFrequency;
    472     _glfwSplitBPP(dm.dmBitsPerPel,
    473                   &mode->redBits,
    474                   &mode->greenBits,
    475                   &mode->blueBits);
    476 }
    477 
    478 GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
    479 {
    480     HDC dc;
    481     WORD values[3][256];
    482 
    483     dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
    484     GetDeviceGammaRamp(dc, values);
    485     DeleteDC(dc);
    486 
    487     _glfwAllocGammaArrays(ramp, 256);
    488 
    489     memcpy(ramp->red,   values[0], sizeof(values[0]));
    490     memcpy(ramp->green, values[1], sizeof(values[1]));
    491     memcpy(ramp->blue,  values[2], sizeof(values[2]));
    492 
    493     return GLFW_TRUE;
    494 }
    495 
    496 void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
    497 {
    498     HDC dc;
    499     WORD values[3][256];
    500 
    501     if (ramp->size != 256)
    502     {
    503         _glfwInputError(GLFW_PLATFORM_ERROR,
    504                         "Win32: Gamma ramp size must be 256");
    505         return;
    506     }
    507 
    508     memcpy(values[0], ramp->red,   sizeof(values[0]));
    509     memcpy(values[1], ramp->green, sizeof(values[1]));
    510     memcpy(values[2], ramp->blue,  sizeof(values[2]));
    511 
    512     dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
    513     SetDeviceGammaRamp(dc, values);
    514     DeleteDC(dc);
    515 }
    516 
    517 
    518 //////////////////////////////////////////////////////////////////////////
    519 //////                        GLFW native API                       //////
    520 //////////////////////////////////////////////////////////////////////////
    521 
    522 GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle)
    523 {
    524     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    525     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    526     return monitor->win32.publicAdapterName;
    527 }
    528 
    529 GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle)
    530 {
    531     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    532     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    533     return monitor->win32.publicDisplayName;
    534 }
    535