1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 16:37:47 +00:00

LibGUI+WindowServer: Notify Windows on input preemption

Previously Menus set themselves as active input solely to make
sure CaptureInput modals would close, but this is a functional
half-truth. Menus don't actually use the active input role; they
preempt normal Windows during event handling instead.

Now the active input window is notified on preemption and Menus
can remain outside the active input concept. This lets us make
more granular choices about modal behavior. For now, the only
thing clients care about is menu preemption on popup.

Fixes windows which close on changes to active input closing
on their own context menus.
This commit is contained in:
thankyouverycool 2022-09-07 07:49:00 -04:00 committed by Linus Groh
parent 6c35aac617
commit 463aff827e
13 changed files with 48 additions and 15 deletions

View file

@ -117,6 +117,7 @@ ComboBox::ComboBox()
}
m_open_button->set_enabled(true);
};
m_list_window->on_input_preemption = [this](auto) { close(); };
m_list_view = m_list_window->set_main_widget<ListView>();
m_list_view->horizontal_scrollbar().set_visible(false);

View file

@ -227,6 +227,11 @@ CommandPalette::CommandPalette(GUI::Window& parent_window, ScreenPosition screen
if (!is_active_window)
close();
};
on_input_preemption = [this](InputPreemptor preemptor) {
if (preemptor != InputPreemptor::ContextMenu)
close();
};
}
void CommandPalette::collect_actions(GUI::Window& parent_window)

View file

@ -401,6 +401,12 @@ void ConnectionToWindowServer::window_state_changed(i32 window_id, bool minimize
window->notify_state_changed({}, minimized, maximized, occluded);
}
void ConnectionToWindowServer::window_input_preempted(i32 window_id, i32 preemptor)
{
if (auto* window = Window::from_window_id(window_id))
window->notify_input_preempted({}, static_cast<InputPreemptor>(preemptor));
}
void ConnectionToWindowServer::display_link_notification()
{
if (m_display_link_notification_pending)

View file

@ -54,6 +54,7 @@ private:
virtual void update_system_fonts(String const&, String const&, String const&) override;
virtual void update_system_effects(Vector<bool> const&) override;
virtual void window_state_changed(i32, bool, bool, bool) override;
virtual void window_input_preempted(i32, i32) override;
virtual void display_link_notification() override;
virtual void track_mouse_move(Gfx::IntPoint const&) override;
virtual void ping() override;

View file

@ -1110,6 +1110,12 @@ void Window::notify_state_changed(Badge<ConnectionToWindowServer>, bool minimize
}
}
void Window::notify_input_preempted(Badge<ConnectionToWindowServer>, InputPreemptor preemptor)
{
if (on_input_preemption)
on_input_preemption(preemptor);
}
Action* Window::action_for_shortcut(Shortcut const& shortcut)
{
Action* found_action = nullptr;

View file

@ -91,6 +91,7 @@ public:
Function<CloseRequestDecision()> on_close_request;
Function<void(bool is_active_input)> on_active_input_change;
Function<void(bool is_active_window)> on_active_window_change;
Function<void(InputPreemptor)> on_input_preemption;
int x() const { return rect().x(); }
int y() const { return rect().y(); }
@ -197,6 +198,7 @@ public:
static void for_each_window(Badge<ConnectionToWindowServer>, Function<void(Window&)>);
static void update_all_windows(Badge<ConnectionToWindowServer>);
void notify_state_changed(Badge<ConnectionToWindowServer>, bool minimized, bool maximized, bool occluded);
void notify_input_preempted(Badge<ConnectionToWindowServer>, InputPreemptor);
virtual bool is_visible_for_timer_purposes() const override { return m_visible_for_timer_purposes; }

View file

@ -11,5 +11,6 @@
namespace GUI {
using WindowMode = WindowServer::WindowMode;
using InputPreemptor = WindowServer::InputPreemptor;
}