port examples to wayland_rs 0.20
This commit is contained in:
parent
4bd1501b96
commit
4579f20fae
|
@ -34,7 +34,6 @@ use std::os::unix::io::AsRawFd;
|
||||||
use std::os::unix::io::RawFd;
|
use std::os::unix::io::RawFd;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use wayland_server::EventLoopHandle;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Card(File);
|
pub struct Card(File);
|
||||||
|
@ -56,7 +55,7 @@ fn main() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Initialize the wayland server
|
// Initialize the wayland server
|
||||||
let (mut display, mut event_loop) = wayland_server::create_display();
|
let (mut display, mut event_loop) = wayland_server::Display::new();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the drm backend
|
* Initialize the drm backend
|
||||||
|
@ -124,10 +123,10 @@ fn main() {
|
||||||
* Initialize the globals
|
* Initialize the globals
|
||||||
*/
|
*/
|
||||||
|
|
||||||
init_shm_global(&mut event_loop, vec![], log.clone());
|
init_shm_global(&mut display, event_loop.token(), vec![], log.clone());
|
||||||
|
|
||||||
let (compositor_token, _shell_state_token, window_map) =
|
let (compositor_token, _shell_state_token, window_map) =
|
||||||
init_shell(&mut event_loop, log.clone(), egl_display.clone());
|
init_shell(&mut display, event_loop.token(), log.clone(), egl_display);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a listening socket:
|
* Add a listening socket:
|
||||||
|
@ -139,7 +138,7 @@ fn main() {
|
||||||
* Register the DrmDevice on the EventLoop
|
* Register the DrmDevice on the EventLoop
|
||||||
*/
|
*/
|
||||||
let _source = drm_device_bind(
|
let _source = drm_device_bind(
|
||||||
&mut event_loop,
|
&event_loop.token(),
|
||||||
device,
|
device,
|
||||||
DrmHandlerImpl {
|
DrmHandlerImpl {
|
||||||
compositor_token,
|
compositor_token,
|
||||||
|
@ -159,7 +158,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DrmHandlerImpl {
|
pub struct DrmHandlerImpl {
|
||||||
compositor_token: CompositorToken<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>>,
|
compositor_token: CompositorToken<SurfaceData, Roles>,
|
||||||
window_map: Rc<RefCell<MyWindowMap>>,
|
window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
drawer: GliumDrawer<DrmBackend<Card>>,
|
drawer: GliumDrawer<DrmBackend<Card>>,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
|
@ -167,8 +166,11 @@ pub struct DrmHandlerImpl {
|
||||||
|
|
||||||
impl DrmHandler<Card> for DrmHandlerImpl {
|
impl DrmHandler<Card> for DrmHandlerImpl {
|
||||||
fn ready(
|
fn ready(
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _device: &mut DrmDevice<Card>, _crtc: crtc::Handle,
|
&mut self,
|
||||||
_frame: u32, _duration: Duration,
|
_device: &mut DrmDevice<Card>,
|
||||||
|
_crtc: crtc::Handle,
|
||||||
|
_frame: u32,
|
||||||
|
_duration: Duration,
|
||||||
) {
|
) {
|
||||||
let mut frame = self.drawer.draw();
|
let mut frame = self.drawer.draw();
|
||||||
frame.clear_color(0.8, 0.8, 0.9, 1.0);
|
frame.clear_color(0.8, 0.8, 0.9, 1.0);
|
||||||
|
@ -215,8 +217,8 @@ impl DrmHandler<Card> for DrmHandlerImpl {
|
||||||
|
|
||||||
if let Some(ref texture) = attributes.user_data.texture {
|
if let Some(ref texture) = attributes.user_data.texture {
|
||||||
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
||||||
x += subdata.x;
|
x += subdata.location.0;
|
||||||
y += subdata.y;
|
y += subdata.location.1;
|
||||||
}
|
}
|
||||||
info!(self.logger, "Render window");
|
info!(self.logger, "Render window");
|
||||||
self.drawer.render_texture(
|
self.drawer.render_texture(
|
||||||
|
@ -248,7 +250,7 @@ impl DrmHandler<Card> for DrmHandlerImpl {
|
||||||
frame.finish().unwrap();
|
frame.finish().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error(&mut self, _evlh: &mut EventLoopHandle, _device: &mut DrmDevice<Card>, error: DrmError) {
|
fn error(&mut self, _device: &mut DrmDevice<Card>, error: DrmError) {
|
||||||
panic!("{:?}", error);
|
panic!("{:?}", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,8 +135,13 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_texture(
|
pub fn render_texture(
|
||||||
&self, target: &mut glium::Frame, texture: &Texture2d, y_inverted: bool,
|
&self,
|
||||||
surface_dimensions: (u32, u32), surface_location: (i32, i32), screen_size: (u32, u32),
|
target: &mut glium::Frame,
|
||||||
|
texture: &Texture2d,
|
||||||
|
y_inverted: bool,
|
||||||
|
surface_dimensions: (u32, u32),
|
||||||
|
surface_location: (i32, i32),
|
||||||
|
screen_size: (u32, u32),
|
||||||
blending: glium::Blend,
|
blending: glium::Blend,
|
||||||
) {
|
) {
|
||||||
let xscale = 2.0 * (surface_dimensions.0 as f32) / (screen_size.0 as f32);
|
let xscale = 2.0 * (surface_dimensions.0 as f32) / (screen_size.0 as f32);
|
||||||
|
|
|
@ -3,14 +3,15 @@ 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,
|
use smithay::wayland::compositor::{compositor_init, CompositorToken, SurfaceAttributes, SurfaceEvent};
|
||||||
SurfaceUserImplementation};
|
use smithay::wayland::shell::xdg::{xdg_shell_init, PopupConfigure, ShellEvent, ShellState, ShellSurfaceRole,
|
||||||
use smithay::wayland::shell::{shell_init, PopupConfigure, ShellState, ShellSurfaceRole,
|
ToplevelConfigure};
|
||||||
ShellSurfaceUserImplementation, ToplevelConfigure};
|
|
||||||
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 std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wayland_server::{EventLoop, StateToken};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use wayland_server::{Display, LoopToken, Resource};
|
||||||
|
use wayland_server::protocol::{wl_buffer, wl_callback, wl_surface};
|
||||||
|
|
||||||
define_roles!(Roles => [ ShellSurface, ShellSurfaceRole ] );
|
define_roles!(Roles => [ ShellSurface, ShellSurfaceRole ] );
|
||||||
|
|
||||||
|
@ -25,110 +26,62 @@ pub enum Buffer {
|
||||||
Shm { data: Vec<u8>, size: (u32, u32) },
|
Shm { data: Vec<u8>, size: (u32, u32) },
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn surface_implementation(
|
fn surface_commit(
|
||||||
) -> SurfaceUserImplementation<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>> {
|
surface: &Resource<wl_surface::WlSurface>,
|
||||||
SurfaceUserImplementation {
|
token: CompositorToken<SurfaceData, Roles>,
|
||||||
commit: |_, display, surface, token| {
|
display: &RefCell<Option<EGLDisplay>>,
|
||||||
// we retrieve the contents of the associated buffer and copy it
|
) {
|
||||||
token.with_surface_data(surface, |attributes| {
|
// we retrieve the contents of the associated buffer and copy it
|
||||||
match attributes.buffer.take() {
|
token.with_surface_data(surface, |attributes| {
|
||||||
Some(Some((buffer, (_x, _y)))) => {
|
match attributes.buffer.take() {
|
||||||
// we ignore hotspot coordinates in this simple example
|
Some(Some((buffer, (_x, _y)))) => {
|
||||||
match if let Some(display) = display.borrow().as_ref() {
|
// we ignore hotspot coordinates in this simple example
|
||||||
display.egl_buffer_contents(buffer)
|
match if let Some(display) = display.borrow().as_ref() {
|
||||||
} else {
|
display.egl_buffer_contents(buffer)
|
||||||
Err(BufferAccessError::NotManaged(buffer))
|
} else {
|
||||||
} {
|
Err(BufferAccessError::NotManaged(buffer))
|
||||||
Ok(images) => {
|
} {
|
||||||
match images.format {
|
Ok(images) => {
|
||||||
Format::RGB => {}
|
match images.format {
|
||||||
Format::RGBA => {}
|
Format::RGB => {}
|
||||||
_ => {
|
Format::RGBA => {}
|
||||||
// we don't handle the more complex formats here.
|
_ => {
|
||||||
attributes.user_data.buffer = None;
|
// we don't handle the more complex formats here.
|
||||||
attributes.user_data.texture = None;
|
attributes.user_data.buffer = None;
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
attributes.user_data.texture = None;
|
attributes.user_data.texture = None;
|
||||||
attributes.user_data.buffer = Some(Buffer::Egl { images });
|
return;
|
||||||
}
|
}
|
||||||
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.release();
|
|
||||||
}
|
|
||||||
Err(err) => panic!("EGL error: {}", err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(None) => {
|
|
||||||
// erase the contents
|
|
||||||
attributes.user_data.buffer = None;
|
|
||||||
attributes.user_data.texture = None;
|
attributes.user_data.texture = None;
|
||||||
|
attributes.user_data.buffer = Some(Buffer::Egl { images });
|
||||||
}
|
}
|
||||||
None => {}
|
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),
|
||||||
}
|
}
|
||||||
});
|
|
||||||
},
|
|
||||||
frame: |_, _, _, callback, _| {
|
|
||||||
callback.done(0);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ShellIData<F> {
|
|
||||||
pub token: CompositorToken<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>>,
|
|
||||||
pub window_map: Rc<RefCell<super::WindowMap<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, (), F>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn shell_implementation<F>(
|
|
||||||
) -> ShellSurfaceUserImplementation<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ShellIData<F>, ()>
|
|
||||||
where
|
|
||||||
F: Fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>,
|
|
||||||
{
|
|
||||||
ShellSurfaceUserImplementation {
|
|
||||||
new_client: |_, _, _| {},
|
|
||||||
client_pong: |_, _, _| {},
|
|
||||||
new_toplevel: |_, idata, toplevel| {
|
|
||||||
// place the window at a random location in the [0;300]x[0;300] square
|
|
||||||
use rand::distributions::{IndependentSample, Range};
|
|
||||||
let range = Range::new(0, 300);
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
let x = range.ind_sample(&mut rng);
|
|
||||||
let y = range.ind_sample(&mut rng);
|
|
||||||
idata.window_map.borrow_mut().insert(toplevel, (x, y));
|
|
||||||
ToplevelConfigure {
|
|
||||||
size: None,
|
|
||||||
states: vec![],
|
|
||||||
serial: 42,
|
|
||||||
}
|
}
|
||||||
},
|
Some(None) => {
|
||||||
new_popup: |_, _, _| PopupConfigure {
|
// erase the contents
|
||||||
size: (10, 10),
|
attributes.user_data.buffer = None;
|
||||||
position: (10, 10),
|
attributes.user_data.texture = None;
|
||||||
serial: 42,
|
}
|
||||||
},
|
None => {}
|
||||||
move_: |_, _, _, _, _| {},
|
}
|
||||||
resize: |_, _, _, _, _, _| {},
|
});
|
||||||
grab: |_, _, _, _, _| {},
|
|
||||||
change_display_state: |_, _, _, _, _, _, _| ToplevelConfigure {
|
|
||||||
size: None,
|
|
||||||
states: vec![],
|
|
||||||
serial: 42,
|
|
||||||
},
|
|
||||||
show_window_menu: |_, _, _, _, _, _, _| {},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_size(attrs: &SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)> {
|
fn get_size(attrs: &SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)> {
|
||||||
|
@ -143,38 +96,70 @@ fn get_size(attrs: &SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)> {
|
||||||
.map(|(x, y)| (x as i32, y as i32))
|
.map(|(x, y)| (x as i32, y as i32))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type MyWindowMap = WindowMap<
|
pub type MyWindowMap =
|
||||||
SurfaceData,
|
WindowMap<SurfaceData, Roles, (), fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>>;
|
||||||
Roles,
|
|
||||||
Rc<RefCell<Option<EGLDisplay>>>,
|
|
||||||
(),
|
|
||||||
fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
pub fn init_shell(
|
pub fn init_shell(
|
||||||
evl: &mut EventLoop, log: ::slog::Logger, data: Rc<RefCell<Option<EGLDisplay>>>
|
display: &mut Display,
|
||||||
|
looptoken: LoopToken,
|
||||||
|
log: ::slog::Logger,
|
||||||
|
egl_display: Rc<RefCell<Option<EGLDisplay>>>,
|
||||||
) -> (
|
) -> (
|
||||||
CompositorToken<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>>,
|
CompositorToken<SurfaceData, Roles>,
|
||||||
StateToken<ShellState<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ()>>,
|
Arc<Mutex<ShellState<SurfaceData, Roles, ()>>>,
|
||||||
Rc<RefCell<MyWindowMap>>,
|
Rc<RefCell<MyWindowMap>>,
|
||||||
) {
|
) {
|
||||||
let (compositor_token, _, _) = compositor_init(evl, surface_implementation(), data, log.clone());
|
// Create the compositor
|
||||||
|
let c_egl_display = egl_display.clone();
|
||||||
let window_map = Rc::new(RefCell::new(WindowMap::<_, _, _, (), _>::new(
|
let (compositor_token, _, _) = compositor_init(
|
||||||
compositor_token,
|
display,
|
||||||
get_size as _,
|
looptoken.clone(),
|
||||||
)));
|
move |request, (surface, ctoken)| match request {
|
||||||
|
SurfaceEvent::Commit => surface_commit(&surface, ctoken, &*c_egl_display),
|
||||||
let (shell_state_token, _, _) = shell_init(
|
SurfaceEvent::Frame { callback } => {
|
||||||
evl,
|
// TODO: uncomment when https://github.com/rust-lang/rust/issues/50153 is fixed
|
||||||
compositor_token,
|
// callback.implement(|e, _| match e {}, None::<fn(_,_)>).send(wl_callback::Event::Done { callback_data: 0})
|
||||||
shell_implementation(),
|
}
|
||||||
ShellIData {
|
|
||||||
token: compositor_token,
|
|
||||||
window_map: window_map.clone(),
|
|
||||||
},
|
},
|
||||||
log.clone(),
|
log.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
(compositor_token, shell_state_token, window_map)
|
// Init a window map, to track the location of our windows
|
||||||
|
let window_map = Rc::new(RefCell::new(WindowMap::<_, _, (), _>::new(
|
||||||
|
compositor_token,
|
||||||
|
get_size as _,
|
||||||
|
)));
|
||||||
|
|
||||||
|
// init the xdg_shell
|
||||||
|
let shell_window_map = window_map.clone();
|
||||||
|
let (shell_state, _, _) = xdg_shell_init(
|
||||||
|
display,
|
||||||
|
looptoken,
|
||||||
|
compositor_token.clone(),
|
||||||
|
move |shell_event, ()| match shell_event {
|
||||||
|
ShellEvent::NewToplevel { surface } => {
|
||||||
|
// place the window at a random location in the [0;300]x[0;300] square
|
||||||
|
use rand::distributions::{IndependentSample, Range};
|
||||||
|
let range = Range::new(0, 300);
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let x = range.ind_sample(&mut rng);
|
||||||
|
let y = range.ind_sample(&mut rng);
|
||||||
|
surface.send_configure(ToplevelConfigure {
|
||||||
|
size: None,
|
||||||
|
states: vec![],
|
||||||
|
serial: 42,
|
||||||
|
});
|
||||||
|
shell_window_map.borrow_mut().insert(surface, (x, y));
|
||||||
|
}
|
||||||
|
ShellEvent::NewPopup { surface } => surface.send_configure(PopupConfigure {
|
||||||
|
size: (10, 10),
|
||||||
|
position: (10, 10),
|
||||||
|
serial: 42,
|
||||||
|
}),
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
log.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
(compositor_token, shell_state, window_map)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,29 @@
|
||||||
use smithay::utils::Rectangle;
|
use smithay::utils::Rectangle;
|
||||||
use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, SurfaceAttributes, TraversalAction};
|
use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, SurfaceAttributes, TraversalAction};
|
||||||
use smithay::wayland::compositor::roles::Role;
|
use smithay::wayland::compositor::roles::Role;
|
||||||
use smithay::wayland::shell::{ShellSurfaceRole, ToplevelSurface};
|
use smithay::wayland::shell::xdg::{ShellSurfaceRole, ToplevelSurface};
|
||||||
use wayland_server::Resource;
|
use wayland_server::Resource;
|
||||||
use wayland_server::protocol::wl_surface;
|
use wayland_server::protocol::wl_surface;
|
||||||
|
|
||||||
struct Window<U, R, CID, SD> {
|
struct Window<U, R, SD> {
|
||||||
location: (i32, i32),
|
location: (i32, i32),
|
||||||
surface: Rectangle,
|
surface: Rectangle,
|
||||||
toplevel: ToplevelSurface<U, R, CID, SD>,
|
toplevel: ToplevelSurface<U, R, SD>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<U, R, CID, SD> Window<U, R, CID, SD>
|
impl<U, R, SD> Window<U, R, SD>
|
||||||
where
|
where
|
||||||
U: 'static,
|
U: 'static,
|
||||||
R: Role<SubsurfaceRole> + Role<ShellSurfaceRole> + 'static,
|
R: Role<SubsurfaceRole> + Role<ShellSurfaceRole> + 'static,
|
||||||
CID: 'static,
|
|
||||||
SD: 'static,
|
SD: 'static,
|
||||||
{
|
{
|
||||||
// Find the topmost surface under this point if any and the location of this point in the surface
|
// Find the topmost surface under this point if any and the location of this point in the surface
|
||||||
fn matching<F>(
|
fn matching<F>(
|
||||||
&self, point: (f64, f64), ctoken: CompositorToken<U, R, CID>, get_size: F
|
&self,
|
||||||
) -> Option<(wl_surface::WlSurface, (f64, f64))>
|
point: (f64, f64),
|
||||||
|
ctoken: CompositorToken<U, R>,
|
||||||
|
get_size: F,
|
||||||
|
) -> Option<(Resource<wl_surface::WlSurface>, (f64, f64))>
|
||||||
where
|
where
|
||||||
F: Fn(&SurfaceAttributes<U>) -> Option<(i32, i32)>,
|
F: Fn(&SurfaceAttributes<U>) -> Option<(i32, i32)>,
|
||||||
{
|
{
|
||||||
|
@ -37,8 +39,8 @@ where
|
||||||
|wl_surface, attributes, role, &(mut x, mut y)| {
|
|wl_surface, attributes, role, &(mut x, mut y)| {
|
||||||
if let Some((w, h)) = get_size(attributes) {
|
if let Some((w, h)) = get_size(attributes) {
|
||||||
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
||||||
x += subdata.x;
|
x += subdata.location.0;
|
||||||
y += subdata.y;
|
y += subdata.location.1;
|
||||||
}
|
}
|
||||||
let my_rect = Rectangle {
|
let my_rect = Rectangle {
|
||||||
x,
|
x,
|
||||||
|
@ -47,9 +49,10 @@ where
|
||||||
height: h,
|
height: h,
|
||||||
};
|
};
|
||||||
if my_rect.contains((point.0 as i32, point.1 as i32)) {
|
if my_rect.contains((point.0 as i32, point.1 as i32)) {
|
||||||
found = wl_surface
|
found = Some((
|
||||||
.clone()
|
wl_surface.clone(),
|
||||||
.map(|s| (s, (point.0 - my_rect.x as f64, point.1 - my_rect.y as f64)));
|
(point.0 - my_rect.x as f64, point.1 - my_rect.y as f64),
|
||||||
|
));
|
||||||
TraversalAction::Break
|
TraversalAction::Break
|
||||||
} else {
|
} else {
|
||||||
TraversalAction::DoChildren((x, y))
|
TraversalAction::DoChildren((x, y))
|
||||||
|
@ -63,7 +66,7 @@ where
|
||||||
found
|
found
|
||||||
}
|
}
|
||||||
|
|
||||||
fn self_update<F>(&mut self, ctoken: CompositorToken<U, R, CID>, get_size: F)
|
fn self_update<F>(&mut self, ctoken: CompositorToken<U, R>, get_size: F)
|
||||||
where
|
where
|
||||||
F: Fn(&SurfaceAttributes<U>) -> Option<(i32, i32)>,
|
F: Fn(&SurfaceAttributes<U>) -> Option<(i32, i32)>,
|
||||||
{
|
{
|
||||||
|
@ -76,8 +79,8 @@ where
|
||||||
|_, attributes, role, &(mut x, mut y)| {
|
|_, attributes, role, &(mut x, mut y)| {
|
||||||
if let Some((w, h)) = get_size(attributes) {
|
if let Some((w, h)) = get_size(attributes) {
|
||||||
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
||||||
x += subdata.x;
|
x += subdata.location.0;
|
||||||
y += subdata.y;
|
y += subdata.location.1;
|
||||||
}
|
}
|
||||||
// update the bounding box
|
// update the bounding box
|
||||||
if x < min_x {
|
if x < min_x {
|
||||||
|
@ -108,21 +111,20 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WindowMap<U, R, CID, SD, F> {
|
pub struct WindowMap<U, R, SD, F> {
|
||||||
ctoken: CompositorToken<U, R, CID>,
|
ctoken: CompositorToken<U, R>,
|
||||||
windows: Vec<Window<U, R, CID, SD>>,
|
windows: Vec<Window<U, R, SD>>,
|
||||||
get_size: F,
|
get_size: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<U, R, CID, SD, F> WindowMap<U, R, CID, SD, F>
|
impl<U, R, SD, F> WindowMap<U, R, SD, F>
|
||||||
where
|
where
|
||||||
F: Fn(&SurfaceAttributes<U>) -> Option<(i32, i32)>,
|
F: Fn(&SurfaceAttributes<U>) -> Option<(i32, i32)>,
|
||||||
U: 'static,
|
U: 'static,
|
||||||
R: Role<SubsurfaceRole> + Role<ShellSurfaceRole> + 'static,
|
R: Role<SubsurfaceRole> + Role<ShellSurfaceRole> + 'static,
|
||||||
CID: 'static,
|
|
||||||
SD: 'static,
|
SD: 'static,
|
||||||
{
|
{
|
||||||
pub fn new(ctoken: CompositorToken<U, R, CID>, get_size: F) -> WindowMap<U, R, CID, SD, F> {
|
pub fn new(ctoken: CompositorToken<U, R>, get_size: F) -> WindowMap<U, R, SD, F> {
|
||||||
WindowMap {
|
WindowMap {
|
||||||
ctoken: ctoken,
|
ctoken: ctoken,
|
||||||
windows: Vec::new(),
|
windows: Vec::new(),
|
||||||
|
@ -130,7 +132,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, toplevel: ToplevelSurface<U, R, CID, SD>, location: (i32, i32)) {
|
pub fn insert(&mut self, toplevel: ToplevelSurface<U, R, SD>, location: (i32, i32)) {
|
||||||
let mut window = Window {
|
let mut window = Window {
|
||||||
location: location,
|
location: location,
|
||||||
surface: Rectangle {
|
surface: Rectangle {
|
||||||
|
@ -145,7 +147,10 @@ where
|
||||||
self.windows.insert(0, window);
|
self.windows.insert(0, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_surface_under(&self, point: (f64, f64)) -> Option<(wl_surface::WlSurface, (f64, f64))> {
|
pub fn get_surface_under(
|
||||||
|
&self,
|
||||||
|
point: (f64, f64),
|
||||||
|
) -> Option<(Resource<wl_surface::WlSurface>, (f64, f64))> {
|
||||||
for w in &self.windows {
|
for w in &self.windows {
|
||||||
if let Some(surface) = w.matching(point, self.ctoken, &self.get_size) {
|
if let Some(surface) = w.matching(point, self.ctoken, &self.get_size) {
|
||||||
return Some(surface);
|
return Some(surface);
|
||||||
|
@ -155,8 +160,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_surface_and_bring_to_top(
|
pub fn get_surface_and_bring_to_top(
|
||||||
&mut self, point: (f64, f64)
|
&mut self,
|
||||||
) -> Option<(wl_surface::WlSurface, (f64, f64))> {
|
point: (f64, f64),
|
||||||
|
) -> Option<(Resource<wl_surface::WlSurface>, (f64, f64))> {
|
||||||
let mut found = None;
|
let mut found = None;
|
||||||
for (i, w) in self.windows.iter().enumerate() {
|
for (i, w) in self.windows.iter().enumerate() {
|
||||||
if let Some(surface) = w.matching(point, self.ctoken, &self.get_size) {
|
if let Some(surface) = w.matching(point, self.ctoken, &self.get_size) {
|
||||||
|
@ -175,7 +181,7 @@ where
|
||||||
|
|
||||||
pub fn with_windows_from_bottom_to_top<Func>(&self, mut f: Func)
|
pub fn with_windows_from_bottom_to_top<Func>(&self, mut f: Func)
|
||||||
where
|
where
|
||||||
Func: FnMut(&ToplevelSurface<U, R, CID, SD>, (i32, i32)),
|
Func: FnMut(&ToplevelSurface<U, R, SD>, (i32, i32)),
|
||||||
{
|
{
|
||||||
for w in self.windows.iter().rev() {
|
for w in self.windows.iter().rev() {
|
||||||
f(&w.toplevel, w.location)
|
f(&w.toplevel, w.location)
|
||||||
|
|
193
examples/udev.rs
193
examples/udev.rs
|
@ -53,9 +53,9 @@ use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use wayland_server::{Display, EventLoopHandle};
|
use wayland_server::Display;
|
||||||
|
use wayland_server::commons::downcast_impl;
|
||||||
use wayland_server::protocol::{wl_output, wl_pointer};
|
use wayland_server::protocol::{wl_output, wl_pointer};
|
||||||
use wayland_server::sources::EventSource;
|
|
||||||
use xkbcommon::xkb::keysyms as xkb;
|
use xkbcommon::xkb::keysyms as xkb;
|
||||||
|
|
||||||
struct LibinputInputHandler {
|
struct LibinputInputHandler {
|
||||||
|
@ -78,18 +78,16 @@ impl LibinputInputHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
fn on_seat_created(&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat) {
|
fn on_seat_created(&mut self, _: &input::Seat) {
|
||||||
/* we just create a single static one */
|
/* we just create a single static one */
|
||||||
}
|
}
|
||||||
fn on_seat_destroyed(&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat) {
|
fn on_seat_destroyed(&mut self, _: &input::Seat) {
|
||||||
/* we just create a single static one */
|
/* we just create a single static one */
|
||||||
}
|
}
|
||||||
fn on_seat_changed(&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat) {
|
fn on_seat_changed(&mut self, _: &input::Seat) {
|
||||||
/* we just create a single static one */
|
/* we just create a single static one */
|
||||||
}
|
}
|
||||||
fn on_keyboard_key(
|
fn on_keyboard_key(&mut self, _: &input::Seat, evt: event::keyboard::KeyboardKeyEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, evt: event::keyboard::KeyboardKeyEvent
|
|
||||||
) {
|
|
||||||
let keycode = evt.key();
|
let keycode = evt.key();
|
||||||
let state = evt.state();
|
let state = evt.state();
|
||||||
debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state));
|
debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state));
|
||||||
|
@ -100,8 +98,9 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
let running = &self.running;
|
let running = &self.running;
|
||||||
let mut session = &mut self.session;
|
let mut session = &mut self.session;
|
||||||
let log = &self.log;
|
let log = &self.log;
|
||||||
|
let time = Event::time(&evt);
|
||||||
self.keyboard
|
self.keyboard
|
||||||
.input(keycode, state, serial, 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
|
||||||
|
@ -132,9 +131,7 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
fn on_pointer_move(
|
fn on_pointer_move(&mut self, _: &input::Seat, evt: event::pointer::PointerMotionEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, evt: event::pointer::PointerMotionEvent
|
|
||||||
) {
|
|
||||||
let (x, y) = (evt.dx(), evt.dy());
|
let (x, y) = (evt.dx(), evt.dy());
|
||||||
let serial = self.next_serial();
|
let serial = self.next_serial();
|
||||||
let mut location = self.pointer_location.borrow_mut();
|
let mut location = self.pointer_location.borrow_mut();
|
||||||
|
@ -149,10 +146,7 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
evt.time(),
|
evt.time(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
fn on_pointer_move_absolute(
|
fn on_pointer_move_absolute(&mut self, _: &input::Seat, evt: event::pointer::PointerMotionAbsoluteEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat,
|
|
||||||
evt: event::pointer::PointerMotionAbsoluteEvent,
|
|
||||||
) {
|
|
||||||
let (x, y) = (
|
let (x, y) = (
|
||||||
evt.absolute_x_transformed(self.screen_size.0),
|
evt.absolute_x_transformed(self.screen_size.0),
|
||||||
evt.absolute_y_transformed(self.screen_size.1),
|
evt.absolute_y_transformed(self.screen_size.1),
|
||||||
|
@ -166,9 +160,7 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
evt.time(),
|
evt.time(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
fn on_pointer_button(
|
fn on_pointer_button(&mut self, _: &input::Seat, evt: event::pointer::PointerButtonEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, evt: event::pointer::PointerButtonEvent
|
|
||||||
) {
|
|
||||||
let serial = self.next_serial();
|
let serial = self.next_serial();
|
||||||
let button = evt.button();
|
let button = evt.button();
|
||||||
let state = match evt.state() {
|
let state = match evt.state() {
|
||||||
|
@ -185,9 +177,7 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
};
|
};
|
||||||
self.pointer.button(button, state, serial, evt.time());
|
self.pointer.button(button, state, serial, evt.time());
|
||||||
}
|
}
|
||||||
fn on_pointer_axis(
|
fn on_pointer_axis(&mut self, _: &input::Seat, evt: event::pointer::PointerAxisEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &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 => wayland_server::protocol::wl_pointer::AxisSource::Continuous,
|
||||||
input::AxisSource::Finger => wayland_server::protocol::wl_pointer::AxisSource::Finger,
|
input::AxisSource::Finger => wayland_server::protocol::wl_pointer::AxisSource::Finger,
|
||||||
|
@ -244,30 +234,22 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
event.done();
|
event.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn on_touch_down(
|
fn on_touch_down(&mut self, _: &input::Seat, _: event::touch::TouchDownEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, _: event::touch::TouchDownEvent
|
|
||||||
) {
|
|
||||||
/* not done in this example */
|
/* not done in this example */
|
||||||
}
|
}
|
||||||
fn on_touch_motion(
|
fn on_touch_motion(&mut self, _: &input::Seat, _: event::touch::TouchMotionEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, _: event::touch::TouchMotionEvent
|
|
||||||
) {
|
|
||||||
/* not done in this example */
|
/* not done in this example */
|
||||||
}
|
}
|
||||||
fn on_touch_up(&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, _: event::touch::TouchUpEvent) {
|
fn on_touch_up(&mut self, _: &input::Seat, _: event::touch::TouchUpEvent) {
|
||||||
/* not done in this example */
|
/* not done in this example */
|
||||||
}
|
}
|
||||||
fn on_touch_cancel(
|
fn on_touch_cancel(&mut self, _: &input::Seat, _: event::touch::TouchCancelEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, _: event::touch::TouchCancelEvent
|
|
||||||
) {
|
|
||||||
/* not done in this example */
|
/* not done in this example */
|
||||||
}
|
}
|
||||||
fn on_touch_frame(
|
fn on_touch_frame(&mut self, _: &input::Seat, _: event::touch::TouchFrameEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, _: event::touch::TouchFrameEvent
|
|
||||||
) {
|
|
||||||
/* not done in this example */
|
/* not done in this example */
|
||||||
}
|
}
|
||||||
fn on_input_config_changed(&mut self, _evlh: &mut EventLoopHandle, _: &mut [LibinputDevice]) {
|
fn on_input_config_changed(&mut self, _: &mut [LibinputDevice]) {
|
||||||
/* not done in this example */
|
/* not done in this example */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,7 +266,7 @@ fn main() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Initialize the wayland server
|
// Initialize the wayland server
|
||||||
let (mut display, mut event_loop) = wayland_server::create_display();
|
let (mut display, mut event_loop) = wayland_server::Display::new();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a listening socket
|
* Add a listening socket
|
||||||
|
@ -292,15 +274,24 @@ fn main() {
|
||||||
let name = display.add_socket_auto().unwrap().into_string().unwrap();
|
let name = display.add_socket_auto().unwrap().into_string().unwrap();
|
||||||
println!("Listening on socket: {}", name);
|
println!("Listening on socket: {}", name);
|
||||||
env::set_var("WAYLAND_DISPLAY", name);
|
env::set_var("WAYLAND_DISPLAY", name);
|
||||||
let display = Rc::new(display);
|
let display = Rc::new(RefCell::new(display));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the compositor
|
* Initialize the compositor
|
||||||
*/
|
*/
|
||||||
init_shm_global(&mut event_loop, vec![], log.clone());
|
init_shm_global(
|
||||||
|
&mut display.borrow_mut(),
|
||||||
|
event_loop.token(),
|
||||||
|
vec![],
|
||||||
|
log.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
let (compositor_token, _shell_state_token, window_map) =
|
let (compositor_token, _shell_state_token, window_map) = init_shell(
|
||||||
init_shell(&mut event_loop, log.clone(), active_egl_context.clone());
|
&mut display.borrow_mut(),
|
||||||
|
event_loop.token(),
|
||||||
|
log.clone(),
|
||||||
|
active_egl_context.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize session
|
* Initialize session
|
||||||
|
@ -321,7 +312,7 @@ fn main() {
|
||||||
|
|
||||||
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(
|
||||||
&mut event_loop,
|
event_loop.token(),
|
||||||
&context,
|
&context,
|
||||||
session.clone(),
|
session.clone(),
|
||||||
UdevHandlerImpl {
|
UdevHandlerImpl {
|
||||||
|
@ -340,17 +331,21 @@ fn main() {
|
||||||
|
|
||||||
let udev_session_id = notifier.register(&mut udev_backend);
|
let udev_session_id = notifier.register(&mut udev_backend);
|
||||||
|
|
||||||
let (seat_token, _) = Seat::new(&mut event_loop, session.seat().into(), log.clone());
|
let (mut w_seat, _) = Seat::new(
|
||||||
|
&mut display.borrow_mut(),
|
||||||
|
event_loop.token(),
|
||||||
|
session.seat().into(),
|
||||||
|
log.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
let pointer = event_loop.state().get_mut(&seat_token).add_pointer();
|
let pointer = w_seat.add_pointer();
|
||||||
let keyboard = event_loop
|
let keyboard = w_seat
|
||||||
.state()
|
|
||||||
.get_mut(&seat_token)
|
|
||||||
.add_keyboard("", "", "", None, 1000, 500)
|
.add_keyboard("", "", "", None, 1000, 500)
|
||||||
.expect("Failed to initialize the keyboard");
|
.expect("Failed to initialize the keyboard");
|
||||||
|
|
||||||
let (output_token, _output_global) = Output::new(
|
let (output, _output_global) = Output::new(
|
||||||
&mut event_loop,
|
&mut display.borrow_mut(),
|
||||||
|
event_loop.token(),
|
||||||
"Drm".into(),
|
"Drm".into(),
|
||||||
PhysicalProperties {
|
PhysicalProperties {
|
||||||
width: 0,
|
width: 0,
|
||||||
|
@ -363,26 +358,20 @@ fn main() {
|
||||||
);
|
);
|
||||||
|
|
||||||
let (w, h) = (1920, 1080); // Hardcode full-hd res
|
let (w, h) = (1920, 1080); // Hardcode full-hd res
|
||||||
event_loop
|
output.change_current_state(
|
||||||
.state()
|
Some(Mode {
|
||||||
.get_mut(&output_token)
|
|
||||||
.change_current_state(
|
|
||||||
Some(Mode {
|
|
||||||
width: w as i32,
|
|
||||||
height: h as i32,
|
|
||||||
refresh: 60_000,
|
|
||||||
}),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
event_loop
|
|
||||||
.state()
|
|
||||||
.get_mut(&output_token)
|
|
||||||
.set_preferred(Mode {
|
|
||||||
width: w as i32,
|
width: w as i32,
|
||||||
height: h as i32,
|
height: h as i32,
|
||||||
refresh: 60_000,
|
refresh: 60_000,
|
||||||
});
|
}),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
output.set_preferred(Mode {
|
||||||
|
width: w as i32,
|
||||||
|
height: h as i32,
|
||||||
|
refresh: 60_000,
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize libinput backend
|
* Initialize libinput backend
|
||||||
|
@ -392,28 +381,25 @@ fn main() {
|
||||||
let libinput_session_id = notifier.register(&mut libinput_context);
|
let libinput_session_id = notifier.register(&mut libinput_context);
|
||||||
libinput_context.udev_assign_seat(&seat).unwrap();
|
libinput_context.udev_assign_seat(&seat).unwrap();
|
||||||
let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
|
let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
|
||||||
libinput_backend.set_handler(
|
libinput_backend.set_handler(LibinputInputHandler {
|
||||||
&mut event_loop,
|
log: log.clone(),
|
||||||
LibinputInputHandler {
|
pointer,
|
||||||
log: log.clone(),
|
keyboard,
|
||||||
pointer,
|
window_map: window_map.clone(),
|
||||||
keyboard,
|
pointer_location,
|
||||||
window_map: window_map.clone(),
|
screen_size: (w, h),
|
||||||
pointer_location,
|
serial: 0,
|
||||||
screen_size: (w, h),
|
session: session,
|
||||||
serial: 0,
|
running: running.clone(),
|
||||||
session: session,
|
});
|
||||||
running: running.clone(),
|
let libinput_event_source = libinput_bind(libinput_backend, event_loop.token())
|
||||||
},
|
|
||||||
);
|
|
||||||
let libinput_event_source = libinput_bind(libinput_backend, &mut event_loop)
|
|
||||||
.map_err(|(err, _)| err)
|
.map_err(|(err, _)| err)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let session_event_source = auto_session_bind(notifier, &mut event_loop)
|
let session_event_source = auto_session_bind(notifier, &event_loop.token())
|
||||||
.map_err(|(err, _)| err)
|
.map_err(|(err, _)| err)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let udev_event_source = udev_backend_bind(&mut event_loop, udev_backend)
|
let udev_event_source = udev_backend_bind(&event_loop.token(), udev_backend)
|
||||||
.map_err(|(err, _)| err)
|
.map_err(|(err, _)| err)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -421,7 +407,7 @@ fn main() {
|
||||||
if let Err(_) = event_loop.dispatch(Some(16)) {
|
if let Err(_) = event_loop.dispatch(Some(16)) {
|
||||||
running.store(false, Ordering::SeqCst);
|
running.store(false, Ordering::SeqCst);
|
||||||
} else {
|
} else {
|
||||||
display.flush_clients();
|
display.borrow_mut().flush_clients();
|
||||||
window_map.borrow_mut().refresh();
|
window_map.borrow_mut().refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -435,14 +421,15 @@ fn main() {
|
||||||
libinput_event_source.remove();
|
libinput_event_source.remove();
|
||||||
|
|
||||||
// destroy the udev backend freeing the drm devices
|
// destroy the udev backend freeing the drm devices
|
||||||
udev_event_source.remove().close(&mut event_loop)
|
udev_backend = *(downcast_impl(udev_event_source.remove()).unwrap_or_else(|_| unreachable!()));
|
||||||
|
udev_backend.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UdevHandlerImpl {
|
struct UdevHandlerImpl {
|
||||||
compositor_token: CompositorToken<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>>,
|
compositor_token: CompositorToken<SurfaceData, Roles>,
|
||||||
active_egl_context: Rc<RefCell<Option<EGLDisplay>>>,
|
active_egl_context: Rc<RefCell<Option<EGLDisplay>>>,
|
||||||
backends: HashMap<u64, Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>>>>>,
|
backends: HashMap<u64, Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>>>>>,
|
||||||
display: Rc<Display>,
|
display: Rc<RefCell<Display>>,
|
||||||
primary_gpu: Option<PathBuf>,
|
primary_gpu: Option<PathBuf>,
|
||||||
window_map: Rc<RefCell<MyWindowMap>>,
|
window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
pointer_location: Rc<RefCell<(f64, f64)>>,
|
pointer_location: Rc<RefCell<(f64, f64)>>,
|
||||||
|
@ -452,7 +439,8 @@ struct UdevHandlerImpl {
|
||||||
|
|
||||||
impl UdevHandlerImpl {
|
impl UdevHandlerImpl {
|
||||||
pub fn scan_connectors(
|
pub fn scan_connectors(
|
||||||
&self, device: &mut DrmDevice<SessionFdDrmDevice>
|
&self,
|
||||||
|
device: &mut DrmDevice<SessionFdDrmDevice>,
|
||||||
) -> HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>> {
|
) -> HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>> {
|
||||||
// Get a set of all modesetting resource handles (excluding planes):
|
// Get a set of all modesetting resource handles (excluding planes):
|
||||||
let res_handles = device.resource_handles().unwrap();
|
let res_handles = device.resource_handles().unwrap();
|
||||||
|
@ -511,12 +499,10 @@ impl UdevHandlerImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {
|
impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {
|
||||||
fn device_added(
|
fn device_added(&mut self, device: &mut DrmDevice<SessionFdDrmDevice>) -> Option<DrmHandlerImpl> {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>
|
|
||||||
) -> Option<DrmHandlerImpl> {
|
|
||||||
// init hardware acceleration on the primary gpu.
|
// init hardware acceleration on the primary gpu.
|
||||||
if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu {
|
if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu {
|
||||||
*self.active_egl_context.borrow_mut() = device.bind_wl_display(&*self.display).ok();
|
*self.active_egl_context.borrow_mut() = device.bind_wl_display(&*self.display.borrow()).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
let backends = Rc::new(RefCell::new(self.scan_connectors(device)));
|
let backends = Rc::new(RefCell::new(self.scan_connectors(device)));
|
||||||
|
@ -531,13 +517,13 @@ impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn device_changed(&mut self, _evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>) {
|
fn device_changed(&mut self, device: &mut DrmDevice<SessionFdDrmDevice>) {
|
||||||
//quick and dirt, just re-init all backends
|
//quick and dirt, just re-init all backends
|
||||||
let backends = self.backends.get(&device.device_id()).unwrap();
|
let backends = self.backends.get(&device.device_id()).unwrap();
|
||||||
*backends.borrow_mut() = self.scan_connectors(device);
|
*backends.borrow_mut() = self.scan_connectors(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn device_removed(&mut self, _evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>) {
|
fn device_removed(&mut self, device: &mut DrmDevice<SessionFdDrmDevice>) {
|
||||||
// drop the backends on this side
|
// drop the backends on this side
|
||||||
self.backends.remove(&device.device_id());
|
self.backends.remove(&device.device_id());
|
||||||
|
|
||||||
|
@ -547,13 +533,13 @@ impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error(&mut self, _evlh: &mut EventLoopHandle, error: IoError) {
|
fn error(&mut self, error: IoError) {
|
||||||
error!(self.logger, "{:?}", error);
|
error!(self.logger, "{:?}", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DrmHandlerImpl {
|
pub struct DrmHandlerImpl {
|
||||||
compositor_token: CompositorToken<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>>,
|
compositor_token: CompositorToken<SurfaceData, Roles>,
|
||||||
backends: Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>>>>,
|
backends: Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>>>>,
|
||||||
window_map: Rc<RefCell<MyWindowMap>>,
|
window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
pointer_location: Rc<RefCell<(f64, f64)>>,
|
pointer_location: Rc<RefCell<(f64, f64)>>,
|
||||||
|
@ -562,8 +548,11 @@ pub struct DrmHandlerImpl {
|
||||||
|
|
||||||
impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
|
impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
|
||||||
fn ready(
|
fn ready(
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _device: &mut DrmDevice<SessionFdDrmDevice>,
|
&mut self,
|
||||||
crtc: crtc::Handle, _frame: u32, _duration: Duration,
|
_device: &mut DrmDevice<SessionFdDrmDevice>,
|
||||||
|
crtc: crtc::Handle,
|
||||||
|
_frame: u32,
|
||||||
|
_duration: Duration,
|
||||||
) {
|
) {
|
||||||
if let Some(drawer) = self.backends.borrow().get(&crtc) {
|
if let Some(drawer) = self.backends.borrow().get(&crtc) {
|
||||||
{
|
{
|
||||||
|
@ -616,8 +605,8 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
|
||||||
|
|
||||||
if let Some(ref texture) = attributes.user_data.texture {
|
if let Some(ref texture) = attributes.user_data.texture {
|
||||||
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
||||||
x += subdata.x;
|
x += subdata.location.0;
|
||||||
y += subdata.y;
|
y += subdata.location.1;
|
||||||
}
|
}
|
||||||
info!(self.logger, "Render window");
|
info!(self.logger, "Render window");
|
||||||
drawer.render_texture(
|
drawer.render_texture(
|
||||||
|
@ -655,9 +644,7 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error(
|
fn error(&mut self, _device: &mut DrmDevice<SessionFdDrmDevice>, error: DrmError) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _device: &mut DrmDevice<SessionFdDrmDevice>, error: DrmError
|
|
||||||
) {
|
|
||||||
error!(self.logger, "{:?}", error);
|
error!(self.logger, "{:?}", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat};
|
||||||
use smithay::wayland::shm::init_shm_global;
|
use smithay::wayland::shm::init_shm_global;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wayland_server::EventLoopHandle;
|
use wayland_server::Display;
|
||||||
use wayland_server::protocol::{wl_output, wl_pointer};
|
use wayland_server::protocol::{wl_output, wl_pointer};
|
||||||
|
|
||||||
struct WinitInputHandler {
|
struct WinitInputHandler {
|
||||||
|
@ -46,30 +46,27 @@ impl WinitInputHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputHandler<winit::WinitInputBackend> for WinitInputHandler {
|
impl InputHandler<winit::WinitInputBackend> for WinitInputHandler {
|
||||||
fn on_seat_created(&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat) {
|
fn on_seat_created(&mut self, _: &input::Seat) {
|
||||||
/* never happens with winit */
|
/* never happens with winit */
|
||||||
}
|
}
|
||||||
fn on_seat_destroyed(&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat) {
|
fn on_seat_destroyed(&mut self, _: &input::Seat) {
|
||||||
/* never happens with winit */
|
/* never happens with winit */
|
||||||
}
|
}
|
||||||
fn on_seat_changed(&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat) {
|
fn on_seat_changed(&mut self, _: &input::Seat) {
|
||||||
/* never happens with winit */
|
/* never happens with winit */
|
||||||
}
|
}
|
||||||
fn on_keyboard_key(
|
fn on_keyboard_key(&mut self, _: &input::Seat, evt: winit::WinitKeyboardInputEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, evt: winit::WinitKeyboardInputEvent
|
|
||||||
) {
|
|
||||||
let keycode = evt.key_code();
|
let keycode = evt.key_code();
|
||||||
let state = evt.state();
|
let state = evt.state();
|
||||||
debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state));
|
debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state));
|
||||||
let serial = self.next_serial();
|
let serial = self.next_serial();
|
||||||
self.keyboard.input(keycode, state, serial, |_, _| true);
|
self.keyboard
|
||||||
|
.input(keycode, state, serial, evt.time(), |_, _| true);
|
||||||
}
|
}
|
||||||
fn on_pointer_move(&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, _: input::UnusedEvent) {
|
fn on_pointer_move(&mut self, _: &input::Seat, _: input::UnusedEvent) {
|
||||||
/* never happens with winit */
|
/* never happens with winit */
|
||||||
}
|
}
|
||||||
fn on_pointer_move_absolute(
|
fn on_pointer_move_absolute(&mut self, _: &input::Seat, evt: winit::WinitMouseMovedEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, evt: winit::WinitMouseMovedEvent
|
|
||||||
) {
|
|
||||||
// on winit, mouse events are already in pixel coordinates
|
// on winit, mouse events are already in pixel coordinates
|
||||||
let (x, y) = evt.position();
|
let (x, y) = evt.position();
|
||||||
self.pointer_location = (x, y);
|
self.pointer_location = (x, y);
|
||||||
|
@ -81,9 +78,7 @@ impl InputHandler<winit::WinitInputBackend> for WinitInputHandler {
|
||||||
evt.time(),
|
evt.time(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
fn on_pointer_button(
|
fn on_pointer_button(&mut self, _: &input::Seat, evt: winit::WinitMouseInputEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, evt: winit::WinitMouseInputEvent
|
|
||||||
) {
|
|
||||||
let serial = self.next_serial();
|
let serial = self.next_serial();
|
||||||
let button = match evt.button() {
|
let button = match evt.button() {
|
||||||
input::MouseButton::Left => 0x110,
|
input::MouseButton::Left => 0x110,
|
||||||
|
@ -105,9 +100,7 @@ impl InputHandler<winit::WinitInputBackend> for WinitInputHandler {
|
||||||
};
|
};
|
||||||
self.pointer.button(button, state, serial, evt.time());
|
self.pointer.button(button, state, serial, evt.time());
|
||||||
}
|
}
|
||||||
fn on_pointer_axis(
|
fn on_pointer_axis(&mut self, _: &input::Seat, evt: winit::WinitMouseWheelEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &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 => wayland_server::protocol::wl_pointer::AxisSource::Continuous,
|
||||||
input::AxisSource::Wheel => wayland_server::protocol::wl_pointer::AxisSource::Wheel,
|
input::AxisSource::Wheel => wayland_server::protocol::wl_pointer::AxisSource::Wheel,
|
||||||
|
@ -152,28 +145,22 @@ impl InputHandler<winit::WinitInputBackend> for WinitInputHandler {
|
||||||
event.done();
|
event.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn on_touch_down(
|
fn on_touch_down(&mut self, _: &input::Seat, _: winit::WinitTouchStartedEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, _: winit::WinitTouchStartedEvent
|
|
||||||
) {
|
|
||||||
/* not done in this example */
|
/* not done in this example */
|
||||||
}
|
}
|
||||||
fn on_touch_motion(
|
fn on_touch_motion(&mut self, _: &input::Seat, _: winit::WinitTouchMovedEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, _: winit::WinitTouchMovedEvent
|
|
||||||
) {
|
|
||||||
/* not done in this example */
|
/* not done in this example */
|
||||||
}
|
}
|
||||||
fn on_touch_up(&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, _: winit::WinitTouchEndedEvent) {
|
fn on_touch_up(&mut self, _: &input::Seat, _: winit::WinitTouchEndedEvent) {
|
||||||
/* not done in this example */
|
/* not done in this example */
|
||||||
}
|
}
|
||||||
fn on_touch_cancel(
|
fn on_touch_cancel(&mut self, _: &input::Seat, _: winit::WinitTouchCancelledEvent) {
|
||||||
&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, _: winit::WinitTouchCancelledEvent
|
|
||||||
) {
|
|
||||||
/* not done in this example */
|
/* not done in this example */
|
||||||
}
|
}
|
||||||
fn on_touch_frame(&mut self, _evlh: &mut EventLoopHandle, _: &input::Seat, _: input::UnusedEvent) {
|
fn on_touch_frame(&mut self, _: &input::Seat, _: input::UnusedEvent) {
|
||||||
/* never happens with winit */
|
/* never happens with winit */
|
||||||
}
|
}
|
||||||
fn on_input_config_changed(&mut self, _evlh: &mut EventLoopHandle, _: &mut ()) {
|
fn on_input_config_changed(&mut self, _: &mut ()) {
|
||||||
/* never happens with winit */
|
/* never happens with winit */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,7 +175,7 @@ fn main() {
|
||||||
// Initialize a simple backend for testing
|
// Initialize a simple backend for testing
|
||||||
let (renderer, mut input) = winit::init(log.clone()).unwrap();
|
let (renderer, mut input) = winit::init(log.clone()).unwrap();
|
||||||
|
|
||||||
let (mut display, mut event_loop) = wayland_server::create_display();
|
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) {
|
||||||
|
@ -206,22 +193,25 @@ fn main() {
|
||||||
* Initialize the globals
|
* Initialize the globals
|
||||||
*/
|
*/
|
||||||
|
|
||||||
init_shm_global(&mut event_loop, vec![], log.clone());
|
init_shm_global(&mut display, event_loop.token(), vec![], log.clone());
|
||||||
|
|
||||||
let (compositor_token, _shell_state_token, window_map) =
|
let (compositor_token, _shell_state_token, window_map) =
|
||||||
init_shell(&mut event_loop, log.clone(), egl_display);
|
init_shell(&mut display, event_loop.token(), log.clone(), egl_display);
|
||||||
|
|
||||||
let (seat_token, _) = Seat::new(&mut event_loop, "winit".into(), log.clone());
|
let (mut seat, _) = Seat::new(
|
||||||
|
&mut display,
|
||||||
|
event_loop.token(),
|
||||||
|
"winit".into(),
|
||||||
|
log.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
let pointer = event_loop.state().get_mut(&seat_token).add_pointer();
|
let pointer = seat.add_pointer();
|
||||||
let keyboard = event_loop
|
let keyboard = seat.add_keyboard("", "fr", "oss", None, 1000, 500)
|
||||||
.state()
|
|
||||||
.get_mut(&seat_token)
|
|
||||||
.add_keyboard("", "fr", "oss", None, 1000, 500)
|
|
||||||
.expect("Failed to initialize the keyboard");
|
.expect("Failed to initialize the keyboard");
|
||||||
|
|
||||||
let (output_token, _output_global) = Output::new(
|
let (output, _) = Output::new(
|
||||||
&mut event_loop,
|
&mut display,
|
||||||
|
event_loop.token(),
|
||||||
"Winit".into(),
|
"Winit".into(),
|
||||||
PhysicalProperties {
|
PhysicalProperties {
|
||||||
width: 0,
|
width: 0,
|
||||||
|
@ -233,38 +223,29 @@ fn main() {
|
||||||
log.clone(),
|
log.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
event_loop
|
output.change_current_state(
|
||||||
.state()
|
Some(Mode {
|
||||||
.get_mut(&output_token)
|
|
||||||
.change_current_state(
|
|
||||||
Some(Mode {
|
|
||||||
width: w as i32,
|
|
||||||
height: h as i32,
|
|
||||||
refresh: 60_000,
|
|
||||||
}),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
event_loop
|
|
||||||
.state()
|
|
||||||
.get_mut(&output_token)
|
|
||||||
.set_preferred(Mode {
|
|
||||||
width: w as i32,
|
width: w as i32,
|
||||||
height: h as i32,
|
height: h as i32,
|
||||||
refresh: 60_000,
|
refresh: 60_000,
|
||||||
});
|
}),
|
||||||
|
None,
|
||||||
input.set_handler(
|
None,
|
||||||
&mut event_loop,
|
|
||||||
WinitInputHandler {
|
|
||||||
log: log.clone(),
|
|
||||||
pointer,
|
|
||||||
keyboard,
|
|
||||||
window_map: window_map.clone(),
|
|
||||||
pointer_location: (0.0, 0.0),
|
|
||||||
serial: 0,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
output.set_preferred(Mode {
|
||||||
|
width: w as i32,
|
||||||
|
height: h as i32,
|
||||||
|
refresh: 60_000,
|
||||||
|
});
|
||||||
|
|
||||||
|
input.set_handler(WinitInputHandler {
|
||||||
|
log: log.clone(),
|
||||||
|
pointer,
|
||||||
|
keyboard,
|
||||||
|
window_map: window_map.clone(),
|
||||||
|
pointer_location: (0.0, 0.0),
|
||||||
|
serial: 0,
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a listening socket:
|
* Add a listening socket:
|
||||||
|
@ -273,7 +254,7 @@ fn main() {
|
||||||
println!("Listening on socket: {}", name);
|
println!("Listening on socket: {}", name);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
input.dispatch_new_events(&mut event_loop).unwrap();
|
input.dispatch_new_events().unwrap();
|
||||||
|
|
||||||
let mut frame = drawer.draw();
|
let mut frame = drawer.draw();
|
||||||
frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None);
|
frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None);
|
||||||
|
@ -320,8 +301,8 @@ fn main() {
|
||||||
|
|
||||||
if let Some(ref texture) = attributes.user_data.texture {
|
if let Some(ref texture) = attributes.user_data.texture {
|
||||||
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
||||||
x += subdata.x;
|
x += subdata.location.0;
|
||||||
y += subdata.y;
|
y += subdata.location.1;
|
||||||
}
|
}
|
||||||
drawer.render_texture(
|
drawer.render_texture(
|
||||||
&mut frame,
|
&mut frame,
|
||||||
|
|
Loading…
Reference in New Issue