Merge pull request #97005 from Repiteo/core/window-corner-style

Core: Add `DisplayServer` flag for sharp corners
This commit is contained in:
Thaddeus Crews 2024-10-21 16:39:25 -05:00
commit 7dbea98c49
No known key found for this signature in database
GPG key ID: 62181B86FE9E5D84
11 changed files with 62 additions and 2 deletions

View file

@ -1477,6 +1477,7 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("display/window/size/transparent", false);
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(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

@ -2099,7 +2099,11 @@
<constant name="WINDOW_FLAG_MOUSE_PASSTHROUGH" value="7" enum="WindowFlags">
All mouse events are passed to the underlying window of the same application.
</constant>
<constant name="WINDOW_FLAG_MAX" value="8" enum="WindowFlags">
<constant name="WINDOW_FLAG_SHARP_CORNERS" value="8" enum="WindowFlags">
Window style is overridden, forcing sharp corners.
[b]Note:[/b] This flag is implemented only on Windows (11).
</constant>
<constant name="WINDOW_FLAG_MAX" value="9" enum="WindowFlags">
Max value of the [enum WindowFlags].
</constant>
<constant name="WINDOW_EVENT_MOUSE_ENTER" value="0" enum="WindowEvent">

View file

@ -875,6 +875,10 @@
[b]Note:[/b] Certain window managers can be configured to ignore the non-resizable status of a window. Do not rely on this setting as a guarantee that the window will [i]never[/i] be resizable.
[b]Note:[/b] This setting is ignored on iOS.
</member>
<member name="display/window/size/sharp_corners" type="bool" setter="" getter="" default="false">
If [code]true[/code], the main window uses sharp corners by default.
[b]Note:[/b] This property is implemented only on Windows (11).
</member>
<member name="display/window/size/transparent" type="bool" setter="" getter="" default="false">
If [code]true[/code], enables a window manager hint that the main window background [i]can[/i] be transparent. This does not make the background actually transparent. For the background to be transparent, the root viewport must also be made transparent by enabling [member rendering/viewport/transparent_background].
[b]Note:[/b] To use a transparent splash screen, set [member application/boot_splash/bg_color] to [code]Color(0, 0, 0, 0)[/code].

View file

@ -659,6 +659,11 @@
If [member ProjectSettings.display/window/subwindows/embed_subwindows] is [code]false[/code], the position is in absolute screen coordinates. This typically applies to editor plugins. If the setting is [code]true[/code], the window's position is in the coordinates of its parent [Viewport].
[b]Note:[/b] This property only works if [member initial_position] is set to [constant WINDOW_INITIAL_POSITION_ABSOLUTE].
</member>
<member name="sharp_corners" type="bool" setter="set_flag" getter="get_flag" default="false">
If [code]true[/code], the [Window] will override the OS window style to display sharp corners.
[b]Note:[/b] This property is implemented only on Windows (11).
[b]Note:[/b] This property only works with native windows.
</member>
<member name="size" type="Vector2i" setter="set_size" getter="get_size" default="Vector2i(100, 100)">
The window's size in pixels.
</member>
@ -842,7 +847,12 @@
All mouse events are passed to the underlying window of the same application.
[b]Note:[/b] This flag has no effect in embedded windows.
</constant>
<constant name="FLAG_MAX" value="8" enum="Flags">
<constant name="FLAG_SHARP_CORNERS" value="8" enum="Flags">
Window style is overridden, forcing sharp corners.
[b]Note:[/b] This flag has no effect in embedded windows.
[b]Note:[/b] This flag is implemented only on Windows (11).
</constant>
<constant name="FLAG_MAX" value="9" enum="Flags">
Max value of the [enum Flags].
</constant>
<constant name="CONTENT_SCALE_MODE_DISABLED" value="0" enum="ContentScaleMode">

View file

@ -2413,6 +2413,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
if (bool(GLOBAL_GET("display/window/size/no_focus"))) {
window_flags |= DisplayServer::WINDOW_FLAG_NO_FOCUS_BIT;
}
if (bool(GLOBAL_GET("display/window/size/sharp_corners"))) {
window_flags |= DisplayServer::WINDOW_FLAG_SHARP_CORNERS_BIT;
}
window_mode = (DisplayServer::WindowMode)(GLOBAL_GET("display/window/size/mode").operator int());
int initial_position_type = GLOBAL_GET("display/window/size/initial_position_type").operator int();
if (initial_position_type == 0) { // Absolute.

View file

@ -67,6 +67,18 @@
#define DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 19
#endif
#ifndef DWMWA_WINDOW_CORNER_PREFERENCE
#define DWMWA_WINDOW_CORNER_PREFERENCE 33
#endif
#ifndef DWMWCP_DEFAULT
#define DWMWCP_DEFAULT 0
#endif
#ifndef DWMWCP_DONOTROUND
#define DWMWCP_DONOTROUND 1
#endif
#define WM_INDICATOR_CALLBACK_MESSAGE (WM_USER + 1)
#if defined(__GNUC__)
@ -1483,6 +1495,9 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod
if (p_flags & WINDOW_FLAG_ALWAYS_ON_TOP_BIT && p_mode != WINDOW_MODE_FULLSCREEN && p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
wd.always_on_top = true;
}
if (p_flags & WINDOW_FLAG_SHARP_CORNERS_BIT) {
wd.sharp_corners = true;
}
if (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) {
wd.no_focus = true;
}
@ -2297,6 +2312,12 @@ void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, W
wd.always_on_top = p_enabled;
_update_window_style(p_window);
} break;
case WINDOW_FLAG_SHARP_CORNERS: {
wd.sharp_corners = p_enabled;
DWORD value = wd.sharp_corners ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT;
::DwmSetWindowAttribute(wd.hWnd, DWMWA_WINDOW_CORNER_PREFERENCE, &value, sizeof(value));
_update_window_style(p_window);
} break;
case WINDOW_FLAG_TRANSPARENT: {
if (p_enabled) {
// Enable per-pixel alpha.
@ -3994,6 +4015,10 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
native_menu->_menu_activate(HMENU(lParam), (int)wParam);
} break;
case WM_CREATE: {
{
DWORD value = windows[window_id].sharp_corners ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT;
::DwmSetWindowAttribute(windows[window_id].hWnd, DWMWA_WINDOW_CORNER_PREFERENCE, &value, sizeof(value));
}
if (is_dark_mode_supported() && dark_title_available) {
BOOL value = is_dark_mode();
@ -5645,6 +5670,12 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
wd_transient_parent->transient_children.insert(id);
}
wd.sharp_corners = p_flags & WINDOW_FLAG_SHARP_CORNERS_BIT;
{
DWORD value = wd.sharp_corners ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT;
::DwmSetWindowAttribute(wd.hWnd, DWMWA_WINDOW_CORNER_PREFERENCE, &value, sizeof(value));
}
if (is_dark_mode_supported() && dark_title_available) {
BOOL value = is_dark_mode();
::DwmSetWindowAttribute(wd.hWnd, use_legacy_dark_mode_before_20H1 ? DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 : DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));

View file

@ -474,6 +474,7 @@ class DisplayServerWindows : public DisplayServer {
bool exclusive = false;
bool context_created = false;
bool mpass = false;
bool sharp_corners = false;
// Used to transfer data between events using timer.
WPARAM saved_wparam;

View file

@ -3008,6 +3008,7 @@ void Window::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "popup_window"), "set_flag", "get_flag", FLAG_POPUP);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "extend_to_title"), "set_flag", "get_flag", FLAG_EXTEND_TO_TITLE);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "mouse_passthrough"), "set_flag", "get_flag", FLAG_MOUSE_PASSTHROUGH);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "sharp_corners"), "set_flag", "get_flag", FLAG_SHARP_CORNERS);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_native"), "set_force_native", "get_force_native");
ADD_GROUP("Limits", "");
@ -3061,6 +3062,7 @@ void Window::_bind_methods() {
BIND_ENUM_CONSTANT(FLAG_POPUP);
BIND_ENUM_CONSTANT(FLAG_EXTEND_TO_TITLE);
BIND_ENUM_CONSTANT(FLAG_MOUSE_PASSTHROUGH);
BIND_ENUM_CONSTANT(FLAG_SHARP_CORNERS);
BIND_ENUM_CONSTANT(FLAG_MAX);
BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_DISABLED);

View file

@ -62,6 +62,7 @@ public:
FLAG_POPUP = DisplayServer::WINDOW_FLAG_POPUP,
FLAG_EXTEND_TO_TITLE = DisplayServer::WINDOW_FLAG_EXTEND_TO_TITLE,
FLAG_MOUSE_PASSTHROUGH = DisplayServer::WINDOW_FLAG_MOUSE_PASSTHROUGH,
FLAG_SHARP_CORNERS = DisplayServer::WINDOW_FLAG_SHARP_CORNERS,
FLAG_MAX = DisplayServer::WINDOW_FLAG_MAX,
};

View file

@ -1128,6 +1128,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(WINDOW_FLAG_POPUP);
BIND_ENUM_CONSTANT(WINDOW_FLAG_EXTEND_TO_TITLE);
BIND_ENUM_CONSTANT(WINDOW_FLAG_MOUSE_PASSTHROUGH);
BIND_ENUM_CONSTANT(WINDOW_FLAG_SHARP_CORNERS);
BIND_ENUM_CONSTANT(WINDOW_FLAG_MAX);
BIND_ENUM_CONSTANT(WINDOW_EVENT_MOUSE_ENTER);

View file

@ -381,6 +381,7 @@ public:
WINDOW_FLAG_POPUP,
WINDOW_FLAG_EXTEND_TO_TITLE,
WINDOW_FLAG_MOUSE_PASSTHROUGH,
WINDOW_FLAG_SHARP_CORNERS,
WINDOW_FLAG_MAX,
};
@ -394,6 +395,7 @@ public:
WINDOW_FLAG_POPUP_BIT = (1 << WINDOW_FLAG_POPUP),
WINDOW_FLAG_EXTEND_TO_TITLE_BIT = (1 << WINDOW_FLAG_EXTEND_TO_TITLE),
WINDOW_FLAG_MOUSE_PASSTHROUGH_BIT = (1 << WINDOW_FLAG_MOUSE_PASSTHROUGH),
WINDOW_FLAG_SHARP_CORNERS_BIT = (1 << WINDOW_FLAG_SHARP_CORNERS),
};
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);