// Copyright 2023 System76 // SPDX-License-Identifier: GPL-3.0-only //! # DBus interface proxy for: `org.freedesktop.UPower.KbdBacklight` //! //! This code was generated by `zbus-xmlgen` `2.0.1` from DBus introspection data. //! Source: `Interface '/org/freedesktop/UPower/KbdBacklight' from service 'org.freedesktop.UPower' on system bus`. use cctk::{sctk::reexports::calloop, toplevel_info::ToplevelInfo}; use cosmic::{ cctk::{self, cosmic_protocols}, iced::{self, Subscription}, iced_core::image::Bytes, iced_futures::{futures, stream}, }; use cosmic_protocols::toplevel_info::v1::client::zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1; use futures::{ channel::mpsc::{unbounded, UnboundedReceiver}, SinkExt, StreamExt, }; use image::EncodableLayout; use once_cell::sync::Lazy; use std::fmt::Debug; use tokio::sync::Mutex; use crate::wayland_handler::wayland_handler; pub static WAYLAND_RX: Lazy>>> = Lazy::new(|| Mutex::new(None)); pub fn wayland_subscription() -> iced::Subscription { Subscription::run_with_id( std::any::TypeId::of::(), stream::channel(50, move |mut output| async move { let mut state = State::Waiting; loop { state = start_listening(state, &mut output).await; } }), ) } pub enum State { Waiting, Finished, } async fn start_listening( state: State, output: &mut futures::channel::mpsc::Sender, ) -> State { match state { State::Waiting => { let mut guard = WAYLAND_RX.lock().await; let rx = { if guard.is_none() { let (calloop_tx, calloop_rx) = calloop::channel::channel(); let (toplevel_tx, toplevel_rx) = unbounded(); let _ = std::thread::spawn(move || { wayland_handler(toplevel_tx, calloop_rx); }); *guard = Some(toplevel_rx); _ = output.send(WaylandUpdate::Init(calloop_tx)).await; } guard.as_mut().unwrap() }; match rx.next().await { Some(u) => { _ = output.send(u).await; State::Waiting } None => { _ = output.send(WaylandUpdate::Finished).await; tracing::error!("Wayland handler thread died"); State::Finished } } } State::Finished => iced::futures::future::pending().await, } } #[derive(Clone, Debug)] pub enum WaylandUpdate { Init(calloop::channel::Sender), Finished, Toplevel(ToplevelUpdate), Image(ZcosmicToplevelHandleV1, WaylandImage), } #[derive(Debug, Clone)] pub struct WaylandImage { pub img: Bytes, pub width: u32, pub height: u32, } impl WaylandImage { pub fn new(img: image::RgbaImage) -> Self { Self { img: Bytes::copy_from_slice(img.as_bytes()), width: img.width(), height: img.height(), } } } impl AsRef<[u8]> for WaylandImage { fn as_ref(&self) -> &[u8] { self.img.as_bytes() } } #[derive(Clone, Debug)] pub enum ToplevelUpdate { Add(ZcosmicToplevelHandleV1, ToplevelInfo), Update(ZcosmicToplevelHandleV1, ToplevelInfo), Remove(ZcosmicToplevelHandleV1), } #[derive(Clone, Debug)] pub enum WaylandRequest { Toplevel(ToplevelRequest), } #[derive(Debug, Clone)] pub enum ToplevelRequest { Activate(ZcosmicToplevelHandleV1), }