Basic lock
This commit is contained in:
parent
105d70d2ca
commit
d0192547df
|
@ -1 +1,5 @@
|
||||||
|
.*
|
||||||
|
!.gitignore
|
||||||
|
|
||||||
|
*.log
|
||||||
/target
|
/target
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
17
Cargo.toml
17
Cargo.toml
|
@ -2,6 +2,21 @@
|
||||||
name = "udon"
|
name = "udon"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
description = "A kanban-lockscreen"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wayland-client = "0.30.2"
|
# Logs and error reporting
|
||||||
|
log = "0.4.20"
|
||||||
|
log4rs = "1.2.0"
|
||||||
|
color-eyre = "0.6.2"
|
||||||
|
|
||||||
|
# Surface drawing
|
||||||
|
cairo = "0.0.4"
|
||||||
|
|
||||||
|
# the version here must match the one used by wayland-client
|
||||||
|
calloop = "0.10.0"
|
||||||
|
calloop-wayland-source = "0.1.0"
|
||||||
|
tempfile = "3.7.0"
|
||||||
|
wayland-client = { version = "0.30.2" }
|
||||||
|
# staging needed for ext session lock
|
||||||
|
wayland-protocols = { version = "0.30.1", features = ["staging", "client"] }
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
# Udon
|
# Udon
|
||||||
|
|
||||||
A Wayland lockscreen supporting rotating display of informations
|
A Wayland lockscreen supporting rotating display of informations
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
The following code repositories were consulted to make Udon possible
|
||||||
|
- [wpaperd](https://github.com/danyspin97/wpaperd)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
edition = "2021"
|
||||||
|
brace_style = "AlwaysNextLine"
|
||||||
|
hard_tabs = true
|
||||||
|
tab_spaces = 3
|
||||||
|
imports_granularity = "Crate"
|
140
src/main.rs
140
src/main.rs
|
@ -1,81 +1,69 @@
|
||||||
use wayland_client::{protocol::wl_registry, Connection, Dispatch, QueueHandle};
|
mod state;
|
||||||
// This struct represents the state of our app. This simple app does not
|
|
||||||
// need any state, by this type still supports the `Dispatch` implementations.
|
|
||||||
struct AppData;
|
|
||||||
|
|
||||||
// Implement `Dispatch<WlRegistry, ()> for out state. This provides the logic
|
use crate::state::State;
|
||||||
// to be able to process events for the wl_registry interface.
|
|
||||||
//
|
use calloop_wayland_source::WaylandSource;
|
||||||
// The second type parameter is the user-data of our implementation. It is a
|
use color_eyre::eyre::{self, Context};
|
||||||
// mechanism that allows you to associate a value to each particular Wayland
|
use wayland_client::{globals as WG, Connection};
|
||||||
// object, and allow different dispatching logic depending on the type of the
|
|
||||||
// associated value.
|
fn setup() -> eyre::Result<()>
|
||||||
//
|
|
||||||
// In this example, we just use () as we don't have any value to associate. See
|
|
||||||
// the `Dispatch` documentation for more details about this.
|
|
||||||
impl Dispatch<wl_registry::WlRegistry, ()> for AppData
|
|
||||||
{
|
{
|
||||||
fn event(
|
use log4rs::{append, config, encode::pattern::PatternEncoder};
|
||||||
_state: &mut Self,
|
let stdout = append::console::ConsoleAppender::builder()
|
||||||
_: &wl_registry::WlRegistry,
|
.encoder(Box::new(PatternEncoder::new(
|
||||||
event: wl_registry::Event,
|
"{d(%Y-%m-%d %H:%M:%S)} | {h({l}):5.5} | [{T}] {f}:{L} — {m}{n}",
|
||||||
_: &(),
|
)))
|
||||||
_: &Connection,
|
.build();
|
||||||
_: &QueueHandle<AppData>,
|
|
||||||
)
|
let file = append::file::FileAppender::builder()
|
||||||
{
|
.encoder(Box::new(PatternEncoder::new("{d} - {m}{n}")))
|
||||||
// When receiving events from the wl_registry, we are only interested in the
|
.build("requests.log")?;
|
||||||
// `global` event, which signals a new available global.
|
|
||||||
// When receiving this event, we just print its characteristics in this example.
|
let config = config::Config::builder()
|
||||||
if let wl_registry::Event::Global {
|
.appender(config::Appender::builder().build("stdout", Box::new(stdout)))
|
||||||
name,
|
.appender(config::Appender::builder().build("file", Box::new(file)))
|
||||||
interface,
|
.build(
|
||||||
version,
|
config::Root::builder()
|
||||||
} = event
|
.appender("stdout")
|
||||||
{
|
.build(log::LevelFilter::Trace),
|
||||||
println!("[{}] {} (v{})", name, interface, version);
|
)?;
|
||||||
|
|
||||||
|
let _handle = log4rs::init_config(config)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> eyre::Result<()>
|
||||||
|
{
|
||||||
|
// Initialise on I/O modules
|
||||||
|
color_eyre::install()?;
|
||||||
|
setup().wrap_err("Could not initialize logging")?;
|
||||||
|
|
||||||
|
// Create WL connection and get the display
|
||||||
|
let connection = Connection::connect_to_env()?;
|
||||||
|
let display = connection.display();
|
||||||
|
let (globals, event_queue) = WG::registry_queue_init::<State>(&connection)?;
|
||||||
|
let q_handle = event_queue.handle();
|
||||||
|
|
||||||
|
let registry = display.get_registry(&q_handle, ());
|
||||||
|
|
||||||
|
let mut state = State::new(globals.contents().clone_list(), ®istry, &q_handle)?;
|
||||||
|
|
||||||
|
// Main calloop event loop
|
||||||
|
let mut event_loop = calloop::EventLoop::<State>::try_new()?;
|
||||||
|
|
||||||
|
WaylandSource::new(event_queue)?.insert(event_loop.handle())?;
|
||||||
|
|
||||||
|
log::trace!("Main loop starting");
|
||||||
|
|
||||||
|
state.lock(&q_handle);
|
||||||
|
|
||||||
|
while let Ok(_) = event_loop.dispatch(None, &mut state) {
|
||||||
|
if state.stop {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
log::trace!("Teardown");
|
||||||
// The main function of our program
|
|
||||||
fn main()
|
Ok(())
|
||||||
{
|
|
||||||
// Create a Wayland connection by connecting to the server through the
|
|
||||||
// environment-provided configuration.
|
|
||||||
let conn = Connection::connect_to_env().unwrap();
|
|
||||||
|
|
||||||
// Retrieve the WlDisplay Wayland object from the connection. This object is
|
|
||||||
// the starting point of any Wayland program, from which all other objects will
|
|
||||||
// be created.
|
|
||||||
let display = conn.display();
|
|
||||||
|
|
||||||
// Create an event queue for our event processing
|
|
||||||
let mut event_queue = conn.new_event_queue();
|
|
||||||
// An get its handle to associated new objects to it
|
|
||||||
let qh = event_queue.handle();
|
|
||||||
|
|
||||||
// Create a wl_registry object by sending the wl_display.get_registry request
|
|
||||||
// This method takes two arguments: a handle to the queue the newly created
|
|
||||||
// wl_registry will be assigned to, and the user-data that should be associated
|
|
||||||
// with this registry (here it is () as we don't need user-data).
|
|
||||||
let _registry = display.get_registry(&qh, ());
|
|
||||||
|
|
||||||
// At this point everything is ready, and we just need to wait to receive the events
|
|
||||||
// from the wl_registry, our callback will print the advertized globals.
|
|
||||||
println!("Advertized globals:");
|
|
||||||
|
|
||||||
// To actually receive the events, we invoke the `sync_roundtrip` method. This method
|
|
||||||
// is special and you will generally only invoke it during the setup of your program:
|
|
||||||
// it will block until the server has received and processed all the messages you've
|
|
||||||
// sent up to now.
|
|
||||||
//
|
|
||||||
// In our case, that means it'll block until the server has received our
|
|
||||||
// wl_display.get_registry request, and as a reaction has sent us a batch of
|
|
||||||
// wl_registry.global events.
|
|
||||||
//
|
|
||||||
// `sync_roundtrip` will then empty the internal buffer of the queue it has been invoked
|
|
||||||
// on, and thus invoke our `Dispatch` implementation that prints the list of advertized
|
|
||||||
// globals.
|
|
||||||
event_queue.roundtrip(&mut AppData).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,448 @@
|
||||||
|
use color_eyre::eyre::{self, eyre};
|
||||||
|
use wayland_client::{globals as WG, protocol as WP, Connection, Dispatch, QueueHandle, WEnum};
|
||||||
|
use wayland_protocols::ext::session_lock::v1::client as WpSl;
|
||||||
|
|
||||||
|
pub struct State
|
||||||
|
{
|
||||||
|
pub stop: bool,
|
||||||
|
|
||||||
|
// wayland globals
|
||||||
|
pub compositor: WP::wl_compositor::WlCompositor,
|
||||||
|
pub subcompositor: WP::wl_subcompositor::WlSubcompositor,
|
||||||
|
pub shm: WP::wl_shm::WlShm,
|
||||||
|
pub seat: WP::wl_seat::WlSeat,
|
||||||
|
pub output: WP::wl_output::WlOutput,
|
||||||
|
pub ext_session_lock_manager: WpSl::ext_session_lock_manager_v1::ExtSessionLockManagerV1,
|
||||||
|
|
||||||
|
// wayland objects
|
||||||
|
pub surface: Option<WP::wl_surface::WlSurface>,
|
||||||
|
pub ext_session_lock: Option<WpSl::ext_session_lock_v1::ExtSessionLockV1>,
|
||||||
|
pub ext_session_lock_surface: Option<WpSl::ext_session_lock_surface_v1::ExtSessionLockSurfaceV1>,
|
||||||
|
buffer: Option<WP::wl_buffer::WlBuffer>,
|
||||||
|
//cairo_surface: Option<cairo::ImageSurface>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State
|
||||||
|
{
|
||||||
|
pub fn new(
|
||||||
|
globals: Vec<WG::Global>,
|
||||||
|
registry: &WP::wl_registry::WlRegistry,
|
||||||
|
q_handle: &wayland_client::QueueHandle<State>,
|
||||||
|
) -> eyre::Result<State, eyre::Report>
|
||||||
|
{
|
||||||
|
let globals: std::collections::BTreeMap<_, _> = globals
|
||||||
|
.into_iter()
|
||||||
|
.map(|global| (global.interface, global.name))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let compositor_name = globals
|
||||||
|
.get("wl_compositor")
|
||||||
|
.ok_or_else(|| eyre!("compositor global not found"))?;
|
||||||
|
let subcompositor_name = globals
|
||||||
|
.get("wl_subcompositor")
|
||||||
|
.ok_or_else(|| eyre!("subcompositor global not found"))?;
|
||||||
|
let shm_name = globals
|
||||||
|
.get("wl_shm")
|
||||||
|
.ok_or_else(|| eyre!("shm global not found"))?;
|
||||||
|
let seat_name = globals
|
||||||
|
.get("wl_seat")
|
||||||
|
.ok_or_else(|| eyre!("seat global not found"))?;
|
||||||
|
let output_name = globals
|
||||||
|
.get("wl_output")
|
||||||
|
.ok_or_else(|| eyre!("output global not found"))?;
|
||||||
|
let eslm_name = globals
|
||||||
|
.get("ext_session_lock_manager_v1")
|
||||||
|
.ok_or_else(|| eyre!("session lock global not found"))?;
|
||||||
|
|
||||||
|
Ok(State {
|
||||||
|
stop: false,
|
||||||
|
|
||||||
|
compositor: registry.bind(*compositor_name, 4, q_handle, ()),
|
||||||
|
subcompositor: registry.bind(*subcompositor_name, 1, q_handle, ()),
|
||||||
|
shm: registry.bind(*shm_name, 1, q_handle, ()),
|
||||||
|
seat: registry.bind(*seat_name, 4, q_handle, ()),
|
||||||
|
output: registry.bind(*output_name, 4, q_handle, ()),
|
||||||
|
ext_session_lock_manager: registry.bind(*eslm_name, 1, q_handle, ()),
|
||||||
|
|
||||||
|
surface: None,
|
||||||
|
ext_session_lock: None,
|
||||||
|
ext_session_lock_surface: None,
|
||||||
|
buffer: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lock(&mut self, q_handle: &wayland_client::QueueHandle<State>)
|
||||||
|
{
|
||||||
|
self.ext_session_lock = Some(self.ext_session_lock_manager.lock(&q_handle, ()));
|
||||||
|
/*
|
||||||
|
let surface = self.compositor.create_surface(&q_handle, ());
|
||||||
|
self.ext_session_lock_surface =
|
||||||
|
Some(registry.get_lock_surface(&surface, &self.output, &q_handle, ()));
|
||||||
|
self.surface = Some(surface);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unlock(&mut self)
|
||||||
|
{
|
||||||
|
match &self.ext_session_lock {
|
||||||
|
Some(lock) => {
|
||||||
|
lock.unlock_and_destroy();
|
||||||
|
self.stop = true;
|
||||||
|
}
|
||||||
|
None => log::warn!("Attempting to unlock lock that does not exist"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This hook is required to read globals
|
||||||
|
impl Dispatch<WP::wl_registry::WlRegistry, WG::GlobalListContents> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
_state: &mut Self,
|
||||||
|
_proxy: &WP::wl_registry::WlRegistry,
|
||||||
|
_event: WP::wl_registry::Event,
|
||||||
|
_data: &WG::GlobalListContents,
|
||||||
|
_conn: &Connection,
|
||||||
|
_q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Dispatch<WP::wl_registry::WlRegistry, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
_state: &mut Self,
|
||||||
|
_proxy: &WP::wl_registry::WlRegistry,
|
||||||
|
_event: WP::wl_registry::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
_q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
impl Dispatch<WP::wl_registry::WlRegistry, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
proxy: &WP::wl_registry::WlRegistry,
|
||||||
|
event: WP::wl_registry::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if let WP::wl_registry::Event::Global {
|
||||||
|
name,
|
||||||
|
interface,
|
||||||
|
version,
|
||||||
|
} = event
|
||||||
|
{
|
||||||
|
match interface.as_str() {
|
||||||
|
"wl_compositor" => {
|
||||||
|
let v = 4; // Version override
|
||||||
|
state.compositor = Some(proxy.bind(name, v, q_handle, ()));
|
||||||
|
log::trace!("Compositor [{}] {} (v{})", name, interface, version);
|
||||||
|
}
|
||||||
|
"wl_subcompositor" => {
|
||||||
|
let v = 1; // Version override
|
||||||
|
state.subcompositor = Some(proxy.bind(name, v, q_handle, ()));
|
||||||
|
log::trace!("Subcompositor [{}] {} (v{})", name, interface, version);
|
||||||
|
}
|
||||||
|
"wl_shm" => {
|
||||||
|
let v = 1; // Version override
|
||||||
|
state.shm = Some(proxy.bind(name, v, q_handle, ()));
|
||||||
|
log::trace!("Shared Memory [{}] {} (v{})", name, interface, version);
|
||||||
|
}
|
||||||
|
"wl_seat" => {
|
||||||
|
let v = 4; // Version override
|
||||||
|
state.seat = Some(proxy.bind(name, v, q_handle, ()));
|
||||||
|
log::trace!("Seat [{}] {} (v{})", name, interface, version);
|
||||||
|
}
|
||||||
|
"wl_output" => {
|
||||||
|
let v = 4; // Version override
|
||||||
|
state.output = Some(proxy.bind(name, v, q_handle, ()));
|
||||||
|
log::trace!("Output [{}] {} (v{})", name, interface, version);
|
||||||
|
}
|
||||||
|
"ext_session_lock_manager_v1" => {
|
||||||
|
let v = 1;
|
||||||
|
state.ext_session_lock_manager = Some(proxy.bind(name, v, q_handle, ()));
|
||||||
|
log::trace!(
|
||||||
|
"Ext Session Lock Manager [{}] {} (v{})",
|
||||||
|
name, interface, version
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => log::trace!("Other Global [{}] {} (v{})", name, interface, version),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
impl Dispatch<WP::wl_compositor::WlCompositor, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
_state: &mut Self,
|
||||||
|
_proxy: &WP::wl_compositor::WlCompositor,
|
||||||
|
_event: WP::wl_compositor::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
_q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
log::trace!("Event from compositor!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Dispatch<WP::wl_subcompositor::WlSubcompositor, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
_state: &mut Self,
|
||||||
|
_proxy: &WP::wl_subcompositor::WlSubcompositor,
|
||||||
|
_event: WP::wl_subcompositor::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
_q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
log::trace!("Event from subcompositor!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Dispatch<WP::wl_shm::WlShm, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
_state: &mut Self,
|
||||||
|
_proxy: &WP::wl_shm::WlShm,
|
||||||
|
_event: WP::wl_shm::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
_q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
log::trace!("Event from shm!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Dispatch<WP::wl_output::WlOutput, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
_state: &mut Self,
|
||||||
|
_proxy: &WP::wl_output::WlOutput,
|
||||||
|
_event: WP::wl_output::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
_q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
log::trace!("Event from output!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Dispatch<WpSl::ext_session_lock_manager_v1::ExtSessionLockManagerV1, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
_state: &mut Self,
|
||||||
|
_proxy: &WpSl::ext_session_lock_manager_v1::ExtSessionLockManagerV1,
|
||||||
|
_event: WpSl::ext_session_lock_manager_v1::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
_q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
unreachable!("Session lock manager should not emit any event");
|
||||||
|
//state.lock(&q_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<WP::wl_surface::WlSurface, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
_state: &mut Self,
|
||||||
|
_proxy: &WP::wl_surface::WlSurface,
|
||||||
|
_event: WP::wl_surface::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
_q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
log::trace!("Event from surface!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Dispatch<WpSl::ext_session_lock_v1::ExtSessionLockV1, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
proxy: &WpSl::ext_session_lock_v1::ExtSessionLockV1,
|
||||||
|
event: WpSl::ext_session_lock_v1::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
match event {
|
||||||
|
WpSl::ext_session_lock_v1::Event::Locked => {
|
||||||
|
if state.stop {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let surface = state.compositor.create_surface(&q_handle, ());
|
||||||
|
state.ext_session_lock_surface =
|
||||||
|
Some(proxy.get_lock_surface(&surface, &state.output, &q_handle, ()));
|
||||||
|
state.surface = Some(surface);
|
||||||
|
log::info!("Locked.");
|
||||||
|
}
|
||||||
|
WpSl::ext_session_lock_v1::Event::Finished => {
|
||||||
|
state.ext_session_lock_surface = None;
|
||||||
|
log::trace!("Could not lock surface!");
|
||||||
|
}
|
||||||
|
_ => log::trace!("Unknown event"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(tmp: &mut std::fs::File, (buf_x, buf_y): (u32, u32))
|
||||||
|
{
|
||||||
|
use std::{cmp::min, io::Write};
|
||||||
|
let mut buf = std::io::BufWriter::new(tmp);
|
||||||
|
for y in 0..buf_y {
|
||||||
|
for x in 0..buf_x {
|
||||||
|
let a = 0xFF;
|
||||||
|
let r = min(((buf_x - x) * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
|
||||||
|
let g = min((x * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
|
||||||
|
let b = min(((buf_x - x) * 0xFF) / buf_x, (y * 0xFF) / buf_y);
|
||||||
|
|
||||||
|
let color = (a << 24) + (r << 16) + (g << 8) + b;
|
||||||
|
buf.write_all(&color.to_ne_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.flush().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<WpSl::ext_session_lock_surface_v1::ExtSessionLockSurfaceV1, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
proxy: &WpSl::ext_session_lock_surface_v1::ExtSessionLockSurfaceV1,
|
||||||
|
event: WpSl::ext_session_lock_surface_v1::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
match event {
|
||||||
|
WpSl::ext_session_lock_surface_v1::Event::Configure {
|
||||||
|
serial,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
} => {
|
||||||
|
use std::os::unix::prelude::AsRawFd;
|
||||||
|
log::info!(
|
||||||
|
"Lock surface configuration event: ({}), {} {}",
|
||||||
|
serial,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
);
|
||||||
|
// Ack should go before any buffer commitment.
|
||||||
|
proxy.ack_configure(serial);
|
||||||
|
|
||||||
|
let mut file = tempfile::tempfile().unwrap();
|
||||||
|
draw(&mut file, (width, height));
|
||||||
|
let pool =
|
||||||
|
state
|
||||||
|
.shm
|
||||||
|
.create_pool(file.as_raw_fd(), (width * height * 4) as i32, q_handle, ());
|
||||||
|
let buffer = pool.create_buffer(
|
||||||
|
0,
|
||||||
|
width as i32,
|
||||||
|
height as i32,
|
||||||
|
(width * 4) as i32,
|
||||||
|
WP::wl_shm::Format::Argb8888,
|
||||||
|
q_handle,
|
||||||
|
(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let surface = state.surface.as_ref().unwrap();
|
||||||
|
surface.attach(Some(&buffer), 0, 0);
|
||||||
|
surface.commit();
|
||||||
|
|
||||||
|
state.buffer = Some(buffer);
|
||||||
|
}
|
||||||
|
_ => log::trace!("Unknown event"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<WP::wl_seat::WlSeat, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
proxy: &WP::wl_seat::WlSeat,
|
||||||
|
event: WP::wl_seat::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
log::trace!("Event from seat!");
|
||||||
|
if let WP::wl_seat::Event::Capabilities {
|
||||||
|
capabilities: WEnum::Value(capabilities),
|
||||||
|
} = event
|
||||||
|
{
|
||||||
|
if capabilities.contains(WP::wl_seat::Capability::Keyboard) {
|
||||||
|
proxy.get_keyboard(q_handle, ());
|
||||||
|
} else {
|
||||||
|
log::error!("Seat capability does not contain keyboard");
|
||||||
|
state.stop = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Dispatch<WP::wl_keyboard::WlKeyboard, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
state: &mut Self,
|
||||||
|
_proxy: &WP::wl_keyboard::WlKeyboard,
|
||||||
|
event: WP::wl_keyboard::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
_q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if let WP::wl_keyboard::Event::Key { key, .. } = event {
|
||||||
|
if key == 1 {
|
||||||
|
// ESC key
|
||||||
|
log::trace!("Event from keyboard! Unlocking.");
|
||||||
|
state.stop = true;
|
||||||
|
state.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<WP::wl_shm_pool::WlShmPool, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
_state: &mut Self,
|
||||||
|
_proxy: &WP::wl_shm_pool::WlShmPool,
|
||||||
|
_event: WP::wl_shm_pool::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
_q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
log::trace!("Event from shm pool!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<WP::wl_buffer::WlBuffer, ()> for State
|
||||||
|
{
|
||||||
|
fn event(
|
||||||
|
_state: &mut Self,
|
||||||
|
_proxy: &WP::wl_buffer::WlBuffer,
|
||||||
|
_event: WP::wl_buffer::Event,
|
||||||
|
_data: &(),
|
||||||
|
_conn: &Connection,
|
||||||
|
_q_handle: &QueueHandle<State>,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
log::trace!("Event from shm pool!")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue