17# define _WIN32_IE 0x0501
24#include <shellscalingapi.h>
46#ifdef WITH_OPENGL_BACKEND
49#ifdef WITH_VULKAN_BACKEND
62# define VK_SEMICOLON 0xBA
65# define VK_PERIOD 0xBE
71# define VK_BACK_QUOTE 0xC0
77# define VK_BACK_SLASH 0xDC
80# define VK_EQUALS 0xBB
82#ifndef VK_OPEN_BRACKET
83# define VK_OPEN_BRACKET 0xDB
85#ifndef VK_CLOSE_BRACKET
86# define VK_CLOSE_BRACKET 0xDD
89# define VK_GR_LESS 0xE2
102#define BROKEN_PEEK_TOUCHPAD
135#ifdef WITH_INPUT_NDOF
136# define DEVICE_COUNT 2
138# define DEVICE_COUNT 1
142 memset(devices, 0,
DEVICE_COUNT *
sizeof(RAWINPUTDEVICE));
146 devices[0].usUsagePage = 0x01;
147 devices[0].usUsage = 0x06;
149#ifdef WITH_INPUT_NDOF
151 devices[1].usUsagePage = 0x01;
152 devices[1].usUsage = 0x08;
155 if (RegisterRawInputDevices(devices,
DEVICE_COUNT,
sizeof(RAWINPUTDEVICE))) {
159 GHOST_PRINTF(
"could not register for RawInput: %d\n",
int(GetLastError()));
176 SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
180 SetCurrentProcessExplicitAppUserModelID(BLENDER_WIN_APPID_16);
190#ifdef WITH_INPUT_NDOF
208 __int64 delta = perf_ticks * 1000;
218 return ::GetTickCount64();
223 ::QueryPerformanceCounter((LARGE_INTEGER *)&
count);
236 int64_t t_delta = GetMessageTime() - GetTickCount();
257 width = ::GetSystemMetrics(SM_CXSCREEN);
258 height = ::GetSystemMetrics(SM_CYSCREEN);
263 width = ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
264 height = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
275 const bool is_dialog,
300 GHOST_PRINT(
"GHOST_SystemWin32::createWindow(): window invalid\n");
318#ifdef WITH_VULKAN_BACKEND
319 case GHOST_kDrawingContextTypeVulkan: {
322 if (context->initializeDrawingContext()) {
330#ifdef WITH_OPENGL_BACKEND
331 case GHOST_kDrawingContextTypeOpenGL: {
334 HWND wnd = CreateWindowA(
"STATIC",
336 WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
343 GetModuleHandle(
nullptr),
346 HDC mHDC = GetDC(wnd);
347 HDC prev_hdc = wglGetCurrentDC();
348 HGLRC prev_context = wglGetCurrentContext();
350 for (
int minor = 6; minor >= 3; --minor) {
356 WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
359 (debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
362 if (context->initializeDrawingContext()) {
363 wglMakeCurrent(prev_hdc, prev_context);
368 wglMakeCurrent(prev_hdc, prev_context);
397 HWND wnd = CreateWindowA(
"STATIC",
399 WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
406 GetModuleHandle(
nullptr),
410 if (context->initializeDrawingContext()) {
427 bool hasEventHandled =
false;
432 if (waitForEvent && !::PeekMessage(&msg,
nullptr, 0, 0, PM_NOREMOVE)) {
442 else if (maxSleep >= 0.0) {
443 ::SetTimer(
nullptr, 0, maxSleep,
nullptr);
445 ::KillTimer(
nullptr, 0);
451 hasEventHandled =
true;
457 while (::PeekMessageW(&msg,
nullptr, 0, 0, PM_REMOVE) != 0) {
460 ::TranslateMessage(&msg);
461 ::DispatchMessageW(&msg);
462 hasEventHandled =
true;
472 }
while (waitForEvent && !hasEventHandled);
474 return hasEventHandled;
480 if (::GetCursorPos(&point)) {
490 if (!::GetActiveWindow()) {
499 if (!GetCursorPos(&point)) {
503 HDC dc = GetDC(
NULL);
508 COLORREF color = GetPixel(dc, point.x, point.y);
511 if (color == CLR_INVALID) {
515 r_color[0] = GetRValue(color) / 255.0f;
516 r_color[1] = GetGValue(color) / 255.0f;
517 r_color[2] = GetBValue(color) / 255.0f;
526 if (!GetCursorPos(&point)) {
530 HWND win = WindowFromPoint(point);
543 bool down = HIBYTE(::GetAsyncKeyState(VK_LSHIFT)) != 0;
545 down = HIBYTE(::GetAsyncKeyState(VK_RSHIFT)) != 0;
548 down = HIBYTE(::GetAsyncKeyState(VK_LMENU)) != 0;
550 down = HIBYTE(::GetAsyncKeyState(VK_RMENU)) != 0;
553 down = HIBYTE(::GetAsyncKeyState(VK_LCONTROL)) != 0;
555 down = HIBYTE(::GetAsyncKeyState(VK_RCONTROL)) != 0;
558 down = HIBYTE(::GetAsyncKeyState(VK_LWIN)) != 0;
560 down = HIBYTE(::GetAsyncKeyState(VK_RWIN)) != 0;
571 bool swapped = ::GetSystemMetrics(SM_SWAPBUTTON) == TRUE;
573 bool down = HIBYTE(::GetAsyncKeyState(VK_LBUTTON)) != 0;
576 down = HIBYTE(::GetAsyncKeyState(VK_MBUTTON)) != 0;
579 down = HIBYTE(::GetAsyncKeyState(VK_RBUTTON)) != 0;
595 InitCommonControls();
598 SetProcessDPIAware();
606 wc.style = CS_HREDRAW | CS_VREDRAW;
610 wc.hInstance = ::GetModuleHandle(0);
611 wc.hIcon = ::LoadIcon(wc.hInstance,
"APPICON");
614 ::LoadIcon(
nullptr, IDI_APPLICATION);
616 wc.hCursor = ::LoadCursor(0, IDC_ARROW);
618#ifdef INW32_COMPISITING
619 (HBRUSH)CreateSolidBrush
623 wc.lpszClassName =
L"GHOST_WindowClass";
626 if (::RegisterClassW(&wc) == 0) {
642 uint msg = raw.data.keyboard.Message;
643 *r_key_down = !(raw.data.keyboard.Flags & RI_KEY_BREAK) && msg != WM_KEYUP && msg != WM_SYSKEYUP;
645 return this->
convertKey(raw.data.keyboard.VKey,
646 raw.data.keyboard.MakeCode,
647 (raw.data.keyboard.Flags & (RI_KEY_E1 | RI_KEY_E0)));
664 char ch = char(MapVirtualKeyA(vKey, MAPVK_VK_TO_CHAR));
685 if (vKey == VK_OEM_7) {
688 else if (vKey == VK_OEM_8) {
689 if (PRIMARYLANGID(
m_langId) == LANG_FRENCH) {
704 if ((vKey >=
'0') && (vKey <=
'9')) {
708 else if ((vKey >=
'A') && (vKey <=
'Z')) {
712 else if ((vKey >= VK_F1) && (vKey <= VK_F24)) {
834 if (scanCode == 0x36) {
837 else if (scanCode == 0x2a) {
871 case VK_MEDIA_PLAY_PAUSE:
877 case VK_MEDIA_PREV_TRACK:
880 case VK_MEDIA_NEXT_TRACK:
906 DWORD msgPos = ::GetMessagePos();
907 int msgPosX = GET_X_LPARAM(msgPos);
908 int msgPosY = GET_Y_LPARAM(msgPos);
933 std::vector<GHOST_WintabInfoWin32> wintabInfo;
942 bool mouseMoveHandled;
963 switch (info.button) {
965 message = WM_LBUTTONDOWN;
968 message = WM_RBUTTONDOWN;
971 message = WM_MBUTTONDOWN;
981 if (PeekMessage(&msg, window->
getHWND(), message, message, PM_NOYIELD) &&
982 msg.message != WM_QUIT)
986 useWintabPos = wt->
testCoordinates(msg.pt.x, msg.pt.y, info.x, info.y);
988 WINTAB_PRINTF(
" ... but associated system button mismatched position\n");
995 PeekMessage(&msg, window->
getHWND(), message, message, PM_REMOVE | PM_NOYIELD);
1005 new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
1007 mouseMoveHandled =
true;
1016 if (!useWintabPos) {
1022 switch (info.button) {
1024 message = WM_LBUTTONUP;
1027 message = WM_RBUTTONUP;
1030 message = WM_MBUTTONUP;
1040 if (PeekMessage(&msg, window->
getHWND(), message, message, PM_REMOVE | PM_NOYIELD) &&
1041 msg.message != WM_QUIT)
1047 new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
1060 if (!mouseMoveHandled) {
1061 DWORD
pos = GetMessagePos();
1062 int x = GET_X_LPARAM(
pos);
1063 int y = GET_Y_LPARAM(
pos);
1081 std::vector<GHOST_PointerInfoWin32> pointerInfo;
1088 case WM_POINTERUPDATE: {
1091 for (
uint32_t i = pointerInfo.size(); i-- > 0;) {
1095 pointerInfo[i].pixelLocation.x,
1096 pointerInfo[i].pixelLocation.y,
1097 pointerInfo[i].tabletData));
1104 case WM_POINTERDOWN: {
1109 pointerInfo[0].pixelLocation.x,
1110 pointerInfo[0].pixelLocation.y,
1111 pointerInfo[0].tabletData));
1115 pointerInfo[0].buttonMask,
1116 pointerInfo[0].tabletData));
1120 eventHandled =
true;
1124 case WM_POINTERUP: {
1128 pointerInfo[0].buttonMask,
1129 pointerInfo[0].tabletData));
1133 eventHandled =
true;
1153 int32_t x_screen = screen_co[0], y_screen = screen_co[1];
1158 static bool is_warping_x =
false;
1159 static bool is_warping_y =
false;
1187 bounds.wrapPoint(x_new, y_new, bounds_margin, bounds_axis);
1191 if (x_new != x_screen || y_new != y_screen) {
1195 if (!is_warping_x) {
1196 is_warping_x = x_new != x_screen;
1198 x_accum += (x_screen - x_new);
1202 if (!is_warping_y) {
1203 is_warping_y = y_new != y_screen;
1205 y_accum += (y_screen - y_new);
1215 is_warping_x =
false;
1216 is_warping_y =
false;
1217 x_screen += x_accum;
1218 y_screen += y_accum;
1236 int delta = GET_WHEEL_DELTA_WPARAM(wParam);
1238 if (acc * delta < 0) {
1243 int direction = (acc >= 0) ? 1 : -1;
1246 while (acc >= WHEEL_DELTA) {
1255 const char vk = raw.data.keyboard.VKey;
1256 bool key_down =
false;
1267 bool is_repeat =
false;
1268 bool is_repeated_modifier =
false;
1270 if (HIBYTE(::GetKeyState(vk)) != 0) {
1280 if (!is_repeated_modifier) {
1281 char utf8_char[6] = {0};
1283 const BOOL has_state = GetKeyboardState((PBYTE)
state);
1284 const bool ctrl_pressed = has_state &&
state[VK_CONTROL] & 0x80;
1285 const bool alt_pressed = has_state &&
state[VK_MENU] & 0x80;
1290 if (ctrl_pressed && !alt_pressed) {
1296 else if (MapVirtualKeyW(vk, MAPVK_VK_TO_CHAR) != 0) {
1297 wchar_t utf16[3] = {0};
1301 if ((r = ToUnicodeEx(
1304 if ((r > 0 && r < 3)) {
1309 utf8_char[0] =
'\0';
1314 utf8_char[0] =
'\0';
1318#ifdef WITH_INPUT_IME
1319 if (key_down && ((utf8_char[0] & 0x80) == 0)) {
1320 const char ascii = utf8_char[0];
1321 if (window->getImeInput()->IsImeKeyEvent(ascii, key)) {
1371#ifdef WITH_INPUT_IME
1377 return new GHOST_EventIME(
getMessageTime(system), type, window, data);
1390 getMessageTime(system), eventType, draggedObjectType, window, mouseX, mouseY, data));
1426 minmax->ptMinTrackSize.x = 320;
1427 minmax->ptMinTrackSize.y = 240;
1430#ifdef WITH_INPUT_NDOF
1431bool GHOST_SystemWin32::processNDOF(RAWINPUT
const &raw)
1433 bool eventSent =
false;
1436 RID_DEVICE_INFO info;
1437 unsigned infoSize =
sizeof(RID_DEVICE_INFO);
1438 info.cbSize = infoSize;
1440 GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize);
1442 if (info.dwType == RIM_TYPEHID) {
1443 m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId);
1446 GHOST_PRINT(
"<!> not a HID device... mouse/kb perhaps?\n");
1453 BYTE
const *data = raw.data.hid.bRawData;
1455 BYTE packetType = data[0];
1456 switch (packetType) {
1458 const short *axis = (
short *)(data + 1);
1460 const int t[3] = {axis[0], -axis[2], axis[1]};
1461 m_ndofManager->updateTranslation(t, now);
1463 if (raw.data.hid.dwSizeHid == 13) {
1465 const int r[3] = {-axis[3], axis[5], -axis[4]};
1466 m_ndofManager->updateRotation(r, now);
1475 const short *axis = (
short *)(data + 1);
1476 const int r[3] = {-axis[0], axis[2], -axis[1]};
1477 m_ndofManager->updateRotation(r, now);
1482 memcpy(&button_bits, data + 1,
sizeof(button_bits));
1483 m_ndofManager->updateButtonsBitmask(button_bits, now);
1489 for (
int i = 0; i < buttons.size(); i++) {
1498 for (
int i = 0; i < buttons.size(); i++) {
1513 if (active_window) {
1523 if (!active_window) {
1533 if (trackpad_info.
x != 0 || trackpad_info.
y != 0) {
1543 if (trackpad_info.
scale != 0) {
1549 trackpad_info.
scale,
1558 bool eventHandled =
false;
1560 LRESULT lResult = 0;
1562#ifdef WITH_INPUT_IME
1565 GHOST_ASSERT(system,
"GHOST_SystemWin32::s_wndProc(): system not initialized");
1569 if (msg == WM_NCCREATE) {
1572 HMODULE m_user32 = ::LoadLibrary(
"User32.dll");
1576 "EnableNonClientDpiScaling");
1577 if (fpEnableNonClientDpiScaling) {
1578 fpEnableNonClientDpiScaling(hwnd);
1587 case WM_INPUTLANGCHANGE: {
1589#ifdef WITH_INPUT_IME
1590 window->getImeInput()->UpdateInputLanguage();
1591 window->getImeInput()->UpdateConversionStatus(hwnd);
1600 RAWINPUT *raw_ptr = &raw;
1601 uint rawSize =
sizeof(RAWINPUT);
1603 GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize,
sizeof(RAWINPUTHEADER));
1605 switch (raw.header.dwType) {
1606 case RIM_TYPEKEYBOARD: {
1609 GHOST_PRINT(
"GHOST_SystemWin32::wndProc: key event ");
1615#ifdef WITH_INPUT_NDOF
1617 if (system->processNDOF(raw)) {
1618 eventHandled =
true;
1626#ifdef WITH_INPUT_IME
1630 case WM_IME_NOTIFY: {
1632 if (wParam == IMN_SETOPENSTATUS || wParam == IMN_SETCONVERSIONMODE) {
1633 window->getImeInput()->UpdateConversionStatus(hwnd);
1637 case WM_IME_SETCONTEXT: {
1638 GHOST_ImeWin32 *ime = window->getImeInput();
1639 ime->UpdateInputLanguage();
1640 ime->UpdateConversionStatus(hwnd);
1641 ime->CreateImeWindow(hwnd);
1642 ime->CleanupComposition(hwnd);
1643 ime->CheckFirst(hwnd);
1646 case WM_IME_STARTCOMPOSITION: {
1647 GHOST_ImeWin32 *ime = window->getImeInput();
1648 eventHandled =
true;
1649 ime->CreateImeWindow(hwnd);
1650 ime->ResetComposition(hwnd);
1654 case WM_IME_COMPOSITION: {
1655 GHOST_ImeWin32 *ime = window->getImeInput();
1656 eventHandled =
true;
1657 ime->UpdateImeWindow(hwnd);
1658 ime->UpdateInfo(hwnd);
1659 if (ime->eventImeData.result_len) {
1666 case WM_IME_ENDCOMPOSITION: {
1667 GHOST_ImeWin32 *ime = window->getImeInput();
1668 eventHandled =
true;
1671 ime->ResetComposition(hwnd);
1672 ime->DestroyImeWindow(hwnd);
1698 case WM_SYSDEADCHAR:
1711 case WM_SYSCOMMAND: {
1719 switch (wParam & 0xFFF0) {
1721 eventHandled =
true;
1725 ::ShowWindow(hwnd, SW_RESTORE);
1733 eventHandled =
true;
1758 case WT_CSRCHANGE: {
1764 eventHandled =
true;
1767 case WT_PROXIMITY: {
1769 if (LOWORD(lParam)) {
1775 if (HIWORD(lParam)) {
1776 WINTAB_PRINTF(
" Cursor entering or leaving hardware proximity.\n");
1779 WINTAB_PRINTF(
" Cursor neither entering nor leaving hardware proximity.\n");
1784 bool inRange = LOWORD(lParam);
1793 eventHandled =
true;
1796 case WT_INFOCHANGE: {
1806 eventHandled =
true;
1811 eventHandled =
true;
1825 case WT_CTXUPDATE: {
1829 case WT_CTXOVERLAP: {
1832 case CXS_DISABLED: {
1836 case CXS_OBSCURED: {
1850 case WM_POINTERUPDATE:
1851 case WM_POINTERDOWN:
1852 case WM_POINTERUP: {
1856 case WM_POINTERLEAVE: {
1858 POINTER_INFO pointerInfo;
1859 if (!GetPointerInfo(pointerId, &pointerInfo)) {
1864 if (pointerInfo.pointerType == PT_PEN) {
1866 eventHandled =
true;
1873 case WM_LBUTTONDOWN: {
1877 case WM_MBUTTONDOWN: {
1881 case WM_RBUTTONDOWN: {
1885 case WM_XBUTTONDOWN: {
1886 if (
short(HIWORD(wParam)) == XBUTTON1) {
1889 else if (
short(HIWORD(wParam)) == XBUTTON2) {
1894 case WM_LBUTTONUP: {
1898 case WM_MBUTTONUP: {
1902 case WM_RBUTTONUP: {
1906 case WM_XBUTTONUP: {
1907 if (
short(HIWORD(wParam)) == XBUTTON1) {
1910 else if (
short(HIWORD(wParam)) == XBUTTON2) {
1915 case WM_MOUSEMOVE: {
1918 TRACKMOUSEEVENT tme = {
sizeof(tme)};
1920 tme.dwFlags = TME_LEAVE;
1923 tme.dwFlags |= TME_HOVER;
1924 tme.dwHoverTime = 100;
1926 tme.hwndTrack = hwnd;
1927 TrackMouseEvent(&tme);
1935 const int32_t window_co[2] = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
1942 case WM_MOUSEHOVER: {
1948 HWND old_hwnd = ::GetFocus();
1949 if (old_hwnd && hwnd != old_hwnd) {
1950 HWND new_parent = ::GetParent(hwnd);
1951 HWND old_parent = ::GetParent(old_hwnd);
1952 if (hwnd == old_parent || old_hwnd == new_parent) {
1956 else if (new_parent != HWND_DESKTOP && new_parent == old_parent) {
1960 else if (!new_parent && !old_parent) {
1962 RECT new_rect, old_rect, dest_rect;
1965 DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &new_rect,
sizeof(RECT));
1966 ::InflateRect(&new_rect, -1, -1);
1967 DwmGetWindowAttribute(
1968 old_hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &old_rect,
sizeof(RECT));
1969 ::InflateRect(&old_rect, -1, -1);
1971 if (!IntersectRect(&dest_rect, &new_rect, &old_rect)) {
1978 case WM_MOUSEWHEEL: {
1987 eventHandled =
true;
1988#ifdef BROKEN_PEEK_TOUCHPAD
1989 PostMessage(hwnd, WM_USER, 0, 0);
1993 case WM_SETCURSOR: {
2000 if (LOWORD(lParam) == HTCLIENT) {
2012 case WM_MOUSELEAVE: {
2017 int32_t screen_co[2] = {0, 0};
2030 case WM_NCMOUSEMOVE: {
2036 case WM_NCHITTEST: {
2050 if (IsIconic(hwnd)) {
2051 ShowWindow(hwnd, SW_RESTORE);
2069 if (LOWORD(wParam) == WA_INACTIVE) {
2073 lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
2076 case WM_ENTERSIZEMOVE: {
2087 case WM_EXITSIZEMOVE: {
2100 ::ValidateRect(hwnd,
nullptr);
2103 eventHandled =
true;
2107 case WM_GETMINMAXINFO: {
2131 case WM_CAPTURECHANGED: {
2157 case WM_DPICHANGED: {
2164 RECT *
const suggestedWindowRect = (RECT *)lParam;
2169 eventHandled =
true;
2174 suggestedWindowRect->left,
2175 suggestedWindowRect->top,
2176 suggestedWindowRect->right - suggestedWindowRect->left,
2177 suggestedWindowRect->bottom - suggestedWindowRect->top,
2178 SWP_NOZORDER | SWP_NOACTIVATE);
2183 case WM_DISPLAYCHANGE: {
2190 case WM_KILLFOCUS: {
2194 if (!wParam && hwnd == ::GetActiveWindow()) {
2199 case WM_SETTINGCHANGE: {
2202 if (((
void *)lParam !=
nullptr) && (wcscmp(LPCWSTR(lParam),
L"ImmersiveColorSet") == 0))
2211 case WM_WINDOWPOSCHANGED:
2236 case WM_NCDESTROY: {
2247 case WM_WINDOWPOSCHANGING:
2261 case WM_ACTIVATEAPP:
2277 case DM_POINTERHITTEST: {
2290 GHOST_PRINT(
"GHOST_SystemWin32::wndProc: GHOST window event before creation\n");
2302 GHOST_PRINT(
"GHOST_SystemWin32::wndProc: event without window\n");
2307 eventHandled =
true;
2310 if (!eventHandled) {
2311 lResult = ::DefWindowProcW(hwnd, msg, wParam, lParam);
2319 if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(
nullptr)) {
2321 HANDLE hData = GetClipboardData(CF_UNICODETEXT);
2322 if (hData ==
nullptr) {
2326 buffer = (
wchar_t *)GlobalLock(hData);
2336 GlobalUnlock(hData);
2341 if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(
nullptr)) {
2344 HANDLE hData = GetClipboardData(CF_TEXT);
2345 if (hData ==
nullptr) {
2349 buffer = (
char *)GlobalLock(hData);
2355 len = strlen(buffer);
2356 char *temp_buff = (
char *)malloc(
len + 1);
2357 strncpy(temp_buff, buffer,
len);
2358 temp_buff[
len] =
'\0';
2362 GlobalUnlock(hData);
2372 if (selection || !buffer) {
2376 if (OpenClipboard(
nullptr)) {
2382 HGLOBAL clipbuffer = GlobalAlloc(GMEM_MOVEABLE,
sizeof(
wchar_t) *
len);
2384 wchar_t *data = (
wchar_t *)GlobalLock(clipbuffer);
2388 GlobalUnlock(clipbuffer);
2389 SetClipboardData(CF_UNICODETEXT, clipbuffer);
2398 if (IsClipboardFormatAvailable(CF_DIBV5) ||
2399 IsClipboardFormatAvailable(RegisterClipboardFormat(
"PNG")))
2409 HANDLE hGlobal = GetClipboardData(CF_DIBV5);
2410 if (hGlobal ==
nullptr) {
2414 BITMAPV5HEADER *bitmapV5Header = (BITMAPV5HEADER *)GlobalLock(hGlobal);
2415 if (bitmapV5Header ==
nullptr) {
2419 int offset = bitmapV5Header->bV5Size + bitmapV5Header->bV5ClrUsed *
sizeof(RGBQUAD);
2421 BYTE *buffer = (BYTE *)bitmapV5Header + offset;
2422 int bitcount = bitmapV5Header->bV5BitCount;
2423 int width = bitmapV5Header->bV5Width;
2424 int height = bitmapV5Header->bV5Height;
2428 if (
uint64_t(width) *
uint64_t(height) > (std::numeric_limits<DWORD>::max() / 4)) {
2429 GlobalUnlock(hGlobal);
2436 DWORD ColorMasks[4];
2437 ColorMasks[0] = bitmapV5Header->bV5RedMask ? bitmapV5Header->bV5RedMask : 0xff;
2438 ColorMasks[1] = bitmapV5Header->bV5GreenMask ? bitmapV5Header->bV5GreenMask : 0xff00;
2439 ColorMasks[2] = bitmapV5Header->bV5BlueMask ? bitmapV5Header->bV5BlueMask : 0xff0000;
2440 ColorMasks[3] = bitmapV5Header->bV5AlphaMask ? bitmapV5Header->bV5AlphaMask : 0xff000000;
2443 DWORD ColorShifts[4];
2444 for (
int i = 0; i < 4; i++) {
2445 _BitScanForward(&ColorShifts[i], ColorMasks[i]);
2452 if (bitmapV5Header->bV5Compression == BI_BITFIELDS && bitcount == 32) {
2453 for (
int h = 0; h < height; h++) {
2454 for (
int w = 0;
w < width;
w++, target += 4, source += 4) {
2455 DWORD *pix = (DWORD *)source;
2456 target[0] =
uint8_t((*pix & ColorMasks[0]) >> ColorShifts[0]);
2457 target[1] =
uint8_t((*pix & ColorMasks[1]) >> ColorShifts[1]);
2458 target[2] =
uint8_t((*pix & ColorMasks[2]) >> ColorShifts[2]);
2459 target[3] =
uint8_t((*pix & ColorMasks[3]) >> ColorShifts[3]);
2463 else if (bitmapV5Header->bV5Compression == BI_RGB && bitcount == 32) {
2464 for (
int h = 0; h < height; h++) {
2465 for (
int w = 0;
w < width;
w++, target += 4, source += 4) {
2466 RGBQUAD *
quad = (RGBQUAD *)source;
2470 target[3] = (bitmapV5Header->bV5AlphaMask) ?
uint8_t(
quad->rgbReserved) : 255;
2474 else if (bitmapV5Header->bV5Compression == BI_RGB && bitcount == 24) {
2475 int bytes_per_row = ((((width * bitcount) + 31) & ~31) >> 3);
2476 int slack = bytes_per_row - (width * 3);
2477 for (
int h = 0; h < height; h++, source += slack) {
2478 for (
int w = 0;
w < width;
w++, target += 4, source += 3) {
2479 RGBTRIPLE *
triple = (RGBTRIPLE *)source;
2488 GlobalUnlock(hGlobal);
2495 HANDLE hGlobal = GetClipboardData(
format);
2496 if (hGlobal ==
nullptr) {
2500 LPVOID pMem = GlobalLock(hGlobal);
2505 uint *rgba =
nullptr;
2508 (
uchar *)pMem, GlobalSize(hGlobal),
IB_rect,
nullptr,
"<clipboard>");
2512 *r_height = ibuf->
y;
2514 rgba = (
uint *)malloc(byte_count);
2519 GlobalUnlock(hGlobal);
2525 if (!OpenClipboard(
nullptr)) {
2530 UINT cfPNG = RegisterClipboardFormat(
"PNG");
2532 for (
int cf = EnumClipboardFormats(0); cf; cf = EnumClipboardFormats(cf)) {
2533 if (
ELEM(cf, CF_DIBV5, cfPNG)) {
2536 if (cf == CF_DIBV5 || (cf == CF_BITMAP &&
format == cfPNG)) {
2541 uint *rgba =
nullptr;
2543 if (
format == CF_DIBV5) {
2546 else if (
format == cfPNG) {
2563 if (
uint64_t(width) *
uint64_t(height) > (std::numeric_limits<DWORD>::max() / 4)) {
2567 DWORD size_pixels = width * height * 4;
2569 HGLOBAL hMem = GlobalAlloc(GHND,
sizeof(BITMAPV5HEADER) + size_pixels);
2574 BITMAPV5HEADER *hdr = (BITMAPV5HEADER *)GlobalLock(hMem);
2580 hdr->bV5Size =
sizeof(BITMAPV5HEADER);
2581 hdr->bV5Width = width;
2582 hdr->bV5Height = height;
2584 hdr->bV5BitCount = 32;
2585 hdr->bV5SizeImage = size_pixels;
2586 hdr->bV5Compression = BI_BITFIELDS;
2587 hdr->bV5RedMask = 0x000000ff;
2588 hdr->bV5GreenMask = 0x0000ff00;
2589 hdr->bV5BlueMask = 0x00ff0000;
2590 hdr->bV5AlphaMask = 0xff000000;
2591 hdr->bV5CSType = LCS_sRGB;
2592 hdr->bV5Intent = LCS_GM_IMAGES;
2593 hdr->bV5ClrUsed = 0;
2595 memcpy((
char *)hdr +
sizeof(BITMAPV5HEADER), rgba, size_pixels);
2599 if (!SetClipboardData(CF_DIBV5, hMem)) {
2609 UINT cf = RegisterClipboardFormat(
"PNG");
2626 LPVOID pMem = GlobalLock(hMem);
2638 if (!SetClipboardData(cf, hMem)) {
2648 if (!OpenClipboard(
nullptr) || !EmptyClipboard()) {
2665 const char *message,
2666 const char *help_label,
2667 const char *continue_label,
2676 int nButtonPressed = 0;
2677 TASKDIALOGCONFIG config = {0};
2678 const TASKDIALOG_BUTTON buttons[] = {{IDOK, help_label_16}, {IDCONTINUE, continue_label_16}};
2680 config.cbSize =
sizeof(config);
2681 config.hInstance = 0;
2682 config.dwCommonButtons = 0;
2685 TD_INFORMATION_ICON);
2686 config.pszWindowTitle =
L"Blender";
2687 config.pszMainInstruction = title_16;
2688 config.pszContent = message_16;
2689 const bool has_link = link && strlen(link);
2690 config.pButtons = has_link ? buttons : buttons + 1;
2691 config.cButtons = has_link ? 2 : 1;
2693 TaskDialogIndirect(&config, &nButtonPressed,
nullptr,
nullptr);
2694 switch (nButtonPressed) {
2696 ShellExecute(
nullptr,
"open", link,
nullptr,
nullptr, SW_SHOWNORMAL);
2704 free((
void *)title_16);
2705 free((
void *)message_16);
2706 free((
void *)help_label_16);
2707 free((
void *)continue_label_16);
2717 PROCESSENTRY32 pe32 = {0};
2718 DWORD ppid = 0, pid = GetCurrentProcessId();
2719 snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
2720 if (snapshot == INVALID_HANDLE_VALUE) {
2723 pe32.dwSize =
sizeof(pe32);
2724 if (!Process32First(snapshot, &pe32)) {
2725 CloseHandle(snapshot);
2729 if (pe32.th32ProcessID == pid) {
2730 ppid = pe32.th32ParentProcessID;
2733 }
while (Process32Next(snapshot, &pe32));
2734 CloseHandle(snapshot);
2740 bool result =
false;
2741 HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, pid);
2743 GetModuleFileNameEx(handle, 0, buffer, max_len);
2746 CloseHandle(handle);
2752 HWND hwnd = GetConsoleWindow();
2755 DWORD pid = (DWORD)-1;
2757 char parent_name[MAX_PATH];
2758 bool start_from_launcher =
false;
2760 GetWindowThreadProcessId(hwnd, &pid);
2762 char *filename = strrchr(parent_name,
'\\');
2763 if (filename !=
nullptr) {
2764 start_from_launcher = strstr(filename,
"blender.exe") !=
nullptr;
2769 if (pid != (start_from_launcher ? ppid : GetCurrentProcessId())) {
2779 HWND wnd = GetConsoleWindow();
2784 ShowWindow(wnd, SW_HIDE);
2790 ShowWindow(wnd, SW_HIDE);
2795 ShowWindow(wnd, SW_SHOW);
2797 DeleteMenu(GetSystemMenu(wnd,
FALSE), SC_CLOSE, MF_BYCOMMAND);
2806 DeleteMenu(GetSystemMenu(wnd,
FALSE), SC_CLOSE, MF_BYCOMMAND);
void BLI_kdtree_nd_ free(KDTree *tree)
#define GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY
#define GHOST_PRINTF(x,...)
#define GHOST_ASSERT(x, info)
std::array< GHOST_NDOF_ButtonT, 6 > NDOF_Button_Array
static void initRawInput()
static bool putClipboardImageDibV5(uint *rgba, int width, int height)
static uint * getClipboardImageImBuf(int *r_width, int *r_height, UINT format)
static const std::map< uint16_t, GHOST_NDOF_ButtonT > longButtonHIDsToGHOST_NDOFButtons
static GHOST_NDOF_ButtonT translateLongButtonToNDOFButton(uint16_t longKey)
BOOL(API * GHOST_WIN32_EnableNonClientDpiScaling)(HWND)
static bool isStartedFromCommandPrompt()
static uint * getClipboardImageDibV5(int *r_width, int *r_height)
static bool putClipboardImagePNG(uint *rgba, int width, int height)
static uint64_t getMessageTime(GHOST_SystemWin32 *system)
static DWORD GetParentProcessID(void)
static bool getProcessName(int pid, char *buffer, int max_len)
@ GHOST_kTrackpadEventMagnify
@ GHOST_kTrackpadEventScroll
@ GHOST_kWindowStateMinimized
@ GHOST_kStandardCursorDefault
@ GHOST_NDOF_BUTTON_TILT_CCW
@ GHOST_NDOF_BUTTON_SAVE_V1
@ GHOST_NDOF_BUTTON_ROLL_CCW
@ GHOST_NDOF_BUTTON_SPIN_CCW
@ GHOST_NDOF_BUTTON_SAVE_V3
@ GHOST_NDOF_BUTTON_SAVE_V2
@ GHOST_NDOF_BUTTON_BOTTOM
@ GHOST_kEventWindowClose
@ GHOST_kEventImeComposition
@ GHOST_kEventWindowActivate
@ GHOST_kEventWindowUpdate
@ GHOST_kEventWindowDeactivate
@ GHOST_kEventImeCompositionStart
@ GHOST_kEventImeCompositionEnd
@ GHOST_kEventWindowDPIHintChanged
static const GHOST_TabletData GHOST_TABLET_DATA_NONE
#define GHOST_KEY_MODIFIER_CHECK(key)
@ GHOST_kCapabilityPrimaryClipboard
#define GHOST_CAPABILITY_FLAG_ALL
@ GHOST_kKeyNumpadAsterisk
@ GHOST_kModifierKeyRightControl
@ GHOST_kModifierKeyLeftControl
@ GHOST_kModifierKeyRightAlt
@ GHOST_kModifierKeyRightShift
@ GHOST_kModifierKeyLeftAlt
@ GHOST_kModifierKeyLeftShift
@ GHOST_kModifierKeyLeftOS
@ GHOST_kModifierKeyRightOS
@ GHOST_kButtonMaskButton4
@ GHOST_kButtonMaskButton5
@ GHOST_kButtonMaskMiddle
GHOST_TConsoleWindowState
@ GHOST_kConsoleWindowStateShow
@ GHOST_kConsoleWindowStateHideForNonConsoleLaunch
@ GHOST_kConsoleWindowStateHide
@ GHOST_kConsoleWindowStateToggle
@ GHOST_kTabletWinPointer
#define GET_POINTERID_WPARAM(wParam)
#define WINTAB_PRINTF(x,...)
Contains defines and structs used throughout the imbuf module.
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)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
SIMD_FORCE_INLINE btScalar triple(const btVector3 &v1, const btVector3 &v2) const
virtual GHOST_TSuccess initialize()
virtual GHOST_TSuccess getNumDisplays(uint8_t &numDisplays) const
void removeTypeEvents(GHOST_TEventType type, const GHOST_IWindow *window=nullptr)
static GHOST_ISystem * getSystem()
GHOST_TSuccess setCursorPosition(int32_t x, int32_t y)
uint64_t getMilliSeconds() const
void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const
GHOST_TKey hardKey(RAWINPUT const &raw, bool *r_key_down)
uint * getClipboardImage(int *r_width, int *r_height) const
void setTabletAPI(GHOST_TTabletAPI api) override
static void processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam)
static GHOST_EventButton * processButtonEvent(GHOST_TEventType type, GHOST_WindowWin32 *window, GHOST_TButton mask)
GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const
GHOST_TKey processSpecialKey(short vKey, short scanCode) const
GHOST_TSuccess hasClipboardImage() const
static GHOST_Event * processWindowSizeEvent(GHOST_WindowWin32 *window)
GHOST_TKey convertKey(short vKey, short ScanCode, short extend) const
GHOST_IContext * createOffscreenContext(GHOST_GPUSettings gpuSettings)
void putClipboard(const char *buffer, bool selection) const
static GHOST_EventCursor * processCursorEvent(GHOST_WindowWin32 *window, const int32_t screen_co[2])
GHOST_IWindow * createWindow(const char *title, int32_t left, int32_t top, uint32_t width, uint32_t height, GHOST_TWindowState state, GHOST_GPUSettings gpuSettings, const bool exclusive=false, const bool is_dialog=false, const GHOST_IWindow *parentWindow=0)
static GHOST_ContextD3D * createOffscreenContextD3D()
bool processEvents(bool waitForEvent)
char * getClipboard(bool selection) const
static GHOST_TSuccess disposeContextD3D(GHOST_ContextD3D *context)
static void processWintabEvent(GHOST_WindowWin32 *window)
uint64_t performanceCounterToMillis(__int64 perf_ticks) const
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const
GHOST_TSuccess putClipboardImage(uint *rgba, int width, int height) const
static GHOST_EventKey * processKeyEvent(GHOST_WindowWin32 *window, RAWINPUT const &raw)
void initDebug(GHOST_Debug debug) override
void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const
GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const
static void processMinMaxInfo(MINMAXINFO *minmax)
bool setConsoleWindowState(GHOST_TConsoleWindowState action)
GHOST_TSuccess getPixelAtCursor(float r_color[3]) const
static GHOST_Event * processWindowEvent(GHOST_TEventType type, GHOST_WindowWin32 *window)
uint8_t getNumDisplays() const
static void processPointerEvent(UINT type, GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam, bool &eventhandled)
GHOST_TSuccess disposeContext(GHOST_IContext *context)
void handleKeyboardChange()
GHOST_TCapabilityFlag getCapabilities() 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)
bool m_hasPerformanceCounter
GHOST_IWindow * getWindowUnderCursor(int32_t, int32_t)
GHOST_EventManager * getEventManager() const
GHOST_WindowManager * getWindowManager() const
virtual GHOST_TSuccess exit()
GHOST_TSuccess pushEvent(const GHOST_IEvent *event)
bool m_multitouchGestures
virtual GHOST_TSuccess init()
virtual void setTabletAPI(GHOST_TTabletAPI api)
GHOST_TimerManager * getTimerManager() const
GHOST_WindowManager * m_windowManager
virtual void initDebug(GHOST_Debug debug)
GHOST_DisplayManager * m_displayManager
GHOST_EventManager * m_eventManager
bool fireTimers(uint64_t time)
GHOST_TSuccess addWindow(GHOST_IWindow *window)
GHOST_IWindow * getWindowAssociatedWithOSWindow(const void *osWindow)
const std::vector< GHOST_IWindow * > & getWindows() const
GHOST_IWindow * getActiveWindow() const
GHOST_TSuccess setActiveWindow(GHOST_IWindow *window)
void resetPointerPenInfo()
GHOST_TTrackpadInfo getTrackpadInfo()
void updateDirectManipulation()
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)
void loadWintab(bool enable)
GHOST_TabletData getTabletData()
GHOST_Wintab * getWintab() const
void updateMouseCapture(GHOST_MouseCaptureEventWin32 event)
GHOST_TSuccess setState(GHOST_TWindowState state)
void getClientBounds(GHOST_Rect &bounds) const
void onPointerHitTest(WPARAM wParam)
void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
GHOST_TWindowState getState() const
GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds) const override
void setCursorGrabAccum(int32_t x, int32_t y)
GHOST_TAxisFlag getCursorGrabAxis() const
GHOST_TStandardCursor getCursorShape() const override
bool getCursorVisibility() const override
GHOST_TGrabCursorMode getCursorGrabMode() const
bool getCursorGrabModeIsWarp() const
void getCursorGrabAccum(int32_t &x, int32_t &y) const
void mapWintabToSysCoordinates(int x_in, int y_in, int &x_out, int &y_out)
GHOST_TabletData getLastTabletData()
void getInput(std::vector< GHOST_WintabInfoWin32 > &outWintabInfo)
void processInfoChange(LPARAM lParam)
bool testCoordinates(int sysX, int sysY, int wtX, int wtY)
static void setDebug(bool debug)
blender::gpu::Batch * quad
struct ImBuf * IMB_ibImageFromMemory(const unsigned char *, size_t, int, char[IM_MAX_SPACE], const char *)
bool IMB_saveiff(struct ImBuf *, const char *, int)
struct ImBuf * IMB_allocFromBuffer(const uint8_t *, const float *, unsigned int, unsigned int, unsigned int)
void IMB_freeImBuf(ImBuf *)
unsigned __int64 uint64_t
GHOST_TDrawingContextType context_type
GHOST_GPUDevice preferred_device
void set(GHOST_TModifierKey mask, bool down)
bool isScrollDirectionInverted
ImbFormatOptions foptions
ImBufByteBuffer byte_buffer
unsigned int encoded_buffer_size
ImBufByteBuffer encoded_buffer
wchar_t * alloc_utf16_from_8(const char *in8, size_t add)
char * alloc_utf_8_from_16(const wchar_t *in16, size_t add)
int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16)
int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8)
size_t count_utf_16_from_8(const char *string8)
#define UTF16_ENCODE(in8str)
#define UTF16_UN_ENCODE(in8str)
ccl_device_inline int abs(int x)