Move screenshooter to rust
diff --git a/build.rs b/build.rs
index 7d05e6b..33dcfb9 100644
--- a/build.rs
+++ b/build.rs
@@ -34,6 +34,7 @@
fn main() {
let protocols = [
"wayland",
+ "weston-screenshooter",
"linux-dmabuf-unstable-v1",
"croscomp",
"alpha-compositing-unstable-v1",
diff --git a/src/display.rs b/src/display.rs
index 8b97614..178efda 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -11,7 +11,10 @@
use super::protocol::croscomp_output::CroscompOutput;
use crate::server::Resource;
-fn handle_bind(resource: &mut Resource<CroscompDisplay>, compositor: &mut super::Compositor) {
+fn handle_bind(
+ resource: &mut Resource<CroscompDisplay>,
+ compositor: &mut super::Compositor,
+) -> bool {
for head in compositor.head_iter().filter(|h| h.is_enabled()) {
println!("head {:?}", head);
@@ -52,6 +55,8 @@
output_resource.send(Done {});
}
+
+ true
}
pub fn init(shell: &Rc<RefCell<crate::Shell>>) {
diff --git a/src/main.rs b/src/main.rs
index dc5d5ce..49b92bd 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -26,6 +26,7 @@
mod protocol;
mod remote_shell;
mod rotate;
+mod screenshooter;
mod server;
mod shell;
mod splash;
@@ -217,6 +218,8 @@
aura_shell::init(&shell);
+ screenshooter::init(&shell);
+
compositor.borrow_mut().wake();
unsafe {
diff --git a/src/protocol.rs b/src/protocol.rs
index 02bcba9..7c2986c 100644
--- a/src/protocol.rs
+++ b/src/protocol.rs
@@ -16,6 +16,7 @@
pub(crate) use wayland_server::AnonymousObject;
include!(concat!(env!("OUT_DIR"), "/wayland.rs"));
+include!(concat!(env!("OUT_DIR"), "/weston-screenshooter.rs"));
include!(concat!(env!("OUT_DIR"), "/croscomp.rs"));
include!(concat!(env!("OUT_DIR"), "/aura-shell.rs"));
include!(concat!(
diff --git a/src/remote_shell.rs b/src/remote_shell.rs
index 8155fee..4ba1413 100644
--- a/src/remote_shell.rs
+++ b/src/remote_shell.rs
@@ -56,6 +56,8 @@
resource.send(Configure {
layout_mode: LayoutMode::Windowed.to_raw(),
});
+
+ true
})
.on_request(|_resource, request| {
use super::protocol::zcr_remote_shell_v1::Request::*;
diff --git a/src/screenshooter.rs b/src/screenshooter.rs
new file mode 100644
index 0000000..e910aed
--- /dev/null
+++ b/src/screenshooter.rs
@@ -0,0 +1,114 @@
+// 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::Shell;
+use std::cell::RefCell;
+use std::rc::Rc;
+
+use crate::ffi;
+use crate::protocol;
+
+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) {
+ println!("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(
+ ffi::wl_display_error::WL_DISPLAY_ERROR_INVALID_OBJECT 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;
+ println!("destroy shooter")
+ });
+
+ 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(),
+ );
+}
diff --git a/src/server.rs b/src/server.rs
index 9c8325a..cdc4e95 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -45,6 +45,10 @@
}
}
+ pub fn drop_native(&mut self) {
+ unsafe { ffi::wl_resource_destroy(self.native) }
+ }
+
pub unsafe fn make_child_for<J>(&self, id: u32) -> Option<Main<J>>
where
J: wayland_server::Interface + From<Resource<J>> + AsRef<Resource<J>>,
@@ -80,6 +84,18 @@
})
}
+ pub fn post_error(&self, err: u32, msg: &str) {
+ unsafe {
+ let msg = std::ffi::CString::new(msg).expect("invalid error message");
+
+ ffi::wl_resource_post_error(self.native, err, msg.as_ptr())
+ }
+ }
+
+ pub fn post_no_memory(&self) {
+ unsafe { ffi::wl_resource_post_no_memory(self.native) }
+ }
+
pub fn on_request<F>(&self, f: F) -> &Self
where
F: 'static + Fn(&mut Resource<I>, &I::Request),
@@ -167,7 +183,7 @@
where
I: wayland_server::Interface,
{
- handle_bind: Option<Box<dyn Fn(&mut Resource<I>)>>,
+ handle_bind: Option<Box<dyn Fn(&mut Resource<I>) -> bool>>,
dispatcher: Option<Box<dyn Fn(&mut Resource<I>, &I::Request)>>,
handle_destroy: Option<Box<dyn Fn(&mut Resource<I>)>>,
}
@@ -192,7 +208,7 @@
impl<I: wayland_server::Interface> Global<I> {
pub fn on_bind<F>(mut self, f: F) -> Self
where
- F: 'static + Fn(&mut Resource<I>),
+ F: 'static + Fn(&mut Resource<I>) -> bool,
{
// hook for handling bind time checks or allocations
self.handlers.handle_bind = Some(Box::new(f));
@@ -307,15 +323,21 @@
println!("handlers: {:?}", handlers as *const _);
- if let Some(ref handle_bind) = handlers.handle_bind {
+ let success = if let Some(ref handle_bind) = handlers.handle_bind {
println!(
"calling handle_bind for {}: {:?}",
I::NAME,
&(*handle_bind) as *const _
);
- (*handle_bind)(&mut resource);
- // xxx return value from handle_bind should indicate whether
- // or not bind was successful
+ (*handle_bind)(&mut resource)
+ } else {
+ false
+ };
+
+ if !success {
+ println!("on_bind returns failure");
+ resource.drop_native();
+ return;
}
if let Some(ref dispatcher) = handlers.dispatcher {
diff --git a/src/splash.rs b/src/splash.rs
index 6fe9ebe..aa68cb3 100644
--- a/src/splash.rs
+++ b/src/splash.rs
@@ -67,7 +67,10 @@
let global = compositor
.server
.create_global::<CroscompSplash>(version)
- .on_bind(|_| println!("splash: handle bind"))
+ .on_bind(|_| {
+ println!("splash: handle bind");
+ true
+ })
.on_request(|resource, request| handle_request(resource, request))
.on_destroy(move |_resource| super::Shell::finish_init(&rc));
diff --git a/weston/desktop-shell/screenshooter.c b/weston/desktop-shell/screenshooter.c
deleted file mode 100644
index 0b93fe0..0000000
--- a/weston/desktop-shell/screenshooter.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright © 2008-2011 Kristian Høgsberg
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "config.h"
-
-#include <stdint.h>
-#include <linux/input.h>
-
-#include <libweston/libweston.h>
-#include "weston.h"
-#include "weston-screenshooter-server-protocol.h"
-#include "shared/helpers.h"
-#include "shared/zalloc.h"
-#include <libweston/weston-log.h>
-
-struct screenshooter {
- struct weston_compositor *ec;
- struct wl_global *global;
- struct wl_client *client;
- struct weston_process process;
- struct wl_listener destroy_listener;
- struct weston_recorder *recorder;
-};
-
-static void
-screenshooter_done(void *data, enum weston_screenshooter_outcome outcome)
-{
- struct wl_resource *resource = data;
-
- switch (outcome) {
- case WESTON_SCREENSHOOTER_SUCCESS:
- weston_screenshooter_send_done(resource);
- break;
- case WESTON_SCREENSHOOTER_NO_MEMORY:
- wl_resource_post_no_memory(resource);
- break;
- default:
- break;
- }
-}
-
-static void
-screenshooter_shoot(struct wl_client *client,
- struct wl_resource *resource,
- struct wl_resource *output_resource,
- struct wl_resource *buffer_resource)
-{
- struct weston_output *output =
- weston_head_from_resource(output_resource)->output;
- struct weston_buffer *buffer =
- weston_buffer_from_resource(buffer_resource);
-
- if (buffer == NULL) {
- wl_resource_post_no_memory(resource);
- return;
- }
-
- weston_screenshooter_shoot(output, buffer, screenshooter_done, resource);
-}
-
-struct weston_screenshooter_interface screenshooter_implementation = {
- screenshooter_shoot
-};
-
-static void
-bind_shooter(struct wl_client *client,
- void *data, uint32_t version, uint32_t id)
-{
- struct screenshooter *shooter = data;
- struct wl_resource *resource;
- bool debug_enabled =
- weston_compositor_is_debug_protocol_enabled(shooter->ec);
-
- resource = wl_resource_create(client,
- &weston_screenshooter_interface, 1, id);
-
- if (!debug_enabled && !shooter->client) {
- wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
- "screenshooter failed: permission denied. "\
- "Debug protocol must be enabled");
- return;
- } else if (!debug_enabled && client != shooter->client) {
- wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
- "screenshooter failed: permission denied.");
- return;
- }
-
- wl_resource_set_implementation(resource, &screenshooter_implementation,
- data, NULL);
-}
-
-static void
-screenshooter_sigchld(struct weston_process *process, int status)
-{
- struct screenshooter *shooter =
- container_of(process, struct screenshooter, process);
-
- shooter->client = NULL;
-}
-
-static void
-screenshooter_binding(struct weston_keyboard *keyboard,
- const struct timespec *time, uint32_t key, void *data)
-{
- struct screenshooter *shooter = data;
- char *screenshooter_exe;
-
-
- screenshooter_exe = wet_get_bindir_path("weston-screenshooter");
- if (!screenshooter_exe) {
- weston_log("Could not construct screenshooter path.\n");
- return;
- }
-
- if (!shooter->client)
- shooter->client = weston_client_launch(shooter->ec,
- &shooter->process,
- screenshooter_exe, screenshooter_sigchld);
- free(screenshooter_exe);
-}
-
-static void
-recorder_binding(struct weston_keyboard *keyboard, const struct timespec *time,
- uint32_t key, void *data)
-{
- struct weston_compositor *ec = keyboard->seat->compositor;
- struct weston_output *output;
- struct screenshooter *shooter = data;
- struct weston_recorder *recorder = shooter->recorder;;
- static const char filename[] = "capture.wcap";
-
- if (recorder) {
- weston_recorder_stop(recorder);
- shooter->recorder = NULL;
- } else {
- if (keyboard->focus && keyboard->focus->output)
- output = keyboard->focus->output;
- else
- output = container_of(ec->output_list.next,
- struct weston_output, link);
-
- shooter->recorder = weston_recorder_start(output, filename);
- }
-}
-
-static void
-screenshooter_destroy(struct wl_listener *listener, void *data)
-{
- struct screenshooter *shooter =
- container_of(listener, struct screenshooter, destroy_listener);
-
- wl_list_remove(&shooter->destroy_listener.link);
-
- wl_global_destroy(shooter->global);
- free(shooter);
-}
-
-WL_EXPORT void
-screenshooter_create(struct weston_compositor *ec)
-{
- struct screenshooter *shooter;
-
- shooter = zalloc(sizeof *shooter);
- if (shooter == NULL)
- return;
-
- shooter->ec = ec;
-
- shooter->global = wl_global_create(ec->wl_display,
- &weston_screenshooter_interface, 1,
- shooter, bind_shooter);
- weston_compositor_add_key_binding(ec, KEY_S, MODIFIER_SUPER,
- screenshooter_binding, shooter);
- weston_compositor_add_key_binding(ec, KEY_R, MODIFIER_SUPER,
- recorder_binding, shooter);
-
- shooter->destroy_listener.notify = screenshooter_destroy;
- wl_signal_add(&ec->destroy_signal, &shooter->destroy_listener);
-}