backends.winit: only expose physical sizes
Unify winit with the other backends in only ever dealing with physical sizes. All dimensions and coordinates are provided in the physical space (transformed by the dpi factor provided by winit), and the user is responsible for dealing with the dpi scaling if they want. A compositor using it can deal with it either by following the scaling transmitted by the backend or using some value retrieved by other means (like a command line argument, like weston does). This means that a non-hidpi aware implementation will appear very small on an hidpi screen, but not broken. This is now the current state of anvil. This also changes the WinitEventsHandler trait to merge the resized() and hidpifactorchanged() callbacks into a single one, providing the physical size and the dpi factor whenever either changes.
This commit is contained in:
parent
f9bd83c3b5
commit
df12fa4e8b
|
@ -20,7 +20,7 @@ use backend::{
|
|||
},
|
||||
};
|
||||
use nix::libc::c_void;
|
||||
use std::{cmp, error, fmt, rc::Rc, time::Instant};
|
||||
use std::{cell::RefCell, cmp, error, fmt, rc::Rc, time::Instant};
|
||||
use wayland_client::egl as wegl;
|
||||
use wayland_server::Display;
|
||||
use winit::{
|
||||
|
@ -67,10 +67,16 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
struct WindowSize {
|
||||
logical_size: LogicalSize,
|
||||
dpi_factor: f64,
|
||||
}
|
||||
|
||||
/// Window with an active EGL Context created by `winit`. Implements the
|
||||
/// `EGLGraphicsBackend` graphics backend trait
|
||||
pub struct WinitGraphicsBackend {
|
||||
window: Rc<Window>,
|
||||
size: Rc<RefCell<WindowSize>>,
|
||||
logger: ::slog::Logger,
|
||||
}
|
||||
|
||||
|
@ -87,7 +93,7 @@ pub struct WinitInputBackend {
|
|||
input_config: (),
|
||||
handler: Option<Box<InputHandler<WinitInputBackend> + 'static>>,
|
||||
logger: ::slog::Logger,
|
||||
dpi: f64,
|
||||
size: Rc<RefCell<WindowSize>>,
|
||||
}
|
||||
|
||||
/// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend`
|
||||
|
@ -164,9 +170,18 @@ where
|
|||
},
|
||||
);
|
||||
|
||||
let size = Rc::new(RefCell::new(WindowSize {
|
||||
logical_size: window
|
||||
.window()
|
||||
.get_inner_size()
|
||||
.expect("Winit window was killed during init."),
|
||||
dpi_factor: window.window().get_hidpi_factor(),
|
||||
}));
|
||||
|
||||
Ok((
|
||||
WinitGraphicsBackend {
|
||||
window: window.clone(),
|
||||
size: size.clone(),
|
||||
logger: log.new(o!("smithay_winit_component" => "graphics")),
|
||||
},
|
||||
WinitInputBackend {
|
||||
|
@ -187,7 +202,7 @@ where
|
|||
input_config: (),
|
||||
handler: None,
|
||||
logger: log.new(o!("smithay_winit_component" => "input")),
|
||||
dpi: 1.0,
|
||||
size,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
@ -195,15 +210,15 @@ where
|
|||
/// Handler trait to recieve window-related events to provide a better *nested* experience.
|
||||
pub trait WinitEventsHandler {
|
||||
/// The window was resized, can be used to adjust the associated `wayland::output::Output`s mode.
|
||||
fn resized(&mut self, size: LogicalSize);
|
||||
///
|
||||
/// Here are provided the new size (in physical pixels) and the new scale factor provided by winit.
|
||||
fn resized(&mut self, size: (f64, f64), scale: f64);
|
||||
/// The window was moved
|
||||
fn moved(&mut self, position: LogicalPosition);
|
||||
/// The window gained or lost focus
|
||||
fn focus_changed(&mut self, focused: bool);
|
||||
/// The window needs to be redrawn
|
||||
fn refresh(&mut self);
|
||||
/// The window's hidpi factor changed
|
||||
fn hidpi_changed(&mut self, scale: f32);
|
||||
}
|
||||
|
||||
impl WinitGraphicsBackend {
|
||||
|
@ -257,11 +272,8 @@ impl EGLGraphicsBackend for WinitGraphicsBackend {
|
|||
}
|
||||
|
||||
fn get_framebuffer_dimensions(&self) -> (u32, u32) {
|
||||
self.window
|
||||
.window()
|
||||
.get_inner_size()
|
||||
.expect("Window does not exist anymore")
|
||||
.into()
|
||||
let size = self.size.borrow();
|
||||
size.logical_size.to_physical(size.dpi_factor).into()
|
||||
}
|
||||
|
||||
fn is_current(&self) -> bool {
|
||||
|
@ -357,7 +369,7 @@ impl KeyboardKeyEvent for WinitKeyboardInputEvent {
|
|||
#[derive(Clone)]
|
||||
/// Winit-Backend internal event wrapping winit's types into a `PointerMotionAbsoluteEvent`
|
||||
pub struct WinitMouseMovedEvent {
|
||||
window: Rc<Window>,
|
||||
size: Rc<RefCell<WindowSize>>,
|
||||
time: u32,
|
||||
x: f64,
|
||||
y: f64,
|
||||
|
@ -371,35 +383,23 @@ impl BackendEvent for WinitMouseMovedEvent {
|
|||
|
||||
impl PointerMotionAbsoluteEvent for WinitMouseMovedEvent {
|
||||
fn x(&self) -> f64 {
|
||||
self.x
|
||||
let wsize = self.size.borrow();
|
||||
self.x * wsize.dpi_factor
|
||||
}
|
||||
|
||||
fn y(&self) -> f64 {
|
||||
self.y
|
||||
let wsize = self.size.borrow();
|
||||
self.y * wsize.dpi_factor
|
||||
}
|
||||
|
||||
fn x_transformed(&self, width: u32) -> u32 {
|
||||
cmp::max(
|
||||
(self.x * width as f64 / self
|
||||
.window
|
||||
.window()
|
||||
.get_inner_size()
|
||||
.unwrap_or(LogicalSize::new(width.into(), 0.0))
|
||||
.width) as i32,
|
||||
0,
|
||||
) as u32
|
||||
let wsize = self.size.borrow();
|
||||
cmp::max((self.x * width as f64 / wsize.logical_size.width) as i32, 0) as u32
|
||||
}
|
||||
|
||||
fn y_transformed(&self, height: u32) -> u32 {
|
||||
cmp::max(
|
||||
(self.y * height as f64 / self
|
||||
.window
|
||||
.window()
|
||||
.get_inner_size()
|
||||
.unwrap_or(LogicalSize::new(0.0, height.into()))
|
||||
.height) as i32,
|
||||
0,
|
||||
) as u32
|
||||
let wsize = self.size.borrow();
|
||||
cmp::max((self.y * height as f64 / wsize.logical_size.height) as i32, 0) as u32
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,7 +468,7 @@ impl PointerButtonEvent for WinitMouseInputEvent {
|
|||
#[derive(Clone)]
|
||||
/// Winit-Backend internal event wrapping winit's types into a `TouchDownEvent`
|
||||
pub struct WinitTouchStartedEvent {
|
||||
window: Rc<Window>,
|
||||
size: Rc<RefCell<WindowSize>>,
|
||||
time: u32,
|
||||
location: (f64, f64),
|
||||
id: u64,
|
||||
|
@ -486,33 +486,27 @@ impl TouchDownEvent for WinitTouchStartedEvent {
|
|||
}
|
||||
|
||||
fn x(&self) -> f64 {
|
||||
self.location.0
|
||||
let wsize = self.size.borrow();
|
||||
self.location.0 * wsize.dpi_factor
|
||||
}
|
||||
|
||||
fn y(&self) -> f64 {
|
||||
self.location.1
|
||||
let wsize = self.size.borrow();
|
||||
self.location.1 * wsize.dpi_factor
|
||||
}
|
||||
|
||||
fn x_transformed(&self, width: u32) -> u32 {
|
||||
let wsize = self.size.borrow();
|
||||
cmp::min(
|
||||
self.location.0 as i32 * width as i32 / self
|
||||
.window
|
||||
.window()
|
||||
.get_inner_size()
|
||||
.unwrap_or(LogicalSize::new(width.into(), 0.0))
|
||||
.width as i32,
|
||||
self.location.0 as i32 * width as i32 / wsize.logical_size.width as i32,
|
||||
0,
|
||||
) as u32
|
||||
}
|
||||
|
||||
fn y_transformed(&self, height: u32) -> u32 {
|
||||
let wsize = self.size.borrow();
|
||||
cmp::min(
|
||||
self.location.1 as i32 * height as i32 / self
|
||||
.window
|
||||
.window()
|
||||
.get_inner_size()
|
||||
.unwrap_or(LogicalSize::new(0.0, height.into()))
|
||||
.height as i32,
|
||||
self.location.1 as i32 * height as i32 / wsize.logical_size.height as i32,
|
||||
0,
|
||||
) as u32
|
||||
}
|
||||
|
@ -521,7 +515,7 @@ impl TouchDownEvent for WinitTouchStartedEvent {
|
|||
#[derive(Clone)]
|
||||
/// Winit-Backend internal event wrapping winit's types into a `TouchMotionEvent`
|
||||
pub struct WinitTouchMovedEvent {
|
||||
window: Rc<Window>,
|
||||
size: Rc<RefCell<WindowSize>>,
|
||||
time: u32,
|
||||
location: (f64, f64),
|
||||
id: u64,
|
||||
|
@ -539,29 +533,23 @@ impl TouchMotionEvent for WinitTouchMovedEvent {
|
|||
}
|
||||
|
||||
fn x(&self) -> f64 {
|
||||
self.location.0
|
||||
let wsize = self.size.borrow();
|
||||
self.location.0 * wsize.dpi_factor
|
||||
}
|
||||
|
||||
fn y(&self) -> f64 {
|
||||
self.location.1
|
||||
let wsize = self.size.borrow();
|
||||
self.location.1 * wsize.dpi_factor
|
||||
}
|
||||
|
||||
fn x_transformed(&self, width: u32) -> u32 {
|
||||
self.location.0 as u32 * width / self
|
||||
.window
|
||||
.window()
|
||||
.get_inner_size()
|
||||
.unwrap_or(LogicalSize::new(width.into(), 0.0))
|
||||
.width as u32
|
||||
let wsize = self.size.borrow();
|
||||
self.location.0 as u32 * width / wsize.logical_size.width as u32
|
||||
}
|
||||
|
||||
fn y_transformed(&self, height: u32) -> u32 {
|
||||
self.location.1 as u32 * height / self
|
||||
.window
|
||||
.window()
|
||||
.get_inner_size()
|
||||
.unwrap_or(LogicalSize::new(0.0, height.into()))
|
||||
.height as u32
|
||||
let wsize = self.size.borrow();
|
||||
self.location.1 as u32 * height / wsize.logical_size.height as u32
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -696,7 +684,7 @@ impl InputBackend for WinitInputBackend {
|
|||
let mut handler = self.handler.as_mut();
|
||||
let mut events_handler = self.events_handler.as_mut();
|
||||
let logger = &self.logger;
|
||||
let dpi = &mut self.dpi;
|
||||
let window_size = &self.size;
|
||||
|
||||
self.events_loop.poll_events(move |event| {
|
||||
if let Event::WindowEvent { event, .. } = event {
|
||||
|
@ -707,12 +695,14 @@ impl InputBackend for WinitInputBackend {
|
|||
(WindowEvent::Resized(size), _, events_handler) => {
|
||||
trace!(logger, "Resizing window to {:?}", size);
|
||||
window.window().set_inner_size(size);
|
||||
let mut wsize = window_size.borrow_mut();
|
||||
wsize.logical_size = size;
|
||||
let physical_size = size.to_physical(wsize.dpi_factor);
|
||||
if let Window::Wayland { ref surface, .. } = **window {
|
||||
let physical_size = size.to_physical(*dpi);
|
||||
surface.resize(physical_size.width as i32, physical_size.height as i32, 0, 0);
|
||||
}
|
||||
if let Some(events_handler) = events_handler {
|
||||
events_handler.resized(size);
|
||||
events_handler.resized(physical_size.into(), wsize.dpi_factor);
|
||||
}
|
||||
}
|
||||
(WindowEvent::Moved(position), _, Some(events_handler)) => {
|
||||
|
@ -722,9 +712,16 @@ impl InputBackend for WinitInputBackend {
|
|||
events_handler.focus_changed(focus)
|
||||
}
|
||||
(WindowEvent::Refresh, _, Some(events_handler)) => events_handler.refresh(),
|
||||
(WindowEvent::HiDpiFactorChanged(factor), _, Some(events_handler)) => {
|
||||
*dpi = factor;
|
||||
events_handler.hidpi_changed(factor as f32)
|
||||
(WindowEvent::HiDpiFactorChanged(factor), _, events_handler) => {
|
||||
let mut wsize = window_size.borrow_mut();
|
||||
wsize.dpi_factor = factor;
|
||||
let physical_size = wsize.logical_size.to_physical(factor);
|
||||
if let Window::Wayland { ref surface, .. } = **window {
|
||||
surface.resize(physical_size.width as i32, physical_size.height as i32, 0, 0);
|
||||
}
|
||||
if let Some(events_handler) = events_handler {
|
||||
events_handler.resized(physical_size.into(), wsize.dpi_factor);
|
||||
}
|
||||
}
|
||||
(
|
||||
WindowEvent::KeyboardInput {
|
||||
|
@ -756,7 +753,7 @@ impl InputBackend for WinitInputBackend {
|
|||
handler.on_pointer_move_absolute(
|
||||
seat,
|
||||
WinitMouseMovedEvent {
|
||||
window: window.clone(),
|
||||
size: window_size.clone(),
|
||||
time,
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
|
@ -786,7 +783,7 @@ impl InputBackend for WinitInputBackend {
|
|||
handler.on_touch_down(
|
||||
seat,
|
||||
WinitTouchStartedEvent {
|
||||
window: window.clone(),
|
||||
size: window_size.clone(),
|
||||
time,
|
||||
location: location.into(),
|
||||
id,
|
||||
|
@ -807,7 +804,7 @@ impl InputBackend for WinitInputBackend {
|
|||
handler.on_touch_motion(
|
||||
seat,
|
||||
WinitTouchMovedEvent {
|
||||
window: window.clone(),
|
||||
size: window_size.clone(),
|
||||
time,
|
||||
location: location.into(),
|
||||
id,
|
||||
|
@ -828,7 +825,7 @@ impl InputBackend for WinitInputBackend {
|
|||
handler.on_touch_motion(
|
||||
seat,
|
||||
WinitTouchMovedEvent {
|
||||
window: window.clone(),
|
||||
size: window_size.clone(),
|
||||
time,
|
||||
location: location.into(),
|
||||
id,
|
||||
|
|
Loading…
Reference in New Issue