clamp cursor with current output height
move fullscreen output geometry calculation to a helper function rename with_outputs to with_client_outputs and take client instead of generic resource
This commit is contained in:
parent
d7e10acc78
commit
df208fa6c8
|
@ -265,11 +265,18 @@ impl AnvilState<UdevData> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (pos_x, pos_y) = pos;
|
let (pos_x, pos_y) = pos;
|
||||||
let (max_x, max_y) = self.output_map.borrow().size();
|
let output_map = self.output_map.borrow();
|
||||||
|
let max_x = output_map.width();
|
||||||
let clamped_x = pos_x.max(0.0).min(max_x as f64);
|
let clamped_x = pos_x.max(0.0).min(max_x as f64);
|
||||||
|
let max_y = output_map.height(clamped_x as i32);
|
||||||
|
|
||||||
|
if let Some(max_y) = max_y {
|
||||||
let clamped_y = pos_y.max(0.0).min(max_y as f64);
|
let clamped_y = pos_y.max(0.0).min(max_y as f64);
|
||||||
|
|
||||||
(clamped_x, clamped_y)
|
(clamped_x, clamped_y)
|
||||||
|
} else {
|
||||||
|
(clamped_x, pos_y)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -212,18 +212,12 @@ impl OutputMap {
|
||||||
.fold(0u32, |acc, output| acc + output.geometry.width as u32)
|
.fold(0u32, |acc, output| acc + output.geometry.width as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn height(&self) -> u32 {
|
pub fn height(&self, x: i32) -> Option<u32> {
|
||||||
// This is a simplification, we only arrange the outputs on the y axis side-by-side
|
// This is a simplification, we only arrange the outputs on the y axis side-by-side
|
||||||
// so that the max height is simply the max of all output heights.
|
|
||||||
self.outputs
|
self.outputs
|
||||||
.iter()
|
.iter()
|
||||||
|
.find(|output| x >= output.geometry.x && x < (output.geometry.x + output.geometry.width))
|
||||||
.map(|output| output.geometry.height as u32)
|
.map(|output| output.geometry.height as u32)
|
||||||
.max()
|
|
||||||
.unwrap_or_default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size(&self) -> (u32, u32) {
|
|
||||||
(self.width(), self.height())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
|
|
|
@ -297,6 +297,36 @@ pub struct ShellHandles {
|
||||||
pub output_map: Rc<RefCell<OutputMap>>,
|
pub output_map: Rc<RefCell<OutputMap>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fullscreen_output_geometry(
|
||||||
|
wl_surface: &wl_surface::WlSurface,
|
||||||
|
wl_output: Option<&wl_output::WlOutput>,
|
||||||
|
window_map: &WindowMap,
|
||||||
|
output_map: &OutputMap,
|
||||||
|
) -> Option<Rectangle> {
|
||||||
|
// First test if a specific output has been requested
|
||||||
|
// if the requested output is not found ignore the request
|
||||||
|
if let Some(wl_output) = wl_output {
|
||||||
|
return output_map.find(&wl_output, |_, geometry| geometry).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is no output preference, try to find the output
|
||||||
|
// where the window is currently active
|
||||||
|
let window_location = window_map
|
||||||
|
.find(wl_surface)
|
||||||
|
.and_then(|kind| window_map.location(&kind));
|
||||||
|
|
||||||
|
if let Some(location) = window_location {
|
||||||
|
let window_output = output_map.find_by_position(location, |_, geometry| geometry).ok();
|
||||||
|
|
||||||
|
if let Some(result) = window_output {
|
||||||
|
return Some(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to primary output
|
||||||
|
output_map.with_primary(|_, geometry| geometry).ok()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::slog::Logger) -> ShellHandles {
|
pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::slog::Logger) -> ShellHandles {
|
||||||
// Create the compositor
|
// Create the compositor
|
||||||
compositor_init(
|
compositor_init(
|
||||||
|
@ -510,49 +540,14 @@ pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::sl
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use the specified preferred output or else the current output the window
|
let output_geometry = fullscreen_output_geometry(
|
||||||
// is shown or the primary output
|
wl_surface,
|
||||||
let output = output
|
output.as_ref(),
|
||||||
.map(|output| {
|
&xdg_window_map.borrow(),
|
||||||
xdg_output_map
|
&xdg_output_map.borrow(),
|
||||||
.borrow()
|
);
|
||||||
.find(&output, |_, geometry| (Some(output.clone()), geometry))
|
|
||||||
.ok()
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
.or_else(|| {
|
|
||||||
let xdg_window_map = xdg_window_map.borrow();
|
|
||||||
|
|
||||||
xdg_window_map
|
if let Some(geometry) = output_geometry {
|
||||||
.find(wl_surface)
|
|
||||||
.and_then(|kind| xdg_window_map.location(&kind))
|
|
||||||
.and_then(|position| {
|
|
||||||
xdg_output_map
|
|
||||||
.borrow()
|
|
||||||
.find_by_position(position, |output, geometry| {
|
|
||||||
let mut window_output: Option<wl_output::WlOutput> = None;
|
|
||||||
output.with_output(wl_surface, |_, output| {
|
|
||||||
window_output = Some(output.to_owned());
|
|
||||||
});
|
|
||||||
(window_output, geometry)
|
|
||||||
})
|
|
||||||
.ok()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
xdg_output_map
|
|
||||||
.borrow()
|
|
||||||
.with_primary(|output, geometry| {
|
|
||||||
let mut primary_output: Option<wl_output::WlOutput> = None;
|
|
||||||
output.with_output(wl_surface, |_, output| {
|
|
||||||
primary_output = Some(output.to_owned());
|
|
||||||
});
|
|
||||||
(primary_output, geometry)
|
|
||||||
})
|
|
||||||
.ok()
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some((output, geometry)) = output {
|
|
||||||
if let Some(surface) = surface.get_surface() {
|
if let Some(surface) = surface.get_surface() {
|
||||||
let mut xdg_window_map = xdg_window_map.borrow_mut();
|
let mut xdg_window_map = xdg_window_map.borrow_mut();
|
||||||
if let Some(kind) = xdg_window_map.find(surface) {
|
if let Some(kind) = xdg_window_map.find(surface) {
|
||||||
|
@ -676,49 +671,14 @@ pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::sl
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use the specified preferred output or else the current output the window
|
let output_geometry = fullscreen_output_geometry(
|
||||||
// is shown or the primary output
|
wl_surface,
|
||||||
let output = output
|
output.as_ref(),
|
||||||
.map(|output| {
|
&shell_window_map.borrow(),
|
||||||
shell_output_map
|
&shell_output_map.borrow(),
|
||||||
.borrow()
|
);
|
||||||
.find(&output, |_, geometry| (Some(output.clone()), geometry))
|
|
||||||
.ok()
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
.or_else(|| {
|
|
||||||
let shell_window_map = shell_window_map.borrow();
|
|
||||||
|
|
||||||
shell_window_map
|
if let Some(geometry) = output_geometry {
|
||||||
.find(wl_surface)
|
|
||||||
.and_then(|kind| shell_window_map.location(&kind))
|
|
||||||
.and_then(|position| {
|
|
||||||
shell_output_map
|
|
||||||
.borrow()
|
|
||||||
.find_by_position(position, |output, geometry| {
|
|
||||||
let mut window_output: Option<wl_output::WlOutput> = None;
|
|
||||||
output.with_output(wl_surface, |_, output| {
|
|
||||||
window_output = Some(output.to_owned());
|
|
||||||
});
|
|
||||||
(window_output, geometry)
|
|
||||||
})
|
|
||||||
.ok()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
shell_output_map
|
|
||||||
.borrow()
|
|
||||||
.with_primary(|output, geometry| {
|
|
||||||
let mut primary_output: Option<wl_output::WlOutput> = None;
|
|
||||||
output.with_output(wl_surface, |_, output| {
|
|
||||||
primary_output = Some(output.to_owned());
|
|
||||||
});
|
|
||||||
(primary_output, geometry)
|
|
||||||
})
|
|
||||||
.ok()
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some((_, geometry)) = output {
|
|
||||||
shell_window_map
|
shell_window_map
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.insert(SurfaceKind::Wl(surface), (geometry.x, geometry.y));
|
.insert(SurfaceKind::Wl(surface), (geometry.x, geometry.y));
|
||||||
|
|
|
@ -613,7 +613,7 @@ impl AnvilState<UdevData> {
|
||||||
device_backend.dev_id,
|
device_backend.dev_id,
|
||||||
crtc,
|
crtc,
|
||||||
&mut *self.window_map.borrow_mut(),
|
&mut *self.window_map.borrow_mut(),
|
||||||
&mut self.backend_data.output_map,
|
&self.backend_data.output_map,
|
||||||
&*self.output_map.borrow(),
|
&*self.output_map.borrow(),
|
||||||
&self.pointer_location,
|
&self.pointer_location,
|
||||||
&device_backend.pointer_image,
|
&device_backend.pointer_image,
|
||||||
|
|
|
@ -22,7 +22,7 @@ use slog::Logger;
|
||||||
use crate::drawing::*;
|
use crate::drawing::*;
|
||||||
use crate::state::{AnvilState, Backend};
|
use crate::state::{AnvilState, Backend};
|
||||||
|
|
||||||
pub const OUTPUT_NAME: &'static str = "winit";
|
pub const OUTPUT_NAME: &str = "winit";
|
||||||
|
|
||||||
pub struct WinitData;
|
pub struct WinitData;
|
||||||
|
|
||||||
|
|
|
@ -53,16 +53,13 @@ use std::{
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use wayland_server::{
|
use wayland_server::protocol::{
|
||||||
protocol::wl_output::{Mode as WMode, WlOutput},
|
|
||||||
Display, Filter, Global, Main,
|
|
||||||
};
|
|
||||||
use wayland_server::{
|
|
||||||
protocol::{
|
|
||||||
wl_output::{Subpixel, Transform},
|
wl_output::{Subpixel, Transform},
|
||||||
wl_surface,
|
wl_surface,
|
||||||
},
|
};
|
||||||
Resource,
|
use wayland_server::{
|
||||||
|
protocol::wl_output::{Mode as WMode, WlOutput},
|
||||||
|
Client, Display, Filter, Global, Main,
|
||||||
};
|
};
|
||||||
|
|
||||||
use slog::{info, o, trace, warn};
|
use slog::{info, o, trace, warn};
|
||||||
|
@ -321,33 +318,37 @@ impl Output {
|
||||||
.any(|o| o.as_ref().equals(output.as_ref()))
|
.any(|o| o.as_ref().equals(output.as_ref()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function allows to run a `Fn` for the matching
|
/// This function allows to run a [FnMut] on every
|
||||||
/// client outputs for a specific `Resource`.
|
/// [WlOutput] matching the same [Client] as provided
|
||||||
pub fn with_output<F, R, II>(&self, resource: &R, mut f: F)
|
pub fn with_client_outputs<F>(&self, client: Client, mut f: F)
|
||||||
where
|
where
|
||||||
R: AsRef<Resource<II>>,
|
F: FnMut(&WlOutput),
|
||||||
II: wayland_server::Interface,
|
|
||||||
F: FnMut(&R, &WlOutput),
|
|
||||||
{
|
{
|
||||||
let tmp = resource.as_ref();
|
|
||||||
self.inner
|
self.inner
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.instances
|
.instances
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|output| output.as_ref().same_client_as(tmp))
|
.filter(|output| match output.as_ref().client() {
|
||||||
.for_each(|output| f(resource, output))
|
Some(output_client) => output_client.equals(&client),
|
||||||
|
None => false,
|
||||||
|
})
|
||||||
|
.for_each(|output| f(output))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends `wl_surface.enter` for the provided surface
|
/// Sends `wl_surface.enter` for the provided surface
|
||||||
/// with the matching client output
|
/// with the matching client output
|
||||||
pub fn enter(&self, surface: &wl_surface::WlSurface) {
|
pub fn enter(&self, surface: &wl_surface::WlSurface) {
|
||||||
self.with_output(surface, |surface, output| surface.enter(output))
|
if let Some(client) = surface.as_ref().client() {
|
||||||
|
self.with_client_outputs(client, |output| surface.enter(output))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends `wl_surface.leave` for the provided surface
|
/// Sends `wl_surface.leave` for the provided surface
|
||||||
/// with the matching client output
|
/// with the matching client output
|
||||||
pub fn leave(&self, surface: &wl_surface::WlSurface) {
|
pub fn leave(&self, surface: &wl_surface::WlSurface) {
|
||||||
self.with_output(surface, |surface, output| surface.leave(output))
|
if let Some(client) = surface.as_ref().client() {
|
||||||
|
self.with_client_outputs(client, |output| surface.leave(output))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue