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