anvil: clamp input to current output instead of full hd

This commit is contained in:
Victor Brekenfeld 2020-06-11 19:36:57 +02:00
parent d7f800c76d
commit 33fb393383
4 changed files with 89 additions and 15 deletions

View File

@ -92,10 +92,14 @@ impl AnvilState {
let mut location = self.pointer_location.borrow_mut();
location.0 += x as f64;
location.1 += y as f64;
// clamp to screen limits
// this event is never generated by winit so self.screen_size is relevant
location.0 = (location.0).max(0.0).min(self.screen_size.0 as f64);
location.1 = (location.1).max(0.0).min(self.screen_size.1 as f64);
#[cfg(feature = "udev")]
{
// clamp to screen limits
// this event is never generated by winit
*location = self.clamp_coords(*location);
}
let under = self
.window_map
.borrow()
@ -110,8 +114,11 @@ impl AnvilState {
{
if self.session.is_some() {
// we are started on a tty
let (ux, uy) = evt.position_transformed(self.screen_size);
(ux as f64, uy as f64)
let x = self.pointer_location.borrow().0;
let screen_size = self.current_output_size(x);
// monitor coordinates
let (ux, uy) = evt.position_transformed(screen_size);
((ux + self.current_output_offset(x)) as f64, uy as f64)
} else {
// we are started in winit
evt.position()
@ -128,6 +135,67 @@ impl AnvilState {
self.pointer.motion((x, y), under, serial, evt.time());
}
#[cfg(feature = "udev")]
fn clamp_coords(&self, pos: (f64, f64)) -> (f64, f64) {
let output_map = self.output_map
.as_ref().unwrap();
let outputs = output_map.borrow();
if outputs.len() == 0 {
return pos;
}
let (mut x, mut y) = pos;
// max_x is the sum of the width of all outputs
let max_x = outputs
.iter()
.fold(0u32, |acc, output| acc + output.size.0);
x = x.max(0.0).min(max_x as f64);
// max y depends on the current output
let max_y = self.current_output_size(x).1;
y = y.max(0.0).min(max_y as f64);
(x, y)
}
#[cfg(feature = "udev")]
fn current_output_idx(&self, x: f64) -> usize {
let output_map = self.output_map.as_ref().unwrap();
let outputs = output_map.borrow();
outputs
.iter()
// map each output to their x position
.scan(0u32, |acc, output| {
let curr_x = *acc;
*acc += output.size.0;
Some(curr_x)
})
// get an index
.enumerate()
// find the first one with a greater x
.find(|(_idx, x_pos)| *x_pos as f64 > x)
// the previous output is the one we are on
.map(|(idx, _)| idx - 1)
.unwrap_or(outputs.len() - 1)
}
#[cfg(feature = "udev")]
fn current_output_size(&self, x: f64) -> (u32, u32) {
let output_map = self.output_map.as_ref().unwrap();
let outputs = output_map.borrow();
outputs[self.current_output_idx(x)].size
}
#[cfg(feature = "udev")]
fn current_output_offset(&self, x: f64) -> u32 {
let output_map = self.output_map.as_ref().unwrap();
let outputs = output_map.borrow();
outputs
.iter()
.take(self.current_output_idx(x))
.fold(0u32, |acc, output| acc + output.size.0)
}
fn on_pointer_button<B: InputBackend>(&mut self, evt: B::PointerButtonEvent) {
let serial = SCOUNTER.next_serial();
let button = match evt.button() {

View File

@ -27,7 +27,7 @@ use smithay::{
#[cfg(feature = "udev")]
use smithay::backend::session::Session;
use crate::{buffer_utils::BufferUtils, shell::init_shell};
use crate::{buffer_utils::BufferUtils, shell::init_shell, udev::MyOutput};
pub struct AnvilState {
pub socket_name: String,
@ -43,7 +43,8 @@ pub struct AnvilState {
pub keyboard: KeyboardHandle,
pub pointer_location: Rc<RefCell<(f64, f64)>>,
pub cursor_status: Arc<Mutex<CursorImageStatus>>,
pub screen_size: (u32, u32),
#[cfg(feature = "udev")]
pub output_map: Option<Rc<RefCell<Vec<MyOutput>>>>,
pub seat_name: String,
#[cfg(feature = "udev")]
pub session: Option<AutoSession>,
@ -58,6 +59,8 @@ impl AnvilState {
buffer_utils: BufferUtils,
#[cfg(feature = "udev")] session: Option<AutoSession>,
#[cfg(not(feature = "udev"))] _session: Option<()>,
#[cfg(feature = "udev")] output_map: Option<Rc<RefCell<Vec<MyOutput>>>>,
#[cfg(not(feature = "udev"))] _output_map: Option<()>,
log: slog::Logger,
) -> AnvilState {
// init the wayland connection
@ -162,7 +165,8 @@ impl AnvilState {
keyboard,
cursor_status,
pointer_location: Rc::new(RefCell::new((0.0, 0.0))),
screen_size: (1920, 1080),
#[cfg(feature = "udev")]
output_map,
seat_name,
#[cfg(feature = "udev")]
session,

View File

@ -113,6 +113,8 @@ pub fn run_udev(
#[cfg(not(feature = "egl"))]
let buffer_utils = BufferUtils::new(log.clone());
let output_map = Rc::new(RefCell::new(Vec::new()));
/*
* Initialize session
*/
@ -127,6 +129,7 @@ pub fn run_udev(
event_loop.handle(),
buffer_utils,
Some(session),
Some(output_map.clone()),
log.clone(),
);
@ -138,8 +141,6 @@ pub fn run_udev(
let bytes = include_bytes!("../resources/cursor2.rgba");
let udev_backend = UdevBackend::new(state.seat_name.clone(), log.clone()).map_err(|_| ())?;
let output_map = Rc::new(RefCell::new(Vec::new()));
let mut udev_handler = UdevHandlerImpl {
compositor_token: state.ctoken,
#[cfg(feature = "egl")]
@ -227,10 +228,10 @@ pub fn run_udev(
Ok(())
}
struct MyOutput {
device_id: dev_t,
crtc: crtc::Handle,
size: (u32, u32),
pub struct MyOutput {
pub device_id: dev_t,
pub crtc: crtc::Handle,
pub size: (u32, u32),
_wl: Output,
global: Option<Global<wl_output::WlOutput>>,
}

View File

@ -58,6 +58,7 @@ pub fn run_winit(
event_loop.handle(),
buffer_utils,
None,
None,
log.clone(),
);