blob: 8dbaa1e469e3f91aad40e7f2f096bf0388aeaee1 [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::ffi;
use crate::protocol;
use crate::Shell;
use log::debug;
use std::cell::RefCell;
use std::rc::Rc;
use crate::server::Resource;
use protocol::weston_screenshooter::{Request, WestonScreenshooter};
struct ScreenShooter {
shell: Rc<RefCell<crate::Shell>>,
client: Option<*mut ffi::wl_client>,
}
impl ScreenShooter {
fn shoot(&mut self) {
let path = "/usr/bin/weston-screenshooter";
let shell = self.shell.borrow();
let mut compositor = shell.compositor.borrow_mut();
if self.client.is_none() {
self.client = compositor.launch_client(path).ok();
}
}
fn record(&mut self) {
debug!("screenshooter record");
}
}
fn handle_request(resource: &mut Resource<WestonScreenshooter>, request: &Request) {
unsafe extern "C" fn done(
data: *mut ::std::ffi::c_void,
outcome: ffi::weston_screenshooter_outcome,
) {
use protocol::weston_screenshooter::Event::Done;
let resource = Resource::<WestonScreenshooter>::from_c_ptr(data as *mut _);
match outcome {
ffi::weston_screenshooter_outcome::WESTON_SCREENSHOOTER_SUCCESS => resource.send(Done),
_ => resource.post_no_memory(),
}
}
match request {
Request::Shoot { output, buffer } => unsafe {
let output = (*ffi::weston_head_from_resource(output.as_ref().c_ptr())).output;
let buffer = ffi::weston_buffer_from_resource(buffer.as_ref().c_ptr());
ffi::weston_screenshooter_shoot(output, buffer, Some(done), resource.c_ptr() as *mut _);
},
}
}
pub fn init(shell: &Rc<RefCell<Shell>>) {
let shooter = Rc::new(RefCell::new(ScreenShooter {
shell: Rc::clone(shell),
client: None,
}));
let s = shell.borrow();
let mut compositor = s.compositor.borrow_mut();
let rc = Rc::clone(&shooter);
let destroy_rc = Rc::clone(&shooter);
let version = 1;
let global = compositor
.server
.create_global::<WestonScreenshooter>(version)
.on_bind(move |resource| {
match rc.borrow().client {
Some(native_client) if native_client == resource.client() => {
// good case
true
}
_ => {
resource.post_error(
protocol::wl_display::Error::InvalidObject as u32,
"screenshooter failed: permission denied",
);
false
}
}
})
.on_request(|resource, request| handle_request(resource, request))
.on_destroy(move |_resource| {
let mut s = destroy_rc.borrow_mut();
s.client = None;
});
Box::into_raw(Box::new(global));
use crate::ffi::evdev::{KEY_R, KEY_S};
let rc = Rc::clone(&shooter);
compositor.bind_key(
KEY_S,
ffi::weston_keyboard_modifier::MODIFIER_SUPER,
move |_, _, _| rc.borrow_mut().shoot(),
);
let rc = Rc::clone(&shooter);
compositor.bind_key(
KEY_R,
ffi::weston_keyboard_modifier::MODIFIER_SUPER,
move |_keyboard, _, _| rc.borrow_mut().record(),
);
}