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 Adw 1;
template $SwayNotificationCenterNotification: Box {
template $SwayNotificationCenterNotification: Adw.Bin {
hexpand: true;
styles [
......
......@@ -134,6 +134,8 @@ public class AnimatedList : Gtk.Widget, Gtk.Scrollable {
transition_children = false;
remove.begin (child, false);
}
base.dispose ();
}
public bool get_border (out Gtk.Border border) {
......@@ -538,7 +540,7 @@ public class AnimatedList : Gtk.Widget, Gtk.Scrollable {
* BOTTOM_TO_TOP: Top
*/
public async AnimatedListItem ? prepend (Gtk.Widget widget) {
if (widget == null) {
if (widget == null || widget.parent != null) {
warn_if_reached ();
return null;
}
......@@ -570,7 +572,7 @@ public class AnimatedList : Gtk.Widget, Gtk.Scrollable {
* BOTTOM_TO_TOP: Bottom
*/
public async AnimatedListItem ? append (Gtk.Widget widget) {
if (widget == null) {
if (widget == null || widget.parent != null) {
warn_if_reached ();
return null;
}
......@@ -645,9 +647,9 @@ public class AnimatedList : Gtk.Widget, Gtk.Scrollable {
// Will unparent itself when done animating
bool result = yield item.removed (transition_children && transition);
item.unparent ();
children.remove (item);
n_children--;
item.destroy ();
queue_resize ();
return result;
}
......
......@@ -29,9 +29,8 @@ public class AnimatedListItem : Gtk.Widget {
public bool animation_child_fade { get; construct set; }
public bool destroying { get; private set; default = false; }
private Adw.CallbackAnimationTarget target;
private Adw.TimedAnimation animation;
private double animation_value = 0.0;
private double animation_value = 1.0;
private ulong animation_done_cb_id = 0;
private unowned SourceFunc ? removed_cb = null;
private unowned SourceFunc ? added_cb = null;
......@@ -48,14 +47,22 @@ public class AnimatedListItem : Gtk.Widget {
animation_child_fade: true
);
target = new Adw.CallbackAnimationTarget (animation_value_cb);
animation = new Adw.TimedAnimation (this, 0.0, 1.0,
animation_duration, target);
Adw.CallbackAnimationTarget target = new Adw.CallbackAnimationTarget (set_animation_value);
animation = new Adw.TimedAnimation (this, 0.0, 1.0, animation_duration, target);
bind_property ("animation-easing",
animation, "easing",
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 () {
return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH;
}
......@@ -164,26 +171,12 @@ public class AnimatedListItem : Gtk.Widget {
}
}
private void animation_value_cb (double value) {
this.animation_value = value;
private void set_animation_value (double value) {
animation_value = value;
queue_resize ();
}
private void animation_done_add () {
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 () {
private inline void remove_animation_done_cb () {
if (animation_done_cb_id != 0) {
animation.disconnect (animation_done_cb_id);
animation_done_cb_id = 0;
......@@ -191,9 +184,16 @@ public class AnimatedListItem : Gtk.Widget {
}
delegate void animation_done (Adw.Animation animation);
private void animation_add_done_cb (animation_done handler) {
animation_remove_done_cb ();
animation_done_cb_id = animation.done.connect ((a) => handler (a));
private void set_animation_done_cb (animation_done handler) {
remove_animation_done_cb ();
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) {
......@@ -202,10 +202,10 @@ public class AnimatedListItem : Gtk.Widget {
return;
}
animation_remove_done_cb ();
remove_animation_done_cb ();
if (get_mapped () && transition) {
animation_add_done_cb (animation_done_add);
set_animation_done_cb (added_finished_cb);
added_cb = added.callback;
animation.value_from
= animation.state == Adw.AnimationState.PLAYING
......@@ -215,8 +215,15 @@ public class AnimatedListItem : Gtk.Widget {
animation.play ();
yield;
} else {
animation_value = 1.0;
animation_done_add ();
set_animation_value (1.0);
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 {
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_target (false);
if (get_mapped () && transition) {
animation_add_done_cb (animation_done_remove);
set_animation_done_cb (removed_finised_cb);
removed_cb = removed.callback;
animation.value_from
= animation.state == Adw.AnimationState.PLAYING
......@@ -242,9 +251,16 @@ public class AnimatedListItem : Gtk.Widget {
animation.play ();
yield;
} else {
animation_value = 0.0;
animation_done_remove ();
set_animation_value (0.0);
removed_finised_cb ();
}
if (child != null) {
child.unparent ();
child = null;
}
// Fixes the animation keeping a reference of the widget
animation = null;
return true;
}
......
......@@ -25,15 +25,22 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable {
// Animation
Adw.SpringAnimation animation;
Adw.AnimationTarget target;
// Swipe Gesture
Adw.SwipeTracker swipe_tracker;
bool transition_running = false;
bool gesture_active = false;
double child_offset = 0;
double swipe_progress = 0.0;
private 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;
......@@ -52,7 +59,7 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable {
swipe_tracker.end_swipe.connect (swipe_end_swipe_cb);
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],
new Adw.SpringParams (1, 0.5, 500),
target);
......@@ -60,6 +67,14 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable {
animation.done.connect (animation_done_cb);
}
public override void dispose () {
if (child != null) {
child.unparent ();
child = null;
}
base.dispose ();
}
public signal void dismissed ();
public void set_can_dismiss (bool state) {
......@@ -121,10 +136,6 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable {
* Callbacks
*/
private void animate_value_cb (double value) {
set_position (value);
}
private void animation_done_cb () {
transition_running = false;
if (swipe_progress != 0) {
......@@ -142,7 +153,7 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable {
}
private void swipe_update_swipe_cb (double distance) {
set_position (distance);
swipe_progress = distance;
}
private void swipe_end_swipe_cb (double velocity, double to) {
......@@ -166,15 +177,10 @@ public class DismissibleWidget : Gtk.Widget, Adw.Swipeable {
* Methods
*/
private void set_position (double value) {
this.swipe_progress = value;
queue_allocate ();
}
public void set_gesture_direction (SwipeDirection swipe_direction) {
this.swipe_direction = swipe_direction;
// Reset the position
set_position (0.0);
swipe_progress = 0.0;
}
/*
......
......@@ -40,7 +40,14 @@ namespace SwayNotificationCenter {
try {
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);
} catch (Error e) {
stderr.printf (e.message + "\n");
......@@ -59,14 +66,22 @@ namespace SwayNotificationCenter {
public static void set_image_data (ImageData data,
Gtk.Image img) {
Gdk.MemoryFormat format = Gdk.MemoryFormat.R8G8B8;
if (data.has_alpha) {
format = Gdk.MemoryFormat.R8G8B8A8;
}
var texture = new Gdk.MemoryTexture (data.width, data.height,
format,
new Bytes.static (data.data),
data.rowstride);
Gtk.Requisition natural_size;
img.get_preferred_size (null, out natural_size);
Gdk.Pixbuf pixbuf = new Gdk.Pixbuf.with_unowned_data (data.data,
Gdk.Colorspace.RGB,
data.has_alpha,
data.bits_per_sample,
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);
}
......
......@@ -8,6 +8,14 @@ public class IterBox : Gtk.Box {
set_name ("iterbox");
}
public override void dispose () {
foreach (Gtk.Widget child in children) {
remove (child);
}
base.dispose ();
}
private void on_add (Gtk.Widget child) {
length++;
child.destroy.connect (() => {
......
......@@ -24,10 +24,14 @@ namespace SwayNotificationCenter {
};
button.add_css_class ("close-button");
button.add_css_class ("circular");
button.clicked.connect (() => this.clicked ());
button.clicked.connect (click_cb);
revealer.set_child (button);
}
private void click_cb () {
clicked ();
}
public signal void clicked ();
public void set_reveal (bool state) {
......@@ -50,7 +54,7 @@ namespace SwayNotificationCenter {
public enum NotificationType { CONTROL_CENTER, POPUP }
[GtkTemplate (ui = "/org/erikreider/swaync/ui/notification.ui")]
public class Notification : Gtk.Box {
public class Notification : Adw.Bin {
[GtkChild]
unowned Gtk.Revealer revealer;
[GtkChild]
......@@ -276,8 +280,7 @@ namespace SwayNotificationCenter {
noti_daemon.manually_close_notification (
param.applied_id, false);
} catch (Error e) {
printerr ("Error: %s\n", e.message);
this.destroy ();
critical ("Error: %s", e.message);
}
});
......@@ -671,8 +674,7 @@ namespace SwayNotificationCenter {
noti_daemon.manually_close_notification (param.applied_id,
is_timeout);
} catch (Error e) {
print ("Error: %s\n", e.message);
this.destroy ();
critical ("Error: %s", e.message);
}
return Source.REMOVE;
});
......
......@@ -266,7 +266,6 @@ namespace SwayNotificationCenter {
Idle.add_once (() => {
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