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

Make PopupMenu hide after its parent window loss focus #98245

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
26 changes: 26 additions & 0 deletions scene/gui/popup_menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,12 @@ void PopupMenu::_parent_focused() {
}
}

void PopupMenu::_parent_unfocused() {
if (hide_on_parent_unfocused && !is_embedded()) {
hide();
}
}

void PopupMenu::_submenu_timeout() {
if (mouse_over == submenu_over) {
_activate_submenu(mouse_over);
Expand Down Expand Up @@ -1018,12 +1024,20 @@ void PopupMenu::_notification(int p_what) {
if (system_menu_id != NativeMenu::INVALID_MENU_ID) {
bind_global_menu();
}

if (Window *p = get_transient_parent()) {
p->connect(SceneStringName(focus_exited), callable_mp(this, &PopupMenu::_parent_unfocused));
}
} break;

case NOTIFICATION_EXIT_TREE: {
if (system_menu_id != NativeMenu::INVALID_MENU_ID) {
unbind_global_menu();
}

if (Window *p = get_transient_parent()) {
p->disconnect(SceneStringName(focus_exited), callable_mp(this, &PopupMenu::_parent_unfocused));
}
} break;

case NOTIFICATION_THEME_CHANGED: {
Expand Down Expand Up @@ -2556,6 +2570,14 @@ bool PopupMenu::is_hide_on_multistate_item_selection() const {
return hide_on_multistate_item_selection;
}

void PopupMenu::set_hide_on_parent_unfocused(bool p_enabled) {
hide_on_parent_unfocused = p_enabled;
}

bool PopupMenu::is_hide_on_parent_unfocused() const {
return hide_on_parent_unfocused;
}

void PopupMenu::set_submenu_popup_delay(float p_time) {
if (p_time <= 0) {
p_time = 0.01;
Expand Down Expand Up @@ -2740,6 +2762,9 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_hide_on_state_item_selection", "enable"), &PopupMenu::set_hide_on_multistate_item_selection);
ClassDB::bind_method(D_METHOD("is_hide_on_state_item_selection"), &PopupMenu::is_hide_on_multistate_item_selection);

ClassDB::bind_method(D_METHOD("set_hide_on_parent_unfocused", "enable"), &PopupMenu::set_hide_on_parent_unfocused);
ClassDB::bind_method(D_METHOD("is_hide_on_parent_unfocused"), &PopupMenu::is_hide_on_parent_unfocused);

ClassDB::bind_method(D_METHOD("set_submenu_popup_delay", "seconds"), &PopupMenu::set_submenu_popup_delay);
ClassDB::bind_method(D_METHOD("get_submenu_popup_delay"), &PopupMenu::get_submenu_popup_delay);

Expand All @@ -2753,6 +2778,7 @@ void PopupMenu::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_item_selection"), "set_hide_on_item_selection", "is_hide_on_item_selection");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_checkable_item_selection"), "set_hide_on_checkable_item_selection", "is_hide_on_checkable_item_selection");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_state_item_selection"), "set_hide_on_state_item_selection", "is_hide_on_state_item_selection");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_parent_unfocused"), "set_hide_on_parent_unfocused", "is_hide_on_parent_unfocused");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "submenu_popup_delay", PROPERTY_HINT_NONE, "suffix:s"), "set_submenu_popup_delay", "get_submenu_popup_delay");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_search"), "set_allow_search", "get_allow_search");
ADD_PROPERTY(PropertyInfo(Variant::INT, "system_menu_id", PROPERTY_HINT_ENUM, "None:0,Application Menu:2,Window Menu:3,Help Menu:4,Dock:5"), "set_system_menu", "get_system_menu");
Expand Down
5 changes: 5 additions & 0 deletions scene/gui/popup_menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class PopupMenu : public Popup {
bool hide_on_item_selection = true;
bool hide_on_checkable_item_selection = true;
bool hide_on_multistate_item_selection = false;
bool hide_on_parent_unfocused = true;
Vector2 moved;

HashMap<Ref<Shortcut>, int> shortcut_refcount;
Expand Down Expand Up @@ -209,6 +210,7 @@ class PopupMenu : public Popup {
bool _set_item_accelerator(int p_index, const Ref<InputEventKey> &p_ie);
void _set_item_checkable_type(int p_index, int p_checkable_type);
int _get_item_checkable_type(int p_index) const;
void _parent_unfocused();

protected:
virtual void add_child_notify(Node *p_child) override;
Expand Down Expand Up @@ -360,6 +362,9 @@ class PopupMenu : public Popup {
void set_hide_on_multistate_item_selection(bool p_enabled);
bool is_hide_on_multistate_item_selection() const;

void set_hide_on_parent_unfocused(bool p_enabled);
bool is_hide_on_parent_unfocused() const;

void set_submenu_popup_delay(float p_time);
float get_submenu_popup_delay() const;

Expand Down
20 changes: 19 additions & 1 deletion scene/main/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ void Window::_clear_window() {
window_id = DisplayServer::INVALID_WINDOW_ID;

// If closing window was focused and has a parent, return focus.
if (had_focus && transient_parent) {
if (return_to_transient && had_focus && transient_parent) {
transient_parent->grab_focus();
}

Expand Down Expand Up @@ -995,6 +995,16 @@ bool Window::is_transient_to_focused() const {
return transient_to_focused;
}

void Window::set_return_to_transient(bool p_return_to_transient) {
ERR_MAIN_THREAD_GUARD;
return_to_transient = p_return_to_transient;
}

bool Window::is_return_to_transient() const {
ERR_READ_THREAD_GUARD_V(false);
return return_to_transient;
}

void Window::set_exclusive(bool p_exclusive) {
ERR_MAIN_THREAD_GUARD;
if (exclusive == p_exclusive) {
Expand Down Expand Up @@ -1716,6 +1726,10 @@ Window *Window::get_parent_visible_window() const {
return window;
}

Window *Window::get_transient_parent() const {
return transient_parent;
}

void Window::popup_on_parent(const Rect2i &p_parent_rect) {
ERR_MAIN_THREAD_GUARD;
ERR_FAIL_COND(!is_inside_tree());
Expand Down Expand Up @@ -2858,6 +2872,9 @@ void Window::_bind_methods() {
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_return_to_transient", "enable"), &Window::set_return_to_transient);
ClassDB::bind_method(D_METHOD("is_return_to_transient"), &Window::is_return_to_transient);

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 @@ -2992,6 +3009,7 @@ void Window::_bind_methods() {
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, "return_to_transient"), "set_return_to_transient", "is_return_to_transient");
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
5 changes: 5 additions & 0 deletions scene/main/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class Window : public Viewport {
bool use_font_oversampling = false;
bool transient = false;
bool transient_to_focused = false;
bool return_to_transient = false;
bool exclusive = false;
bool wrap_controls = false;
bool updating_child_controls = false;
Expand Down Expand Up @@ -322,6 +323,9 @@ class Window : public Viewport {
void set_transient_to_focused(bool p_transient_to_focused);
bool is_transient_to_focused() const;

void set_return_to_transient(bool p_return_to_transient);
bool is_return_to_transient() const;

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

Expand Down Expand Up @@ -371,6 +375,7 @@ class Window : public Viewport {
Window *get_exclusive_child() const { return exclusive_child; };
Window *get_parent_visible_window() const;
Viewport *get_parent_viewport() const;
Window *get_transient_parent() const;

virtual void popup(const Rect2i &p_screen_rect = Rect2i());
void popup_on_parent(const Rect2i &p_parent_rect);
Expand Down
Loading