poweroff popup

This commit is contained in:
Jiří Maxmilián Stříbrný 2026-03-17 22:59:43 +01:00
parent e857dd93cc
commit 58166358ba

View file

@ -1,18 +1,21 @@
use iced::Color;
use iced::Element;
use iced::Task;
use iced::widget::button;
use iced::widget::container;
use iced::widget::row;
use iced::widget::text;
use iced_layershell::daemon;
use iced_layershell::reexport::Anchor;
use iced_layershell::reexport::NewLayerShellSettings;
use iced_layershell::settings::LayerShellSettings;
use iced_layershell::settings::Settings;
use iced_layershell::to_layer_message;
use std::collections::HashMap;
use std::time::Duration;
pub fn main() -> Result<(), iced_layershell::Error> {
daemon(App::default, || "rbaw".into(), App::update, App::view)
daemon(App::default, App::name, App::update, App::view)
.style(App::style)
.theme(App::theme)
.subscription(App::subscription)
@ -30,13 +33,21 @@ pub fn main() -> Result<(), iced_layershell::Error> {
}
struct App {
popups: HashMap<iced::window::Id, PopupKind>,
power_off_widget: PowerOffWidget,
time_widget: TimeWidget,
battery_widget: BatteryWidget,
}
enum PopupKind {
PowerOff,
}
impl Default for App {
fn default() -> Self {
let mut output = Self {
popups: HashMap::new(),
power_off_widget: PowerOffWidget(None),
time_widget: Default::default(),
battery_widget: Default::default(),
};
@ -47,10 +58,38 @@ impl Default for App {
}
impl App {
fn view(&self, _id: iced::window::Id) -> Element<'_, Message> {
fn name() -> String {
"wayland_panel".into()
}
fn close_popup(&mut self, id: iced::window::Id) -> Task<Message> {
self.popups.remove(&id);
return Task::done(Message::RemoveWindow(id));
}
fn view(&self, id: iced::window::Id) -> Element<'_, Message> {
if let Some(kind) = self.popups.get(&id) {
return match kind {
PopupKind::PowerOff => container(
row![
text("Shut down?"),
button("").on_press(Message::PowerOffConfirm),
button("").on_press(Message::PowerOffCancel),
]
.spacing(8)
.align_y(iced::Alignment::Center),
)
.center(iced::Length::Fill)
.into(),
};
}
// default: the bar
let content = row![
self.time_widget.view(),
iced::widget::space().width(iced::Length::Fill),
self.power_off_widget.view(),
iced::widget::space().width(iced::Length::Fill),
self.battery_widget.view(),
]
.padding(iced::Padding::from([0, 5]))
@ -62,13 +101,40 @@ impl App {
}
fn update(&mut self, message: Message) -> Task<Message> {
if let Message::Clock = message {
match message {
Message::Clock => {
self.time_widget.update();
self.battery_widget.update();
}
Task::none()
}
Message::PowerOff => {
let id = iced::window::Id::unique();
self.popups.insert(id, PopupKind::PowerOff);
self.power_off_widget.0 = Some(id);
Task::done(Message::NewLayerShell {
settings: NewLayerShellSettings {
size: Some((220, 40)),
anchor: Anchor::Top,
layer: iced_layershell::reexport::Layer::Overlay,
keyboard_interactivity:
iced_layershell::reexport::KeyboardInteractivity::OnDemand,
exclusive_zone: None,
..Default::default()
},
id,
})
}
Message::PowerOffConfirm => {
std::process::Command::new("poweroff").spawn().ok();
Task::none()
}
Message::PowerOffCancel => self.close_popup(self.power_off_widget.0.unwrap()),
_ => Task::none(),
}
}
fn style(&self, theme: &iced::Theme) -> iced::theme::Style {
iced::theme::Style {
@ -160,9 +226,22 @@ impl PanelWidget for TimeWidget {
}
}
#[to_layer_message]
#[derive(Debug)]
enum Message {
IcedEvent(iced::Event),
Clock,
#[derive(Default)]
struct PowerOffWidget(Option<iced::window::Id>);
impl PanelWidget for PowerOffWidget {
fn update(&mut self) {}
fn view(&self) -> Element<'_, Message> {
button("").on_press(Message::PowerOff).into()
}
}
#[to_layer_message(multi)]
#[derive(Debug, Clone)]
pub enum Message {
Clock,
PowerOff,
PowerOffConfirm,
PowerOffCancel,
}