Blender  V2.93
GHOST_SystemWin32.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
24 #include "GHOST_SystemWin32.h"
25 #include "GHOST_ContextD3D.h"
26 #include "GHOST_EventDragnDrop.h"
27 
28 #ifndef _WIN32_IE
29 # define _WIN32_IE 0x0501 /* shipped before XP, so doesn't impose additional requirements */
30 #endif
31 
32 #include <commctrl.h>
33 #include <psapi.h>
34 #include <shellapi.h>
35 #include <shlobj.h>
36 #include <tlhelp32.h>
37 #include <windowsx.h>
38 
39 #include "utf_winfunc.h"
40 #include "utfconv.h"
41 
43 #include "GHOST_EventButton.h"
44 #include "GHOST_EventCursor.h"
45 #include "GHOST_EventKey.h"
46 #include "GHOST_EventWheel.h"
47 #include "GHOST_TimerManager.h"
48 #include "GHOST_TimerTask.h"
49 #include "GHOST_WindowManager.h"
50 #include "GHOST_WindowWin32.h"
51 
52 #if defined(WITH_GL_EGL)
53 # include "GHOST_ContextEGL.h"
54 #else
55 # include "GHOST_ContextWGL.h"
56 #endif
57 
58 #ifdef WITH_INPUT_NDOF
59 # include "GHOST_NDOFManagerWin32.h"
60 #endif
61 
62 // Key code values not found in winuser.h
63 #ifndef VK_MINUS
64 # define VK_MINUS 0xBD
65 #endif // VK_MINUS
66 #ifndef VK_SEMICOLON
67 # define VK_SEMICOLON 0xBA
68 #endif // VK_SEMICOLON
69 #ifndef VK_PERIOD
70 # define VK_PERIOD 0xBE
71 #endif // VK_PERIOD
72 #ifndef VK_COMMA
73 # define VK_COMMA 0xBC
74 #endif // VK_COMMA
75 #ifndef VK_QUOTE
76 # define VK_QUOTE 0xDE
77 #endif // VK_QUOTE
78 #ifndef VK_BACK_QUOTE
79 # define VK_BACK_QUOTE 0xC0
80 #endif // VK_BACK_QUOTE
81 #ifndef VK_SLASH
82 # define VK_SLASH 0xBF
83 #endif // VK_SLASH
84 #ifndef VK_BACK_SLASH
85 # define VK_BACK_SLASH 0xDC
86 #endif // VK_BACK_SLASH
87 #ifndef VK_EQUALS
88 # define VK_EQUALS 0xBB
89 #endif // VK_EQUALS
90 #ifndef VK_OPEN_BRACKET
91 # define VK_OPEN_BRACKET 0xDB
92 #endif // VK_OPEN_BRACKET
93 #ifndef VK_CLOSE_BRACKET
94 # define VK_CLOSE_BRACKET 0xDD
95 #endif // VK_CLOSE_BRACKET
96 #ifndef VK_GR_LESS
97 # define VK_GR_LESS 0xE2
98 #endif // VK_GR_LESS
99 
100 #ifndef VK_MEDIA_NEXT_TRACK
101 # define VK_MEDIA_NEXT_TRACK 0xB0
102 #endif // VK_MEDIA_NEXT_TRACK
103 #ifndef VK_MEDIA_PREV_TRACK
104 # define VK_MEDIA_PREV_TRACK 0xB1
105 #endif // VK_MEDIA_PREV_TRACK
106 #ifndef VK_MEDIA_STOP
107 # define VK_MEDIA_STOP 0xB2
108 #endif // VK_MEDIA_STOP
109 #ifndef VK_MEDIA_PLAY_PAUSE
110 # define VK_MEDIA_PLAY_PAUSE 0xB3
111 #endif // VK_MEDIA_PLAY_PAUSE
112 
113 // Window message newer than Windows 7
114 #ifndef WM_DPICHANGED
115 # define WM_DPICHANGED 0x02E0
116 #endif // WM_DPICHANGED
117 
118 // WM_POINTER API messages minimum Windows 7
119 #ifndef WM_POINTERENTER
120 # define WM_POINTERENTER 0x0249
121 #endif // WM_POINTERENTER
122 #ifndef WM_POINTERDOWN
123 # define WM_POINTERDOWN 0x0246
124 #endif // WM_POINTERDOWN
125 #ifndef WM_POINTERUPDATE
126 # define WM_POINTERUPDATE 0x0245
127 #endif // WM_POINTERUPDATE
128 #ifndef WM_POINTERUP
129 # define WM_POINTERUP 0x0247
130 #endif // WM_POINTERUP
131 #ifndef WM_POINTERLEAVE
132 # define WM_POINTERLEAVE 0x024A
133 #endif // WM_POINTERLEAVE
134 
135 /* Workaround for some laptop touchpads, some of which seems to
136  * have driver issues which makes it so window function receives
137  * the message, but PeekMessage doesn't pick those messages for
138  * some reason.
139  *
140  * We send a dummy WM_USER message to force PeekMessage to receive
141  * something, making it so blender's window manager sees the new
142  * messages coming in.
143  */
144 #define BROKEN_PEEK_TOUCHPAD
145 
146 static void initRawInput()
147 {
148 #ifdef WITH_INPUT_NDOF
149 # define DEVICE_COUNT 2
150 #else
151 # define DEVICE_COUNT 1
152 #endif
153 
154  RAWINPUTDEVICE devices[DEVICE_COUNT];
155  memset(devices, 0, DEVICE_COUNT * sizeof(RAWINPUTDEVICE));
156 
157  // Initiates WM_INPUT messages from keyboard
158  // That way GHOST can retrieve true keys
159  devices[0].usUsagePage = 0x01;
160  devices[0].usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
161 
162 #ifdef WITH_INPUT_NDOF
163  // multi-axis mouse (SpaceNavigator, etc.)
164  devices[1].usUsagePage = 0x01;
165  devices[1].usUsage = 0x08;
166 #endif
167 
168  if (RegisterRawInputDevices(devices, DEVICE_COUNT, sizeof(RAWINPUTDEVICE)))
169  ; // yay!
170  else
171  GHOST_PRINTF("could not register for RawInput: %d\n", (int)GetLastError());
172 
173 #undef DEVICE_COUNT
174 }
175 
176 #ifndef DPI_ENUMS_DECLARED
177 typedef enum PROCESS_DPI_AWARENESS {
182 
183 typedef enum MONITOR_DPI_TYPE {
189 
190 # define USER_DEFAULT_SCREEN_DPI 96
191 
192 # define DPI_ENUMS_DECLARED
193 #endif
195 typedef BOOL(API *GHOST_WIN32_EnableNonClientDpiScaling)(HWND);
196 
198  : m_hasPerformanceCounter(false), m_freq(0), m_start(0), m_lfstart(0)
199 {
201  GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
203 
204  m_consoleStatus = 1;
205 
206  // Tell Windows we are per monitor DPI aware. This disables the default
207  // blurry scaling and enables WM_DPICHANGED to allow us to draw at proper DPI.
208  HMODULE m_shcore = ::LoadLibrary("Shcore.dll");
209  if (m_shcore) {
210  GHOST_WIN32_SetProcessDpiAwareness fpSetProcessDpiAwareness =
211  (GHOST_WIN32_SetProcessDpiAwareness)::GetProcAddress(m_shcore, "SetProcessDpiAwareness");
212 
213  if (fpSetProcessDpiAwareness) {
214  fpSetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
215  }
216  }
217 
218  // Check if current keyboard layout uses AltGr and save keylayout ID for
219  // specialized handling if keys like VK_OEM_*. I.e. french keylayout
220  // generates VK_OEM_8 for their exclamation key (key left of right shift)
221  this->handleKeyboardChange();
222  // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
223  OleInitialize(0);
224 
225 #ifdef WITH_INPUT_NDOF
226  m_ndofManager = new GHOST_NDOFManagerWin32(*this);
227 #endif
228 }
229 
231 {
232  // Shutdown COM
233  OleUninitialize();
234  toggleConsole(1);
235 }
236 
238 {
239  // Calculate the time passed since system initialization.
240  __int64 delta = (perf_ticks - m_start) * 1000;
241 
242  GHOST_TUns64 t = (GHOST_TUns64)(delta / m_freq);
243  return t;
244 }
245 
247 {
248  return ticks - m_lfstart;
249 }
250 
252 {
253  // Hardware does not support high resolution timers. We will use GetTickCount instead then.
255  return tickCountToMillis(::GetTickCount());
256  }
257 
258  // Retrieve current count
259  __int64 count = 0;
260  ::QueryPerformanceCounter((LARGE_INTEGER *)&count);
261 
263 }
264 
266 {
267  GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::getNumDisplays(): m_displayManager==0\n");
268  GHOST_TUns8 numDisplays;
269  m_displayManager->getNumDisplays(numDisplays);
270  return numDisplays;
271 }
272 
274 {
275  width = ::GetSystemMetrics(SM_CXSCREEN);
276  height = ::GetSystemMetrics(SM_CYSCREEN);
277 }
278 
280 {
281  width = ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
282  height = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
283 }
284 
292  GHOST_GLSettings glSettings,
293  const bool exclusive,
294  const bool is_dialog,
295  const GHOST_IWindow *parentWindow)
296 {
297  GHOST_WindowWin32 *window = new GHOST_WindowWin32(
298  this,
299  title,
300  left,
301  top,
302  width,
303  height,
304  state,
305  type,
306  ((glSettings.flags & GHOST_glStereoVisual) != 0),
307  ((glSettings.flags & GHOST_glAlphaBackground) != 0),
308  (GHOST_WindowWin32 *)parentWindow,
309  ((glSettings.flags & GHOST_glDebugContext) != 0),
310  is_dialog);
311 
312  if (window->getValid()) {
313  // Store the pointer to the window
314  m_windowManager->addWindow(window);
316  }
317  else {
318  GHOST_PRINT("GHOST_SystemWin32::createWindow(): window invalid\n");
319  delete window;
320  window = NULL;
321  }
322 
323  return window;
324 }
325 
332 {
333  const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
334 
336 
337  HWND wnd = CreateWindowA("STATIC",
338  "BlenderGLEW",
339  WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
340  0,
341  0,
342  64,
343  64,
344  NULL,
345  NULL,
346  GetModuleHandle(NULL),
347  NULL);
348 
349  HDC mHDC = GetDC(wnd);
350  HDC prev_hdc = wglGetCurrentDC();
351  HGLRC prev_context = wglGetCurrentContext();
352 #if defined(WITH_GL_PROFILE_CORE)
353  for (int minor = 5; minor >= 0; --minor) {
354  context = new GHOST_ContextWGL(false,
355  true,
356  wnd,
357  mHDC,
358  WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
359  4,
360  minor,
361  (debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
363 
364  if (context->initializeDrawingContext()) {
365  goto finished;
366  }
367  else {
368  delete context;
369  }
370  }
371 
372  context = new GHOST_ContextWGL(false,
373  true,
374  wnd,
375  mHDC,
376  WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
377  3,
378  3,
379  (debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
381 
382  if (context->initializeDrawingContext()) {
383  goto finished;
384  }
385  else {
386  delete context;
387  return NULL;
388  }
389 
390 #elif defined(WITH_GL_PROFILE_COMPAT)
391  // ask for 2.1 context, driver gives any GL version >= 2.1
392  // (hopefully the latest compatibility profile)
393  // 2.1 ignores the profile bit & is incompatible with core profile
394  context = new GHOST_ContextWGL(false,
395  true,
396  NULL,
397  NULL,
398  0, // no profile bit
399  2,
400  1,
401  (debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
403 
404  if (context->initializeDrawingContext()) {
405  return context;
406  }
407  else {
408  delete context;
409  }
410 #else
411 # error // must specify either core or compat at build time
412 #endif
413 finished:
414  wglMakeCurrent(prev_hdc, prev_context);
415  return context;
416 }
417 
424 {
425  delete context;
426 
427  return GHOST_kSuccess;
428 }
429 
436 {
438 
439  HWND wnd = CreateWindowA("STATIC",
440  "Blender XR",
441  WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
442  0,
443  0,
444  64,
445  64,
446  NULL,
447  NULL,
448  GetModuleHandle(NULL),
449  NULL);
450 
451  context = new GHOST_ContextD3D(false, wnd);
452  if (context->initializeDrawingContext() == GHOST_kFailure) {
453  delete context;
454  }
455 
456  return context;
457 }
458 
460 {
461  delete context;
462 
463  return GHOST_kSuccess;
464 }
465 
466 bool GHOST_SystemWin32::processEvents(bool waitForEvent)
467 {
468  MSG msg;
469  bool hasEventHandled = false;
470 
471  do {
472  GHOST_TimerManager *timerMgr = getTimerManager();
473 
474  if (waitForEvent && !::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
475 #if 1
476  ::Sleep(1);
477 #else
478  GHOST_TUns64 next = timerMgr->nextFireTime();
479  GHOST_TInt64 maxSleep = next - getMilliSeconds();
480 
481  if (next == GHOST_kFireTimeNever) {
482  ::WaitMessage();
483  }
484  else if (maxSleep >= 0.0) {
485  ::SetTimer(NULL, 0, maxSleep, NULL);
486  ::WaitMessage();
487  ::KillTimer(NULL, 0);
488  }
489 #endif
490  }
491 
492  if (timerMgr->fireTimers(getMilliSeconds())) {
493  hasEventHandled = true;
494  }
495 
496  // Process all the events waiting for us
497  while (::PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
498  // TranslateMessage doesn't alter the message, and doesn't change our raw keyboard data.
499  // Needed for MapVirtualKey or if we ever need to get chars from wm_ime_char or similar.
500  ::TranslateMessage(&msg);
501  ::DispatchMessageW(&msg);
502  hasEventHandled = true;
503  }
504 
505  /* PeekMessage above is allowed to dispatch messages to the wndproc without us
506  * noticing, so we need to check the event manager here to see if there are
507  * events waiting in the queue.
508  */
509  hasEventHandled |= this->m_eventManager->getNumEvents() > 0;
510 
511  } while (waitForEvent && !hasEventHandled);
512 
513  return hasEventHandled;
514 }
515 
517 {
518  POINT point;
519  if (::GetCursorPos(&point)) {
520  x = point.x;
521  y = point.y;
522  return GHOST_kSuccess;
523  }
524  return GHOST_kFailure;
525 }
526 
528 {
529  if (!::GetActiveWindow())
530  return GHOST_kFailure;
531  return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
532 }
533 
535 {
536  bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
537  keys.set(GHOST_kModifierKeyLeftShift, down);
538  down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0;
539  keys.set(GHOST_kModifierKeyRightShift, down);
540 
541  down = HIBYTE(::GetKeyState(VK_LMENU)) != 0;
542  keys.set(GHOST_kModifierKeyLeftAlt, down);
543  down = HIBYTE(::GetKeyState(VK_RMENU)) != 0;
544  keys.set(GHOST_kModifierKeyRightAlt, down);
545 
546  down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 0;
548  down = HIBYTE(::GetKeyState(VK_RCONTROL)) != 0;
550 
551  bool lwindown = HIBYTE(::GetKeyState(VK_LWIN)) != 0;
552  bool rwindown = HIBYTE(::GetKeyState(VK_RWIN)) != 0;
553  if (lwindown || rwindown)
554  keys.set(GHOST_kModifierKeyOS, true);
555  else
556  keys.set(GHOST_kModifierKeyOS, false);
557  return GHOST_kSuccess;
558 }
559 
561 {
562  /* Check for swapped buttons (left-handed mouse buttons)
563  * GetAsyncKeyState() will give back the state of the physical mouse buttons.
564  */
565  bool swapped = ::GetSystemMetrics(SM_SWAPBUTTON) == TRUE;
566 
567  bool down = HIBYTE(::GetAsyncKeyState(VK_LBUTTON)) != 0;
568  buttons.set(swapped ? GHOST_kButtonMaskRight : GHOST_kButtonMaskLeft, down);
569 
570  down = HIBYTE(::GetAsyncKeyState(VK_MBUTTON)) != 0;
571  buttons.set(GHOST_kButtonMaskMiddle, down);
572 
573  down = HIBYTE(::GetAsyncKeyState(VK_RBUTTON)) != 0;
574  buttons.set(swapped ? GHOST_kButtonMaskLeft : GHOST_kButtonMaskRight, down);
575  return GHOST_kSuccess;
576 }
577 
579 {
581  InitCommonControls();
582 
583  /* Disable scaling on high DPI displays on Vista */
584  HMODULE
585  user32 = ::LoadLibraryA("user32.dll");
586  typedef BOOL(WINAPI * LPFNSETPROCESSDPIAWARE)();
587  LPFNSETPROCESSDPIAWARE SetProcessDPIAware = (LPFNSETPROCESSDPIAWARE)GetProcAddress(
588  user32, "SetProcessDPIAware");
589  if (SetProcessDPIAware)
590  SetProcessDPIAware();
591  FreeLibrary(user32);
592  initRawInput();
593 
594  m_lfstart = ::GetTickCount();
595  // Determine whether this system has a high frequency performance counter. */
596  m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER *)&m_freq) == TRUE;
598  GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer available\n");
599  ::QueryPerformanceCounter((LARGE_INTEGER *)&m_start);
600  }
601  else {
602  GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer not available\n");
603  }
604 
605  if (success) {
606  WNDCLASSW wc = {0};
607  wc.style = CS_HREDRAW | CS_VREDRAW;
608  wc.lpfnWndProc = s_wndProc;
609  wc.cbClsExtra = 0;
610  wc.cbWndExtra = 0;
611  wc.hInstance = ::GetModuleHandle(0);
612  wc.hIcon = ::LoadIcon(wc.hInstance, "APPICON");
613 
614  if (!wc.hIcon) {
615  ::LoadIcon(NULL, IDI_APPLICATION);
616  }
617  wc.hCursor = ::LoadCursor(0, IDC_ARROW);
618  wc.hbrBackground =
619 #ifdef INW32_COMPISITING
620  (HBRUSH)CreateSolidBrush
621 #endif
622  (0x00000000);
623  wc.lpszMenuName = 0;
624  wc.lpszClassName = L"GHOST_WindowClass";
625 
626  // Use RegisterClassEx for setting small icon
627  if (::RegisterClassW(&wc) == 0) {
628  success = GHOST_kFailure;
629  }
630  }
631 
632  return success;
633 }
634 
636 {
637  return GHOST_System::exit();
638 }
639 
641  bool *r_keyDown,
642  bool *r_is_repeated_modifier)
643 {
644  bool is_repeated_modifier = false;
645 
648  GHOST_ModifierKeys modifiers;
649  system->retrieveModifierKeys(modifiers);
650 
651  // RI_KEY_BREAK doesn't work for sticky keys release, so we also
652  // check for the up message
653  unsigned int msg = raw.data.keyboard.Message;
654  *r_keyDown = !(raw.data.keyboard.Flags & RI_KEY_BREAK) && msg != WM_KEYUP && msg != WM_SYSKEYUP;
655 
656  key = this->convertKey(raw.data.keyboard.VKey,
657  raw.data.keyboard.MakeCode,
658  (raw.data.keyboard.Flags & (RI_KEY_E1 | RI_KEY_E0)));
659 
660  // extra handling of modifier keys: don't send repeats out from GHOST
661  if (key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt) {
662  bool changed = false;
663  GHOST_TModifierKeyMask modifier;
664  switch (key) {
665  case GHOST_kKeyLeftShift: {
666  changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != *r_keyDown);
667  modifier = GHOST_kModifierKeyLeftShift;
668  break;
669  }
670  case GHOST_kKeyRightShift: {
671  changed = (modifiers.get(GHOST_kModifierKeyRightShift) != *r_keyDown);
672  modifier = GHOST_kModifierKeyRightShift;
673  break;
674  }
675  case GHOST_kKeyLeftControl: {
676  changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != *r_keyDown);
678  break;
679  }
680  case GHOST_kKeyRightControl: {
681  changed = (modifiers.get(GHOST_kModifierKeyRightControl) != *r_keyDown);
683  break;
684  }
685  case GHOST_kKeyLeftAlt: {
686  changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != *r_keyDown);
687  modifier = GHOST_kModifierKeyLeftAlt;
688  break;
689  }
690  case GHOST_kKeyRightAlt: {
691  changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != *r_keyDown);
692  modifier = GHOST_kModifierKeyRightAlt;
693  break;
694  }
695  default:
696  break;
697  }
698 
699  if (changed) {
700  modifiers.set(modifier, *r_keyDown);
701  system->storeModifierKeys(modifiers);
702  }
703  else {
704  is_repeated_modifier = true;
705  }
706  }
707 
708  *r_is_repeated_modifier = is_repeated_modifier;
709  return key;
710 }
711 
718 GHOST_TKey GHOST_SystemWin32::processSpecialKey(short vKey, short scanCode) const
719 {
721  switch (PRIMARYLANGID(m_langId)) {
722  case LANG_FRENCH:
723  if (vKey == VK_OEM_8)
724  key = GHOST_kKeyF13; // oem key; used purely for shortcuts .
725  break;
726  case LANG_ENGLISH:
727  if (SUBLANGID(m_langId) == SUBLANG_ENGLISH_UK && vKey == VK_OEM_8) // "`¬"
728  key = GHOST_kKeyAccentGrave;
729  break;
730  }
731 
732  return key;
733 }
734 
735 GHOST_TKey GHOST_SystemWin32::convertKey(short vKey, short scanCode, short extend) const
736 {
737  GHOST_TKey key;
738 
739  if ((vKey >= '0') && (vKey <= '9')) {
740  // VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)
741  key = (GHOST_TKey)(vKey - '0' + GHOST_kKey0);
742  }
743  else if ((vKey >= 'A') && (vKey <= 'Z')) {
744  // VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)
745  key = (GHOST_TKey)(vKey - 'A' + GHOST_kKeyA);
746  }
747  else if ((vKey >= VK_F1) && (vKey <= VK_F24)) {
748  key = (GHOST_TKey)(vKey - VK_F1 + GHOST_kKeyF1);
749  }
750  else {
751  switch (vKey) {
752  case VK_RETURN:
753  key = (extend) ? GHOST_kKeyNumpadEnter : GHOST_kKeyEnter;
754  break;
755 
756  case VK_BACK:
757  key = GHOST_kKeyBackSpace;
758  break;
759  case VK_TAB:
760  key = GHOST_kKeyTab;
761  break;
762  case VK_ESCAPE:
763  key = GHOST_kKeyEsc;
764  break;
765  case VK_SPACE:
766  key = GHOST_kKeySpace;
767  break;
768 
769  case VK_INSERT:
770  case VK_NUMPAD0:
771  key = (extend) ? GHOST_kKeyInsert : GHOST_kKeyNumpad0;
772  break;
773  case VK_END:
774  case VK_NUMPAD1:
775  key = (extend) ? GHOST_kKeyEnd : GHOST_kKeyNumpad1;
776  break;
777  case VK_DOWN:
778  case VK_NUMPAD2:
779  key = (extend) ? GHOST_kKeyDownArrow : GHOST_kKeyNumpad2;
780  break;
781  case VK_NEXT:
782  case VK_NUMPAD3:
783  key = (extend) ? GHOST_kKeyDownPage : GHOST_kKeyNumpad3;
784  break;
785  case VK_LEFT:
786  case VK_NUMPAD4:
787  key = (extend) ? GHOST_kKeyLeftArrow : GHOST_kKeyNumpad4;
788  break;
789  case VK_CLEAR:
790  case VK_NUMPAD5:
791  key = (extend) ? GHOST_kKeyUnknown : GHOST_kKeyNumpad5;
792  break;
793  case VK_RIGHT:
794  case VK_NUMPAD6:
795  key = (extend) ? GHOST_kKeyRightArrow : GHOST_kKeyNumpad6;
796  break;
797  case VK_HOME:
798  case VK_NUMPAD7:
799  key = (extend) ? GHOST_kKeyHome : GHOST_kKeyNumpad7;
800  break;
801  case VK_UP:
802  case VK_NUMPAD8:
803  key = (extend) ? GHOST_kKeyUpArrow : GHOST_kKeyNumpad8;
804  break;
805  case VK_PRIOR:
806  case VK_NUMPAD9:
807  key = (extend) ? GHOST_kKeyUpPage : GHOST_kKeyNumpad9;
808  break;
809  case VK_DECIMAL:
810  case VK_DELETE:
811  key = (extend) ? GHOST_kKeyDelete : GHOST_kKeyNumpadPeriod;
812  break;
813 
814  case VK_SNAPSHOT:
815  key = GHOST_kKeyPrintScreen;
816  break;
817  case VK_PAUSE:
818  key = GHOST_kKeyPause;
819  break;
820  case VK_MULTIPLY:
822  break;
823  case VK_SUBTRACT:
824  key = GHOST_kKeyNumpadMinus;
825  break;
826  case VK_DIVIDE:
827  key = GHOST_kKeyNumpadSlash;
828  break;
829  case VK_ADD:
830  key = GHOST_kKeyNumpadPlus;
831  break;
832 
833  case VK_SEMICOLON:
834  key = GHOST_kKeySemicolon;
835  break;
836  case VK_EQUALS:
837  key = GHOST_kKeyEqual;
838  break;
839  case VK_COMMA:
840  key = GHOST_kKeyComma;
841  break;
842  case VK_MINUS:
843  key = GHOST_kKeyMinus;
844  break;
845  case VK_PERIOD:
846  key = GHOST_kKeyPeriod;
847  break;
848  case VK_SLASH:
849  key = GHOST_kKeySlash;
850  break;
851  case VK_BACK_QUOTE:
852  key = GHOST_kKeyAccentGrave;
853  break;
854  case VK_OPEN_BRACKET:
855  key = GHOST_kKeyLeftBracket;
856  break;
857  case VK_BACK_SLASH:
858  key = GHOST_kKeyBackslash;
859  break;
860  case VK_CLOSE_BRACKET:
862  break;
863  case VK_QUOTE:
864  key = GHOST_kKeyQuote;
865  break;
866  case VK_GR_LESS:
867  key = GHOST_kKeyGrLess;
868  break;
869 
870  case VK_SHIFT:
871  /* Check single shift presses */
872  if (scanCode == 0x36) {
873  key = GHOST_kKeyRightShift;
874  }
875  else if (scanCode == 0x2a) {
876  key = GHOST_kKeyLeftShift;
877  }
878  else {
879  /* Must be a combination SHIFT (Left or Right) + a Key
880  * Ignore this as the next message will contain
881  * the desired "Key" */
882  key = GHOST_kKeyUnknown;
883  }
884  break;
885  case VK_CONTROL:
887  break;
888  case VK_MENU:
889  key = (extend) ? GHOST_kKeyRightAlt : GHOST_kKeyLeftAlt;
890  break;
891  case VK_LWIN:
892  case VK_RWIN:
893  key = GHOST_kKeyOS;
894  break;
895  case VK_APPS:
896  key = GHOST_kKeyApp;
897  break;
898  case VK_NUMLOCK:
899  key = GHOST_kKeyNumLock;
900  break;
901  case VK_SCROLL:
902  key = GHOST_kKeyScrollLock;
903  break;
904  case VK_CAPITAL:
905  key = GHOST_kKeyCapsLock;
906  break;
907  case VK_OEM_8:
908  key = ((GHOST_SystemWin32 *)getSystem())->processSpecialKey(vKey, scanCode);
909  break;
910  case VK_MEDIA_PLAY_PAUSE:
911  key = GHOST_kKeyMediaPlay;
912  break;
913  case VK_MEDIA_STOP:
914  key = GHOST_kKeyMediaStop;
915  break;
916  case VK_MEDIA_PREV_TRACK:
917  key = GHOST_kKeyMediaFirst;
918  break;
919  case VK_MEDIA_NEXT_TRACK:
920  key = GHOST_kKeyMediaLast;
921  break;
922  default:
923  key = GHOST_kKeyUnknown;
924  break;
925  }
926  }
927 
928  return key;
929 }
930 
932  GHOST_WindowWin32 *window,
934 {
936 
937  if (type == GHOST_kEventButtonDown) {
939  }
940  else if (type == GHOST_kEventButtonUp) {
942  }
943 
944  return new GHOST_EventButton(
945  system->getMilliSeconds(), type, window, mask, window->getTabletData());
946 }
947 
949  UINT type, GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam, bool &eventHandled)
950 {
951  /* Pointer events might fire when changing windows for a device which is set to use Wintab, even
952  * when when Wintab is left enabled but set to the bottom of Wintab overlap order. */
953  if (!window->useTabletAPI(GHOST_kTabletNative)) {
954  return;
955  }
956 
958  std::vector<GHOST_PointerInfoWin32> pointerInfo;
959 
960  if (window->getPointerInfo(pointerInfo, wParam, lParam) != GHOST_kSuccess) {
961  return;
962  }
963 
964  if (!pointerInfo[0].isPrimary) {
965  eventHandled = true;
966  return; // For multi-touch displays we ignore these events
967  }
968 
969  switch (type) {
970  case WM_POINTERENTER:
971  window->m_tabletInRange = true;
972  system->pushEvent(new GHOST_EventCursor(pointerInfo[0].time,
974  window,
975  pointerInfo[0].pixelLocation.x,
976  pointerInfo[0].pixelLocation.y,
977  pointerInfo[0].tabletData));
978  break;
979  case WM_POINTERDOWN:
980  /* Move cursor to point of contact because GHOST_EventButton does not include position. */
981  system->pushEvent(new GHOST_EventCursor(pointerInfo[0].time,
983  window,
984  pointerInfo[0].pixelLocation.x,
985  pointerInfo[0].pixelLocation.y,
986  pointerInfo[0].tabletData));
987  system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
989  window,
990  pointerInfo[0].buttonMask,
991  pointerInfo[0].tabletData));
993  break;
994  case WM_POINTERUPDATE:
995  /* Coalesced pointer events are reverse chronological order, reorder chronologically.
996  * Only contiguous move events are coalesced. */
997  for (GHOST_TUns32 i = pointerInfo.size(); i-- > 0;) {
998  system->pushEvent(new GHOST_EventCursor(pointerInfo[i].time,
1000  window,
1001  pointerInfo[i].pixelLocation.x,
1002  pointerInfo[i].pixelLocation.y,
1003  pointerInfo[i].tabletData));
1004  }
1005  break;
1006  case WM_POINTERUP:
1007  system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
1009  window,
1010  pointerInfo[0].buttonMask,
1011  pointerInfo[0].tabletData));
1013  break;
1014  case WM_POINTERLEAVE:
1015  window->m_tabletInRange = false;
1016  break;
1017  default:
1018  break;
1019  }
1020 
1021  eventHandled = true;
1022  system->setCursorPosition(pointerInfo[0].pixelLocation.x, pointerInfo[0].pixelLocation.y);
1023 }
1024 
1026 {
1027  GHOST_TInt32 x_screen, y_screen;
1029 
1030  if (window->m_tabletInRange) {
1031  if (window->useTabletAPI(GHOST_kTabletNative)) {
1032  /* Tablet input handled in WM_POINTER* events. WM_MOUSEMOVE events in response to tablet
1033  * input aren't normally generated when using WM_POINTER events, but manually moving the
1034  * system cursor as we do in WM_POINTER handling does. */
1035  return NULL;
1036  }
1037  }
1038 
1039  system->getCursorPosition(x_screen, y_screen);
1040 
1041  if (window->getCursorGrabModeIsWarp() && !window->m_tabletInRange) {
1042  GHOST_TInt32 x_new = x_screen;
1043  GHOST_TInt32 y_new = y_screen;
1044  GHOST_TInt32 x_accum, y_accum;
1046 
1047  /* Fallback to window bounds. */
1048  if (window->getCursorGrabBounds(bounds) == GHOST_kFailure) {
1049  window->getClientBounds(bounds);
1050  }
1051 
1052  /* Could also clamp to screen bounds wrap with a window outside the view will fail atm.
1053  * Use offset of 8 in case the window is at screen bounds. */
1054  bounds.wrapPoint(x_new, y_new, 2, window->getCursorGrabAxis());
1055 
1056  window->getCursorGrabAccum(x_accum, y_accum);
1057  if (x_new != x_screen || y_new != y_screen) {
1058  /* When wrapping we don't need to add an event because the setCursorPosition call will cause
1059  * a new event after. */
1060  system->setCursorPosition(x_new, y_new); /* wrap */
1061  window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
1062  }
1063  else {
1064  return new GHOST_EventCursor(system->getMilliSeconds(),
1066  window,
1067  x_screen + x_accum,
1068  y_screen + y_accum,
1069  window->getTabletData());
1070  }
1071  }
1072  else {
1073  return new GHOST_EventCursor(system->getMilliSeconds(),
1075  window,
1076  x_screen,
1077  y_screen,
1078  window->getTabletData());
1079  }
1080  return NULL;
1081 }
1082 
1083 void GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam)
1084 {
1086 
1087  int acc = system->m_wheelDeltaAccum;
1088  int delta = GET_WHEEL_DELTA_WPARAM(wParam);
1089 
1090  if (acc * delta < 0) {
1091  // scroll direction reversed.
1092  acc = 0;
1093  }
1094  acc += delta;
1095  int direction = (acc >= 0) ? 1 : -1;
1096  acc = abs(acc);
1097 
1098  while (acc >= WHEEL_DELTA) {
1099  system->pushEvent(new GHOST_EventWheel(system->getMilliSeconds(), window, direction));
1100  acc -= WHEEL_DELTA;
1101  }
1102  system->m_wheelDeltaAccum = acc * direction;
1103 }
1104 
1106 {
1107  bool keyDown = false;
1108  bool is_repeated_modifier = false;
1110  GHOST_TKey key = system->hardKey(raw, &keyDown, &is_repeated_modifier);
1111  GHOST_EventKey *event;
1112 
1113  /* We used to check `if (key != GHOST_kKeyUnknown)`, but since the message
1114  * values `WM_SYSKEYUP`, `WM_KEYUP` and `WM_CHAR` are ignored, we capture
1115  * those events here as well. */
1116  if (!is_repeated_modifier) {
1117  char vk = raw.data.keyboard.VKey;
1118  char utf8_char[6] = {0};
1119  char ascii = 0;
1120  bool is_repeat = false;
1121 
1122  /* Unlike on Linux, not all keys can send repeat events. E.g. modifier keys don't. */
1123  if (keyDown) {
1124  if (system->m_keycode_last_repeat_key == vk) {
1125  is_repeat = true;
1126  }
1127  system->m_keycode_last_repeat_key = vk;
1128  }
1129  else {
1130  if (system->m_keycode_last_repeat_key == vk) {
1131  system->m_keycode_last_repeat_key = 0;
1132  }
1133  }
1134 
1135  wchar_t utf16[3] = {0};
1136  BYTE state[256] = {0};
1137  int r;
1138  GetKeyboardState((PBYTE)state);
1139  bool ctrl_pressed = state[VK_CONTROL] & 0x80;
1140  bool alt_pressed = state[VK_MENU] & 0x80;
1141 
1142  /* No text with control key pressed (Alt can be used to insert special characters though!). */
1143  if (ctrl_pressed && !alt_pressed) {
1144  utf8_char[0] = '\0';
1145  }
1146  // Don't call ToUnicodeEx on dead keys as it clears the buffer and so won't allow diacritical
1147  // composition.
1148  else if (MapVirtualKeyW(vk, 2) != 0) {
1149  // todo: ToUnicodeEx can respond with up to 4 utf16 chars (only 2 here).
1150  // Could be up to 24 utf8 bytes.
1151  if ((r = ToUnicodeEx(
1152  vk, raw.data.keyboard.MakeCode, state, utf16, 2, 0, system->m_keylayout))) {
1153  if ((r > 0 && r < 3)) {
1154  utf16[r] = 0;
1155  conv_utf_16_to_8(utf16, utf8_char, 6);
1156  }
1157  else if (r == -1) {
1158  utf8_char[0] = '\0';
1159  }
1160  }
1161  }
1162 
1163  if (!keyDown) {
1164  utf8_char[0] = '\0';
1165  ascii = '\0';
1166  }
1167  else {
1168  ascii = utf8_char[0] & 0x80 ? '?' : utf8_char[0];
1169  }
1170 
1171  event = new GHOST_EventKey(system->getMilliSeconds(),
1173  window,
1174  key,
1175  ascii,
1176  utf8_char,
1177  is_repeat);
1178 
1179  // GHOST_PRINTF("%c\n", ascii); // we already get this info via EventPrinter
1180  }
1181  else {
1182  event = NULL;
1183  }
1184 
1185  return event;
1186 }
1187 
1189  GHOST_WindowWin32 *window)
1190 {
1192 
1194  system->getWindowManager()->setActiveWindow(window);
1195  window->bringTabletContextToFront();
1196  }
1197 
1198  return new GHOST_Event(system->getMilliSeconds(), type, window);
1199 }
1200 
1201 #ifdef WITH_INPUT_IME
1202 GHOST_Event *GHOST_SystemWin32::processImeEvent(GHOST_TEventType type,
1203  GHOST_WindowWin32 *window,
1205 {
1207  return new GHOST_EventIME(system->getMilliSeconds(), type, window, data);
1208 }
1209 #endif
1210 
1212  GHOST_TDragnDropTypes draggedObjectType,
1213  GHOST_WindowWin32 *window,
1214  int mouseX,
1215  int mouseY,
1216  void *data)
1217 {
1219  return system->pushEvent(new GHOST_EventDragnDrop(
1220  system->getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, data));
1221 }
1222 
1224 {
1225  minmax->ptMinTrackSize.x = 320;
1226  minmax->ptMinTrackSize.y = 240;
1227 }
1228 
1229 #ifdef WITH_INPUT_NDOF
1230 bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw)
1231 {
1232  bool eventSent = false;
1233  GHOST_TUns64 now = getMilliSeconds();
1234 
1235  static bool firstEvent = true;
1236  if (firstEvent) { // determine exactly which device is plugged in
1237  RID_DEVICE_INFO info;
1238  unsigned infoSize = sizeof(RID_DEVICE_INFO);
1239  info.cbSize = infoSize;
1240 
1241  GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize);
1242  if (info.dwType == RIM_TYPEHID)
1243  m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId);
1244  else
1245  GHOST_PRINT("<!> not a HID device... mouse/kb perhaps?\n");
1246 
1247  firstEvent = false;
1248  }
1249 
1250  // The NDOF manager sends button changes immediately, and *pretends* to
1251  // send motion. Mark as 'sent' so motion will always get dispatched.
1252  eventSent = true;
1253 
1254  BYTE const *data = raw.data.hid.bRawData;
1255 
1256  BYTE packetType = data[0];
1257  switch (packetType) {
1258  case 1: // translation
1259  {
1260  const short *axis = (short *)(data + 1);
1261  // massage into blender view coords (same goes for rotation)
1262  const int t[3] = {axis[0], -axis[2], axis[1]};
1263  m_ndofManager->updateTranslation(t, now);
1264 
1265  if (raw.data.hid.dwSizeHid == 13) {
1266  // this report also includes rotation
1267  const int r[3] = {-axis[3], axis[5], -axis[4]};
1268  m_ndofManager->updateRotation(r, now);
1269 
1270  // I've never gotten one of these, has anyone else?
1271  GHOST_PRINT("ndof: combined T + R\n");
1272  }
1273  break;
1274  }
1275  case 2: // rotation
1276  {
1277  const short *axis = (short *)(data + 1);
1278  const int r[3] = {-axis[0], axis[2], -axis[1]};
1279  m_ndofManager->updateRotation(r, now);
1280  break;
1281  }
1282  case 3: // buttons
1283  {
1284  int button_bits;
1285  memcpy(&button_bits, data + 1, sizeof(button_bits));
1286  m_ndofManager->updateButtons(button_bits, now);
1287  break;
1288  }
1289  }
1290  return eventSent;
1291 }
1292 #endif // WITH_INPUT_NDOF
1293 
1294 LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1295 {
1296  GHOST_Event *event = NULL;
1297  bool eventHandled = false;
1298 
1299  LRESULT lResult = 0;
1301 #ifdef WITH_INPUT_IME
1302  GHOST_EventManager *eventManager = system->getEventManager();
1303 #endif
1304  GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized");
1305 
1306  if (hwnd) {
1307 
1308  if (msg == WM_NCCREATE) {
1309  // Tell Windows to automatically handle scaling of non-client areas
1310  // such as the caption bar. EnableNonClientDpiScaling was introduced in Windows 10
1311  HMODULE m_user32 = ::LoadLibrary("User32.dll");
1312  if (m_user32) {
1313  GHOST_WIN32_EnableNonClientDpiScaling fpEnableNonClientDpiScaling =
1314  (GHOST_WIN32_EnableNonClientDpiScaling)::GetProcAddress(m_user32,
1315  "EnableNonClientDpiScaling");
1316  if (fpEnableNonClientDpiScaling) {
1317  fpEnableNonClientDpiScaling(hwnd);
1318  }
1319  }
1320  }
1321 
1322  GHOST_WindowWin32 *window = (GHOST_WindowWin32 *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
1323  if (window) {
1324  switch (msg) {
1325  // we need to check if new key layout has AltGr
1326  case WM_INPUTLANGCHANGE: {
1327  system->handleKeyboardChange();
1328 #ifdef WITH_INPUT_IME
1329  window->getImeInput()->SetInputLanguage();
1330 #endif
1331  break;
1332  }
1334  // Keyboard events, processed
1336  case WM_INPUT: {
1337  RAWINPUT raw;
1338  RAWINPUT *raw_ptr = &raw;
1339  UINT rawSize = sizeof(RAWINPUT);
1340 
1341  GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER));
1342 
1343  switch (raw.header.dwType) {
1344  case RIM_TYPEKEYBOARD:
1345  event = processKeyEvent(window, raw);
1346  if (!event) {
1347  GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ");
1348  GHOST_PRINT(msg);
1349  GHOST_PRINT(" key ignored\n");
1350  }
1351  break;
1352 #ifdef WITH_INPUT_NDOF
1353  case RIM_TYPEHID:
1354  if (system->processNDOF(raw)) {
1355  eventHandled = true;
1356  }
1357  break;
1358 #endif
1359  }
1360  break;
1361  }
1362 #ifdef WITH_INPUT_IME
1364  // IME events, processed, read more in GHOST_IME.h
1366  case WM_IME_SETCONTEXT: {
1367  GHOST_ImeWin32 *ime = window->getImeInput();
1368  ime->SetInputLanguage();
1369  ime->CreateImeWindow(hwnd);
1370  ime->CleanupComposition(hwnd);
1371  ime->CheckFirst(hwnd);
1372  break;
1373  }
1374  case WM_IME_STARTCOMPOSITION: {
1375  GHOST_ImeWin32 *ime = window->getImeInput();
1376  eventHandled = true;
1377  /* remove input event before start comp event, avoid redundant input */
1378  eventManager->removeTypeEvents(GHOST_kEventKeyDown, window);
1379  ime->CreateImeWindow(hwnd);
1380  ime->ResetComposition(hwnd);
1381  event = processImeEvent(GHOST_kEventImeCompositionStart, window, &ime->eventImeData);
1382  break;
1383  }
1384  case WM_IME_COMPOSITION: {
1385  GHOST_ImeWin32 *ime = window->getImeInput();
1386  eventHandled = true;
1387  ime->UpdateImeWindow(hwnd);
1388  ime->UpdateInfo(hwnd);
1389  if (ime->eventImeData.result_len) {
1390  /* remove redundant IME event */
1391  eventManager->removeTypeEvents(GHOST_kEventImeComposition, window);
1392  }
1393  event = processImeEvent(GHOST_kEventImeComposition, window, &ime->eventImeData);
1394  break;
1395  }
1396  case WM_IME_ENDCOMPOSITION: {
1397  GHOST_ImeWin32 *ime = window->getImeInput();
1398  eventHandled = true;
1399  /* remove input event after end comp event, avoid redundant input */
1400  eventManager->removeTypeEvents(GHOST_kEventKeyDown, window);
1401  ime->ResetComposition(hwnd);
1402  ime->DestroyImeWindow(hwnd);
1403  event = processImeEvent(GHOST_kEventImeCompositionEnd, window, &ime->eventImeData);
1404  break;
1405  }
1406 #endif /* WITH_INPUT_IME */
1408  // Keyboard events, ignored
1410  case WM_KEYDOWN:
1411  case WM_SYSKEYDOWN:
1412  case WM_KEYUP:
1413  case WM_SYSKEYUP:
1414  /* These functions were replaced by WM_INPUT*/
1415  case WM_CHAR:
1416  /* The WM_CHAR message is posted to the window with the keyboard focus when
1417  * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR
1418  * contains the character code of the key that was pressed.
1419  */
1420  case WM_DEADCHAR:
1421  /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a
1422  * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR
1423  * specifies a character code generated by a dead key. A dead key is a key that
1424  * generates a character, such as the umlaut (double-dot), that is combined with
1425  * another character to form a composite character. For example, the umlaut-O
1426  * character (Ö) is generated by typing the dead key for the umlaut character, and
1427  * then typing the O key.
1428  */
1429  break;
1430  case WM_SYSDEADCHAR:
1431  /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when
1432  * a WM_SYSKEYDOWN message is translated by the TranslateMessage function.
1433  * WM_SYSDEADCHAR specifies the character code of a system dead key - that is,
1434  * a dead key that is pressed while holding down the alt key.
1435  */
1436  case WM_SYSCHAR:
1437  /* The WM_SYSCHAR message is sent to the window with the keyboard focus when
1438  * a WM_SYSCHAR message is translated by the TranslateMessage function.
1439  * WM_SYSCHAR specifies the character code of a dead key - that is,
1440  * a dead key that is pressed while holding down the alt key.
1441  * To prevent the sound, DefWindowProc must be avoided by return
1442  */
1443  break;
1444  case WM_SYSCOMMAND:
1445  /* The WM_SYSCOMMAND message is sent to the window when system commands such as
1446  * maximize, minimize or close the window are triggered. Also it is sent when ALT
1447  * button is press for menu. To prevent this we must return preventing DefWindowProc.
1448  *
1449  * Note that the four low-order bits of the wParam parameter are used internally by the
1450  * OS. To obtain the correct result when testing the value of wParam, an application
1451  * must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator.
1452  */
1453  switch (wParam & 0xFFF0) {
1454  case SC_KEYMENU:
1455  eventHandled = true;
1456  break;
1457  case SC_RESTORE:
1458  ::ShowWindow(hwnd, SW_RESTORE);
1459  window->setState(window->getState());
1460  eventHandled = true;
1461  break;
1462  }
1463  break;
1465  // Wintab events, processed
1467  case WT_PACKET:
1468  window->processWin32TabletEvent(wParam, lParam);
1469  break;
1470  case WT_CSRCHANGE:
1471  case WT_PROXIMITY:
1472  window->processWin32TabletInitEvent();
1473  break;
1475  // Pointer events, processed
1477  case WM_POINTERENTER:
1478  case WM_POINTERDOWN:
1479  case WM_POINTERUPDATE:
1480  case WM_POINTERUP:
1481  case WM_POINTERLEAVE:
1482  processPointerEvent(msg, window, wParam, lParam, eventHandled);
1483  break;
1485  // Mouse events, processed
1487  case WM_LBUTTONDOWN:
1489  break;
1490  case WM_MBUTTONDOWN:
1492  break;
1493  case WM_RBUTTONDOWN:
1495  break;
1496  case WM_XBUTTONDOWN:
1497  if ((short)HIWORD(wParam) == XBUTTON1) {
1499  }
1500  else if ((short)HIWORD(wParam) == XBUTTON2) {
1502  }
1503  break;
1504  case WM_LBUTTONUP:
1506  break;
1507  case WM_MBUTTONUP:
1509  break;
1510  case WM_RBUTTONUP:
1512  break;
1513  case WM_XBUTTONUP:
1514  if ((short)HIWORD(wParam) == XBUTTON1) {
1516  }
1517  else if ((short)HIWORD(wParam) == XBUTTON2) {
1519  }
1520  break;
1521  case WM_MOUSEMOVE:
1522  event = processCursorEvent(window);
1523  break;
1524  case WM_MOUSEWHEEL: {
1525  /* The WM_MOUSEWHEEL message is sent to the focus window
1526  * when the mouse wheel is rotated. The DefWindowProc
1527  * function propagates the message to the window's parent.
1528  * There should be no internal forwarding of the message,
1529  * since DefWindowProc propagates it up the parent chain
1530  * until it finds a window that processes it.
1531  */
1532 
1533  /* Get the window under the mouse and send event to its queue. */
1534  POINT mouse_pos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
1535  HWND mouse_hwnd = ChildWindowFromPoint(HWND_DESKTOP, mouse_pos);
1536  GHOST_WindowWin32 *mouse_window = (GHOST_WindowWin32 *)::GetWindowLongPtr(mouse_hwnd,
1537  GWLP_USERDATA);
1538 
1539  processWheelEvent(mouse_window ? mouse_window : window, wParam, lParam);
1540  eventHandled = true;
1541 #ifdef BROKEN_PEEK_TOUCHPAD
1542  PostMessage(hwnd, WM_USER, 0, 0);
1543 #endif
1544  break;
1545  }
1546  case WM_SETCURSOR:
1547  /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor
1548  * to move within a window and mouse input is not captured.
1549  * This means we have to set the cursor shape every time the mouse moves!
1550  * The DefWindowProc function uses this message to set the cursor to an
1551  * arrow if it is not in the client area.
1552  */
1553  if (LOWORD(lParam) == HTCLIENT) {
1554  // Load the current cursor
1555  window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
1556  // Bypass call to DefWindowProc
1557  return 0;
1558  }
1559  else {
1560  // Outside of client area show standard cursor
1562  }
1563  break;
1564 
1566  // Mouse events, ignored
1568  case WM_NCMOUSEMOVE:
1569  /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved
1570  * within the non-client area of the window. This message is posted to the window that
1571  * contains the cursor. If a window has captured the mouse, this message is not posted.
1572  */
1573  case WM_NCHITTEST:
1574  /* The WM_NCHITTEST message is sent to a window when the cursor moves, or
1575  * when a mouse button is pressed or released. If the mouse is not captured,
1576  * the message is sent to the window beneath the cursor. Otherwise, the message
1577  * is sent to the window that has captured the mouse.
1578  */
1579  break;
1580 
1582  // Window events, processed
1584  case WM_CLOSE:
1585  /* The WM_CLOSE message is sent as a signal that a window
1586  * or an application should terminate. Restore if minimized. */
1587  if (IsIconic(hwnd)) {
1588  ShowWindow(hwnd, SW_RESTORE);
1589  }
1591  break;
1592  case WM_ACTIVATE:
1593  /* The WM_ACTIVATE message is sent to both the window being activated and the window
1594  * being deactivated. If the windows use the same input queue, the message is sent
1595  * synchronously, first to the window procedure of the top-level window being
1596  * deactivated, then to the window procedure of the top-level window being activated.
1597  * If the windows use different input queues, the message is sent asynchronously,
1598  * so the window is activated immediately. */
1599  {
1600  GHOST_ModifierKeys modifiers;
1601  modifiers.clear();
1602  system->storeModifierKeys(modifiers);
1603  system->m_wheelDeltaAccum = 0;
1604  system->m_keycode_last_repeat_key = 0;
1605  event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate :
1607  window);
1608  /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
1609  * will not be dispatched to OUR active window if we minimize one of OUR windows. */
1610  if (LOWORD(wParam) == WA_INACTIVE)
1611  window->lostMouseCapture();
1612  window->processWin32TabletActivateEvent(GET_WM_ACTIVATE_STATE(wParam, lParam));
1613  lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
1614  break;
1615  }
1616  case WM_ENTERSIZEMOVE:
1617  /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving
1618  * or sizing modal loop. The window enters the moving or sizing modal loop when the user
1619  * clicks the window's title bar or sizing border, or when the window passes the
1620  * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the
1621  * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when
1622  * DefWindowProc returns.
1623  */
1624  window->m_inLiveResize = 1;
1625  break;
1626  case WM_EXITSIZEMOVE:
1627  window->m_inLiveResize = 0;
1628  break;
1629  case WM_PAINT:
1630  /* An application sends the WM_PAINT message when the system or another application
1631  * makes a request to paint a portion of an application's window. The message is sent
1632  * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage
1633  * function when the application obtains a WM_PAINT message by using the GetMessage or
1634  * PeekMessage function.
1635  */
1636  if (!window->m_inLiveResize) {
1638  ::ValidateRect(hwnd, NULL);
1639  }
1640  else {
1641  eventHandled = true;
1642  }
1643  break;
1644  case WM_GETMINMAXINFO:
1645  /* The WM_GETMINMAXINFO message is sent to a window when the size or
1646  * position of the window is about to change. An application can use
1647  * this message to override the window's default maximized size and
1648  * position, or its default minimum or maximum tracking size.
1649  */
1650  processMinMaxInfo((MINMAXINFO *)lParam);
1651  /* Let DefWindowProc handle it. */
1652  break;
1653  case WM_SIZING:
1654  case WM_SIZE:
1655  /* The WM_SIZE message is sent to a window after its size has changed.
1656  * The WM_SIZE and WM_MOVE messages are not sent if an application handles the
1657  * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
1658  * to perform any move or size change processing during the WM_WINDOWPOSCHANGED
1659  * message without calling DefWindowProc.
1660  */
1661  /* we get first WM_SIZE before we fully init.
1662  * So, do not dispatch before we continuously resizing. */
1663  if (window->m_inLiveResize) {
1665  system->dispatchEvents();
1666  }
1667  else {
1668  event = processWindowEvent(GHOST_kEventWindowSize, window);
1669  }
1670  break;
1671  case WM_CAPTURECHANGED:
1672  window->lostMouseCapture();
1673  break;
1674  case WM_MOVING:
1675  /* The WM_MOVING message is sent to a window that the user is moving. By processing
1676  * this message, an application can monitor the size and position of the drag rectangle
1677  * and, if needed, change its size or position.
1678  */
1679  case WM_MOVE:
1680  /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the
1681  * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
1682  * to perform any move or size change processing during the WM_WINDOWPOSCHANGED
1683  * message without calling DefWindowProc.
1684  */
1685  /* see WM_SIZE comment*/
1686  if (window->m_inLiveResize) {
1688  system->dispatchEvents();
1689  }
1690  else {
1691  event = processWindowEvent(GHOST_kEventWindowMove, window);
1692  }
1693 
1694  break;
1695  case WM_DPICHANGED:
1696  /* The WM_DPICHANGED message is sent when the effective dots per inch (dpi) for a
1697  * window has changed. The DPI is the scale factor for a window. There are multiple
1698  * events that can cause the DPI to change such as when the window is moved to a monitor
1699  * with a different DPI.
1700  */
1701  {
1702  // The suggested new size and position of the window.
1703  RECT *const suggestedWindowRect = (RECT *)lParam;
1704 
1705  // Push DPI change event first
1707  system->dispatchEvents();
1708  eventHandled = true;
1709 
1710  // Then move and resize window
1711  SetWindowPos(hwnd,
1712  NULL,
1713  suggestedWindowRect->left,
1714  suggestedWindowRect->top,
1715  suggestedWindowRect->right - suggestedWindowRect->left,
1716  suggestedWindowRect->bottom - suggestedWindowRect->top,
1717  SWP_NOZORDER | SWP_NOACTIVATE);
1718  }
1719  break;
1721  // Window events, ignored
1723  case WM_WINDOWPOSCHANGED:
1724  /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place
1725  * in the Z order has changed as a result of a call to the SetWindowPos function or
1726  * another window-management function.
1727  * The WM_SIZE and WM_MOVE messages are not sent if an application handles the
1728  * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
1729  * to perform any move or size change processing during the WM_WINDOWPOSCHANGED
1730  * message without calling DefWindowProc.
1731  */
1732  case WM_ERASEBKGND:
1733  /* An application sends the WM_ERASEBKGND message when the window background must be
1734  * erased (for example, when a window is resized). The message is sent to prepare an
1735  * invalidated portion of a window for painting.
1736  */
1737  case WM_NCPAINT:
1738  /* An application sends the WM_NCPAINT message to a window
1739  * when its frame must be painted. */
1740  case WM_NCACTIVATE:
1741  /* The WM_NCACTIVATE message is sent to a window when its non-client area needs to be
1742  * changed to indicate an active or inactive state. */
1743  case WM_DESTROY:
1744  /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the
1745  * window procedure of the window being destroyed after the window is removed from the
1746  * screen. This message is sent first to the window being destroyed and then to the child
1747  * windows (if any) as they are destroyed. During the processing of the message, it can
1748  * be assumed that all child windows still exist. */
1749  case WM_NCDESTROY:
1750  /* The WM_NCDESTROY message informs a window that its non-client area is being
1751  * destroyed. The DestroyWindow function sends the WM_NCDESTROY message to the window
1752  * following the WM_DESTROY message. WM_DESTROY is used to free the allocated memory
1753  * object associated with the window.
1754  */
1755  break;
1756  case WM_KILLFOCUS:
1757  /* The WM_KILLFOCUS message is sent to a window immediately before it loses the
1758  * keyboard focus. We want to prevent this if a window is still active and it loses
1759  * focus to nowhere. */
1760  if (!wParam && hwnd == ::GetActiveWindow())
1761  ::SetFocus(hwnd);
1762  case WM_SHOWWINDOW:
1763  /* The WM_SHOWWINDOW message is sent to a window when the window is
1764  * about to be hidden or shown. */
1765  case WM_WINDOWPOSCHANGING:
1766  /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in
1767  * the Z order is about to change as a result of a call to the SetWindowPos function or
1768  * another window-management function.
1769  */
1770  case WM_SETFOCUS:
1771  /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */
1772  break;
1774  // Other events
1776  case WM_GETTEXT:
1777  /* An application sends a WM_GETTEXT message to copy the text that
1778  * corresponds to a window into a buffer provided by the caller.
1779  */
1780  case WM_ACTIVATEAPP:
1781  /* The WM_ACTIVATEAPP message is sent when a window belonging to a
1782  * different application than the active window is about to be activated.
1783  * The message is sent to the application whose window is being activated
1784  * and to the application whose window is being deactivated.
1785  */
1786  case WM_TIMER:
1787  /* The WIN32 docs say:
1788  * The WM_TIMER message is posted to the installing thread's message queue
1789  * when a timer expires. You can process the message by providing a WM_TIMER
1790  * case in the window procedure. Otherwise, the default window procedure will
1791  * call the TimerProc callback function specified in the call to the SetTimer
1792  * function used to install the timer.
1793  *
1794  * In GHOST, we let DefWindowProc call the timer callback.
1795  */
1796  break;
1797  }
1798  }
1799  else {
1800  // Event found for a window before the pointer to the class has been set.
1801  GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n");
1802  /* These are events we typically miss at this point:
1803  * WM_GETMINMAXINFO 0x24
1804  * WM_NCCREATE 0x81
1805  * WM_NCCALCSIZE 0x83
1806  * WM_CREATE 0x01
1807  * We let DefWindowProc do the work.
1808  */
1809  }
1810  }
1811  else {
1812  // Events without valid hwnd
1813  GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n");
1814  }
1815 
1816  if (event) {
1817  system->pushEvent(event);
1818  eventHandled = true;
1819  }
1820 
1821  if (!eventHandled)
1822  lResult = ::DefWindowProcW(hwnd, msg, wParam, lParam);
1823 
1824  return lResult;
1825 }
1826 
1828 {
1829  char *temp_buff;
1830 
1831  if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL)) {
1832  wchar_t *buffer;
1833  HANDLE hData = GetClipboardData(CF_UNICODETEXT);
1834  if (hData == NULL) {
1835  CloseClipboard();
1836  return NULL;
1837  }
1838  buffer = (wchar_t *)GlobalLock(hData);
1839  if (!buffer) {
1840  CloseClipboard();
1841  return NULL;
1842  }
1843 
1844  temp_buff = alloc_utf_8_from_16(buffer, 0);
1845 
1846  /* Buffer mustn't be accessed after CloseClipboard
1847  * it would like accessing free-d memory */
1848  GlobalUnlock(hData);
1849  CloseClipboard();
1850 
1851  return (GHOST_TUns8 *)temp_buff;
1852  }
1853  else if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL)) {
1854  char *buffer;
1855  size_t len = 0;
1856  HANDLE hData = GetClipboardData(CF_TEXT);
1857  if (hData == NULL) {
1858  CloseClipboard();
1859  return NULL;
1860  }
1861  buffer = (char *)GlobalLock(hData);
1862  if (!buffer) {
1863  CloseClipboard();
1864  return NULL;
1865  }
1866 
1867  len = strlen(buffer);
1868  temp_buff = (char *)malloc(len + 1);
1869  strncpy(temp_buff, buffer, len);
1870  temp_buff[len] = '\0';
1871 
1872  /* Buffer mustn't be accessed after CloseClipboard
1873  * it would like accessing free-d memory */
1874  GlobalUnlock(hData);
1875  CloseClipboard();
1876 
1877  return (GHOST_TUns8 *)temp_buff;
1878  }
1879  else {
1880  return NULL;
1881  }
1882 }
1883 
1885 {
1886  if (selection) {
1887  return;
1888  } // for copying the selection, used on X11
1889 
1890  if (OpenClipboard(NULL)) {
1891  HLOCAL clipbuffer;
1892  wchar_t *data;
1893 
1894  if (buffer) {
1895  size_t len = count_utf_16_from_8(buffer);
1896  EmptyClipboard();
1897 
1898  clipbuffer = LocalAlloc(LMEM_FIXED, sizeof(wchar_t) * len);
1899  data = (wchar_t *)GlobalLock(clipbuffer);
1900 
1902 
1903  LocalUnlock(clipbuffer);
1904  SetClipboardData(CF_UNICODETEXT, clipbuffer);
1905  }
1906  CloseClipboard();
1907  }
1908  else {
1909  return;
1910  }
1911 }
1912 
1913 /* -------------------------------------------------------------------- */
1918  const char *message,
1919  const char *help_label,
1920  const char *continue_label,
1921  const char *link,
1922  GHOST_DialogOptions dialog_options) const
1923 {
1924  const wchar_t *title_16 = alloc_utf16_from_8(title, 0);
1925  const wchar_t *message_16 = alloc_utf16_from_8(message, 0);
1926  const wchar_t *help_label_16 = alloc_utf16_from_8(help_label, 0);
1927  const wchar_t *continue_label_16 = alloc_utf16_from_8(continue_label, 0);
1928 
1929  int nButtonPressed = 0;
1930  TASKDIALOGCONFIG config = {0};
1931  const TASKDIALOG_BUTTON buttons[] = {{IDOK, help_label_16}, {IDCONTINUE, continue_label_16}};
1932 
1933  config.cbSize = sizeof(config);
1934  config.hInstance = 0;
1935  config.dwCommonButtons = 0;
1936  config.pszMainIcon = (dialog_options & GHOST_DialogError ?
1937  TD_ERROR_ICON :
1938  dialog_options & GHOST_DialogWarning ? TD_WARNING_ICON :
1939  TD_INFORMATION_ICON);
1940  config.pszWindowTitle = L"Blender";
1941  config.pszMainInstruction = title_16;
1942  config.pszContent = message_16;
1943  config.pButtons = (link) ? buttons : buttons + 1;
1944  config.cButtons = (link) ? 2 : 1;
1945 
1946  TaskDialogIndirect(&config, &nButtonPressed, NULL, NULL);
1947  switch (nButtonPressed) {
1948  case IDOK:
1949  ShellExecute(NULL, "open", link, NULL, NULL, SW_SHOWNORMAL);
1950  break;
1951  case IDCONTINUE:
1952  break;
1953  default:
1954  break; // should never happen
1955  }
1956 
1957  free((void *)title_16);
1958  free((void *)message_16);
1959  free((void *)help_label_16);
1960  free((void *)continue_label_16);
1961 
1962  return GHOST_kSuccess;
1963 }
1964 
1967 static DWORD GetParentProcessID(void)
1968 {
1969  HANDLE snapshot;
1970  PROCESSENTRY32 pe32 = {0};
1971  DWORD ppid = 0, pid = GetCurrentProcessId();
1972  snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1973  if (snapshot == INVALID_HANDLE_VALUE) {
1974  return -1;
1975  }
1976  pe32.dwSize = sizeof(pe32);
1977  if (!Process32First(snapshot, &pe32)) {
1978  CloseHandle(snapshot);
1979  return -1;
1980  }
1981  do {
1982  if (pe32.th32ProcessID == pid) {
1983  ppid = pe32.th32ParentProcessID;
1984  break;
1985  }
1986  } while (Process32Next(snapshot, &pe32));
1987  CloseHandle(snapshot);
1988  return ppid;
1989 }
1990 
1991 static bool getProcessName(int pid, char *buffer, int max_len)
1992 {
1993  bool result = false;
1994  HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
1995  if (handle) {
1996  GetModuleFileNameEx(handle, 0, buffer, max_len);
1997  result = true;
1998  }
1999  CloseHandle(handle);
2000  return result;
2001 }
2002 
2004 {
2005  HWND hwnd = GetConsoleWindow();
2006 
2007  if (hwnd) {
2008  DWORD pid = (DWORD)-1;
2009  DWORD ppid = GetParentProcessID();
2010  char parent_name[MAX_PATH];
2011  bool start_from_launcher = false;
2012 
2013  GetWindowThreadProcessId(hwnd, &pid);
2014  if (getProcessName(ppid, parent_name, sizeof(parent_name))) {
2015  char *filename = strrchr(parent_name, '\\');
2016  if (filename != NULL) {
2017  start_from_launcher = strstr(filename, "blender.exe") != NULL;
2018  }
2019  }
2020 
2021  /* When we're starting from a wrapper we need to compare with parent process ID. */
2022  if (pid != (start_from_launcher ? ppid : GetCurrentProcessId()))
2023  return true;
2024  }
2025 
2026  return false;
2027 }
2028 
2030 {
2031  HWND wnd = GetConsoleWindow();
2032 
2033  switch (action) {
2034  case 3: // startup: hide if not started from command prompt
2035  {
2036  if (!isStartedFromCommandPrompt()) {
2037  ShowWindow(wnd, SW_HIDE);
2038  m_consoleStatus = 0;
2039  }
2040  break;
2041  }
2042  case 0: // hide
2043  ShowWindow(wnd, SW_HIDE);
2044  m_consoleStatus = 0;
2045  break;
2046  case 1: // show
2047  ShowWindow(wnd, SW_SHOW);
2048  if (!isStartedFromCommandPrompt()) {
2049  DeleteMenu(GetSystemMenu(wnd, FALSE), SC_CLOSE, MF_BYCOMMAND);
2050  }
2051  m_consoleStatus = 1;
2052  break;
2053  case 2: // toggle
2054  ShowWindow(wnd, m_consoleStatus ? SW_HIDE : SW_SHOW);
2057  DeleteMenu(GetSystemMenu(wnd, FALSE), SC_CLOSE, MF_BYCOMMAND);
2058  }
2059  break;
2060  }
2061 
2062  return m_consoleStatus;
2063 }
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:116
#define FALSE
Definition: GHOST_C-Test.c:33
#define GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY
#define GHOST_PRINTF(x,...)
Definition: GHOST_Debug.h:52
#define GHOST_ASSERT(x, info)
Definition: GHOST_Debug.h:79
#define GHOST_PRINT(x)
Definition: GHOST_Debug.h:51
#define VK_EQUALS
PROCESS_DPI_AWARENESS
@ PROCESS_SYSTEM_DPI_AWARE
@ PROCESS_PER_MONITOR_DPI_AWARE
@ PROCESS_DPI_UNAWARE
static void initRawInput()
#define VK_MEDIA_NEXT_TRACK
#define WM_POINTERUPDATE
#define DEVICE_COUNT
#define VK_BACK_QUOTE
#define WM_POINTERLEAVE
#define VK_CLOSE_BRACKET
HRESULT(API * GHOST_WIN32_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS)
#define VK_SEMICOLON
#define VK_COMMA
#define VK_SLASH
#define WM_DPICHANGED
BOOL(API * GHOST_WIN32_EnableNonClientDpiScaling)(HWND)
#define WM_POINTERUP
static bool isStartedFromCommandPrompt()
MONITOR_DPI_TYPE
@ MDT_RAW_DPI
@ MDT_EFFECTIVE_DPI
@ MDT_ANGULAR_DPI
@ MDT_DEFAULT
#define VK_MEDIA_PLAY_PAUSE
#define VK_MEDIA_STOP
#define VK_OPEN_BRACKET
#define VK_BACK_SLASH
#define VK_QUOTE
#define WM_POINTERENTER
#define VK_GR_LESS
#define VK_PERIOD
#define WM_POINTERDOWN
#define VK_MEDIA_PREV_TRACK
static DWORD GetParentProcessID(void)
static bool getProcessName(int pid, char *buffer, int max_len)
#define VK_MINUS
GHOST_TWindowState
Definition: GHOST_Types.h:144
@ GHOST_kStandardCursorDefault
Definition: GHOST_Types.h:224
unsigned int GHOST_TUns32
Definition: GHOST_Types.h:64
unsigned long long GHOST_TUns64
Definition: GHOST_Types.h:86
GHOST_TEventType
Definition: GHOST_Types.h:177
@ GHOST_kEventWindowClose
Definition: GHOST_Types.h:197
@ GHOST_kEventWindowMove
Definition: GHOST_Types.h:202
@ GHOST_kEventWindowSize
Definition: GHOST_Types.h:201
@ GHOST_kEventImeComposition
Definition: GHOST_Types.h:216
@ GHOST_kEventCursorMove
Definition: GHOST_Types.h:180
@ GHOST_kEventButtonUp
Mouse button event.
Definition: GHOST_Types.h:182
@ GHOST_kEventWindowActivate
Definition: GHOST_Types.h:198
@ GHOST_kEventWindowUpdate
Definition: GHOST_Types.h:200
@ GHOST_kEventWindowDeactivate
Definition: GHOST_Types.h:199
@ GHOST_kEventButtonDown
Mouse move event.
Definition: GHOST_Types.h:181
@ GHOST_kEventKeyDown
Trackpad event.
Definition: GHOST_Types.h:191
@ GHOST_kEventImeCompositionStart
Definition: GHOST_Types.h:215
@ GHOST_kEventImeCompositionEnd
Definition: GHOST_Types.h:217
@ GHOST_kEventWindowDPIHintChanged
Definition: GHOST_Types.h:203
@ GHOST_kEventKeyUp
Definition: GHOST_Types.h:192
int GHOST_TInt32
Definition: GHOST_Types.h:63
@ GHOST_glAlphaBackground
Definition: GHOST_Types.h:73
@ GHOST_glStereoVisual
Definition: GHOST_Types.h:71
@ GHOST_glDebugContext
Definition: GHOST_Types.h:72
GHOST_TKey
Definition: GHOST_Types.h:267
@ GHOST_kKeyInsert
Definition: GHOST_Types.h:354
@ GHOST_kKeySemicolon
Definition: GHOST_Types.h:296
@ GHOST_kKeyMediaPlay
Definition: GHOST_Types.h:406
@ GHOST_kKeyQuote
Definition: GHOST_Types.h:277
@ GHOST_kKeyNumpad3
Definition: GHOST_Types.h:365
@ GHOST_kKeyAccentGrave
Definition: GHOST_Types.h:330
@ GHOST_kKeyNumpad1
Definition: GHOST_Types.h:363
@ GHOST_kKeyLeftAlt
Definition: GHOST_Types.h:336
@ GHOST_kKeyRightShift
Definition: GHOST_Types.h:333
@ GHOST_kKeyNumLock
Definition: GHOST_Types.h:343
@ GHOST_kKeyEnter
Definition: GHOST_Types.h:273
@ GHOST_kKeyNumpadSlash
Definition: GHOST_Types.h:377
@ GHOST_kKeyRightArrow
Definition: GHOST_Types.h:347
@ GHOST_kKeyF13
Definition: GHOST_Types.h:392
@ GHOST_kKeyNumpad4
Definition: GHOST_Types.h:366
@ GHOST_kKeyPause
Definition: GHOST_Types.h:352
@ GHOST_kKeyCapsLock
Definition: GHOST_Types.h:342
@ GHOST_kKeyApp
Definition: GHOST_Types.h:340
@ GHOST_kKeyMinus
Definition: GHOST_Types.h:279
@ GHOST_kKeyMediaStop
Definition: GHOST_Types.h:407
@ GHOST_kKeyBackSpace
Definition: GHOST_Types.h:269
@ GHOST_kKey0
Definition: GHOST_Types.h:285
@ GHOST_kKeyDownPage
Definition: GHOST_Types.h:359
@ GHOST_kKeyGrLess
Definition: GHOST_Types.h:339
@ GHOST_kKeyDownArrow
Definition: GHOST_Types.h:349
@ GHOST_kKeyNumpadPeriod
Definition: GHOST_Types.h:372
@ GHOST_kKeyF1
Definition: GHOST_Types.h:380
@ GHOST_kKeyNumpadAsterisk
Definition: GHOST_Types.h:376
@ GHOST_kKeyPrintScreen
Definition: GHOST_Types.h:351
@ GHOST_kKeyLeftControl
Definition: GHOST_Types.h:334
@ GHOST_kKeyLeftBracket
Definition: GHOST_Types.h:327
@ GHOST_kKeyTab
Definition: GHOST_Types.h:270
@ GHOST_kKeyComma
Definition: GHOST_Types.h:278
@ GHOST_kKeyRightBracket
Definition: GHOST_Types.h:328
@ GHOST_kKeyBackslash
Definition: GHOST_Types.h:329
@ GHOST_kKeyOS
Definition: GHOST_Types.h:338
@ GHOST_kKeyNumpad2
Definition: GHOST_Types.h:364
@ GHOST_kKeyRightAlt
Definition: GHOST_Types.h:337
@ GHOST_kKeyPeriod
Definition: GHOST_Types.h:281
@ GHOST_kKeyNumpadPlus
Definition: GHOST_Types.h:374
@ GHOST_kKeyUpPage
Definition: GHOST_Types.h:358
@ GHOST_kKeyNumpad5
Definition: GHOST_Types.h:367
@ GHOST_kKeyLeftArrow
Definition: GHOST_Types.h:346
@ GHOST_kKeyEqual
Definition: GHOST_Types.h:297
@ GHOST_kKeyHome
Definition: GHOST_Types.h:356
@ GHOST_kKeyNumpad6
Definition: GHOST_Types.h:368
@ GHOST_kKeyNumpad8
Definition: GHOST_Types.h:370
@ GHOST_kKeyNumpad9
Definition: GHOST_Types.h:371
@ GHOST_kKeyEnd
Definition: GHOST_Types.h:357
@ GHOST_kKeyUpArrow
Definition: GHOST_Types.h:348
@ GHOST_kKeyDelete
Definition: GHOST_Types.h:355
@ GHOST_kKeyNumpad0
Definition: GHOST_Types.h:362
@ GHOST_kKeyA
Definition: GHOST_Types.h:300
@ GHOST_kKeyMediaFirst
Definition: GHOST_Types.h:408
@ GHOST_kKeyNumpad7
Definition: GHOST_Types.h:369
@ GHOST_kKeyRightControl
Definition: GHOST_Types.h:335
@ GHOST_kKeyEsc
Definition: GHOST_Types.h:275
@ GHOST_kKeyUnknown
Definition: GHOST_Types.h:268
@ GHOST_kKeyScrollLock
Definition: GHOST_Types.h:344
@ GHOST_kKeySlash
Definition: GHOST_Types.h:282
@ GHOST_kKeyNumpadEnter
Definition: GHOST_Types.h:373
@ GHOST_kKeyNumpadMinus
Definition: GHOST_Types.h:375
@ GHOST_kKeyLeftShift
Definition: GHOST_Types.h:332
@ GHOST_kKeyMediaLast
Definition: GHOST_Types.h:409
@ GHOST_kKeySpace
Definition: GHOST_Types.h:276
GHOST_TDrawingContextType
Definition: GHOST_Types.h:156
GHOST_TButtonMask
Definition: GHOST_Types.h:164
@ GHOST_kButtonMaskRight
Definition: GHOST_Types.h:168
@ GHOST_kButtonMaskButton4
Definition: GHOST_Types.h:169
@ GHOST_kButtonMaskLeft
Definition: GHOST_Types.h:166
@ GHOST_kButtonMaskButton5
Definition: GHOST_Types.h:170
@ GHOST_kButtonMaskMiddle
Definition: GHOST_Types.h:167
char GHOST_TInt8
Definition: GHOST_Types.h:59
GHOST_TSuccess
Definition: GHOST_Types.h:91
@ GHOST_kFailure
Definition: GHOST_Types.h:91
@ GHOST_kSuccess
Definition: GHOST_Types.h:91
@ GHOST_kFireTimeNever
Definition: GHOST_Types.h:131
GHOST_TModifierKeyMask
Definition: GHOST_Types.h:133
@ GHOST_kModifierKeyRightControl
Definition: GHOST_Types.h:139
@ GHOST_kModifierKeyLeftControl
Definition: GHOST_Types.h:138
@ GHOST_kModifierKeyRightAlt
Definition: GHOST_Types.h:137
@ GHOST_kModifierKeyOS
Definition: GHOST_Types.h:140
@ GHOST_kModifierKeyRightShift
Definition: GHOST_Types.h:135
@ GHOST_kModifierKeyLeftAlt
Definition: GHOST_Types.h:136
@ GHOST_kModifierKeyLeftShift
Definition: GHOST_Types.h:134
GHOST_TDragnDropTypes
Definition: GHOST_Types.h:477
unsigned char GHOST_TUns8
Definition: GHOST_Types.h:60
@ GHOST_kTabletNative
Definition: GHOST_Types.h:108
long long GHOST_TInt64
Definition: GHOST_Types.h:85
GHOST_DialogOptions
Definition: GHOST_Types.h:76
@ GHOST_DialogError
Definition: GHOST_Types.h:78
@ GHOST_DialogWarning
Definition: GHOST_Types.h:77
typedef UINT
@ MousePressed
@ MouseReleased
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble top
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:299
virtual GHOST_TSuccess initialize(void)
virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const
GHOST_TUns32 getNumEvents()
void removeTypeEvents(GHOST_TEventType type, GHOST_IWindow *window=NULL)
static GHOST_ISystem * getSystem()
GHOST_TUns64 tickCountToMillis(__int64 ticks) const
GHOST_TKey hardKey(RAWINPUT const &raw, bool *r_keyDown, bool *r_is_repeated_modifier)
static void processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam)
GHOST_TUns64 getMilliSeconds() const
GHOST_IContext * createOffscreenContext(GHOST_GLSettings glSettings)
unsigned short m_keycode_last_repeat_key
GHOST_TUns8 * getClipboard(bool selection) const
GHOST_TKey processSpecialKey(short vKey, short scanCode) const
static GHOST_EventButton * processButtonEvent(GHOST_TEventType type, GHOST_WindowWin32 *window, GHOST_TButtonMask mask)
GHOST_TKey convertKey(short vKey, short ScanCode, short extend) const
GHOST_TSuccess init()
int toggleConsole(int action)
void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
GHOST_TUns8 getNumDisplays() const
static GHOST_ContextD3D * createOffscreenContextD3D()
bool processEvents(bool waitForEvent)
static GHOST_TSuccess disposeContextD3D(GHOST_ContextD3D *context)
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const
void retrieveModifierKeys(GHOST_ModifierKeys &keys) const
static GHOST_EventKey * processKeyEvent(GHOST_WindowWin32 *window, RAWINPUT const &raw)
GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const
static void processMinMaxInfo(MINMAXINFO *minmax)
void storeModifierKeys(const GHOST_ModifierKeys &keys)
GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
static GHOST_Event * processWindowEvent(GHOST_TEventType type, GHOST_WindowWin32 *window)
GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const
GHOST_IWindow * createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive=false, const bool is_dialog=false, const GHOST_IWindow *parentWindow=0)
static GHOST_EventCursor * processCursorEvent(GHOST_WindowWin32 *window)
void handleKeyboardChange(void)
static void processPointerEvent(UINT type, GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam, bool &eventhandled)
GHOST_TSuccess disposeContext(GHOST_IContext *context)
void putClipboard(GHOST_TInt8 *buffer, bool selection) const
GHOST_TUns64 performanceCounterToMillis(__int64 perf_ticks) const
GHOST_TSuccess showMessageBox(const char *title, const char *message, const char *help_label, const char *continue_label, const char *link, GHOST_DialogOptions dialog_options) const
static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, GHOST_WindowWin32 *window, int mouseX, int mouseY, void *data)
GHOST_TSuccess exit()
GHOST_EventManager * getEventManager() const
Definition: GHOST_System.h:412
GHOST_WindowManager * getWindowManager() const
Definition: GHOST_System.h:417
virtual GHOST_TSuccess exit()
virtual GHOST_TSuccess init()
GHOST_TimerManager * getTimerManager() const
Definition: GHOST_System.h:407
GHOST_WindowManager * m_windowManager
Definition: GHOST_System.h:383
void dispatchEvents()
GHOST_TSuccess pushEvent(GHOST_IEvent *event)
GHOST_DisplayManager * m_displayManager
Definition: GHOST_System.h:377
GHOST_EventManager * m_eventManager
Definition: GHOST_System.h:386
GHOST_TUns64 nextFireTime()
bool fireTimers(GHOST_TUns64 time)
GHOST_TSuccess addWindow(GHOST_IWindow *window)
GHOST_TSuccess setActiveWindow(GHOST_IWindow *window)
void processWin32TabletActivateEvent(WORD state)
void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const
GHOST_TSuccess getPointerInfo(std::vector< GHOST_PointerInfoWin32 > &outPointerInfo, WPARAM wParam, LPARAM lParam)
const GHOST_TabletData & getTabletData()
void processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
void updateMouseCapture(GHOST_MouseCaptureEventWin32 event)
GHOST_TSuccess setState(GHOST_TWindowState state)
void getClientBounds(GHOST_Rect &bounds) const
GHOST_TWindowState getState() const
bool useTabletAPI(GHOST_TTabletAPI api) const
GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds)
bool getCursorVisibility() const
Definition: GHOST_Window.h:415
GHOST_TAxisFlag getCursorGrabAxis() const
Definition: GHOST_Window.h:430
void setCursorGrabAccum(GHOST_TInt32 x, GHOST_TInt32 y)
Definition: GHOST_Window.h:447
void getCursorGrabAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const
Definition: GHOST_Window.h:441
GHOST_TStandardCursor getCursorShape() const
Definition: GHOST_Window.h:453
bool getCursorGrabModeIsWarp() const
Definition: GHOST_Window.h:425
double time
int count
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
static ulong * next
static ulong state[N]
static int left
#define L
static const VertexNature POINT
Definition: Nature.h:34
Vector< CPUDevice > devices
list of all CPUDevices. for every hardware thread an instance of CPUDevice is created
struct SELECTID_Context context
Definition: select_engine.c:47
void set(GHOST_TButtonMask mask, bool down)
bool get(GHOST_TModifierKeyMask mask) const
void set(GHOST_TModifierKeyMask mask, bool down)
wchar_t * alloc_utf16_from_8(const char *in8, size_t add)
Definition: utfconv.c:296
int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16)
Definition: utfconv.c:189
char * alloc_utf_8_from_16(const wchar_t *in16, size_t add)
Definition: utfconv.c:285
int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8)
Definition: utfconv.c:127
size_t count_utf_16_from_8(const char *string8)
Definition: utfconv.c:70
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
uint len