Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core: Add DisplayServer flag for sharp corners #97005

Merged
merged 1 commit into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/config/project_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1460,6 +1460,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
Expand Down
6 changes: 5 additions & 1 deletion doc/classes/DisplayServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down
4 changes: 4 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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].
Expand Down
12 changes: 11 additions & 1 deletion doc/classes/Window.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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">
Expand Down
3 changes: 3 additions & 0 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2412,6 +2412,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.
Expand Down
31 changes: 31 additions & 0 deletions platform/windows/display_server_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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));
Expand Down
1 change: 1 addition & 0 deletions platform/windows/display_server_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,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;
Expand Down
2 changes: 2 additions & 0 deletions scene/main/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3001,6 +3001,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", "");
Expand Down Expand Up @@ -3054,6 +3055,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);
Expand Down
1 change: 1 addition & 0 deletions scene/main/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class Window : public Viewport {
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,
};

Expand Down
1 change: 1 addition & 0 deletions servers/display_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions servers/display_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ class DisplayServer : public Object {
WINDOW_FLAG_POPUP,
WINDOW_FLAG_EXTEND_TO_TITLE,
WINDOW_FLAG_MOUSE_PASSTHROUGH,
WINDOW_FLAG_SHARP_CORNERS,
WINDOW_FLAG_MAX,
};

Expand All @@ -394,6 +395,7 @@ class DisplayServer : public Object {
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);
Expand Down
Loading