Initial port of notifications to an applet
This commit is contained in:
parent
25a8e8353e
commit
04ce88e4ce
17 changed files with 231 additions and 28 deletions
15
Cargo.lock
generated
15
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
16
applets/cosmic-applet-notifications/Cargo.toml
Normal file
16
applets/cosmic-applet-notifications/Cargo.toml
Normal file
|
|
@ -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"]}
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128px" height="128px" viewBox="0 0 128 128" version="1.1">
|
||||
<defs>
|
||||
<filter id="alpha" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
|
||||
<feColorMatrix type="matrix" in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
|
||||
</filter>
|
||||
<mask id="mask0">
|
||||
<g filter="url(#alpha)">
|
||||
<rect x="0" y="0" width="128" height="128" style="fill:rgb(0%,0%,0%);fill-opacity:0.1;stroke:none;"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="clip1">
|
||||
<rect x="0" y="0" width="192" height="152"/>
|
||||
</clipPath>
|
||||
<g id="surface10632" clip-path="url(#clip1)">
|
||||
<path style="fill:none;stroke-width:0.99;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.99,0.99;stroke-miterlimit:4;" d="M 123.503906 236 C 123.503906 268.863281 96.863281 295.503906 64 295.503906 C 31.136719 295.503906 4.496094 268.863281 4.496094 236 C 4.496094 203.136719 31.136719 176.496094 64 176.496094 C 96.863281 176.496094 123.503906 203.136719 123.503906 236 Z M 123.503906 236 " transform="matrix(1,0,0,1,8,-156)"/>
|
||||
</g>
|
||||
<mask id="mask1">
|
||||
<g filter="url(#alpha)">
|
||||
<rect x="0" y="0" width="128" height="128" style="fill:rgb(0%,0%,0%);fill-opacity:0.1;stroke:none;"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="clip2">
|
||||
<rect x="0" y="0" width="192" height="152"/>
|
||||
</clipPath>
|
||||
<g id="surface10635" clip-path="url(#clip2)">
|
||||
<path style="fill:none;stroke-width:0.99;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.99,0.99;stroke-miterlimit:4;" d="M 29.195312 180.496094 L 98.804688 180.496094 C 103.609375 180.496094 107.503906 184.046875 107.503906 188.425781 L 107.503906 283.574219 C 107.503906 287.953125 103.609375 291.503906 98.804688 291.503906 L 29.195312 291.503906 C 24.390625 291.503906 20.496094 287.953125 20.496094 283.574219 L 20.496094 188.425781 C 20.496094 184.046875 24.390625 180.496094 29.195312 180.496094 Z M 29.195312 180.496094 " transform="matrix(1,0,0,1,8,-156)"/>
|
||||
</g>
|
||||
<mask id="mask2">
|
||||
<g filter="url(#alpha)">
|
||||
<rect x="0" y="0" width="128" height="128" style="fill:rgb(0%,0%,0%);fill-opacity:0.1;stroke:none;"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="clip3">
|
||||
<rect x="0" y="0" width="192" height="152"/>
|
||||
</clipPath>
|
||||
<g id="surface10638" clip-path="url(#clip3)">
|
||||
<path style="fill:none;stroke-width:0.99;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.99,0.99;stroke-miterlimit:4;" d="M 20.417969 184.496094 L 107.582031 184.496094 C 111.957031 184.496094 115.503906 188.042969 115.503906 192.417969 L 115.503906 279.582031 C 115.503906 283.957031 111.957031 287.503906 107.582031 287.503906 L 20.417969 287.503906 C 16.042969 287.503906 12.496094 283.957031 12.496094 279.582031 L 12.496094 192.417969 C 12.496094 188.042969 16.042969 184.496094 20.417969 184.496094 Z M 20.417969 184.496094 " transform="matrix(1,0,0,1,8,-156)"/>
|
||||
</g>
|
||||
<mask id="mask3">
|
||||
<g filter="url(#alpha)">
|
||||
<rect x="0" y="0" width="128" height="128" style="fill:rgb(0%,0%,0%);fill-opacity:0.1;stroke:none;"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="clip4">
|
||||
<rect x="0" y="0" width="192" height="152"/>
|
||||
</clipPath>
|
||||
<g id="surface10641" clip-path="url(#clip4)">
|
||||
<path style="fill:none;stroke-width:0.99;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.99,0.99;stroke-miterlimit:4;" d="M 16.425781 200.496094 L 111.574219 200.496094 C 115.953125 200.496094 119.503906 204.390625 119.503906 209.195312 L 119.503906 278.804688 C 119.503906 283.609375 115.953125 287.503906 111.574219 287.503906 L 16.425781 287.503906 C 12.046875 287.503906 8.496094 283.609375 8.496094 278.804688 L 8.496094 209.195312 C 8.496094 204.390625 12.046875 200.496094 16.425781 200.496094 Z M 16.425781 200.496094 " transform="matrix(1,0,0,1,8,-156)"/>
|
||||
</g>
|
||||
</defs>
|
||||
<g id="surface10578">
|
||||
<rect x="0" y="0" width="128" height="128" style="fill:rgb(94.117647%,94.117647%,94.117647%);fill-opacity:1;stroke:none;"/>
|
||||
<use xlink:href="#surface10632" transform="matrix(1,0,0,1,-8,-16)" mask="url(#mask0)"/>
|
||||
<use xlink:href="#surface10635" transform="matrix(1,0,0,1,-8,-16)" mask="url(#mask1)"/>
|
||||
<use xlink:href="#surface10638" transform="matrix(1,0,0,1,-8,-16)" mask="url(#mask2)"/>
|
||||
<use xlink:href="#surface10641" transform="matrix(1,0,0,1,-8,-16)" mask="url(#mask3)"/>
|
||||
<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(38.431373%,62.7451%,91.764706%);stroke-opacity:1;stroke-miterlimit:4;" d="M 0 289 L 128 289 " transform="matrix(1,0,0,1,0,-172)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
31
applets/cosmic-applet-notifications/src/deref_cell.rs
Normal file
31
applets/cosmic-applet-notifications/src/deref_cell.rs
Normal file
|
|
@ -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<T>(OnceCell<T>);
|
||||
|
||||
impl<T> DerefCell<T> {
|
||||
#[track_caller]
|
||||
pub fn set(&self, value: T) {
|
||||
if self.0.set(value).is_err() {
|
||||
panic!("Initialized twice");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for DerefCell<T> {
|
||||
fn default() -> Self {
|
||||
Self(OnceCell::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::Deref for DerefCell<T> {
|
||||
type Target = T;
|
||||
|
||||
#[track_caller]
|
||||
fn deref(&self) -> &T {
|
||||
self.0.get().unwrap()
|
||||
}
|
||||
}
|
||||
58
applets/cosmic-applet-notifications/src/main.rs
Normal file
58
applets/cosmic-applet-notifications/src/main.rs
Normal file
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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::*,
|
||||
33
applets/cosmic-applet-notifications/src/style.css
Normal file
33
applets/cosmic-applet-notifications/src/style.css
Normal file
|
|
@ -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;
|
||||
}
|
||||
6
justfile
6
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
|
||||
|
|
|
|||
|
|
@ -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<Notifications>,
|
||||
activated: Cell<bool>,
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<gtk4::Calendar>,
|
||||
button: DerefCell<gtk4::ToggleButton>,
|
||||
label: DerefCell<gtk4::Label>,
|
||||
notification_popover: DerefCell<NotificationPopover>,
|
||||
left_box: DerefCell<gtk4::Box>,
|
||||
}
|
||||
|
||||
|
|
@ -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::<Self>(&[]).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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue