summaryrefslogtreecommitdiff
path: root/platform/windows
diff options
context:
space:
mode:
Diffstat (limited to 'platform/windows')
-rw-r--r--platform/windows/SCsub2
-rw-r--r--platform/windows/context_gl_windows.cpp41
-rw-r--r--platform/windows/context_gl_windows.h9
-rw-r--r--platform/windows/crash_handler_windows.cpp20
-rw-r--r--platform/windows/crash_handler_windows.h4
-rw-r--r--platform/windows/detect.py77
-rw-r--r--platform/windows/display_server_windows.cpp890
-rw-r--r--platform/windows/display_server_windows.h200
-rw-r--r--platform/windows/export/export.cpp309
-rw-r--r--platform/windows/export/export.h9
-rw-r--r--platform/windows/export/export_plugin.cpp323
-rw-r--r--platform/windows/export/export_plugin.h51
-rw-r--r--platform/windows/godot.natvis70
-rw-r--r--platform/windows/godot_windows.cpp4
-rw-r--r--platform/windows/joypad_windows.cpp53
-rw-r--r--platform/windows/joypad_windows.h28
-rw-r--r--platform/windows/key_mapping_windows.cpp28
-rw-r--r--platform/windows/key_mapping_windows.h5
-rw-r--r--platform/windows/lang_table.h4
-rw-r--r--platform/windows/os_windows.cpp261
-rw-r--r--platform/windows/os_windows.h99
-rw-r--r--platform/windows/platform_config.h4
-rw-r--r--platform/windows/vulkan_context_win.cpp17
-rw-r--r--platform/windows/vulkan_context_win.h6
-rw-r--r--platform/windows/windows_terminal_logger.cpp33
-rw-r--r--platform/windows/windows_terminal_logger.h4
26 files changed, 1399 insertions, 1152 deletions
diff --git a/platform/windows/SCsub b/platform/windows/SCsub
index e3f86977a4..47d8e14680 100644
--- a/platform/windows/SCsub
+++ b/platform/windows/SCsub
@@ -32,5 +32,5 @@ if env["vsproj"]:
env.vs_srcs += ["platform/windows/" + str(x)]
if not os.getenv("VCINSTALLDIR"):
- if (env["debug_symbols"] == "full" or env["debug_symbols"] == "yes") and env["separate_debug_symbols"]:
+ if env["debug_symbols"] and env["separate_debug_symbols"]:
env.AddPostAction(prog, run_in_subprocess(platform_windows_builders.make_debug_mingw))
diff --git a/platform/windows/context_gl_windows.cpp b/platform/windows/context_gl_windows.cpp
index 1c32639a38..74b12cbb3b 100644
--- a/platform/windows/context_gl_windows.cpp
+++ b/platform/windows/context_gl_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 */
@@ -66,46 +66,13 @@ int ContextGL_Windows::get_window_height() {
return OS::get_singleton()->get_video_mode().height;
}
-bool ContextGL_Windows::should_vsync_via_compositor() {
- if (OS::get_singleton()->is_window_fullscreen() || !OS::get_singleton()->is_vsync_via_compositor_enabled()) {
- return false;
- }
-
- // Note: All Windows versions supported by Godot have a compositor.
- // It can be disabled on earlier Windows versions.
- BOOL dwm_enabled;
-
- if (SUCCEEDED(DwmIsCompositionEnabled(&dwm_enabled))) {
- return dwm_enabled;
- }
-
- return false;
-}
-
void ContextGL_Windows::swap_buffers() {
SwapBuffers(hDC);
-
- if (use_vsync) {
- bool vsync_via_compositor_now = should_vsync_via_compositor();
-
- if (vsync_via_compositor_now && wglGetSwapIntervalEXT() == 0) {
- DwmFlush();
- }
-
- if (vsync_via_compositor_now != vsync_via_compositor) {
- // The previous frame had a different operating mode than this
- // frame. Set the 'vsync_via_compositor' member variable and the
- // OpenGL swap interval to their proper values.
- set_use_vsync(true);
- }
- }
}
void ContextGL_Windows::set_use_vsync(bool p_use) {
- vsync_via_compositor = p_use && should_vsync_via_compositor();
-
if (wglSwapIntervalEXT) {
- int swap_interval = (p_use && !vsync_via_compositor) ? 1 : 0;
+ int swap_interval = p_use ? 1 : 0;
wglSwapIntervalEXT(swap_interval);
}
@@ -210,7 +177,7 @@ ContextGL_Windows::ContextGL_Windows(HWND hwnd, bool p_opengl_3_context) {
opengl_3_context = p_opengl_3_context;
hWnd = hwnd;
use_vsync = false;
- vsync_via_compositor = false;
+ pixel_format = 0;
}
ContextGL_Windows::~ContextGL_Windows() {
diff --git a/platform/windows/context_gl_windows.h b/platform/windows/context_gl_windows.h
index 046e3437ea..c8e8a0891d 100644
--- a/platform/windows/context_gl_windows.h
+++ b/platform/windows/context_gl_windows.h
@@ -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 */
@@ -35,7 +35,7 @@
#ifndef CONTEXT_GL_WIN_H
#define CONTEXT_GL_WIN_H
-#include "core/error_list.h"
+#include "core/error/error_list.h"
#include "core/os/os.h"
#include <windows.h>
@@ -50,13 +50,10 @@ class ContextGL_Windows {
HWND hWnd;
bool opengl_3_context;
bool use_vsync;
- bool vsync_via_compositor;
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
- static bool should_vsync_via_compositor();
-
public:
void release_current();
diff --git a/platform/windows/crash_handler_windows.cpp b/platform/windows/crash_handler_windows.cpp
index 02031ef6bb..1b4dae207f 100644
--- a/platform/windows/crash_handler_windows.cpp
+++ b/platform/windows/crash_handler_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 */
@@ -30,13 +30,15 @@
#include "crash_handler_windows.h"
+#include "core/config/project_settings.h"
#include "core/os/os.h"
-#include "core/project_settings.h"
+#include "core/version.h"
+#include "core/version_hash.gen.h"
#include "main/main.h"
#ifdef CRASH_HANDLER_EXCEPTION
-// Backtrace code code based on: https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app
+// Backtrace code based on: https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app
#include <algorithm>
#include <iterator>
@@ -57,7 +59,7 @@
struct module_data {
std::string image_name;
std::string module_name;
- void *base_address;
+ void *base_address = nullptr;
DWORD load_size;
};
@@ -127,6 +129,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) {
return EXCEPTION_CONTINUE_SEARCH;
}
+ fprintf(stderr, "\n================================================================\n");
fprintf(stderr, "%s: Program crashed\n", __FUNCTION__);
if (OS::get_singleton()->get_main_loop())
@@ -175,6 +178,12 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) {
msg = proj_settings->get("debug/settings/crash_handler/message");
}
+ // Print the engine version just before, so that people are reminded to include the version in backtrace reports.
+ if (String(VERSION_HASH).length() != 0) {
+ fprintf(stderr, "Engine version: " VERSION_FULL_NAME " (" VERSION_HASH ")\n");
+ } else {
+ fprintf(stderr, "Engine version: " VERSION_FULL_NAME "\n");
+ }
fprintf(stderr, "Dumping the backtrace. %s\n", msg.utf8().get_data());
int n = 0;
@@ -200,6 +209,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) {
} while (frame.AddrReturn.Offset != 0 && n < 256);
fprintf(stderr, "-- END OF BACKTRACE --\n");
+ fprintf(stderr, "================================================================\n");
SymCleanup(process);
diff --git a/platform/windows/crash_handler_windows.h b/platform/windows/crash_handler_windows.h
index 66a4cac296..e1ec8e6787 100644
--- a/platform/windows/crash_handler_windows.h
+++ b/platform/windows/crash_handler_windows.h
@@ -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 */
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 489e45404f..3961480d23 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -64,23 +64,23 @@ def get_opts():
# XP support dropped after EOL due to missing API for IPv6 and other issues
# Vista support dropped after EOL due to GH-10243
("target_win_version", "Targeted Windows version, >= 0x0601 (Windows 7)", "0x0601"),
- EnumVariable("debug_symbols", "Add debugging symbols to release builds", "yes", ("yes", "no", "full")),
+ BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True),
EnumVariable("windows_subsystem", "Windows subsystem", "default", ("default", "console", "gui")),
BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False),
("msvc_version", "MSVC version to use. Ignored if VCINSTALLDIR is set in shell env.", None),
- BoolVariable("use_mingw", "Use the Mingw compiler, even if MSVC is installed. Only used on Windows.", False),
+ BoolVariable("use_mingw", "Use the Mingw compiler, even if MSVC is installed.", False),
BoolVariable("use_llvm", "Use the LLVM compiler", False),
BoolVariable("use_thinlto", "Use ThinLTO", False),
+ BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True),
+ BoolVariable("use_asan", "Use address sanitizer (ASAN)", False),
]
def get_flags():
-
return []
def build_res_file(target, source, env):
-
if env["bits"] == "32":
cmdbase = env["mingw_prefix_32"]
else:
@@ -94,7 +94,7 @@ def build_res_file(target, source, env):
out = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE).communicate()
if len(out[1]):
return 1
- except:
+ except Exception:
return 1
return 0
@@ -152,7 +152,7 @@ def setup_msvc_auto(env):
env["TARGET_ARCH"] = None
if env["bits"] != "default":
env["TARGET_ARCH"] = {"32": "x86", "64": "x86_64"}[env["bits"]]
- if env.has_key("msvc_version"):
+ if "msvc_version" in env:
env["MSVC_VERSION"] = env["msvc_version"]
env.Tool("msvc")
env.Tool("mssdk") # we want the MS SDK
@@ -171,7 +171,6 @@ def setup_mingw(env):
"""Set up env for use with mingw"""
# Nothing to do here
print("Using MinGW")
- pass
def configure_msvc(env, manual_msvc_config):
@@ -191,26 +190,28 @@ def configure_msvc(env, manual_msvc_config):
if env["target"] == "release":
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(CCFLAGS=["/O2"])
- else: # optimize for size
+ env.Append(LINKFLAGS=["/OPT:REF"])
+ elif env["optimize"] == "size": # optimize for size
env.Append(CCFLAGS=["/O1"])
+ env.Append(LINKFLAGS=["/OPT:REF"])
env.Append(LINKFLAGS=["/ENTRY:mainCRTStartup"])
- env.Append(LINKFLAGS=["/OPT:REF"])
elif env["target"] == "release_debug":
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(CCFLAGS=["/O2"])
- else: # optimize for size
+ env.Append(LINKFLAGS=["/OPT:REF"])
+ elif env["optimize"] == "size": # optimize for size
env.Append(CCFLAGS=["/O1"])
+ env.Append(LINKFLAGS=["/OPT:REF"])
env.AppendUnique(CPPDEFINES=["DEBUG_ENABLED"])
- env.Append(LINKFLAGS=["/OPT:REF"])
elif env["target"] == "debug":
- env.AppendUnique(CCFLAGS=["/Z7", "/Od", "/EHsc"])
+ env.AppendUnique(CCFLAGS=["/Zi", "/FS", "/Od", "/EHsc"])
env.AppendUnique(CPPDEFINES=["DEBUG_ENABLED"])
env.Append(LINKFLAGS=["/DEBUG"])
- if env["debug_symbols"] == "full" or env["debug_symbols"] == "yes":
- env.AppendUnique(CCFLAGS=["/Z7"])
+ if env["debug_symbols"]:
+ env.AppendUnique(CCFLAGS=["/Zi", "/FS"])
env.AppendUnique(LINKFLAGS=["/DEBUG"])
if env["windows_subsystem"] == "gui":
@@ -221,7 +222,12 @@ def configure_msvc(env, manual_msvc_config):
## Compile/link flags
- env.AppendUnique(CCFLAGS=["/MT", "/Gd", "/GR", "/nologo"])
+ if env["use_static_cpp"]:
+ env.AppendUnique(CCFLAGS=["/MT"])
+ else:
+ env.AppendUnique(CCFLAGS=["/MD"])
+
+ env.AppendUnique(CCFLAGS=["/Gd", "/GR", "/nologo"])
# Force to use Unicode encoding
env.AppendUnique(CCFLAGS=["/utf-8"])
env.AppendUnique(CXXFLAGS=["/TP"]) # assume all sources are C++
@@ -272,10 +278,8 @@ def configure_msvc(env, manual_msvc_config):
]
env.AppendUnique(CPPDEFINES=["VULKAN_ENABLED"])
- if not env["builtin_vulkan"]:
+ if not env["use_volk"]:
LIBS += ["vulkan"]
- else:
- LIBS += ["cfgmgr32"]
# env.AppendUnique(CPPDEFINES = ['OPENGL_ENABLED'])
LIBS += ["opengl32"]
@@ -302,6 +306,12 @@ def configure_msvc(env, manual_msvc_config):
env.Prepend(CPPPATH=[p for p in os.getenv("INCLUDE").split(";")])
env.Append(LIBPATH=[p for p in os.getenv("LIB").split(";")])
+ # Sanitizers
+ if env["use_asan"]:
+ env.extra_suffix += ".s"
+ env.Append(LINKFLAGS=["/INFERASANLIBS"])
+ env.Append(CCFLAGS=["/fsanitize=address"])
+
# Incremental linking fix
env["BUILDERS"]["ProgramOriginal"] = env["BUILDERS"]["Program"]
env["BUILDERS"]["Program"] = methods.precious_program
@@ -311,7 +321,7 @@ def configure_msvc(env, manual_msvc_config):
def configure_mingw(env):
# Workaround for MinGW. See:
- # http://www.scons.org/wiki/LongCmdLinesOnWin32
+ # https://www.scons.org/wiki/LongCmdLinesOnWin32
env.use_windows_spawn_fix()
## Build type
@@ -336,17 +346,13 @@ def configure_mingw(env):
else: # optimize for size
env.Prepend(CCFLAGS=["-Os"])
- if env["debug_symbols"] == "yes":
- env.Prepend(CCFLAGS=["-g1"])
- if env["debug_symbols"] == "full":
+ if env["debug_symbols"]:
env.Prepend(CCFLAGS=["-g2"])
elif env["target"] == "release_debug":
env.Append(CCFLAGS=["-O2"])
env.Append(CPPDEFINES=["DEBUG_ENABLED"])
- if env["debug_symbols"] == "yes":
- env.Prepend(CCFLAGS=["-g1"])
- if env["debug_symbols"] == "full":
+ if env["debug_symbols"]:
env.Prepend(CCFLAGS=["-g2"])
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(CCFLAGS=["-O2"])
@@ -377,28 +383,29 @@ def configure_mingw(env):
mingw_prefix = ""
if env["bits"] == "32":
- env.Append(LINKFLAGS=["-static"])
- env.Append(LINKFLAGS=["-static-libgcc"])
- env.Append(LINKFLAGS=["-static-libstdc++"])
+ if env["use_static_cpp"]:
+ env.Append(LINKFLAGS=["-static"])
+ env.Append(LINKFLAGS=["-static-libgcc"])
+ env.Append(LINKFLAGS=["-static-libstdc++"])
mingw_prefix = env["mingw_prefix_32"]
else:
- env.Append(LINKFLAGS=["-static"])
+ if env["use_static_cpp"]:
+ env.Append(LINKFLAGS=["-static"])
mingw_prefix = env["mingw_prefix_64"]
if env["use_llvm"]:
env["CC"] = mingw_prefix + "clang"
- env["AS"] = mingw_prefix + "as"
env["CXX"] = mingw_prefix + "clang++"
+ env["AS"] = mingw_prefix + "as"
env["AR"] = mingw_prefix + "ar"
env["RANLIB"] = mingw_prefix + "ranlib"
- env["LINK"] = mingw_prefix + "clang++"
else:
env["CC"] = mingw_prefix + "gcc"
- env["AS"] = mingw_prefix + "as"
env["CXX"] = mingw_prefix + "g++"
+ env["AS"] = mingw_prefix + "as"
env["AR"] = mingw_prefix + "gcc-ar"
env["RANLIB"] = mingw_prefix + "gcc-ranlib"
- env["LINK"] = mingw_prefix + "g++"
+
env["x86_libtheora_opt_gcc"] = True
if env["use_lto"]:
@@ -447,10 +454,8 @@ def configure_mingw(env):
)
env.Append(CPPDEFINES=["VULKAN_ENABLED"])
- if not env["builtin_vulkan"]:
+ if not env["use_volk"]:
env.Append(LIBS=["vulkan"])
- else:
- env.Append(LIBS=["cfgmgr32"])
## TODO !!! Re-enable when OpenGLES Rendering Device is implemented !!!
# env.Append(CPPDEFINES=['OPENGL_ENABLED'])
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index dfbb734ee4..3100c0bd27 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 */
@@ -79,12 +79,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 +97,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 +118,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 +136,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 +156,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 +166,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 +188,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 +207,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 +331,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 +454,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 +465,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 +499,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.
}
}
@@ -535,7 +536,7 @@ void DisplayServerWindows::delete_sub_window(WindowID 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;
}
@@ -608,6 +609,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 +669,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 +691,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 +706,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 +724,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));
@@ -840,8 +832,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 +848,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 +867,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 +885,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 +897,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 +907,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 +940,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 +949,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 +972,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 +999,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 +1033,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 +1125,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 +1178,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 +1194,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,7 +1206,7 @@ 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,
@@ -1228,49 +1237,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 +1307,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 +1330,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 +1351,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 +1367,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 +1375,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 +1403,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 +1428,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 +1449,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 +1460,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 +1476,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 {
+ unsigned int modifiers = p_keycode & KEY_MODIFIER_MASK;
+ Key keycode_no_mod = (Key)(p_keycode & KEY_CODE_MASK);
+
+ if (keycode_no_mod == KEY_PRINT ||
+ keycode_no_mod == KEY_KP_ADD ||
+ keycode_no_mod == KEY_KP_5 ||
+ (keycode_no_mod >= KEY_0 && keycode_no_mod <= 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 == KEY_BRACKETLEFT || char_code == KEY_BRACKETRIGHT) {
+ char_code += 32;
+ }
+ return (Key)(char_code | 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 +1526,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 +1534,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 +1574,7 @@ void DisplayServerWindows::process_events() {
if (!drop_events) {
_process_key_events();
- Input::get_singleton()->flush_accumulated_events();
+ Input::get_singleton()->flush_buffered_events();
}
}
@@ -1575,9 +1621,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 +1653,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 +1663,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 +1673,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 +1694,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 +1734,27 @@ 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)
+ 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)
+ return context_vulkan->get_vsync_mode(p_window);
+#else
+ return DisplayServer::VSYNC_ENABLED;
+#endif
}
void DisplayServerWindows::set_context(Context p_context) {
@@ -1709,13 +1765,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 +1780,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 +1839,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 +1851,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 +1864,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 +1879,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 +1909,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 +1935,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 +1963,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 +2016,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 +2029,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 +2052,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 +2061,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 +2085,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 +2110,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 +2154,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 +2164,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 +2190,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 +2210,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 +2218,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 +2229,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 +2239,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 +2256,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 +2301,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 +2316,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 +2324,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 +2335,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 +2345,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 +2407,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 +2433,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(MOUSE_BUTTON_LEFT);
} break;
case WM_LBUTTONUP: {
mb->set_pressed(false);
- mb->set_button_index(1);
+ mb->set_button_index(MOUSE_BUTTON_LEFT);
} break;
case WM_MBUTTONDOWN: {
mb->set_pressed(true);
- mb->set_button_index(3);
+ mb->set_button_index(MOUSE_BUTTON_MIDDLE);
} break;
case WM_MBUTTONUP: {
mb->set_pressed(false);
- mb->set_button_index(3);
+ mb->set_button_index(MOUSE_BUTTON_MIDDLE);
} break;
case WM_RBUTTONDOWN: {
mb->set_pressed(true);
- mb->set_button_index(2);
+ mb->set_button_index(MOUSE_BUTTON_RIGHT);
} break;
case WM_RBUTTONUP: {
mb->set_pressed(false);
- mb->set_button_index(2);
+ mb->set_button_index(MOUSE_BUTTON_RIGHT);
} break;
case WM_LBUTTONDBLCLK: {
mb->set_pressed(true);
- mb->set_button_index(1);
- mb->set_doubleclick(true);
+ mb->set_button_index(MOUSE_BUTTON_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(MOUSE_BUTTON_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(MOUSE_BUTTON_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(MOUSE_BUTTON_WHEEL_UP);
+ } else {
+ mb->set_button_index(MOUSE_BUTTON_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(MOUSE_BUTTON_WHEEL_LEFT);
} else {
- mb->set_button_index(BUTTON_WHEEL_RIGHT);
- mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA));
+ mb->set_button_index(MOUSE_BUTTON_WHEEL_RIGHT);
}
+ mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA));
} break;
case WM_XBUTTONDOWN: {
mb->set_pressed(true);
- if (HIWORD(wParam) == XBUTTON1)
- mb->set_button_index(BUTTON_XBUTTON1);
- else
- mb->set_button_index(BUTTON_XBUTTON2);
+ if (HIWORD(wParam) == XBUTTON1) {
+ mb->set_button_index(MOUSE_BUTTON_XBUTTON1);
+ } else {
+ mb->set_button_index(MOUSE_BUTTON_XBUTTON2);
+ }
} break;
case WM_XBUTTONUP: {
mb->set_pressed(false);
- if (HIWORD(wParam) == XBUTTON1)
- mb->set_button_index(BUTTON_XBUTTON1);
- else
- mb->set_button_index(BUTTON_XBUTTON2);
+ if (HIWORD(wParam) == XBUTTON1) {
+ mb->set_button_index(MOUSE_BUTTON_XBUTTON1);
+ } else {
+ mb->set_button_index(MOUSE_BUTTON_XBUTTON2);
+ }
} break;
case WM_XBUTTONDBLCLK: {
mb->set_pressed(true);
- if (HIWORD(wParam) == XBUTTON1)
- mb->set_button_index(BUTTON_XBUTTON1);
- else
- mb->set_button_index(BUTTON_XBUTTON2);
- mb->set_doubleclick(true);
+ if (HIWORD(wParam) == XBUTTON1) {
+ mb->set_button_index(MOUSE_BUTTON_XBUTTON1);
+ } else {
+ mb->set_button_index(MOUSE_BUTTON_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 |= MouseButton(1 << (mb->get_button_index() - 1));
+ } else {
+ last_button_state &= (MouseButton) ~(1 << (mb->get_button_index() - 1));
+ }
mb->set_button_mask(last_button_state);
mb->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
@@ -2510,7 +2564,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 +2576,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);
+ Input::get_singleton()->parse_input_event(mb);
if (mb->is_pressed() && mb->get_button_index() > 3 && mb->get_button_index() < 8) {
- //send release for mouse wheel
+ // 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 &= (MouseButton) ~(1 << (mbd->get_button_index() - 1));
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 +2603,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 +2621,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 +2679,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 +2750,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 +2763,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 +2772,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 +2784,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 +2805,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
}
-
} break;
case WM_DROPFILES: {
HDROP hDropInfo = (HDROP)wParam;
@@ -2764,9 +2828,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 +2847,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
+ // 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 +2969,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 +2979,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 +3017,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 +3037,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 +3073,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);
@@ -2979,7 +3099,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 +3132,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 +3147,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 +3155,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 +3166,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 +3218,35 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
outside = true;
+ // 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 +3267,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,7 +3290,7 @@ 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;
}
@@ -3125,6 +3307,7 @@ 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));
@@ -3136,7 +3319,6 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
}
context_gles2->set_use_vsync(video_mode.use_vsync);
- set_vsync_via_compositor(video_mode.vsync_via_compositor);
if (RasterizerGLES2::is_viable() == OK) {
RasterizerGLES2::register_config();
@@ -3148,11 +3330,12 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
}
}
#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 +3352,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 +3366,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);
}
@@ -3215,11 +3395,11 @@ Vector<String> DisplayServerWindows::get_rendering_drivers_func() {
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 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;
@@ -3263,4 +3443,8 @@ DisplayServerWindows::~DisplayServerWindows() {
memdelete(context_vulkan);
}
#endif
+
+ if (restore_mouse_trails > 1) {
+ SystemParametersInfoA(SPI_SETMOUSETRAILS, restore_mouse_trails, 0, 0);
+ }
}
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index 0fca2589ae..8b82288a40 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -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 */
@@ -33,9 +33,9 @@
#include "servers/display_server.h"
+#include "core/config/project_settings.h"
#include "core/input/input.h"
#include "core/os/os.h"
-#include "core/project_settings.h"
#include "crash_handler_windows.h"
#include "drivers/unix/ip_unix.h"
#include "drivers/wasapi/audio_driver_wasapi.h"
@@ -43,8 +43,8 @@
#include "joypad_windows.h"
#include "key_mapping_windows.h"
#include "servers/audio_server.h"
-#include "servers/rendering/rasterizer.h"
-#include "servers/rendering/rasterizer_rd/rasterizer_rd.h"
+#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering_server.h"
#ifdef XAUDIO2_ENABLED
@@ -264,7 +264,6 @@ class DisplayServerWindows : public DisplayServer {
_THREAD_SAFE_CLASS_
-public:
// WinTab API
static bool wintab_available;
static WTOpenPtr wintab_WTOpen;
@@ -279,8 +278,9 @@ public:
static GetPointerPenInfoPtr win8p_GetPointerPenInfo;
void _update_tablet_ctx(const String &p_old_driver, const String &p_new_driver);
+ String tablet_driver;
+ Vector<String> tablet_drivers;
-private:
void GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap);
enum {
@@ -339,6 +339,14 @@ private:
bool no_focus = false;
bool window_has_focus = false;
+ // Used to transfer data between events using timer.
+ WPARAM saved_wparam;
+ LPARAM saved_lparam;
+
+ // Timers.
+ uint32_t move_timer_id = 0U;
+ uint32_t focus_timer_id = 0U;
+
HANDLE wtctx;
LOGCONTEXTW wtlc;
int min_pressure;
@@ -381,14 +389,12 @@ private:
JoypadWindows *joypad;
- WindowID _create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect);
+ WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect);
WindowID window_id_counter = MAIN_WINDOW_ID;
Map<WindowID, WindowData> windows;
WindowID last_focused_window = INVALID_WINDOW_ID;
- uint32_t move_timer_id;
-
HCURSOR hCursor;
WNDPROC user_proc = nullptr;
@@ -397,12 +403,13 @@ private:
void _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);
MouseMode mouse_mode;
+ int restore_mouse_trails = 0;
bool alt_mem = false;
bool gr_mem = false;
bool shift_mem = false;
bool control_mem = false;
bool meta_mem = false;
- uint32_t last_button_state = 0;
+ MouseButton last_button_state = MOUSE_BUTTON_NONE;
bool use_raw_input = false;
bool drop_events = false;
bool in_dispatch_input_event = false;
@@ -411,19 +418,20 @@ private:
WNDCLASSEXW wc;
HCURSOR cursors[CURSOR_MAX] = { nullptr };
- CursorShape cursor_shape;
+ CursorShape cursor_shape = CursorShape::CURSOR_ARROW;
Map<CursorShape, Vector<Variant>> cursors_cache;
void _drag_event(WindowID p_window, float p_x, float p_y, int idx);
void _touch_event(WindowID p_window, bool p_pressed, float p_x, float p_y, int idx);
- void _update_window_style(WindowID p_window, bool p_repaint = true, bool p_maximized = false);
+ void _update_window_style(WindowID p_window, bool p_repaint = true);
void _update_window_mouse_passthrough(WindowID p_window);
void _update_real_mouse_position(WindowID p_window);
void _set_mouse_mode_impl(MouseMode p_mode);
+ void _process_activate_event(WindowID p_window_id, WPARAM wParam, LPARAM lParam);
void _process_key_events();
static void _dispatch_input_events(const Ref<InputEvent> &p_event);
@@ -432,130 +440,134 @@ private:
public:
LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
- virtual bool has_feature(Feature p_feature) const;
- virtual String get_name() const;
-
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
+ virtual bool has_feature(Feature p_feature) const override;
+ virtual String get_name() const override;
- virtual void mouse_set_mode(MouseMode p_mode);
- virtual MouseMode mouse_get_mode() const;
+ virtual void mouse_set_mode(MouseMode p_mode) override;
+ virtual MouseMode mouse_get_mode() const override;
- virtual void mouse_warp_to_position(const Point2i &p_to);
- virtual Point2i mouse_get_position() const;
- virtual int mouse_get_button_state() const;
+ virtual void mouse_warp_to_position(const Point2i &p_to) override;
+ virtual Point2i mouse_get_position() const override;
+ virtual MouseButton mouse_get_button_state() const override;
- virtual void clipboard_set(const String &p_text);
- virtual String clipboard_get() const;
+ virtual void clipboard_set(const String &p_text) override;
+ virtual String clipboard_get() const override;
- virtual int get_screen_count() const;
- virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
+ virtual int get_screen_count() const override;
+ virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- virtual void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW);
+ virtual void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW) override;
ScreenOrientation screen_get_orientation(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual void screen_set_keep_on(bool p_enable); //disable screensaver
- virtual bool screen_is_kept_on() const;
+ virtual void screen_set_keep_on(bool p_enable) override; //disable screensaver
+ virtual bool screen_is_kept_on() const override;
+
+ virtual Vector<DisplayServer::WindowID> get_window_list() const override;
- virtual Vector<DisplayServer::WindowID> get_window_list() const;
+ virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
+ virtual void show_window(WindowID p_window) override;
+ virtual void delete_sub_window(WindowID p_window) override;
- virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
- virtual void show_window(WindowID p_window);
- virtual void delete_sub_window(WindowID p_window);
+ virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override;
- virtual WindowID get_window_at_screen_position(const Point2i &p_position) const;
+ virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID);
- virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID);
+ virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID);
+ virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
- virtual void window_set_transient(WindowID p_window, WindowID p_parent);
+ virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override; //wtf is this? should probable use proper name
- virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const; //wtf is this? should probable use proper name
+ virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID);
- virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID);
- virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID);
+ virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual bool can_any_window_draw() const override;
- virtual bool can_any_window_draw() const;
+ virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
- virtual void console_set_visible(bool p_enabled);
- virtual bool is_console_visible() const;
+ virtual void console_set_visible(bool p_enabled) override;
+ virtual bool is_console_visible() const override;
- virtual void cursor_set_shape(CursorShape p_shape);
- virtual CursorShape cursor_get_shape() const;
- virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
+ virtual void cursor_set_shape(CursorShape p_shape) override;
+ virtual CursorShape cursor_get_shape() const override;
+ virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override;
- virtual bool get_swap_cancel_ok();
+ virtual bool get_swap_cancel_ok() override;
- virtual void enable_for_stealing_focus(OS::ProcessID pid);
+ virtual void enable_for_stealing_focus(OS::ProcessID pid) override;
- virtual int keyboard_get_layout_count() const;
- virtual int keyboard_get_current_layout() const;
- virtual void keyboard_set_current_layout(int p_index);
- virtual String keyboard_get_layout_language(int p_index) const;
- virtual String keyboard_get_layout_name(int p_index) const;
+ virtual int keyboard_get_layout_count() const override;
+ virtual int keyboard_get_current_layout() const override;
+ virtual void keyboard_set_current_layout(int p_index) override;
+ virtual String keyboard_get_layout_language(int p_index) const override;
+ virtual String keyboard_get_layout_name(int p_index) const override;
+ virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const override;
- virtual void process_events();
+ virtual int tablet_get_driver_count() const override;
+ virtual String tablet_get_driver_name(int p_driver) const override;
+ virtual String tablet_get_current_driver() const override;
+ virtual void tablet_set_current_driver(const String &p_driver) override;
- virtual void force_process_and_drop_events();
+ virtual void process_events() override;
- virtual void release_rendering_thread();
- virtual void make_rendering_thread();
- virtual void swap_buffers();
+ virtual void force_process_and_drop_events() override;
- virtual void set_native_icon(const String &p_filename);
- virtual void set_icon(const Ref<Image> &p_icon);
+ virtual void release_rendering_thread() override;
+ virtual void make_rendering_thread() override;
+ virtual void swap_buffers() override;
- virtual void vsync_set_use_via_compositor(bool p_enable);
- virtual bool vsync_is_using_via_compositor() const;
+ virtual void set_native_icon(const String &p_filename) override;
+ virtual void set_icon(const Ref<Image> &p_icon) override;
- virtual void set_context(Context p_context);
+ virtual void set_context(Context p_context) override;
- static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ static DisplayServer *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);
static Vector<String> get_rendering_drivers_func();
static void register_windows_driver();
- DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
~DisplayServerWindows();
};
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp
index c2436e8b64..4ff42f3f62 100644
--- a/platform/windows/export/export.cpp
+++ b/platform/windows/export/export.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 */
@@ -28,306 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "core/os/file_access.h"
-#include "core/os/os.h"
-#include "editor/editor_export.h"
-#include "editor/editor_node.h"
-#include "editor/editor_settings.h"
-#include "platform/windows/logo.gen.h"
+#include "export.h"
-static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size);
-
-class EditorExportPlatformWindows : public EditorExportPlatformPC {
- void _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path);
- Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
-
-public:
- virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
- virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
- virtual void get_export_options(List<ExportOption> *r_options);
-};
-
-Error EditorExportPlatformWindows::sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) {
- if (p_preset->get("codesign/enable")) {
- return _code_sign(p_preset, p_path);
- } else {
- return OK;
- }
-}
-
-Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
- Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, p_path, p_flags);
-
- if (err != OK) {
- return err;
- }
-
- _rcedit_add_data(p_preset, p_path);
-
- if (p_preset->get("codesign/enable") && err == OK) {
- err = _code_sign(p_preset, p_path);
- }
-
- return err;
-}
-
-void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) {
- EditorExportPlatformPC::get_export_options(r_options);
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false));
-#ifdef WINDOWS_ENABLED
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA1 hash)"), 0));
-#endif
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/timestamp_server_url"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/digest_algorithm", PROPERTY_HINT_ENUM, "SHA1,SHA256"), 1));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/description"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray()));
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_description"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/trademarks"), ""));
-}
-
-void EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
- String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit");
-
- if (rcedit_path == String()) {
- return;
- }
-
- if (!FileAccess::exists(rcedit_path)) {
- ERR_PRINT("Could not find rcedit executable at " + rcedit_path + ", no icon or app information data will be included.");
- return;
- }
-
-#ifndef WINDOWS_ENABLED
- // On non-Windows we need WINE to run rcedit
- String wine_path = EditorSettings::get_singleton()->get("export/windows/wine");
-
- if (wine_path != String() && !FileAccess::exists(wine_path)) {
- ERR_PRINT("Could not find wine executable at " + wine_path + ", no icon or app information data will be included.");
- return;
- }
-
- if (wine_path == String()) {
- wine_path = "wine"; // try to run wine from PATH
- }
-#endif
-
- String icon_path = ProjectSettings::get_singleton()->globalize_path(p_preset->get("application/icon"));
- String file_verion = p_preset->get("application/file_version");
- String product_version = p_preset->get("application/product_version");
- String company_name = p_preset->get("application/company_name");
- String product_name = p_preset->get("application/product_name");
- String file_description = p_preset->get("application/file_description");
- String copyright = p_preset->get("application/copyright");
- String trademarks = p_preset->get("application/trademarks");
- String comments = p_preset->get("application/comments");
-
- List<String> args;
- args.push_back(p_path);
- if (icon_path != String()) {
- args.push_back("--set-icon");
- args.push_back(icon_path);
- }
- if (file_verion != String()) {
- args.push_back("--set-file-version");
- args.push_back(file_verion);
- }
- if (product_version != String()) {
- args.push_back("--set-product-version");
- args.push_back(product_version);
- }
- if (company_name != String()) {
- args.push_back("--set-version-string");
- args.push_back("CompanyName");
- args.push_back(company_name);
- }
- if (product_name != String()) {
- args.push_back("--set-version-string");
- args.push_back("ProductName");
- args.push_back(product_name);
- }
- if (file_description != String()) {
- args.push_back("--set-version-string");
- args.push_back("FileDescription");
- args.push_back(file_description);
- }
- if (copyright != String()) {
- args.push_back("--set-version-string");
- args.push_back("LegalCopyright");
- args.push_back(copyright);
- }
- if (trademarks != String()) {
- args.push_back("--set-version-string");
- args.push_back("LegalTrademarks");
- args.push_back(trademarks);
- }
-
-#ifdef WINDOWS_ENABLED
- OS::get_singleton()->execute(rcedit_path, args, true);
-#else
- // On non-Windows we need WINE to run rcedit
- args.push_front(rcedit_path);
- OS::get_singleton()->execute(wine_path, args, true);
-#endif
-}
-
-Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
- List<String> args;
-
-#ifdef WINDOWS_ENABLED
- String signtool_path = EditorSettings::get_singleton()->get("export/windows/signtool");
- if (signtool_path != String() && !FileAccess::exists(signtool_path)) {
- ERR_PRINT("Could not find signtool executable at " + signtool_path + ", aborting.");
- return ERR_FILE_NOT_FOUND;
- }
- if (signtool_path == String()) {
- signtool_path = "signtool"; // try to run signtool from PATH
- }
-#else
- String signtool_path = EditorSettings::get_singleton()->get("export/windows/osslsigncode");
- if (signtool_path != String() && !FileAccess::exists(signtool_path)) {
- ERR_PRINT("Could not find osslsigncode executable at " + signtool_path + ", aborting.");
- return ERR_FILE_NOT_FOUND;
- }
- if (signtool_path == String()) {
- signtool_path = "osslsigncode"; // try to run signtool from PATH
- }
-#endif
-
- args.push_back("sign");
-
- //identity
-#ifdef WINDOWS_ENABLED
- int id_type = p_preset->get("codesign/identity_type");
- if (id_type == 0) { //auto select
- args.push_back("/a");
- } else if (id_type == 1) { //pkcs12
- if (p_preset->get("codesign/identity") != "") {
- args.push_back("/f");
- args.push_back(p_preset->get("codesign/identity"));
- } else {
- EditorNode::add_io_error("codesign: no identity found");
- return FAILED;
- }
- } else if (id_type == 2) { //Windows certificate store
- if (p_preset->get("codesign/identity") != "") {
- args.push_back("/sha1");
- args.push_back(p_preset->get("codesign/identity"));
- } else {
- EditorNode::add_io_error("codesign: no identity found");
- return FAILED;
- }
- } else {
- EditorNode::add_io_error("codesign: invalid identity type");
- return FAILED;
- }
-#else
- if (p_preset->get("codesign/identity") != "") {
- args.push_back("-pkcs12");
- args.push_back(p_preset->get("codesign/identity"));
- } else {
- EditorNode::add_io_error("codesign: no identity found");
- return FAILED;
- }
-#endif
-
- //password
- if (p_preset->get("codesign/password") != "") {
-#ifdef WINDOWS_ENABLED
- args.push_back("/p");
-#else
- args.push_back("-pass");
-#endif
- args.push_back(p_preset->get("codesign/password"));
- }
-
- //timestamp
- if (p_preset->get("codesign/timestamp")) {
- if (p_preset->get("codesign/timestamp_server") != "") {
-#ifdef WINDOWS_ENABLED
- args.push_back("/tr");
- args.push_back(p_preset->get("codesign/timestamp_server_url"));
- args.push_back("/td");
- if ((int)p_preset->get("codesign/digest_algorithm") == 0) {
- args.push_back("sha1");
- } else {
- args.push_back("sha256");
- }
-#else
- args.push_back("-ts");
- args.push_back(p_preset->get("codesign/timestamp_server_url"));
-#endif
- } else {
- EditorNode::add_io_error("codesign: invalid timestamp server");
- return FAILED;
- }
- }
-
- //digest
-#ifdef WINDOWS_ENABLED
- args.push_back("/fd");
-#else
- args.push_back("-h");
-#endif
- if ((int)p_preset->get("codesign/digest_algorithm") == 0) {
- args.push_back("sha1");
- } else {
- args.push_back("sha256");
- }
+#include "export_plugin.h"
- //description
- if (p_preset->get("codesign/description") != "") {
-#ifdef WINDOWS_ENABLED
- args.push_back("/d");
-#else
- args.push_back("-n");
-#endif
- args.push_back(p_preset->get("codesign/description"));
- }
-
- //user options
- PackedStringArray user_args = p_preset->get("codesign/custom_options");
- for (int i = 0; i < user_args.size(); i++) {
- String user_arg = user_args[i].strip_edges();
- if (!user_arg.empty()) {
- args.push_back(user_arg);
- }
- }
-
-#ifndef WINDOWS_ENABLED
- args.push_back("-in");
-#endif
- args.push_back(p_path);
-#ifndef WINDOWS_ENABLED
- args.push_back("-out");
- args.push_back(p_path);
-#endif
-
- String str;
- Error err = OS::get_singleton()->execute(signtool_path, args, true, nullptr, &str, nullptr, true);
- ERR_FAIL_COND_V(err != OK, err);
-
- print_line("codesign (" + p_path + "): " + str);
-#ifndef WINDOWS_ENABLED
- if (str.find("SignTool Error") != -1) {
-#else
- if (str.find("Failed") != -1) {
-#endif
- return FAILED;
- }
-
- return OK;
-}
+static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size);
void register_windows_exporter() {
EDITOR_DEF("export/windows/rcedit", "");
@@ -344,11 +49,11 @@ void register_windows_exporter() {
#endif
Ref<EditorExportPlatformWindows> platform;
- platform.instance();
+ platform.instantiate();
Ref<Image> img = memnew(Image(_windows_logo));
Ref<ImageTexture> logo;
- logo.instance();
+ logo.instantiate();
logo->create_from_image(img);
platform->set_logo(logo);
platform->set_name("Windows Desktop");
diff --git a/platform/windows/export/export.h b/platform/windows/export/export.h
index d669192831..110e1439e2 100644
--- a/platform/windows/export/export.h
+++ b/platform/windows/export/export.h
@@ -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 */
@@ -28,4 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef WINDOWS_EXPORT_H
+#define WINDOWS_EXPORT_H
+
void register_windows_exporter();
+
+#endif
diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp
new file mode 100644
index 0000000000..165e86c066
--- /dev/null
+++ b/platform/windows/export/export_plugin.cpp
@@ -0,0 +1,323 @@
+/*************************************************************************/
+/* export_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "export_plugin.h"
+
+Error EditorExportPlatformWindows::sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) {
+ if (p_preset->get("codesign/enable")) {
+ return _code_sign(p_preset, p_path);
+ } else {
+ return OK;
+ }
+}
+
+Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+ Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, p_path, p_flags);
+
+ if (err != OK) {
+ return err;
+ }
+
+ _rcedit_add_data(p_preset, p_path);
+
+ if (p_preset->get("codesign/enable") && err == OK) {
+ err = _code_sign(p_preset, p_path);
+ }
+
+ return err;
+}
+
+void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) {
+ EditorExportPlatformPC::get_export_options(r_options);
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false));
+#ifdef WINDOWS_ENABLED
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA1 hash)"), 0));
+#endif
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/timestamp_server_url"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/digest_algorithm", PROPERTY_HINT_ENUM, "SHA1,SHA256"), 1));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/description"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray()));
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_description"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/trademarks"), ""));
+}
+
+void EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
+ String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit");
+
+ if (rcedit_path == String()) {
+ return;
+ }
+
+ if (!FileAccess::exists(rcedit_path)) {
+ ERR_PRINT("Could not find rcedit executable at " + rcedit_path + ", no icon or app information data will be included.");
+ return;
+ }
+
+#ifndef WINDOWS_ENABLED
+ // On non-Windows we need WINE to run rcedit
+ String wine_path = EditorSettings::get_singleton()->get("export/windows/wine");
+
+ if (wine_path != String() && !FileAccess::exists(wine_path)) {
+ ERR_PRINT("Could not find wine executable at " + wine_path + ", no icon or app information data will be included.");
+ return;
+ }
+
+ if (wine_path == String()) {
+ wine_path = "wine"; // try to run wine from PATH
+ }
+#endif
+
+ String icon_path = ProjectSettings::get_singleton()->globalize_path(p_preset->get("application/icon"));
+ String file_verion = p_preset->get("application/file_version");
+ String product_version = p_preset->get("application/product_version");
+ String company_name = p_preset->get("application/company_name");
+ String product_name = p_preset->get("application/product_name");
+ String file_description = p_preset->get("application/file_description");
+ String copyright = p_preset->get("application/copyright");
+ String trademarks = p_preset->get("application/trademarks");
+ String comments = p_preset->get("application/comments");
+
+ List<String> args;
+ args.push_back(p_path);
+ if (icon_path != String()) {
+ args.push_back("--set-icon");
+ args.push_back(icon_path);
+ }
+ if (file_verion != String()) {
+ args.push_back("--set-file-version");
+ args.push_back(file_verion);
+ }
+ if (product_version != String()) {
+ args.push_back("--set-product-version");
+ args.push_back(product_version);
+ }
+ if (company_name != String()) {
+ args.push_back("--set-version-string");
+ args.push_back("CompanyName");
+ args.push_back(company_name);
+ }
+ if (product_name != String()) {
+ args.push_back("--set-version-string");
+ args.push_back("ProductName");
+ args.push_back(product_name);
+ }
+ if (file_description != String()) {
+ args.push_back("--set-version-string");
+ args.push_back("FileDescription");
+ args.push_back(file_description);
+ }
+ if (copyright != String()) {
+ args.push_back("--set-version-string");
+ args.push_back("LegalCopyright");
+ args.push_back(copyright);
+ }
+ if (trademarks != String()) {
+ args.push_back("--set-version-string");
+ args.push_back("LegalTrademarks");
+ args.push_back(trademarks);
+ }
+
+#ifdef WINDOWS_ENABLED
+ OS::get_singleton()->execute(rcedit_path, args);
+#else
+ // On non-Windows we need WINE to run rcedit
+ args.push_front(rcedit_path);
+ OS::get_singleton()->execute(wine_path, args);
+#endif
+}
+
+Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
+ List<String> args;
+
+#ifdef WINDOWS_ENABLED
+ String signtool_path = EditorSettings::get_singleton()->get("export/windows/signtool");
+ if (signtool_path != String() && !FileAccess::exists(signtool_path)) {
+ ERR_PRINT("Could not find signtool executable at " + signtool_path + ", aborting.");
+ return ERR_FILE_NOT_FOUND;
+ }
+ if (signtool_path == String()) {
+ signtool_path = "signtool"; // try to run signtool from PATH
+ }
+#else
+ String signtool_path = EditorSettings::get_singleton()->get("export/windows/osslsigncode");
+ if (signtool_path != String() && !FileAccess::exists(signtool_path)) {
+ ERR_PRINT("Could not find osslsigncode executable at " + signtool_path + ", aborting.");
+ return ERR_FILE_NOT_FOUND;
+ }
+ if (signtool_path == String()) {
+ signtool_path = "osslsigncode"; // try to run signtool from PATH
+ }
+#endif
+
+ args.push_back("sign");
+
+ //identity
+#ifdef WINDOWS_ENABLED
+ int id_type = p_preset->get("codesign/identity_type");
+ if (id_type == 0) { //auto select
+ args.push_back("/a");
+ } else if (id_type == 1) { //pkcs12
+ if (p_preset->get("codesign/identity") != "") {
+ args.push_back("/f");
+ args.push_back(p_preset->get("codesign/identity"));
+ } else {
+ EditorNode::add_io_error("codesign: no identity found");
+ return FAILED;
+ }
+ } else if (id_type == 2) { //Windows certificate store
+ if (p_preset->get("codesign/identity") != "") {
+ args.push_back("/sha1");
+ args.push_back(p_preset->get("codesign/identity"));
+ } else {
+ EditorNode::add_io_error("codesign: no identity found");
+ return FAILED;
+ }
+ } else {
+ EditorNode::add_io_error("codesign: invalid identity type");
+ return FAILED;
+ }
+#else
+ if (p_preset->get("codesign/identity") != "") {
+ args.push_back("-pkcs12");
+ args.push_back(p_preset->get("codesign/identity"));
+ } else {
+ EditorNode::add_io_error("codesign: no identity found");
+ return FAILED;
+ }
+#endif
+
+ //password
+ if (p_preset->get("codesign/password") != "") {
+#ifdef WINDOWS_ENABLED
+ args.push_back("/p");
+#else
+ args.push_back("-pass");
+#endif
+ args.push_back(p_preset->get("codesign/password"));
+ }
+
+ //timestamp
+ if (p_preset->get("codesign/timestamp")) {
+ if (p_preset->get("codesign/timestamp_server") != "") {
+#ifdef WINDOWS_ENABLED
+ args.push_back("/tr");
+ args.push_back(p_preset->get("codesign/timestamp_server_url"));
+ args.push_back("/td");
+ if ((int)p_preset->get("codesign/digest_algorithm") == 0) {
+ args.push_back("sha1");
+ } else {
+ args.push_back("sha256");
+ }
+#else
+ args.push_back("-ts");
+ args.push_back(p_preset->get("codesign/timestamp_server_url"));
+#endif
+ } else {
+ EditorNode::add_io_error("codesign: invalid timestamp server");
+ return FAILED;
+ }
+ }
+
+ //digest
+#ifdef WINDOWS_ENABLED
+ args.push_back("/fd");
+#else
+ args.push_back("-h");
+#endif
+ if ((int)p_preset->get("codesign/digest_algorithm") == 0) {
+ args.push_back("sha1");
+ } else {
+ args.push_back("sha256");
+ }
+
+ //description
+ if (p_preset->get("codesign/description") != "") {
+#ifdef WINDOWS_ENABLED
+ args.push_back("/d");
+#else
+ args.push_back("-n");
+#endif
+ args.push_back(p_preset->get("codesign/description"));
+ }
+
+ //user options
+ PackedStringArray user_args = p_preset->get("codesign/custom_options");
+ for (int i = 0; i < user_args.size(); i++) {
+ String user_arg = user_args[i].strip_edges();
+ if (!user_arg.is_empty()) {
+ args.push_back(user_arg);
+ }
+ }
+
+#ifndef WINDOWS_ENABLED
+ args.push_back("-in");
+#endif
+ args.push_back(p_path);
+#ifndef WINDOWS_ENABLED
+ args.push_back("-out");
+ args.push_back(p_path + "_signed");
+#endif
+
+ String str;
+ Error err = OS::get_singleton()->execute(signtool_path, args, &str, nullptr, true);
+ ERR_FAIL_COND_V(err != OK, err);
+
+ print_line("codesign (" + p_path + "): " + str);
+#ifndef WINDOWS_ENABLED
+ if (str.find("SignTool Error") != -1) {
+#else
+ if (str.find("Failed") != -1) {
+#endif
+ return FAILED;
+ }
+
+#ifndef WINDOWS_ENABLED
+ DirAccessRef tmp_dir = DirAccess::create_for_path(p_path.get_base_dir());
+
+ err = tmp_dir->remove(p_path);
+ ERR_FAIL_COND_V(err != OK, err);
+
+ err = tmp_dir->rename(p_path + "_signed", p_path);
+ ERR_FAIL_COND_V(err != OK, err);
+#endif
+
+ return OK;
+}
diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h
new file mode 100644
index 0000000000..11d3826410
--- /dev/null
+++ b/platform/windows/export/export_plugin.h
@@ -0,0 +1,51 @@
+/*************************************************************************/
+/* export_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* 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 */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef WINDOWS_EXPORT_PLUGIN_H
+#define WINDOWS_EXPORT_PLUGIN_H
+
+#include "core/io/file_access.h"
+#include "core/os/os.h"
+#include "editor/editor_export.h"
+#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
+#include "platform/windows/logo.gen.h"
+
+class EditorExportPlatformWindows : public EditorExportPlatformPC {
+ void _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path);
+ Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
+
+public:
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
+ virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
+ virtual void get_export_options(List<ExportOption> *r_options);
+};
+
+#endif
diff --git a/platform/windows/godot.natvis b/platform/windows/godot.natvis
index 90f0b55d0a..bb855e4ac8 100644
--- a/platform/windows/godot.natvis
+++ b/platform/windows/godot.natvis
@@ -10,12 +10,12 @@
</Expand>
</Type>
- <Type Name="PoolVector&lt;*&gt;">
+ <Type Name="LocalVector&lt;*&gt;">
<Expand>
- <Item Name="[size]">alloc ? (alloc-&gt;size / sizeof($T1)) : 0</Item>
+ <Item Name="[size]">count</Item>
<ArrayItems>
- <Size>alloc ? (alloc-&gt;size / sizeof($T1)) : 0</Size>
- <ValuePointer>alloc ? (($T1 *)alloc-&gt;mem) : 0</ValuePointer>
+ <Size>count</Size>
+ <ValuePointer>data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
@@ -36,75 +36,79 @@
<DisplayString Condition="type == Variant::NIL">nil</DisplayString>
<DisplayString Condition="type == Variant::BOOL">{_data._bool}</DisplayString>
<DisplayString Condition="type == Variant::INT">{_data._int}</DisplayString>
- <DisplayString Condition="type == Variant::REAL">{_data._real}</DisplayString>
+ <DisplayString Condition="type == Variant::FLOAT">{_data._float}</DisplayString>
<DisplayString Condition="type == Variant::TRANSFORM2D">{_data._transform2d}</DisplayString>
<DisplayString Condition="type == Variant::AABB">{_data._aabb}</DisplayString>
<DisplayString Condition="type == Variant::BASIS">{_data._basis}</DisplayString>
- <DisplayString Condition="type == Variant::TRANSFORM">{_data._transform}</DisplayString>
+ <DisplayString Condition="type == Variant::TRANSFORM3D">{_data._transform}</DisplayString>
<DisplayString Condition="type == Variant::STRING">{*(String *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::VECTOR2">{*(Vector2 *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::RECT2">{*(Rect2 *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::VECTOR3">{*(Vector3 *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::PLANE">{*(Plane *)_data._mem}</DisplayString>
- <DisplayString Condition="type == Variant::QUAT">{*(Quat *)_data._mem}</DisplayString>
+ <DisplayString Condition="type == Variant::QUATERNION">{*(Quaternion *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::COLOR">{*(Color *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::NODE_PATH">{*(NodePath *)_data._mem}</DisplayString>
- <DisplayString Condition="type == Variant::_RID">{*(RID *)_data._mem}</DisplayString>
+ <DisplayString Condition="type == Variant::RID">{*(::RID *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::OBJECT">{*(Object *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::DICTIONARY">{*(Dictionary *)_data._mem}</DisplayString>
<DisplayString Condition="type == Variant::ARRAY">{*(Array *)_data._mem}</DisplayString>
- <DisplayString Condition="type == Variant::POOL_BYTE_ARRAY">{*(PoolByteArray *)_data._mem}</DisplayString>
- <DisplayString Condition="type == Variant::POOL_INT_ARRAY">{*(PoolIntArray *)_data._mem}</DisplayString>
- <DisplayString Condition="type == Variant::POOL_REAL_ARRAY">{*(PoolRealArray *)_data._mem}</DisplayString>
- <DisplayString Condition="type == Variant::POOL_STRING_ARRAY">{*(PoolStringArray *)_data._mem}</DisplayString>
- <DisplayString Condition="type == Variant::POOL_VECTOR2_ARRAY">{*(PoolVector2Array *)_data._mem}</DisplayString>
- <DisplayString Condition="type == Variant::POOL_VECTOR3_ARRAY">{*(PoolVector3Array *)_data._mem}</DisplayString>
- <DisplayString Condition="type == Variant::POOL_COLOR_ARRAY">{*(PoolColorArray *)_data._mem}</DisplayString>
+ <DisplayString Condition="type == Variant::PACKED_BYTE_ARRAY">{*(PackedByteArray *)_data._mem}</DisplayString>
+ <DisplayString Condition="type == Variant::PACKED_INT32_ARRAY">{*(PackedInt32Array *)_data._mem}</DisplayString>
+ <DisplayString Condition="type == Variant::PACKED_INT64_ARRAY">{*(PackedInt64Array *)_data._mem}</DisplayString>
+ <DisplayString Condition="type == Variant::PACKED_FLOAT32_ARRAY">{*(PackedFloat32Array *)_data._mem}</DisplayString>
+ <DisplayString Condition="type == Variant::PACKED_FLOAT64_ARRAY">{*(PackedFloat64Array *)_data._mem}</DisplayString>
+ <DisplayString Condition="type == Variant::PACKED_STRING_ARRAY">{*(PackedStringArray *)_data._mem}</DisplayString>
+ <DisplayString Condition="type == Variant::PACKED_VECTOR2_ARRAY">{*(PackedVector2Array *)_data._mem}</DisplayString>
+ <DisplayString Condition="type == Variant::PACKED_VECTOR3_ARRAY">{*(PackedVector3Array *)_data._mem}</DisplayString>
+ <DisplayString Condition="type == Variant::PACKED_COLOR_ARRAY">{*(PackedColorArray *)_data._mem}</DisplayString>
- <StringView Condition="type == Variant::STRING &amp;&amp; ((String *)(_data._mem))->_cowdata._ptr">((String *)(_data._mem))->_cowdata._ptr,su</StringView>
+ <StringView Condition="type == Variant::STRING &amp;&amp; ((String *)(_data._mem))->_cowdata._ptr">((String *)(_data._mem))->_cowdata._ptr,s32</StringView>
<Expand>
<Item Name="[value]" Condition="type == Variant::BOOL">_data._bool</Item>
<Item Name="[value]" Condition="type == Variant::INT">_data._int</Item>
- <Item Name="[value]" Condition="type == Variant::REAL">_data._real</Item>
+ <Item Name="[value]" Condition="type == Variant::FLOAT">_data._float</Item>
<Item Name="[value]" Condition="type == Variant::TRANSFORM2D">_data._transform2d</Item>
<Item Name="[value]" Condition="type == Variant::AABB">_data._aabb</Item>
<Item Name="[value]" Condition="type == Variant::BASIS">_data._basis</Item>
- <Item Name="[value]" Condition="type == Variant::TRANSFORM">_data._transform</Item>
+ <Item Name="[value]" Condition="type == Variant::TRANSFORM3D">_data._transform</Item>
<Item Name="[value]" Condition="type == Variant::STRING">*(String *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::VECTOR2">*(Vector2 *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::RECT2">*(Rect2 *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::VECTOR3">*(Vector3 *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::PLANE">*(Plane *)_data._mem</Item>
- <Item Name="[value]" Condition="type == Variant::QUAT">*(Quat *)_data._mem</Item>
+ <Item Name="[value]" Condition="type == Variant::QUATERNION">*(Quaternion *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::COLOR">*(Color *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::NODE_PATH">*(NodePath *)_data._mem</Item>
- <Item Name="[value]" Condition="type == Variant::_RID">*(RID *)_data._mem</Item>
+ <Item Name="[value]" Condition="type == Variant::RID">*(::RID *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::OBJECT">*(Object *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::DICTIONARY">*(Dictionary *)_data._mem</Item>
<Item Name="[value]" Condition="type == Variant::ARRAY">*(Array *)_data._mem</Item>
- <Item Name="[value]" Condition="type == Variant::POOL_BYTE_ARRAY">*(PoolByteArray *)_data._mem</Item>
- <Item Name="[value]" Condition="type == Variant::POOL_INT_ARRAY">*(PoolIntArray *)_data._mem</Item>
- <Item Name="[value]" Condition="type == Variant::POOL_REAL_ARRAY">*(PoolRealArray *)_data._mem</Item>
- <Item Name="[value]" Condition="type == Variant::POOL_STRING_ARRAY">*(PoolStringArray *)_data._mem</Item>
- <Item Name="[value]" Condition="type == Variant::POOL_VECTOR2_ARRAY">*(PoolVector2Array *)_data._mem</Item>
- <Item Name="[value]" Condition="type == Variant::POOL_VECTOR3_ARRAY">*(PoolVector3Array *)_data._mem</Item>
- <Item Name="[value]" Condition="type == Variant::POOL_COLOR_ARRAY">*(PoolColorArray *)_data._mem</Item>
+ <Item Name="[value]" Condition="type == Variant::PACKED_BYTE_ARRAY">*(PackedByteArray *)_data._mem</Item>
+ <Item Name="[value]" Condition="type == Variant::PACKED_INT32_ARRAY">*(PackedInt32Array *)_data._mem</Item>
+ <Item Name="[value]" Condition="type == Variant::PACKED_INT64_ARRAY">*(PackedInt64Array *)_data._mem</Item>
+ <Item Name="[value]" Condition="type == Variant::PACKED_FLOAT32_ARRAY">*(PackedFloat32Array *)_data._mem</Item>
+ <Item Name="[value]" Condition="type == Variant::PACKED_FLOAT64_ARRAY">*(PackedFloat64Array *)_data._mem</Item>
+ <Item Name="[value]" Condition="type == Variant::PACKED_STRING_ARRAY">*(PackedStringArray *)_data._mem</Item>
+ <Item Name="[value]" Condition="type == Variant::PACKED_VECTOR2_ARRAY">*(PackedVector2Array *)_data._mem</Item>
+ <Item Name="[value]" Condition="type == Variant::PACKED_VECTOR3_ARRAY">*(PackedVector3Array *)_data._mem</Item>
+ <Item Name="[value]" Condition="type == Variant::PACKED_COLOR_ARRAY">*(PackedColorArray *)_data._mem</Item>
</Expand>
</Type>
<Type Name="String">
<DisplayString Condition="_cowdata._ptr == 0">[empty]</DisplayString>
- <DisplayString Condition="_cowdata._ptr != 0">{_cowdata._ptr,su}</DisplayString>
- <StringView Condition="_cowdata._ptr != 0">_cowdata._ptr,su</StringView>
+ <DisplayString Condition="_cowdata._ptr != 0">{_cowdata._ptr,s32}</DisplayString>
+ <StringView Condition="_cowdata._ptr != 0">_cowdata._ptr,s32</StringView>
</Type>
<Type Name="StringName">
<DisplayString Condition="_data &amp;&amp; _data->cname">{_data->cname}</DisplayString>
- <DisplayString Condition="_data &amp;&amp; !_data->cname">{_data->name,su}</DisplayString>
+ <DisplayString Condition="_data &amp;&amp; !_data->cname">{_data->name,s32}</DisplayString>
<DisplayString Condition="!_data">[empty]</DisplayString>
<StringView Condition="_data &amp;&amp; _data->cname">_data->cname</StringView>
- <StringView Condition="_data &amp;&amp; !_data->cname">_data->name,su</StringView>
+ <StringView Condition="_data &amp;&amp; !_data->cname">_data->name,s32</StringView>
</Type>
<Type Name="Vector2">
@@ -124,8 +128,8 @@
</Expand>
</Type>
- <Type Name="Quat">
- <DisplayString>Quat {{{x},{y},{z},{w}}}</DisplayString>
+ <Type Name="Quaternion">
+ <DisplayString>Quaternion {{{x},{y},{z},{w}}}</DisplayString>
<Expand>
<Item Name="x">x</Item>
<Item Name="y">y</Item>
diff --git a/platform/windows/godot_windows.cpp b/platform/windows/godot_windows.cpp
index add559a717..22e2e5f7e5 100644
--- a/platform/windows/godot_windows.cpp
+++ b/platform/windows/godot_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 */
diff --git a/platform/windows/joypad_windows.cpp b/platform/windows/joypad_windows.cpp
index d1454c9096..94da63e49d 100644
--- a/platform/windows/joypad_windows.cpp
+++ b/platform/windows/joypad_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 */
@@ -110,12 +110,11 @@ bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
if (GetRawInputDeviceList(nullptr, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
return false;
}
- dev_list = (PRAWINPUTDEVICELIST)malloc(sizeof(RAWINPUTDEVICELIST) * dev_list_count);
- if (!dev_list)
- return false;
+ dev_list = (PRAWINPUTDEVICELIST)memalloc(sizeof(RAWINPUTDEVICELIST) * dev_list_count);
+ ERR_FAIL_NULL_V_MSG(dev_list, false, "Out of memory.");
if (GetRawInputDeviceList(dev_list, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
- free(dev_list);
+ memfree(dev_list);
return false;
}
for (unsigned int i = 0; i < dev_list_count; i++) {
@@ -130,11 +129,11 @@ bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
(MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == (LONG)p_guid->Data1) &&
(GetRawInputDeviceInfoA(dev_list[i].hDevice, RIDI_DEVICENAME, &dev_name, &nameSize) != (UINT)-1) &&
(strstr(dev_name, "IG_") != nullptr)) {
- free(dev_list);
+ memfree(dev_list);
return true;
}
}
- free(dev_list);
+ memfree(dev_list);
return false;
}
@@ -151,7 +150,7 @@ bool JoypadWindows::setup_dinput_joypad(const DIDEVICEINSTANCE *instance) {
const DWORD devtype = (instance->dwDevType & 0xFF);
- if ((devtype != DI8DEVTYPE_JOYSTICK) && (devtype != DI8DEVTYPE_GAMEPAD) && (devtype != DI8DEVTYPE_1STPERSON)) {
+ if ((devtype != DI8DEVTYPE_JOYSTICK) && (devtype != DI8DEVTYPE_GAMEPAD) && (devtype != DI8DEVTYPE_1STPERSON) && (devtype != DI8DEVTYPE_DRIVING)) {
return false;
}
@@ -194,7 +193,7 @@ void JoypadWindows::setup_joypad_object(const DIDEVICEOBJECTINSTANCE *ob, int p_
HRESULT res;
DIPROPRANGE prop_range;
DIPROPDWORD dilong;
- DWORD ofs;
+ LONG ofs;
if (ob->guidType == GUID_XAxis)
ofs = DIJOFS_X;
else if (ob->guidType == GUID_YAxis)
@@ -331,7 +330,7 @@ void JoypadWindows::process_joypads() {
if (joy.state.dwPacketNumber != joy.last_packet) {
int button_mask = XINPUT_GAMEPAD_DPAD_UP;
for (int j = 0; j <= 16; j++) {
- input->joy_button(joy.id, j, joy.state.Gamepad.wButtons & button_mask);
+ input->joy_button(joy.id, (JoyButton)j, joy.state.Gamepad.wButtons & button_mask);
button_mask = button_mask * 2;
}
@@ -382,12 +381,12 @@ void JoypadWindows::process_joypads() {
for (int j = 0; j < 128; j++) {
if (js.rgbButtons[j] & 0x80) {
if (!joy->last_buttons[j]) {
- input->joy_button(joy->id, j, true);
+ input->joy_button(joy->id, (JoyButton)j, true);
joy->last_buttons[j] = true;
}
} else {
if (joy->last_buttons[j]) {
- input->joy_button(joy->id, j, false);
+ input->joy_button(joy->id, (JoyButton)j, false);
joy->last_buttons[j] = false;
}
}
@@ -395,13 +394,13 @@ void JoypadWindows::process_joypads() {
// on mingw, these constants are not constants
int count = 8;
- unsigned int axes[] = { DIJOFS_X, DIJOFS_Y, DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ, DIJOFS_SLIDER(0), DIJOFS_SLIDER(1) };
+ LONG axes[] = { DIJOFS_X, DIJOFS_Y, DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ, (LONG)DIJOFS_SLIDER(0), (LONG)DIJOFS_SLIDER(1) };
int values[] = { js.lX, js.lY, js.lZ, js.lRx, js.lRy, js.lRz, js.rglSlider[0], js.rglSlider[1] };
for (int j = 0; j < joy->joy_axis.size(); j++) {
for (int k = 0; k < count; k++) {
if (joy->joy_axis[j] == axes[k]) {
- input->joy_axis(joy->id, j, axis_correct(values[k]));
+ input->joy_axis(joy->id, (JoyAxis)j, axis_correct(values[k]));
break;
};
};
@@ -411,44 +410,44 @@ void JoypadWindows::process_joypads() {
}
void JoypadWindows::post_hat(int p_device, DWORD p_dpad) {
- int dpad_val = 0;
+ HatMask dpad_val = (HatMask)0;
// Should be -1 when centered, but according to docs:
// "Some drivers report the centered position of the POV indicator as 65,535. Determine whether the indicator is centered as follows:
// BOOL POVCentered = (LOWORD(dwPOV) == 0xFFFF);"
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ee416628(v%3Dvs.85)#remarks
if (LOWORD(p_dpad) == 0xFFFF) {
- dpad_val = Input::HAT_MASK_CENTER;
+ dpad_val = (HatMask)HatMask::HAT_MASK_CENTER;
}
if (p_dpad == 0) {
- dpad_val = Input::HAT_MASK_UP;
+ dpad_val = (HatMask)HatMask::HAT_MASK_UP;
} else if (p_dpad == 4500) {
- dpad_val = (Input::HAT_MASK_UP | Input::HAT_MASK_RIGHT);
+ dpad_val = (HatMask)(HatMask::HAT_MASK_UP | HatMask::HAT_MASK_RIGHT);
} else if (p_dpad == 9000) {
- dpad_val = Input::HAT_MASK_RIGHT;
+ dpad_val = (HatMask)HatMask::HAT_MASK_RIGHT;
} else if (p_dpad == 13500) {
- dpad_val = (Input::HAT_MASK_RIGHT | Input::HAT_MASK_DOWN);
+ dpad_val = (HatMask)(HatMask::HAT_MASK_RIGHT | HatMask::HAT_MASK_DOWN);
} else if (p_dpad == 18000) {
- dpad_val = Input::HAT_MASK_DOWN;
+ dpad_val = (HatMask)HatMask::HAT_MASK_DOWN;
} else if (p_dpad == 22500) {
- dpad_val = (Input::HAT_MASK_DOWN | Input::HAT_MASK_LEFT);
+ dpad_val = (HatMask)(HatMask::HAT_MASK_DOWN | HatMask::HAT_MASK_LEFT);
} else if (p_dpad == 27000) {
- dpad_val = Input::HAT_MASK_LEFT;
+ dpad_val = (HatMask)HatMask::HAT_MASK_LEFT;
} else if (p_dpad == 31500) {
- dpad_val = (Input::HAT_MASK_LEFT | Input::HAT_MASK_UP);
+ dpad_val = (HatMask)(HatMask::HAT_MASK_LEFT | HatMask::HAT_MASK_UP);
}
input->joy_hat(p_device, dpad_val);
};
-Input::JoyAxis JoypadWindows::axis_correct(int p_val, bool p_xinput, bool p_trigger, bool p_negate) const {
- Input::JoyAxis jx;
+Input::JoyAxisValue JoypadWindows::axis_correct(int p_val, bool p_xinput, bool p_trigger, bool p_negate) const {
+ Input::JoyAxisValue jx;
if (Math::abs(p_val) < MIN_JOY_AXIS) {
jx.min = p_trigger ? 0 : -1;
jx.value = 0.0f;
diff --git a/platform/windows/joypad_windows.h b/platform/windows/joypad_windows.h
index c961abf0a5..757fb54fb3 100644
--- a/platform/windows/joypad_windows.h
+++ b/platform/windows/joypad_windows.h
@@ -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 */
@@ -77,7 +77,7 @@ private:
DWORD last_pad;
LPDIRECTINPUTDEVICE8 di_joy;
- List<DWORD> joy_axis;
+ List<LONG> joy_axis;
GUID guid;
dinput_gamepad() {
@@ -92,21 +92,13 @@ private:
};
struct xinput_gamepad {
- int id;
- bool attached;
- bool vibrating;
- DWORD last_packet;
+ int id = 0;
+ bool attached = false;
+ bool vibrating = false;
+ DWORD last_packet = 0;
XINPUT_STATE state;
- uint64_t ff_timestamp;
- uint64_t ff_end_timestamp;
-
- xinput_gamepad() {
- attached = false;
- vibrating = false;
- ff_timestamp = 0;
- ff_end_timestamp = 0;
- last_packet = 0;
- }
+ uint64_t ff_timestamp = 0;
+ uint64_t ff_end_timestamp = 0;
};
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex, XINPUT_STATE *pState);
@@ -140,7 +132,7 @@ private:
void joypad_vibration_start_xinput(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp);
void joypad_vibration_stop_xinput(int p_device, uint64_t p_timestamp);
- Input::JoyAxis axis_correct(int p_val, bool p_xinput = false, bool p_trigger = false, bool p_negate = false) const;
+ Input::JoyAxisValue axis_correct(int p_val, bool p_xinput = false, bool p_trigger = false, bool p_negate = false) const;
XInputGetState_t xinput_get_state;
XInputSetState_t xinput_set_state;
};
diff --git a/platform/windows/key_mapping_windows.cpp b/platform/windows/key_mapping_windows.cpp
index d8d0b13068..8016d20470 100644
--- a/platform/windows/key_mapping_windows.cpp
+++ b/platform/windows/key_mapping_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,6 @@ struct _WinTranslatePair {
};
static _WinTranslatePair _vk_to_keycode[] = {
-
{ KEY_BACKSPACE, VK_BACK }, // (0x08) // backspace
{ KEY_TAB, VK_TAB }, //(0x09)
@@ -48,7 +47,7 @@ static _WinTranslatePair _vk_to_keycode[] = {
{ KEY_SHIFT, VK_SHIFT }, //(0x10)
- { KEY_CONTROL, VK_CONTROL }, //(0x11)
+ { KEY_CTRL, VK_CONTROL }, //(0x11)
{ KEY_ALT, VK_MENU }, //(0x12)
@@ -167,8 +166,8 @@ static _WinTranslatePair _vk_to_keycode[] = {
{ KEY_SCROLLLOCK, VK_SCROLL }, // (0x91)
{ KEY_SHIFT, VK_LSHIFT }, // (0xA0)
{ KEY_SHIFT, VK_RSHIFT }, // (0xA1)
- { KEY_CONTROL, VK_LCONTROL }, // (0xA2)
- { KEY_CONTROL, VK_RCONTROL }, // (0xA3)
+ { KEY_CTRL, VK_LCONTROL }, // (0xA2)
+ { KEY_CTRL, VK_RCONTROL }, // (0xA3)
{ KEY_MENU, VK_LMENU }, // (0xA4)
{ KEY_MENU, VK_RMENU }, // (0xA5)
@@ -238,7 +237,6 @@ VK_OEM_CLEAR (0xFE)
*/
static _WinTranslatePair _scancode_to_keycode[] = {
-
{ KEY_ESCAPE, 0x01 },
{ KEY_1, 0x02 },
{ KEY_2, 0x03 },
@@ -267,7 +265,7 @@ static _WinTranslatePair _scancode_to_keycode[] = {
{ KEY_BRACELEFT, 0x1A },
{ KEY_BRACERIGHT, 0x1B },
{ KEY_ENTER, 0x1C },
- { KEY_CONTROL, 0x1D },
+ { KEY_CTRL, 0x1D },
{ KEY_A, 0x1E },
{ KEY_S, 0x1F },
{ KEY_D, 0x20 },
@@ -347,6 +345,16 @@ unsigned int KeyMappingWindows::get_keysym(unsigned int p_code) {
return KEY_UNKNOWN;
}
+unsigned int KeyMappingWindows::get_scancode(Key p_keycode) {
+ for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
+ if (_scancode_to_keycode[i].keysym == p_keycode) {
+ return _scancode_to_keycode[i].keycode;
+ }
+ }
+
+ return 0;
+}
+
unsigned int KeyMappingWindows::get_scansym(unsigned int p_code, bool p_extended) {
unsigned int keycode = KEY_UNKNOWN;
for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
@@ -367,6 +375,8 @@ unsigned int KeyMappingWindows::get_scansym(unsigned int p_code, bool p_extended
case KEY_CAPSLOCK: {
keycode = KEY_KP_ADD;
} break;
+ default:
+ break;
}
} else {
switch (keycode) {
@@ -406,6 +416,8 @@ unsigned int KeyMappingWindows::get_scansym(unsigned int p_code, bool p_extended
case KEY_PRINT: {
keycode = KEY_KP_MULTIPLY;
} break;
+ default:
+ break;
}
}
diff --git a/platform/windows/key_mapping_windows.h b/platform/windows/key_mapping_windows.h
index f64f1feb9f..f260666a3e 100644
--- a/platform/windows/key_mapping_windows.h
+++ b/platform/windows/key_mapping_windows.h
@@ -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 */
@@ -42,6 +42,7 @@ class KeyMappingWindows {
public:
static unsigned int get_keysym(unsigned int p_code);
+ static unsigned int get_scancode(Key p_keycode);
static unsigned int get_scansym(unsigned int p_code, bool p_extended);
static bool is_extended_key(unsigned int p_code);
};
diff --git a/platform/windows/lang_table.h b/platform/windows/lang_table.h
index f81bab13a4..51583cc11e 100644
--- a/platform/windows/lang_table.h
+++ b/platform/windows/lang_table.h
@@ -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 */
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index f73516b370..78b7be8a30 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_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 */
@@ -39,15 +39,12 @@
#include "core/version_generated.gen.h"
#include "drivers/windows/dir_access_windows.h"
#include "drivers/windows/file_access_windows.h"
-#include "drivers/windows/rw_lock_windows.h"
-#include "drivers/windows/thread_windows.h"
#include "joypad_windows.h"
#include "lang_table.h"
#include "main/main.h"
#include "platform/windows/display_server_windows.h"
#include "servers/audio_server.h"
-#include "servers/rendering/rendering_server_raster.h"
-#include "servers/rendering/rendering_server_wrap_mt.h"
+#include "servers/rendering/rendering_server_default.h"
#include "windows_terminal_logger.h"
#include <avrt.h>
@@ -168,6 +165,10 @@ BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType) {
}
}
+void OS_Windows::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 OS_Windows::initialize_debugging() {
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
}
@@ -177,13 +178,9 @@ void OS_Windows::initialize() {
//RedirectIOToConsole();
- ThreadWindows::make_default();
- RWLockWindows::make_default();
-
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);
- //FileAccessBufferedFA<FileAccessWindows>::make_default();
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_RESOURCES);
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_USERDATA);
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM);
@@ -211,7 +208,7 @@ void OS_Windows::initialize() {
current_pi.pi.hProcess = GetCurrentProcess();
process_map->insert(GetCurrentProcessId(), current_pi);
- IP_Unix::make_default();
+ IPUnix::make_default();
main_loop = nullptr;
}
@@ -244,7 +241,7 @@ void OS_Windows::finalize_core() {
}
Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
- String path = p_path;
+ String path = p_path.replace("/", "\\");
if (!FileAccess::exists(path)) {
//this code exists so gdnative can load .dll files from within the executable path
@@ -322,8 +319,8 @@ OS::Time OS_Windows::get_time(bool utc) const {
Time time;
time.hour = systemtime.wHour;
- time.min = systemtime.wMinute;
- time.sec = systemtime.wSecond;
+ time.minute = systemtime.wMinute;
+ time.second = systemtime.wSecond;
return time;
}
@@ -341,7 +338,7 @@ OS::TimeZoneInfo OS_Windows::get_time_zone_info() const {
}
// Bias value returned by GetTimeZoneInformation is inverted of what we expect
- // For example on GMT-3 GetTimeZoneInformation return a Bias of 180, so invert the value to get -180
+ // For example, on GMT-3 GetTimeZoneInformation return a Bias of 180, so invert the value to get -180
ret.bias = -info.Bias;
return ret;
}
@@ -411,22 +408,23 @@ String OS_Windows::_quote_command_line_argument(const String &p_text) const {
return p_text;
}
-Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
- if (p_blocking && r_pipe) {
- String argss = _quote_command_line_argument(p_path);
- for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
- argss += " " + _quote_command_line_argument(E->get());
- }
+Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
+ String path = p_path.replace("/", "\\");
+ String command = _quote_command_line_argument(path);
+ for (const String &E : p_arguments) {
+ command += " " + _quote_command_line_argument(E);
+ }
+ if (r_pipe) {
if (read_stderr) {
- argss += " 2>&1"; // Read stderr too
+ command += " 2>&1"; // Include stderr
}
- // Note: _wpopen is calling command as "cmd.exe /c argss", instead of executing it directly, add extra quotes around full command, to prevent it from stripping quotes in the command.
- argss = _quote_command_line_argument(argss);
-
- FILE *f = _wpopen((LPCWSTR)(argss.utf16().get_data()), L"r");
- ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
+ // Add extra quotes around the full command, to prevent it from stripping quotes in the command,
+ // because _wpopen calls command as "cmd.exe /c command", instead of executing it directly
+ command = _quote_command_line_argument(command);
+ FILE *f = _wpopen((LPCWSTR)(command.utf16().get_data()), L"r");
+ ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot create pipe from command: " + command);
char buf[65535];
while (fgets(buf, 65535, f)) {
if (p_pipe_mutex) {
@@ -437,20 +435,40 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
p_pipe_mutex->unlock();
}
}
-
int rv = _pclose(f);
+
if (r_exitcode) {
*r_exitcode = rv;
}
-
return OK;
}
- String cmdline = _quote_command_line_argument(p_path);
- const List<String>::Element *I = p_arguments.front();
- while (I) {
- cmdline += " " + _quote_command_line_argument(I->get());
- I = I->next();
+ ProcessInfo pi;
+ ZeroMemory(&pi.si, sizeof(pi.si));
+ pi.si.cb = sizeof(pi.si);
+ ZeroMemory(&pi.pi, sizeof(pi.pi));
+ LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
+
+ int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi);
+ ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command);
+
+ WaitForSingleObject(pi.pi.hProcess, INFINITE);
+ if (r_exitcode) {
+ DWORD ret2;
+ GetExitCodeProcess(pi.pi.hProcess, &ret2);
+ *r_exitcode = ret2;
+ }
+ CloseHandle(pi.pi.hProcess);
+ CloseHandle(pi.pi.hThread);
+
+ return OK;
+};
+
+Error OS_Windows::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
+ String path = p_path.replace("/", "\\");
+ String command = _quote_command_line_argument(path);
+ for (const String &E : p_arguments) {
+ command += " " + _quote_command_line_argument(E);
}
ProcessInfo pi;
@@ -459,25 +477,15 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
ZeroMemory(&pi.pi, sizeof(pi.pi));
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
- Char16String modstr = cmdline.utf16(); // Windows wants to change this no idea why.
- int ret = CreateProcessW(nullptr, (LPWSTR)(modstr.ptrw()), nullptr, nullptr, 0, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi);
- ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK);
+ int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi);
+ ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command);
- if (p_blocking) {
- DWORD ret2 = WaitForSingleObject(pi.pi.hProcess, INFINITE);
- if (r_exitcode) {
- *r_exitcode = ret2;
- }
-
- CloseHandle(pi.pi.hProcess);
- CloseHandle(pi.pi.hThread);
- } else {
- ProcessID pid = pi.pi.dwProcessId;
- if (r_child_id) {
- *r_child_id = pid;
- }
- process_map->insert(pid, pi);
+ ProcessID pid = pi.pi.dwProcessId;
+ if (r_child_id) {
+ *r_child_id = pid;
}
+ process_map->insert(pid, pi);
+
return OK;
};
@@ -509,7 +517,7 @@ Error OS_Windows::set_cwd(const String &p_cwd) {
String OS_Windows::get_executable_path() const {
WCHAR bufname[4096];
GetModuleFileNameW(nullptr, bufname, 4096);
- String s = String::utf16((const char16_t *)bufname);
+ String s = String::utf16((const char16_t *)bufname).replace("\\", "/");
return s;
}
@@ -549,8 +557,27 @@ String OS_Windows::get_stdin_string(bool p_block) {
}
Error OS_Windows::shell_open(String p_uri) {
- ShellExecuteW(nullptr, nullptr, (LPCWSTR)(p_uri.utf16().get_data()), nullptr, nullptr, SW_SHOWNORMAL);
- return OK;
+ INT_PTR ret = (INT_PTR)ShellExecuteW(nullptr, nullptr, (LPCWSTR)(p_uri.utf16().get_data()), nullptr, nullptr, SW_SHOWNORMAL);
+ if (ret > 32) {
+ return OK;
+ } else {
+ switch (ret) {
+ case ERROR_FILE_NOT_FOUND:
+ case SE_ERR_DLLNOTFOUND:
+ return ERR_FILE_NOT_FOUND;
+ case ERROR_PATH_NOT_FOUND:
+ return ERR_FILE_BAD_PATH;
+ case ERROR_BAD_FORMAT:
+ return ERR_FILE_CORRUPT;
+ case SE_ERR_ACCESSDENIED:
+ return ERR_UNAUTHORIZED;
+ case 0:
+ case SE_ERR_OOM:
+ return ERR_OUT_OF_MEMORY;
+ default:
+ return FAILED;
+ }
+ }
}
String OS_Windows::get_locale() const {
@@ -558,21 +585,21 @@ String OS_Windows::get_locale() const {
LANGID langid = GetUserDefaultUILanguage();
String neutral;
- int lang = langid & ((1 << 9) - 1);
- int sublang = langid & ~((1 << 9) - 1);
+ int lang = PRIMARYLANGID(langid);
+ int sublang = SUBLANGID(langid);
while (wl->locale) {
if (wl->main_lang == lang && wl->sublang == SUBLANG_NEUTRAL)
neutral = wl->locale;
if (lang == wl->main_lang && sublang == wl->sublang)
- return wl->locale;
+ return String(wl->locale).replace("-", "_");
wl++;
}
if (neutral != "")
- return neutral;
+ return String(neutral).replace("-", "_");
return "en";
}
@@ -611,7 +638,7 @@ void OS_Windows::run() {
if (!main_loop)
return;
- main_loop->init();
+ main_loop->initialize();
while (!force_quit) {
DisplayServer::get_singleton()->process_events(); // get rid of pending events
@@ -619,7 +646,7 @@ void OS_Windows::run() {
break;
};
- main_loop->finish();
+ main_loop->finalize();
}
MainLoop *OS_Windows::get_main_loop() const {
@@ -627,31 +654,45 @@ MainLoop *OS_Windows::get_main_loop() const {
}
String OS_Windows::get_config_path() const {
- if (has_environment("XDG_CONFIG_HOME")) { // unlikely, but after all why not?
- return get_environment("XDG_CONFIG_HOME");
- } else if (has_environment("APPDATA")) {
- return get_environment("APPDATA");
- } else {
- return ".";
+ // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
+ if (has_environment("XDG_CONFIG_HOME")) {
+ if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) {
+ return get_environment("XDG_CONFIG_HOME").replace("\\", "/");
+ } else {
+ WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `%APPDATA%` or `.` per the XDG Base Directory specification.");
+ }
}
+ if (has_environment("APPDATA")) {
+ return get_environment("APPDATA").replace("\\", "/");
+ }
+ return ".";
}
String OS_Windows::get_data_path() const {
+ // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
if (has_environment("XDG_DATA_HOME")) {
- return get_environment("XDG_DATA_HOME");
- } else {
- return get_config_path();
+ if (get_environment("XDG_DATA_HOME").is_absolute_path()) {
+ return get_environment("XDG_DATA_HOME").replace("\\", "/");
+ } else {
+ WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `get_config_path()` per the XDG Base Directory specification.");
+ }
}
+ return get_config_path();
}
String OS_Windows::get_cache_path() const {
+ // The XDG Base Directory specification technically only applies on Linux/*BSD, but it doesn't hurt to support it on Windows as well.
if (has_environment("XDG_CACHE_HOME")) {
- return get_environment("XDG_CACHE_HOME");
- } else if (has_environment("TEMP")) {
- return get_environment("TEMP");
- } else {
- return get_config_path();
+ if (get_environment("XDG_CACHE_HOME").is_absolute_path()) {
+ return get_environment("XDG_CACHE_HOME").replace("\\", "/");
+ } else {
+ WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `%TEMP%` or `get_config_path()` per the XDG Base Directory specification.");
+ }
}
+ if (has_environment("TEMP")) {
+ return get_environment("TEMP").replace("\\", "/");
+ }
+ return get_config_path();
}
// Get properly capitalized engine name for system paths
@@ -659,7 +700,7 @@ String OS_Windows::get_godot_dir_name() const {
return String(VERSION_SHORT_NAME).capitalize();
}
-String OS_Windows::get_system_dir(SystemDir p_dir) const {
+String OS_Windows::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
KNOWNFOLDERID id;
switch (p_dir) {
@@ -692,7 +733,7 @@ String OS_Windows::get_system_dir(SystemDir p_dir) const {
PWSTR szPath;
HRESULT res = SHGetKnownFolderPath(id, 0, nullptr, &szPath);
ERR_FAIL_COND_V(res != S_OK, String());
- String path = String::utf16((const char16_t *)szPath);
+ String path = String::utf16((const char16_t *)szPath).replace("\\", "/");
CoTaskMemFree(szPath);
return path;
}
@@ -761,71 +802,11 @@ Error OS_Windows::move_to_trash(const String &p_path) {
return OK;
}
-int OS_Windows::get_tablet_driver_count() const {
- return tablet_drivers.size();
-}
-
-String OS_Windows::get_tablet_driver_name(int p_driver) const {
- if (p_driver < 0 || p_driver >= tablet_drivers.size()) {
- return "";
- } else {
- return tablet_drivers[p_driver];
- }
-}
-
-String OS_Windows::get_current_tablet_driver() const {
- return tablet_driver;
-}
-
-void OS_Windows::set_current_tablet_driver(const String &p_driver) {
- if (get_tablet_driver_count() == 0) {
- return;
- }
- bool found = false;
- for (int i = 0; i < get_tablet_driver_count(); i++) {
- if (p_driver == get_tablet_driver_name(i)) {
- found = true;
- }
- }
- if (found) {
- if (DisplayServerWindows::get_singleton()) {
- ((DisplayServerWindows *)DisplayServerWindows::get_singleton())->_update_tablet_ctx(tablet_driver, p_driver);
- }
- tablet_driver = p_driver;
- } else {
- ERR_PRINT("Unknown tablet driver " + p_driver + ".");
- }
-}
-
OS_Windows::OS_Windows(HINSTANCE _hInstance) {
- //Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink.
- HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll");
- if (wintab_lib) {
- DisplayServerWindows::wintab_WTOpen = (WTOpenPtr)GetProcAddress(wintab_lib, "WTOpenW");
- DisplayServerWindows::wintab_WTClose = (WTClosePtr)GetProcAddress(wintab_lib, "WTClose");
- DisplayServerWindows::wintab_WTInfo = (WTInfoPtr)GetProcAddress(wintab_lib, "WTInfoW");
- DisplayServerWindows::wintab_WTPacket = (WTPacketPtr)GetProcAddress(wintab_lib, "WTPacket");
- DisplayServerWindows::wintab_WTEnable = (WTEnablePtr)GetProcAddress(wintab_lib, "WTEnable");
-
- DisplayServerWindows::wintab_available = DisplayServerWindows::wintab_WTOpen && DisplayServerWindows::wintab_WTClose && DisplayServerWindows::wintab_WTInfo && DisplayServerWindows::wintab_WTPacket && DisplayServerWindows::wintab_WTEnable;
- }
-
- if (DisplayServerWindows::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) {
- DisplayServerWindows::win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType");
- DisplayServerWindows::win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo");
-
- DisplayServerWindows::winink_available = DisplayServerWindows::win8p_GetPointerType && DisplayServerWindows::win8p_GetPointerPenInfo;
- }
-
- if (DisplayServerWindows::winink_available) {
- tablet_drivers.push_back("winink");
- }
+ ticks_per_second = 0;
+ ticks_start = 0;
+ main_loop = nullptr;
+ process_map = nullptr;
force_quit = false;
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 910a83539a..c4a2eda8f4 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -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 */
@@ -31,16 +31,16 @@
#ifndef OS_WINDOWS_H
#define OS_WINDOWS_H
+#include "core/config/project_settings.h"
#include "core/input/input.h"
#include "core/os/os.h"
-#include "core/project_settings.h"
#include "crash_handler_windows.h"
#include "drivers/unix/ip_unix.h"
#include "drivers/wasapi/audio_driver_wasapi.h"
#include "drivers/winmidi/midi_driver_winmidi.h"
#include "key_mapping_windows.h"
#include "servers/audio_server.h"
-#include "servers/rendering/rasterizer.h"
+#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering_server.h"
#ifdef XAUDIO2_ENABLED
#include "drivers/xaudio2/audio_driver_xaudio2.h"
@@ -73,9 +73,6 @@ class OS_Windows : public OS {
HINSTANCE hInstance;
MainLoop *main_loop;
- String tablet_driver;
- Vector<String> tablet_drivers;
-
#ifdef WASAPI_ENABLED
AudioDriverWASAPI driver_wasapi;
#endif
@@ -93,14 +90,14 @@ class OS_Windows : public OS {
// functions used by main to initialize/deinitialize the OS
protected:
- virtual void initialize();
+ virtual void initialize() override;
- virtual void set_main_loop(MainLoop *p_main_loop);
- virtual void delete_main_loop();
+ virtual void set_main_loop(MainLoop *p_main_loop) override;
+ virtual void delete_main_loop() override;
- virtual void finalize();
- virtual void finalize_core();
- virtual String get_stdin_string(bool p_block);
+ virtual void finalize() override;
+ virtual void finalize_core() override;
+ virtual String get_stdin_string(bool p_block) override;
String _quote_command_line_argument(const String &p_text) const;
@@ -111,66 +108,64 @@ protected:
Map<ProcessID, ProcessInfo> *process_map;
public:
- virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false);
- virtual Error close_dynamic_library(void *p_library_handle);
- virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false);
+ virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
- virtual MainLoop *get_main_loop() const;
+ virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
+ virtual Error close_dynamic_library(void *p_library_handle) override;
+ virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
- virtual String get_name() const;
+ virtual MainLoop *get_main_loop() const override;
- virtual int get_tablet_driver_count() const;
- virtual String get_tablet_driver_name(int p_driver) const;
- virtual String get_current_tablet_driver() const;
- virtual void set_current_tablet_driver(const String &p_driver);
+ virtual String get_name() const override;
- virtual void initialize_joypads() {}
+ virtual void initialize_joypads() override {}
- virtual Date get_date(bool utc) const;
- virtual Time get_time(bool utc) const;
- virtual TimeZoneInfo get_time_zone_info() const;
- virtual double get_unix_time() const;
+ virtual Date get_date(bool utc) const override;
+ virtual Time get_time(bool utc) const override;
+ virtual TimeZoneInfo get_time_zone_info() const override;
+ virtual double get_unix_time() const override;
- virtual Error set_cwd(const String &p_cwd);
+ virtual Error set_cwd(const String &p_cwd) override;
- virtual void delay_usec(uint32_t p_usec) const;
- virtual uint64_t get_ticks_usec() const;
+ virtual void delay_usec(uint32_t p_usec) const override;
+ virtual uint64_t get_ticks_usec() const override;
- virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr);
- virtual Error kill(const ProcessID &p_pid);
- virtual int get_process_id() const;
+ virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr) override;
+ virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
+ virtual Error kill(const ProcessID &p_pid) override;
+ virtual int get_process_id() const override;
- virtual bool has_environment(const String &p_var) const;
- virtual String get_environment(const String &p_var) const;
- virtual bool set_environment(const String &p_var, const String &p_value) const;
+ virtual bool has_environment(const String &p_var) const override;
+ virtual String get_environment(const String &p_var) const override;
+ virtual bool set_environment(const String &p_var, const String &p_value) const override;
- virtual String get_executable_path() const;
+ virtual String get_executable_path() const override;
- virtual String get_locale() const;
+ virtual String get_locale() const override;
- virtual int get_processor_count() const;
+ virtual int get_processor_count() const override;
- virtual String get_config_path() const;
- virtual String get_data_path() const;
- virtual String get_cache_path() const;
- virtual String get_godot_dir_name() const;
+ virtual String get_config_path() const override;
+ virtual String get_data_path() const override;
+ virtual String get_cache_path() const override;
+ virtual String get_godot_dir_name() const override;
- virtual String get_system_dir(SystemDir p_dir) const;
- virtual String get_user_data_dir() const;
+ virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const override;
+ virtual String get_user_data_dir() const override;
- virtual String get_unique_id() const;
+ virtual String get_unique_id() const override;
- virtual Error shell_open(String p_uri);
+ virtual Error shell_open(String p_uri) override;
void run();
- virtual bool _check_internal_feature_support(const String &p_feature);
+ virtual bool _check_internal_feature_support(const String &p_feature) override;
- void disable_crash_handler();
- bool is_disable_crash_handler() const;
- virtual void initialize_debugging();
+ virtual void disable_crash_handler() override;
+ virtual bool is_disable_crash_handler() const override;
+ virtual void initialize_debugging() override;
- virtual Error move_to_trash(const String &p_path);
+ virtual Error move_to_trash(const String &p_path) override;
void set_main_window(HWND p_main_window) { main_window = p_main_window; }
diff --git a/platform/windows/platform_config.h b/platform/windows/platform_config.h
index 09a16614e0..481f583f6f 100644
--- a/platform/windows/platform_config.h
+++ b/platform/windows/platform_config.h
@@ -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 */
diff --git a/platform/windows/vulkan_context_win.cpp b/platform/windows/vulkan_context_win.cpp
index 2c63281c49..db5e6466be 100644
--- a/platform/windows/vulkan_context_win.cpp
+++ b/platform/windows/vulkan_context_win.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 */
@@ -29,24 +29,27 @@
/*************************************************************************/
#include "vulkan_context_win.h"
-#include <vulkan/vulkan_win32.h>
+#ifdef USE_VOLK
+#include <volk.h>
+#else
+#include <vulkan/vulkan.h>
+#endif
const char *VulkanContextWindows::_get_platform_surface_extension() const {
return VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
}
-int VulkanContextWindows::window_create(DisplayServer::WindowID p_window_id, HWND p_window, HINSTANCE p_instance, int p_width, int p_height) {
+int VulkanContextWindows::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, HWND p_window, HINSTANCE p_instance, int p_width, int p_height) {
VkWin32SurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.hinstance = p_instance;
createInfo.hwnd = p_window;
-
VkSurfaceKHR surface;
- VkResult err = vkCreateWin32SurfaceKHR(_get_instance(), &createInfo, nullptr, &surface);
+ VkResult err = vkCreateWin32SurfaceKHR(get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, -1);
- return _window_create(p_window_id, surface, p_width, p_height);
+ return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
}
VulkanContextWindows::VulkanContextWindows() {
diff --git a/platform/windows/vulkan_context_win.h b/platform/windows/vulkan_context_win.h
index 6e80db0286..39dd2641fd 100644
--- a/platform/windows/vulkan_context_win.h
+++ b/platform/windows/vulkan_context_win.h
@@ -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,7 @@ class VulkanContextWindows : public VulkanContext {
virtual const char *_get_platform_surface_extension() const;
public:
- int window_create(DisplayServer::WindowID p_window_id, HWND p_window, HINSTANCE p_instance, int p_width, int p_height);
+ int window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, HWND p_window, HINSTANCE p_instance, int p_width, int p_height);
VulkanContextWindows();
~VulkanContextWindows();
diff --git a/platform/windows/windows_terminal_logger.cpp b/platform/windows/windows_terminal_logger.cpp
index 0938b65b04..8cab7ca521 100644
--- a/platform/windows/windows_terminal_logger.cpp
+++ b/platform/windows/windows_terminal_logger.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 */
@@ -53,7 +53,8 @@ void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_er
if (wlen < 0)
return;
- wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
+ wchar_t *wbuf = (wchar_t *)memalloc((len + 1) * sizeof(wchar_t));
+ ERR_FAIL_NULL_MSG(wbuf, "Out of memory.");
MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
wbuf[wlen] = 0;
@@ -62,7 +63,7 @@ void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_er
else
wprintf(L"%ls", wbuf);
- free(wbuf);
+ memfree(wbuf);
#ifdef DEBUG_ENABLED
fflush(stdout);
@@ -107,47 +108,47 @@ void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file
SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
switch (p_type) {
case ERR_ERROR:
- logf("ERROR:");
+ logf_error("ERROR:");
break;
case ERR_WARNING:
- logf("WARNING:");
+ logf_error("WARNING:");
break;
case ERR_SCRIPT:
- logf("SCRIPT ERROR:");
+ logf_error("SCRIPT ERROR:");
break;
case ERR_SHADER:
- logf("SHADER ERROR:");
+ logf_error("SHADER ERROR:");
break;
}
SetConsoleTextAttribute(hCon, basecol);
if (p_rationale && p_rationale[0]) {
- logf(" %s\n", p_rationale);
+ logf_error(" %s\n", p_rationale);
} else {
- logf(" %s\n", p_code);
+ logf_error(" %s\n", p_code);
}
// `FOREGROUND_INTENSITY` alone results in gray text.
SetConsoleTextAttribute(hCon, FOREGROUND_INTENSITY);
switch (p_type) {
case ERR_ERROR:
- logf(" at: ");
+ logf_error(" at: ");
break;
case ERR_WARNING:
- logf(" at: ");
+ logf_error(" at: ");
break;
case ERR_SCRIPT:
- logf(" at: ");
+ logf_error(" at: ");
break;
case ERR_SHADER:
- logf(" at: ");
+ logf_error(" at: ");
break;
}
if (p_rationale && p_rationale[0]) {
- logf("(%s:%i)\n", p_file, p_line);
+ logf_error("(%s:%i)\n", p_file, p_line);
} else {
- logf("%s (%s:%i)\n", p_function, p_file, p_line);
+ logf_error("%s (%s:%i)\n", p_function, p_file, p_line);
}
SetConsoleTextAttribute(hCon, sbi.wAttributes);
diff --git a/platform/windows/windows_terminal_logger.h b/platform/windows/windows_terminal_logger.h
index d4443a707d..aacfe5869e 100644
--- a/platform/windows/windows_terminal_logger.h
+++ b/platform/windows/windows_terminal_logger.h
@@ -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 */