summaryrefslogtreecommitdiff
path: root/Servers
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-12-03 21:34:34 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-12-03 21:34:34 +0100
commitd111b6ead445590148a4b5f352c925a5f9eb0ca0 (patch)
tree69bf0017fff0711e7d99c897b6fa7c97d348780b /Servers
parent51262e7e2d5b3d4859337a5df784ab4f470be41a (diff)
downloadserenity-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.cpp16
-rw-r--r--Servers/WindowServer/WSClientConnection.h1
-rw-r--r--Servers/WindowServer/WSCompositor.cpp36
-rw-r--r--Servers/WindowServer/WSWindow.cpp1
-rw-r--r--Servers/WindowServer/WSWindow.h12
-rw-r--r--Servers/WindowServer/WindowServer.ipc1
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) => ()