diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-12-03 21:34:34 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-12-03 21:34:34 +0100 |
commit | d111b6ead445590148a4b5f352c925a5f9eb0ca0 (patch) | |
tree | 69bf0017fff0711e7d99c897b6fa7c97d348780b /Servers | |
parent | 51262e7e2d5b3d4859337a5df784ab4f470be41a (diff) | |
download | serenity-d111b6ead445590148a4b5f352c925a5f9eb0ca0.zip |
WindowServer+Taskbar: Animate window frames on minimize/unminimize
We now show a quick window outline animation when going in/out of
minimized state. It's a simple 10 frame animation at 60fps, just to
give a visual cue of what's happening with the window.
The Taskbar sends over the corresponding button rect for each window
to the WindowServer using a new WM_SetWindowTaskbarRect message.
Note that when unminimizing, we still *show* the window right away,
and don't hold off until the animation has finished. This avoids
making the desktop feel slow/sluggish. :^)
Diffstat (limited to 'Servers')
-rw-r--r-- | Servers/WindowServer/WSClientConnection.cpp | 16 | ||||
-rw-r--r-- | Servers/WindowServer/WSClientConnection.h | 1 | ||||
-rw-r--r-- | Servers/WindowServer/WSCompositor.cpp | 36 | ||||
-rw-r--r-- | Servers/WindowServer/WSWindow.cpp | 1 | ||||
-rw-r--r-- | Servers/WindowServer/WSWindow.h | 12 | ||||
-rw-r--r-- | Servers/WindowServer/WindowServer.ipc | 1 |
6 files changed, 67 insertions, 0 deletions
diff --git a/Servers/WindowServer/WSClientConnection.cpp b/Servers/WindowServer/WSClientConnection.cpp index 7f3e26efdb..3d365d3682 100644 --- a/Servers/WindowServer/WSClientConnection.cpp +++ b/Servers/WindowServer/WSClientConnection.cpp @@ -612,3 +612,19 @@ bool WSClientConnection::is_showing_modal_window() const } return false; } + +void WSClientConnection::handle(const WindowServer::WM_SetWindowTaskbarRect& message) +{ + auto* client = WSClientConnection::from_client_id(message.client_id()); + if (!client) { + did_misbehave("WM_SetWindowTaskbarRect: Bad client ID"); + return; + } + auto it = client->m_windows.find(message.window_id()); + if (it == client->m_windows.end()) { + did_misbehave("WM_SetWindowTaskbarRect: Bad window ID"); + return; + } + auto& window = *(*it).value; + window.set_taskbar_rect(message.rect()); +} diff --git a/Servers/WindowServer/WSClientConnection.h b/Servers/WindowServer/WSClientConnection.h index f0898ac6ad..9f50a0c901 100644 --- a/Servers/WindowServer/WSClientConnection.h +++ b/Servers/WindowServer/WSClientConnection.h @@ -86,6 +86,7 @@ private: virtual OwnPtr<WindowServer::PopupMenuResponse> handle(const WindowServer::PopupMenu&) override; virtual OwnPtr<WindowServer::DismissMenuResponse> handle(const WindowServer::DismissMenu&) override; virtual OwnPtr<WindowServer::SetWindowIconBitmapResponse> handle(const WindowServer::SetWindowIconBitmap&) override; + virtual void handle(const WindowServer::WM_SetWindowTaskbarRect&) override; HashMap<int, NonnullRefPtr<WSWindow>> m_windows; HashMap<int, NonnullOwnPtr<WSMenuBar>> m_menubars; diff --git a/Servers/WindowServer/WSCompositor.cpp b/Servers/WindowServer/WSCompositor.cpp index 98c16dd5b2..bf93ad7fd1 100644 --- a/Servers/WindowServer/WSCompositor.cpp +++ b/Servers/WindowServer/WSCompositor.cpp @@ -212,6 +212,42 @@ void WSCompositor::compose() draw_geometry_label(); } + static const int minimize_animation_steps = 10; + + wm.for_each_window([&](WSWindow& window) { + if (window.in_minimize_animation()) { + int animation_index = window.minimize_animation_index(); + + auto from_rect = window.is_minimized() ? window.frame().rect() : window.taskbar_rect(); + auto to_rect = window.is_minimized() ? window.taskbar_rect() : window.frame().rect(); + + float x_delta_per_step = (float)(from_rect.x() - to_rect.x()) / minimize_animation_steps; + float y_delta_per_step = (float)(from_rect.y() - to_rect.y()) / minimize_animation_steps; + float width_delta_per_step = (float)(from_rect.width() - to_rect.width()) / minimize_animation_steps; + float height_delta_per_step = (float)(from_rect.height() - to_rect.height()) / minimize_animation_steps; + + Rect rect { + from_rect.x() - (int)(x_delta_per_step * animation_index), + from_rect.y() - (int)(y_delta_per_step * animation_index), + from_rect.width() - (int)(width_delta_per_step * animation_index), + from_rect.height() - (int)(height_delta_per_step * animation_index) + }; + +#ifdef MINIMIZE_ANIMATION_DEBUG + dbg() << "Minimize animation from " << from_rect << " to " << to_rect << " frame# " << animation_index << " " << rect; +#endif + + m_back_painter->draw_rect(rect, Color::White); + + window.step_minimize_animation(); + if (window.minimize_animation_index() >= minimize_animation_steps) + window.end_minimize_animation(); + + invalidate(rect); + } + return IterationDecision::Continue; + }); + draw_cursor(); if (m_flash_flush) { diff --git a/Servers/WindowServer/WSWindow.cpp b/Servers/WindowServer/WSWindow.cpp index 855ece5094..d1fd08bfe7 100644 --- a/Servers/WindowServer/WSWindow.cpp +++ b/Servers/WindowServer/WSWindow.cpp @@ -103,6 +103,7 @@ void WSWindow::set_minimized(bool minimized) if (m_minimized == minimized) return; m_minimized = minimized; + start_minimize_animation(); if (!minimized) request_update({ {}, size() }); invalidate(); diff --git a/Servers/WindowServer/WSWindow.h b/Servers/WindowServer/WSWindow.h index 0be54481ca..9276a6a192 100644 --- a/Servers/WindowServer/WSWindow.h +++ b/Servers/WindowServer/WSWindow.h @@ -102,6 +102,9 @@ public: void set_rect_from_window_manager_resize(const Rect&); + void set_taskbar_rect(const Rect& rect) { m_taskbar_rect = rect; } + const Rect& taskbar_rect() const { return m_taskbar_rect; } + void move_to(const Point& position) { set_rect({ position, size() }); } void move_to(int x, int y) { move_to({ x, y }); } @@ -152,6 +155,13 @@ public: void request_update(const Rect&); DisjointRectSet take_pending_paint_rects() { return move(m_pending_paint_rects); } + bool in_minimize_animation() const { return m_minimize_animation_step != -1; } + + int minimize_animation_index() const { return m_minimize_animation_step; } + void step_minimize_animation() { m_minimize_animation_step += 1; } + void start_minimize_animation() { m_minimize_animation_step = 0; } + void end_minimize_animation() { m_minimize_animation_step = -1; } + // For InlineLinkedList. // FIXME: Maybe make a ListHashSet and then WSWindowManager can just use that. WSWindow* m_next { nullptr }; @@ -164,6 +174,7 @@ private: String m_title; Rect m_rect; Rect m_saved_nonfullscreen_rect; + Rect m_taskbar_rect; WSWindowType m_type { WSWindowType::Normal }; bool m_global_cursor_tracking_enabled { false }; bool m_automatic_cursor_tracking_enabled { false }; @@ -190,4 +201,5 @@ private: DisjointRectSet m_pending_paint_rects; Rect m_unmaximized_rect; RefPtr<WSMenu> m_window_menu; + int m_minimize_animation_step { -1 }; }; diff --git a/Servers/WindowServer/WindowServer.ipc b/Servers/WindowServer/WindowServer.ipc index e75ad0daf0..883d820219 100644 --- a/Servers/WindowServer/WindowServer.ipc +++ b/Servers/WindowServer/WindowServer.ipc @@ -52,6 +52,7 @@ endpoint WindowServer = 2 WM_SetWindowMinimized(i32 client_id, i32 window_id, bool minimized) =| WM_StartWindowResize(i32 client_id, i32 window_id) =| WM_PopupWindowMenu(i32 client_id, i32 window_id, Point screen_position) =| + WM_SetWindowTaskbarRect(i32 client_id, i32 window_id, Rect rect) =| SetWindowHasAlphaChannel(i32 window_id, bool has_alpha_channel) => () MoveWindowToFront(i32 window_id) => () |