diff options
Diffstat (limited to 'platform/windows/os_windows.cpp')
-rw-r--r-- | platform/windows/os_windows.cpp | 184 |
1 files changed, 159 insertions, 25 deletions
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 6125455e74..6df2ad4821 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> @@ -345,6 +346,7 @@ 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; }; @@ -384,8 +386,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 +480,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; @@ -670,7 +668,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 +705,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 +787,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: { @@ -1412,26 +1413,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."); @@ -2115,7 +2119,7 @@ void OS_Windows::request_attention() { FlashWindowEx(&info); } -String OS_Windows::get_name() { +String OS_Windows::get_name() const { return "Windows"; } @@ -2297,6 +2301,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; @@ -2457,7 +2466,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 +2475,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 +2491,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); @@ -2562,6 +2583,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 +2999,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 { |