1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 06:37:43 +00:00

WindowServer: Support two window switcher modes: all or current desktop

When using the Super+Tab hotkey then all windows will be displayed,
and we will switch to another virtual desktop if needed.

When using the Alt+Tab hotkey then only the windows on the current
desktop will be displayed.
This commit is contained in:
Tom 2021-07-01 20:42:48 -06:00 committed by Andreas Kling
parent 7984c2836d
commit 6472ee0eff
4 changed files with 50 additions and 9 deletions

View file

@ -1001,7 +1001,19 @@ void Compositor::recompute_occlusions()
auto& wm = WindowManager::the(); auto& wm = WindowManager::the();
bool is_switcher_visible = wm.m_switcher.is_visible(); bool is_switcher_visible = wm.m_switcher.is_visible();
wm.for_each_window_stack([&](WindowStack& window_stack) { wm.for_each_window_stack([&](WindowStack& window_stack) {
window_stack.set_all_occluded(!is_switcher_visible); if (is_switcher_visible) {
switch (wm.m_switcher.mode()) {
case WindowSwitcher::Mode::ShowCurrentDesktop:
window_stack.set_all_occluded(!(&window_stack == m_current_window_stack || &window_stack == m_transitioning_to_window_stack));
break;
case WindowSwitcher::Mode::ShowAllWindows:
window_stack.set_all_occluded(false);
break;
}
} else {
window_stack.set_all_occluded(!(&window_stack == m_current_window_stack || &window_stack == m_transitioning_to_window_stack));
}
return IterationDecision::Continue; return IterationDecision::Continue;
}); });
if (!is_switcher_visible) { if (!is_switcher_visible) {

View file

@ -1567,8 +1567,12 @@ void WindowManager::process_key_event(KeyEvent& event)
return; return;
} }
if (event.type() == Event::KeyDown && ((event.modifiers() == Mod_Super && event.key() == Key_Tab) || (event.modifiers() == (Mod_Super | Mod_Shift) && event.key() == Key_Tab))) if (event.type() == Event::KeyDown) {
m_switcher.show(); if ((event.modifiers() == Mod_Super && event.key() == Key_Tab) || (event.modifiers() == (Mod_Super | Mod_Shift) && event.key() == Key_Tab))
m_switcher.show(WindowSwitcher::Mode::ShowAllWindows);
else if ((event.modifiers() == Mod_Alt && event.key() == Key_Tab) || (event.modifiers() == (Mod_Alt | Mod_Shift) && event.key() == Key_Tab))
m_switcher.show(WindowSwitcher::Mode::ShowCurrentDesktop);
}
if (m_switcher.is_visible()) { if (m_switcher.is_visible()) {
m_switcher.on_key_event(event); m_switcher.on_key_event(event);
return; return;

View file

@ -86,7 +86,7 @@ void WindowSwitcher::event(Core::Event& event)
void WindowSwitcher::on_key_event(const KeyEvent& event) void WindowSwitcher::on_key_event(const KeyEvent& event)
{ {
if (event.type() == Event::KeyUp) { if (event.type() == Event::KeyUp) {
if (event.key() == Key_Super) { if (event.key() == (m_mode == Mode::ShowAllWindows ? Key_Super : Key_Alt)) {
if (auto* window = selected_window()) { if (auto* window = selected_window()) {
window->set_minimized(false); window->set_minimized(false);
WindowManager::the().move_to_front_and_make_active(*window); WindowManager::the().move_to_front_and_make_active(*window);
@ -135,7 +135,12 @@ void WindowSwitcher::select_window_at_index(int index)
m_selected_index = index; m_selected_index = index;
auto* highlight_window = m_windows.at(index).ptr(); auto* highlight_window = m_windows.at(index).ptr();
VERIFY(highlight_window); VERIFY(highlight_window);
WindowManager::the().set_highlight_window(highlight_window); auto& wm = WindowManager::the();
if (m_mode == Mode::ShowAllWindows) {
if (auto* window_stack = highlight_window->outer_stack(); window_stack != &wm.current_window_stack())
wm.switch_to_window_stack(*window_stack, nullptr, false);
}
wm.set_highlight_window(highlight_window);
redraw(); redraw();
} }
@ -202,7 +207,8 @@ void WindowSwitcher::refresh()
m_selected_index = 0; m_selected_index = 0;
int window_count = 0; int window_count = 0;
int longest_title_width = 0; int longest_title_width = 0;
wm.for_each_window_stack([&](auto& window_stack) {
auto add_window_stack_windows = [&](WindowStack& window_stack) {
window_stack.for_each_window_of_type_from_front_to_back( window_stack.for_each_window_of_type_from_front_to_back(
WindowType::Normal, [&](Window& window) { WindowType::Normal, [&](Window& window) {
if (window.is_frameless()) if (window.is_frameless())
@ -215,8 +221,16 @@ void WindowSwitcher::refresh()
return IterationDecision::Continue; return IterationDecision::Continue;
}, },
true); true);
return IterationDecision::Continue; };
}); if (m_mode == Mode::ShowAllWindows) {
wm.for_each_window_stack([&](auto& window_stack) {
add_window_stack_windows(window_stack);
return IterationDecision::Continue;
});
} else {
add_window_stack_windows(wm.current_window_stack());
}
if (m_windows.is_empty()) { if (m_windows.is_empty()) {
hide(); hide();
return; return;

View file

@ -20,6 +20,10 @@ class Window;
class WindowSwitcher final : public Core::Object { class WindowSwitcher final : public Core::Object {
C_OBJECT(WindowSwitcher) C_OBJECT(WindowSwitcher)
public: public:
enum class Mode {
ShowAllWindows,
ShowCurrentDesktop
};
static WindowSwitcher& the(); static WindowSwitcher& the();
WindowSwitcher(); WindowSwitcher();
@ -28,7 +32,11 @@ public:
bool is_visible() const { return m_visible; } bool is_visible() const { return m_visible; }
void set_visible(bool); void set_visible(bool);
void show() { set_visible(true); } void show(Mode mode)
{
m_mode = mode;
set_visible(true);
}
void hide() { set_visible(false); } void hide() { set_visible(false); }
void on_key_event(const KeyEvent&); void on_key_event(const KeyEvent&);
@ -38,6 +46,8 @@ public:
void select_window(Window&); void select_window(Window&);
Mode mode() const { return m_mode; }
private: private:
int thumbnail_width() const { return 40; } int thumbnail_width() const { return 40; }
int thumbnail_height() const { return 40; } int thumbnail_height() const { return 40; }
@ -54,6 +64,7 @@ private:
virtual void event(Core::Event&) override; virtual void event(Core::Event&) override;
RefPtr<Window> m_switcher_window; RefPtr<Window> m_switcher_window;
Mode m_mode { Mode::ShowCurrentDesktop };
Gfx::IntRect m_rect; Gfx::IntRect m_rect;
bool m_visible { false }; bool m_visible { false };
Vector<WeakPtr<Window>> m_windows; Vector<WeakPtr<Window>> m_windows;