diff options
Diffstat (limited to 'platform/windows')
| -rw-r--r-- | platform/windows/camera_win.cpp | 12 | ||||
| -rw-r--r-- | platform/windows/detect.py | 13 | ||||
| -rw-r--r-- | platform/windows/export/export.cpp | 76 | ||||
| -rw-r--r-- | platform/windows/godot_windows.cpp | 11 | ||||
| -rw-r--r-- | platform/windows/os_windows.cpp | 115 | ||||
| -rw-r--r-- | platform/windows/os_windows.h | 8 |
6 files changed, 167 insertions, 68 deletions
diff --git a/platform/windows/camera_win.cpp b/platform/windows/camera_win.cpp index b97796fe89..10787d0d0a 100644 --- a/platform/windows/camera_win.cpp +++ b/platform/windows/camera_win.cpp @@ -30,9 +30,12 @@ #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.... +///@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 promising 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 @@ -69,7 +72,8 @@ bool CameraFeedWindows::activate_feed() { 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 +///@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 diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 4b4b507499..cc9ba720a8 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -274,7 +274,7 @@ def configure_mingw(env): elif (env["target"] == "release_debug"): env.Append(CCFLAGS=['-O2']) - env.Append(CPPFLAGS=['-DDEBUG_ENABLED']) + env.Append(CPPDEFINES=['DEBUG_ENABLED']) if (env["debug_symbols"] == "yes"): env.Prepend(CCFLAGS=['-g1']) if (env["debug_symbols"] == "full"): @@ -286,7 +286,7 @@ def configure_mingw(env): elif (env["target"] == "debug"): env.Append(CCFLAGS=['-g3']) - env.Append(CPPFLAGS=['-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED']) + env.Append(CPPDEFINES=['DEBUG_ENABLED', 'DEBUG_MEMORY_ENABLED']) ## Compiler configuration @@ -328,14 +328,11 @@ def configure_mingw(env): ## Compile flags 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(CPPDEFINES=['WINDOWS_ENABLED', 'OPENGL_ENABLED', 'WASAPI_ENABLED', 'WINMIDI_ENABLED']) + env.Append(CPPDEFINES=[('WINVER', env['target_win_version']), ('_WIN32_WINNT', 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']) + env.Append(CPPDEFINES=['MINGW_ENABLED']) # resrc env.Append(BUILDERS={'RES': env.Builder(action=build_res_file, suffix='.o', src_suffix='.rc')}) diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp index 4a72d07adc..827daa2d58 100644 --- a/platform/windows/export/export.cpp +++ b/platform/windows/export/export.cpp @@ -34,6 +34,8 @@ #include "editor/editor_settings.h" #include "platform/windows/logo.gen.h" +static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size); + class EditorExportPlatformWindows : public EditorExportPlatformPC { public: @@ -172,6 +174,80 @@ void register_windows_exporter() { platform->set_release_64("windows_64_release.exe"); platform->set_debug_64("windows_64_debug.exe"); platform->set_os_name("Windows"); + platform->set_fixup_embedded_pck_func(&fixup_embedded_pck); EditorExport::get_singleton()->add_export_platform(platform); } + +static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) { + + // Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data + + FileAccess *f = FileAccess::open(p_path, FileAccess::READ_WRITE); + if (!f) { + return ERR_CANT_OPEN; + } + + // Jump to the PE header and check the magic number + { + f->seek(0x3c); + uint32_t pe_pos = f->get_32(); + + f->seek(pe_pos); + uint32_t magic = f->get_32(); + if (magic != 0x00004550) { + f->close(); + return ERR_FILE_CORRUPT; + } + } + + // Process header + + int num_sections; + { + int64_t header_pos = f->get_position(); + + f->seek(header_pos + 2); + num_sections = f->get_16(); + f->seek(header_pos + 16); + uint16_t opt_header_size = f->get_16(); + + // Skip rest of header + optional header to go to the section headers + f->seek(f->get_position() + 2 + opt_header_size); + } + + // Search for the "pck" section + + int64_t section_table_pos = f->get_position(); + + bool found = false; + for (int i = 0; i < num_sections; ++i) { + + int64_t section_header_pos = section_table_pos + i * 40; + f->seek(section_header_pos); + + uint8_t section_name[9]; + f->get_buffer(section_name, 8); + section_name[8] = '\0'; + + if (strcmp((char *)section_name, "pck") == 0) { + // "pck" section found, let's patch! + + // Set virtual size to a little to avoid it taking memory (zero would give issues) + f->seek(section_header_pos + 8); + f->store_32(8); + + f->seek(section_header_pos + 16); + f->store_32(p_embedded_size); + f->seek(section_header_pos + 20); + f->store_32(p_embedded_start); + + found = true; + break; + } + } + + f->close(); + + return found ? OK : ERR_FILE_CORRUPT; +} diff --git a/platform/windows/godot_windows.cpp b/platform/windows/godot_windows.cpp index 0b52682c7c..11bfea6922 100644 --- a/platform/windows/godot_windows.cpp +++ b/platform/windows/godot_windows.cpp @@ -34,6 +34,17 @@ #include <locale.h> #include <stdio.h> +// For export templates, add a section; the exporter will patch it to enclose +// the data appended to the executable (bundled PCK) +#ifndef TOOLS_ENABLED +#if defined _MSC_VER +#pragma section("pck", read) +__declspec(allocate("pck")) static char dummy[8] = { 0 }; +#elif defined __GNUC__ +static const char dummy[8] __attribute__((section("pck"), used)) = { 0 }; +#endif +#endif + PCHAR * CommandLineToArgvA( PCHAR CmdLine, diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 6e6df08f02..facf5b8d91 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -719,7 +719,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) pressrc = 0; } } - } else if (mouse_mode != MOUSE_MODE_CAPTURED) { + } else { // for reasons unknown to mankind, wheel comes in screen coordinates POINT coords; coords.x = mb->get_position().x; @@ -843,8 +843,8 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (wParam==VK_WIN) TODO wtf is this? meta_mem=uMsg==WM_KEYDOWN; */ - - } //fallthrough + FALLTHROUGH; + } case WM_CHAR: { ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE); @@ -1435,16 +1435,13 @@ void OS_Windows::set_clipboard(const String &p_text) { String text = p_text.replace("\n", "\r\n"); if (!OpenClipboard(hWnd)) { - ERR_EXPLAIN("Unable to open clipboard."); - ERR_FAIL(); - }; + ERR_FAIL_MSG("Unable to open clipboard."); + } EmptyClipboard(); HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) * sizeof(CharType)); - if (mem == NULL) { - ERR_EXPLAIN("Unable to allocate memory for clipboard contents."); - ERR_FAIL(); - }; + ERR_FAIL_COND_MSG(mem == NULL, "Unable to allocate memory for clipboard contents."); + LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem); memcpy(lptstrCopy, text.c_str(), (text.length() + 1) * sizeof(CharType)); GlobalUnlock(mem); @@ -1454,10 +1451,8 @@ void OS_Windows::set_clipboard(const String &p_text) { // set the CF_TEXT version (not needed?) CharString utf8 = text.utf8(); mem = GlobalAlloc(GMEM_MOVEABLE, utf8.length() + 1); - if (mem == NULL) { - ERR_EXPLAIN("Unable to allocate memory for clipboard contents."); - ERR_FAIL(); - }; + ERR_FAIL_COND_MSG(mem == NULL, "Unable to allocate memory for clipboard contents."); + LPTSTR ptr = (LPTSTR)GlobalLock(mem); memcpy(ptr, utf8.get_data(), utf8.length()); ptr[utf8.length()] = 0; @@ -1472,8 +1467,7 @@ String OS_Windows::get_clipboard() const { String ret; if (!OpenClipboard(hWnd)) { - ERR_EXPLAIN("Unable to open clipboard."); - ERR_FAIL_V(""); + ERR_FAIL_V_MSG("", "Unable to open clipboard."); }; if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { @@ -1537,6 +1531,7 @@ void OS_Windows::finalize() { memdelete(camera_server); touch_state.clear(); + cursors_cache.clear(); visual_server->finish(); memdelete(visual_server); #ifdef OPENGL_ENABLED @@ -1812,7 +1807,7 @@ Size2 OS_Windows::get_min_window_size() const { 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!"); + ERR_PRINT("Minimum window size can't be larger than maximum window size!"); return; } min_size = p_size; @@ -1821,7 +1816,7 @@ void OS_Windows::set_min_window_size(const Size2 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!"); + ERR_PRINT("Maximum window size can't be smaller than minimum window size!"); return; } max_size = p_size; @@ -1979,6 +1974,17 @@ bool OS_Windows::is_window_always_on_top() const { return video_mode.always_on_top; } +void OS_Windows::set_console_visible(bool p_enabled) { + if (console_visible == p_enabled) + return; + ShowWindow(GetConsoleWindow(), p_enabled ? SW_SHOW : SW_HIDE); + console_visible = p_enabled; +} + +bool OS_Windows::is_console_visible() const { + return console_visible; +} + bool OS_Windows::get_window_per_pixel_transparency_enabled() const { if (!is_layered_allowed()) return false; @@ -2123,15 +2129,12 @@ Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_han } p_library_handle = (void *)LoadLibraryExW(path.c_str(), NULL, (p_also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0); + ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + format_error_message(GetLastError()) + "."); if (cookie) { remove_dll_directory(cookie); } - if (!p_library_handle) { - ERR_EXPLAIN("Can't open dynamic library: " + p_path + ". Error: " + format_error_message(GetLastError())); - ERR_FAIL_V(ERR_CANT_OPEN); - } return OK; } @@ -2146,8 +2149,7 @@ Error OS_Windows::get_dynamic_library_symbol_handle(void *p_library_handle, cons p_symbol_handle = (void *)GetProcAddress((HMODULE)p_library_handle, p_name.utf8().get_data()); if (!p_symbol_handle) { if (!p_optional) { - ERR_EXPLAIN("Can't resolve symbol " + p_name + ". Error: " + String::num(GetLastError())); - ERR_FAIL_V(ERR_CANT_RESOLVE); + ERR_FAIL_V_MSG(ERR_CANT_RESOLVE, "Can't resolve symbol " + p_name + ", error: " + String::num(GetLastError()) + "."); } else { return ERR_CANT_RESOLVE; } @@ -2240,9 +2242,17 @@ 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) + // Type punning through unions (rather than pointer cast) as per: // https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ns-minwinbase-filetime#remarks - return (*(uint64_t *)&ft - *(uint64_t *)&fep) / 10000000; + ULARGE_INTEGER ft_punning; + ft_punning.LowPart = ft.dwLowDateTime; + ft_punning.HighPart = ft.dwHighDateTime; + + ULARGE_INTEGER fep_punning; + fep_punning.LowPart = fep.dwLowDateTime; + fep_punning.HighPart = fep.dwHighDateTime; + + return (ft_punning.QuadPart - fep_punning.QuadPart) / 10000000; }; uint64_t OS_Windows::get_system_time_secs() const { @@ -2356,7 +2366,20 @@ OS::CursorShape OS_Windows::get_cursor_shape() const { } void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + if (p_cursor.is_valid()) { + + Map<CursorShape, Vector<Variant> >::Element *cursor_c = cursors_cache.find(p_shape); + + if (cursor_c) { + if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) { + set_cursor_shape(p_shape); + return; + } + + cursors_cache.erase(p_shape); + } + Ref<Texture> texture = p_cursor; Ref<AtlasTexture> atlas_texture = p_cursor; Ref<Image> image; @@ -2439,6 +2462,11 @@ void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shap cursors[p_shape] = CreateIconIndirect(&iconinfo); + Vector<Variant> params; + params.push_back(p_cursor); + params.push_back(p_hotspot); + cursors_cache.insert(p_shape, params); + if (p_shape == cursor_shape) { if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { SetCursor(cursors[p_shape]); @@ -2575,7 +2603,7 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, modstr.resize(cmdline.size()); for (int i = 0; i < cmdline.size(); i++) modstr.write[i] = cmdline[i]; - int ret = CreateProcessW(NULL, modstr.ptrw(), NULL, NULL, 0, NORMAL_PRIORITY_CLASS, NULL, NULL, si_w, &pi.pi); + int ret = CreateProcessW(NULL, modstr.ptrw(), NULL, NULL, 0, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, NULL, NULL, si_w, &pi.pi); ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK); if (p_blocking) { @@ -2635,7 +2663,7 @@ String OS_Windows::get_executable_path() const { void OS_Windows::set_native_icon(const String &p_filename) { FileAccess *f = FileAccess::open(p_filename, FileAccess::READ); - ERR_FAIL_COND(!f); + ERR_FAIL_COND_MSG(!f, "Cannot open file with icon '" + p_filename + "'."); ICONDIR *icon_dir = (ICONDIR *)memalloc(sizeof(ICONDIR)); int pos = 0; @@ -2648,10 +2676,7 @@ void OS_Windows::set_native_icon(const String &p_filename) { pos += sizeof(WORD); f->seek(pos); - if (icon_dir->idType != 1) { - ERR_EXPLAIN("Invalid icon file format!"); - ERR_FAIL(); - } + ERR_FAIL_COND_MSG(icon_dir->idType != 1, "Invalid icon file format!"); icon_dir->idCount = f->get_32(); pos += sizeof(WORD); @@ -2684,10 +2709,7 @@ void OS_Windows::set_native_icon(const String &p_filename) { } } - if (big_icon_index == -1) { - ERR_EXPLAIN("No valid icons found!"); - ERR_FAIL(); - } + ERR_FAIL_COND_MSG(big_icon_index == -1, "No valid icons found!"); 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!"); @@ -2703,10 +2725,7 @@ void OS_Windows::set_native_icon(const String &p_filename) { 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(); - } + ERR_FAIL_COND_MSG(!icon_big, "Could not create " + itos(big_icon_width) + "x" + itos(big_icon_width) + " @" + itos(big_icon_cc) + " icon, error: " + format_error_message(GetLastError()) + "."); // Read the small icon DWORD bytecount_small = icon_dir->idEntries[small_icon_index].dwBytesInRes; @@ -2716,10 +2735,7 @@ void OS_Windows::set_native_icon(const String &p_filename) { 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(); - } + ERR_FAIL_COND_MSG(!icon_small, "Could not create 16x16 @" + itos(small_icon_cc) + " icon, error: " + format_error_message(GetLastError()) + "."); // Online tradition says to be sure last error is cleared and set the small icon first int err = 0; @@ -2727,17 +2743,11 @@ void OS_Windows::set_native_icon(const String &p_filename) { 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(); - } + ERR_FAIL_COND_MSG(err, "Error setting ICON_SMALL: " + format_error_message(err) + "."); 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(); - } + ERR_FAIL_COND_MSG(err, "Error setting ICON_BIG: " + format_error_message(err) + "."); memdelete(f); memdelete(icon_dir); @@ -3231,6 +3241,7 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { control_mem = false; meta_mem = false; minimized = false; + console_visible = IsWindowVisible(GetConsoleWindow()); hInstance = _hInstance; pressrc = 0; diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 4660c16b97..915d025e3b 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -56,10 +56,6 @@ #include <windows.h> #include <windowsx.h> -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ - typedef struct { BYTE bWidth; // Width, in pixels, of the image BYTE bHeight; // Height, in pixels, of the image @@ -155,6 +151,7 @@ class OS_Windows : public OS { HCURSOR cursors[CURSOR_MAX] = { NULL }; CursorShape cursor_shape; + Map<CursorShape, Vector<Variant> > cursors_cache; InputDefault *input; JoypadWindows *joypad; @@ -210,6 +207,7 @@ protected: bool maximized; bool minimized; bool borderless; + bool console_visible; public: LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -256,6 +254,8 @@ public: virtual bool is_window_maximized() const; virtual void set_window_always_on_top(bool p_enabled); virtual bool is_window_always_on_top() const; + virtual void set_console_visible(bool p_enabled); + virtual bool is_console_visible() const; virtual void request_attention(); virtual void set_borderless_window(bool p_borderless); |