1
0
mirror of https://github.com/godotengine/godot.git synced 2026-01-04 19:21:46 +00:00

Merge pull request #105107 from bruvzg/min-max-flag

Add separate `minimize_disabled` and `maximize_disabled` window flags.
This commit is contained in:
Thaddeus Crews
2025-04-08 12:32:44 -05:00
20 changed files with 212 additions and 20 deletions

View File

@@ -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

View File

@@ -73,6 +73,8 @@
</member>
<member name="exclusive" type="bool" setter="set_exclusive" getter="is_exclusive" overrides="Window" default="true" />
<member name="keep_title_visible" type="bool" setter="set_keep_title_visible" getter="get_keep_title_visible" overrides="Window" default="true" />
<member name="maximize_disabled" type="bool" setter="set_flag" getter="get_flag" overrides="Window" default="true" />
<member name="minimize_disabled" type="bool" setter="set_flag" getter="get_flag" overrides="Window" default="true" />
<member name="ok_button_text" type="String" setter="set_ok_button_text" getter="get_ok_button_text" default="&quot;&quot;">
The text displayed by the OK button (see [method get_ok_button]). If empty, a default text will be used.
</member>

View File

@@ -2195,7 +2195,15 @@
<constant name="WINDOW_FLAG_POPUP_WM_HINT" value="10" enum="WindowFlags">
Signals the window manager that this window is supposed to be an implementation-defined "popup" (usually a floating, borderless, untileable and immovable child window).
</constant>
<constant name="WINDOW_FLAG_MAX" value="11" enum="WindowFlags">
<constant name="WINDOW_FLAG_MINIMIZE_DISABLED" value="11" enum="WindowFlags">
Window minimize button is disabled.
[b]Note:[/b] This flag is implemented on macOS and Windows.
</constant>
<constant name="WINDOW_FLAG_MAXIMIZE_DISABLED" value="12" enum="WindowFlags">
Window maximize button is disabled.
[b]Note:[/b] This flag is implemented on macOS and Windows.
</constant>
<constant name="WINDOW_FLAG_MAX" value="13" enum="WindowFlags">
Max value of the [enum WindowFlags].
</constant>
<constant name="WINDOW_EVENT_MOUSE_ENTER" value="0" enum="WindowEvent">

View File

@@ -10,6 +10,8 @@
</tutorials>
<members>
<member name="borderless" type="bool" setter="set_flag" getter="get_flag" overrides="Window" default="true" />
<member name="maximize_disabled" type="bool" setter="set_flag" getter="get_flag" overrides="Window" default="true" />
<member name="minimize_disabled" type="bool" setter="set_flag" getter="get_flag" overrides="Window" default="true" />
<member name="popup_window" type="bool" setter="set_flag" getter="get_flag" overrides="Window" default="true" />
<member name="popup_wm_hint" type="bool" setter="set_flag" getter="get_flag" overrides="Window" default="true" />
<member name="transient" type="bool" setter="set_transient" getter="is_transient" overrides="Window" default="true" />

View File

@@ -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.
</member>
<member name="display/window/size/maximize_disabled" type="bool" setter="" getter="" default="false">
If [code]true[/code], the main window's maximize button is disabled.
</member>
<member name="display/window/size/minimize_disabled" type="bool" setter="" getter="" default="false">
If [code]true[/code], the main window's minimize button is disabled.
</member>
<member name="display/window/size/mode" type="int" setter="" getter="" default="0">
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.

View File

@@ -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].
</member>
<member name="maximize_disabled" type="bool" setter="set_flag" getter="get_flag" default="false">
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.
</member>
<member name="min_size" type="Vector2i" setter="set_min_size" getter="get_min_size" default="Vector2i(0, 0)">
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.
</member>
<member name="minimize_disabled" type="bool" setter="set_flag" getter="get_flag" default="false">
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.
</member>
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="Window.Mode" default="0">
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.
</member>
<member name="unresizable" type="bool" setter="set_flag" getter="get_flag" default="false">
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.
</member>
<member name="visible" type="bool" setter="set_visible" getter="is_visible" default="true">
If [code]true[/code], the window is visible.
@@ -887,7 +897,15 @@
<constant name="FLAG_POPUP_WM_HINT" value="10" enum="Flags">
Signals the window manager that this window is supposed to be an implementation-defined "popup" (usually a floating, borderless, untileable and immovable child window).
</constant>
<constant name="FLAG_MAX" value="11" enum="Flags">
<constant name="FLAG_MINIMIZE_DISABLED" value="11" enum="Flags">
Window minimize button is disabled.
[b]Note:[/b] This flag is implemented on macOS and Windows.
</constant>
<constant name="FLAG_MAXIMIZE_DISABLED" value="12" enum="Flags">
Window maximize button is disabled.
[b]Note:[/b] This flag is implemented on macOS and Windows.
</constant>
<constant name="FLAG_MAX" value="13" enum="Flags">
Max value of the [enum Flags].
</constant>
<constant name="CONTENT_SCALE_MODE_DISABLED" value="0" enum="ContentScaleMode">

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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<Atom> 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.

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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<int64_t, Vector2> 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;

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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,
};

View File

@@ -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);

View File

@@ -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);