Skip to content

Commit

Permalink
sctk: WIP session lock surface support
Browse files Browse the repository at this point in the history
  • Loading branch information
ids1024 committed Nov 15, 2023
1 parent f20c85d commit 0cc1494
Show file tree
Hide file tree
Showing 14 changed files with 560 additions and 3 deletions.
4 changes: 4 additions & 0 deletions core/src/event/wayland/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod layer;
mod output;
mod popup;
mod seat;
mod session_lock;
mod window;

use crate::{time::Instant, window::Id};
Expand All @@ -15,6 +16,7 @@ pub use layer::*;
pub use output::*;
pub use popup::*;
pub use seat::*;
pub use session_lock::*;
pub use window::*;

/// wayland events
Expand All @@ -36,6 +38,8 @@ pub enum Event {
DndOffer(DndOfferEvent),
/// Selection Offer events
SelectionOffer(SelectionOfferEvent),
/// Session lock events
SessionLock(SessionLockEvent),
/// Frame events
Frame(Instant, WlSurface, Id),
}
19 changes: 19 additions & 0 deletions core/src/event/wayland/session_lock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use crate::window::Id;
use sctk::reexports::client::protocol::wl_surface::WlSurface;

/// session lock events
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SessionLockEvent {
/// Compositor has activated lock
Locked,
/// Lock rejected / canceled by compositor
Finished,
/// Session lock protocol not supported
NotSupported,
/// Session lock surface focused
Focused(WlSurface, Id),
/// Session lock surface unfocused
Unfocused(WlSurface, Id),
/// Session unlock has been processed by server
Unlocked,
}
11 changes: 11 additions & 0 deletions examples/sctk_session_lock/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "sctk_session_lock"
version = "0.1.0"
edition = "2021"

[dependencies]
sctk = { package = "smithay-client-toolkit", git = "https://github.com/smithay/client-toolkit", rev = "828b1eb" }
iced = { path = "../..", default-features = false, features = ["async-std", "wayland", "debug", "a11y"] }
iced_runtime = { path = "../../runtime" }
env_logger = "0.10"
async-std = "1.0"
117 changes: 117 additions & 0 deletions examples/sctk_session_lock/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use iced::wayland::session_lock;
use iced::{
event::wayland::{Event as WaylandEvent, OutputEvent, SessionLockEvent},
wayland::InitialSurface,
widget::text,
window, Application, Command, Element, Subscription, Theme,
};
use iced_runtime::window::Id as SurfaceId;

fn main() {
let mut settings = iced::Settings::default();
settings.initial_surface = InitialSurface::None;
Locker::run(settings).unwrap();
}

#[derive(Debug, Clone, Default)]
struct Locker {
max_surface_id: u128,
exit: bool,
}

#[derive(Debug, Clone)]
pub enum Message {
WaylandEvent(WaylandEvent),
TimeUp,
Ignore,
}

impl Locker {
fn next_surface_id(&mut self) -> SurfaceId {
self.max_surface_id += 1;
SurfaceId(self.max_surface_id)
}
}

impl Application for Locker {
type Executor = iced::executor::Default;
type Message = Message;
type Flags = ();
type Theme = Theme;

fn new(_flags: ()) -> (Locker, Command<Self::Message>) {
(
Locker {
..Locker::default()
},
session_lock::lock(),
)
}

fn title(&self) -> String {
String::from("Locker")
}

fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
match message {
Message::WaylandEvent(evt) => match evt {
WaylandEvent::Output(evt, output) => match evt {
OutputEvent::Created(_) => {
return session_lock::get_lock_surface(
self.next_surface_id(),
output,
);
}
OutputEvent::Removed => {}
_ => {}
},
WaylandEvent::SessionLock(evt) => match evt {
SessionLockEvent::Locked => {
return iced::Command::perform(
async_std::task::sleep(
std::time::Duration::from_secs(5),
),
|_| Message::TimeUp,
);
}
SessionLockEvent::Unlocked => {
// Server has processed unlock, so it's safe to exit
self.exit = true;
}
_ => {}
},
_ => {}
},
Message::TimeUp => {
return session_lock::unlock();
}
Message::Ignore => {}
}
Command::none()
}

fn should_exit(&self) -> bool {
self.exit
}

fn view(&self, id: window::Id) -> Element<Self::Message> {
text(format!("Lock Surface {:?}", id)).into()
}

fn subscription(&self) -> Subscription<Self::Message> {
iced::subscription::events_with(|evt, _| {
if let iced::Event::PlatformSpecific(
iced::event::PlatformSpecific::Wayland(evt),
) = evt
{
Some(Message::WaylandEvent(evt))
} else {
None
}
})
}

fn close_requested(&self, _id: window::Id) -> Self::Message {
Message::Ignore
}
}
8 changes: 8 additions & 0 deletions runtime/src/command/platform_specific/wayland/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub mod data_device;
pub mod layer_surface;
/// popup actions
pub mod popup;
/// session locks
pub mod session_lock;
/// window actions
pub mod window;

Expand All @@ -25,6 +27,8 @@ pub enum Action<T> {
DataDevice(data_device::Action<T>),
/// activation
Activation(activation::Action<T>),
/// session lock
SessionLock(session_lock::Action<T>),
}

impl<T> Action<T> {
Expand All @@ -43,6 +47,7 @@ impl<T> Action<T> {
Action::Popup(a) => Action::Popup(a.map(f)),
Action::DataDevice(a) => Action::DataDevice(a.map(f)),
Action::Activation(a) => Action::Activation(a.map(f)),
Action::SessionLock(a) => Action::SessionLock(a.map(f)),
}
}
}
Expand All @@ -61,6 +66,9 @@ impl<T> Debug for Action<T> {
Self::Activation(arg0) => {
f.debug_tuple("Activation").field(arg0).finish()
}
Self::SessionLock(arg0) => {
f.debug_tuple("SessionLock").field(arg0).finish()
}
}
}
}
80 changes: 80 additions & 0 deletions runtime/src/command/platform_specific/wayland/session_lock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use std::{fmt, marker::PhantomData};

use iced_core::window::Id;
use iced_futures::MaybeSend;

use sctk::reexports::client::protocol::wl_output::WlOutput;

/// Session lock action
#[derive(Clone)]
pub enum Action<T> {
/// Request a session lock
Lock,
/// Destroy lock
Unlock,
/// Create lock surface for output
LockSurface {
/// unique id for surface
id: Id,
/// output
output: WlOutput,
/// phantom
_phantom: PhantomData<T>,
},
/// Destroy lock surface
DestroyLockSurface {
/// unique id for surface
id: Id,
},
}

impl<T> Action<T> {
/// Maps the output of a window [`Action`] using the provided closure.
pub fn map<A>(
self,
_: impl Fn(T) -> A + 'static + MaybeSend + Sync,
) -> Action<A>
where
T: 'static,
{
match self {
Action::Lock => Action::Lock,
Action::Unlock => Action::Unlock,
Action::LockSurface {
id,
output,
_phantom,
} => Action::LockSurface {
id,
output,
_phantom: PhantomData,
},
Action::DestroyLockSurface { id } => {
Action::DestroyLockSurface { id }
}
}
}
}

impl<T> fmt::Debug for Action<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Action::Lock => write!(f, "Action::SessionLock::Lock"),
Action::Unlock => write!(f, "Action::SessionLock::Unlock"),
Action::LockSurface {
id,
output,
_phantom,
} => write!(
f,
"Action::SessionLock::LockSurface {{ id: {:?}, output: {:?} }}",
id, output
),
Action::DestroyLockSurface { id } => write!(
f,
"Action::SessionLock::DestroyLockSurface {{ id: {:?} }}",
id
),
}
}
}
Loading

0 comments on commit 0cc1494

Please sign in to comment.