Unverified Commit 3e83f1f4 authored by Erik Reider's avatar Erik Reider Committed by GitHub

Fixed Notification widgets not being disposed of properly (#653)

* Fixed Notification widgets not being disposed of properly * Fix notifications loading in whole image size instead of scaling it down * Fixed floating Notifications not being fully destroyed for quick notifications
parent fd056811
using Gtk 4.0; using Gtk 4.0;
using Adw 1;
template $SwayNotificationCenterNotification: Box { template $SwayNotificationCenterNotification: Adw.Bin {
hexpand: true; hexpand: true;
styles [ styles [
......
...@@ -134,6 +134,8 @@ public class AnimatedList : Gtk.Widget, Gtk.Scrollable { ...@@ -134,6 +134,8 @@ public class AnimatedList : Gtk.Widget, Gtk.Scrollable {
transition_children = false; transition_children = false;
remove.begin (child, false); remove.begin (child, false);
} }
base.dispose ();
} }
public bool get_border (out Gtk.Border border) { public bool get_border (out Gtk.Border border) {
...@@ -538,7 +540,7 @@ public class AnimatedList : Gtk.Widget, Gtk.Scrollable { ...@@ -538,7 +540,7 @@ public class AnimatedList : Gtk.Widget, Gtk.Scrollable {
* BOTTOM_TO_TOP: Top * BOTTOM_TO_TOP: Top
*/ */
public async AnimatedListItem ? prepend (Gtk.Widget widget) { public async AnimatedListItem ? prepend (Gtk.Widget widget) {
if (widget == null) { if (widget == null || widget.parent != null) {
warn_if_reached (); warn_if_reached ();
return null; return null;
} }
...@@ -570,7 +572,7 @@ public class AnimatedList : Gtk.Widget, Gtk.Scrollable { ...@@ -570,7 +572,7 @@ public class AnimatedList : Gtk.Widget, Gtk.Scrollable {
* BOTTOM_TO_TOP: Bottom * BOTTOM_TO_TOP: Bottom
*/ */
public async AnimatedListItem ? append (Gtk.Widget widget) { public async AnimatedListItem ? append (Gtk.Widget widget) {
if (widget == null) { if (widget == null || widget.parent != null) {
warn_if_reached (); warn_if_reached ();
return null; return null;
} }
...@@ -645,9 +647,9 @@ public class AnimatedList : Gtk.Widget, Gtk.Scrollable { ...@@ -645,9 +647,9 @@ public class AnimatedList : Gtk.Widget, Gtk.Scrollable {
// Will unparent itself when done animating // Will unparent itself when done animating
bool result = yield item.removed (transition_children && transition); bool result = yield item.removed (transition_children && transition);
item.unparent ();
children.remove (item); children.remove (item);
n_children--; n_children--;
item.destroy ();
queue_resize (); queue_resize ();
return result; return result;
} }
......
...@@ -29,9 +29,8 @@ public class AnimatedListItem : Gtk.Widget { ...@@ -29,9 +29,8 @@ public class AnimatedListItem : Gtk.Widget {
public bool animation_child_fade { get; construct set; } public bool animation_child_fade { get; construct set; }
public bool destroying { get; private set; default = false; } public bool destroying { get; private set; default = false; }
private Adw.CallbackAnimationTarget target;
private Adw.TimedAnimation animation; private Adw.TimedAnimation animation;
private double animation_value = 0.0; private double animation_value = 1.0;
private ulong animation_done_cb_id = 0; private ulong animation_done_cb_id = 0;
private unowned SourceFunc ? removed_cb = null; private unowned SourceFunc ? removed_cb = null;
private unowned SourceFunc ? added_cb = null; private unowned SourceFunc ? added_cb = null;
...@@ -48,14 +47,22 @@ public class AnimatedListItem : Gtk.Widget { ...@@ -48,14 +47,22 @@ public class AnimatedListItem : Gtk.Widget {
animation_child_fade: true animation_child_fade: true
); );
target = new Adw.CallbackAnimationTarget (animation_value_cb); Adw.CallbackAnimationTarget target = new Adw.CallbackAnimationTarget (set_animation_value);
animation = new Adw.TimedAnimation (this, 0.0, 1.0, animation = new Adw.TimedAnimation (this, 0.0, 1.0, animation_duration, target);
animation_duration, target);
bind_property ("animation-easing", bind_property ("animation-easing",
animation, "easing", animation, "easing",
BindingFlags.SYNC_CREATE, null, null); BindingFlags.SYNC_CREATE, null, null);
} }
public override void dispose () {
if (child != null) {
child.unparent ();
child = null;
}
base.dispose ();
}
public override Gtk.SizeRequestMode get_request_mode () { public override Gtk.SizeRequestMode get_request_mode () {
return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH; return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH;
} }
...@@ -164,26 +171,12 @@ public class AnimatedListItem : Gtk.Widget { ...@@ -164,26 +171,12 @@ public class AnimatedListItem : Gtk.Widget {
} }
} }
private void animation_value_cb (double value) { private void set_animation_value (double value) {
this.animation_value = value; animation_value = value;
queue_resize (); queue_resize ();
} }
private void animation_done_add () { private inline void remove_animation_done_cb () {
if (added_cb != null) {
added_cb ();
added_cb = null;
}
}
private void animation_done_remove () {
unparent ();
if (removed_cb != null) {
removed_cb ();
removed_cb = null;
}
}
private void animation_remove_done_cb () {
if (animation_done_cb_id != 0) { if (animation_done_cb_id != 0) {
animation.disconnect (animation_done_cb_id); animation.disconnect (animation_done_cb_id);
animation_done_cb_id = 0; animation_done_cb_id = 0;
...@@ -191,9 +184,16 @@ public class AnimatedListItem : Gtk.Widget { ...@@ -191,9 +184,16 @@ public class AnimatedListItem : Gtk.Widget {
} }
delegate void animation_done (Adw.Animation animation); delegate void animation_done (Adw.Animation animation);
private void animation_add_done_cb (animation_done handler) { private void set_animation_done_cb (animation_done handler) {
animation_remove_done_cb (); remove_animation_done_cb ();
animation_done_cb_id = animation.done.connect ((a) => handler (a)); animation_done_cb_id = animation.done.connect (handler);
}
private void added_finished_cb () {
if (added_cb != null) {
added_cb ();
added_cb = null;
}
} }
public async void added (bool transition) { public async void added (bool transition) {
...@@ -202,10 +202,10 @@ public class AnimatedListItem : Gtk.Widget { ...@@ -202,10 +202,10 @@ public class AnimatedListItem : Gtk.Widget {
return; return;
} }
animation_remove_done_cb (); remove_animation_done_cb ();
if (get_mapped () && transition) { if (get_mapped () && transition) {
animation_add_done_cb (animation_done_add); set_animation_done_cb (added_finished_cb);
added_cb = added.callback; added_cb = added.callback;
animation.value_from animation.value_from
= animation.state == Adw.AnimationState.PLAYING = animation.state == Adw.AnimationState.PLAYING
...@@ -215,8 +215,15 @@ public class AnimatedListItem : Gtk.Widget { ...@@ -215,8 +215,15 @@ public class AnimatedListItem : Gtk.Widget {
animation.play (); animation.play ();
yield; yield;
} else { } else {
animation_value = 1.0; set_animation_value (1.0);
animation_done_add (); added_finished_cb ();
}
}
private void removed_finised_cb () {
if (removed_cb != null) {
removed_cb ();
removed_cb = null;
} }
} }
...@@ -226,13 +233,15 @@ public class AnimatedListItem : Gtk.Widget { ...@@ -226,13 +233,15 @@ public class AnimatedListItem : Gtk.Widget {
return false; return false;
} }
animation_remove_done_cb (); remove_animation_done_cb ();
// Call the `added` callback if it's still stuck in the yield waiting state
added_finished_cb ();
set_can_focus (false); set_can_focus (false);
set_can_target (false); set_can_target (false);
if (get_mapped () && transition) { if (get_mapped () && transition) {
animation_add_done_cb (animation_done_remove); set_animation_done_cb (removed_finised_cb);
removed_cb = removed.callback; removed_cb = removed.callback;
animation.value_from animation.value_from
= animation.state == Adw.AnimationState.PLAYING = animation.state == Adw.AnimationState.PLAYING
...@@ -242,9 +251,16 @@ public class AnimatedListItem : Gtk.Widget { ...@@ -242,9 +251,16 @@ public class AnimatedListItem : Gtk.Widget {
animation.play (); animation.play ();
yield; yield;
} else { } else {
animation_value = 0.0; set_animation_value (0.0);
animation_done_remove (); removed_finised_cb ();
}
if (child != null) {
child.unparent ();
child = null;
} }
// Fixes the animation keeping a reference of the widget
animation = null;
return true; return true;
} }
......
...@@ -25,15 +25,22 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable { ...@@ -25,15 +25,22 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable {
// Animation // Animation
Adw.SpringAnimation animation; Adw.SpringAnimation animation;
Adw.AnimationTarget target;
// Swipe Gesture // Swipe Gesture
Adw.SwipeTracker swipe_tracker; Adw.SwipeTracker swipe_tracker;
bool transition_running = false; bool transition_running = false;
bool gesture_active = false; bool gesture_active = false;
double child_offset = 0; private double _swipe_progress = 0.0;
double swipe_progress = 0.0; public double swipe_progress {
get {
return _swipe_progress;
}
set {
_swipe_progress = value;
queue_allocate ();
}
}
SwipeDirection swipe_direction = SwipeDirection.SWIPE_RIGHT; SwipeDirection swipe_direction = SwipeDirection.SWIPE_RIGHT;
...@@ -52,7 +59,7 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable { ...@@ -52,7 +59,7 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable {
swipe_tracker.end_swipe.connect (swipe_end_swipe_cb); swipe_tracker.end_swipe.connect (swipe_end_swipe_cb);
double[] snap_dir = get_snap_points (); double[] snap_dir = get_snap_points ();
target = new Adw.CallbackAnimationTarget (animate_value_cb); Adw.PropertyAnimationTarget target = new Adw.PropertyAnimationTarget (this, "swipe-progress");
animation = new Adw.SpringAnimation (this, snap_dir[0], snap_dir[1], animation = new Adw.SpringAnimation (this, snap_dir[0], snap_dir[1],
new Adw.SpringParams (1, 0.5, 500), new Adw.SpringParams (1, 0.5, 500),
target); target);
...@@ -60,6 +67,14 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable { ...@@ -60,6 +67,14 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable {
animation.done.connect (animation_done_cb); animation.done.connect (animation_done_cb);
} }
public override void dispose () {
if (child != null) {
child.unparent ();
child = null;
}
base.dispose ();
}
public signal void dismissed (); public signal void dismissed ();
public void set_can_dismiss (bool state) { public void set_can_dismiss (bool state) {
...@@ -121,10 +136,6 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable { ...@@ -121,10 +136,6 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable {
* Callbacks * Callbacks
*/ */
private void animate_value_cb (double value) {
set_position (value);
}
private void animation_done_cb () { private void animation_done_cb () {
transition_running = false; transition_running = false;
if (swipe_progress != 0) { if (swipe_progress != 0) {
...@@ -142,7 +153,7 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable { ...@@ -142,7 +153,7 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable {
} }
private void swipe_update_swipe_cb (double distance) { private void swipe_update_swipe_cb (double distance) {
set_position (distance); swipe_progress = distance;
} }
private void swipe_end_swipe_cb (double velocity, double to) { private void swipe_end_swipe_cb (double velocity, double to) {
...@@ -166,15 +177,10 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable { ...@@ -166,15 +177,10 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable {
* Methods * Methods
*/ */
private void set_position (double value) {
this.swipe_progress = value;
queue_allocate ();
}
public void set_gesture_direction (SwipeDirection swipe_direction) { public void set_gesture_direction (SwipeDirection swipe_direction) {
this.swipe_direction = swipe_direction; this.swipe_direction = swipe_direction;
// Reset the position // Reset the position
set_position (0.0); swipe_progress = 0.0;
} }
/* /*
......
...@@ -40,7 +40,14 @@ namespace SwayNotificationCenter { ...@@ -40,7 +40,14 @@ namespace SwayNotificationCenter {
try { try {
if (is_uri) uri = uri.slice (URI_PREFIX.length, uri.length); if (is_uri) uri = uri.slice (URI_PREFIX.length, uri.length);
Gdk.Texture texture = Gdk.Texture.from_filename (Uri.unescape_string (uri)); Gtk.Requisition natural_size;
img.get_preferred_size (null, out natural_size);
Gdk.Pixbuf pixbuf = new Gdk.Pixbuf.from_file_at_size (
Uri.unescape_string (uri),
natural_size.width, natural_size.height);
Gdk.Texture texture = Gdk.Texture.for_pixbuf (pixbuf);
img.set_from_paintable (texture); img.set_from_paintable (texture);
} catch (Error e) { } catch (Error e) {
stderr.printf (e.message + "\n"); stderr.printf (e.message + "\n");
...@@ -59,14 +66,22 @@ namespace SwayNotificationCenter { ...@@ -59,14 +66,22 @@ namespace SwayNotificationCenter {
public static void set_image_data (ImageData data, public static void set_image_data (ImageData data,
Gtk.Image img) { Gtk.Image img) {
Gdk.MemoryFormat format = Gdk.MemoryFormat.R8G8B8; Gtk.Requisition natural_size;
if (data.has_alpha) { img.get_preferred_size (null, out natural_size);
format = Gdk.MemoryFormat.R8G8B8A8;
} Gdk.Pixbuf pixbuf = new Gdk.Pixbuf.with_unowned_data (data.data,
var texture = new Gdk.MemoryTexture (data.width, data.height, Gdk.Colorspace.RGB,
format, data.has_alpha,
new Bytes.static (data.data), data.bits_per_sample,
data.rowstride); data.width,
data.height,
data.rowstride,
null);
Gdk.Pixbuf scaled = pixbuf.scale_simple (natural_size.width,
natural_size.height,
Gdk.InterpType.BILINEAR);
Gdk.Texture texture = Gdk.Texture.for_pixbuf (scaled);
img.set_from_paintable (texture); img.set_from_paintable (texture);
} }
......
...@@ -8,6 +8,14 @@ public class IterBox : Gtk.Box { ...@@ -8,6 +8,14 @@ public class IterBox : Gtk.Box {
set_name ("iterbox"); set_name ("iterbox");
} }
public override void dispose () {
foreach (Gtk.Widget child in children) {
remove (child);
}
base.dispose ();
}
private void on_add (Gtk.Widget child) { private void on_add (Gtk.Widget child) {
length++; length++;
child.destroy.connect (() => { child.destroy.connect (() => {
......
...@@ -24,10 +24,14 @@ namespace SwayNotificationCenter { ...@@ -24,10 +24,14 @@ namespace SwayNotificationCenter {
}; };
button.add_css_class ("close-button"); button.add_css_class ("close-button");
button.add_css_class ("circular"); button.add_css_class ("circular");
button.clicked.connect (() => this.clicked ()); button.clicked.connect (click_cb);
revealer.set_child (button); revealer.set_child (button);
} }
private void click_cb () {
clicked ();
}
public signal void clicked (); public signal void clicked ();
public void set_reveal (bool state) { public void set_reveal (bool state) {
...@@ -50,7 +54,7 @@ namespace SwayNotificationCenter { ...@@ -50,7 +54,7 @@ namespace SwayNotificationCenter {
public enum NotificationType { CONTROL_CENTER, POPUP } public enum NotificationType { CONTROL_CENTER, POPUP }
[GtkTemplate (ui = "/org/erikreider/swaync/ui/notification.ui")] [GtkTemplate (ui = "/org/erikreider/swaync/ui/notification.ui")]
public class Notification : Gtk.Box { public class Notification : Adw.Bin {
[GtkChild] [GtkChild]
unowned Gtk.Revealer revealer; unowned Gtk.Revealer revealer;
[GtkChild] [GtkChild]
...@@ -276,8 +280,7 @@ namespace SwayNotificationCenter { ...@@ -276,8 +280,7 @@ namespace SwayNotificationCenter {
noti_daemon.manually_close_notification ( noti_daemon.manually_close_notification (
param.applied_id, false); param.applied_id, false);
} catch (Error e) { } catch (Error e) {
printerr ("Error: %s\n", e.message); critical ("Error: %s", e.message);
this.destroy ();
} }
}); });
...@@ -671,8 +674,7 @@ namespace SwayNotificationCenter { ...@@ -671,8 +674,7 @@ namespace SwayNotificationCenter {
noti_daemon.manually_close_notification (param.applied_id, noti_daemon.manually_close_notification (param.applied_id,
is_timeout); is_timeout);
} catch (Error e) { } catch (Error e) {
print ("Error: %s\n", e.message); critical ("Error: %s", e.message);
this.destroy ();
} }
return Source.REMOVE; return Source.REMOVE;
}); });
......
...@@ -266,7 +266,6 @@ namespace SwayNotificationCenter { ...@@ -266,7 +266,6 @@ namespace SwayNotificationCenter {
Idle.add_once (() => { Idle.add_once (() => {
close (); close ();
}); });
return;
} }
}); });
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment