mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
WindowServer: Add ability to initiate window resize from window edges.
This commit is contained in:
parent
0808d5158c
commit
c7365a00f8
Notes:
sideshowbarker
2024-07-19 14:47:57 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/c7365a00f85
3 changed files with 57 additions and 3 deletions
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
Loading…
Reference in a new issue