Browse Source

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.
Tom 4 years ago
parent
commit
6472ee0eff

+ 13 - 1
Userland/Services/WindowServer/Compositor.cpp

@@ -1001,7 +1001,19 @@ void Compositor::recompute_occlusions()
     auto& wm = WindowManager::the();
     bool is_switcher_visible = wm.m_switcher.is_visible();
     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;
     });
     if (!is_switcher_visible) {

+ 6 - 2
Userland/Services/WindowServer/WindowManager.cpp

@@ -1567,8 +1567,12 @@ void WindowManager::process_key_event(KeyEvent& event)
         return;
     }
 
-    if (event.type() == Event::KeyDown && ((event.modifiers() == Mod_Super && event.key() == Key_Tab) || (event.modifiers() == (Mod_Super | Mod_Shift) && event.key() == Key_Tab)))
-        m_switcher.show();
+    if (event.type() == Event::KeyDown) {
+        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()) {
         m_switcher.on_key_event(event);
         return;

+ 19 - 5
Userland/Services/WindowServer/WindowSwitcher.cpp

@@ -86,7 +86,7 @@ void WindowSwitcher::event(Core::Event& event)
 void WindowSwitcher::on_key_event(const KeyEvent& event)
 {
     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()) {
                 window->set_minimized(false);
                 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;
     auto* highlight_window = m_windows.at(index).ptr();
     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();
 }
 
@@ -202,7 +207,8 @@ void WindowSwitcher::refresh()
     m_selected_index = 0;
     int window_count = 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(
             WindowType::Normal, [&](Window& window) {
                 if (window.is_frameless())
@@ -215,8 +221,16 @@ void WindowSwitcher::refresh()
                 return IterationDecision::Continue;
             },
             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()) {
         hide();
         return;

+ 12 - 1
Userland/Services/WindowServer/WindowSwitcher.h

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