Explorar o código

Add concept of size increments to windowing system.

Use this to implement incremental resizing for Terminal so that we only
ever resize to fit a perfect number of rows and columns.

This is very nice. :^)
Andreas Kling %!s(int64=6) %!d(string=hai) anos
pai
achega
6084cd0c56

+ 6 - 1
Applications/Terminal/Terminal.cpp

@@ -785,7 +785,6 @@ void Terminal::force_repaint()
 {
 {
     for (int i = 0; i < m_rows; ++i)
     for (int i = 0; i < m_rows; ++i)
         line(i).dirty = true;
         line(i).dirty = true;
-    m_need_full_flush = true;
     update();
     update();
 }
 }
 
 
@@ -795,3 +794,9 @@ void Terminal::resize_event(GResizeEvent& event)
     int new_rows = event.size().height() / m_line_height;
     int new_rows = event.size().height() / m_line_height;
     set_size(new_columns, new_rows);
     set_size(new_columns, new_rows);
 }
 }
+
+void Terminal::apply_size_increments_to_window(GWindow& window)
+{
+    window.set_size_increment({ font().glyph_width(), m_line_height });
+    window.set_base_size({ m_inset, m_inset });
+}

+ 2 - 0
Applications/Terminal/Terminal.h

@@ -21,6 +21,8 @@ public:
     void flush_dirty_lines();
     void flush_dirty_lines();
     void force_repaint();
     void force_repaint();
 
 
+    void apply_size_increments_to_window(GWindow&);
+
 private:
 private:
     virtual void event(GEvent&) override;
     virtual void event(GEvent&) override;
     virtual void paint_event(GPaintEvent&) override;
     virtual void paint_event(GPaintEvent&) override;

+ 1 - 0
Applications/Terminal/main.cpp

@@ -92,6 +92,7 @@ int main(int argc, char** argv)
     window->set_has_alpha_channel(true);
     window->set_has_alpha_channel(true);
     window->set_main_widget(&terminal);
     window->set_main_widget(&terminal);
     window->move_to(300, 300);
     window->move_to(300, 300);
+    terminal.apply_size_increments_to_window(*window);
     window->show();
     window->show();
 
 
     auto menubar = make<GMenuBar>();
     auto menubar = make<GMenuBar>();

+ 2 - 0
LibGUI/GWindow.cpp

@@ -61,6 +61,8 @@ void GWindow::show()
     request.window.rect = m_rect_when_windowless;
     request.window.rect = m_rect_when_windowless;
     request.window.has_alpha_channel = m_has_alpha_channel;
     request.window.has_alpha_channel = m_has_alpha_channel;
     request.window.opacity = m_opacity_when_windowless;
     request.window.opacity = m_opacity_when_windowless;
+    request.window.size_increment = m_size_increment;
+    request.window.base_size = m_base_size;
     ASSERT(m_title_when_windowless.length() < sizeof(request.text));
     ASSERT(m_title_when_windowless.length() < sizeof(request.text));
     strcpy(request.text, m_title_when_windowless.characters());
     strcpy(request.text, m_title_when_windowless.characters());
     request.text_length = m_title_when_windowless.length();
     request.text_length = m_title_when_windowless.length();

+ 7 - 0
LibGUI/GWindow.h

@@ -70,6 +70,11 @@ public:
 
 
     GraphicsBitmap* backing() { return m_backing.ptr(); }
     GraphicsBitmap* backing() { return m_backing.ptr(); }
 
 
+    Size size_increment() const { return m_size_increment; }
+    void set_size_increment(const Size& increment) { m_size_increment = increment; }
+    Size base_size() const { return m_base_size; }
+    void set_base_size(const Size& size) { m_base_size = size; }
+
 private:
 private:
     virtual const char* class_name() const override { return "GWindow"; }
     virtual const char* class_name() const override { return "GWindow"; }
 
 
@@ -83,6 +88,8 @@ private:
     Rect m_rect_when_windowless;
     Rect m_rect_when_windowless;
     String m_title_when_windowless;
     String m_title_when_windowless;
     Vector<Rect> m_pending_paint_event_rects;
     Vector<Rect> m_pending_paint_event_rects;
+    Size m_size_increment;
+    Size m_base_size;
     bool m_is_active { false };
     bool m_is_active { false };
     bool m_should_exit_app_on_close { false };
     bool m_should_exit_app_on_close { false };
     bool m_has_alpha_channel { false };
     bool m_has_alpha_channel { false };

+ 2 - 1
SharedGraphics/Size.h

@@ -10,7 +10,8 @@ public:
     Size(int w, int h) : m_width(w), m_height(h) { }
     Size(int w, int h) : m_width(w), m_height(h) { }
     Size(const WSAPI_Size&);
     Size(const WSAPI_Size&);
 
 
-    bool is_empty() const { return !m_width || !m_height; }
+    bool is_null() const { return !m_width && !m_height; }
+    bool is_empty() const { return m_width <= 0 || m_height <= 0; }
 
 
     int width() const { return m_width; }
     int width() const { return m_width; }
     int height() const { return m_height; }
     int height() const { return m_height; }

+ 2 - 0
WindowServer/WSAPITypes.h

@@ -170,6 +170,8 @@ struct WSAPI_ClientMessage {
             WSAPI_Rect rect;
             WSAPI_Rect rect;
             bool has_alpha_channel;
             bool has_alpha_channel;
             float opacity;
             float opacity;
+            WSAPI_Size base_size;
+            WSAPI_Size size_increment;
         } window;
         } window;
         struct {
         struct {
             WSAPI_Size size;
             WSAPI_Size size;

+ 1 - 0
WindowServer/WSClientConnection.cpp

@@ -319,6 +319,7 @@ void WSClientConnection::handle_request(WSAPICreateWindowRequest& request)
     window->set_title(request.title());
     window->set_title(request.title());
     window->set_rect(request.rect());
     window->set_rect(request.rect());
     window->set_opacity(request.opacity());
     window->set_opacity(request.opacity());
+    window->set_size_increment(request.size_increment());
     m_windows.set(window_id, move(window));
     m_windows.set(window_id, move(window));
     WSAPI_ServerMessage response;
     WSAPI_ServerMessage response;
     response.type = WSAPI_ServerMessage::Type::DidCreateWindow;
     response.type = WSAPI_ServerMessage::Type::DidCreateWindow;

+ 7 - 1
WindowServer/WSMessage.h

@@ -349,12 +349,14 @@ private:
 
 
 class WSAPICreateWindowRequest : public WSAPIClientRequest {
 class WSAPICreateWindowRequest : public WSAPIClientRequest {
 public:
 public:
-    WSAPICreateWindowRequest(int client_id, const Rect& rect, const String& title, bool has_alpha_channel, float opacity)
+    WSAPICreateWindowRequest(int client_id, const Rect& rect, const String& title, bool has_alpha_channel, float opacity, const Size& base_size, const Size& size_increment)
         : WSAPIClientRequest(WSMessage::APICreateWindowRequest, client_id)
         : WSAPIClientRequest(WSMessage::APICreateWindowRequest, client_id)
         , m_rect(rect)
         , m_rect(rect)
         , m_title(title)
         , m_title(title)
         , m_opacity(opacity)
         , m_opacity(opacity)
         , m_has_alpha_channel(has_alpha_channel)
         , m_has_alpha_channel(has_alpha_channel)
+        , m_base_size(base_size)
+        , m_size_increment(size_increment)
     {
     {
     }
     }
 
 
@@ -362,12 +364,16 @@ public:
     String title() const { return m_title; }
     String title() const { return m_title; }
     bool has_alpha_channel() const { return m_has_alpha_channel; }
     bool has_alpha_channel() const { return m_has_alpha_channel; }
     float opacity() const { return m_opacity; }
     float opacity() const { return m_opacity; }
+    Size size_increment() const { return m_size_increment; }
+    Size base_size() const { return m_base_size; }
 
 
 private:
 private:
     Rect m_rect;
     Rect m_rect;
     String m_title;
     String m_title;
     float m_opacity { 0 };
     float m_opacity { 0 };
     bool m_has_alpha_channel { false };
     bool m_has_alpha_channel { false };
+    Size m_size_increment;
+    Size m_base_size;
 };
 };
 
 
 class WSAPIDestroyWindowRequest : public WSAPIClientRequest {
 class WSAPIDestroyWindowRequest : public WSAPIClientRequest {

+ 1 - 1
WindowServer/WSMessageLoop.cpp

@@ -302,7 +302,7 @@ void WSMessageLoop::on_receive_from_client(int client_id, const WSAPI_ClientMess
         break;
         break;
     case WSAPI_ClientMessage::Type::CreateWindow:
     case WSAPI_ClientMessage::Type::CreateWindow:
         ASSERT(message.text_length < sizeof(message.text));
         ASSERT(message.text_length < sizeof(message.text));
-        post_message(client, make<WSAPICreateWindowRequest>(client_id, message.window.rect, String(message.text, message.text_length), message.window.has_alpha_channel, message.window.opacity));
+        post_message(client, make<WSAPICreateWindowRequest>(client_id, message.window.rect, String(message.text, message.text_length), message.window.has_alpha_channel, message.window.opacity, message.window.base_size, message.window.size_increment));
         break;
         break;
     case WSAPI_ClientMessage::Type::DestroyWindow:
     case WSAPI_ClientMessage::Type::DestroyWindow:
         post_message(client, make<WSAPIDestroyWindowRequest>(client_id, message.window_id));
         post_message(client, make<WSAPIDestroyWindowRequest>(client_id, message.window_id));

+ 8 - 0
WindowServer/WSWindow.h

@@ -70,6 +70,12 @@ public:
     bool has_painted_since_last_resize() const { return m_has_painted_since_last_resize; }
     bool has_painted_since_last_resize() const { return m_has_painted_since_last_resize; }
     void set_has_painted_since_last_resize(bool b) { m_has_painted_since_last_resize = b; }
     void set_has_painted_since_last_resize(bool b) { m_has_painted_since_last_resize = b; }
 
 
+    Size size_increment() const { return m_size_increment; }
+    void set_size_increment(const Size& increment) { m_size_increment = increment; }
+
+    Size base_size() const { return m_base_size; }
+    void set_base_size(const Size& size) { m_base_size = size; }
+
     // For InlineLinkedList.
     // For InlineLinkedList.
     // FIXME: Maybe make a ListHashSet and then WSWindowManager can just use that.
     // FIXME: Maybe make a ListHashSet and then WSWindowManager can just use that.
     WSWindow* m_next { nullptr };
     WSWindow* m_next { nullptr };
@@ -89,4 +95,6 @@ private:
     int m_window_id { -1 };
     int m_window_id { -1 };
     float m_opacity { 1 };
     float m_opacity { 1 };
     Rect m_last_lazy_resize_rect;
     Rect m_last_lazy_resize_rect;
+    Size m_size_increment;
+    Size m_base_size;
 };
 };

+ 8 - 0
WindowServer/WSWindowManager.cpp

@@ -548,6 +548,14 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_
             auto new_rect = m_resize_window_original_rect;
             auto new_rect = m_resize_window_original_rect;
             new_rect.set_width(max(50, new_rect.width() + dx));
             new_rect.set_width(max(50, new_rect.width() + dx));
             new_rect.set_height(max(50, new_rect.height() + dy));
             new_rect.set_height(max(50, new_rect.height() + dy));
+
+            if (!m_resize_window->size_increment().is_null()) {
+                int horizontal_incs = (new_rect.width() - m_resize_window->base_size().width()) / m_resize_window->size_increment().width();
+                new_rect.set_width(m_resize_window->base_size().width() + horizontal_incs * m_resize_window->size_increment().width());
+                int vertical_incs = (new_rect.height() - m_resize_window->base_size().height()) / m_resize_window->size_increment().height();
+                new_rect.set_height(m_resize_window->base_size().height() + vertical_incs * m_resize_window->size_increment().height());
+            }
+
             if (m_resize_window->rect() == new_rect)
             if (m_resize_window->rect() == new_rect)
                 return;
                 return;
 #ifdef RESIZE_DEBUG
 #ifdef RESIZE_DEBUG