Blender V4.3
GHOST_WindowWin32.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
10#include "GHOST_ContextD3D.hh"
11#include "GHOST_ContextNone.hh"
13#include "GHOST_SystemWin32.hh"
15#include "utf_winfunc.hh"
16#include "utfconv.hh"
17
18#ifdef WITH_OPENGL_BACKEND
19# include "GHOST_ContextWGL.hh"
20#endif
21#ifdef WITH_VULKAN_BACKEND
22# include "GHOST_ContextVK.hh"
23#endif
24
25#ifdef WIN32
26# include "BLI_path_utils.hh"
27#endif
28
29#include <Dwmapi.h>
30
31#include <assert.h>
32#include <math.h>
33#include <propkey.h>
34#include <propvarutil.h>
35#include <shellapi.h>
36#include <shellscalingapi.h>
37#include <string.h>
38#include <windowsx.h>
39
40#ifndef GET_POINTERID_WPARAM
41# define GET_POINTERID_WPARAM(wParam) (LOWORD(wParam))
42#endif /* GET_POINTERID_WPARAM */
43
44const wchar_t *GHOST_WindowWin32::s_windowClassName = L"GHOST_WindowClass";
45const int GHOST_WindowWin32::s_maxTitleLength = 128;
46
47/* force NVidia OPTIMUS to used dedicated graphics */
48extern "C" {
49__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
50}
51
53 const char *title,
56 uint32_t width,
57 uint32_t height,
60 bool wantStereoVisual,
61 bool alphaBackground,
62 GHOST_WindowWin32 *parentwindow,
63 bool is_debug,
64 bool dialog,
65 const GHOST_GPUDevice &preferred_device)
66 : GHOST_Window(width, height, state, wantStereoVisual, false),
69 m_system(system),
70 m_dropTarget(nullptr),
71 m_hWnd(0),
72 m_hDC(0),
73 m_isDialog(dialog),
74 m_preferred_device(preferred_device),
75 m_hasMouseCaptured(false),
76 m_hasGrabMouse(false),
77 m_nPressedButtons(0),
78 m_customCursor(0),
79 m_wantAlphaBackground(alphaBackground),
80 m_Bar(nullptr),
81 m_wintab(nullptr),
82 m_lastPointerTabletData(GHOST_TABLET_DATA_NONE),
83 m_normal_state(GHOST_kWindowStateNormal),
84 m_user32(::LoadLibrary("user32.dll")),
85 m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : HWND_DESKTOP),
86 m_directManipulationHelper(nullptr),
87 m_debug_context(is_debug)
88{
89 DWORD style = parentwindow ?
90 WS_POPUPWINDOW | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX :
91 WS_OVERLAPPEDWINDOW;
92
94 style |= WS_MAXIMIZE;
95 }
96
97 /* Forces owned windows onto taskbar and allows minimization. */
98 DWORD extended_style = parentwindow ? WS_EX_APPWINDOW : 0;
99
100 if (dialog) {
101 /* When we are ready to make windows of this type:
102 * style = WS_POPUPWINDOW | WS_CAPTION
103 * extended_style = WS_EX_DLGMODALFRAME | WS_EX_TOPMOST
104 */
105 }
106
107 RECT win_rect = {left, top, long(left + width), long(top + height)};
108 adjustWindowRectForClosestMonitor(&win_rect, style, extended_style);
109
110 wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
111 m_hWnd = ::CreateWindowExW(extended_style, /* window extended style */
112 s_windowClassName, /* pointer to registered class name */
113 title_16, /* pointer to window name */
114 style, /* window style */
115 win_rect.left, /* horizontal position of window */
116 win_rect.top, /* vertical position of window */
117 win_rect.right - win_rect.left, /* window width */
118 win_rect.bottom - win_rect.top, /* window height */
119 m_parentWindowHwnd, /* handle to parent or owner window */
120 0, /* handle to menu or child-window identifier */
121 ::GetModuleHandle(0), /* handle to application instance */
122 0); /* pointer to window-creation data */
123 free(title_16);
124
125 if (m_hWnd == nullptr) {
126 return;
127 }
128
129 registerWindowAppUserModelProperties();
130
131 /* Store the device context. */
132 m_hDC = ::GetDC(m_hWnd);
133
134 if (!setDrawingContextType(type)) {
135 const char *title = "Blender - Unsupported Graphics Card Configuration";
136 const char *text = "";
137#if defined(WIN32)
138 if (strncmp(BLI_getenv("PROCESSOR_IDENTIFIER"), "ARM", 3) == 0 &&
139 strstr(BLI_getenv("PROCESSOR_IDENTIFIER"), "Qualcomm") != NULL)
140 {
141 text =
142 "A driver with support for OpenGL 4.3 or higher is required.\n\n"
143 "Qualcomm devices require the \"OpenCL™, OpenGL®, and Vulkan® Compatibility Pack\" "
144 "from the Microsoft Store.\n\n"
145 "Devices using processors older than a Qualcomm Snapdragon 8cx Gen3 are incompatible, "
146 "but may be able to run an emulated x64 copy of Blender, such as a 3.x LTS release.";
147 }
148 else
149#endif
150 {
151 text =
152 "A graphics card and driver with support for OpenGL 4.3 or higher is "
153 "required.\n\nInstalling the latest driver for your graphics card might resolve the "
154 "issue.";
155 if (GetSystemMetrics(SM_CMONITORS) > 1) {
156 text =
157 "A graphics card and driver with support for OpenGL 4.3 or higher is "
158 "required.\n\nPlugging all monitors into your primary graphics card might resolve "
159 "this issue. Installing the latest driver for your graphics card could also help.";
160 }
161 }
162 MessageBox(m_hWnd, text, title, MB_OK | MB_ICONERROR);
163 ::ReleaseDC(m_hWnd, m_hDC);
164 ::DestroyWindow(m_hWnd);
165 m_hWnd = nullptr;
166 if (!parentwindow) {
167 exit(0);
168 }
169 return;
170 }
171
172 RegisterTouchWindow(m_hWnd, 0);
173
174 /* Register as drop-target. #OleInitialize(0) required first, done in GHOST_SystemWin32. */
175 m_dropTarget = new GHOST_DropTargetWin32(this, m_system);
176 ::RegisterDragDrop(m_hWnd, m_dropTarget);
177
178 /* Store a pointer to this class in the window structure. */
179 ::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);
180
181 if (!m_system->m_windowFocus) {
182 /* If we don't want focus then lower to bottom. */
183 ::SetWindowPos(m_hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
184 }
185
186 if (parentwindow) {
187 /* Release any parent capture to allow immediate interaction (#90110). */
188 ::ReleaseCapture();
189 parentwindow->lostMouseCapture();
190 }
191
192 /* Show the window. */
193 int nCmdShow;
194 switch (state) {
196 nCmdShow = SW_SHOWMAXIMIZED;
197 break;
199 nCmdShow = (m_system->m_windowFocus) ? SW_SHOWMINIMIZED : SW_SHOWMINNOACTIVE;
200 break;
202 default:
203 nCmdShow = (m_system->m_windowFocus) ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE;
204 break;
205 }
206
207 ThemeRefresh();
208
209 ::ShowWindow(m_hWnd, nCmdShow);
210
211#ifdef WIN32_COMPOSITING
212 if (alphaBackground && parentwindowhwnd == 0) {
213
214 HRESULT hr = S_OK;
215
216 /* Create and populate the Blur Behind structure. */
217 DWM_BLURBEHIND bb = {0};
218
219 /* Enable Blur Behind and apply to the entire client area. */
220 bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
221 bb.fEnable = true;
222 bb.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
223
224 /* Apply Blur Behind. */
225 hr = DwmEnableBlurBehindWindow(m_hWnd, &bb);
226 DeleteObject(bb.hRgnBlur);
227 }
228#endif
229
230 /* Initialize WINTAB. */
231 if (system->getTabletAPI() != GHOST_kTabletWinPointer) {
233 }
234
235 /* Allow the showing of a progress bar on the taskbar. */
236 CoCreateInstance(
237 CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
238
239 /* Initialize Direct Manipulation. */
240 m_directManipulationHelper = GHOST_DirectManipulationHelper::create(m_hWnd, getDPIHint());
241}
242
244{
245 if (!m_directManipulationHelper) {
246 return;
247 }
248
249 m_directManipulationHelper->update();
250}
251
253{
254 /* Only #DM_POINTERHITTEST can be the first message of input sequence of touch-pad input. */
255
256 if (!m_directManipulationHelper) {
257 return;
258 }
259
260 UINT32 pointerId = GET_POINTERID_WPARAM(wParam);
261 POINTER_INPUT_TYPE pointerType;
262 if (GetPointerType(pointerId, &pointerType) && pointerType == PT_TOUCHPAD) {
263 m_directManipulationHelper->onPointerHitTest(pointerId);
264 }
265}
266
268{
269 if (!m_directManipulationHelper) {
270 return {0, 0, 0};
271 }
272
273 return m_directManipulationHelper->getTrackpadInfo();
274}
275
277{
278 if (m_hWnd) {
279 unregisterWindowAppUserModelProperties();
280 }
281
282 if (m_Bar) {
283 m_Bar->SetProgressState(m_hWnd, TBPF_NOPROGRESS);
284 m_Bar->Release();
285 m_Bar = nullptr;
286 }
287
288 closeWintab();
289
290 if (m_user32) {
291 FreeLibrary(m_user32);
292 m_user32 = nullptr;
293 }
294
295 if (m_customCursor) {
296 DestroyCursor(m_customCursor);
297 m_customCursor = nullptr;
298 }
299
300 if (m_hWnd != nullptr && m_hDC != nullptr && releaseNativeHandles()) {
301 ::ReleaseDC(m_hWnd, m_hDC);
302 m_hDC = nullptr;
303 }
304
305 if (m_hWnd) {
306 /* If this window is referenced by others as parent, clear that relation or windows will free
307 * the handle while we still reference it. */
308 for (GHOST_IWindow *iter_win : m_system->getWindowManager()->getWindows()) {
309 GHOST_WindowWin32 *iter_winwin = (GHOST_WindowWin32 *)iter_win;
310 if (iter_winwin->m_parentWindowHwnd == m_hWnd) {
311 ::SetWindowLongPtr(iter_winwin->m_hWnd, GWLP_HWNDPARENT, 0);
312 iter_winwin->m_parentWindowHwnd = 0;
313 }
314 }
315
316 if (m_dropTarget) {
317 /* Disable DragDrop. */
318 RevokeDragDrop(m_hWnd);
319 /* Release our reference of the DropTarget and it will delete itself eventually. */
320 m_dropTarget->Release();
321 m_dropTarget = nullptr;
322 }
323 ::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, 0);
324 ::DestroyWindow(m_hWnd);
325 m_hWnd = 0;
326 }
327
328 delete m_directManipulationHelper;
329 m_directManipulationHelper = nullptr;
330}
331
333 DWORD dwStyle,
334 DWORD dwExStyle)
335{
336 /* Get Details of the closest monitor. */
337 HMONITOR hmonitor = MonitorFromRect(win_rect, MONITOR_DEFAULTTONEAREST);
338 MONITORINFOEX monitor;
339 monitor.cbSize = sizeof(MONITORINFOEX);
340 monitor.dwFlags = 0;
341 GetMonitorInfo(hmonitor, &monitor);
342
343 /* Constrain requested size and position to fit within this monitor. */
344 LONG width = min(monitor.rcWork.right - monitor.rcWork.left, win_rect->right - win_rect->left);
345 LONG height = min(monitor.rcWork.bottom - monitor.rcWork.top, win_rect->bottom - win_rect->top);
346 win_rect->left = min(max(monitor.rcWork.left, win_rect->left), monitor.rcWork.right - width);
347 win_rect->right = win_rect->left + width;
348 win_rect->top = min(max(monitor.rcWork.top, win_rect->top), monitor.rcWork.bottom - height);
349 win_rect->bottom = win_rect->top + height;
350
351 /* With Windows 10 and newer we can adjust for chrome that differs with DPI and scale. */
352 GHOST_WIN32_AdjustWindowRectExForDpi fpAdjustWindowRectExForDpi = nullptr;
353 if (m_user32) {
354 fpAdjustWindowRectExForDpi = (GHOST_WIN32_AdjustWindowRectExForDpi)::GetProcAddress(
355 m_user32, "AdjustWindowRectExForDpi");
356 }
357
358 /* Adjust to allow for caption, borders, shadows, scaling, etc. Resulting values can be
359 * correctly outside of monitor bounds. NOTE: You cannot specify #WS_OVERLAPPED when calling. */
360 if (fpAdjustWindowRectExForDpi) {
361 UINT dpiX, dpiY;
362 GetDpiForMonitor(hmonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
363 fpAdjustWindowRectExForDpi(win_rect, dwStyle & ~WS_OVERLAPPED, FALSE, dwExStyle, dpiX);
364 }
365 else {
366 AdjustWindowRectEx(win_rect, dwStyle & ~WS_OVERLAPPED, FALSE, dwExStyle);
367 }
368
369 /* But never allow a top position that can hide part of the title bar. */
370 win_rect->top = max(monitor.rcWork.top, win_rect->top);
371}
372
374{
375 return GHOST_Window::getValid() && m_hWnd != 0 && m_hDC != 0;
376}
377
379{
380 return m_hWnd;
381}
382
384{
385 return (void *)m_hWnd;
386}
387
388void GHOST_WindowWin32::setTitle(const char *title)
389{
390 wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
391 ::SetWindowTextW(m_hWnd, (wchar_t *)title_16);
392 free(title_16);
393}
394
396{
397 std::wstring wtitle(::GetWindowTextLengthW(m_hWnd) + 1, L'\0');
398 ::GetWindowTextW(m_hWnd, &wtitle[0], wtitle.capacity());
399
400 std::string title(count_utf_8_from_16(wtitle.c_str()) + 1, '\0');
401 conv_utf_16_to_8(wtitle.c_str(), &title[0], title.capacity());
402
403 return title;
404}
405
407{
408 RECT rect;
409 ::GetWindowRect(m_hWnd, &rect);
410 bounds.m_b = rect.bottom;
411 bounds.m_l = rect.left;
412 bounds.m_r = rect.right;
413 bounds.m_t = rect.top;
414}
415
417{
418 RECT rect;
419 POINT coord;
420 if (!IsIconic(m_hWnd)) {
421 ::GetClientRect(m_hWnd, &rect);
422
423 coord.x = rect.left;
424 coord.y = rect.top;
425 ::ClientToScreen(m_hWnd, &coord);
426
427 bounds.m_l = coord.x;
428 bounds.m_t = coord.y;
429
430 coord.x = rect.right;
431 coord.y = rect.bottom;
432 ::ClientToScreen(m_hWnd, &coord);
433
434 bounds.m_r = coord.x;
435 bounds.m_b = coord.y;
436 }
437 else {
438 bounds.m_b = 0;
439 bounds.m_l = 0;
440 bounds.m_r = 0;
441 bounds.m_t = 0;
442 }
443}
444
446{
447 GHOST_TSuccess success;
448 GHOST_Rect cBnds, wBnds;
449 getClientBounds(cBnds);
450 if (cBnds.getWidth() != int32_t(width)) {
451 getWindowBounds(wBnds);
452 int cx = wBnds.getWidth() + width - cBnds.getWidth();
453 int cy = wBnds.getHeight();
454 success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ?
457 }
458 else {
459 success = GHOST_kSuccess;
460 }
461 return success;
462}
463
465{
466 GHOST_TSuccess success;
467 GHOST_Rect cBnds, wBnds;
468 getClientBounds(cBnds);
469 if (cBnds.getHeight() != int32_t(height)) {
470 getWindowBounds(wBnds);
471 int cx = wBnds.getWidth();
472 int cy = wBnds.getHeight() + height - cBnds.getHeight();
473 success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ?
476 }
477 else {
478 success = GHOST_kSuccess;
479 }
480 return success;
481}
482
484{
485 GHOST_TSuccess success;
486 GHOST_Rect cBnds, wBnds;
487 getClientBounds(cBnds);
488 if ((cBnds.getWidth() != int32_t(width)) || (cBnds.getHeight() != int32_t(height))) {
489 getWindowBounds(wBnds);
490 int cx = wBnds.getWidth() + width - cBnds.getWidth();
491 int cy = wBnds.getHeight() + height - cBnds.getHeight();
492 success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ?
495 }
496 else {
497 success = GHOST_kSuccess;
498 }
499 return success;
500}
501
503{
504 if (::IsIconic(m_hWnd)) {
506 }
507 else if (::IsZoomed(m_hWnd)) {
508 LONG_PTR result = ::GetWindowLongPtr(m_hWnd, GWL_STYLE);
510 }
512}
513
515 int32_t inY,
516 int32_t &outX,
517 int32_t &outY) const
518{
519 POINT point = {inX, inY};
520 ::ScreenToClient(m_hWnd, &point);
521 outX = point.x;
522 outY = point.y;
523}
524
526 int32_t inY,
527 int32_t &outX,
528 int32_t &outY) const
529{
530 POINT point = {inX, inY};
531 ::ClientToScreen(m_hWnd, &point);
532 outX = point.x;
533 outY = point.y;
534}
535
537{
538 GHOST_TWindowState curstate = getState();
539 LONG_PTR style = GetWindowLongPtr(m_hWnd, GWL_STYLE) | WS_CAPTION;
540 WINDOWPLACEMENT wp;
541 wp.length = sizeof(WINDOWPLACEMENT);
542 ::GetWindowPlacement(m_hWnd, &wp);
543
544 switch (state) {
546 wp.showCmd = SW_MINIMIZE;
547 break;
549 wp.showCmd = SW_SHOWMAXIMIZED;
550 break;
552 if (curstate != state && curstate != GHOST_kWindowStateMinimized) {
553 m_normal_state = curstate;
554 }
555 wp.showCmd = SW_SHOWMAXIMIZED;
556 wp.ptMaxPosition.x = 0;
557 wp.ptMaxPosition.y = 0;
558 style &= ~(WS_CAPTION | WS_MAXIMIZE);
559 break;
561 default:
562 if (curstate == GHOST_kWindowStateFullScreen &&
563 m_normal_state == GHOST_kWindowStateMaximized)
564 {
565 wp.showCmd = SW_SHOWMAXIMIZED;
566 m_normal_state = GHOST_kWindowStateNormal;
567 }
568 else {
569 wp.showCmd = SW_SHOWNORMAL;
570 }
571 break;
572 }
573 ::SetWindowLongPtr(m_hWnd, GWL_STYLE, style);
574 /* #SetWindowLongPtr Docs:
575 * Frame changes not visible until #SetWindowPos with #SWP_FRAMECHANGED. */
576 ::SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
577 return ::SetWindowPlacement(m_hWnd, &wp) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
578}
579
581{
582 HWND hWndInsertAfter, hWndToRaise;
583
584 if (order == GHOST_kWindowOrderBottom) {
585 hWndInsertAfter = HWND_BOTTOM;
586 hWndToRaise = ::GetWindow(m_hWnd, GW_HWNDNEXT); /* the window to raise */
587 }
588 else {
591 }
592 hWndInsertAfter = HWND_TOP;
593 hWndToRaise = nullptr;
594 }
595
596 if (::SetWindowPos(m_hWnd, hWndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE) == FALSE) {
597 return GHOST_kFailure;
598 }
599
600 if (hWndToRaise &&
601 ::SetWindowPos(hWndToRaise, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE) == FALSE)
602 {
603 return GHOST_kFailure;
604 }
605 return GHOST_kSuccess;
606}
607
609{
610 GHOST_TSuccess success;
611 if (m_hWnd) {
612 success = ::InvalidateRect(m_hWnd, 0, FALSE) != 0 ? GHOST_kSuccess : GHOST_kFailure;
613 }
614 else {
615 success = GHOST_kFailure;
616 }
617 return success;
618}
619
620GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType type)
621{
622 switch (type) {
623#ifdef WITH_VULKAN_BACKEND
624 case GHOST_kDrawingContextTypeVulkan: {
625 GHOST_Context *context = new GHOST_ContextVK(
626 false, m_hWnd, 1, 2, m_debug_context, m_preferred_device);
627 if (context->initializeDrawingContext()) {
628 return context;
629 }
630 delete context;
631 return nullptr;
632 }
633#endif
634
635#ifdef WITH_OPENGL_BACKEND
636 case GHOST_kDrawingContextTypeOpenGL: {
637 for (int minor = 6; minor >= 3; --minor) {
638 GHOST_Context *context = new GHOST_ContextWGL(
640 m_wantAlphaBackground,
641 m_hWnd,
642 m_hDC,
643 WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
644 4,
645 minor,
646 (m_debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
648
649 if (context->initializeDrawingContext()) {
650 return context;
651 }
652 delete context;
653 }
654 return nullptr;
655 }
656#endif
657
658 case GHOST_kDrawingContextTypeD3D: {
659 GHOST_Context *context = new GHOST_ContextD3D(false, m_hWnd);
660
661 if (context->initializeDrawingContext()) {
662 return context;
663 }
664 delete context;
665 return nullptr;
666 }
667
668 default:
669 /* Unsupported backend. */
670 return nullptr;
671 }
672}
673
675{
676 if (m_hasMouseCaptured) {
677 m_hasGrabMouse = false;
678 m_nPressedButtons = 0;
679 m_hasMouseCaptured = false;
680 }
681}
682
684{
685 return m_isDialog;
686}
687
689{
690 switch (event) {
691 case MousePressed:
692 m_nPressedButtons++;
693 break;
694 case MouseReleased:
695 if (m_nPressedButtons) {
696 m_nPressedButtons--;
697 }
698 break;
699 case OperatorGrab:
700 m_hasGrabMouse = true;
701 break;
702 case OperatorUngrab:
703 m_hasGrabMouse = false;
704 break;
705 }
706
707 if (!m_nPressedButtons && !m_hasGrabMouse && m_hasMouseCaptured) {
708 ::ReleaseCapture();
709 m_hasMouseCaptured = false;
710 }
711 else if ((m_nPressedButtons || m_hasGrabMouse) && !m_hasMouseCaptured) {
712 ::SetCapture(m_hWnd);
713 m_hasMouseCaptured = true;
714 }
715}
716
718{
719 /* Convert GHOST cursor to Windows OEM cursor. */
720 HANDLE cursor = nullptr;
721 HMODULE module = ::GetModuleHandle(0);
722 uint32_t flags = LR_SHARED | LR_DEFAULTSIZE;
723 int cx = 0, cy = 0;
724
725 switch (shape) {
727 if (m_customCursor) {
728 return m_customCursor;
729 }
730 else {
731 return nullptr;
732 }
734 cursor = ::LoadImage(module, "arrowright_cursor", IMAGE_CURSOR, cx, cy, flags);
735 break;
737 cursor = ::LoadImage(module, "arrowleft_cursor", IMAGE_CURSOR, cx, cy, flags);
738 break;
740 cursor = ::LoadImage(module, "arrowup_cursor", IMAGE_CURSOR, cx, cy, flags);
741 break;
743 cursor = ::LoadImage(module, "arrowdown_cursor", IMAGE_CURSOR, cx, cy, flags);
744 break;
746 cursor = ::LoadImage(module, "splitv_cursor", IMAGE_CURSOR, cx, cy, flags);
747 break;
749 cursor = ::LoadImage(module, "splith_cursor", IMAGE_CURSOR, cx, cy, flags);
750 break;
752 cursor = ::LoadImage(module, "knife_cursor", IMAGE_CURSOR, cx, cy, flags);
753 break;
755 cursor = ::LoadImage(module, "eyedropper_cursor", IMAGE_CURSOR, cx, cy, flags);
756 break;
758 cursor = ::LoadImage(module, "zoomin_cursor", IMAGE_CURSOR, cx, cy, flags);
759 break;
761 cursor = ::LoadImage(module, "zoomout_cursor", IMAGE_CURSOR, cx, cy, flags);
762 break;
764 cursor = ::LoadImage(nullptr, IDC_SIZEALL, IMAGE_CURSOR, cx, cy, flags);
765 break;
767 cursor = ::LoadImage(module, "handopen_cursor", IMAGE_CURSOR, cx, cy, flags);
768 break;
770 cursor = ::LoadImage(module, "handclosed_cursor", IMAGE_CURSOR, cx, cy, flags);
771 break;
773 cursor = ::LoadImage(module, "handpoint_cursor", IMAGE_CURSOR, cx, cy, flags);
774 break;
776 cursor = ::LoadImage(module, "scrollnsew_cursor", IMAGE_CURSOR, cx, cy, flags);
777 break;
779 cursor = ::LoadImage(module, "scrollns_cursor", IMAGE_CURSOR, cx, cy, flags);
780 break;
782 cursor = ::LoadImage(module, "scrollew_cursor", IMAGE_CURSOR, cx, cy, flags);
783 break;
785 cursor = ::LoadImage(nullptr, IDC_HELP, IMAGE_CURSOR, cx, cy, flags);
786 break; /* Arrow and question mark */
788 cursor = ::LoadImage(nullptr, IDC_WAIT, IMAGE_CURSOR, cx, cy, flags);
789 break; /* Hourglass */
791 cursor = ::LoadImage(nullptr, IDC_IBEAM, IMAGE_CURSOR, cx, cy, flags);
792 break; /* I-beam */
794 cursor = ::LoadImage(module, "cross_cursor", IMAGE_CURSOR, cx, cy, flags);
795 break; /* Standard Cross */
797 cursor = ::LoadImage(module, "crossA_cursor", IMAGE_CURSOR, cx, cy, flags);
798 break; /* Crosshair A */
800 cursor = ::LoadImage(module, "crossB_cursor", IMAGE_CURSOR, cx, cy, flags);
801 break; /* Diagonal Crosshair B */
803 cursor = ::LoadImage(module, "crossC_cursor", IMAGE_CURSOR, cx, cy, flags);
804 break; /* Minimal Crosshair C */
807 cursor = ::LoadImage(module, "movens_cursor", IMAGE_CURSOR, cx, cy, flags);
808 break; /* Double-pointed arrow pointing north and south */
811 cursor = ::LoadImage(module, "moveew_cursor", IMAGE_CURSOR, cx, cy, flags);
812 break; /* Double-pointed arrow pointing west and east */
814 cursor = ::LoadImage(nullptr, IDC_UPARROW, IMAGE_CURSOR, cx, cy, flags);
815 break; /* Vertical arrow */
817 cursor = ::LoadImage(nullptr, IDC_SIZENWSE, IMAGE_CURSOR, cx, cy, flags);
818 break;
820 cursor = ::LoadImage(nullptr, IDC_SIZENESW, IMAGE_CURSOR, cx, cy, flags);
821 break;
823 cursor = ::LoadImage(nullptr, IDC_SIZENWSE, IMAGE_CURSOR, cx, cy, flags);
824 break;
826 cursor = ::LoadImage(nullptr, IDC_SIZENESW, IMAGE_CURSOR, cx, cy, flags);
827 break;
829 cursor = ::LoadImage(module, "pencil_cursor", IMAGE_CURSOR, cx, cy, flags);
830 break;
832 cursor = ::LoadImage(module, "eraser_cursor", IMAGE_CURSOR, cx, cy, flags);
833 break;
836 cursor = ::LoadImage(module, "forbidden_cursor", IMAGE_CURSOR, cx, cy, flags);
837 break; /* Slashed circle */
839 cursor = ::LoadImage(module, "handle_left_cursor", IMAGE_CURSOR, cx, cy, flags);
840 break;
842 cursor = ::LoadImage(module, "handle_right_cursor", IMAGE_CURSOR, cx, cy, flags);
843 break;
845 cursor = ::LoadImage(module, "handle_both_cursor", IMAGE_CURSOR, cx, cy, flags);
846 break;
847
849 cursor = nullptr;
850 break;
851 default:
852 return nullptr;
853 }
854
855 if (cursor == nullptr) {
856 cursor = ::LoadImage(nullptr, IDC_ARROW, IMAGE_CURSOR, cx, cy, flags);
857 }
858
859 return (HCURSOR)cursor;
860}
861
863{
864 if (!visible) {
865 while (::ShowCursor(FALSE) >= 0) {
866 /* Pass. */
867 }
868 }
869 else {
870 while (::ShowCursor(TRUE) < 0) {
871 /* Pass. */
872 }
873 }
874
875 HCURSOR cursor = getStandardCursor(shape);
876 if (cursor == nullptr) {
878 }
879 ::SetCursor(cursor);
880}
881
882GHOST_TSuccess GHOST_WindowWin32::setWindowCursorVisibility(bool visible)
883{
884 if (::GetForegroundWindow() == m_hWnd) {
885 loadCursor(visible, getCursorShape());
886 }
887
888 return GHOST_kSuccess;
889}
890
891GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
892{
893 if (mode != GHOST_kGrabDisable) {
894 if (mode != GHOST_kGrabNormal) {
895 m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
896 setCursorGrabAccum(0, 0);
897
898 if (mode == GHOST_kGrabHide) {
899 setWindowCursorVisibility(false);
900 }
901 }
903 }
904 else {
906 m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
907 setWindowCursorVisibility(true);
908 }
910 /* Use to generate a mouse move event, otherwise the last event
911 * blender gets can be outside the screen causing menus not to show
912 * properly unless the user moves the mouse. */
913 int32_t pos[2];
914 m_system->getCursorPosition(pos[0], pos[1]);
915 m_system->setCursorPosition(pos[0], pos[1]);
916 }
917
918 /* Almost works without but important otherwise the mouse GHOST location
919 * can be incorrect on exit. */
920 setCursorGrabAccum(0, 0);
921 m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
923 }
924
925 return GHOST_kSuccess;
926}
927
928GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cursorShape)
929{
930 if (::GetForegroundWindow() == m_hWnd) {
931 loadCursor(getCursorVisibility(), cursorShape);
932 }
933
934 return GHOST_kSuccess;
935}
936
937GHOST_TSuccess GHOST_WindowWin32::hasCursorShape(GHOST_TStandardCursor cursorShape)
938{
939 return (getStandardCursor(cursorShape)) ? GHOST_kSuccess : GHOST_kFailure;
940}
941
943 std::vector<GHOST_PointerInfoWin32> &outPointerInfo, WPARAM wParam, LPARAM /*lParam*/)
944{
945 int32_t pointerId = GET_POINTERID_WPARAM(wParam);
946 int32_t isPrimary = IS_POINTER_PRIMARY_WPARAM(wParam);
948 uint32_t outCount = 0;
949
950 if (!(GetPointerPenInfoHistory(pointerId, &outCount, nullptr))) {
951 return GHOST_kFailure;
952 }
953
954 std::vector<POINTER_PEN_INFO> pointerPenInfo(outCount);
955 outPointerInfo.resize(outCount);
956
957 if (!(GetPointerPenInfoHistory(pointerId, &outCount, pointerPenInfo.data()))) {
958 return GHOST_kFailure;
959 }
960
961 for (uint32_t i = 0; i < outCount; i++) {
962 POINTER_INFO pointerApiInfo = pointerPenInfo[i].pointerInfo;
963 /* Obtain the basic information from the event. */
964 outPointerInfo[i].pointerId = pointerId;
965 outPointerInfo[i].isPrimary = isPrimary;
966
967 switch (pointerApiInfo.ButtonChangeType) {
968 case POINTER_CHANGE_FIRSTBUTTON_DOWN:
969 case POINTER_CHANGE_FIRSTBUTTON_UP:
970 outPointerInfo[i].buttonMask = GHOST_kButtonMaskLeft;
971 break;
972 case POINTER_CHANGE_SECONDBUTTON_DOWN:
973 case POINTER_CHANGE_SECONDBUTTON_UP:
974 outPointerInfo[i].buttonMask = GHOST_kButtonMaskRight;
975 break;
976 case POINTER_CHANGE_THIRDBUTTON_DOWN:
977 case POINTER_CHANGE_THIRDBUTTON_UP:
978 outPointerInfo[i].buttonMask = GHOST_kButtonMaskMiddle;
979 break;
980 case POINTER_CHANGE_FOURTHBUTTON_DOWN:
981 case POINTER_CHANGE_FOURTHBUTTON_UP:
982 outPointerInfo[i].buttonMask = GHOST_kButtonMaskButton4;
983 break;
984 case POINTER_CHANGE_FIFTHBUTTON_DOWN:
985 case POINTER_CHANGE_FIFTHBUTTON_UP:
986 outPointerInfo[i].buttonMask = GHOST_kButtonMaskButton5;
987 break;
988 default:
989 break;
990 }
991
992 outPointerInfo[i].pixelLocation = pointerApiInfo.ptPixelLocation;
993 outPointerInfo[i].tabletData.Active = GHOST_kTabletModeStylus;
994 outPointerInfo[i].tabletData.Pressure = 1.0f;
995 outPointerInfo[i].tabletData.Xtilt = 0.0f;
996 outPointerInfo[i].tabletData.Ytilt = 0.0f;
997 outPointerInfo[i].time = system->performanceCounterToMillis(pointerApiInfo.PerformanceCount);
998
999 if (pointerPenInfo[i].penMask & PEN_MASK_PRESSURE) {
1000 outPointerInfo[i].tabletData.Pressure = pointerPenInfo[i].pressure / 1024.0f;
1001 }
1002
1003 if (pointerPenInfo[i].penFlags & PEN_FLAG_ERASER) {
1004 outPointerInfo[i].tabletData.Active = GHOST_kTabletModeEraser;
1005 }
1006
1007 if (pointerPenInfo[i].penMask & PEN_MASK_TILT_X) {
1008 outPointerInfo[i].tabletData.Xtilt = fmin(fabs(pointerPenInfo[i].tiltX / 90.0f), 1.0f);
1009 }
1010
1011 if (pointerPenInfo[i].penMask & PEN_MASK_TILT_Y) {
1012 outPointerInfo[i].tabletData.Ytilt = fmin(fabs(pointerPenInfo[i].tiltY / 90.0f), 1.0f);
1013 }
1014 }
1015
1016 if (!outPointerInfo.empty()) {
1017 m_lastPointerTabletData = outPointerInfo.back().tabletData;
1018 }
1019
1020 return GHOST_kSuccess;
1021}
1022
1024{
1025 m_lastPointerTabletData = GHOST_TABLET_DATA_NONE;
1026}
1027
1029{
1030 return m_wintab;
1031}
1032
1034{
1035 if (!m_wintab) {
1036 WINTAB_PRINTF("Loading Wintab for window %p\n", m_hWnd);
1037 if (m_wintab = GHOST_Wintab::loadWintab(m_hWnd)) {
1038 if (enable) {
1039 m_wintab->enable();
1040
1041 /* Focus Wintab if cursor is inside this window. This ensures Wintab is enabled when the
1042 * tablet is used to change the Tablet API. */
1043 int32_t x, y;
1044 if (m_system->getCursorPosition(x, y)) {
1045 GHOST_Rect rect;
1046 getClientBounds(rect);
1047
1048 if (rect.isInside(x, y)) {
1049 m_wintab->gainFocus();
1050 }
1051 }
1052 }
1053 }
1054 }
1055}
1056
1058{
1059 WINTAB_PRINTF("Closing Wintab for window %p\n", m_hWnd);
1060 delete m_wintab;
1061 m_wintab = nullptr;
1062}
1063
1065{
1066 if (m_system->getTabletAPI() == api) {
1067 return true;
1068 }
1069 else if (m_system->getTabletAPI() == GHOST_kTabletAutomatic) {
1070 if (m_wintab && m_wintab->devicesPresent()) {
1071 return api == GHOST_kTabletWintab;
1072 }
1073 else {
1074 return api == GHOST_kTabletWinPointer;
1075 }
1076 }
1077 else {
1078 return false;
1079 }
1080}
1081
1083{
1085 return m_wintab ? m_wintab->getLastTabletData() : GHOST_TABLET_DATA_NONE;
1086 }
1087 else {
1088 return m_lastPointerTabletData;
1089 }
1090}
1091
1093{
1094 DWORD lightMode;
1095 DWORD pcbData = sizeof(lightMode);
1096 if (RegGetValueW(HKEY_CURRENT_USER,
1097 L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\\",
1098 L"AppsUseLightTheme",
1099 RRF_RT_REG_DWORD,
1100 nullptr,
1101 &lightMode,
1102 &pcbData) == ERROR_SUCCESS)
1103 {
1104 BOOL DarkMode = !lightMode;
1105
1106 /* `20 == DWMWA_USE_IMMERSIVE_DARK_MODE` in Windows 11 SDK.
1107 * This value was undocumented for Windows 10 versions 2004 and later,
1108 * supported for Windows 11 Build 22000 and later. */
1109 DwmSetWindowAttribute(this->m_hWnd, 20, &DarkMode, sizeof(DarkMode));
1110 }
1111}
1112
1114{
1115 if (m_directManipulationHelper) {
1116 m_directManipulationHelper->setDPI(getDPIHint());
1117 }
1118}
1119
1121{
1122 if (m_user32) {
1123 GHOST_WIN32_GetDpiForWindow fpGetDpiForWindow = (GHOST_WIN32_GetDpiForWindow)::GetProcAddress(
1124 m_user32, "GetDpiForWindow");
1125
1126 if (fpGetDpiForWindow) {
1127 return fpGetDpiForWindow(this->m_hWnd);
1128 }
1129 }
1130
1131 return USER_DEFAULT_SCREEN_DPI;
1132}
1133
1136{
1137 ch = ((ch >> 1) & 0x55) | ((ch << 1) & 0xAA);
1138 ch = ((ch >> 2) & 0x33) | ((ch << 2) & 0xCC);
1139 ch = ((ch >> 4) & 0x0F) | ((ch << 4) & 0xF0);
1140 return ch;
1141}
1142
1143#if 0 /* UNUSED */
1146{
1147 shrt = ((shrt >> 1) & 0x5555) | ((shrt << 1) & 0xAAAA);
1148 shrt = ((shrt >> 2) & 0x3333) | ((shrt << 2) & 0xCCCC);
1149 shrt = ((shrt >> 4) & 0x0F0F) | ((shrt << 4) & 0xF0F0);
1150 shrt = ((shrt >> 8) & 0x00FF) | ((shrt << 8) & 0xFF00);
1151 return shrt;
1152}
1153#endif
1154
1155GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(uint8_t *bitmap,
1156 uint8_t *mask,
1157 int sizeX,
1158 int sizeY,
1159 int hotX,
1160 int hotY,
1161 bool /*canInvertColor*/)
1162{
1163 uint32_t andData[32];
1164 uint32_t xorData[32];
1165 uint32_t fullBitRow, fullMaskRow;
1166 int x, y, cols;
1167
1168 cols = sizeX / 8; /* Number of whole bytes per row (width of bitmap/mask). */
1169 if (sizeX % 8) {
1170 cols++;
1171 }
1172
1173 if (m_customCursor) {
1174 DestroyCursor(m_customCursor);
1175 m_customCursor = nullptr;
1176 }
1177
1178 memset(&andData, 0xFF, sizeof(andData));
1179 memset(&xorData, 0, sizeof(xorData));
1180
1181 for (y = 0; y < sizeY; y++) {
1182 fullBitRow = 0;
1183 fullMaskRow = 0;
1184 for (x = cols - 1; x >= 0; x--) {
1185 fullBitRow <<= 8;
1186 fullMaskRow <<= 8;
1187 fullBitRow |= uns8ReverseBits(bitmap[cols * y + x]);
1188 fullMaskRow |= uns8ReverseBits(mask[cols * y + x]);
1189 }
1190 xorData[y] = fullBitRow & fullMaskRow;
1191 andData[y] = ~fullMaskRow;
1192 }
1193
1194 m_customCursor = ::CreateCursor(::GetModuleHandle(0), hotX, hotY, 32, 32, andData, xorData);
1195 if (!m_customCursor) {
1196 return GHOST_kFailure;
1197 }
1198
1199 if (::GetForegroundWindow() == m_hWnd) {
1201 }
1202
1203 return GHOST_kSuccess;
1204}
1205
1207{
1208 /* #SetProgressValue sets state to #TBPF_NORMAL automatically. */
1209 if (m_Bar && S_OK == m_Bar->SetProgressValue(m_hWnd, 10000 * progress, 10000)) {
1210 return GHOST_kSuccess;
1211 }
1212
1213 return GHOST_kFailure;
1214}
1215
1217{
1218 if (m_Bar && S_OK == m_Bar->SetProgressState(m_hWnd, TBPF_NOPROGRESS)) {
1219 return GHOST_kSuccess;
1220 }
1221
1222 return GHOST_kFailure;
1223}
1224
1225#ifdef WITH_INPUT_IME
1226void GHOST_WindowWin32::beginIME(int32_t x, int32_t y, int32_t /*w*/, int32_t h, bool completed)
1227{
1228 m_imeInput.BeginIME(m_hWnd, GHOST_Rect(x, y - h, x, y), completed);
1229}
1230
1231void GHOST_WindowWin32::endIME()
1232{
1233 m_imeInput.EndIME(m_hWnd);
1234}
1235#endif /* WITH_INPUT_IME */
1236
1237void GHOST_WindowWin32::registerWindowAppUserModelProperties()
1238{
1239 IPropertyStore *pstore;
1240 char blender_path[MAX_PATH];
1241 wchar_t shell_command[MAX_PATH];
1242
1243 /* Find the current executable, and see if it's blender.exe if not bail out. */
1244 GetModuleFileName(0, blender_path, sizeof(blender_path));
1245 char *blender_app = strstr(blender_path, "blender.exe");
1246 if (!blender_app) {
1247 return;
1248 }
1249
1250 HRESULT hr = SHGetPropertyStoreForWindow(m_hWnd, IID_PPV_ARGS(&pstore));
1251 if (!SUCCEEDED(hr)) {
1252 return;
1253 }
1254
1255 /* Set the launcher as the shell command so the console window will not flash.
1256 * when people pin blender to the taskbar. */
1257 strcpy(blender_app, "blender-launcher.exe");
1258 wsprintfW(shell_command, L"\"%S\"", blender_path);
1259 UTF16_ENCODE(BLENDER_WIN_APPID);
1260 UTF16_ENCODE(BLENDER_WIN_APPID_FRIENDLY_NAME);
1261 PROPVARIANT propvar;
1262 hr = InitPropVariantFromString(BLENDER_WIN_APPID_16, &propvar);
1263 hr = pstore->SetValue(PKEY_AppUserModel_ID, propvar);
1264 hr = InitPropVariantFromString(shell_command, &propvar);
1265 hr = pstore->SetValue(PKEY_AppUserModel_RelaunchCommand, propvar);
1266 hr = InitPropVariantFromString(BLENDER_WIN_APPID_FRIENDLY_NAME_16, &propvar);
1267 hr = pstore->SetValue(PKEY_AppUserModel_RelaunchDisplayNameResource, propvar);
1268 pstore->Release();
1269 UTF16_UN_ENCODE(BLENDER_WIN_APPID_FRIENDLY_NAME);
1270 UTF16_UN_ENCODE(BLENDER_WIN_APPID);
1271}
1272
1273/* as per MSDN: Any property not cleared before closing the window, will be leaked and NOT be
1274 * returned to the OS. */
1275void GHOST_WindowWin32::unregisterWindowAppUserModelProperties()
1276{
1277 IPropertyStore *pstore;
1278 HRESULT hr = SHGetPropertyStoreForWindow(m_hWnd, IID_PPV_ARGS(&pstore));
1279 if (SUCCEEDED(hr)) {
1280 PROPVARIANT value;
1281 PropVariantInit(&value);
1282 pstore->SetValue(PKEY_AppUserModel_ID, value);
1283 pstore->SetValue(PKEY_AppUserModel_RelaunchCommand, value);
1284 pstore->SetValue(PKEY_AppUserModel_RelaunchDisplayNameResource, value);
1285 pstore->Release();
1286 }
1287}
void BLI_kdtree_nd_ free(KDTree *tree)
const char * BLI_getenv(const char *env) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define FALSE
#define GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY
@ TBPF_NOPROGRESS
const GUID CLSID_TaskbarList
GHOST_TWindowState
@ GHOST_kWindowStateMinimized
@ GHOST_kWindowStateMaximized
@ GHOST_kWindowStateNormal
@ GHOST_kWindowStateFullScreen
GHOST_TStandardCursor
@ GHOST_kStandardCursorLeftHandle
@ GHOST_kStandardCursorHandClosed
@ GHOST_kStandardCursorHandOpen
@ GHOST_kStandardCursorBottomLeftCorner
@ GHOST_kStandardCursorZoomIn
@ GHOST_kStandardCursorVerticalSplit
@ GHOST_kStandardCursorHelp
@ GHOST_kStandardCursorWait
@ GHOST_kStandardCursorRightHandle
@ GHOST_kStandardCursorHorizontalSplit
@ GHOST_kStandardCursorTopSide
@ GHOST_kStandardCursorStop
@ GHOST_kStandardCursorCrosshair
@ GHOST_kStandardCursorCustom
@ GHOST_kStandardCursorNSEWScroll
@ GHOST_kStandardCursorLeftRight
@ GHOST_kStandardCursorPencil
@ GHOST_kStandardCursorNSScroll
@ GHOST_kStandardCursorCrosshairA
@ GHOST_kStandardCursorUpDown
@ GHOST_kStandardCursorUpArrow
@ GHOST_kStandardCursorHandPoint
@ GHOST_kStandardCursorBottomSide
@ GHOST_kStandardCursorBothHandles
@ GHOST_kStandardCursorTopLeftCorner
@ GHOST_kStandardCursorEyedropper
@ GHOST_kStandardCursorKnife
@ GHOST_kStandardCursorMove
@ GHOST_kStandardCursorCrosshairB
@ GHOST_kStandardCursorBottomRightCorner
@ GHOST_kStandardCursorDownArrow
@ GHOST_kStandardCursorEraser
@ GHOST_kStandardCursorDefault
@ GHOST_kStandardCursorEWScroll
@ GHOST_kStandardCursorRightArrow
@ GHOST_kStandardCursorTopRightCorner
@ GHOST_kStandardCursorDestroy
@ GHOST_kStandardCursorCrosshairC
@ GHOST_kStandardCursorZoomOut
@ GHOST_kStandardCursorLeftSide
@ GHOST_kStandardCursorText
@ GHOST_kStandardCursorLeftArrow
static const GHOST_TabletData GHOST_TABLET_DATA_NONE
@ GHOST_kTabletModeEraser
@ GHOST_kTabletModeStylus
GHOST_TDrawingContextType
GHOST_TWindowOrder
@ GHOST_kWindowOrderBottom
GHOST_TSuccess
Definition GHOST_Types.h:87
@ GHOST_kFailure
Definition GHOST_Types.h:87
@ GHOST_kSuccess
Definition GHOST_Types.h:87
GHOST_TGrabCursorMode
@ GHOST_kGrabDisable
@ GHOST_kGrabHide
@ GHOST_kGrabNormal
@ GHOST_kButtonMaskRight
@ GHOST_kButtonMaskButton4
@ GHOST_kButtonMaskLeft
@ GHOST_kButtonMaskButton5
@ GHOST_kButtonMaskMiddle
GHOST_TTabletAPI
@ GHOST_kTabletAutomatic
@ GHOST_kTabletWinPointer
@ GHOST_kTabletWintab
static uint16_t uns16ReverseBits(uint16_t shrt)
#define GET_POINTERID_WPARAM(wParam)
static uint8_t uns8ReverseBits(uint8_t ch)
__declspec(dllexport) DWORD NvOptimusEnablement=0x00000001
UINT(API * GHOST_WIN32_GetDpiForWindow)(HWND)
BOOL(API * GHOST_WIN32_AdjustWindowRectExForDpi)(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi)
GHOST_MouseCaptureEventWin32
@ MousePressed
@ OperatorUngrab
@ MouseReleased
@ OperatorGrab
#define WINTAB_PRINTF(x,...)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
static GHOST_DirectManipulationHelper * create(HWND hWnd, uint16_t dpi)
static GHOST_ISystem * getSystem()
virtual bool isInside(int32_t x, int32_t y) const
virtual int32_t getHeight() const
virtual int32_t getWidth() const
uint64_t performanceCounterToMillis(__int64 perf_ticks) const
GHOST_TTabletAPI getTabletAPI()
GHOST_TSuccess invalidate()
GHOST_TSuccess setOrder(GHOST_TWindowOrder order)
uint16_t getDPIHint() override
GHOST_TTrackpadInfo getTrackpadInfo()
GHOST_TSuccess setProgressBar(float progress)
void setTitle(const char *title)
std::string getTitle() const
GHOST_TSuccess setClientSize(uint32_t width, uint32_t height)
void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const
bool usingTabletAPI(GHOST_TTabletAPI api) const
GHOST_TSuccess getPointerInfo(std::vector< GHOST_PointerInfoWin32 > &outPointerInfo, WPARAM wParam, LPARAM lParam)
GHOST_TSuccess setClientHeight(uint32_t height)
void loadWintab(bool enable)
GHOST_TabletData getTabletData()
GHOST_Wintab * getWintab() const
HCURSOR getStandardCursor(GHOST_TStandardCursor shape) const
void updateMouseCapture(GHOST_MouseCaptureEventWin32 event)
GHOST_TSuccess setClientWidth(uint32_t width)
GHOST_TSuccess setState(GHOST_TWindowState state)
void getWindowBounds(GHOST_Rect &bounds) const
void getClientBounds(GHOST_Rect &bounds) const
GHOST_WindowWin32(GHOST_SystemWin32 *system, const char *title, int32_t left, int32_t top, uint32_t width, uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, bool wantStereoVisual, bool alphaBackground, GHOST_WindowWin32 *parentWindow, bool is_debug, bool dialog, const GHOST_GPUDevice &preferred_device)
void onPointerHitTest(WPARAM wParam)
void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
GHOST_TSuccess endProgressBar()
GHOST_TWindowState getState() const
void * getOSWindow() const
void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
void adjustWindowRectForClosestMonitor(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle)
GHOST_Rect m_cursorGrabBounds
void setCursorGrabAccum(int32_t x, int32_t y)
GHOST_TGrabCursorMode m_cursorGrab
bool m_wantStereoVisual
int32_t m_cursorGrabInitPos[2]
GHOST_TStandardCursor getCursorShape() const override
GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) override
GHOST_TSuccess releaseNativeHandles()
bool getCursorVisibility() const override
GHOST_Window(uint32_t width, uint32_t height, GHOST_TWindowState state, const bool wantStereoVisual=false, const bool exclusive=false)
virtual bool getValid() const override
static GHOST_Wintab * loadWintab(HWND hwnd)
#define NULL
uint top
ccl_device_inline float2 fabs(const float2 a)
ccl_device_inline float4 mask(const int4 mask, const float4 a)
static ulong state[N]
static int left
#define L
int context(const bContext *C, const char *member, bContextDataResult *result)
static struct PyModuleDef module
Definition python.cpp:991
#define min(a, b)
Definition sort.c:32
unsigned short uint16_t
Definition stdint.h:79
unsigned int uint32_t
Definition stdint.h:80
signed int int32_t
Definition stdint.h:77
unsigned char uint8_t
Definition stdint.h:78
float max
wchar_t * alloc_utf16_from_8(const char *in8, size_t add)
Definition utfconv.cc:292
size_t count_utf_8_from_16(const wchar_t *string16)
Definition utfconv.cc:11
int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8)
Definition utfconv.cc:116
#define UTF16_ENCODE(in8str)
Definition utfconv.hh:80
#define UTF16_UN_ENCODE(in8str)
Definition utfconv.hh:84