diff --git a/Cargo.lock b/Cargo.lock
index b320e7c6..0d81eb03 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -363,6 +363,21 @@ dependencies = [
"zbus",
]
+[[package]]
+name = "cosmic-applet-notifications"
+version = "0.1.0"
+dependencies = [
+ "cascade",
+ "cosmic-panel-config",
+ "futures",
+ "gtk4",
+ "once_cell",
+ "serde",
+ "zbus",
+ "zbus_names",
+ "zvariant",
+]
+
[[package]]
name = "cosmic-applet-power"
version = "0.1.0"
diff --git a/Cargo.toml b/Cargo.toml
index bee4d6a5..4591550b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,6 +3,7 @@ members = [
"applets/cosmic-applet-audio",
"applets/cosmic-applet-graphics",
"applets/cosmic-applet-network",
+ "applets/cosmic-applet-notifications",
"applets/cosmic-applet-power",
"applets/cosmic-applet-workspaces",
"applets/cosmic-applet-status-area",
diff --git a/applets/cosmic-applet-notifications/Cargo.toml b/applets/cosmic-applet-notifications/Cargo.toml
new file mode 100644
index 00000000..5ac15b82
--- /dev/null
+++ b/applets/cosmic-applet-notifications/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "cosmic-applet-notifications"
+version = "0.1.0"
+edition = "2021"
+license = "GPL-3.0-or-later"
+
+[dependencies]
+cascade = "1"
+futures = "0.3"
+gtk4 = "0.4.6"
+once_cell = "1.12"
+serde = "1"
+zbus = "2.0.1"
+zbus_names = "2"
+zvariant = "3"
+cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"]}
diff --git a/applets/cosmic-applet-notifications/data/com.system76.CosmicAppletNotifications.desktop b/applets/cosmic-applet-notifications/data/com.system76.CosmicAppletNotifications.desktop
new file mode 100644
index 00000000..c0b0c48e
--- /dev/null
+++ b/applets/cosmic-applet-notifications/data/com.system76.CosmicAppletNotifications.desktop
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Name=Cosmic Applet Notifications
+Type=Application
+Exec=cosmic-applet-notifications
+Terminal=false
+Categories=GNOME;GTK;
+Keywords=Gnome;GTK;
+# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
+Icon=com.system76.CosmicAppletNotifications
+NoDisplay=true
diff --git a/applets/cosmic-applet-notifications/data/icons/com.system76.CosmicAppletNotifications.svg b/applets/cosmic-applet-notifications/data/icons/com.system76.CosmicAppletNotifications.svg
new file mode 100644
index 00000000..c2bd5b1b
--- /dev/null
+++ b/applets/cosmic-applet-notifications/data/icons/com.system76.CosmicAppletNotifications.svg
@@ -0,0 +1,60 @@
+
+
diff --git a/old-panel/src/dbus_service.rs b/applets/cosmic-applet-notifications/src/dbus_service.rs
similarity index 100%
rename from old-panel/src/dbus_service.rs
rename to applets/cosmic-applet-notifications/src/dbus_service.rs
diff --git a/applets/cosmic-applet-notifications/src/deref_cell.rs b/applets/cosmic-applet-notifications/src/deref_cell.rs
new file mode 100644
index 00000000..dfdd4936
--- /dev/null
+++ b/applets/cosmic-applet-notifications/src/deref_cell.rs
@@ -0,0 +1,31 @@
+use once_cell::unsync::OnceCell;
+
+/// Wrapper around `OnceCell` implementing `Deref`, and thus also panicking
+/// when not set (or set twice).
+///
+/// To be used in place of `gtk::TemplateChild`, but without xml.
+pub struct DerefCell(OnceCell);
+
+impl DerefCell {
+ #[track_caller]
+ pub fn set(&self, value: T) {
+ if self.0.set(value).is_err() {
+ panic!("Initialized twice");
+ }
+ }
+}
+
+impl Default for DerefCell {
+ fn default() -> Self {
+ Self(OnceCell::default())
+ }
+}
+
+impl std::ops::Deref for DerefCell {
+ type Target = T;
+
+ #[track_caller]
+ fn deref(&self) -> &T {
+ self.0.get().unwrap()
+ }
+}
diff --git a/applets/cosmic-applet-notifications/src/main.rs b/applets/cosmic-applet-notifications/src/main.rs
new file mode 100644
index 00000000..a4dd7e67
--- /dev/null
+++ b/applets/cosmic-applet-notifications/src/main.rs
@@ -0,0 +1,58 @@
+use cascade::cascade;
+use gtk4::{glib, prelude::*};
+
+mod dbus_service;
+mod deref_cell;
+mod notification_popover;
+use notification_popover::NotificationPopover;
+mod notification_list;
+mod notification_widget;
+use notification_list::NotificationList;
+mod notifications;
+use notifications::Notifications;
+
+fn main() {
+ gtk4::init().unwrap();
+
+ // XXX Implement DBus service somewhere other than applet?
+ let notifications = Notifications::new();
+
+ let provider = gtk4::CssProvider::new();
+ provider.load_from_data(include_bytes!("style.css"));
+ gtk4::StyleContext::add_provider_for_display(
+ >k4::gdk::Display::default().expect("Could not connect to a display."),
+ &provider,
+ gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
+ );
+
+ let notification_list = NotificationList::new(¬ifications);
+
+ let popover = cascade! {
+ gtk4::Popover::new();
+ ..set_child(Some(¬ification_list));
+ };
+
+ let menu_button = cascade! {
+ gtk4::MenuButton::new();
+ ..set_popover(Some(&popover));
+ };
+
+ // XXX show in correct place
+ cascade! {
+ NotificationPopover::new(¬ifications);
+ ..set_parent(&menu_button);
+ };
+
+ gtk4::Window::builder()
+ .decorated(false)
+ .child(&menu_button)
+ .resizable(false)
+ .width_request(1)
+ .height_request(1)
+ .css_classes(vec!["root_window".to_string()])
+ .build()
+ .show();
+
+ let main_loop = glib::MainLoop::new(None, false);
+ main_loop.run();
+}
diff --git a/old-panel/src/notification_list.rs b/applets/cosmic-applet-notifications/src/notification_list.rs
similarity index 100%
rename from old-panel/src/notification_list.rs
rename to applets/cosmic-applet-notifications/src/notification_list.rs
diff --git a/old-panel/src/notification_popover.rs b/applets/cosmic-applet-notifications/src/notification_popover.rs
similarity index 100%
rename from old-panel/src/notification_popover.rs
rename to applets/cosmic-applet-notifications/src/notification_popover.rs
diff --git a/old-panel/src/notification_widget.rs b/applets/cosmic-applet-notifications/src/notification_widget.rs
similarity index 100%
rename from old-panel/src/notification_widget.rs
rename to applets/cosmic-applet-notifications/src/notification_widget.rs
diff --git a/old-panel/src/notifications.rs b/applets/cosmic-applet-notifications/src/notifications.rs
similarity index 99%
rename from old-panel/src/notifications.rs
rename to applets/cosmic-applet-notifications/src/notifications.rs
index 33a921d9..ee766db0 100644
--- a/old-panel/src/notifications.rs
+++ b/applets/cosmic-applet-notifications/src/notifications.rs
@@ -1,7 +1,7 @@
#![allow(non_snake_case)]
+use futures::channel::mpsc;
use futures::stream::StreamExt;
-use futures_channel::mpsc;
use gtk4::{
glib::{self, clone, subclass::Signal, SignalHandlerId},
prelude::*,
diff --git a/applets/cosmic-applet-notifications/src/style.css b/applets/cosmic-applet-notifications/src/style.css
new file mode 100644
index 00000000..8a91f3eb
--- /dev/null
+++ b/applets/cosmic-applet-notifications/src/style.css
@@ -0,0 +1,33 @@
+.loading-overlay {
+ background-color: #2f2f2f;
+ opacity: 0.85;
+}
+
+image.panel_icon {
+ padding-left: 0px;
+ padding-right: 0px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+}
+
+button.panel_icon {
+ border-radius: 12px;
+ transition: 100ms;
+ padding: 4px;
+ border-color: transparent;
+ background: transparent;
+ outline-color: transparent;
+}
+
+button.panel_icon:hover {
+ border-radius: 12px;
+ transition: 100ms;
+ padding: 4px;
+ border-color: rgba(255, 255, 255, 0.1);
+ outline-color: rgba(255, 255, 255, 0.1);
+ background: rgba(255, 255, 255, 0.1);
+}
+
+window.root_window {
+ background: transparent;
+}
\ No newline at end of file
diff --git a/justfile b/justfile
index 24069719..469502d1 100644
--- a/justfile
+++ b/justfile
@@ -17,6 +17,7 @@ app_list_id := 'com.system76.CosmicAppList'
audio_id := 'com.system76.CosmicAppletAudio'
graphics_id := 'com.system76.CosmicAppletGraphics'
network_id := 'com.system76.CosmicAppletNetwork'
+notifications_id := 'com.system76.CosmicAppletNotifications'
power_id := 'com.system76.CosmicAppletPower'
workspaces_id := 'com.system76.CosmicAppletWorkspaces'
status_area_id := 'com.system76.CosmicAppletStatusArea'
@@ -50,6 +51,11 @@ install:
install -Dm0644 applets/cosmic-applet-network/data/{{network_id}}.desktop {{sharedir}}/applications/{{network_id}}.desktop
install -Dm0755 target/release/cosmic-applet-network {{bindir}}/cosmic-applet-network
+ # notifications
+ install -Dm0644 applets/cosmic-applet-notifications/data/icons/{{notifications_id}}.svg {{iconsdir}}/{{notifications_id}}.svg
+ install -Dm0644 applets/cosmic-applet-notifications/data/{{notifications_id}}.desktop {{sharedir}}/applications/{{notifications_id}}.desktop
+ install -Dm04755 target/release/cosmic-applet-notifications {{bindir}}/cosmic-applet-notifications
+
# power
install -Dm0644 applets/cosmic-applet-power/data/icons/{{power_id}}.svg {{iconsdir}}/{{power_id}}.svg
install -Dm0644 applets/cosmic-applet-power/data/{{power_id}}.desktop {{sharedir}}/applications/{{power_id}}.desktop
diff --git a/old-panel/src/application.rs b/old-panel/src/application.rs
index 3bb83332..f1b10199 100644
--- a/old-panel/src/application.rs
+++ b/old-panel/src/application.rs
@@ -6,13 +6,10 @@ use gtk4::{
};
use std::cell::Cell;
-use crate::deref_cell::DerefCell;
-use crate::notifications::Notifications;
use crate::window;
#[derive(Default)]
pub struct PanelAppInner {
- notifications: DerefCell,
activated: Cell,
}
@@ -28,8 +25,6 @@ impl ObjectImpl for PanelAppInner {
obj.set_application_id(Some("com.system76.cosmicpanel"));
self.parent_constructed(obj);
-
- self.notifications.set(Notifications::new());
}
}
@@ -83,8 +78,4 @@ impl PanelApp {
fn add_window_for_monitor(&self, monitor: gdk::Monitor) {
window::create(self, monitor);
}
-
- pub fn notifications(&self) -> &Notifications {
- &*self.inner().notifications
- }
}
diff --git a/old-panel/src/main.rs b/old-panel/src/main.rs
index df717497..5e9b34a4 100644
--- a/old-panel/src/main.rs
+++ b/old-panel/src/main.rs
@@ -1,14 +1,9 @@
use gtk4::{glib, prelude::*};
mod application;
-mod dbus_service;
mod deref_cell;
mod mpris;
mod mpris_player;
-mod notification_list;
-mod notification_popover;
-mod notification_widget;
-mod notifications;
mod popover_container;
mod time_button;
mod window;
diff --git a/old-panel/src/time_button.rs b/old-panel/src/time_button.rs
index 4a9b45ce..85f64fbb 100644
--- a/old-panel/src/time_button.rs
+++ b/old-panel/src/time_button.rs
@@ -9,8 +9,6 @@ use gtk4::{
use crate::application::PanelApp;
use crate::deref_cell::DerefCell;
use crate::mpris::MprisControls;
-use crate::notification_list::NotificationList;
-use crate::notification_popover::NotificationPopover;
use crate::popover_container::PopoverContainer;
#[derive(Default)]
@@ -18,7 +16,6 @@ pub struct TimeButtonInner {
calendar: DerefCell,
button: DerefCell,
label: DerefCell,
- notification_popover: DerefCell,
left_box: DerefCell,
}
@@ -88,7 +85,6 @@ impl ObjectImpl for TimeButtonInner {
fn dispose(&self, _obj: &TimeButton) {
self.button.unparent();
- self.notification_popover.unparent();
}
}
@@ -103,15 +99,6 @@ impl TimeButton {
pub fn new(app: &PanelApp) -> Self {
let obj = glib::Object::new::(&[]).unwrap();
- let notification_list = NotificationList::new(app.notifications());
- obj.inner().left_box.prepend(¬ification_list);
-
- let notification_popover = cascade! {
- NotificationPopover::new(app.notifications());
- ..set_parent(&obj);
- };
- obj.inner().notification_popover.set(notification_popover);
-
obj
}