1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 06:07:34 +00:00

WindowServer: Support resizing windows.

This is pretty limited and not entirely stable, but it does work! :^)
This commit is contained in:
Andreas Kling 2019-02-20 15:34:55 +01:00
parent a9911fca80
commit 59b8183c4b
11 changed files with 112 additions and 13 deletions

View file

@ -68,6 +68,7 @@ struct WSAPI_ServerMessage {
KeyUp,
WindowActivated,
WindowDeactivated,
WindowResized,
WindowCloseRequest,
MenuItemActivated,
DidCreateMenubar,
@ -92,6 +93,7 @@ struct WSAPI_ServerMessage {
union {
struct {
WSAPI_Rect rect;
WSAPI_Rect old_rect;
} window;
struct {
WSAPI_Rect rect;

View file

@ -21,6 +21,7 @@ public:
WindowActivated,
WindowDeactivated,
WindowCloseRequest,
WindowResized,
__Begin_API_Client_Requests,
APICreateMenubarRequest,
@ -451,3 +452,20 @@ private:
unsigned m_buttons { 0 };
MouseButton m_button { MouseButton::None };
};
class WSResizeEvent final : public WSMessage {
public:
WSResizeEvent(const Rect& old_rect, const Rect& rect)
: WSMessage(WSMessage::WindowResized)
, m_old_rect(old_rect)
, m_rect(rect)
{
}
Rect old_rect() const { return m_old_rect; }
Rect rect() const { return m_rect; }
private:
Rect m_old_rect;
Rect m_rect;
};

View file

@ -48,7 +48,6 @@ void WSWindow::set_rect(const Rect& rect)
else if (m_client) {
m_backing = m_client->create_shared_bitmap(m_has_alpha_channel ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32, m_rect.size());
}
}
WSWindowManager::the().notify_rect_changed(*this, old_rect, rect);
}
@ -125,6 +124,11 @@ void WSWindow::on_message(WSMessage& message)
case WSMessage::WindowCloseRequest:
server_message.type = WSAPI_ServerMessage::Type::WindowCloseRequest;
break;
case WSMessage::WindowResized:
server_message.type = WSAPI_ServerMessage::Type::WindowResized;
server_message.window.old_rect = static_cast<WSResizeEvent&>(message).old_rect();
server_message.window.rect = static_cast<WSResizeEvent&>(message).rect();
break;
default:
break;
}

View file

@ -40,6 +40,7 @@ public:
void set_rect(const Rect&);
void set_rect(int x, int y, int width, int height) { set_rect({ x, y, width, height }); }
void set_rect_without_repaint(const Rect& rect) { m_rect = rect; }
void set_rect_from_window_manager_resize(const Rect&);
void move_to(const Point& position) { set_rect({ position, size() }); }
void move_to(int x, int y) { move_to({ x, y }); }
@ -54,9 +55,6 @@ public:
virtual void on_message(WSMessage&) override;
bool is_being_dragged() const { return m_is_being_dragged; }
void set_is_being_dragged(bool b) { m_is_being_dragged = b; }
GraphicsBitmap* backing() { return m_backing.ptr(); }
void set_global_cursor_tracking_enabled(bool);
@ -75,7 +73,6 @@ private:
String m_title;
Rect m_rect;
WSWindowType m_type { WSWindowType::Normal };
bool m_is_being_dragged { false };
bool m_global_cursor_tracking_enabled { false };
bool m_visible { true };
bool m_has_alpha_channel { false };

View file

@ -21,6 +21,7 @@
//#define DEBUG_COUNTERS
//#define DEBUG_WID_IN_TITLE_BAR
#define RESIZE_DEBUG
static const int window_titlebar_height = 16;
@ -472,7 +473,6 @@ void WSWindowManager::handle_titlebar_mouse_event(WSWindow& window, WSMouseEvent
m_drag_window = window.make_weak_ptr();;
m_drag_origin = event.position();
m_drag_window_origin = window.position();
window.set_is_being_dragged(true);
invalidate(window);
return;
}
@ -487,6 +487,17 @@ void WSWindowManager::handle_close_button_mouse_event(WSWindow& window, WSMouseE
}
}
void WSWindowManager::start_window_resize(WSWindow& window, WSMouseEvent& event)
{
#ifdef RESIZE_DEBUG
printf("[WM] Begin resizing WSWindow{%p}\n", &window);
#endif
m_resize_window = window.make_weak_ptr();;
m_resize_origin = event.position();
m_resize_window_original_rect = window.rect();
invalidate(window);
}
void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_window)
{
event_window = nullptr;
@ -497,7 +508,6 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_
printf("[WM] Finish dragging WSWindow{%p}\n", m_drag_window.ptr());
#endif
invalidate(*m_drag_window);
m_drag_window->set_is_being_dragged(false);
m_drag_window = nullptr;
return;
}
@ -516,6 +526,38 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_
}
}
if (m_resize_window) {
if (event.type() == WSMessage::MouseUp && event.button() == MouseButton::Right) {
#ifdef RESIZE_DEBUG
printf("[WM] Finish resizing WSWindow{%p}\n", m_resize_window.ptr());
#endif
invalidate(*m_resize_window);
m_resize_window = nullptr;
return;
}
if (event.type() == WSMessage::MouseMove) {
auto old_rect = m_resize_window->rect();
int dx = event.x() - m_resize_origin.x();
int dy = event.y() - m_resize_origin.y();
auto new_rect = m_resize_window_original_rect;
new_rect.set_width(new_rect.width() + dx);
new_rect.set_height(new_rect.height() + dy);
#ifdef RESIZE_DEBUG
dbgprintf("[WM] Resizing [original: %s] now: %s\n",
m_resize_window_original_rect.to_string().characters(),
new_rect.to_string().characters());
#endif
if (new_rect.width() < 50)
new_rect.set_width(50);
if (new_rect.height() < 50)
new_rect.set_height(50);
m_resize_window->set_rect(new_rect);
WSMessageLoop::the().post_message(m_resize_window.ptr(), make<WSResizeEvent>(old_rect, new_rect));
return;
}
}
for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) {
if (!window->global_cursor_tracking())
continue;
@ -559,6 +601,10 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_
move_to_front(window);
set_active_window(&window);
}
if (event.type() == WSMessage::MouseDown && event.button() == MouseButton::Right) {
start_window_resize(window, event);
return IterationDecision::Abort;
}
event_window = &window;
// FIXME: Should we just alter the coordinates of the existing MouseEvent and pass it through?
Point position { event.x() - window.rect().x(), event.y() - window.rect().y() };

View file

@ -23,6 +23,7 @@ class CharacterBitmap;
class GraphicsBitmap;
enum class IterationDecision { Continue, Abort };
enum class ResizeDirection { None, Left, UpLeft, Up, UpRight, Right, DownRight, Down, DownLeft };
class WSWindowManager : public WSMessageReceiver {
public:
@ -76,6 +77,7 @@ private:
void handle_menubar_mouse_event(WSMouseEvent&);
void handle_titlebar_mouse_event(WSWindow&, WSMouseEvent&);
void handle_close_button_mouse_event(WSWindow&, WSMouseEvent&);
void start_window_resize(WSWindow&, WSMouseEvent&);
void handle_client_request(WSAPIClientRequest&);
void set_active_window(WSWindow*);
@ -113,11 +115,16 @@ private:
WeakPtr<WSWindow> m_active_window;
WeakPtr<WSWindow> m_hovered_window;
WeakPtr<WSWindow> m_drag_window;
WeakPtr<WSWindow> m_drag_window;
Point m_drag_origin;
Point m_drag_window_origin;
WeakPtr<WSWindow> m_resize_window;
Rect m_resize_window_original_rect;
Point m_resize_origin;
ResizeDirection m_resize_direction { ResizeDirection::None };
Rect m_last_cursor_rect;
unsigned m_compose_count { 0 };