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..d5c1c285 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; @@ -54,30 +56,91 @@ 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); - popover.popup (); - _current_indicator.set_state_flags (CHECKED, true); - _current_indicator.base_indicator.opened (); + set_revealed (true); } 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 popover_height = popover.get_height (); + var popover_width = popover.get_width (); + + 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, 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) { + _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_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; + } + + 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,