summaryrefslogtreecommitdiff
path: root/Servers
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-04-06 23:20:06 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-04-06 23:20:06 +0200
commitc7365a00f8508d387395c6f0f9fd4d07ee34aa73 (patch)
treef176ada863d0369e2dc4cc64251244cb24afc4c8 /Servers
parent0808d5158c6dfa003b18ce768497ec3cafb4feed (diff)
downloadserenity-c7365a00f8508d387395c6f0f9fd4d07ee34aa73.zip
WindowServer: Add ability to initiate window resize from window edges.
Diffstat (limited to 'Servers')
-rw-r--r--Servers/WindowServer/WSWindowFrame.cpp23
-rw-r--r--Servers/WindowServer/WSWindowManager.cpp31
-rw-r--r--Servers/WindowServer/WSWindowManager.h6
3 files changed, 57 insertions, 3 deletions
diff --git a/Servers/WindowServer/WSWindowFrame.cpp b/Servers/WindowServer/WSWindowFrame.cpp
index ab6b70d6c1..5d33c6a09b 100644
--- a/Servers/WindowServer/WSWindowFrame.cpp
+++ b/Servers/WindowServer/WSWindowFrame.cpp
@@ -234,6 +234,8 @@ void WSWindowFrame::on_mouse_event(const WSMouseEvent& event)
if (m_window.type() != WSWindowType::Normal)
return;
if (title_bar_rect().contains(event.position())) {
+ wm.clear_resize_candidate();
+
if (event.type() == WSMessage::MouseDown)
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)
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()));
}
diff --git a/Servers/WindowServer/WSWindowManager.cpp b/Servers/WindowServer/WSWindowManager.cpp
index aef4667396..bb2624bca1 100644
--- a/Servers/WindowServer/WSWindowManager.cpp
+++ b/Servers/WindowServer/WSWindowManager.cpp
@@ -488,6 +488,7 @@ void WSWindowManager::start_window_resize(WSWindow& window, const WSMouseEvent&
#ifdef RESIZE_DEBUG
printf("[WM] Begin resizing WSWindow{%p}\n", &window);
#endif
+ m_resizing_mouse_button = event.button();
m_resize_window = window.make_weak_ptr();;
m_resize_origin = event.position();
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)
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
printf("[WM] Finish resizing WSWindow{%p}\n", m_resize_window.ptr());
#endif
WSMessageLoop::the().post_message(*m_resize_window, make<WSResizeEvent>(m_resize_window->rect(), m_resize_window->rect()));
invalidate(*m_resize_window);
m_resize_window = nullptr;
+ m_resizing_mouse_button = MouseButton::None;
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) {
auto window_frame_rect = window.frame().rect();
if (!window_frame_rect.contains(event.position()))
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).
// In those cases, the event is swallowed by the window manager.
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.
window.frame().on_mouse_event(event.translated(-window_frame_rect.location()));
+ event_window_with_frame = &window;
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()
@@ -1095,7 +1114,7 @@ const WSCursor& WSWindowManager::active_cursor() const
if (m_drag_window)
return *m_move_cursor;
- if (m_resize_window) {
+ if (m_resize_window || m_resize_candidate) {
switch (m_resize_direction) {
case ResizeDirection::Up:
case ResizeDirection::Down:
@@ -1110,7 +1129,7 @@ const WSCursor& WSWindowManager::active_cursor() const
case ResizeDirection::DownLeft:
return *m_resize_diagonally_bltr_cursor;
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;
}
+
+void WSWindowManager::set_resize_candidate(WSWindow& window, ResizeDirection direction)
+{
+ m_resize_candidate = window.make_weak_ptr();
+ m_resize_direction = direction;
+}
diff --git a/Servers/WindowServer/WSWindowManager.h b/Servers/WindowServer/WSWindowManager.h
index 9c1c74d0e6..b38524b15d 100644
--- a/Servers/WindowServer/WSWindowManager.h
+++ b/Servers/WindowServer/WSWindowManager.h
@@ -14,6 +14,7 @@
#include <WindowServer/WSWindowType.h>
#include <WindowServer/WSWindow.h>
#include <WindowServer/WSCursor.h>
+#include <WindowServer/WSMessage.h>
#include <AK/CircularQueue.h>
class WSAPIClientRequest;
@@ -103,6 +104,9 @@ public:
void set_cursor_tracking_button(WSButton*);
void set_hovered_button(WSButton*);
+ void set_resize_candidate(WSWindow&, ResizeDirection);
+ void clear_resize_candidate();
+
private:
void process_mouse_event(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;
WeakPtr<WSWindow> m_resize_window;
+ WeakPtr<WSWindow> m_resize_candidate;
+ MouseButton m_resizing_mouse_button { MouseButton::None };
Rect m_resize_window_original_rect;
Point m_resize_origin;
ResizeDirection m_resize_direction { ResizeDirection::None };