1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-29 20:15:11 +00:00

LibGUI+WindowServer+Apps: Replace Accessory Windows

with the CaptureInput WindowMode. This mode will serve the same
function as accessories: redirecting input while allowing parent
windows to remain active.
This commit is contained in:
thankyouverycool 2022-08-22 13:54:38 -04:00 committed by Andreas Kling
parent 0d4fd4e2a6
commit 4c7f95e2f8
13 changed files with 23 additions and 91 deletions

View file

@ -66,7 +66,6 @@ HelpWindow::HelpWindow(GUI::Window* parent)
resize(530, 365);
set_title("Spreadsheet Functions Help");
set_icon(Gfx::Bitmap::try_load_from_file("/res/icons/16x16/app-help.png"sv).release_value_but_fixme_should_propagate_errors());
set_accessory(true);
auto& widget = set_main_widget<GUI::Widget>();
widget.set_layout<GUI::VerticalBoxLayout>();

View file

@ -109,7 +109,7 @@ ComboBox::ComboBox()
m_list_window = add<Window>(window());
m_list_window->set_frameless(true);
m_list_window->set_accessory(true);
m_list_window->set_window_mode(WindowMode::CaptureInput);
m_list_window->on_active_input_change = [this](bool is_active_input) {
if (!is_active_input) {
m_open_button->set_enabled(false);

View file

@ -731,7 +731,7 @@ bool Widget::is_focused() const
auto* win = window();
if (!win)
return false;
// Accessory windows are not active despite being the active
// Capturing modals 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())

View file

@ -153,7 +153,6 @@ void Window::show()
m_fullscreen,
m_frameless,
m_forced_shadow,
m_accessory,
m_opacity_when_windowless,
m_alpha_hit_threshold,
m_base_size,

View file

@ -124,9 +124,6 @@ public:
bool is_active() const;
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();
virtual void close();
@ -306,7 +303,6 @@ private:
bool m_layout_pending { false };
bool m_visible_for_timer_purposes { true };
bool m_visible { false };
bool m_accessory { false };
bool m_moved_by_client { false };
};

View file

@ -564,7 +564,7 @@ Window* ConnectionFromClient::window_from_id(i32 window_id)
void ConnectionFromClient::create_window(i32 window_id, Gfx::IntRect const& rect,
bool auto_position, bool has_alpha_channel, bool minimizable, bool closeable, bool resizable,
bool fullscreen, bool frameless, bool forced_shadow, bool accessory, float opacity,
bool fullscreen, bool frameless, bool forced_shadow, float opacity,
float alpha_hit_threshold, Gfx::IntSize const& base_size, Gfx::IntSize const& size_increment,
Gfx::IntSize const& minimum_size, Optional<Gfx::IntSize> const& resize_aspect_ratio, i32 type, i32 mode,
String const& title, i32 parent_window_id, Gfx::IntRect const& launch_origin_rect)
@ -597,7 +597,7 @@ void ConnectionFromClient::create_window(i32 window_id, Gfx::IntRect const& rect
return;
}
auto window = Window::construct(*this, (WindowType)type, (WindowMode)mode, window_id, minimizable, closeable, frameless, resizable, fullscreen, accessory, parent_window);
auto window = Window::construct(*this, (WindowType)type, (WindowMode)mode, window_id, minimizable, closeable, frameless, resizable, fullscreen, parent_window);
window->set_forced_shadow(forced_shadow);
@ -646,13 +646,6 @@ void ConnectionFromClient::destroy_window(Window& window, Vector<i32>& destroyed
destroy_window(*child_window, destroyed_window_ids);
}
for (auto& accessory_window : window.accessory_windows()) {
if (!accessory_window)
continue;
VERIFY(accessory_window->window_id() != window.window_id());
destroy_window(*accessory_window, destroyed_window_ids);
}
destroyed_window_ids.append(window.window_id());
if (window.type() == WindowType::Applet)

View file

@ -101,7 +101,7 @@ private:
virtual void update_menu_item(i32, i32, i32, String const&, bool, bool, bool, bool, String const&, Gfx::ShareableBitmap const&) override;
virtual void remove_menu_item(i32 menu_id, i32 identifier) override;
virtual void flash_menubar_menu(i32, i32) override;
virtual void create_window(i32, Gfx::IntRect const&, bool, bool, bool, bool,
virtual void create_window(i32, Gfx::IntRect const&, bool, bool, bool,
bool, bool, bool, bool, bool, float, float, Gfx::IntSize const&, Gfx::IntSize const&, Gfx::IntSize const&,
Optional<Gfx::IntSize> const&, i32, i32, String const&, i32, Gfx::IntRect const&) override;
virtual Messages::WindowServer::DestroyWindowResponse destroy_window(i32) override;

View file

@ -90,7 +90,7 @@ Window::Window(Core::Object& parent, WindowType type)
frame().window_was_constructed({});
}
Window::Window(ConnectionFromClient& client, WindowType window_type, WindowMode window_mode, int window_id, bool minimizable, bool closeable, bool frameless, bool resizable, bool fullscreen, bool accessory, Window* parent_window)
Window::Window(ConnectionFromClient& client, WindowType window_type, WindowMode window_mode, int window_id, bool minimizable, bool closeable, bool frameless, bool resizable, bool fullscreen, Window* parent_window)
: Core::Object(&client)
, m_client(&client)
, m_type(window_type)
@ -100,7 +100,6 @@ Window::Window(ConnectionFromClient& client, WindowType window_type, WindowMode
, m_frameless(frameless)
, m_resizable(resizable)
, m_fullscreen(fullscreen)
, m_accessory(accessory)
, m_window_id(window_id)
, m_client_id(client.client_id())
, m_icon(default_window_icon())
@ -974,19 +973,11 @@ void Window::add_child_window(Window& child_window)
m_child_windows.append(child_window);
}
void Window::add_accessory_window(Window& accessory_window)
{
m_accessory_windows.append(accessory_window);
}
void Window::set_parent_window(Window& parent_window)
{
VERIFY(!m_parent_window);
m_parent_window = parent_window;
if (m_accessory)
parent_window.add_accessory_window(*this);
else
parent_window.add_child_window(*this);
parent_window.add_child_window(*this);
}
Window* Window::modeless_ancestor()
@ -1000,21 +991,9 @@ Window* Window::modeless_ancestor()
return nullptr;
}
bool Window::is_accessory() const
bool Window::is_capturing_active_input_from(Window const& window) const
{
if (!m_accessory)
return false;
if (parent_window() != nullptr)
return true;
// If accessory window was unparented, convert to a regular window
const_cast<Window*>(this)->set_accessory(false);
return false;
}
bool Window::is_accessory_of(Window& window) const
{
if (!is_accessory())
if (!is_capturing_input())
return false;
return parent_window() == &window;
}
@ -1030,14 +1009,9 @@ void Window::set_progress(Optional<int> progress)
bool Window::is_descendant_of(Window& window) const
{
for (auto* parent = parent_window(); parent; parent = parent->parent_window()) {
for (auto* parent = parent_window(); parent; parent = parent->parent_window())
if (parent == &window)
return true;
for (auto& accessory : parent->accessory_windows()) {
if (accessory == &window)
return true;
}
}
return false;
}

View file

@ -182,6 +182,9 @@ public:
bool is_passive() { return m_mode == WindowMode::Passive; }
bool is_rendering_above() { return m_mode == WindowMode::RenderAbove; }
bool is_capturing_input() const { return m_mode == WindowMode::CaptureInput; }
bool is_capturing_active_input_from(Window const&) const;
bool is_blocking() const { return m_mode == WindowMode::Blocking; }
Window* blocking_modal_window();
@ -308,15 +311,8 @@ public:
Vector<WeakPtr<Window>>& child_windows() { return m_child_windows; }
Vector<WeakPtr<Window>> const& child_windows() const { return m_child_windows; }
Vector<WeakPtr<Window>>& accessory_windows() { return m_accessory_windows; }
Vector<WeakPtr<Window>> const& accessory_windows() const { return m_accessory_windows; }
bool is_descendant_of(Window&) const;
void set_accessory(bool accessory) { m_accessory = accessory; }
bool is_accessory() const;
bool is_accessory_of(Window&) const;
void set_frameless(bool);
bool is_frameless() const { return m_frameless; }
@ -383,14 +379,13 @@ public:
bool is_stealable_by_client(i32 client_id) const { return m_stealable_by_client_ids.contains_slow(client_id); }
private:
Window(ConnectionFromClient&, WindowType, WindowMode, int window_id, bool minimizable, bool closeable, bool frameless, bool resizable, bool fullscreen, bool accessory, Window* parent_window = nullptr);
Window(ConnectionFromClient&, WindowType, WindowMode, int window_id, bool minimizable, bool closeable, bool frameless, bool resizable, bool fullscreen, Window* parent_window = nullptr);
Window(Core::Object&, WindowType);
virtual void event(Core::Event&) override;
void handle_mouse_event(MouseEvent const&);
void handle_keydown_event(KeyEvent const&);
void add_child_window(Window&);
void add_accessory_window(Window&);
void ensure_window_menu();
void update_window_menu_items();
void modal_unparented();
@ -399,7 +394,6 @@ private:
WeakPtr<Window> m_parent_window;
Vector<WeakPtr<Window>> m_child_windows;
Vector<WeakPtr<Window>> m_accessory_windows;
Menubar m_menubar;
@ -426,7 +420,6 @@ private:
Optional<Gfx::IntSize> m_resize_aspect_ratio {};
WindowMinimizedState m_minimized_state { WindowMinimizedState::None };
bool m_fullscreen { false };
bool m_accessory { false };
bool m_destroyed { false };
bool m_default_positioned { false };
bool m_have_taskbar_rect { false };

View file

@ -278,7 +278,7 @@ Gfx::WindowTheme::WindowState WindowFrame::window_state_for_theme() const
return Gfx::WindowTheme::WindowState::Highlighted;
if (&m_window == wm.m_move_window)
return Gfx::WindowTheme::WindowState::Moving;
if (wm.is_active_window_or_accessory(m_window))
if (wm.is_active_window_or_capturing_modal(m_window))
return Gfx::WindowTheme::WindowState::Active;
return Gfx::WindowTheme::WindowState::Inactive;
}

View file

@ -343,25 +343,8 @@ void WindowManager::add_window(Window& window)
void WindowManager::move_to_front_and_make_active(Window& window)
{
auto move_window_to_front = [&](Window& wnd, bool make_active, bool make_input) {
if (wnd.is_accessory()) {
auto* parent = wnd.parent_window();
do_move_to_front(*parent, true, false);
make_active = false;
for (auto& accessory_window : parent->accessory_windows()) {
if (accessory_window && accessory_window.ptr() != &wnd)
do_move_to_front(*accessory_window, false, false);
}
}
do_move_to_front(wnd, make_active, make_input);
};
// If a window that is currently blocked by a modal child is being
// brought to the front, bring the entire stack of modal windows
// to the front and activate the modal window. Also set the
// active input window to that same window (which would pull
// active input from any accessory window)
for_each_window_in_modal_stack(window, [&](auto& w, bool is_stack_top) {
move_window_to_front(w, is_stack_top, is_stack_top);
return IterationDecision::Continue;
@ -379,7 +362,7 @@ void WindowManager::do_move_to_front(Window& window, bool make_active, bool make
if (m_switcher->is_visible()) {
m_switcher->refresh();
if (!window.is_accessory()) {
if (!window.is_modal()) {
m_switcher->select_window(window);
set_highlight_window(&window);
}
@ -655,7 +638,7 @@ bool WindowManager::pick_new_active_window(Window* previous_active)
return IterationDecision::Continue;
if (previous_active != first_candidate)
first_candidate = &candidate;
if ((!previous_active && !candidate.is_accessory()) || (previous_active && !candidate.is_accessory_of(*previous_active))) {
if ((!previous_active && !candidate.is_capturing_input()) || (previous_active && !candidate.is_capturing_active_input_from(*previous_active))) {
set_active_window(&candidate);
new_window_picked = true;
return IterationDecision::Break;
@ -1460,10 +1443,6 @@ bool WindowManager::is_window_in_modal_stack(Window& window_in_modal_stack, Wind
auto result = for_each_window_in_modal_stack(window_in_modal_stack, [&](auto& window, auto) {
if (&other_window == &window)
return IterationDecision::Break;
for (auto& accessory : window.accessory_windows()) {
if (accessory.ptr() == &other_window)
return IterationDecision::Break;
}
return IterationDecision::Continue;
});
return result == IterationDecision::Break;
@ -1786,9 +1765,9 @@ void WindowManager::set_highlight_window(Window* new_highlight_window)
Compositor::the().invalidate_occlusions();
}
bool WindowManager::is_active_window_or_accessory(Window& window) const
bool WindowManager::is_active_window_or_capturing_modal(Window& window) const
{
if (window.is_accessory())
if (window.is_capturing_input())
return window.parent_window()->is_active();
return window.is_active();
@ -1857,9 +1836,9 @@ void WindowManager::set_active_window(Window* new_active_window, bool make_input
}
auto* new_active_input_window = new_active_window;
if (new_active_window && new_active_window->is_accessory()) {
// The parent of an accessory window is always the active
// window, but input is routed to the accessory window
if (new_active_window && new_active_window->is_capturing_input()) {
// The parent of a capturing modal is always the active
// window, but input is routed to the capturing window
new_active_window = new_active_window->parent_window();
}

View file

@ -194,7 +194,7 @@ public:
void tell_wms_super_digit_key_pressed(u8);
void tell_wms_current_window_stack_changed();
bool is_active_window_or_accessory(Window&) const;
bool is_active_window_or_capturing_modal(Window&) const;
void check_hide_geometry_overlay(Window&);

View file

@ -50,7 +50,6 @@ endpoint WindowServer
bool fullscreen,
bool frameless,
bool forced_shadow,
bool accessory,
float opacity,
float alpha_hit_threshold,
Gfx::IntSize base_size,