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

Implement a transient_to_focused Window mode #86446

Merged
merged 1 commit into from
Jan 15, 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
3 changes: 3 additions & 0 deletions doc/classes/Window.xml
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,9 @@
If [code]true[/code], the [Window] is transient, i.e. it's considered a child of another [Window]. The transient window will be destroyed with its transient parent and will return focus to their parent when closed. The transient window is displayed on top of a non-exclusive full-screen parent window. Transient windows can't enter full-screen mode.
Note that behavior might be different depending on the platform.
</member>
<member name="transient_to_focused" type="bool" setter="set_transient_to_focused" getter="is_transient_to_focused" default="false">
If [code]true[/code], and the [Window] is [member transient], this window will (at the time of becoming visible) become transient to the currently focused window instead of the immediate parent window in the hierarchy. Note that the transient parent is assigned at the time this window becomes visible, so changing it afterwards has no effect until re-shown.
</member>
<member name="transparent" type="bool" setter="set_flag" getter="get_flag" default="false">
If [code]true[/code], the [Window]'s background can be transparent. This is best used with embedded windows.
[b]Note:[/b] Transparency support is implemented on Linux, macOS and Windows, but availability might vary depending on GPU driver, display manager, and compositor capabilities.
Expand Down
1 change: 1 addition & 0 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7803,6 +7803,7 @@ EditorNode::EditorNode() {
file = memnew(EditorFileDialog);
gui_base->add_child(file);
file->set_current_dir("res://");
file->set_transient_to_focused(true);

file_export_lib = memnew(EditorFileDialog);
file_export_lib->set_title(TTR("Export Library"));
Expand Down
5 changes: 5 additions & 0 deletions platform/linuxbsd/x11/display_server_x11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2891,10 +2891,15 @@ void DisplayServerX11::window_move_to_foreground(WindowID p_window) {
XFlush(x11_display);
}

DisplayServerX11::WindowID DisplayServerX11::get_focused_window() const {
return last_focused_window;
Sauermann marked this conversation as resolved.
Show resolved Hide resolved
}

bool DisplayServerX11::window_is_focused(WindowID p_window) const {
_THREAD_SAFE_METHOD_

ERR_FAIL_COND_V(!windows.has(p_window), false);

const WindowData &wd = windows[p_window];

return wd.focused;
Expand Down
2 changes: 2 additions & 0 deletions platform/linuxbsd/x11/display_server_x11.h
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,8 @@ class DisplayServerX11 : public DisplayServer {
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override;

virtual WindowID get_focused_window() const override;

virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;

virtual bool can_any_window_draw() const override;
Expand Down
2 changes: 2 additions & 0 deletions platform/macos/display_server_macos.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,8 @@ class DisplayServerMacOS : public DisplayServer {
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override;

virtual WindowID get_focused_window() const override;

virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;

virtual bool can_any_window_draw() const override;
Expand Down
4 changes: 4 additions & 0 deletions platform/macos/display_server_macos.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3723,6 +3723,10 @@ - (void)popupAction:(id)sender {
return wd.focused;
}

DisplayServerMacOS::WindowID DisplayServerMacOS::get_focused_window() const {
return last_focused_window;
}

bool DisplayServerMacOS::window_can_draw(WindowID p_window) const {
return windows[p_window].is_visible;
}
Expand Down
4 changes: 4 additions & 0 deletions platform/windows/display_server_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1916,6 +1916,10 @@ bool DisplayServerWindows::window_is_focused(WindowID p_window) const {
return wd.window_focused;
}

DisplayServerWindows::WindowID DisplayServerWindows::get_focused_window() const {
return last_focused_window;
}

bool DisplayServerWindows::window_can_draw(WindowID p_window) const {
_THREAD_SAFE_METHOD_

Expand Down
2 changes: 2 additions & 0 deletions platform/windows/display_server_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,8 @@ class DisplayServerWindows : public DisplayServer {
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override;

virtual WindowID get_focused_window() const override;

virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;

virtual bool can_any_window_draw() const override;
Expand Down
62 changes: 50 additions & 12 deletions scene/main/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,10 @@ bool Window::is_in_edited_scene_root() const {
void Window::_make_window() {
ERR_FAIL_COND(window_id != DisplayServer::INVALID_WINDOW_ID);

if (transient && transient_to_focused) {
_make_transient();
}

uint32_t f = 0;
for (int i = 0; i < FLAG_MAX; i++) {
if (flags[i]) {
Expand Down Expand Up @@ -665,6 +669,10 @@ void Window::_clear_window() {

_update_viewport_size();
RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED);

if (transient && transient_to_focused) {
_clear_transient();
}
}

void Window::_rect_changed_callback(const Rect2i &p_callback) {
Expand Down Expand Up @@ -864,18 +872,29 @@ void Window::_make_transient() {
return;
}
//find transient parent
Viewport *vp = get_parent()->get_viewport();

Window *window = nullptr;
while (vp) {
window = Object::cast_to<Window>(vp);
if (window) {
break;
}
if (!vp->get_parent()) {
break;

if (!is_embedded() && transient_to_focused) {
DisplayServer::WindowID focused_window_id = DisplayServer::get_singleton()->get_focused_window();
if (focused_window_id != DisplayServer::INVALID_WINDOW_ID) {
window = Object::cast_to<Window>(ObjectDB::get_instance(DisplayServer::get_singleton()->window_get_attached_instance_id(focused_window_id)));
}
}

vp = vp->get_parent()->get_viewport();
if (!window) {
Viewport *vp = get_parent()->get_viewport();
while (vp) {
window = Object::cast_to<Window>(vp);
if (window) {
break;
}
if (!vp->get_parent()) {
break;
}

vp = vp->get_parent()->get_viewport();
}
}

if (window) {
Expand Down Expand Up @@ -919,17 +938,32 @@ void Window::set_transient(bool p_transient) {
}

if (transient) {
_make_transient();
if (!transient_to_focused) {
_make_transient();
}
} else {
_clear_transient();
}
}

bool Window::is_transient() const {
ERR_READ_THREAD_GUARD_V(false);
return transient;
}

void Window::set_transient_to_focused(bool p_transient_to_focused) {
ERR_MAIN_THREAD_GUARD;
if (transient_to_focused == p_transient_to_focused) {
YuriSizov marked this conversation as resolved.
Show resolved Hide resolved
return;
}

transient_to_focused = p_transient_to_focused;
}

bool Window::is_transient_to_focused() const {
ERR_READ_THREAD_GUARD_V(false);
return transient_to_focused;
}

void Window::set_exclusive(bool p_exclusive) {
ERR_MAIN_THREAD_GUARD;
if (exclusive == p_exclusive) {
Expand Down Expand Up @@ -1259,7 +1293,7 @@ void Window::_notification(int p_what) {
}
}

if (transient) {
if (transient && !transient_to_focused) {
_make_transient();
}
if (visible) {
Expand Down Expand Up @@ -2753,6 +2787,9 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transient", "transient"), &Window::set_transient);
ClassDB::bind_method(D_METHOD("is_transient"), &Window::is_transient);

ClassDB::bind_method(D_METHOD("set_transient_to_focused", "enable"), &Window::set_transient_to_focused);
ClassDB::bind_method(D_METHOD("is_transient_to_focused"), &Window::is_transient_to_focused);

ClassDB::bind_method(D_METHOD("set_exclusive", "exclusive"), &Window::set_exclusive);
ClassDB::bind_method(D_METHOD("is_exclusive"), &Window::is_exclusive);

Expand Down Expand Up @@ -2884,6 +2921,7 @@ void Window::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "wrap_controls"), "set_wrap_controls", "is_wrapping_controls");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transient"), "set_transient", "is_transient");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transient_to_focused"), "set_transient_to_focused", "is_transient_to_focused");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclusive"), "set_exclusive", "is_exclusive");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "unresizable"), "set_flag", "get_flag", FLAG_RESIZE_DISABLED);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "borderless"), "set_flag", "get_flag", FLAG_BORDERLESS);
Expand Down
4 changes: 4 additions & 0 deletions scene/main/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class Window : public Viewport {

bool use_font_oversampling = false;
bool transient = false;
bool transient_to_focused = false;
bool exclusive = false;
bool wrap_controls = false;
bool updating_child_controls = false;
Expand Down Expand Up @@ -313,6 +314,9 @@ class Window : public Viewport {
void set_transient(bool p_transient);
bool is_transient() const;

void set_transient_to_focused(bool p_transient_to_focused);
bool is_transient_to_focused() const;

void set_exclusive(bool p_exclusive);
bool is_exclusive() const;

Expand Down
4 changes: 4 additions & 0 deletions servers/display_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,10 @@ DisplayServer::VSyncMode DisplayServer::window_get_vsync_mode(WindowID p_window)
return VSyncMode::VSYNC_ENABLED;
}

DisplayServer::WindowID DisplayServer::get_focused_window() const {
return MAIN_WINDOW_ID; // Proper value for single windows.
}

void DisplayServer::set_context(Context p_context) {
}

Expand Down
2 changes: 2 additions & 0 deletions servers/display_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,8 @@ class DisplayServer : public Object {
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) = 0;
virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const = 0;

virtual WindowID get_focused_window() const;

virtual void window_set_window_buttons_offset(const Vector2i &p_offset, WindowID p_window = MAIN_WINDOW_ID) {}
virtual Vector3i window_get_safe_title_margins(WindowID p_window = MAIN_WINDOW_ID) const { return Vector3i(); }

Expand Down
Loading