diff --git a/src/miral/application_selector.cpp b/src/miral/application_selector.cpp index f71c5cc7e7..daa6fa79f2 100644 --- a/src/miral/application_selector.cpp +++ b/src/miral/application_selector.cpp @@ -223,7 +223,11 @@ auto ApplicationSelector::advance(bool reverse, bool within_app) -> Window // This means that there is no other selectable window in the list but // the currently selected one, so we don't need to select anything. if (*it == selected) + { + if(!tools.info_for(selected).is_visible()) + tools.select_active_window(selected); return selected; + } if (within_app) { @@ -271,7 +275,13 @@ auto ApplicationSelector::advance(bool reverse, bool within_app) -> Window auto next_state_to_preserve = tools.info_for(next_window.value()).state(); tools.select_active_window(next_window.value()); - restore_state = next_state_to_preserve; + + // Don't re-minimize windows selected with alt tab on focus loss + if(next_state_to_preserve != mir_window_state_minimized) + restore_state = next_state_to_preserve; + else + restore_state.reset(); + return next_window.value(); } @@ -281,4 +291,4 @@ auto ApplicationSelector::find(Window window) -> std::vector::iterator { return window == other; }); -} \ No newline at end of file +} diff --git a/src/miral/basic_window_manager.cpp b/src/miral/basic_window_manager.cpp index c4490d0e38..604c210e07 100644 --- a/src/miral/basic_window_manager.cpp +++ b/src/miral/basic_window_manager.cpp @@ -294,22 +294,17 @@ void miral::BasicWindowManager::refocus( // Try to activate to recently active window of any application in a shared workspace { miral::Window new_focus; + auto workspaces_containing_window_mut = workspaces_containing_window; + std::sort(workspaces_containing_window_mut.begin(), workspaces_containing_window_mut.end()); - mru_active_windows.enumerate([&](miral::Window& window) + mru_active_windows.enumerate( + [&](miral::Window& other_window) { - // select_active_window() calls set_focus_to() which updates mru_active_windows and changes window - auto const w = window; + if (!info_for(other_window).is_visible()) + return true; - for (auto const& workspace : workspaces_containing(w)) - { - for (auto const& ww : workspaces_containing_window) - { - if (ww == workspace) - { - return !(new_focus = select_active_window(w)); - } - } - } + if (window_workspaces_intersect(workspaces_containing_window_mut, other_window)) + return !(new_focus = select_active_window(other_window)); return true; }); @@ -328,14 +323,15 @@ void miral::BasicWindowManager::refocus( { // select_active_window() calls set_focus_to() which updates mru_active_windows and changes window auto const w = window; + if(!info_for(w).is_visible()) return true; return !(new_focus = select_active_window(w)); }); if (new_focus) return; } - // Fallback to cycling through applications - focus_next_application(); + // Can't focus anything else + focus_controller->set_focus_to(nullptr, nullptr); } void miral::BasicWindowManager::erase(miral::WindowInfo const& info) @@ -1494,24 +1490,17 @@ void miral::BasicWindowManager::set_state(miral::WindowInfo& window_info, MirWin if (window == active_window() || !active_window()) { - auto const workspaces_containing_window = workspaces_containing(window); + auto workspaces_containing_window = workspaces_containing(window); + std::sort(workspaces_containing_window.begin(), workspaces_containing_window.end()); // Try to activate to recently active window of any application mru_active_windows.enumerate([&](Window& candidate) { - if (candidate == window) + if (candidate == window || !info_for(candidate).is_visible()) return true; - auto const w = candidate; - for (auto const& workspace : workspaces_containing(w)) - { - for (auto const& ww : workspaces_containing_window) - { - if (ww == workspace) - { - return !(select_active_window(w)); - } - } - } + + if(window_workspaces_intersect(workspaces_containing_window, candidate)) + select_active_window(candidate); return true; }); @@ -1521,10 +1510,9 @@ void miral::BasicWindowManager::set_state(miral::WindowInfo& window_info, MirWin if (window == active_window() || !active_window()) mru_active_windows.enumerate([&](Window& candidate) { - if (candidate == window) + if (candidate == window || !info_for(candidate).is_visible()) return true; - auto const w = candidate; - return !(select_active_window(w)); + return !(select_active_window(candidate)); }); if (window == active_window()) @@ -2993,4 +2981,21 @@ void miral::BasicWindowManager::move_cursor_to(mir::geometry::PointF point) sink->handle_input(std::move(event)); }); }); -} \ No newline at end of file +} + +auto miral::BasicWindowManager::window_workspaces_intersect(std::vector> const& w1_workspaces, Window const& w2) const -> bool +{ + auto w2_workspaces = workspaces_containing(w2); + std::sort(w2_workspaces.begin(), w2_workspaces.end()); + + auto intersection = std::vector>(); + + std::set_intersection( + w1_workspaces.begin(), + w1_workspaces.end(), + w2_workspaces.begin(), + w2_workspaces.end(), + std::back_inserter(intersection)); + + return !intersection.empty(); +} diff --git a/src/miral/basic_window_manager.h b/src/miral/basic_window_manager.h index f2ac8ed19e..da8a0473ae 100644 --- a/src/miral/basic_window_manager.h +++ b/src/miral/basic_window_manager.h @@ -332,6 +332,10 @@ class BasicWindowManager : public virtual mir::shell::WindowManager, void for_each_descendent_in(WindowInfo const& info, std::function func); /// Gathers windows provided WindowInfo auto collect_windows(WindowInfo const& info) -> SurfaceSet; + + // w1_workspaces must be sorted + auto window_workspaces_intersect( + std::vector> const& w1_workspaces, Window const& w2) const -> bool; }; } diff --git a/src/server/frontend_wayland/input_method_v1.cpp b/src/server/frontend_wayland/input_method_v1.cpp index 579a282bcf..9d500db3f4 100644 --- a/src/server/frontend_wayland/input_method_v1.cpp +++ b/src/server/frontend_wayland/input_method_v1.cpp @@ -576,7 +576,6 @@ mf::InputPanelV1::InputPanelV1( OutputManager* const output_manager, std::shared_ptr const text_input_hub) : Global(display, Version<1>()), - display{display}, wayland_executor{wayland_executor}, shell{shell}, seat{seat}, @@ -594,4 +593,4 @@ void mf::InputPanelV1::bind(wl_resource *new_resource) new_resource, text_input_hub }; -} \ No newline at end of file +} diff --git a/src/server/frontend_wayland/input_method_v1.h b/src/server/frontend_wayland/input_method_v1.h index 75b1c357a3..b4555fbee5 100644 --- a/src/server/frontend_wayland/input_method_v1.h +++ b/src/server/frontend_wayland/input_method_v1.h @@ -72,7 +72,6 @@ class InputPanelV1 : public wayland::InputPanelV1::Global class Instance; void bind(wl_resource* new_zwp_input_panel_v1) override; - wl_display* display; std::shared_ptr const wayland_executor; std::shared_ptr const shell; WlSeat* seat; @@ -83,4 +82,4 @@ class InputPanelV1 : public wayland::InputPanelV1::Global } } -#endif \ No newline at end of file +#endif