Explorar o código

WindowServer: Add a window minimization button.

The window is simply ignored in the painting and hit testing traversal
when in minimized state, same as we do for invisible windows.

The WM_SetActiveWindow message (sent by Taskbar) brings it back into the
non-minimized state. :^)
Andreas Kling %!s(int64=6) %!d(string=hai) anos
pai
achega
f6ca94605c

+ 1 - 0
Servers/WindowServer/WSClientConnection.cpp

@@ -532,6 +532,7 @@ void WSClientConnection::handle_request(const WSWMAPISetActiveWindowRequest& req
         return;
     }
     auto& window = *(*it).value;
+    window.set_minimized(false);
     WSWindowManager::the().move_to_front_and_make_active(window);
 }
 

+ 8 - 0
Servers/WindowServer/WSWindow.cpp

@@ -112,6 +112,14 @@ static WSAPI_WindowType to_api(WSWindowType ws_type)
     }
 }
 
+void WSWindow::set_minimized(bool minimized)
+{
+    if (m_minimized == minimized)
+        return;
+    m_minimized = minimized;
+    invalidate();
+}
+
 void WSWindow::on_message(const WSMessage& message)
 {
     if (m_internal_owner)

+ 4 - 0
Servers/WindowServer/WSWindow.h

@@ -19,6 +19,9 @@ public:
     WSWindow(WSMessageReceiver&, WSWindowType);
     virtual ~WSWindow() override;
 
+    bool is_minimized() const { return m_minimized; }
+    void set_minimized(bool);
+
     WSWindowFrame& frame() { return m_frame; }
     const WSWindowFrame& frame() const { return m_frame; }
 
@@ -139,6 +142,7 @@ private:
     bool m_modal { false };
     bool m_resizable { false };
     bool m_listens_to_wm_events { false };
+    bool m_minimized { false };
     RetainPtr<GraphicsBitmap> m_backing_store;
     RetainPtr<GraphicsBitmap> m_last_backing_store;
     int m_window_id { -1 };

+ 24 - 0
Servers/WindowServer/WSWindowFrame.cpp

@@ -26,15 +26,39 @@ static CharacterBitmap* s_close_button_bitmap;
 static const int s_close_button_bitmap_width = 8;
 static const int s_close_button_bitmap_height = 9;
 
+static const char* s_minimize_button_bitmap_data = {
+    "        "
+    "        "
+    "##    ##"
+    "###  ###"
+    " ###### "
+    "  ####  "
+    "   ##   "
+    "        "
+    "        "
+};
+
+static CharacterBitmap* s_minimize_button_bitmap;
+static const int s_minimize_button_bitmap_width = 8;
+static const int s_minimize_button_bitmap_height = 9;
+
+
 WSWindowFrame::WSWindowFrame(WSWindow& window)
     : m_window(window)
 {
     if (!s_close_button_bitmap)
         s_close_button_bitmap = &CharacterBitmap::create_from_ascii(s_close_button_bitmap_data, s_close_button_bitmap_width, s_close_button_bitmap_height).leak_ref();
 
+    if (!s_minimize_button_bitmap)
+        s_minimize_button_bitmap = &CharacterBitmap::create_from_ascii(s_minimize_button_bitmap_data, s_minimize_button_bitmap_width, s_minimize_button_bitmap_height).leak_ref();
+
     m_buttons.append(make<WSButton>(*this, *s_close_button_bitmap, [this] {
         m_window.on_message(WSMessage(WSMessage::WindowCloseRequest));
     }));
+
+    m_buttons.append(make<WSButton>(*this, *s_minimize_button_bitmap, [this] {
+        m_window.set_minimized(true);
+    }));
 }
 
 WSWindowFrame::~WSWindowFrame()

+ 8 - 3
Servers/WindowServer/WSWindowManager.cpp

@@ -624,6 +624,7 @@ void WSWindowManager::process_mouse_event(const WSMouseEvent& event, WSWindow*&
         if (!window->global_cursor_tracking())
             continue;
         ASSERT(window->is_visible()); // Maybe this should be supported? Idk. Let's catch it and think about it later.
+        ASSERT(!window->is_minimized()); // Maybe this should also be supported? Idk.
         windows_who_received_mouse_event_due_to_cursor_tracking.set(window);
         window->on_message(event.translated(-window->position()));
     }
@@ -688,6 +689,8 @@ void WSWindowManager::compose()
         for (auto* window = m_windows_in_order.head(); window; window = window->next()) {
             if (!window->is_visible())
                 continue;
+            if (window->is_minimized())
+                continue;
             if (window->opacity() < 1.0f)
                 continue;
             if (window->has_alpha_channel()) {
@@ -712,11 +715,13 @@ void WSWindowManager::compose()
             if (!checking)
                 return IterationDecision::Continue;
             if (!window.is_visible())
-                return IterationDecision::Continue;;
+                return IterationDecision::Continue;
+            if (window.is_minimized())
+                return IterationDecision::Continue;
             if (window.opacity() < 1.0f)
-                return IterationDecision::Continue;;
+                return IterationDecision::Continue;
             if (window.has_alpha_channel())
-                return IterationDecision::Continue;;
+                return IterationDecision::Continue;
             if (window.frame().rect().contains(rect)) {
                 found = true;
                 return IterationDecision::Abort;

+ 4 - 0
Servers/WindowServer/WSWindowManager.h

@@ -214,6 +214,8 @@ IterationDecision WSWindowManager::for_each_visible_window_of_type_from_back_to_
     for (auto* window = m_windows_in_order.head(); window; window = window->next()) {
         if (!window->is_visible())
             continue;
+        if (window->is_minimized())
+            continue;
         if (window->type() != type)
             continue;
         if (m_highlight_window.ptr() == window) {
@@ -253,6 +255,8 @@ IterationDecision WSWindowManager::for_each_visible_window_of_type_from_front_to
     for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) {
         if (!window->is_visible())
             continue;
+        if (window->is_minimized())
+            continue;
         if (window->type() != type)
             continue;
         if (window == m_highlight_window.ptr())