From 77971919fe8fbef9037bd2bef6997ce327469d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Sat, 5 Sep 2026 16:50:22 -0700 Subject: [PATCH 1/2] PopoverManager: animate popover --- meson.build | 1 + src/Services/PopoverManager.vala | 68 +++++++++++++++++++++++++++++++- src/meson.build | 1 + 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 57719c49..1451cdbb 100644 --- a/meson.build +++ b/meson.build @@ -24,6 +24,7 @@ i18n = import('i18n') gnome = import('gnome') pkg = import('pkgconfig') +adw_dep = dependency('libadwaita-1') glib_dep = dependency('glib-2.0', version: '>=2.32') gio_dep = dependency('gio-2.0') gio_unix_dep = dependency('gio-unix-2.0') diff --git a/src/Services/PopoverManager.vala b/src/Services/PopoverManager.vala index 78bfe843..879880c3 100644 --- a/src/Services/PopoverManager.vala +++ b/src/Services/PopoverManager.vala @@ -20,6 +20,8 @@ public class Wingpanel.Services.PopoverManager : Object { public bool indicator_open { get; private set; default = false; } + private Adw.TimedAnimation fade; + private Adw.TimedAnimation scale; private Gtk.Popover popover; private Wingpanel.Widgets.IndicatorEntry? _current_indicator = null; @@ -57,27 +59,89 @@ public class Wingpanel.Services.PopoverManager : Object { popover.child = _current_indicator.indicator_widget; _current_indicator.display_widget.has_tooltip = false; popover.set_parent (_current_indicator); - popover.popup (); + set_revealed (true); _current_indicator.set_state_flags (CHECKED, true); _current_indicator.base_indicator.opened (); } else { ((Widgets.IndicatorEntry)popover.parent).display_widget.has_tooltip = true; - popover.popdown (); + set_revealed (false); } } } construct { popover = new Gtk.Popover () { + halign = CENTER, has_arrow = false, position = BOTTOM }; popover.add_css_class ("indicator"); + fade = new Adw.TimedAnimation ( + popover, 0, 1, + Granite.TRANSITION_DURATION_OPEN, + new Adw.PropertyAnimationTarget (popover, "opacity") + ) { + easing = EASE_IN_OUT_QUAD + }; + + var scale_target = new Adw.CallbackAnimationTarget ((val) => { + var height = _current_indicator.indicator_widget.get_height (); + var width = _current_indicator.indicator_widget.get_width (); + + var center_x = (width - (val * width)) / 2.0; + + _current_indicator.indicator_widget.allocate ( + width, height, -1, + new Gsk.Transform () + .scale ((float) val, (float) val) + ); + + var popover_height = popover.get_height (); + var popover_width = popover.get_width (); + + popover.present (); + popover.size_allocate ( + (int) (popover_width * val), (int) (popover_height * val), -1 + ); + }); + + scale = new Adw.TimedAnimation ( + popover, 0.5, 1, + Granite.TRANSITION_DURATION_OPEN, + scale_target + ) { + easing = EASE_IN_OUT_QUAD + }; + popover.closed.connect (() => { _current_indicator.set_state_flags (NORMAL, true); current_indicator = null; popover.unparent (); }); } + + private void set_revealed (bool revealed) { + fade.skip (); + scale.skip (); + + // Avoid a stutter at the beginning + popover.opacity = 0; + + fade.reverse = !revealed; + + if (revealed) { + popover.popup (); + fade.duration = Granite.TRANSITION_DURATION_OPEN; + scale.duration = Granite.TRANSITION_DURATION_OPEN; + scale.easing = EASE_IN_OUT_QUAD; + } else { + fade.duration = Granite.TRANSITION_DURATION_CLOSE; + scale.duration = Granite.TRANSITION_DURATION_CLOSE; + scale.easing = EASE_IN_OUT_QUAD; + } + + fade.play (); + scale.play (); + } } diff --git a/src/meson.build b/src/meson.build index 876f50d4..2785c83c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -12,6 +12,7 @@ wingpanel_files = files( wingpanel_deps = [ libwingpanel_dep, + adw_dep, granite_dep, gdk_wl_dep, posix_dep, From 5f64ac5405be26c06084825540d237f977bb7468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Sat, 5 Sep 2026 17:52:18 -0700 Subject: [PATCH 2/2] Fix some flicker --- src/Services/PopoverManager.vala | 39 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/Services/PopoverManager.vala b/src/Services/PopoverManager.vala index 879880c3..d5c1c285 100644 --- a/src/Services/PopoverManager.vala +++ b/src/Services/PopoverManager.vala @@ -56,14 +56,8 @@ public class Wingpanel.Services.PopoverManager : Object { } if (_current_indicator != null) { - popover.child = _current_indicator.indicator_widget; - _current_indicator.display_widget.has_tooltip = false; - popover.set_parent (_current_indicator); set_revealed (true); - _current_indicator.set_state_flags (CHECKED, true); - _current_indicator.base_indicator.opened (); } else { - ((Widgets.IndicatorEntry)popover.parent).display_widget.has_tooltip = true; set_revealed (false); } } @@ -86,28 +80,23 @@ public class Wingpanel.Services.PopoverManager : Object { }; var scale_target = new Adw.CallbackAnimationTarget ((val) => { - var height = _current_indicator.indicator_widget.get_height (); - var width = _current_indicator.indicator_widget.get_width (); - - var center_x = (width - (val * width)) / 2.0; - - _current_indicator.indicator_widget.allocate ( - width, height, -1, - new Gsk.Transform () - .scale ((float) val, (float) val) - ); - var popover_height = popover.get_height (); var popover_width = popover.get_width (); - popover.present (); popover.size_allocate ( (int) (popover_width * val), (int) (popover_height * val), -1 ); + + _current_indicator.indicator_widget.allocate ( + //FIXME: what sorcery is this? + int.max (0, popover_width - 14), int.max (0, popover_height - 20), -1, + new Gsk.Transform () + .scale ((float) val, (float) val) + ); }); scale = new Adw.TimedAnimation ( - popover, 0.5, 1, + popover, 0, 1, Granite.TRANSITION_DURATION_OPEN, scale_target ) { @@ -131,11 +120,21 @@ public class Wingpanel.Services.PopoverManager : Object { fade.reverse = !revealed; if (revealed) { + _current_indicator.display_widget.has_tooltip = false; + _current_indicator.set_state_flags (CHECKED, true); + _current_indicator.base_indicator.opened (); + + popover.set_parent (_current_indicator); + popover.child = _current_indicator.indicator_widget; + popover.present (); popover.popup (); + fade.duration = Granite.TRANSITION_DURATION_OPEN; scale.duration = Granite.TRANSITION_DURATION_OPEN; - scale.easing = EASE_IN_OUT_QUAD; + scale.easing = EASE_OUT_ELASTIC; } else { + ((Widgets.IndicatorEntry)popover.parent).display_widget.has_tooltip = true; + fade.duration = Granite.TRANSITION_DURATION_CLOSE; scale.duration = Granite.TRANSITION_DURATION_CLOSE; scale.easing = EASE_IN_OUT_QUAD;