mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 18:07:34 +00:00
WindowServer: Fix picking new active window after destroy
We need to mark windows as destroyed and not consider them when picking a new active window. Fixes lost focus after closing some windows.
This commit is contained in:
parent
603c17262c
commit
f591157eb8
4 changed files with 29 additions and 7 deletions
|
@ -475,12 +475,19 @@ void ClientConnection::destroy_window(Window& window, Vector<i32>& destroyed_win
|
||||||
destroy_window(*child_window, destroyed_window_ids);
|
destroy_window(*child_window, destroyed_window_ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& accessory_window : window.accessory_windows()) {
|
||||||
|
if (!accessory_window)
|
||||||
|
continue;
|
||||||
|
ASSERT(accessory_window->window_id() != window.window_id());
|
||||||
|
destroy_window(*accessory_window, destroyed_window_ids);
|
||||||
|
}
|
||||||
|
|
||||||
destroyed_window_ids.append(window.window_id());
|
destroyed_window_ids.append(window.window_id());
|
||||||
|
|
||||||
if (window.type() == WindowType::MenuApplet)
|
if (window.type() == WindowType::MenuApplet)
|
||||||
AppletManager::the().remove_applet(window);
|
AppletManager::the().remove_applet(window);
|
||||||
|
|
||||||
window.invalidate();
|
window.destroy();
|
||||||
remove_child(window);
|
remove_child(window);
|
||||||
m_windows.remove(window.window_id());
|
m_windows.remove(window.window_id());
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,12 @@ Window::~Window()
|
||||||
WindowManager::the().remove_window(*this);
|
WindowManager::the().remove_window(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::destroy()
|
||||||
|
{
|
||||||
|
m_destroyed = true;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
void Window::set_title(const String& title)
|
void Window::set_title(const String& title)
|
||||||
{
|
{
|
||||||
if (m_title == title)
|
if (m_title == title)
|
||||||
|
@ -389,7 +395,7 @@ Window* Window::is_blocked_by_modal_window()
|
||||||
// A window is blocked if any immediate child, or any child further
|
// A window is blocked if any immediate child, or any child further
|
||||||
// down the chain is modal
|
// down the chain is modal
|
||||||
for (auto& window: m_child_windows) {
|
for (auto& window: m_child_windows) {
|
||||||
if (window) {
|
if (window && !window->is_destroyed()) {
|
||||||
if (window->is_modal())
|
if (window->is_modal())
|
||||||
return window;
|
return window;
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,9 @@ public:
|
||||||
int progress() const { return m_progress; }
|
int progress() const { return m_progress; }
|
||||||
void set_progress(int);
|
void set_progress(int);
|
||||||
|
|
||||||
|
bool is_destroyed() const { return m_destroyed; }
|
||||||
|
void destroy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handle_mouse_event(const MouseEvent&);
|
void handle_mouse_event(const MouseEvent&);
|
||||||
void update_menu_item_text(PopupMenuItem item);
|
void update_menu_item_text(PopupMenuItem item);
|
||||||
|
@ -289,6 +292,7 @@ private:
|
||||||
bool m_maximized { false };
|
bool m_maximized { false };
|
||||||
bool m_fullscreen { false };
|
bool m_fullscreen { false };
|
||||||
bool m_accessory { false };
|
bool m_accessory { false };
|
||||||
|
bool m_destroyed { false };
|
||||||
WindowTileType m_tiled { WindowTileType::None };
|
WindowTileType m_tiled { WindowTileType::None };
|
||||||
Gfx::IntRect m_untiled_rect;
|
Gfx::IntRect m_untiled_rect;
|
||||||
bool m_occluded { false };
|
bool m_occluded { false };
|
||||||
|
|
|
@ -260,7 +260,9 @@ void WindowManager::remove_window(Window& window)
|
||||||
{
|
{
|
||||||
window.invalidate();
|
window.invalidate();
|
||||||
m_windows_in_order.remove(&window);
|
m_windows_in_order.remove(&window);
|
||||||
if (window.is_active())
|
auto* active = active_window();
|
||||||
|
auto* active_input = active_input_window();
|
||||||
|
if (active == &window || active_input == &window || (active && window.is_descendant_of(*active)) || (active_input && active_input != active && window.is_descendant_of(*active_input)))
|
||||||
pick_new_active_window(&window);
|
pick_new_active_window(&window);
|
||||||
if (m_switcher.is_visible() && window.type() != WindowType::WindowSwitcher)
|
if (m_switcher.is_visible() && window.type() != WindowType::WindowSwitcher)
|
||||||
m_switcher.refresh();
|
m_switcher.refresh();
|
||||||
|
@ -412,7 +414,10 @@ bool WindowManager::pick_new_active_window(Window* previous_active)
|
||||||
bool new_window_picked = false;
|
bool new_window_picked = false;
|
||||||
Window* first_candidate = nullptr;
|
Window* first_candidate = nullptr;
|
||||||
for_each_visible_window_of_type_from_front_to_back(WindowType::Normal, [&](Window& candidate) {
|
for_each_visible_window_of_type_from_front_to_back(WindowType::Normal, [&](Window& candidate) {
|
||||||
first_candidate = &candidate;
|
if (candidate.is_destroyed())
|
||||||
|
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_accessory()) || (previous_active && !candidate.is_accessory_of(*previous_active))) {
|
||||||
set_active_window(&candidate);
|
set_active_window(&candidate);
|
||||||
new_window_picked = true;
|
new_window_picked = true;
|
||||||
|
@ -1167,10 +1172,10 @@ void WindowManager::set_active_window(Window* window, bool make_input)
|
||||||
window = modal_window;
|
window = modal_window;
|
||||||
make_input = true;
|
make_input = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (window && !window_type_can_become_active(window->type()))
|
if (!window_type_can_become_active(window->type()))
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto* new_active_input_window = window;
|
auto* new_active_input_window = window;
|
||||||
if (window && window->is_accessory()) {
|
if (window && window->is_accessory()) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue