mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-12 01:10:42 +00:00
LibGUI+WindowServer+Applets+Taskbar: Remove active input concepts
and the CaptureInput mode. They are a source of unneeded complexity in WindowServer and have proven prone to regressions, so this patch replaces them with a simple input preemption scheme using Popups. Popup windows now have ergonomics similar to menus: When open, a popup preempts all mouse and key events for the entire window stack; however, they are fragile and will close after WindowServer swallows the first event outside them. This is similar to how combo box windows and popups work in the classic Windows DE and has the added benefit of letting the user click anywhere to dismiss a popup without having to worry about unwanted interactions with other widgets.
This commit is contained in:
parent
35bd79701c
commit
24d299c9c8
Notes:
sideshowbarker
2024-07-17 04:18:51 +09:00
Author: https://github.com/thankyouverycool Commit: https://github.com/SerenityOS/serenity/commit/24d299c9c8 Pull-request: https://github.com/SerenityOS/serenity/pull/16098
17 changed files with 76 additions and 191 deletions
|
@ -81,10 +81,6 @@ private:
|
|||
m_slider_window->set_frameless(true);
|
||||
m_slider_window->set_resizable(false);
|
||||
m_slider_window->set_minimizable(false);
|
||||
m_slider_window->on_active_input_change = [this](bool is_active_input) {
|
||||
if (!is_active_input)
|
||||
close();
|
||||
};
|
||||
|
||||
m_root_container = TRY(m_slider_window->try_set_main_widget<GUI::Frame>());
|
||||
m_root_container->set_fill_with_background_color(true);
|
||||
|
|
|
@ -115,15 +115,6 @@ ComboBox::ComboBox()
|
|||
|
||||
m_list_window = add<Window>(window());
|
||||
m_list_window->set_window_type(GUI::WindowType::Popup);
|
||||
m_list_window->set_frameless(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);
|
||||
close();
|
||||
}
|
||||
m_open_button->set_enabled(true);
|
||||
};
|
||||
|
||||
m_list_view = m_list_window->set_main_widget<ListView>();
|
||||
m_list_view->set_should_hide_unnecessary_scrollbars(true);
|
||||
|
|
|
@ -223,12 +223,6 @@ CommandPalette::CommandPalette(GUI::Window& parent_window, ScreenPosition screen
|
|||
};
|
||||
|
||||
m_text_box->set_focus(true);
|
||||
|
||||
on_active_input_change = [this](bool is_active_input) {
|
||||
if (!is_active_input)
|
||||
close();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void CommandPalette::collect_actions(GUI::Window& parent_window)
|
||||
|
|
|
@ -202,7 +202,6 @@ NonnullRefPtr<Action> make_command_palette_action(Window* window)
|
|||
{
|
||||
auto action = Action::create("&Commands...", { Mod_Ctrl | Mod_Shift, Key_A }, MUST(Gfx::Bitmap::try_load_from_file("/res/icons/16x16/find.png"sv)), [=](auto&) {
|
||||
auto command_palette = CommandPalette::construct(*window);
|
||||
command_palette->set_window_mode(GUI::WindowMode::CaptureInput);
|
||||
if (command_palette->exec() != GUI::Dialog::ExecResult::OK)
|
||||
return;
|
||||
auto* action = command_palette->selected_action();
|
||||
|
|
|
@ -170,7 +170,7 @@ static Action* action_for_shortcut(Window& window, Shortcut const& shortcut)
|
|||
}
|
||||
|
||||
// NOTE: Application-global shortcuts are ignored while a blocking modal window is up.
|
||||
if (!window.is_blocking() && !window.is_capturing_input()) {
|
||||
if (!window.is_blocking() && !window.is_popup()) {
|
||||
if (auto* action = Application::the()->action_for_shortcut(shortcut)) {
|
||||
dbgln_if(KEYBOARD_SHORTCUTS_DEBUG, " > Asked application, got action: {} {} (enabled: {}, shortcut: {}, alt-shortcut: {})", action, action->text(), action->is_enabled(), action->shortcut().to_string(), action->alternate_shortcut().to_string());
|
||||
return action;
|
||||
|
|
|
@ -100,7 +100,6 @@ EmojiInputDialog::EmojiInputDialog(Window* parent_window)
|
|||
|
||||
set_frameless(true);
|
||||
set_blocks_emoji_input(true);
|
||||
set_window_mode(GUI::WindowMode::CaptureInput);
|
||||
resize(400, 300);
|
||||
|
||||
auto& scrollable_container = *main_widget.find_descendant_of_type_named<GUI::ScrollableContainerWidget>("scrollable_container"sv);
|
||||
|
@ -139,11 +138,6 @@ EmojiInputDialog::EmojiInputDialog(Window* parent_window)
|
|||
scrollable_container.horizontal_scrollbar().set_visible(false);
|
||||
update_displayed_emoji();
|
||||
|
||||
on_active_input_change = [this](bool is_active_input) {
|
||||
if (!is_active_input)
|
||||
close();
|
||||
};
|
||||
|
||||
m_search_box->on_change = [this]() {
|
||||
update_displayed_emoji();
|
||||
};
|
||||
|
|
|
@ -752,10 +752,7 @@ bool Widget::is_focused() const
|
|||
auto* win = window();
|
||||
if (!win)
|
||||
return false;
|
||||
// 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())
|
||||
if (win->is_focusable())
|
||||
return win->focused_widget() == this;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@ public:
|
|||
|
||||
bool is_modal() const { return m_window_mode != WindowMode::Modeless; }
|
||||
bool is_blocking() const { return m_window_mode == WindowMode::Blocking; }
|
||||
bool is_capturing_input() const { return m_window_mode == WindowMode::CaptureInput; }
|
||||
|
||||
bool is_popup() const { return m_window_type == WindowType::Popup; }
|
||||
bool is_autocomplete() const { return m_window_type == WindowType::Autocomplete; }
|
||||
|
||||
bool is_fullscreen() const { return m_fullscreen; }
|
||||
|
@ -96,7 +96,6 @@ public:
|
|||
|
||||
Function<void()> on_close;
|
||||
Function<CloseRequestDecision()> on_close_request;
|
||||
Function<void(bool is_active_input)> on_active_input_change;
|
||||
Function<void(bool is_preempted)> on_input_preemption_change;
|
||||
Function<void(bool is_active_window)> on_active_window_change;
|
||||
|
||||
|
@ -130,7 +129,7 @@ public:
|
|||
|
||||
bool is_visible() const;
|
||||
bool is_active() const;
|
||||
bool is_active_input() const { return m_is_active_input; }
|
||||
bool is_focusable() const { return is_active() || is_popup() || is_autocomplete(); }
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
|
@ -304,7 +303,6 @@ private:
|
|||
WindowMode m_window_mode { WindowMode::Modeless };
|
||||
AK::Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> m_cursor { Gfx::StandardCursor::None };
|
||||
AK::Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> m_effective_cursor { Gfx::StandardCursor::None };
|
||||
bool m_is_active_input { false };
|
||||
bool m_has_alpha_channel { false };
|
||||
bool m_double_buffering_enabled { true };
|
||||
bool m_resizable { true };
|
||||
|
|
|
@ -41,10 +41,6 @@ ClockWidget::ClockWidget()
|
|||
m_calendar_window->set_frameless(true);
|
||||
m_calendar_window->set_resizable(false);
|
||||
m_calendar_window->set_minimizable(false);
|
||||
m_calendar_window->on_active_input_change = [this](bool is_active_input) {
|
||||
if (!is_active_input)
|
||||
close();
|
||||
};
|
||||
|
||||
auto& root_container = m_calendar_window->set_main_widget<GUI::Frame>();
|
||||
root_container.set_fill_with_background_color(true);
|
||||
|
|
|
@ -450,7 +450,7 @@ void Window::event(Core::Event& event)
|
|||
return;
|
||||
}
|
||||
|
||||
if (blocking_modal_window()) {
|
||||
if (blocking_modal_window() && type() != WindowType::Popup) {
|
||||
// Allow windows to process their inactivity after being blocked
|
||||
if (event.type() != Event::WindowDeactivated && event.type() != Event::WindowInputPreempted)
|
||||
return;
|
||||
|
@ -980,13 +980,6 @@ Window* Window::modeless_ancestor()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool Window::is_capturing_active_input_from(Window const& window) const
|
||||
{
|
||||
if (!is_capturing_input())
|
||||
return false;
|
||||
return parent_window() == &window;
|
||||
}
|
||||
|
||||
void Window::set_progress(Optional<int> progress)
|
||||
{
|
||||
if (m_progress == progress)
|
||||
|
|
|
@ -106,7 +106,7 @@ public:
|
|||
bool is_closeable() const { return m_closeable; }
|
||||
void set_closeable(bool);
|
||||
|
||||
bool is_resizable() const { return m_resizable && !m_fullscreen; }
|
||||
bool is_resizable() const { return m_type != WindowType::Popup && m_resizable && !m_fullscreen; }
|
||||
void set_resizable(bool);
|
||||
|
||||
bool is_maximized() const { return m_tile_type == WindowTileType::Maximized; }
|
||||
|
@ -182,9 +182,6 @@ 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();
|
||||
|
||||
|
|
|
@ -221,6 +221,12 @@ MultiScaleBitmaps const* WindowFrame::shadow_bitmap() const
|
|||
return nullptr;
|
||||
case WindowType::WindowSwitcher:
|
||||
return nullptr;
|
||||
case WindowType::Popup:
|
||||
if (!WindowManager::the().system_effects().window_shadow())
|
||||
return nullptr;
|
||||
if (!m_window.has_forced_shadow())
|
||||
return nullptr;
|
||||
return s_active_window_shadow;
|
||||
default:
|
||||
if (!WindowManager::the().system_effects().window_shadow())
|
||||
return nullptr;
|
||||
|
@ -280,7 +286,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_capturing_modal(m_window))
|
||||
if (m_window.is_active())
|
||||
return Gfx::WindowTheme::WindowState::Active;
|
||||
return Gfx::WindowTheme::WindowState::Inactive;
|
||||
}
|
||||
|
|
|
@ -330,6 +330,9 @@ void WindowManager::add_window(Window& window)
|
|||
if (window.type() != WindowType::Desktop || is_first_window)
|
||||
set_active_window(&window);
|
||||
|
||||
if (window.type() == WindowType::Popup)
|
||||
notify_active_window_input_preempted();
|
||||
|
||||
if (m_switcher->is_visible() && window.type() != WindowType::WindowSwitcher)
|
||||
m_switcher->refresh();
|
||||
|
||||
|
@ -350,18 +353,16 @@ void WindowManager::move_to_front_and_make_active(Window& window)
|
|||
|
||||
if (auto* blocker = window.blocking_modal_window()) {
|
||||
blocker->window_stack().move_to_front(*blocker);
|
||||
set_active_window(blocker, true);
|
||||
set_active_window(blocker);
|
||||
} else {
|
||||
window.window_stack().move_to_front(window);
|
||||
set_active_window(&window, true);
|
||||
set_active_window(&window);
|
||||
|
||||
for (auto& child : window.child_windows()) {
|
||||
if (!child || !child->is_modal())
|
||||
continue;
|
||||
if (child->is_rendering_above())
|
||||
child->window_stack().move_to_front(*child);
|
||||
if (child->is_capturing_input())
|
||||
set_active_input_window(child);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,12 +381,14 @@ void WindowManager::remove_window(Window& window)
|
|||
{
|
||||
check_hide_geometry_overlay(window);
|
||||
auto* active = active_window();
|
||||
auto* active_input = active_input_window();
|
||||
bool was_modal = window.is_modal(); // This requires the window to be on a window stack still!
|
||||
window.window_stack().remove(window);
|
||||
if (active == &window || active_input == &window || (active && window.is_descendant_of(*active)) || (active_input && active_input != active && window.is_descendant_of(*active_input)))
|
||||
if (active == &window)
|
||||
pick_new_active_window(&window);
|
||||
|
||||
if (window.type() == WindowType::Popup)
|
||||
notify_active_window_input_restored();
|
||||
|
||||
window.invalidate_last_rendered_screen_rects_now();
|
||||
|
||||
if (m_switcher->is_visible() && window.type() != WindowType::WindowSwitcher)
|
||||
|
@ -429,8 +432,6 @@ void WindowManager::tell_wm_about_window(WMConnectionFromClient& conn, Window& w
|
|||
return;
|
||||
if (window.is_internal())
|
||||
return;
|
||||
if (window.is_capturing_input())
|
||||
return;
|
||||
if (window.blocking_modal_window())
|
||||
return;
|
||||
|
||||
|
@ -652,7 +653,7 @@ void WindowManager::pick_new_active_window(Window* previous_active)
|
|||
return IterationDecision::Continue;
|
||||
if (candidate.is_destroyed())
|
||||
return IterationDecision::Continue;
|
||||
if ((!previous_active && !candidate.is_capturing_input()) || (previous_active && !candidate.is_capturing_active_input_from(*previous_active))) {
|
||||
if (!previous_active || previous_active != &candidate) {
|
||||
set_active_window(&candidate);
|
||||
return IterationDecision::Break;
|
||||
}
|
||||
|
@ -1249,7 +1250,7 @@ void WindowManager::process_mouse_event_for_window(HitTestResult& result, MouseE
|
|||
set_active_window(&window);
|
||||
}
|
||||
|
||||
if (blocking_modal_window) {
|
||||
if (blocking_modal_window && window.type() != WindowType::Popup) {
|
||||
if (event.type() == Event::Type::MouseDown) {
|
||||
// We're clicking on something that's blocked by a modal window.
|
||||
// Flash the modal window to let the user know about it.
|
||||
|
@ -1343,6 +1344,15 @@ void WindowManager::process_mouse_event(MouseEvent& event)
|
|||
if (!result.has_value())
|
||||
return;
|
||||
|
||||
auto* event_window = result.value().window.ptr();
|
||||
if (auto* popup_window = foremost_popup_window()) {
|
||||
if (event_window == popup_window)
|
||||
process_mouse_event_for_window(result.value(), event);
|
||||
else if (event.buttons())
|
||||
popup_window->request_close();
|
||||
return;
|
||||
}
|
||||
|
||||
process_mouse_event_for_window(result.value(), event);
|
||||
}
|
||||
|
||||
|
@ -1468,7 +1478,6 @@ void WindowManager::switch_to_window_stack(WindowStack& window_stack, Window* ca
|
|||
for_each_visible_window_from_back_to_front([&](Window& window) {
|
||||
if (is_stationary_window_type(window.type()))
|
||||
return IterationDecision::Continue;
|
||||
|
||||
if (&window.window_stack() != &carry_window->window_stack())
|
||||
return IterationDecision::Continue;
|
||||
if (&window == carry_window || is_window_in_modal_chain(*carry_window, window))
|
||||
|
@ -1478,29 +1487,23 @@ void WindowManager::switch_to_window_stack(WindowStack& window_stack, Window* ca
|
|||
&from_stack);
|
||||
|
||||
auto* from_active_window = from_stack.active_window();
|
||||
auto* from_active_input_window = from_stack.active_input_window();
|
||||
bool did_carry_active_window = false;
|
||||
bool did_carry_active_input_window = false;
|
||||
for (auto& window : m_carry_window_to_new_stack) {
|
||||
if (window == from_active_window)
|
||||
did_carry_active_window = true;
|
||||
if (window == from_active_input_window)
|
||||
did_carry_active_input_window = true;
|
||||
window->set_moving_to_another_stack(true);
|
||||
VERIFY(&window->window_stack() == &from_stack);
|
||||
from_stack.remove(*window);
|
||||
window_stack.add(*window);
|
||||
}
|
||||
// Before we change to the new stack, find a new active window on the stack we're switching from
|
||||
if (did_carry_active_window || did_carry_active_input_window)
|
||||
if (did_carry_active_window)
|
||||
pick_new_active_window(from_active_window);
|
||||
|
||||
// Now switch to the new stack
|
||||
m_current_window_stack = &window_stack;
|
||||
if (did_carry_active_window && from_active_window)
|
||||
set_active_window(from_active_window, from_active_input_window == from_active_window);
|
||||
if (did_carry_active_input_window && from_active_input_window && from_active_input_window != from_active_window)
|
||||
set_active_input_window(from_active_input_window);
|
||||
set_active_window(from_active_window);
|
||||
|
||||
// Because we moved windows between stacks we need to invalidate occlusions
|
||||
Compositor::the().invalidate_occlusions();
|
||||
|
@ -1535,13 +1538,7 @@ void WindowManager::did_switch_window_stack(Badge<Compositor>, WindowStack& prev
|
|||
}
|
||||
|
||||
auto* previous_stack_active_window = previous_stack.active_window();
|
||||
auto* previous_stack_active_input_window = previous_stack.active_input_window();
|
||||
auto* new_stack_active_window = new_stack.active_window();
|
||||
auto* new_stack_active_input_window = new_stack.active_input_window();
|
||||
if (previous_stack_active_input_window && previous_stack_active_input_window != new_stack_active_input_window)
|
||||
notify_previous_active_input_window(*previous_stack_active_input_window);
|
||||
if (new_stack_active_input_window && previous_stack_active_input_window != new_stack_active_input_window)
|
||||
notify_new_active_input_window(*new_stack_active_input_window);
|
||||
if (previous_stack_active_window != new_stack_active_window) {
|
||||
if (previous_stack_active_window && is_stationary_window_type(previous_stack_active_window->type()))
|
||||
notify_previous_active_window(*previous_stack_active_window);
|
||||
|
@ -1549,7 +1546,7 @@ void WindowManager::did_switch_window_stack(Badge<Compositor>, WindowStack& prev
|
|||
notify_new_active_window(*new_stack_active_window);
|
||||
}
|
||||
|
||||
if (!new_stack_active_input_window)
|
||||
if (!new_stack_active_window)
|
||||
pick_new_active_window(nullptr);
|
||||
|
||||
reevaluate_hover_state_for_window();
|
||||
|
@ -1618,6 +1615,7 @@ void WindowManager::process_key_event(KeyEvent& event)
|
|||
m_switcher->show(WindowSwitcher::Mode::ShowCurrentDesktop);
|
||||
}
|
||||
if (m_switcher->is_visible()) {
|
||||
request_close_fragile_windows();
|
||||
m_switcher->on_key_event(event);
|
||||
return;
|
||||
}
|
||||
|
@ -1658,6 +1656,7 @@ void WindowManager::process_key_event(KeyEvent& event)
|
|||
}
|
||||
};
|
||||
if (handle_window_stack_switch_key()) {
|
||||
request_close_fragile_windows();
|
||||
Window* carry_window = nullptr;
|
||||
auto& new_window_stack = m_window_stacks[row][column];
|
||||
if (&new_window_stack != ¤t_stack) {
|
||||
|
@ -1671,8 +1670,10 @@ void WindowManager::process_key_event(KeyEvent& event)
|
|||
}
|
||||
}
|
||||
|
||||
auto* active_input_window = current_window_stack().active_input_window();
|
||||
if (!active_input_window)
|
||||
auto* event_window = current_window_stack().active_window();
|
||||
if (auto* popup_window = foremost_popup_window())
|
||||
event_window = popup_window;
|
||||
if (!event_window)
|
||||
return;
|
||||
|
||||
if (event.type() == Event::KeyDown && event.modifiers() == Mod_Super) {
|
||||
|
@ -1681,71 +1682,71 @@ void WindowManager::process_key_event(KeyEvent& event)
|
|||
Compositor::the().invalidate_cursor();
|
||||
return;
|
||||
}
|
||||
if (active_input_window->type() != WindowType::Desktop) {
|
||||
if (event_window->type() != WindowType::Desktop) {
|
||||
if (event.key() == Key_Down) {
|
||||
if (active_input_window->is_resizable() && active_input_window->is_maximized()) {
|
||||
maximize_windows(*active_input_window, false);
|
||||
if (event_window->is_resizable() && event_window->is_maximized()) {
|
||||
maximize_windows(*event_window, false);
|
||||
return;
|
||||
}
|
||||
if (active_input_window->is_minimizable() && !active_input_window->is_modal())
|
||||
minimize_windows(*active_input_window, true);
|
||||
if (event_window->is_minimizable() && !event_window->is_modal())
|
||||
minimize_windows(*event_window, true);
|
||||
return;
|
||||
}
|
||||
if (active_input_window->is_resizable()) {
|
||||
if (event_window->is_resizable()) {
|
||||
if (event.key() == Key_Up) {
|
||||
maximize_windows(*active_input_window, !active_input_window->is_maximized());
|
||||
maximize_windows(*event_window, !event_window->is_maximized());
|
||||
return;
|
||||
}
|
||||
if (event.key() == Key_Left) {
|
||||
if (active_input_window->tile_type() == WindowTileType::Left) {
|
||||
active_input_window->set_untiled();
|
||||
if (event_window->tile_type() == WindowTileType::Left) {
|
||||
event_window->set_untiled();
|
||||
return;
|
||||
}
|
||||
if (active_input_window->is_maximized())
|
||||
maximize_windows(*active_input_window, false);
|
||||
active_input_window->set_tiled(WindowTileType::Left);
|
||||
if (event_window->is_maximized())
|
||||
maximize_windows(*event_window, false);
|
||||
event_window->set_tiled(WindowTileType::Left);
|
||||
return;
|
||||
}
|
||||
if (event.key() == Key_Right) {
|
||||
if (active_input_window->tile_type() == WindowTileType::Right) {
|
||||
active_input_window->set_untiled();
|
||||
if (event_window->tile_type() == WindowTileType::Right) {
|
||||
event_window->set_untiled();
|
||||
return;
|
||||
}
|
||||
if (active_input_window->is_maximized())
|
||||
maximize_windows(*active_input_window, false);
|
||||
active_input_window->set_tiled(WindowTileType::Right);
|
||||
if (event_window->is_maximized())
|
||||
maximize_windows(*event_window, false);
|
||||
event_window->set_tiled(WindowTileType::Right);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type() == Event::KeyDown && event.modifiers() == (Mod_Super | Mod_Alt) && active_input_window->type() != WindowType::Desktop) {
|
||||
if (active_input_window->is_resizable()) {
|
||||
if (event.type() == Event::KeyDown && event.modifiers() == (Mod_Super | Mod_Alt) && event_window->type() != WindowType::Desktop) {
|
||||
if (event_window->is_resizable()) {
|
||||
if (event.key() == Key_Right || event.key() == Key_Left) {
|
||||
if (active_input_window->tile_type() == WindowTileType::HorizontallyMaximized) {
|
||||
active_input_window->set_untiled();
|
||||
if (event_window->tile_type() == WindowTileType::HorizontallyMaximized) {
|
||||
event_window->set_untiled();
|
||||
return;
|
||||
}
|
||||
if (active_input_window->is_maximized())
|
||||
maximize_windows(*active_input_window, false);
|
||||
active_input_window->set_tiled(WindowTileType::HorizontallyMaximized);
|
||||
if (event_window->is_maximized())
|
||||
maximize_windows(*event_window, false);
|
||||
event_window->set_tiled(WindowTileType::HorizontallyMaximized);
|
||||
return;
|
||||
}
|
||||
if (event.key() == Key_Up || event.key() == Key_Down) {
|
||||
if (active_input_window->tile_type() == WindowTileType::VerticallyMaximized) {
|
||||
active_input_window->set_untiled();
|
||||
if (event_window->tile_type() == WindowTileType::VerticallyMaximized) {
|
||||
event_window->set_untiled();
|
||||
return;
|
||||
}
|
||||
if (active_input_window->is_maximized())
|
||||
maximize_windows(*active_input_window, false);
|
||||
active_input_window->set_tiled(WindowTileType::VerticallyMaximized);
|
||||
if (event_window->is_maximized())
|
||||
maximize_windows(*event_window, false);
|
||||
event_window->set_tiled(WindowTileType::VerticallyMaximized);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
active_input_window->dispatch_event(event);
|
||||
event_window->dispatch_event(event);
|
||||
}
|
||||
|
||||
void WindowManager::set_highlight_window(Window* new_highlight_window)
|
||||
|
@ -1774,78 +1775,24 @@ void WindowManager::set_highlight_window(Window* new_highlight_window)
|
|||
Compositor::the().invalidate_occlusions();
|
||||
}
|
||||
|
||||
bool WindowManager::is_active_window_or_capturing_modal(Window& window) const
|
||||
{
|
||||
if (window.is_capturing_input())
|
||||
return window.parent_window()->is_active();
|
||||
|
||||
return window.is_active();
|
||||
}
|
||||
|
||||
static bool window_type_can_become_active(WindowType type)
|
||||
{
|
||||
return type == WindowType::Normal || type == WindowType::Desktop;
|
||||
}
|
||||
|
||||
void WindowManager::restore_active_input_window(Window* window)
|
||||
{
|
||||
// If the previous active input window is gone, fall back to the
|
||||
// current active window
|
||||
if (!window)
|
||||
window = active_window();
|
||||
// If the current active window is also gone, pick some other window
|
||||
if (!window) {
|
||||
pick_new_active_window(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (window && !window->is_minimized() && window->is_visible())
|
||||
set_active_input_window(window);
|
||||
else
|
||||
set_active_input_window(nullptr);
|
||||
}
|
||||
|
||||
Window* WindowManager::set_active_input_window(Window* window)
|
||||
{
|
||||
auto& window_stack = current_window_stack();
|
||||
auto* previous_input_window = window_stack.active_input_window();
|
||||
if (window == previous_input_window)
|
||||
return window;
|
||||
|
||||
if (previous_input_window)
|
||||
notify_previous_active_input_window(*previous_input_window);
|
||||
|
||||
window_stack.set_active_input_window(window);
|
||||
if (window)
|
||||
notify_new_active_input_window(*window);
|
||||
|
||||
return previous_input_window;
|
||||
}
|
||||
|
||||
void WindowManager::set_active_window(Window* new_active_window, bool make_input)
|
||||
void WindowManager::set_active_window(Window* new_active_window)
|
||||
{
|
||||
if (new_active_window) {
|
||||
if (auto* blocker = new_active_window->blocking_modal_window()) {
|
||||
VERIFY(blocker->is_modal());
|
||||
VERIFY(blocker != new_active_window);
|
||||
new_active_window = blocker;
|
||||
make_input = true;
|
||||
}
|
||||
|
||||
if (!window_type_can_become_active(new_active_window->type()))
|
||||
return;
|
||||
}
|
||||
|
||||
auto* new_active_input_window = new_active_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();
|
||||
}
|
||||
|
||||
if (make_input)
|
||||
set_active_input_window(new_active_input_window);
|
||||
|
||||
auto& window_stack = current_window_stack();
|
||||
if (new_active_window == window_stack.active_window())
|
||||
return;
|
||||
|
@ -1857,6 +1804,7 @@ void WindowManager::set_active_window(Window* new_active_window, bool make_input
|
|||
}
|
||||
|
||||
if (new_active_window) {
|
||||
request_close_fragile_windows();
|
||||
window_stack.set_active_window(new_active_window);
|
||||
notify_new_active_window(*new_active_window);
|
||||
reevaluate_hover_state_for_window(new_active_window);
|
||||
|
|
|
@ -100,16 +100,6 @@ public:
|
|||
|
||||
Window* foremost_popup_window(WindowStack& stack = WindowManager::the().current_window_stack());
|
||||
void request_close_fragile_windows(WindowStack& stack = WindowManager::the().current_window_stack());
|
||||
Window* active_input_window()
|
||||
{
|
||||
VERIFY(m_current_window_stack);
|
||||
return m_current_window_stack->active_input_window();
|
||||
}
|
||||
Window const* active_input_window() const
|
||||
{
|
||||
VERIFY(m_current_window_stack);
|
||||
return m_current_window_stack->active_input_window();
|
||||
}
|
||||
|
||||
ConnectionFromClient const* active_client() const;
|
||||
|
||||
|
@ -164,9 +154,7 @@ public:
|
|||
void set_buttons_switched(bool);
|
||||
bool get_buttons_switched() const;
|
||||
|
||||
Window* set_active_input_window(Window*);
|
||||
void restore_active_input_window(Window*);
|
||||
void set_active_window(Window*, bool make_input = true);
|
||||
void set_active_window(Window*);
|
||||
void set_hovered_button(Button*);
|
||||
|
||||
Button const* cursor_tracking_button() const { return m_cursor_tracking_button.ptr(); }
|
||||
|
@ -188,8 +176,6 @@ public:
|
|||
void tell_wms_super_digit_key_pressed(u8);
|
||||
void tell_wms_current_window_stack_changed();
|
||||
|
||||
bool is_active_window_or_capturing_modal(Window&) const;
|
||||
|
||||
void check_hide_geometry_overlay(Window&);
|
||||
|
||||
void start_window_resize(Window&, Gfx::IntPoint const&, MouseButton, ResizeDirection);
|
||||
|
|
|
@ -13,13 +13,11 @@ namespace WindowServer {
|
|||
// - Modeless: No modal effect (default mode for parentless windows)
|
||||
// - Passive: Joins the modal chain but has no modal effect (default mode for child windows)
|
||||
// - RenderAbove: Renders above its parent
|
||||
// - CaptureInput: Captures input from its parent
|
||||
// - Blocking: Preempts all interaction with its modal chain excepting descendants (default mode for Dialogs)
|
||||
// - Blocking: Preempts all interaction with its modal chain excepting descendants and popups (default mode for Dialogs)
|
||||
enum class WindowMode {
|
||||
Modeless = 0,
|
||||
Passive,
|
||||
RenderAbove,
|
||||
CaptureInput,
|
||||
Blocking,
|
||||
_Count,
|
||||
};
|
||||
|
|
|
@ -38,8 +38,6 @@ void WindowStack::remove(Window& window)
|
|||
window.set_window_stack({}, nullptr);
|
||||
if (m_active_window == &window)
|
||||
m_active_window = nullptr;
|
||||
if (m_active_input_window == &window)
|
||||
m_active_input_window = nullptr;
|
||||
}
|
||||
|
||||
void WindowStack::move_to_front(Window& window)
|
||||
|
@ -99,7 +97,6 @@ void WindowStack::move_all_windows(WindowStack& new_window_stack, Vector<Window*
|
|||
}
|
||||
}
|
||||
m_active_window = nullptr;
|
||||
m_active_input_window = nullptr;
|
||||
}
|
||||
|
||||
Window* WindowStack::window_at(Gfx::IntPoint const& position, IncludeWindowFrame include_window_frame) const
|
||||
|
|
|
@ -56,10 +56,6 @@ public:
|
|||
Window const* active_window() const { return m_active_window; }
|
||||
void set_active_window(Window*);
|
||||
|
||||
Window* active_input_window() { return m_active_input_window; }
|
||||
Window const* active_input_window() const { return m_active_input_window; }
|
||||
void set_active_input_window(Window* window) { m_active_input_window = window; }
|
||||
|
||||
Optional<HitTestResult> hit_test(Gfx::IntPoint const&) const;
|
||||
|
||||
unsigned row() const { return m_row; }
|
||||
|
@ -79,7 +75,6 @@ public:
|
|||
|
||||
private:
|
||||
WeakPtr<Window> m_active_window;
|
||||
WeakPtr<Window> m_active_input_window;
|
||||
|
||||
Window::List m_windows;
|
||||
unsigned m_row { 0 };
|
||||
|
|
Loading…
Reference in a new issue