diff options
author | Tom <tomut@yahoo.com> | 2021-03-27 14:34:38 -0600 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-03-28 20:42:21 +0200 |
commit | b8f462a78b459466d34945ee82fb1e6bcea936ae (patch) | |
tree | 1f38972a21c885d14b02af6e79786448b6e6051d /Userland | |
parent | 7e9c265cc071a00c39ade29d7735106d37f44b10 (diff) | |
download | serenity-b8f462a78b459466d34945ee82fb1e6bcea936ae.zip |
WindowServer: Add menu item fade-out animation upon activation
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Services/WindowServer/Menu.cpp | 50 | ||||
-rw-r--r-- | Userland/Services/WindowServer/Menu.h | 2 |
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; |