move examples into our own compositor: anvil
This commit is contained in:
parent
6f52f9c75a
commit
23faeae20f
|
@ -6,6 +6,9 @@ license = "MIT"
|
||||||
description = "Smithay is a library for writing wayland compositors."
|
description = "Smithay is a library for writing wayland compositors."
|
||||||
repository = "https://github.com/Smithay/smithay"
|
repository = "https://github.com/Smithay/smithay"
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members = [ "anvil" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wayland-server = "0.20.2"
|
wayland-server = "0.20.2"
|
||||||
wayland-sys = "0.20.2"
|
wayland-sys = "0.20.2"
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
[package]
|
||||||
|
name = "anvil"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = ["Victor Berger <victor.berger@m4x.org>", "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" ]
|
||||||
|
|
|
@ -6,9 +6,9 @@ use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
||||||
use smithay::backend::graphics::egl::error::Result as EGLResult;
|
use smithay::backend::graphics::egl::error::Result as EGLResult;
|
||||||
use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages, EGLWaylandExtensions, Format};
|
use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages, EGLWaylandExtensions, Format};
|
||||||
use smithay::backend::graphics::glium::GliumGraphicsBackend;
|
use smithay::backend::graphics::glium::GliumGraphicsBackend;
|
||||||
|
use smithay::wayland_server::Display;
|
||||||
|
|
||||||
use std::cell::Ref;
|
use std::cell::Ref;
|
||||||
use std::ops::Deref;
|
|
||||||
use wayland_server::Display;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct Vertex {
|
struct Vertex {
|
|
@ -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.");
|
||||||
|
}
|
|
@ -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 glium::texture::Texture2d;
|
||||||
|
|
||||||
use rand;
|
use rand;
|
||||||
|
|
||||||
use smithay::backend::graphics::egl::wayland::{BufferAccessError, Format};
|
use smithay::backend::graphics::egl::wayland::{BufferAccessError, Format};
|
||||||
use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages};
|
use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages};
|
||||||
use smithay::wayland::compositor::{compositor_init, CompositorToken, SurfaceAttributes, SurfaceEvent};
|
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,
|
use smithay::wayland::shell::legacy::{wl_shell_init, ShellRequest, ShellState as WlShellState,
|
||||||
ShellSurfaceKind, ShellSurfaceRole};
|
ShellSurfaceKind, ShellSurfaceRole};
|
||||||
use smithay::wayland::shm::with_buffer_contents as shm_buffer_contents;
|
use smithay::wayland::shm::with_buffer_contents as shm_buffer_contents;
|
||||||
use std::cell::RefCell;
|
use smithay::wayland_server::{Display, LoopToken, Resource};
|
||||||
use std::rc::Rc;
|
use smithay::wayland_server::protocol::{wl_buffer, wl_callback, wl_shell_surface, wl_surface};
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use wayland_server::{Display, LoopToken, Resource};
|
use window_map::{Kind as SurfaceKind, WindowMap};
|
||||||
use wayland_server::protocol::{wl_buffer, wl_callback, wl_shell_surface, wl_surface};
|
|
||||||
|
|
||||||
define_roles!(Roles => [ XdgSurface, XdgSurfaceRole ] [ ShellSurface, ShellSurfaceRole<()>] );
|
define_roles!(Roles => [ XdgSurface, XdgSurfaceRole ] [ ShellSurface, ShellSurfaceRole<()>] );
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct SurfaceData {
|
|
||||||
pub buffer: Option<Buffer>,
|
|
||||||
pub texture: Option<Texture2d>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Buffer {
|
|
||||||
Egl { images: EGLImages },
|
|
||||||
Shm { data: Vec<u8>, size: (u32, u32) },
|
|
||||||
}
|
|
||||||
|
|
||||||
fn surface_commit(
|
|
||||||
surface: &Resource<wl_surface::WlSurface>,
|
|
||||||
token: CompositorToken<SurfaceData, Roles>,
|
|
||||||
display: &RefCell<Option<EGLDisplay>>,
|
|
||||||
) {
|
|
||||||
// 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<SurfaceData>) -> 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 =
|
pub type MyWindowMap =
|
||||||
WindowMap<SurfaceData, Roles, (), (), fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>>;
|
WindowMap<SurfaceData, Roles, (), (), fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>>;
|
||||||
|
|
||||||
|
@ -199,3 +122,84 @@ pub fn init_shell(
|
||||||
window_map,
|
window_map,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct SurfaceData {
|
||||||
|
pub buffer: Option<Buffer>,
|
||||||
|
pub texture: Option<Texture2d>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Buffer {
|
||||||
|
Egl { images: EGLImages },
|
||||||
|
Shm { data: Vec<u8>, size: (u32, u32) },
|
||||||
|
}
|
||||||
|
|
||||||
|
fn surface_commit(
|
||||||
|
surface: &Resource<wl_surface::WlSurface>,
|
||||||
|
token: CompositorToken<SurfaceData, Roles>,
|
||||||
|
display: &RefCell<Option<EGLDisplay>>,
|
||||||
|
) {
|
||||||
|
// 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<SurfaceData>) -> 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))
|
||||||
|
}
|
|
@ -1,33 +1,24 @@
|
||||||
extern crate drm;
|
use std::cell::RefCell;
|
||||||
#[macro_use]
|
use std::collections::HashMap;
|
||||||
extern crate glium;
|
use std::io::Error as IoError;
|
||||||
extern crate image;
|
use std::path::PathBuf;
|
||||||
extern crate input as libinput;
|
use std::process::Command;
|
||||||
extern crate rand;
|
use std::rc::Rc;
|
||||||
#[macro_use(define_roles)]
|
use std::sync::Arc;
|
||||||
extern crate smithay;
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
extern crate udev;
|
use std::time::Duration;
|
||||||
extern crate wayland_server;
|
|
||||||
extern crate xkbcommon;
|
|
||||||
|
|
||||||
#[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 glium::{Blend, Surface};
|
||||||
use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap, Roles, SurfaceData};
|
|
||||||
use image::{ImageBuffer, Rgba};
|
use smithay::image::{ImageBuffer, Rgba};
|
||||||
use libinput::{event, Device as LibinputDevice, Libinput};
|
|
||||||
use libinput::event::keyboard::KeyboardEventTrait;
|
use slog::Logger;
|
||||||
use slog::{Drain, 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::drm::{DevPath, DrmBackend, DrmDevice, DrmHandler};
|
||||||
use smithay::backend::graphics::GraphicsBackend;
|
use smithay::backend::graphics::GraphicsBackend;
|
||||||
use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
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::{CompositorToken, SubsurfaceRole, TraversalAction};
|
||||||
use smithay::wayland::compositor::roles::Role;
|
use smithay::wayland::compositor::roles::Role;
|
||||||
use smithay::wayland::output::{Mode, Output, PhysicalProperties};
|
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 smithay::wayland::shm::init_shm_global;
|
||||||
use std::cell::RefCell;
|
use smithay::wayland_server::{Display, EventLoop};
|
||||||
use std::collections::HashMap;
|
use smithay::wayland_server::commons::downcast_impl;
|
||||||
use std::env;
|
use smithay::wayland_server::protocol::{wl_output, wl_pointer};
|
||||||
use std::io::Error as IoError;
|
use smithay::input::{event, Device as LibinputDevice, Libinput};
|
||||||
use std::path::PathBuf;
|
use smithay::input::event::keyboard::KeyboardEventTrait;
|
||||||
use std::process::Command;
|
|
||||||
use std::rc::Rc;
|
use glium_drawer::GliumDrawer;
|
||||||
use std::sync::Arc;
|
use shell::{init_shell, MyWindowMap, Buffer, Roles, SurfaceData};
|
||||||
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;
|
|
||||||
|
|
||||||
struct LibinputInputHandler {
|
struct LibinputInputHandler {
|
||||||
log: Logger,
|
log: Logger,
|
||||||
|
@ -101,7 +86,11 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
let time = Event::time(&evt);
|
let time = Event::time(&evt);
|
||||||
self.keyboard
|
self.keyboard
|
||||||
.input(keycode, state, serial, time, move |modifiers, keysym| {
|
.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
|
if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace
|
||||||
&& state == KeyState::Pressed
|
&& state == KeyState::Pressed
|
||||||
{
|
{
|
||||||
|
@ -179,10 +168,10 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
}
|
}
|
||||||
fn on_pointer_axis(&mut self, _: &input::Seat, evt: event::pointer::PointerAxisEvent) {
|
fn on_pointer_axis(&mut self, _: &input::Seat, evt: event::pointer::PointerAxisEvent) {
|
||||||
let source = match evt.source() {
|
let source = match evt.source() {
|
||||||
input::AxisSource::Continuous => wayland_server::protocol::wl_pointer::AxisSource::Continuous,
|
input::AxisSource::Continuous => wl_pointer::AxisSource::Continuous,
|
||||||
input::AxisSource::Finger => wayland_server::protocol::wl_pointer::AxisSource::Finger,
|
input::AxisSource::Finger => wl_pointer::AxisSource::Finger,
|
||||||
input::AxisSource::Wheel | input::AxisSource::WheelTilt => {
|
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)
|
let horizontal_amount = evt.amount(&input::Axis::Horizontal)
|
||||||
|
@ -197,37 +186,37 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
event.source(source);
|
event.source(source);
|
||||||
if horizontal_amount != 0.0 {
|
if horizontal_amount != 0.0 {
|
||||||
event.value(
|
event.value(
|
||||||
wayland_server::protocol::wl_pointer::Axis::HorizontalScroll,
|
wl_pointer::Axis::HorizontalScroll,
|
||||||
horizontal_amount,
|
horizontal_amount,
|
||||||
evt.time(),
|
evt.time(),
|
||||||
);
|
);
|
||||||
if let Some(discrete) = horizontal_amount_discrete {
|
if let Some(discrete) = horizontal_amount_discrete {
|
||||||
event.discrete(
|
event.discrete(
|
||||||
wayland_server::protocol::wl_pointer::Axis::HorizontalScroll,
|
wl_pointer::Axis::HorizontalScroll,
|
||||||
discrete as i32,
|
discrete as i32,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if source == wayland_server::protocol::wl_pointer::AxisSource::Finger {
|
} else if source == wl_pointer::AxisSource::Finger {
|
||||||
event.stop(
|
event.stop(
|
||||||
wayland_server::protocol::wl_pointer::Axis::HorizontalScroll,
|
wl_pointer::Axis::HorizontalScroll,
|
||||||
evt.time(),
|
evt.time(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if vertical_amount != 0.0 {
|
if vertical_amount != 0.0 {
|
||||||
event.value(
|
event.value(
|
||||||
wayland_server::protocol::wl_pointer::Axis::VerticalScroll,
|
wl_pointer::Axis::VerticalScroll,
|
||||||
vertical_amount,
|
vertical_amount,
|
||||||
evt.time(),
|
evt.time(),
|
||||||
);
|
);
|
||||||
if let Some(discrete) = vertical_amount_discrete {
|
if let Some(discrete) = vertical_amount_discrete {
|
||||||
event.discrete(
|
event.discrete(
|
||||||
wayland_server::protocol::wl_pointer::Axis::VerticalScroll,
|
wl_pointer::Axis::VerticalScroll,
|
||||||
discrete as i32,
|
discrete as i32,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if source == wayland_server::protocol::wl_pointer::AxisSource::Finger {
|
} else if source == wl_pointer::AxisSource::Finger {
|
||||||
event.stop(
|
event.stop(
|
||||||
wayland_server::protocol::wl_pointer::Axis::VerticalScroll,
|
wl_pointer::Axis::VerticalScroll,
|
||||||
evt.time(),
|
evt.time(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -254,26 +243,14 @@ impl InputHandler<LibinputInputBackend> 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));
|
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));
|
let display = Rc::new(RefCell::new(display));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -296,7 +273,7 @@ fn main() {
|
||||||
/*
|
/*
|
||||||
* Initialize session
|
* 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));
|
let running = Arc::new(AtomicBool::new(true));
|
||||||
|
|
||||||
|
@ -305,12 +282,12 @@ fn main() {
|
||||||
/*
|
/*
|
||||||
* Initialize the udev backend
|
* Initialize the udev backend
|
||||||
*/
|
*/
|
||||||
let context = udev::Context::new().unwrap();
|
let context = ::smithay::udev::Context::new().map_err(|_| ())?;
|
||||||
let seat = session.seat();
|
let seat = session.seat();
|
||||||
|
|
||||||
let primary_gpu = primary_gpu(&context, &seat).unwrap_or_default();
|
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(
|
let mut udev_backend = UdevBackend::new(
|
||||||
event_loop.token(),
|
event_loop.token(),
|
||||||
&context,
|
&context,
|
||||||
|
@ -327,7 +304,7 @@ fn main() {
|
||||||
logger: log.clone(),
|
logger: log.clone(),
|
||||||
},
|
},
|
||||||
log.clone(),
|
log.clone(),
|
||||||
).unwrap();
|
).map_err(|_| ())?;
|
||||||
|
|
||||||
let udev_session_id = notifier.register(&mut udev_backend);
|
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();
|
let mut notifier = session_event_source.unbind();
|
||||||
notifier.unregister(udev_session_id);
|
notifier.unregister(udev_session_id);
|
||||||
notifier.unregister(libinput_session_id);
|
notifier.unregister(libinput_session_id);
|
||||||
|
@ -427,6 +402,7 @@ fn main() {
|
||||||
// variable to simplify type inference.
|
// variable to simplify type inference.
|
||||||
udev_backend = *(downcast_impl(udev_event_source.remove()).unwrap_or_else(|_| unreachable!()));
|
udev_backend = *(downcast_impl(udev_event_source.remove()).unwrap_or_else(|_| unreachable!()));
|
||||||
udev_backend.close();
|
udev_backend.close();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UdevHandlerImpl {
|
struct UdevHandlerImpl {
|
|
@ -3,8 +3,8 @@ use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, SurfaceAttri
|
||||||
use smithay::wayland::compositor::roles::Role;
|
use smithay::wayland::compositor::roles::Role;
|
||||||
use smithay::wayland::shell::xdg::{ToplevelSurface, XdgSurfaceRole};
|
use smithay::wayland::shell::xdg::{ToplevelSurface, XdgSurfaceRole};
|
||||||
use smithay::wayland::shell::legacy::{ShellSurface, ShellSurfaceRole};
|
use smithay::wayland::shell::legacy::{ShellSurface, ShellSurfaceRole};
|
||||||
use wayland_server::Resource;
|
use smithay::wayland_server::Resource;
|
||||||
use wayland_server::protocol::wl_surface;
|
use smithay::wayland_server::protocol::wl_surface;
|
||||||
|
|
||||||
pub enum Kind<U, R, SD, D> {
|
pub enum Kind<U, R, SD, D> {
|
||||||
Xdg(ToplevelSurface<U, R, SD>),
|
Xdg(ToplevelSurface<U, R, SD>),
|
|
@ -1,33 +1,25 @@
|
||||||
#[macro_use]
|
use std::cell::RefCell;
|
||||||
extern crate glium;
|
use std::rc::Rc;
|
||||||
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;
|
|
||||||
|
|
||||||
mod helpers;
|
use smithay::wayland::shm::init_shm_global;
|
||||||
|
use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat};
|
||||||
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::compositor::{SubsurfaceRole, TraversalAction};
|
use smithay::wayland::compositor::{SubsurfaceRole, TraversalAction};
|
||||||
use smithay::wayland::compositor::roles::Role;
|
use smithay::wayland::compositor::roles::Role;
|
||||||
use smithay::wayland::output::{Mode, Output, PhysicalProperties};
|
use smithay::wayland::output::{Mode, Output, PhysicalProperties};
|
||||||
use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat};
|
use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyboardKeyEvent, PointerAxisEvent,
|
||||||
use smithay::wayland::shm::init_shm_global;
|
PointerButtonEvent, PointerMotionAbsoluteEvent};
|
||||||
use std::cell::RefCell;
|
use smithay::backend::winit;
|
||||||
use std::rc::Rc;
|
use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
||||||
use wayland_server::Display;
|
use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format};
|
||||||
use wayland_server::protocol::{wl_output, wl_pointer};
|
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 {
|
struct WinitInputHandler {
|
||||||
log: Logger,
|
log: Logger,
|
||||||
|
@ -102,8 +94,8 @@ impl InputHandler<winit::WinitInputBackend> for WinitInputHandler {
|
||||||
}
|
}
|
||||||
fn on_pointer_axis(&mut self, _: &input::Seat, evt: winit::WinitMouseWheelEvent) {
|
fn on_pointer_axis(&mut self, _: &input::Seat, evt: winit::WinitMouseWheelEvent) {
|
||||||
let source = match evt.source() {
|
let source = match evt.source() {
|
||||||
input::AxisSource::Continuous => wayland_server::protocol::wl_pointer::AxisSource::Continuous,
|
input::AxisSource::Continuous => wl_pointer::AxisSource::Continuous,
|
||||||
input::AxisSource::Wheel => wayland_server::protocol::wl_pointer::AxisSource::Wheel,
|
input::AxisSource::Wheel => wl_pointer::AxisSource::Wheel,
|
||||||
_ => unreachable!(), //winit does not have more specific sources
|
_ => unreachable!(), //winit does not have more specific sources
|
||||||
};
|
};
|
||||||
let horizontal_amount = evt.amount(&input::Axis::Horizontal)
|
let horizontal_amount = evt.amount(&input::Axis::Horizontal)
|
||||||
|
@ -118,26 +110,26 @@ impl InputHandler<winit::WinitInputBackend> for WinitInputHandler {
|
||||||
event.source(source);
|
event.source(source);
|
||||||
if horizontal_amount != 0.0 {
|
if horizontal_amount != 0.0 {
|
||||||
event.value(
|
event.value(
|
||||||
wayland_server::protocol::wl_pointer::Axis::HorizontalScroll,
|
wl_pointer::Axis::HorizontalScroll,
|
||||||
horizontal_amount,
|
horizontal_amount,
|
||||||
evt.time(),
|
evt.time(),
|
||||||
);
|
);
|
||||||
if let Some(discrete) = horizontal_amount_discrete {
|
if let Some(discrete) = horizontal_amount_discrete {
|
||||||
event.discrete(
|
event.discrete(
|
||||||
wayland_server::protocol::wl_pointer::Axis::HorizontalScroll,
|
wl_pointer::Axis::HorizontalScroll,
|
||||||
discrete as i32,
|
discrete as i32,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if vertical_amount != 0.0 {
|
if vertical_amount != 0.0 {
|
||||||
event.value(
|
event.value(
|
||||||
wayland_server::protocol::wl_pointer::Axis::VerticalScroll,
|
wl_pointer::Axis::VerticalScroll,
|
||||||
vertical_amount,
|
vertical_amount,
|
||||||
evt.time(),
|
evt.time(),
|
||||||
);
|
);
|
||||||
if let Some(discrete) = vertical_amount_discrete {
|
if let Some(discrete) = vertical_amount_discrete {
|
||||||
event.discrete(
|
event.discrete(
|
||||||
wayland_server::protocol::wl_pointer::Axis::VerticalScroll,
|
wl_pointer::Axis::VerticalScroll,
|
||||||
discrete as i32,
|
discrete as i32,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -165,17 +157,8 @@ impl InputHandler<winit::WinitInputBackend> for WinitInputHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger) -> Result<(), ()> {
|
||||||
// A logger facility, here we use the terminal for this example
|
let (renderer, mut input) = winit::init(log.clone()).map_err(|_| ())?;
|
||||||
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();
|
|
||||||
|
|
||||||
let egl_display = Rc::new(RefCell::new(
|
let egl_display = Rc::new(RefCell::new(
|
||||||
if let Ok(egl_display) = renderer.bind_wl_display(&display) {
|
if let Ok(egl_display) = renderer.bind_wl_display(&display) {
|
||||||
|
@ -189,17 +172,21 @@ fn main() {
|
||||||
let (w, h) = renderer.get_framebuffer_dimensions();
|
let (w, h) = renderer.get_framebuffer_dimensions();
|
||||||
let drawer = GliumDrawer::from(renderer);
|
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
|
* 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) =
|
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(
|
let (mut seat, _) = Seat::new(
|
||||||
&mut display,
|
display,
|
||||||
event_loop.token(),
|
event_loop.token(),
|
||||||
"winit".into(),
|
"winit".into(),
|
||||||
log.clone(),
|
log.clone(),
|
||||||
|
@ -210,7 +197,7 @@ fn main() {
|
||||||
.expect("Failed to initialize the keyboard");
|
.expect("Failed to initialize the keyboard");
|
||||||
|
|
||||||
let (output, _) = Output::new(
|
let (output, _) = Output::new(
|
||||||
&mut display,
|
display,
|
||||||
event_loop.token(),
|
event_loop.token(),
|
||||||
"Winit".into(),
|
"Winit".into(),
|
||||||
PhysicalProperties {
|
PhysicalProperties {
|
||||||
|
@ -247,11 +234,7 @@ fn main() {
|
||||||
serial: 0,
|
serial: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
info!(log, "Initialization completed, starting the main loop.");
|
||||||
* Add a listening socket:
|
|
||||||
*/
|
|
||||||
let name = display.add_socket_auto().unwrap().into_string().unwrap();
|
|
||||||
println!("Listening on socket: {}", name);
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
input.dispatch_new_events().unwrap();
|
input.dispatch_new_events().unwrap();
|
||||||
|
@ -317,16 +300,16 @@ fn main() {
|
||||||
},
|
},
|
||||||
(x, y),
|
(x, y),
|
||||||
screen_dimensions,
|
screen_dimensions,
|
||||||
glium::Blend {
|
::glium::Blend {
|
||||||
color: glium::BlendingFunction::Addition {
|
color: ::glium::BlendingFunction::Addition {
|
||||||
source: glium::LinearBlendingFactor::One,
|
source: ::glium::LinearBlendingFactor::One,
|
||||||
destination:
|
destination:
|
||||||
glium::LinearBlendingFactor::OneMinusSourceAlpha,
|
::glium::LinearBlendingFactor::OneMinusSourceAlpha,
|
||||||
},
|
},
|
||||||
alpha: glium::BlendingFunction::Addition {
|
alpha: ::glium::BlendingFunction::Addition {
|
||||||
source: glium::LinearBlendingFactor::One,
|
source: ::glium::LinearBlendingFactor::One,
|
||||||
destination:
|
destination:
|
||||||
glium::LinearBlendingFactor::OneMinusSourceAlpha,
|
::glium::LinearBlendingFactor::OneMinusSourceAlpha,
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
@ -349,4 +332,4 @@ fn main() {
|
||||||
|
|
||||||
window_map.borrow_mut().refresh();
|
window_map.borrow_mut().refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
256
examples/drm.rs
256
examples/drm.rs
|
@ -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<SurfaceData, Roles>,
|
|
||||||
window_map: Rc<RefCell<MyWindowMap>>,
|
|
||||||
drawer: GliumDrawer<DrmBackend<Card>>,
|
|
||||||
logger: ::slog::Logger,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DrmHandler<Card> for DrmHandlerImpl {
|
|
||||||
fn ready(
|
|
||||||
&mut self,
|
|
||||||
_device: &mut DrmDevice<Card>,
|
|
||||||
_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::<SubsurfaceRole>::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<Card>, error: DrmError) {
|
|
||||||
panic!("{:?}", error);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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};
|
|
Loading…
Reference in New Issue