diff --git a/userspace/libraries/LibGUI/Window.cpp b/userspace/libraries/LibGUI/Window.cpp index 857db9bd..d0b91b63 100644 --- a/userspace/libraries/LibGUI/Window.cpp +++ b/userspace/libraries/LibGUI/Window.cpp @@ -306,6 +306,16 @@ namespace LibGUI return on_socket_error(__FUNCTION__); } + void Window::set_min_size(uint32_t width, uint32_t height) + { + WindowPacket::WindowSetMinSize packet; + packet.width = width; + packet.height = height; + + if (auto ret = packet.send_serialized(m_server_fd); ret.is_error()) + return on_socket_error(__FUNCTION__); + } + void Window::set_attributes(Attributes attributes) { WindowPacket::WindowSetAttributes packet; diff --git a/userspace/libraries/LibGUI/include/LibGUI/Packet.h b/userspace/libraries/LibGUI/include/LibGUI/Packet.h index eeee5233..0ce2820a 100644 --- a/userspace/libraries/LibGUI/include/LibGUI/Packet.h +++ b/userspace/libraries/LibGUI/include/LibGUI/Packet.h @@ -164,6 +164,7 @@ namespace LibGUI WindowSetAttributes, WindowSetMouseCapture, WindowSetSize, + WindowSetMinSize, WindowSetFullscreen, WindowSetTitle, @@ -227,6 +228,12 @@ namespace LibGUI uint32_t, height ); + DEFINE_PACKET( + WindowSetMinSize, + uint32_t, width, + uint32_t, height + ); + DEFINE_PACKET( WindowSetFullscreen, bool, fullscreen diff --git a/userspace/libraries/LibGUI/include/LibGUI/Window.h b/userspace/libraries/LibGUI/include/LibGUI/Window.h index f9321a32..ef66b581 100644 --- a/userspace/libraries/LibGUI/include/LibGUI/Window.h +++ b/userspace/libraries/LibGUI/include/LibGUI/Window.h @@ -76,6 +76,8 @@ namespace LibGUI Attributes get_attributes() const { return m_attributes; } void set_attributes(Attributes attributes); + void set_min_size(uint32_t width, uint32_t height); + // send resize request to window server // actual resize is only done after resize callback is called void request_resize(uint32_t width, uint32_t height); diff --git a/userspace/programs/WindowServer/Window.h b/userspace/programs/WindowServer/Window.h index ba30ec62..aed9b46c 100644 --- a/userspace/programs/WindowServer/Window.h +++ b/userspace/programs/WindowServer/Window.h @@ -52,6 +52,9 @@ public: LibGUI::Window::Attributes get_attributes() const { return m_attributes; }; void set_attributes(LibGUI::Window::Attributes attributes) { m_attributes = attributes; }; + Rectangle get_min_size() const { return m_min_size; } + void set_min_size(Rectangle min_size) { m_min_size = min_size.get_bounding_box({ 0, 0, m_title_bar_height, 0 }); } + BAN::ErrorOr set_title(BAN::StringView title) { m_title.clear(); TRY(m_title.append(title)); TRY(prepare_title_bar()); return {}; } const uint32_t* framebuffer() const { return m_fb_addr; } @@ -84,6 +87,7 @@ private: const int m_client_fd { -1 }; Rectangle m_client_area { 0, 0, 0, 0 }; + Rectangle m_min_size { 0, 0, m_title_bar_height, 0 }; long m_smo_key { 0 }; uint32_t* m_fb_addr { nullptr }; BAN::String m_title; diff --git a/userspace/programs/WindowServer/WindowServer.cpp b/userspace/programs/WindowServer/WindowServer.cpp index cef4741f..02d8a03b 100644 --- a/userspace/programs/WindowServer/WindowServer.cpp +++ b/userspace/programs/WindowServer/WindowServer.cpp @@ -261,6 +261,26 @@ void WindowServer::on_window_set_size(int fd, const LibGUI::WindowPacket::Window invalidate(target_window->full_area().get_bounding_box(old_area)); } +void WindowServer::on_window_set_min_size(int fd, const LibGUI::WindowPacket::WindowSetMinSize& packet) +{ + BAN::RefPtr target_window; + for (auto& window : m_client_windows) + { + if (window->client_fd() != fd) + continue; + target_window = window; + break; + } + + if (!target_window) + { + dwarnln("client tried to set window min size while not owning a window"); + return; + } + + target_window->set_min_size({ 0, 0, static_cast(packet.width), static_cast(packet.height) }); +} + void WindowServer::on_window_set_fullscreen(int fd, const LibGUI::WindowPacket::WindowSetFullscreen& packet) { if (m_state == State::Fullscreen) @@ -1173,15 +1193,17 @@ Rectangle WindowServer::cursor_area() const Rectangle WindowServer::resize_area(Position cursor) const { + const auto min_size = m_focused_window->get_min_size(); + int32_t diff_x = m_resize_start.x - cursor.x; if (m_resize_quadrant % 2) diff_x = -diff_x; - diff_x = BAN::Math::max(diff_x, -m_focused_window->client_width() + 20); + diff_x = BAN::Math::max(diff_x, -m_focused_window->client_width() + min_size.width); int32_t diff_y = m_resize_start.y - cursor.y; if (m_resize_quadrant / 2) diff_y = -diff_y; - diff_y = BAN::Math::max(diff_y, -m_focused_window->client_height() + 20); + diff_y = BAN::Math::max(diff_y, -m_focused_window->client_height() + min_size.height); int32_t off_x = 0; if (m_resize_quadrant % 2 == 0) diff --git a/userspace/programs/WindowServer/WindowServer.h b/userspace/programs/WindowServer/WindowServer.h index 76e35ac4..b9db4a4e 100644 --- a/userspace/programs/WindowServer/WindowServer.h +++ b/userspace/programs/WindowServer/WindowServer.h @@ -37,6 +37,7 @@ public: void on_window_set_attributes(int fd, const LibGUI::WindowPacket::WindowSetAttributes&); void on_window_set_mouse_capture(int fd, const LibGUI::WindowPacket::WindowSetMouseCapture&); void on_window_set_size(int fd, const LibGUI::WindowPacket::WindowSetSize&); + void on_window_set_min_size(int fd, const LibGUI::WindowPacket::WindowSetMinSize&); void on_window_set_fullscreen(int fd, const LibGUI::WindowPacket::WindowSetFullscreen&); void on_window_set_title(int fd, const LibGUI::WindowPacket::WindowSetTitle&); diff --git a/userspace/programs/WindowServer/main.cpp b/userspace/programs/WindowServer/main.cpp index 2d3546ce..04070565 100644 --- a/userspace/programs/WindowServer/main.cpp +++ b/userspace/programs/WindowServer/main.cpp @@ -375,6 +375,10 @@ int main() if (auto ret = LibGUI::WindowPacket::WindowSetSize::deserialize(client_data.packet_buffer.span()); !ret.is_error()) window_server.on_window_set_size(fd, ret.release_value()); break; + case LibGUI::PacketType::WindowSetMinSize: + if (auto ret = LibGUI::WindowPacket::WindowSetMinSize::deserialize(client_data.packet_buffer.span()); !ret.is_error()) + window_server.on_window_set_min_size(fd, ret.release_value()); + break; case LibGUI::PacketType::WindowSetFullscreen: if (auto ret = LibGUI::WindowPacket::WindowSetFullscreen::deserialize(client_data.packet_buffer.span()); !ret.is_error()) window_server.on_window_set_fullscreen(fd, ret.release_value());