Add app icon above the regular icon (#354)

* Add app icon above the regular icon

* Fixed linting issues

* Tweaked the CSS
This commit is contained in:
Erik Reider
2023-12-15 16:15:48 +01:00
parent b07a296bf8
commit 1fcef5c966
5 changed files with 91 additions and 37 deletions

View File

@@ -109,19 +109,25 @@ $notification-shadow: 0 0 0 1px rgba(0, 0, 0, 0.3),
.notification-content { .notification-content {
background: transparent; background: transparent;
$padding: 6px;
padding: $padding;
border-radius: $border-radius; border-radius: $border-radius;
$margin: 8px;
.image { .image {
/* Notification Primary Image */ /* Notification Primary Image */
-gtk-icon-effect: none; -gtk-icon-effect: none;
border-radius: 100px; /* Size in px */ border-radius: 100px; /* Size in px */
margin: 4px; margin: $margin;
}
.app-icon {
/* Notification app icon (only visible when the primary image is set) */
-gtk-icon-effect: none;
-gtk-icon-shadow: 0 1px 4px black;
margin: 6px;
} }
.text-box { .text-box {
margin: 0 8px; margin: $margin;
.summary { .summary {
/* Notification summary/title */ /* Notification summary/title */
font-size: $font-size-summary; font-size: $font-size-summary;

View File

@@ -92,7 +92,7 @@
}, },
"notification-icon-size": { "notification-icon-size": {
"type": "integer", "type": "integer",
"description": "The notification icon size (in pixels)", "description": "The notification icon size (in pixels). The app icon size is 1/3",
"default": 64, "default": 64,
"minimum": 16 "minimum": 16
}, },
@@ -157,7 +157,7 @@
}, },
"image-visibility": { "image-visibility": {
"type": "string", "type": "string",
"description": "An explanation about the purpose of this instance.", "description": "The notification image visibility when no icon is available.",
"default": "when-available", "default": "when-available",
"enum": ["always", "when-available", "never"] "enum": ["always", "when-available", "never"]
}, },

View File

@@ -14,30 +14,30 @@ namespace SwayNotificationCenter {
theme.add_resource_path ("/org/erikreider/swaync/icons"); theme.add_resource_path ("/org/erikreider/swaync/icons");
} }
public static void set_image_path (owned string path, public static void set_image_uri (owned string uri,
Gtk.Image img, Gtk.Image img,
int icon_size, int icon_size,
int radius, int radius,
bool file_exists) { bool file_exists) {
if ((path.length > 6 && path.slice (0, 7) == "file://") || file_exists) { const string URI_PREFIX = "file://";
const uint PREFIX_SIZE = 7;
bool is_uri = (uri.length >= PREFIX_SIZE
&& uri.slice (0, PREFIX_SIZE) == URI_PREFIX);
if (is_uri || file_exists) {
// Try as a URI (file:// is the only URI schema supported right now) // Try as a URI (file:// is the only URI schema supported right now)
try { try {
if (!file_exists) path = path.slice (7, path.length); if (is_uri) uri = uri.slice (PREFIX_SIZE, uri.length);
var pixbuf = new Gdk.Pixbuf.from_file (path); var pixbuf = new Gdk.Pixbuf.from_file (uri);
var surface = scale_round_pixbuf (pixbuf, var surface = scale_round_pixbuf (pixbuf,
icon_size, icon_size,
icon_size, icon_size,
img.scale_factor, img.scale_factor,
radius); radius);
img.set_from_surface (surface); img.set_from_surface (surface);
return;
} catch (Error e) { } catch (Error e) {
stderr.printf (e.message + "\n"); stderr.printf (e.message + "\n");
} }
} else if (Gtk.IconTheme.get_default ().has_icon (path)) {
// Try as a freedesktop.org-compliant icon theme
img.set_from_icon_name (path, Notification.icon_size);
} }
} }

View File

@@ -59,17 +59,39 @@
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<child>
<object class="GtkOverlay">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<child> <child>
<object class="GtkImage" id="img"> <object class="GtkImage" id="img">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="valign">center</property> <property name="valign">center</property>
<property name="margin-end">12</property>
<property name="icon_size">6</property> <property name="icon_size">6</property>
<style> <style>
<class name="image"/> <class name="image"/>
</style> </style>
</object> </object>
<packing>
<property name="index">-1</property>
</packing>
</child>
<child type="overlay">
<object class="GtkImage" id="img_app_icon">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="valign">end</property>
<property name="icon_size">6</property>
<style>
<class name="app-icon"/>
</style>
</object>
</child>
</object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>

View File

@@ -41,6 +41,8 @@ namespace SwayNotificationCenter {
[GtkChild] [GtkChild]
unowned Gtk.Image img; unowned Gtk.Image img;
[GtkChild] [GtkChild]
unowned Gtk.Image img_app_icon;
[GtkChild]
unowned Gtk.Image body_image; unowned Gtk.Image body_image;
// Inline Reply // Inline Reply
@@ -652,21 +654,36 @@ namespace SwayNotificationCenter {
private void set_icon () { private void set_icon () {
img.clear (); img.clear ();
img.set_visible (true);
img_app_icon.clear ();
img_app_icon.set_visible (true);
Icon ? app_icon_name = null;
string ? app_icon_uri = null;
if (param.desktop_app_info != null) {
app_icon_name = param.desktop_app_info.get_icon ();
}
if (param.app_icon != null && param.app_icon != "") {
app_icon_uri = param.app_icon;
}
var image_visibility = ConfigModel.instance.image_visibility; var image_visibility = ConfigModel.instance.image_visibility;
if (image_visibility == ImageVisibility.NEVER) { if (image_visibility == ImageVisibility.NEVER) {
img.set_visible (false); img.set_visible (false);
img_app_icon.set_visible (false);
return; return;
} }
img.set_pixel_size (notification_icon_size); img.set_pixel_size (notification_icon_size);
img.height_request = notification_icon_size; img.height_request = notification_icon_size;
img.width_request = notification_icon_size; img.width_request = notification_icon_size;
int app_icon_size = notification_icon_size / 3;
img_app_icon.set_pixel_size (app_icon_size);
var img_path_exists = File.new_for_path ( var img_path_exists = File.new_for_uri (
param.image_path ?? "").query_exists (); param.image_path ?? "").query_exists ();
var app_icon_exists = File.new_for_path ( var app_icon_exists = File.new_for_uri (
param.app_icon ?? "").query_exists (); app_icon_uri ?? "").query_exists ();
// Get the image CSS corner radius in pixels // Get the image CSS corner radius in pixels
int radius = 0; int radius = 0;
@@ -677,21 +694,17 @@ namespace SwayNotificationCenter {
radius = value.get_int (); radius = value.get_int ();
} }
// Set the main image to the provided image
if (param.image_data.is_initialized) { if (param.image_data.is_initialized) {
Functions.set_image_data (param.image_data, img, Functions.set_image_data (param.image_data, img,
notification_icon_size, radius); notification_icon_size, radius);
} else if (param.image_path != null && } else if (param.image_path != null &&
param.image_path != "" && param.image_path != "" &&
img_path_exists) { img_path_exists) {
Functions.set_image_path (param.image_path, img, Functions.set_image_uri (param.image_path, img,
notification_icon_size, notification_icon_size,
radius, radius,
img_path_exists); img_path_exists);
} else if (param.app_icon != null && param.app_icon != "") {
Functions.set_image_path (param.app_icon, img,
notification_icon_size,
radius,
app_icon_exists);
} else if (param.icon_data.is_initialized) { } else if (param.icon_data.is_initialized) {
Functions.set_image_data (param.icon_data, img, Functions.set_image_data (param.icon_data, img,
notification_icon_size, radius); notification_icon_size, radius);
@@ -699,16 +712,29 @@ namespace SwayNotificationCenter {
if (img.storage_type == Gtk.ImageType.EMPTY) { if (img.storage_type == Gtk.ImageType.EMPTY) {
// Get the app icon // Get the app icon
Icon ? icon = null; if (app_icon_uri != null) {
if (param.desktop_app_info != null Functions.set_image_uri (app_icon_uri, img,
&& (icon = param.desktop_app_info.get_icon ()) != null) { notification_icon_size,
img.set_from_gicon (icon, icon_size); radius,
app_icon_exists);
} else if (app_icon_name != null) {
img.set_from_gicon (app_icon_name, icon_size);
} else if (image_visibility == ImageVisibility.ALWAYS) { } else if (image_visibility == ImageVisibility.ALWAYS) {
// Default icon // Default icon
img.set_from_icon_name ("image-missing", icon_size); img.set_from_icon_name ("image-missing", icon_size);
} else { } else {
img.set_visible (false); img.set_visible (false);
} }
} else {
// We only set the app icon if the main image is set
if (app_icon_uri != null) {
Functions.set_image_uri (app_icon_uri, img_app_icon,
app_icon_size,
0,
app_icon_exists);
} else if (app_icon_name != null) {
img_app_icon.set_from_gicon (app_icon_name, Gtk.IconSize.INVALID);
}
} }
} }