summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2021-03-27 14:34:38 -0600
committerAndreas Kling <kling@serenityos.org>2021-03-28 20:42:21 +0200
commitb8f462a78b459466d34945ee82fb1e6bcea936ae (patch)
tree1f38972a21c885d14b02af6e79786448b6e6051d /Userland
parent7e9c265cc071a00c39ade29d7735106d37f44b10 (diff)
downloadserenity-b8f462a78b459466d34945ee82fb1e6bcea936ae.zip
WindowServer: Add menu item fade-out animation upon activation
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Services/WindowServer/Menu.cpp50
-rw-r--r--Userland/Services/WindowServer/Menu.h2
2 files changed, 52 insertions, 0 deletions
diff --git a/Userland/Services/WindowServer/Menu.cpp b/Userland/Services/WindowServer/Menu.cpp
index f476741f3d..c0293e2440 100644
--- a/Userland/Services/WindowServer/Menu.cpp
+++ b/Userland/Services/WindowServer/Menu.cpp
@@ -456,11 +456,61 @@ void Menu::clear_hovered_item()
redraw();
}
+void Menu::start_activation_animation(MenuItem& item)
+{
+ VERIFY(menu_window());
+ VERIFY(menu_window()->backing_store());
+ auto window = Window::construct(*this, WindowType::Menu);
+ window->set_frameless(true);
+ window->set_hit_testing_enabled(false);
+ window->set_opacity(0.8f); // start out transparent so we don't have to recompute occlusions
+ window->set_rect(item.rect().translated(m_menu_window->rect().location()));
+ window->set_event_filter([](Core::Event&) {
+ // ignore all events
+ return false;
+ });
+
+ VERIFY(window->backing_store());
+ Gfx::Painter painter(*window->backing_store());
+ painter.blit({}, *menu_window()->backing_store(), item.rect(), 1.0f, false);
+ window->invalidate();
+
+ struct AnimationInfo {
+ RefPtr<Core::Timer> timer;
+ RefPtr<Window> window;
+ u8 step { 8 }; // Must be even number!
+
+ AnimationInfo(NonnullRefPtr<Window>&& window)
+ : window(move(window))
+ {
+ }
+ };
+ auto animation = adopt_own(*new AnimationInfo(move(window)));
+ auto& timer = animation->timer;
+ timer = Core::Timer::create_repeating(50, [this, animation = animation.ptr(), animation_ref = move(animation)] {
+ VERIFY(animation->step % 2 == 0);
+ animation->step -= 2;
+ if (animation->step == 0) {
+ animation->window->set_visible(false);
+ animation->timer->stop();
+ animation->timer = nullptr; // break circular reference
+ return;
+ }
+
+ float opacity = (float)animation->step / 10.0f;
+ animation->window->set_opacity(opacity);
+ });
+ timer->start();
+}
+
void Menu::did_activate(MenuItem& item, bool leave_menu_open)
{
if (item.type() == MenuItem::Type::Separator)
return;
+ if (!leave_menu_open)
+ start_activation_animation(item);
+
if (on_item_activation)
on_item_activation(item);
diff --git a/Userland/Services/WindowServer/Menu.h b/Userland/Services/WindowServer/Menu.h
index eacee3d7de..9ef4cc34ae 100644
--- a/Userland/Services/WindowServer/Menu.h
+++ b/Userland/Services/WindowServer/Menu.h
@@ -135,6 +135,8 @@ private:
void did_activate(MenuItem&, bool leave_menu_open);
void update_for_new_hovered_item(bool make_input = false);
+ void start_activation_animation(MenuItem&);
+
ClientConnection* m_client { nullptr };
int m_menu_id { 0 };
String m_name;