Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sctk: Add support for ext-session-lock protocol #71

Merged
merged 1 commit into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading