summaryrefslogtreecommitdiff
path: root/platform/windows/display_server_windows.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/windows/display_server_windows.cpp')
-rw-r--r--platform/windows/display_server_windows.cpp982
1 files changed, 603 insertions, 379 deletions
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index dfbb734ee4..9fe15366f4 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -38,7 +38,15 @@
#include <avrt.h>
-#ifdef DEBUG_ENABLED
+#if defined(GLES3_ENABLED)
+#include "drivers/gles3/rasterizer_gles3.h"
+#endif
+
+#if defined(__GNUC__)
+// Workaround GCC warning from -Wcast-function-type.
+#define GetProcAddress (void *)GetProcAddress
+#endif
+
static String format_error_message(DWORD id) {
LPWSTR messageBuffer = nullptr;
size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
@@ -50,7 +58,6 @@ static String format_error_message(DWORD id) {
return msg;
}
-#endif // DEBUG_ENABLED
bool DisplayServerWindows::has_feature(Feature p_feature) const {
switch (p_feature) {
@@ -79,12 +86,9 @@ String DisplayServerWindows::get_name() const {
return "Windows";
}
-void DisplayServerWindows::alert(const String &p_alert, const String &p_title) {
- MessageBoxW(nullptr, (LPCWSTR)(p_alert.utf16().get_data()), (LPCWSTR)(p_title.utf16().get_data()), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
-}
-
void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) {
- if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED) {
+ if (windows.has(MAIN_WINDOW_ID) && (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN)) {
+ // Mouse is grabbed (captured or confined).
WindowData &wd = windows[MAIN_WINDOW_ID];
RECT clipRect;
@@ -100,11 +104,12 @@ void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) {
SetCapture(wd.hWnd);
}
} else {
+ // Mouse is free to move around (not captured or confined).
ReleaseCapture();
ClipCursor(nullptr);
}
- if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_HIDDEN) {
+ if (p_mode == MOUSE_MODE_HIDDEN || p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED_HIDDEN) {
if (hCursor == nullptr) {
hCursor = SetCursor(nullptr);
} else {
@@ -120,8 +125,10 @@ void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) {
void DisplayServerWindows::mouse_set_mode(MouseMode p_mode) {
_THREAD_SAFE_METHOD_
- if (mouse_mode == p_mode)
+ if (mouse_mode == p_mode) {
+ // Already in the same mode; do nothing.
return;
+ }
mouse_mode = p_mode;
@@ -136,7 +143,7 @@ void DisplayServerWindows::mouse_warp_to_position(const Point2i &p_to) {
_THREAD_SAFE_METHOD_
if (!windows.has(last_focused_window)) {
- return; //no window focused?
+ return; // No focused window?
}
if (mouse_mode == MOUSE_MODE_CAPTURED) {
@@ -156,10 +163,9 @@ Point2i DisplayServerWindows::mouse_get_position() const {
POINT p;
GetCursorPos(&p);
return Point2i(p.x, p.y);
- //return Point2(old_x, old_y);
}
-int DisplayServerWindows::mouse_get_button_state() const {
+MouseButton DisplayServerWindows::mouse_get_button_state() const {
return last_button_state;
}
@@ -167,12 +173,12 @@ void DisplayServerWindows::clipboard_set(const String &p_text) {
_THREAD_SAFE_METHOD_
if (!windows.has(last_focused_window)) {
- return; //no window focused?
+ return; // No focused window?
}
- // 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("\r\n", "\n").replace("\n", "\r\n"); // avoid \r\r\n
+ // 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("\r\n", "\n").replace("\n", "\r\n"); // Avoid \r\r\n.
if (!OpenClipboard(windows[last_focused_window].hWnd)) {
ERR_FAIL_MSG("Unable to open clipboard.");
@@ -189,7 +195,7 @@ void DisplayServerWindows::clipboard_set(const String &p_text) {
SetClipboardData(CF_UNICODETEXT, mem);
- // set the CF_TEXT version (not needed?)
+ // Set the CF_TEXT version (not needed?).
CharString utf8 = text.utf8();
mem = GlobalAlloc(GMEM_MOVEABLE, utf8.length() + 1);
ERR_FAIL_COND_MSG(mem == nullptr, "Unable to allocate memory for clipboard contents.");
@@ -208,7 +214,7 @@ String DisplayServerWindows::clipboard_get() const {
_THREAD_SAFE_METHOD_
if (!windows.has(last_focused_window)) {
- return String(); //no window focused?
+ return String(); // No focused window?
}
String ret;
@@ -332,7 +338,7 @@ static BOOL CALLBACK _MonitorEnumProcUsableSize(HMONITOR hMonitor, HDC hdcMonito
EnumRectData *data = (EnumRectData *)dwData;
if (data->count == data->screen) {
MONITORINFO minfo;
- zeromem(&minfo, sizeof(MONITORINFO));
+ memset(&minfo, 0, sizeof(MONITORINFO));
minfo.cbSize = sizeof(MONITORINFO);
GetMonitorInfoA(hMonitor, &minfo);
@@ -455,8 +461,8 @@ Vector<DisplayServer::WindowID> DisplayServerWindows::get_window_list() const {
_THREAD_SAFE_METHOD_
Vector<DisplayServer::WindowID> ret;
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- ret.push_back(E->key());
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ ret.push_back(E.key);
}
return ret;
}
@@ -466,19 +472,19 @@ DisplayServer::WindowID DisplayServerWindows::get_window_at_screen_position(cons
p.x = p_position.x;
p.y = p_position.y;
HWND hwnd = WindowFromPoint(p);
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- if (E->get().hWnd == hwnd) {
- return E->key();
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ if (E.value.hWnd == hwnd) {
+ return E.key;
}
}
return INVALID_WINDOW_ID;
}
-DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_
- WindowID window_id = _create_window(p_mode, p_flags, p_rect);
+ WindowID window_id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect);
ERR_FAIL_COND_V_MSG(window_id == INVALID_WINDOW_ID, INVALID_WINDOW_ID, "Failed to create sub window.");
WindowData &wd = windows[window_id];
@@ -500,16 +506,18 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod
}
void DisplayServerWindows::show_window(WindowID p_id) {
+ ERR_FAIL_COND(!windows.has(p_id));
+
WindowData &wd = windows[p_id];
if (p_id != MAIN_WINDOW_ID) {
_update_window_style(p_id);
}
- ShowWindow(wd.hWnd, wd.no_focus ? SW_SHOWNOACTIVATE : SW_SHOW); // Show The Window
+ ShowWindow(wd.hWnd, wd.no_focus ? SW_SHOWNOACTIVATE : SW_SHOW); // Show the window.
if (!wd.no_focus) {
- SetForegroundWindow(wd.hWnd); // Slightly Higher Priority
- SetFocus(wd.hWnd); // Sets Keyboard Focus To
+ SetForegroundWindow(wd.hWnd); // Slightly higher priority.
+ SetFocus(wd.hWnd); // Set keyboard focus.
}
}
@@ -534,8 +542,13 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
context_vulkan->window_destroy(p_window);
}
#endif
+#ifdef GLES3_ENABLED
+ if (rendering_driver == "opengl3") {
+ gl_manager->window_destroy(p_window);
+ }
+#endif
- if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[p_window].wtctx) {
+ if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[p_window].wtctx) {
wintab_WTClose(windows[p_window].wtctx);
windows[p_window].wtctx = 0;
}
@@ -543,6 +556,12 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
windows.erase(p_window);
}
+void DisplayServerWindows::gl_window_make_current(DisplayServer::WindowID p_window_id) {
+#if defined(GLES3_ENABLED)
+ gl_manager->window_make_current(p_window_id);
+#endif
+}
+
void DisplayServerWindows::window_attach_instance_id(ObjectID p_instance, WindowID p_window) {
_THREAD_SAFE_METHOD_
@@ -608,6 +627,8 @@ void DisplayServerWindows::window_set_mouse_passthrough(const Vector<Vector2> &p
}
void DisplayServerWindows::_update_window_mouse_passthrough(WindowID p_window) {
+ ERR_FAIL_COND(!windows.has(p_window));
+
if (windows[p_window].mpath.size() == 0) {
SetWindowRgn(windows[p_window].hWnd, nullptr, TRUE);
} else {
@@ -666,16 +687,11 @@ Point2i DisplayServerWindows::window_get_position(WindowID p_window) const {
ClientToScreen(wd.hWnd, &point);
return Point2i(point.x, point.y);
-
-#if 0
- //do not use this method, as it includes windows decorations
- RECT r;
- GetWindowRect(wd.hWnd, &r);
- return Point2(r.left, r.top);
-#endif
}
void DisplayServerWindows::_update_real_mouse_position(WindowID p_window) {
+ ERR_FAIL_COND(!windows.has(p_window));
+
POINT mouse_pos;
if (GetCursorPos(&mouse_pos) && ScreenToClient(windows[p_window].hWnd, &mouse_pos)) {
if (mouse_pos.x > 0 && mouse_pos.y > 0 && mouse_pos.x <= windows[p_window].width && mouse_pos.y <= windows[p_window].height) {
@@ -693,14 +709,9 @@ void DisplayServerWindows::window_set_position(const Point2i &p_position, Window
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
- if (wd.fullscreen)
+ if (wd.fullscreen) {
return;
-#if 0
- //wrong needs to account properly for decorations
- RECT r;
- GetWindowRect(wd.hWnd, &r);
- MoveWindow(wd.hWnd, p_position.x, p_position.y, r.right - r.left, r.bottom - r.top, TRUE);
-#else
+ }
RECT rc;
rc.left = p_position.x;
@@ -713,9 +724,9 @@ void DisplayServerWindows::window_set_position(const Point2i &p_position, Window
AdjustWindowRectEx(&rc, style, false, exStyle);
MoveWindow(wd.hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
-#endif
- // Don't let the mouse leave the window when moved
- if (mouse_mode == MOUSE_MODE_CONFINED) {
+
+ // Don't let the mouse leave the window when moved.
+ if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
RECT rect;
GetClientRect(wd.hWnd, &rect);
ClientToScreen(wd.hWnd, (POINT *)&rect.left);
@@ -731,16 +742,15 @@ void DisplayServerWindows::window_set_transient(WindowID p_window, WindowID p_pa
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(p_window == p_parent);
-
ERR_FAIL_COND(!windows.has(p_window));
+
WindowData &wd_window = windows[p_window];
ERR_FAIL_COND(wd_window.transient_parent == p_parent);
-
ERR_FAIL_COND_MSG(wd_window.always_on_top, "Windows with the 'on top' can't become transient.");
if (p_parent == INVALID_WINDOW_ID) {
- //remove transient
+ // Remove transient.
ERR_FAIL_COND(wd_window.transient_parent == INVALID_WINDOW_ID);
ERR_FAIL_COND(!windows.has(wd_window.transient_parent));
@@ -822,6 +832,11 @@ void DisplayServerWindows::window_set_size(const Size2i p_size, WindowID p_windo
context_vulkan->window_resize(p_window, w, h);
}
#endif
+#if defined(GLES3_ENABLED)
+ if (rendering_driver == "opengl3") {
+ gl_manager->window_resize(p_window, w, h);
+ }
+#endif
if (wd.fullscreen) {
return;
@@ -840,8 +855,8 @@ void DisplayServerWindows::window_set_size(const Size2i p_size, WindowID p_windo
MoveWindow(wd.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) {
+ // Don't let the mouse leave the window when resizing to a smaller resolution.
+ if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
RECT crect;
GetClientRect(wd.hWnd, &crect);
ClientToScreen(wd.hWnd, (POINT *)&crect.left);
@@ -856,12 +871,13 @@ Size2i DisplayServerWindows::window_get_size(WindowID p_window) const {
ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
const WindowData &wd = windows[p_window];
+ // GetClientRect() returns a zero rect for a minimized window, so we need to get the size in another way.
if (wd.minimized) {
return Size2(wd.width, wd.height);
}
RECT r;
- if (GetClientRect(wd.hWnd, &r)) { // Only area inside of window border
+ if (GetClientRect(wd.hWnd, &r)) { // Retrieves area inside of window border, including decoration.
return Size2(r.right - r.left, r.bottom - r.top);
}
return Size2();
@@ -874,13 +890,17 @@ Size2i DisplayServerWindows::window_get_real_size(WindowID p_window) const {
const WindowData &wd = windows[p_window];
RECT r;
- if (GetWindowRect(wd.hWnd, &r)) { // Includes area of the window border
+ if (GetWindowRect(wd.hWnd, &r)) { // Retrieves area inside of window border, including decoration.
return Size2(r.right - r.left, r.bottom - r.top);
}
return Size2();
}
void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscreen, bool p_borderless, bool p_resizable, bool p_maximized, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex) {
+ // Windows docs for window styles:
+ // https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles
+ // https://docs.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles
+
r_style = 0;
r_style_ex = WS_EX_WINDOWEDGE;
if (p_main_window) {
@@ -888,10 +908,7 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre
}
if (p_fullscreen || p_borderless) {
- r_style |= WS_POPUP;
- //if (p_borderless) {
- // r_style_ex |= WS_EX_TOOLWINDOW;
- //}
+ r_style |= WS_POPUP; // p_borderless was WS_EX_TOOLWINDOW in the past.
} else {
if (p_resizable) {
if (p_maximized) {
@@ -903,6 +920,9 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre
r_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;
}
}
+ if (!p_borderless) {
+ r_style |= WS_VISIBLE;
+ }
if (p_no_activate_focus) {
r_style_ex |= WS_EX_TOPMOST | WS_EX_NOACTIVATE;
@@ -910,7 +930,7 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre
r_style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
}
-void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repaint, bool p_maximized) {
+void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repaint) {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
@@ -943,6 +963,7 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
RECT rect;
wd.fullscreen = false;
+ wd.maximized = wd.was_maximized;
if (wd.pre_fs_valid) {
rect = wd.pre_fs_rect;
@@ -951,13 +972,21 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
rect.right = wd.width;
rect.top = 0;
rect.bottom = wd.height;
+ wd.pre_fs_valid = true;
}
- _update_window_style(p_window, false, wd.was_maximized);
+ _update_window_style(p_window, false);
MoveWindow(wd.hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
- wd.pre_fs_valid = true;
+ if (restore_mouse_trails > 1) {
+ SystemParametersInfoA(SPI_SETMOUSETRAILS, restore_mouse_trails, 0, 0);
+ restore_mouse_trails = 0;
+ }
+ } else if (p_mode == WINDOW_MODE_WINDOWED) {
+ ShowWindow(wd.hWnd, SW_RESTORE);
+ wd.maximized = false;
+ wd.minimized = false;
}
if (p_mode == WINDOW_MODE_MAXIMIZED) {
@@ -966,12 +995,6 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
wd.minimized = false;
}
- if (p_mode == WINDOW_MODE_WINDOWED) {
- ShowWindow(wd.hWnd, SW_RESTORE);
- wd.maximized = false;
- wd.minimized = false;
- }
-
if (p_mode == WINDOW_MODE_MINIMIZED) {
ShowWindow(wd.hWnd, SW_MINIMIZE);
wd.maximized = false;
@@ -999,6 +1022,13 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
_update_window_style(false);
MoveWindow(wd.hWnd, pos.x, pos.y, size.width, size.height, TRUE);
+
+ // If the user has mouse trails enabled in windows, then sometimes the cursor disappears in fullscreen mode.
+ // Save number of trails so we can restore when exiting, then turn off mouse trails
+ SystemParametersInfoA(SPI_GETMOUSETRAILS, 0, &restore_mouse_trails, 0);
+ if (restore_mouse_trails > 1) {
+ SystemParametersInfoA(SPI_SETMOUSETRAILS, 0, 0, 0);
+ }
}
}
@@ -1026,7 +1056,7 @@ bool DisplayServerWindows::window_is_maximize_allowed(WindowID p_window) const {
// FIXME: Implement this, or confirm that it should always be true.
- return true; //no idea
+ return true;
}
void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) {
@@ -1118,14 +1148,14 @@ bool DisplayServerWindows::window_can_draw(WindowID p_window) const {
ERR_FAIL_COND_V(!windows.has(p_window), false);
const WindowData &wd = windows[p_window];
- return wd.minimized;
+ return !wd.minimized;
}
bool DisplayServerWindows::can_any_window_draw() const {
_THREAD_SAFE_METHOD_
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- if (!E->get().minimized) {
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ if (!E.value.minimized) {
return true;
}
}
@@ -1171,8 +1201,9 @@ void DisplayServerWindows::window_set_ime_position(const Point2i &p_pos, WindowI
void DisplayServerWindows::console_set_visible(bool p_enabled) {
_THREAD_SAFE_METHOD_
- if (console_visible == p_enabled)
+ if (console_visible == p_enabled) {
return;
+ }
ShowWindow(GetConsoleWindow(), p_enabled ? SW_SHOW : SW_HIDE);
console_visible = p_enabled;
}
@@ -1186,8 +1217,9 @@ void DisplayServerWindows::cursor_set_shape(CursorShape p_shape) {
ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
- if (cursor_shape == p_shape)
+ if (cursor_shape == p_shape) {
return;
+ }
if (mouse_mode != MOUSE_MODE_VISIBLE && mouse_mode != MOUSE_MODE_CONFINED) {
cursor_shape = p_shape;
@@ -1197,11 +1229,11 @@ void DisplayServerWindows::cursor_set_shape(CursorShape p_shape) {
static const LPCTSTR win_cursors[CURSOR_MAX] = {
IDC_ARROW,
IDC_IBEAM,
- IDC_HAND, //finger
+ IDC_HAND, // Finger.
IDC_CROSS,
IDC_WAIT,
IDC_APPSTARTING,
- IDC_ARROW,
+ IDC_SIZEALL,
IDC_ARROW,
IDC_NO,
IDC_SIZENS,
@@ -1228,49 +1260,49 @@ DisplayServer::CursorShape DisplayServerWindows::cursor_get_shape() const {
}
void DisplayServerWindows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap) {
- // Get the system display DC
+ // Get the system display DC.
HDC hDC = GetDC(nullptr);
- // Create helper DC
+ // Create helper DC.
HDC hMainDC = CreateCompatibleDC(hDC);
HDC hAndMaskDC = CreateCompatibleDC(hDC);
HDC hXorMaskDC = CreateCompatibleDC(hDC);
- // Get the dimensions of the source bitmap
+ // 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
+ // 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
+ // Release the system display DC.
ReleaseDC(nullptr, hDC);
- // Select the bitmaps to helper DC
+ // 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
+ // Assign the monochrome AND mask bitmap pixels so that the 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
+ // Assign the color XOR mask bitmap pixels so that the pixels of the source bitmap
// with 'clrTransparent' will be black and rest the pixels same as corresponding
- // pixels of the source bitmap
+ // 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
+ // Deselect bitmaps from the helper DC.
SelectObject(hMainDC, hOldMainBitmap);
SelectObject(hAndMaskDC, hOldAndMaskBitmap);
SelectObject(hXorMaskDC, hOldXorMaskBitmap);
- // Delete the helper DC
+ // Delete the helper DC.
DeleteDC(hXorMaskDC);
DeleteDC(hAndMaskDC);
DeleteDC(hMainDC);
@@ -1298,7 +1330,7 @@ void DisplayServerWindows::cursor_set_custom_image(const RES &p_cursor, CursorSh
Rect2 atlas_rect;
if (texture.is_valid()) {
- image = texture->get_data();
+ image = texture->get_image();
}
if (!image.is_valid() && atlas_texture.is_valid()) {
@@ -1321,13 +1353,13 @@ void DisplayServerWindows::cursor_set_custom_image(const RES &p_cursor, CursorSh
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();
+ image = texture->get_image();
ERR_FAIL_COND(!image.is_valid());
UINT image_size = texture_size.width * texture_size.height;
- // Create the BITMAP with alpha channel
+ // Create the BITMAP with alpha channel.
COLORREF *buffer = (COLORREF *)memalloc(sizeof(COLORREF) * image_size);
for (UINT index = 0; index < image_size; index++) {
@@ -1342,11 +1374,11 @@ void DisplayServerWindows::cursor_set_custom_image(const RES &p_cursor, CursorSh
*(buffer + index) = image->get_pixel(column_index, row_index).to_argb32();
}
- // Using 4 channels, so 4 * 8 bits
+ // 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
+ // Create the AND and XOR masks for the bitmap.
HBITMAP hAndMask = nullptr;
HBITMAP hXorMask = nullptr;
@@ -1358,7 +1390,7 @@ void DisplayServerWindows::cursor_set_custom_image(const RES &p_cursor, CursorSh
return;
}
- // Finally, create the icon
+ // Finally, create the icon.
ICONINFO iconinfo;
iconinfo.fIcon = FALSE;
iconinfo.xHotspot = p_hotspot.x;
@@ -1366,8 +1398,9 @@ void DisplayServerWindows::cursor_set_custom_image(const RES &p_cursor, CursorSh
iconinfo.hbmMask = hAndMask;
iconinfo.hbmColor = hXorMask;
- if (cursors[p_shape])
+ if (cursors[p_shape]) {
DestroyIcon(cursors[p_shape]);
+ }
cursors[p_shape] = CreateIconIndirect(&iconinfo);
@@ -1393,7 +1426,7 @@ void DisplayServerWindows::cursor_set_custom_image(const RES &p_cursor, CursorSh
memfree(buffer);
DeleteObject(bitmap);
} else {
- // Reset to default system cursor
+ // Reset to default system cursor.
if (cursors[p_shape]) {
DestroyIcon(cursors[p_shape]);
cursors[p_shape] = nullptr;
@@ -1418,13 +1451,13 @@ void DisplayServerWindows::enable_for_stealing_focus(OS::ProcessID pid) {
}
int DisplayServerWindows::keyboard_get_layout_count() const {
- return GetKeyboardLayoutList(0, NULL);
+ return GetKeyboardLayoutList(0, nullptr);
}
int DisplayServerWindows::keyboard_get_current_layout() const {
HKL cur_layout = GetKeyboardLayout(0);
- int layout_count = GetKeyboardLayoutList(0, NULL);
+ int layout_count = GetKeyboardLayoutList(0, nullptr);
HKL *layouts = (HKL *)memalloc(layout_count * sizeof(HKL));
GetKeyboardLayoutList(layout_count, layouts);
@@ -1439,7 +1472,7 @@ int DisplayServerWindows::keyboard_get_current_layout() const {
}
void DisplayServerWindows::keyboard_set_current_layout(int p_index) {
- int layout_count = GetKeyboardLayoutList(0, NULL);
+ int layout_count = GetKeyboardLayoutList(0, nullptr);
ERR_FAIL_INDEX(p_index, layout_count);
@@ -1450,7 +1483,7 @@ void DisplayServerWindows::keyboard_set_current_layout(int p_index) {
}
String DisplayServerWindows::keyboard_get_layout_language(int p_index) const {
- int layout_count = GetKeyboardLayoutList(0, NULL);
+ int layout_count = GetKeyboardLayoutList(0, nullptr);
ERR_FAIL_INDEX_V(p_index, layout_count, "");
@@ -1466,6 +1499,42 @@ String DisplayServerWindows::keyboard_get_layout_language(int p_index) const {
return String::utf16((const char16_t *)buf).substr(0, 2);
}
+Key DisplayServerWindows::keyboard_get_keycode_from_physical(Key p_keycode) const {
+ Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK;
+ Key keycode_no_mod = (Key)(p_keycode & KeyModifierMask::CODE_MASK);
+
+ if (keycode_no_mod == Key::PRINT ||
+ keycode_no_mod == Key::KP_ADD ||
+ keycode_no_mod == Key::KP_5 ||
+ (keycode_no_mod >= Key::KEY_0 && keycode_no_mod <= Key::KEY_9)) {
+ return p_keycode;
+ }
+
+ unsigned int scancode = KeyMappingWindows::get_scancode(keycode_no_mod);
+ if (scancode == 0) {
+ return p_keycode;
+ }
+
+ HKL current_layout = GetKeyboardLayout(0);
+ UINT vk = MapVirtualKeyEx(scancode, MAPVK_VSC_TO_VK, current_layout);
+ if (vk == 0) {
+ return p_keycode;
+ }
+
+ UINT char_code = MapVirtualKeyEx(vk, MAPVK_VK_TO_CHAR, current_layout) & 0x7FFF;
+ // Unlike a similar Linux/BSD check which matches full Latin-1 range,
+ // we limit these to ASCII to fix some layouts, including Arabic ones
+ if (char_code >= 32 && char_code <= 127) {
+ // Godot uses 'braces' instead of 'brackets'
+ if (char_code == (unsigned int)Key::BRACKETLEFT || char_code == (unsigned int)Key::BRACKETRIGHT) {
+ char_code += 32;
+ }
+ return (Key)(char_code | (unsigned int)modifiers);
+ }
+
+ return (Key)(KeyMappingWindows::get_keysym(vk) | modifiers);
+}
+
String _get_full_layout_name_from_registry(HKL p_layout) {
String id = "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\" + String::num_int64((int64_t)p_layout, 16, false).lpad(8, "0");
String ret;
@@ -1480,7 +1549,7 @@ String _get_full_layout_name_from_registry(HKL p_layout) {
DWORD buffer = 1024;
DWORD vtype = REG_SZ;
- if (RegQueryValueExW(hkey, L"Layout Text", NULL, &vtype, (LPBYTE)layout_text, &buffer) == ERROR_SUCCESS) {
+ if (RegQueryValueExW(hkey, L"Layout Text", nullptr, &vtype, (LPBYTE)layout_text, &buffer) == ERROR_SUCCESS) {
ret = String::utf16((const char16_t *)layout_text);
}
RegCloseKey(hkey);
@@ -1488,7 +1557,7 @@ String _get_full_layout_name_from_registry(HKL p_layout) {
}
String DisplayServerWindows::keyboard_get_layout_name(int p_index) const {
- int layout_count = GetKeyboardLayoutList(0, NULL);
+ int layout_count = GetKeyboardLayoutList(0, nullptr);
ERR_FAIL_INDEX_V(p_index, layout_count, "");
@@ -1528,7 +1597,7 @@ void DisplayServerWindows::process_events() {
if (!drop_events) {
_process_key_events();
- Input::get_singleton()->flush_accumulated_events();
+ Input::get_singleton()->flush_buffered_events();
}
}
@@ -1547,6 +1616,9 @@ void DisplayServerWindows::make_rendering_thread() {
}
void DisplayServerWindows::swap_buffers() {
+#if defined(GLES3_ENABLED)
+ gl_manager->swap_buffers();
+#endif
}
void DisplayServerWindows::set_native_icon(const String &p_filename) {
@@ -1575,9 +1647,9 @@ void DisplayServerWindows::set_native_icon(const String &p_filename) {
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_index = -1; // Select 16x16 with largest color count.
int small_icon_cc = 0;
- int big_icon_index = -1; // Select largest
+ int big_icon_index = -1; // Select largest.
int big_icon_width = 16;
int big_icon_cc = 0;
@@ -1607,7 +1679,7 @@ void DisplayServerWindows::set_native_icon(const String &p_filename) {
small_icon_cc = big_icon_cc;
}
- // Read the big icon
+ // Read the big icon.
DWORD bytecount_big = icon_dir->idEntries[big_icon_index].dwBytesInRes;
Vector<uint8_t> data_big;
data_big.resize(bytecount_big);
@@ -1617,7 +1689,7 @@ void DisplayServerWindows::set_native_icon(const String &p_filename) {
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
+ // Read the small icon.
DWORD bytecount_small = icon_dir->idEntries[small_icon_index].dwBytesInRes;
Vector<uint8_t> data_small;
data_small.resize(bytecount_small);
@@ -1627,7 +1699,7 @@ void DisplayServerWindows::set_native_icon(const String &p_filename) {
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
+ // Online tradition says to be sure last error is cleared and set the small icon first.
int err = 0;
SetLastError(err);
@@ -1648,12 +1720,13 @@ void DisplayServerWindows::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)
+ 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 */
+ // Create temporary bitmap buffer.
int icon_len = 40 + h * w * 4;
Vector<BYTE> v;
v.resize(icon_len);
@@ -1687,18 +1760,28 @@ void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) {
HICON hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
- /* Set the icon for the window */
+ // Set the icon for the window.
SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon);
- /* Set the icon in the task manager (should we do this?) */
+ // Set the icon in the task manager (should we do this?).
SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_BIG, (LPARAM)hicon);
}
-void DisplayServerWindows::vsync_set_use_via_compositor(bool p_enable) {
+void DisplayServerWindows::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ // TODO disabling for now
+ //context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+#endif
}
-bool DisplayServerWindows::vsync_is_using_via_compositor() const {
- return false;
+DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ //TODO disabling for now
+ //return context_vulkan->get_vsync_mode(p_window);
+#endif
+ return DisplayServer::VSYNC_ENABLED;
}
void DisplayServerWindows::set_context(Context p_context) {
@@ -1709,13 +1792,13 @@ void DisplayServerWindows::set_context(Context p_context) {
// 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)
+// This one tells whether the event comes from touchscreen (and not from pen).
#define IsTouchEvent(dw) (IsPenEvent(dw) && ((dw)&0x80))
void DisplayServerWindows::_touch_event(WindowID p_window, bool p_pressed, float p_x, float p_y, int idx) {
- // Defensive
- if (touch_state.has(idx) == p_pressed)
+ if (touch_state.has(idx) == p_pressed) {
return;
+ }
if (p_pressed) {
touch_state.insert(idx, Vector2(p_x, p_y));
@@ -1724,32 +1807,33 @@ void DisplayServerWindows::_touch_event(WindowID p_window, bool p_pressed, float
}
Ref<InputEventScreenTouch> event;
- event.instance();
+ event.instantiate();
event->set_index(idx);
event->set_window_id(p_window);
event->set_pressed(p_pressed);
event->set_position(Vector2(p_x, p_y));
- Input::get_singleton()->accumulate_input_event(event);
+ Input::get_singleton()->parse_input_event(event);
}
void DisplayServerWindows::_drag_event(WindowID p_window, float p_x, float p_y, int idx) {
Map<int, Vector2>::Element *curr = touch_state.find(idx);
- // Defensive
- if (!curr)
+ if (!curr) {
return;
+ }
- if (curr->get() == Vector2(p_x, p_y))
+ if (curr->get() == Vector2(p_x, p_y)) {
return;
+ }
Ref<InputEventScreenDrag> event;
- event.instance();
+ event.instantiate();
event->set_window_id(p_window);
event->set_index(idx);
event->set_position(Vector2(p_x, p_y));
event->set_relative(Vector2(p_x, p_y) - curr->get());
- Input::get_singleton()->accumulate_input_event(event);
+ Input::get_singleton()->parse_input_event(event);
curr->get() = Vector2(p_x, p_y);
}
@@ -1782,8 +1866,11 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
Ref<InputEventFromWindow> event_from_window = p_event;
if (event_from_window.is_valid() && event_from_window->get_window_id() != INVALID_WINDOW_ID) {
- //send to a window
- ERR_FAIL_COND(!windows.has(event_from_window->get_window_id()));
+ // Send to a single window.
+ if (!windows.has(event_from_window->get_window_id())) {
+ in_dispatch_input_event = false;
+ ERR_FAIL_MSG("DisplayServerWindows: Invalid window id in input event.");
+ }
Callable callable = windows[event_from_window->get_window_id()].input_event_callback;
if (callable.is_null()) {
in_dispatch_input_event = false;
@@ -1791,9 +1878,9 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
}
callable.call((const Variant **)&evp, 1, ret, ce);
} else {
- //send to all windows
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- Callable callable = E->get().input_event_callback;
+ // Send to all windows.
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ const Callable callable = E.value.input_event_callback;
if (callable.is_null()) {
continue;
}
@@ -1804,6 +1891,9 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
in_dispatch_input_event = false;
}
+// Our default window procedure to handle processing of window-related system messages/events.
+// Also known as DefProc or DefWindowProc.
+// See: https://docs.microsoft.com/en-us/windows/win32/winmsg/window-procedures
LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (drop_events) {
if (user_proc) {
@@ -1816,27 +1906,28 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
WindowID window_id = INVALID_WINDOW_ID;
bool window_created = false;
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- if (E->get().hWnd == hWnd) {
- window_id = E->key();
+ // Check whether window exists.
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ if (E.value.hWnd == hWnd) {
+ window_id = E.key;
window_created = true;
break;
}
}
+ // Window doesn't exist or creation in progress, don't handle messages yet.
if (!window_created) {
- // Window creation in progress.
window_id = window_id_counter;
ERR_FAIL_COND_V(!windows.has(window_id), 0);
}
- switch (uMsg) // Check For Windows Messages
- {
+ // Process window messages.
+ switch (uMsg) {
case WM_SETFOCUS: {
windows[window_id].window_has_focus = true;
last_focused_window = window_id;
- // Restore mouse mode
+ // Restore mouse mode.
_set_mouse_mode_impl(mouse_mode);
if (!app_focused) {
@@ -1845,18 +1936,17 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
app_focused = true;
}
- break;
- }
+ } break;
case WM_KILLFOCUS: {
windows[window_id].window_has_focus = false;
last_focused_window = window_id;
- // Release capture unconditionally because it can be set due to dragging, in addition to captured mode
+ // 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(window_id, false, E->get().x, E->get().y, E->key());
+ // Release every touch to avoid sticky points.
+ for (const KeyValue<int, Vector2> &E : touch_state) {
+ _touch_event(window_id, false, E.value.x, E.value.y, E.key);
}
touch_state.clear();
@@ -1872,35 +1962,24 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
app_focused = false;
}
+ } break;
+ case WM_ACTIVATE: { // Watch for window activate message.
+ if (!windows[window_id].window_focused) {
+ _process_activate_event(window_id, wParam, lParam);
+ } else {
+ windows[window_id].saved_wparam = wParam;
+ windows[window_id].saved_lparam = lParam;
- break;
- }
- case WM_ACTIVATE: // Watch For Window Activate Message
- {
- windows[window_id].minimized = HIWORD(wParam) != 0;
-
- if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) {
- _send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_IN);
- windows[window_id].window_focused = true;
- alt_mem = false;
- control_mem = false;
- shift_mem = false;
- } else { // WM_INACTIVE
- Input::get_singleton()->release_pressed_events();
- _send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_OUT);
- windows[window_id].window_focused = false;
- alt_mem = false;
- };
-
- if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
- wintab_WTEnable(windows[window_id].wtctx, GET_WM_ACTIVATE_STATE(wParam, lParam));
+ // Run a timer to prevent event catching warning if the focused window is closing.
+ windows[window_id].focus_timer_id = SetTimer(windows[window_id].hWnd, 2, USER_TIMER_MINIMUM, (TIMERPROC) nullptr);
}
-
- return 0; // Return To The Message Loop
- }
+ return 0; // Return to the message loop.
+ } break;
case WM_GETMINMAXINFO: {
if (windows[window_id].resizable && !windows[window_id].fullscreen) {
- Size2 decor = window_get_size(window_id) - window_get_real_size(window_id); // Size of window decorations
+ // Size of window decorations.
+ Size2 decor = window_get_real_size(window_id) - window_get_size(window_id);
+
MINMAXINFO *min_max_info = (MINMAXINFO *)lParam;
if (windows[window_id].min_size != Size2()) {
min_max_info->ptMinTrackSize.x = windows[window_id].min_size.x + decor.x;
@@ -1911,34 +1990,31 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
min_max_info->ptMaxTrackSize.y = windows[window_id].max_size.y + decor.y;
}
return 0;
- } else {
- break;
}
- }
- case WM_PAINT:
-
+ } break;
+ case WM_PAINT: {
Main::force_redraw();
- break;
-
- case WM_SYSCOMMAND: // Intercept System Commands
+ } break;
+ case WM_SYSCOMMAND: // Intercept system commands.
{
- switch (wParam) // Check System Calls
+ 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_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?
+ } break;
+ case WM_CLOSE: // Did we receive a close message?
{
+ if (windows[window_id].focus_timer_id != 0U) {
+ KillTimer(windows[window_id].hWnd, windows[window_id].focus_timer_id);
+ }
_send_window_event(windows[window_id], WINDOW_EVENT_CLOSE_REQUEST);
- return 0; // Jump Back
+ return 0; // Jump back.
}
case WM_MOUSELEAVE: {
old_invalid = true;
@@ -1967,12 +2043,12 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
if (raw->header.dwType == RIM_TYPEMOUSE) {
Ref<InputEventMouseMotion> mm;
- mm.instance();
+ mm.instantiate();
mm->set_window_id(window_id);
- mm->set_control(control_mem);
- mm->set_shift(shift_mem);
- mm->set_alt(alt_mem);
+ mm->set_ctrl_pressed(control_mem);
+ mm->set_shift_pressed(shift_mem);
+ mm->set_alt_pressed(alt_mem);
mm->set_pressure((raw->data.mouse.ulButtons & RI_MOUSE_LEFT_BUTTON_DOWN) ? 1.0f : 0.0f);
@@ -1980,7 +2056,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
Point2i c(windows[window_id].width / 2, windows[window_id].height / 2);
- // centering just so it works as before
+ // Centering just so it works as before.
POINT pos = { (int)c.x, (int)c.y };
ClientToScreen(windows[window_id].hWnd, &pos);
SetCursorPos(pos.x, pos.y);
@@ -2003,7 +2079,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
(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
+ POINT coords; // Client coords.
coords.x = abs_pos.x;
coords.y = abs_pos.y;
@@ -2012,20 +2088,17 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
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 (windows[window_id].window_has_focus && mm->get_relative() != Vector2())
- Input::get_singleton()->accumulate_input_event(mm);
+ if (windows[window_id].window_has_focus && mm->get_relative() != Vector2()) {
+ Input::get_singleton()->parse_input_event(mm);
+ }
}
delete[] lpb;
} break;
case WT_CSRCHANGE:
case WT_PROXIMITY: {
- if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
+ if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
AXIS pressure;
if (wintab_WTInfo(WTI_DEVICES + windows[window_id].wtlc.lcDevice, DVC_NPRESSURE, &pressure)) {
windows[window_id].min_pressure = int(pressure.axMin);
@@ -2039,7 +2112,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
} break;
case WT_PACKET: {
- if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
+ if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
PACKET packet;
if (wintab_WTPacket(windows[window_id].wtctx, wParam, &packet)) {
float pressure = float(packet.pkNormalPressure - windows[window_id].min_pressure) / float(windows[window_id].max_pressure - windows[window_id].min_pressure);
@@ -2064,11 +2137,11 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
break;
Ref<InputEventMouseMotion> mm;
- mm.instance();
+ mm.instantiate();
mm->set_window_id(window_id);
- mm->set_control(GetKeyState(VK_CONTROL) < 0);
- mm->set_shift(GetKeyState(VK_SHIFT) < 0);
- mm->set_alt(alt_mem);
+ mm->set_ctrl_pressed(GetKeyState(VK_CONTROL) < 0);
+ mm->set_shift_pressed(GetKeyState(VK_SHIFT) < 0);
+ mm->set_alt_pressed(alt_mem);
mm->set_pressure(windows[window_id].last_pressure);
mm->set_tilt(windows[window_id].last_tilt);
@@ -2108,7 +2181,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
old_x = mm->get_position().x;
old_y = mm->get_position().y;
if (windows[window_id].window_has_focus)
- Input::get_singleton()->accumulate_input_event(mm);
+ Input::get_singleton()->parse_input_event(mm);
}
return 0;
}
@@ -2118,7 +2191,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
break;
}
- if ((OS::get_singleton()->get_current_tablet_driver() != "winink") || !winink_available) {
+ if ((tablet_get_current_driver() != "winink") || !winink_available) {
break;
}
@@ -2144,7 +2217,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
break;
}
- if ((OS::get_singleton()->get_current_tablet_driver() != "winink") || !winink_available) {
+ if ((tablet_get_current_driver() != "winink") || !winink_available) {
break;
}
@@ -2164,7 +2237,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
if (Input::get_singleton()->is_emulating_mouse_from_touch()) {
- // Universal translation enabled; ignore OS translation
+ // Universal translation enabled; ignore OS translation.
LPARAM extra = GetMessageExtraInfo();
if (IsTouchEvent(extra)) {
break;
@@ -2172,7 +2245,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
if (outside) {
- //mouse enter
+ // Mouse enter.
if (mouse_mode != MOUSE_MODE_CAPTURED) {
_send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_ENTER);
@@ -2183,7 +2256,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
cursor_set_shape(c);
outside = false;
- //Once-Off notification, must call again....
+ // Once-off notification, must call again.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
@@ -2193,11 +2266,12 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
// Don't calculate relative mouse movement if we don't have focus in CAPTURED mode.
- if (!windows[window_id].window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED)
+ if (!windows[window_id].window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) {
break;
+ }
Ref<InputEventMouseMotion> mm;
- mm.instance();
+ mm.instantiate();
mm->set_window_id(window_id);
if (pen_info.penMask & PEN_MASK_PRESSURE) {
@@ -2209,13 +2283,13 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
mm->set_tilt(Vector2((float)pen_info.tiltX / 90, (float)pen_info.tiltY / 90));
}
- mm->set_control(GetKeyState(VK_CONTROL) < 0);
- mm->set_shift(GetKeyState(VK_SHIFT) < 0);
- mm->set_alt(alt_mem);
+ mm->set_ctrl_pressed(GetKeyState(VK_CONTROL) < 0);
+ mm->set_shift_pressed(GetKeyState(VK_SHIFT) < 0);
+ mm->set_alt_pressed(alt_mem);
mm->set_button_mask(last_button_state);
- POINT coords; //client coords
+ POINT coords; // Client coords.
coords.x = GET_X_LPARAM(lParam);
coords.y = GET_Y_LPARAM(lParam);
@@ -2254,10 +2328,10 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
old_x = mm->get_position().x;
old_y = mm->get_position().y;
if (windows[window_id].window_has_focus) {
- Input::get_singleton()->accumulate_input_event(mm);
+ Input::get_singleton()->parse_input_event(mm);
}
- return 0; //Pointer event handled return 0 to avoid duplicate WM_MOUSEMOVE event
+ return 0; // Pointer event handled return 0 to avoid duplicate WM_MOUSEMOVE event.
} break;
case WM_MOUSEMOVE: {
if (windows[window_id].block_mm) {
@@ -2269,7 +2343,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
if (Input::get_singleton()->is_emulating_mouse_from_touch()) {
- // Universal translation enabled; ignore OS translation
+ // Universal translation enabled; ignore OS translation.
LPARAM extra = GetMessageExtraInfo();
if (IsTouchEvent(extra)) {
break;
@@ -2277,7 +2351,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
if (outside) {
- //mouse enter
+ // Mouse enter.
if (mouse_mode != MOUSE_MODE_CAPTURED) {
_send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_ENTER);
@@ -2288,7 +2362,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
cursor_set_shape(c);
outside = false;
- //Once-Off notification, must call again....
+ // Once-off notification, must call again.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
@@ -2298,18 +2372,19 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
// Don't calculate relative mouse movement if we don't have focus in CAPTURED mode.
- if (!windows[window_id].window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED)
+ if (!windows[window_id].window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) {
break;
+ }
Ref<InputEventMouseMotion> mm;
- mm.instance();
+ mm.instantiate();
mm->set_window_id(window_id);
- mm->set_control((wParam & MK_CONTROL) != 0);
- mm->set_shift((wParam & MK_SHIFT) != 0);
- mm->set_alt(alt_mem);
+ mm->set_ctrl_pressed((wParam & MK_CONTROL) != 0);
+ mm->set_shift_pressed((wParam & MK_SHIFT) != 0);
+ mm->set_alt_pressed(alt_mem);
- if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
- // Note: WinTab sends both WT_PACKET and WM_xBUTTONDOWN/UP/MOUSEMOVE events, use mouse 1/0 pressure only when last_pressure was not update recently.
+ if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
+ // Note: WinTab sends both WT_PACKET and WM_xBUTTONDOWN/UP/MOUSEMOVE events, use mouse 1/0 pressure only when last_pressure was not updated recently.
if (windows[window_id].last_pressure_update < 10) {
windows[window_id].last_pressure_update++;
} else {
@@ -2359,13 +2434,13 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
old_x = mm->get_position().x;
old_y = mm->get_position().y;
if (windows[window_id].window_has_focus)
- Input::get_singleton()->accumulate_input_event(mm);
+ Input::get_singleton()->parse_input_event(mm);
} break;
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
if (Input::get_singleton()->is_emulating_mouse_from_touch()) {
- // Universal translation enabled; ignore OS translations for left button
+ // Universal translation enabled; ignore OS translations for left button.
LPARAM extra = GetMessageExtraInfo();
if (IsTouchEvent(extra)) {
break;
@@ -2385,110 +2460,116 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
case WM_XBUTTONDOWN:
case WM_XBUTTONUP: {
Ref<InputEventMouseButton> mb;
- mb.instance();
+ mb.instantiate();
mb->set_window_id(window_id);
switch (uMsg) {
case WM_LBUTTONDOWN: {
mb->set_pressed(true);
- mb->set_button_index(1);
+ mb->set_button_index(MouseButton::LEFT);
} break;
case WM_LBUTTONUP: {
mb->set_pressed(false);
- mb->set_button_index(1);
+ mb->set_button_index(MouseButton::LEFT);
} break;
case WM_MBUTTONDOWN: {
mb->set_pressed(true);
- mb->set_button_index(3);
+ mb->set_button_index(MouseButton::MIDDLE);
} break;
case WM_MBUTTONUP: {
mb->set_pressed(false);
- mb->set_button_index(3);
+ mb->set_button_index(MouseButton::MIDDLE);
} break;
case WM_RBUTTONDOWN: {
mb->set_pressed(true);
- mb->set_button_index(2);
+ mb->set_button_index(MouseButton::RIGHT);
} break;
case WM_RBUTTONUP: {
mb->set_pressed(false);
- mb->set_button_index(2);
+ mb->set_button_index(MouseButton::RIGHT);
} break;
case WM_LBUTTONDBLCLK: {
mb->set_pressed(true);
- mb->set_button_index(1);
- mb->set_doubleclick(true);
+ mb->set_button_index(MouseButton::LEFT);
+ mb->set_double_click(true);
} break;
case WM_RBUTTONDBLCLK: {
mb->set_pressed(true);
- mb->set_button_index(2);
- mb->set_doubleclick(true);
+ mb->set_button_index(MouseButton::RIGHT);
+ mb->set_double_click(true);
} break;
case WM_MBUTTONDBLCLK: {
mb->set_pressed(true);
- mb->set_button_index(3);
- mb->set_doubleclick(true);
+ mb->set_button_index(MouseButton::MIDDLE);
+ mb->set_double_click(true);
} break;
case WM_MOUSEWHEEL: {
mb->set_pressed(true);
int motion = (short)HIWORD(wParam);
- if (!motion)
+ if (!motion) {
return 0;
+ }
- if (motion > 0)
- mb->set_button_index(BUTTON_WHEEL_UP);
- else
- mb->set_button_index(BUTTON_WHEEL_DOWN);
-
+ if (motion > 0) {
+ mb->set_button_index(MouseButton::WHEEL_UP);
+ } else {
+ mb->set_button_index(MouseButton::WHEEL_DOWN);
+ }
+ mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA));
} break;
case WM_MOUSEHWHEEL: {
mb->set_pressed(true);
int motion = (short)HIWORD(wParam);
- if (!motion)
+ if (!motion) {
return 0;
+ }
if (motion < 0) {
- mb->set_button_index(BUTTON_WHEEL_LEFT);
- mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA));
+ mb->set_button_index(MouseButton::WHEEL_LEFT);
} else {
- mb->set_button_index(BUTTON_WHEEL_RIGHT);
- mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA));
+ mb->set_button_index(MouseButton::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);
+ if (HIWORD(wParam) == XBUTTON1) {
+ mb->set_button_index(MouseButton::MB_XBUTTON1);
+ } else {
+ mb->set_button_index(MouseButton::MB_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);
+ if (HIWORD(wParam) == XBUTTON1) {
+ mb->set_button_index(MouseButton::MB_XBUTTON1);
+ } else {
+ mb->set_button_index(MouseButton::MB_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);
+ if (HIWORD(wParam) == XBUTTON1) {
+ mb->set_button_index(MouseButton::MB_XBUTTON1);
+ } else {
+ mb->set_button_index(MouseButton::MB_XBUTTON2);
+ }
+ mb->set_double_click(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_ctrl_pressed((wParam & MK_CONTROL) != 0);
+ mb->set_shift_pressed((wParam & MK_SHIFT) != 0);
+ mb->set_alt_pressed(alt_mem);
+ // mb->is_alt_pressed()=(wParam&MK_MENU)!=0;
+ if (mb->is_pressed()) {
+ last_button_state |= mouse_button_to_mask(mb->get_button_index());
+ } else {
+ last_button_state &= ~mouse_button_to_mask(mb->get_button_index());
+ }
mb->set_button_mask(last_button_state);
mb->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
@@ -2510,7 +2591,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
} else {
- // for reasons unknown to mankind, wheel comes in screen coordinates
+ // For reasons unknown to mankind, wheel comes in screen coordinates.
POINT coords;
coords.x = mb->get_position().x;
coords.y = mb->get_position().y;
@@ -2522,19 +2603,18 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
mb->set_global_position(mb->get_position());
- Input::get_singleton()->accumulate_input_event(mb);
- if (mb->is_pressed() && mb->get_button_index() > 3 && mb->get_button_index() < 8) {
- //send release for mouse wheel
+ Input::get_singleton()->parse_input_event(mb);
+ if (mb->is_pressed() && mb->get_button_index() >= MouseButton::WHEEL_UP && mb->get_button_index() <= MouseButton::WHEEL_RIGHT) {
+ // Send release for mouse wheel.
Ref<InputEventMouseButton> mbd = mb->duplicate();
mbd->set_window_id(window_id);
- last_button_state &= ~(1 << (mbd->get_button_index() - 1));
+ last_button_state &= ~mouse_button_to_mask(mbd->get_button_index());
mbd->set_button_mask(last_button_state);
mbd->set_pressed(false);
- Input::get_singleton()->accumulate_input_event(mbd);
+ Input::get_singleton()->parse_input_event(mbd);
}
} break;
-
case WM_MOVE: {
if (!IsIconic(windows[window_id].hWnd)) {
int x = int16_t(LOWORD(lParam));
@@ -2550,12 +2630,14 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
} break;
-
case WM_SIZE: {
- // Ignore size when a SIZE_MINIMIZED event is triggered
+ // Ignore window size change when a SIZE_MINIMIZED event is triggered.
if (wParam != SIZE_MINIMIZED) {
+ // The new width and height of the client area.
int window_w = LOWORD(lParam);
int window_h = HIWORD(lParam);
+
+ // Set new value to the size if it isn't preserved.
if (window_w > 0 && window_h > 0 && !windows[window_id].preserve_window_size) {
windows[window_id].width = window_w;
windows[window_id].height = window_h;
@@ -2566,27 +2648,38 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
#endif
- } else {
+ } else { // If the size is preserved.
windows[window_id].preserve_window_size = false;
+
+ // Restore the old size.
window_set_size(Size2(windows[window_id].width, windows[window_id].height), window_id);
}
+ } else { // When the window has been minimized, preserve its size.
+ windows[window_id].preserve_window_size = true;
}
+ // Call windows rect change callback.
if (!windows[window_id].rect_changed_callback.is_null()) {
Variant size = Rect2i(windows[window_id].last_pos.x, windows[window_id].last_pos.y, windows[window_id].width, windows[window_id].height);
- Variant *sizep = &size;
+ Variant *size_ptr = &size;
Variant ret;
Callable::CallError ce;
- windows[window_id].rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce);
+ windows[window_id].rect_changed_callback.call((const Variant **)&size_ptr, 1, ret, ce);
}
+ // The window has been maximized.
if (wParam == SIZE_MAXIMIZED) {
windows[window_id].maximized = true;
windows[window_id].minimized = false;
- } else if (wParam == SIZE_MINIMIZED) {
+ }
+ // The window has been minimized.
+ else if (wParam == SIZE_MINIMIZED) {
windows[window_id].maximized = false;
windows[window_id].minimized = true;
- } else if (wParam == SIZE_RESTORED) {
+ windows[window_id].preserve_window_size = false;
+ }
+ // The window has been resized, but neither the SIZE_MINIMIZED nor SIZE_MAXIMIZED value applies.
+ else if (wParam == SIZE_RESTORED) {
windows[window_id].maximized = false;
windows[window_id].minimized = false;
}
@@ -2613,25 +2706,26 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
ZeroMemory(dib_data, dib_size.x * dib_size.y * 4);
}
#endif
- //return 0; // Jump Back
} break;
-
case WM_ENTERSIZEMOVE: {
Input::get_singleton()->release_pressed_events();
- move_timer_id = SetTimer(windows[window_id].hWnd, 1, USER_TIMER_MINIMUM, (TIMERPROC) nullptr);
+ windows[window_id].move_timer_id = SetTimer(windows[window_id].hWnd, 1, USER_TIMER_MINIMUM, (TIMERPROC) nullptr);
} break;
case WM_EXITSIZEMOVE: {
- KillTimer(windows[window_id].hWnd, move_timer_id);
+ KillTimer(windows[window_id].hWnd, windows[window_id].move_timer_id);
} break;
case WM_TIMER: {
- if (wParam == move_timer_id) {
+ if (wParam == windows[window_id].move_timer_id) {
_process_key_events();
if (!Main::is_iterating()) {
Main::iteration();
}
+ } else if (wParam == windows[window_id].focus_timer_id) {
+ _process_activate_event(window_id, windows[window_id].saved_wparam, windows[window_id].saved_lparam);
+ KillTimer(windows[window_id].hWnd, wParam);
+ windows[window_id].focus_timer_id = 0U;
}
} break;
-
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYUP:
@@ -2683,7 +2777,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
case WM_INPUTLANGCHANGEREQUEST: {
// FIXME: Do something?
} break;
-
case WM_TOUCH: {
BOOL bHandled = FALSE;
UINT cInputs = LOWORD(wParam);
@@ -2697,7 +2790,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
TOUCH_COORD_TO_PIXEL(ti.y),
};
ScreenToClient(hWnd, &touch_pos);
- //do something with each touch input entry
+ // Do something with each touch input entry.
if (ti.dwFlags & TOUCHEVENTF_MOVE) {
_drag_event(window_id, touch_pos.x, touch_pos.y, ti.dwID);
} else if (ti.dwFlags & (TOUCHEVENTF_UP | TOUCHEVENTF_DOWN)) {
@@ -2706,11 +2799,11 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
bHandled = TRUE;
} else {
- /* handle the error here */
+ // TODO: Handle the error here.
}
memdelete_arr(pInputs);
} else {
- /* handle the error here, probably out of memory */
+ // TODO: Handle the error here, probably out of memory.
}
if (bHandled) {
CloseTouchInputHandle((HTOUCHINPUT)lParam);
@@ -2718,14 +2811,13 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
};
} break;
-
case WM_DEVICECHANGE: {
joypad->probe_joypads();
} break;
case WM_SETCURSOR: {
if (LOWORD(lParam) == HTCLIENT) {
- if (windows[window_id].window_has_focus && (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED)) {
- //Hide the cursor
+ if (windows[window_id].window_has_focus && (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN)) {
+ // Hide the cursor.
if (hCursor == nullptr) {
hCursor = SetCursor(nullptr);
} else {
@@ -2740,7 +2832,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
}
-
} break;
case WM_DROPFILES: {
HDROP hDropInfo = (HDROP)wParam;
@@ -2764,9 +2855,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
Callable::CallError ce;
windows[window_id].drop_files_callback.call((const Variant **)&vp, 1, ret, ce);
}
-
} break;
-
default: {
if (user_proc) {
return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam);
@@ -2785,66 +2874,121 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
+void DisplayServerWindows::_process_activate_event(WindowID p_window_id, WPARAM wParam, LPARAM lParam) {
+ if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) {
+ _send_window_event(windows[p_window_id], WINDOW_EVENT_FOCUS_IN);
+ windows[p_window_id].window_focused = true;
+ alt_mem = false;
+ control_mem = false;
+ shift_mem = false;
+ } else { // WM_INACTIVE.
+ Input::get_singleton()->release_pressed_events();
+ _send_window_event(windows[p_window_id], WINDOW_EVENT_FOCUS_OUT);
+ windows[p_window_id].window_focused = false;
+ alt_mem = false;
+ }
+
+ if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[p_window_id].wtctx) {
+ wintab_WTEnable(windows[p_window_id].wtctx, GET_WM_ACTIVATE_STATE(wParam, lParam));
+ }
+}
+
void DisplayServerWindows::_process_key_events() {
for (int i = 0; i < key_event_pos; i++) {
KeyEvent &ke = key_event_buffer[i];
switch (ke.uMsg) {
case WM_CHAR: {
- // extended keys should only be processed as WM_KEYDOWN message.
+ // Extended keys should only be processed as WM_KEYDOWN message.
if (!KeyMappingWindows::is_extended_key(ke.wParam) && ((i == 0 && ke.uMsg == WM_CHAR) || (i > 0 && key_event_buffer[i - 1].uMsg == WM_CHAR))) {
+ static char32_t prev_wc = 0;
+ char32_t unicode = ke.wParam;
+ if ((unicode & 0xfffffc00) == 0xd800) {
+ if (prev_wc != 0) {
+ ERR_PRINT("invalid utf16 surrogate input");
+ }
+ prev_wc = unicode;
+ break; // Skip surrogate.
+ } else if ((unicode & 0xfffffc00) == 0xdc00) {
+ if (prev_wc == 0) {
+ ERR_PRINT("invalid utf16 surrogate input");
+ break; // Skip invalid surrogate.
+ }
+ unicode = (prev_wc << 10UL) + unicode - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
+ prev_wc = 0;
+ } else {
+ prev_wc = 0;
+ }
Ref<InputEventKey> k;
- k.instance();
+ k.instantiate();
k->set_window_id(ke.window_id);
- k->set_shift(ke.shift);
- k->set_alt(ke.alt);
- k->set_control(ke.control);
- k->set_metakey(ke.meta);
+ k->set_shift_pressed(ke.shift);
+ k->set_alt_pressed(ke.alt);
+ k->set_ctrl_pressed(ke.control);
+ k->set_meta_pressed(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);
+ k->set_keycode((Key)KeyMappingWindows::get_keysym(ke.wParam));
+ k->set_physical_keycode((Key)(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24))));
+ k->set_unicode(unicode);
if (k->get_unicode() && gr_mem) {
- k->set_alt(false);
- k->set_control(false);
+ k->set_alt_pressed(false);
+ k->set_ctrl_pressed(false);
}
if (k->get_unicode() < 32)
k->set_unicode(0);
- Input::get_singleton()->accumulate_input_event(k);
+ Input::get_singleton()->parse_input_event(k);
+ } else {
+ // Do nothing.
}
-
- //do nothing
} break;
case WM_KEYUP:
case WM_KEYDOWN: {
Ref<InputEventKey> k;
- k.instance();
+ k.instantiate();
k->set_window_id(ke.window_id);
- k->set_shift(ke.shift);
- k->set_alt(ke.alt);
- k->set_control(ke.control);
- k->set_metakey(ke.meta);
+ k->set_shift_pressed(ke.shift);
+ k->set_alt_pressed(ke.alt);
+ k->set_ctrl_pressed(ke.control);
+ k->set_meta_pressed(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);
+ // Special case for Numpad Enter key.
+ k->set_keycode(Key::KP_ENTER);
} else {
- k->set_keycode(KeyMappingWindows::get_keysym(ke.wParam));
+ k->set_keycode((Key)KeyMappingWindows::get_keysym(ke.wParam));
}
- k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24)));
+ k->set_physical_keycode((Key)(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);
+ char32_t unicode = key_event_buffer[i + 1].wParam;
+ static char32_t prev_wck = 0;
+ if ((unicode & 0xfffffc00) == 0xd800) {
+ if (prev_wck != 0) {
+ ERR_PRINT("invalid utf16 surrogate input");
+ }
+ prev_wck = unicode;
+ break; // Skip surrogate.
+ } else if ((unicode & 0xfffffc00) == 0xdc00) {
+ if (prev_wck == 0) {
+ ERR_PRINT("invalid utf16 surrogate input");
+ break; // Skip invalid surrogate.
+ }
+ unicode = (prev_wck << 10UL) + unicode - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
+ prev_wck = 0;
+ } else {
+ prev_wck = 0;
+ }
+ k->set_unicode(unicode);
}
if (k->get_unicode() && gr_mem) {
- k->set_alt(false);
- k->set_control(false);
+ k->set_alt_pressed(false);
+ k->set_ctrl_pressed(false);
}
if (k->get_unicode() < 32)
@@ -2852,7 +2996,7 @@ void DisplayServerWindows::_process_key_events() {
k->set_echo((ke.uMsg == WM_KEYDOWN && (ke.lParam & (1 << 30))));
- Input::get_singleton()->accumulate_input_event(k);
+ Input::get_singleton()->parse_input_event(k);
} break;
}
@@ -2862,8 +3006,8 @@ void DisplayServerWindows::_process_key_events() {
}
void DisplayServerWindows::_update_tablet_ctx(const String &p_old_driver, const String &p_new_driver) {
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- WindowData &wd = E->get();
+ for (KeyValue<WindowID, WindowData> &E : windows) {
+ WindowData &wd = E.value;
wd.block_mm = false;
if ((p_old_driver == "wintab") && wintab_available && wd.wtctx) {
wintab_WTEnable(wd.wtctx, false);
@@ -2900,7 +3044,7 @@ void DisplayServerWindows::_update_tablet_ctx(const String &p_old_driver, const
}
}
-DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
DWORD dwExStyle;
DWORD dwStyle;
@@ -2920,7 +3064,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
Rect2i r;
r.position = screen_get_position(i);
r.size = screen_get_size(i);
- Rect2 inters = r.clip(p_rect);
+ Rect2 inters = r.intersection(p_rect);
int area = inters.size.width * inters.size.height;
if (area >= nearest_area) {
screen_rect = r;
@@ -2956,10 +3100,13 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
windows.erase(id);
return INVALID_WINDOW_ID;
}
-#ifdef VULKAN_ENABLED
+ if (p_mode != WINDOW_MODE_FULLSCREEN) {
+ wd.pre_fs_valid = true;
+ }
+#ifdef VULKAN_ENABLED
if (rendering_driver == "vulkan") {
- if (context_vulkan->window_create(id, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top) == -1) {
+ if (context_vulkan->window_create(id, p_vsync_mode, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top) == -1) {
memdelete(context_vulkan);
context_vulkan = nullptr;
windows.erase(id);
@@ -2968,6 +3115,13 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
}
#endif
+#ifdef GLES3_ENABLED
+ if (rendering_driver == "opengl3") {
+ Error err = gl_manager->window_create(id, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top);
+ ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Failed to create an OpenGL window.");
+ }
+#endif
+
RegisterTouchWindow(wd.hWnd, 0);
TRACKMOUSEEVENT tme;
@@ -2979,7 +3133,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
DragAcceptFiles(wd.hWnd, true);
- if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available) {
+ if ((tablet_get_current_driver() == "wintab") && wintab_available) {
wintab_WTInfo(WTI_DEFSYSCTX, 0, &wd.wtlc);
wd.wtlc.lcOptions |= CXO_MESSAGES;
wd.wtlc.lcPktData = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
@@ -3012,7 +3166,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
wd.last_pressure_update = 0;
wd.last_tilt = Vector2();
- // IME
+ // IME.
wd.im_himc = ImmGetContext(wd.hWnd);
ImmReleaseContext(wd.hWnd, wd.im_himc);
@@ -3027,7 +3181,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
return id;
}
-// WinTab API
+// WinTab API.
bool DisplayServerWindows::wintab_available = false;
WTOpenPtr DisplayServerWindows::wintab_WTOpen = nullptr;
WTClosePtr DisplayServerWindows::wintab_WTClose = nullptr;
@@ -3035,7 +3189,7 @@ WTInfoPtr DisplayServerWindows::wintab_WTInfo = nullptr;
WTPacketPtr DisplayServerWindows::wintab_WTPacket = nullptr;
WTEnablePtr DisplayServerWindows::wintab_WTEnable = nullptr;
-// Windows Ink API
+// Windows Ink API.
bool DisplayServerWindows::winink_available = false;
GetPointerTypePtr DisplayServerWindows::win8p_GetPointerType = nullptr;
GetPointerPenInfoPtr DisplayServerWindows::win8p_GetPointerPenInfo = nullptr;
@@ -3046,7 +3200,41 @@ typedef enum _SHC_PROCESS_DPI_AWARENESS {
SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2
} SHC_PROCESS_DPI_AWARENESS;
-DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+int DisplayServerWindows::tablet_get_driver_count() const {
+ return tablet_drivers.size();
+}
+
+String DisplayServerWindows::tablet_get_driver_name(int p_driver) const {
+ if (p_driver < 0 || p_driver >= tablet_drivers.size()) {
+ return "";
+ } else {
+ return tablet_drivers[p_driver];
+ }
+}
+
+String DisplayServerWindows::tablet_get_current_driver() const {
+ return tablet_driver;
+}
+
+void DisplayServerWindows::tablet_set_current_driver(const String &p_driver) {
+ if (tablet_get_driver_count() == 0) {
+ return;
+ }
+ bool found = false;
+ for (int i = 0; i < tablet_get_driver_count(); i++) {
+ if (p_driver == tablet_get_driver_name(i)) {
+ found = true;
+ }
+ }
+ if (found) {
+ _update_tablet_ctx(tablet_driver, p_driver);
+ tablet_driver = p_driver;
+ } else {
+ ERR_PRINT("Unknown tablet driver " + p_driver + ".");
+ }
+}
+
+DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
drop_events = false;
key_event_pos = 0;
@@ -3064,6 +3252,37 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
outside = true;
+ rendering_driver = p_rendering_driver;
+
+ // Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink.
+ HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll");
+ if (wintab_lib) {
+ wintab_WTOpen = (WTOpenPtr)GetProcAddress(wintab_lib, "WTOpenW");
+ wintab_WTClose = (WTClosePtr)GetProcAddress(wintab_lib, "WTClose");
+ wintab_WTInfo = (WTInfoPtr)GetProcAddress(wintab_lib, "WTInfoW");
+ wintab_WTPacket = (WTPacketPtr)GetProcAddress(wintab_lib, "WTPacket");
+ wintab_WTEnable = (WTEnablePtr)GetProcAddress(wintab_lib, "WTEnable");
+
+ wintab_available = wintab_WTOpen && wintab_WTClose && wintab_WTInfo && wintab_WTPacket && wintab_WTEnable;
+ }
+
+ if (wintab_available) {
+ tablet_drivers.push_back("wintab");
+ }
+
+ // Note: Windows Ink API for pen input, available on Windows 8+ only.
+ HMODULE user32_lib = LoadLibraryW(L"user32.dll");
+ if (user32_lib) {
+ win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType");
+ win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo");
+
+ winink_available = win8p_GetPointerType && win8p_GetPointerPenInfo;
+ }
+
+ if (winink_available) {
+ tablet_drivers.push_back("winink");
+ }
+
if (OS::get_singleton()->is_hidpi_allowed()) {
HMODULE Shcore = LoadLibraryW(L"Shcore.dll");
@@ -3084,7 +3303,6 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
wc.lpfnWndProc = (WNDPROC)::WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
- //wc.hInstance = hInstance;
wc.hInstance = hInstance ? hInstance : GetModuleHandle(nullptr);
wc.hIcon = LoadIcon(nullptr, IDI_WINLOGO);
wc.hCursor = nullptr; //LoadCursor(nullptr, IDC_ARROW);
@@ -3108,12 +3326,10 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
Rid[0].hwndTarget = 0;
if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) {
- //registration failed.
+ // Registration failed.
use_raw_input = false;
}
- rendering_driver = "vulkan";
-
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
context_vulkan = memnew(VulkanContextWindows);
@@ -3125,34 +3341,31 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
}
}
#endif
-#if defined(OPENGL_ENABLED)
- if (rendering_driver_index == VIDEO_DRIVER_GLES2) {
- context_gles2 = memnew(ContextGL_Windows(hWnd, false));
-
- if (context_gles2->initialize() != OK) {
- memdelete(context_gles2);
- context_gles2 = nullptr;
- ERR_FAIL_V(ERR_UNAVAILABLE);
- }
+ // Init context and rendering device
+#if defined(GLES3_ENABLED)
- context_gles2->set_use_vsync(video_mode.use_vsync);
- set_vsync_via_compositor(video_mode.vsync_via_compositor);
+ if (rendering_driver == "opengl3") {
+ GLManager_Windows::ContextType opengl_api_type = GLManager_Windows::GLES_3_0_COMPATIBLE;
- if (RasterizerGLES2::is_viable() == OK) {
- RasterizerGLES2::register_config();
- RasterizerGLES2::make_current();
- } else {
- memdelete(context_gles2);
- context_gles2 = nullptr;
- ERR_FAIL_V(ERR_UNAVAILABLE);
+ gl_manager = memnew(GLManager_Windows(opengl_api_type));
+
+ if (gl_manager->initialize() != OK) {
+ memdelete(gl_manager);
+ gl_manager = nullptr;
+ r_error = ERR_UNAVAILABLE;
+ return;
}
+
+ // gl_manager->set_use_vsync(current_videomode.use_vsync);
+ RasterizerGLES3::make_current();
}
#endif
+
Point2i window_position(
(screen_get_size(0).width - p_resolution.width) / 2,
(screen_get_size(0).height - p_resolution.height) / 2);
- WindowID main_window = _create_window(p_mode, 0, Rect2i(window_position, p_resolution));
+ WindowID main_window = _create_window(p_mode, p_vsync_mode, 0, Rect2i(window_position, p_resolution));
ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window.");
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
@@ -3169,16 +3382,13 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
rendering_device_vulkan = memnew(RenderingDeviceVulkan);
rendering_device_vulkan->initialize(context_vulkan);
- RasterizerRD::make_current();
+ RendererCompositorRD::make_current();
}
#endif
- move_timer_id = 1;
-
//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);
@@ -3186,7 +3396,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
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.
+ // This is only setting the priority of this thread, not the whole process.
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
}
@@ -3208,18 +3418,18 @@ Vector<String> DisplayServerWindows::get_rendering_drivers_func() {
#ifdef VULKAN_ENABLED
drivers.push_back("vulkan");
#endif
-#ifdef OPENGL_ENABLED
- drivers.push_back("opengl");
+#ifdef GLES3_ENABLED
+ drivers.push_back("opengl3");
#endif
return drivers;
}
-DisplayServer *DisplayServerWindows::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- DisplayServer *ds = memnew(DisplayServerWindows(p_rendering_driver, p_mode, p_flags, p_resolution, r_error));
+DisplayServer *DisplayServerWindows::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+ DisplayServer *ds = memnew(DisplayServerWindows(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) {
- ds->alert("Your video card driver does not support any of the supported Vulkan versions.\n"
- "Please update your drivers or if you have a very old or integrated GPU upgrade it.",
+ OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan or OpenGL versions.\n"
+ "Please update your drivers or if you have a very old or integrated GPU upgrade it.",
"Unable to initialize Video driver");
}
return ds;
@@ -3239,6 +3449,10 @@ DisplayServerWindows::~DisplayServerWindows() {
SetWindowLongPtr(windows[MAIN_WINDOW_ID].hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
};
+#ifdef GLES3_ENABLED
+ // destroy windows .. NYI?
+#endif
+
if (windows.has(MAIN_WINDOW_ID)) {
#ifdef VULKAN_ENABLED
if (rendering_driver == "vulkan") {
@@ -3263,4 +3477,14 @@ DisplayServerWindows::~DisplayServerWindows() {
memdelete(context_vulkan);
}
#endif
+
+ if (restore_mouse_trails > 1) {
+ SystemParametersInfoA(SPI_SETMOUSETRAILS, restore_mouse_trails, 0, 0);
+ }
+#ifdef GLES3_ENABLED
+ if (gl_manager) {
+ memdelete(gl_manager);
+ gl_manager = nullptr;
+ }
+#endif
}