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.cpp205
1 files changed, 164 insertions, 41 deletions
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 0412eb2d9c..8c8dbef8a4 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -531,10 +531,43 @@ DisplayServer::ScreenOrientation DisplayServerWindows::screen_get_orientation(in
}
void DisplayServerWindows::screen_set_keep_on(bool p_enable) {
+ if (keep_screen_on == p_enable) {
+ return;
+ }
+
+ if (p_enable) {
+ const String reason = "Godot Engine running with display/window/energy_saving/keep_screen_on = true";
+ Char16String reason_utf16 = reason.utf16();
+
+ REASON_CONTEXT context;
+ context.Version = POWER_REQUEST_CONTEXT_VERSION;
+ context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
+ context.Reason.SimpleReasonString = (LPWSTR)(reason_utf16.ptrw());
+ power_request = PowerCreateRequest(&context);
+ if (power_request == INVALID_HANDLE_VALUE) {
+ print_error("Failed to enable screen_keep_on.");
+ return;
+ }
+ if (PowerSetRequest(power_request, POWER_REQUEST_TYPE::PowerRequestSystemRequired) == 0) {
+ print_error("Failed to request system sleep override.");
+ return;
+ }
+ if (PowerSetRequest(power_request, POWER_REQUEST_TYPE::PowerRequestDisplayRequired) == 0) {
+ print_error("Failed to request display timeout override.");
+ return;
+ }
+ } else {
+ PowerClearRequest(power_request, POWER_REQUEST_TYPE::PowerRequestSystemRequired);
+ PowerClearRequest(power_request, POWER_REQUEST_TYPE::PowerRequestDisplayRequired);
+ CloseHandle(power_request);
+ power_request = nullptr;
+ }
+
+ keep_screen_on = p_enable;
}
bool DisplayServerWindows::screen_is_kept_on() const {
- return false;
+ return keep_screen_on;
}
Vector<DisplayServer::WindowID> DisplayServerWindows::get_window_list() const {
@@ -607,8 +640,11 @@ void DisplayServerWindows::show_window(WindowID p_id) {
_update_window_style(p_id);
}
- ShowWindow(wd.hWnd, (wd.no_focus || wd.is_popup) ? SW_SHOWNOACTIVATE : SW_SHOW); // Show the window.
- if (!wd.no_focus && !wd.is_popup) {
+ if (wd.no_focus || wd.is_popup) {
+ // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
+ ShowWindow(wd.hWnd, SW_SHOWNA);
+ } else {
+ ShowWindow(wd.hWnd, SW_SHOW);
SetForegroundWindow(wd.hWnd); // Slightly higher priority.
SetFocus(wd.hWnd); // Set keyboard focus.
}
@@ -625,7 +661,7 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
WindowData &wd = windows[p_window];
while (wd.transient_children.size()) {
- window_set_transient(wd.transient_children.front()->get(), INVALID_WINDOW_ID);
+ window_set_transient(*wd.transient_children.begin(), INVALID_WINDOW_ID);
}
if (wd.transient_parent != INVALID_WINDOW_ID) {
@@ -653,7 +689,9 @@ void DisplayServerWindows::delete_sub_window(WindowID 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);
+ if (gl_manager) {
+ gl_manager->window_make_current(p_window_id);
+ }
#endif
}
@@ -1106,6 +1144,10 @@ void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repain
SetWindowLongPtr(wd.hWnd, GWL_STYLE, style);
SetWindowLongPtr(wd.hWnd, GWL_EXSTYLE, style_ex);
+ if (icon.is_valid()) {
+ set_icon(icon);
+ }
+
SetWindowPos(wd.hWnd, wd.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | ((wd.no_focus || wd.is_popup) ? SWP_NOACTIVATE : 0));
if (p_repaint) {
@@ -1490,11 +1532,11 @@ void DisplayServerWindows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTra
DeleteDC(hMainDC);
}
-void DisplayServerWindows::cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+void DisplayServerWindows::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
_THREAD_SAFE_METHOD_
if (p_cursor.is_valid()) {
- Map<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape);
+ RBMap<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) {
@@ -1794,7 +1836,9 @@ void DisplayServerWindows::make_rendering_thread() {
void DisplayServerWindows::swap_buffers() {
#if defined(GLES3_ENABLED)
- gl_manager->swap_buffers();
+ if (gl_manager) {
+ gl_manager->swap_buffers();
+ }
#endif
}
@@ -1895,9 +1939,11 @@ void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) {
_THREAD_SAFE_METHOD_
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);
+ if (icon != p_icon) {
+ 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();
@@ -1946,14 +1992,18 @@ void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) {
void DisplayServerWindows::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
- context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+ if (context_vulkan) {
+ context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+ }
#endif
}
DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
- return context_vulkan->get_vsync_mode(p_window);
+ if (context_vulkan) {
+ return context_vulkan->get_vsync_mode(p_window);
+ }
#endif
return DisplayServer::VSYNC_ENABLED;
}
@@ -1991,7 +2041,7 @@ void DisplayServerWindows::_touch_event(WindowID p_window, bool p_pressed, float
}
void DisplayServerWindows::_drag_event(WindowID p_window, float p_x, float p_y, int idx) {
- Map<int, Vector2>::Element *curr = touch_state.find(idx);
+ RBMap<int, Vector2>::Element *curr = touch_state.find(idx);
if (!curr) {
return;
}
@@ -2018,7 +2068,7 @@ void DisplayServerWindows::_send_window_event(const WindowData &wd, WindowEvent
Variant *eventp = &event;
Variant ret;
Callable::CallError ce;
- wd.event_callback.call((const Variant **)&eventp, 1, ret, ce);
+ wd.event_callback.callp((const Variant **)&eventp, 1, ret, ce);
}
}
@@ -2045,7 +2095,7 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
if (windows.has(E->get())) {
Callable callable = windows[E->get()].input_event_callback;
if (callable.is_valid()) {
- callable.call((const Variant **)&evp, 1, ret, ce);
+ callable.callp((const Variant **)&evp, 1, ret, ce);
}
}
in_dispatch_input_event = false;
@@ -2059,7 +2109,7 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
if (windows.has(event_from_window->get_window_id())) {
Callable callable = windows[event_from_window->get_window_id()].input_event_callback;
if (callable.is_valid()) {
- callable.call((const Variant **)&evp, 1, ret, ce);
+ callable.callp((const Variant **)&evp, 1, ret, ce);
}
}
} else {
@@ -2067,7 +2117,7 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
for (const KeyValue<WindowID, WindowData> &E : windows) {
const Callable callable = E.value.input_event_callback;
if (callable.is_valid()) {
- callable.call((const Variant **)&evp, 1, ret, ce);
+ callable.callp((const Variant **)&evp, 1, ret, ce);
}
}
}
@@ -2143,7 +2193,10 @@ void DisplayServerWindows::popup_close(WindowID p_window) {
WindowID win_id = E->get();
popup_list.erase(E);
- _send_window_event(windows[win_id], DisplayServerWindows::WINDOW_EVENT_CLOSE_REQUEST);
+ if (win_id != p_window) {
+ // Only request close on related windows, not this window. We are already processing it.
+ _send_window_event(windows[win_id], DisplayServerWindows::WINDOW_EVENT_CLOSE_REQUEST);
+ }
E = F;
}
}
@@ -2158,6 +2211,7 @@ LRESULT DisplayServerWindows::MouseProc(int code, WPARAM wParam, LPARAM lParam)
case WM_NCRBUTTONDOWN:
case WM_NCMBUTTONDOWN:
case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN: {
MOUSEHOOKSTRUCT *ms = (MOUSEHOOKSTRUCT *)lParam;
Point2i pos = Point2i(ms->pt.x, ms->pt.y);
@@ -2180,6 +2234,7 @@ LRESULT DisplayServerWindows::MouseProc(int code, WPARAM wParam, LPARAM lParam)
}
if (C) {
_send_window_event(windows[C->get()], DisplayServerWindows::WINDOW_EVENT_CLOSE_REQUEST);
+ return 1;
}
} break;
}
@@ -2187,8 +2242,39 @@ LRESULT DisplayServerWindows::MouseProc(int code, WPARAM wParam, LPARAM lParam)
return ::CallNextHookEx(mouse_monitor, code, wParam, lParam);
}
-// Our default window procedure to handle processing of window-related system messages/events.
-// Also known as DefProc or DefWindowProc.
+// Handle a single window message received while CreateWindowEx is still on the stack and our data
+// structures are not fully initialized.
+LRESULT DisplayServerWindows::_handle_early_window_message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ switch (uMsg) {
+ case WM_GETMINMAXINFO: {
+ // We receive this during CreateWindowEx and we haven't initialized the window
+ // struct, so let Windows figure out the maximized size.
+ // Silently forward to user/default.
+ } break;
+ case WM_NCCREATE: {
+ // We tunnel an unowned pointer to our window context (WindowData) through the
+ // first possible message (WM_NCCREATE) to fix up our window context collection.
+ CREATESTRUCTW *pCreate = (CREATESTRUCTW *)lParam;
+ WindowData *pWindowData = reinterpret_cast<WindowData *>(pCreate->lpCreateParams);
+
+ // Fix this up so we can recognize the remaining messages.
+ pWindowData->hWnd = hWnd;
+ } break;
+ default: {
+ // Additional messages during window creation should happen after we fixed
+ // up the data structures on WM_NCCREATE, but this might change in the future,
+ // so report an error here and then we can implement them.
+ ERR_PRINT_ONCE(vformat("Unexpected window message 0x%x received for window we cannot recognize in our collection; sequence error.", uMsg));
+ } break;
+ }
+
+ if (user_proc) {
+ return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam);
+ }
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+}
+
+// The window procedure for our window class "Engine", used to handle processing of window-related system messages/events.
// 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) {
@@ -2202,7 +2288,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
WindowID window_id = INVALID_WINDOW_ID;
bool window_created = false;
- // Check whether window exists.
+ // Check whether window exists
+ // FIXME this is O(n), where n is the set of currently open windows and subwindows
+ // we should have a secondary map from HWND to WindowID or even WindowData* alias, if we want to eliminate all the map lookups below
for (const KeyValue<WindowID, WindowData> &E : windows) {
if (E.value.hWnd == hWnd) {
window_id = E.key;
@@ -2211,10 +2299,12 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
- // Window doesn't exist or creation in progress, don't handle messages yet.
+ // WARNING: we get called with events before the window is registered in our collection
+ // specifically, even the call to CreateWindowEx already calls here while still on the stack,
+ // so there is no way to store the window handle in our collection before we get here
if (!window_created) {
- window_id = window_id_counter;
- ERR_FAIL_COND_V(!windows.has(window_id), 0);
+ // don't let code below operate on incompletely initialized window objects or missing window_id
+ return _handle_early_window_message(hWnd, uMsg, wParam, lParam);
}
// Process window messages.
@@ -2325,7 +2415,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
case WM_MOUSELEAVE: {
old_invalid = true;
- outside = true;
+ windows[window_id].mouse_outside = true;
_send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_EXIT);
@@ -2435,6 +2525,8 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
windows[window_id].last_tilt = Vector2();
}
+ windows[window_id].last_pen_inverted = packet.pkStatus & TPS_INVERT;
+
POINT coords;
GetCursorPos(&coords);
ScreenToClient(windows[window_id].hWnd, &coords);
@@ -2453,6 +2545,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
mm->set_pressure(windows[window_id].last_pressure);
mm->set_tilt(windows[window_id].last_tilt);
+ mm->set_pen_inverted(windows[window_id].last_pen_inverted);
mm->set_button_mask(last_button_state);
@@ -2552,7 +2645,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
- if (outside) {
+ if (windows[window_id].mouse_outside) {
// Mouse enter.
if (mouse_mode != MOUSE_MODE_CAPTURED) {
@@ -2562,7 +2655,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
CursorShape c = cursor_shape;
cursor_shape = CURSOR_MAX;
cursor_set_shape(c);
- outside = false;
+ windows[window_id].mouse_outside = false;
// Once-off notification, must call again.
track_mouse_leave_event(hWnd);
@@ -2585,6 +2678,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
if ((pen_info.penMask & PEN_MASK_TILT_X) && (pen_info.penMask & PEN_MASK_TILT_Y)) {
mm->set_tilt(Vector2((float)pen_info.tiltX / 90, (float)pen_info.tiltY / 90));
}
+ mm->set_pen_inverted(pen_info.penFlags & (PEN_FLAG_INVERTED | PEN_FLAG_ERASER));
mm->set_ctrl_pressed(GetKeyState(VK_CONTROL) < 0);
mm->set_shift_pressed(GetKeyState(VK_SHIFT) < 0);
@@ -2652,7 +2746,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
- if (outside) {
+ if (windows[window_id].mouse_outside) {
// Mouse enter.
if (mouse_mode != MOUSE_MODE_CAPTURED) {
@@ -2662,7 +2756,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
CursorShape c = cursor_shape;
cursor_shape = CURSOR_MAX;
cursor_set_shape(c);
- outside = false;
+ windows[window_id].mouse_outside = false;
// Once-off notification, must call again.
track_mouse_leave_event(hWnd);
@@ -2687,14 +2781,17 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
} else {
windows[window_id].last_tilt = Vector2();
windows[window_id].last_pressure = (wParam & MK_LBUTTON) ? 1.0f : 0.0f;
+ windows[window_id].last_pen_inverted = false;
}
} else {
windows[window_id].last_tilt = Vector2();
windows[window_id].last_pressure = (wParam & MK_LBUTTON) ? 1.0f : 0.0f;
+ windows[window_id].last_pen_inverted = false;
}
mm->set_pressure(windows[window_id].last_pressure);
mm->set_tilt(windows[window_id].last_tilt);
+ mm->set_pen_inverted(windows[window_id].last_pen_inverted);
mm->set_button_mask(last_button_state);
@@ -2975,7 +3072,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
const Variant *args[] = { &size };
Variant ret;
Callable::CallError ce;
- window.rect_changed_callback.call(args, 1, ret, ce);
+ window.rect_changed_callback.callp(args, 1, ret, ce);
}
}
@@ -3135,7 +3232,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
Variant *vp = &v;
Variant ret;
Callable::CallError ce;
- windows[window_id].drop_files_callback.call((const Variant **)&vp, 1, ret, ce);
+ windows[window_id].drop_files_callback.callp((const Variant **)&vp, 1, ret, ce);
}
} break;
default: {
@@ -3305,8 +3402,8 @@ void DisplayServerWindows::_update_tablet_ctx(const String &p_old_driver, const
if ((p_new_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;
- wd.wtlc.lcMoveMask = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE;
+ wd.wtlc.lcPktData = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
+ wd.wtlc.lcMoveMask = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE;
wd.wtlc.lcPktMode = 0;
wd.wtlc.lcOutOrgX = 0;
wd.wtlc.lcOutExtX = wd.wtlc.lcInExtX;
@@ -3382,11 +3479,23 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
WindowRect.top,
WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top,
- nullptr, nullptr, hInstance, nullptr);
+ nullptr,
+ nullptr,
+ hInstance,
+ // tunnel the WindowData we need to handle creation message
+ // lifetime is ensured because we are still on the stack when this is
+ // processed in the window proc
+ reinterpret_cast<void *>(&wd));
if (!wd.hWnd) {
MessageBoxW(nullptr, L"Window Creation Error.", L"ERROR", MB_OK | MB_ICONEXCLAMATION);
windows.erase(id);
- return INVALID_WINDOW_ID;
+ ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Failed to create Windows OS window.");
+ }
+ if (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
+ wd.fullscreen = true;
+ if (p_mode == WINDOW_MODE_FULLSCREEN) {
+ wd.multiwindow_fs = true;
+ }
}
if (p_mode != WINDOW_MODE_FULLSCREEN && p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
wd.pre_fs_valid = true;
@@ -3406,7 +3515,14 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
#ifdef GLES3_ENABLED
if (gl_manager) {
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.");
+
+ // shut down OpenGL, to mirror behavior of Vulkan code
+ if (err != OK) {
+ memdelete(gl_manager);
+ gl_manager = nullptr;
+ windows.erase(id);
+ ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Failed to create an OpenGL window.");
+ }
}
#endif
@@ -3416,8 +3532,8 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
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;
- wd.wtlc.lcMoveMask = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE;
+ wd.wtlc.lcPktData = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
+ wd.wtlc.lcMoveMask = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE;
wd.wtlc.lcPktMode = 0;
wd.wtlc.lcOutOrgX = 0;
wd.wtlc.lcOutExtX = wd.wtlc.lcInExtX;
@@ -3451,6 +3567,8 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
ImmReleaseContext(wd.hWnd, wd.im_himc);
wd.im_position = Vector2();
+
+ // FIXME this is wrong in cases where the window coordinates were changed due to full screen mode; use WindowRect
wd.last_pos = p_rect.position;
wd.width = p_rect.size.width;
wd.height = p_rect.size.height;
@@ -3529,13 +3647,14 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
old_invalid = true;
mouse_mode = MOUSE_MODE_VISIBLE;
- outside = true;
-
rendering_driver = p_rendering_driver;
// Init TTS
tts = memnew(TTS_Windows);
+ // Enforce default keep screen on value.
+ screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
+
// Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink.
HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll");
if (wintab_lib) {
@@ -3739,8 +3858,12 @@ DisplayServerWindows::~DisplayServerWindows() {
SetWindowLongPtr(windows[MAIN_WINDOW_ID].hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
}
+ // Close power request handle.
+ screen_set_keep_on(false);
+
#ifdef GLES3_ENABLED
// destroy windows .. NYI?
+ // FIXME wglDeleteContext is never called
#endif
if (windows.has(MAIN_WINDOW_ID)) {