mirror of
https://github.com/RGBCube/serenity
synced 2025-06-01 03:08:13 +00:00
WindowServer: Add accessory windows
Accessory windows are windows that, when activated, will activate their parent and bring all other accessory windows of that parent to the front of the window stack. Accessory windows can only be active input windows. The accessory window's parent is always the active window regardless of whether it is also the active input window. In order to route input correctly, input is now sent to the active input window, which can be any accessory window or their parent, or any regular window.
This commit is contained in:
parent
396291b356
commit
ec3737510d
16 changed files with 216 additions and 59 deletions
|
@ -99,8 +99,17 @@ ComboBox::ComboBox()
|
|||
open();
|
||||
};
|
||||
|
||||
m_list_window = add<Window>();
|
||||
m_list_window = add<Window>(window());
|
||||
m_list_window->set_frameless(true);
|
||||
m_list_window->set_accessory(true);
|
||||
|
||||
m_list_window->on_active_input_change = [this](bool is_active_input) {
|
||||
if (!is_active_input) {
|
||||
m_open_button->set_enabled(true);
|
||||
close();
|
||||
}
|
||||
};
|
||||
|
||||
m_list_window->on_activity_change = [this](const bool is_active) {
|
||||
if (!is_active) {
|
||||
m_open_button->set_enabled(false);
|
||||
|
|
|
@ -57,6 +57,8 @@ public:
|
|||
WindowLeft,
|
||||
WindowBecameInactive,
|
||||
WindowBecameActive,
|
||||
WindowInputEntered,
|
||||
WindowInputLeft,
|
||||
FocusIn,
|
||||
FocusOut,
|
||||
WindowCloseRequest,
|
||||
|
|
|
@ -502,9 +502,12 @@ bool Widget::is_focused() const
|
|||
auto* win = window();
|
||||
if (!win)
|
||||
return false;
|
||||
if (!win->is_active())
|
||||
return false;
|
||||
return win->focused_widget() == this;
|
||||
// Accessory windows are not active despite being the active
|
||||
// input window. So we can have focus if either we're the active
|
||||
// input window or we're the active window
|
||||
if (win->is_active_input() || win->is_active())
|
||||
return win->focused_widget() == this;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Widget::set_focus(bool focus)
|
||||
|
|
|
@ -101,6 +101,7 @@ void Window::show()
|
|||
m_resizable,
|
||||
m_fullscreen,
|
||||
m_frameless,
|
||||
m_accessory,
|
||||
m_opacity_when_windowless,
|
||||
m_base_size,
|
||||
m_size_increment,
|
||||
|
@ -338,6 +339,17 @@ void Window::event(Core::Event& event)
|
|||
return;
|
||||
}
|
||||
|
||||
if (event.type() == Event::WindowInputEntered || event.type() == Event::WindowInputLeft) {
|
||||
m_is_active_input = event.type() == Event::WindowInputEntered;
|
||||
if (on_active_input_change)
|
||||
on_active_input_change(m_is_active_input);
|
||||
if (m_main_widget)
|
||||
m_main_widget->dispatch_event(event, this);
|
||||
if (m_focused_widget)
|
||||
m_focused_widget->update();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.type() == Event::WindowCloseRequest) {
|
||||
if (on_close_request) {
|
||||
if (on_close_request() == Window::CloseRequestDecision::StayOpen)
|
||||
|
|
|
@ -98,6 +98,7 @@ public:
|
|||
};
|
||||
|
||||
Function<CloseRequestDecision()> on_close_request;
|
||||
Function<void(bool is_active_input)> on_active_input_change;
|
||||
Function<void(const bool is_active)> on_activity_change;
|
||||
|
||||
int x() const { return rect().x(); }
|
||||
|
@ -122,6 +123,10 @@ public:
|
|||
|
||||
bool is_visible() const;
|
||||
bool is_active() const { return m_is_active; }
|
||||
bool is_active_input() const { return m_is_active_input; }
|
||||
|
||||
bool is_accessory() const { return m_accessory; }
|
||||
void set_accessory(bool accessory) { m_accessory = accessory; }
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
|
@ -232,6 +237,7 @@ private:
|
|||
WindowType m_window_type { WindowType::Normal };
|
||||
StandardCursor m_override_cursor { StandardCursor::None };
|
||||
bool m_is_active { false };
|
||||
bool m_is_active_input { false };
|
||||
bool m_has_alpha_channel { false };
|
||||
bool m_double_buffering_enabled { true };
|
||||
bool m_modal { false };
|
||||
|
@ -242,6 +248,7 @@ private:
|
|||
bool m_layout_pending { false };
|
||||
bool m_visible_for_timer_purposes { true };
|
||||
bool m_visible { false };
|
||||
bool m_accessory { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -106,6 +106,18 @@ void WindowServerConnection::handle(const Messages::WindowClient::WindowDeactiva
|
|||
Core::EventLoop::current().post_event(*window, make<Event>(Event::WindowBecameInactive));
|
||||
}
|
||||
|
||||
void WindowServerConnection::handle(const Messages::WindowClient::WindowInputEntered& message)
|
||||
{
|
||||
if (auto* window = Window::from_window_id(message.window_id()))
|
||||
Core::EventLoop::current().post_event(*window, make<Event>(Event::WindowInputEntered));
|
||||
}
|
||||
|
||||
void WindowServerConnection::handle(const Messages::WindowClient::WindowInputLeft& message)
|
||||
{
|
||||
if (auto* window = Window::from_window_id(message.window_id()))
|
||||
Core::EventLoop::current().post_event(*window, make<Event>(Event::WindowInputLeft));
|
||||
}
|
||||
|
||||
void WindowServerConnection::handle(const Messages::WindowClient::WindowCloseRequest& message)
|
||||
{
|
||||
if (auto* window = Window::from_window_id(message.window_id()))
|
||||
|
|
|
@ -59,6 +59,8 @@ private:
|
|||
virtual void handle(const Messages::WindowClient::KeyUp&) override;
|
||||
virtual void handle(const Messages::WindowClient::WindowActivated&) override;
|
||||
virtual void handle(const Messages::WindowClient::WindowDeactivated&) override;
|
||||
virtual void handle(const Messages::WindowClient::WindowInputEntered&) override;
|
||||
virtual void handle(const Messages::WindowClient::WindowInputLeft&) override;
|
||||
virtual void handle(const Messages::WindowClient::WindowCloseRequest&) override;
|
||||
virtual void handle(const Messages::WindowClient::WindowResized&) override;
|
||||
virtual void handle(const Messages::WindowClient::MenuItemActivated&) override;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue