Skip to content

Commit

Permalink
Windows: Add alt+space menu and fix window modes
Browse files Browse the repository at this point in the history
  • Loading branch information
ManpreetXSingh committed Apr 6, 2024
1 parent 655e93d commit 329d04d
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 7 deletions.
1 change: 1 addition & 0 deletions core/config/project_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1438,6 +1438,7 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("application/run/disable_stdout", false);
GLOBAL_DEF("application/run/disable_stderr", false);
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("application/config/use_custom_user_dir", false);
GLOBAL_DEF("application/config/custom_user_dir_name", "");
Expand Down
5 changes: 5 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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].
Changes to this setting will only be applied upon restarting the application.
</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">
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").
Expand Down
57 changes: 51 additions & 6 deletions platform/windows/display_server_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1895,7 +1895,7 @@ Size2i DisplayServerWindows::window_get_size_with_decorations(WindowID p_window)
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:
// https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles
// https://docs.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles
Expand All @@ -1909,7 +1909,17 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre

if (p_fullscreen || p_borderless) {
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.
}
} else {
Expand Down Expand Up @@ -1945,7 +1955,7 @@ void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repain
DWORD style = 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_EXSTYLE, style_ex);
Expand Down Expand Up @@ -1988,6 +1998,7 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
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);

if (restore_mouse_trails > 1) {
Expand Down Expand Up @@ -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 (wd.minimized) {
if (wd.minimized || wd.maximized) {
ShowWindow(wd.hWnd, SW_RESTORE);
}
wd.was_maximized = wd.maximized;
Expand Down Expand Up @@ -3782,6 +3793,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.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;
}
} break;
Expand Down Expand Up @@ -3833,9 +3853,15 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
case SC_MONITORPOWER: // Monitor trying to enter powersave?
return 0; // Prevent from happening.
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;
}
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;
case WM_INDICATOR_CALLBACK_MESSAGE: {
Expand Down Expand Up @@ -4569,10 +4595,23 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
window.minimized = true;
} else if (IsZoomed(hWnd)) {
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) {
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) {
window.width = window_client_rect.size.width;
window.height = window_client_rect.size.height;
Expand Down Expand Up @@ -5051,7 +5090,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
DWORD dwExStyle;
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;

Expand Down Expand Up @@ -5284,6 +5323,12 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
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++;
}

Expand Down
3 changes: 2 additions & 1 deletion platform/windows/display_server_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ class DisplayServerWindows : public DisplayServer {
bool pre_fs_valid = false;
RECT pre_fs_rect;
bool maximized = false;
bool maximized_fs = false;
bool minimized = false;
bool fullscreen = false;
bool multiwindow_fs = false;
Expand Down Expand Up @@ -472,7 +473,7 @@ class DisplayServerWindows : public DisplayServer {
HashMap<IndicatorID, IndicatorData> indicators;

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;
int restore_mouse_trails = 0;
Expand Down

0 comments on commit 329d04d

Please sign in to comment.