Polish authentication dialog colors and agent registration

This commit is contained in:
Samuel Onoja committed 2026-09-28 09:42:34 +01:00
1 parent c8e89fb758
commit f9d5d9a8a8
4 files changed
+48 -37

No files matched your search

Generated
+1
View File
@@ -1726,6 +1726,7 @@ name = "ferese-polkit-agent"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ferese-config", "ferese-config",
"ferese-theme",
"glib", "glib",
"libc", "libc",
"libcosmic", "libcosmic",
+1
View File
@@ -7,6 +7,7 @@ rust-version = "1.95"
[dependencies] [dependencies]
ferese-config = { path = "../../crates/ferese-config" } ferese-config = { path = "../../crates/ferese-config" }
ferese-theme = { path = "../../crates/ferese-theme" }
glib = "0.21.5" glib = "0.21.5"
libc.workspace = true libc.workspace = true
libcosmic = { workspace = true, features = ["wgpu"] } libcosmic = { workspace = true, features = ["wgpu"] }
+21 -11
View File
@@ -14,6 +14,7 @@ use zbus::zvariant::{OwnedValue, Value};
const AGENT_PATH: &str = "/dev/ferese/PolkitAgent"; const AGENT_PATH: &str = "/dev/ferese/PolkitAgent";
const AUTHORITY: &str = "org.freedesktop.PolicyKit1"; const AUTHORITY: &str = "org.freedesktop.PolicyKit1";
const AUTHORITY_PATH: &str = "/org/freedesktop/PolicyKit1/Authority"; const AUTHORITY_PATH: &str = "/org/freedesktop/PolicyKit1/Authority";
const AUTHORITY_INTERFACE: &str = "org.freedesktop.PolicyKit1.Authority";
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")] #[serde(tag = "type", rename_all = "snake_case")]
@@ -102,17 +103,25 @@ fn choose_identity(identities: &[Identity]) -> Option<u32> {
} }
fn session_subject() -> Result<(String, HashMap<String, Value<'static>>), String> { fn session_subject() -> Result<(String, HashMap<String, Value<'static>>), String> {
let id = std::env::var("XDG_SESSION_ID") let stat = std::fs::read_to_string("/proc/self/stat").map_err(|error| error.to_string())?;
.map_err(|_| "XDG_SESSION_ID is required for polkit registration".to_owned())?; let suffix = stat
.rsplit_once(") ")
if id.is_empty() { .map(|(_, suffix)| suffix)
return Err("XDG_SESSION_ID is empty".into()); .ok_or("Invalid /proc/self/stat")?;
} let started = suffix
.split_whitespace()
.nth(19)
.ok_or("Missing process start time")?
.parse::<u64>()
.map_err(|error| error.to_string())?;
let mut details = HashMap::new(); let mut details = HashMap::new();
details.insert("session-id".to_owned(), Value::from(id)); details.insert("pid".to_owned(), Value::from(std::process::id()));
details.insert(
Ok(("unix-session".into(), details)) "uid".to_owned(),
Value::from(unsafe { libc::geteuid() } as i32),
);
details.insert("start-time".to_owned(), Value::from(started));
Ok(("unix-process".into(), details))
} }
async fn run_agent() -> Result<(), Box<dyn std::error::Error>> { async fn run_agent() -> Result<(), Box<dyn std::error::Error>> {
@@ -121,7 +130,8 @@ async fn run_agent() -> Result<(), Box<dyn std::error::Error>> {
.serve_at(AGENT_PATH, Agent::default())? .serve_at(AGENT_PATH, Agent::default())?
.build() .build()
.await?; .await?;
let authority = zbus::Proxy::new(&connection, AUTHORITY, AUTHORITY_PATH, AUTHORITY).await?; let authority =
zbus::Proxy::new(&connection, AUTHORITY, AUTHORITY_PATH, AUTHORITY_INTERFACE).await?;
let locale = std::env::var("LANG").unwrap_or_default(); let locale = std::env::var("LANG").unwrap_or_default();
authority authority
+25 -26
View File
@@ -17,7 +17,6 @@ use zeroize::{Zeroize, Zeroizing};
#[derive(Clone)] #[derive(Clone)]
struct Appearance { struct Appearance {
surface: Color, surface: Color,
translucent: bool,
text: Color, text: Color,
muted: Color, muted: Color,
accent: Color, accent: Color,
@@ -48,12 +47,12 @@ impl Appearance {
.and_then(|value| value.as_f64()) .and_then(|value| value.as_f64())
.unwrap_or(ferese_config::DEFAULT_MATERIAL_OPACITY) .unwrap_or(ferese_config::DEFAULT_MATERIAL_OPACITY)
.clamp(0., 1.) as f32; .clamp(0., 1.) as f32;
let mut surface = color("theme.colors.surface_base", "#111821"); let mut surface = color("theme.colors.surface_base", "#111821");
surface.a = if translucent { shell_opacity } else { 1. }; surface.a = if translucent { shell_opacity } else { 1. };
Self { Self {
surface, surface,
translucent,
text: color("theme.colors.text_primary", "#F4F7FB"), text: color("theme.colors.text_primary", "#F4F7FB"),
muted: color("theme.colors.text_muted", "#8793A2"), muted: color("theme.colors.text_muted", "#8793A2"),
accent: color("theme.colors.accent", "#3D7BE6"), accent: color("theme.colors.accent", "#3D7BE6"),
@@ -74,6 +73,10 @@ impl Appearance {
use cosmic::cosmic_theme::{ThemeBuilder, palette::Srgba}; use cosmic::cosmic_theme::{ThemeBuilder, palette::Srgba};
let rgba = |color: Color| Srgba::new(color.r, color.g, color.b, color.a); let rgba = |color: Color| Srgba::new(color.r, color.g, color.b, color.a);
let opaque_surface = Color {
a: 1.,
..self.surface
};
let builder = if self.surface.r + self.surface.g + self.surface.b > 1.5 { let builder = if self.surface.r + self.surface.g + self.surface.b > 1.5 {
ThemeBuilder::light() ThemeBuilder::light()
} else { } else {
@@ -87,18 +90,15 @@ impl Appearance {
corners.radius_l = [self.radius; 4]; corners.radius_l = [self.radius; 4];
corners.radius_xl = [self.radius; 4]; corners.radius_xl = [self.radius; 4];
cosmic::Theme::custom(Arc::new( let mut native = builder
builder .corner_radii(corners)
.corner_radii(corners) .bg_color(rgba(opaque_surface))
.bg_color(rgba(Color { .primary_container_bg(rgba(opaque_surface))
a: if self.translucent { 0. } else { 1. }, .text_tint(rgba(self.text).color)
..self.surface .accent(ferese_theme::accent_color(self.accent, opaque_surface))
})) .build();
.primary_container_bg(rgba(self.surface)) ferese_theme::apply(&mut native, self.text);
.text_tint(rgba(self.text).color) cosmic::Theme::custom(Arc::new(native))
.accent(rgba(self.accent).color)
.build(),
))
} }
} }
@@ -272,11 +272,21 @@ impl cosmic::Application for Prompt {
&mut self.core &mut self.core
} }
fn style(&self) -> Option<cosmic::iced::theme::Style> {
Some(cosmic::iced::theme::Style {
background_color: self.appearance.surface,
text_color: self.appearance.text,
icon_color: self.appearance.text,
})
}
fn init( fn init(
mut core: Core, mut core: Core,
(incoming, description, user, appearance): Self::Flags, (incoming, description, user, appearance): Self::Flags,
) -> (Self, Task<Message>) { ) -> (Self, Task<Message>) {
core.window.show_headerbar = false; core.window.show_headerbar = false;
core.window.border_padding = Some(0);
core.window.content_container = false;
let height = content_height(&description, None); let height = content_height(&description, None);
let bounds = core let bounds = core
.main_window_id() .main_window_id()
@@ -375,7 +385,7 @@ impl cosmic::Application for Prompt {
}); });
} }
let action = button::custom(text("Authenticate").font(palette.font).size(13)) let action = button::custom(text("Authenticate").font(palette.font).size(13))
.class(theme::Button::Suggested) .class(ferese_theme::accent_button())
.height(Length::Fixed(36.)) .height(Length::Fixed(36.))
.padding([8, 16]) .padding([8, 16])
.on_press_maybe((!self.waiting && !self.answer.is_empty()).then_some(Message::Submit)); .on_press_maybe((!self.waiting && !self.answer.is_empty()).then_some(Message::Submit));
@@ -460,17 +470,6 @@ impl cosmic::Application for Prompt {
.padding(20) .padding(20)
.width(Length::Fill) .width(Length::Fill)
.height(Length::Fill) .height(Length::Fill)
.class(theme::Container::custom(move |_| {
widget::container::Style {
background: Some(Background::Color(palette.surface)),
text_color: Some(palette.text),
border: Border {
radius: palette.radius.into(),
..Default::default()
},
..Default::default()
}
}))
.into() .into()
} }
} }