diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index c328332387d..9dc43497596 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -1513,6 +1513,8 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("display/window/size/extend_to_title", false);
GLOBAL_DEF("display/window/size/no_focus", false);
GLOBAL_DEF("display/window/size/sharp_corners", false);
+ GLOBAL_DEF("display/window/size/minimize_disabled", false);
+ GLOBAL_DEF("display/window/size/maximize_disabled", false);
GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, "0,7680,1,or_greater"), 0); // 8K resolution
GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"), 0); // 8K resolution
diff --git a/doc/classes/AcceptDialog.xml b/doc/classes/AcceptDialog.xml
index 198429831ea..ccbe2ddd555 100644
--- a/doc/classes/AcceptDialog.xml
+++ b/doc/classes/AcceptDialog.xml
@@ -73,6 +73,8 @@
+
+
The text displayed by the OK button (see [method get_ok_button]). If empty, a default text will be used.
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index 0103cff1df4..93cf2994e5e 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -2195,7 +2195,15 @@
Signals the window manager that this window is supposed to be an implementation-defined "popup" (usually a floating, borderless, untileable and immovable child window).
-
+
+ Window minimize button is disabled.
+ [b]Note:[/b] This flag is implemented on macOS and Windows.
+
+
+ Window maximize button is disabled.
+ [b]Note:[/b] This flag is implemented on macOS and Windows.
+
+
Max value of the [enum WindowFlags].
diff --git a/doc/classes/Popup.xml b/doc/classes/Popup.xml
index a7ca692aa0d..e31184112df 100644
--- a/doc/classes/Popup.xml
+++ b/doc/classes/Popup.xml
@@ -10,6 +10,8 @@
+
+
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index a156c0ad275..257cbb8fd0f 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -948,6 +948,12 @@
Main window initial screen, this setting is used only if [member display/window/size/initial_position_type] is set to "Other Screen Center" ([code]2[/code]).
[b]Note:[/b] This setting only affects the exported project, or when the project is run from the command line. In the editor, the value of [member EditorSettings.run/window_placement/screen] is used instead.
+
+ If [code]true[/code], the main window's maximize button is disabled.
+
+
+ If [code]true[/code], the main window's minimize button is disabled.
+
Main window mode. See [enum DisplayServer.WindowMode] for possible values and how each mode behaves.
[b]Note:[/b] Game embedding is available only in the "Windowed" mode.
diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml
index 4016f05628f..b8c3d580696 100644
--- a/doc/classes/Window.xml
+++ b/doc/classes/Window.xml
@@ -626,10 +626,20 @@
If non-zero, the [Window] can't be resized to be bigger than this size.
[b]Note:[/b] This property will be ignored if the value is lower than [member min_size].
+
+ If [code]true[/code], the [Window]'s maximize button is disabled.
+ [b]Note:[/b] If both minimize and maximize buttons are disabled, buttons are fully hidden, and only close button is visible.
+ [b]Note:[/b] This property is implemented only on macOS and Windows.
+
If non-zero, the [Window] can't be resized to be smaller than this size.
[b]Note:[/b] This property will be ignored in favor of [method get_contents_minimum_size] if [member wrap_controls] is enabled and if its size is bigger.
+
+ If [code]true[/code], the [Window]'s minimize button is disabled.
+ [b]Note:[/b] If both minimize and maximize buttons are disabled, buttons are fully hidden, and only close button is visible.
+ [b]Note:[/b] This property is implemented only on macOS and Windows.
+
Set's the window's current mode.
[b]Note:[/b] Fullscreen mode is not exclusive full screen on Windows and Linux.
@@ -714,7 +724,7 @@
If [code]true[/code], the [Window] can't be focused nor interacted with. It can still be visible.
- If [code]true[/code], the window can't be resized. Minimize and maximize buttons are disabled.
+ If [code]true[/code], the window can't be resized.
If [code]true[/code], the window is visible.
@@ -887,7 +897,15 @@
Signals the window manager that this window is supposed to be an implementation-defined "popup" (usually a floating, borderless, untileable and immovable child window).
-
+
+ Window minimize button is disabled.
+ [b]Note:[/b] This flag is implemented on macOS and Windows.
+
+
+ Window maximize button is disabled.
+ [b]Note:[/b] This flag is implemented on macOS and Windows.
+
+
Max value of the [enum Flags].
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index aa886d9a864..158a8c00297 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -1946,6 +1946,8 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
delete_window = memnew(ConfirmationDialog);
delete_window->set_flag(Window::FLAG_RESIZE_DISABLED, true);
+ delete_window->set_flag(Window::FLAG_MINIMIZE_DISABLED, true);
+ delete_window->set_flag(Window::FLAG_MAXIMIZE_DISABLED, true);
add_child(delete_window);
delete_tree = memnew(Tree);
diff --git a/main/main.cpp b/main/main.cpp
index 0cea51cacf9..339a3029744 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -2542,6 +2542,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
if (!bool(GLOBAL_GET("display/window/size/resizable"))) {
window_flags |= DisplayServer::WINDOW_FLAG_RESIZE_DISABLED_BIT;
}
+ if (bool(GLOBAL_GET("display/window/size/minimize_disabled"))) {
+ window_flags |= DisplayServer::WINDOW_FLAG_MINIMIZE_DISABLED_BIT;
+ }
+ if (bool(GLOBAL_GET("display/window/size/maximize_disabled"))) {
+ window_flags |= DisplayServer::WINDOW_FLAG_MAXIMIZE_DISABLED_BIT;
+ }
if (bool(GLOBAL_GET("display/window/size/borderless"))) {
window_flags |= DisplayServer::WINDOW_FLAG_BORDERLESS_BIT;
}
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 5f2850c83c5..ee035dfd92b 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -2315,6 +2315,40 @@ void DisplayServerX11::_update_size_hints(WindowID p_window) {
XFree(xsh);
}
+void DisplayServerX11::_update_actions_hints(WindowID p_window) {
+ WindowData &wd = windows[p_window];
+
+ Atom prop = XInternAtom(x11_display, "_NET_WM_ALLOWED_ACTIONS", False);
+ if (prop != None) {
+ Atom wm_act_max_horz = XInternAtom(x11_display, "_NET_WM_ACTION_MAXIMIZE_HORZ", False);
+ Atom wm_act_max_vert = XInternAtom(x11_display, "_NET_WM_ACTION_MAXIMIZE_VERT", False);
+ Atom wm_act_min = XInternAtom(x11_display, "_NET_WM_ACTION_MINIMIZE", False);
+ Atom type;
+ int format;
+ unsigned long len;
+ unsigned long remaining;
+ unsigned char *data = nullptr;
+ if (XGetWindowProperty(x11_display, wd.x11_window, prop, 0, 1024, False, XA_ATOM, &type, &format, &len, &remaining, &data) == Success) {
+ Atom *atoms = (Atom *)data;
+ Vector new_atoms;
+ for (uint64_t i = 0; i < len; i++) {
+ if (atoms[i] != wm_act_max_horz && atoms[i] != wm_act_max_vert && atoms[i] != wm_act_min) {
+ new_atoms.push_back(atoms[i]);
+ }
+ }
+ if (!wd.no_max_btn) {
+ new_atoms.push_back(wm_act_max_horz);
+ new_atoms.push_back(wm_act_max_vert);
+ }
+ if (!wd.no_min_btn) {
+ new_atoms.push_back(wm_act_min);
+ }
+ XChangeProperty(x11_display, wd.x11_window, prop, XA_ATOM, 32, PropModeReplace, (unsigned char *)new_atoms.ptrw(), new_atoms.size());
+ XFree(data);
+ }
+ }
+}
+
Point2i DisplayServerX11::window_get_position(WindowID p_window) const {
_THREAD_SAFE_METHOD_
@@ -3001,6 +3035,18 @@ void DisplayServerX11::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
WindowData &wd = windows[p_window];
switch (p_flag) {
+ case WINDOW_FLAG_MAXIMIZE_DISABLED: {
+ wd.no_max_btn = p_enabled;
+ _update_actions_hints(p_window);
+
+ XFlush(x11_display);
+ } break;
+ case WINDOW_FLAG_MINIMIZE_DISABLED: {
+ wd.no_min_btn = p_enabled;
+ _update_actions_hints(p_window);
+
+ XFlush(x11_display);
+ } break;
case WINDOW_FLAG_RESIZE_DISABLED: {
if (p_enabled && wd.embed_parent) {
print_line("Embedded window resize can't be disabled.");
@@ -3009,6 +3055,7 @@ void DisplayServerX11::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
wd.resize_disabled = p_enabled;
_update_size_hints(p_window);
+ _update_actions_hints(p_window);
XFlush(x11_display);
} break;
@@ -3095,6 +3142,12 @@ bool DisplayServerX11::window_get_flag(WindowFlags p_flag, WindowID p_window) co
const WindowData &wd = windows[p_window];
switch (p_flag) {
+ case WINDOW_FLAG_MAXIMIZE_DISABLED: {
+ return wd.no_max_btn;
+ } break;
+ case WINDOW_FLAG_MINIMIZE_DISABLED: {
+ return wd.no_min_btn;
+ } break;
case WINDOW_FLAG_RESIZE_DISABLED: {
return wd.resize_disabled;
} break;
@@ -4842,6 +4895,9 @@ void DisplayServerX11::process_events() {
XSync(x11_display, False);
XGetWindowAttributes(x11_display, wd.x11_window, &xwa);
+ _update_actions_hints(window_id);
+ XFlush(x11_display);
+
// Set focus when menu window is started.
// RevertToPointerRoot is used to make sure we don't lose all focus in case
// a subwindow and its parent are both destroyed.
diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h
index 25bf3111dc2..28334b80850 100644
--- a/platform/linuxbsd/x11/display_server_x11.h
+++ b/platform/linuxbsd/x11/display_server_x11.h
@@ -199,6 +199,8 @@ class DisplayServerX11 : public DisplayServer {
bool on_top = false;
bool borderless = false;
bool resize_disabled = false;
+ bool no_min_btn = false;
+ bool no_max_btn = false;
Vector2i last_position_before_fs;
bool focused = true;
bool minimized = false;
@@ -352,6 +354,7 @@ class DisplayServerX11 : public DisplayServer {
bool _window_minimize_check(WindowID p_window) const;
void _validate_mode_on_map(WindowID p_window);
void _update_size_hints(WindowID p_window);
+ void _update_actions_hints(WindowID p_window);
void _set_wm_fullscreen(WindowID p_window, bool p_enabled, bool p_exclusive);
void _set_wm_maximized(WindowID p_window, bool p_enabled);
void _set_wm_minimized(WindowID p_window, bool p_enabled);
diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h
index e6cfd976ae4..18f41676b16 100644
--- a/platform/macos/display_server_macos.h
+++ b/platform/macos/display_server_macos.h
@@ -123,6 +123,8 @@ public:
bool on_top = false;
bool borderless = false;
bool resize_disabled = false;
+ bool no_min_btn = false;
+ bool no_max_btn = false;
bool no_focus = false;
bool is_popup = false;
bool mpass = false;
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 942d3a27e3e..91482d2aa2f 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -2454,6 +2454,10 @@ void DisplayServerMacOS::window_set_mode(WindowMode p_mode, WindowID p_window) {
if (wd.resize_disabled) { // Restore resize disabled.
[wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable];
}
+ [[wd.window_object standardWindowButton:NSWindowMiniaturizeButton] setEnabled:!wd.no_min_btn];
+ [[wd.window_object standardWindowButton:NSWindowZoomButton] setEnabled:!wd.no_max_btn];
+ [[wd.window_object standardWindowButton:NSWindowMiniaturizeButton] setHidden:(wd.no_min_btn && wd.no_max_btn)];
+ [[wd.window_object standardWindowButton:NSWindowZoomButton] setHidden:(wd.no_min_btn && wd.no_max_btn)];
if (wd.min_size != Size2i()) {
Size2i size = wd.min_size / screen_get_max_scale();
[wd.window_object setContentMinSize:NSMakeSize(size.x, size.y)];
@@ -2539,7 +2543,10 @@ DisplayServer::WindowMode DisplayServerMacOS::window_get_mode(WindowID p_window)
}
bool DisplayServerMacOS::window_is_maximize_allowed(WindowID p_window) const {
- return true;
+ ERR_FAIL_COND_V(!windows.has(p_window), false);
+ const WindowData &wd = windows[p_window];
+
+ return [wd.window_object standardWindowButton:NSWindowZoomButton].enabled;
}
bool DisplayServerMacOS::window_maximize_on_title_dbl_click() const {
@@ -2632,11 +2639,14 @@ void DisplayServerMacOS::window_set_custom_window_buttons(WindowData &p_wd, bool
p_wd.window_button_view = [[GodotButtonView alloc] initWithFrame:NSZeroRect];
[p_wd.window_button_view initButtons:window_buttons_spacing offset:NSMakePoint(p_wd.wb_offset.x, p_wd.wb_offset.y) rtl:is_rtl];
[p_wd.window_view addSubview:p_wd.window_button_view];
+
+ [[p_wd.window_object standardWindowButton:NSWindowMiniaturizeButton] setHidden:(p_wd.no_min_btn && p_wd.no_max_btn)];
+ [[p_wd.window_object standardWindowButton:NSWindowZoomButton] setHidden:(p_wd.no_min_btn && p_wd.no_max_btn)];
} else {
[p_wd.window_object setTitleVisibility:NSWindowTitleVisible];
[[p_wd.window_object standardWindowButton:NSWindowZoomButton] setHidden:NO];
- [[p_wd.window_object standardWindowButton:NSWindowMiniaturizeButton] setHidden:NO];
- [[p_wd.window_object standardWindowButton:NSWindowCloseButton] setHidden:NO];
+ [[p_wd.window_object standardWindowButton:NSWindowMiniaturizeButton] setHidden:(p_wd.no_min_btn && p_wd.no_max_btn)];
+ [[p_wd.window_object standardWindowButton:NSWindowZoomButton] setHidden:(p_wd.no_min_btn && p_wd.no_max_btn)];
}
}
@@ -2647,6 +2657,18 @@ void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, Win
WindowData &wd = windows[p_window];
switch (p_flag) {
+ case WINDOW_FLAG_MINIMIZE_DISABLED: {
+ wd.no_min_btn = p_enabled;
+ [[wd.window_object standardWindowButton:NSWindowMiniaturizeButton] setEnabled:!p_enabled];
+ [[wd.window_object standardWindowButton:NSWindowMiniaturizeButton] setHidden:(wd.no_min_btn && wd.no_max_btn)];
+ [[wd.window_object standardWindowButton:NSWindowZoomButton] setHidden:(wd.no_min_btn && wd.no_max_btn)];
+ } break;
+ case WINDOW_FLAG_MAXIMIZE_DISABLED: {
+ wd.no_max_btn = p_enabled;
+ [[wd.window_object standardWindowButton:NSWindowZoomButton] setEnabled:!p_enabled];
+ [[wd.window_object standardWindowButton:NSWindowMiniaturizeButton] setHidden:(wd.no_min_btn && wd.no_max_btn)];
+ [[wd.window_object standardWindowButton:NSWindowZoomButton] setHidden:(wd.no_min_btn && wd.no_max_btn)];
+ } break;
case WINDOW_FLAG_RESIZE_DISABLED: {
wd.resize_disabled = p_enabled;
if (wd.fullscreen) { // Fullscreen window should be resizable, style will be applied on exiting fullscreen.
@@ -2654,11 +2676,13 @@ void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, Win
}
if (p_enabled) {
[wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable];
- [[wd.window_object standardWindowButton:NSWindowZoomButton] setEnabled:NO];
} else {
[wd.window_object setStyleMask:[wd.window_object styleMask] | NSWindowStyleMaskResizable];
- [[wd.window_object standardWindowButton:NSWindowZoomButton] setEnabled:YES];
}
+ [[wd.window_object standardWindowButton:NSWindowMiniaturizeButton] setEnabled:!wd.no_min_btn];
+ [[wd.window_object standardWindowButton:NSWindowZoomButton] setEnabled:!wd.no_max_btn];
+ [[wd.window_object standardWindowButton:NSWindowMiniaturizeButton] setHidden:(wd.no_min_btn && wd.no_max_btn)];
+ [[wd.window_object standardWindowButton:NSWindowZoomButton] setHidden:(wd.no_min_btn && wd.no_max_btn)];
} break;
case WINDOW_FLAG_EXTEND_TO_TITLE: {
NSRect rect = [wd.window_object frame];
@@ -2700,6 +2724,8 @@ void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, Win
}
} else {
[wd.window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (wd.extend_to_title ? NSWindowStyleMaskFullSizeContentView : 0) | (wd.resize_disabled ? 0 : NSWindowStyleMaskResizable)];
+ [[wd.window_object standardWindowButton:NSWindowMiniaturizeButton] setEnabled:!wd.no_min_btn];
+ [[wd.window_object standardWindowButton:NSWindowZoomButton] setEnabled:!wd.no_max_btn];
[wd.window_object setHasShadow:YES];
if (wd.layered_window) {
// Note: transparent and not borderless - set alpha to non-zero value to ensure window shadow is rendered correctly.
@@ -2780,6 +2806,12 @@ bool DisplayServerMacOS::window_get_flag(WindowFlags p_flag, WindowID p_window)
const WindowData &wd = windows[p_window];
switch (p_flag) {
+ case WINDOW_FLAG_MAXIMIZE_DISABLED: {
+ return wd.no_max_btn;
+ } break;
+ case WINDOW_FLAG_MINIMIZE_DISABLED: {
+ return wd.no_min_btn;
+ } break;
case WINDOW_FLAG_RESIZE_DISABLED: {
return wd.resize_disabled;
} break;
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 5d3fe5aa113..6fbb89b98cf 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -1622,6 +1622,12 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod
if (p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT) {
wd.resizable = false;
}
+ if (p_flags & WINDOW_FLAG_MINIMIZE_DISABLED_BIT) {
+ wd.no_min_btn = true;
+ }
+ if (p_flags & WINDOW_FLAG_MAXIMIZE_DISABLED_BIT) {
+ wd.no_max_btn = true;
+ }
if (p_flags & WINDOW_FLAG_BORDERLESS_BIT) {
wd.borderless = true;
}
@@ -2303,7 +2309,7 @@ Size2i DisplayServerWindows::window_get_size_with_decorations(WindowID p_window)
return Size2();
}
-void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_initialized, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_minimized, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, bool p_embed_child, DWORD &r_style, DWORD &r_style_ex) {
+void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_initialized, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_no_min_btn, bool p_no_max_btn, bool p_minimized, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, bool p_embed_child, 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
@@ -2331,9 +2337,11 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_initiali
r_style |= WS_MAXIMIZE;
}
if (!p_fullscreen) {
- r_style |= WS_SYSMENU | WS_MINIMIZEBOX;
-
- if (p_resizable) {
+ r_style |= WS_SYSMENU;
+ if (!p_no_min_btn) {
+ r_style |= WS_MINIMIZEBOX;
+ }
+ if (!p_no_max_btn) {
r_style |= WS_MAXIMIZEBOX;
}
}
@@ -2346,11 +2354,23 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_initiali
} else {
r_style = WS_OVERLAPPEDWINDOW;
}
+ if (p_no_min_btn) {
+ r_style &= ~WS_MINIMIZEBOX;
+ }
+ if (p_no_max_btn) {
+ r_style &= ~WS_MAXIMIZEBOX;
+ }
} else {
if (p_minimized) {
- r_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MINIMIZE;
+ r_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZE;
} else {
- r_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
+ r_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;
+ }
+ if (!p_no_min_btn) {
+ r_style |= WS_MINIMIZEBOX;
+ }
+ if (!p_no_max_btn) {
+ r_style |= WS_MAXIMIZEBOX;
}
}
}
@@ -2380,7 +2400,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.initialized, wd.fullscreen, wd.multiwindow_fs, wd.borderless, wd.resizable, wd.minimized, wd.maximized, wd.maximized_fs, wd.no_focus || wd.is_popup, wd.parent_hwnd, style, style_ex);
+ _get_window_style(p_window == MAIN_WINDOW_ID, wd.initialized, wd.fullscreen, wd.multiwindow_fs, wd.borderless, wd.resizable, wd.no_min_btn, wd.no_max_btn, wd.minimized, wd.maximized, wd.maximized_fs, wd.no_focus || wd.is_popup, wd.parent_hwnd, style, style_ex);
SetWindowLongPtr(wd.hWnd, GWL_STYLE, style);
SetWindowLongPtr(wd.hWnd, GWL_EXSTYLE, style_ex);
@@ -2535,10 +2555,10 @@ bool DisplayServerWindows::window_is_maximize_allowed(WindowID p_window) const {
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V(!windows.has(p_window), false);
+ const WindowData &wd = windows[p_window];
- // FIXME: Implement this, or confirm that it should always be true.
-
- return true;
+ const DWORD style = GetWindowLongPtr(wd.hWnd, GWL_STYLE);
+ return (style & WS_MAXIMIZEBOX) == WS_MAXIMIZEBOX;
}
void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) {
@@ -2547,6 +2567,14 @@ void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, W
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
switch (p_flag) {
+ case WINDOW_FLAG_MINIMIZE_DISABLED: {
+ wd.no_min_btn = p_enabled;
+ _update_window_style(p_window);
+ } break;
+ case WINDOW_FLAG_MAXIMIZE_DISABLED: {
+ wd.no_max_btn = p_enabled;
+ _update_window_style(p_window);
+ } break;
case WINDOW_FLAG_RESIZE_DISABLED: {
if (p_enabled && wd.parent_hwnd) {
print_line("Embedded window resize can't be disabled.");
@@ -2642,6 +2670,12 @@ bool DisplayServerWindows::window_get_flag(WindowFlags p_flag, WindowID p_window
ERR_FAIL_COND_V(!windows.has(p_window), false);
const WindowData &wd = windows[p_window];
switch (p_flag) {
+ case WINDOW_FLAG_MAXIMIZE_DISABLED: {
+ return wd.no_max_btn;
+ } break;
+ case WINDOW_FLAG_MINIMIZE_DISABLED: {
+ return wd.no_min_btn;
+ } break;
case WINDOW_FLAG_RESIZE_DISABLED: {
return !wd.resizable;
} break;
@@ -6153,7 +6187,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
DWORD dwExStyle;
DWORD dwStyle;
- _get_window_style(window_id_counter == MAIN_WINDOW_ID, false, (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_MINIMIZED, p_mode == WINDOW_MODE_MAXIMIZED, false, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) | (p_flags & WINDOW_FLAG_POPUP_BIT), p_parent_hwnd, dwStyle, dwExStyle);
+ _get_window_style(window_id_counter == MAIN_WINDOW_ID, false, (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_flags & WINDOW_FLAG_MINIMIZE_DISABLED_BIT, p_flags & WINDOW_FLAG_MAXIMIZE_DISABLED_BIT, p_mode == WINDOW_MODE_MINIMIZED, p_mode == WINDOW_MODE_MAXIMIZED, false, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) | (p_flags & WINDOW_FLAG_POPUP_BIT), p_parent_hwnd, dwStyle, dwExStyle);
int rq_screen = get_screen_from_rect(p_rect);
if (rq_screen < 0) {
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index cf50408f760..4365fdcd364 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -479,6 +479,8 @@ class DisplayServerWindows : public DisplayServer {
bool multiwindow_fs = false;
bool borderless = false;
bool resizable = true;
+ bool no_min_btn = false;
+ bool no_max_btn = false;
bool window_focused = false;
int activate_state = 0;
bool was_maximized_pre_fs = false;
@@ -617,7 +619,7 @@ class DisplayServerWindows : public DisplayServer {
HashMap pointer_last_pos;
void _send_window_event(const WindowData &wd, WindowEvent p_event);
- void _get_window_style(bool p_main_window, bool p_initialized, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_minimized, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, bool p_embed_child, DWORD &r_style, DWORD &r_style_ex);
+ void _get_window_style(bool p_main_window, bool p_initialized, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_no_min_btn, bool p_no_max_btn, bool p_minimized, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, bool p_embed_child, DWORD &r_style, DWORD &r_style_ex);
MouseMode mouse_mode;
MouseMode mouse_mode_base = MOUSE_MODE_VISIBLE;
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index feea863e5ae..43aead7c41b 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -448,6 +448,9 @@ AcceptDialog::AcceptDialog() {
set_clamp_to_embedder(true);
set_keep_title_visible(true);
+ set_flag(FLAG_MINIMIZE_DISABLED, true);
+ set_flag(FLAG_MAXIMIZE_DISABLED, true);
+
bg_panel = memnew(Panel);
add_child(bg_panel, false, INTERNAL_MODE_FRONT);
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index cb88492d2c3..11d74e04065 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -223,6 +223,8 @@ Popup::Popup() {
set_transient(true);
set_flag(FLAG_BORDERLESS, true);
set_flag(FLAG_RESIZE_DISABLED, true);
+ set_flag(FLAG_MINIMIZE_DISABLED, true);
+ set_flag(FLAG_MAXIMIZE_DISABLED, true);
set_flag(FLAG_POPUP, true);
set_flag(FLAG_POPUP_WM_HINT, true);
}
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index f5e19d2eef7..50368ed10c4 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -3106,6 +3106,8 @@ void Window::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "sharp_corners"), "set_flag", "get_flag", FLAG_SHARP_CORNERS);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "exclude_from_capture"), "set_flag", "get_flag", FLAG_EXCLUDE_FROM_CAPTURE);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "popup_wm_hint"), "set_flag", "get_flag", FLAG_POPUP_WM_HINT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "minimize_disabled"), "set_flag", "get_flag", FLAG_MINIMIZE_DISABLED);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "maximize_disabled"), "set_flag", "get_flag", FLAG_MAXIMIZE_DISABLED);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_native"), "set_force_native", "get_force_native");
ADD_GROUP("Limits", "");
@@ -3163,6 +3165,8 @@ void Window::_bind_methods() {
BIND_ENUM_CONSTANT(FLAG_SHARP_CORNERS);
BIND_ENUM_CONSTANT(FLAG_EXCLUDE_FROM_CAPTURE);
BIND_ENUM_CONSTANT(FLAG_POPUP_WM_HINT);
+ BIND_ENUM_CONSTANT(FLAG_MINIMIZE_DISABLED);
+ BIND_ENUM_CONSTANT(FLAG_MAXIMIZE_DISABLED);
BIND_ENUM_CONSTANT(FLAG_MAX);
BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_DISABLED);
diff --git a/scene/main/window.h b/scene/main/window.h
index abce073bc51..505582bfa47 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -65,6 +65,8 @@ public:
FLAG_SHARP_CORNERS = DisplayServer::WINDOW_FLAG_SHARP_CORNERS,
FLAG_EXCLUDE_FROM_CAPTURE = DisplayServer::WINDOW_FLAG_EXCLUDE_FROM_CAPTURE,
FLAG_POPUP_WM_HINT = DisplayServer::WINDOW_FLAG_POPUP_WM_HINT,
+ FLAG_MINIMIZE_DISABLED = DisplayServer::WINDOW_FLAG_MINIMIZE_DISABLED,
+ FLAG_MAXIMIZE_DISABLED = DisplayServer::WINDOW_FLAG_MAXIMIZE_DISABLED,
FLAG_MAX = DisplayServer::WINDOW_FLAG_MAX,
};
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 32fdc36cbe4..0403f2f0eec 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -1198,6 +1198,8 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(WINDOW_FLAG_SHARP_CORNERS);
BIND_ENUM_CONSTANT(WINDOW_FLAG_EXCLUDE_FROM_CAPTURE);
BIND_ENUM_CONSTANT(WINDOW_FLAG_POPUP_WM_HINT);
+ BIND_ENUM_CONSTANT(WINDOW_FLAG_MINIMIZE_DISABLED);
+ BIND_ENUM_CONSTANT(WINDOW_FLAG_MAXIMIZE_DISABLED);
BIND_ENUM_CONSTANT(WINDOW_FLAG_MAX);
BIND_ENUM_CONSTANT(WINDOW_EVENT_MOUSE_ENTER);
diff --git a/servers/display_server.h b/servers/display_server.h
index 345d0752bdb..fcad959008c 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -409,6 +409,8 @@ public:
WINDOW_FLAG_SHARP_CORNERS,
WINDOW_FLAG_EXCLUDE_FROM_CAPTURE,
WINDOW_FLAG_POPUP_WM_HINT,
+ WINDOW_FLAG_MINIMIZE_DISABLED,
+ WINDOW_FLAG_MAXIMIZE_DISABLED,
WINDOW_FLAG_MAX,
};
@@ -425,6 +427,8 @@ public:
WINDOW_FLAG_SHARP_CORNERS_BIT = (1 << WINDOW_FLAG_SHARP_CORNERS),
WINDOW_FLAG_EXCLUDE_FROM_CAPTURE_BIT = (1 << WINDOW_FLAG_EXCLUDE_FROM_CAPTURE),
WINDOW_FLAG_POPUP_WM_HINT_BIT = (1 << WINDOW_FLAG_POPUP_WM_HINT),
+ WINDOW_FLAG_MINIMIZE_DISABLED_BIT = (1 << WINDOW_FLAG_MINIMIZE_DISABLED),
+ WINDOW_FLAG_MAXIMIZE_DISABLED_BIT = (1 << WINDOW_FLAG_MAXIMIZE_DISABLED),
};
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), bool p_exclusive = false, WindowID p_transient_parent = INVALID_WINDOW_ID);