anvil: draw custom cursors and dnd icons
This commit is contained in:
parent
280decf863
commit
d1d608ab2b
|
@ -20,9 +20,14 @@ use smithay::{
|
||||||
},
|
},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::{roles::Role, SubsurfaceRole, TraversalAction},
|
compositor::{roles::Role, SubsurfaceRole, TraversalAction},
|
||||||
|
data_device::DnDIconRole,
|
||||||
|
seat::CursorImageRole,
|
||||||
shm::with_buffer_contents as shm_buffer_contents,
|
shm::with_buffer_contents as shm_buffer_contents,
|
||||||
},
|
},
|
||||||
wayland_server::{protocol::wl_buffer, Resource},
|
wayland_server::{
|
||||||
|
protocol::{wl_buffer, wl_surface},
|
||||||
|
Resource,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use shaders;
|
use shaders;
|
||||||
|
@ -284,20 +289,16 @@ pub struct TextureMetadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
|
impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
|
||||||
pub fn draw_windows(&self, window_map: &MyWindowMap, compositor_token: MyCompositorToken, log: &Logger) {
|
fn draw_surface_tree(
|
||||||
let mut frame = self.draw();
|
&self,
|
||||||
frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None);
|
frame: &mut Frame,
|
||||||
// redraw the frame, in a simple but inneficient way
|
root: &Resource<wl_surface::WlSurface>,
|
||||||
{
|
location: (i32, i32),
|
||||||
let screen_dimensions = self.borrow().get_framebuffer_dimensions();
|
compositor_token: MyCompositorToken,
|
||||||
window_map.with_windows_from_bottom_to_top(|toplevel_surface, initial_place| {
|
screen_dimensions: (u32, u32),
|
||||||
if let Some(wl_surface) = toplevel_surface.get_surface() {
|
) {
|
||||||
// this surface is a root of a subsurface tree that needs to be drawn
|
|
||||||
compositor_token
|
compositor_token
|
||||||
.with_surface_tree_upward(
|
.with_surface_tree_upward(root, location, |_surface, attributes, role, &(mut x, mut y)| {
|
||||||
wl_surface,
|
|
||||||
initial_place,
|
|
||||||
|_surface, attributes, role, &(mut x, mut y)| {
|
|
||||||
// there is actually something to draw !
|
// there is actually something to draw !
|
||||||
if attributes.user_data.texture.is_none() {
|
if attributes.user_data.texture.is_none() {
|
||||||
if let Some(buffer) = attributes.user_data.buffer.take() {
|
if let Some(buffer) = attributes.user_data.buffer.take() {
|
||||||
|
@ -315,7 +316,7 @@ impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
|
||||||
y += subdata.location.1;
|
y += subdata.location.1;
|
||||||
}
|
}
|
||||||
self.render_texture(
|
self.render_texture(
|
||||||
&mut frame,
|
frame,
|
||||||
&metadata.texture,
|
&metadata.texture,
|
||||||
metadata.fragment,
|
metadata.fragment,
|
||||||
metadata.y_inverted,
|
metadata.y_inverted,
|
||||||
|
@ -325,13 +326,11 @@ impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
|
||||||
::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()
|
||||||
},
|
},
|
||||||
|
@ -341,14 +340,69 @@ impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
|
||||||
// we are not display, so our children are neither
|
// we are not display, so our children are neither
|
||||||
TraversalAction::SkipChildren
|
TraversalAction::SkipChildren
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn draw_windows(
|
||||||
|
&self,
|
||||||
|
frame: &mut Frame,
|
||||||
|
window_map: &MyWindowMap,
|
||||||
|
compositor_token: MyCompositorToken,
|
||||||
|
) {
|
||||||
|
// redraw the frame, in a simple but inneficient way
|
||||||
|
{
|
||||||
|
let screen_dimensions = self.borrow().get_framebuffer_dimensions();
|
||||||
|
window_map.with_windows_from_bottom_to_top(|toplevel_surface, initial_place| {
|
||||||
|
if let Some(wl_surface) = toplevel_surface.get_surface() {
|
||||||
|
// this surface is a root of a subsurface tree that needs to be drawn
|
||||||
|
self.draw_surface_tree(
|
||||||
|
frame,
|
||||||
|
&wl_surface,
|
||||||
|
initial_place,
|
||||||
|
compositor_token,
|
||||||
|
screen_dimensions,
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if let Err(err) = frame.finish() {
|
}
|
||||||
error!(log, "Error during rendering: {:?}", err);
|
|
||||||
}
|
pub fn draw_cursor(
|
||||||
|
&self,
|
||||||
|
frame: &mut Frame,
|
||||||
|
surface: &Resource<wl_surface::WlSurface>,
|
||||||
|
(x, y): (i32, i32),
|
||||||
|
token: MyCompositorToken,
|
||||||
|
) {
|
||||||
|
let (dx, dy) = match token.with_role_data::<CursorImageRole, _, _>(surface, |data| data.hotspot) {
|
||||||
|
Ok(h) => h,
|
||||||
|
Err(_) => {
|
||||||
|
warn!(
|
||||||
|
self.log,
|
||||||
|
"Trying to display as a cursor a surface that does not have the CursorImage role."
|
||||||
|
);
|
||||||
|
(0, 0)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let screen_dimensions = self.borrow().get_framebuffer_dimensions();
|
||||||
|
self.draw_surface_tree(frame, surface, (x - dx, y - dy), token, screen_dimensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_dnd_icon(
|
||||||
|
&self,
|
||||||
|
frame: &mut Frame,
|
||||||
|
surface: &Resource<wl_surface::WlSurface>,
|
||||||
|
(x, y): (i32, i32),
|
||||||
|
token: MyCompositorToken,
|
||||||
|
) {
|
||||||
|
if !token.has_role::<DnDIconRole>(surface) {
|
||||||
|
warn!(
|
||||||
|
self.log,
|
||||||
|
"Trying to display as a dnd icon a surface that does not have the DndIcon role."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let screen_dimensions = self.borrow().get_framebuffer_dimensions();
|
||||||
|
self.draw_surface_tree(frame, surface, (x, y), token, screen_dimensions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::{
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, Ordering},
|
atomic::{AtomicBool, Ordering},
|
||||||
Arc,
|
Arc, Mutex,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,9 +43,9 @@ use smithay::{
|
||||||
input::Libinput,
|
input::Libinput,
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::CompositorToken,
|
compositor::CompositorToken,
|
||||||
data_device::{default_action_chooser, init_data_device, set_data_device_focus},
|
data_device::{default_action_chooser, init_data_device, set_data_device_focus, DataDeviceEvent},
|
||||||
output::{Mode, Output, PhysicalProperties},
|
output::{Mode, Output, PhysicalProperties},
|
||||||
seat::{Seat, XkbConfig},
|
seat::{CursorImageStatus, Seat, XkbConfig},
|
||||||
shm::init_shm_global,
|
shm::init_shm_global,
|
||||||
},
|
},
|
||||||
wayland_server::{
|
wayland_server::{
|
||||||
|
@ -53,8 +53,8 @@ use smithay::{
|
||||||
generic::{EventedFd, Generic},
|
generic::{EventedFd, Generic},
|
||||||
EventLoop, LoopHandle, Source,
|
EventLoop, LoopHandle, Source,
|
||||||
},
|
},
|
||||||
protocol::wl_output,
|
protocol::{wl_output, wl_surface},
|
||||||
Display,
|
Display, Resource,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -101,6 +101,8 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
||||||
let running = Arc::new(AtomicBool::new(true));
|
let running = Arc::new(AtomicBool::new(true));
|
||||||
|
|
||||||
let pointer_location = Rc::new(RefCell::new((0.0, 0.0)));
|
let pointer_location = Rc::new(RefCell::new((0.0, 0.0)));
|
||||||
|
let cursor_status = Arc::new(Mutex::new(CursorImageStatus::Default));
|
||||||
|
let dnd_icon = Arc::new(Mutex::new(None));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the udev backend
|
* Initialize the udev backend
|
||||||
|
@ -124,6 +126,8 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
||||||
window_map: window_map.clone(),
|
window_map: window_map.clone(),
|
||||||
pointer_location: pointer_location.clone(),
|
pointer_location: pointer_location.clone(),
|
||||||
pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(),
|
pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(),
|
||||||
|
cursor_status: cursor_status.clone(),
|
||||||
|
dnd_icon: dnd_icon.clone(),
|
||||||
loop_handle: event_loop.handle(),
|
loop_handle: event_loop.handle(),
|
||||||
notifier: udev_notifier,
|
notifier: udev_notifier,
|
||||||
logger: log.clone(),
|
logger: log.clone(),
|
||||||
|
@ -136,9 +140,18 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
||||||
/*
|
/*
|
||||||
* Initialize wayland clipboard
|
* Initialize wayland clipboard
|
||||||
*/
|
*/
|
||||||
|
|
||||||
init_data_device(
|
init_data_device(
|
||||||
&mut display.borrow_mut(),
|
&mut display.borrow_mut(),
|
||||||
|_| {},
|
move |event| match event {
|
||||||
|
DataDeviceEvent::DnDStarted { icon, .. } => {
|
||||||
|
*dnd_icon.lock().unwrap() = icon;
|
||||||
|
}
|
||||||
|
DataDeviceEvent::DnDDropped => {
|
||||||
|
*dnd_icon.lock().unwrap() = None;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
default_action_chooser,
|
default_action_chooser,
|
||||||
compositor_token.clone(),
|
compositor_token.clone(),
|
||||||
log.clone(),
|
log.clone(),
|
||||||
|
@ -154,7 +167,9 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
||||||
log.clone(),
|
log.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let pointer = w_seat.add_pointer(compositor_token.clone(), |_| {});
|
let pointer = w_seat.add_pointer(compositor_token.clone(), move |new_status| {
|
||||||
|
*cursor_status.lock().unwrap() = new_status;
|
||||||
|
});
|
||||||
let keyboard = w_seat
|
let keyboard = w_seat
|
||||||
.add_keyboard(XkbConfig::default(), 1000, 500, |seat, focus| {
|
.add_keyboard(XkbConfig::default(), 1000, 500, |seat, focus| {
|
||||||
set_data_device_focus(seat, focus.and_then(|s| s.client()))
|
set_data_device_focus(seat, focus.and_then(|s| s.client()))
|
||||||
|
@ -271,6 +286,8 @@ struct UdevHandlerImpl<S: SessionNotifier, Data: 'static> {
|
||||||
window_map: Rc<RefCell<MyWindowMap>>,
|
window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
pointer_location: Rc<RefCell<(f64, f64)>>,
|
pointer_location: Rc<RefCell<(f64, f64)>>,
|
||||||
pointer_image: ImageBuffer<Rgba<u8>, Vec<u8>>,
|
pointer_image: ImageBuffer<Rgba<u8>, Vec<u8>>,
|
||||||
|
cursor_status: Arc<Mutex<CursorImageStatus>>,
|
||||||
|
dnd_icon: Arc<Mutex<Option<Resource<wl_surface::WlSurface>>>>,
|
||||||
loop_handle: LoopHandle<Data>,
|
loop_handle: LoopHandle<Data>,
|
||||||
notifier: S,
|
notifier: S,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
|
@ -410,6 +427,8 @@ impl<S: SessionNotifier, Data: 'static> UdevHandler for UdevHandlerImpl<S, Data>
|
||||||
backends: backends.clone(),
|
backends: backends.clone(),
|
||||||
window_map: self.window_map.clone(),
|
window_map: self.window_map.clone(),
|
||||||
pointer_location: self.pointer_location.clone(),
|
pointer_location: self.pointer_location.clone(),
|
||||||
|
cursor_status: self.cursor_status.clone(),
|
||||||
|
dnd_icon: self.dnd_icon.clone(),
|
||||||
logger: self.logger.clone(),
|
logger: self.logger.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -504,6 +523,8 @@ pub struct DrmHandlerImpl {
|
||||||
backends: Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<RenderSurface>>>>,
|
backends: Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<RenderSurface>>>>,
|
||||||
window_map: Rc<RefCell<MyWindowMap>>,
|
window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
pointer_location: Rc<RefCell<(f64, f64)>>,
|
pointer_location: Rc<RefCell<(f64, f64)>>,
|
||||||
|
cursor_status: Arc<Mutex<CursorImageStatus>>,
|
||||||
|
dnd_icon: Arc<Mutex<Option<Resource<wl_surface::WlSurface>>>>,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,7 +541,44 @@ impl DeviceHandler for DrmHandlerImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
// and draw in sync with our monitor
|
// and draw in sync with our monitor
|
||||||
drawer.draw_windows(&*self.window_map.borrow(), self.compositor_token, &self.logger);
|
let mut frame = drawer.draw();
|
||||||
|
frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None);
|
||||||
|
// draw the surfaces
|
||||||
|
drawer.draw_windows(&mut frame, &*self.window_map.borrow(), self.compositor_token);
|
||||||
|
let (x, y) = *self.pointer_location.borrow();
|
||||||
|
// draw the dnd icon if applicable
|
||||||
|
{
|
||||||
|
let guard = self.dnd_icon.lock().unwrap();
|
||||||
|
if let Some(ref surface) = *guard {
|
||||||
|
if surface.is_alive() {
|
||||||
|
drawer.draw_dnd_icon(
|
||||||
|
&mut frame,
|
||||||
|
surface,
|
||||||
|
(x as i32, y as i32),
|
||||||
|
self.compositor_token,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// draw the cursor as relevant
|
||||||
|
{
|
||||||
|
let mut guard = self.cursor_status.lock().unwrap();
|
||||||
|
// reset the cursor if the surface is no longer alive
|
||||||
|
let mut reset = false;
|
||||||
|
if let CursorImageStatus::Image(ref surface) = *guard {
|
||||||
|
reset = !surface.is_alive();
|
||||||
|
}
|
||||||
|
if reset {
|
||||||
|
*guard = CursorImageStatus::Default;
|
||||||
|
}
|
||||||
|
if let CursorImageStatus::Image(ref surface) = *guard {
|
||||||
|
drawer.draw_cursor(&mut frame, surface, (x as i32, y as i32), self.compositor_token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(err) = frame.finish() {
|
||||||
|
error!(self.logger, "Error during rendering: {:?}", err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
sync::{atomic::AtomicBool, Arc},
|
sync::{atomic::AtomicBool, Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::{egl::EGLGraphicsBackend, graphics::gl::GLGraphicsBackend, input::InputBackend, winit},
|
backend::{egl::EGLGraphicsBackend, graphics::gl::GLGraphicsBackend, input::InputBackend, winit},
|
||||||
wayland::{
|
wayland::{
|
||||||
data_device::{default_action_chooser, init_data_device, set_data_device_focus},
|
data_device::{default_action_chooser, init_data_device, set_data_device_focus, DataDeviceEvent},
|
||||||
output::{Mode, Output, PhysicalProperties},
|
output::{Mode, Output, PhysicalProperties},
|
||||||
seat::{Seat, XkbConfig},
|
seat::{CursorImageStatus, Seat, XkbConfig},
|
||||||
shm::init_shm_global,
|
shm::init_shm_global,
|
||||||
},
|
},
|
||||||
wayland_server::{calloop::EventLoop, protocol::wl_output, Display},
|
wayland_server::{calloop::EventLoop, protocol::wl_output, Display},
|
||||||
|
@ -50,9 +50,20 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Log
|
||||||
|
|
||||||
let (compositor_token, _, _, window_map) = init_shell(display, log.clone());
|
let (compositor_token, _, _, window_map) = init_shell(display, log.clone());
|
||||||
|
|
||||||
|
let dnd_icon = Arc::new(Mutex::new(None));
|
||||||
|
|
||||||
|
let dnd_icon2 = dnd_icon.clone();
|
||||||
init_data_device(
|
init_data_device(
|
||||||
display,
|
display,
|
||||||
|_| {},
|
move |event| match event {
|
||||||
|
DataDeviceEvent::DnDStarted { icon, .. } => {
|
||||||
|
*dnd_icon2.lock().unwrap() = icon;
|
||||||
|
}
|
||||||
|
DataDeviceEvent::DnDDropped => {
|
||||||
|
*dnd_icon2.lock().unwrap() = None;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
default_action_chooser,
|
default_action_chooser,
|
||||||
compositor_token.clone(),
|
compositor_token.clone(),
|
||||||
log.clone(),
|
log.clone(),
|
||||||
|
@ -60,7 +71,13 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Log
|
||||||
|
|
||||||
let (mut seat, _) = Seat::new(display, "winit".into(), compositor_token.clone(), log.clone());
|
let (mut seat, _) = Seat::new(display, "winit".into(), compositor_token.clone(), log.clone());
|
||||||
|
|
||||||
let pointer = seat.add_pointer(compositor_token.clone(), |_| {});
|
let cursor_status = Arc::new(Mutex::new(CursorImageStatus::Default));
|
||||||
|
|
||||||
|
let cursor_status2 = cursor_status.clone();
|
||||||
|
let pointer = seat.add_pointer(compositor_token.clone(), move |new_status| {
|
||||||
|
// TODO: hide winit system cursor when relevant
|
||||||
|
*cursor_status2.lock().unwrap() = new_status
|
||||||
|
});
|
||||||
|
|
||||||
let keyboard = seat
|
let keyboard = seat
|
||||||
.add_keyboard(XkbConfig::default(), 1000, 500, |seat, focus| {
|
.add_keyboard(XkbConfig::default(), 1000, 500, |seat, focus| {
|
||||||
|
@ -96,6 +113,8 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Log
|
||||||
refresh: 60_000,
|
refresh: 60_000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let pointer_location = Rc::new(RefCell::new((0.0, 0.0)));
|
||||||
|
|
||||||
input.set_handler(AnvilInputHandler::new(
|
input.set_handler(AnvilInputHandler::new(
|
||||||
log.clone(),
|
log.clone(),
|
||||||
pointer,
|
pointer,
|
||||||
|
@ -103,7 +122,7 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Log
|
||||||
window_map.clone(),
|
window_map.clone(),
|
||||||
(0, 0),
|
(0, 0),
|
||||||
running.clone(),
|
running.clone(),
|
||||||
Rc::new(RefCell::new((0.0, 0.0))),
|
pointer_location.clone(),
|
||||||
));
|
));
|
||||||
|
|
||||||
info!(log, "Initialization completed, starting the main loop.");
|
info!(log, "Initialization completed, starting the main loop.");
|
||||||
|
@ -111,7 +130,46 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Log
|
||||||
loop {
|
loop {
|
||||||
input.dispatch_new_events().unwrap();
|
input.dispatch_new_events().unwrap();
|
||||||
|
|
||||||
drawer.draw_windows(&*window_map.borrow(), compositor_token, &log);
|
// drawing logic
|
||||||
|
{
|
||||||
|
use glium::Surface;
|
||||||
|
let mut frame = drawer.draw();
|
||||||
|
frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None);
|
||||||
|
|
||||||
|
// draw the windows
|
||||||
|
drawer.draw_windows(&mut frame, &*window_map.borrow(), compositor_token);
|
||||||
|
|
||||||
|
let (x, y) = *pointer_location.borrow();
|
||||||
|
// draw the dnd icon if any
|
||||||
|
{
|
||||||
|
let guard = dnd_icon.lock().unwrap();
|
||||||
|
if let Some(ref surface) = *guard {
|
||||||
|
if surface.is_alive() {
|
||||||
|
drawer.draw_dnd_icon(&mut frame, surface, (x as i32, y as i32), compositor_token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// draw the cursor as relevant
|
||||||
|
{
|
||||||
|
let mut guard = cursor_status.lock().unwrap();
|
||||||
|
// reset the cursor if the surface is no longer alive
|
||||||
|
let mut reset = false;
|
||||||
|
if let CursorImageStatus::Image(ref surface) = *guard {
|
||||||
|
reset = !surface.is_alive();
|
||||||
|
}
|
||||||
|
if reset {
|
||||||
|
*guard = CursorImageStatus::Default;
|
||||||
|
}
|
||||||
|
// draw as relevant
|
||||||
|
if let CursorImageStatus::Image(ref surface) = *guard {
|
||||||
|
drawer.draw_cursor(&mut frame, surface, (x as i32, y as i32), compositor_token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(err) = frame.finish() {
|
||||||
|
error!(log, "Error during rendering: {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
event_loop
|
event_loop
|
||||||
.dispatch(Some(::std::time::Duration::from_millis(16)), &mut ())
|
.dispatch(Some(::std::time::Duration::from_millis(16)), &mut ())
|
||||||
|
|
|
@ -17,7 +17,7 @@ pub struct CursorImageRole {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Possible status of a cursor as requested by clients
|
/// Possible status of a cursor as requested by clients
|
||||||
#[derive(Clone)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub enum CursorImageStatus {
|
pub enum CursorImageStatus {
|
||||||
/// The cursor should be hidden
|
/// The cursor should be hidden
|
||||||
Hidden,
|
Hidden,
|
||||||
|
|
Loading…
Reference in New Issue