Merge pull request #88329 from ManpreetXSingh/key-window-menu
Windows: Add support for enabling Alt+Space menu and fix borderless maximize
This commit is contained in:
commit
7d96ec4f9d
|
@ -1438,6 +1438,7 @@ ProjectSettings::ProjectSettings() {
|
||||||
GLOBAL_DEF("application/run/disable_stdout", false);
|
GLOBAL_DEF("application/run/disable_stdout", false);
|
||||||
GLOBAL_DEF("application/run/disable_stderr", false);
|
GLOBAL_DEF("application/run/disable_stderr", false);
|
||||||
GLOBAL_DEF("application/run/print_header", true);
|
GLOBAL_DEF("application/run/print_header", true);
|
||||||
|
GLOBAL_DEF("application/run/enable_alt_space_menu", false);
|
||||||
GLOBAL_DEF_RST("application/config/use_hidden_project_data_directory", true);
|
GLOBAL_DEF_RST("application/config/use_hidden_project_data_directory", true);
|
||||||
GLOBAL_DEF("application/config/use_custom_user_dir", false);
|
GLOBAL_DEF("application/config/use_custom_user_dir", false);
|
||||||
GLOBAL_DEF("application/config/custom_user_dir_name", "");
|
GLOBAL_DEF("application/config/custom_user_dir_name", "");
|
||||||
|
|
|
@ -323,6 +323,11 @@
|
||||||
If [code]true[/code], disables printing to standard output. This is equivalent to starting the editor or project with the [code]--quiet[/code] [url=$DOCS_URL/tutorials/editor/command_line_tutorial.html]command line argument[/url]. See also [member application/run/disable_stderr].
|
If [code]true[/code], disables printing to standard output. This is equivalent to starting the editor or project with the [code]--quiet[/code] [url=$DOCS_URL/tutorials/editor/command_line_tutorial.html]command line argument[/url]. See also [member application/run/disable_stderr].
|
||||||
Changes to this setting will only be applied upon restarting the application.
|
Changes to this setting will only be applied upon restarting the application.
|
||||||
</member>
|
</member>
|
||||||
|
<member name="application/run/enable_alt_space_menu" type="bool" setter="" getter="" default="false">
|
||||||
|
If [code]true[/code], allows the [kbd]Alt + Space[/kbd] keys to display the window menu. This menu allows the user to perform various window management operations such as moving, resizing, or minimizing the window.
|
||||||
|
[b]Note:[/b] When the menu is displayed, project execution will pause until the menu is [i]fully[/i] closed due to Windows behavior. Consider this when enabling this setting in a networked multiplayer game. The menu is only considered fully closed when an option is selected, when the user clicks outside, or when [kbd]Escape[/kbd] is pressed after bringing up the window menu [i]and[/i] another key is pressed afterwards.
|
||||||
|
[b]Note:[/b] This setting is implemented only on Windows.
|
||||||
|
</member>
|
||||||
<member name="application/run/flush_stdout_on_print" type="bool" setter="" getter="" default="false">
|
<member name="application/run/flush_stdout_on_print" type="bool" setter="" getter="" default="false">
|
||||||
If [code]true[/code], flushes the standard output stream every time a line is printed. This affects both terminal logging and file logging.
|
If [code]true[/code], flushes the standard output stream every time a line is printed. This affects both terminal logging and file logging.
|
||||||
When running a project, this setting must be enabled if you want logs to be collected by service managers such as systemd/journalctl. This setting is disabled by default on release builds, since flushing on every printed line will negatively affect performance if lots of lines are printed in a rapid succession. Also, if this setting is enabled, logged files will still be written successfully if the application crashes or is otherwise killed by the user (without being closed "normally").
|
When running a project, this setting must be enabled if you want logs to be collected by service managers such as systemd/journalctl. This setting is disabled by default on release builds, since flushing on every printed line will negatively affect performance if lots of lines are printed in a rapid succession. Also, if this setting is enabled, logged files will still be written successfully if the application crashes or is otherwise killed by the user (without being closed "normally").
|
||||||
|
|
|
@ -1895,7 +1895,7 @@ Size2i DisplayServerWindows::window_get_size_with_decorations(WindowID p_window)
|
||||||
return Size2();
|
return Size2();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_maximized, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex) {
|
void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex) {
|
||||||
// Windows docs for window styles:
|
// 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/window-styles
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles
|
// https://docs.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles
|
||||||
|
@ -1909,7 +1909,17 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre
|
||||||
|
|
||||||
if (p_fullscreen || p_borderless) {
|
if (p_fullscreen || p_borderless) {
|
||||||
r_style |= WS_POPUP; // p_borderless was WS_EX_TOOLWINDOW in the past.
|
r_style |= WS_POPUP; // p_borderless was WS_EX_TOOLWINDOW in the past.
|
||||||
if ((p_fullscreen && p_multiwindow_fs) || p_maximized) {
|
if (p_maximized) {
|
||||||
|
r_style |= WS_MAXIMIZE;
|
||||||
|
}
|
||||||
|
if (!p_fullscreen) {
|
||||||
|
r_style |= WS_SYSMENU | WS_MINIMIZEBOX;
|
||||||
|
|
||||||
|
if (p_resizable) {
|
||||||
|
r_style |= WS_MAXIMIZEBOX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((p_fullscreen && p_multiwindow_fs) || p_maximized_fs) {
|
||||||
r_style |= WS_BORDER; // Allows child windows to be displayed on top of full screen.
|
r_style |= WS_BORDER; // Allows child windows to be displayed on top of full screen.
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1945,7 +1955,7 @@ void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repain
|
||||||
DWORD style = 0;
|
DWORD style = 0;
|
||||||
DWORD style_ex = 0;
|
DWORD style_ex = 0;
|
||||||
|
|
||||||
_get_window_style(p_window == MAIN_WINDOW_ID, wd.fullscreen, wd.multiwindow_fs, wd.borderless, wd.resizable, wd.maximized, wd.no_focus || wd.is_popup, style, style_ex);
|
_get_window_style(p_window == MAIN_WINDOW_ID, wd.fullscreen, wd.multiwindow_fs, wd.borderless, wd.resizable, wd.maximized, wd.maximized_fs, wd.no_focus || wd.is_popup, style, style_ex);
|
||||||
|
|
||||||
SetWindowLongPtr(wd.hWnd, GWL_STYLE, style);
|
SetWindowLongPtr(wd.hWnd, GWL_STYLE, style);
|
||||||
SetWindowLongPtr(wd.hWnd, GWL_EXSTYLE, style_ex);
|
SetWindowLongPtr(wd.hWnd, GWL_EXSTYLE, style_ex);
|
||||||
|
@ -1988,6 +1998,7 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
|
||||||
wd.pre_fs_valid = true;
|
wd.pre_fs_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShowWindow(wd.hWnd, SW_RESTORE);
|
||||||
MoveWindow(wd.hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
|
MoveWindow(wd.hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
|
||||||
|
|
||||||
if (restore_mouse_trails > 1) {
|
if (restore_mouse_trails > 1) {
|
||||||
|
@ -2023,7 +2034,7 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) && !wd.fullscreen) {
|
if ((p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) && !wd.fullscreen) {
|
||||||
if (wd.minimized) {
|
if (wd.minimized || wd.maximized) {
|
||||||
ShowWindow(wd.hWnd, SW_RESTORE);
|
ShowWindow(wd.hWnd, SW_RESTORE);
|
||||||
}
|
}
|
||||||
wd.was_maximized = wd.maximized;
|
wd.was_maximized = wd.maximized;
|
||||||
|
@ -3737,6 +3748,15 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
||||||
min_max_info->ptMaxTrackSize.x = windows[window_id].max_size.x + decor.x;
|
min_max_info->ptMaxTrackSize.x = windows[window_id].max_size.x + decor.x;
|
||||||
min_max_info->ptMaxTrackSize.y = windows[window_id].max_size.y + decor.y;
|
min_max_info->ptMaxTrackSize.y = windows[window_id].max_size.y + decor.y;
|
||||||
}
|
}
|
||||||
|
if (windows[window_id].borderless) {
|
||||||
|
Rect2i screen_rect = screen_get_usable_rect(window_get_current_screen(window_id));
|
||||||
|
|
||||||
|
// Set the size of (borderless) maximized mode to exclude taskbar (or any other panel) if present.
|
||||||
|
min_max_info->ptMaxPosition.x = screen_rect.position.x;
|
||||||
|
min_max_info->ptMaxPosition.y = screen_rect.position.y;
|
||||||
|
min_max_info->ptMaxSize.x = screen_rect.size.x;
|
||||||
|
min_max_info->ptMaxSize.y = screen_rect.size.y;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
@ -3788,9 +3808,15 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
||||||
case SC_MONITORPOWER: // Monitor trying to enter powersave?
|
case SC_MONITORPOWER: // Monitor trying to enter powersave?
|
||||||
return 0; // Prevent from happening.
|
return 0; // Prevent from happening.
|
||||||
case SC_KEYMENU:
|
case SC_KEYMENU:
|
||||||
if ((lParam >> 16) <= 0) {
|
Engine *engine = Engine::get_singleton();
|
||||||
|
if (((lParam >> 16) <= 0) && !engine->is_project_manager_hint() && !engine->is_editor_hint() && !GLOBAL_GET("application/run/enable_alt_space_menu")) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (!alt_mem || !(GetAsyncKeyState(VK_SPACE) & (1 << 15))) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SendMessage(windows[window_id].hWnd, WM_SYSKEYUP, VK_SPACE, 0);
|
||||||
|
SendMessage(windows[window_id].hWnd, WM_SYSKEYUP, VK_MENU, 0);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case WM_INDICATOR_CALLBACK_MESSAGE: {
|
case WM_INDICATOR_CALLBACK_MESSAGE: {
|
||||||
|
@ -4521,10 +4547,23 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
||||||
window.minimized = true;
|
window.minimized = true;
|
||||||
} else if (IsZoomed(hWnd)) {
|
} else if (IsZoomed(hWnd)) {
|
||||||
window.maximized = true;
|
window.maximized = true;
|
||||||
|
|
||||||
|
// If maximized_window_size == screen_size add 1px border to prevent switching to exclusive_fs.
|
||||||
|
if (!window.maximized_fs && window.borderless && window_rect.position == screen_position && window_rect.size == screen_size) {
|
||||||
|
// Window (borderless) was just maximized and the covers the entire screen.
|
||||||
|
window.maximized_fs = true;
|
||||||
|
_update_window_style(window_id, false);
|
||||||
|
}
|
||||||
} else if (window_rect.position == screen_position && window_rect.size == screen_size) {
|
} else if (window_rect.position == screen_position && window_rect.size == screen_size) {
|
||||||
window.fullscreen = true;
|
window.fullscreen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window.maximized_fs && !window.maximized) {
|
||||||
|
// Window (maximized and covering fullscreen) was just non-maximized.
|
||||||
|
window.maximized_fs = false;
|
||||||
|
_update_window_style(window_id, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (!window.minimized) {
|
if (!window.minimized) {
|
||||||
window.width = window_client_rect.size.width;
|
window.width = window_client_rect.size.width;
|
||||||
window.height = window_client_rect.size.height;
|
window.height = window_client_rect.size.height;
|
||||||
|
@ -5004,7 +5043,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
|
||||||
DWORD dwExStyle;
|
DWORD dwExStyle;
|
||||||
DWORD dwStyle;
|
DWORD dwStyle;
|
||||||
|
|
||||||
_get_window_style(window_id_counter == MAIN_WINDOW_ID, (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN), p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MAXIMIZED, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) | (p_flags & WINDOW_FLAG_POPUP), dwStyle, dwExStyle);
|
_get_window_style(window_id_counter == MAIN_WINDOW_ID, (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN), p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MAXIMIZED, false, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) | (p_flags & WINDOW_FLAG_POPUP), dwStyle, dwExStyle);
|
||||||
|
|
||||||
RECT WindowRect;
|
RECT WindowRect;
|
||||||
|
|
||||||
|
@ -5237,6 +5276,12 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
|
||||||
wd.height = p_rect.size.height;
|
wd.height = p_rect.size.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set size of maximized borderless window (by default it covers the entire screen).
|
||||||
|
if (p_mode == WINDOW_MODE_MAXIMIZED && (p_flags & WINDOW_FLAG_BORDERLESS_BIT)) {
|
||||||
|
Rect2i srect = screen_get_usable_rect(rq_screen);
|
||||||
|
SetWindowPos(wd.hWnd, HWND_TOP, srect.position.x, srect.position.y, srect.size.width, srect.size.height, SWP_NOZORDER | SWP_NOACTIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
window_id_counter++;
|
window_id_counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -382,6 +382,7 @@ class DisplayServerWindows : public DisplayServer {
|
||||||
bool pre_fs_valid = false;
|
bool pre_fs_valid = false;
|
||||||
RECT pre_fs_rect;
|
RECT pre_fs_rect;
|
||||||
bool maximized = false;
|
bool maximized = false;
|
||||||
|
bool maximized_fs = false;
|
||||||
bool minimized = false;
|
bool minimized = false;
|
||||||
bool fullscreen = false;
|
bool fullscreen = false;
|
||||||
bool multiwindow_fs = false;
|
bool multiwindow_fs = false;
|
||||||
|
@ -471,7 +472,7 @@ class DisplayServerWindows : public DisplayServer {
|
||||||
HashMap<IndicatorID, IndicatorData> indicators;
|
HashMap<IndicatorID, IndicatorData> indicators;
|
||||||
|
|
||||||
void _send_window_event(const WindowData &wd, WindowEvent p_event);
|
void _send_window_event(const WindowData &wd, WindowEvent p_event);
|
||||||
void _get_window_style(bool p_main_window, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_maximized, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex);
|
void _get_window_style(bool p_main_window, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex);
|
||||||
|
|
||||||
MouseMode mouse_mode;
|
MouseMode mouse_mode;
|
||||||
int restore_mouse_trails = 0;
|
int restore_mouse_trails = 0;
|
||||||
|
|
Loading…
Reference in New Issue