summaryrefslogtreecommitdiff
path: root/platform/windows
diff options
context:
space:
mode:
Diffstat (limited to 'platform/windows')
-rw-r--r--platform/windows/SCsub1
-rw-r--r--platform/windows/camera_win.cpp94
-rw-r--r--platform/windows/camera_win.h46
-rw-r--r--platform/windows/context_gl_windows.h21
-rw-r--r--platform/windows/crash_handler_windows.cpp9
-rw-r--r--platform/windows/detect.py28
-rw-r--r--platform/windows/export/export.cpp4
-rw-r--r--platform/windows/godot_res.rc2
-rw-r--r--platform/windows/joypad_windows.cpp18
-rw-r--r--platform/windows/os_windows.cpp261
-rw-r--r--platform/windows/os_windows.h35
-rw-r--r--platform/windows/power_windows.cpp2
-rw-r--r--platform/windows/windows_terminal_logger.cpp4
13 files changed, 446 insertions, 79 deletions
diff --git a/platform/windows/SCsub b/platform/windows/SCsub
index 892d734734..8426ccbb89 100644
--- a/platform/windows/SCsub
+++ b/platform/windows/SCsub
@@ -8,6 +8,7 @@ import platform_windows_builders
common_win = [
"godot_windows.cpp",
+ "camera_win.cpp",
"context_gl_windows.cpp",
"crash_handler_windows.cpp",
"os_windows.cpp",
diff --git a/platform/windows/camera_win.cpp b/platform/windows/camera_win.cpp
new file mode 100644
index 0000000000..b97796fe89
--- /dev/null
+++ b/platform/windows/camera_win.cpp
@@ -0,0 +1,94 @@
+/*************************************************************************/
+/* camera_win.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 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 "camera_win.h"
+
+///@TODO sorry guys, I got about 80% through implementing this using DirectShow only to find out Microsoft deprecated half the API and its replacement is as confusing as they could make it
+// Joey suggested looking into libuvc which offers a more direct route to webcams over USB and this is very promissing but it wouldn't compile on windows for me...
+// I've gutted the classes I implemented DirectShow in just to have a skeleton for someone to work on, mail me for more details or if you want a copy....
+
+//////////////////////////////////////////////////////////////////////////
+// CameraFeedWindows - Subclass for our camera feed on windows
+
+/// @TODO need to implement this
+
+class CameraFeedWindows : public CameraFeed {
+private:
+protected:
+public:
+ CameraFeedWindows();
+ virtual ~CameraFeedWindows();
+
+ bool activate_feed();
+ void deactivate_feed();
+};
+
+CameraFeedWindows::CameraFeedWindows(){
+ ///@TODO implement this, should store information about our available camera
+};
+
+CameraFeedWindows::~CameraFeedWindows() {
+ // make sure we stop recording if we are!
+ if (is_active()) {
+ deactivate_feed();
+ };
+
+ ///@TODO free up anything used by this
+};
+
+bool CameraFeedWindows::activate_feed() {
+ ///@TODO this should activate our camera and start the process of capturing frames
+
+ return true;
+};
+
+///@TODO we should probably have a callback method here that is being called by the camera API which provides frames and call back into the CameraServer to update our texture
+
+void CameraFeedWindows::deactivate_feed(){
+ ///@TODO this should deactivate our camera and stop the process of capturing frames
+};
+
+//////////////////////////////////////////////////////////////////////////
+// CameraWindows - Subclass for our camera server on windows
+
+void CameraWindows::add_active_cameras(){
+ ///@TODO scan through any active cameras and create CameraFeedWindows objects for them
+};
+
+CameraWindows::CameraWindows() {
+ // Find cameras active right now
+ add_active_cameras();
+
+ // need to add something that will react to devices being connected/removed...
+};
+
+CameraWindows::~CameraWindows(){
+
+};
diff --git a/platform/windows/camera_win.h b/platform/windows/camera_win.h
new file mode 100644
index 0000000000..22ce9aa43f
--- /dev/null
+++ b/platform/windows/camera_win.h
@@ -0,0 +1,46 @@
+/*************************************************************************/
+/* camera_win.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 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 CAMERAWIN_H
+#define CAMERAWIN_H
+
+#include "servers/camera/camera_feed.h"
+#include "servers/camera_server.h"
+
+class CameraWindows : public CameraServer {
+private:
+ void add_active_cameras();
+
+public:
+ CameraWindows();
+ ~CameraWindows();
+};
+
+#endif /* CAMERAWIN_H */
diff --git a/platform/windows/context_gl_windows.h b/platform/windows/context_gl_windows.h
index 09801b9146..d23fba50e1 100644
--- a/platform/windows/context_gl_windows.h
+++ b/platform/windows/context_gl_windows.h
@@ -37,13 +37,12 @@
#include "core/error_list.h"
#include "core/os/os.h"
-#include "drivers/gl_context/context_gl.h"
#include <windows.h>
typedef bool(APIENTRY *PFNWGLSWAPINTERVALEXTPROC)(int interval);
-class ContextGL_Windows : public ContextGL {
+class ContextGL_Windows {
HDC hDC;
HGLRC hRC;
@@ -55,21 +54,21 @@ class ContextGL_Windows : public ContextGL {
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
public:
- virtual void release_current();
+ void release_current();
- virtual void make_current();
+ void make_current();
- virtual int get_window_width();
- virtual int get_window_height();
- virtual void swap_buffers();
+ int get_window_width();
+ int get_window_height();
+ void swap_buffers();
- virtual Error initialize();
+ Error initialize();
- virtual void set_use_vsync(bool p_use);
- virtual bool is_using_vsync() const;
+ void set_use_vsync(bool p_use);
+ bool is_using_vsync() const;
ContextGL_Windows(HWND hwnd, bool p_opengl_3_context);
- virtual ~ContextGL_Windows();
+ ~ContextGL_Windows();
};
#endif
diff --git a/platform/windows/crash_handler_windows.cpp b/platform/windows/crash_handler_windows.cpp
index 4006c4c60e..0716ee67f4 100644
--- a/platform/windows/crash_handler_windows.cpp
+++ b/platform/windows/crash_handler_windows.cpp
@@ -166,11 +166,16 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) {
line.SizeOfStruct = sizeof(line);
IMAGE_NT_HEADERS *h = ImageNtHeader(base);
DWORD image_type = h->FileHeader.Machine;
- int n = 0;
- String msg = GLOBAL_GET("debug/settings/crash_handler/message");
+
+ String msg;
+ const ProjectSettings *proj_settings = ProjectSettings::get_singleton();
+ if (proj_settings) {
+ msg = proj_settings->get("debug/settings/crash_handler/message");
+ }
fprintf(stderr, "Dumping the backtrace. %ls\n", msg.c_str());
+ int n = 0;
do {
if (skip_first) {
skip_first = false;
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 426a5e9e61..4b4b507499 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -1,6 +1,5 @@
import methods
import os
-import sys
def is_active():
@@ -197,10 +196,12 @@ def configure_msvc(env, manual_msvc_config):
## Compile/link flags
env.AppendUnique(CCFLAGS=['/MT', '/Gd', '/GR', '/nologo'])
+ if int(env['MSVC_VERSION'].split('.')[0]) >= 14: #vs2015 and later
+ env.AppendUnique(CCFLAGS=['/utf-8'])
env.AppendUnique(CXXFLAGS=['/TP']) # assume all sources are C++
if manual_msvc_config: # should be automatic if SCons found it
if os.getenv("WindowsSdkDir") is not None:
- env.Append(CPPPATH=[os.getenv("WindowsSdkDir") + "/Include"])
+ env.Prepend(CPPPATH=[os.getenv("WindowsSdkDir") + "/Include"])
else:
print("Missing environment variable: WindowsSdkDir")
@@ -238,7 +239,7 @@ def configure_msvc(env, manual_msvc_config):
env.AppendUnique(LINKFLAGS=['/LTCG'])
if manual_msvc_config:
- env.Append(CPPPATH=[p for p in os.getenv("INCLUDE").split(";")])
+ env.Prepend(CPPPATH=[p for p in os.getenv("INCLUDE").split(";")])
env.Append(LIBPATH=[p for p in os.getenv("LIB").split(";")])
# Incremental linking fix
@@ -272,7 +273,8 @@ def configure_mingw(env):
env.Prepend(CCFLAGS=['-g2'])
elif (env["target"] == "release_debug"):
- env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
+ env.Append(CCFLAGS=['-O2'])
+ env.Append(CPPFLAGS=['-DDEBUG_ENABLED'])
if (env["debug_symbols"] == "yes"):
env.Prepend(CCFLAGS=['-g1'])
if (env["debug_symbols"] == "full"):
@@ -283,7 +285,8 @@ def configure_mingw(env):
env.Prepend(CCFLAGS=['-Os'])
elif (env["target"] == "debug"):
- env.Append(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ env.Append(CCFLAGS=['-g3'])
+ env.Append(CPPFLAGS=['-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
## Compiler configuration
@@ -324,12 +327,13 @@ def configure_mingw(env):
## Compile flags
- env.Append(CCFLAGS=['-DWINDOWS_ENABLED', '-mwindows'])
- env.Append(CCFLAGS=['-DOPENGL_ENABLED'])
- env.Append(CCFLAGS=['-DWASAPI_ENABLED'])
- env.Append(CCFLAGS=['-DWINMIDI_ENABLED'])
- env.Append(CCFLAGS=['-DWINVER=%s' % env['target_win_version'], '-D_WIN32_WINNT=%s' % env['target_win_version']])
- env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser', 'imm32', 'bcrypt','avrt'])
+ env.Append(CCFLAGS=['-mwindows'])
+ env.Append(CPPFLAGS=['-DWINDOWS_ENABLED'])
+ env.Append(CPPFLAGS=['-DOPENGL_ENABLED'])
+ env.Append(CPPFLAGS=['-DWASAPI_ENABLED'])
+ env.Append(CPPFLAGS=['-DWINMIDI_ENABLED'])
+ env.Append(CPPFLAGS=['-DWINVER=%s' % env['target_win_version'], '-D_WIN32_WINNT=%s' % env['target_win_version']])
+ env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser', 'imm32', 'bcrypt', 'avrt', 'uuid'])
env.Append(CPPFLAGS=['-DMINGW_ENABLED'])
@@ -338,7 +342,7 @@ def configure_mingw(env):
def configure(env):
# At this point the env has been set up with basic tools/compilers.
- env.Append(CPPPATH=['#platform/windows'])
+ env.Prepend(CPPPATH=['#platform/windows'])
print("Configuring for Windows: target=%s, bits=%s" % (env['target'], env['bits']))
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp
index 141ab96370..4a72d07adc 100644
--- a/platform/windows/export/export.cpp
+++ b/platform/windows/export/export.cpp
@@ -138,8 +138,8 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio
EditorExportPlatformPC::get_export_options(r_options);
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"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version"), ""));
+ 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"), ""));
diff --git a/platform/windows/godot_res.rc b/platform/windows/godot_res.rc
index f2dca10d55..1fa8957f15 100644
--- a/platform/windows/godot_res.rc
+++ b/platform/windows/godot_res.rc
@@ -21,7 +21,7 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Godot Engine"
- VALUE "FileDescription", VERSION_NAME " Editor"
+ VALUE "FileDescription", VERSION_NAME
VALUE "FileVersion", VERSION_NUMBER
VALUE "ProductName", VERSION_NAME
VALUE "Licence", "MIT"
diff --git a/platform/windows/joypad_windows.cpp b/platform/windows/joypad_windows.cpp
index 5a399cdf90..53ce342e8c 100644
--- a/platform/windows/joypad_windows.cpp
+++ b/platform/windows/joypad_windows.cpp
@@ -103,17 +103,17 @@ bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
PRAWINPUTDEVICELIST dev_list = NULL;
unsigned int dev_list_count = 0;
- if (GetRawInputDeviceList(NULL, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == -1) {
+ if (GetRawInputDeviceList(NULL, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
return false;
}
dev_list = (PRAWINPUTDEVICELIST)malloc(sizeof(RAWINPUTDEVICELIST) * dev_list_count);
if (!dev_list) return false;
- if (GetRawInputDeviceList(dev_list, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == -1) {
+ if (GetRawInputDeviceList(dev_list, &dev_list_count, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
free(dev_list);
return false;
}
- for (int i = 0; i < dev_list_count; i++) {
+ for (unsigned int i = 0; i < dev_list_count; i++) {
RID_DEVICE_INFO rdi;
char dev_name[128];
@@ -334,9 +334,9 @@ void JoypadWindows::process_joypads() {
if (joy.state.dwPacketNumber != joy.last_packet) {
int button_mask = XINPUT_GAMEPAD_DPAD_UP;
- for (int i = 0; i <= 16; i++) {
+ for (int j = 0; j <= 16; j++) {
- input->joy_button(joy.id, i, joy.state.Gamepad.wButtons & button_mask);
+ input->joy_button(joy.id, j, joy.state.Gamepad.wButtons & button_mask);
button_mask = button_mask * 2;
}
@@ -406,7 +406,7 @@ void JoypadWindows::process_joypads() {
// on mingw, these constants are not constants
int count = 6;
- int axes[] = { DIJOFS_X, DIJOFS_Y, DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ };
+ unsigned int axes[] = { DIJOFS_X, DIJOFS_Y, DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ };
int values[] = { js.lX, js.lY, js.lZ, js.lRx, js.lRy, js.lRz };
for (int j = 0; j < joy->joy_axis.size(); j++) {
@@ -426,7 +426,11 @@ void JoypadWindows::post_hat(int p_device, DWORD p_dpad) {
int dpad_val = 0;
- if (p_dpad == -1) {
+ // 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 = InputDefault::HAT_MASK_CENTER;
}
if (p_dpad == 0) {
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 6125455e74..6e6df08f02 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -53,6 +53,7 @@
#include <avrt.h>
#include <direct.h>
+#include <knownfolders.h>
#include <process.h>
#include <regstr.h>
#include <shlobj.h>
@@ -93,6 +94,7 @@ static BOOL CALLBACK _MonitorEnumProcSize(HMONITOR hMonitor, HDC hdcMonitor, LPR
return TRUE;
}
+#ifdef DEBUG_ENABLED
static String format_error_message(DWORD id) {
LPWSTR messageBuffer = NULL;
@@ -105,6 +107,7 @@ static String format_error_message(DWORD id) {
return msg;
}
+#endif // DEBUG_ENABLED
extern HINSTANCE godot_hinstance;
@@ -345,13 +348,30 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
control_mem = false;
shift_mem = false;
} else { // WM_INACTIVE
+ input->release_pressed_events();
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
alt_mem = false;
};
return 0; // Return To The Message Loop
}
-
+ case WM_GETMINMAXINFO: {
+ if (video_mode.resizable && !video_mode.fullscreen) {
+ Size2 decor = get_real_window_size() - get_window_size(); // Size of window decorations
+ MINMAXINFO *min_max_info = (MINMAXINFO *)lParam;
+ if (min_size != Size2()) {
+ min_max_info->ptMinTrackSize.x = min_size.x + decor.x;
+ min_max_info->ptMinTrackSize.y = min_size.y + decor.y;
+ }
+ if (max_size != Size2()) {
+ min_max_info->ptMaxTrackSize.x = max_size.x + decor.x;
+ min_max_info->ptMaxTrackSize.y = max_size.y + decor.y;
+ }
+ return 0;
+ } else {
+ break;
+ }
+ }
case WM_PAINT:
Main::force_redraw();
@@ -384,8 +404,6 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
outside = true;
if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
- if (input)
- input->set_mouse_in_window(false);
} break;
case WM_INPUT: {
@@ -480,8 +498,6 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
- if (input)
- input->set_mouse_in_window(true);
CursorShape c = cursor_shape;
cursor_shape = CURSOR_MAX;
@@ -557,6 +573,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
break;
}
}
+ FALLTHROUGH;
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_RBUTTONDOWN:
@@ -585,7 +602,6 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_MBUTTONDOWN: {
mb->set_pressed(true);
mb->set_button_index(3);
-
} break;
case WM_MBUTTONUP: {
mb->set_pressed(false);
@@ -600,19 +616,16 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
mb->set_button_index(2);
} break;
case WM_LBUTTONDBLCLK: {
-
mb->set_pressed(true);
mb->set_button_index(1);
mb->set_doubleclick(true);
} break;
case WM_RBUTTONDBLCLK: {
-
mb->set_pressed(true);
mb->set_button_index(2);
mb->set_doubleclick(true);
} break;
case WM_MBUTTONDBLCLK: {
-
mb->set_pressed(true);
mb->set_button_index(3);
mb->set_doubleclick(true);
@@ -670,7 +683,9 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
mb->set_button_index(BUTTON_XBUTTON2);
mb->set_doubleclick(true);
} break;
- default: { return 0; }
+ default: {
+ return 0;
+ }
}
mb->set_control((wParam & MK_CONTROL) != 0);
@@ -705,7 +720,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
}
} else if (mouse_mode != MOUSE_MODE_CAPTURED) {
- // for reasons unknown to mankind, wheel comes in screen cordinates
+ // for reasons unknown to mankind, wheel comes in screen coordinates
POINT coords;
coords.x = mb->get_position().x;
coords.y = mb->get_position().y;
@@ -787,6 +802,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
} break;
case WM_ENTERSIZEMOVE: {
+ input->release_pressed_events();
move_timer_id = SetTimer(hWnd, 1, USER_TIMER_MINIMUM, (TIMERPROC)NULL);
} break;
case WM_EXITSIZEMOVE: {
@@ -1357,6 +1373,8 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
power_manager = memnew(PowerWindows);
+ camera_server = memnew(CameraWindows);
+
AudioDriverManager::initialize(p_audio_driver);
TRACKMOUSEEVENT tme;
@@ -1380,7 +1398,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
SetFocus(hWnd); // Sets Keyboard Focus To
}
- if (p_desired.layered_splash) {
+ if (p_desired.layered) {
set_window_per_pixel_transparency_enabled(true);
}
@@ -1412,26 +1430,29 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
void OS_Windows::set_clipboard(const String &p_text) {
+ // Convert LF line endings to CRLF in clipboard content
+ // Otherwise, line endings won't be visible when pasted in other software
+ String text = p_text.replace("\n", "\r\n");
+
if (!OpenClipboard(hWnd)) {
ERR_EXPLAIN("Unable to open clipboard.");
ERR_FAIL();
};
EmptyClipboard();
- HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (p_text.length() + 1) * sizeof(CharType));
+ HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) * sizeof(CharType));
if (mem == NULL) {
ERR_EXPLAIN("Unable to allocate memory for clipboard contents.");
ERR_FAIL();
};
LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem);
- memcpy(lptstrCopy, p_text.c_str(), (p_text.length() + 1) * sizeof(CharType));
- //memset((lptstrCopy + p_text.length()), 0, sizeof(CharType));
+ memcpy(lptstrCopy, text.c_str(), (text.length() + 1) * sizeof(CharType));
GlobalUnlock(mem);
SetClipboardData(CF_UNICODETEXT, mem);
// set the CF_TEXT version (not needed?)
- CharString utf8 = p_text.utf8();
+ CharString utf8 = text.utf8();
mem = GlobalAlloc(GMEM_MOVEABLE, utf8.length() + 1);
if (mem == NULL) {
ERR_EXPLAIN("Unable to allocate memory for clipboard contents.");
@@ -1513,6 +1534,7 @@ void OS_Windows::finalize() {
memdelete(joypad);
memdelete(input);
+ memdelete(camera_server);
touch_state.clear();
visual_server->finish();
@@ -1765,6 +1787,7 @@ void OS_Windows::set_window_position(const Point2 &p_position) {
last_pos = p_position;
update_real_mouse_position();
}
+
Size2 OS_Windows::get_window_size() const {
if (minimized) {
@@ -1777,6 +1800,33 @@ Size2 OS_Windows::get_window_size() const {
}
return Size2();
}
+
+Size2 OS_Windows::get_max_window_size() const {
+ return max_size;
+}
+
+Size2 OS_Windows::get_min_window_size() const {
+ return min_size;
+}
+
+void OS_Windows::set_min_window_size(const Size2 p_size) {
+
+ if ((p_size != Size2()) && (max_size != Size2()) && ((p_size.x > max_size.x) || (p_size.y > max_size.y))) {
+ WARN_PRINT("Minimum window size can't be larger than maximum window size!");
+ return;
+ }
+ min_size = p_size;
+}
+
+void OS_Windows::set_max_window_size(const Size2 p_size) {
+
+ if ((p_size != Size2()) && ((p_size.x < min_size.x) || (p_size.y < min_size.y))) {
+ WARN_PRINT("Maximum window size can't be smaller than minimum window size!");
+ return;
+ }
+ max_size = p_size;
+}
+
Size2 OS_Windows::get_real_window_size() const {
RECT r;
@@ -1785,6 +1835,7 @@ Size2 OS_Windows::get_real_window_size() const {
}
return Size2();
}
+
void OS_Windows::set_window_size(const Size2 p_size) {
int w = p_size.width;
@@ -1812,11 +1863,11 @@ void OS_Windows::set_window_size(const Size2 p_size) {
// Don't let the mouse leave the window when resizing to a smaller resolution
if (mouse_mode == MOUSE_MODE_CONFINED) {
- RECT rect;
- GetClientRect(hWnd, &rect);
- ClientToScreen(hWnd, (POINT *)&rect.left);
- ClientToScreen(hWnd, (POINT *)&rect.right);
- ClipCursor(&rect);
+ RECT crect;
+ GetClientRect(hWnd, &crect);
+ ClientToScreen(hWnd, (POINT *)&crect.left);
+ ClientToScreen(hWnd, (POINT *)&crect.right);
+ ClipCursor(&crect);
}
}
void OS_Windows::set_window_fullscreen(bool p_enabled) {
@@ -2115,7 +2166,7 @@ void OS_Windows::request_attention() {
FlashWindowEx(&info);
}
-String OS_Windows::get_name() {
+String OS_Windows::get_name() const {
return "Windows";
}
@@ -2189,6 +2240,8 @@ uint64_t OS_Windows::get_unix_time() const {
FILETIME fep;
SystemTimeToFileTime(&ep, &fep);
+ // FIXME: dereferencing type-punned pointer will break strict-aliasing rules (GCC warning)
+ // https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ns-minwinbase-filetime#remarks
return (*(uint64_t *)&ft - *(uint64_t *)&fep) / 10000000;
};
@@ -2297,6 +2350,11 @@ void OS_Windows::set_cursor_shape(CursorShape p_shape) {
cursor_shape = p_shape;
}
+OS::CursorShape OS_Windows::get_cursor_shape() const {
+
+ return cursor_shape;
+}
+
void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
if (p_cursor.is_valid()) {
Ref<Texture> texture = p_cursor;
@@ -2369,7 +2427,7 @@ void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shap
}
// Finally, create the icon
- ICONINFO iconinfo = { 0 };
+ ICONINFO iconinfo;
iconinfo.fIcon = FALSE;
iconinfo.xHotspot = p_hotspot.x;
iconinfo.yHotspot = p_hotspot.y;
@@ -2457,7 +2515,7 @@ void OS_Windows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent,
DeleteDC(hMainDC);
}
-Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
+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) {
@@ -2466,7 +2524,13 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
- argss += String(" \"") + E->get() + "\"";
+ argss += " \"" + E->get() + "\"";
+ }
+
+ argss += "\"";
+
+ if (read_stderr) {
+ argss += " 2>&1"; // Read stderr too
}
FILE *f = _wpopen(argss.c_str(), L"r");
@@ -2476,7 +2540,13 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
char buf[65535];
while (fgets(buf, 65535, f)) {
+ if (p_pipe_mutex) {
+ p_pipe_mutex->lock();
+ }
(*r_pipe) += buf;
+ if (p_pipe_mutex) {
+ p_pipe_mutex->unlock();
+ }
}
int rv = _pclose(f);
@@ -2510,9 +2580,9 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
if (p_blocking) {
- DWORD ret = WaitForSingleObject(pi.pi.hProcess, INFINITE);
+ DWORD ret2 = WaitForSingleObject(pi.pi.hProcess, INFINITE);
if (r_exitcode)
- *r_exitcode = ret;
+ *r_exitcode = ret2;
CloseHandle(pi.pi.hProcess);
CloseHandle(pi.pi.hThread);
@@ -2562,6 +2632,117 @@ String OS_Windows::get_executable_path() const {
return s;
}
+void OS_Windows::set_native_icon(const String &p_filename) {
+
+ FileAccess *f = FileAccess::open(p_filename, FileAccess::READ);
+ ERR_FAIL_COND(!f);
+
+ ICONDIR *icon_dir = (ICONDIR *)memalloc(sizeof(ICONDIR));
+ int pos = 0;
+
+ icon_dir->idReserved = f->get_32();
+ pos += sizeof(WORD);
+ f->seek(pos);
+
+ icon_dir->idType = f->get_32();
+ pos += sizeof(WORD);
+ f->seek(pos);
+
+ if (icon_dir->idType != 1) {
+ ERR_EXPLAIN("Invalid icon file format!");
+ ERR_FAIL();
+ }
+
+ icon_dir->idCount = f->get_32();
+ pos += sizeof(WORD);
+ f->seek(pos);
+
+ icon_dir = (ICONDIR *)memrealloc(icon_dir, 3 * sizeof(WORD) + icon_dir->idCount * sizeof(ICONDIRENTRY));
+ f->get_buffer((uint8_t *)&icon_dir->idEntries[0], icon_dir->idCount * sizeof(ICONDIRENTRY));
+
+ int small_icon_index = -1; // Select 16x16 with largest color count
+ int small_icon_cc = 0;
+ int big_icon_index = -1; // Select largest
+ int big_icon_width = 16;
+ int big_icon_cc = 0;
+
+ for (int i = 0; i < icon_dir->idCount; i++) {
+ int colors = (icon_dir->idEntries[i].bColorCount == 0) ? 32768 : icon_dir->idEntries[i].bColorCount;
+ int width = (icon_dir->idEntries[i].bWidth == 0) ? 256 : icon_dir->idEntries[i].bWidth;
+ if (width == 16) {
+ if (colors >= small_icon_cc) {
+ small_icon_index = i;
+ small_icon_cc = colors;
+ }
+ }
+ if (width >= big_icon_width) {
+ if (colors >= big_icon_cc) {
+ big_icon_index = i;
+ big_icon_width = width;
+ big_icon_cc = colors;
+ }
+ }
+ }
+
+ if (big_icon_index == -1) {
+ ERR_EXPLAIN("No valid icons found!");
+ ERR_FAIL();
+ }
+
+ if (small_icon_index == -1) {
+ WARN_PRINTS("No small icon found, reusing " + itos(big_icon_width) + "x" + itos(big_icon_width) + " @" + itos(big_icon_cc) + " icon!");
+ small_icon_index = big_icon_index;
+ small_icon_cc = big_icon_cc;
+ }
+
+ // Read the big icon
+ DWORD bytecount_big = icon_dir->idEntries[big_icon_index].dwBytesInRes;
+ Vector<uint8_t> data_big;
+ data_big.resize(bytecount_big);
+ pos = icon_dir->idEntries[big_icon_index].dwImageOffset;
+ f->seek(pos);
+ f->get_buffer((uint8_t *)&data_big.write[0], bytecount_big);
+ HICON icon_big = CreateIconFromResource((PBYTE)&data_big.write[0], bytecount_big, TRUE, 0x00030000);
+ if (!icon_big) {
+ ERR_EXPLAIN("Could not create " + itos(big_icon_width) + "x" + itos(big_icon_width) + " @" + itos(big_icon_cc) + " icon, error: " + format_error_message(GetLastError()));
+ ERR_FAIL();
+ }
+
+ // Read the small icon
+ DWORD bytecount_small = icon_dir->idEntries[small_icon_index].dwBytesInRes;
+ Vector<uint8_t> data_small;
+ data_small.resize(bytecount_small);
+ pos = icon_dir->idEntries[small_icon_index].dwImageOffset;
+ f->seek(pos);
+ f->get_buffer((uint8_t *)&data_small.write[0], bytecount_small);
+ HICON icon_small = CreateIconFromResource((PBYTE)&data_small.write[0], bytecount_small, TRUE, 0x00030000);
+ if (!icon_small) {
+ ERR_EXPLAIN("Could not create 16x16 @" + itos(small_icon_cc) + " icon, error: " + format_error_message(GetLastError()));
+ ERR_FAIL();
+ }
+
+ // Online tradition says to be sure last error is cleared and set the small icon first
+ int err = 0;
+ SetLastError(err);
+
+ SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)icon_small);
+ err = GetLastError();
+ if (err) {
+ ERR_EXPLAIN("Error setting ICON_SMALL: " + format_error_message(err));
+ ERR_FAIL();
+ }
+
+ SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)icon_big);
+ err = GetLastError();
+ if (err) {
+ ERR_EXPLAIN("Error setting ICON_BIG: " + format_error_message(err));
+ ERR_FAIL();
+ }
+
+ memdelete(f);
+ memdelete(icon_dir);
+}
+
void OS_Windows::set_icon(const Ref<Image> &p_icon) {
ERR_FAIL_COND(!p_icon.is_valid());
@@ -2867,39 +3048,41 @@ String OS_Windows::get_godot_dir_name() const {
String OS_Windows::get_system_dir(SystemDir p_dir) const {
- int id;
+ KNOWNFOLDERID id;
switch (p_dir) {
case SYSTEM_DIR_DESKTOP: {
- id = CSIDL_DESKTOPDIRECTORY;
+ id = FOLDERID_Desktop;
} break;
case SYSTEM_DIR_DCIM: {
- id = CSIDL_MYPICTURES;
+ id = FOLDERID_Pictures;
} break;
case SYSTEM_DIR_DOCUMENTS: {
- id = CSIDL_PERSONAL;
+ id = FOLDERID_Documents;
} break;
case SYSTEM_DIR_DOWNLOADS: {
- id = 0x000C;
+ id = FOLDERID_Downloads;
} break;
case SYSTEM_DIR_MOVIES: {
- id = CSIDL_MYVIDEO;
+ id = FOLDERID_Videos;
} break;
case SYSTEM_DIR_MUSIC: {
- id = CSIDL_MYMUSIC;
+ id = FOLDERID_Music;
} break;
case SYSTEM_DIR_PICTURES: {
- id = CSIDL_MYPICTURES;
+ id = FOLDERID_Pictures;
} break;
case SYSTEM_DIR_RINGTONES: {
- id = CSIDL_MYMUSIC;
+ id = FOLDERID_Music;
} break;
}
- WCHAR szPath[MAX_PATH];
- HRESULT res = SHGetFolderPathW(NULL, id, NULL, 0, szPath);
+ PWSTR szPath;
+ HRESULT res = SHGetKnownFolderPath(id, 0, NULL, &szPath);
ERR_FAIL_COND_V(res != S_OK, String());
- return String(szPath);
+ String path = String(szPath);
+ CoTaskMemFree(szPath);
+ return path;
}
String OS_Windows::get_user_data_dir() const {
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 2d03532c69..4660c16b97 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -31,6 +31,7 @@
#ifndef OS_WINDOWS_H
#define OS_WINDOWS_H
+#include "camera_win.h"
#include "context_gl_windows.h"
#include "core/os/input.h"
#include "core/os/os.h"
@@ -58,6 +59,25 @@
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
+
+typedef struct {
+ BYTE bWidth; // Width, in pixels, of the image
+ BYTE bHeight; // Height, in pixels, of the image
+ BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
+ BYTE bReserved; // Reserved ( must be 0)
+ WORD wPlanes; // Color Planes
+ WORD wBitCount; // Bits per pixel
+ DWORD dwBytesInRes; // How many bytes in this resource?
+ DWORD dwImageOffset; // Where in the file is this image?
+} ICONDIRENTRY, *LPICONDIRENTRY;
+
+typedef struct {
+ WORD idReserved; // Reserved (must be 0)
+ WORD idType; // Resource Type (1 for icons)
+ WORD idCount; // How many images?
+ ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em)
+} ICONDIR, *LPICONDIR;
+
class JoypadWindows;
class OS_Windows : public OS {
@@ -89,6 +109,7 @@ class OS_Windows : public OS {
ContextGL_Windows *gl_context;
#endif
VisualServer *visual_server;
+ CameraWindows *camera_server;
int pressrc;
HDC hDC; // Private GDI Device Context
HINSTANCE hInstance; // Holds The Instance Of The Application
@@ -105,6 +126,9 @@ class OS_Windows : public OS {
HCURSOR hCursor;
+ Size2 min_size;
+ Size2 max_size;
+
Size2 window_rect;
VideoMode video_mode;
bool preserve_window_size = false;
@@ -217,6 +241,10 @@ public:
virtual void set_window_position(const Point2 &p_position);
virtual Size2 get_window_size() const;
virtual Size2 get_real_window_size() const;
+ virtual Size2 get_max_window_size() const;
+ virtual Size2 get_min_window_size() const;
+ virtual void set_min_window_size(const Size2 p_size);
+ virtual void set_max_window_size(const Size2 p_size);
virtual void set_window_size(const Size2 p_size);
virtual void set_window_fullscreen(bool p_enabled);
virtual bool is_window_fullscreen() const;
@@ -246,7 +274,7 @@ public:
virtual MainLoop *get_main_loop() const;
- virtual String get_name();
+ virtual String get_name() const;
virtual Date get_date(bool utc) const;
virtual Time get_time(bool utc) const;
@@ -261,7 +289,7 @@ public:
virtual void delay_usec(uint32_t p_usec) const;
virtual uint64_t get_ticks_usec() const;
- virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false);
+ virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL);
virtual Error kill(const ProcessID &p_pid);
virtual int get_process_id() const;
@@ -273,8 +301,11 @@ public:
virtual String get_clipboard() const;
void set_cursor_shape(CursorShape p_shape);
+ CursorShape get_cursor_shape() const;
virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
void GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap);
+
+ void set_native_icon(const String &p_filename);
void set_icon(const Ref<Image> &p_icon);
virtual String get_executable_path() const;
diff --git a/platform/windows/power_windows.cpp b/platform/windows/power_windows.cpp
index b96ae51132..0efd88c216 100644
--- a/platform/windows/power_windows.cpp
+++ b/platform/windows/power_windows.cpp
@@ -89,7 +89,7 @@ bool PowerWindows::GetPowerInfo_Windows() {
if (pct != 255) { /* 255 == unknown */
percent_left = (pct > 100) ? 100 : pct; /* clamp between 0%, 100% */
}
- if (secs != 0xFFFFFFFF) { /* ((DWORD)-1) == unknown */
+ if (secs != (int)0xFFFFFFFF) { /* ((DWORD)-1) == unknown */
nsecs_left = secs;
}
}
diff --git a/platform/windows/windows_terminal_logger.cpp b/platform/windows/windows_terminal_logger.cpp
index 7def419103..adbdafb07e 100644
--- a/platform/windows/windows_terminal_logger.cpp
+++ b/platform/windows/windows_terminal_logger.cpp
@@ -45,7 +45,7 @@ void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_er
int len = vsnprintf(buf, BUFFER_SIZE, p_format, p_list);
if (len <= 0)
return;
- if (len >= BUFFER_SIZE)
+ if ((unsigned int)len >= BUFFER_SIZE)
len = BUFFER_SIZE; // Output is too big, will be truncated
buf[len] = 0;
@@ -154,4 +154,4 @@ void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file
WindowsTerminalLogger::~WindowsTerminalLogger() {}
-#endif \ No newline at end of file
+#endif