1b877906bSopenharmony_ci//========================================================================
2b877906bSopenharmony_ci// GLFW 3.5 Win32 - www.glfw.org
3b877906bSopenharmony_ci//------------------------------------------------------------------------
4b877906bSopenharmony_ci// Copyright (c) 2002-2006 Marcus Geelnard
5b877906bSopenharmony_ci// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
6b877906bSopenharmony_ci//
7b877906bSopenharmony_ci// This software is provided 'as-is', without any express or implied
8b877906bSopenharmony_ci// warranty. In no event will the authors be held liable for any damages
9b877906bSopenharmony_ci// arising from the use of this software.
10b877906bSopenharmony_ci//
11b877906bSopenharmony_ci// Permission is granted to anyone to use this software for any purpose,
12b877906bSopenharmony_ci// including commercial applications, and to alter it and redistribute it
13b877906bSopenharmony_ci// freely, subject to the following restrictions:
14b877906bSopenharmony_ci//
15b877906bSopenharmony_ci// 1. The origin of this software must not be misrepresented; you must not
16b877906bSopenharmony_ci//    claim that you wrote the original software. If you use this software
17b877906bSopenharmony_ci//    in a product, an acknowledgment in the product documentation would
18b877906bSopenharmony_ci//    be appreciated but is not required.
19b877906bSopenharmony_ci//
20b877906bSopenharmony_ci// 2. Altered source versions must be plainly marked as such, and must not
21b877906bSopenharmony_ci//    be misrepresented as being the original software.
22b877906bSopenharmony_ci//
23b877906bSopenharmony_ci// 3. This notice may not be removed or altered from any source
24b877906bSopenharmony_ci//    distribution.
25b877906bSopenharmony_ci//
26b877906bSopenharmony_ci//========================================================================
27b877906bSopenharmony_ci
28b877906bSopenharmony_ci#include "internal.h"
29b877906bSopenharmony_ci
30b877906bSopenharmony_ci#if defined(_GLFW_WIN32)
31b877906bSopenharmony_ci
32b877906bSopenharmony_ci#include <limits.h>
33b877906bSopenharmony_ci#include <stdlib.h>
34b877906bSopenharmony_ci#include <string.h>
35b877906bSopenharmony_ci#include <assert.h>
36b877906bSopenharmony_ci#include <windowsx.h>
37b877906bSopenharmony_ci#include <shellapi.h>
38b877906bSopenharmony_ci
39b877906bSopenharmony_ci// Returns the window style for the specified window
40b877906bSopenharmony_ci//
41b877906bSopenharmony_cistatic DWORD getWindowStyle(const _GLFWwindow* window)
42b877906bSopenharmony_ci{
43b877906bSopenharmony_ci    DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
44b877906bSopenharmony_ci
45b877906bSopenharmony_ci    if (window->monitor)
46b877906bSopenharmony_ci        style |= WS_POPUP;
47b877906bSopenharmony_ci    else
48b877906bSopenharmony_ci    {
49b877906bSopenharmony_ci        style |= WS_SYSMENU | WS_MINIMIZEBOX;
50b877906bSopenharmony_ci
51b877906bSopenharmony_ci        if (window->decorated)
52b877906bSopenharmony_ci        {
53b877906bSopenharmony_ci            style |= WS_CAPTION;
54b877906bSopenharmony_ci
55b877906bSopenharmony_ci            if (window->resizable)
56b877906bSopenharmony_ci                style |= WS_MAXIMIZEBOX | WS_THICKFRAME;
57b877906bSopenharmony_ci        }
58b877906bSopenharmony_ci        else
59b877906bSopenharmony_ci            style |= WS_POPUP;
60b877906bSopenharmony_ci    }
61b877906bSopenharmony_ci
62b877906bSopenharmony_ci    return style;
63b877906bSopenharmony_ci}
64b877906bSopenharmony_ci
65b877906bSopenharmony_ci// Returns the extended window style for the specified window
66b877906bSopenharmony_ci//
67b877906bSopenharmony_cistatic DWORD getWindowExStyle(const _GLFWwindow* window)
68b877906bSopenharmony_ci{
69b877906bSopenharmony_ci    DWORD style = WS_EX_APPWINDOW;
70b877906bSopenharmony_ci
71b877906bSopenharmony_ci    if (window->monitor || window->floating)
72b877906bSopenharmony_ci        style |= WS_EX_TOPMOST;
73b877906bSopenharmony_ci
74b877906bSopenharmony_ci    return style;
75b877906bSopenharmony_ci}
76b877906bSopenharmony_ci
77b877906bSopenharmony_ci// Returns the image whose area most closely matches the desired one
78b877906bSopenharmony_ci//
79b877906bSopenharmony_cistatic const GLFWimage* chooseImage(int count, const GLFWimage* images,
80b877906bSopenharmony_ci                                    int width, int height)
81b877906bSopenharmony_ci{
82b877906bSopenharmony_ci    int i, leastDiff = INT_MAX;
83b877906bSopenharmony_ci    const GLFWimage* closest = NULL;
84b877906bSopenharmony_ci
85b877906bSopenharmony_ci    for (i = 0;  i < count;  i++)
86b877906bSopenharmony_ci    {
87b877906bSopenharmony_ci        const int currDiff = abs(images[i].width * images[i].height -
88b877906bSopenharmony_ci                                 width * height);
89b877906bSopenharmony_ci        if (currDiff < leastDiff)
90b877906bSopenharmony_ci        {
91b877906bSopenharmony_ci            closest = images + i;
92b877906bSopenharmony_ci            leastDiff = currDiff;
93b877906bSopenharmony_ci        }
94b877906bSopenharmony_ci    }
95b877906bSopenharmony_ci
96b877906bSopenharmony_ci    return closest;
97b877906bSopenharmony_ci}
98b877906bSopenharmony_ci
99b877906bSopenharmony_ci// Creates an RGBA icon or cursor
100b877906bSopenharmony_ci//
101b877906bSopenharmony_cistatic HICON createIcon(const GLFWimage* image, int xhot, int yhot, GLFWbool icon)
102b877906bSopenharmony_ci{
103b877906bSopenharmony_ci    int i;
104b877906bSopenharmony_ci    HDC dc;
105b877906bSopenharmony_ci    HICON handle;
106b877906bSopenharmony_ci    HBITMAP color, mask;
107b877906bSopenharmony_ci    BITMAPV5HEADER bi;
108b877906bSopenharmony_ci    ICONINFO ii;
109b877906bSopenharmony_ci    unsigned char* target = NULL;
110b877906bSopenharmony_ci    unsigned char* source = image->pixels;
111b877906bSopenharmony_ci
112b877906bSopenharmony_ci    ZeroMemory(&bi, sizeof(bi));
113b877906bSopenharmony_ci    bi.bV5Size        = sizeof(bi);
114b877906bSopenharmony_ci    bi.bV5Width       = image->width;
115b877906bSopenharmony_ci    bi.bV5Height      = -image->height;
116b877906bSopenharmony_ci    bi.bV5Planes      = 1;
117b877906bSopenharmony_ci    bi.bV5BitCount    = 32;
118b877906bSopenharmony_ci    bi.bV5Compression = BI_BITFIELDS;
119b877906bSopenharmony_ci    bi.bV5RedMask     = 0x00ff0000;
120b877906bSopenharmony_ci    bi.bV5GreenMask   = 0x0000ff00;
121b877906bSopenharmony_ci    bi.bV5BlueMask    = 0x000000ff;
122b877906bSopenharmony_ci    bi.bV5AlphaMask   = 0xff000000;
123b877906bSopenharmony_ci
124b877906bSopenharmony_ci    dc = GetDC(NULL);
125b877906bSopenharmony_ci    color = CreateDIBSection(dc,
126b877906bSopenharmony_ci                             (BITMAPINFO*) &bi,
127b877906bSopenharmony_ci                             DIB_RGB_COLORS,
128b877906bSopenharmony_ci                             (void**) &target,
129b877906bSopenharmony_ci                             NULL,
130b877906bSopenharmony_ci                             (DWORD) 0);
131b877906bSopenharmony_ci    ReleaseDC(NULL, dc);
132b877906bSopenharmony_ci
133b877906bSopenharmony_ci    if (!color)
134b877906bSopenharmony_ci    {
135b877906bSopenharmony_ci        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
136b877906bSopenharmony_ci                             "Win32: Failed to create RGBA bitmap");
137b877906bSopenharmony_ci        return NULL;
138b877906bSopenharmony_ci    }
139b877906bSopenharmony_ci
140b877906bSopenharmony_ci    mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
141b877906bSopenharmony_ci    if (!mask)
142b877906bSopenharmony_ci    {
143b877906bSopenharmony_ci        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
144b877906bSopenharmony_ci                             "Win32: Failed to create mask bitmap");
145b877906bSopenharmony_ci        DeleteObject(color);
146b877906bSopenharmony_ci        return NULL;
147b877906bSopenharmony_ci    }
148b877906bSopenharmony_ci
149b877906bSopenharmony_ci    for (i = 0;  i < image->width * image->height;  i++)
150b877906bSopenharmony_ci    {
151b877906bSopenharmony_ci        target[0] = source[2];
152b877906bSopenharmony_ci        target[1] = source[1];
153b877906bSopenharmony_ci        target[2] = source[0];
154b877906bSopenharmony_ci        target[3] = source[3];
155b877906bSopenharmony_ci        target += 4;
156b877906bSopenharmony_ci        source += 4;
157b877906bSopenharmony_ci    }
158b877906bSopenharmony_ci
159b877906bSopenharmony_ci    ZeroMemory(&ii, sizeof(ii));
160b877906bSopenharmony_ci    ii.fIcon    = icon;
161b877906bSopenharmony_ci    ii.xHotspot = xhot;
162b877906bSopenharmony_ci    ii.yHotspot = yhot;
163b877906bSopenharmony_ci    ii.hbmMask  = mask;
164b877906bSopenharmony_ci    ii.hbmColor = color;
165b877906bSopenharmony_ci
166b877906bSopenharmony_ci    handle = CreateIconIndirect(&ii);
167b877906bSopenharmony_ci
168b877906bSopenharmony_ci    DeleteObject(color);
169b877906bSopenharmony_ci    DeleteObject(mask);
170b877906bSopenharmony_ci
171b877906bSopenharmony_ci    if (!handle)
172b877906bSopenharmony_ci    {
173b877906bSopenharmony_ci        if (icon)
174b877906bSopenharmony_ci        {
175b877906bSopenharmony_ci            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
176b877906bSopenharmony_ci                                 "Win32: Failed to create icon");
177b877906bSopenharmony_ci        }
178b877906bSopenharmony_ci        else
179b877906bSopenharmony_ci        {
180b877906bSopenharmony_ci            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
181b877906bSopenharmony_ci                                 "Win32: Failed to create cursor");
182b877906bSopenharmony_ci        }
183b877906bSopenharmony_ci    }
184b877906bSopenharmony_ci
185b877906bSopenharmony_ci    return handle;
186b877906bSopenharmony_ci}
187b877906bSopenharmony_ci
188b877906bSopenharmony_ci// Enforce the content area aspect ratio based on which edge is being dragged
189b877906bSopenharmony_ci//
190b877906bSopenharmony_cistatic void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
191b877906bSopenharmony_ci{
192b877906bSopenharmony_ci    RECT frame = {0};
193b877906bSopenharmony_ci    const float ratio = (float) window->numer / (float) window->denom;
194b877906bSopenharmony_ci    const DWORD style = getWindowStyle(window);
195b877906bSopenharmony_ci    const DWORD exStyle = getWindowExStyle(window);
196b877906bSopenharmony_ci
197b877906bSopenharmony_ci    if (_glfwIsWindows10Version1607OrGreaterWin32())
198b877906bSopenharmony_ci    {
199b877906bSopenharmony_ci        AdjustWindowRectExForDpi(&frame, style, FALSE, exStyle,
200b877906bSopenharmony_ci                                 GetDpiForWindow(window->win32.handle));
201b877906bSopenharmony_ci    }
202b877906bSopenharmony_ci    else
203b877906bSopenharmony_ci        AdjustWindowRectEx(&frame, style, FALSE, exStyle);
204b877906bSopenharmony_ci
205b877906bSopenharmony_ci    if (edge == WMSZ_LEFT  || edge == WMSZ_BOTTOMLEFT ||
206b877906bSopenharmony_ci        edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT)
207b877906bSopenharmony_ci    {
208b877906bSopenharmony_ci        area->bottom = area->top + (frame.bottom - frame.top) +
209b877906bSopenharmony_ci            (int) (((area->right - area->left) - (frame.right - frame.left)) / ratio);
210b877906bSopenharmony_ci    }
211b877906bSopenharmony_ci    else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT)
212b877906bSopenharmony_ci    {
213b877906bSopenharmony_ci        area->top = area->bottom - (frame.bottom - frame.top) -
214b877906bSopenharmony_ci            (int) (((area->right - area->left) - (frame.right - frame.left)) / ratio);
215b877906bSopenharmony_ci    }
216b877906bSopenharmony_ci    else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM)
217b877906bSopenharmony_ci    {
218b877906bSopenharmony_ci        area->right = area->left + (frame.right - frame.left) +
219b877906bSopenharmony_ci            (int) (((area->bottom - area->top) - (frame.bottom - frame.top)) * ratio);
220b877906bSopenharmony_ci    }
221b877906bSopenharmony_ci}
222b877906bSopenharmony_ci
223b877906bSopenharmony_ci// Updates the cursor image according to its cursor mode
224b877906bSopenharmony_ci//
225b877906bSopenharmony_cistatic void updateCursorImage(_GLFWwindow* window)
226b877906bSopenharmony_ci{
227b877906bSopenharmony_ci    if (window->cursorMode == GLFW_CURSOR_NORMAL ||
228b877906bSopenharmony_ci        window->cursorMode == GLFW_CURSOR_CAPTURED)
229b877906bSopenharmony_ci    {
230b877906bSopenharmony_ci        if (window->cursor)
231b877906bSopenharmony_ci            SetCursor(window->cursor->win32.handle);
232b877906bSopenharmony_ci        else
233b877906bSopenharmony_ci            SetCursor(LoadCursorW(NULL, IDC_ARROW));
234b877906bSopenharmony_ci    }
235b877906bSopenharmony_ci    else
236b877906bSopenharmony_ci    {
237b877906bSopenharmony_ci        // NOTE: Via Remote Desktop, setting the cursor to NULL does not hide it.
238b877906bSopenharmony_ci        // HACK: When running locally, it is set to NULL, but when connected via Remote
239b877906bSopenharmony_ci        //       Desktop, this is a transparent cursor.
240b877906bSopenharmony_ci        SetCursor(_glfw.win32.blankCursor);
241b877906bSopenharmony_ci    }
242b877906bSopenharmony_ci}
243b877906bSopenharmony_ci
244b877906bSopenharmony_ci// Sets the cursor clip rect to the window content area
245b877906bSopenharmony_ci//
246b877906bSopenharmony_cistatic void captureCursor(_GLFWwindow* window)
247b877906bSopenharmony_ci{
248b877906bSopenharmony_ci    RECT clipRect;
249b877906bSopenharmony_ci    GetClientRect(window->win32.handle, &clipRect);
250b877906bSopenharmony_ci    ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
251b877906bSopenharmony_ci    ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
252b877906bSopenharmony_ci    ClipCursor(&clipRect);
253b877906bSopenharmony_ci    _glfw.win32.capturedCursorWindow = window;
254b877906bSopenharmony_ci}
255b877906bSopenharmony_ci
256b877906bSopenharmony_ci// Disabled clip cursor
257b877906bSopenharmony_ci//
258b877906bSopenharmony_cistatic void releaseCursor(void)
259b877906bSopenharmony_ci{
260b877906bSopenharmony_ci    ClipCursor(NULL);
261b877906bSopenharmony_ci    _glfw.win32.capturedCursorWindow = NULL;
262b877906bSopenharmony_ci}
263b877906bSopenharmony_ci
264b877906bSopenharmony_ci// Enables WM_INPUT messages for the mouse for the specified window
265b877906bSopenharmony_ci//
266b877906bSopenharmony_cistatic void enableRawMouseMotion(_GLFWwindow* window)
267b877906bSopenharmony_ci{
268b877906bSopenharmony_ci    const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };
269b877906bSopenharmony_ci
270b877906bSopenharmony_ci    if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
271b877906bSopenharmony_ci    {
272b877906bSopenharmony_ci        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
273b877906bSopenharmony_ci                             "Win32: Failed to register raw input device");
274b877906bSopenharmony_ci    }
275b877906bSopenharmony_ci}
276b877906bSopenharmony_ci
277b877906bSopenharmony_ci// Disables WM_INPUT messages for the mouse
278b877906bSopenharmony_ci//
279b877906bSopenharmony_cistatic void disableRawMouseMotion(_GLFWwindow* window)
280b877906bSopenharmony_ci{
281b877906bSopenharmony_ci    const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL };
282b877906bSopenharmony_ci
283b877906bSopenharmony_ci    if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
284b877906bSopenharmony_ci    {
285b877906bSopenharmony_ci        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
286b877906bSopenharmony_ci                             "Win32: Failed to remove raw input device");
287b877906bSopenharmony_ci    }
288b877906bSopenharmony_ci}
289b877906bSopenharmony_ci
290b877906bSopenharmony_ci// Apply disabled cursor mode to a focused window
291b877906bSopenharmony_ci//
292b877906bSopenharmony_cistatic void disableCursor(_GLFWwindow* window)
293b877906bSopenharmony_ci{
294b877906bSopenharmony_ci    _glfw.win32.disabledCursorWindow = window;
295b877906bSopenharmony_ci    _glfwGetCursorPosWin32(window,
296b877906bSopenharmony_ci                           &_glfw.win32.restoreCursorPosX,
297b877906bSopenharmony_ci                           &_glfw.win32.restoreCursorPosY);
298b877906bSopenharmony_ci    updateCursorImage(window);
299b877906bSopenharmony_ci    _glfwCenterCursorInContentArea(window);
300b877906bSopenharmony_ci    captureCursor(window);
301b877906bSopenharmony_ci
302b877906bSopenharmony_ci    if (window->rawMouseMotion)
303b877906bSopenharmony_ci        enableRawMouseMotion(window);
304b877906bSopenharmony_ci}
305b877906bSopenharmony_ci
306b877906bSopenharmony_ci// Exit disabled cursor mode for the specified window
307b877906bSopenharmony_ci//
308b877906bSopenharmony_cistatic void enableCursor(_GLFWwindow* window)
309b877906bSopenharmony_ci{
310b877906bSopenharmony_ci    if (window->rawMouseMotion)
311b877906bSopenharmony_ci        disableRawMouseMotion(window);
312b877906bSopenharmony_ci
313b877906bSopenharmony_ci    _glfw.win32.disabledCursorWindow = NULL;
314b877906bSopenharmony_ci    releaseCursor();
315b877906bSopenharmony_ci    _glfwSetCursorPosWin32(window,
316b877906bSopenharmony_ci                           _glfw.win32.restoreCursorPosX,
317b877906bSopenharmony_ci                           _glfw.win32.restoreCursorPosY);
318b877906bSopenharmony_ci    updateCursorImage(window);
319b877906bSopenharmony_ci}
320b877906bSopenharmony_ci
321b877906bSopenharmony_ci// Returns whether the cursor is in the content area of the specified window
322b877906bSopenharmony_ci//
323b877906bSopenharmony_cistatic GLFWbool cursorInContentArea(_GLFWwindow* window)
324b877906bSopenharmony_ci{
325b877906bSopenharmony_ci    RECT area;
326b877906bSopenharmony_ci    POINT pos;
327b877906bSopenharmony_ci
328b877906bSopenharmony_ci    if (!GetCursorPos(&pos))
329b877906bSopenharmony_ci        return GLFW_FALSE;
330b877906bSopenharmony_ci
331b877906bSopenharmony_ci    if (WindowFromPoint(pos) != window->win32.handle)
332b877906bSopenharmony_ci        return GLFW_FALSE;
333b877906bSopenharmony_ci
334b877906bSopenharmony_ci    GetClientRect(window->win32.handle, &area);
335b877906bSopenharmony_ci    ClientToScreen(window->win32.handle, (POINT*) &area.left);
336b877906bSopenharmony_ci    ClientToScreen(window->win32.handle, (POINT*) &area.right);
337b877906bSopenharmony_ci
338b877906bSopenharmony_ci    return PtInRect(&area, pos);
339b877906bSopenharmony_ci}
340b877906bSopenharmony_ci
341b877906bSopenharmony_ci// Update native window styles to match attributes
342b877906bSopenharmony_ci//
343b877906bSopenharmony_cistatic void updateWindowStyles(const _GLFWwindow* window)
344b877906bSopenharmony_ci{
345b877906bSopenharmony_ci    RECT rect;
346b877906bSopenharmony_ci    DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
347b877906bSopenharmony_ci    style &= ~(WS_OVERLAPPEDWINDOW | WS_POPUP);
348b877906bSopenharmony_ci    style |= getWindowStyle(window);
349b877906bSopenharmony_ci
350b877906bSopenharmony_ci    GetClientRect(window->win32.handle, &rect);
351b877906bSopenharmony_ci
352b877906bSopenharmony_ci    if (_glfwIsWindows10Version1607OrGreaterWin32())
353b877906bSopenharmony_ci    {
354b877906bSopenharmony_ci        AdjustWindowRectExForDpi(&rect, style, FALSE,
355b877906bSopenharmony_ci                                 getWindowExStyle(window),
356b877906bSopenharmony_ci                                 GetDpiForWindow(window->win32.handle));
357b877906bSopenharmony_ci    }
358b877906bSopenharmony_ci    else
359b877906bSopenharmony_ci        AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window));
360b877906bSopenharmony_ci
361b877906bSopenharmony_ci    ClientToScreen(window->win32.handle, (POINT*) &rect.left);
362b877906bSopenharmony_ci    ClientToScreen(window->win32.handle, (POINT*) &rect.right);
363b877906bSopenharmony_ci    SetWindowLongW(window->win32.handle, GWL_STYLE, style);
364b877906bSopenharmony_ci    SetWindowPos(window->win32.handle, HWND_TOP,
365b877906bSopenharmony_ci                 rect.left, rect.top,
366b877906bSopenharmony_ci                 rect.right - rect.left, rect.bottom - rect.top,
367b877906bSopenharmony_ci                 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
368b877906bSopenharmony_ci}
369b877906bSopenharmony_ci
370b877906bSopenharmony_ci// Update window framebuffer transparency
371b877906bSopenharmony_ci//
372b877906bSopenharmony_cistatic void updateFramebufferTransparency(const _GLFWwindow* window)
373b877906bSopenharmony_ci{
374b877906bSopenharmony_ci    BOOL composition, opaque;
375b877906bSopenharmony_ci    DWORD color;
376b877906bSopenharmony_ci
377b877906bSopenharmony_ci    if (!IsWindowsVistaOrGreater())
378b877906bSopenharmony_ci        return;
379b877906bSopenharmony_ci
380b877906bSopenharmony_ci    if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)
381b877906bSopenharmony_ci       return;
382b877906bSopenharmony_ci
383b877906bSopenharmony_ci    if (IsWindows8OrGreater() ||
384b877906bSopenharmony_ci        (SUCCEEDED(DwmGetColorizationColor(&color, &opaque)) && !opaque))
385b877906bSopenharmony_ci    {
386b877906bSopenharmony_ci        HRGN region = CreateRectRgn(0, 0, -1, -1);
387b877906bSopenharmony_ci        DWM_BLURBEHIND bb = {0};
388b877906bSopenharmony_ci        bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
389b877906bSopenharmony_ci        bb.hRgnBlur = region;
390b877906bSopenharmony_ci        bb.fEnable = TRUE;
391b877906bSopenharmony_ci
392b877906bSopenharmony_ci        DwmEnableBlurBehindWindow(window->win32.handle, &bb);
393b877906bSopenharmony_ci        DeleteObject(region);
394b877906bSopenharmony_ci    }
395b877906bSopenharmony_ci    else
396b877906bSopenharmony_ci    {
397b877906bSopenharmony_ci        // HACK: Disable framebuffer transparency on Windows 7 when the
398b877906bSopenharmony_ci        //       colorization color is opaque, because otherwise the window
399b877906bSopenharmony_ci        //       contents is blended additively with the previous frame instead
400b877906bSopenharmony_ci        //       of replacing it
401b877906bSopenharmony_ci        DWM_BLURBEHIND bb = {0};
402b877906bSopenharmony_ci        bb.dwFlags = DWM_BB_ENABLE;
403b877906bSopenharmony_ci        DwmEnableBlurBehindWindow(window->win32.handle, &bb);
404b877906bSopenharmony_ci    }
405b877906bSopenharmony_ci}
406b877906bSopenharmony_ci
407b877906bSopenharmony_ci// Retrieves and translates modifier keys
408b877906bSopenharmony_ci//
409b877906bSopenharmony_cistatic int getKeyMods(void)
410b877906bSopenharmony_ci{
411b877906bSopenharmony_ci    int mods = 0;
412b877906bSopenharmony_ci
413b877906bSopenharmony_ci    if (GetKeyState(VK_SHIFT) & 0x8000)
414b877906bSopenharmony_ci        mods |= GLFW_MOD_SHIFT;
415b877906bSopenharmony_ci    if (GetKeyState(VK_CONTROL) & 0x8000)
416b877906bSopenharmony_ci        mods |= GLFW_MOD_CONTROL;
417b877906bSopenharmony_ci    if (GetKeyState(VK_MENU) & 0x8000)
418b877906bSopenharmony_ci        mods |= GLFW_MOD_ALT;
419b877906bSopenharmony_ci    if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x8000)
420b877906bSopenharmony_ci        mods |= GLFW_MOD_SUPER;
421b877906bSopenharmony_ci    if (GetKeyState(VK_CAPITAL) & 1)
422b877906bSopenharmony_ci        mods |= GLFW_MOD_CAPS_LOCK;
423b877906bSopenharmony_ci    if (GetKeyState(VK_NUMLOCK) & 1)
424b877906bSopenharmony_ci        mods |= GLFW_MOD_NUM_LOCK;
425b877906bSopenharmony_ci
426b877906bSopenharmony_ci    return mods;
427b877906bSopenharmony_ci}
428b877906bSopenharmony_ci
429b877906bSopenharmony_cistatic void fitToMonitor(_GLFWwindow* window)
430b877906bSopenharmony_ci{
431b877906bSopenharmony_ci    MONITORINFO mi = { sizeof(mi) };
432b877906bSopenharmony_ci    GetMonitorInfoW(window->monitor->win32.handle, &mi);
433b877906bSopenharmony_ci    SetWindowPos(window->win32.handle, HWND_TOPMOST,
434b877906bSopenharmony_ci                 mi.rcMonitor.left,
435b877906bSopenharmony_ci                 mi.rcMonitor.top,
436b877906bSopenharmony_ci                 mi.rcMonitor.right - mi.rcMonitor.left,
437b877906bSopenharmony_ci                 mi.rcMonitor.bottom - mi.rcMonitor.top,
438b877906bSopenharmony_ci                 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);
439b877906bSopenharmony_ci}
440b877906bSopenharmony_ci
441b877906bSopenharmony_ci// Make the specified window and its video mode active on its monitor
442b877906bSopenharmony_ci//
443b877906bSopenharmony_cistatic void acquireMonitor(_GLFWwindow* window)
444b877906bSopenharmony_ci{
445b877906bSopenharmony_ci    if (!_glfw.win32.acquiredMonitorCount)
446b877906bSopenharmony_ci    {
447b877906bSopenharmony_ci        SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
448b877906bSopenharmony_ci
449b877906bSopenharmony_ci        // HACK: When mouse trails are enabled the cursor becomes invisible when
450b877906bSopenharmony_ci        //       the OpenGL ICD switches to page flipping
451b877906bSopenharmony_ci        SystemParametersInfoW(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
452b877906bSopenharmony_ci        SystemParametersInfoW(SPI_SETMOUSETRAILS, 0, 0, 0);
453b877906bSopenharmony_ci    }
454b877906bSopenharmony_ci
455b877906bSopenharmony_ci    if (!window->monitor->window)
456b877906bSopenharmony_ci        _glfw.win32.acquiredMonitorCount++;
457b877906bSopenharmony_ci
458b877906bSopenharmony_ci    _glfwSetVideoModeWin32(window->monitor, &window->videoMode);
459b877906bSopenharmony_ci    _glfwInputMonitorWindow(window->monitor, window);
460b877906bSopenharmony_ci}
461b877906bSopenharmony_ci
462b877906bSopenharmony_ci// Remove the window and restore the original video mode
463b877906bSopenharmony_ci//
464b877906bSopenharmony_cistatic void releaseMonitor(_GLFWwindow* window)
465b877906bSopenharmony_ci{
466b877906bSopenharmony_ci    if (window->monitor->window != window)
467b877906bSopenharmony_ci        return;
468b877906bSopenharmony_ci
469b877906bSopenharmony_ci    _glfw.win32.acquiredMonitorCount--;
470b877906bSopenharmony_ci    if (!_glfw.win32.acquiredMonitorCount)
471b877906bSopenharmony_ci    {
472b877906bSopenharmony_ci        SetThreadExecutionState(ES_CONTINUOUS);
473b877906bSopenharmony_ci
474b877906bSopenharmony_ci        // HACK: Restore mouse trail length saved in acquireMonitor
475b877906bSopenharmony_ci        SystemParametersInfoW(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
476b877906bSopenharmony_ci    }
477b877906bSopenharmony_ci
478b877906bSopenharmony_ci    _glfwInputMonitorWindow(window->monitor, NULL);
479b877906bSopenharmony_ci    _glfwRestoreVideoModeWin32(window->monitor);
480b877906bSopenharmony_ci}
481b877906bSopenharmony_ci
482b877906bSopenharmony_ci// Manually maximize the window, for when SW_MAXIMIZE cannot be used
483b877906bSopenharmony_ci//
484b877906bSopenharmony_cistatic void maximizeWindowManually(_GLFWwindow* window)
485b877906bSopenharmony_ci{
486b877906bSopenharmony_ci    RECT rect;
487b877906bSopenharmony_ci    DWORD style;
488b877906bSopenharmony_ci    MONITORINFO mi = { sizeof(mi) };
489b877906bSopenharmony_ci
490b877906bSopenharmony_ci    GetMonitorInfoW(MonitorFromWindow(window->win32.handle,
491b877906bSopenharmony_ci                                      MONITOR_DEFAULTTONEAREST), &mi);
492b877906bSopenharmony_ci
493b877906bSopenharmony_ci    rect = mi.rcWork;
494b877906bSopenharmony_ci
495b877906bSopenharmony_ci    if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)
496b877906bSopenharmony_ci    {
497b877906bSopenharmony_ci        rect.right = _glfw_min(rect.right, rect.left + window->maxwidth);
498b877906bSopenharmony_ci        rect.bottom = _glfw_min(rect.bottom, rect.top + window->maxheight);
499b877906bSopenharmony_ci    }
500b877906bSopenharmony_ci
501b877906bSopenharmony_ci    style = GetWindowLongW(window->win32.handle, GWL_STYLE);
502b877906bSopenharmony_ci    style |= WS_MAXIMIZE;
503b877906bSopenharmony_ci    SetWindowLongW(window->win32.handle, GWL_STYLE, style);
504b877906bSopenharmony_ci
505b877906bSopenharmony_ci    if (window->decorated)
506b877906bSopenharmony_ci    {
507b877906bSopenharmony_ci        const DWORD exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
508b877906bSopenharmony_ci
509b877906bSopenharmony_ci        if (_glfwIsWindows10Version1607OrGreaterWin32())
510b877906bSopenharmony_ci        {
511b877906bSopenharmony_ci            const UINT dpi = GetDpiForWindow(window->win32.handle);
512b877906bSopenharmony_ci            AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
513b877906bSopenharmony_ci            OffsetRect(&rect, 0, GetSystemMetricsForDpi(SM_CYCAPTION, dpi));
514b877906bSopenharmony_ci        }
515b877906bSopenharmony_ci        else
516b877906bSopenharmony_ci        {
517b877906bSopenharmony_ci            AdjustWindowRectEx(&rect, style, FALSE, exStyle);
518b877906bSopenharmony_ci            OffsetRect(&rect, 0, GetSystemMetrics(SM_CYCAPTION));
519b877906bSopenharmony_ci        }
520b877906bSopenharmony_ci
521b877906bSopenharmony_ci        rect.bottom = _glfw_min(rect.bottom, mi.rcWork.bottom);
522b877906bSopenharmony_ci    }
523b877906bSopenharmony_ci
524b877906bSopenharmony_ci    SetWindowPos(window->win32.handle, HWND_TOP,
525b877906bSopenharmony_ci                 rect.left,
526b877906bSopenharmony_ci                 rect.top,
527b877906bSopenharmony_ci                 rect.right - rect.left,
528b877906bSopenharmony_ci                 rect.bottom - rect.top,
529b877906bSopenharmony_ci                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
530b877906bSopenharmony_ci}
531b877906bSopenharmony_ci
532b877906bSopenharmony_ci// Window procedure for user-created windows
533b877906bSopenharmony_ci//
534b877906bSopenharmony_cistatic LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
535b877906bSopenharmony_ci{
536b877906bSopenharmony_ci    _GLFWwindow* window = GetPropW(hWnd, L"GLFW");
537b877906bSopenharmony_ci    if (!window)
538b877906bSopenharmony_ci    {
539b877906bSopenharmony_ci        if (uMsg == WM_NCCREATE)
540b877906bSopenharmony_ci        {
541b877906bSopenharmony_ci            if (_glfwIsWindows10Version1607OrGreaterWin32())
542b877906bSopenharmony_ci            {
543b877906bSopenharmony_ci                const CREATESTRUCTW* cs = (const CREATESTRUCTW*) lParam;
544b877906bSopenharmony_ci                const _GLFWwndconfig* wndconfig = cs->lpCreateParams;
545b877906bSopenharmony_ci
546b877906bSopenharmony_ci                // On per-monitor DPI aware V1 systems, only enable
547b877906bSopenharmony_ci                // non-client scaling for windows that scale the client area
548b877906bSopenharmony_ci                // We need WM_GETDPISCALEDSIZE from V2 to keep the client
549b877906bSopenharmony_ci                // area static when the non-client area is scaled
550b877906bSopenharmony_ci                if (wndconfig && wndconfig->scaleToMonitor)
551b877906bSopenharmony_ci                    EnableNonClientDpiScaling(hWnd);
552b877906bSopenharmony_ci            }
553b877906bSopenharmony_ci        }
554b877906bSopenharmony_ci
555b877906bSopenharmony_ci        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
556b877906bSopenharmony_ci    }
557b877906bSopenharmony_ci
558b877906bSopenharmony_ci    switch (uMsg)
559b877906bSopenharmony_ci    {
560b877906bSopenharmony_ci        case WM_MOUSEACTIVATE:
561b877906bSopenharmony_ci        {
562b877906bSopenharmony_ci            // HACK: Postpone cursor disabling when the window was activated by
563b877906bSopenharmony_ci            //       clicking a caption button
564b877906bSopenharmony_ci            if (HIWORD(lParam) == WM_LBUTTONDOWN)
565b877906bSopenharmony_ci            {
566b877906bSopenharmony_ci                if (LOWORD(lParam) != HTCLIENT)
567b877906bSopenharmony_ci                    window->win32.frameAction = GLFW_TRUE;
568b877906bSopenharmony_ci            }
569b877906bSopenharmony_ci
570b877906bSopenharmony_ci            break;
571b877906bSopenharmony_ci        }
572b877906bSopenharmony_ci
573b877906bSopenharmony_ci        case WM_CAPTURECHANGED:
574b877906bSopenharmony_ci        {
575b877906bSopenharmony_ci            // HACK: Disable the cursor once the caption button action has been
576b877906bSopenharmony_ci            //       completed or cancelled
577b877906bSopenharmony_ci            if (lParam == 0 && window->win32.frameAction)
578b877906bSopenharmony_ci            {
579b877906bSopenharmony_ci                if (window->cursorMode == GLFW_CURSOR_DISABLED)
580b877906bSopenharmony_ci                    disableCursor(window);
581b877906bSopenharmony_ci                else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
582b877906bSopenharmony_ci                    captureCursor(window);
583b877906bSopenharmony_ci
584b877906bSopenharmony_ci                window->win32.frameAction = GLFW_FALSE;
585b877906bSopenharmony_ci            }
586b877906bSopenharmony_ci
587b877906bSopenharmony_ci            break;
588b877906bSopenharmony_ci        }
589b877906bSopenharmony_ci
590b877906bSopenharmony_ci        case WM_SETFOCUS:
591b877906bSopenharmony_ci        {
592b877906bSopenharmony_ci            _glfwInputWindowFocus(window, GLFW_TRUE);
593b877906bSopenharmony_ci
594b877906bSopenharmony_ci            // HACK: Do not disable cursor while the user is interacting with
595b877906bSopenharmony_ci            //       a caption button
596b877906bSopenharmony_ci            if (window->win32.frameAction)
597b877906bSopenharmony_ci                break;
598b877906bSopenharmony_ci
599b877906bSopenharmony_ci            if (window->cursorMode == GLFW_CURSOR_DISABLED)
600b877906bSopenharmony_ci                disableCursor(window);
601b877906bSopenharmony_ci            else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
602b877906bSopenharmony_ci                captureCursor(window);
603b877906bSopenharmony_ci
604b877906bSopenharmony_ci            return 0;
605b877906bSopenharmony_ci        }
606b877906bSopenharmony_ci
607b877906bSopenharmony_ci        case WM_KILLFOCUS:
608b877906bSopenharmony_ci        {
609b877906bSopenharmony_ci            if (window->cursorMode == GLFW_CURSOR_DISABLED)
610b877906bSopenharmony_ci                enableCursor(window);
611b877906bSopenharmony_ci            else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
612b877906bSopenharmony_ci                releaseCursor();
613b877906bSopenharmony_ci
614b877906bSopenharmony_ci            if (window->monitor && window->autoIconify)
615b877906bSopenharmony_ci                _glfwIconifyWindowWin32(window);
616b877906bSopenharmony_ci
617b877906bSopenharmony_ci            _glfwInputWindowFocus(window, GLFW_FALSE);
618b877906bSopenharmony_ci            return 0;
619b877906bSopenharmony_ci        }
620b877906bSopenharmony_ci
621b877906bSopenharmony_ci        case WM_SYSCOMMAND:
622b877906bSopenharmony_ci        {
623b877906bSopenharmony_ci            switch (wParam & 0xfff0)
624b877906bSopenharmony_ci            {
625b877906bSopenharmony_ci                case SC_SCREENSAVE:
626b877906bSopenharmony_ci                case SC_MONITORPOWER:
627b877906bSopenharmony_ci                {
628b877906bSopenharmony_ci                    if (window->monitor)
629b877906bSopenharmony_ci                    {
630b877906bSopenharmony_ci                        // We are running in full screen mode, so disallow
631b877906bSopenharmony_ci                        // screen saver and screen blanking
632b877906bSopenharmony_ci                        return 0;
633b877906bSopenharmony_ci                    }
634b877906bSopenharmony_ci                    else
635b877906bSopenharmony_ci                        break;
636b877906bSopenharmony_ci                }
637b877906bSopenharmony_ci
638b877906bSopenharmony_ci                // User trying to access application menu using ALT?
639b877906bSopenharmony_ci                case SC_KEYMENU:
640b877906bSopenharmony_ci                {
641b877906bSopenharmony_ci                    if (!window->win32.keymenu)
642b877906bSopenharmony_ci                        return 0;
643b877906bSopenharmony_ci
644b877906bSopenharmony_ci                    break;
645b877906bSopenharmony_ci                }
646b877906bSopenharmony_ci            }
647b877906bSopenharmony_ci            break;
648b877906bSopenharmony_ci        }
649b877906bSopenharmony_ci
650b877906bSopenharmony_ci        case WM_CLOSE:
651b877906bSopenharmony_ci        {
652b877906bSopenharmony_ci            _glfwInputWindowCloseRequest(window);
653b877906bSopenharmony_ci            return 0;
654b877906bSopenharmony_ci        }
655b877906bSopenharmony_ci
656b877906bSopenharmony_ci        case WM_INPUTLANGCHANGE:
657b877906bSopenharmony_ci        {
658b877906bSopenharmony_ci            _glfwUpdateKeyNamesWin32();
659b877906bSopenharmony_ci            break;
660b877906bSopenharmony_ci        }
661b877906bSopenharmony_ci
662b877906bSopenharmony_ci        case WM_CHAR:
663b877906bSopenharmony_ci        case WM_SYSCHAR:
664b877906bSopenharmony_ci        {
665b877906bSopenharmony_ci            if (wParam >= 0xd800 && wParam <= 0xdbff)
666b877906bSopenharmony_ci                window->win32.highSurrogate = (WCHAR) wParam;
667b877906bSopenharmony_ci            else
668b877906bSopenharmony_ci            {
669b877906bSopenharmony_ci                uint32_t codepoint = 0;
670b877906bSopenharmony_ci
671b877906bSopenharmony_ci                if (wParam >= 0xdc00 && wParam <= 0xdfff)
672b877906bSopenharmony_ci                {
673b877906bSopenharmony_ci                    if (window->win32.highSurrogate)
674b877906bSopenharmony_ci                    {
675b877906bSopenharmony_ci                        codepoint += (window->win32.highSurrogate - 0xd800) << 10;
676b877906bSopenharmony_ci                        codepoint += (WCHAR) wParam - 0xdc00;
677b877906bSopenharmony_ci                        codepoint += 0x10000;
678b877906bSopenharmony_ci                    }
679b877906bSopenharmony_ci                }
680b877906bSopenharmony_ci                else
681b877906bSopenharmony_ci                    codepoint = (WCHAR) wParam;
682b877906bSopenharmony_ci
683b877906bSopenharmony_ci                window->win32.highSurrogate = 0;
684b877906bSopenharmony_ci                _glfwInputChar(window, codepoint, getKeyMods(), uMsg != WM_SYSCHAR);
685b877906bSopenharmony_ci            }
686b877906bSopenharmony_ci
687b877906bSopenharmony_ci            if (uMsg == WM_SYSCHAR && window->win32.keymenu)
688b877906bSopenharmony_ci                break;
689b877906bSopenharmony_ci
690b877906bSopenharmony_ci            return 0;
691b877906bSopenharmony_ci        }
692b877906bSopenharmony_ci
693b877906bSopenharmony_ci        case WM_UNICHAR:
694b877906bSopenharmony_ci        {
695b877906bSopenharmony_ci            if (wParam == UNICODE_NOCHAR)
696b877906bSopenharmony_ci            {
697b877906bSopenharmony_ci                // WM_UNICHAR is not sent by Windows, but is sent by some
698b877906bSopenharmony_ci                // third-party input method engine
699b877906bSopenharmony_ci                // Returning TRUE here announces support for this message
700b877906bSopenharmony_ci                return TRUE;
701b877906bSopenharmony_ci            }
702b877906bSopenharmony_ci
703b877906bSopenharmony_ci            _glfwInputChar(window, (uint32_t) wParam, getKeyMods(), GLFW_TRUE);
704b877906bSopenharmony_ci            return 0;
705b877906bSopenharmony_ci        }
706b877906bSopenharmony_ci
707b877906bSopenharmony_ci        case WM_KEYDOWN:
708b877906bSopenharmony_ci        case WM_SYSKEYDOWN:
709b877906bSopenharmony_ci        case WM_KEYUP:
710b877906bSopenharmony_ci        case WM_SYSKEYUP:
711b877906bSopenharmony_ci        {
712b877906bSopenharmony_ci            int key, scancode;
713b877906bSopenharmony_ci            const int action = (HIWORD(lParam) & KF_UP) ? GLFW_RELEASE : GLFW_PRESS;
714b877906bSopenharmony_ci            const int mods = getKeyMods();
715b877906bSopenharmony_ci
716b877906bSopenharmony_ci            scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff));
717b877906bSopenharmony_ci            if (!scancode)
718b877906bSopenharmony_ci            {
719b877906bSopenharmony_ci                // NOTE: Some synthetic key messages have a scancode of zero
720b877906bSopenharmony_ci                // HACK: Map the virtual key back to a usable scancode
721b877906bSopenharmony_ci                scancode = MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC);
722b877906bSopenharmony_ci            }
723b877906bSopenharmony_ci
724b877906bSopenharmony_ci            // HACK: Alt+PrtSc has a different scancode than just PrtSc
725b877906bSopenharmony_ci            if (scancode == 0x54)
726b877906bSopenharmony_ci                scancode = 0x137;
727b877906bSopenharmony_ci
728b877906bSopenharmony_ci            // HACK: Ctrl+Pause has a different scancode than just Pause
729b877906bSopenharmony_ci            if (scancode == 0x146)
730b877906bSopenharmony_ci                scancode = 0x45;
731b877906bSopenharmony_ci
732b877906bSopenharmony_ci            // HACK: CJK IME sets the extended bit for right Shift
733b877906bSopenharmony_ci            if (scancode == 0x136)
734b877906bSopenharmony_ci                scancode = 0x36;
735b877906bSopenharmony_ci
736b877906bSopenharmony_ci            key = _glfw.win32.keycodes[scancode];
737b877906bSopenharmony_ci
738b877906bSopenharmony_ci            // The Ctrl keys require special handling
739b877906bSopenharmony_ci            if (wParam == VK_CONTROL)
740b877906bSopenharmony_ci            {
741b877906bSopenharmony_ci                if (HIWORD(lParam) & KF_EXTENDED)
742b877906bSopenharmony_ci                {
743b877906bSopenharmony_ci                    // Right side keys have the extended key bit set
744b877906bSopenharmony_ci                    key = GLFW_KEY_RIGHT_CONTROL;
745b877906bSopenharmony_ci                }
746b877906bSopenharmony_ci                else
747b877906bSopenharmony_ci                {
748b877906bSopenharmony_ci                    // NOTE: Alt Gr sends Left Ctrl followed by Right Alt
749b877906bSopenharmony_ci                    // HACK: We only want one event for Alt Gr, so if we detect
750b877906bSopenharmony_ci                    //       this sequence we discard this Left Ctrl message now
751b877906bSopenharmony_ci                    //       and later report Right Alt normally
752b877906bSopenharmony_ci                    MSG next;
753b877906bSopenharmony_ci                    const DWORD time = GetMessageTime();
754b877906bSopenharmony_ci
755b877906bSopenharmony_ci                    if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))
756b877906bSopenharmony_ci                    {
757b877906bSopenharmony_ci                        if (next.message == WM_KEYDOWN ||
758b877906bSopenharmony_ci                            next.message == WM_SYSKEYDOWN ||
759b877906bSopenharmony_ci                            next.message == WM_KEYUP ||
760b877906bSopenharmony_ci                            next.message == WM_SYSKEYUP)
761b877906bSopenharmony_ci                        {
762b877906bSopenharmony_ci                            if (next.wParam == VK_MENU &&
763b877906bSopenharmony_ci                                (HIWORD(next.lParam) & KF_EXTENDED) &&
764b877906bSopenharmony_ci                                next.time == time)
765b877906bSopenharmony_ci                            {
766b877906bSopenharmony_ci                                // Next message is Right Alt down so discard this
767b877906bSopenharmony_ci                                break;
768b877906bSopenharmony_ci                            }
769b877906bSopenharmony_ci                        }
770b877906bSopenharmony_ci                    }
771b877906bSopenharmony_ci
772b877906bSopenharmony_ci                    // This is a regular Left Ctrl message
773b877906bSopenharmony_ci                    key = GLFW_KEY_LEFT_CONTROL;
774b877906bSopenharmony_ci                }
775b877906bSopenharmony_ci            }
776b877906bSopenharmony_ci            else if (wParam == VK_PROCESSKEY)
777b877906bSopenharmony_ci            {
778b877906bSopenharmony_ci                // IME notifies that keys have been filtered by setting the
779b877906bSopenharmony_ci                // virtual key-code to VK_PROCESSKEY
780b877906bSopenharmony_ci                break;
781b877906bSopenharmony_ci            }
782b877906bSopenharmony_ci
783b877906bSopenharmony_ci            if (action == GLFW_RELEASE && wParam == VK_SHIFT)
784b877906bSopenharmony_ci            {
785b877906bSopenharmony_ci                // HACK: Release both Shift keys on Shift up event, as when both
786b877906bSopenharmony_ci                //       are pressed the first release does not emit any event
787b877906bSopenharmony_ci                // NOTE: The other half of this is in _glfwPollEventsWin32
788b877906bSopenharmony_ci                _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods);
789b877906bSopenharmony_ci                _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods);
790b877906bSopenharmony_ci            }
791b877906bSopenharmony_ci            else if (wParam == VK_SNAPSHOT)
792b877906bSopenharmony_ci            {
793b877906bSopenharmony_ci                // HACK: Key down is not reported for the Print Screen key
794b877906bSopenharmony_ci                _glfwInputKey(window, key, scancode, GLFW_PRESS, mods);
795b877906bSopenharmony_ci                _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods);
796b877906bSopenharmony_ci            }
797b877906bSopenharmony_ci            else
798b877906bSopenharmony_ci                _glfwInputKey(window, key, scancode, action, mods);
799b877906bSopenharmony_ci
800b877906bSopenharmony_ci            break;
801b877906bSopenharmony_ci        }
802b877906bSopenharmony_ci
803b877906bSopenharmony_ci        case WM_LBUTTONDOWN:
804b877906bSopenharmony_ci        case WM_RBUTTONDOWN:
805b877906bSopenharmony_ci        case WM_MBUTTONDOWN:
806b877906bSopenharmony_ci        case WM_XBUTTONDOWN:
807b877906bSopenharmony_ci        case WM_LBUTTONUP:
808b877906bSopenharmony_ci        case WM_RBUTTONUP:
809b877906bSopenharmony_ci        case WM_MBUTTONUP:
810b877906bSopenharmony_ci        case WM_XBUTTONUP:
811b877906bSopenharmony_ci        {
812b877906bSopenharmony_ci            int i, button, action;
813b877906bSopenharmony_ci
814b877906bSopenharmony_ci            if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
815b877906bSopenharmony_ci                button = GLFW_MOUSE_BUTTON_LEFT;
816b877906bSopenharmony_ci            else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP)
817b877906bSopenharmony_ci                button = GLFW_MOUSE_BUTTON_RIGHT;
818b877906bSopenharmony_ci            else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP)
819b877906bSopenharmony_ci                button = GLFW_MOUSE_BUTTON_MIDDLE;
820b877906bSopenharmony_ci            else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)
821b877906bSopenharmony_ci                button = GLFW_MOUSE_BUTTON_4;
822b877906bSopenharmony_ci            else
823b877906bSopenharmony_ci                button = GLFW_MOUSE_BUTTON_5;
824b877906bSopenharmony_ci
825b877906bSopenharmony_ci            if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN ||
826b877906bSopenharmony_ci                uMsg == WM_MBUTTONDOWN || uMsg == WM_XBUTTONDOWN)
827b877906bSopenharmony_ci            {
828b877906bSopenharmony_ci                action = GLFW_PRESS;
829b877906bSopenharmony_ci            }
830b877906bSopenharmony_ci            else
831b877906bSopenharmony_ci                action = GLFW_RELEASE;
832b877906bSopenharmony_ci
833b877906bSopenharmony_ci            for (i = 0;  i <= GLFW_MOUSE_BUTTON_LAST;  i++)
834b877906bSopenharmony_ci            {
835b877906bSopenharmony_ci                if (window->mouseButtons[i] == GLFW_PRESS)
836b877906bSopenharmony_ci                    break;
837b877906bSopenharmony_ci            }
838b877906bSopenharmony_ci
839b877906bSopenharmony_ci            if (i > GLFW_MOUSE_BUTTON_LAST)
840b877906bSopenharmony_ci                SetCapture(hWnd);
841b877906bSopenharmony_ci
842b877906bSopenharmony_ci            _glfwInputMouseClick(window, button, action, getKeyMods());
843b877906bSopenharmony_ci
844b877906bSopenharmony_ci            for (i = 0;  i <= GLFW_MOUSE_BUTTON_LAST;  i++)
845b877906bSopenharmony_ci            {
846b877906bSopenharmony_ci                if (window->mouseButtons[i] == GLFW_PRESS)
847b877906bSopenharmony_ci                    break;
848b877906bSopenharmony_ci            }
849b877906bSopenharmony_ci
850b877906bSopenharmony_ci            if (i > GLFW_MOUSE_BUTTON_LAST)
851b877906bSopenharmony_ci                ReleaseCapture();
852b877906bSopenharmony_ci
853b877906bSopenharmony_ci            if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP)
854b877906bSopenharmony_ci                return TRUE;
855b877906bSopenharmony_ci
856b877906bSopenharmony_ci            return 0;
857b877906bSopenharmony_ci        }
858b877906bSopenharmony_ci
859b877906bSopenharmony_ci        case WM_MOUSEMOVE:
860b877906bSopenharmony_ci        {
861b877906bSopenharmony_ci            const int x = GET_X_LPARAM(lParam);
862b877906bSopenharmony_ci            const int y = GET_Y_LPARAM(lParam);
863b877906bSopenharmony_ci
864b877906bSopenharmony_ci            if (!window->win32.cursorTracked)
865b877906bSopenharmony_ci            {
866b877906bSopenharmony_ci                TRACKMOUSEEVENT tme;
867b877906bSopenharmony_ci                ZeroMemory(&tme, sizeof(tme));
868b877906bSopenharmony_ci                tme.cbSize = sizeof(tme);
869b877906bSopenharmony_ci                tme.dwFlags = TME_LEAVE;
870b877906bSopenharmony_ci                tme.hwndTrack = window->win32.handle;
871b877906bSopenharmony_ci                TrackMouseEvent(&tme);
872b877906bSopenharmony_ci
873b877906bSopenharmony_ci                window->win32.cursorTracked = GLFW_TRUE;
874b877906bSopenharmony_ci                _glfwInputCursorEnter(window, GLFW_TRUE);
875b877906bSopenharmony_ci            }
876b877906bSopenharmony_ci
877b877906bSopenharmony_ci            if (window->cursorMode == GLFW_CURSOR_DISABLED)
878b877906bSopenharmony_ci            {
879b877906bSopenharmony_ci                const int dx = x - window->win32.lastCursorPosX;
880b877906bSopenharmony_ci                const int dy = y - window->win32.lastCursorPosY;
881b877906bSopenharmony_ci
882b877906bSopenharmony_ci                if (_glfw.win32.disabledCursorWindow != window)
883b877906bSopenharmony_ci                    break;
884b877906bSopenharmony_ci                if (window->rawMouseMotion)
885b877906bSopenharmony_ci                    break;
886b877906bSopenharmony_ci
887b877906bSopenharmony_ci                _glfwInputCursorPos(window,
888b877906bSopenharmony_ci                                    window->virtualCursorPosX + dx,
889b877906bSopenharmony_ci                                    window->virtualCursorPosY + dy);
890b877906bSopenharmony_ci            }
891b877906bSopenharmony_ci            else
892b877906bSopenharmony_ci                _glfwInputCursorPos(window, x, y);
893b877906bSopenharmony_ci
894b877906bSopenharmony_ci            window->win32.lastCursorPosX = x;
895b877906bSopenharmony_ci            window->win32.lastCursorPosY = y;
896b877906bSopenharmony_ci
897b877906bSopenharmony_ci            return 0;
898b877906bSopenharmony_ci        }
899b877906bSopenharmony_ci
900b877906bSopenharmony_ci        case WM_INPUT:
901b877906bSopenharmony_ci        {
902b877906bSopenharmony_ci            UINT size = 0;
903b877906bSopenharmony_ci            HRAWINPUT ri = (HRAWINPUT) lParam;
904b877906bSopenharmony_ci            RAWINPUT* data = NULL;
905b877906bSopenharmony_ci            int dx, dy;
906b877906bSopenharmony_ci
907b877906bSopenharmony_ci            if (_glfw.win32.disabledCursorWindow != window)
908b877906bSopenharmony_ci                break;
909b877906bSopenharmony_ci            if (!window->rawMouseMotion)
910b877906bSopenharmony_ci                break;
911b877906bSopenharmony_ci
912b877906bSopenharmony_ci            GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
913b877906bSopenharmony_ci            if (size > (UINT) _glfw.win32.rawInputSize)
914b877906bSopenharmony_ci            {
915b877906bSopenharmony_ci                _glfw_free(_glfw.win32.rawInput);
916b877906bSopenharmony_ci                _glfw.win32.rawInput = _glfw_calloc(size, 1);
917b877906bSopenharmony_ci                _glfw.win32.rawInputSize = size;
918b877906bSopenharmony_ci            }
919b877906bSopenharmony_ci
920b877906bSopenharmony_ci            size = _glfw.win32.rawInputSize;
921b877906bSopenharmony_ci            if (GetRawInputData(ri, RID_INPUT,
922b877906bSopenharmony_ci                                _glfw.win32.rawInput, &size,
923b877906bSopenharmony_ci                                sizeof(RAWINPUTHEADER)) == (UINT) -1)
924b877906bSopenharmony_ci            {
925b877906bSopenharmony_ci                _glfwInputError(GLFW_PLATFORM_ERROR,
926b877906bSopenharmony_ci                                "Win32: Failed to retrieve raw input data");
927b877906bSopenharmony_ci                break;
928b877906bSopenharmony_ci            }
929b877906bSopenharmony_ci
930b877906bSopenharmony_ci            data = _glfw.win32.rawInput;
931b877906bSopenharmony_ci            if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
932b877906bSopenharmony_ci            {
933b877906bSopenharmony_ci                POINT pos = {0};
934b877906bSopenharmony_ci                int width, height;
935b877906bSopenharmony_ci
936b877906bSopenharmony_ci                if (data->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP)
937b877906bSopenharmony_ci                {
938b877906bSopenharmony_ci                    pos.x += GetSystemMetrics(SM_XVIRTUALSCREEN);
939b877906bSopenharmony_ci                    pos.y += GetSystemMetrics(SM_YVIRTUALSCREEN);
940b877906bSopenharmony_ci                    width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
941b877906bSopenharmony_ci                    height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
942b877906bSopenharmony_ci                }
943b877906bSopenharmony_ci                else
944b877906bSopenharmony_ci                {
945b877906bSopenharmony_ci                    width = GetSystemMetrics(SM_CXSCREEN);
946b877906bSopenharmony_ci                    height = GetSystemMetrics(SM_CYSCREEN);
947b877906bSopenharmony_ci                }
948b877906bSopenharmony_ci
949b877906bSopenharmony_ci                pos.x += (int) ((data->data.mouse.lLastX / 65535.f) * width);
950b877906bSopenharmony_ci                pos.y += (int) ((data->data.mouse.lLastY / 65535.f) * height);
951b877906bSopenharmony_ci                ScreenToClient(window->win32.handle, &pos);
952b877906bSopenharmony_ci
953b877906bSopenharmony_ci                dx = pos.x - window->win32.lastCursorPosX;
954b877906bSopenharmony_ci                dy = pos.y - window->win32.lastCursorPosY;
955b877906bSopenharmony_ci            }
956b877906bSopenharmony_ci            else
957b877906bSopenharmony_ci            {
958b877906bSopenharmony_ci                dx = data->data.mouse.lLastX;
959b877906bSopenharmony_ci                dy = data->data.mouse.lLastY;
960b877906bSopenharmony_ci            }
961b877906bSopenharmony_ci
962b877906bSopenharmony_ci            _glfwInputCursorPos(window,
963b877906bSopenharmony_ci                                window->virtualCursorPosX + dx,
964b877906bSopenharmony_ci                                window->virtualCursorPosY + dy);
965b877906bSopenharmony_ci
966b877906bSopenharmony_ci            window->win32.lastCursorPosX += dx;
967b877906bSopenharmony_ci            window->win32.lastCursorPosY += dy;
968b877906bSopenharmony_ci            break;
969b877906bSopenharmony_ci        }
970b877906bSopenharmony_ci
971b877906bSopenharmony_ci        case WM_MOUSELEAVE:
972b877906bSopenharmony_ci        {
973b877906bSopenharmony_ci            window->win32.cursorTracked = GLFW_FALSE;
974b877906bSopenharmony_ci            _glfwInputCursorEnter(window, GLFW_FALSE);
975b877906bSopenharmony_ci            return 0;
976b877906bSopenharmony_ci        }
977b877906bSopenharmony_ci
978b877906bSopenharmony_ci        case WM_MOUSEWHEEL:
979b877906bSopenharmony_ci        {
980b877906bSopenharmony_ci            _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA);
981b877906bSopenharmony_ci            return 0;
982b877906bSopenharmony_ci        }
983b877906bSopenharmony_ci
984b877906bSopenharmony_ci        case WM_MOUSEHWHEEL:
985b877906bSopenharmony_ci        {
986b877906bSopenharmony_ci            // This message is only sent on Windows Vista and later
987b877906bSopenharmony_ci            // NOTE: The X-axis is inverted for consistency with macOS and X11
988b877906bSopenharmony_ci            _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
989b877906bSopenharmony_ci            return 0;
990b877906bSopenharmony_ci        }
991b877906bSopenharmony_ci
992b877906bSopenharmony_ci        case WM_ENTERSIZEMOVE:
993b877906bSopenharmony_ci        case WM_ENTERMENULOOP:
994b877906bSopenharmony_ci        {
995b877906bSopenharmony_ci            if (window->win32.frameAction)
996b877906bSopenharmony_ci                break;
997b877906bSopenharmony_ci
998b877906bSopenharmony_ci            // HACK: Enable the cursor while the user is moving or
999b877906bSopenharmony_ci            //       resizing the window or using the window menu
1000b877906bSopenharmony_ci            if (window->cursorMode == GLFW_CURSOR_DISABLED)
1001b877906bSopenharmony_ci                enableCursor(window);
1002b877906bSopenharmony_ci            else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
1003b877906bSopenharmony_ci                releaseCursor();
1004b877906bSopenharmony_ci
1005b877906bSopenharmony_ci            break;
1006b877906bSopenharmony_ci        }
1007b877906bSopenharmony_ci
1008b877906bSopenharmony_ci        case WM_EXITSIZEMOVE:
1009b877906bSopenharmony_ci        case WM_EXITMENULOOP:
1010b877906bSopenharmony_ci        {
1011b877906bSopenharmony_ci            if (window->win32.frameAction)
1012b877906bSopenharmony_ci                break;
1013b877906bSopenharmony_ci
1014b877906bSopenharmony_ci            // HACK: Disable the cursor once the user is done moving or
1015b877906bSopenharmony_ci            //       resizing the window or using the menu
1016b877906bSopenharmony_ci            if (window->cursorMode == GLFW_CURSOR_DISABLED)
1017b877906bSopenharmony_ci                disableCursor(window);
1018b877906bSopenharmony_ci            else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
1019b877906bSopenharmony_ci                captureCursor(window);
1020b877906bSopenharmony_ci
1021b877906bSopenharmony_ci            break;
1022b877906bSopenharmony_ci        }
1023b877906bSopenharmony_ci
1024b877906bSopenharmony_ci        case WM_SIZE:
1025b877906bSopenharmony_ci        {
1026b877906bSopenharmony_ci            const int width = LOWORD(lParam);
1027b877906bSopenharmony_ci            const int height = HIWORD(lParam);
1028b877906bSopenharmony_ci            const GLFWbool iconified = wParam == SIZE_MINIMIZED;
1029b877906bSopenharmony_ci            const GLFWbool maximized = wParam == SIZE_MAXIMIZED ||
1030b877906bSopenharmony_ci                                       (window->win32.maximized &&
1031b877906bSopenharmony_ci                                        wParam != SIZE_RESTORED);
1032b877906bSopenharmony_ci
1033b877906bSopenharmony_ci            if (_glfw.win32.capturedCursorWindow == window)
1034b877906bSopenharmony_ci                captureCursor(window);
1035b877906bSopenharmony_ci
1036b877906bSopenharmony_ci            if (window->win32.iconified != iconified)
1037b877906bSopenharmony_ci                _glfwInputWindowIconify(window, iconified);
1038b877906bSopenharmony_ci
1039b877906bSopenharmony_ci            if (window->win32.maximized != maximized)
1040b877906bSopenharmony_ci                _glfwInputWindowMaximize(window, maximized);
1041b877906bSopenharmony_ci
1042b877906bSopenharmony_ci            if (width != window->win32.width || height != window->win32.height)
1043b877906bSopenharmony_ci            {
1044b877906bSopenharmony_ci                window->win32.width = width;
1045b877906bSopenharmony_ci                window->win32.height = height;
1046b877906bSopenharmony_ci
1047b877906bSopenharmony_ci                _glfwInputFramebufferSize(window, width, height);
1048b877906bSopenharmony_ci                _glfwInputWindowSize(window, width, height);
1049b877906bSopenharmony_ci            }
1050b877906bSopenharmony_ci
1051b877906bSopenharmony_ci            if (window->monitor && window->win32.iconified != iconified)
1052b877906bSopenharmony_ci            {
1053b877906bSopenharmony_ci                if (iconified)
1054b877906bSopenharmony_ci                    releaseMonitor(window);
1055b877906bSopenharmony_ci                else
1056b877906bSopenharmony_ci                {
1057b877906bSopenharmony_ci                    acquireMonitor(window);
1058b877906bSopenharmony_ci                    fitToMonitor(window);
1059b877906bSopenharmony_ci                }
1060b877906bSopenharmony_ci            }
1061b877906bSopenharmony_ci
1062b877906bSopenharmony_ci            window->win32.iconified = iconified;
1063b877906bSopenharmony_ci            window->win32.maximized = maximized;
1064b877906bSopenharmony_ci            return 0;
1065b877906bSopenharmony_ci        }
1066b877906bSopenharmony_ci
1067b877906bSopenharmony_ci        case WM_MOVE:
1068b877906bSopenharmony_ci        {
1069b877906bSopenharmony_ci            if (_glfw.win32.capturedCursorWindow == window)
1070b877906bSopenharmony_ci                captureCursor(window);
1071b877906bSopenharmony_ci
1072b877906bSopenharmony_ci            // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as
1073b877906bSopenharmony_ci            // those macros do not handle negative window positions correctly
1074b877906bSopenharmony_ci            _glfwInputWindowPos(window,
1075b877906bSopenharmony_ci                                GET_X_LPARAM(lParam),
1076b877906bSopenharmony_ci                                GET_Y_LPARAM(lParam));
1077b877906bSopenharmony_ci            return 0;
1078b877906bSopenharmony_ci        }
1079b877906bSopenharmony_ci
1080b877906bSopenharmony_ci        case WM_SIZING:
1081b877906bSopenharmony_ci        {
1082b877906bSopenharmony_ci            if (window->numer == GLFW_DONT_CARE ||
1083b877906bSopenharmony_ci                window->denom == GLFW_DONT_CARE)
1084b877906bSopenharmony_ci            {
1085b877906bSopenharmony_ci                break;
1086b877906bSopenharmony_ci            }
1087b877906bSopenharmony_ci
1088b877906bSopenharmony_ci            applyAspectRatio(window, (int) wParam, (RECT*) lParam);
1089b877906bSopenharmony_ci            return TRUE;
1090b877906bSopenharmony_ci        }
1091b877906bSopenharmony_ci
1092b877906bSopenharmony_ci        case WM_GETMINMAXINFO:
1093b877906bSopenharmony_ci        {
1094b877906bSopenharmony_ci            RECT frame = {0};
1095b877906bSopenharmony_ci            MINMAXINFO* mmi = (MINMAXINFO*) lParam;
1096b877906bSopenharmony_ci            const DWORD style = getWindowStyle(window);
1097b877906bSopenharmony_ci            const DWORD exStyle = getWindowExStyle(window);
1098b877906bSopenharmony_ci
1099b877906bSopenharmony_ci            if (window->monitor)
1100b877906bSopenharmony_ci                break;
1101b877906bSopenharmony_ci
1102b877906bSopenharmony_ci            if (_glfwIsWindows10Version1607OrGreaterWin32())
1103b877906bSopenharmony_ci            {
1104b877906bSopenharmony_ci                AdjustWindowRectExForDpi(&frame, style, FALSE, exStyle,
1105b877906bSopenharmony_ci                                         GetDpiForWindow(window->win32.handle));
1106b877906bSopenharmony_ci            }
1107b877906bSopenharmony_ci            else
1108b877906bSopenharmony_ci                AdjustWindowRectEx(&frame, style, FALSE, exStyle);
1109b877906bSopenharmony_ci
1110b877906bSopenharmony_ci            if (window->minwidth != GLFW_DONT_CARE &&
1111b877906bSopenharmony_ci                window->minheight != GLFW_DONT_CARE)
1112b877906bSopenharmony_ci            {
1113b877906bSopenharmony_ci                mmi->ptMinTrackSize.x = window->minwidth + frame.right - frame.left;
1114b877906bSopenharmony_ci                mmi->ptMinTrackSize.y = window->minheight + frame.bottom - frame.top;
1115b877906bSopenharmony_ci            }
1116b877906bSopenharmony_ci
1117b877906bSopenharmony_ci            if (window->maxwidth != GLFW_DONT_CARE &&
1118b877906bSopenharmony_ci                window->maxheight != GLFW_DONT_CARE)
1119b877906bSopenharmony_ci            {
1120b877906bSopenharmony_ci                mmi->ptMaxTrackSize.x = window->maxwidth + frame.right - frame.left;
1121b877906bSopenharmony_ci                mmi->ptMaxTrackSize.y = window->maxheight + frame.bottom - frame.top;
1122b877906bSopenharmony_ci            }
1123b877906bSopenharmony_ci
1124b877906bSopenharmony_ci            if (!window->decorated)
1125b877906bSopenharmony_ci            {
1126b877906bSopenharmony_ci                MONITORINFO mi;
1127b877906bSopenharmony_ci                const HMONITOR mh = MonitorFromWindow(window->win32.handle,
1128b877906bSopenharmony_ci                                                      MONITOR_DEFAULTTONEAREST);
1129b877906bSopenharmony_ci
1130b877906bSopenharmony_ci                ZeroMemory(&mi, sizeof(mi));
1131b877906bSopenharmony_ci                mi.cbSize = sizeof(mi);
1132b877906bSopenharmony_ci                GetMonitorInfoW(mh, &mi);
1133b877906bSopenharmony_ci
1134b877906bSopenharmony_ci                mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;
1135b877906bSopenharmony_ci                mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;
1136b877906bSopenharmony_ci                mmi->ptMaxSize.x = mi.rcWork.right - mi.rcWork.left;
1137b877906bSopenharmony_ci                mmi->ptMaxSize.y = mi.rcWork.bottom - mi.rcWork.top;
1138b877906bSopenharmony_ci            }
1139b877906bSopenharmony_ci
1140b877906bSopenharmony_ci            return 0;
1141b877906bSopenharmony_ci        }
1142b877906bSopenharmony_ci
1143b877906bSopenharmony_ci        case WM_PAINT:
1144b877906bSopenharmony_ci        {
1145b877906bSopenharmony_ci            _glfwInputWindowDamage(window);
1146b877906bSopenharmony_ci            break;
1147b877906bSopenharmony_ci        }
1148b877906bSopenharmony_ci
1149b877906bSopenharmony_ci        case WM_ERASEBKGND:
1150b877906bSopenharmony_ci        {
1151b877906bSopenharmony_ci            return TRUE;
1152b877906bSopenharmony_ci        }
1153b877906bSopenharmony_ci
1154b877906bSopenharmony_ci        case WM_NCACTIVATE:
1155b877906bSopenharmony_ci        case WM_NCPAINT:
1156b877906bSopenharmony_ci        {
1157b877906bSopenharmony_ci            // Prevent title bar from being drawn after restoring a minimized
1158b877906bSopenharmony_ci            // undecorated window
1159b877906bSopenharmony_ci            if (!window->decorated)
1160b877906bSopenharmony_ci                return TRUE;
1161b877906bSopenharmony_ci
1162b877906bSopenharmony_ci            break;
1163b877906bSopenharmony_ci        }
1164b877906bSopenharmony_ci
1165b877906bSopenharmony_ci        case WM_DWMCOMPOSITIONCHANGED:
1166b877906bSopenharmony_ci        case WM_DWMCOLORIZATIONCOLORCHANGED:
1167b877906bSopenharmony_ci        {
1168b877906bSopenharmony_ci            if (window->win32.transparent)
1169b877906bSopenharmony_ci                updateFramebufferTransparency(window);
1170b877906bSopenharmony_ci            return 0;
1171b877906bSopenharmony_ci        }
1172b877906bSopenharmony_ci
1173b877906bSopenharmony_ci        case WM_GETDPISCALEDSIZE:
1174b877906bSopenharmony_ci        {
1175b877906bSopenharmony_ci            if (window->win32.scaleToMonitor)
1176b877906bSopenharmony_ci                break;
1177b877906bSopenharmony_ci
1178b877906bSopenharmony_ci            // Adjust the window size to keep the content area size constant
1179b877906bSopenharmony_ci            if (_glfwIsWindows10Version1703OrGreaterWin32())
1180b877906bSopenharmony_ci            {
1181b877906bSopenharmony_ci                RECT source = {0}, target = {0};
1182b877906bSopenharmony_ci                SIZE* size = (SIZE*) lParam;
1183b877906bSopenharmony_ci
1184b877906bSopenharmony_ci                AdjustWindowRectExForDpi(&source, getWindowStyle(window),
1185b877906bSopenharmony_ci                                         FALSE, getWindowExStyle(window),
1186b877906bSopenharmony_ci                                         GetDpiForWindow(window->win32.handle));
1187b877906bSopenharmony_ci                AdjustWindowRectExForDpi(&target, getWindowStyle(window),
1188b877906bSopenharmony_ci                                         FALSE, getWindowExStyle(window),
1189b877906bSopenharmony_ci                                         LOWORD(wParam));
1190b877906bSopenharmony_ci
1191b877906bSopenharmony_ci                size->cx += (target.right - target.left) -
1192b877906bSopenharmony_ci                            (source.right - source.left);
1193b877906bSopenharmony_ci                size->cy += (target.bottom - target.top) -
1194b877906bSopenharmony_ci                            (source.bottom - source.top);
1195b877906bSopenharmony_ci                return TRUE;
1196b877906bSopenharmony_ci            }
1197b877906bSopenharmony_ci
1198b877906bSopenharmony_ci            break;
1199b877906bSopenharmony_ci        }
1200b877906bSopenharmony_ci
1201b877906bSopenharmony_ci        case WM_DPICHANGED:
1202b877906bSopenharmony_ci        {
1203b877906bSopenharmony_ci            const float xscale = HIWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
1204b877906bSopenharmony_ci            const float yscale = LOWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
1205b877906bSopenharmony_ci
1206b877906bSopenharmony_ci            // Resize windowed mode windows that either permit rescaling or that
1207b877906bSopenharmony_ci            // need it to compensate for non-client area scaling
1208b877906bSopenharmony_ci            if (!window->monitor &&
1209b877906bSopenharmony_ci                (window->win32.scaleToMonitor ||
1210b877906bSopenharmony_ci                 _glfwIsWindows10Version1703OrGreaterWin32()))
1211b877906bSopenharmony_ci            {
1212b877906bSopenharmony_ci                RECT* suggested = (RECT*) lParam;
1213b877906bSopenharmony_ci                SetWindowPos(window->win32.handle, HWND_TOP,
1214b877906bSopenharmony_ci                             suggested->left,
1215b877906bSopenharmony_ci                             suggested->top,
1216b877906bSopenharmony_ci                             suggested->right - suggested->left,
1217b877906bSopenharmony_ci                             suggested->bottom - suggested->top,
1218b877906bSopenharmony_ci                             SWP_NOACTIVATE | SWP_NOZORDER);
1219b877906bSopenharmony_ci            }
1220b877906bSopenharmony_ci
1221b877906bSopenharmony_ci            _glfwInputWindowContentScale(window, xscale, yscale);
1222b877906bSopenharmony_ci            break;
1223b877906bSopenharmony_ci        }
1224b877906bSopenharmony_ci
1225b877906bSopenharmony_ci        case WM_SETCURSOR:
1226b877906bSopenharmony_ci        {
1227b877906bSopenharmony_ci            if (LOWORD(lParam) == HTCLIENT)
1228b877906bSopenharmony_ci            {
1229b877906bSopenharmony_ci                updateCursorImage(window);
1230b877906bSopenharmony_ci                return TRUE;
1231b877906bSopenharmony_ci            }
1232b877906bSopenharmony_ci
1233b877906bSopenharmony_ci            break;
1234b877906bSopenharmony_ci        }
1235b877906bSopenharmony_ci
1236b877906bSopenharmony_ci        case WM_DROPFILES:
1237b877906bSopenharmony_ci        {
1238b877906bSopenharmony_ci            HDROP drop = (HDROP) wParam;
1239b877906bSopenharmony_ci            POINT pt;
1240b877906bSopenharmony_ci            int i;
1241b877906bSopenharmony_ci
1242b877906bSopenharmony_ci            const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
1243b877906bSopenharmony_ci            char** paths = _glfw_calloc(count, sizeof(char*));
1244b877906bSopenharmony_ci
1245b877906bSopenharmony_ci            // Move the mouse to the position of the drop
1246b877906bSopenharmony_ci            DragQueryPoint(drop, &pt);
1247b877906bSopenharmony_ci            _glfwInputCursorPos(window, pt.x, pt.y);
1248b877906bSopenharmony_ci
1249b877906bSopenharmony_ci            for (i = 0;  i < count;  i++)
1250b877906bSopenharmony_ci            {
1251b877906bSopenharmony_ci                const UINT length = DragQueryFileW(drop, i, NULL, 0);
1252b877906bSopenharmony_ci                WCHAR* buffer = _glfw_calloc((size_t) length + 1, sizeof(WCHAR));
1253b877906bSopenharmony_ci
1254b877906bSopenharmony_ci                DragQueryFileW(drop, i, buffer, length + 1);
1255b877906bSopenharmony_ci                paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer);
1256b877906bSopenharmony_ci
1257b877906bSopenharmony_ci                _glfw_free(buffer);
1258b877906bSopenharmony_ci            }
1259b877906bSopenharmony_ci
1260b877906bSopenharmony_ci            _glfwInputDrop(window, count, (const char**) paths);
1261b877906bSopenharmony_ci
1262b877906bSopenharmony_ci            for (i = 0;  i < count;  i++)
1263b877906bSopenharmony_ci                _glfw_free(paths[i]);
1264b877906bSopenharmony_ci            _glfw_free(paths);
1265b877906bSopenharmony_ci
1266b877906bSopenharmony_ci            DragFinish(drop);
1267b877906bSopenharmony_ci            return 0;
1268b877906bSopenharmony_ci        }
1269b877906bSopenharmony_ci    }
1270b877906bSopenharmony_ci
1271b877906bSopenharmony_ci    return DefWindowProcW(hWnd, uMsg, wParam, lParam);
1272b877906bSopenharmony_ci}
1273b877906bSopenharmony_ci
1274b877906bSopenharmony_ci// Creates the GLFW window
1275b877906bSopenharmony_ci//
1276b877906bSopenharmony_cistatic int createNativeWindow(_GLFWwindow* window,
1277b877906bSopenharmony_ci                              const _GLFWwndconfig* wndconfig,
1278b877906bSopenharmony_ci                              const _GLFWfbconfig* fbconfig)
1279b877906bSopenharmony_ci{
1280b877906bSopenharmony_ci    int frameX, frameY, frameWidth, frameHeight;
1281b877906bSopenharmony_ci    WCHAR* wideTitle;
1282b877906bSopenharmony_ci    DWORD style = getWindowStyle(window);
1283b877906bSopenharmony_ci    DWORD exStyle = getWindowExStyle(window);
1284b877906bSopenharmony_ci
1285b877906bSopenharmony_ci    if (!_glfw.win32.mainWindowClass)
1286b877906bSopenharmony_ci    {
1287b877906bSopenharmony_ci        WNDCLASSEXW wc = { sizeof(wc) };
1288b877906bSopenharmony_ci        wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
1289b877906bSopenharmony_ci        wc.lpfnWndProc   = windowProc;
1290b877906bSopenharmony_ci        wc.hInstance     = _glfw.win32.instance;
1291b877906bSopenharmony_ci        wc.hCursor       = LoadCursorW(NULL, IDC_ARROW);
1292b877906bSopenharmony_ci#if defined(_GLFW_WNDCLASSNAME)
1293b877906bSopenharmony_ci        wc.lpszClassName = _GLFW_WNDCLASSNAME;
1294b877906bSopenharmony_ci#else
1295b877906bSopenharmony_ci        wc.lpszClassName = L"GLFW30";
1296b877906bSopenharmony_ci#endif
1297b877906bSopenharmony_ci        // Load user-provided icon if available
1298b877906bSopenharmony_ci        wc.hIcon = LoadImageW(GetModuleHandleW(NULL),
1299b877906bSopenharmony_ci                              L"GLFW_ICON", IMAGE_ICON,
1300b877906bSopenharmony_ci                              0, 0, LR_DEFAULTSIZE | LR_SHARED);
1301b877906bSopenharmony_ci        if (!wc.hIcon)
1302b877906bSopenharmony_ci        {
1303b877906bSopenharmony_ci            // No user-provided icon found, load default icon
1304b877906bSopenharmony_ci            wc.hIcon = LoadImageW(NULL,
1305b877906bSopenharmony_ci                                  IDI_APPLICATION, IMAGE_ICON,
1306b877906bSopenharmony_ci                                  0, 0, LR_DEFAULTSIZE | LR_SHARED);
1307b877906bSopenharmony_ci        }
1308b877906bSopenharmony_ci
1309b877906bSopenharmony_ci        _glfw.win32.mainWindowClass = RegisterClassExW(&wc);
1310b877906bSopenharmony_ci        if (!_glfw.win32.mainWindowClass)
1311b877906bSopenharmony_ci        {
1312b877906bSopenharmony_ci            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
1313b877906bSopenharmony_ci                                 "Win32: Failed to register window class");
1314b877906bSopenharmony_ci            return GLFW_FALSE;
1315b877906bSopenharmony_ci        }
1316b877906bSopenharmony_ci    }
1317b877906bSopenharmony_ci
1318b877906bSopenharmony_ci    if (GetSystemMetrics(SM_REMOTESESSION))
1319b877906bSopenharmony_ci    {
1320b877906bSopenharmony_ci        // NOTE: On Remote Desktop, setting the cursor to NULL does not hide it
1321b877906bSopenharmony_ci        // HACK: Create a transparent cursor and always set that instead of NULL
1322b877906bSopenharmony_ci        //       When not on Remote Desktop, this handle is NULL and normal hiding is used
1323b877906bSopenharmony_ci        if (!_glfw.win32.blankCursor)
1324b877906bSopenharmony_ci        {
1325b877906bSopenharmony_ci            const int cursorWidth = GetSystemMetrics(SM_CXCURSOR);
1326b877906bSopenharmony_ci            const int cursorHeight = GetSystemMetrics(SM_CYCURSOR);
1327b877906bSopenharmony_ci
1328b877906bSopenharmony_ci            unsigned char* cursorPixels = _glfw_calloc(cursorWidth * cursorHeight, 4);
1329b877906bSopenharmony_ci            if (!cursorPixels)
1330b877906bSopenharmony_ci                return GLFW_FALSE;
1331b877906bSopenharmony_ci
1332b877906bSopenharmony_ci            // NOTE: Windows checks whether the image is fully transparent and if so
1333b877906bSopenharmony_ci            //       just ignores the alpha channel and makes the whole cursor opaque
1334b877906bSopenharmony_ci            // HACK: Make one pixel slightly less transparent
1335b877906bSopenharmony_ci            cursorPixels[3] = 1;
1336b877906bSopenharmony_ci
1337b877906bSopenharmony_ci            const GLFWimage cursorImage = { cursorWidth, cursorHeight, cursorPixels };
1338b877906bSopenharmony_ci            _glfw.win32.blankCursor = createIcon(&cursorImage, 0, 0, FALSE);
1339b877906bSopenharmony_ci            _glfw_free(cursorPixels);
1340b877906bSopenharmony_ci
1341b877906bSopenharmony_ci            if (!_glfw.win32.blankCursor)
1342b877906bSopenharmony_ci                return GLFW_FALSE;
1343b877906bSopenharmony_ci        }
1344b877906bSopenharmony_ci    }
1345b877906bSopenharmony_ci
1346b877906bSopenharmony_ci    if (window->monitor)
1347b877906bSopenharmony_ci    {
1348b877906bSopenharmony_ci        MONITORINFO mi = { sizeof(mi) };
1349b877906bSopenharmony_ci        GetMonitorInfoW(window->monitor->win32.handle, &mi);
1350b877906bSopenharmony_ci
1351b877906bSopenharmony_ci        // NOTE: This window placement is temporary and approximate, as the
1352b877906bSopenharmony_ci        //       correct position and size cannot be known until the monitor
1353b877906bSopenharmony_ci        //       video mode has been picked in _glfwSetVideoModeWin32
1354b877906bSopenharmony_ci        frameX = mi.rcMonitor.left;
1355b877906bSopenharmony_ci        frameY = mi.rcMonitor.top;
1356b877906bSopenharmony_ci        frameWidth  = mi.rcMonitor.right - mi.rcMonitor.left;
1357b877906bSopenharmony_ci        frameHeight = mi.rcMonitor.bottom - mi.rcMonitor.top;
1358b877906bSopenharmony_ci    }
1359b877906bSopenharmony_ci    else
1360b877906bSopenharmony_ci    {
1361b877906bSopenharmony_ci        RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
1362b877906bSopenharmony_ci
1363b877906bSopenharmony_ci        window->win32.maximized = wndconfig->maximized;
1364b877906bSopenharmony_ci        if (wndconfig->maximized)
1365b877906bSopenharmony_ci            style |= WS_MAXIMIZE;
1366b877906bSopenharmony_ci
1367b877906bSopenharmony_ci        AdjustWindowRectEx(&rect, style, FALSE, exStyle);
1368b877906bSopenharmony_ci
1369b877906bSopenharmony_ci        if (wndconfig->xpos == GLFW_ANY_POSITION && wndconfig->ypos == GLFW_ANY_POSITION)
1370b877906bSopenharmony_ci        {
1371b877906bSopenharmony_ci            frameX = CW_USEDEFAULT;
1372b877906bSopenharmony_ci            frameY = CW_USEDEFAULT;
1373b877906bSopenharmony_ci        }
1374b877906bSopenharmony_ci        else
1375b877906bSopenharmony_ci        {
1376b877906bSopenharmony_ci            frameX = wndconfig->xpos + rect.left;
1377b877906bSopenharmony_ci            frameY = wndconfig->ypos + rect.top;
1378b877906bSopenharmony_ci        }
1379b877906bSopenharmony_ci
1380b877906bSopenharmony_ci        frameWidth  = rect.right - rect.left;
1381b877906bSopenharmony_ci        frameHeight = rect.bottom - rect.top;
1382b877906bSopenharmony_ci    }
1383b877906bSopenharmony_ci
1384b877906bSopenharmony_ci    wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
1385b877906bSopenharmony_ci    if (!wideTitle)
1386b877906bSopenharmony_ci        return GLFW_FALSE;
1387b877906bSopenharmony_ci
1388b877906bSopenharmony_ci    window->win32.handle = CreateWindowExW(exStyle,
1389b877906bSopenharmony_ci                                           MAKEINTATOM(_glfw.win32.mainWindowClass),
1390b877906bSopenharmony_ci                                           wideTitle,
1391b877906bSopenharmony_ci                                           style,
1392b877906bSopenharmony_ci                                           frameX, frameY,
1393b877906bSopenharmony_ci                                           frameWidth, frameHeight,
1394b877906bSopenharmony_ci                                           NULL, // No parent window
1395b877906bSopenharmony_ci                                           NULL, // No window menu
1396b877906bSopenharmony_ci                                           _glfw.win32.instance,
1397b877906bSopenharmony_ci                                           (LPVOID) wndconfig);
1398b877906bSopenharmony_ci
1399b877906bSopenharmony_ci    _glfw_free(wideTitle);
1400b877906bSopenharmony_ci
1401b877906bSopenharmony_ci    if (!window->win32.handle)
1402b877906bSopenharmony_ci    {
1403b877906bSopenharmony_ci        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
1404b877906bSopenharmony_ci                             "Win32: Failed to create window");
1405b877906bSopenharmony_ci        return GLFW_FALSE;
1406b877906bSopenharmony_ci    }
1407b877906bSopenharmony_ci
1408b877906bSopenharmony_ci    SetPropW(window->win32.handle, L"GLFW", window);
1409b877906bSopenharmony_ci
1410b877906bSopenharmony_ci    if (IsWindows7OrGreater())
1411b877906bSopenharmony_ci    {
1412b877906bSopenharmony_ci        ChangeWindowMessageFilterEx(window->win32.handle,
1413b877906bSopenharmony_ci                                    WM_DROPFILES, MSGFLT_ALLOW, NULL);
1414b877906bSopenharmony_ci        ChangeWindowMessageFilterEx(window->win32.handle,
1415b877906bSopenharmony_ci                                    WM_COPYDATA, MSGFLT_ALLOW, NULL);
1416b877906bSopenharmony_ci        ChangeWindowMessageFilterEx(window->win32.handle,
1417b877906bSopenharmony_ci                                    WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
1418b877906bSopenharmony_ci    }
1419b877906bSopenharmony_ci
1420b877906bSopenharmony_ci    window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
1421b877906bSopenharmony_ci    window->win32.keymenu = wndconfig->win32.keymenu;
1422b877906bSopenharmony_ci    window->win32.showDefault = wndconfig->win32.showDefault;
1423b877906bSopenharmony_ci
1424b877906bSopenharmony_ci    if (!window->monitor)
1425b877906bSopenharmony_ci    {
1426b877906bSopenharmony_ci        RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
1427b877906bSopenharmony_ci        WINDOWPLACEMENT wp = { sizeof(wp) };
1428b877906bSopenharmony_ci        const HMONITOR mh = MonitorFromWindow(window->win32.handle,
1429b877906bSopenharmony_ci                                              MONITOR_DEFAULTTONEAREST);
1430b877906bSopenharmony_ci
1431b877906bSopenharmony_ci        // Adjust window rect to account for DPI scaling of the window frame and
1432b877906bSopenharmony_ci        // (if enabled) DPI scaling of the content area
1433b877906bSopenharmony_ci        // This cannot be done until we know what monitor the window was placed on
1434b877906bSopenharmony_ci        // Only update the restored window rect as the window may be maximized
1435b877906bSopenharmony_ci
1436b877906bSopenharmony_ci        if (wndconfig->scaleToMonitor)
1437b877906bSopenharmony_ci        {
1438b877906bSopenharmony_ci            float xscale, yscale;
1439b877906bSopenharmony_ci            _glfwGetHMONITORContentScaleWin32(mh, &xscale, &yscale);
1440b877906bSopenharmony_ci
1441b877906bSopenharmony_ci            if (xscale > 0.f && yscale > 0.f)
1442b877906bSopenharmony_ci            {
1443b877906bSopenharmony_ci                rect.right = (int) (rect.right * xscale);
1444b877906bSopenharmony_ci                rect.bottom = (int) (rect.bottom * yscale);
1445b877906bSopenharmony_ci            }
1446b877906bSopenharmony_ci        }
1447b877906bSopenharmony_ci
1448b877906bSopenharmony_ci        if (_glfwIsWindows10Version1607OrGreaterWin32())
1449b877906bSopenharmony_ci        {
1450b877906bSopenharmony_ci            AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
1451b877906bSopenharmony_ci                                     GetDpiForWindow(window->win32.handle));
1452b877906bSopenharmony_ci        }
1453b877906bSopenharmony_ci        else
1454b877906bSopenharmony_ci            AdjustWindowRectEx(&rect, style, FALSE, exStyle);
1455b877906bSopenharmony_ci
1456b877906bSopenharmony_ci        GetWindowPlacement(window->win32.handle, &wp);
1457b877906bSopenharmony_ci        OffsetRect(&rect,
1458b877906bSopenharmony_ci                   wp.rcNormalPosition.left - rect.left,
1459b877906bSopenharmony_ci                   wp.rcNormalPosition.top - rect.top);
1460b877906bSopenharmony_ci
1461b877906bSopenharmony_ci        wp.rcNormalPosition = rect;
1462b877906bSopenharmony_ci        wp.showCmd = SW_HIDE;
1463b877906bSopenharmony_ci        SetWindowPlacement(window->win32.handle, &wp);
1464b877906bSopenharmony_ci
1465b877906bSopenharmony_ci        // Adjust rect of maximized undecorated window, because by default Windows will
1466b877906bSopenharmony_ci        // make such a window cover the whole monitor instead of its workarea
1467b877906bSopenharmony_ci
1468b877906bSopenharmony_ci        if (wndconfig->maximized && !wndconfig->decorated)
1469b877906bSopenharmony_ci        {
1470b877906bSopenharmony_ci            MONITORINFO mi = { sizeof(mi) };
1471b877906bSopenharmony_ci            GetMonitorInfoW(mh, &mi);
1472b877906bSopenharmony_ci
1473b877906bSopenharmony_ci            SetWindowPos(window->win32.handle, HWND_TOP,
1474b877906bSopenharmony_ci                         mi.rcWork.left,
1475b877906bSopenharmony_ci                         mi.rcWork.top,
1476b877906bSopenharmony_ci                         mi.rcWork.right - mi.rcWork.left,
1477b877906bSopenharmony_ci                         mi.rcWork.bottom - mi.rcWork.top,
1478b877906bSopenharmony_ci                         SWP_NOACTIVATE | SWP_NOZORDER);
1479b877906bSopenharmony_ci        }
1480b877906bSopenharmony_ci    }
1481b877906bSopenharmony_ci
1482b877906bSopenharmony_ci    DragAcceptFiles(window->win32.handle, TRUE);
1483b877906bSopenharmony_ci
1484b877906bSopenharmony_ci    if (fbconfig->transparent)
1485b877906bSopenharmony_ci    {
1486b877906bSopenharmony_ci        updateFramebufferTransparency(window);
1487b877906bSopenharmony_ci        window->win32.transparent = GLFW_TRUE;
1488b877906bSopenharmony_ci    }
1489b877906bSopenharmony_ci
1490b877906bSopenharmony_ci    _glfwGetWindowSizeWin32(window, &window->win32.width, &window->win32.height);
1491b877906bSopenharmony_ci
1492b877906bSopenharmony_ci    return GLFW_TRUE;
1493b877906bSopenharmony_ci}
1494b877906bSopenharmony_ci
1495b877906bSopenharmony_ciGLFWbool _glfwCreateWindowWin32(_GLFWwindow* window,
1496b877906bSopenharmony_ci                                const _GLFWwndconfig* wndconfig,
1497b877906bSopenharmony_ci                                const _GLFWctxconfig* ctxconfig,
1498b877906bSopenharmony_ci                                const _GLFWfbconfig* fbconfig)
1499b877906bSopenharmony_ci{
1500b877906bSopenharmony_ci    if (!createNativeWindow(window, wndconfig, fbconfig))
1501b877906bSopenharmony_ci        return GLFW_FALSE;
1502b877906bSopenharmony_ci
1503b877906bSopenharmony_ci    if (ctxconfig->client != GLFW_NO_API)
1504b877906bSopenharmony_ci    {
1505b877906bSopenharmony_ci        if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
1506b877906bSopenharmony_ci        {
1507b877906bSopenharmony_ci            if (!_glfwInitWGL())
1508b877906bSopenharmony_ci                return GLFW_FALSE;
1509b877906bSopenharmony_ci            if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
1510b877906bSopenharmony_ci                return GLFW_FALSE;
1511b877906bSopenharmony_ci        }
1512b877906bSopenharmony_ci        else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
1513b877906bSopenharmony_ci        {
1514b877906bSopenharmony_ci            if (!_glfwInitEGL())
1515b877906bSopenharmony_ci                return GLFW_FALSE;
1516b877906bSopenharmony_ci            if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
1517b877906bSopenharmony_ci                return GLFW_FALSE;
1518b877906bSopenharmony_ci        }
1519b877906bSopenharmony_ci        else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
1520b877906bSopenharmony_ci        {
1521b877906bSopenharmony_ci            if (!_glfwInitOSMesa())
1522b877906bSopenharmony_ci                return GLFW_FALSE;
1523b877906bSopenharmony_ci            if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
1524b877906bSopenharmony_ci                return GLFW_FALSE;
1525b877906bSopenharmony_ci        }
1526b877906bSopenharmony_ci
1527b877906bSopenharmony_ci        if (!_glfwRefreshContextAttribs(window, ctxconfig))
1528b877906bSopenharmony_ci            return GLFW_FALSE;
1529b877906bSopenharmony_ci    }
1530b877906bSopenharmony_ci
1531b877906bSopenharmony_ci    if (wndconfig->mousePassthrough)
1532b877906bSopenharmony_ci        _glfwSetWindowMousePassthroughWin32(window, GLFW_TRUE);
1533b877906bSopenharmony_ci
1534b877906bSopenharmony_ci    if (window->monitor)
1535b877906bSopenharmony_ci    {
1536b877906bSopenharmony_ci        _glfwShowWindowWin32(window);
1537b877906bSopenharmony_ci        _glfwFocusWindowWin32(window);
1538b877906bSopenharmony_ci        acquireMonitor(window);
1539b877906bSopenharmony_ci        fitToMonitor(window);
1540b877906bSopenharmony_ci
1541b877906bSopenharmony_ci        if (wndconfig->centerCursor)
1542b877906bSopenharmony_ci            _glfwCenterCursorInContentArea(window);
1543b877906bSopenharmony_ci    }
1544b877906bSopenharmony_ci    else
1545b877906bSopenharmony_ci    {
1546b877906bSopenharmony_ci        if (wndconfig->visible)
1547b877906bSopenharmony_ci        {
1548b877906bSopenharmony_ci            _glfwShowWindowWin32(window);
1549b877906bSopenharmony_ci            if (wndconfig->focused)
1550b877906bSopenharmony_ci                _glfwFocusWindowWin32(window);
1551b877906bSopenharmony_ci        }
1552b877906bSopenharmony_ci    }
1553b877906bSopenharmony_ci
1554b877906bSopenharmony_ci    return GLFW_TRUE;
1555b877906bSopenharmony_ci}
1556b877906bSopenharmony_ci
1557b877906bSopenharmony_civoid _glfwDestroyWindowWin32(_GLFWwindow* window)
1558b877906bSopenharmony_ci{
1559b877906bSopenharmony_ci    if (window->monitor)
1560b877906bSopenharmony_ci        releaseMonitor(window);
1561b877906bSopenharmony_ci
1562b877906bSopenharmony_ci    if (window->context.destroy)
1563b877906bSopenharmony_ci        window->context.destroy(window);
1564b877906bSopenharmony_ci
1565b877906bSopenharmony_ci    if (_glfw.win32.disabledCursorWindow == window)
1566b877906bSopenharmony_ci        enableCursor(window);
1567b877906bSopenharmony_ci
1568b877906bSopenharmony_ci    if (_glfw.win32.capturedCursorWindow == window)
1569b877906bSopenharmony_ci        releaseCursor();
1570b877906bSopenharmony_ci
1571b877906bSopenharmony_ci    if (window->win32.handle)
1572b877906bSopenharmony_ci    {
1573b877906bSopenharmony_ci        RemovePropW(window->win32.handle, L"GLFW");
1574b877906bSopenharmony_ci        DestroyWindow(window->win32.handle);
1575b877906bSopenharmony_ci        window->win32.handle = NULL;
1576b877906bSopenharmony_ci    }
1577b877906bSopenharmony_ci
1578b877906bSopenharmony_ci    if (window->win32.bigIcon)
1579b877906bSopenharmony_ci        DestroyIcon(window->win32.bigIcon);
1580b877906bSopenharmony_ci
1581b877906bSopenharmony_ci    if (window->win32.smallIcon)
1582b877906bSopenharmony_ci        DestroyIcon(window->win32.smallIcon);
1583b877906bSopenharmony_ci}
1584b877906bSopenharmony_ci
1585b877906bSopenharmony_civoid _glfwSetWindowTitleWin32(_GLFWwindow* window, const char* title)
1586b877906bSopenharmony_ci{
1587b877906bSopenharmony_ci    WCHAR* wideTitle = _glfwCreateWideStringFromUTF8Win32(title);
1588b877906bSopenharmony_ci    if (!wideTitle)
1589b877906bSopenharmony_ci        return;
1590b877906bSopenharmony_ci
1591b877906bSopenharmony_ci    SetWindowTextW(window->win32.handle, wideTitle);
1592b877906bSopenharmony_ci    _glfw_free(wideTitle);
1593b877906bSopenharmony_ci}
1594b877906bSopenharmony_ci
1595b877906bSopenharmony_civoid _glfwSetWindowIconWin32(_GLFWwindow* window, int count, const GLFWimage* images)
1596b877906bSopenharmony_ci{
1597b877906bSopenharmony_ci    HICON bigIcon = NULL, smallIcon = NULL;
1598b877906bSopenharmony_ci
1599b877906bSopenharmony_ci    if (count)
1600b877906bSopenharmony_ci    {
1601b877906bSopenharmony_ci        const GLFWimage* bigImage = chooseImage(count, images,
1602b877906bSopenharmony_ci                                                GetSystemMetrics(SM_CXICON),
1603b877906bSopenharmony_ci                                                GetSystemMetrics(SM_CYICON));
1604b877906bSopenharmony_ci        const GLFWimage* smallImage = chooseImage(count, images,
1605b877906bSopenharmony_ci                                                  GetSystemMetrics(SM_CXSMICON),
1606b877906bSopenharmony_ci                                                  GetSystemMetrics(SM_CYSMICON));
1607b877906bSopenharmony_ci
1608b877906bSopenharmony_ci        bigIcon = createIcon(bigImage, 0, 0, GLFW_TRUE);
1609b877906bSopenharmony_ci        smallIcon = createIcon(smallImage, 0, 0, GLFW_TRUE);
1610b877906bSopenharmony_ci    }
1611b877906bSopenharmony_ci    else
1612b877906bSopenharmony_ci    {
1613b877906bSopenharmony_ci        bigIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICON);
1614b877906bSopenharmony_ci        smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM);
1615b877906bSopenharmony_ci    }
1616b877906bSopenharmony_ci
1617b877906bSopenharmony_ci    SendMessageW(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
1618b877906bSopenharmony_ci    SendMessageW(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
1619b877906bSopenharmony_ci
1620b877906bSopenharmony_ci    if (window->win32.bigIcon)
1621b877906bSopenharmony_ci        DestroyIcon(window->win32.bigIcon);
1622b877906bSopenharmony_ci
1623b877906bSopenharmony_ci    if (window->win32.smallIcon)
1624b877906bSopenharmony_ci        DestroyIcon(window->win32.smallIcon);
1625b877906bSopenharmony_ci
1626b877906bSopenharmony_ci    if (count)
1627b877906bSopenharmony_ci    {
1628b877906bSopenharmony_ci        window->win32.bigIcon = bigIcon;
1629b877906bSopenharmony_ci        window->win32.smallIcon = smallIcon;
1630b877906bSopenharmony_ci    }
1631b877906bSopenharmony_ci}
1632b877906bSopenharmony_ci
1633b877906bSopenharmony_civoid _glfwGetWindowPosWin32(_GLFWwindow* window, int* xpos, int* ypos)
1634b877906bSopenharmony_ci{
1635b877906bSopenharmony_ci    POINT pos = { 0, 0 };
1636b877906bSopenharmony_ci    ClientToScreen(window->win32.handle, &pos);
1637b877906bSopenharmony_ci
1638b877906bSopenharmony_ci    if (xpos)
1639b877906bSopenharmony_ci        *xpos = pos.x;
1640b877906bSopenharmony_ci    if (ypos)
1641b877906bSopenharmony_ci        *ypos = pos.y;
1642b877906bSopenharmony_ci}
1643b877906bSopenharmony_ci
1644b877906bSopenharmony_civoid _glfwSetWindowPosWin32(_GLFWwindow* window, int xpos, int ypos)
1645b877906bSopenharmony_ci{
1646b877906bSopenharmony_ci    RECT rect = { xpos, ypos, xpos, ypos };
1647b877906bSopenharmony_ci
1648b877906bSopenharmony_ci    if (_glfwIsWindows10Version1607OrGreaterWin32())
1649b877906bSopenharmony_ci    {
1650b877906bSopenharmony_ci        AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
1651b877906bSopenharmony_ci                                 FALSE, getWindowExStyle(window),
1652b877906bSopenharmony_ci                                 GetDpiForWindow(window->win32.handle));
1653b877906bSopenharmony_ci    }
1654b877906bSopenharmony_ci    else
1655b877906bSopenharmony_ci    {
1656b877906bSopenharmony_ci        AdjustWindowRectEx(&rect, getWindowStyle(window),
1657b877906bSopenharmony_ci                           FALSE, getWindowExStyle(window));
1658b877906bSopenharmony_ci    }
1659b877906bSopenharmony_ci
1660b877906bSopenharmony_ci    SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0,
1661b877906bSopenharmony_ci                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
1662b877906bSopenharmony_ci}
1663b877906bSopenharmony_ci
1664b877906bSopenharmony_civoid _glfwGetWindowSizeWin32(_GLFWwindow* window, int* width, int* height)
1665b877906bSopenharmony_ci{
1666b877906bSopenharmony_ci    RECT area;
1667b877906bSopenharmony_ci    GetClientRect(window->win32.handle, &area);
1668b877906bSopenharmony_ci
1669b877906bSopenharmony_ci    if (width)
1670b877906bSopenharmony_ci        *width = area.right;
1671b877906bSopenharmony_ci    if (height)
1672b877906bSopenharmony_ci        *height = area.bottom;
1673b877906bSopenharmony_ci}
1674b877906bSopenharmony_ci
1675b877906bSopenharmony_civoid _glfwSetWindowSizeWin32(_GLFWwindow* window, int width, int height)
1676b877906bSopenharmony_ci{
1677b877906bSopenharmony_ci    if (window->monitor)
1678b877906bSopenharmony_ci    {
1679b877906bSopenharmony_ci        if (window->monitor->window == window)
1680b877906bSopenharmony_ci        {
1681b877906bSopenharmony_ci            acquireMonitor(window);
1682b877906bSopenharmony_ci            fitToMonitor(window);
1683b877906bSopenharmony_ci        }
1684b877906bSopenharmony_ci    }
1685b877906bSopenharmony_ci    else
1686b877906bSopenharmony_ci    {
1687b877906bSopenharmony_ci        RECT rect = { 0, 0, width, height };
1688b877906bSopenharmony_ci
1689b877906bSopenharmony_ci        if (_glfwIsWindows10Version1607OrGreaterWin32())
1690b877906bSopenharmony_ci        {
1691b877906bSopenharmony_ci            AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
1692b877906bSopenharmony_ci                                     FALSE, getWindowExStyle(window),
1693b877906bSopenharmony_ci                                     GetDpiForWindow(window->win32.handle));
1694b877906bSopenharmony_ci        }
1695b877906bSopenharmony_ci        else
1696b877906bSopenharmony_ci        {
1697b877906bSopenharmony_ci            AdjustWindowRectEx(&rect, getWindowStyle(window),
1698b877906bSopenharmony_ci                               FALSE, getWindowExStyle(window));
1699b877906bSopenharmony_ci        }
1700b877906bSopenharmony_ci
1701b877906bSopenharmony_ci        SetWindowPos(window->win32.handle, HWND_TOP,
1702b877906bSopenharmony_ci                     0, 0, rect.right - rect.left, rect.bottom - rect.top,
1703b877906bSopenharmony_ci                     SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);
1704b877906bSopenharmony_ci    }
1705b877906bSopenharmony_ci}
1706b877906bSopenharmony_ci
1707b877906bSopenharmony_civoid _glfwSetWindowSizeLimitsWin32(_GLFWwindow* window,
1708b877906bSopenharmony_ci                                   int minwidth, int minheight,
1709b877906bSopenharmony_ci                                   int maxwidth, int maxheight)
1710b877906bSopenharmony_ci{
1711b877906bSopenharmony_ci    RECT area;
1712b877906bSopenharmony_ci
1713b877906bSopenharmony_ci    if ((minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) &&
1714b877906bSopenharmony_ci        (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE))
1715b877906bSopenharmony_ci    {
1716b877906bSopenharmony_ci        return;
1717b877906bSopenharmony_ci    }
1718b877906bSopenharmony_ci
1719b877906bSopenharmony_ci    GetWindowRect(window->win32.handle, &area);
1720b877906bSopenharmony_ci    MoveWindow(window->win32.handle,
1721b877906bSopenharmony_ci               area.left, area.top,
1722b877906bSopenharmony_ci               area.right - area.left,
1723b877906bSopenharmony_ci               area.bottom - area.top, TRUE);
1724b877906bSopenharmony_ci}
1725b877906bSopenharmony_ci
1726b877906bSopenharmony_civoid _glfwSetWindowAspectRatioWin32(_GLFWwindow* window, int numer, int denom)
1727b877906bSopenharmony_ci{
1728b877906bSopenharmony_ci    RECT area;
1729b877906bSopenharmony_ci
1730b877906bSopenharmony_ci    if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
1731b877906bSopenharmony_ci        return;
1732b877906bSopenharmony_ci
1733b877906bSopenharmony_ci    GetWindowRect(window->win32.handle, &area);
1734b877906bSopenharmony_ci    applyAspectRatio(window, WMSZ_BOTTOMRIGHT, &area);
1735b877906bSopenharmony_ci    MoveWindow(window->win32.handle,
1736b877906bSopenharmony_ci               area.left, area.top,
1737b877906bSopenharmony_ci               area.right - area.left,
1738b877906bSopenharmony_ci               area.bottom - area.top, TRUE);
1739b877906bSopenharmony_ci}
1740b877906bSopenharmony_ci
1741b877906bSopenharmony_civoid _glfwGetFramebufferSizeWin32(_GLFWwindow* window, int* width, int* height)
1742b877906bSopenharmony_ci{
1743b877906bSopenharmony_ci    _glfwGetWindowSizeWin32(window, width, height);
1744b877906bSopenharmony_ci}
1745b877906bSopenharmony_ci
1746b877906bSopenharmony_civoid _glfwGetWindowFrameSizeWin32(_GLFWwindow* window,
1747b877906bSopenharmony_ci                                  int* left, int* top,
1748b877906bSopenharmony_ci                                  int* right, int* bottom)
1749b877906bSopenharmony_ci{
1750b877906bSopenharmony_ci    RECT rect;
1751b877906bSopenharmony_ci    int width, height;
1752b877906bSopenharmony_ci
1753b877906bSopenharmony_ci    _glfwGetWindowSizeWin32(window, &width, &height);
1754b877906bSopenharmony_ci    SetRect(&rect, 0, 0, width, height);
1755b877906bSopenharmony_ci
1756b877906bSopenharmony_ci    if (_glfwIsWindows10Version1607OrGreaterWin32())
1757b877906bSopenharmony_ci    {
1758b877906bSopenharmony_ci        AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
1759b877906bSopenharmony_ci                                 FALSE, getWindowExStyle(window),
1760b877906bSopenharmony_ci                                 GetDpiForWindow(window->win32.handle));
1761b877906bSopenharmony_ci    }
1762b877906bSopenharmony_ci    else
1763b877906bSopenharmony_ci    {
1764b877906bSopenharmony_ci        AdjustWindowRectEx(&rect, getWindowStyle(window),
1765b877906bSopenharmony_ci                           FALSE, getWindowExStyle(window));
1766b877906bSopenharmony_ci    }
1767b877906bSopenharmony_ci
1768b877906bSopenharmony_ci    if (left)
1769b877906bSopenharmony_ci        *left = -rect.left;
1770b877906bSopenharmony_ci    if (top)
1771b877906bSopenharmony_ci        *top = -rect.top;
1772b877906bSopenharmony_ci    if (right)
1773b877906bSopenharmony_ci        *right = rect.right - width;
1774b877906bSopenharmony_ci    if (bottom)
1775b877906bSopenharmony_ci        *bottom = rect.bottom - height;
1776b877906bSopenharmony_ci}
1777b877906bSopenharmony_ci
1778b877906bSopenharmony_civoid _glfwGetWindowContentScaleWin32(_GLFWwindow* window, float* xscale, float* yscale)
1779b877906bSopenharmony_ci{
1780b877906bSopenharmony_ci    const HANDLE handle = MonitorFromWindow(window->win32.handle,
1781b877906bSopenharmony_ci                                            MONITOR_DEFAULTTONEAREST);
1782b877906bSopenharmony_ci    _glfwGetHMONITORContentScaleWin32(handle, xscale, yscale);
1783b877906bSopenharmony_ci}
1784b877906bSopenharmony_ci
1785b877906bSopenharmony_civoid _glfwIconifyWindowWin32(_GLFWwindow* window)
1786b877906bSopenharmony_ci{
1787b877906bSopenharmony_ci    ShowWindow(window->win32.handle, SW_MINIMIZE);
1788b877906bSopenharmony_ci}
1789b877906bSopenharmony_ci
1790b877906bSopenharmony_civoid _glfwRestoreWindowWin32(_GLFWwindow* window)
1791b877906bSopenharmony_ci{
1792b877906bSopenharmony_ci    ShowWindow(window->win32.handle, SW_RESTORE);
1793b877906bSopenharmony_ci}
1794b877906bSopenharmony_ci
1795b877906bSopenharmony_civoid _glfwMaximizeWindowWin32(_GLFWwindow* window)
1796b877906bSopenharmony_ci{
1797b877906bSopenharmony_ci    if (IsWindowVisible(window->win32.handle))
1798b877906bSopenharmony_ci        ShowWindow(window->win32.handle, SW_MAXIMIZE);
1799b877906bSopenharmony_ci    else
1800b877906bSopenharmony_ci        maximizeWindowManually(window);
1801b877906bSopenharmony_ci}
1802b877906bSopenharmony_ci
1803b877906bSopenharmony_civoid _glfwShowWindowWin32(_GLFWwindow* window)
1804b877906bSopenharmony_ci{
1805b877906bSopenharmony_ci    int showCommand = SW_SHOWNA;
1806b877906bSopenharmony_ci
1807b877906bSopenharmony_ci    if (window->win32.showDefault)
1808b877906bSopenharmony_ci    {
1809b877906bSopenharmony_ci        // NOTE: GLFW windows currently do not seem to match the Windows 10 definition of
1810b877906bSopenharmony_ci        //       a main window, so even SW_SHOWDEFAULT does nothing
1811b877906bSopenharmony_ci        //       This definition is undocumented and can change (source: Raymond Chen)
1812b877906bSopenharmony_ci        // HACK: Apply the STARTUPINFO show command manually if available
1813b877906bSopenharmony_ci        STARTUPINFOW si = { sizeof(si) };
1814b877906bSopenharmony_ci        GetStartupInfoW(&si);
1815b877906bSopenharmony_ci        if (si.dwFlags & STARTF_USESHOWWINDOW)
1816b877906bSopenharmony_ci            showCommand = si.wShowWindow;
1817b877906bSopenharmony_ci
1818b877906bSopenharmony_ci        window->win32.showDefault = GLFW_FALSE;
1819b877906bSopenharmony_ci    }
1820b877906bSopenharmony_ci
1821b877906bSopenharmony_ci    ShowWindow(window->win32.handle, showCommand);
1822b877906bSopenharmony_ci}
1823b877906bSopenharmony_ci
1824b877906bSopenharmony_civoid _glfwHideWindowWin32(_GLFWwindow* window)
1825b877906bSopenharmony_ci{
1826b877906bSopenharmony_ci    ShowWindow(window->win32.handle, SW_HIDE);
1827b877906bSopenharmony_ci}
1828b877906bSopenharmony_ci
1829b877906bSopenharmony_civoid _glfwRequestWindowAttentionWin32(_GLFWwindow* window)
1830b877906bSopenharmony_ci{
1831b877906bSopenharmony_ci    FlashWindow(window->win32.handle, TRUE);
1832b877906bSopenharmony_ci}
1833b877906bSopenharmony_ci
1834b877906bSopenharmony_civoid _glfwFocusWindowWin32(_GLFWwindow* window)
1835b877906bSopenharmony_ci{
1836b877906bSopenharmony_ci    BringWindowToTop(window->win32.handle);
1837b877906bSopenharmony_ci    SetForegroundWindow(window->win32.handle);
1838b877906bSopenharmony_ci    SetFocus(window->win32.handle);
1839b877906bSopenharmony_ci}
1840b877906bSopenharmony_ci
1841b877906bSopenharmony_civoid _glfwSetWindowMonitorWin32(_GLFWwindow* window,
1842b877906bSopenharmony_ci                                _GLFWmonitor* monitor,
1843b877906bSopenharmony_ci                                int xpos, int ypos,
1844b877906bSopenharmony_ci                                int width, int height,
1845b877906bSopenharmony_ci                                int refreshRate)
1846b877906bSopenharmony_ci{
1847b877906bSopenharmony_ci    if (window->monitor == monitor)
1848b877906bSopenharmony_ci    {
1849b877906bSopenharmony_ci        if (monitor)
1850b877906bSopenharmony_ci        {
1851b877906bSopenharmony_ci            if (monitor->window == window)
1852b877906bSopenharmony_ci            {
1853b877906bSopenharmony_ci                acquireMonitor(window);
1854b877906bSopenharmony_ci                fitToMonitor(window);
1855b877906bSopenharmony_ci            }
1856b877906bSopenharmony_ci        }
1857b877906bSopenharmony_ci        else
1858b877906bSopenharmony_ci        {
1859b877906bSopenharmony_ci            RECT rect = { xpos, ypos, xpos + width, ypos + height };
1860b877906bSopenharmony_ci
1861b877906bSopenharmony_ci            if (_glfwIsWindows10Version1607OrGreaterWin32())
1862b877906bSopenharmony_ci            {
1863b877906bSopenharmony_ci                AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
1864b877906bSopenharmony_ci                                         FALSE, getWindowExStyle(window),
1865b877906bSopenharmony_ci                                         GetDpiForWindow(window->win32.handle));
1866b877906bSopenharmony_ci            }
1867b877906bSopenharmony_ci            else
1868b877906bSopenharmony_ci            {
1869b877906bSopenharmony_ci                AdjustWindowRectEx(&rect, getWindowStyle(window),
1870b877906bSopenharmony_ci                                   FALSE, getWindowExStyle(window));
1871b877906bSopenharmony_ci            }
1872b877906bSopenharmony_ci
1873b877906bSopenharmony_ci            SetWindowPos(window->win32.handle, HWND_TOP,
1874b877906bSopenharmony_ci                         rect.left, rect.top,
1875b877906bSopenharmony_ci                         rect.right - rect.left, rect.bottom - rect.top,
1876b877906bSopenharmony_ci                         SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOZORDER);
1877b877906bSopenharmony_ci        }
1878b877906bSopenharmony_ci
1879b877906bSopenharmony_ci        return;
1880b877906bSopenharmony_ci    }
1881b877906bSopenharmony_ci
1882b877906bSopenharmony_ci    if (window->monitor)
1883b877906bSopenharmony_ci        releaseMonitor(window);
1884b877906bSopenharmony_ci
1885b877906bSopenharmony_ci    _glfwInputWindowMonitor(window, monitor);
1886b877906bSopenharmony_ci
1887b877906bSopenharmony_ci    if (window->monitor)
1888b877906bSopenharmony_ci    {
1889b877906bSopenharmony_ci        MONITORINFO mi = { sizeof(mi) };
1890b877906bSopenharmony_ci        UINT flags = SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS;
1891b877906bSopenharmony_ci
1892b877906bSopenharmony_ci        if (window->decorated)
1893b877906bSopenharmony_ci        {
1894b877906bSopenharmony_ci            DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
1895b877906bSopenharmony_ci            style &= ~WS_OVERLAPPEDWINDOW;
1896b877906bSopenharmony_ci            style |= getWindowStyle(window);
1897b877906bSopenharmony_ci            SetWindowLongW(window->win32.handle, GWL_STYLE, style);
1898b877906bSopenharmony_ci            flags |= SWP_FRAMECHANGED;
1899b877906bSopenharmony_ci        }
1900b877906bSopenharmony_ci
1901b877906bSopenharmony_ci        acquireMonitor(window);
1902b877906bSopenharmony_ci
1903b877906bSopenharmony_ci        GetMonitorInfoW(window->monitor->win32.handle, &mi);
1904b877906bSopenharmony_ci        SetWindowPos(window->win32.handle, HWND_TOPMOST,
1905b877906bSopenharmony_ci                     mi.rcMonitor.left,
1906b877906bSopenharmony_ci                     mi.rcMonitor.top,
1907b877906bSopenharmony_ci                     mi.rcMonitor.right - mi.rcMonitor.left,
1908b877906bSopenharmony_ci                     mi.rcMonitor.bottom - mi.rcMonitor.top,
1909b877906bSopenharmony_ci                     flags);
1910b877906bSopenharmony_ci    }
1911b877906bSopenharmony_ci    else
1912b877906bSopenharmony_ci    {
1913b877906bSopenharmony_ci        HWND after;
1914b877906bSopenharmony_ci        RECT rect = { xpos, ypos, xpos + width, ypos + height };
1915b877906bSopenharmony_ci        DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
1916b877906bSopenharmony_ci        UINT flags = SWP_NOACTIVATE | SWP_NOCOPYBITS;
1917b877906bSopenharmony_ci
1918b877906bSopenharmony_ci        if (window->decorated)
1919b877906bSopenharmony_ci        {
1920b877906bSopenharmony_ci            style &= ~WS_POPUP;
1921b877906bSopenharmony_ci            style |= getWindowStyle(window);
1922b877906bSopenharmony_ci            SetWindowLongW(window->win32.handle, GWL_STYLE, style);
1923b877906bSopenharmony_ci
1924b877906bSopenharmony_ci            flags |= SWP_FRAMECHANGED;
1925b877906bSopenharmony_ci        }
1926b877906bSopenharmony_ci
1927b877906bSopenharmony_ci        if (window->floating)
1928b877906bSopenharmony_ci            after = HWND_TOPMOST;
1929b877906bSopenharmony_ci        else
1930b877906bSopenharmony_ci            after = HWND_NOTOPMOST;
1931b877906bSopenharmony_ci
1932b877906bSopenharmony_ci        if (_glfwIsWindows10Version1607OrGreaterWin32())
1933b877906bSopenharmony_ci        {
1934b877906bSopenharmony_ci            AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
1935b877906bSopenharmony_ci                                     FALSE, getWindowExStyle(window),
1936b877906bSopenharmony_ci                                     GetDpiForWindow(window->win32.handle));
1937b877906bSopenharmony_ci        }
1938b877906bSopenharmony_ci        else
1939b877906bSopenharmony_ci        {
1940b877906bSopenharmony_ci            AdjustWindowRectEx(&rect, getWindowStyle(window),
1941b877906bSopenharmony_ci                               FALSE, getWindowExStyle(window));
1942b877906bSopenharmony_ci        }
1943b877906bSopenharmony_ci
1944b877906bSopenharmony_ci        SetWindowPos(window->win32.handle, after,
1945b877906bSopenharmony_ci                     rect.left, rect.top,
1946b877906bSopenharmony_ci                     rect.right - rect.left, rect.bottom - rect.top,
1947b877906bSopenharmony_ci                     flags);
1948b877906bSopenharmony_ci    }
1949b877906bSopenharmony_ci}
1950b877906bSopenharmony_ci
1951b877906bSopenharmony_ciGLFWbool _glfwWindowFocusedWin32(_GLFWwindow* window)
1952b877906bSopenharmony_ci{
1953b877906bSopenharmony_ci    return window->win32.handle == GetActiveWindow();
1954b877906bSopenharmony_ci}
1955b877906bSopenharmony_ci
1956b877906bSopenharmony_ciGLFWbool _glfwWindowIconifiedWin32(_GLFWwindow* window)
1957b877906bSopenharmony_ci{
1958b877906bSopenharmony_ci    return IsIconic(window->win32.handle);
1959b877906bSopenharmony_ci}
1960b877906bSopenharmony_ci
1961b877906bSopenharmony_ciGLFWbool _glfwWindowVisibleWin32(_GLFWwindow* window)
1962b877906bSopenharmony_ci{
1963b877906bSopenharmony_ci    return IsWindowVisible(window->win32.handle);
1964b877906bSopenharmony_ci}
1965b877906bSopenharmony_ci
1966b877906bSopenharmony_ciGLFWbool _glfwWindowMaximizedWin32(_GLFWwindow* window)
1967b877906bSopenharmony_ci{
1968b877906bSopenharmony_ci    return IsZoomed(window->win32.handle);
1969b877906bSopenharmony_ci}
1970b877906bSopenharmony_ci
1971b877906bSopenharmony_ciGLFWbool _glfwWindowHoveredWin32(_GLFWwindow* window)
1972b877906bSopenharmony_ci{
1973b877906bSopenharmony_ci    return cursorInContentArea(window);
1974b877906bSopenharmony_ci}
1975b877906bSopenharmony_ci
1976b877906bSopenharmony_ciGLFWbool _glfwFramebufferTransparentWin32(_GLFWwindow* window)
1977b877906bSopenharmony_ci{
1978b877906bSopenharmony_ci    BOOL composition, opaque;
1979b877906bSopenharmony_ci    DWORD color;
1980b877906bSopenharmony_ci
1981b877906bSopenharmony_ci    if (!window->win32.transparent)
1982b877906bSopenharmony_ci        return GLFW_FALSE;
1983b877906bSopenharmony_ci
1984b877906bSopenharmony_ci    if (!IsWindowsVistaOrGreater())
1985b877906bSopenharmony_ci        return GLFW_FALSE;
1986b877906bSopenharmony_ci
1987b877906bSopenharmony_ci    if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)
1988b877906bSopenharmony_ci        return GLFW_FALSE;
1989b877906bSopenharmony_ci
1990b877906bSopenharmony_ci    if (!IsWindows8OrGreater())
1991b877906bSopenharmony_ci    {
1992b877906bSopenharmony_ci        // HACK: Disable framebuffer transparency on Windows 7 when the
1993b877906bSopenharmony_ci        //       colorization color is opaque, because otherwise the window
1994b877906bSopenharmony_ci        //       contents is blended additively with the previous frame instead
1995b877906bSopenharmony_ci        //       of replacing it
1996b877906bSopenharmony_ci        if (FAILED(DwmGetColorizationColor(&color, &opaque)) || opaque)
1997b877906bSopenharmony_ci            return GLFW_FALSE;
1998b877906bSopenharmony_ci    }
1999b877906bSopenharmony_ci
2000b877906bSopenharmony_ci    return GLFW_TRUE;
2001b877906bSopenharmony_ci}
2002b877906bSopenharmony_ci
2003b877906bSopenharmony_civoid _glfwSetWindowResizableWin32(_GLFWwindow* window, GLFWbool enabled)
2004b877906bSopenharmony_ci{
2005b877906bSopenharmony_ci    updateWindowStyles(window);
2006b877906bSopenharmony_ci}
2007b877906bSopenharmony_ci
2008b877906bSopenharmony_civoid _glfwSetWindowDecoratedWin32(_GLFWwindow* window, GLFWbool enabled)
2009b877906bSopenharmony_ci{
2010b877906bSopenharmony_ci    updateWindowStyles(window);
2011b877906bSopenharmony_ci}
2012b877906bSopenharmony_ci
2013b877906bSopenharmony_civoid _glfwSetWindowFloatingWin32(_GLFWwindow* window, GLFWbool enabled)
2014b877906bSopenharmony_ci{
2015b877906bSopenharmony_ci    const HWND after = enabled ? HWND_TOPMOST : HWND_NOTOPMOST;
2016b877906bSopenharmony_ci    SetWindowPos(window->win32.handle, after, 0, 0, 0, 0,
2017b877906bSopenharmony_ci                 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
2018b877906bSopenharmony_ci}
2019b877906bSopenharmony_ci
2020b877906bSopenharmony_civoid _glfwSetWindowMousePassthroughWin32(_GLFWwindow* window, GLFWbool enabled)
2021b877906bSopenharmony_ci{
2022b877906bSopenharmony_ci    COLORREF key = 0;
2023b877906bSopenharmony_ci    BYTE alpha = 0;
2024b877906bSopenharmony_ci    DWORD flags = 0;
2025b877906bSopenharmony_ci    DWORD exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
2026b877906bSopenharmony_ci
2027b877906bSopenharmony_ci    if (exStyle & WS_EX_LAYERED)
2028b877906bSopenharmony_ci        GetLayeredWindowAttributes(window->win32.handle, &key, &alpha, &flags);
2029b877906bSopenharmony_ci
2030b877906bSopenharmony_ci    if (enabled)
2031b877906bSopenharmony_ci        exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);
2032b877906bSopenharmony_ci    else
2033b877906bSopenharmony_ci    {
2034b877906bSopenharmony_ci        exStyle &= ~WS_EX_TRANSPARENT;
2035b877906bSopenharmony_ci        // NOTE: Window opacity also needs the layered window style so do not
2036b877906bSopenharmony_ci        //       remove it if the window is alpha blended
2037b877906bSopenharmony_ci        if (exStyle & WS_EX_LAYERED)
2038b877906bSopenharmony_ci        {
2039b877906bSopenharmony_ci            if (!(flags & LWA_ALPHA))
2040b877906bSopenharmony_ci                exStyle &= ~WS_EX_LAYERED;
2041b877906bSopenharmony_ci        }
2042b877906bSopenharmony_ci    }
2043b877906bSopenharmony_ci
2044b877906bSopenharmony_ci    SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
2045b877906bSopenharmony_ci
2046b877906bSopenharmony_ci    if (enabled)
2047b877906bSopenharmony_ci        SetLayeredWindowAttributes(window->win32.handle, key, alpha, flags);
2048b877906bSopenharmony_ci}
2049b877906bSopenharmony_ci
2050b877906bSopenharmony_cifloat _glfwGetWindowOpacityWin32(_GLFWwindow* window)
2051b877906bSopenharmony_ci{
2052b877906bSopenharmony_ci    BYTE alpha;
2053b877906bSopenharmony_ci    DWORD flags;
2054b877906bSopenharmony_ci
2055b877906bSopenharmony_ci    if ((GetWindowLongW(window->win32.handle, GWL_EXSTYLE) & WS_EX_LAYERED) &&
2056b877906bSopenharmony_ci        GetLayeredWindowAttributes(window->win32.handle, NULL, &alpha, &flags))
2057b877906bSopenharmony_ci    {
2058b877906bSopenharmony_ci        if (flags & LWA_ALPHA)
2059b877906bSopenharmony_ci            return alpha / 255.f;
2060b877906bSopenharmony_ci    }
2061b877906bSopenharmony_ci
2062b877906bSopenharmony_ci    return 1.f;
2063b877906bSopenharmony_ci}
2064b877906bSopenharmony_ci
2065b877906bSopenharmony_civoid _glfwSetWindowOpacityWin32(_GLFWwindow* window, float opacity)
2066b877906bSopenharmony_ci{
2067b877906bSopenharmony_ci    LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
2068b877906bSopenharmony_ci    if (opacity < 1.f || (exStyle & WS_EX_TRANSPARENT))
2069b877906bSopenharmony_ci    {
2070b877906bSopenharmony_ci        const BYTE alpha = (BYTE) (255 * opacity);
2071b877906bSopenharmony_ci        exStyle |= WS_EX_LAYERED;
2072b877906bSopenharmony_ci        SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
2073b877906bSopenharmony_ci        SetLayeredWindowAttributes(window->win32.handle, 0, alpha, LWA_ALPHA);
2074b877906bSopenharmony_ci    }
2075b877906bSopenharmony_ci    else if (exStyle & WS_EX_TRANSPARENT)
2076b877906bSopenharmony_ci    {
2077b877906bSopenharmony_ci        SetLayeredWindowAttributes(window->win32.handle, 0, 0, 0);
2078b877906bSopenharmony_ci    }
2079b877906bSopenharmony_ci    else
2080b877906bSopenharmony_ci    {
2081b877906bSopenharmony_ci        exStyle &= ~WS_EX_LAYERED;
2082b877906bSopenharmony_ci        SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
2083b877906bSopenharmony_ci    }
2084b877906bSopenharmony_ci}
2085b877906bSopenharmony_ci
2086b877906bSopenharmony_civoid _glfwSetRawMouseMotionWin32(_GLFWwindow *window, GLFWbool enabled)
2087b877906bSopenharmony_ci{
2088b877906bSopenharmony_ci    if (_glfw.win32.disabledCursorWindow != window)
2089b877906bSopenharmony_ci        return;
2090b877906bSopenharmony_ci
2091b877906bSopenharmony_ci    if (enabled)
2092b877906bSopenharmony_ci        enableRawMouseMotion(window);
2093b877906bSopenharmony_ci    else
2094b877906bSopenharmony_ci        disableRawMouseMotion(window);
2095b877906bSopenharmony_ci}
2096b877906bSopenharmony_ci
2097b877906bSopenharmony_ciGLFWbool _glfwRawMouseMotionSupportedWin32(void)
2098b877906bSopenharmony_ci{
2099b877906bSopenharmony_ci    return GLFW_TRUE;
2100b877906bSopenharmony_ci}
2101b877906bSopenharmony_ci
2102b877906bSopenharmony_civoid _glfwPollEventsWin32(void)
2103b877906bSopenharmony_ci{
2104b877906bSopenharmony_ci    MSG msg;
2105b877906bSopenharmony_ci    HWND handle;
2106b877906bSopenharmony_ci    _GLFWwindow* window;
2107b877906bSopenharmony_ci
2108b877906bSopenharmony_ci    while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
2109b877906bSopenharmony_ci    {
2110b877906bSopenharmony_ci        if (msg.message == WM_QUIT)
2111b877906bSopenharmony_ci        {
2112b877906bSopenharmony_ci            // NOTE: While GLFW does not itself post WM_QUIT, other processes
2113b877906bSopenharmony_ci            //       may post it to this one, for example Task Manager
2114b877906bSopenharmony_ci            // HACK: Treat WM_QUIT as a close on all windows
2115b877906bSopenharmony_ci
2116b877906bSopenharmony_ci            window = _glfw.windowListHead;
2117b877906bSopenharmony_ci            while (window)
2118b877906bSopenharmony_ci            {
2119b877906bSopenharmony_ci                _glfwInputWindowCloseRequest(window);
2120b877906bSopenharmony_ci                window = window->next;
2121b877906bSopenharmony_ci            }
2122b877906bSopenharmony_ci        }
2123b877906bSopenharmony_ci        else
2124b877906bSopenharmony_ci        {
2125b877906bSopenharmony_ci            TranslateMessage(&msg);
2126b877906bSopenharmony_ci            DispatchMessageW(&msg);
2127b877906bSopenharmony_ci        }
2128b877906bSopenharmony_ci    }
2129b877906bSopenharmony_ci
2130b877906bSopenharmony_ci    // HACK: Release modifier keys that the system did not emit KEYUP for
2131b877906bSopenharmony_ci    // NOTE: Shift keys on Windows tend to "stick" when both are pressed as
2132b877906bSopenharmony_ci    //       no key up message is generated by the first key release
2133b877906bSopenharmony_ci    // NOTE: Windows key is not reported as released by the Win+V hotkey
2134b877906bSopenharmony_ci    //       Other Win hotkeys are handled implicitly by _glfwInputWindowFocus
2135b877906bSopenharmony_ci    //       because they change the input focus
2136b877906bSopenharmony_ci    // NOTE: The other half of this is in the WM_*KEY* handler in windowProc
2137b877906bSopenharmony_ci    handle = GetActiveWindow();
2138b877906bSopenharmony_ci    if (handle)
2139b877906bSopenharmony_ci    {
2140b877906bSopenharmony_ci        window = GetPropW(handle, L"GLFW");
2141b877906bSopenharmony_ci        if (window)
2142b877906bSopenharmony_ci        {
2143b877906bSopenharmony_ci            int i;
2144b877906bSopenharmony_ci            const int keys[4][2] =
2145b877906bSopenharmony_ci            {
2146b877906bSopenharmony_ci                { VK_LSHIFT, GLFW_KEY_LEFT_SHIFT },
2147b877906bSopenharmony_ci                { VK_RSHIFT, GLFW_KEY_RIGHT_SHIFT },
2148b877906bSopenharmony_ci                { VK_LWIN, GLFW_KEY_LEFT_SUPER },
2149b877906bSopenharmony_ci                { VK_RWIN, GLFW_KEY_RIGHT_SUPER }
2150b877906bSopenharmony_ci            };
2151b877906bSopenharmony_ci
2152b877906bSopenharmony_ci            for (i = 0;  i < 4;  i++)
2153b877906bSopenharmony_ci            {
2154b877906bSopenharmony_ci                const int vk = keys[i][0];
2155b877906bSopenharmony_ci                const int key = keys[i][1];
2156b877906bSopenharmony_ci                const int scancode = _glfw.win32.scancodes[key];
2157b877906bSopenharmony_ci
2158b877906bSopenharmony_ci                if ((GetKeyState(vk) & 0x8000))
2159b877906bSopenharmony_ci                    continue;
2160b877906bSopenharmony_ci                if (window->keys[key] != GLFW_PRESS)
2161b877906bSopenharmony_ci                    continue;
2162b877906bSopenharmony_ci
2163b877906bSopenharmony_ci                _glfwInputKey(window, key, scancode, GLFW_RELEASE, getKeyMods());
2164b877906bSopenharmony_ci            }
2165b877906bSopenharmony_ci        }
2166b877906bSopenharmony_ci    }
2167b877906bSopenharmony_ci
2168b877906bSopenharmony_ci    window = _glfw.win32.disabledCursorWindow;
2169b877906bSopenharmony_ci    if (window)
2170b877906bSopenharmony_ci    {
2171b877906bSopenharmony_ci        int width, height;
2172b877906bSopenharmony_ci        _glfwGetWindowSizeWin32(window, &width, &height);
2173b877906bSopenharmony_ci
2174b877906bSopenharmony_ci        // NOTE: Re-center the cursor only if it has moved since the last call,
2175b877906bSopenharmony_ci        //       to avoid breaking glfwWaitEvents with WM_MOUSEMOVE
2176b877906bSopenharmony_ci        // The re-center is required in order to prevent the mouse cursor stopping at the edges of the screen.
2177b877906bSopenharmony_ci        if (window->win32.lastCursorPosX != width / 2 ||
2178b877906bSopenharmony_ci            window->win32.lastCursorPosY != height / 2)
2179b877906bSopenharmony_ci        {
2180b877906bSopenharmony_ci            _glfwSetCursorPosWin32(window, width / 2, height / 2);
2181b877906bSopenharmony_ci        }
2182b877906bSopenharmony_ci    }
2183b877906bSopenharmony_ci}
2184b877906bSopenharmony_ci
2185b877906bSopenharmony_civoid _glfwWaitEventsWin32(void)
2186b877906bSopenharmony_ci{
2187b877906bSopenharmony_ci    WaitMessage();
2188b877906bSopenharmony_ci
2189b877906bSopenharmony_ci    _glfwPollEventsWin32();
2190b877906bSopenharmony_ci}
2191b877906bSopenharmony_ci
2192b877906bSopenharmony_civoid _glfwWaitEventsTimeoutWin32(double timeout)
2193b877906bSopenharmony_ci{
2194b877906bSopenharmony_ci    MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLINPUT);
2195b877906bSopenharmony_ci
2196b877906bSopenharmony_ci    _glfwPollEventsWin32();
2197b877906bSopenharmony_ci}
2198b877906bSopenharmony_ci
2199b877906bSopenharmony_civoid _glfwPostEmptyEventWin32(void)
2200b877906bSopenharmony_ci{
2201b877906bSopenharmony_ci    PostMessageW(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
2202b877906bSopenharmony_ci}
2203b877906bSopenharmony_ci
2204b877906bSopenharmony_civoid _glfwGetCursorPosWin32(_GLFWwindow* window, double* xpos, double* ypos)
2205b877906bSopenharmony_ci{
2206b877906bSopenharmony_ci    POINT pos;
2207b877906bSopenharmony_ci
2208b877906bSopenharmony_ci    if (GetCursorPos(&pos))
2209b877906bSopenharmony_ci    {
2210b877906bSopenharmony_ci        ScreenToClient(window->win32.handle, &pos);
2211b877906bSopenharmony_ci
2212b877906bSopenharmony_ci        if (xpos)
2213b877906bSopenharmony_ci            *xpos = pos.x;
2214b877906bSopenharmony_ci        if (ypos)
2215b877906bSopenharmony_ci            *ypos = pos.y;
2216b877906bSopenharmony_ci    }
2217b877906bSopenharmony_ci}
2218b877906bSopenharmony_ci
2219b877906bSopenharmony_civoid _glfwSetCursorPosWin32(_GLFWwindow* window, double xpos, double ypos)
2220b877906bSopenharmony_ci{
2221b877906bSopenharmony_ci    POINT pos = { (int) xpos, (int) ypos };
2222b877906bSopenharmony_ci
2223b877906bSopenharmony_ci    // Store the new position so it can be recognized later
2224b877906bSopenharmony_ci    window->win32.lastCursorPosX = pos.x;
2225b877906bSopenharmony_ci    window->win32.lastCursorPosY = pos.y;
2226b877906bSopenharmony_ci
2227b877906bSopenharmony_ci    ClientToScreen(window->win32.handle, &pos);
2228b877906bSopenharmony_ci    SetCursorPos(pos.x, pos.y);
2229b877906bSopenharmony_ci}
2230b877906bSopenharmony_ci
2231b877906bSopenharmony_civoid _glfwSetCursorModeWin32(_GLFWwindow* window, int mode)
2232b877906bSopenharmony_ci{
2233b877906bSopenharmony_ci    if (_glfwWindowFocusedWin32(window))
2234b877906bSopenharmony_ci    {
2235b877906bSopenharmony_ci        if (mode == GLFW_CURSOR_DISABLED)
2236b877906bSopenharmony_ci        {
2237b877906bSopenharmony_ci            _glfwGetCursorPosWin32(window,
2238b877906bSopenharmony_ci                                   &_glfw.win32.restoreCursorPosX,
2239b877906bSopenharmony_ci                                   &_glfw.win32.restoreCursorPosY);
2240b877906bSopenharmony_ci            _glfwCenterCursorInContentArea(window);
2241b877906bSopenharmony_ci            if (window->rawMouseMotion)
2242b877906bSopenharmony_ci                enableRawMouseMotion(window);
2243b877906bSopenharmony_ci        }
2244b877906bSopenharmony_ci        else if (_glfw.win32.disabledCursorWindow == window)
2245b877906bSopenharmony_ci        {
2246b877906bSopenharmony_ci            if (window->rawMouseMotion)
2247b877906bSopenharmony_ci                disableRawMouseMotion(window);
2248b877906bSopenharmony_ci        }
2249b877906bSopenharmony_ci
2250b877906bSopenharmony_ci        if (mode == GLFW_CURSOR_DISABLED || mode == GLFW_CURSOR_CAPTURED)
2251b877906bSopenharmony_ci            captureCursor(window);
2252b877906bSopenharmony_ci        else
2253b877906bSopenharmony_ci            releaseCursor();
2254b877906bSopenharmony_ci
2255b877906bSopenharmony_ci        if (mode == GLFW_CURSOR_DISABLED)
2256b877906bSopenharmony_ci            _glfw.win32.disabledCursorWindow = window;
2257b877906bSopenharmony_ci        else if (_glfw.win32.disabledCursorWindow == window)
2258b877906bSopenharmony_ci        {
2259b877906bSopenharmony_ci            _glfw.win32.disabledCursorWindow = NULL;
2260b877906bSopenharmony_ci            _glfwSetCursorPosWin32(window,
2261b877906bSopenharmony_ci                                   _glfw.win32.restoreCursorPosX,
2262b877906bSopenharmony_ci                                   _glfw.win32.restoreCursorPosY);
2263b877906bSopenharmony_ci        }
2264b877906bSopenharmony_ci    }
2265b877906bSopenharmony_ci
2266b877906bSopenharmony_ci    if (cursorInContentArea(window))
2267b877906bSopenharmony_ci        updateCursorImage(window);
2268b877906bSopenharmony_ci}
2269b877906bSopenharmony_ci
2270b877906bSopenharmony_ciconst char* _glfwGetScancodeNameWin32(int scancode)
2271b877906bSopenharmony_ci{
2272b877906bSopenharmony_ci    if (scancode < 0 || scancode > (KF_EXTENDED | 0xff))
2273b877906bSopenharmony_ci    {
2274b877906bSopenharmony_ci        _glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode %i", scancode);
2275b877906bSopenharmony_ci        return NULL;
2276b877906bSopenharmony_ci    }
2277b877906bSopenharmony_ci
2278b877906bSopenharmony_ci    const int key = _glfw.win32.keycodes[scancode];
2279b877906bSopenharmony_ci    if (key == GLFW_KEY_UNKNOWN)
2280b877906bSopenharmony_ci        return NULL;
2281b877906bSopenharmony_ci
2282b877906bSopenharmony_ci    return _glfw.win32.keynames[key];
2283b877906bSopenharmony_ci}
2284b877906bSopenharmony_ci
2285b877906bSopenharmony_ciint _glfwGetKeyScancodeWin32(int key)
2286b877906bSopenharmony_ci{
2287b877906bSopenharmony_ci    return _glfw.win32.scancodes[key];
2288b877906bSopenharmony_ci}
2289b877906bSopenharmony_ci
2290b877906bSopenharmony_ciGLFWbool _glfwCreateCursorWin32(_GLFWcursor* cursor,
2291b877906bSopenharmony_ci                                const GLFWimage* image,
2292b877906bSopenharmony_ci                                int xhot, int yhot)
2293b877906bSopenharmony_ci{
2294b877906bSopenharmony_ci    cursor->win32.handle = (HCURSOR) createIcon(image, xhot, yhot, GLFW_FALSE);
2295b877906bSopenharmony_ci    if (!cursor->win32.handle)
2296b877906bSopenharmony_ci        return GLFW_FALSE;
2297b877906bSopenharmony_ci
2298b877906bSopenharmony_ci    return GLFW_TRUE;
2299b877906bSopenharmony_ci}
2300b877906bSopenharmony_ci
2301b877906bSopenharmony_ciGLFWbool _glfwCreateStandardCursorWin32(_GLFWcursor* cursor, int shape)
2302b877906bSopenharmony_ci{
2303b877906bSopenharmony_ci    int id = 0;
2304b877906bSopenharmony_ci
2305b877906bSopenharmony_ci    switch (shape)
2306b877906bSopenharmony_ci    {
2307b877906bSopenharmony_ci        case GLFW_ARROW_CURSOR:
2308b877906bSopenharmony_ci            id = OCR_NORMAL;
2309b877906bSopenharmony_ci            break;
2310b877906bSopenharmony_ci        case GLFW_IBEAM_CURSOR:
2311b877906bSopenharmony_ci            id = OCR_IBEAM;
2312b877906bSopenharmony_ci            break;
2313b877906bSopenharmony_ci        case GLFW_CROSSHAIR_CURSOR:
2314b877906bSopenharmony_ci            id = OCR_CROSS;
2315b877906bSopenharmony_ci            break;
2316b877906bSopenharmony_ci        case GLFW_POINTING_HAND_CURSOR:
2317b877906bSopenharmony_ci            id = OCR_HAND;
2318b877906bSopenharmony_ci            break;
2319b877906bSopenharmony_ci        case GLFW_RESIZE_EW_CURSOR:
2320b877906bSopenharmony_ci            id = OCR_SIZEWE;
2321b877906bSopenharmony_ci            break;
2322b877906bSopenharmony_ci        case GLFW_RESIZE_NS_CURSOR:
2323b877906bSopenharmony_ci            id = OCR_SIZENS;
2324b877906bSopenharmony_ci            break;
2325b877906bSopenharmony_ci        case GLFW_RESIZE_NWSE_CURSOR:
2326b877906bSopenharmony_ci            id = OCR_SIZENWSE;
2327b877906bSopenharmony_ci            break;
2328b877906bSopenharmony_ci        case GLFW_RESIZE_NESW_CURSOR:
2329b877906bSopenharmony_ci            id = OCR_SIZENESW;
2330b877906bSopenharmony_ci            break;
2331b877906bSopenharmony_ci        case GLFW_RESIZE_ALL_CURSOR:
2332b877906bSopenharmony_ci            id = OCR_SIZEALL;
2333b877906bSopenharmony_ci            break;
2334b877906bSopenharmony_ci        case GLFW_NOT_ALLOWED_CURSOR:
2335b877906bSopenharmony_ci            id = OCR_NO;
2336b877906bSopenharmony_ci            break;
2337b877906bSopenharmony_ci        default:
2338b877906bSopenharmony_ci            _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Unknown standard cursor");
2339b877906bSopenharmony_ci            return GLFW_FALSE;
2340b877906bSopenharmony_ci    }
2341b877906bSopenharmony_ci
2342b877906bSopenharmony_ci    cursor->win32.handle = LoadImageW(NULL,
2343b877906bSopenharmony_ci                                      MAKEINTRESOURCEW(id), IMAGE_CURSOR, 0, 0,
2344b877906bSopenharmony_ci                                      LR_DEFAULTSIZE | LR_SHARED);
2345b877906bSopenharmony_ci    if (!cursor->win32.handle)
2346b877906bSopenharmony_ci    {
2347b877906bSopenharmony_ci        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
2348b877906bSopenharmony_ci                             "Win32: Failed to create standard cursor");
2349b877906bSopenharmony_ci        return GLFW_FALSE;
2350b877906bSopenharmony_ci    }
2351b877906bSopenharmony_ci
2352b877906bSopenharmony_ci    return GLFW_TRUE;
2353b877906bSopenharmony_ci}
2354b877906bSopenharmony_ci
2355b877906bSopenharmony_civoid _glfwDestroyCursorWin32(_GLFWcursor* cursor)
2356b877906bSopenharmony_ci{
2357b877906bSopenharmony_ci    if (cursor->win32.handle)
2358b877906bSopenharmony_ci        DestroyIcon((HICON) cursor->win32.handle);
2359b877906bSopenharmony_ci}
2360b877906bSopenharmony_ci
2361b877906bSopenharmony_civoid _glfwSetCursorWin32(_GLFWwindow* window, _GLFWcursor* cursor)
2362b877906bSopenharmony_ci{
2363b877906bSopenharmony_ci    if (cursorInContentArea(window))
2364b877906bSopenharmony_ci        updateCursorImage(window);
2365b877906bSopenharmony_ci}
2366b877906bSopenharmony_ci
2367b877906bSopenharmony_civoid _glfwSetClipboardStringWin32(const char* string)
2368b877906bSopenharmony_ci{
2369b877906bSopenharmony_ci    int characterCount, tries = 0;
2370b877906bSopenharmony_ci    HANDLE object;
2371b877906bSopenharmony_ci    WCHAR* buffer;
2372b877906bSopenharmony_ci
2373b877906bSopenharmony_ci    characterCount = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
2374b877906bSopenharmony_ci    if (!characterCount)
2375b877906bSopenharmony_ci        return;
2376b877906bSopenharmony_ci
2377b877906bSopenharmony_ci    object = GlobalAlloc(GMEM_MOVEABLE, characterCount * sizeof(WCHAR));
2378b877906bSopenharmony_ci    if (!object)
2379b877906bSopenharmony_ci    {
2380b877906bSopenharmony_ci        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
2381b877906bSopenharmony_ci                             "Win32: Failed to allocate global handle for clipboard");
2382b877906bSopenharmony_ci        return;
2383b877906bSopenharmony_ci    }
2384b877906bSopenharmony_ci
2385b877906bSopenharmony_ci    buffer = GlobalLock(object);
2386b877906bSopenharmony_ci    if (!buffer)
2387b877906bSopenharmony_ci    {
2388b877906bSopenharmony_ci        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
2389b877906bSopenharmony_ci                             "Win32: Failed to lock global handle");
2390b877906bSopenharmony_ci        GlobalFree(object);
2391b877906bSopenharmony_ci        return;
2392b877906bSopenharmony_ci    }
2393b877906bSopenharmony_ci
2394b877906bSopenharmony_ci    MultiByteToWideChar(CP_UTF8, 0, string, -1, buffer, characterCount);
2395b877906bSopenharmony_ci    GlobalUnlock(object);
2396b877906bSopenharmony_ci
2397b877906bSopenharmony_ci    // NOTE: Retry clipboard opening a few times as some other application may have it
2398b877906bSopenharmony_ci    //       open and also the Windows Clipboard History reads it after each update
2399b877906bSopenharmony_ci    while (!OpenClipboard(_glfw.win32.helperWindowHandle))
2400b877906bSopenharmony_ci    {
2401b877906bSopenharmony_ci        Sleep(1);
2402b877906bSopenharmony_ci        tries++;
2403b877906bSopenharmony_ci
2404b877906bSopenharmony_ci        if (tries == 3)
2405b877906bSopenharmony_ci        {
2406b877906bSopenharmony_ci            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
2407b877906bSopenharmony_ci                                 "Win32: Failed to open clipboard");
2408b877906bSopenharmony_ci            GlobalFree(object);
2409b877906bSopenharmony_ci            return;
2410b877906bSopenharmony_ci        }
2411b877906bSopenharmony_ci    }
2412b877906bSopenharmony_ci
2413b877906bSopenharmony_ci    EmptyClipboard();
2414b877906bSopenharmony_ci    SetClipboardData(CF_UNICODETEXT, object);
2415b877906bSopenharmony_ci    CloseClipboard();
2416b877906bSopenharmony_ci}
2417b877906bSopenharmony_ci
2418b877906bSopenharmony_ciconst char* _glfwGetClipboardStringWin32(void)
2419b877906bSopenharmony_ci{
2420b877906bSopenharmony_ci    HANDLE object;
2421b877906bSopenharmony_ci    WCHAR* buffer;
2422b877906bSopenharmony_ci    int tries = 0;
2423b877906bSopenharmony_ci
2424b877906bSopenharmony_ci    // NOTE: Retry clipboard opening a few times as some other application may have it
2425b877906bSopenharmony_ci    //       open and also the Windows Clipboard History reads it after each update
2426b877906bSopenharmony_ci    while (!OpenClipboard(_glfw.win32.helperWindowHandle))
2427b877906bSopenharmony_ci    {
2428b877906bSopenharmony_ci        Sleep(1);
2429b877906bSopenharmony_ci        tries++;
2430b877906bSopenharmony_ci
2431b877906bSopenharmony_ci        if (tries == 3)
2432b877906bSopenharmony_ci        {
2433b877906bSopenharmony_ci            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
2434b877906bSopenharmony_ci                                 "Win32: Failed to open clipboard");
2435b877906bSopenharmony_ci            return NULL;
2436b877906bSopenharmony_ci        }
2437b877906bSopenharmony_ci    }
2438b877906bSopenharmony_ci
2439b877906bSopenharmony_ci    object = GetClipboardData(CF_UNICODETEXT);
2440b877906bSopenharmony_ci    if (!object)
2441b877906bSopenharmony_ci    {
2442b877906bSopenharmony_ci        _glfwInputErrorWin32(GLFW_FORMAT_UNAVAILABLE,
2443b877906bSopenharmony_ci                             "Win32: Failed to convert clipboard to string");
2444b877906bSopenharmony_ci        CloseClipboard();
2445b877906bSopenharmony_ci        return NULL;
2446b877906bSopenharmony_ci    }
2447b877906bSopenharmony_ci
2448b877906bSopenharmony_ci    buffer = GlobalLock(object);
2449b877906bSopenharmony_ci    if (!buffer)
2450b877906bSopenharmony_ci    {
2451b877906bSopenharmony_ci        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
2452b877906bSopenharmony_ci                             "Win32: Failed to lock global handle");
2453b877906bSopenharmony_ci        CloseClipboard();
2454b877906bSopenharmony_ci        return NULL;
2455b877906bSopenharmony_ci    }
2456b877906bSopenharmony_ci
2457b877906bSopenharmony_ci    _glfw_free(_glfw.win32.clipboardString);
2458b877906bSopenharmony_ci    _glfw.win32.clipboardString = _glfwCreateUTF8FromWideStringWin32(buffer);
2459b877906bSopenharmony_ci
2460b877906bSopenharmony_ci    GlobalUnlock(object);
2461b877906bSopenharmony_ci    CloseClipboard();
2462b877906bSopenharmony_ci
2463b877906bSopenharmony_ci    return _glfw.win32.clipboardString;
2464b877906bSopenharmony_ci}
2465b877906bSopenharmony_ci
2466b877906bSopenharmony_ciEGLenum _glfwGetEGLPlatformWin32(EGLint** attribs)
2467b877906bSopenharmony_ci{
2468b877906bSopenharmony_ci    if (_glfw.egl.ANGLE_platform_angle)
2469b877906bSopenharmony_ci    {
2470b877906bSopenharmony_ci        int type = 0;
2471b877906bSopenharmony_ci
2472b877906bSopenharmony_ci        if (_glfw.egl.ANGLE_platform_angle_opengl)
2473b877906bSopenharmony_ci        {
2474b877906bSopenharmony_ci            if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_OPENGL)
2475b877906bSopenharmony_ci                type = EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
2476b877906bSopenharmony_ci            else if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_OPENGLES)
2477b877906bSopenharmony_ci                type = EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
2478b877906bSopenharmony_ci        }
2479b877906bSopenharmony_ci
2480b877906bSopenharmony_ci        if (_glfw.egl.ANGLE_platform_angle_d3d)
2481b877906bSopenharmony_ci        {
2482b877906bSopenharmony_ci            if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_D3D9)
2483b877906bSopenharmony_ci                type = EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
2484b877906bSopenharmony_ci            else if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_D3D11)
2485b877906bSopenharmony_ci                type = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
2486b877906bSopenharmony_ci        }
2487b877906bSopenharmony_ci
2488b877906bSopenharmony_ci        if (_glfw.egl.ANGLE_platform_angle_vulkan)
2489b877906bSopenharmony_ci        {
2490b877906bSopenharmony_ci            if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_VULKAN)
2491b877906bSopenharmony_ci                type = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
2492b877906bSopenharmony_ci        }
2493b877906bSopenharmony_ci
2494b877906bSopenharmony_ci        if (type)
2495b877906bSopenharmony_ci        {
2496b877906bSopenharmony_ci            *attribs = _glfw_calloc(3, sizeof(EGLint));
2497b877906bSopenharmony_ci            (*attribs)[0] = EGL_PLATFORM_ANGLE_TYPE_ANGLE;
2498b877906bSopenharmony_ci            (*attribs)[1] = type;
2499b877906bSopenharmony_ci            (*attribs)[2] = EGL_NONE;
2500b877906bSopenharmony_ci            return EGL_PLATFORM_ANGLE_ANGLE;
2501b877906bSopenharmony_ci        }
2502b877906bSopenharmony_ci    }
2503b877906bSopenharmony_ci
2504b877906bSopenharmony_ci    return 0;
2505b877906bSopenharmony_ci}
2506b877906bSopenharmony_ci
2507b877906bSopenharmony_ciEGLNativeDisplayType _glfwGetEGLNativeDisplayWin32(void)
2508b877906bSopenharmony_ci{
2509b877906bSopenharmony_ci    return GetDC(_glfw.win32.helperWindowHandle);
2510b877906bSopenharmony_ci}
2511b877906bSopenharmony_ci
2512b877906bSopenharmony_ciEGLNativeWindowType _glfwGetEGLNativeWindowWin32(_GLFWwindow* window)
2513b877906bSopenharmony_ci{
2514b877906bSopenharmony_ci    return window->win32.handle;
2515b877906bSopenharmony_ci}
2516b877906bSopenharmony_ci
2517b877906bSopenharmony_civoid _glfwGetRequiredInstanceExtensionsWin32(char** extensions)
2518b877906bSopenharmony_ci{
2519b877906bSopenharmony_ci    if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_win32_surface)
2520b877906bSopenharmony_ci        return;
2521b877906bSopenharmony_ci
2522b877906bSopenharmony_ci    extensions[0] = "VK_KHR_surface";
2523b877906bSopenharmony_ci    extensions[1] = "VK_KHR_win32_surface";
2524b877906bSopenharmony_ci}
2525b877906bSopenharmony_ci
2526b877906bSopenharmony_ciGLFWbool _glfwGetPhysicalDevicePresentationSupportWin32(VkInstance instance,
2527b877906bSopenharmony_ci                                                        VkPhysicalDevice device,
2528b877906bSopenharmony_ci                                                        uint32_t queuefamily)
2529b877906bSopenharmony_ci{
2530b877906bSopenharmony_ci    PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
2531b877906bSopenharmony_ci        vkGetPhysicalDeviceWin32PresentationSupportKHR =
2532b877906bSopenharmony_ci        (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)
2533b877906bSopenharmony_ci        vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
2534b877906bSopenharmony_ci    if (!vkGetPhysicalDeviceWin32PresentationSupportKHR)
2535b877906bSopenharmony_ci    {
2536b877906bSopenharmony_ci        _glfwInputError(GLFW_API_UNAVAILABLE,
2537b877906bSopenharmony_ci                        "Win32: Vulkan instance missing VK_KHR_win32_surface extension");
2538b877906bSopenharmony_ci        return GLFW_FALSE;
2539b877906bSopenharmony_ci    }
2540b877906bSopenharmony_ci
2541b877906bSopenharmony_ci    return vkGetPhysicalDeviceWin32PresentationSupportKHR(device, queuefamily);
2542b877906bSopenharmony_ci}
2543b877906bSopenharmony_ci
2544b877906bSopenharmony_ciVkResult _glfwCreateWindowSurfaceWin32(VkInstance instance,
2545b877906bSopenharmony_ci                                       _GLFWwindow* window,
2546b877906bSopenharmony_ci                                       const VkAllocationCallbacks* allocator,
2547b877906bSopenharmony_ci                                       VkSurfaceKHR* surface)
2548b877906bSopenharmony_ci{
2549b877906bSopenharmony_ci    VkResult err;
2550b877906bSopenharmony_ci    VkWin32SurfaceCreateInfoKHR sci;
2551b877906bSopenharmony_ci    PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;
2552b877906bSopenharmony_ci
2553b877906bSopenharmony_ci    vkCreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)
2554b877906bSopenharmony_ci        vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR");
2555b877906bSopenharmony_ci    if (!vkCreateWin32SurfaceKHR)
2556b877906bSopenharmony_ci    {
2557b877906bSopenharmony_ci        _glfwInputError(GLFW_API_UNAVAILABLE,
2558b877906bSopenharmony_ci                        "Win32: Vulkan instance missing VK_KHR_win32_surface extension");
2559b877906bSopenharmony_ci        return VK_ERROR_EXTENSION_NOT_PRESENT;
2560b877906bSopenharmony_ci    }
2561b877906bSopenharmony_ci
2562b877906bSopenharmony_ci    memset(&sci, 0, sizeof(sci));
2563b877906bSopenharmony_ci    sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
2564b877906bSopenharmony_ci    sci.hinstance = _glfw.win32.instance;
2565b877906bSopenharmony_ci    sci.hwnd = window->win32.handle;
2566b877906bSopenharmony_ci
2567b877906bSopenharmony_ci    err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);
2568b877906bSopenharmony_ci    if (err)
2569b877906bSopenharmony_ci    {
2570b877906bSopenharmony_ci        _glfwInputError(GLFW_PLATFORM_ERROR,
2571b877906bSopenharmony_ci                        "Win32: Failed to create Vulkan surface: %s",
2572b877906bSopenharmony_ci                        _glfwGetVulkanResultString(err));
2573b877906bSopenharmony_ci    }
2574b877906bSopenharmony_ci
2575b877906bSopenharmony_ci    return err;
2576b877906bSopenharmony_ci}
2577b877906bSopenharmony_ci
2578b877906bSopenharmony_ciGLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
2579b877906bSopenharmony_ci{
2580b877906bSopenharmony_ci    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
2581b877906bSopenharmony_ci
2582b877906bSopenharmony_ci    if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32)
2583b877906bSopenharmony_ci    {
2584b877906bSopenharmony_ci        _glfwInputError(GLFW_PLATFORM_UNAVAILABLE,
2585b877906bSopenharmony_ci                        "Win32: Platform not initialized");
2586b877906bSopenharmony_ci        return NULL;
2587b877906bSopenharmony_ci    }
2588b877906bSopenharmony_ci
2589b877906bSopenharmony_ci    _GLFWwindow* window = (_GLFWwindow*) handle;
2590b877906bSopenharmony_ci    assert(window != NULL);
2591b877906bSopenharmony_ci
2592b877906bSopenharmony_ci    return window->win32.handle;
2593b877906bSopenharmony_ci}
2594b877906bSopenharmony_ci
2595b877906bSopenharmony_ci#endif // _GLFW_WIN32
2596b877906bSopenharmony_ci
2597