From 312a69dd69e815f52b8650d52694c1af8b3374c7 Mon Sep 17 00:00:00 2001 From: Nicolas Berbiche Date: Fri, 6 May 2022 05:29:07 -0400 Subject: [PATCH] Ellipsize and wrap notification body (#37) * Ellipsize and wrap notification body * Implement hack around clipped notification in notification window * Removed lines hack * Manually set scrolled window properties Co-authored-by: Erik Reider <35975961+ErikReider@users.noreply.github.com> --- src/notiWindow/notiWindow.ui | 1 - src/notiWindow/notiWindow.vala | 13 +++++++++++++ src/notification/notification.vala | 22 ++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/notiWindow/notiWindow.ui b/src/notiWindow/notiWindow.ui index 513a87f..2eab4c0 100644 --- a/src/notiWindow/notiWindow.ui +++ b/src/notiWindow/notiWindow.ui @@ -20,7 +20,6 @@ False never top-right - 600 True diff --git a/src/notiWindow/notiWindow.vala b/src/notiWindow/notiWindow.vala index f1d7dd5..626589e 100644 --- a/src/notiWindow/notiWindow.vala +++ b/src/notiWindow/notiWindow.vala @@ -37,6 +37,8 @@ namespace SwayNotificationCenter { [GtkTemplate (ui = "/org/erikreider/sway-notification-center/notiWindow/notiWindow.ui")] private class NotificationWindow : Gtk.ApplicationWindow { + [GtkChild] + unowned Gtk.ScrolledWindow scrolled_window; [GtkChild] unowned Gtk.Viewport viewport; [GtkChild] @@ -48,6 +50,8 @@ namespace SwayNotificationCenter { public bool closed = false; + private const int MAX_HEIGHT = 600; + public NotificationWindow () { if (!GtkLayerShell.is_supported ()) { stderr.printf ("GTKLAYERSHELL IS NOT SUPPORTED!\n"); @@ -59,6 +63,12 @@ namespace SwayNotificationCenter { GtkLayerShell.init_for_window (this); GtkLayerShell.set_layer (this, GtkLayerShell.Layer.OVERLAY); this.set_anchor (); + + // -1 should set it to the content size unless it exceeds max_height + scrolled_window.set_min_content_height (-1); + scrolled_window.set_max_content_height (MAX_HEIGHT); + scrolled_window.set_propagate_natural_height (true); + viewport.size_allocate.connect (size_alloc); this.default_width = ConfigModel.instance.notification_window_width; @@ -162,6 +172,9 @@ namespace SwayNotificationCenter { } this.grab_focus (); this.show (); + + // IMPORTANT: queue a resize event to force the layout to be recomputed + noti.queue_resize (); scroll_to_start (list_reverse); } diff --git a/src/notification/notification.vala b/src/notification/notification.vala index 8aec74f..bbb8189 100644 --- a/src/notification/notification.vala +++ b/src/notification/notification.vala @@ -41,6 +41,7 @@ namespace SwayNotificationCenter { private uint timeout_id = 0; + private int number_of_body_lines = 10; public bool is_timed = false; public NotifyParams param; private NotiDaemon noti_daemon; @@ -81,8 +82,21 @@ namespace SwayNotificationCenter { this.timeout_delay = timeout; this.timeout_low_delay = timeout_low; this.timeout_critical_delay = timeout_critical; + this.number_of_body_lines = 5; + build_noti (param, noti_daemon); add_noti_timeout (); + this.size_allocate.connect (on_size_allocation); + } + + private void on_size_allocation (Gtk.Allocation _ignored) { + // Force recomputing the allocated size of the wrapped GTK label in the body. + // `queue_resize` alone DOES NOT WORK because it does not properly invalidate + // the cache, this is a GTK bug! + // See https://gitlab.gnome.org/GNOME/gtk/-/issues/2556 + if (body != null) { + body.set_size_request (-1, body.get_allocated_height ()); + } } private void build_noti (NotifyParams param, NotiDaemon noti_daemon) { @@ -91,7 +105,13 @@ namespace SwayNotificationCenter { this.noti_daemon = noti_daemon; this.param = param; + this.body.set_line_wrap (true); + this.body.set_line_wrap_mode (Pango.WrapMode.WORD_CHAR); + this.body.set_ellipsize (Pango.EllipsizeMode.END); + + this.summary.set_line_wrap (false); this.summary.set_text (param.summary ?? param.app_name); + this.summary.set_ellipsize (Pango.EllipsizeMode.END); this.button_press_event.connect ((event) => { if (event.button != Gdk.BUTTON_SECONDARY) return false; @@ -173,6 +193,8 @@ namespace SwayNotificationCenter { private void set_body () { string text = param.body ?? ""; + this.body.set_lines (this.number_of_body_lines); + // Removes all image tags and adds them to an array if (text.length > 0) { try {