From 6f52f9c75a0cbbd874d9d6fd98647b886379259f Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Mon, 7 May 2018 19:55:34 +0200 Subject: [PATCH 1/6] re-export crates that are actually part of the public API --- src/lib.rs | 18 +++++++++--------- src/wayland/seat/mod.rs | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9366821..28f7707 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,27 +7,27 @@ // `error_chain!` can recurse deeply #![recursion_limit = "1024"] -extern crate image; +pub extern crate image; #[cfg_attr(feature = "backend_session", macro_use)] extern crate nix; extern crate tempfile; -extern crate wayland_protocols; -extern crate wayland_server; +pub extern crate wayland_protocols; +pub extern crate wayland_server; extern crate wayland_sys; extern crate xkbcommon; #[cfg(feature = "dbus")] -extern crate dbus; +pub extern crate dbus; #[cfg(feature = "backend_drm")] -extern crate drm; +pub extern crate drm; #[cfg(feature = "backend_drm")] -extern crate gbm; +pub extern crate gbm; #[cfg(feature = "backend_libinput")] -extern crate input; +pub extern crate input; #[cfg(feature = "backend_session_logind")] -extern crate systemd; +pub extern crate systemd; #[cfg(feature = "udev")] -extern crate udev; +pub extern crate udev; #[cfg(feature = "backend_winit")] extern crate wayland_client; #[cfg(feature = "backend_winit")] diff --git a/src/wayland/seat/mod.rs b/src/wayland/seat/mod.rs index 9684636..35ceb58 100644 --- a/src/wayland/seat/mod.rs +++ b/src/wayland/seat/mod.rs @@ -59,7 +59,7 @@ use std::sync::{Arc, Mutex}; mod keyboard; mod pointer; -pub use self::keyboard::{Error as KeyboardError, KeyboardHandle, ModifiersState}; +pub use self::keyboard::{Error as KeyboardError, KeyboardHandle, ModifiersState, Keysym, keysyms}; pub use self::pointer::{PointerAxisHandle, PointerHandle}; use wayland_server::{Display, Global, LoopToken, NewResource, Resource}; use wayland_server::protocol::wl_seat; From 23faeae20f9623310f92ad8854d6371b92761af5 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Mon, 7 May 2018 19:56:38 +0200 Subject: [PATCH 2/6] move examples into our own compositor: anvil --- Cargo.toml | 3 + anvil/Cargo.toml | 30 ++ {examples => anvil}/resources/cursor.rgba | Bin {examples => anvil}/resources/cursor2.rgba | Bin .../glium.rs => anvil/src/glium_drawer.rs | 4 +- anvil/src/main.rs | 50 ++++ .../implementations.rs => anvil/src/shell.rs | 178 ++++++------ {examples => anvil/src}/udev.rs | 134 ++++----- {examples/helpers => anvil/src}/window_map.rs | 4 +- {examples => anvil/src}/winit.rs | 103 +++---- examples/drm.rs | 256 ------------------ examples/helpers/mod.rs | 7 - 12 files changed, 276 insertions(+), 493 deletions(-) create mode 100644 anvil/Cargo.toml rename {examples => anvil}/resources/cursor.rgba (100%) rename {examples => anvil}/resources/cursor2.rgba (100%) rename examples/helpers/glium.rs => anvil/src/glium_drawer.rs (99%) create mode 100644 anvil/src/main.rs rename examples/helpers/implementations.rs => anvil/src/shell.rs (97%) rename {examples => anvil/src}/udev.rs (89%) rename {examples/helpers => anvil/src}/window_map.rs (98%) rename {examples => anvil/src}/winit.rs (84%) delete mode 100644 examples/drm.rs delete mode 100644 examples/helpers/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 93f6b2a..e1f1619 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,9 @@ license = "MIT" description = "Smithay is a library for writing wayland compositors." repository = "https://github.com/Smithay/smithay" +[workspace] +members = [ "anvil" ] + [dependencies] wayland-server = "0.20.2" wayland-sys = "0.20.2" diff --git a/anvil/Cargo.toml b/anvil/Cargo.toml new file mode 100644 index 0000000..72dbc4b --- /dev/null +++ b/anvil/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "anvil" +version = "0.0.1" +authors = ["Victor Berger ", "Drakulix (Victor Brekenfeld)"] +license = "MIT" +publish = false + +[dependencies] +slog = { version = "2.1.1" } +slog-term = "2.3" +slog-async = "2.2" +rand = "0.3" +glium = { version = "0.19.0", default-features = false } +wayland-server = "0.20" +xkbcommon = "0.2.1" + +[dependencies.smithay] +path = ".." +default-features = false +features = [ "renderer_glium" ] + +[build-dependencies] +gl_generator = "0.9" + +[features] +default = [ "winit", "tty_launch" ] +winit = [ "smithay/backend_winit" ] +tty_launch = [ "smithay/backend_udev", "smithay/backend_libinput", "smithay/backend_drm" ] +logind = [ "smithay/backend_session_logind" ] + diff --git a/examples/resources/cursor.rgba b/anvil/resources/cursor.rgba similarity index 100% rename from examples/resources/cursor.rgba rename to anvil/resources/cursor.rgba diff --git a/examples/resources/cursor2.rgba b/anvil/resources/cursor2.rgba similarity index 100% rename from examples/resources/cursor2.rgba rename to anvil/resources/cursor2.rgba diff --git a/examples/helpers/glium.rs b/anvil/src/glium_drawer.rs similarity index 99% rename from examples/helpers/glium.rs rename to anvil/src/glium_drawer.rs index ecb2ec2..201ff8d 100644 --- a/examples/helpers/glium.rs +++ b/anvil/src/glium_drawer.rs @@ -6,9 +6,9 @@ use smithay::backend::graphics::egl::EGLGraphicsBackend; use smithay::backend::graphics::egl::error::Result as EGLResult; use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages, EGLWaylandExtensions, Format}; use smithay::backend::graphics::glium::GliumGraphicsBackend; +use smithay::wayland_server::Display; + use std::cell::Ref; -use std::ops::Deref; -use wayland_server::Display; #[derive(Copy, Clone)] struct Vertex { diff --git a/anvil/src/main.rs b/anvil/src/main.rs new file mode 100644 index 0000000..6bfddfb --- /dev/null +++ b/anvil/src/main.rs @@ -0,0 +1,50 @@ +#[macro_use] +extern crate glium; +extern crate rand; +#[macro_use] +extern crate slog; +extern crate slog_async; +extern crate slog_term; +#[macro_use(define_roles)] +extern crate smithay; +extern crate xkbcommon; + + +use slog::Drain; +use smithay::wayland_server::Display; + +mod glium_drawer; +mod shell; +#[cfg(feature = "tty_launch")] +mod udev; +mod window_map; +#[cfg(feature = "winit")] +mod winit; + +fn main() { + // A logger facility, here we use the terminal here + let log = slog::Logger::root( + slog_async::Async::default(slog_term::term_full().fuse()).fuse(), + o!(), + ); + + let (mut display, mut event_loop) = Display::new(); + + #[cfg(feature = "winit")] + { + if let Ok(()) = winit::run_winit(&mut display, &mut event_loop, log.clone()) { + return; + } + warn!(log, "Failed to initialize winit backend, skipping."); + } + + #[cfg(feature = "tty_launch")] + { + if let Ok(()) = udev::run_udev(display, event_loop, log.clone()) { + return; + } + warn!(log, "Failed to initialize udev backend, skipping."); + } + + error!(log, "Failed to initialize any backend."); +} diff --git a/examples/helpers/implementations.rs b/anvil/src/shell.rs similarity index 97% rename from examples/helpers/implementations.rs rename to anvil/src/shell.rs index d494bb9..811f297 100644 --- a/examples/helpers/implementations.rs +++ b/anvil/src/shell.rs @@ -1,6 +1,11 @@ -use super::{SurfaceKind, WindowMap}; +use std::cell::RefCell; +use std::rc::Rc; +use std::sync::{Arc, Mutex}; + use glium::texture::Texture2d; + use rand; + use smithay::backend::graphics::egl::wayland::{BufferAccessError, Format}; use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages}; use smithay::wayland::compositor::{compositor_init, CompositorToken, SurfaceAttributes, SurfaceEvent}; @@ -9,95 +14,13 @@ use smithay::wayland::shell::xdg::{xdg_shell_init, PopupConfigure, ShellState as use smithay::wayland::shell::legacy::{wl_shell_init, ShellRequest, ShellState as WlShellState, ShellSurfaceKind, ShellSurfaceRole}; use smithay::wayland::shm::with_buffer_contents as shm_buffer_contents; -use std::cell::RefCell; -use std::rc::Rc; -use std::sync::{Arc, Mutex}; -use wayland_server::{Display, LoopToken, Resource}; -use wayland_server::protocol::{wl_buffer, wl_callback, wl_shell_surface, wl_surface}; +use smithay::wayland_server::{Display, LoopToken, Resource}; +use smithay::wayland_server::protocol::{wl_buffer, wl_callback, wl_shell_surface, wl_surface}; + +use window_map::{Kind as SurfaceKind, WindowMap}; define_roles!(Roles => [ XdgSurface, XdgSurfaceRole ] [ ShellSurface, ShellSurfaceRole<()>] ); -#[derive(Default)] -pub struct SurfaceData { - pub buffer: Option, - pub texture: Option, -} - -pub enum Buffer { - Egl { images: EGLImages }, - Shm { data: Vec, size: (u32, u32) }, -} - -fn surface_commit( - surface: &Resource, - token: CompositorToken, - display: &RefCell>, -) { - // we retrieve the contents of the associated buffer and copy it - token.with_surface_data(surface, |attributes| { - match attributes.buffer.take() { - Some(Some((buffer, (_x, _y)))) => { - // we ignore hotspot coordinates in this simple example - match if let Some(display) = display.borrow().as_ref() { - display.egl_buffer_contents(buffer) - } else { - Err(BufferAccessError::NotManaged(buffer)) - } { - Ok(images) => { - match images.format { - Format::RGB => {} - Format::RGBA => {} - _ => { - // we don't handle the more complex formats here. - attributes.user_data.buffer = None; - attributes.user_data.texture = None; - return; - } - }; - attributes.user_data.texture = None; - attributes.user_data.buffer = Some(Buffer::Egl { images }); - } - Err(BufferAccessError::NotManaged(buffer)) => { - shm_buffer_contents(&buffer, |slice, data| { - let offset = data.offset as usize; - let stride = data.stride as usize; - let width = data.width as usize; - let height = data.height as usize; - let mut new_vec = Vec::with_capacity(width * height * 4); - for i in 0..height { - new_vec - .extend(&slice[(offset + i * stride)..(offset + i * stride + width * 4)]); - } - attributes.user_data.texture = None; - attributes.user_data.buffer = Some(Buffer::Shm { data: new_vec, size: (data.width as u32, data.height as u32) }); - }).expect("Got EGL buffer with no set EGLDisplay. You need to unbind your EGLContexts before dropping them!"); - buffer.send(wl_buffer::Event::Release); - } - Err(err) => panic!("EGL error: {}", err), - } - } - Some(None) => { - // erase the contents - attributes.user_data.buffer = None; - attributes.user_data.texture = None; - } - None => {} - } - }); -} - -fn get_size(attrs: &SurfaceAttributes) -> Option<(i32, i32)> { - attrs - .user_data - .buffer - .as_ref() - .map(|ref buffer| match **buffer { - Buffer::Shm { ref size, .. } => *size, - Buffer::Egl { ref images } => (images.width, images.height), - }) - .map(|(x, y)| (x as i32, y as i32)) -} - pub type MyWindowMap = WindowMap) -> Option<(i32, i32)>>; @@ -199,3 +122,84 @@ pub fn init_shell( window_map, ) } + +#[derive(Default)] +pub struct SurfaceData { + pub buffer: Option, + pub texture: Option, +} + +pub enum Buffer { + Egl { images: EGLImages }, + Shm { data: Vec, size: (u32, u32) }, +} + +fn surface_commit( + surface: &Resource, + token: CompositorToken, + display: &RefCell>, +) { + // we retrieve the contents of the associated buffer and copy it + token.with_surface_data(surface, |attributes| { + match attributes.buffer.take() { + Some(Some((buffer, (_x, _y)))) => { + // we ignore hotspot coordinates in this simple example + match if let Some(display) = display.borrow().as_ref() { + display.egl_buffer_contents(buffer) + } else { + Err(BufferAccessError::NotManaged(buffer)) + } { + Ok(images) => { + match images.format { + Format::RGB => {} + Format::RGBA => {} + _ => { + // we don't handle the more complex formats here. + attributes.user_data.buffer = None; + attributes.user_data.texture = None; + return; + } + }; + attributes.user_data.texture = None; + attributes.user_data.buffer = Some(Buffer::Egl { images }); + } + Err(BufferAccessError::NotManaged(buffer)) => { + shm_buffer_contents(&buffer, |slice, data| { + let offset = data.offset as usize; + let stride = data.stride as usize; + let width = data.width as usize; + let height = data.height as usize; + let mut new_vec = Vec::with_capacity(width * height * 4); + for i in 0..height { + new_vec + .extend(&slice[(offset + i * stride)..(offset + i * stride + width * 4)]); + } + attributes.user_data.texture = None; + attributes.user_data.buffer = Some(Buffer::Shm { data: new_vec, size: (data.width as u32, data.height as u32) }); + }).expect("Got EGL buffer with no set EGLDisplay. You need to unbind your EGLContexts before dropping them!"); + buffer.send(wl_buffer::Event::Release); + } + Err(err) => panic!("EGL error: {}", err), + } + } + Some(None) => { + // erase the contents + attributes.user_data.buffer = None; + attributes.user_data.texture = None; + } + None => {} + } + }); +} + +fn get_size(attrs: &SurfaceAttributes) -> Option<(i32, i32)> { + attrs + .user_data + .buffer + .as_ref() + .map(|ref buffer| match **buffer { + Buffer::Shm { ref size, .. } => *size, + Buffer::Egl { ref images } => (images.width, images.height), + }) + .map(|(x, y)| (x as i32, y as i32)) +} diff --git a/examples/udev.rs b/anvil/src/udev.rs similarity index 89% rename from examples/udev.rs rename to anvil/src/udev.rs index 36adbaa..3a8cdef 100644 --- a/examples/udev.rs +++ b/anvil/src/udev.rs @@ -1,33 +1,24 @@ -extern crate drm; -#[macro_use] -extern crate glium; -extern crate image; -extern crate input as libinput; -extern crate rand; -#[macro_use(define_roles)] -extern crate smithay; -extern crate udev; -extern crate wayland_server; -extern crate xkbcommon; +use std::cell::RefCell; +use std::collections::HashMap; +use std::io::Error as IoError; +use std::path::PathBuf; +use std::process::Command; +use std::rc::Rc; +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::time::Duration; -#[macro_use] -extern crate slog; -extern crate slog_async; -extern crate slog_term; - -mod helpers; - -use drm::control::{Device as ControlDevice, ResourceInfo}; -use drm::control::connector::{Info as ConnectorInfo, State as ConnectorState}; -use drm::control::crtc; -use drm::control::encoder::Info as EncoderInfo; -use drm::result::Error as DrmError; use glium::{Blend, Surface}; -use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap, Roles, SurfaceData}; -use image::{ImageBuffer, Rgba}; -use libinput::{event, Device as LibinputDevice, Libinput}; -use libinput::event::keyboard::KeyboardEventTrait; -use slog::{Drain, Logger}; + +use smithay::image::{ImageBuffer, Rgba}; + +use slog::Logger; + +use smithay::drm::control::{Device as ControlDevice, ResourceInfo}; +use smithay::drm::control::connector::{Info as ConnectorInfo, State as ConnectorState}; +use smithay::drm::control::crtc; +use smithay::drm::control::encoder::Info as EncoderInfo; +use smithay::drm::result::Error as DrmError; use smithay::backend::drm::{DevPath, DrmBackend, DrmDevice, DrmHandler}; use smithay::backend::graphics::GraphicsBackend; use smithay::backend::graphics::egl::EGLGraphicsBackend; @@ -41,22 +32,16 @@ use smithay::backend::udev::{primary_gpu, udev_backend_bind, SessionFdDrmDevice, use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction}; use smithay::wayland::compositor::roles::Role; use smithay::wayland::output::{Mode, Output, PhysicalProperties}; -use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat}; +use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat, keysyms as xkb}; use smithay::wayland::shm::init_shm_global; -use std::cell::RefCell; -use std::collections::HashMap; -use std::env; -use std::io::Error as IoError; -use std::path::PathBuf; -use std::process::Command; -use std::rc::Rc; -use std::sync::Arc; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::time::Duration; -use wayland_server::Display; -use wayland_server::commons::downcast_impl; -use wayland_server::protocol::{wl_output, wl_pointer}; -use xkbcommon::xkb::keysyms as xkb; +use smithay::wayland_server::{Display, EventLoop}; +use smithay::wayland_server::commons::downcast_impl; +use smithay::wayland_server::protocol::{wl_output, wl_pointer}; +use smithay::input::{event, Device as LibinputDevice, Libinput}; +use smithay::input::event::keyboard::KeyboardEventTrait; + +use glium_drawer::GliumDrawer; +use shell::{init_shell, MyWindowMap, Buffer, Roles, SurfaceData}; struct LibinputInputHandler { log: Logger, @@ -101,7 +86,11 @@ impl InputHandler for LibinputInputHandler { let time = Event::time(&evt); self.keyboard .input(keycode, state, serial, time, move |modifiers, keysym| { - debug!(log, "keysym"; "state" => format!("{:?}", state), "mods" => format!("{:?}", modifiers), "keysym" => xkbcommon::xkb::keysym_get_name(keysym)); + debug!(log, "keysym"; + "state" => format!("{:?}", state), + "mods" => format!("{:?}", modifiers), + "keysym" => ::xkbcommon::xkb::keysym_get_name(keysym) + ); if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace && state == KeyState::Pressed { @@ -179,10 +168,10 @@ impl InputHandler for LibinputInputHandler { } fn on_pointer_axis(&mut self, _: &input::Seat, evt: event::pointer::PointerAxisEvent) { let source = match evt.source() { - input::AxisSource::Continuous => wayland_server::protocol::wl_pointer::AxisSource::Continuous, - input::AxisSource::Finger => wayland_server::protocol::wl_pointer::AxisSource::Finger, + input::AxisSource::Continuous => wl_pointer::AxisSource::Continuous, + input::AxisSource::Finger => wl_pointer::AxisSource::Finger, input::AxisSource::Wheel | input::AxisSource::WheelTilt => { - wayland_server::protocol::wl_pointer::AxisSource::Wheel + wl_pointer::AxisSource::Wheel } }; let horizontal_amount = evt.amount(&input::Axis::Horizontal) @@ -197,37 +186,37 @@ impl InputHandler for LibinputInputHandler { event.source(source); if horizontal_amount != 0.0 { event.value( - wayland_server::protocol::wl_pointer::Axis::HorizontalScroll, + wl_pointer::Axis::HorizontalScroll, horizontal_amount, evt.time(), ); if let Some(discrete) = horizontal_amount_discrete { event.discrete( - wayland_server::protocol::wl_pointer::Axis::HorizontalScroll, + wl_pointer::Axis::HorizontalScroll, discrete as i32, ); } - } else if source == wayland_server::protocol::wl_pointer::AxisSource::Finger { + } else if source == wl_pointer::AxisSource::Finger { event.stop( - wayland_server::protocol::wl_pointer::Axis::HorizontalScroll, + wl_pointer::Axis::HorizontalScroll, evt.time(), ); } if vertical_amount != 0.0 { event.value( - wayland_server::protocol::wl_pointer::Axis::VerticalScroll, + wl_pointer::Axis::VerticalScroll, vertical_amount, evt.time(), ); if let Some(discrete) = vertical_amount_discrete { event.discrete( - wayland_server::protocol::wl_pointer::Axis::VerticalScroll, + wl_pointer::Axis::VerticalScroll, discrete as i32, ); } - } else if source == wayland_server::protocol::wl_pointer::AxisSource::Finger { + } else if source == wl_pointer::AxisSource::Finger { event.stop( - wayland_server::protocol::wl_pointer::Axis::VerticalScroll, + wl_pointer::Axis::VerticalScroll, evt.time(), ); } @@ -254,26 +243,14 @@ impl InputHandler for LibinputInputHandler { } } -fn main() { +pub fn run_udev(mut display: Display, mut event_loop: EventLoop, log: Logger) -> Result<(),()> { + + let name = display.add_socket_auto().unwrap().into_string().unwrap(); + info!(log, "Listening on wayland socket"; "name" => name.clone()); + ::std::env::set_var("WAYLAND_DISPLAY", name); + let active_egl_context = Rc::new(RefCell::new(None)); - // A logger facility, here we use the terminal for this example - let log = Logger::root( - slog_term::FullFormat::new(slog_term::PlainSyncDecorator::new(std::io::stdout())) - .build() - .fuse(), - o!(), - ); - - // Initialize the wayland server - let (mut display, mut event_loop) = wayland_server::Display::new(); - - /* - * Add a listening socket - */ - let name = display.add_socket_auto().unwrap().into_string().unwrap(); - println!("Listening on socket: {}", name); - env::set_var("WAYLAND_DISPLAY", name); let display = Rc::new(RefCell::new(display)); /* @@ -296,7 +273,7 @@ fn main() { /* * Initialize session */ - let (session, mut notifier) = AutoSession::new(log.clone()).unwrap(); + let (session, mut notifier) = AutoSession::new(log.clone()).ok_or(())?; let running = Arc::new(AtomicBool::new(true)); @@ -305,12 +282,12 @@ fn main() { /* * Initialize the udev backend */ - let context = udev::Context::new().unwrap(); + let context = ::smithay::udev::Context::new().map_err(|_| ())?; let seat = session.seat(); let primary_gpu = primary_gpu(&context, &seat).unwrap_or_default(); - let bytes = include_bytes!("resources/cursor2.rgba"); + let bytes = include_bytes!("../resources/cursor2.rgba"); let mut udev_backend = UdevBackend::new( event_loop.token(), &context, @@ -327,7 +304,7 @@ fn main() { logger: log.clone(), }, log.clone(), - ).unwrap(); + ).map_err(|_| ())?; let udev_session_id = notifier.register(&mut udev_backend); @@ -412,8 +389,6 @@ fn main() { } } - println!("Bye Bye"); - let mut notifier = session_event_source.unbind(); notifier.unregister(udev_session_id); notifier.unregister(libinput_session_id); @@ -427,6 +402,7 @@ fn main() { // variable to simplify type inference. udev_backend = *(downcast_impl(udev_event_source.remove()).unwrap_or_else(|_| unreachable!())); udev_backend.close(); + Ok(()) } struct UdevHandlerImpl { diff --git a/examples/helpers/window_map.rs b/anvil/src/window_map.rs similarity index 98% rename from examples/helpers/window_map.rs rename to anvil/src/window_map.rs index af79ca3..e0f6fd3 100644 --- a/examples/helpers/window_map.rs +++ b/anvil/src/window_map.rs @@ -3,8 +3,8 @@ use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, SurfaceAttri use smithay::wayland::compositor::roles::Role; use smithay::wayland::shell::xdg::{ToplevelSurface, XdgSurfaceRole}; use smithay::wayland::shell::legacy::{ShellSurface, ShellSurfaceRole}; -use wayland_server::Resource; -use wayland_server::protocol::wl_surface; +use smithay::wayland_server::Resource; +use smithay::wayland_server::protocol::wl_surface; pub enum Kind { Xdg(ToplevelSurface), diff --git a/examples/winit.rs b/anvil/src/winit.rs similarity index 84% rename from examples/winit.rs rename to anvil/src/winit.rs index a680b8d..73fd298 100644 --- a/examples/winit.rs +++ b/anvil/src/winit.rs @@ -1,33 +1,25 @@ -#[macro_use] -extern crate glium; -extern crate rand; -#[macro_use] -extern crate slog; -extern crate slog_async; -extern crate slog_term; -#[macro_use(define_roles)] -extern crate smithay; -extern crate wayland_server; +use std::cell::RefCell; +use std::rc::Rc; -mod helpers; - -use glium::Surface; -use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap}; -use slog::{Drain, Logger}; -use smithay::backend::graphics::egl::EGLGraphicsBackend; -use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format}; -use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyboardKeyEvent, PointerAxisEvent, - PointerButtonEvent, PointerMotionAbsoluteEvent}; -use smithay::backend::winit; +use smithay::wayland::shm::init_shm_global; +use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat}; use smithay::wayland::compositor::{SubsurfaceRole, TraversalAction}; use smithay::wayland::compositor::roles::Role; use smithay::wayland::output::{Mode, Output, PhysicalProperties}; -use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat}; -use smithay::wayland::shm::init_shm_global; -use std::cell::RefCell; -use std::rc::Rc; -use wayland_server::Display; -use wayland_server::protocol::{wl_output, wl_pointer}; +use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyboardKeyEvent, PointerAxisEvent, + PointerButtonEvent, PointerMotionAbsoluteEvent}; +use smithay::backend::winit; +use smithay::backend::graphics::egl::EGLGraphicsBackend; +use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format}; +use smithay::wayland_server::{Display, EventLoop}; +use smithay::wayland_server::protocol::{wl_pointer, wl_output}; + +use glium::Surface; + +use slog::Logger; + +use glium_drawer::GliumDrawer; +use shell::{init_shell, MyWindowMap, Buffer}; struct WinitInputHandler { log: Logger, @@ -102,8 +94,8 @@ impl InputHandler for WinitInputHandler { } fn on_pointer_axis(&mut self, _: &input::Seat, evt: winit::WinitMouseWheelEvent) { let source = match evt.source() { - input::AxisSource::Continuous => wayland_server::protocol::wl_pointer::AxisSource::Continuous, - input::AxisSource::Wheel => wayland_server::protocol::wl_pointer::AxisSource::Wheel, + input::AxisSource::Continuous => wl_pointer::AxisSource::Continuous, + input::AxisSource::Wheel => wl_pointer::AxisSource::Wheel, _ => unreachable!(), //winit does not have more specific sources }; let horizontal_amount = evt.amount(&input::Axis::Horizontal) @@ -118,26 +110,26 @@ impl InputHandler for WinitInputHandler { event.source(source); if horizontal_amount != 0.0 { event.value( - wayland_server::protocol::wl_pointer::Axis::HorizontalScroll, + wl_pointer::Axis::HorizontalScroll, horizontal_amount, evt.time(), ); if let Some(discrete) = horizontal_amount_discrete { event.discrete( - wayland_server::protocol::wl_pointer::Axis::HorizontalScroll, + wl_pointer::Axis::HorizontalScroll, discrete as i32, ); } } if vertical_amount != 0.0 { event.value( - wayland_server::protocol::wl_pointer::Axis::VerticalScroll, + wl_pointer::Axis::VerticalScroll, vertical_amount, evt.time(), ); if let Some(discrete) = vertical_amount_discrete { event.discrete( - wayland_server::protocol::wl_pointer::Axis::VerticalScroll, + wl_pointer::Axis::VerticalScroll, discrete as i32, ); } @@ -165,17 +157,8 @@ impl InputHandler for WinitInputHandler { } } -fn main() { - // A logger facility, here we use the terminal for this example - let log = Logger::root( - slog_async::Async::default(slog_term::term_full().fuse()).fuse(), - o!(), - ); - - // Initialize a simple backend for testing - let (renderer, mut input) = winit::init(log.clone()).unwrap(); - - let (mut display, mut event_loop) = wayland_server::Display::new(); +pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger) -> Result<(), ()> { + let (renderer, mut input) = winit::init(log.clone()).map_err(|_| ())?; let egl_display = Rc::new(RefCell::new( if let Ok(egl_display) = renderer.bind_wl_display(&display) { @@ -189,17 +172,21 @@ fn main() { let (w, h) = renderer.get_framebuffer_dimensions(); let drawer = GliumDrawer::from(renderer); + let name = display.add_socket_auto().unwrap().into_string().unwrap(); + info!(log, "Listening on wayland socket"; "name" => name.clone()); + ::std::env::set_var("WAYLAND_DISPLAY", name); + /* * Initialize the globals */ - init_shm_global(&mut display, event_loop.token(), vec![], log.clone()); + init_shm_global(display, event_loop.token(), vec![], log.clone()); let (compositor_token, _, _, window_map) = - init_shell(&mut display, event_loop.token(), log.clone(), egl_display); + init_shell(display, event_loop.token(), log.clone(), egl_display); let (mut seat, _) = Seat::new( - &mut display, + display, event_loop.token(), "winit".into(), log.clone(), @@ -210,7 +197,7 @@ fn main() { .expect("Failed to initialize the keyboard"); let (output, _) = Output::new( - &mut display, + display, event_loop.token(), "Winit".into(), PhysicalProperties { @@ -247,11 +234,7 @@ fn main() { serial: 0, }); - /* - * Add a listening socket: - */ - let name = display.add_socket_auto().unwrap().into_string().unwrap(); - println!("Listening on socket: {}", name); + info!(log, "Initialization completed, starting the main loop."); loop { input.dispatch_new_events().unwrap(); @@ -317,16 +300,16 @@ fn main() { }, (x, y), screen_dimensions, - glium::Blend { - color: glium::BlendingFunction::Addition { - source: glium::LinearBlendingFactor::One, + ::glium::Blend { + color: ::glium::BlendingFunction::Addition { + source: ::glium::LinearBlendingFactor::One, destination: - glium::LinearBlendingFactor::OneMinusSourceAlpha, + ::glium::LinearBlendingFactor::OneMinusSourceAlpha, }, - alpha: glium::BlendingFunction::Addition { - source: glium::LinearBlendingFactor::One, + alpha: ::glium::BlendingFunction::Addition { + source: ::glium::LinearBlendingFactor::One, destination: - glium::LinearBlendingFactor::OneMinusSourceAlpha, + ::glium::LinearBlendingFactor::OneMinusSourceAlpha, }, ..Default::default() }, @@ -349,4 +332,4 @@ fn main() { window_map.borrow_mut().refresh(); } -} +} \ No newline at end of file diff --git a/examples/drm.rs b/examples/drm.rs deleted file mode 100644 index 7993c72..0000000 --- a/examples/drm.rs +++ /dev/null @@ -1,256 +0,0 @@ -extern crate drm; -#[macro_use] -extern crate glium; -extern crate rand; -#[macro_use(define_roles)] -extern crate smithay; -extern crate wayland_server; - -#[macro_use] -extern crate slog; -extern crate slog_async; -extern crate slog_term; - -mod helpers; - -use drm::Device as BasicDevice; -use drm::control::{Device as ControlDevice, ResourceInfo}; -use drm::control::connector::{Info as ConnectorInfo, State as ConnectorState}; -use drm::control::crtc; -use drm::control::encoder::Info as EncoderInfo; -use drm::result::Error as DrmError; -use glium::{Blend, Surface}; -use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap, Roles, SurfaceData}; -use slog::{Drain, Logger}; -use smithay::backend::drm::{drm_device_bind, DrmBackend, DrmDevice, DrmHandler}; -use smithay::backend::graphics::egl::EGLGraphicsBackend; -use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions, Format}; -use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction}; -use smithay::wayland::compositor::roles::Role; -use smithay::wayland::shm::init_shm_global; -use std::cell::RefCell; -use std::fs::{File, OpenOptions}; -use std::os::unix::io::AsRawFd; -use std::os::unix::io::RawFd; -use std::rc::Rc; -use std::time::Duration; - -#[derive(Debug)] -pub struct Card(File); - -impl AsRawFd for Card { - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } -} - -impl BasicDevice for Card {} -impl ControlDevice for Card {} - -fn main() { - // A logger facility, here we use the terminal for this example - let log = Logger::root( - slog_async::Async::default(slog_term::term_full().fuse()).fuse(), - o!(), - ); - - // Initialize the wayland server - let (mut display, mut event_loop) = wayland_server::Display::new(); - - /* - * Initialize the drm backend - */ - // "Find" a suitable drm device - let mut options = OpenOptions::new(); - options.read(true); - options.write(true); - let mut device = DrmDevice::new( - Card(options.clone().open("/dev/dri/card0").unwrap()), - log.clone(), - ).unwrap(); - - // Get a set of all modesetting resource handles (excluding planes): - let res_handles = device.resource_handles().unwrap(); - - // Use first connected connector - let connector_info = res_handles - .connectors() - .iter() - .map(|conn| ConnectorInfo::load_from_device(&device, *conn).unwrap()) - .find(|conn| conn.connection_state() == ConnectorState::Connected) - .unwrap(); - - // Use the first encoder - let encoder_info = EncoderInfo::load_from_device(&device, connector_info.encoders()[0]).unwrap(); - - // use the connected crtc if any - let crtc = encoder_info.current_crtc() - // or use the first one that is compatible with the encoder - .unwrap_or_else(|| - *res_handles.filter_crtcs(encoder_info.possible_crtcs()) - .iter() - .next() - .unwrap()); - - // Assuming we found a good connector and loaded the info into `connector_info` - let mode = connector_info.modes()[0]; // Use first mode (usually highest resoltion, but in reality you should filter and sort and check and match with other connectors, if you use more then one.) - - // Initialize the hardware backend - let renderer = GliumDrawer::from( - device - .create_backend(crtc, mode, vec![connector_info.handle()]) - .unwrap(), - ); - { - /* - * Initialize glium - */ - let mut frame = renderer.draw(); - frame.clear_color(0.8, 0.8, 0.9, 1.0); - frame.finish().unwrap(); - } - - let egl_display = Rc::new(RefCell::new( - if let Ok(egl_display) = renderer.bind_wl_display(&display) { - info!(log, "EGL hardware-acceleration enabled"); - Some(egl_display) - } else { - None - }, - )); - - /* - * Initialize the globals - */ - - init_shm_global(&mut display, event_loop.token(), vec![], log.clone()); - - let (compositor_token, _, _, window_map) = - init_shell(&mut display, event_loop.token(), log.clone(), egl_display); - - /* - * Add a listening socket: - */ - let name = display.add_socket_auto().unwrap().into_string().unwrap(); - println!("Listening on socket: {}", name); - - /* - * Register the DrmDevice on the EventLoop - */ - let _source = drm_device_bind( - &event_loop.token(), - device, - DrmHandlerImpl { - compositor_token, - window_map: window_map.clone(), - drawer: renderer, - logger: log, - }, - ).map_err(|(err, _)| err) - .unwrap(); - - loop { - event_loop.dispatch(Some(16)).unwrap(); - display.flush_clients(); - - window_map.borrow_mut().refresh(); - } -} - -pub struct DrmHandlerImpl { - compositor_token: CompositorToken, - window_map: Rc>, - drawer: GliumDrawer>, - logger: ::slog::Logger, -} - -impl DrmHandler for DrmHandlerImpl { - fn ready( - &mut self, - _device: &mut DrmDevice, - _crtc: crtc::Handle, - _frame: u32, - _duration: Duration, - ) { - let mut frame = self.drawer.draw(); - frame.clear_color(0.8, 0.8, 0.9, 1.0); - // redraw the frame, in a simple but inneficient way - { - let screen_dimensions = self.drawer.borrow().get_framebuffer_dimensions(); - self.window_map - .borrow() - .with_windows_from_bottom_to_top(|toplevel_surface, initial_place| { - if let Some(wl_surface) = toplevel_surface.get_surface() { - // this surface is a root of a subsurface tree that needs to be drawn - self.compositor_token - .with_surface_tree_upward( - wl_surface, - initial_place, - |_surface, attributes, role, &(mut x, mut y)| { - // there is actually something to draw ! - if attributes.user_data.texture.is_none() { - let mut remove = false; - match attributes.user_data.buffer { - Some(Buffer::Egl { ref images }) => { - match images.format { - Format::RGB | Format::RGBA => { - attributes.user_data.texture = - self.drawer.texture_from_egl(&images); - } - _ => { - // we don't handle the more complex formats here. - attributes.user_data.texture = None; - remove = true; - } - }; - } - Some(Buffer::Shm { ref data, ref size }) => { - attributes.user_data.texture = - Some(self.drawer.texture_from_mem(data, *size)); - } - _ => {} - } - if remove { - attributes.user_data.buffer = None; - } - } - - if let Some(ref texture) = attributes.user_data.texture { - if let Ok(subdata) = Role::::data(role) { - x += subdata.location.0; - y += subdata.location.1; - } - info!(self.logger, "Render window"); - self.drawer.render_texture( - &mut frame, - texture, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => images.y_inverted, - Buffer::Shm { .. } => false, - }, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => (images.width, images.height), - Buffer::Shm { ref size, .. } => *size, - }, - (x, y), - screen_dimensions, - Blend::alpha_blending(), - ); - TraversalAction::DoChildren((x, y)) - } else { - // we are not display, so our children are neither - TraversalAction::SkipChildren - } - }, - ) - .unwrap(); - } - }); - } - frame.finish().unwrap(); - } - - fn error(&mut self, _device: &mut DrmDevice, error: DrmError) { - panic!("{:?}", error); - } -} diff --git a/examples/helpers/mod.rs b/examples/helpers/mod.rs deleted file mode 100644 index 2747f60..0000000 --- a/examples/helpers/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod glium; -mod implementations; -mod window_map; - -pub use self::glium::GliumDrawer; -pub use self::implementations::*; -pub use self::window_map::{Kind as SurfaceKind, WindowMap}; From ae1395fb326f0152d38e856157abbf963053bb83 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Mon, 7 May 2018 20:03:14 +0200 Subject: [PATCH 3/6] anvil: test on travis --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index cd24a90..09a0917 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,6 +47,8 @@ env: - FEATURES="default" # test all features simultaneously - FEATURES="all" + # test our house compositor + - FEATURES="anvil" matrix: include: @@ -85,6 +87,9 @@ script: vagga cargo-$TRAVIS_RUST_VERSION install -f clippy && vagga cargo-$TRAVIS_RUST_VERSION clippy --all-features -- -D warnings ;; + "anvil") + vagga cargo-$TRAVIS_RUST_VERSION test -p anvil --all-features + ;; *) vagga cargo-$TRAVIS_RUST_VERSION test --lib --doc --tests --no-default-features --features "$FEATURES" && vagga cargo-$TRAVIS_RUST_VERSION doc --no-deps --no-default-features --features "$FEATURES" From 6ee6fd689040a8eaaa5570b8104a54baf75bc49c Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Tue, 8 May 2018 12:47:09 +0200 Subject: [PATCH 4/6] anvil: factor the input backend code --- anvil/src/input_handler.rs | 321 +++++++++++++++++++++++++++++++++++++ anvil/src/main.rs | 45 ++++-- anvil/src/udev.rs | 232 ++------------------------- anvil/src/winit.rs | 172 +++----------------- src/wayland/seat/mod.rs | 2 +- 5 files changed, 384 insertions(+), 388 deletions(-) create mode 100644 anvil/src/input_handler.rs diff --git a/anvil/src/input_handler.rs b/anvil/src/input_handler.rs new file mode 100644 index 0000000..e52cafe --- /dev/null +++ b/anvil/src/input_handler.rs @@ -0,0 +1,321 @@ +use std::cell::RefCell; +use std::process::Command; +use std::rc::Rc; +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; + +use slog::Logger; + +#[cfg(feature = "tty_launch")] +use smithay::backend::session::auto::AutoSession; +use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyState, KeyboardKeyEvent, + PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, + PointerMotionEvent}; +use smithay::wayland::seat::{keysyms as xkb, KeyboardHandle, Keysym, ModifiersState, PointerHandle}; +use smithay::wayland_server::protocol::wl_pointer; + +use shell::MyWindowMap; + +pub struct AnvilInputHandler { + log: Logger, + pointer: PointerHandle, + keyboard: KeyboardHandle, + window_map: Rc>, + pointer_location: Rc>, + screen_size: (u32, u32), + serial: u32, + #[cfg(feature = "tty_launch")] + session: Option, + running: Arc, +} + +impl AnvilInputHandler { + pub fn new( + log: Logger, + pointer: PointerHandle, + keyboard: KeyboardHandle, + window_map: Rc>, + screen_size: (u32, u32), + running: Arc, + pointer_location: Rc>, + ) -> AnvilInputHandler { + AnvilInputHandler { + log, + pointer, + keyboard, + window_map, + screen_size, + running, + pointer_location, + serial: 1, + #[cfg(feature = "tty_launch")] + session: None, + } + } + + #[cfg(feature = "tty_launch")] + pub fn new_with_session( + log: Logger, + pointer: PointerHandle, + keyboard: KeyboardHandle, + window_map: Rc>, + screen_size: (u32, u32), + running: Arc, + pointer_location: Rc>, + session: AutoSession, + ) -> AnvilInputHandler { + AnvilInputHandler { + log, + pointer, + keyboard, + window_map, + screen_size, + running, + pointer_location, + serial: 1, + session: Some(session), + } + } + + fn next_serial(&mut self) -> u32 { + self.serial += 1; + self.serial + } +} + +impl InputHandler for AnvilInputHandler { + fn on_seat_created(&mut self, _: &input::Seat) { + /* currently we just create a single static one */ + } + + fn on_seat_destroyed(&mut self, _: &input::Seat) { + /* currently we just create a single static one */ + } + + fn on_seat_changed(&mut self, _: &input::Seat) { + /* currently we just create a single static one */ + } + + fn on_keyboard_key(&mut self, _: &input::Seat, evt: B::KeyboardKeyEvent) { + let keycode = evt.key_code(); + let state = evt.state(); + debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state)); + let serial = self.next_serial(); + let log = &self.log; + let time = Event::time(&evt); + let mut action = KeyAction::None; + self.keyboard + .input(keycode, state, serial, time, |modifiers, keysym| { + debug!(log, "keysym"; + "state" => format!("{:?}", state), + "mods" => format!("{:?}", modifiers), + "keysym" => ::xkbcommon::xkb::keysym_get_name(keysym) + ); + action = process_keyboard_shortcut(modifiers, keysym); + // forward to client only if action == KeyAction::Forward + // both for pressed and released, to avoid inconsistencies + if let KeyAction::Forward = action { + true + } else { + false + } + }); + if let KeyState::Released = state { + // only process special actions on key press, not release + return; + } + match action { + KeyAction::Quit => { + info!(self.log, "Quitting."); + self.running.store(false, Ordering::SeqCst); + } + #[cfg(feature = "tty_lauch")] + KeyAction::VtSwitch(vt) => if let Some(ref mut session) = self.session { + info!(log, "Trying to switch to vt {}", vt); + if let Err(err) = session.change_vt(vt) { + error!(log, "Error switching to vt {}: {}", vt, err); + } + }, + KeyAction::Run(cmd) => { + info!(self.log, "Starting program"; "cmd" => cmd.clone()); + if let Err(e) = Command::new(&cmd).spawn() { + error!(log, + "Failed to start program"; + "cmd" => cmd, + "err" => format!("{:?}", e) + ); + } + } + _ => (), + } + } + + fn on_pointer_move(&mut self, _: &input::Seat, evt: B::PointerMotionEvent) { + let (x, y) = (evt.delta_x(), evt.delta_y()); + let serial = self.next_serial(); + let mut location = self.pointer_location.borrow_mut(); + location.0 += x as f64; + location.1 += y as f64; + // clamp to screen limits + // this event is never generated by winit so self.screen_size is relevant + location.0 = (location.0).max(0.0).min(self.screen_size.0 as f64); + location.1 = (location.1).max(0.0).min(self.screen_size.1 as f64); + let under = self.window_map + .borrow() + .get_surface_under((location.0, location.1)); + self.pointer.motion( + under.as_ref().map(|&(ref s, (x, y))| (s, x, y)), + serial, + evt.time(), + ); + } + + fn on_pointer_move_absolute(&mut self, _: &input::Seat, evt: B::PointerMotionAbsoluteEvent) { + // different cases depending on the context: + let (x, y) = { + #[cfg(feature = "tty_launch")] + { + if self.session.is_some() { + // we are started on a tty + let (ux, uy) = evt.position_transformed(self.screen_size); + (ux as f64, uy as f64) + } else { + // we are started in winit + evt.position() + } + } + #[cfg(not(feature = "tty_launch"))] + { + evt.position() + } + }; + *self.pointer_location.borrow_mut() = (x, y); + let serial = self.next_serial(); + let under = self.window_map + .borrow() + .get_surface_under((x as f64, y as f64)); + self.pointer.motion( + under.as_ref().map(|&(ref s, (x, y))| (s, x, y)), + serial, + evt.time(), + ); + } + + fn on_pointer_button(&mut self, _: &input::Seat, evt: B::PointerButtonEvent) { + let serial = self.next_serial(); + let button = match evt.button() { + input::MouseButton::Left => 0x110, + input::MouseButton::Right => 0x111, + input::MouseButton::Middle => 0x112, + input::MouseButton::Other(b) => b as u32, + }; + let state = match evt.state() { + input::MouseButtonState::Pressed => { + // change the keyboard focus + let under = self.window_map + .borrow_mut() + .get_surface_and_bring_to_top(*self.pointer_location.borrow()); + self.keyboard + .set_focus(under.as_ref().map(|&(ref s, _)| s), serial); + wl_pointer::ButtonState::Pressed + } + input::MouseButtonState::Released => wl_pointer::ButtonState::Released, + }; + self.pointer.button(button, state, serial, evt.time()); + } + + fn on_pointer_axis(&mut self, _: &input::Seat, evt: B::PointerAxisEvent) { + let source = match evt.source() { + input::AxisSource::Continuous => wl_pointer::AxisSource::Continuous, + input::AxisSource::Finger => wl_pointer::AxisSource::Finger, + input::AxisSource::Wheel | input::AxisSource::WheelTilt => wl_pointer::AxisSource::Wheel, + }; + let horizontal_amount = evt.amount(&input::Axis::Horizontal) + .unwrap_or_else(|| evt.amount_discrete(&input::Axis::Horizontal).unwrap() * 3.0); + let vertical_amount = evt.amount(&input::Axis::Vertical) + .unwrap_or_else(|| evt.amount_discrete(&input::Axis::Vertical).unwrap() * 3.0); + let horizontal_amount_discrete = evt.amount_discrete(&input::Axis::Horizontal); + let vertical_amount_discrete = evt.amount_discrete(&input::Axis::Vertical); + + { + let mut event = self.pointer.axis(); + event.source(source); + if horizontal_amount != 0.0 { + event.value( + wl_pointer::Axis::HorizontalScroll, + horizontal_amount, + evt.time(), + ); + if let Some(discrete) = horizontal_amount_discrete { + event.discrete(wl_pointer::Axis::HorizontalScroll, discrete as i32); + } + } else if source == wl_pointer::AxisSource::Finger { + event.stop(wl_pointer::Axis::HorizontalScroll, evt.time()); + } + if vertical_amount != 0.0 { + event.value( + wl_pointer::Axis::VerticalScroll, + vertical_amount, + evt.time(), + ); + if let Some(discrete) = vertical_amount_discrete { + event.discrete(wl_pointer::Axis::VerticalScroll, discrete as i32); + } + } else if source == wl_pointer::AxisSource::Finger { + event.stop(wl_pointer::Axis::VerticalScroll, evt.time()); + } + event.done(); + } + } + + fn on_touch_down(&mut self, _: &input::Seat, _: B::TouchDownEvent) { + /* not done in this example */ + } + fn on_touch_motion(&mut self, _: &input::Seat, _: B::TouchMotionEvent) { + /* not done in this example */ + } + fn on_touch_up(&mut self, _: &input::Seat, _: B::TouchUpEvent) { + /* not done in this example */ + } + fn on_touch_cancel(&mut self, _: &input::Seat, _: B::TouchCancelEvent) { + /* not done in this example */ + } + fn on_touch_frame(&mut self, _: &input::Seat, _: B::TouchFrameEvent) { + /* not done in this example */ + } + fn on_input_config_changed(&mut self, _: &mut B::InputConfig) { + /* not done in this example */ + } +} + +/// Possible results of a keyboard action +enum KeyAction { + /// Quit the compositor + Quit, + /// Trigger a vt-switch + VtSwitch(i32), + /// run a command + Run(String), + /// Forward the key to the client + Forward, + /// Do nothing more + None, +} + +fn process_keyboard_shortcut(modifiers: &ModifiersState, keysym: Keysym) -> KeyAction { + if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace { + // ctrl+alt+backspace = quit + KeyAction::Quit + } else if modifiers.logo && keysym == xkb::KEY_q { + // logo + q = quit + KeyAction::Quit + } else if keysym >= xkb::KEY_XF86Switch_VT_1 && keysym <= xkb::KEY_XF86Switch_VT_12 { + // VTSwicth + KeyAction::VtSwitch((keysym - xkb::KEY_XF86Switch_VT_1 + 1) as i32) + } else if modifiers.logo && keysym == xkb::KEY_Return { + // run terminal + KeyAction::Run("weston-terminal".into()) + } else { + KeyAction::Forward + } +} diff --git a/anvil/src/main.rs b/anvil/src/main.rs index 6bfddfb..1cf5f91 100644 --- a/anvil/src/main.rs +++ b/anvil/src/main.rs @@ -9,7 +9,6 @@ extern crate slog_term; extern crate smithay; extern crate xkbcommon; - use slog::Drain; use smithay::wayland_server::Display; @@ -20,6 +19,14 @@ mod udev; mod window_map; #[cfg(feature = "winit")] mod winit; +mod input_handler; + +static POSSIBLE_BACKENDS: &'static [&'static str] = &[ + #[cfg(feature = "winit")] + "--winit", + #[cfg(feature = "tty_launch")] + "--tty", +]; fn main() { // A logger facility, here we use the terminal here @@ -30,21 +37,29 @@ fn main() { let (mut display, mut event_loop) = Display::new(); - #[cfg(feature = "winit")] - { - if let Ok(()) = winit::run_winit(&mut display, &mut event_loop, log.clone()) { - return; + let arg = ::std::env::args().skip(1).next(); + match arg.as_ref().map(|s| &s[..]) { + #[cfg(feature = "winit")] + Some("--winit") => { + info!(log, "Starting anvil with winit backend"); + if let Err(()) = winit::run_winit(&mut display, &mut event_loop, log.clone()) { + crit!(log, "Failed to initialize winit backend."); + } } - warn!(log, "Failed to initialize winit backend, skipping."); - } - - #[cfg(feature = "tty_launch")] - { - if let Ok(()) = udev::run_udev(display, event_loop, log.clone()) { - return; + #[cfg(feature = "tty_launch")] + Some("--tty") => { + info!(log, "Starting anvil on a tty"); + if let Err(()) = udev::run_udev(display, event_loop, log.clone()) { + crit!(log, "Failed to initialize tty backend."); + } + } + _ => { + println!("USAGE: anvil --backend"); + println!(""); + println!("Possible backends are:"); + for b in POSSIBLE_BACKENDS { + println!("\t{}", b); + } } - warn!(log, "Failed to initialize udev backend, skipping."); } - - error!(log, "Failed to initialize any backend."); } diff --git a/anvil/src/udev.rs b/anvil/src/udev.rs index 3a8cdef..7122e5e 100644 --- a/anvil/src/udev.rs +++ b/anvil/src/udev.rs @@ -2,7 +2,6 @@ use std::cell::RefCell; use std::collections::HashMap; use std::io::Error as IoError; use std::path::PathBuf; -use std::process::Command; use std::rc::Rc; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; @@ -23,8 +22,7 @@ use smithay::backend::drm::{DevPath, DrmBackend, DrmDevice, DrmHandler}; use smithay::backend::graphics::GraphicsBackend; use smithay::backend::graphics::egl::EGLGraphicsBackend; use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions, Format}; -use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyState, KeyboardKeyEvent, - PointerAxisEvent, PointerButtonEvent}; +use smithay::backend::input::InputBackend; use smithay::backend::libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface}; use smithay::backend::session::{Session, SessionNotifier}; use smithay::backend::session::auto::{auto_session_bind, AutoSession}; @@ -32,219 +30,18 @@ use smithay::backend::udev::{primary_gpu, udev_backend_bind, SessionFdDrmDevice, use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction}; use smithay::wayland::compositor::roles::Role; use smithay::wayland::output::{Mode, Output, PhysicalProperties}; -use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat, keysyms as xkb}; +use smithay::wayland::seat::Seat; use smithay::wayland::shm::init_shm_global; use smithay::wayland_server::{Display, EventLoop}; use smithay::wayland_server::commons::downcast_impl; -use smithay::wayland_server::protocol::{wl_output, wl_pointer}; -use smithay::input::{event, Device as LibinputDevice, Libinput}; -use smithay::input::event::keyboard::KeyboardEventTrait; +use smithay::wayland_server::protocol::wl_output; +use smithay::input::Libinput; use glium_drawer::GliumDrawer; -use shell::{init_shell, MyWindowMap, Buffer, Roles, SurfaceData}; - -struct LibinputInputHandler { - log: Logger, - pointer: PointerHandle, - keyboard: KeyboardHandle, - window_map: Rc>, - pointer_location: Rc>, - screen_size: (u32, u32), - serial: u32, - session: AutoSession, - running: Arc, -} - -impl LibinputInputHandler { - fn next_serial(&mut self) -> u32 { - self.serial += 1; - self.serial - } -} - -impl InputHandler for LibinputInputHandler { - fn on_seat_created(&mut self, _: &input::Seat) { - /* we just create a single static one */ - } - fn on_seat_destroyed(&mut self, _: &input::Seat) { - /* we just create a single static one */ - } - fn on_seat_changed(&mut self, _: &input::Seat) { - /* we just create a single static one */ - } - fn on_keyboard_key(&mut self, _: &input::Seat, evt: event::keyboard::KeyboardKeyEvent) { - let keycode = evt.key(); - let state = evt.state(); - debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state)); - let serial = self.next_serial(); - - // we cannot borrow `self` into the closure, because we need self.keyboard. - // but rust does not borrow all fields separately, so we need to do that manually... - let running = &self.running; - let mut session = &mut self.session; - let log = &self.log; - let time = Event::time(&evt); - self.keyboard - .input(keycode, state, serial, time, move |modifiers, keysym| { - debug!(log, "keysym"; - "state" => format!("{:?}", state), - "mods" => format!("{:?}", modifiers), - "keysym" => ::xkbcommon::xkb::keysym_get_name(keysym) - ); - if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace - && state == KeyState::Pressed - { - info!(log, "Stopping example using Ctrl+Alt+Backspace"); - running.store(false, Ordering::SeqCst); - false - } else if modifiers.logo && keysym == xkb::KEY_q { - info!(log, "Stopping example using Logo+Q"); - running.store(false, Ordering::SeqCst); - false - } else if modifiers.ctrl && modifiers.alt && keysym >= xkb::KEY_XF86Switch_VT_1 - && keysym <= xkb::KEY_XF86Switch_VT_12 - && state == KeyState::Pressed - { - let vt = (keysym - xkb::KEY_XF86Switch_VT_1 + 1) as i32; - info!(log, "Trying to switch to vt {}", vt); - if let Err(err) = session.change_vt(vt) { - error!(log, "Error switching to vt {}: {}", vt, err); - } - false - } else if modifiers.logo && keysym == xkb::KEY_Return && state == KeyState::Pressed { - info!(log, "Launching terminal"); - let _ = Command::new("weston-terminal").spawn(); - false - } else { - true - } - }); - } - fn on_pointer_move(&mut self, _: &input::Seat, evt: event::pointer::PointerMotionEvent) { - let (x, y) = (evt.dx(), evt.dy()); - let serial = self.next_serial(); - let mut location = self.pointer_location.borrow_mut(); - location.0 += x; - location.1 += y; - let under = self.window_map - .borrow() - .get_surface_under((location.0, location.1)); - self.pointer.motion( - under.as_ref().map(|&(ref s, (x, y))| (s, x, y)), - serial, - evt.time(), - ); - } - fn on_pointer_move_absolute(&mut self, _: &input::Seat, evt: event::pointer::PointerMotionAbsoluteEvent) { - let (x, y) = ( - evt.absolute_x_transformed(self.screen_size.0), - evt.absolute_y_transformed(self.screen_size.1), - ); - *self.pointer_location.borrow_mut() = (x, y); - let serial = self.next_serial(); - let under = self.window_map.borrow().get_surface_under((x, y)); - self.pointer.motion( - under.as_ref().map(|&(ref s, (x, y))| (s, x, y)), - serial, - evt.time(), - ); - } - fn on_pointer_button(&mut self, _: &input::Seat, evt: event::pointer::PointerButtonEvent) { - let serial = self.next_serial(); - let button = evt.button(); - let state = match evt.state() { - input::MouseButtonState::Pressed => { - // change the keyboard focus - let under = self.window_map - .borrow_mut() - .get_surface_and_bring_to_top(*self.pointer_location.borrow()); - self.keyboard - .set_focus(under.as_ref().map(|&(ref s, _)| s), serial); - wl_pointer::ButtonState::Pressed - } - input::MouseButtonState::Released => wl_pointer::ButtonState::Released, - }; - self.pointer.button(button, state, serial, evt.time()); - } - fn on_pointer_axis(&mut self, _: &input::Seat, evt: event::pointer::PointerAxisEvent) { - let source = match evt.source() { - input::AxisSource::Continuous => wl_pointer::AxisSource::Continuous, - input::AxisSource::Finger => wl_pointer::AxisSource::Finger, - input::AxisSource::Wheel | input::AxisSource::WheelTilt => { - wl_pointer::AxisSource::Wheel - } - }; - let horizontal_amount = evt.amount(&input::Axis::Horizontal) - .unwrap_or_else(|| evt.amount_discrete(&input::Axis::Horizontal).unwrap() * 3.0); - let vertical_amount = evt.amount(&input::Axis::Vertical) - .unwrap_or_else(|| evt.amount_discrete(&input::Axis::Vertical).unwrap() * 3.0); - let horizontal_amount_discrete = evt.amount_discrete(&input::Axis::Horizontal); - let vertical_amount_discrete = evt.amount_discrete(&input::Axis::Vertical); - - { - let mut event = self.pointer.axis(); - event.source(source); - if horizontal_amount != 0.0 { - event.value( - wl_pointer::Axis::HorizontalScroll, - horizontal_amount, - evt.time(), - ); - if let Some(discrete) = horizontal_amount_discrete { - event.discrete( - wl_pointer::Axis::HorizontalScroll, - discrete as i32, - ); - } - } else if source == wl_pointer::AxisSource::Finger { - event.stop( - wl_pointer::Axis::HorizontalScroll, - evt.time(), - ); - } - if vertical_amount != 0.0 { - event.value( - wl_pointer::Axis::VerticalScroll, - vertical_amount, - evt.time(), - ); - if let Some(discrete) = vertical_amount_discrete { - event.discrete( - wl_pointer::Axis::VerticalScroll, - discrete as i32, - ); - } - } else if source == wl_pointer::AxisSource::Finger { - event.stop( - wl_pointer::Axis::VerticalScroll, - evt.time(), - ); - } - event.done(); - } - } - fn on_touch_down(&mut self, _: &input::Seat, _: event::touch::TouchDownEvent) { - /* not done in this example */ - } - fn on_touch_motion(&mut self, _: &input::Seat, _: event::touch::TouchMotionEvent) { - /* not done in this example */ - } - fn on_touch_up(&mut self, _: &input::Seat, _: event::touch::TouchUpEvent) { - /* not done in this example */ - } - fn on_touch_cancel(&mut self, _: &input::Seat, _: event::touch::TouchCancelEvent) { - /* not done in this example */ - } - fn on_touch_frame(&mut self, _: &input::Seat, _: event::touch::TouchFrameEvent) { - /* not done in this example */ - } - fn on_input_config_changed(&mut self, _: &mut [LibinputDevice]) { - /* not done in this example */ - } -} - -pub fn run_udev(mut display: Display, mut event_loop: EventLoop, log: Logger) -> Result<(),()> { +use shell::{init_shell, Buffer, MyWindowMap, Roles, SurfaceData}; +use input_handler::AnvilInputHandler; +pub fn run_udev(mut display: Display, mut event_loop: EventLoop, log: Logger) -> Result<(), ()> { let name = display.add_socket_auto().unwrap().into_string().unwrap(); info!(log, "Listening on wayland socket"; "name" => name.clone()); ::std::env::set_var("WAYLAND_DISPLAY", name); @@ -358,17 +155,16 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop, log: Logger) -> let libinput_session_id = notifier.register(&mut libinput_context); libinput_context.udev_assign_seat(&seat).unwrap(); let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone()); - libinput_backend.set_handler(LibinputInputHandler { - log: log.clone(), + libinput_backend.set_handler(AnvilInputHandler::new_with_session( + log.clone(), pointer, keyboard, - window_map: window_map.clone(), + window_map.clone(), + (w, h), + running.clone(), pointer_location, - screen_size: (w, h), - serial: 0, - session: session, - running: running.clone(), - }); + session, + )); let libinput_event_source = libinput_bind(libinput_backend, event_loop.token()) .map_err(|(err, _)| err) .unwrap(); diff --git a/anvil/src/winit.rs b/anvil/src/winit.rs index 73fd298..2c7540e 100644 --- a/anvil/src/winit.rs +++ b/anvil/src/winit.rs @@ -1,161 +1,27 @@ use std::cell::RefCell; use std::rc::Rc; +use std::sync::Arc; +use std::sync::atomic::AtomicBool; use smithay::wayland::shm::init_shm_global; -use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat}; +use smithay::wayland::seat::Seat; use smithay::wayland::compositor::{SubsurfaceRole, TraversalAction}; use smithay::wayland::compositor::roles::Role; use smithay::wayland::output::{Mode, Output, PhysicalProperties}; -use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyboardKeyEvent, PointerAxisEvent, - PointerButtonEvent, PointerMotionAbsoluteEvent}; +use smithay::backend::input::InputBackend; use smithay::backend::winit; use smithay::backend::graphics::egl::EGLGraphicsBackend; use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format}; use smithay::wayland_server::{Display, EventLoop}; -use smithay::wayland_server::protocol::{wl_pointer, wl_output}; +use smithay::wayland_server::protocol::wl_output; use glium::Surface; use slog::Logger; use glium_drawer::GliumDrawer; -use shell::{init_shell, MyWindowMap, Buffer}; - -struct WinitInputHandler { - log: Logger, - pointer: PointerHandle, - keyboard: KeyboardHandle, - window_map: Rc>, - pointer_location: (f64, f64), - serial: u32, -} - -impl WinitInputHandler { - fn next_serial(&mut self) -> u32 { - self.serial += 1; - self.serial - } -} - -impl InputHandler for WinitInputHandler { - fn on_seat_created(&mut self, _: &input::Seat) { - /* never happens with winit */ - } - fn on_seat_destroyed(&mut self, _: &input::Seat) { - /* never happens with winit */ - } - fn on_seat_changed(&mut self, _: &input::Seat) { - /* never happens with winit */ - } - fn on_keyboard_key(&mut self, _: &input::Seat, evt: winit::WinitKeyboardInputEvent) { - let keycode = evt.key_code(); - let state = evt.state(); - debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state)); - let serial = self.next_serial(); - self.keyboard - .input(keycode, state, serial, evt.time(), |_, _| true); - } - fn on_pointer_move(&mut self, _: &input::Seat, _: input::UnusedEvent) { - /* never happens with winit */ - } - fn on_pointer_move_absolute(&mut self, _: &input::Seat, evt: winit::WinitMouseMovedEvent) { - // on winit, mouse events are already in pixel coordinates - let (x, y) = evt.position(); - self.pointer_location = (x, y); - let serial = self.next_serial(); - let under = self.window_map.borrow().get_surface_under((x, y)); - self.pointer.motion( - under.as_ref().map(|&(ref s, (x, y))| (s, x, y)), - serial, - evt.time(), - ); - } - fn on_pointer_button(&mut self, _: &input::Seat, evt: winit::WinitMouseInputEvent) { - let serial = self.next_serial(); - let button = match evt.button() { - input::MouseButton::Left => 0x110, - input::MouseButton::Right => 0x111, - input::MouseButton::Middle => 0x112, - input::MouseButton::Other(b) => b as u32, - }; - let state = match evt.state() { - input::MouseButtonState::Pressed => { - // change the keyboard focus - let under = self.window_map - .borrow_mut() - .get_surface_and_bring_to_top(self.pointer_location); - self.keyboard - .set_focus(under.as_ref().map(|&(ref s, _)| s), serial); - wl_pointer::ButtonState::Pressed - } - input::MouseButtonState::Released => wl_pointer::ButtonState::Released, - }; - self.pointer.button(button, state, serial, evt.time()); - } - fn on_pointer_axis(&mut self, _: &input::Seat, evt: winit::WinitMouseWheelEvent) { - let source = match evt.source() { - input::AxisSource::Continuous => wl_pointer::AxisSource::Continuous, - input::AxisSource::Wheel => wl_pointer::AxisSource::Wheel, - _ => unreachable!(), //winit does not have more specific sources - }; - let horizontal_amount = evt.amount(&input::Axis::Horizontal) - .unwrap_or_else(|| evt.amount_discrete(&input::Axis::Horizontal).unwrap() * 3.0); - let vertical_amount = evt.amount(&input::Axis::Vertical) - .unwrap_or_else(|| evt.amount_discrete(&input::Axis::Vertical).unwrap() * 3.0); - let horizontal_amount_discrete = evt.amount_discrete(&input::Axis::Horizontal); - let vertical_amount_discrete = evt.amount_discrete(&input::Axis::Vertical); - - { - let mut event = self.pointer.axis(); - event.source(source); - if horizontal_amount != 0.0 { - event.value( - wl_pointer::Axis::HorizontalScroll, - horizontal_amount, - evt.time(), - ); - if let Some(discrete) = horizontal_amount_discrete { - event.discrete( - wl_pointer::Axis::HorizontalScroll, - discrete as i32, - ); - } - } - if vertical_amount != 0.0 { - event.value( - wl_pointer::Axis::VerticalScroll, - vertical_amount, - evt.time(), - ); - if let Some(discrete) = vertical_amount_discrete { - event.discrete( - wl_pointer::Axis::VerticalScroll, - discrete as i32, - ); - } - } - event.done(); - } - } - fn on_touch_down(&mut self, _: &input::Seat, _: winit::WinitTouchStartedEvent) { - /* not done in this example */ - } - fn on_touch_motion(&mut self, _: &input::Seat, _: winit::WinitTouchMovedEvent) { - /* not done in this example */ - } - fn on_touch_up(&mut self, _: &input::Seat, _: winit::WinitTouchEndedEvent) { - /* not done in this example */ - } - fn on_touch_cancel(&mut self, _: &input::Seat, _: winit::WinitTouchCancelledEvent) { - /* not done in this example */ - } - fn on_touch_frame(&mut self, _: &input::Seat, _: input::UnusedEvent) { - /* never happens with winit */ - } - fn on_input_config_changed(&mut self, _: &mut ()) { - /* never happens with winit */ - } -} +use shell::{init_shell, Buffer}; +use input_handler::AnvilInputHandler; pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger) -> Result<(), ()> { let (renderer, mut input) = winit::init(log.clone()).map_err(|_| ())?; @@ -176,6 +42,8 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger) info!(log, "Listening on wayland socket"; "name" => name.clone()); ::std::env::set_var("WAYLAND_DISPLAY", name); + let running = Arc::new(AtomicBool::new(true)); + /* * Initialize the globals */ @@ -185,12 +53,7 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger) let (compositor_token, _, _, window_map) = init_shell(display, event_loop.token(), log.clone(), egl_display); - let (mut seat, _) = Seat::new( - display, - event_loop.token(), - "winit".into(), - log.clone(), - ); + let (mut seat, _) = Seat::new(display, event_loop.token(), "winit".into(), log.clone()); let pointer = seat.add_pointer(); let keyboard = seat.add_keyboard("", "fr", "oss", None, 1000, 500) @@ -225,14 +88,15 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger) refresh: 60_000, }); - input.set_handler(WinitInputHandler { - log: log.clone(), + input.set_handler(AnvilInputHandler::new( + log.clone(), pointer, keyboard, - window_map: window_map.clone(), - pointer_location: (0.0, 0.0), - serial: 0, - }); + window_map.clone(), + (0, 0), + running.clone(), + Rc::new(RefCell::new((0.0, 0.0))), + )); info!(log, "Initialization completed, starting the main loop."); @@ -332,4 +196,4 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger) window_map.borrow_mut().refresh(); } -} \ No newline at end of file +} diff --git a/src/wayland/seat/mod.rs b/src/wayland/seat/mod.rs index 35ceb58..d45d229 100644 --- a/src/wayland/seat/mod.rs +++ b/src/wayland/seat/mod.rs @@ -59,7 +59,7 @@ use std::sync::{Arc, Mutex}; mod keyboard; mod pointer; -pub use self::keyboard::{Error as KeyboardError, KeyboardHandle, ModifiersState, Keysym, keysyms}; +pub use self::keyboard::{keysyms, Error as KeyboardError, KeyboardHandle, Keysym, ModifiersState}; pub use self::pointer::{PointerAxisHandle, PointerHandle}; use wayland_server::{Display, Global, LoopToken, NewResource, Resource}; use wayland_server::protocol::wl_seat; From 011d067ce577246dd250a1cd621ea10730996986 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Tue, 8 May 2018 19:39:38 +0200 Subject: [PATCH 5/6] anvil: add a raw DRM backend --- anvil/Cargo.toml | 5 +- anvil/src/input_handler.rs | 12 +- anvil/src/main.rs | 21 +++- anvil/src/raw_drm.rs | 237 +++++++++++++++++++++++++++++++++++++ 4 files changed, 262 insertions(+), 13 deletions(-) create mode 100644 anvil/src/raw_drm.rs diff --git a/anvil/Cargo.toml b/anvil/Cargo.toml index 72dbc4b..c49841b 100644 --- a/anvil/Cargo.toml +++ b/anvil/Cargo.toml @@ -23,8 +23,9 @@ features = [ "renderer_glium" ] gl_generator = "0.9" [features] -default = [ "winit", "tty_launch" ] +default = [ "winit", "tty_launch", "udev" ] winit = [ "smithay/backend_winit" ] -tty_launch = [ "smithay/backend_udev", "smithay/backend_libinput", "smithay/backend_drm" ] +tty_launch = [ "smithay/backend_libinput", "smithay/backend_drm" ] +udev = [ "tty_launch", "smithay/backend_udev" ] logind = [ "smithay/backend_session_logind" ] diff --git a/anvil/src/input_handler.rs b/anvil/src/input_handler.rs index e52cafe..28edc94 100644 --- a/anvil/src/input_handler.rs +++ b/anvil/src/input_handler.rs @@ -6,7 +6,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use slog::Logger; -#[cfg(feature = "tty_launch")] +#[cfg(feature = "udev")] use smithay::backend::session::auto::AutoSession; use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyState, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, @@ -24,7 +24,7 @@ pub struct AnvilInputHandler { pointer_location: Rc>, screen_size: (u32, u32), serial: u32, - #[cfg(feature = "tty_launch")] + #[cfg(feature = "udev")] session: Option, running: Arc, } @@ -48,12 +48,12 @@ impl AnvilInputHandler { running, pointer_location, serial: 1, - #[cfg(feature = "tty_launch")] + #[cfg(feature = "udev")] session: None, } } - #[cfg(feature = "tty_launch")] + #[cfg(feature = "udev")] pub fn new_with_session( log: Logger, pointer: PointerHandle, @@ -173,7 +173,7 @@ impl InputHandler for AnvilInputHandler { fn on_pointer_move_absolute(&mut self, _: &input::Seat, evt: B::PointerMotionAbsoluteEvent) { // different cases depending on the context: let (x, y) = { - #[cfg(feature = "tty_launch")] + #[cfg(feature = "udev")] { if self.session.is_some() { // we are started on a tty @@ -184,7 +184,7 @@ impl InputHandler for AnvilInputHandler { evt.position() } } - #[cfg(not(feature = "tty_launch"))] + #[cfg(not(feature = "udev"))] { evt.position() } diff --git a/anvil/src/main.rs b/anvil/src/main.rs index 1cf5f91..e108950 100644 --- a/anvil/src/main.rs +++ b/anvil/src/main.rs @@ -14,18 +14,22 @@ use smithay::wayland_server::Display; mod glium_drawer; mod shell; -#[cfg(feature = "tty_launch")] +#[cfg(feature = "udev")] mod udev; mod window_map; #[cfg(feature = "winit")] mod winit; mod input_handler; +#[cfg(feature = "tty_launch")] +mod raw_drm; static POSSIBLE_BACKENDS: &'static [&'static str] = &[ #[cfg(feature = "winit")] - "--winit", + "--winit : Run anvil as a X11 or Wayland client using winit.", #[cfg(feature = "tty_launch")] - "--tty", + "--tty-raw : Run anvil as a raw DRM client (requires root).", + #[cfg(feature = "udev")] + "--tty-udev : Run anvil as a tty udev client (requires root if without logind).", ]; fn main() { @@ -47,8 +51,15 @@ fn main() { } } #[cfg(feature = "tty_launch")] - Some("--tty") => { - info!(log, "Starting anvil on a tty"); + Some("--tty-raw") => { + info!(log, "Starting anvil on a tty using raw DRM"); + if let Err(()) = raw_drm::run_raw_drm(display, event_loop, log.clone()) { + crit!(log, "Failed to initialize tty backend."); + } + } + #[cfg(feature = "udev")] + Some("--tty-udev") => { + info!(log, "Starting anvil on a tty using udev"); if let Err(()) = udev::run_udev(display, event_loop, log.clone()) { crit!(log, "Failed to initialize tty backend."); } diff --git a/anvil/src/raw_drm.rs b/anvil/src/raw_drm.rs new file mode 100644 index 0000000..2b96312 --- /dev/null +++ b/anvil/src/raw_drm.rs @@ -0,0 +1,237 @@ +use std::cell::RefCell; +use std::fs::{File, OpenOptions}; +use std::os::unix::io::AsRawFd; +use std::os::unix::io::RawFd; +use std::rc::Rc; +use std::time::Duration; + +use smithay::drm::Device as BasicDevice; +use smithay::drm::control::{Device as ControlDevice, ResourceInfo}; +use smithay::drm::control::connector::{Info as ConnectorInfo, State as ConnectorState}; +use smithay::drm::control::crtc; +use smithay::drm::control::encoder::Info as EncoderInfo; +use smithay::drm::result::Error as DrmError; +use smithay::backend::drm::{drm_device_bind, DrmBackend, DrmDevice, DrmHandler}; +use smithay::backend::graphics::egl::EGLGraphicsBackend; +use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format}; +use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction}; +use smithay::wayland::compositor::roles::Role; +use smithay::wayland::shm::init_shm_global; +use smithay::wayland_server::{Display, EventLoop}; + +use glium::{Blend, Surface}; +use slog::Logger; + +use glium_drawer::GliumDrawer; +use shell::{init_shell, Buffer, MyWindowMap, Roles, SurfaceData}; + +#[derive(Debug)] +pub struct Card(File); + +impl AsRawFd for Card { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} + +impl BasicDevice for Card {} +impl ControlDevice for Card {} + +pub fn run_raw_drm(mut display: Display, mut event_loop: EventLoop, log: Logger) -> Result<(), ()> { + /* + * Initialize the drm backend + */ + // "Find" a suitable drm device + let mut options = OpenOptions::new(); + options.read(true); + options.write(true); + let mut device = DrmDevice::new( + Card(options.clone().open("/dev/dri/card0").unwrap()), + log.clone(), + ).unwrap(); + + // Get a set of all modesetting resource handles (excluding planes): + let res_handles = device.resource_handles().unwrap(); + + // Use first connected connector + let connector_info = res_handles + .connectors() + .iter() + .map(|conn| ConnectorInfo::load_from_device(&device, *conn).unwrap()) + .find(|conn| conn.connection_state() == ConnectorState::Connected) + .unwrap(); + + // Use the first encoder + let encoder_info = EncoderInfo::load_from_device(&device, connector_info.encoders()[0]).unwrap(); + + // use the connected crtc if any + let crtc = encoder_info.current_crtc() + // or use the first one that is compatible with the encoder + .unwrap_or_else(|| + *res_handles.filter_crtcs(encoder_info.possible_crtcs()) + .iter() + .next() + .unwrap()); + + // Assuming we found a good connector and loaded the info into `connector_info` + let mode = connector_info.modes()[0]; // Use first mode (usually highest resoltion, but in reality you should filter and sort and check and match with other connectors, if you use more then one.) + + // Initialize the hardware backend + let renderer = GliumDrawer::from( + device + .create_backend(crtc, mode, vec![connector_info.handle()]) + .unwrap(), + ); + { + /* + * Initialize glium + */ + let mut frame = renderer.draw(); + frame.clear_color(0.8, 0.8, 0.9, 1.0); + frame.finish().unwrap(); + } + + let egl_display = Rc::new(RefCell::new( + if let Ok(egl_display) = renderer.bind_wl_display(&display) { + info!(log, "EGL hardware-acceleration enabled"); + Some(egl_display) + } else { + None + }, + )); + + /* + * Initialize the globals + */ + + init_shm_global(&mut display, event_loop.token(), vec![], log.clone()); + + let (compositor_token, _, _, window_map) = + init_shell(&mut display, event_loop.token(), log.clone(), egl_display); + + /* + * Add a listening socket: + */ + let name = display.add_socket_auto().unwrap().into_string().unwrap(); + println!("Listening on socket: {}", name); + + /* + * Register the DrmDevice on the EventLoop + */ + let _source = drm_device_bind( + &event_loop.token(), + device, + DrmHandlerImpl { + compositor_token, + window_map: window_map.clone(), + drawer: renderer, + logger: log, + }, + ).map_err(|(err, _)| err) + .unwrap(); + + loop { + event_loop.dispatch(Some(16)).unwrap(); + display.flush_clients(); + + window_map.borrow_mut().refresh(); + } +} + +pub struct DrmHandlerImpl { + compositor_token: CompositorToken, + window_map: Rc>, + drawer: GliumDrawer>, + logger: ::slog::Logger, +} + +impl DrmHandler for DrmHandlerImpl { + fn ready( + &mut self, + _device: &mut DrmDevice, + _crtc: crtc::Handle, + _frame: u32, + _duration: Duration, + ) { + let mut frame = self.drawer.draw(); + frame.clear_color(0.8, 0.8, 0.9, 1.0); + // redraw the frame, in a simple but inneficient way + { + let screen_dimensions = self.drawer.borrow().get_framebuffer_dimensions(); + self.window_map + .borrow() + .with_windows_from_bottom_to_top(|toplevel_surface, initial_place| { + if let Some(wl_surface) = toplevel_surface.get_surface() { + // this surface is a root of a subsurface tree that needs to be drawn + self.compositor_token + .with_surface_tree_upward( + wl_surface, + initial_place, + |_surface, attributes, role, &(mut x, mut y)| { + // there is actually something to draw ! + if attributes.user_data.texture.is_none() { + let mut remove = false; + match attributes.user_data.buffer { + Some(Buffer::Egl { ref images }) => { + match images.format { + Format::RGB | Format::RGBA => { + attributes.user_data.texture = + self.drawer.texture_from_egl(&images); + } + _ => { + // we don't handle the more complex formats here. + attributes.user_data.texture = None; + remove = true; + } + }; + } + Some(Buffer::Shm { ref data, ref size }) => { + attributes.user_data.texture = + Some(self.drawer.texture_from_mem(data, *size)); + } + _ => {} + } + if remove { + attributes.user_data.buffer = None; + } + } + + if let Some(ref texture) = attributes.user_data.texture { + if let Ok(subdata) = Role::::data(role) { + x += subdata.location.0; + y += subdata.location.1; + } + info!(self.logger, "Render window"); + self.drawer.render_texture( + &mut frame, + texture, + match *attributes.user_data.buffer.as_ref().unwrap() { + Buffer::Egl { ref images } => images.y_inverted, + Buffer::Shm { .. } => false, + }, + match *attributes.user_data.buffer.as_ref().unwrap() { + Buffer::Egl { ref images } => (images.width, images.height), + Buffer::Shm { ref size, .. } => *size, + }, + (x, y), + screen_dimensions, + Blend::alpha_blending(), + ); + TraversalAction::DoChildren((x, y)) + } else { + // we are not display, so our children are neither + TraversalAction::SkipChildren + } + }, + ) + .unwrap(); + } + }); + } + frame.finish().unwrap(); + } + + fn error(&mut self, _device: &mut DrmDevice, error: DrmError) { + panic!("{:?}", error); + } +} From a137a7fa8f366d3f5c720cce045ab3cc0b97b46f Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Tue, 8 May 2018 20:08:17 +0200 Subject: [PATCH 6/6] anvil: factor the drawing code --- anvil/src/glium_drawer.rs | 98 +++++++++++++++++++++++++++++++++++++++ anvil/src/raw_drm.rs | 91 ++++-------------------------------- anvil/src/shell.rs | 2 + anvil/src/udev.rs | 94 ++++--------------------------------- anvil/src/winit.rs | 96 ++------------------------------------ 5 files changed, 121 insertions(+), 260 deletions(-) diff --git a/anvil/src/glium_drawer.rs b/anvil/src/glium_drawer.rs index 201ff8d..30c5e3c 100644 --- a/anvil/src/glium_drawer.rs +++ b/anvil/src/glium_drawer.rs @@ -6,10 +6,16 @@ use smithay::backend::graphics::egl::EGLGraphicsBackend; use smithay::backend::graphics::egl::error::Result as EGLResult; use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages, EGLWaylandExtensions, Format}; use smithay::backend::graphics::glium::GliumGraphicsBackend; +use smithay::wayland::compositor::{SubsurfaceRole, TraversalAction}; +use smithay::wayland::compositor::roles::Role; use smithay::wayland_server::Display; use std::cell::Ref; +use slog::Logger; + +use shell::{Buffer, MyCompositorToken, MyWindowMap}; + #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], @@ -190,3 +196,95 @@ impl EGLWaylandExtension self.display.bind_wl_display(display) } } + +impl GliumDrawer { + pub fn draw_windows(&self, window_map: &MyWindowMap, compositor_token: MyCompositorToken, log: &Logger) { + let mut frame = self.draw(); + frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None); + // redraw the frame, in a simple but inneficient way + { + let screen_dimensions = self.borrow().get_framebuffer_dimensions(); + window_map.with_windows_from_bottom_to_top(|toplevel_surface, initial_place| { + if let Some(wl_surface) = toplevel_surface.get_surface() { + // this surface is a root of a subsurface tree that needs to be drawn + compositor_token + .with_surface_tree_upward( + wl_surface, + initial_place, + |_surface, attributes, role, &(mut x, mut y)| { + // there is actually something to draw ! + if attributes.user_data.texture.is_none() { + let mut remove = false; + match attributes.user_data.buffer { + Some(Buffer::Egl { ref images }) => { + match images.format { + Format::RGB | Format::RGBA => { + attributes.user_data.texture = + self.texture_from_egl(&images); + } + _ => { + // we don't handle the more complex formats here. + attributes.user_data.texture = None; + remove = true; + } + }; + } + Some(Buffer::Shm { ref data, ref size }) => { + attributes.user_data.texture = + Some(self.texture_from_mem(data, *size)); + } + _ => {} + } + if remove { + attributes.user_data.buffer = None; + } + } + + if let Some(ref texture) = attributes.user_data.texture { + if let Ok(subdata) = Role::::data(role) { + x += subdata.location.0; + y += subdata.location.1; + } + self.render_texture( + &mut frame, + texture, + match *attributes.user_data.buffer.as_ref().unwrap() { + Buffer::Egl { ref images } => images.y_inverted, + Buffer::Shm { .. } => false, + }, + match *attributes.user_data.buffer.as_ref().unwrap() { + Buffer::Egl { ref images } => (images.width, images.height), + Buffer::Shm { ref size, .. } => *size, + }, + (x, y), + screen_dimensions, + ::glium::Blend { + color: ::glium::BlendingFunction::Addition { + source: ::glium::LinearBlendingFactor::One, + destination: + ::glium::LinearBlendingFactor::OneMinusSourceAlpha, + }, + alpha: ::glium::BlendingFunction::Addition { + source: ::glium::LinearBlendingFactor::One, + destination: + ::glium::LinearBlendingFactor::OneMinusSourceAlpha, + }, + ..Default::default() + }, + ); + TraversalAction::DoChildren((x, y)) + } else { + // we are not display, so our children are neither + TraversalAction::SkipChildren + } + }, + ) + .unwrap(); + } + }); + } + if let Err(err) = frame.finish() { + error!(log, "Error during rendering: {:?}", err); + } + } +} diff --git a/anvil/src/raw_drm.rs b/anvil/src/raw_drm.rs index 2b96312..e282a1d 100644 --- a/anvil/src/raw_drm.rs +++ b/anvil/src/raw_drm.rs @@ -12,18 +12,16 @@ use smithay::drm::control::crtc; use smithay::drm::control::encoder::Info as EncoderInfo; use smithay::drm::result::Error as DrmError; use smithay::backend::drm::{drm_device_bind, DrmBackend, DrmDevice, DrmHandler}; -use smithay::backend::graphics::egl::EGLGraphicsBackend; -use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format}; -use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction}; -use smithay::wayland::compositor::roles::Role; +use smithay::backend::graphics::egl::wayland::EGLWaylandExtensions; +use smithay::wayland::compositor::CompositorToken; use smithay::wayland::shm::init_shm_global; use smithay::wayland_server::{Display, EventLoop}; -use glium::{Blend, Surface}; +use glium::Surface; use slog::Logger; use glium_drawer::GliumDrawer; -use shell::{init_shell, Buffer, MyWindowMap, Roles, SurfaceData}; +use shell::{init_shell, MyWindowMap, Roles, SurfaceData}; #[derive(Debug)] pub struct Card(File); @@ -153,82 +151,11 @@ impl DrmHandler for DrmHandlerImpl { _frame: u32, _duration: Duration, ) { - let mut frame = self.drawer.draw(); - frame.clear_color(0.8, 0.8, 0.9, 1.0); - // redraw the frame, in a simple but inneficient way - { - let screen_dimensions = self.drawer.borrow().get_framebuffer_dimensions(); - self.window_map - .borrow() - .with_windows_from_bottom_to_top(|toplevel_surface, initial_place| { - if let Some(wl_surface) = toplevel_surface.get_surface() { - // this surface is a root of a subsurface tree that needs to be drawn - self.compositor_token - .with_surface_tree_upward( - wl_surface, - initial_place, - |_surface, attributes, role, &(mut x, mut y)| { - // there is actually something to draw ! - if attributes.user_data.texture.is_none() { - let mut remove = false; - match attributes.user_data.buffer { - Some(Buffer::Egl { ref images }) => { - match images.format { - Format::RGB | Format::RGBA => { - attributes.user_data.texture = - self.drawer.texture_from_egl(&images); - } - _ => { - // we don't handle the more complex formats here. - attributes.user_data.texture = None; - remove = true; - } - }; - } - Some(Buffer::Shm { ref data, ref size }) => { - attributes.user_data.texture = - Some(self.drawer.texture_from_mem(data, *size)); - } - _ => {} - } - if remove { - attributes.user_data.buffer = None; - } - } - - if let Some(ref texture) = attributes.user_data.texture { - if let Ok(subdata) = Role::::data(role) { - x += subdata.location.0; - y += subdata.location.1; - } - info!(self.logger, "Render window"); - self.drawer.render_texture( - &mut frame, - texture, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => images.y_inverted, - Buffer::Shm { .. } => false, - }, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => (images.width, images.height), - Buffer::Shm { ref size, .. } => *size, - }, - (x, y), - screen_dimensions, - Blend::alpha_blending(), - ); - TraversalAction::DoChildren((x, y)) - } else { - // we are not display, so our children are neither - TraversalAction::SkipChildren - } - }, - ) - .unwrap(); - } - }); - } - frame.finish().unwrap(); + self.drawer.draw_windows( + &*self.window_map.borrow(), + self.compositor_token, + &self.logger, + ); } fn error(&mut self, _device: &mut DrmDevice, error: DrmError) { diff --git a/anvil/src/shell.rs b/anvil/src/shell.rs index 811f297..ad5940e 100644 --- a/anvil/src/shell.rs +++ b/anvil/src/shell.rs @@ -24,6 +24,8 @@ define_roles!(Roles => [ XdgSurface, XdgSurfaceRole ] [ ShellSurface, ShellSurfa pub type MyWindowMap = WindowMap) -> Option<(i32, i32)>>; +pub type MyCompositorToken = CompositorToken; + pub fn init_shell( display: &mut Display, looptoken: LoopToken, diff --git a/anvil/src/udev.rs b/anvil/src/udev.rs index 7122e5e..1dc710e 100644 --- a/anvil/src/udev.rs +++ b/anvil/src/udev.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; -use glium::{Blend, Surface}; +use glium::Surface; use smithay::image::{ImageBuffer, Rgba}; @@ -20,15 +20,13 @@ use smithay::drm::control::encoder::Info as EncoderInfo; use smithay::drm::result::Error as DrmError; use smithay::backend::drm::{DevPath, DrmBackend, DrmDevice, DrmHandler}; use smithay::backend::graphics::GraphicsBackend; -use smithay::backend::graphics::egl::EGLGraphicsBackend; -use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions, Format}; +use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions}; use smithay::backend::input::InputBackend; use smithay::backend::libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface}; use smithay::backend::session::{Session, SessionNotifier}; use smithay::backend::session::auto::{auto_session_bind, AutoSession}; use smithay::backend::udev::{primary_gpu, udev_backend_bind, SessionFdDrmDevice, UdevBackend, UdevHandler}; -use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction}; -use smithay::wayland::compositor::roles::Role; +use smithay::wayland::compositor::CompositorToken; use smithay::wayland::output::{Mode, Output, PhysicalProperties}; use smithay::wayland::seat::Seat; use smithay::wayland::shm::init_shm_global; @@ -38,7 +36,7 @@ use smithay::wayland_server::protocol::wl_output; use smithay::input::Libinput; use glium_drawer::GliumDrawer; -use shell::{init_shell, Buffer, MyWindowMap, Roles, SurfaceData}; +use shell::{init_shell, MyWindowMap, Roles, SurfaceData}; use input_handler::AnvilInputHandler; pub fn run_udev(mut display: Display, mut event_loop: EventLoop, log: Logger) -> Result<(), ()> { @@ -337,86 +335,12 @@ impl DrmHandler for DrmHandlerImpl { .borrow() .set_cursor_position(x.trunc().abs() as u32, y.trunc().abs() as u32); } - let mut frame = drawer.draw(); - frame.clear_color(0.8, 0.8, 0.9, 1.0); - // redraw the frame, in a simple but inneficient way - { - let screen_dimensions = drawer.borrow().get_framebuffer_dimensions(); - self.window_map.borrow().with_windows_from_bottom_to_top( - |toplevel_surface, initial_place| { - if let Some(wl_surface) = toplevel_surface.get_surface() { - // this surface is a root of a subsurface tree that needs to be drawn - self.compositor_token - .with_surface_tree_upward( - wl_surface, - initial_place, - |_surface, attributes, role, &(mut x, mut y)| { - // there is actually something to draw ! - if attributes.user_data.texture.is_none() { - let mut remove = false; - match attributes.user_data.buffer { - Some(Buffer::Egl { ref images }) => { - match images.format { - Format::RGB | Format::RGBA => { - attributes.user_data.texture = - drawer.texture_from_egl(&images); - } - _ => { - // we don't handle the more complex formats here. - attributes.user_data.texture = None; - remove = true; - } - }; - } - Some(Buffer::Shm { ref data, ref size }) => { - attributes.user_data.texture = - Some(drawer.texture_from_mem(data, *size)); - } - _ => {} - } - if remove { - attributes.user_data.buffer = None; - } - } - if let Some(ref texture) = attributes.user_data.texture { - if let Ok(subdata) = Role::::data(role) { - x += subdata.location.0; - y += subdata.location.1; - } - info!(self.logger, "Render window"); - drawer.render_texture( - &mut frame, - texture, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => images.y_inverted, - Buffer::Shm { .. } => false, - }, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => { - (images.width, images.height) - } - Buffer::Shm { ref size, .. } => *size, - }, - (x, y), - screen_dimensions, - Blend::alpha_blending(), - ); - TraversalAction::DoChildren((x, y)) - } else { - // we are not display, so our children are neither - TraversalAction::SkipChildren - } - }, - ) - .unwrap(); - } - }, - ); - } - if let Err(err) = frame.finish() { - error!(self.logger, "Error during rendering: {:?}", err); - } + drawer.draw_windows( + &*self.window_map.borrow(), + self.compositor_token, + &self.logger, + ); } } diff --git a/anvil/src/winit.rs b/anvil/src/winit.rs index 2c7540e..b737bf3 100644 --- a/anvil/src/winit.rs +++ b/anvil/src/winit.rs @@ -5,22 +5,18 @@ use std::sync::atomic::AtomicBool; use smithay::wayland::shm::init_shm_global; use smithay::wayland::seat::Seat; -use smithay::wayland::compositor::{SubsurfaceRole, TraversalAction}; -use smithay::wayland::compositor::roles::Role; use smithay::wayland::output::{Mode, Output, PhysicalProperties}; use smithay::backend::input::InputBackend; use smithay::backend::winit; use smithay::backend::graphics::egl::EGLGraphicsBackend; -use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format}; +use smithay::backend::graphics::egl::wayland::EGLWaylandExtensions; use smithay::wayland_server::{Display, EventLoop}; use smithay::wayland_server::protocol::wl_output; -use glium::Surface; - use slog::Logger; use glium_drawer::GliumDrawer; -use shell::{init_shell, Buffer}; +use shell::init_shell; use input_handler::AnvilInputHandler; pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger) -> Result<(), ()> { @@ -103,93 +99,7 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger) loop { input.dispatch_new_events().unwrap(); - let mut frame = drawer.draw(); - frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None); - // redraw the frame, in a simple but inneficient way - { - let screen_dimensions = drawer.borrow().get_framebuffer_dimensions(); - window_map - .borrow() - .with_windows_from_bottom_to_top(|toplevel_surface, initial_place| { - if let Some(wl_surface) = toplevel_surface.get_surface() { - // this surface is a root of a subsurface tree that needs to be drawn - compositor_token - .with_surface_tree_upward( - wl_surface, - initial_place, - |_surface, attributes, role, &(mut x, mut y)| { - // there is actually something to draw ! - if attributes.user_data.texture.is_none() { - let mut remove = false; - match attributes.user_data.buffer { - Some(Buffer::Egl { ref images }) => { - match images.format { - Format::RGB | Format::RGBA => { - attributes.user_data.texture = - drawer.texture_from_egl(&images); - } - _ => { - // we don't handle the more complex formats here. - attributes.user_data.texture = None; - remove = true; - } - }; - } - Some(Buffer::Shm { ref data, ref size }) => { - attributes.user_data.texture = - Some(drawer.texture_from_mem(data, *size)); - } - _ => {} - } - if remove { - attributes.user_data.buffer = None; - } - } - - if let Some(ref texture) = attributes.user_data.texture { - if let Ok(subdata) = Role::::data(role) { - x += subdata.location.0; - y += subdata.location.1; - } - drawer.render_texture( - &mut frame, - texture, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => images.y_inverted, - Buffer::Shm { .. } => false, - }, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => (images.width, images.height), - Buffer::Shm { ref size, .. } => *size, - }, - (x, y), - screen_dimensions, - ::glium::Blend { - color: ::glium::BlendingFunction::Addition { - source: ::glium::LinearBlendingFactor::One, - destination: - ::glium::LinearBlendingFactor::OneMinusSourceAlpha, - }, - alpha: ::glium::BlendingFunction::Addition { - source: ::glium::LinearBlendingFactor::One, - destination: - ::glium::LinearBlendingFactor::OneMinusSourceAlpha, - }, - ..Default::default() - }, - ); - TraversalAction::DoChildren((x, y)) - } else { - // we are not display, so our children are neither - TraversalAction::SkipChildren - } - }, - ) - .unwrap(); - } - }); - } - frame.finish().unwrap(); + drawer.draw_windows(&*window_map.borrow(), compositor_token, &log); event_loop.dispatch(Some(16)).unwrap(); display.flush_clients();