Ver Fonte

WindowServer: Add ability to initiate window resize from window edges.

Andreas Kling há 6 anos atrás
pai
commit
c7365a00f8

+ 23 - 0
Servers/WindowServer/WSWindowFrame.cpp

@@ -234,6 +234,8 @@ void WSWindowFrame::on_mouse_event(const WSMouseEvent& event)
     if (m_window.type() != WSWindowType::Normal)
     if (m_window.type() != WSWindowType::Normal)
         return;
         return;
     if (title_bar_rect().contains(event.position())) {
     if (title_bar_rect().contains(event.position())) {
+        wm.clear_resize_candidate();
+
         if (event.type() == WSMessage::MouseDown)
         if (event.type() == WSMessage::MouseDown)
             wm.move_to_front_and_make_active(m_window);
             wm.move_to_front_and_make_active(m_window);
 
 
@@ -243,5 +245,26 @@ void WSWindowFrame::on_mouse_event(const WSMouseEvent& event)
         }
         }
         if (event.type() == WSMessage::MouseDown && event.button() == MouseButton::Left)
         if (event.type() == WSMessage::MouseDown && event.button() == MouseButton::Left)
             wm.start_window_drag(m_window, event.translated(rect().location()));
             wm.start_window_drag(m_window, event.translated(rect().location()));
+        return;
+    }
+
+    if (event.type() == WSMessage::MouseMove && event.buttons() == 0) {
+        constexpr ResizeDirection direction_for_hot_area[3][3] = {
+            { ResizeDirection::UpLeft, ResizeDirection::Up, ResizeDirection::UpRight },
+            { ResizeDirection::Left, ResizeDirection::None, ResizeDirection::Right },
+            { ResizeDirection::DownLeft, ResizeDirection::Down, ResizeDirection::DownRight },
+        };
+        Rect outer_rect = { { }, rect().size() };
+        ASSERT(outer_rect.contains(event.position()));
+        int window_relative_x = event.x() - outer_rect.x();
+        int window_relative_y = event.y() - outer_rect.y();
+        int hot_area_row = min(2, window_relative_y / (outer_rect.height() / 3));
+        int hot_area_column = min(2, window_relative_x / (outer_rect.width() / 3));
+        wm.set_resize_candidate(m_window, direction_for_hot_area[hot_area_row][hot_area_column]);
+        wm.invalidate_cursor();
+        return;
     }
     }
+
+    if (event.button() == MouseButton::Left)
+        wm.start_window_resize(m_window, event.translated(rect().location()));
 }
 }

+ 28 - 3
Servers/WindowServer/WSWindowManager.cpp

@@ -488,6 +488,7 @@ void WSWindowManager::start_window_resize(WSWindow& window, const WSMouseEvent&
 #ifdef RESIZE_DEBUG
 #ifdef RESIZE_DEBUG
     printf("[WM] Begin resizing WSWindow{%p}\n", &window);
     printf("[WM] Begin resizing WSWindow{%p}\n", &window);
 #endif
 #endif
+    m_resizing_mouse_button = event.button();
     m_resize_window = window.make_weak_ptr();;
     m_resize_window = window.make_weak_ptr();;
     m_resize_origin = event.position();
     m_resize_origin = event.position();
     m_resize_window_original_rect = window.rect();
     m_resize_window_original_rect = window.rect();
@@ -525,13 +526,14 @@ bool WSWindowManager::process_ongoing_window_resize(const WSMouseEvent& event, W
     if (!m_resize_window)
     if (!m_resize_window)
         return false;
         return false;
 
 
-    if (event.type() == WSMessage::MouseUp && event.button() == MouseButton::Right) {
+    if (event.type() == WSMessage::MouseUp && event.button() == m_resizing_mouse_button) {
 #ifdef RESIZE_DEBUG
 #ifdef RESIZE_DEBUG
         printf("[WM] Finish resizing WSWindow{%p}\n", m_resize_window.ptr());
         printf("[WM] Finish resizing WSWindow{%p}\n", m_resize_window.ptr());
 #endif
 #endif
         WSMessageLoop::the().post_message(*m_resize_window, make<WSResizeEvent>(m_resize_window->rect(), m_resize_window->rect()));
         WSMessageLoop::the().post_message(*m_resize_window, make<WSResizeEvent>(m_resize_window->rect(), m_resize_window->rect()));
         invalidate(*m_resize_window);
         invalidate(*m_resize_window);
         m_resize_window = nullptr;
         m_resize_window = nullptr;
+        m_resizing_mouse_button = MouseButton::None;
         return true;
         return true;
     }
     }
 
 
@@ -669,10 +671,16 @@ void WSWindowManager::process_mouse_event(const WSMouseEvent& event, WSWindow*&
         }
         }
     }
     }
 
 
+    WSWindow* event_window_with_frame = nullptr;
+
     for_each_visible_window_from_front_to_back([&] (WSWindow& window) {
     for_each_visible_window_from_front_to_back([&] (WSWindow& window) {
         auto window_frame_rect = window.frame().rect();
         auto window_frame_rect = window.frame().rect();
         if (!window_frame_rect.contains(event.position()))
         if (!window_frame_rect.contains(event.position()))
             return IterationDecision::Continue;
             return IterationDecision::Continue;
+
+        if (&window != m_resize_candidate.ptr())
+            clear_resize_candidate();
+
         // First check if we should initiate a drag or resize (Logo+LMB or Logo+RMB).
         // First check if we should initiate a drag or resize (Logo+LMB or Logo+RMB).
         // In those cases, the event is swallowed by the window manager.
         // In those cases, the event is swallowed by the window manager.
         if (window.type() == WSWindowType::Normal) {
         if (window.type() == WSWindowType::Normal) {
@@ -697,8 +705,19 @@ void WSWindowManager::process_mouse_event(const WSMouseEvent& event, WSWindow*&
 
 
         // We are hitting the frame, pass the event along to WSWindowFrame.
         // We are hitting the frame, pass the event along to WSWindowFrame.
         window.frame().on_mouse_event(event.translated(-window_frame_rect.location()));
         window.frame().on_mouse_event(event.translated(-window_frame_rect.location()));
+        event_window_with_frame = &window;
         return IterationDecision::Abort;
         return IterationDecision::Abort;
     });
     });
+
+    if (event_window_with_frame != m_resize_candidate.ptr())
+        clear_resize_candidate();
+}
+
+void WSWindowManager::clear_resize_candidate()
+{
+    if (m_resize_candidate)
+        invalidate_cursor();
+    m_resize_candidate = nullptr;
 }
 }
 
 
 void WSWindowManager::compose()
 void WSWindowManager::compose()
@@ -1095,7 +1114,7 @@ const WSCursor& WSWindowManager::active_cursor() const
     if (m_drag_window)
     if (m_drag_window)
         return *m_move_cursor;
         return *m_move_cursor;
 
 
-    if (m_resize_window) {
+    if (m_resize_window || m_resize_candidate) {
         switch (m_resize_direction) {
         switch (m_resize_direction) {
         case ResizeDirection::Up:
         case ResizeDirection::Up:
         case ResizeDirection::Down:
         case ResizeDirection::Down:
@@ -1110,7 +1129,7 @@ const WSCursor& WSWindowManager::active_cursor() const
         case ResizeDirection::DownLeft:
         case ResizeDirection::DownLeft:
             return *m_resize_diagonally_bltr_cursor;
             return *m_resize_diagonally_bltr_cursor;
         case ResizeDirection::None:
         case ResizeDirection::None:
-            ASSERT_NOT_REACHED();
+            break;
         }
         }
     }
     }
 
 
@@ -1124,3 +1143,9 @@ void WSWindowManager::set_hovered_button(WSButton* button)
 {
 {
     m_hovered_button = button ? button->make_weak_ptr() : nullptr;
     m_hovered_button = button ? button->make_weak_ptr() : nullptr;
 }
 }
+
+void WSWindowManager::set_resize_candidate(WSWindow& window, ResizeDirection direction)
+{
+    m_resize_candidate = window.make_weak_ptr();
+    m_resize_direction = direction;
+}

+ 6 - 0
Servers/WindowServer/WSWindowManager.h

@@ -14,6 +14,7 @@
 #include <WindowServer/WSWindowType.h>
 #include <WindowServer/WSWindowType.h>
 #include <WindowServer/WSWindow.h>
 #include <WindowServer/WSWindow.h>
 #include <WindowServer/WSCursor.h>
 #include <WindowServer/WSCursor.h>
+#include <WindowServer/WSMessage.h>
 #include <AK/CircularQueue.h>
 #include <AK/CircularQueue.h>
 
 
 class WSAPIClientRequest;
 class WSAPIClientRequest;
@@ -103,6 +104,9 @@ public:
     void set_cursor_tracking_button(WSButton*);
     void set_cursor_tracking_button(WSButton*);
     void set_hovered_button(WSButton*);
     void set_hovered_button(WSButton*);
 
 
+    void set_resize_candidate(WSWindow&, ResizeDirection);
+    void clear_resize_candidate();
+
 private:
 private:
     void process_mouse_event(const WSMouseEvent&, WSWindow*& event_window);
     void process_mouse_event(const WSMouseEvent&, WSWindow*& event_window);
     bool process_ongoing_window_resize(const WSMouseEvent&, WSWindow*& event_window);
     bool process_ongoing_window_resize(const WSMouseEvent&, WSWindow*& event_window);
@@ -161,6 +165,8 @@ private:
     Point m_drag_window_origin;
     Point m_drag_window_origin;
 
 
     WeakPtr<WSWindow> m_resize_window;
     WeakPtr<WSWindow> m_resize_window;
+    WeakPtr<WSWindow> m_resize_candidate;
+    MouseButton m_resizing_mouse_button { MouseButton::None };
     Rect m_resize_window_original_rect;
     Rect m_resize_window_original_rect;
     Point m_resize_origin;
     Point m_resize_origin;
     ResizeDirection m_resize_direction { ResizeDirection::None };
     ResizeDirection m_resize_direction { ResizeDirection::None };