win32_window.c
Go to the documentation of this file.
1 //========================================================================
2 // GLFW 3.3 Win32 - www.glfw.org
3 //------------------------------------------------------------------------
4 // Copyright (c) 2002-2006 Marcus Geelnard
5 // Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
6 //
7 // This software is provided 'as-is', without any express or implied
8 // warranty. In no event will the authors be held liable for any damages
9 // arising from the use of this software.
10 //
11 // Permission is granted to anyone to use this software for any purpose,
12 // including commercial applications, and to alter it and redistribute it
13 // freely, subject to the following restrictions:
14 //
15 // 1. The origin of this software must not be misrepresented; you must not
16 // claim that you wrote the original software. If you use this software
17 // in a product, an acknowledgment in the product documentation would
18 // be appreciated but is not required.
19 //
20 // 2. Altered source versions must be plainly marked as such, and must not
21 // be misrepresented as being the original software.
22 //
23 // 3. This notice may not be removed or altered from any source
24 // distribution.
25 //
26 //========================================================================
27 
28 #include "internal.h"
29 
30 #include <limits.h>
31 #include <stdlib.h>
32 #include <malloc.h>
33 #include <string.h>
34 #include <windowsx.h>
35 #include <shellapi.h>
36 
37 #define _GLFW_KEY_INVALID -2
38 
39 // Returns the window style for the specified window
40 //
41 static DWORD getWindowStyle(const _GLFWwindow* window)
42 {
43  DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
44 
45  if (window->monitor)
46  style |= WS_POPUP;
47  else
48  {
49  style |= WS_SYSMENU | WS_MINIMIZEBOX;
50 
51  if (window->decorated)
52  {
53  style |= WS_CAPTION;
54 
55  if (window->resizable)
56  style |= WS_MAXIMIZEBOX | WS_THICKFRAME;
57  }
58  else
59  style |= WS_POPUP;
60  }
61 
62  return style;
63 }
64 
65 // Returns the extended window style for the specified window
66 //
67 static DWORD getWindowExStyle(const _GLFWwindow* window)
68 {
69  DWORD style = WS_EX_APPWINDOW;
70 
71  if (window->monitor || window->floating)
72  style |= WS_EX_TOPMOST;
73 
74  return style;
75 }
76 
77 // Returns the image whose area most closely matches the desired one
78 //
79 static const GLFWimage* chooseImage(int count, const GLFWimage* images,
80  int width, int height)
81 {
82  int i, leastDiff = INT_MAX;
83  const GLFWimage* closest = NULL;
84 
85  for (i = 0; i < count; i++)
86  {
87  const int currDiff = abs(images[i].width * images[i].height -
88  width * height);
89  if (currDiff < leastDiff)
90  {
91  closest = images + i;
92  leastDiff = currDiff;
93  }
94  }
95 
96  return closest;
97 }
98 
99 // Creates an RGBA icon or cursor
100 //
101 static HICON createIcon(const GLFWimage* image,
102  int xhot, int yhot, GLFWbool icon)
103 {
104  int i;
105  HDC dc;
106  HICON handle;
107  HBITMAP color, mask;
108  BITMAPV5HEADER bi;
109  ICONINFO ii;
110  unsigned char* target = NULL;
111  unsigned char* source = image->pixels;
112 
113  ZeroMemory(&bi, sizeof(bi));
114  bi.bV5Size = sizeof(bi);
115  bi.bV5Width = image->width;
116  bi.bV5Height = -image->height;
117  bi.bV5Planes = 1;
118  bi.bV5BitCount = 32;
119  bi.bV5Compression = BI_BITFIELDS;
120  bi.bV5RedMask = 0x00ff0000;
121  bi.bV5GreenMask = 0x0000ff00;
122  bi.bV5BlueMask = 0x000000ff;
123  bi.bV5AlphaMask = 0xff000000;
124 
125  dc = GetDC(NULL);
126  color = CreateDIBSection(dc,
127  (BITMAPINFO*) &bi,
128  DIB_RGB_COLORS,
129  (void**) &target,
130  NULL,
131  (DWORD) 0);
132  ReleaseDC(NULL, dc);
133 
134  if (!color)
135  {
137  "Win32: Failed to create RGBA bitmap");
138  return NULL;
139  }
140 
141  mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
142  if (!mask)
143  {
145  "Win32: Failed to create mask bitmap");
146  DeleteObject(color);
147  return NULL;
148  }
149 
150  for (i = 0; i < image->width * image->height; i++)
151  {
152  target[0] = source[2];
153  target[1] = source[1];
154  target[2] = source[0];
155  target[3] = source[3];
156  target += 4;
157  source += 4;
158  }
159 
160  ZeroMemory(&ii, sizeof(ii));
161  ii.fIcon = icon;
162  ii.xHotspot = xhot;
163  ii.yHotspot = yhot;
164  ii.hbmMask = mask;
165  ii.hbmColor = color;
166 
167  handle = CreateIconIndirect(&ii);
168 
169  DeleteObject(color);
170  DeleteObject(mask);
171 
172  if (!handle)
173  {
174  if (icon)
175  {
177  "Win32: Failed to create icon");
178  }
179  else
180  {
182  "Win32: Failed to create cursor");
183  }
184  }
185 
186  return handle;
187 }
188 
189 // Translate client window size to full window size according to styles and DPI
190 //
191 static void getFullWindowSize(DWORD style, DWORD exStyle,
192  int clientWidth, int clientHeight,
193  int* fullWidth, int* fullHeight,
194  UINT dpi)
195 {
196  RECT rect = { 0, 0, clientWidth, clientHeight };
197 
199  AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
200  else
201  AdjustWindowRectEx(&rect, style, FALSE, exStyle);
202 
203  *fullWidth = rect.right - rect.left;
204  *fullHeight = rect.bottom - rect.top;
205 }
206 
207 // Enforce the client rect aspect ratio based on which edge is being dragged
208 //
209 static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
210 {
211  int xoff, yoff;
212  UINT dpi = USER_DEFAULT_SCREEN_DPI;
213  const float ratio = (float) window->numer / (float) window->denom;
214 
216  dpi = GetDpiForWindow(window->win32.handle);
217 
219  0, 0, &xoff, &yoff, dpi);
220 
221  if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT ||
222  edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT)
223  {
224  area->bottom = area->top + yoff +
225  (int) ((area->right - area->left - xoff) / ratio);
226  }
227  else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT)
228  {
229  area->top = area->bottom - yoff -
230  (int) ((area->right - area->left - xoff) / ratio);
231  }
232  else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM)
233  {
234  area->right = area->left + xoff +
235  (int) ((area->bottom - area->top - yoff) * ratio);
236  }
237 }
238 
239 // Centers the cursor over the window client area
240 //
241 static void centerCursor(_GLFWwindow* window)
242 {
243  int width, height;
244  _glfwPlatformGetWindowSize(window, &width, &height);
245  _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
246 }
247 
248 // Updates the cursor image according to its cursor mode
249 //
250 static void updateCursorImage(_GLFWwindow* window)
251 {
252  if (window->cursorMode == GLFW_CURSOR_NORMAL)
253  {
254  if (window->cursor)
255  SetCursor(window->cursor->win32.handle);
256  else
257  SetCursor(LoadCursorW(NULL, IDC_ARROW));
258  }
259  else
260  SetCursor(NULL);
261 }
262 
263 // Updates the cursor clip rect
264 //
265 static void updateClipRect(_GLFWwindow* window)
266 {
267  if (window)
268  {
269  RECT clipRect;
270  GetClientRect(window->win32.handle, &clipRect);
271  ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
272  ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
273  ClipCursor(&clipRect);
274  }
275  else
276  ClipCursor(NULL);
277 }
278 
279 // Apply disabled cursor mode to a focused window
280 //
281 static void disableCursor(_GLFWwindow* window)
282 {
283  const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };
284 
285  _glfw.win32.disabledCursorWindow = window;
287  &_glfw.win32.restoreCursorPosX,
288  &_glfw.win32.restoreCursorPosY);
289  updateCursorImage(window);
290  centerCursor(window);
291  updateClipRect(window);
292 
293  if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
294  {
296  "Win32: Failed to register raw input device");
297  }
298 }
299 
300 // Exit disabled cursor mode for the specified window
301 //
302 static void enableCursor(_GLFWwindow* window)
303 {
304  const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL };
305 
306  _glfw.win32.disabledCursorWindow = NULL;
307  updateClipRect(NULL);
309  _glfw.win32.restoreCursorPosX,
310  _glfw.win32.restoreCursorPosY);
311  updateCursorImage(window);
312 
313  if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
314  {
316  "Win32: Failed to remove raw input device");
317  }
318 }
319 
320 // Returns whether the cursor is in the client area of the specified window
321 //
323 {
324  RECT area;
325  POINT pos;
326 
327  if (!GetCursorPos(&pos))
328  return GLFW_FALSE;
329 
330  if (WindowFromPoint(pos) != window->win32.handle)
331  return GLFW_FALSE;
332 
333  GetClientRect(window->win32.handle, &area);
334  ClientToScreen(window->win32.handle, (POINT*) &area.left);
335  ClientToScreen(window->win32.handle, (POINT*) &area.right);
336 
337  return PtInRect(&area, pos);
338 }
339 
340 // Update native window styles to match attributes
341 //
342 static void updateWindowStyles(const _GLFWwindow* window)
343 {
344  RECT rect;
345  DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
346  style &= ~(WS_OVERLAPPEDWINDOW | WS_POPUP);
347  style |= getWindowStyle(window);
348 
349  GetClientRect(window->win32.handle, &rect);
350 
352  {
353  AdjustWindowRectExForDpi(&rect, style, FALSE,
354  getWindowExStyle(window),
355  GetDpiForWindow(window->win32.handle));
356  }
357  else
358  AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window));
359 
360  ClientToScreen(window->win32.handle, (POINT*) &rect.left);
361  ClientToScreen(window->win32.handle, (POINT*) &rect.right);
362  SetWindowLongW(window->win32.handle, GWL_STYLE, style);
363  SetWindowPos(window->win32.handle, HWND_TOP,
364  rect.left, rect.top,
365  rect.right - rect.left, rect.bottom - rect.top,
366  SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
367 }
368 
369 // Update window framebuffer transparency
370 //
371 static void updateFramebufferTransparency(const _GLFWwindow* window)
372 {
373  BOOL enabled;
374 
376  return;
377 
378  if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
379  {
380  HRGN region = CreateRectRgn(0, 0, -1, -1);
381  DWM_BLURBEHIND bb = {0};
383  bb.hRgnBlur = region;
384  bb.fEnable = TRUE;
385 
386  if (SUCCEEDED(DwmEnableBlurBehindWindow(window->win32.handle, &bb)))
387  {
388  // Decorated windows don't repaint the transparent background
389  // leaving a trail behind animations
390  // HACK: Making the window layered with a transparency color key
391  // seems to fix this. Normally, when specifying
392  // a transparency color key to be used when composing the
393  // layered window, all pixels painted by the window in this
394  // color will be transparent. That doesn't seem to be the
395  // case anymore, at least when used with blur behind window
396  // plus negative region.
397  LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
398  exStyle |= WS_EX_LAYERED;
399  SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
400 
401  // Using a color key not equal to black to fix the trailing
402  // issue. When set to black, something is making the hit test
403  // not resize with the window frame.
404  SetLayeredWindowAttributes(window->win32.handle,
405  RGB(0, 193, 48), 255, LWA_COLORKEY);
406  }
407 
408  DeleteObject(region);
409  }
410  else
411  {
412  LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
413  exStyle &= ~WS_EX_LAYERED;
414  SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
415  RedrawWindow(window->win32.handle, NULL, NULL,
416  RDW_ERASE | RDW_INVALIDATE | RDW_FRAME);
417  }
418 }
419 
420 // Retrieves and translates modifier keys
421 //
422 static int getKeyMods(void)
423 {
424  int mods = 0;
425 
426  if (GetKeyState(VK_SHIFT) & 0x8000)
427  mods |= GLFW_MOD_SHIFT;
428  if (GetKeyState(VK_CONTROL) & 0x8000)
429  mods |= GLFW_MOD_CONTROL;
430  if (GetKeyState(VK_MENU) & 0x8000)
431  mods |= GLFW_MOD_ALT;
432  if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x8000)
433  mods |= GLFW_MOD_SUPER;
434  if (GetKeyState(VK_CAPITAL) & 1)
435  mods |= GLFW_MOD_CAPS_LOCK;
436  if (GetKeyState(VK_NUMLOCK) & 1)
437  mods |= GLFW_MOD_NUM_LOCK;
438 
439  return mods;
440 }
441 
442 // Retrieves and translates modifier keys
443 //
444 static int getAsyncKeyMods(void)
445 {
446  int mods = 0;
447 
448  if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
449  mods |= GLFW_MOD_SHIFT;
450  if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
451  mods |= GLFW_MOD_CONTROL;
452  if (GetAsyncKeyState(VK_MENU) & 0x8000)
453  mods |= GLFW_MOD_ALT;
454  if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) & 0x8000)
455  mods |= GLFW_MOD_SUPER;
456  if (GetAsyncKeyState(VK_CAPITAL) & 1)
457  mods |= GLFW_MOD_CAPS_LOCK;
458  if (GetAsyncKeyState(VK_NUMLOCK) & 1)
459  mods |= GLFW_MOD_NUM_LOCK;
460 
461  return mods;
462 }
463 
464 // Translates a Windows key to the corresponding GLFW key
465 //
466 static int translateKey(WPARAM wParam, LPARAM lParam)
467 {
468  // The Ctrl keys require special handling
469  if (wParam == VK_CONTROL)
470  {
471  MSG next;
472  DWORD time;
473 
474  // Right side keys have the extended key bit set
475  if (lParam & 0x01000000)
476  return GLFW_KEY_RIGHT_CONTROL;
477 
478  // HACK: Alt Gr sends Left Ctrl and then Right Alt in close sequence
479  // We only want the Right Alt message, so if the next message is
480  // Right Alt we ignore this (synthetic) Left Ctrl message
481  time = GetMessageTime();
482 
483  if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))
484  {
485  if (next.message == WM_KEYDOWN ||
486  next.message == WM_SYSKEYDOWN ||
487  next.message == WM_KEYUP ||
488  next.message == WM_SYSKEYUP)
489  {
490  if (next.wParam == VK_MENU &&
491  (next.lParam & 0x01000000) &&
492  next.time == time)
493  {
494  // Next message is Right Alt down so discard this
495  return _GLFW_KEY_INVALID;
496  }
497  }
498  }
499 
500  return GLFW_KEY_LEFT_CONTROL;
501  }
502 
503  if (wParam == VK_PROCESSKEY)
504  {
505  // IME notifies that keys have been filtered by setting the virtual
506  // key-code to VK_PROCESSKEY
507  return _GLFW_KEY_INVALID;
508  }
509 
510  return _glfw.win32.keycodes[HIWORD(lParam) & 0x1FF];
511 }
512 
513 static void fitToMonitor(_GLFWwindow* window)
514 {
515  MONITORINFO mi = { sizeof(mi) };
516  GetMonitorInfo(window->monitor->win32.handle, &mi);
517  SetWindowPos(window->win32.handle, HWND_TOPMOST,
518  mi.rcMonitor.left,
519  mi.rcMonitor.top,
520  mi.rcMonitor.right - mi.rcMonitor.left,
521  mi.rcMonitor.bottom - mi.rcMonitor.top,
522  SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);
523 }
524 
525 // Make the specified window and its video mode active on its monitor
526 //
527 static void acquireMonitor(_GLFWwindow* window)
528 {
529  if (!_glfw.win32.acquiredMonitorCount)
530  {
531  SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
532 
533  // HACK: When mouse trails are enabled the cursor becomes invisible when
534  // the OpenGL ICD switches to page flipping
535  if (IsWindowsXPOrGreater())
536  {
537  SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
538  SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);
539  }
540  }
541 
542  if (!window->monitor->window)
543  _glfw.win32.acquiredMonitorCount++;
544 
545  _glfwSetVideoModeWin32(window->monitor, &window->videoMode);
546  _glfwInputMonitorWindow(window->monitor, window);
547 }
548 
549 // Remove the window and restore the original video mode
550 //
551 static void releaseMonitor(_GLFWwindow* window)
552 {
553  if (window->monitor->window != window)
554  return;
555 
556  _glfw.win32.acquiredMonitorCount--;
557  if (!_glfw.win32.acquiredMonitorCount)
558  {
559  SetThreadExecutionState(ES_CONTINUOUS);
560 
561  // HACK: Restore mouse trail length saved in acquireMonitor
562  if (IsWindowsXPOrGreater())
563  SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
564  }
565 
566  _glfwInputMonitorWindow(window->monitor, NULL);
568 }
569 
570 // Window callback function (handles window messages)
571 //
572 static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
573  WPARAM wParam, LPARAM lParam)
574 {
575  _GLFWwindow* window = GetPropW(hWnd, L"GLFW");
576  if (!window)
577  {
578  // This is the message handling for the hidden helper window
579  // and for a regular window during its initial creation
580 
581  switch (uMsg)
582  {
583  case WM_NCCREATE:
584  {
587 
588  break;
589  }
590 
591  case WM_DISPLAYCHANGE:
593  break;
594 
595  case WM_DEVICECHANGE:
596  {
597  if (wParam == DBT_DEVICEARRIVAL)
598  {
599  DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
600  if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
602  }
603  else if (wParam == DBT_DEVICEREMOVECOMPLETE)
604  {
605  DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
606  if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
608  }
609 
610  break;
611  }
612  }
613 
614  return DefWindowProcW(hWnd, uMsg, wParam, lParam);
615  }
616 
617  switch (uMsg)
618  {
619  case WM_MOUSEACTIVATE:
620  {
621  // HACK: Postpone cursor disabling when the window was activated by
622  // clicking a caption button
623  if (HIWORD(lParam) == WM_LBUTTONDOWN)
624  {
625  if (LOWORD(lParam) == HTCLOSE ||
626  LOWORD(lParam) == HTMINBUTTON ||
627  LOWORD(lParam) == HTMAXBUTTON)
628  {
629  window->win32.frameAction = GLFW_TRUE;
630  }
631  }
632 
633  break;
634  }
635 
636  case WM_CAPTURECHANGED:
637  {
638  // HACK: Disable the cursor once the caption button action has been
639  // completed or cancelled
640  if (lParam == 0 && window->win32.frameAction)
641  {
642  if (window->cursorMode == GLFW_CURSOR_DISABLED)
643  disableCursor(window);
644 
645  window->win32.frameAction = GLFW_FALSE;
646  }
647 
648  break;
649  }
650 
651  case WM_SETFOCUS:
652  {
654 
655  // HACK: Do not disable cursor while the user is interacting with
656  // a caption button
657  if (window->win32.frameAction)
658  break;
659 
660  if (window->cursorMode == GLFW_CURSOR_DISABLED)
661  disableCursor(window);
662 
663  return 0;
664  }
665 
666  case WM_KILLFOCUS:
667  {
668  if (window->cursorMode == GLFW_CURSOR_DISABLED)
669  enableCursor(window);
670 
671  if (window->monitor && window->autoIconify)
673 
675  return 0;
676  }
677 
678  case WM_SYSCOMMAND:
679  {
680  switch (wParam & 0xfff0)
681  {
682  case SC_SCREENSAVE:
683  case SC_MONITORPOWER:
684  {
685  if (window->monitor)
686  {
687  // We are running in full screen mode, so disallow
688  // screen saver and screen blanking
689  return 0;
690  }
691  else
692  break;
693  }
694 
695  // User trying to access application menu using ALT?
696  case SC_KEYMENU:
697  return 0;
698  }
699  break;
700  }
701 
702  case WM_CLOSE:
703  {
705  return 0;
706  }
707 
708  case WM_INPUTLANGCHANGE:
709  {
711  break;
712  }
713 
714  case WM_CHAR:
715  case WM_SYSCHAR:
716  case WM_UNICHAR:
717  {
718  const GLFWbool plain = (uMsg != WM_SYSCHAR);
719 
720  if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR)
721  {
722  // WM_UNICHAR is not sent by Windows, but is sent by some
723  // third-party input method engine
724  // Returning TRUE here announces support for this message
725  return TRUE;
726  }
727 
728  _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), plain);
729  return 0;
730  }
731 
732  case WM_KEYDOWN:
733  case WM_SYSKEYDOWN:
734  case WM_KEYUP:
735  case WM_SYSKEYUP:
736  {
737  const int key = translateKey(wParam, lParam);
738  const int scancode = (lParam >> 16) & 0x1ff;
739  const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS;
740  const int mods = getKeyMods();
741 
742  if (key == _GLFW_KEY_INVALID)
743  break;
744 
745  if (action == GLFW_RELEASE && wParam == VK_SHIFT)
746  {
747  // HACK: Release both Shift keys on Shift up event, as when both
748  // are pressed the first release does not emit any event
749  // NOTE: The other half of this is in _glfwPlatformPollEvents
750  _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods);
751  _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods);
752  }
753  else if (wParam == VK_SNAPSHOT)
754  {
755  // HACK: Key down is not reported for the Print Screen key
756  _glfwInputKey(window, key, scancode, GLFW_PRESS, mods);
757  _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods);
758  }
759  else
760  _glfwInputKey(window, key, scancode, action, mods);
761 
762  break;
763  }
764 
765  case WM_LBUTTONDOWN:
766  case WM_RBUTTONDOWN:
767  case WM_MBUTTONDOWN:
768  case WM_XBUTTONDOWN:
769  case WM_LBUTTONUP:
770  case WM_RBUTTONUP:
771  case WM_MBUTTONUP:
772  case WM_XBUTTONUP:
773  {
774  int i, button, action;
775 
776  if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
777  button = GLFW_MOUSE_BUTTON_LEFT;
778  else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP)
779  button = GLFW_MOUSE_BUTTON_RIGHT;
780  else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP)
781  button = GLFW_MOUSE_BUTTON_MIDDLE;
782  else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)
783  button = GLFW_MOUSE_BUTTON_4;
784  else
785  button = GLFW_MOUSE_BUTTON_5;
786 
787  if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN ||
788  uMsg == WM_MBUTTONDOWN || uMsg == WM_XBUTTONDOWN)
789  {
790  action = GLFW_PRESS;
791  }
792  else
793  action = GLFW_RELEASE;
794 
795  for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
796  {
797  if (window->mouseButtons[i] == GLFW_PRESS)
798  break;
799  }
800 
801  if (i > GLFW_MOUSE_BUTTON_LAST)
802  SetCapture(hWnd);
803 
804  _glfwInputMouseClick(window, button, action, getKeyMods());
805 
806  for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
807  {
808  if (window->mouseButtons[i] == GLFW_PRESS)
809  break;
810  }
811 
812  if (i > GLFW_MOUSE_BUTTON_LAST)
813  ReleaseCapture();
814 
815  if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP)
816  return TRUE;
817 
818  return 0;
819  }
820 
821  case WM_MOUSEMOVE:
822  {
823  const int x = GET_X_LPARAM(lParam);
824  const int y = GET_Y_LPARAM(lParam);
825 
826  // Disabled cursor motion input is provided by WM_INPUT
827  if (window->cursorMode == GLFW_CURSOR_DISABLED)
828  break;
829 
830  _glfwInputCursorPos(window, x, y);
831 
832  window->win32.lastCursorPosX = x;
833  window->win32.lastCursorPosY = y;
834 
835  if (!window->win32.cursorTracked)
836  {
837  TRACKMOUSEEVENT tme;
838  ZeroMemory(&tme, sizeof(tme));
839  tme.cbSize = sizeof(tme);
840  tme.dwFlags = TME_LEAVE;
841  tme.hwndTrack = window->win32.handle;
842  TrackMouseEvent(&tme);
843 
844  window->win32.cursorTracked = GLFW_TRUE;
846  }
847 
848  return 0;
849  }
850 
851  case WM_INPUT:
852  {
853  UINT size;
854  HRAWINPUT ri = (HRAWINPUT) lParam;
855  RAWINPUT* data;
856  int dx, dy;
857 
858  // Only process input when disabled cursor mode is applied
859  if (_glfw.win32.disabledCursorWindow != window)
860  break;
861 
862  GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
863  if (size > (UINT) _glfw.win32.rawInputSize)
864  {
865  free(_glfw.win32.rawInput);
866  _glfw.win32.rawInput = calloc(size, 1);
867  _glfw.win32.rawInputSize = size;
868  }
869 
870  size = _glfw.win32.rawInputSize;
871  if (GetRawInputData(ri, RID_INPUT,
872  _glfw.win32.rawInput, &size,
873  sizeof(RAWINPUTHEADER)) == (UINT) -1)
874  {
876  "Win32: Failed to retrieve raw input data");
877  break;
878  }
879 
880  data = _glfw.win32.rawInput;
881  if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
882  {
883  dx = data->data.mouse.lLastX - window->win32.lastCursorPosX;
884  dy = data->data.mouse.lLastY - window->win32.lastCursorPosY;
885  }
886  else
887  {
888  dx = data->data.mouse.lLastX;
889  dy = data->data.mouse.lLastY;
890  }
891 
892  _glfwInputCursorPos(window,
893  window->virtualCursorPosX + dx,
894  window->virtualCursorPosY + dy);
895 
896  window->win32.lastCursorPosX += dx;
897  window->win32.lastCursorPosY += dy;
898  break;
899  }
900 
901  case WM_MOUSELEAVE:
902  {
903  window->win32.cursorTracked = GLFW_FALSE;
905  return 0;
906  }
907 
908  case WM_MOUSEWHEEL:
909  {
910  _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA);
911  return 0;
912  }
913 
914  case WM_MOUSEHWHEEL:
915  {
916  // This message is only sent on Windows Vista and later
917  // NOTE: The X-axis is inverted for consistency with macOS and X11
918  _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
919  return 0;
920  }
921 
922  case WM_ENTERSIZEMOVE:
923  case WM_ENTERMENULOOP:
924  {
925  // HACK: Enable the cursor while the user is moving or
926  // resizing the window or using the window menu
927  if (window->cursorMode == GLFW_CURSOR_DISABLED)
928  enableCursor(window);
929 
930  break;
931  }
932 
933  case WM_EXITSIZEMOVE:
934  case WM_EXITMENULOOP:
935  {
936  // HACK: Disable the cursor once the user is done moving or
937  // resizing the window or using the menu
938  if (window->cursorMode == GLFW_CURSOR_DISABLED)
939  disableCursor(window);
940 
941  break;
942  }
943 
944  case WM_SIZE:
945  {
946  const GLFWbool iconified = wParam == SIZE_MINIMIZED;
947  const GLFWbool maximized = wParam == SIZE_MAXIMIZED ||
948  (window->win32.maximized &&
949  wParam != SIZE_RESTORED);
950 
951  if (_glfw.win32.disabledCursorWindow == window)
952  updateClipRect(window);
953 
954  if (window->win32.iconified != iconified)
955  _glfwInputWindowIconify(window, iconified);
956 
957  if (window->win32.maximized != maximized)
958  _glfwInputWindowMaximize(window, maximized);
959 
960  _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));
961  _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));
962 
963  if (window->monitor && window->win32.iconified != iconified)
964  {
965  if (iconified)
966  releaseMonitor(window);
967  else
968  {
969  acquireMonitor(window);
970  fitToMonitor(window);
971  }
972  }
973 
974  window->win32.iconified = iconified;
975  window->win32.maximized = maximized;
976  return 0;
977  }
978 
979  case WM_MOVE:
980  {
981  if (_glfw.win32.disabledCursorWindow == window)
982  updateClipRect(window);
983 
984  // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as
985  // those macros do not handle negative window positions correctly
986  _glfwInputWindowPos(window,
987  GET_X_LPARAM(lParam),
988  GET_Y_LPARAM(lParam));
989  return 0;
990  }
991 
992  case WM_SIZING:
993  {
994  if (window->numer == GLFW_DONT_CARE ||
995  window->denom == GLFW_DONT_CARE)
996  {
997  break;
998  }
999 
1000  applyAspectRatio(window, (int) wParam, (RECT*) lParam);
1001  return TRUE;
1002  }
1003 
1004  case WM_GETMINMAXINFO:
1005  {
1006  int xoff, yoff;
1007  UINT dpi = USER_DEFAULT_SCREEN_DPI;
1008  MINMAXINFO* mmi = (MINMAXINFO*) lParam;
1009 
1010  if (window->monitor)
1011  break;
1012 
1014  dpi = GetDpiForWindow(window->win32.handle);
1015 
1017  0, 0, &xoff, &yoff, dpi);
1018 
1019  if (window->minwidth != GLFW_DONT_CARE &&
1020  window->minheight != GLFW_DONT_CARE)
1021  {
1022  mmi->ptMinTrackSize.x = window->minwidth + xoff;
1023  mmi->ptMinTrackSize.y = window->minheight + yoff;
1024  }
1025 
1026  if (window->maxwidth != GLFW_DONT_CARE &&
1027  window->maxheight != GLFW_DONT_CARE)
1028  {
1029  mmi->ptMaxTrackSize.x = window->maxwidth + xoff;
1030  mmi->ptMaxTrackSize.y = window->maxheight + yoff;
1031  }
1032 
1033  if (!window->decorated)
1034  {
1035  MONITORINFO mi;
1036  const HMONITOR mh = MonitorFromWindow(window->win32.handle,
1037  MONITOR_DEFAULTTONEAREST);
1038 
1039  ZeroMemory(&mi, sizeof(mi));
1040  mi.cbSize = sizeof(mi);
1041  GetMonitorInfo(mh, &mi);
1042 
1043  mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;
1044  mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;
1045  mmi->ptMaxSize.x = mi.rcWork.right - mi.rcWork.left;
1046  mmi->ptMaxSize.y = mi.rcWork.bottom - mi.rcWork.top;
1047  }
1048 
1049  return 0;
1050  }
1051 
1052  case WM_PAINT:
1053  {
1054  _glfwInputWindowDamage(window);
1055  break;
1056  }
1057 
1058  case WM_ERASEBKGND:
1059  {
1060  return TRUE;
1061  }
1062 
1063  case WM_NCACTIVATE:
1064  case WM_NCPAINT:
1065  {
1066  // Prevent title bar from being drawn after restoring a minimized
1067  // undecorated window
1068  if (!window->decorated)
1069  return TRUE;
1070 
1071  break;
1072  }
1073 
1075  {
1076  if (window->win32.transparent)
1078  return 0;
1079  }
1080 
1081  case WM_GETDPISCALEDSIZE:
1082  {
1083  if (window->win32.scaleToMonitor)
1084  break;
1085 
1086  // Adjust the window size to keep the client area size constant
1088  {
1089  RECT source = {0}, target = {0};
1090  SIZE* size = (SIZE*) lParam;
1091 
1092  AdjustWindowRectExForDpi(&source, getWindowStyle(window),
1093  FALSE, getWindowExStyle(window),
1094  GetDpiForWindow(window->win32.handle));
1095  AdjustWindowRectExForDpi(&target, getWindowStyle(window),
1096  FALSE, getWindowExStyle(window),
1097  LOWORD(wParam));
1098 
1099  size->cx += (target.right - target.left) -
1100  (source.right - source.left);
1101  size->cy += (target.bottom - target.top) -
1102  (source.bottom - source.top);
1103  return TRUE;
1104  }
1105 
1106  break;
1107  }
1108 
1109  case WM_DPICHANGED:
1110  {
1111  const float xscale = HIWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
1112  const float yscale = LOWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
1113 
1114  // Only apply the suggested size if the OS is new enough to have
1115  // sent a WM_GETDPISCALEDSIZE before this
1117  {
1118  RECT* suggested = (RECT*) lParam;
1119  SetWindowPos(window->win32.handle, HWND_TOP,
1120  suggested->left,
1121  suggested->top,
1122  suggested->right - suggested->left,
1123  suggested->bottom - suggested->top,
1124  SWP_NOACTIVATE | SWP_NOZORDER);
1125  }
1126 
1127  _glfwInputWindowContentScale(window, xscale, yscale);
1128  break;
1129  }
1130 
1131  case WM_SETCURSOR:
1132  {
1133  if (LOWORD(lParam) == HTCLIENT)
1134  {
1135  updateCursorImage(window);
1136  return TRUE;
1137  }
1138 
1139  break;
1140  }
1141 
1142  case WM_DROPFILES:
1143  {
1144  HDROP drop = (HDROP) wParam;
1145  POINT pt;
1146  int i;
1147 
1148  const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
1149  char** paths = calloc(count, sizeof(char*));
1150 
1151  // Move the mouse to the position of the drop
1152  DragQueryPoint(drop, &pt);
1153  _glfwInputCursorPos(window, pt.x, pt.y);
1154 
1155  for (i = 0; i < count; i++)
1156  {
1157  const UINT length = DragQueryFileW(drop, i, NULL, 0);
1158  WCHAR* buffer = calloc(length + 1, sizeof(WCHAR));
1159 
1160  DragQueryFileW(drop, i, buffer, length + 1);
1161  paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer);
1162 
1163  free(buffer);
1164  }
1165 
1166  _glfwInputDrop(window, count, (const char**) paths);
1167 
1168  for (i = 0; i < count; i++)
1169  free(paths[i]);
1170  free(paths);
1171 
1172  DragFinish(drop);
1173  return 0;
1174  }
1175  }
1176 
1177  return DefWindowProcW(hWnd, uMsg, wParam, lParam);
1178 }
1179 
1180 // Creates the GLFW window
1181 //
1182 static int createNativeWindow(_GLFWwindow* window,
1183  const _GLFWwndconfig* wndconfig,
1184  const _GLFWfbconfig* fbconfig)
1185 {
1186  int xpos, ypos, fullWidth, fullHeight;
1187  WCHAR* wideTitle;
1188  DWORD style = getWindowStyle(window);
1189  DWORD exStyle = getWindowExStyle(window);
1190 
1191  if (window->monitor)
1192  {
1193  GLFWvidmode mode;
1194 
1195  // NOTE: This window placement is temporary and approximate, as the
1196  // correct position and size cannot be known until the monitor
1197  // video mode has been picked in _glfwSetVideoModeWin32
1198  _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
1199  _glfwPlatformGetVideoMode(window->monitor, &mode);
1200  fullWidth = mode.width;
1201  fullHeight = mode.height;
1202  }
1203  else
1204  {
1205  xpos = CW_USEDEFAULT;
1206  ypos = CW_USEDEFAULT;
1207 
1208  if (wndconfig->maximized)
1209  style |= WS_MAXIMIZE;
1210 
1211  getFullWindowSize(style, exStyle,
1212  wndconfig->width, wndconfig->height,
1213  &fullWidth, &fullHeight,
1215  }
1216 
1217  wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
1218  if (!wideTitle)
1219  return GLFW_FALSE;
1220 
1221  window->win32.handle = CreateWindowExW(exStyle,
1223  wideTitle,
1224  style,
1225  xpos, ypos,
1226  fullWidth, fullHeight,
1227  NULL, // No parent window
1228  NULL, // No window menu
1229  GetModuleHandleW(NULL),
1230  NULL);
1231 
1232  free(wideTitle);
1233 
1234  if (!window->win32.handle)
1235  {
1237  "Win32: Failed to create window");
1238  return GLFW_FALSE;
1239  }
1240 
1241  SetPropW(window->win32.handle, L"GLFW", window);
1242 
1243  if (IsWindows7OrGreater())
1244  {
1245  ChangeWindowMessageFilterEx(window->win32.handle,
1246  WM_DROPFILES, MSGFLT_ALLOW, NULL);
1247  ChangeWindowMessageFilterEx(window->win32.handle,
1248  WM_COPYDATA, MSGFLT_ALLOW, NULL);
1249  ChangeWindowMessageFilterEx(window->win32.handle,
1251  }
1252 
1253  window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
1254 
1255  // Adjust window size to account for DPI scaling of the window frame and
1256  // optionally DPI scaling of the client area
1257  // This cannot be done until we know what monitor it was placed on
1258  if (!window->monitor)
1259  {
1260  RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
1261 
1262  if (wndconfig->scaleToMonitor)
1263  {
1264  float xscale, yscale;
1265  _glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
1266  rect.right = (int) (rect.right * xscale);
1267  rect.bottom = (int) (rect.bottom * yscale);
1268  }
1269 
1270  ClientToScreen(window->win32.handle, (POINT*) &rect.left);
1271  ClientToScreen(window->win32.handle, (POINT*) &rect.right);
1272 
1274  {
1275  AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
1276  GetDpiForWindow(window->win32.handle));
1277  }
1278  else
1279  AdjustWindowRectEx(&rect, style, FALSE, exStyle);
1280 
1281  SetWindowPos(window->win32.handle, NULL,
1282  rect.left, rect.top,
1283  rect.right - rect.left, rect.bottom - rect.top,
1284  SWP_NOACTIVATE | SWP_NOZORDER);
1285  }
1286 
1287  DragAcceptFiles(window->win32.handle, TRUE);
1288 
1289  if (fbconfig->transparent)
1290  {
1292  window->win32.transparent = GLFW_TRUE;
1293  }
1294 
1295  return GLFW_TRUE;
1296 }
1297 
1298 
1302 
1303 // Registers the GLFW window class
1304 //
1306 {
1307  WNDCLASSEXW wc;
1308 
1309  ZeroMemory(&wc, sizeof(wc));
1310  wc.cbSize = sizeof(wc);
1311  wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
1312  wc.lpfnWndProc = (WNDPROC) windowProc;
1313  wc.hInstance = GetModuleHandleW(NULL);
1314  wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
1315  wc.lpszClassName = _GLFW_WNDCLASSNAME;
1316 
1317  // Load user-provided icon if available
1318  wc.hIcon = LoadImageW(GetModuleHandleW(NULL),
1319  L"GLFW_ICON", IMAGE_ICON,
1320  0, 0, LR_DEFAULTSIZE | LR_SHARED);
1321  if (!wc.hIcon)
1322  {
1323  // No user-provided icon found, load default icon
1324  wc.hIcon = LoadImageW(NULL,
1325  IDI_APPLICATION, IMAGE_ICON,
1326  0, 0, LR_DEFAULTSIZE | LR_SHARED);
1327  }
1328 
1329  if (!RegisterClassExW(&wc))
1330  {
1332  "Win32: Failed to register window class");
1333  return GLFW_FALSE;
1334  }
1335 
1336  return GLFW_TRUE;
1337 }
1338 
1339 // Unregisters the GLFW window class
1340 //
1342 {
1343  UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));
1344 }
1345 
1346 
1350 
1352  const _GLFWwndconfig* wndconfig,
1353  const _GLFWctxconfig* ctxconfig,
1354  const _GLFWfbconfig* fbconfig)
1355 {
1356  if (!createNativeWindow(window, wndconfig, fbconfig))
1357  return GLFW_FALSE;
1358 
1359  if (ctxconfig->client != GLFW_NO_API)
1360  {
1361  if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
1362  {
1363  if (!_glfwInitWGL())
1364  return GLFW_FALSE;
1365  if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
1366  return GLFW_FALSE;
1367  }
1368  else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
1369  {
1370  if (!_glfwInitEGL())
1371  return GLFW_FALSE;
1372  if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
1373  return GLFW_FALSE;
1374  }
1375  else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
1376  {
1377  if (!_glfwInitOSMesa())
1378  return GLFW_FALSE;
1379  if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
1380  return GLFW_FALSE;
1381  }
1382  }
1383 
1384  if (window->monitor)
1385  {
1386  _glfwPlatformShowWindow(window);
1387  _glfwPlatformFocusWindow(window);
1388  acquireMonitor(window);
1389  fitToMonitor(window);
1390  }
1391 
1392  return GLFW_TRUE;
1393 }
1394 
1396 {
1397  if (window->monitor)
1398  releaseMonitor(window);
1399 
1400  if (window->context.destroy)
1401  window->context.destroy(window);
1402 
1403  if (_glfw.win32.disabledCursorWindow == window)
1404  _glfw.win32.disabledCursorWindow = NULL;
1405 
1406  if (window->win32.handle)
1407  {
1408  RemovePropW(window->win32.handle, L"GLFW");
1409  DestroyWindow(window->win32.handle);
1410  window->win32.handle = NULL;
1411  }
1412 
1413  if (window->win32.bigIcon)
1414  DestroyIcon(window->win32.bigIcon);
1415 
1416  if (window->win32.smallIcon)
1417  DestroyIcon(window->win32.smallIcon);
1418 }
1419 
1420 void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
1421 {
1422  WCHAR* wideTitle = _glfwCreateWideStringFromUTF8Win32(title);
1423  if (!wideTitle)
1424  return;
1425 
1426  SetWindowTextW(window->win32.handle, wideTitle);
1427  free(wideTitle);
1428 }
1429 
1431  int count, const GLFWimage* images)
1432 {
1433  HICON bigIcon = NULL, smallIcon = NULL;
1434 
1435  if (count)
1436  {
1437  const GLFWimage* bigImage = chooseImage(count, images,
1438  GetSystemMetrics(SM_CXICON),
1439  GetSystemMetrics(SM_CYICON));
1440  const GLFWimage* smallImage = chooseImage(count, images,
1441  GetSystemMetrics(SM_CXSMICON),
1442  GetSystemMetrics(SM_CYSMICON));
1443 
1444  bigIcon = createIcon(bigImage, 0, 0, GLFW_TRUE);
1445  smallIcon = createIcon(smallImage, 0, 0, GLFW_TRUE);
1446  }
1447  else
1448  {
1449  bigIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICON);
1450  smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM);
1451  }
1452 
1453  SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
1454  SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
1455 
1456  if (window->win32.bigIcon)
1457  DestroyIcon(window->win32.bigIcon);
1458 
1459  if (window->win32.smallIcon)
1460  DestroyIcon(window->win32.smallIcon);
1461 
1462  if (count)
1463  {
1464  window->win32.bigIcon = bigIcon;
1465  window->win32.smallIcon = smallIcon;
1466  }
1467 }
1468 
1469 void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
1470 {
1471  POINT pos = { 0, 0 };
1472  ClientToScreen(window->win32.handle, &pos);
1473 
1474  if (xpos)
1475  *xpos = pos.x;
1476  if (ypos)
1477  *ypos = pos.y;
1478 }
1479 
1480 void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
1481 {
1482  RECT rect = { xpos, ypos, xpos, ypos };
1483 
1485  {
1487  FALSE, getWindowExStyle(window),
1488  GetDpiForWindow(window->win32.handle));
1489  }
1490  else
1491  {
1492  AdjustWindowRectEx(&rect, getWindowStyle(window),
1493  FALSE, getWindowExStyle(window));
1494  }
1495 
1496  SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0,
1497  SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
1498 }
1499 
1500 void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
1501 {
1502  RECT area;
1503  GetClientRect(window->win32.handle, &area);
1504 
1505  if (width)
1506  *width = area.right;
1507  if (height)
1508  *height = area.bottom;
1509 }
1510 
1511 void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
1512 {
1513  if (window->monitor)
1514  {
1515  if (window->monitor->window == window)
1516  {
1517  acquireMonitor(window);
1518  fitToMonitor(window);
1519  }
1520  }
1521  else
1522  {
1523  RECT rect = { 0, 0, width, height };
1524 
1526  {
1528  FALSE, getWindowExStyle(window),
1529  GetDpiForWindow(window->win32.handle));
1530  }
1531  else
1532  {
1533  AdjustWindowRectEx(&rect, getWindowStyle(window),
1534  FALSE, getWindowExStyle(window));
1535  }
1536 
1537  SetWindowPos(window->win32.handle, HWND_TOP,
1538  0, 0, rect.right - rect.left, rect.bottom - rect.top,
1539  SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);
1540  }
1541 }
1542 
1544  int minwidth, int minheight,
1545  int maxwidth, int maxheight)
1546 {
1547  RECT area;
1548 
1549  if ((minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) &&
1550  (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE))
1551  {
1552  return;
1553  }
1554 
1555  GetWindowRect(window->win32.handle, &area);
1556  MoveWindow(window->win32.handle,
1557  area.left, area.top,
1558  area.right - area.left,
1559  area.bottom - area.top, TRUE);
1560 }
1561 
1562 void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
1563 {
1564  RECT area;
1565 
1566  if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
1567  return;
1568 
1569  GetWindowRect(window->win32.handle, &area);
1570  applyAspectRatio(window, WMSZ_BOTTOMRIGHT, &area);
1571  MoveWindow(window->win32.handle,
1572  area.left, area.top,
1573  area.right - area.left,
1574  area.bottom - area.top, TRUE);
1575 }
1576 
1577 void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
1578 {
1579  _glfwPlatformGetWindowSize(window, width, height);
1580 }
1581 
1583  int* left, int* top,
1584  int* right, int* bottom)
1585 {
1586  RECT rect;
1587  int width, height;
1588 
1589  _glfwPlatformGetWindowSize(window, &width, &height);
1590  SetRect(&rect, 0, 0, width, height);
1591 
1593  {
1595  FALSE, getWindowExStyle(window),
1596  GetDpiForWindow(window->win32.handle));
1597  }
1598  else
1599  {
1600  AdjustWindowRectEx(&rect, getWindowStyle(window),
1601  FALSE, getWindowExStyle(window));
1602  }
1603 
1604  if (left)
1605  *left = -rect.left;
1606  if (top)
1607  *top = -rect.top;
1608  if (right)
1609  *right = rect.right - width;
1610  if (bottom)
1611  *bottom = rect.bottom - height;
1612 }
1613 
1615  float* xscale, float* yscale)
1616 {
1617  const HANDLE handle = MonitorFromWindow(window->win32.handle,
1618  MONITOR_DEFAULTTONEAREST);
1619  _glfwGetMonitorContentScaleWin32(handle, xscale, yscale);
1620 }
1621 
1623 {
1624  ShowWindow(window->win32.handle, SW_MINIMIZE);
1625 }
1626 
1628 {
1629  ShowWindow(window->win32.handle, SW_RESTORE);
1630 }
1631 
1633 {
1634  ShowWindow(window->win32.handle, SW_MAXIMIZE);
1635 }
1636 
1638 {
1639  ShowWindow(window->win32.handle, SW_SHOWNA);
1640 }
1641 
1643 {
1644  ShowWindow(window->win32.handle, SW_HIDE);
1645 }
1646 
1648 {
1649  FlashWindow(window->win32.handle, TRUE);
1650 }
1651 
1653 {
1654  BringWindowToTop(window->win32.handle);
1655  SetForegroundWindow(window->win32.handle);
1656  SetFocus(window->win32.handle);
1657 }
1658 
1660  _GLFWmonitor* monitor,
1661  int xpos, int ypos,
1662  int width, int height,
1663  int refreshRate)
1664 {
1665  if (window->monitor == monitor)
1666  {
1667  if (monitor)
1668  {
1669  if (monitor->window == window)
1670  {
1671  acquireMonitor(window);
1672  fitToMonitor(window);
1673  }
1674  }
1675  else
1676  {
1677  RECT rect = { xpos, ypos, xpos + width, ypos + height };
1678 
1680  {
1682  FALSE, getWindowExStyle(window),
1683  GetDpiForWindow(window->win32.handle));
1684  }
1685  else
1686  {
1687  AdjustWindowRectEx(&rect, getWindowStyle(window),
1688  FALSE, getWindowExStyle(window));
1689  }
1690 
1691  SetWindowPos(window->win32.handle, HWND_TOP,
1692  rect.left, rect.top,
1693  rect.right - rect.left, rect.bottom - rect.top,
1694  SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOZORDER);
1695  }
1696 
1697  return;
1698  }
1699 
1700  if (window->monitor)
1701  releaseMonitor(window);
1702 
1703  _glfwInputWindowMonitor(window, monitor);
1704 
1705  if (monitor)
1706  {
1707  MONITORINFO mi = { sizeof(mi) };
1708  UINT flags = SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS;
1709 
1710  if (window->decorated)
1711  {
1712  DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
1713  style &= ~WS_OVERLAPPEDWINDOW;
1714  style |= getWindowStyle(window);
1715  SetWindowLongW(window->win32.handle, GWL_STYLE, style);
1716  flags |= SWP_FRAMECHANGED;
1717  }
1718 
1719  acquireMonitor(window);
1720 
1721  GetMonitorInfo(window->monitor->win32.handle, &mi);
1722  SetWindowPos(window->win32.handle, HWND_TOPMOST,
1723  mi.rcMonitor.left,
1724  mi.rcMonitor.top,
1725  mi.rcMonitor.right - mi.rcMonitor.left,
1726  mi.rcMonitor.bottom - mi.rcMonitor.top,
1727  flags);
1728  }
1729  else
1730  {
1731  HWND after;
1732  RECT rect = { xpos, ypos, xpos + width, ypos + height };
1733  DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
1734  UINT flags = SWP_NOACTIVATE | SWP_NOCOPYBITS;
1735 
1736  if (window->decorated)
1737  {
1738  style &= ~WS_POPUP;
1739  style |= getWindowStyle(window);
1740  SetWindowLongW(window->win32.handle, GWL_STYLE, style);
1741 
1742  flags |= SWP_FRAMECHANGED;
1743  }
1744 
1745  if (window->floating)
1746  after = HWND_TOPMOST;
1747  else
1748  after = HWND_NOTOPMOST;
1749 
1751  {
1753  FALSE, getWindowExStyle(window),
1754  GetDpiForWindow(window->win32.handle));
1755  }
1756  else
1757  {
1758  AdjustWindowRectEx(&rect, getWindowStyle(window),
1759  FALSE, getWindowExStyle(window));
1760  }
1761 
1762  SetWindowPos(window->win32.handle, after,
1763  rect.left, rect.top,
1764  rect.right - rect.left, rect.bottom - rect.top,
1765  flags);
1766  }
1767 }
1768 
1770 {
1771  return window->win32.handle == GetActiveWindow();
1772 }
1773 
1775 {
1776  return IsIconic(window->win32.handle);
1777 }
1778 
1780 {
1781  return IsWindowVisible(window->win32.handle);
1782 }
1783 
1785 {
1786  return IsZoomed(window->win32.handle);
1787 }
1788 
1790 {
1791  return cursorInClientArea(window);
1792 }
1793 
1795 {
1796  BOOL enabled;
1797 
1798  if (!window->win32.transparent)
1799  return GLFW_FALSE;
1800 
1801  if (!IsWindowsVistaOrGreater())
1802  return GLFW_FALSE;
1803 
1804  return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
1805 }
1806 
1808 {
1809  updateWindowStyles(window);
1810 }
1811 
1813 {
1814  updateWindowStyles(window);
1815 }
1816 
1818 {
1819  const HWND after = enabled ? HWND_TOPMOST : HWND_NOTOPMOST;
1820  SetWindowPos(window->win32.handle, after, 0, 0, 0, 0,
1821  SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1822 }
1823 
1825 {
1826  BYTE alpha;
1827  DWORD flags;
1828 
1829  if ((GetWindowLongW(window->win32.handle, GWL_EXSTYLE) & WS_EX_LAYERED) &&
1830  GetLayeredWindowAttributes(window->win32.handle, NULL, &alpha, &flags))
1831  {
1832  if (flags & LWA_ALPHA)
1833  return alpha / 255.f;
1834  }
1835 
1836  return 1.f;
1837 }
1838 
1839 void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
1840 {
1841  if (opacity < 1.f)
1842  {
1843  const BYTE alpha = (BYTE) (255 * opacity);
1844  DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
1845  style |= WS_EX_LAYERED;
1846  SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
1847  SetLayeredWindowAttributes(window->win32.handle, 0, alpha, LWA_ALPHA);
1848  }
1849  else
1850  {
1851  DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
1852  style &= ~WS_EX_LAYERED;
1853  SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
1854  }
1855 }
1856 
1858 {
1859  MSG msg;
1860  HWND handle;
1861  _GLFWwindow* window;
1862 
1863  while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
1864  {
1865  if (msg.message == WM_QUIT)
1866  {
1867  // NOTE: While GLFW does not itself post WM_QUIT, other processes
1868  // may post it to this one, for example Task Manager
1869  // HACK: Treat WM_QUIT as a close on all windows
1870 
1871  window = _glfw.windowListHead;
1872  while (window)
1873  {
1875  window = window->next;
1876  }
1877  }
1878  else
1879  {
1880  TranslateMessage(&msg);
1881  DispatchMessageW(&msg);
1882  }
1883  }
1884 
1885  handle = GetActiveWindow();
1886  if (handle)
1887  {
1888  // NOTE: Shift keys on Windows tend to "stick" when both are pressed as
1889  // no key up message is generated by the first key release
1890  // The other half of this is in the handling of WM_KEYUP
1891  // HACK: Query actual key state and synthesize release events as needed
1892  window = GetPropW(handle, L"GLFW");
1893  if (window)
1894  {
1895  const GLFWbool lshift = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;
1896  const GLFWbool rshift = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;
1897 
1898  if (!lshift && window->keys[GLFW_KEY_LEFT_SHIFT] == GLFW_PRESS)
1899  {
1900  const int mods = getAsyncKeyMods();
1901  const int scancode = _glfw.win32.scancodes[GLFW_KEY_LEFT_SHIFT];
1902  _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, GLFW_RELEASE, mods);
1903  }
1904  else if (!rshift && window->keys[GLFW_KEY_RIGHT_SHIFT] == GLFW_PRESS)
1905  {
1906  const int mods = getAsyncKeyMods();
1907  const int scancode = _glfw.win32.scancodes[GLFW_KEY_RIGHT_SHIFT];
1908  _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, GLFW_RELEASE, mods);
1909  }
1910  }
1911  }
1912 
1913  window = _glfw.win32.disabledCursorWindow;
1914  if (window)
1915  {
1916  int width, height;
1917  _glfwPlatformGetWindowSize(window, &width, &height);
1918 
1919  // NOTE: Re-center the cursor only if it has moved since the last call,
1920  // to avoid breaking glfwWaitEvents with WM_MOUSEMOVE
1921  if (window->win32.lastCursorPosX != width / 2 ||
1922  window->win32.lastCursorPosY != height / 2)
1923  {
1924  _glfwPlatformSetCursorPos(window, width / 2, height / 2);
1925  }
1926  }
1927 }
1928 
1930 {
1931  WaitMessage();
1932 
1934 }
1935 
1937 {
1938  MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLEVENTS);
1939 
1941 }
1942 
1944 {
1945  PostMessage(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
1946 }
1947 
1948 void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
1949 {
1950  POINT pos;
1951 
1952  if (GetCursorPos(&pos))
1953  {
1954  ScreenToClient(window->win32.handle, &pos);
1955 
1956  if (xpos)
1957  *xpos = pos.x;
1958  if (ypos)
1959  *ypos = pos.y;
1960  }
1961 }
1962 
1963 void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
1964 {
1965  POINT pos = { (int) xpos, (int) ypos };
1966 
1967  // Store the new position so it can be recognized later
1968  window->win32.lastCursorPosX = pos.x;
1969  window->win32.lastCursorPosY = pos.y;
1970 
1971  ClientToScreen(window->win32.handle, &pos);
1972  SetCursorPos(pos.x, pos.y);
1973 }
1974 
1976 {
1977  if (mode == GLFW_CURSOR_DISABLED)
1978  {
1979  if (_glfwPlatformWindowFocused(window))
1980  disableCursor(window);
1981  }
1982  else if (_glfw.win32.disabledCursorWindow == window)
1983  enableCursor(window);
1984  else if (cursorInClientArea(window))
1985  updateCursorImage(window);
1986 }
1987 
1988 const char* _glfwPlatformGetScancodeName(int scancode)
1989 {
1990  return _glfw.win32.keynames[_glfw.win32.keycodes[scancode]];
1991 }
1992 
1994 {
1995  return _glfw.win32.scancodes[key];
1996 }
1997 
1999  const GLFWimage* image,
2000  int xhot, int yhot)
2001 {
2002  cursor->win32.handle = (HCURSOR) createIcon(image, xhot, yhot, GLFW_FALSE);
2003  if (!cursor->win32.handle)
2004  return GLFW_FALSE;
2005 
2006  return GLFW_TRUE;
2007 }
2008 
2010 {
2011  LPCWSTR name = NULL;
2012 
2013  if (shape == GLFW_ARROW_CURSOR)
2014  name = IDC_ARROW;
2015  else if (shape == GLFW_IBEAM_CURSOR)
2016  name = IDC_IBEAM;
2017  else if (shape == GLFW_CROSSHAIR_CURSOR)
2018  name = IDC_CROSS;
2019  else if (shape == GLFW_HAND_CURSOR)
2020  name = IDC_HAND;
2021  else if (shape == GLFW_HRESIZE_CURSOR)
2022  name = IDC_SIZEWE;
2023  else if (shape == GLFW_VRESIZE_CURSOR)
2024  name = IDC_SIZENS;
2025  else
2026  return GLFW_FALSE;
2027 
2028  cursor->win32.handle = CopyCursor(LoadCursorW(NULL, name));
2029  if (!cursor->win32.handle)
2030  {
2032  "Win32: Failed to create standard cursor");
2033  return GLFW_FALSE;
2034  }
2035 
2036  return GLFW_TRUE;
2037 }
2038 
2040 {
2041  if (cursor->win32.handle)
2042  DestroyIcon((HICON) cursor->win32.handle);
2043 }
2044 
2046 {
2047  if (cursorInClientArea(window))
2048  updateCursorImage(window);
2049 }
2050 
2051 void _glfwPlatformSetClipboardString(const char* string)
2052 {
2053  int characterCount;
2054  HANDLE object;
2055  WCHAR* buffer;
2056 
2057  characterCount = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
2058  if (!characterCount)
2059  return;
2060 
2061  object = GlobalAlloc(GMEM_MOVEABLE, characterCount * sizeof(WCHAR));
2062  if (!object)
2063  {
2065  "Win32: Failed to allocate global handle for clipboard");
2066  return;
2067  }
2068 
2069  buffer = GlobalLock(object);
2070  if (!buffer)
2071  {
2073  "Win32: Failed to lock global handle");
2074  GlobalFree(object);
2075  return;
2076  }
2077 
2078  MultiByteToWideChar(CP_UTF8, 0, string, -1, buffer, characterCount);
2079  GlobalUnlock(object);
2080 
2081  if (!OpenClipboard(_glfw.win32.helperWindowHandle))
2082  {
2084  "Win32: Failed to open clipboard");
2085  GlobalFree(object);
2086  return;
2087  }
2088 
2089  EmptyClipboard();
2090  SetClipboardData(CF_UNICODETEXT, object);
2091  CloseClipboard();
2092 }
2093 
2095 {
2096  HANDLE object;
2097  WCHAR* buffer;
2098 
2099  if (!OpenClipboard(_glfw.win32.helperWindowHandle))
2100  {
2102  "Win32: Failed to open clipboard");
2103  return NULL;
2104  }
2105 
2106  object = GetClipboardData(CF_UNICODETEXT);
2107  if (!object)
2108  {
2110  "Win32: Failed to convert clipboard to string");
2111  CloseClipboard();
2112  return NULL;
2113  }
2114 
2115  buffer = GlobalLock(object);
2116  if (!buffer)
2117  {
2119  "Win32: Failed to lock global handle");
2120  CloseClipboard();
2121  return NULL;
2122  }
2123 
2124  free(_glfw.win32.clipboardString);
2125  _glfw.win32.clipboardString = _glfwCreateUTF8FromWideStringWin32(buffer);
2126 
2127  GlobalUnlock(object);
2128  CloseClipboard();
2129 
2130  return _glfw.win32.clipboardString;
2131 }
2132 
2134 {
2135  if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_win32_surface)
2136  return;
2137 
2138  extensions[0] = "VK_KHR_surface";
2139  extensions[1] = "VK_KHR_win32_surface";
2140 }
2141 
2143  VkPhysicalDevice device,
2144  uint32_t queuefamily)
2145 {
2147  vkGetPhysicalDeviceWin32PresentationSupportKHR =
2149  vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
2150  if (!vkGetPhysicalDeviceWin32PresentationSupportKHR)
2151  {
2153  "Win32: Vulkan instance missing VK_KHR_win32_surface extension");
2154  return GLFW_FALSE;
2155  }
2156 
2157  return vkGetPhysicalDeviceWin32PresentationSupportKHR(device, queuefamily);
2158 }
2159 
2161  _GLFWwindow* window,
2162  const VkAllocationCallbacks* allocator,
2163  VkSurfaceKHR* surface)
2164 {
2165  VkResult err;
2167  PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;
2168 
2169  vkCreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)
2170  vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR");
2171  if (!vkCreateWin32SurfaceKHR)
2172  {
2174  "Win32: Vulkan instance missing VK_KHR_win32_surface extension");
2176  }
2177 
2178  memset(&sci, 0, sizeof(sci));
2180  sci.hinstance = GetModuleHandle(NULL);
2181  sci.hwnd = window->win32.handle;
2182 
2183  err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);
2184  if (err)
2185  {
2187  "Win32: Failed to create Vulkan surface: %s",
2189  }
2190 
2191  return err;
2192 }
2193 
2194 
2198 
2200 {
2201  _GLFWwindow* window = (_GLFWwindow*) handle;
2203  return window->win32.handle;
2204 }
2205 
static DWORD getWindowStyle(const _GLFWwindow *window)
Definition: win32_window.c:41
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float *xscale, float *yscale)
void _glfwPlatformIconifyWindow(_GLFWwindow *window)
float _glfwPlatformGetWindowOpacity(_GLFWwindow *window)
#define GLFW_KEY_RIGHT_CONTROL
Definition: glfw3.h:478
int height
Definition: glfw3.h:1532
void _glfwRestoreVideoModeWin32(_GLFWmonitor *monitor)
WCHAR * _glfwCreateWideStringFromUTF8Win32(const char *source)
Definition: win32_init.c:384
IMGUI_API ImVec2 GetCursorPos()
Definition: imgui.cpp:6194
VkResult(APIENTRY * PFN_vkCreateWin32SurfaceKHR)(VkInstance, const VkWin32SurfaceCreateInfoKHR *, const VkAllocationCallbacks *, VkSurfaceKHR *)
#define UNICODE_NOCHAR
#define GLFW_MOD_CONTROL
If this bit is set one or more Control keys were held down.
Definition: glfw3.h:504
VkBool32(APIENTRY * PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice, uint32_t)
static HICON createIcon(const GLFWimage *image, int xhot, int yhot, GLFWbool icon)
Definition: win32_window.c:101
list extensions
Definition: conf.py:60
void _glfwInputWindowCloseRequest(_GLFWwindow *window)
Definition: window.c:131
GLFWbool scaleToMonitor
Definition: internal.h:269
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow *window, int minwidth, int minheight, int maxwidth, int maxheight)
unsigned char * pixels
Definition: glfw3.h:1598
static int translateKey(WPARAM wParam, LPARAM lParam)
Definition: win32_window.c:466
#define GLFWAPI
Definition: glfw3.h:240
static void enableCursor(_GLFWwindow *window)
Definition: win32_window.c:302
unsigned char BYTE
void _glfwDetectJoystickConnectionWin32(void)
void _glfwUnregisterWindowClassWin32(void)
f
IMGUI_API void SetCursorPos(const ImVec2 &local_pos)
Definition: imgui.cpp:6212
void _glfwInputChar(_GLFWwindow *window, unsigned int codepoint, int mods, GLFWbool plain)
Definition: input.c:290
static void updateClipRect(_GLFWwindow *window)
Definition: win32_window.c:265
#define WM_DPICHANGED
static void updateCursorImage(_GLFWwindow *window)
Definition: win32_window.c:250
static const GLFWimage * chooseImage(int count, const GLFWimage *images, int width, int height)
Definition: win32_window.c:79
void _glfwPlatformGetCursorPos(_GLFWwindow *window, double *xpos, double *ypos)
GLFWbool _glfwInitOSMesa(void)
static void updateWindowStyles(const _GLFWwindow *window)
Definition: win32_window.c:342
int width
Definition: glfw3.h:1529
void _glfwInputWindowIconify(_GLFWwindow *window, GLFWbool iconified)
Definition: window.c:89
const char * _glfwPlatformGetClipboardString(void)
int _glfwPlatformFramebufferTransparent(_GLFWwindow *window)
#define GLFW_MOUSE_BUTTON_RIGHT
Definition: glfw3.h:547
#define vkGetInstanceProcAddr
Definition: internal.h:180
_GLFWdestroycontextfun destroy
Definition: internal.h:354
void _glfwInputFramebufferSize(_GLFWwindow *window, int width, int height)
Definition: window.c:106
void _glfwPlatformDestroyCursor(_GLFWcursor *cursor)
int height
Definition: glfw3.h:1595
char * _glfwCreateUTF8FromWideStringWin32(const WCHAR *source)
Definition: win32_init.c:412
void _glfwInputWindowMaximize(_GLFWwindow *window, GLFWbool maximized)
Definition: window.c:97
int _glfwPlatformCreateStandardCursor(_GLFWcursor *cursor, int shape)
#define GLFW_KEY_LEFT_SHIFT
Definition: glfw3.h:473
#define GLFW_FALSE
Zero.
Definition: glfw3.h:287
const char * _glfwGetVulkanResultString(VkResult result)
Definition: vulkan.c:159
void _glfwPlatformGetVideoMode(_GLFWmonitor *monitor, GLFWvidmode *mode)
Definition: null_monitor.c:57
#define GLFW_MOUSE_BUTTON_LEFT
Definition: glfw3.h:546
#define GLFW_CROSSHAIR_CURSOR
The crosshair shape.
Definition: glfw3.h:1040
GLenum GLuint GLenum GLsizei length
Definition: gl.h:1033
static void centerCursor(_GLFWwindow *window)
Definition: win32_window.c:241
#define GLFW_API_UNAVAILABLE
GLFW could not find support for the requested API on the system.
Definition: glfw3.h:698
#define GLFW_EGL_CONTEXT_API
Definition: glfw3.h:1015
GLFWbool _glfwCreateContextWGL(_GLFWwindow *window, const _GLFWctxconfig *ctxconfig, const _GLFWfbconfig *fbconfig)
Definition: wgl_context.c:478
#define EnableNonClientDpiScaling
#define GLFW_FORMAT_UNAVAILABLE
The requested format is not supported or available.
Definition: glfw3.h:745
#define DWM_BB_ENABLE
void _glfwPlatformGetWindowContentScale(_GLFWwindow *window, float *xscale, float *yscale)
#define GLFW_ARROW_CURSOR
The regular arrow cursor shape.
Definition: glfw3.h:1030
static int getAsyncKeyMods(void)
Definition: win32_window.c:444
void _glfwPlatformSetWindowResizable(_GLFWwindow *window, GLFWbool enabled)
_GLFWcontext context
Definition: internal.h:395
_GLFWwindow * windowListHead
Definition: internal.h:527
int GLFWbool
Definition: internal.h:62
void _glfwPlatformSetWindowIcon(_GLFWwindow *window, int count, const GLFWimage *images)
int _glfwPlatformWindowFocused(_GLFWwindow *window)
#define GLFW_MOUSE_BUTTON_5
Definition: glfw3.h:541
const char * title
Definition: internal.h:259
void _glfwInputWindowDamage(_GLFWwindow *window)
Definition: window.c:123
#define MSGFLT_ALLOW
#define GLFW_DONT_CARE
Definition: glfw3.h:1080
struct GLFWwindow GLFWwindow
Opaque window object.
Definition: glfw3.h:1137
void _glfwInputCursorEnter(_GLFWwindow *window, GLFWbool entered)
Definition: input.c:352
void _glfwInputWindowPos(_GLFWwindow *window, int xpos, int ypos)
Definition: window.c:72
void _glfwPlatformDestroyWindow(_GLFWwindow *window)
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow *window, int numer, int denom)
GLFWvidmode videoMode
Definition: internal.h:378
GLFWbool KHR_surface
Definition: internal.h:554
void _glfwPlatformSetCursorPos(_GLFWwindow *window, double xpos, double ypos)
void _glfwPlatformSetWindowSize(_GLFWwindow *window, int width, int height)
void _glfwInputScroll(_GLFWwindow *window, double xoffset, double yoffset)
Definition: input.c:310
#define GLFW_RELEASE
The key or mouse button was released.
Definition: glfw3.h:297
#define GLFW_CURSOR_DISABLED
Definition: glfw3.h:1008
void _glfwPlatformWaitEventsTimeout(double timeout)
void _glfwPlatformShowWindow(_GLFWwindow *window)
GLFWbool resizable
Definition: internal.h:371
GLFWbool transparent
Definition: internal.h:329
#define IsWindowsXPOrGreater()
void _glfwPlatformGetRequiredInstanceExtensions(char **extensions)
int maxwidth
Definition: internal.h:383
#define GLFW_VRESIZE_CURSOR
The vertical resize arrow shape.
Definition: glfw3.h:1055
#define _GLFW_REQUIRE_INIT_OR_RETURN(x)
Definition: internal.h:211
char keys[GLFW_KEY_LAST+1]
Definition: internal.h:391
#define WM_COPYGLOBALDATA
#define GLFW_MOUSE_BUTTON_MIDDLE
Definition: glfw3.h:548
static int createNativeWindow(_GLFWwindow *window, const _GLFWwndconfig *wndconfig, const _GLFWfbconfig *fbconfig)
GLFWbool _glfwCreateContextEGL(_GLFWwindow *window, const _GLFWctxconfig *ctxconfig, const _GLFWfbconfig *fbconfig)
Definition: egl_context.c:456
static void fitToMonitor(_GLFWwindow *window)
Definition: win32_window.c:513
void _glfwPlatformHideWindow(_GLFWwindow *window)
int maxheight
Definition: internal.h:383
#define GLFW_CURSOR_NORMAL
Definition: glfw3.h:1006
GLFWbool maximized
Definition: internal.h:266
#define GLFW_PLATFORM_ERROR
A platform-specific error occurred that does not match any of the more specific categories.
Definition: glfw3.h:726
int _glfwPlatformWindowVisible(_GLFWwindow *window)
#define GLFW_NATIVE_CONTEXT_API
Definition: glfw3.h:1014
_GLFWlibrary _glfw
Definition: init.c:44
#define WM_GETDPISCALEDSIZE
void _glfwInputWindowFocus(_GLFWwindow *window, GLFWbool focused)
Definition: window.c:43
#define DWM_BB_BLURREGION
#define GLFW_MOD_SUPER
If this bit is set one or more Super keys were held down.
Definition: glfw3.h:514
void * VkInstance
Definition: internal.h:119
#define GLFW_HAND_CURSOR
The hand shape.
Definition: glfw3.h:1045
void _glfwInputWindowContentScale(_GLFWwindow *window, float xscale, float yscale)
Definition: window.c:115
#define GLFW_MOD_SHIFT
If this bit is set one or more Shift keys were held down.
Definition: glfw3.h:499
int cursorMode
Definition: internal.h:389
void * VkPhysicalDevice
Definition: internal.h:120
void _glfwPlatformSetCursorMode(_GLFWwindow *window, int mode)
void _glfwInputErrorWin32(int error, const char *description)
Definition: win32_init.c:440
int _glfwPlatformCreateWindow(_GLFWwindow *window, const _GLFWwndconfig *wndconfig, const _GLFWctxconfig *ctxconfig, const _GLFWfbconfig *fbconfig)
struct _GLFWwindow * next
Definition: internal.h:368
GLFWbool _glfwRegisterWindowClassWin32(void)
#define DwmEnableBlurBehindWindow
void _glfwPlatformGetMonitorPos(_GLFWmonitor *monitor, int *xpos, int *ypos)
Definition: null_monitor.c:39
void _glfwPlatformSetWindowMonitor(_GLFWwindow *window, _GLFWmonitor *monitor, int xpos, int ypos, int width, int height, int refreshRate)
void _glfwInputKey(_GLFWwindow *window, int key, int scancode, int action, int mods)
Definition: input.c:259
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily)
void _glfwPlatformGetWindowPos(_GLFWwindow *window, int *xpos, int *ypos)
void _glfwPlatformGetWindowSize(_GLFWwindow *window, int *width, int *height)
double virtualCursorPosY
Definition: internal.h:393
uint64_t VkSurfaceKHR
Definition: internal.h:121
#define GLFW_OSMESA_CONTEXT_API
Definition: glfw3.h:1016
int minwidth
Definition: internal.h:382
#define WM_UNICHAR
void _glfwInputError(int code, const char *format,...)
Definition: init.c:153
void _glfwPollMonitorsWin32(void)
#define GLFW_MOD_ALT
If this bit is set one or more Alt keys were held down.
Definition: glfw3.h:509
void _glfwSetVideoModeWin32(_GLFWmonitor *monitor, const GLFWvidmode *desired)
#define IsWindows7OrGreater()
#define AdjustWindowRectExForDpi
void _glfwInputWindowSize(_GLFWwindow *window, int width, int height)
Definition: window.c:81
void _glfwPlatformSetWindowPos(_GLFWwindow *window, int xpos, int ypos)
#define GLFW_MOD_CAPS_LOCK
If this bit is set the Caps Lock key is enabled.
Definition: glfw3.h:520
#define IsWindowsVistaOrGreater()
#define GET_XBUTTON_WPARAM(w)
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: win32_window.c:572
int _glfwPlatformWindowHovered(_GLFWwindow *window)
GLFWbool floating
Definition: internal.h:374
void _glfwPlatformRequestWindowAttention(_GLFWwindow *window)
action
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, _GLFWwindow *window, const VkAllocationCallbacks *allocator, VkSurfaceKHR *surface)
void _glfwPlatformSetWindowTitle(_GLFWwindow *window, const char *title)
static DWORD getWindowExStyle(const _GLFWwindow *window)
Definition: win32_window.c:67
void _glfwInputWindowMonitor(_GLFWwindow *window, _GLFWmonitor *monitor)
Definition: window.c:141
int width
Definition: glfw3.h:1592
#define GLFW_TRUE
One.
Definition: glfw3.h:279
struct _GLFWlibrary::@8 vk
void _glfwInputCursorPos(_GLFWwindow *window, double xpos, double ypos)
Definition: input.c:338
GLFWbool autoIconify
Definition: internal.h:373
#define _glfwIsWindows10CreatorsUpdateOrGreaterWin32()
#define WM_MOUSEHWHEEL
void _glfwPlatformSetWindowFloating(_GLFWwindow *window, GLFWbool enabled)
int _glfwPlatformWindowIconified(_GLFWwindow *window)
void _glfwPlatformFocusWindow(_GLFWwindow *window)
struct VkAllocationCallbacks VkAllocationCallbacks
Definition: internal.h:163
Video mode type.
Definition: glfw3.h:1525
static void releaseMonitor(_GLFWwindow *window)
Definition: win32_window.c:551
int _glfwPlatformGetKeyScancode(int key)
INLINE Rall1d< T, V, S > abs(const Rall1d< T, V, S > &x)
#define GLFW_HRESIZE_CURSOR
The horizontal resize arrow shape.
Definition: glfw3.h:1050
#define GLFW_IBEAM_CURSOR
The text input I-beam cursor shape.
Definition: glfw3.h:1035
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow *window, const _GLFWctxconfig *ctxconfig, const _GLFWfbconfig *fbconfig)
void _glfwInputMonitorWindow(_GLFWmonitor *monitor, _GLFWwindow *window)
Definition: monitor.c:149
void _glfwDetectJoystickDisconnectionWin32(void)
#define GLFW_KEY_LEFT_CONTROL
Definition: glfw3.h:474
GLFWbool _glfwInitWGL(void)
Definition: wgl_context.c:343
void _glfwPlatformWaitEvents(void)
static void updateFramebufferTransparency(const _GLFWwindow *window)
Definition: win32_window.c:371
void _glfwPlatformPostEmptyEvent(void)
_GLFWcursor * cursor
Definition: internal.h:380
#define GLFW_MOUSE_BUTTON_LAST
Definition: glfw3.h:545
int minheight
Definition: internal.h:382
#define WM_DWMCOMPOSITIONCHANGED
void _glfwPlatformSetWindowOpacity(_GLFWwindow *window, float opacity)
static void applyAspectRatio(_GLFWwindow *window, int edge, RECT *area)
Definition: win32_window.c:209
#define DwmIsCompositionEnabled
char mouseButtons[GLFW_MOUSE_BUTTON_LAST+1]
Definition: internal.h:390
int _glfwPlatformCreateCursor(_GLFWcursor *cursor, const GLFWimage *image, int xhot, int yhot)
void _glfwPlatformRestoreWindow(_GLFWwindow *window)
static void getFullWindowSize(DWORD style, DWORD exStyle, int clientWidth, int clientHeight, int *fullWidth, int *fullHeight, UINT dpi)
Definition: win32_window.c:191
Image data.
Definition: glfw3.h:1588
#define _GLFW_KEY_INVALID
Definition: win32_window.c:37
#define USER_DEFAULT_SCREEN_DPI
#define ChangeWindowMessageFilterEx
void _glfwPlatformMaximizeWindow(_GLFWwindow *window)
void _glfwInputMouseClick(_GLFWwindow *window, int button, int action, int mods)
Definition: input.c:318
void _glfwPlatformSetWindowDecorated(_GLFWwindow *window, GLFWbool enabled)
GLFWbool _glfwInitEGL(void)
Definition: egl_context.c:300
static GLFWbool cursorInClientArea(_GLFWwindow *window)
Definition: win32_window.c:322
void _glfwPlatformPollEvents(void)
#define GLFW_KEY_RIGHT_SHIFT
Definition: glfw3.h:477
void _glfwPlatformSetCursor(_GLFWwindow *window, _GLFWcursor *cursor)
void _glfwPlatformGetWindowFrameSize(_GLFWwindow *window, int *left, int *top, int *right, int *bottom)
double virtualCursorPosX
Definition: internal.h:393
_GLFWwindow * window
Definition: internal.h:432
#define GLFW_PRESS
The key or mouse button was pressed.
Definition: glfw3.h:304
#define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32()
_GLFWmonitor * monitor
Definition: internal.h:379
void _glfwPlatformGetFramebufferSize(_GLFWwindow *window, int *width, int *height)
void _glfwUpdateKeyNamesWin32(void)
Definition: win32_init.c:461
void _glfwInputDrop(_GLFWwindow *window, int count, const char **paths)
Definition: input.c:360
GLFWbool decorated
Definition: internal.h:372
static int getKeyMods(void)
Definition: win32_window.c:422
static void acquireMonitor(_GLFWwindow *window)
Definition: win32_window.c:527
int _glfwPlatformWindowMaximized(_GLFWwindow *window)
#define GetDpiForWindow
const char * _glfwPlatformGetScancodeName(int scancode)
#define GLFW_MOD_NUM_LOCK
If this bit is set the Num Lock key is enabled.
Definition: glfw3.h:526
#define GLFW_MOUSE_BUTTON_4
Definition: glfw3.h:540
void _glfwPlatformSetClipboardString(const char *string)
static void SetWindowPos(ImGuiWindow *window, const ImVec2 &pos, ImGuiCond cond)
Definition: imgui.cpp:5915
#define GLFW_NO_API
Definition: glfw3.h:989
GLFWAPI HWND glfwGetWin32Window(GLFWwindow *handle)
VkResult
Definition: internal.h:135
static void disableCursor(_GLFWwindow *window)
Definition: win32_window.c:281
#define _GLFW_WNDCLASSNAME


mvsim
Author(s):
autogenerated on Tue Jul 4 2023 03:08:22