Ver Fonte

WindowServer: Add Vertically/HorizontallyMaximized WindowTileTypes

VerticallyMaximized tiling replaces set_vertically_maximized() to
take advantage of tiling ergonomics.

Middle-clicking a window's maximize button now tiles vertically;
secondary-clicking tiles horizontally.

Adds Super+Alt+Arrow shortcuts for both. Super+Left/Right tiling
shortcuts now let windows shift between tile types directly.
thankyouverycool há 3 anos atrás
pai
commit
ee637b44fb

+ 21 - 14
Userland/Services/WindowServer/Window.cpp

@@ -499,6 +499,7 @@ void Window::set_maximized(bool maximized, Optional<Gfx::IntPoint> fixed_point)
     Core::EventLoop::current().post_event(*this, make<ResizeEvent>(m_rect));
     set_default_positioned(false);
 }
+
 void Window::set_always_on_top(bool always_on_top)
 {
     if (m_always_on_top == always_on_top)
@@ -510,21 +511,7 @@ void Window::set_always_on_top(bool always_on_top)
     window_stack().move_always_on_top_windows_to_front();
     Compositor::the().invalidate_occlusions();
 }
-void Window::set_vertically_maximized()
-{
-    if (m_maximized)
-        return;
-    if (!is_resizable() || resize_aspect_ratio().has_value())
-        return;
-
-    auto max_rect = WindowManager::the().maximized_window_rect(*this);
 
-    auto new_rect = Gfx::IntRect(
-        Gfx::IntPoint(rect().x(), max_rect.y()),
-        Gfx::IntSize(rect().width(), max_rect.height()));
-    set_rect(new_rect);
-    Core::EventLoop::current().post_event(*this, make<ResizeEvent>(new_rect));
-}
 void Window::set_resizable(bool resizable)
 {
     if (m_resizable == resizable)
@@ -1021,6 +1008,26 @@ Gfx::IntRect Window::tiled_rect(Screen* target_screen, WindowTileType tile_type)
             { screen.width() - location.x(), screen.height() - location.y() })
             .translated(screen_location);
     }
+    case WindowTileType::VerticallyMaximized: {
+        Gfx::IntPoint location {
+            floating_rect().location().x(),
+            menu_height
+        };
+        return Gfx::IntRect(
+            location,
+            { floating_rect().width(), max_height })
+            .translated(screen_location);
+    }
+    case WindowTileType::HorizontallyMaximized: {
+        Gfx::IntPoint location {
+            0,
+            floating_rect().location().y()
+        };
+        return Gfx::IntRect(
+            location,
+            { screen.width(), floating_rect().height() })
+            .translated(screen_location);
+    }
     default:
         VERIFY_NOT_REACHED();
     }

+ 3 - 3
Userland/Services/WindowServer/Window.h

@@ -48,7 +48,9 @@ enum class WindowTileType {
     TopLeft,
     TopRight,
     BottomLeft,
-    BottomRight
+    BottomRight,
+    VerticallyMaximized,
+    HorizontallyMaximized,
 };
 
 enum class WindowMenuAction {
@@ -111,8 +113,6 @@ public:
     bool is_always_on_top() const { return m_always_on_top; }
     void set_always_on_top(bool);
 
-    void set_vertically_maximized();
-
     bool is_fullscreen() const { return m_fullscreen; }
     void set_fullscreen(bool);
 

+ 12 - 1
Userland/Services/WindowServer/WindowFrame.cpp

@@ -84,7 +84,18 @@ void WindowFrame::window_was_constructed(Badge<Window>)
             m_window.handle_window_menu_action(WindowMenuAction::MaximizeOrRestore);
         });
         button->on_middle_click = [&](auto&) {
-            m_window.set_vertically_maximized();
+            auto& window_screen = Screen::closest_to_location(m_window.rect().location());
+            if (m_window.tile_type() == WindowTileType::VerticallyMaximized)
+                m_window.set_untiled();
+            else
+                m_window.set_tiled(&window_screen, WindowTileType::VerticallyMaximized);
+        };
+        button->on_secondary_click = [&](auto&) {
+            auto& window_screen = Screen::closest_to_location(m_window.rect().location());
+            if (m_window.tile_type() == WindowTileType::HorizontallyMaximized)
+                m_window.set_untiled();
+            else
+                m_window.set_tiled(&window_screen, WindowTileType::HorizontallyMaximized);
         };
         m_maximize_button = button.ptr();
         m_buttons.append(move(button));

+ 38 - 14
Userland/Services/WindowServer/WindowManager.cpp

@@ -825,25 +825,27 @@ bool WindowManager::process_ongoing_window_resize(MouseEvent const& event)
     if (!m_resize_window)
         return false;
 
-    if (event.type() == Event::MouseUp && event.button() == m_resizing_mouse_button) {
-        dbgln_if(RESIZE_DEBUG, "[WM] Finish resizing Window({})", m_resize_window);
-
-        if (!m_resize_window->is_tiled() && !m_resize_window->is_maximized())
-            m_resize_window->set_floating_rect(m_resize_window->rect());
-
+    if (event.type() == Event::MouseMove) {
         const int vertical_maximize_deadzone = 5;
         auto& cursor_screen = ScreenInput::the().cursor_location_screen();
         if (&cursor_screen == &Screen::closest_to_rect(m_resize_window->rect())) {
             auto desktop_rect = this->desktop_rect(cursor_screen);
             if (event.y() >= desktop_rect.bottom() - vertical_maximize_deadzone + 1 || event.y() <= desktop_rect.top() + vertical_maximize_deadzone - 1) {
-                dbgln_if(RESIZE_DEBUG, "Should Maximize vertically");
-                m_resize_window->set_vertically_maximized();
+                dbgln_if(RESIZE_DEBUG, "Should tile as VerticallyMaximized");
+                m_resize_window->set_tiled(&cursor_screen, WindowTileType::VerticallyMaximized);
                 m_resize_window = nullptr;
                 m_geometry_overlay = nullptr;
                 m_resizing_mouse_button = MouseButton::None;
                 return true;
             }
         }
+    }
+
+    if (event.type() == Event::MouseUp && event.button() == m_resizing_mouse_button) {
+        dbgln_if(RESIZE_DEBUG, "[WM] Finish resizing Window({})", m_resize_window);
+
+        if (!m_resize_window->is_tiled() && !m_resize_window->is_maximized())
+            m_resize_window->set_floating_rect(m_resize_window->rect());
 
         Core::EventLoop::current().post_event(*m_resize_window, make<ResizeEvent>(m_resize_window->rect()));
         m_resize_window->invalidate(true, true);
@@ -1646,9 +1648,7 @@ void WindowManager::process_key_event(KeyEvent& event)
                 return;
             }
             if (event.key() == Key_Left) {
-                if (active_input_window->tile_type() == WindowTileType::Left)
-                    return;
-                if (active_input_window->is_tiled()) {
+                if (active_input_window->tile_type() == WindowTileType::Left) {
                     active_input_window->set_untiled();
                     return;
                 }
@@ -1658,9 +1658,7 @@ void WindowManager::process_key_event(KeyEvent& event)
                 return;
             }
             if (event.key() == Key_Right) {
-                if (active_input_window->tile_type() == WindowTileType::Right)
-                    return;
-                if (active_input_window->is_tiled()) {
+                if (active_input_window->tile_type() == WindowTileType::Right) {
                     active_input_window->set_untiled();
                     return;
                 }
@@ -1671,6 +1669,32 @@ void WindowManager::process_key_event(KeyEvent& event)
             }
         }
     }
+
+    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.key() == Key_Right || event.key() == Key_Left) {
+                if (active_input_window->tile_type() == WindowTileType::HorizontallyMaximized) {
+                    active_input_window->set_untiled();
+                    return;
+                }
+                if (active_input_window->is_maximized())
+                    maximize_windows(*active_input_window, false);
+                active_input_window->set_tiled(nullptr, 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();
+                    return;
+                }
+                if (active_input_window->is_maximized())
+                    maximize_windows(*active_input_window, false);
+                active_input_window->set_tiled(nullptr, WindowTileType::VerticallyMaximized);
+                return;
+            }
+        }
+    }
+
     active_input_window->dispatch_event(event);
 }