mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-26 19:32:06 -05:00
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. :^)
This commit is contained in:
parent
51262e7e2d
commit
d111b6ead4
8 changed files with 78 additions and 0 deletions
|
@ -16,3 +16,13 @@ void TaskbarButton::context_menu_event(GContextMenuEvent&)
|
|||
{
|
||||
GWindowServerConnection::the().post_message(WindowServer::WM_PopupWindowMenu(m_identifier.client_id(), m_identifier.window_id(), screen_relative_rect().location()));
|
||||
}
|
||||
|
||||
void TaskbarButton::resize_event(GResizeEvent& event)
|
||||
{
|
||||
GWindowServerConnection::the().post_message(
|
||||
WindowServer::WM_SetWindowTaskbarRect(
|
||||
m_identifier.client_id(),
|
||||
m_identifier.window_id(),
|
||||
screen_relative_rect()));
|
||||
return GButton::resize_event(event);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ public:
|
|||
|
||||
private:
|
||||
virtual void context_menu_event(GContextMenuEvent&) override;
|
||||
virtual void resize_event(GResizeEvent&) override;
|
||||
|
||||
WindowIdentifier m_identifier;
|
||||
};
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
|
|
@ -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) => ()
|
||||
|
|
Loading…
Add table
Reference in a new issue