diff options
Diffstat (limited to 'platform/windows/os_windows.cpp')
-rw-r--r-- | platform/windows/os_windows.cpp | 2604 |
1 files changed, 6 insertions, 2598 deletions
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index c49f096ec5..f78c87be93 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -37,15 +37,6 @@ #include "core/debugger/script_debugger.h" #include "core/io/marshalls.h" #include "core/version_generated.gen.h" - -#if defined(OPENGL_ENABLED) -#include "drivers/gles2/rasterizer_gles2.h" -#endif - -#if defined(VULKAN_ENABLED) -#include "servers/visual/rasterizer_rd/rasterizer_rd.h" -#endif - #include "drivers/windows/dir_access_windows.h" #include "drivers/windows/file_access_windows.h" #include "drivers/windows/rw_lock_windows.h" @@ -53,6 +44,7 @@ #include "joypad_windows.h" #include "lang_table.h" #include "main/main.h" +#include "platform/windows/display_server_windows.h" #include "servers/audio_server.h" #include "servers/visual/visual_server_raster.h" #include "servers/visual/visual_server_wrap_mt.h" @@ -86,30 +78,6 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; #define GetProcAddress (void *)GetProcAddress #endif -typedef struct { - int count; - int screen; - Size2 size; -} EnumSizeData; - -typedef struct { - int count; - int screen; - Point2 pos; -} EnumPosData; - -static BOOL CALLBACK _MonitorEnumProcSize(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - - EnumSizeData *data = (EnumSizeData *)dwData; - if (data->count == data->screen) { - data->size.x = lprcMonitor->right - lprcMonitor->left; - data->size.y = lprcMonitor->bottom - lprcMonitor->top; - } - - data->count++; - return TRUE; -} - #ifdef DEBUG_ENABLED static String format_error_message(DWORD id) { @@ -125,8 +93,6 @@ static String format_error_message(DWORD id) { } #endif // DEBUG_ENABLED -extern HINSTANCE godot_hinstance; - void RedirectIOToConsole() { int hConHandle; @@ -208,24 +174,16 @@ BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType) { } } -GetPointerTypePtr OS_Windows::win8p_GetPointerType = NULL; -GetPointerPenInfoPtr OS_Windows::win8p_GetPointerPenInfo = NULL; - void OS_Windows::initialize_debugging() { SetConsoleCtrlHandler(HandlerRoutine, TRUE); } -void OS_Windows::initialize_core() { +void OS_Windows::initialize() { crash_handler.initialize(); - last_button_state = 0; - //RedirectIOToConsole(); - maximized = false; - minimized = false; - borderless = false; ThreadWindows::make_default(); RWLockWindows::make_default(); @@ -255,1371 +213,9 @@ void OS_Windows::initialize_core() { process_map = memnew((Map<ProcessID, ProcessInfo>)); IP_Unix::make_default(); - - cursor_shape = CURSOR_ARROW; -} - -bool OS_Windows::can_draw() const { - - return !minimized; -}; - -#define MI_WP_SIGNATURE 0xFF515700 -#define SIGNATURE_MASK 0xFFFFFF00 -// Keeping the name suggested by Microsoft, but this macro really answers: -// Is this mouse event emulated from touch or pen input? -#define IsPenEvent(dw) (((dw)&SIGNATURE_MASK) == MI_WP_SIGNATURE) -// This one tells whether the event comes from touchscreen (and not from pen) -#define IsTouchEvent(dw) (IsPenEvent(dw) && ((dw)&0x80)) - -void OS_Windows::_touch_event(bool p_pressed, float p_x, float p_y, int idx) { - - // Defensive - if (touch_state.has(idx) == p_pressed) - return; - - if (p_pressed) { - touch_state.insert(idx, Vector2(p_x, p_y)); - } else { - touch_state.erase(idx); - } - - Ref<InputEventScreenTouch> event; - event.instance(); - event->set_index(idx); - event->set_pressed(p_pressed); - event->set_position(Vector2(p_x, p_y)); - - if (main_loop) { - input->accumulate_input_event(event); - } -}; - -void OS_Windows::_drag_event(float p_x, float p_y, int idx) { - - Map<int, Vector2>::Element *curr = touch_state.find(idx); - // Defensive - if (!curr) - return; - - if (curr->get() == Vector2(p_x, p_y)) - return; - - Ref<InputEventScreenDrag> event; - event.instance(); - event->set_index(idx); - event->set_position(Vector2(p_x, p_y)); - event->set_relative(Vector2(p_x, p_y) - curr->get()); - - if (main_loop) - input->accumulate_input_event(event); - - curr->get() = Vector2(p_x, p_y); -}; - -LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - - if (drop_events) { - - if (user_proc) { - - return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam); - } else { - return DefWindowProcW(hWnd, uMsg, wParam, lParam); - } - }; - - switch (uMsg) // Check For Windows Messages - { - case WM_SETFOCUS: { - window_has_focus = true; - - // Restore mouse mode - _set_mouse_mode_impl(mouse_mode); - - break; - } - case WM_KILLFOCUS: { - window_has_focus = false; - - // Release capture unconditionally because it can be set due to dragging, in addition to captured mode - ReleaseCapture(); - - // Release every touch to avoid sticky points - for (Map<int, Vector2>::Element *E = touch_state.front(); E; E = E->next()) { - _touch_event(false, E->get().x, E->get().y, E->key()); - } - touch_state.clear(); - - break; - } - case WM_ACTIVATE: // Watch For Window Activate Message - { - minimized = HIWORD(wParam) != 0; - if (!main_loop) { - return 0; - }; - if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) { - - main_loop->notification(NOTIFICATION_WM_FOCUS_IN); - window_focused = true; - alt_mem = false; - control_mem = false; - shift_mem = false; - } else { // WM_INACTIVE - input->release_pressed_events(); - main_loop->notification(NOTIFICATION_WM_FOCUS_OUT); - window_focused = false; - alt_mem = false; - }; - - return 0; // Return To The Message Loop - } - case WM_GETMINMAXINFO: { - if (video_mode.resizable && !video_mode.fullscreen) { - Size2 decor = get_real_window_size() - get_window_size(); // Size of window decorations - MINMAXINFO *min_max_info = (MINMAXINFO *)lParam; - if (min_size != Size2()) { - min_max_info->ptMinTrackSize.x = min_size.x + decor.x; - min_max_info->ptMinTrackSize.y = min_size.y + decor.y; - } - if (max_size != Size2()) { - min_max_info->ptMaxTrackSize.x = max_size.x + decor.x; - min_max_info->ptMaxTrackSize.y = max_size.y + decor.y; - } - return 0; - } else { - break; - } - } - case WM_PAINT: - - Main::force_redraw(); - break; - - case WM_SYSCOMMAND: // Intercept System Commands - { - switch (wParam) // Check System Calls - { - case SC_SCREENSAVE: // Screensaver Trying To Start? - case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? - return 0; // Prevent From Happening - case SC_KEYMENU: - if ((lParam >> 16) <= 0) - return 0; - } - break; // Exit - } - - case WM_CLOSE: // Did We Receive A Close Message? - { - if (main_loop) - main_loop->notification(NOTIFICATION_WM_CLOSE_REQUEST); - //force_quit=true; - return 0; // Jump Back - } - case WM_MOUSELEAVE: { - - old_invalid = true; - outside = true; - if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED) - main_loop->notification(NOTIFICATION_WM_MOUSE_EXIT); - - } break; - case WM_INPUT: { - if (mouse_mode != MOUSE_MODE_CAPTURED || !use_raw_input) { - break; - } - - UINT dwSize; - - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); - LPBYTE lpb = new BYTE[dwSize]; - if (lpb == NULL) { - return 0; - } - - if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) - OutputDebugString(TEXT("GetRawInputData does not return correct size !\n")); - - RAWINPUT *raw = (RAWINPUT *)lpb; - - if (raw->header.dwType == RIM_TYPEMOUSE) { - Ref<InputEventMouseMotion> mm; - mm.instance(); - - mm->set_control(control_mem); - mm->set_shift(shift_mem); - mm->set_alt(alt_mem); - - mm->set_button_mask(last_button_state); - - Point2i c(video_mode.width / 2, video_mode.height / 2); - - // centering just so it works as before - POINT pos = { (int)c.x, (int)c.y }; - ClientToScreen(hWnd, &pos); - SetCursorPos(pos.x, pos.y); - - mm->set_position(c); - mm->set_global_position(c); - input->set_mouse_position(c); - mm->set_speed(Vector2(0, 0)); - - if (raw->data.mouse.usFlags == MOUSE_MOVE_RELATIVE) { - mm->set_relative(Vector2(raw->data.mouse.lLastX, raw->data.mouse.lLastY)); - - } else if (raw->data.mouse.usFlags == MOUSE_MOVE_ABSOLUTE) { - - int nScreenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN); - int nScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN); - int nScreenLeft = GetSystemMetrics(SM_XVIRTUALSCREEN); - int nScreenTop = GetSystemMetrics(SM_YVIRTUALSCREEN); - - Vector2 abs_pos( - (double(raw->data.mouse.lLastX) - 65536.0 / (nScreenWidth)) * nScreenWidth / 65536.0 + nScreenLeft, - (double(raw->data.mouse.lLastY) - 65536.0 / (nScreenHeight)) * nScreenHeight / 65536.0 + nScreenTop); - - POINT coords; //client coords - coords.x = abs_pos.x; - coords.y = abs_pos.y; - - ScreenToClient(hWnd, &coords); - - mm->set_relative(Vector2(coords.x - old_x, coords.y - old_y)); - old_x = coords.x; - old_y = coords.y; - - /*Input.mi.dx = (int)((((double)(pos.x)-nScreenLeft) * 65536) / nScreenWidth + 65536 / (nScreenWidth)); - Input.mi.dy = (int)((((double)(pos.y)-nScreenTop) * 65536) / nScreenHeight + 65536 / (nScreenHeight)); - */ - } - - if (window_has_focus && main_loop && mm->get_relative() != Vector2()) - input->accumulate_input_event(mm); - } - delete[] lpb; - } break; - case WM_POINTERUPDATE: { - if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) { - break; - } - - if (!win8p_GetPointerType || !win8p_GetPointerPenInfo) { - break; - } - - uint32_t pointer_id = LOWORD(wParam); - POINTER_INPUT_TYPE pointer_type = PT_POINTER; - if (!win8p_GetPointerType(pointer_id, &pointer_type)) { - break; - } - - if (pointer_type != PT_PEN) { - break; - } - - POINTER_PEN_INFO pen_info; - if (!win8p_GetPointerPenInfo(pointer_id, &pen_info)) { - break; - } - - if (input->is_emulating_mouse_from_touch()) { - // Universal translation enabled; ignore OS translation - LPARAM extra = GetMessageExtraInfo(); - if (IsTouchEvent(extra)) { - break; - } - } - - if (outside) { - //mouse enter - - if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED) - main_loop->notification(NOTIFICATION_WM_MOUSE_ENTER); - - CursorShape c = cursor_shape; - cursor_shape = CURSOR_MAX; - set_cursor_shape(c); - outside = false; - - //Once-Off notification, must call again.... - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof(TRACKMOUSEEVENT); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = hWnd; - tme.dwHoverTime = HOVER_DEFAULT; - TrackMouseEvent(&tme); - } - - // Don't calculate relative mouse movement if we don't have focus in CAPTURED mode. - if (!window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) - break; - - Ref<InputEventMouseMotion> mm; - mm.instance(); - - mm->set_pressure(pen_info.pressure ? (float)pen_info.pressure / 1024 : 0); - mm->set_tilt(Vector2(pen_info.tiltX ? (float)pen_info.tiltX / 90 : 0, pen_info.tiltY ? (float)pen_info.tiltY / 90 : 0)); - - mm->set_control((wParam & MK_CONTROL) != 0); - mm->set_shift((wParam & MK_SHIFT) != 0); - mm->set_alt(alt_mem); - - mm->set_button_mask(last_button_state); - - POINT coords; //client coords - coords.x = GET_X_LPARAM(lParam); - coords.y = GET_Y_LPARAM(lParam); - - ScreenToClient(hWnd, &coords); - - mm->set_position(Vector2(coords.x, coords.y)); - mm->set_global_position(Vector2(coords.x, coords.y)); - - if (mouse_mode == MOUSE_MODE_CAPTURED) { - - Point2i c(video_mode.width / 2, video_mode.height / 2); - old_x = c.x; - old_y = c.y; - - if (mm->get_position() == c) { - center = c; - return 0; - } - - Point2i ncenter = mm->get_position(); - center = ncenter; - POINT pos = { (int)c.x, (int)c.y }; - ClientToScreen(hWnd, &pos); - SetCursorPos(pos.x, pos.y); - } - - input->set_mouse_position(mm->get_position()); - mm->set_speed(input->get_last_mouse_speed()); - - if (old_invalid) { - - old_x = mm->get_position().x; - old_y = mm->get_position().y; - old_invalid = false; - } - - mm->set_relative(Vector2(mm->get_position() - Vector2(old_x, old_y))); - old_x = mm->get_position().x; - old_y = mm->get_position().y; - if (window_has_focus && main_loop) - input->parse_input_event(mm); - - return 0; //Pointer event handled return 0 to avoid duplicate WM_MOUSEMOVE event - } break; - case WM_MOUSEMOVE: { - if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) { - break; - } - - if (input->is_emulating_mouse_from_touch()) { - // Universal translation enabled; ignore OS translation - LPARAM extra = GetMessageExtraInfo(); - if (IsTouchEvent(extra)) { - break; - } - } - - if (outside) { - //mouse enter - - if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED) - main_loop->notification(NOTIFICATION_WM_MOUSE_ENTER); - - CursorShape c = cursor_shape; - cursor_shape = CURSOR_MAX; - set_cursor_shape(c); - outside = false; - - //Once-Off notification, must call again.... - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof(TRACKMOUSEEVENT); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = hWnd; - tme.dwHoverTime = HOVER_DEFAULT; - TrackMouseEvent(&tme); - } - - // Don't calculate relative mouse movement if we don't have focus in CAPTURED mode. - if (!window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) - break; - - Ref<InputEventMouseMotion> mm; - mm.instance(); - - mm->set_control((wParam & MK_CONTROL) != 0); - mm->set_shift((wParam & MK_SHIFT) != 0); - mm->set_alt(alt_mem); - - mm->set_button_mask(last_button_state); - - mm->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); - mm->set_global_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); - - if (mouse_mode == MOUSE_MODE_CAPTURED) { - - Point2i c(video_mode.width / 2, video_mode.height / 2); - old_x = c.x; - old_y = c.y; - - if (mm->get_position() == c) { - center = c; - return 0; - } - - Point2i ncenter = mm->get_position(); - center = ncenter; - POINT pos = { (int)c.x, (int)c.y }; - ClientToScreen(hWnd, &pos); - SetCursorPos(pos.x, pos.y); - } - - input->set_mouse_position(mm->get_position()); - mm->set_speed(input->get_last_mouse_speed()); - - if (old_invalid) { - - old_x = mm->get_position().x; - old_y = mm->get_position().y; - old_invalid = false; - } - - mm->set_relative(Vector2(mm->get_position() - Vector2(old_x, old_y))); - old_x = mm->get_position().x; - old_y = mm->get_position().y; - if (window_has_focus && main_loop) - input->accumulate_input_event(mm); - - } break; - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - if (input->is_emulating_mouse_from_touch()) { - // Universal translation enabled; ignore OS translations for left button - LPARAM extra = GetMessageExtraInfo(); - if (IsTouchEvent(extra)) { - break; - } - } - [[fallthrough]]; - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_MOUSEWHEEL: - case WM_MOUSEHWHEEL: - case WM_LBUTTONDBLCLK: - case WM_MBUTTONDBLCLK: - case WM_RBUTTONDBLCLK: - case WM_XBUTTONDBLCLK: - case WM_XBUTTONDOWN: - case WM_XBUTTONUP: { - - Ref<InputEventMouseButton> mb; - mb.instance(); - - switch (uMsg) { - case WM_LBUTTONDOWN: { - mb->set_pressed(true); - mb->set_button_index(1); - } break; - case WM_LBUTTONUP: { - mb->set_pressed(false); - mb->set_button_index(1); - } break; - case WM_MBUTTONDOWN: { - mb->set_pressed(true); - mb->set_button_index(3); - } break; - case WM_MBUTTONUP: { - mb->set_pressed(false); - mb->set_button_index(3); - } break; - case WM_RBUTTONDOWN: { - mb->set_pressed(true); - mb->set_button_index(2); - } break; - case WM_RBUTTONUP: { - mb->set_pressed(false); - mb->set_button_index(2); - } break; - case WM_LBUTTONDBLCLK: { - mb->set_pressed(true); - mb->set_button_index(1); - mb->set_doubleclick(true); - } break; - case WM_RBUTTONDBLCLK: { - mb->set_pressed(true); - mb->set_button_index(2); - mb->set_doubleclick(true); - } break; - case WM_MBUTTONDBLCLK: { - mb->set_pressed(true); - mb->set_button_index(3); - mb->set_doubleclick(true); - } break; - case WM_MOUSEWHEEL: { - - mb->set_pressed(true); - int motion = (short)HIWORD(wParam); - if (!motion) - return 0; - - if (motion > 0) - mb->set_button_index(BUTTON_WHEEL_UP); - else - mb->set_button_index(BUTTON_WHEEL_DOWN); - - } break; - case WM_MOUSEHWHEEL: { - - mb->set_pressed(true); - int motion = (short)HIWORD(wParam); - if (!motion) - return 0; - - if (motion < 0) { - mb->set_button_index(BUTTON_WHEEL_LEFT); - mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA)); - } else { - mb->set_button_index(BUTTON_WHEEL_RIGHT); - mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA)); - } - } break; - case WM_XBUTTONDOWN: { - - mb->set_pressed(true); - if (HIWORD(wParam) == XBUTTON1) - mb->set_button_index(BUTTON_XBUTTON1); - else - mb->set_button_index(BUTTON_XBUTTON2); - } break; - case WM_XBUTTONUP: { - - mb->set_pressed(false); - if (HIWORD(wParam) == XBUTTON1) - mb->set_button_index(BUTTON_XBUTTON1); - else - mb->set_button_index(BUTTON_XBUTTON2); - } break; - case WM_XBUTTONDBLCLK: { - - mb->set_pressed(true); - if (HIWORD(wParam) == XBUTTON1) - mb->set_button_index(BUTTON_XBUTTON1); - else - mb->set_button_index(BUTTON_XBUTTON2); - mb->set_doubleclick(true); - } break; - default: { - return 0; - } - } - - mb->set_control((wParam & MK_CONTROL) != 0); - mb->set_shift((wParam & MK_SHIFT) != 0); - mb->set_alt(alt_mem); - //mb->get_alt()=(wParam&MK_MENU)!=0; - if (mb->is_pressed()) - last_button_state |= (1 << (mb->get_button_index() - 1)); - else - last_button_state &= ~(1 << (mb->get_button_index() - 1)); - mb->set_button_mask(last_button_state); - - mb->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); - - if (mouse_mode == MOUSE_MODE_CAPTURED && !use_raw_input) { - - mb->set_position(Vector2(old_x, old_y)); - } - - if (uMsg != WM_MOUSEWHEEL && uMsg != WM_MOUSEHWHEEL) { - if (mb->is_pressed()) { - - if (++pressrc > 0 && mouse_mode != MOUSE_MODE_CAPTURED) - SetCapture(hWnd); - } else { - - if (--pressrc <= 0) { - if (mouse_mode != MOUSE_MODE_CAPTURED) { - ReleaseCapture(); - } - pressrc = 0; - } - } - } else { - // for reasons unknown to mankind, wheel comes in screen coordinates - POINT coords; - coords.x = mb->get_position().x; - coords.y = mb->get_position().y; - - ScreenToClient(hWnd, &coords); - - mb->set_position(Vector2(coords.x, coords.y)); - } - - mb->set_global_position(mb->get_position()); - - if (main_loop) { - input->accumulate_input_event(mb); - if (mb->is_pressed() && mb->get_button_index() > 3 && mb->get_button_index() < 8) { - //send release for mouse wheel - Ref<InputEventMouseButton> mbd = mb->duplicate(); - last_button_state &= ~(1 << (mbd->get_button_index() - 1)); - mbd->set_button_mask(last_button_state); - mbd->set_pressed(false); - input->accumulate_input_event(mbd); - } - } - } break; - - case WM_MOVE: { - if (!IsIconic(hWnd)) { - int x = LOWORD(lParam); - int y = HIWORD(lParam); - last_pos = Point2(x, y); - } - } break; - - case WM_SIZE: { - // Ignore size when a SIZE_MINIMIZED event is triggered - if (wParam != SIZE_MINIMIZED) { - int window_w = LOWORD(lParam); - int window_h = HIWORD(lParam); - if (window_w > 0 && window_h > 0 && !preserve_window_size) { - video_mode.width = window_w; - video_mode.height = window_h; - } else { - preserve_window_size = false; - set_window_size(Size2(video_mode.width, video_mode.height)); - } -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - context_vulkan->window_resize(0, video_mode.width, video_mode.height); - } -#endif - } - - if (wParam == SIZE_MAXIMIZED) { - maximized = true; - minimized = false; - } else if (wParam == SIZE_MINIMIZED) { - maximized = false; - minimized = true; - } else if (wParam == SIZE_RESTORED) { - maximized = false; - minimized = false; - } - if (is_layered_allowed() && layered_window) { - DeleteObject(hBitmap); - - RECT r; - GetWindowRect(hWnd, &r); - dib_size = Size2i(r.right - r.left, r.bottom - r.top); - - BITMAPINFO bmi; - ZeroMemory(&bmi, sizeof(BITMAPINFO)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = dib_size.x; - bmi.bmiHeader.biHeight = dib_size.y; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = dib_size.x * dib_size.y * 4; - hBitmap = CreateDIBSection(hDC_dib, &bmi, DIB_RGB_COLORS, (void **)&dib_data, NULL, 0x0); - SelectObject(hDC_dib, hBitmap); - - ZeroMemory(dib_data, dib_size.x * dib_size.y * 4); - } - //return 0; // Jump Back - } break; - - case WM_ENTERSIZEMOVE: { - input->release_pressed_events(); - move_timer_id = SetTimer(hWnd, 1, USER_TIMER_MINIMUM, (TIMERPROC)NULL); - } break; - case WM_EXITSIZEMOVE: { - KillTimer(hWnd, move_timer_id); - } break; - case WM_TIMER: { - if (wParam == move_timer_id) { - process_key_events(); - if (!Main::is_iterating()) { - Main::iteration(); - } - } - } break; - - case WM_SYSKEYDOWN: - case WM_SYSKEYUP: - case WM_KEYUP: - case WM_KEYDOWN: { - - if (wParam == VK_SHIFT) - shift_mem = uMsg == WM_KEYDOWN; - if (wParam == VK_CONTROL) - control_mem = uMsg == WM_KEYDOWN; - if (wParam == VK_MENU) { - alt_mem = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN); - if (lParam & (1 << 24)) - gr_mem = alt_mem; - } - - if (mouse_mode == MOUSE_MODE_CAPTURED) { - // When SetCapture is used, ALT+F4 hotkey is ignored by Windows, so handle it ourselves - if (wParam == VK_F4 && alt_mem && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN)) { - if (main_loop) - main_loop->notification(NOTIFICATION_WM_CLOSE_REQUEST); - } - } - /* - if (wParam==VK_WIN) TODO wtf is this? - meta_mem=uMsg==WM_KEYDOWN; - */ - [[fallthrough]]; - } - case WM_CHAR: { - - ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE); - - // Make sure we don't include modifiers for the modifier key itself. - KeyEvent ke; - ke.shift = (wParam != VK_SHIFT) ? shift_mem : false; - ke.alt = (!(wParam == VK_MENU && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN))) ? alt_mem : false; - ke.control = (wParam != VK_CONTROL) ? control_mem : false; - ke.meta = meta_mem; - ke.uMsg = uMsg; - - if (ke.uMsg == WM_SYSKEYDOWN) - ke.uMsg = WM_KEYDOWN; - if (ke.uMsg == WM_SYSKEYUP) - ke.uMsg = WM_KEYUP; - - ke.wParam = wParam; - ke.lParam = lParam; - key_event_buffer[key_event_pos++] = ke; - - } break; - case WM_INPUTLANGCHANGEREQUEST: { - - // FIXME: Do something? - } break; - - case WM_TOUCH: { - - BOOL bHandled = FALSE; - UINT cInputs = LOWORD(wParam); - PTOUCHINPUT pInputs = memnew_arr(TOUCHINPUT, cInputs); - if (pInputs) { - if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))) { - for (UINT i = 0; i < cInputs; i++) { - TOUCHINPUT ti = pInputs[i]; - POINT touch_pos = { - TOUCH_COORD_TO_PIXEL(ti.x), - TOUCH_COORD_TO_PIXEL(ti.y), - }; - ScreenToClient(hWnd, &touch_pos); - //do something with each touch input entry - if (ti.dwFlags & TOUCHEVENTF_MOVE) { - - _drag_event(touch_pos.x, touch_pos.y, ti.dwID); - } else if (ti.dwFlags & (TOUCHEVENTF_UP | TOUCHEVENTF_DOWN)) { - - _touch_event(ti.dwFlags & TOUCHEVENTF_DOWN, touch_pos.x, touch_pos.y, ti.dwID); - }; - } - bHandled = TRUE; - } else { - /* handle the error here */ - } - memdelete_arr(pInputs); - } else { - /* handle the error here, probably out of memory */ - } - if (bHandled) { - CloseTouchInputHandle((HTOUCHINPUT)lParam); - return 0; - }; - - } break; - - case WM_DEVICECHANGE: { - - joypad->probe_joypads(); - } break; - case WM_SETCURSOR: { - if (LOWORD(lParam) == HTCLIENT) { - if (window_has_focus && (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED)) { - //Hide the cursor - if (hCursor == NULL) - hCursor = SetCursor(NULL); - else - SetCursor(NULL); - } else { - if (hCursor != NULL) { - CursorShape c = cursor_shape; - cursor_shape = CURSOR_MAX; - set_cursor_shape(c); - hCursor = NULL; - } - } - } - - } break; - case WM_DROPFILES: { - - HDROP hDropInfo = (HDROP)wParam; - const int buffsize = 4096; - wchar_t buf[buffsize]; - - int fcount = DragQueryFileW(hDropInfo, 0xFFFFFFFF, NULL, 0); - - Vector<String> files; - - for (int i = 0; i < fcount; i++) { - - DragQueryFileW(hDropInfo, i, buf, buffsize); - String file = buf; - files.push_back(file); - } - - if (files.size() && main_loop) { - main_loop->drop_files(files, 0); - } - - } break; - - default: { - - if (user_proc) { - - return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam); - }; - }; - } - - return DefWindowProcW(hWnd, uMsg, wParam, lParam); -} - -LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - - OS_Windows *os_win = static_cast<OS_Windows *>(OS::get_singleton()); - if (os_win) - return os_win->WndProc(hWnd, uMsg, wParam, lParam); - else - return DefWindowProcW(hWnd, uMsg, wParam, lParam); -} - -void OS_Windows::process_key_events() { - - for (int i = 0; i < key_event_pos; i++) { - - KeyEvent &ke = key_event_buffer[i]; - switch (ke.uMsg) { - - case WM_CHAR: { - if ((i == 0 && ke.uMsg == WM_CHAR) || (i > 0 && key_event_buffer[i - 1].uMsg == WM_CHAR)) { - Ref<InputEventKey> k; - k.instance(); - - k->set_shift(ke.shift); - k->set_alt(ke.alt); - k->set_control(ke.control); - k->set_metakey(ke.meta); - k->set_pressed(true); - k->set_keycode(KeyMappingWindows::get_keysym(ke.wParam)); - k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24))); - k->set_unicode(ke.wParam); - if (k->get_unicode() && gr_mem) { - k->set_alt(false); - k->set_control(false); - } - - if (k->get_unicode() < 32) - k->set_unicode(0); - - input->accumulate_input_event(k); - } - - //do nothing - } break; - case WM_KEYUP: - case WM_KEYDOWN: { - - Ref<InputEventKey> k; - k.instance(); - - k->set_shift(ke.shift); - k->set_alt(ke.alt); - k->set_control(ke.control); - k->set_metakey(ke.meta); - - k->set_pressed(ke.uMsg == WM_KEYDOWN); - - if ((ke.lParam & (1 << 24)) && (ke.wParam == VK_RETURN)) { - // Special case for Numpad Enter key - k->set_keycode(KEY_KP_ENTER); - } else { - k->set_keycode(KeyMappingWindows::get_keysym(ke.wParam)); - } - - k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24))); - - if (i + 1 < key_event_pos && key_event_buffer[i + 1].uMsg == WM_CHAR) { - k->set_unicode(key_event_buffer[i + 1].wParam); - } - if (k->get_unicode() && gr_mem) { - k->set_alt(false); - k->set_control(false); - } - - if (k->get_unicode() < 32) - k->set_unicode(0); - - k->set_echo((ke.uMsg == WM_KEYDOWN && (ke.lParam & (1 << 30)))); - - input->accumulate_input_event(k); - - } break; - } - } - - key_event_pos = 0; -} - -enum _MonitorDpiType { - MDT_Effective_DPI = 0, - MDT_Angular_DPI = 1, - MDT_Raw_DPI = 2, - MDT_Default = MDT_Effective_DPI -}; - -static int QueryDpiForMonitor(HMONITOR hmon, _MonitorDpiType dpiType = MDT_Default) { - - int dpiX = 96, dpiY = 96; - - static HMODULE Shcore = NULL; - typedef HRESULT(WINAPI * GetDPIForMonitor_t)(HMONITOR hmonitor, _MonitorDpiType dpiType, UINT * dpiX, UINT * dpiY); - static GetDPIForMonitor_t getDPIForMonitor = NULL; - - if (Shcore == NULL) { - Shcore = LoadLibraryW(L"Shcore.dll"); - getDPIForMonitor = Shcore ? (GetDPIForMonitor_t)GetProcAddress(Shcore, "GetDpiForMonitor") : NULL; - - if ((Shcore == NULL) || (getDPIForMonitor == NULL)) { - if (Shcore) - FreeLibrary(Shcore); - Shcore = (HMODULE)INVALID_HANDLE_VALUE; - } - } - - UINT x = 0, y = 0; - HRESULT hr = E_FAIL; - if (hmon && (Shcore != (HMODULE)INVALID_HANDLE_VALUE)) { - hr = getDPIForMonitor(hmon, dpiType /*MDT_Effective_DPI*/, &x, &y); - if (SUCCEEDED(hr) && (x > 0) && (y > 0)) { - - dpiX = (int)x; - dpiY = (int)y; - } - } else { - static int overallX = 0, overallY = 0; - if (overallX <= 0 || overallY <= 0) { - HDC hdc = GetDC(NULL); - if (hdc) { - overallX = GetDeviceCaps(hdc, LOGPIXELSX); - overallY = GetDeviceCaps(hdc, LOGPIXELSY); - ReleaseDC(NULL, hdc); - } - } - if (overallX > 0 && overallY > 0) { - dpiX = overallX; - dpiY = overallY; - } - } - - return (dpiX + dpiY) / 2; -} - -typedef enum _SHC_PROCESS_DPI_AWARENESS { - SHC_PROCESS_DPI_UNAWARE = 0, - SHC_PROCESS_SYSTEM_DPI_AWARE = 1, - SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2 -} SHC_PROCESS_DPI_AWARENESS; - -int OS_Windows::get_current_video_driver() const { - return video_driver_index; -} - -Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { - main_loop = NULL; - outside = true; - window_has_focus = true; - WNDCLASSEXW wc; - - if (is_hidpi_allowed()) { - HMODULE Shcore = LoadLibraryW(L"Shcore.dll"); - - if (Shcore != NULL) { - typedef HRESULT(WINAPI * SetProcessDpiAwareness_t)(SHC_PROCESS_DPI_AWARENESS); - - SetProcessDpiAwareness_t SetProcessDpiAwareness = (SetProcessDpiAwareness_t)GetProcAddress(Shcore, "SetProcessDpiAwareness"); - - if (SetProcessDpiAwareness) { - SetProcessDpiAwareness(SHC_PROCESS_SYSTEM_DPI_AWARE); - } - } - } - - video_mode = p_desired; - //printf("**************** desired %s, mode %s\n", p_desired.fullscreen?"true":"false", video_mode.fullscreen?"true":"false"); - RECT WindowRect; - - WindowRect.left = 0; - WindowRect.right = video_mode.width; - WindowRect.top = 0; - WindowRect.bottom = video_mode.height; - - memset(&wc, 0, sizeof(WNDCLASSEXW)); - wc.cbSize = sizeof(WNDCLASSEXW); - wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; - wc.lpfnWndProc = (WNDPROC)::WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - //wc.hInstance = hInstance; - wc.hInstance = godot_hinstance ? godot_hinstance : GetModuleHandle(NULL); - wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); - wc.hCursor = NULL; //LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = NULL; - wc.lpszMenuName = NULL; - wc.lpszClassName = L"Engine"; - - if (!RegisterClassExW(&wc)) { - MessageBox(NULL, "Failed To Register The Window Class.", "ERROR", MB_OK | MB_ICONEXCLAMATION); - return ERR_UNAVAILABLE; - } - - use_raw_input = true; - - RAWINPUTDEVICE Rid[1]; - - Rid[0].usUsagePage = 0x01; - Rid[0].usUsage = 0x02; - Rid[0].dwFlags = 0; - Rid[0].hwndTarget = 0; - - if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) { - //registration failed. - use_raw_input = false; - } - - pre_fs_valid = true; - if (video_mode.fullscreen) { - - /* this returns DPI unaware size, commenting - DEVMODE current; - memset(¤t, 0, sizeof(current)); - EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, ¤t); - - WindowRect.right = current.dmPelsWidth; - WindowRect.bottom = current.dmPelsHeight; - - */ - - EnumSizeData data = { 0, 0, Size2() }; - EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcSize, (LPARAM)&data); - - WindowRect.right = data.size.width; - WindowRect.bottom = data.size.height; - - /* DEVMODE dmScreenSettings; - memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); - dmScreenSettings.dmSize=sizeof(dmScreenSettings); - dmScreenSettings.dmPelsWidth = video_mode.width; - dmScreenSettings.dmPelsHeight = video_mode.height; - dmScreenSettings.dmBitsPerPel = current.dmBitsPerPel; - dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; - - LONG err = ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN); - if (err!=DISP_CHANGE_SUCCESSFUL) { - - video_mode.fullscreen=false; - }*/ - pre_fs_valid = false; - } - - DWORD dwExStyle; - DWORD dwStyle; - - if (video_mode.fullscreen || video_mode.borderless_window) { - - dwExStyle = WS_EX_APPWINDOW; - dwStyle = WS_POPUP; - - } else { - dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; - dwStyle = WS_OVERLAPPEDWINDOW; - if (!video_mode.resizable) { - dwStyle &= ~WS_THICKFRAME; - dwStyle &= ~WS_MAXIMIZEBOX; - } - } - - AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); - - char *windowid; -#ifdef MINGW_ENABLED - windowid = getenv("GODOT_WINDOWID"); -#else - size_t len; - _dupenv_s(&windowid, &len, "GODOT_WINDOWID"); -#endif - - if (windowid) { - -// strtoull on mingw -#ifdef MINGW_ENABLED - hWnd = (HWND)strtoull(windowid, NULL, 0); -#else - hWnd = (HWND)_strtoui64(windowid, NULL, 0); -#endif - free(windowid); - SetLastError(0); - user_proc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC); - SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)(WNDPROC)::WndProc); - DWORD le = GetLastError(); - if (user_proc == 0 && le != 0) { - - printf("Error setting WNDPROC: %li\n", le); - }; - GetWindowLongPtr(hWnd, GWLP_WNDPROC); - - RECT rect; - if (!GetClientRect(hWnd, &rect)) { - MessageBoxW(NULL, L"Window Creation Error.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); - return ERR_UNAVAILABLE; - }; - video_mode.width = rect.right; - video_mode.height = rect.bottom; - video_mode.fullscreen = false; - } else { - - hWnd = CreateWindowExW( - dwExStyle, - L"Engine", L"", - dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, - (GetSystemMetrics(SM_CXSCREEN) - WindowRect.right) / 2, - (GetSystemMetrics(SM_CYSCREEN) - WindowRect.bottom) / 2, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - NULL, NULL, hInstance, NULL); - if (!hWnd) { - MessageBoxW(NULL, L"Window Creation Error.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); - return ERR_UNAVAILABLE; - } - }; - - if (video_mode.always_on_top) { - SetWindowPos(hWnd, video_mode.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - } - - //!!!!!!!!!!!!!!!!!!!!!!!!!! - //TODO - do Vulkan and GLES2 support checks, driver selection and fallback - video_driver_index = p_video_driver; - print_verbose("Driver: " + String(get_video_driver_name(video_driver_index)) + " [" + itos(video_driver_index) + "]"); - //!!!!!!!!!!!!!!!!!!!!!!!!!! - - // Init context and rendering device -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - - context_gles2 = memnew(ContextGL_Windows(hWnd, false)); - - if (context_gles2->initialize() != OK) { - memdelete(context_gles2); - context_gles2 = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - - context_gles2->set_use_vsync(video_mode.use_vsync); - set_vsync_via_compositor(video_mode.vsync_via_compositor); - - if (RasterizerGLES2::is_viable() == OK) { - RasterizerGLES2::register_config(); - RasterizerGLES2::make_current(); - } else { - memdelete(context_gles2); - context_gles2 = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - } -#endif -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - - context_vulkan = memnew(VulkanContextWindows); - if (context_vulkan->initialize() != OK) { - memdelete(context_vulkan); - context_vulkan = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - if (context_vulkan->window_create(hWnd, hInstance, get_video_mode().width, get_video_mode().height) == -1) { - memdelete(context_vulkan); - context_vulkan = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - - //temporary - rendering_device_vulkan = memnew(RenderingDeviceVulkan); - rendering_device_vulkan->initialize(context_vulkan); - - RasterizerRD::make_current(); - } -#endif - - visual_server = memnew(VisualServerRaster); - if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); - } - - visual_server->init(); - - input = memnew(InputDefault); - joypad = memnew(JoypadWindows(input, &hWnd)); - - AudioDriverManager::initialize(p_audio_driver); - - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof(TRACKMOUSEEVENT); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = hWnd; - tme.dwHoverTime = HOVER_DEFAULT; - TrackMouseEvent(&tme); - - RegisterTouchWindow(hWnd, 0); - - _ensure_user_data_dir(); - - DragAcceptFiles(hWnd, true); - - move_timer_id = 1; - - if (!is_no_window_mode_enabled()) { - ShowWindow(hWnd, SW_SHOW); // Show The Window - SetForegroundWindow(hWnd); // Slightly Higher Priority - SetFocus(hWnd); // Sets Keyboard Focus To - } - - if (p_desired.layered) { - set_window_per_pixel_transparency_enabled(true); - } - - // IME - im_himc = ImmGetContext(hWnd); - ImmReleaseContext(hWnd, im_himc); - - im_position = Vector2(); - - set_ime_active(false); - - if (!OS::get_singleton()->is_in_low_processor_usage_mode()) { - //SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); - SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); - DWORD index = 0; - HANDLE handle = AvSetMmThreadCharacteristics("Games", &index); - if (handle) - AvSetMmThreadPriority(handle, AVRT_PRIORITY_CRITICAL); - - // This is needed to make sure that background work does not starve the main thread. - // This is only setting priority of this thread, not the whole process. - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - } - - update_real_mouse_position(); - - return OK; } -void OS_Windows::set_clipboard(const String &p_text) { - - // Convert LF line endings to CRLF in clipboard content - // Otherwise, line endings won't be visible when pasted in other software - String text = p_text.replace("\n", "\r\n"); - - if (!OpenClipboard(hWnd)) { - ERR_FAIL_MSG("Unable to open clipboard."); - } - EmptyClipboard(); - - HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) * sizeof(CharType)); - ERR_FAIL_COND_MSG(mem == NULL, "Unable to allocate memory for clipboard contents."); - - LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem); - memcpy(lptstrCopy, text.c_str(), (text.length() + 1) * sizeof(CharType)); - GlobalUnlock(mem); - - SetClipboardData(CF_UNICODETEXT, mem); - - // set the CF_TEXT version (not needed?) - CharString utf8 = text.utf8(); - mem = GlobalAlloc(GMEM_MOVEABLE, utf8.length() + 1); - ERR_FAIL_COND_MSG(mem == NULL, "Unable to allocate memory for clipboard contents."); - - LPTSTR ptr = (LPTSTR)GlobalLock(mem); - memcpy(ptr, utf8.get_data(), utf8.length()); - ptr[utf8.length()] = 0; - GlobalUnlock(mem); - - SetClipboardData(CF_TEXT, mem); - - CloseClipboard(); -}; - -String OS_Windows::get_clipboard() const { - - String ret; - if (!OpenClipboard(hWnd)) { - ERR_FAIL_V_MSG("", "Unable to open clipboard."); - }; - - if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { - - HGLOBAL mem = GetClipboardData(CF_UNICODETEXT); - if (mem != NULL) { - - LPWSTR ptr = (LPWSTR)GlobalLock(mem); - if (ptr != NULL) { - - ret = String((CharType *)ptr); - GlobalUnlock(mem); - }; - }; - - } else if (IsClipboardFormatAvailable(CF_TEXT)) { - - HGLOBAL mem = GetClipboardData(CF_UNICODETEXT); - if (mem != NULL) { - - LPTSTR ptr = (LPTSTR)GlobalLock(mem); - if (ptr != NULL) { - - ret.parse_utf8((const char *)ptr); - GlobalUnlock(mem); - }; - }; - }; - - CloseClipboard(); - - return ret; -}; - void OS_Windows::delete_main_loop() { if (main_loop) @@ -1629,7 +225,6 @@ void OS_Windows::delete_main_loop() { void OS_Windows::set_main_loop(MainLoop *p_main_loop) { - input->set_main_loop(p_main_loop); main_loop = p_main_loop; } @@ -1643,38 +238,6 @@ void OS_Windows::finalize() { memdelete(main_loop); main_loop = NULL; - - memdelete(joypad); - memdelete(input); - touch_state.clear(); - - cursors_cache.clear(); - visual_server->finish(); - memdelete(visual_server); - -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - - if (context_gles2) - memdelete(context_gles2); - } -#endif -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - - if (rendering_device_vulkan) { - rendering_device_vulkan->finalize(); - memdelete(rendering_device_vulkan); - } - - if (context_vulkan) - memdelete(context_vulkan); - } -#endif - - if (user_proc) { - SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc); - }; } void OS_Windows::finalize_core() { @@ -1685,576 +248,6 @@ void OS_Windows::finalize_core() { NetSocketPosix::cleanup(); } -void OS_Windows::alert(const String &p_alert, const String &p_title) { - - if (!is_no_window_mode_enabled()) - MessageBoxW(NULL, p_alert.c_str(), p_title.c_str(), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL); - else - print_line("ALERT: " + p_alert); -} - -void OS_Windows::set_mouse_mode(MouseMode p_mode) { - - if (mouse_mode == p_mode) - return; - - _set_mouse_mode_impl(p_mode); - - mouse_mode = p_mode; -} - -void OS_Windows::_set_mouse_mode_impl(MouseMode p_mode) { - - if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED) { - RECT clipRect; - GetClientRect(hWnd, &clipRect); - ClientToScreen(hWnd, (POINT *)&clipRect.left); - ClientToScreen(hWnd, (POINT *)&clipRect.right); - ClipCursor(&clipRect); - if (p_mode == MOUSE_MODE_CAPTURED) { - center = Point2i(video_mode.width / 2, video_mode.height / 2); - POINT pos = { (int)center.x, (int)center.y }; - ClientToScreen(hWnd, &pos); - SetCursorPos(pos.x, pos.y); - SetCapture(hWnd); - } - } else { - ReleaseCapture(); - ClipCursor(NULL); - } - - if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_HIDDEN) { - hCursor = SetCursor(NULL); - } else { - CursorShape c = cursor_shape; - cursor_shape = CURSOR_MAX; - set_cursor_shape(c); - } -} -OS_Windows::MouseMode OS_Windows::get_mouse_mode() const { - - return mouse_mode; -} - -void OS_Windows::warp_mouse_position(const Point2 &p_to) { - - if (mouse_mode == MOUSE_MODE_CAPTURED) { - - old_x = p_to.x; - old_y = p_to.y; - } else { - - POINT p; - p.x = p_to.x; - p.y = p_to.y; - ClientToScreen(hWnd, &p); - - SetCursorPos(p.x, p.y); - } -} - -Point2 OS_Windows::get_mouse_position() const { - - return Point2(old_x, old_y); -} - -void OS_Windows::update_real_mouse_position() { - - POINT mouse_pos; - if (GetCursorPos(&mouse_pos) && ScreenToClient(hWnd, &mouse_pos)) { - if (mouse_pos.x > 0 && mouse_pos.y > 0 && mouse_pos.x <= video_mode.width && mouse_pos.y <= video_mode.height) { - old_x = mouse_pos.x; - old_y = mouse_pos.y; - old_invalid = false; - input->set_mouse_position(Point2i(mouse_pos.x, mouse_pos.y)); - } - } -} - -int OS_Windows::get_mouse_button_state() const { - - return last_button_state; -} - -void OS_Windows::set_window_title(const String &p_title) { - - SetWindowTextW(hWnd, p_title.c_str()); -} - -void OS_Windows::set_video_mode(const VideoMode &p_video_mode, int p_screen) { -} - -OS::VideoMode OS_Windows::get_video_mode(int p_screen) const { - - return video_mode; -} -void OS_Windows::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const { -} - -static BOOL CALLBACK _MonitorEnumProcCount(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - - int *data = (int *)dwData; - (*data)++; - return TRUE; -} - -int OS_Windows::get_screen_count() const { - - int data = 0; - EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcCount, (LPARAM)&data); - return data; -} - -typedef struct { - int count; - int screen; - HMONITOR monitor; -} EnumScreenData; - -static BOOL CALLBACK _MonitorEnumProcScreen(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - - EnumScreenData *data = (EnumScreenData *)dwData; - if (data->monitor == hMonitor) { - data->screen = data->count; - } - - data->count++; - return TRUE; -} - -int OS_Windows::get_current_screen() const { - - EnumScreenData data = { 0, 0, MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST) }; - EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcScreen, (LPARAM)&data); - return data.screen; -} - -void OS_Windows::set_current_screen(int p_screen) { - - Vector2 ofs = get_window_position() - get_screen_position(get_current_screen()); - set_window_position(ofs + get_screen_position(p_screen)); -} - -static BOOL CALLBACK _MonitorEnumProcPos(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - - EnumPosData *data = (EnumPosData *)dwData; - if (data->count == data->screen) { - data->pos.x = lprcMonitor->left; - data->pos.y = lprcMonitor->top; - } - - data->count++; - return TRUE; -} - -Point2 OS_Windows::get_screen_position(int p_screen) const { - - EnumPosData data = { 0, p_screen == -1 ? get_current_screen() : p_screen, Point2() }; - EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcPos, (LPARAM)&data); - return data.pos; -} - -Size2 OS_Windows::get_screen_size(int p_screen) const { - - EnumSizeData data = { 0, p_screen == -1 ? get_current_screen() : p_screen, Size2() }; - EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcSize, (LPARAM)&data); - return data.size; -} - -typedef struct { - int count; - int screen; - int dpi; -} EnumDpiData; - -static BOOL CALLBACK _MonitorEnumProcDpi(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - - EnumDpiData *data = (EnumDpiData *)dwData; - if (data->count == data->screen) { - data->dpi = QueryDpiForMonitor(hMonitor); - } - - data->count++; - return TRUE; -} - -int OS_Windows::get_screen_dpi(int p_screen) const { - - EnumDpiData data = { 0, p_screen == -1 ? get_current_screen() : p_screen, 72 }; - EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcDpi, (LPARAM)&data); - return data.dpi; -} - -Point2 OS_Windows::get_window_position() const { - - if (minimized) { - return last_pos; - } - - RECT r; - GetWindowRect(hWnd, &r); - return Point2(r.left, r.top); -} - -void OS_Windows::set_window_position(const Point2 &p_position) { - - if (video_mode.fullscreen) return; - RECT r; - GetWindowRect(hWnd, &r); - MoveWindow(hWnd, p_position.x, p_position.y, r.right - r.left, r.bottom - r.top, TRUE); - - // Don't let the mouse leave the window when moved - if (mouse_mode == MOUSE_MODE_CONFINED) { - RECT rect; - GetClientRect(hWnd, &rect); - ClientToScreen(hWnd, (POINT *)&rect.left); - ClientToScreen(hWnd, (POINT *)&rect.right); - ClipCursor(&rect); - } - - last_pos = p_position; - update_real_mouse_position(); -} - -Size2 OS_Windows::get_window_size() const { - - if (minimized) { - return Size2(video_mode.width, video_mode.height); - } - - RECT r; - if (GetClientRect(hWnd, &r)) { // Only area inside of window border - return Size2(r.right - r.left, r.bottom - r.top); - } - return Size2(); -} - -Size2 OS_Windows::get_max_window_size() const { - return max_size; -} - -Size2 OS_Windows::get_min_window_size() const { - return min_size; -} - -void OS_Windows::set_min_window_size(const Size2 p_size) { - - if ((p_size != Size2()) && (max_size != Size2()) && ((p_size.x > max_size.x) || (p_size.y > max_size.y))) { - ERR_PRINT("Minimum window size can't be larger than maximum window size!"); - return; - } - min_size = p_size; -} - -void OS_Windows::set_max_window_size(const Size2 p_size) { - - if ((p_size != Size2()) && ((p_size.x < min_size.x) || (p_size.y < min_size.y))) { - ERR_PRINT("Maximum window size can't be smaller than minimum window size!"); - return; - } - max_size = p_size; -} - -Size2 OS_Windows::get_real_window_size() const { - - RECT r; - if (GetWindowRect(hWnd, &r)) { // Includes area of the window border - return Size2(r.right - r.left, r.bottom - r.top); - } - return Size2(); -} - -void OS_Windows::set_window_size(const Size2 p_size) { - - int w = p_size.width; - int h = p_size.height; - - video_mode.width = w; - video_mode.height = h; -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - context_vulkan->window_resize(0, video_mode.width, video_mode.height); - } -#endif - - if (video_mode.fullscreen) { - return; - } - - RECT rect; - GetWindowRect(hWnd, &rect); - - if (!video_mode.borderless_window) { - RECT crect; - GetClientRect(hWnd, &crect); - - w += (rect.right - rect.left) - (crect.right - crect.left); - h += (rect.bottom - rect.top) - (crect.bottom - crect.top); - } - - MoveWindow(hWnd, rect.left, rect.top, w, h, TRUE); - - // Don't let the mouse leave the window when resizing to a smaller resolution - if (mouse_mode == MOUSE_MODE_CONFINED) { - RECT crect; - GetClientRect(hWnd, &crect); - ClientToScreen(hWnd, (POINT *)&crect.left); - ClientToScreen(hWnd, (POINT *)&crect.right); - ClipCursor(&crect); - } -} -void OS_Windows::set_window_fullscreen(bool p_enabled) { - - if (video_mode.fullscreen == p_enabled) - return; - - if (layered_window) - set_window_per_pixel_transparency_enabled(false); - - if (p_enabled) { - - was_maximized = maximized; - - if (pre_fs_valid) { - GetWindowRect(hWnd, &pre_fs_rect); - } - - int cs = get_current_screen(); - Point2 pos = get_screen_position(cs); - Size2 size = get_screen_size(cs); - - video_mode.fullscreen = true; - - _update_window_style(false); - - MoveWindow(hWnd, pos.x, pos.y, size.width, size.height, TRUE); - - } else { - - RECT rect; - - video_mode.fullscreen = false; - - if (pre_fs_valid) { - rect = pre_fs_rect; - } else { - rect.left = 0; - rect.right = video_mode.width; - rect.top = 0; - rect.bottom = video_mode.height; - } - - _update_window_style(false, was_maximized); - - MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE); - - pre_fs_valid = true; - } -} -bool OS_Windows::is_window_fullscreen() const { - - return video_mode.fullscreen; -} -void OS_Windows::set_window_resizable(bool p_enabled) { - - if (video_mode.resizable == p_enabled) - return; - - video_mode.resizable = p_enabled; - - _update_window_style(); -} -bool OS_Windows::is_window_resizable() const { - - return video_mode.resizable; -} -void OS_Windows::set_window_minimized(bool p_enabled) { - - if (p_enabled) { - maximized = false; - minimized = true; - ShowWindow(hWnd, SW_MINIMIZE); - } else { - ShowWindow(hWnd, SW_RESTORE); - maximized = false; - minimized = false; - } -} -bool OS_Windows::is_window_minimized() const { - - return minimized; -} -void OS_Windows::set_window_maximized(bool p_enabled) { - - if (p_enabled) { - maximized = true; - minimized = false; - ShowWindow(hWnd, SW_MAXIMIZE); - } else { - ShowWindow(hWnd, SW_RESTORE); - maximized = false; - minimized = false; - } -} -bool OS_Windows::is_window_maximized() const { - - return maximized; -} - -void OS_Windows::set_window_always_on_top(bool p_enabled) { - if (video_mode.always_on_top == p_enabled) - return; - - video_mode.always_on_top = p_enabled; - - _update_window_style(); -} - -bool OS_Windows::is_window_always_on_top() const { - return video_mode.always_on_top; -} - -bool OS_Windows::is_window_focused() const { - - return window_focused; -} - -void OS_Windows::set_console_visible(bool p_enabled) { - if (console_visible == p_enabled) - return; - ShowWindow(GetConsoleWindow(), p_enabled ? SW_SHOW : SW_HIDE); - console_visible = p_enabled; -} - -bool OS_Windows::is_console_visible() const { - return console_visible; -} - -bool OS_Windows::get_window_per_pixel_transparency_enabled() const { - - if (!is_layered_allowed()) return false; - return layered_window; -} - -void OS_Windows::set_window_per_pixel_transparency_enabled(bool p_enabled) { - - if (!is_layered_allowed()) return; - if (layered_window != p_enabled) { - if (p_enabled) { - set_borderless_window(true); - //enable per-pixel alpha - hDC_dib = CreateCompatibleDC(GetDC(hWnd)); - - SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED); - - RECT r; - GetWindowRect(hWnd, &r); - dib_size = Size2(r.right - r.left, r.bottom - r.top); - - BITMAPINFO bmi; - ZeroMemory(&bmi, sizeof(BITMAPINFO)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = dib_size.x; - bmi.bmiHeader.biHeight = dib_size.y; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = dib_size.x * dib_size.y * 4; - hBitmap = CreateDIBSection(hDC_dib, &bmi, DIB_RGB_COLORS, (void **)&dib_data, NULL, 0x0); - SelectObject(hDC_dib, hBitmap); - - ZeroMemory(dib_data, dib_size.x * dib_size.y * 4); - - layered_window = true; - } else { - //disable per-pixel alpha - layered_window = false; - - SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) & ~WS_EX_LAYERED); - - //cleanup - DeleteObject(hBitmap); - DeleteDC(hDC_dib); - } - } -} - -uint8_t *OS_Windows::get_layered_buffer_data() { - - return (is_layered_allowed() && layered_window) ? dib_data : NULL; -} - -Size2 OS_Windows::get_layered_buffer_size() { - - return (is_layered_allowed() && layered_window) ? dib_size : Size2(); -} - -void OS_Windows::swap_layered_buffer() { - - if (is_layered_allowed() && layered_window) { - - //premultiply alpha - for (int y = 0; y < dib_size.y; y++) { - for (int x = 0; x < dib_size.x; x++) { - float alpha = (float)dib_data[y * (int)dib_size.x * 4 + x * 4 + 3] / (float)0xFF; - dib_data[y * (int)dib_size.x * 4 + x * 4 + 0] *= alpha; - dib_data[y * (int)dib_size.x * 4 + x * 4 + 1] *= alpha; - dib_data[y * (int)dib_size.x * 4 + x * 4 + 2] *= alpha; - } - } - //swap layered window buffer - POINT ptSrc = { 0, 0 }; - SIZE sizeWnd = { (long)dib_size.x, (long)dib_size.y }; - BLENDFUNCTION bf; - bf.BlendOp = AC_SRC_OVER; - bf.BlendFlags = 0; - bf.AlphaFormat = AC_SRC_ALPHA; - bf.SourceConstantAlpha = 0xFF; - UpdateLayeredWindow(hWnd, NULL, NULL, &sizeWnd, hDC_dib, &ptSrc, 0, &bf, ULW_ALPHA); - } -} - -void OS_Windows::set_borderless_window(bool p_borderless) { - if (video_mode.borderless_window == p_borderless) - return; - - if (!p_borderless && layered_window) - set_window_per_pixel_transparency_enabled(false); - - video_mode.borderless_window = p_borderless; - - preserve_window_size = true; - _update_window_style(); -} - -bool OS_Windows::get_borderless_window() { - return video_mode.borderless_window; -} - -void OS_Windows::_update_window_style(bool p_repaint, bool p_maximized) { - if (video_mode.fullscreen || video_mode.borderless_window) { - SetWindowLongPtr(hWnd, GWL_STYLE, WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE); - } else { - if (video_mode.resizable) { - if (p_maximized) { - SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_MAXIMIZE); - } else { - SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE); - } - } else { - SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_VISIBLE); - } - } - - SetWindowPos(hWnd, video_mode.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); - - if (p_repaint) { - RECT rect; - GetWindowRect(hWnd, &rect); - MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE); - } -} - Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { String path = p_path; @@ -2306,17 +299,6 @@ Error OS_Windows::get_dynamic_library_symbol_handle(void *p_library_handle, cons return OK; } -void OS_Windows::request_attention() { - - FLASHWINFO info; - info.cbSize = sizeof(FLASHWINFO); - info.hwnd = hWnd; - info.dwFlags = FLASHW_TRAY; - info.dwTimeout = 0; - info.uCount = 2; - FlashWindowEx(&info); -} - String OS_Windows::get_name() const { return "Windows"; @@ -2448,253 +430,6 @@ uint64_t OS_Windows::get_ticks_usec() const { return time; } -void OS_Windows::process_events() { - - MSG msg; - - if (!drop_events) { - joypad->process_joypads(); - } - - while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { - - TranslateMessage(&msg); - DispatchMessageW(&msg); - } - - if (!drop_events) { - process_key_events(); - input->flush_accumulated_events(); - } -} - -void OS_Windows::set_cursor_shape(CursorShape p_shape) { - - ERR_FAIL_INDEX(p_shape, CURSOR_MAX); - - if (cursor_shape == p_shape) - return; - - if (mouse_mode != MOUSE_MODE_VISIBLE && mouse_mode != MOUSE_MODE_CONFINED) { - cursor_shape = p_shape; - return; - } - - static const LPCTSTR win_cursors[CURSOR_MAX] = { - IDC_ARROW, - IDC_IBEAM, - IDC_HAND, //finger - IDC_CROSS, - IDC_WAIT, - IDC_APPSTARTING, - IDC_ARROW, - IDC_ARROW, - IDC_NO, - IDC_SIZENS, - IDC_SIZEWE, - IDC_SIZENESW, - IDC_SIZENWSE, - IDC_SIZEALL, - IDC_SIZENS, - IDC_SIZEWE, - IDC_HELP - }; - - if (cursors[p_shape] != NULL) { - SetCursor(cursors[p_shape]); - } else { - SetCursor(LoadCursor(hInstance, win_cursors[p_shape])); - } - - cursor_shape = p_shape; -} - -OS::CursorShape OS_Windows::get_cursor_shape() const { - - return cursor_shape; -} - -void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { - - if (p_cursor.is_valid()) { - - Map<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape); - - if (cursor_c) { - if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) { - set_cursor_shape(p_shape); - return; - } - - cursors_cache.erase(p_shape); - } - - Ref<Texture2D> texture = p_cursor; - Ref<AtlasTexture> atlas_texture = p_cursor; - Ref<Image> image; - Size2 texture_size; - Rect2 atlas_rect; - - if (texture.is_valid()) { - image = texture->get_data(); - } - - if (!image.is_valid() && atlas_texture.is_valid()) { - texture = atlas_texture->get_atlas(); - - atlas_rect.size.width = texture->get_width(); - atlas_rect.size.height = texture->get_height(); - atlas_rect.position.x = atlas_texture->get_region().position.x; - atlas_rect.position.y = atlas_texture->get_region().position.y; - - texture_size.width = atlas_texture->get_region().size.x; - texture_size.height = atlas_texture->get_region().size.y; - } else if (image.is_valid()) { - texture_size.width = texture->get_width(); - texture_size.height = texture->get_height(); - } - - ERR_FAIL_COND(!texture.is_valid()); - ERR_FAIL_COND(p_hotspot.x < 0 || p_hotspot.y < 0); - ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); - ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); - - image = texture->get_data(); - - ERR_FAIL_COND(!image.is_valid()); - - UINT image_size = texture_size.width * texture_size.height; - - // Create the BITMAP with alpha channel - COLORREF *buffer = (COLORREF *)memalloc(sizeof(COLORREF) * image_size); - - for (UINT index = 0; index < image_size; index++) { - int row_index = floor(index / texture_size.width) + atlas_rect.position.y; - int column_index = (index % int(texture_size.width)) + atlas_rect.position.x; - - if (atlas_texture.is_valid()) { - column_index = MIN(column_index, atlas_rect.size.width - 1); - row_index = MIN(row_index, atlas_rect.size.height - 1); - } - - *(buffer + index) = image->get_pixel(column_index, row_index).to_argb32(); - } - - // Using 4 channels, so 4 * 8 bits - HBITMAP bitmap = CreateBitmap(texture_size.width, texture_size.height, 1, 4 * 8, buffer); - COLORREF clrTransparent = -1; - - // Create the AND and XOR masks for the bitmap - HBITMAP hAndMask = NULL; - HBITMAP hXorMask = NULL; - - GetMaskBitmaps(bitmap, clrTransparent, hAndMask, hXorMask); - - if (NULL == hAndMask || NULL == hXorMask) { - memfree(buffer); - DeleteObject(bitmap); - return; - } - - // Finally, create the icon - ICONINFO iconinfo; - iconinfo.fIcon = FALSE; - iconinfo.xHotspot = p_hotspot.x; - iconinfo.yHotspot = p_hotspot.y; - iconinfo.hbmMask = hAndMask; - iconinfo.hbmColor = hXorMask; - - if (cursors[p_shape]) - DestroyIcon(cursors[p_shape]); - - cursors[p_shape] = CreateIconIndirect(&iconinfo); - - Vector<Variant> params; - params.push_back(p_cursor); - params.push_back(p_hotspot); - cursors_cache.insert(p_shape, params); - - if (p_shape == cursor_shape) { - if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { - SetCursor(cursors[p_shape]); - } - } - - if (hAndMask != NULL) { - DeleteObject(hAndMask); - } - - if (hXorMask != NULL) { - DeleteObject(hXorMask); - } - - memfree(buffer); - DeleteObject(bitmap); - } else { - // Reset to default system cursor - if (cursors[p_shape]) { - DestroyIcon(cursors[p_shape]); - cursors[p_shape] = NULL; - } - - CursorShape c = cursor_shape; - cursor_shape = CURSOR_MAX; - set_cursor_shape(c); - - cursors_cache.erase(p_shape); - } -} - -void OS_Windows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap) { - - // Get the system display DC - HDC hDC = GetDC(NULL); - - // Create helper DC - HDC hMainDC = CreateCompatibleDC(hDC); - HDC hAndMaskDC = CreateCompatibleDC(hDC); - HDC hXorMaskDC = CreateCompatibleDC(hDC); - - // Get the dimensions of the source bitmap - BITMAP bm; - GetObject(hSourceBitmap, sizeof(BITMAP), &bm); - - // Create the mask bitmaps - hAndMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color - hXorMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color - - // Release the system display DC - ReleaseDC(NULL, hDC); - - // Select the bitmaps to helper DC - HBITMAP hOldMainBitmap = (HBITMAP)SelectObject(hMainDC, hSourceBitmap); - HBITMAP hOldAndMaskBitmap = (HBITMAP)SelectObject(hAndMaskDC, hAndMaskBitmap); - HBITMAP hOldXorMaskBitmap = (HBITMAP)SelectObject(hXorMaskDC, hXorMaskBitmap); - - // Assign the monochrome AND mask bitmap pixels so that a pixels of the source bitmap - // with 'clrTransparent' will be white pixels of the monochrome bitmap - SetBkColor(hMainDC, clrTransparent); - BitBlt(hAndMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCCOPY); - - // Assign the color XOR mask bitmap pixels so that a pixels of the source bitmap - // with 'clrTransparent' will be black and rest the pixels same as corresponding - // pixels of the source bitmap - SetBkColor(hXorMaskDC, RGB(0, 0, 0)); - SetTextColor(hXorMaskDC, RGB(255, 255, 255)); - BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hAndMaskDC, 0, 0, SRCCOPY); - BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCAND); - - // Deselect bitmaps from the helper DC - SelectObject(hMainDC, hOldMainBitmap); - SelectObject(hAndMaskDC, hOldAndMaskBitmap); - SelectObject(hXorMaskDC, hOldXorMaskBitmap); - - // Delete the helper DC - DeleteDC(hXorMaskDC); - DeleteDC(hAndMaskDC); - DeleteDC(hMainDC); -} - Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) { if (p_blocking && r_pipe) { @@ -2812,151 +547,6 @@ String OS_Windows::get_executable_path() const { return s; } -void OS_Windows::set_native_icon(const String &p_filename) { - - FileAccess *f = FileAccess::open(p_filename, FileAccess::READ); - ERR_FAIL_COND_MSG(!f, "Cannot open file with icon '" + p_filename + "'."); - - ICONDIR *icon_dir = (ICONDIR *)memalloc(sizeof(ICONDIR)); - int pos = 0; - - icon_dir->idReserved = f->get_32(); - pos += sizeof(WORD); - f->seek(pos); - - icon_dir->idType = f->get_32(); - pos += sizeof(WORD); - f->seek(pos); - - ERR_FAIL_COND_MSG(icon_dir->idType != 1, "Invalid icon file format!"); - - icon_dir->idCount = f->get_32(); - pos += sizeof(WORD); - f->seek(pos); - - icon_dir = (ICONDIR *)memrealloc(icon_dir, 3 * sizeof(WORD) + icon_dir->idCount * sizeof(ICONDIRENTRY)); - f->get_buffer((uint8_t *)&icon_dir->idEntries[0], icon_dir->idCount * sizeof(ICONDIRENTRY)); - - int small_icon_index = -1; // Select 16x16 with largest color count - int small_icon_cc = 0; - int big_icon_index = -1; // Select largest - int big_icon_width = 16; - int big_icon_cc = 0; - - for (int i = 0; i < icon_dir->idCount; i++) { - int colors = (icon_dir->idEntries[i].bColorCount == 0) ? 32768 : icon_dir->idEntries[i].bColorCount; - int width = (icon_dir->idEntries[i].bWidth == 0) ? 256 : icon_dir->idEntries[i].bWidth; - if (width == 16) { - if (colors >= small_icon_cc) { - small_icon_index = i; - small_icon_cc = colors; - } - } - if (width >= big_icon_width) { - if (colors >= big_icon_cc) { - big_icon_index = i; - big_icon_width = width; - big_icon_cc = colors; - } - } - } - - ERR_FAIL_COND_MSG(big_icon_index == -1, "No valid icons found!"); - - if (small_icon_index == -1) { - WARN_PRINT("No small icon found, reusing " + itos(big_icon_width) + "x" + itos(big_icon_width) + " @" + itos(big_icon_cc) + " icon!"); - small_icon_index = big_icon_index; - small_icon_cc = big_icon_cc; - } - - // Read the big icon - DWORD bytecount_big = icon_dir->idEntries[big_icon_index].dwBytesInRes; - Vector<uint8_t> data_big; - data_big.resize(bytecount_big); - pos = icon_dir->idEntries[big_icon_index].dwImageOffset; - f->seek(pos); - f->get_buffer((uint8_t *)&data_big.write[0], bytecount_big); - HICON icon_big = CreateIconFromResource((PBYTE)&data_big.write[0], bytecount_big, TRUE, 0x00030000); - ERR_FAIL_COND_MSG(!icon_big, "Could not create " + itos(big_icon_width) + "x" + itos(big_icon_width) + " @" + itos(big_icon_cc) + " icon, error: " + format_error_message(GetLastError()) + "."); - - // Read the small icon - DWORD bytecount_small = icon_dir->idEntries[small_icon_index].dwBytesInRes; - Vector<uint8_t> data_small; - data_small.resize(bytecount_small); - pos = icon_dir->idEntries[small_icon_index].dwImageOffset; - f->seek(pos); - f->get_buffer((uint8_t *)&data_small.write[0], bytecount_small); - HICON icon_small = CreateIconFromResource((PBYTE)&data_small.write[0], bytecount_small, TRUE, 0x00030000); - ERR_FAIL_COND_MSG(!icon_small, "Could not create 16x16 @" + itos(small_icon_cc) + " icon, error: " + format_error_message(GetLastError()) + "."); - - // Online tradition says to be sure last error is cleared and set the small icon first - int err = 0; - SetLastError(err); - - SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)icon_small); - err = GetLastError(); - ERR_FAIL_COND_MSG(err, "Error setting ICON_SMALL: " + format_error_message(err) + "."); - - SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)icon_big); - err = GetLastError(); - ERR_FAIL_COND_MSG(err, "Error setting ICON_BIG: " + format_error_message(err) + "."); - - memdelete(f); - memdelete(icon_dir); -} - -void OS_Windows::set_icon(const Ref<Image> &p_icon) { - - ERR_FAIL_COND(!p_icon.is_valid()); - Ref<Image> icon = p_icon->duplicate(); - if (icon->get_format() != Image::FORMAT_RGBA8) - icon->convert(Image::FORMAT_RGBA8); - int w = icon->get_width(); - int h = icon->get_height(); - - /* Create temporary bitmap buffer */ - int icon_len = 40 + h * w * 4; - Vector<BYTE> v; - v.resize(icon_len); - BYTE *icon_bmp = v.ptrw(); - - encode_uint32(40, &icon_bmp[0]); - encode_uint32(w, &icon_bmp[4]); - encode_uint32(h * 2, &icon_bmp[8]); - encode_uint16(1, &icon_bmp[12]); - encode_uint16(32, &icon_bmp[14]); - encode_uint32(BI_RGB, &icon_bmp[16]); - encode_uint32(w * h * 4, &icon_bmp[20]); - encode_uint32(0, &icon_bmp[24]); - encode_uint32(0, &icon_bmp[28]); - encode_uint32(0, &icon_bmp[32]); - encode_uint32(0, &icon_bmp[36]); - - uint8_t *wr = &icon_bmp[40]; - const uint8_t *r = icon->get_data().ptr(); - - for (int i = 0; i < h; i++) { - - for (int j = 0; j < w; j++) { - - const uint8_t *rpx = &r[((h - i - 1) * w + j) * 4]; - uint8_t *wpx = &wr[(i * w + j) * 4]; - wpx[0] = rpx[2]; - wpx[1] = rpx[1]; - wpx[2] = rpx[0]; - wpx[3] = rpx[3]; - } - } - - HICON hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000); - - /* Set the icon for the window */ - SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon); - - /* Set the icon in the task manager (should we do this?) */ - SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hicon); -} - bool OS_Windows::has_environment(const String &p_var) const { #ifdef MINGW_ENABLED @@ -2996,16 +586,6 @@ String OS_Windows::get_stdin_string(bool p_block) { return String(); } -void OS_Windows::enable_for_stealing_focus(ProcessID pid) { - - AllowSetForegroundWindow(pid); -} - -void OS_Windows::move_window_to_foreground() { - - SetForegroundWindow(hWnd); -} - Error OS_Windows::shell_open(String p_uri) { ShellExecuteW(NULL, NULL, p_uri.c_str(), NULL, NULL, SW_SHOWNORMAL); @@ -3068,101 +648,6 @@ int OS_Windows::get_processor_count() const { return sysinfo.dwNumberOfProcessors; } -OS::LatinKeyboardVariant OS_Windows::get_latin_keyboard_variant() const { - - unsigned long azerty[] = { - 0x00020401, // Arabic (102) AZERTY - 0x0001080c, // Belgian (Comma) - 0x0000080c, // Belgian French - 0x0000040c, // French - 0 // <--- STOP MARK - }; - unsigned long qwertz[] = { - 0x0000041a, // Croation - 0x00000405, // Czech - 0x00000407, // German - 0x00010407, // German (IBM) - 0x0000040e, // Hungarian - 0x0000046e, // Luxembourgish - 0x00010415, // Polish (214) - 0x00000418, // Romanian (Legacy) - 0x0000081a, // Serbian (Latin) - 0x0000041b, // Slovak - 0x00000424, // Slovenian - 0x0001042e, // Sorbian Extended - 0x0002042e, // Sorbian Standard - 0x0000042e, // Sorbian Standard (Legacy) - 0x0000100c, // Swiss French - 0x00000807, // Swiss German - 0 // <--- STOP MARK - }; - unsigned long dvorak[] = { - 0x00010409, // US-Dvorak - 0x00030409, // US-Dvorak for left hand - 0x00040409, // US-Dvorak for right hand - 0 // <--- STOP MARK - }; - - char name[KL_NAMELENGTH + 1]; - name[0] = 0; - GetKeyboardLayoutNameA(name); - - unsigned long hex = strtoul(name, NULL, 16); - - int i = 0; - while (azerty[i] != 0) { - if (azerty[i] == hex) return LATIN_KEYBOARD_AZERTY; - i++; - } - - i = 0; - while (qwertz[i] != 0) { - if (qwertz[i] == hex) return LATIN_KEYBOARD_QWERTZ; - i++; - } - - i = 0; - while (dvorak[i] != 0) { - if (dvorak[i] == hex) return LATIN_KEYBOARD_DVORAK; - i++; - } - - return LATIN_KEYBOARD_QWERTY; -} - -void OS_Windows::release_rendering_thread() { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->release_current(); - } -#endif -} - -void OS_Windows::make_rendering_thread() { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->make_current(); - } -#endif -} - -void OS_Windows::swap_buffers() { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->swap_buffers(); - } -#endif -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - context_vulkan->swap_buffers(); - } -#endif -} - -void OS_Windows::force_process_input() { - process_events(); // get rid of pending events -} - void OS_Windows::run() { if (!main_loop) @@ -3172,7 +657,7 @@ void OS_Windows::run() { while (!force_quit) { - process_events(); // get rid of pending events + DisplayServer::get_singleton()->process_events(); // get rid of pending events if (Main::iteration()) break; }; @@ -3287,50 +772,6 @@ String OS_Windows::get_unique_id() const { return String(HwProfInfo.szHwProfileGuid); } -void OS_Windows::set_ime_active(const bool p_active) { - - if (p_active) { - ImmAssociateContext(hWnd, im_himc); - - set_ime_position(im_position); - } else { - ImmAssociateContext(hWnd, (HIMC)0); - } -} - -void OS_Windows::set_ime_position(const Point2 &p_pos) { - - im_position = p_pos; - - HIMC himc = ImmGetContext(hWnd); - if (himc == (HIMC)0) - return; - - COMPOSITIONFORM cps; - cps.dwStyle = CFS_FORCE_POSITION; - cps.ptCurrentPos.x = im_position.x; - cps.ptCurrentPos.y = im_position.y; - ImmSetCompositionWindow(himc, &cps); - ImmReleaseContext(hWnd, himc); -} - -bool OS_Windows::is_joy_known(int p_device) { - return input->is_joy_mapped(p_device); -} - -String OS_Windows::get_joy_guid(int p_device) const { - return input->get_joy_guid_remapped(p_device); -} - -void OS_Windows::_set_use_vsync(bool p_enable) { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - if (context_gles2) - context_gles2->set_use_vsync(p_enable); - } -#endif -} - bool OS_Windows::_check_internal_feature_support(const String &p_feature) { return p_feature == "pc"; @@ -3344,20 +785,13 @@ bool OS_Windows::is_disable_crash_handler() const { return crash_handler.is_disabled(); } -void OS_Windows::process_and_drop_events() { - - drop_events = true; - process_events(); - drop_events = false; -} - Error OS_Windows::move_to_trash(const String &p_path) { SHFILEOPSTRUCTW sf; WCHAR *from = new WCHAR[p_path.length() + 2]; wcscpy_s(from, p_path.length() + 1, p_path.c_str()); from[p_path.length() + 1] = 0; - sf.hwnd = hWnd; + sf.hwnd = main_window; sf.wFunc = FO_DELETE; sf.pFrom = from; sf.pTo = NULL; @@ -3379,36 +813,12 @@ Error OS_Windows::move_to_trash(const String &p_path) { OS_Windows::OS_Windows(HINSTANCE _hInstance) { - drop_events = false; - key_event_pos = 0; - layered_window = false; - hBitmap = NULL; force_quit = false; - alt_mem = false; - gr_mem = false; - shift_mem = false; - control_mem = false; - meta_mem = false; - minimized = false; - was_maximized = false; - window_focused = true; - console_visible = IsWindowVisible(GetConsoleWindow()); - - //Note: Functions for pen input, available on Windows 8+ - HMODULE user32_lib = LoadLibraryW(L"user32.dll"); - if (user32_lib) { - win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType"); - win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo"); - } hInstance = _hInstance; - pressrc = 0; - old_invalid = true; - mouse_mode = MOUSE_MODE_VISIBLE; #ifdef STDOUT_FILE stdo = fopen("stdout.txt", "wb"); #endif - user_proc = NULL; #ifdef WASAPI_ENABLED AudioDriverManager::add_driver(&driver_wasapi); @@ -3417,16 +827,14 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { AudioDriverManager::add_driver(&driver_xaudio2); #endif + DisplayServerWindows::register_windows_driver(); + Vector<Logger *> loggers; loggers.push_back(memnew(WindowsTerminalLogger)); _set_logger(memnew(CompositeLogger(loggers))); } OS_Windows::~OS_Windows() { - if (is_layered_allowed() && layered_window) { - DeleteObject(hBitmap); - DeleteDC(hDC_dib); - } #ifdef STDOUT_FILE fclose(stdo); #endif |