Introduce Logical/Physical Point/Rectangle

This commit is contained in:
Victor Berger 2021-07-05 19:21:15 +02:00 committed by Victor Berger
parent aa647c636e
commit 54ea0d3a74
30 changed files with 1386 additions and 649 deletions

View File

@ -9,7 +9,7 @@ use smithay::{
SwapBuffersError, SwapBuffersError,
}, },
reexports::wayland_server::protocol::{wl_buffer, wl_surface}, reexports::wayland_server::protocol::{wl_buffer, wl_surface},
utils::Rectangle, utils::{Logical, Point, Rectangle},
wayland::{ wayland::{
compositor::{ compositor::{
get_role, with_states, with_surface_tree_upward, Damage, SubsurfaceCachedState, get_role, with_states, with_surface_tree_upward, Damage, SubsurfaceCachedState,
@ -38,7 +38,7 @@ pub fn draw_cursor<R, E, F, T>(
renderer: &mut R, renderer: &mut R,
frame: &mut F, frame: &mut F,
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
(x, y): (i32, i32), location: Point<i32, Logical>,
log: &Logger, log: &Logger,
) -> Result<(), SwapBuffersError> ) -> Result<(), SwapBuffersError>
where where
@ -59,24 +59,24 @@ where
) )
}) })
.unwrap_or(None); .unwrap_or(None);
let (dx, dy) = match ret { let delta = match ret {
Some(h) => h, Some(h) => h,
None => { None => {
warn!( warn!(
log, log,
"Trying to display as a cursor a surface that does not have the CursorImage role." "Trying to display as a cursor a surface that does not have the CursorImage role."
); );
(0, 0) (0, 0).into()
} }
}; };
draw_surface_tree(renderer, frame, surface, (x - dx, y - dy), log) draw_surface_tree(renderer, frame, surface, location - delta, log)
} }
fn draw_surface_tree<R, E, F, T>( fn draw_surface_tree<R, E, F, T>(
renderer: &mut R, renderer: &mut R,
frame: &mut F, frame: &mut F,
root: &wl_surface::WlSurface, root: &wl_surface::WlSurface,
location: (i32, i32), location: Point<i32, Logical>,
log: &Logger, log: &Logger,
) -> Result<(), SwapBuffersError> ) -> Result<(), SwapBuffersError>
where where
@ -90,7 +90,8 @@ where
with_surface_tree_upward( with_surface_tree_upward(
root, root,
location, location,
|_surface, states, &(mut x, mut y)| { |_surface, states, location| {
let mut location = *location;
// Pull a new buffer if available // Pull a new buffer if available
if let Some(data) = states.data_map.get::<RefCell<SurfaceData>>() { if let Some(data) = states.data_map.get::<RefCell<SurfaceData>>() {
let mut data = data.borrow_mut(); let mut data = data.borrow_mut();
@ -103,7 +104,7 @@ where
.map(|dmg| match dmg { .map(|dmg| match dmg {
Damage::Buffer(rect) => *rect, Damage::Buffer(rect) => *rect,
// TODO also apply transformations // TODO also apply transformations
Damage::Surface(rect) => rect.scale(attributes.buffer_scale), Damage::Surface(rect) => rect.to_buffer(attributes.buffer_scale),
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -136,10 +137,9 @@ where
// if yes, also process the children // if yes, also process the children
if states.role == Some("subsurface") { if states.role == Some("subsurface") {
let current = states.cached_state.current::<SubsurfaceCachedState>(); let current = states.cached_state.current::<SubsurfaceCachedState>();
x += current.location.0; location += current.location;
y += current.location.1;
} }
TraversalAction::DoChildren((x, y)) TraversalAction::DoChildren(location)
} else { } else {
// we are not displayed, so our children are neither // we are not displayed, so our children are neither
TraversalAction::SkipChildren TraversalAction::SkipChildren
@ -149,7 +149,8 @@ where
TraversalAction::SkipChildren TraversalAction::SkipChildren
} }
}, },
|_surface, states, &(mut x, mut y)| { |_surface, states, location| {
let mut location = *location;
if let Some(ref data) = states.data_map.get::<RefCell<SurfaceData>>() { if let Some(ref data) = states.data_map.get::<RefCell<SurfaceData>>() {
let mut data = data.borrow_mut(); let mut data = data.borrow_mut();
if let Some(texture) = data if let Some(texture) = data
@ -161,12 +162,11 @@ where
// only passes it to our children // only passes it to our children
if states.role == Some("subsurface") { if states.role == Some("subsurface") {
let current = states.cached_state.current::<SubsurfaceCachedState>(); let current = states.cached_state.current::<SubsurfaceCachedState>();
x += current.location.0; location += current.location;
y += current.location.1;
} }
if let Err(err) = frame.render_texture_at( if let Err(err) = frame.render_texture_at(
&texture.texture, &texture.texture,
(x, y), location.to_physical(1), // TODO: handle output scaling factor
Transform::Normal, /* TODO */ Transform::Normal, /* TODO */
1.0, 1.0,
) { ) {
@ -185,7 +185,7 @@ pub fn draw_windows<R, E, F, T>(
renderer: &mut R, renderer: &mut R,
frame: &mut F, frame: &mut F,
window_map: &WindowMap, window_map: &WindowMap,
output_rect: Rectangle, output_rect: Rectangle<i32, Logical>,
log: &::slog::Logger, log: &::slog::Logger,
) -> Result<(), SwapBuffersError> ) -> Result<(), SwapBuffersError>
where where
@ -197,12 +197,12 @@ where
let mut result = Ok(()); let mut result = Ok(());
// redraw the frame, in a simple but inneficient way // redraw the frame, in a simple but inneficient way
window_map.with_windows_from_bottom_to_top(|toplevel_surface, mut initial_place, bounding_box| { window_map.with_windows_from_bottom_to_top(|toplevel_surface, mut initial_place, &bounding_box| {
// skip windows that do not overlap with a given output // skip windows that do not overlap with a given output
if !output_rect.overlaps(bounding_box) { if !output_rect.overlaps(bounding_box) {
return; return;
} }
initial_place.0 -= output_rect.x; initial_place.x -= output_rect.loc.x;
if let Some(wl_surface) = toplevel_surface.get_surface() { if let Some(wl_surface) = toplevel_surface.get_surface() {
// this surface is a root of a subsurface tree that needs to be drawn // this surface is a root of a subsurface tree that needs to be drawn
if let Err(err) = draw_surface_tree(renderer, frame, &wl_surface, initial_place, log) { if let Err(err) = draw_surface_tree(renderer, frame, &wl_surface, initial_place, log) {
@ -211,14 +211,11 @@ where
// furthermore, draw its popups // furthermore, draw its popups
let toplevel_geometry_offset = window_map let toplevel_geometry_offset = window_map
.geometry(toplevel_surface) .geometry(toplevel_surface)
.map(|g| (g.x, g.y)) .map(|g| g.loc)
.unwrap_or_default(); .unwrap_or_default();
window_map.with_child_popups(&wl_surface, |popup| { window_map.with_child_popups(&wl_surface, |popup| {
let location = popup.location(); let location = popup.location();
let draw_location = ( let draw_location = initial_place + location + toplevel_geometry_offset;
initial_place.0 + location.0 + toplevel_geometry_offset.0,
initial_place.1 + location.1 + toplevel_geometry_offset.1,
);
if let Some(wl_surface) = popup.get_surface() { if let Some(wl_surface) = popup.get_surface() {
if let Err(err) = draw_surface_tree(renderer, frame, &wl_surface, draw_location, log) { if let Err(err) = draw_surface_tree(renderer, frame, &wl_surface, draw_location, log) {
result = Err(err); result = Err(err);
@ -235,7 +232,7 @@ pub fn draw_dnd_icon<R, E, F, T>(
renderer: &mut R, renderer: &mut R,
frame: &mut F, frame: &mut F,
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
(x, y): (i32, i32), location: Point<i32, Logical>,
log: &::slog::Logger, log: &::slog::Logger,
) -> Result<(), SwapBuffersError> ) -> Result<(), SwapBuffersError>
where where
@ -250,5 +247,5 @@ where
"Trying to display as a dnd icon a surface that does not have the DndIcon role." "Trying to display as a dnd icon a surface that does not have the DndIcon role."
); );
} }
draw_surface_tree(renderer, frame, surface, (x, y), log) draw_surface_tree(renderer, frame, surface, location, log)
} }

View File

@ -13,6 +13,7 @@ use smithay::{
TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState,
}, },
reexports::wayland_server::protocol::wl_pointer, reexports::wayland_server::protocol::wl_pointer,
utils::{Logical, Point},
wayland::{ wayland::{
output::Mode, output::Mode,
seat::{keysyms as xkb, AxisFrame, Keysym, ModifiersState}, seat::{keysyms as xkb, AxisFrame, Keysym, ModifiersState},
@ -174,8 +175,7 @@ impl AnvilState<WinitData> {
self.output_map.borrow_mut().update_mode( self.output_map.borrow_mut().update_mode(
crate::winit::OUTPUT_NAME, crate::winit::OUTPUT_NAME,
Mode { Mode {
width: size.0 as i32, size,
height: size.1 as i32,
refresh: 60_000, refresh: 60_000,
}, },
); );
@ -187,12 +187,16 @@ impl AnvilState<WinitData> {
} }
fn on_pointer_move_absolute<B: InputBackend>(&mut self, evt: B::PointerMotionAbsoluteEvent) { fn on_pointer_move_absolute<B: InputBackend>(&mut self, evt: B::PointerMotionAbsoluteEvent) {
// different cases depending on the context: let output_size = self
let (x, y) = evt.position(); .output_map
self.pointer_location = (x, y); .borrow()
.with_primary(|_, rect| (rect.size.w as u32, rect.size.h as u32).into())
.unwrap();
let pos = evt.position_transformed(output_size);
self.pointer_location = pos;
let serial = SCOUNTER.next_serial(); let serial = SCOUNTER.next_serial();
let under = self.window_map.borrow().get_surface_under((x as f64, y as f64)); let under = self.window_map.borrow().get_surface_under(pos);
self.pointer.motion((x, y), under, serial, evt.time()); self.pointer.motion(pos, under, serial, evt.time());
} }
} }
@ -231,9 +235,9 @@ impl AnvilState<UdevData> {
.ok(); .ok();
if let Some(geometry) = geometry { if let Some(geometry) = geometry {
let x = geometry.x as f64 + geometry.width as f64 / 2.0; let x = geometry.loc.x as f64 + geometry.size.w as f64 / 2.0;
let y = geometry.height as f64 / 2.0; let y = geometry.size.h as f64 / 2.0;
self.pointer_location = (x, y) self.pointer_location = (x, y).into()
} }
} }
}, },
@ -270,10 +274,8 @@ impl AnvilState<UdevData> {
} }
fn on_pointer_move<B: InputBackend>(&mut self, evt: B::PointerMotionEvent) { fn on_pointer_move<B: InputBackend>(&mut self, evt: B::PointerMotionEvent) {
let (x, y) = (evt.delta_x(), evt.delta_y());
let serial = SCOUNTER.next_serial(); let serial = SCOUNTER.next_serial();
self.pointer_location.0 += x as f64; self.pointer_location += evt.delta();
self.pointer_location.1 += y as f64;
// clamp to screen limits // clamp to screen limits
// this event is never generated by winit // this event is never generated by winit
@ -292,8 +294,8 @@ impl AnvilState<UdevData> {
output_map output_map
.with_primary(|_, rect| { .with_primary(|_, rect| {
pointer_location.0 = evt.x_transformed(rect.width as u32) + rect.x as f64; let rect_size = (rect.size.w as u32, rect.size.h as u32).into();
pointer_location.1 = evt.y_transformed(rect.height as u32) + rect.y as f64; *pointer_location = evt.position_transformed(rect_size) + rect.loc.to_f64();
let under = window_map.get_surface_under(*pointer_location); let under = window_map.get_surface_under(*pointer_location);
let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&evt.device())); let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&evt.device()));
@ -342,8 +344,8 @@ impl AnvilState<UdevData> {
let tool = evt.tool(); let tool = evt.tool();
tablet_seat.add_tool(&tool); tablet_seat.add_tool(&tool);
pointer_location.0 = evt.x_transformed(rect.width as u32) + rect.x as f64; let rect_size = (rect.size.h as u32, rect.size.w as u32).into();
pointer_location.1 = evt.y_transformed(rect.height as u32) + rect.y as f64; *pointer_location = evt.position_transformed(rect_size) + rect.loc.to_f64();
let under = window_map.get_surface_under(*pointer_location); let under = window_map.get_surface_under(*pointer_location);
let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&evt.device())); let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&evt.device()));
@ -405,12 +407,12 @@ impl AnvilState<UdevData> {
} }
} }
fn clamp_coords(&self, pos: (f64, f64)) -> (f64, f64) { fn clamp_coords(&self, pos: Point<f64, Logical>) -> Point<f64, Logical> {
if self.output_map.borrow().is_empty() { if self.output_map.borrow().is_empty() {
return pos; return pos;
} }
let (pos_x, pos_y) = pos; let (pos_x, pos_y) = pos.into();
let output_map = self.output_map.borrow(); let output_map = self.output_map.borrow();
let max_x = output_map.width(); 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);
@ -419,9 +421,9 @@ impl AnvilState<UdevData> {
if let Some(max_y) = max_y { 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).into()
} else { } else {
(clamped_x, pos_y) (clamped_x, pos_y).into()
} }
} }
} }

View File

@ -8,7 +8,7 @@ use smithay::{
Display, Global, Display, Global,
}, },
}, },
utils::Rectangle, utils::{Logical, Point, Rectangle},
wayland::{ wayland::{
compositor::{with_surface_tree_downward, SubsurfaceCachedState, TraversalAction}, compositor::{with_surface_tree_downward, SubsurfaceCachedState, TraversalAction},
output::{self, Mode, PhysicalProperties}, output::{self, Mode, PhysicalProperties},
@ -21,7 +21,7 @@ struct Output {
name: String, name: String,
output: output::Output, output: output::Output,
global: Option<Global<wl_output::WlOutput>>, global: Option<Global<wl_output::WlOutput>>,
geometry: Rectangle, geometry: Rectangle<i32, Logical>,
surfaces: Vec<WlSurface>, surfaces: Vec<WlSurface>,
current_mode: Mode, current_mode: Mode,
} }
@ -29,7 +29,7 @@ struct Output {
impl Output { impl Output {
fn new<N>( fn new<N>(
name: N, name: N,
location: (i32, i32), location: Point<i32, Logical>,
display: &mut Display, display: &mut Display,
physical: PhysicalProperties, physical: PhysicalProperties,
mode: Mode, mode: Mode,
@ -48,10 +48,9 @@ impl Output {
global: Some(global), global: Some(global),
output, output,
geometry: Rectangle { geometry: Rectangle {
x: location.0, loc: location,
y: location.1, // TODO: handle scaling factor
width: mode.width, size: mode.size.to_logical(1),
height: mode.height,
}, },
surfaces: Vec::new(), surfaces: Vec::new(),
current_mode: mode, current_mode: mode,
@ -101,9 +100,9 @@ impl OutputMap {
// First recalculate the outputs location // First recalculate the outputs location
let mut output_x = 0; let mut output_x = 0;
for output in self.outputs.iter_mut() { for output in self.outputs.iter_mut() {
output.geometry.x = output_x; output.geometry.loc.x = output_x;
output.geometry.y = 0; output.geometry.loc.y = 0;
output_x += output.geometry.width; output_x += output.geometry.loc.x;
} }
// Check if any windows are now out of outputs range // Check if any windows are now out of outputs range
@ -111,13 +110,13 @@ impl OutputMap {
let primary_output_location = self let primary_output_location = self
.with_primary(|_, geometry| geometry) .with_primary(|_, geometry| geometry)
.ok() .ok()
.map(|o| (o.x, o.y)) .map(|o| o.loc)
.unwrap_or_default(); .unwrap_or_default();
let mut window_map = self.window_map.borrow_mut(); let mut window_map = self.window_map.borrow_mut();
// TODO: This is a bit unfortunate, we save the windows in a temp vector // TODO: This is a bit unfortunate, we save the windows in a temp vector
// cause we can not call window_map.set_location within the closure. // cause we can not call window_map.set_location within the closure.
let mut windows_to_move = Vec::new(); let mut windows_to_move = Vec::new();
window_map.with_windows_from_bottom_to_top(|kind, _, bbox| { window_map.with_windows_from_bottom_to_top(|kind, _, &bbox| {
let within_outputs = self.outputs.iter().any(|o| o.geometry.overlaps(bbox)); let within_outputs = self.outputs.iter().any(|o| o.geometry.overlaps(bbox));
if !within_outputs { if !within_outputs {
@ -142,12 +141,12 @@ impl OutputMap {
}; };
if let Some(geometry) = output_geometry { if let Some(geometry) = output_geometry {
if location != (geometry.x, geometry.y) { if location != geometry.loc {
windows_to_move.push((kind.to_owned(), (geometry.x, geometry.y))); windows_to_move.push((kind.to_owned(), geometry.loc));
} }
let res = xdg.with_pending_state(|pending_state| { let res = xdg.with_pending_state(|pending_state| {
pending_state.size = Some((geometry.width, geometry.height)); pending_state.size = Some(geometry.size);
}); });
if res.is_ok() { if res.is_ok() {
@ -174,7 +173,7 @@ impl OutputMap {
let output = Output::new( let output = Output::new(
name, name,
location, location.into(),
&mut *self.display.borrow_mut(), &mut *self.display.borrow_mut(),
physical, physical,
mode, mode,
@ -204,20 +203,20 @@ impl OutputMap {
self.arrange(); self.arrange();
} }
pub fn width(&self) -> u32 { pub fn width(&self) -> i32 {
// 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 total width is simply the sum of all output widths. // so that the total width is simply the sum of all output widths.
self.outputs self.outputs
.iter() .iter()
.fold(0u32, |acc, output| acc + output.geometry.width as u32) .fold(0, |acc, output| acc + output.geometry.size.w)
} }
pub fn height(&self, x: i32) -> Option<u32> { pub fn height(&self, x: i32) -> Option<i32> {
// 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
self.outputs self.outputs
.iter() .iter()
.find(|output| x >= output.geometry.x && x < (output.geometry.x + output.geometry.width)) .find(|output| x >= output.geometry.loc.x && x < (output.geometry.loc.x + output.geometry.size.w))
.map(|output| output.geometry.height as u32) .map(|output| output.geometry.size.h)
} }
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
@ -226,7 +225,7 @@ impl OutputMap {
pub fn with_primary<F, T>(&self, f: F) -> Result<T, OutputNotFound> pub fn with_primary<F, T>(&self, f: F) -> Result<T, OutputNotFound>
where where
F: FnOnce(&output::Output, Rectangle) -> T, F: FnOnce(&output::Output, Rectangle<i32, Logical>) -> T,
{ {
let output = self.outputs.get(0).ok_or(OutputNotFound)?; let output = self.outputs.get(0).ok_or(OutputNotFound)?;
@ -235,7 +234,7 @@ impl OutputMap {
pub fn find<F, T>(&self, output: &wl_output::WlOutput, f: F) -> Result<T, OutputNotFound> pub fn find<F, T>(&self, output: &wl_output::WlOutput, f: F) -> Result<T, OutputNotFound>
where where
F: FnOnce(&output::Output, Rectangle) -> T, F: FnOnce(&output::Output, Rectangle<i32, Logical>) -> T,
{ {
let output = self let output = self
.outputs .outputs
@ -249,7 +248,7 @@ impl OutputMap {
pub fn find_by_name<N, F, T>(&self, name: N, f: F) -> Result<T, OutputNotFound> pub fn find_by_name<N, F, T>(&self, name: N, f: F) -> Result<T, OutputNotFound>
where where
N: AsRef<str>, N: AsRef<str>,
F: FnOnce(&output::Output, Rectangle) -> T, F: FnOnce(&output::Output, Rectangle<i32, Logical>) -> T,
{ {
let output = self let output = self
.outputs .outputs
@ -260,9 +259,9 @@ impl OutputMap {
Ok(f(&output.output, output.geometry)) Ok(f(&output.output, output.geometry))
} }
pub fn find_by_position<F, T>(&self, position: (i32, i32), f: F) -> Result<T, OutputNotFound> pub fn find_by_position<F, T>(&self, position: Point<i32, Logical>, f: F) -> Result<T, OutputNotFound>
where where
F: FnOnce(&output::Output, Rectangle) -> T, F: FnOnce(&output::Output, Rectangle<i32, Logical>) -> T,
{ {
let output = self let output = self
.outputs .outputs
@ -275,7 +274,7 @@ impl OutputMap {
pub fn find_by_index<F, T>(&self, index: usize, f: F) -> Result<T, OutputNotFound> pub fn find_by_index<F, T>(&self, index: usize, f: F) -> Result<T, OutputNotFound>
where where
F: FnOnce(&output::Output, Rectangle) -> T, F: FnOnce(&output::Output, Rectangle<i32, Logical>) -> T,
{ {
let output = self.outputs.get(index).ok_or(OutputNotFound)?; let output = self.outputs.get(index).ok_or(OutputNotFound)?;
@ -293,8 +292,8 @@ impl OutputMap {
// the output width decreased the refresh method will take // the output width decreased the refresh method will take
// care and will send enter for the output. // care and will send enter for the output.
if let Some(output) = output { if let Some(output) = output {
output.geometry.width = mode.width; // TODO: handle scale factors
output.geometry.height = mode.height; output.geometry.size = mode.size.to_logical(1);
output.output.delete_mode(output.current_mode); output.output.delete_mode(output.current_mode);
output.output.change_current_state(Some(mode), None, None); output.output.change_current_state(Some(mode), None, None);
@ -316,7 +315,7 @@ impl OutputMap {
window_map window_map
.borrow() .borrow()
.with_windows_from_bottom_to_top(|kind, location, bbox| { .with_windows_from_bottom_to_top(|kind, location, &bbox| {
for output in self.outputs.iter_mut() { for output in self.outputs.iter_mut() {
// Check if the bounding box of the toplevel intersects with // Check if the bounding box of the toplevel intersects with
// the output, if not no surface in the tree can intersect with // the output, if not no surface in the tree can intersect with
@ -343,30 +342,30 @@ impl OutputMap {
with_surface_tree_downward( with_surface_tree_downward(
surface, surface,
location, location,
|_, states, &(mut x, mut y)| { |_, states, location| {
let mut location = *location;
let data = states.data_map.get::<RefCell<SurfaceData>>(); let data = states.data_map.get::<RefCell<SurfaceData>>();
if data.is_some() { if data.is_some() {
if states.role == Some("subsurface") { if states.role == Some("subsurface") {
let current = states.cached_state.current::<SubsurfaceCachedState>(); let current = states.cached_state.current::<SubsurfaceCachedState>();
x += current.location.0; location += current.location;
y += current.location.1;
} }
TraversalAction::DoChildren((x, y)) TraversalAction::DoChildren(location)
} else { } else {
// If the parent surface is unmapped, then the child surfaces are hidden as // If the parent surface is unmapped, then the child surfaces are hidden as
// well, no need to consider them here. // well, no need to consider them here.
TraversalAction::SkipChildren TraversalAction::SkipChildren
} }
}, },
|wl_surface, states, &(x, y)| { |wl_surface, states, &loc| {
let data = states.data_map.get::<RefCell<SurfaceData>>(); let data = states.data_map.get::<RefCell<SurfaceData>>();
if let Some((width, height)) = data.and_then(|d| d.borrow().size()) { if let Some(size) = data.and_then(|d| d.borrow().size()) {
let surface_rectangle = Rectangle { x, y, width, height }; let surface_rectangle = Rectangle { loc, size };
if output.geometry.overlaps(&surface_rectangle) { if output.geometry.overlaps(surface_rectangle) {
// We found a matching output, check if we already sent enter // We found a matching output, check if we already sent enter
if !output.surfaces.contains(wl_surface) { if !output.surfaces.contains(wl_surface) {
output.output.enter(wl_surface); output.output.enter(wl_surface);

View File

@ -13,7 +13,7 @@ use smithay::{
Display, Display,
}, },
}, },
utils::Rectangle, utils::{Logical, Physical, Point, Rectangle, Size},
wayland::{ wayland::{
compositor::{ compositor::{
compositor_init, is_sync_subsurface, with_states, with_surface_tree_upward, BufferAssignment, compositor_init, is_sync_subsurface, with_states, with_surface_tree_upward, BufferAssignment,
@ -41,26 +41,25 @@ struct MoveSurfaceGrab {
start_data: GrabStartData, start_data: GrabStartData,
window_map: Rc<RefCell<WindowMap>>, window_map: Rc<RefCell<WindowMap>>,
toplevel: SurfaceKind, toplevel: SurfaceKind,
initial_window_location: (i32, i32), initial_window_location: Point<i32, Logical>,
} }
impl PointerGrab for MoveSurfaceGrab { impl PointerGrab for MoveSurfaceGrab {
fn motion( fn motion(
&mut self, &mut self,
_handle: &mut PointerInnerHandle<'_>, _handle: &mut PointerInnerHandle<'_>,
location: (f64, f64), location: Point<f64, Logical>,
_focus: Option<(wl_surface::WlSurface, (f64, f64))>, _focus: Option<(wl_surface::WlSurface, Point<i32, Logical>)>,
_serial: Serial, _serial: Serial,
_time: u32, _time: u32,
) { ) {
let dx = location.0 - self.start_data.location.0; let delta = location - self.start_data.location;
let dy = location.1 - self.start_data.location.1; let new_location = self.initial_window_location.to_f64() + delta;
let new_window_x = (self.initial_window_location.0 as f64 + dx) as i32;
let new_window_y = (self.initial_window_location.1 as f64 + dy) as i32;
self.window_map self.window_map.borrow_mut().set_location(
.borrow_mut() &self.toplevel,
.set_location(&self.toplevel, (new_window_x, new_window_y)); (new_location.x as i32, new_location.y as i32).into(),
);
} }
fn button( fn button(
@ -133,16 +132,16 @@ struct ResizeSurfaceGrab {
start_data: GrabStartData, start_data: GrabStartData,
toplevel: SurfaceKind, toplevel: SurfaceKind,
edges: ResizeEdge, edges: ResizeEdge,
initial_window_size: (i32, i32), initial_window_size: Size<i32, Logical>,
last_window_size: (i32, i32), last_window_size: Size<i32, Logical>,
} }
impl PointerGrab for ResizeSurfaceGrab { impl PointerGrab for ResizeSurfaceGrab {
fn motion( fn motion(
&mut self, &mut self,
handle: &mut PointerInnerHandle<'_>, handle: &mut PointerInnerHandle<'_>,
location: (f64, f64), location: Point<f64, Logical>,
_focus: Option<(wl_surface::WlSurface, (f64, f64))>, _focus: Option<(wl_surface::WlSurface, Point<i32, Logical>)>,
serial: Serial, serial: Serial,
time: u32, time: u32,
) { ) {
@ -152,11 +151,10 @@ impl PointerGrab for ResizeSurfaceGrab {
return; return;
} }
let mut dx = location.0 - self.start_data.location.0; let (mut dx, mut dy) = (location - self.start_data.location).into();
let mut dy = location.1 - self.start_data.location.1;
let mut new_window_width = self.initial_window_size.0; let mut new_window_width = self.initial_window_size.w;
let mut new_window_height = self.initial_window_size.1; let mut new_window_height = self.initial_window_size.h;
let left_right = ResizeEdge::LEFT | ResizeEdge::RIGHT; let left_right = ResizeEdge::LEFT | ResizeEdge::RIGHT;
let top_bottom = ResizeEdge::TOP | ResizeEdge::BOTTOM; let top_bottom = ResizeEdge::TOP | ResizeEdge::BOTTOM;
@ -166,7 +164,7 @@ impl PointerGrab for ResizeSurfaceGrab {
dx = -dx; dx = -dx;
} }
new_window_width = (self.initial_window_size.0 as f64 + dx) as i32; new_window_width = (self.initial_window_size.w as f64 + dx) as i32;
} }
if self.edges.intersects(top_bottom) { if self.edges.intersects(top_bottom) {
@ -174,7 +172,7 @@ impl PointerGrab for ResizeSurfaceGrab {
dy = -dy; dy = -dy;
} }
new_window_height = (self.initial_window_size.1 as f64 + dy) as i32; new_window_height = (self.initial_window_size.h as f64 + dy) as i32;
} }
let (min_size, max_size) = with_states(self.toplevel.get_surface().unwrap(), |states| { let (min_size, max_size) = with_states(self.toplevel.get_surface().unwrap(), |states| {
@ -183,23 +181,23 @@ impl PointerGrab for ResizeSurfaceGrab {
}) })
.unwrap(); .unwrap();
let min_width = min_size.0.max(1); let min_width = min_size.w.max(1);
let min_height = min_size.1.max(1); let min_height = min_size.h.max(1);
let max_width = if max_size.0 == 0 { let max_width = if max_size.w == 0 {
i32::max_value() i32::max_value()
} else { } else {
max_size.0 max_size.w
}; };
let max_height = if max_size.1 == 0 { let max_height = if max_size.h == 0 {
i32::max_value() i32::max_value()
} else { } else {
max_size.1 max_size.h
}; };
new_window_width = new_window_width.max(min_width).min(max_width); new_window_width = new_window_width.max(min_width).min(max_width);
new_window_height = new_window_height.max(min_height).min(max_height); new_window_height = new_window_height.max(min_height).min(max_height);
self.last_window_size = (new_window_width, new_window_height); self.last_window_size = (new_window_width, new_window_height).into();
match &self.toplevel { match &self.toplevel {
SurfaceKind::Xdg(xdg) => { SurfaceKind::Xdg(xdg) => {
@ -211,10 +209,7 @@ impl PointerGrab for ResizeSurfaceGrab {
xdg.send_configure(); xdg.send_configure();
} }
} }
SurfaceKind::Wl(wl) => wl.send_configure( SurfaceKind::Wl(wl) => wl.send_configure(self.last_window_size, self.edges.into()),
(self.last_window_size.0 as u32, self.last_window_size.1 as u32),
self.edges.into(),
),
#[cfg(feature = "xwayland")] #[cfg(feature = "xwayland")]
SurfaceKind::X11(_) => { SurfaceKind::X11(_) => {
// TODO: What to do here? Send the update via X11? // TODO: What to do here? Send the update via X11?
@ -302,7 +297,7 @@ fn fullscreen_output_geometry(
wl_output: Option<&wl_output::WlOutput>, wl_output: Option<&wl_output::WlOutput>,
window_map: &WindowMap, window_map: &WindowMap,
output_map: &OutputMap, output_map: &OutputMap,
) -> Option<Rectangle> { ) -> Option<Rectangle<i32, Logical>> {
// First test if a specific output has been requested // First test if a specific output has been requested
// if the requested output is not found ignore the request // if the requested output is not found ignore the request
if let Some(wl_output) = wl_output { if let Some(wl_output) = wl_output {
@ -362,15 +357,11 @@ pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::sl
.borrow() .borrow()
.with_primary(|_, geometry| geometry) .with_primary(|_, geometry| geometry)
.ok() .ok()
.unwrap_or_else(|| Rectangle { .unwrap_or_else(|| Rectangle::from_loc_and_size((0, 0), (800, 800)));
width: 800, let max_x = output_geometry.loc.x + (((output_geometry.size.w as f32) / 3.0) * 2.0) as i32;
height: 800, let max_y = output_geometry.loc.y + (((output_geometry.size.h as f32) / 3.0) * 2.0) as i32;
..Default::default() let x_range = Uniform::new(output_geometry.loc.x, max_x);
}); let y_range = Uniform::new(output_geometry.loc.y, max_y);
let max_x = output_geometry.x + (((output_geometry.width as f32) / 3.0) * 2.0) as i32;
let max_y = output_geometry.y + (((output_geometry.height as f32) / 3.0) * 2.0) as i32;
let x_range = Uniform::new(output_geometry.x, max_x);
let y_range = Uniform::new(output_geometry.y, max_y);
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let x = x_range.sample(&mut rng); let x = x_range.sample(&mut rng);
let y = y_range.sample(&mut rng); let y = y_range.sample(&mut rng);
@ -379,7 +370,7 @@ pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::sl
// the surface is not already configured // the surface is not already configured
xdg_window_map xdg_window_map
.borrow_mut() .borrow_mut()
.insert(SurfaceKind::Xdg(surface), (x, y)); .insert(SurfaceKind::Xdg(surface), (x, y).into());
} }
XdgRequest::NewPopup { surface } => { XdgRequest::NewPopup { surface } => {
// Do not send a configure here, the initial configure // Do not send a configure here, the initial configure
@ -461,7 +452,7 @@ pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::sl
let toplevel = SurfaceKind::Xdg(surface.clone()); let toplevel = SurfaceKind::Xdg(surface.clone());
let initial_window_location = xdg_window_map.borrow().location(&toplevel).unwrap(); let initial_window_location = xdg_window_map.borrow().location(&toplevel).unwrap();
let geometry = xdg_window_map.borrow().geometry(&toplevel).unwrap(); let geometry = xdg_window_map.borrow().geometry(&toplevel).unwrap();
let initial_window_size = (geometry.width, geometry.height); let initial_window_size = geometry.size;
with_states(surface.get_surface().unwrap(), move |states| { with_states(surface.get_surface().unwrap(), move |states| {
states states
@ -566,13 +557,13 @@ pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::sl
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) {
xdg_window_map.set_location(&kind, (geometry.x, geometry.y)); xdg_window_map.set_location(&kind, geometry.loc);
} }
} }
let ret = surface.with_pending_state(|state| { let ret = surface.with_pending_state(|state| {
state.states.set(xdg_toplevel::State::Fullscreen); state.states.set(xdg_toplevel::State::Fullscreen);
state.size = Some((geometry.width, geometry.height)); state.size = Some(geometry.size);
state.fullscreen_output = output; state.fullscreen_output = output;
}); });
if ret.is_ok() { if ret.is_ok() {
@ -611,12 +602,12 @@ pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::sl
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) {
xdg_window_map.set_location(&kind, (geometry.x, geometry.y)); xdg_window_map.set_location(&kind, geometry.loc);
} }
} }
let ret = surface.with_pending_state(|state| { let ret = surface.with_pending_state(|state| {
state.states.set(xdg_toplevel::State::Maximized); state.states.set(xdg_toplevel::State::Maximized);
state.size = Some((geometry.width, geometry.height)); state.size = Some(geometry.size);
}); });
if ret.is_ok() { if ret.is_ok() {
surface.send_configure(); surface.send_configure();
@ -656,21 +647,19 @@ pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::sl
.borrow() .borrow()
.with_primary(|_, geometry| geometry) .with_primary(|_, geometry| geometry)
.ok() .ok()
.unwrap_or_else(|| Rectangle { .unwrap_or_else(|| Rectangle::from_loc_and_size((0, 0), (800, 800)));
width: 800, let max_x =
height: 800, output_geometry.loc.x + (((output_geometry.size.w as f32) / 3.0) * 2.0) as i32;
..Default::default() let max_y =
}); output_geometry.loc.y + (((output_geometry.size.h as f32) / 3.0) * 2.0) as i32;
let max_x = output_geometry.x + (((output_geometry.width as f32) / 3.0) * 2.0) as i32; let x_range = Uniform::new(output_geometry.loc.x, max_x);
let max_y = output_geometry.y + (((output_geometry.height as f32) / 3.0) * 2.0) as i32; let y_range = Uniform::new(output_geometry.loc.y, max_y);
let x_range = Uniform::new(output_geometry.x, max_x);
let y_range = Uniform::new(output_geometry.y, max_y);
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let x = x_range.sample(&mut rng); let x = x_range.sample(&mut rng);
let y = y_range.sample(&mut rng); let y = y_range.sample(&mut rng);
shell_window_map shell_window_map
.borrow_mut() .borrow_mut()
.insert(SurfaceKind::Wl(surface), (x, y)); .insert(SurfaceKind::Wl(surface), (x, y).into());
} }
ShellRequest::SetKind { ShellRequest::SetKind {
surface, surface,
@ -696,7 +685,7 @@ pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::sl
if let Some(geometry) = output_geometry { if let Some(geometry) = output_geometry {
shell_window_map shell_window_map
.borrow_mut() .borrow_mut()
.insert(SurfaceKind::Wl(surface), (geometry.x, geometry.y)); .insert(SurfaceKind::Wl(surface), geometry.loc);
} }
} }
ShellRequest::Move { ShellRequest::Move {
@ -773,7 +762,7 @@ pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::sl
let toplevel = SurfaceKind::Wl(surface.clone()); let toplevel = SurfaceKind::Wl(surface.clone());
let initial_window_location = shell_window_map.borrow().location(&toplevel).unwrap(); let initial_window_location = shell_window_map.borrow().location(&toplevel).unwrap();
let geometry = shell_window_map.borrow().geometry(&toplevel).unwrap(); let geometry = shell_window_map.borrow().geometry(&toplevel).unwrap();
let initial_window_size = (geometry.width, geometry.height); let initial_window_size = geometry.size;
with_states(surface.get_surface().unwrap(), move |states| { with_states(surface.get_surface().unwrap(), move |states| {
states states
@ -819,9 +808,9 @@ pub struct ResizeData {
/// The edges the surface is being resized with. /// The edges the surface is being resized with.
edges: ResizeEdge, edges: ResizeEdge,
/// The initial window location. /// The initial window location.
initial_window_location: (i32, i32), initial_window_location: Point<i32, Logical>,
/// The initial window size (geometry width and height). /// The initial window size (geometry width and height).
initial_window_size: (i32, i32), initial_window_size: Size<i32, Logical>,
} }
/// State of the resize operation. /// State of the resize operation.
@ -847,9 +836,10 @@ impl Default for ResizeState {
pub struct SurfaceData { pub struct SurfaceData {
pub buffer: Option<wl_buffer::WlBuffer>, pub buffer: Option<wl_buffer::WlBuffer>,
pub texture: Option<Box<dyn std::any::Any + 'static>>, pub texture: Option<Box<dyn std::any::Any + 'static>>,
pub geometry: Option<Rectangle>, pub geometry: Option<Rectangle<i32, Logical>>,
pub resize_state: ResizeState, pub resize_state: ResizeState,
pub dimensions: Option<(i32, i32)>, pub buffer_dimensions: Option<Size<i32, Physical>>,
pub buffer_scale: i32,
} }
impl SurfaceData { impl SurfaceData {
@ -857,7 +847,8 @@ impl SurfaceData {
match attrs.buffer.take() { match attrs.buffer.take() {
Some(BufferAssignment::NewBuffer { buffer, .. }) => { Some(BufferAssignment::NewBuffer { buffer, .. }) => {
// new contents // new contents
self.dimensions = buffer_dimensions(&buffer); self.buffer_dimensions = buffer_dimensions(&buffer);
self.buffer_scale = attrs.buffer_scale;
if let Some(old_buffer) = std::mem::replace(&mut self.buffer, Some(buffer)) { if let Some(old_buffer) = std::mem::replace(&mut self.buffer, Some(buffer)) {
old_buffer.release(); old_buffer.release();
} }
@ -866,7 +857,7 @@ impl SurfaceData {
Some(BufferAssignment::Removed) => { Some(BufferAssignment::Removed) => {
// remove the contents // remove the contents
self.buffer = None; self.buffer = None;
self.dimensions = None; self.buffer_dimensions = None;
self.texture = None; self.texture = None;
} }
None => {} None => {}
@ -874,25 +865,23 @@ impl SurfaceData {
} }
/// Returns the size of the surface. /// Returns the size of the surface.
pub fn size(&self) -> Option<(i32, i32)> { pub fn size(&self) -> Option<Size<i32, Logical>> {
self.dimensions self.buffer_dimensions
.map(|dims| dims.to_logical(self.buffer_scale))
} }
/// Checks if the surface's input region contains the point. /// Checks if the surface's input region contains the point.
pub fn contains_point(&self, attrs: &SurfaceAttributes, point: (f64, f64)) -> bool { pub fn contains_point(&self, attrs: &SurfaceAttributes, point: Point<f64, Logical>) -> bool {
let (w, h) = match self.size() { let size = match self.size() {
None => return false, // If the surface has no size, it can't have an input region. None => return false, // If the surface has no size, it can't have an input region.
Some(wh) => wh, Some(size) => size,
}; };
let rect = Rectangle { let rect = Rectangle {
x: 0, loc: (0, 0).into(),
y: 0, size,
width: w, }
height: h, .to_f64();
};
let point = (point.0 as i32, point.1 as i32);
// The input region is always within the surface itself, so if the surface itself doesn't contain the // The input region is always within the surface itself, so if the surface itself doesn't contain the
// point we can return false. // point we can return false.
@ -905,7 +894,11 @@ impl SurfaceData {
return true; return true;
} }
attrs.input_region.as_ref().unwrap().contains(point) attrs
.input_region
.as_ref()
.unwrap()
.contains(point.to_i32_floor())
} }
/// Send the frame callback if it had been requested /// Send the frame callback if it had been requested
@ -962,9 +955,8 @@ fn surface_commit(surface: &wl_surface::WlSurface, window_map: &RefCell<WindowMa
} }
window_map.refresh_toplevel(&toplevel); window_map.refresh_toplevel(&toplevel);
// Get the geometry outside since it uses the token, and so would block inside.
let Rectangle { width, height, .. } = window_map.geometry(&toplevel).unwrap();
let geometry = window_map.geometry(&toplevel).unwrap();
let new_location = with_states(surface, |states| { let new_location = with_states(surface, |states| {
let mut data = states let mut data = states
.data_map .data_map
@ -990,10 +982,12 @@ fn surface_commit(surface: &wl_surface::WlSurface, window_map: &RefCell<WindowMa
let mut location = window_map.location(&toplevel).unwrap(); let mut location = window_map.location(&toplevel).unwrap();
if edges.intersects(ResizeEdge::LEFT) { if edges.intersects(ResizeEdge::LEFT) {
location.0 = initial_window_location.0 + (initial_window_size.0 - width); location.x =
initial_window_location.x + (initial_window_size.w - geometry.size.w);
} }
if edges.intersects(ResizeEdge::TOP) { if edges.intersects(ResizeEdge::TOP) {
location.1 = initial_window_location.1 + (initial_window_size.1 - height); location.y =
initial_window_location.y + (initial_window_size.h - geometry.size.h);
} }
new_location = Some(location); new_location = Some(location);

View File

@ -12,6 +12,7 @@ use smithay::{
calloop::{generic::Generic, Interest, LoopHandle, Mode, PostAction}, calloop::{generic::Generic, Interest, LoopHandle, Mode, PostAction},
wayland_server::{protocol::wl_surface::WlSurface, Display}, wayland_server::{protocol::wl_surface::WlSurface, Display},
}, },
utils::{Logical, Point},
wayland::{ wayland::{
data_device::{default_action_chooser, init_data_device, set_data_device_focus, DataDeviceEvent}, data_device::{default_action_chooser, init_data_device, set_data_device_focus, DataDeviceEvent},
seat::{CursorImageStatus, KeyboardHandle, PointerHandle, Seat, XkbConfig}, seat::{CursorImageStatus, KeyboardHandle, PointerHandle, Seat, XkbConfig},
@ -39,7 +40,7 @@ pub struct AnvilState<BackendData> {
pub pointer: PointerHandle, pub pointer: PointerHandle,
pub keyboard: KeyboardHandle, pub keyboard: KeyboardHandle,
pub suppressed_keys: Vec<u32>, pub suppressed_keys: Vec<u32>,
pub pointer_location: (f64, f64), pub pointer_location: Point<f64, Logical>,
pub cursor_status: Arc<Mutex<CursorImageStatus>>, pub cursor_status: Arc<Mutex<CursorImageStatus>>,
pub seat_name: String, pub seat_name: String,
pub seat: Seat, pub seat: Seat,
@ -167,7 +168,7 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
keyboard, keyboard,
suppressed_keys: Vec::new(), suppressed_keys: Vec::new(),
cursor_status, cursor_status,
pointer_location: (0.0, 0.0), pointer_location: (0.0, 0.0).into(),
seat_name, seat_name,
seat, seat,
start_time: std::time::Instant::now(), start_time: std::time::Instant::now(),

View File

@ -48,7 +48,10 @@ use smithay::{
Display, Display,
}, },
}, },
utils::signaling::{Linkable, SignalToken, Signaler}, utils::{
signaling::{Linkable, SignalToken, Signaler},
Logical, Point,
},
wayland::{ wayland::{
output::{Mode, PhysicalProperties}, output::{Mode, PhysicalProperties},
seat::CursorImageStatus, seat::CursorImageStatus,
@ -335,8 +338,7 @@ fn scan_connectors(
let mode = connector_info.modes()[0]; let mode = connector_info.modes()[0];
let size = mode.size(); let size = mode.size();
let mode = Mode { let mode = Mode {
width: size.0 as i32, size: (size.0 as i32, size.1 as i32).into(),
height: size.1 as i32,
refresh: (mode.vrefresh() * 1000) as i32, refresh: (mode.vrefresh() * 1000) as i32,
}; };
@ -346,11 +348,11 @@ fn scan_connectors(
connector_info.interface_id() connector_info.interface_id()
); );
let (phys_w, phys_h) = connector_info.size().unwrap_or((0, 0));
output_map.add( output_map.add(
&output_name, &output_name,
PhysicalProperties { PhysicalProperties {
width: connector_info.size().unwrap_or((0, 0)).0 as i32, size: (phys_w as i32, phys_h as i32).into(),
height: connector_info.size().unwrap_or((0, 0)).1 as i32,
subpixel: wl_output::Subpixel::Unknown, subpixel: wl_output::Subpixel::Unknown,
make: "Smithay".into(), make: "Smithay".into(),
model: "Generic DRM".into(), model: "Generic DRM".into(),
@ -618,7 +620,7 @@ impl AnvilState<UdevData> {
&mut *self.window_map.borrow_mut(), &mut *self.window_map.borrow_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,
&*self.dnd_icon.lock().unwrap(), &*self.dnd_icon.lock().unwrap(),
&mut *self.cursor_status.lock().unwrap(), &mut *self.cursor_status.lock().unwrap(),
@ -666,7 +668,7 @@ fn render_surface(
window_map: &mut WindowMap, window_map: &mut WindowMap,
backend_output_map: &[UdevOutputMap], backend_output_map: &[UdevOutputMap],
output_map: &crate::output_map::OutputMap, output_map: &crate::output_map::OutputMap,
pointer_location: &(f64, f64), pointer_location: Point<f64, Logical>,
pointer_image: &Gles2Texture, pointer_image: &Gles2Texture,
dnd_icon: &Option<wl_surface::WlSurface>, dnd_icon: &Option<wl_surface::WlSurface>,
cursor_status: &mut CursorImageStatus, cursor_status: &mut CursorImageStatus,
@ -692,27 +694,24 @@ fn render_surface(
// and draw to our buffer // and draw to our buffer
match renderer match renderer
.render( .render(
output_geometry.width as u32, // TODO: handle scale factor
output_geometry.height as u32, output_geometry.size.to_physical(1),
Transform::Flipped180, // Scanout is rotated Transform::Flipped180, // Scanout is rotated
|renderer, frame| { |renderer, frame| {
frame.clear([0.8, 0.8, 0.9, 1.0])?; frame.clear([0.8, 0.8, 0.9, 1.0])?;
// draw the surfaces // draw the surfaces
draw_windows(renderer, frame, window_map, output_geometry, logger)?; draw_windows(renderer, frame, window_map, output_geometry, logger)?;
// get pointer coordinates
let (ptr_x, ptr_y) = *pointer_location;
let ptr_x = ptr_x.trunc().abs() as i32 - output_geometry.x;
let ptr_y = ptr_y.trunc().abs() as i32 - output_geometry.y;
// set cursor // set cursor
if ptr_x >= 0 && ptr_x < output_geometry.width && ptr_y >= 0 && ptr_y < output_geometry.height if output_geometry.to_f64().contains(pointer_location) {
{ let (ptr_x, ptr_y) = pointer_location.into();
let relative_ptr_location =
Point::<i32, Logical>::from((ptr_x as i32, ptr_y as i32)) - output_geometry.loc;
// draw the dnd icon if applicable // draw the dnd icon if applicable
{ {
if let Some(ref wl_surface) = dnd_icon.as_ref() { if let Some(ref wl_surface) = dnd_icon.as_ref() {
if wl_surface.as_ref().is_alive() { if wl_surface.as_ref().is_alive() {
draw_dnd_icon(renderer, frame, wl_surface, (ptr_x, ptr_y), logger)?; draw_dnd_icon(renderer, frame, wl_surface, relative_ptr_location, logger)?;
} }
} }
} }
@ -728,9 +727,15 @@ fn render_surface(
} }
if let CursorImageStatus::Image(ref wl_surface) = *cursor_status { if let CursorImageStatus::Image(ref wl_surface) = *cursor_status {
draw_cursor(renderer, frame, wl_surface, (ptr_x, ptr_y), logger)?; draw_cursor(renderer, frame, wl_surface, relative_ptr_location, logger)?;
} else { } else {
frame.render_texture_at(pointer_image, (ptr_x, ptr_y), Transform::Normal, 1.0)?; // TODO: handle output scale factor
frame.render_texture_at(
pointer_image,
relative_ptr_location.to_physical(1),
Transform::Normal,
1.0,
)?;
} }
} }
} }
@ -776,7 +781,7 @@ fn initial_render(surface: &mut RenderSurface, renderer: &mut Gles2Renderer) ->
renderer.bind(dmabuf)?; renderer.bind(dmabuf)?;
// Does not matter if we render an empty frame // Does not matter if we render an empty frame
renderer renderer
.render(1, 1, Transform::Normal, |_, frame| { .render((1, 1).into(), Transform::Normal, |_, frame| {
frame frame
.clear([0.8, 0.8, 0.9, 1.0]) .clear([0.8, 0.8, 0.9, 1.0])
.map_err(Into::<SwapBuffersError>::into) .map_err(Into::<SwapBuffersError>::into)

View File

@ -3,7 +3,7 @@ use std::sync::Mutex;
use smithay::{ use smithay::{
reexports::{wayland_protocols::xdg_shell::server::xdg_toplevel, wayland_server::protocol::wl_surface}, reexports::{wayland_protocols::xdg_shell::server::xdg_toplevel, wayland_server::protocol::wl_surface},
utils::Rectangle, utils::{Logical, Point, Rectangle},
wayland::{ wayland::{
compositor::{with_states, with_surface_tree_downward, SubsurfaceCachedState, TraversalAction}, compositor::{with_states, with_surface_tree_downward, SubsurfaceCachedState, TraversalAction},
shell::{ shell::{
@ -98,12 +98,12 @@ impl PopupKind {
.flatten() .flatten()
} }
pub fn location(&self) -> (i32, i32) { pub fn location(&self) -> Point<i32, Logical> {
let wl_surface = match self.get_surface() { let wl_surface = match self.get_surface() {
Some(s) => s, Some(s) => s,
None => return (0, 0), None => return (0, 0).into(),
}; };
let geometry = with_states(wl_surface, |states| { with_states(wl_surface, |states| {
states states
.data_map .data_map
.get::<Mutex<XdgPopupSurfaceRoleAttributes>>() .get::<Mutex<XdgPopupSurfaceRoleAttributes>>()
@ -113,26 +113,26 @@ impl PopupKind {
.current .current
.geometry .geometry
}) })
.unwrap_or_default(); .unwrap_or_default()
(geometry.x, geometry.y) .loc
} }
} }
struct Window { struct Window {
location: (i32, i32), location: Point<i32, Logical>,
/// A bounding box over this window and its children. /// A bounding box over this window and its children.
/// ///
/// Used for the fast path of the check in `matching`, and as the fall-back for the window /// Used for the fast path of the check in `matching`, and as the fall-back for the window
/// geometry if that's not set explicitly. /// geometry if that's not set explicitly.
bbox: Rectangle, bbox: Rectangle<i32, Logical>,
toplevel: Kind, toplevel: Kind,
} }
impl Window { impl Window {
/// Finds the topmost surface under this point if any and returns it together with the location of this /// Finds the topmost surface under this point if any and returns it together with the location of this
/// surface. /// surface.
fn matching(&self, point: (f64, f64)) -> Option<(wl_surface::WlSurface, (f64, f64))> { fn matching(&self, point: Point<f64, Logical>) -> Option<(wl_surface::WlSurface, Point<i32, Logical>)> {
if !self.bbox.contains((point.0 as i32, point.1 as i32)) { if !self.bbox.to_f64().contains(point) {
return None; return None;
} }
// need to check more carefully // need to check more carefully
@ -141,27 +141,26 @@ impl Window {
with_surface_tree_downward( with_surface_tree_downward(
wl_surface, wl_surface,
self.location, self.location,
|wl_surface, states, &(mut x, mut y)| { |wl_surface, states, location| {
let mut location = *location;
let data = states.data_map.get::<RefCell<SurfaceData>>(); let data = states.data_map.get::<RefCell<SurfaceData>>();
if states.role == Some("subsurface") { if states.role == Some("subsurface") {
let current = states.cached_state.current::<SubsurfaceCachedState>(); let current = states.cached_state.current::<SubsurfaceCachedState>();
x += current.location.0; location += current.location;
y += current.location.1;
} }
let surface_local_point = (point.0 - x as f64, point.1 - y as f64);
let contains_the_point = data let contains_the_point = data
.map(|data| { .map(|data| {
data.borrow() data.borrow()
.contains_point(&*states.cached_state.current(), surface_local_point) .contains_point(&*states.cached_state.current(), point - location.to_f64())
}) })
.unwrap_or(false); .unwrap_or(false);
if contains_the_point { if contains_the_point {
*found.borrow_mut() = Some((wl_surface.clone(), (x as f64, y as f64))); *found.borrow_mut() = Some((wl_surface.clone(), location));
} }
TraversalAction::DoChildren((x, y)) TraversalAction::DoChildren(location)
}, },
|_, _, _| {}, |_, _, _| {},
|_, _, _| { |_, _, _| {
@ -174,29 +173,25 @@ impl Window {
} }
fn self_update(&mut self) { fn self_update(&mut self) {
let (base_x, base_y) = self.location; let mut bounding_box = Rectangle::from_loc_and_size(self.location, (0, 0));
let (mut min_x, mut min_y, mut max_x, mut max_y) = (base_x, base_y, base_x, base_y);
if let Some(wl_surface) = self.toplevel.get_surface() { if let Some(wl_surface) = self.toplevel.get_surface() {
with_surface_tree_downward( with_surface_tree_downward(
wl_surface, wl_surface,
(base_x, base_y), self.location,
|_, states, &(mut x, mut y)| { |_, states, &loc| {
let mut loc = loc;
let data = states.data_map.get::<RefCell<SurfaceData>>(); let data = states.data_map.get::<RefCell<SurfaceData>>();
if let Some((w, h)) = data.and_then(|d| d.borrow().size()) { if let Some(size) = data.and_then(|d| d.borrow().size()) {
if states.role == Some("subsurface") { if states.role == Some("subsurface") {
let current = states.cached_state.current::<SubsurfaceCachedState>(); let current = states.cached_state.current::<SubsurfaceCachedState>();
x += current.location.0; loc += current.location;
y += current.location.1;
} }
// Update the bounding box. // Update the bounding box.
min_x = min_x.min(x); bounding_box = bounding_box.merge(Rectangle::from_loc_and_size(loc, size));
min_y = min_y.min(y);
max_x = max_x.max(x + w);
max_y = max_y.max(y + h);
TraversalAction::DoChildren((x, y)) TraversalAction::DoChildren(loc)
} else { } else {
// If the parent surface is unmapped, then the child surfaces are hidden as // If the parent surface is unmapped, then the child surfaces are hidden as
// well, no need to consider them here. // well, no need to consider them here.
@ -207,16 +202,11 @@ impl Window {
|_, _, _| true, |_, _, _| true,
); );
} }
self.bbox = Rectangle { self.bbox = bounding_box;
x: min_x,
y: min_y,
width: max_x - min_x,
height: max_y - min_y,
};
} }
/// Returns the geometry of this window. /// Returns the geometry of this window.
pub fn geometry(&self) -> Rectangle { pub fn geometry(&self) -> Rectangle<i32, Logical> {
// It's the set geometry with the full bounding box as the fallback. // It's the set geometry with the full bounding box as the fallback.
with_states(self.toplevel.get_surface().unwrap(), |states| { with_states(self.toplevel.get_surface().unwrap(), |states| {
states.cached_state.current::<SurfaceCachedState>().geometry states.cached_state.current::<SurfaceCachedState>().geometry
@ -261,7 +251,7 @@ impl WindowMap {
} }
} }
pub fn insert(&mut self, toplevel: Kind, location: (i32, i32)) { pub fn insert(&mut self, toplevel: Kind, location: Point<i32, Logical>) {
let mut window = Window { let mut window = Window {
location, location,
bbox: Rectangle::default(), bbox: Rectangle::default(),
@ -276,7 +266,10 @@ impl WindowMap {
self.popups.push(popup); self.popups.push(popup);
} }
pub fn get_surface_under(&self, point: (f64, f64)) -> Option<(wl_surface::WlSurface, (f64, f64))> { pub fn get_surface_under(
&self,
point: Point<f64, Logical>,
) -> Option<(wl_surface::WlSurface, Point<i32, Logical>)> {
for w in &self.windows { for w in &self.windows {
if let Some(surface) = w.matching(point) { if let Some(surface) = w.matching(point) {
return Some(surface); return Some(surface);
@ -287,8 +280,8 @@ impl WindowMap {
pub fn get_surface_and_bring_to_top( pub fn get_surface_and_bring_to_top(
&mut self, &mut self,
point: (f64, f64), point: Point<f64, Logical>,
) -> Option<(wl_surface::WlSurface, (f64, f64))> { ) -> Option<(wl_surface::WlSurface, Point<i32, Logical>)> {
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) { if let Some(surface) = w.matching(point) {
@ -316,7 +309,7 @@ impl WindowMap {
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(&Kind, (i32, i32), &Rectangle), Func: FnMut(&Kind, Point<i32, Logical>, &Rectangle<i32, Logical>),
{ {
for w in self.windows.iter().rev() { for w in self.windows.iter().rev() {
f(&w.toplevel, w.location, &w.bbox) f(&w.toplevel, w.location, &w.bbox)
@ -386,7 +379,7 @@ impl WindowMap {
} }
/// Returns the location of the toplevel, if it exists. /// Returns the location of the toplevel, if it exists.
pub fn location(&self, toplevel: &Kind) -> Option<(i32, i32)> { pub fn location(&self, toplevel: &Kind) -> Option<Point<i32, Logical>> {
self.windows self.windows
.iter() .iter()
.find(|w| &w.toplevel == toplevel) .find(|w| &w.toplevel == toplevel)
@ -394,7 +387,7 @@ impl WindowMap {
} }
/// Sets the location of the toplevel, if it exists. /// Sets the location of the toplevel, if it exists.
pub fn set_location(&mut self, toplevel: &Kind, location: (i32, i32)) { pub fn set_location(&mut self, toplevel: &Kind, location: Point<i32, Logical>) {
if let Some(w) = self.windows.iter_mut().find(|w| &w.toplevel == toplevel) { if let Some(w) = self.windows.iter_mut().find(|w| &w.toplevel == toplevel) {
w.location = location; w.location = location;
w.self_update(); w.self_update();
@ -402,7 +395,7 @@ impl WindowMap {
} }
/// Returns the geometry of the toplevel, if it exists. /// Returns the geometry of the toplevel, if it exists.
pub fn geometry(&self, toplevel: &Kind) -> Option<Rectangle> { pub fn geometry(&self, toplevel: &Kind) -> Option<Rectangle<i32, Logical>> {
self.windows self.windows
.iter() .iter()
.find(|w| &w.toplevel == toplevel) .find(|w| &w.toplevel == toplevel)

View File

@ -65,7 +65,7 @@ pub fn run_winit(
); );
}; };
let (w, h): (u32, u32) = renderer.borrow().window_size().physical_size.into(); let size = renderer.borrow().window_size().physical_size;
/* /*
* Initialize the globals * Initialize the globals
@ -74,16 +74,14 @@ pub fn run_winit(
let mut state = AnvilState::init(display.clone(), event_loop.handle(), WinitData, log.clone()); let mut state = AnvilState::init(display.clone(), event_loop.handle(), WinitData, log.clone());
let mode = Mode { let mode = Mode {
width: w as i32, size,
height: h as i32,
refresh: 60_000, refresh: 60_000,
}; };
state.output_map.borrow_mut().add( state.output_map.borrow_mut().add(
OUTPUT_NAME, OUTPUT_NAME,
PhysicalProperties { PhysicalProperties {
width: 0, size: (0, 0).into(),
height: 0,
subpixel: wl_output::Subpixel::Unknown, subpixel: wl_output::Subpixel::Unknown,
make: "Smithay".into(), make: "Smithay".into(),
model: "Winit".into(), model: "Winit".into(),
@ -132,13 +130,13 @@ pub fn run_winit(
&log, &log,
)?; )?;
let (x, y) = state.pointer_location; let (x, y) = state.pointer_location.into();
// draw the dnd icon if any // draw the dnd icon if any
{ {
let guard = state.dnd_icon.lock().unwrap(); let guard = state.dnd_icon.lock().unwrap();
if let Some(ref surface) = *guard { if let Some(ref surface) = *guard {
if surface.as_ref().is_alive() { if surface.as_ref().is_alive() {
draw_dnd_icon(renderer, frame, surface, (x as i32, y as i32), &log)?; draw_dnd_icon(renderer, frame, surface, (x as i32, y as i32).into(), &log)?;
} }
} }
} }
@ -157,7 +155,7 @@ pub fn run_winit(
// draw as relevant // draw as relevant
if let CursorImageStatus::Image(ref surface) = *guard { if let CursorImageStatus::Image(ref surface) = *guard {
cursor_visible = false; cursor_visible = false;
draw_cursor(renderer, frame, surface, (x as i32, y as i32), &log)?; draw_cursor(renderer, frame, surface, (x as i32, y as i32).into(), &log)?;
} else { } else {
cursor_visible = true; cursor_visible = true;
} }

View File

@ -2,6 +2,7 @@ use std::{cell::RefCell, collections::HashMap, convert::TryFrom, os::unix::net::
use smithay::{ use smithay::{
reexports::wayland_server::{protocol::wl_surface::WlSurface, Client}, reexports::wayland_server::{protocol::wl_surface::WlSurface, Client},
utils::{Logical, Point},
wayland::compositor::give_role, wayland::compositor::give_role,
}; };
@ -67,7 +68,7 @@ struct X11State {
conn: Rc<RustConnection>, conn: Rc<RustConnection>,
atoms: Atoms, atoms: Atoms,
log: slog::Logger, log: slog::Logger,
unpaired_surfaces: HashMap<u32, (Window, (i32, i32))>, unpaired_surfaces: HashMap<u32, (Window, Point<i32, Logical>)>,
window_map: Rc<RefCell<WindowMap>>, window_map: Rc<RefCell<WindowMap>>,
} }
@ -169,7 +170,7 @@ impl X11State {
let location = { let location = {
match self.conn.get_geometry(msg.window)?.reply() { match self.conn.get_geometry(msg.window)?.reply() {
Ok(geo) => (geo.x.into(), geo.y.into()), Ok(geo) => (geo.x as i32, geo.y as i32).into(),
Err(err) => { Err(err) => {
error!( error!(
self.log, self.log,
@ -177,7 +178,7 @@ impl X11State {
msg.window; msg.window;
"err" => format!("{:?}", err), "err" => format!("{:?}", err),
); );
(0, 0) (0, 0).into()
} }
} }
}; };
@ -201,7 +202,7 @@ impl X11State {
Ok(()) Ok(())
} }
fn new_window(&mut self, window: Window, surface: WlSurface, location: (i32, i32)) { fn new_window(&mut self, window: Window, surface: WlSurface, location: Point<i32, Logical>) {
debug!(self.log, "Matched X11 surface {:x?} to {:x?}", window, surface); debug!(self.log, "Matched X11 surface {:x?} to {:x?}", window, surface);
if give_role(&surface, "x11_surface").is_err() { if give_role(&surface, "x11_surface").is_err() {

View File

@ -822,7 +822,10 @@ impl EGLBufferReader {
/// ///
/// In case the buffer is not managed by EGL (but e.g. the [`wayland::shm` module](crate::wayland::shm)) or the /// In case the buffer is not managed by EGL (but e.g. the [`wayland::shm` module](crate::wayland::shm)) or the
/// context has been lost, `None` is returned. /// context has been lost, `None` is returned.
pub fn egl_buffer_dimensions(&self, buffer: &WlBuffer) -> Option<(i32, i32)> { pub fn egl_buffer_dimensions(
&self,
buffer: &WlBuffer,
) -> Option<crate::utils::Size<i32, crate::utils::Physical>> {
let mut width: i32 = 0; let mut width: i32 = 0;
if unsafe { if unsafe {
ffi::egl::QueryWaylandBufferWL( ffi::egl::QueryWaylandBufferWL(
@ -847,7 +850,7 @@ impl EGLBufferReader {
return None; return None;
} }
Some((width, height)) Some((width, height).into())
} }
} }

View File

@ -9,6 +9,8 @@ pub use tablet::{
TabletToolEvent, TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, TabletToolType, TabletToolEvent, TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, TabletToolType,
}; };
use crate::utils::{Logical, Point, Raw};
/// Trait for generic functions every input device does provide /// Trait for generic functions every input device does provide
pub trait Device: PartialEq + Eq + std::hash::Hash { pub trait Device: PartialEq + Eq + std::hash::Hash {
/// Unique id of a single device at a point in time. /// Unique id of a single device at a point in time.
@ -222,8 +224,8 @@ impl<B: InputBackend> PointerAxisEvent<B> for UnusedEvent {
/// Trait for pointer events generated by relative device movement. /// Trait for pointer events generated by relative device movement.
pub trait PointerMotionEvent<B: InputBackend>: Event<B> { pub trait PointerMotionEvent<B: InputBackend>: Event<B> {
/// Delta between the last and new pointer device position interpreted as pixel movement /// Delta between the last and new pointer device position interpreted as pixel movement
fn delta(&self) -> (f64, f64) { fn delta(&self) -> Point<f64, Logical> {
(self.delta_x(), self.delta_y()) (self.delta_x(), self.delta_y()).into()
} }
/// Delta on the x axis between the last and new pointer device position interpreted as pixel movement /// Delta on the x axis between the last and new pointer device position interpreted as pixel movement
@ -247,8 +249,8 @@ pub trait PointerMotionAbsoluteEvent<B: InputBackend>: Event<B> {
/// Device position in it's original coordinate space. /// Device position in it's original coordinate space.
/// ///
/// The format is defined by the backend implementation. /// The format is defined by the backend implementation.
fn position(&self) -> (f64, f64) { fn position(&self) -> Point<f64, Raw> {
(self.x(), self.y()) (self.x(), self.y()).into()
} }
/// Device x position in it's original coordinate space. /// Device x position in it's original coordinate space.
@ -263,11 +265,12 @@ pub trait PointerMotionAbsoluteEvent<B: InputBackend>: Event<B> {
/// Device position converted to the targets coordinate space. /// Device position converted to the targets coordinate space.
/// E.g. the focused output's resolution. /// E.g. the focused output's resolution.
fn position_transformed(&self, coordinate_space: (u32, u32)) -> (f64, f64) { fn position_transformed(&self, coordinate_space: Point<u32, Logical>) -> Point<f64, Logical> {
( (
self.x_transformed(coordinate_space.0), self.x_transformed(coordinate_space.x),
self.y_transformed(coordinate_space.1), self.y_transformed(coordinate_space.y),
) )
.into()
} }
/// Device x position converted to the targets coordinate space's width. /// Device x position converted to the targets coordinate space's width.
@ -322,17 +325,18 @@ pub trait TouchDownEvent<B: InputBackend>: Event<B> {
/// Touch position in the device's native coordinate space /// Touch position in the device's native coordinate space
/// ///
/// The actual format is defined by the implementation. /// The actual format is defined by the implementation.
fn position(&self) -> (f64, f64) { fn position(&self) -> Point<f64, Raw> {
(self.x(), self.y()) (self.x(), self.y()).into()
} }
/// Touch position converted into the target coordinate space. /// Touch position converted into the target coordinate space.
/// E.g. the focused output's resolution. /// E.g. the focused output's resolution.
fn position_transformed(&self, coordinate_space: (u32, u32)) -> (f64, f64) { fn position_transformed(&self, coordinate_space: Point<u32, Logical>) -> Point<f64, Logical> {
( (
self.x_transformed(coordinate_space.0), self.x_transformed(coordinate_space.x),
self.y_transformed(coordinate_space.1), self.y_transformed(coordinate_space.y),
) )
.into()
} }
/// Touch event's x-coordinate in the device's native coordinate space /// Touch event's x-coordinate in the device's native coordinate space
@ -384,17 +388,18 @@ pub trait TouchMotionEvent<B: InputBackend>: Event<B> {
/// Touch position in the device's native coordinate space /// Touch position in the device's native coordinate space
/// ///
/// The actual format is defined by the implementation. /// The actual format is defined by the implementation.
fn position(&self) -> (f64, f64) { fn position(&self) -> Point<f64, Raw> {
(self.x(), self.y()) (self.x(), self.y()).into()
} }
/// Touch position converted into the target coordinate space. /// Touch position converted into the target coordinate space.
/// E.g. the focused output's resolution. /// E.g. the focused output's resolution.
fn position_transformed(&self, coordinate_space: (u32, u32)) -> (f64, f64) { fn position_transformed(&self, coordinate_space: Point<u32, Logical>) -> Point<f64, Logical> {
( (
self.x_transformed(coordinate_space.0), self.x_transformed(coordinate_space.x),
self.y_transformed(coordinate_space.1), self.y_transformed(coordinate_space.y),
) )
.into()
} }
/// Touch event's x-coordinate in the device's native coordinate space /// Touch event's x-coordinate in the device's native coordinate space

View File

@ -1,4 +1,5 @@
use super::{ButtonState, Event, InputBackend, UnusedEvent}; use super::{ButtonState, Event, InputBackend, UnusedEvent};
use crate::utils::{Logical, Point, Raw};
use bitflags::bitflags; use bitflags::bitflags;
/// Description of physical tablet tool /// Description of physical tablet tool
@ -62,21 +63,22 @@ pub trait TabletToolEvent<B: InputBackend> {
fn tool(&self) -> TabletToolDescriptor; fn tool(&self) -> TabletToolDescriptor;
/// Delta between the last and new pointer device position interpreted as pixel movement /// Delta between the last and new pointer device position interpreted as pixel movement
fn delta(&self) -> (f64, f64) { fn delta(&self) -> Point<f64, Logical> {
(self.delta_x(), self.delta_y()) (self.delta_x(), self.delta_y()).into()
} }
/// Tool position in the device's native coordinate space /// Tool position in the device's native coordinate space
fn position(&self) -> (f64, f64) { fn position(&self) -> Point<f64, Raw> {
(self.x(), self.y()) (self.x(), self.y()).into()
} }
/// Tool position converted into the target coordinate space. /// Tool position converted into the target coordinate space.
fn position_transformed(&self, coordinate_space: (u32, u32)) -> (f64, f64) { fn position_transformed(&self, coordinate_space: Point<u32, Logical>) -> Point<f64, Logical> {
( (
self.x_transformed(coordinate_space.0), self.x_transformed(coordinate_space.x),
self.y_transformed(coordinate_space.1), self.y_transformed(coordinate_space.y),
) )
.into()
} }
/// Returns the current tilt along the (X,Y) axis of the tablet's current logical /// Returns the current tilt along the (X,Y) axis of the tablet's current logical

View File

@ -26,6 +26,7 @@ use crate::backend::egl::{
EGLContext, EGLSurface, MakeCurrentError, EGLContext, EGLSurface, MakeCurrentError,
}; };
use crate::backend::SwapBuffersError; use crate::backend::SwapBuffersError;
use crate::utils::{Physical, Size};
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))] #[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
use super::ImportEgl; use super::ImportEgl;
@ -34,7 +35,7 @@ use super::{ImportDma, ImportShm};
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))] #[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
use crate::backend::egl::{display::EGLBufferReader, Format as EGLFormat}; use crate::backend::egl::{display::EGLBufferReader, Format as EGLFormat};
#[cfg(feature = "wayland_frontend")] #[cfg(feature = "wayland_frontend")]
use crate::utils::Rectangle; use crate::utils::{Buffer, Rectangle};
#[cfg(feature = "wayland_frontend")] #[cfg(feature = "wayland_frontend")]
use wayland_server::protocol::{wl_buffer, wl_shm}; use wayland_server::protocol::{wl_buffer, wl_shm};
@ -514,7 +515,7 @@ impl ImportShm for Gles2Renderer {
&mut self, &mut self,
buffer: &wl_buffer::WlBuffer, buffer: &wl_buffer::WlBuffer,
surface: Option<&crate::wayland::compositor::SurfaceData>, surface: Option<&crate::wayland::compositor::SurfaceData>,
damage: &[Rectangle], damage: &[Rectangle<i32, Buffer>],
) -> Result<Gles2Texture, Gles2Error> { ) -> Result<Gles2Texture, Gles2Error> {
use crate::wayland::shm::with_buffer_contents; use crate::wayland::shm::with_buffer_contents;
@ -591,15 +592,15 @@ impl ImportShm for Gles2Renderer {
} else { } else {
for region in damage.iter() { for region in damage.iter() {
trace!(self.logger, "Uploading partial shm texture for {:?}", buffer); trace!(self.logger, "Uploading partial shm texture for {:?}", buffer);
self.gl.PixelStorei(ffi::UNPACK_SKIP_PIXELS, region.x); self.gl.PixelStorei(ffi::UNPACK_SKIP_PIXELS, region.loc.x);
self.gl.PixelStorei(ffi::UNPACK_SKIP_ROWS, region.y); self.gl.PixelStorei(ffi::UNPACK_SKIP_ROWS, region.loc.y);
self.gl.TexSubImage2D( self.gl.TexSubImage2D(
ffi::TEXTURE_2D, ffi::TEXTURE_2D,
0, 0,
region.x, region.loc.x,
region.y, region.loc.y,
region.width, region.size.w,
region.height, region.size.h,
gl_format, gl_format,
ffi::UNSIGNED_BYTE as u32, ffi::UNSIGNED_BYTE as u32,
slice.as_ptr().offset(offset as isize) as *const _, slice.as_ptr().offset(offset as isize) as *const _,
@ -1014,8 +1015,7 @@ impl Renderer for Gles2Renderer {
fn render<F, R>( fn render<F, R>(
&mut self, &mut self,
width: u32, size: Size<i32, Physical>,
height: u32,
transform: Transform, transform: Transform,
rendering: F, rendering: F,
) -> Result<R, Self::Error> ) -> Result<R, Self::Error>
@ -1027,7 +1027,7 @@ impl Renderer for Gles2Renderer {
self.cleanup()?; self.cleanup()?;
unsafe { unsafe {
self.gl.Viewport(0, 0, width as i32, height as i32); self.gl.Viewport(0, 0, size.w, size.h);
self.gl.Enable(ffi::BLEND); self.gl.Enable(ffi::BLEND);
self.gl.BlendFunc(ffi::ONE, ffi::ONE_MINUS_SRC_ALPHA); self.gl.BlendFunc(ffi::ONE, ffi::ONE_MINUS_SRC_ALPHA);
@ -1037,8 +1037,8 @@ impl Renderer for Gles2Renderer {
// glOrtho(0, width, 0, height, 1, 1); // glOrtho(0, width, 0, height, 1, 1);
let mut renderer = Matrix3::<f32>::identity(); let mut renderer = Matrix3::<f32>::identity();
let t = Matrix3::<f32>::identity(); let t = Matrix3::<f32>::identity();
let x = 2.0 / (width as f32); let x = 2.0 / (size.w as f32);
let y = 2.0 / (height as f32); let y = 2.0 / (size.h as f32);
// Rotation & Reflection // Rotation & Reflection
renderer[0][0] = x * t[0][0]; renderer[0][0] = x * t[0][0];

View File

@ -10,6 +10,8 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::error::Error; use std::error::Error;
use crate::utils::{Buffer, Physical, Point, Size};
#[cfg(feature = "wayland_frontend")] #[cfg(feature = "wayland_frontend")]
use crate::{utils::Rectangle, wayland::compositor::SurfaceData}; use crate::{utils::Rectangle, wayland::compositor::SurfaceData};
use cgmath::{prelude::*, Matrix3, Vector2}; use cgmath::{prelude::*, Matrix3, Vector2};
@ -178,7 +180,7 @@ pub trait Frame {
fn render_texture_at( fn render_texture_at(
&mut self, &mut self,
texture: &Self::TextureId, texture: &Self::TextureId,
pos: (i32, i32), pos: Point<i32, Physical>,
transform: Transform, transform: Transform,
alpha: f32, alpha: f32,
) -> Result<(), Self::Error> { ) -> Result<(), Self::Error> {
@ -186,7 +188,7 @@ pub trait Frame {
// position and scale // position and scale
let size = texture.size(); let size = texture.size();
mat = mat * Matrix3::from_translation(Vector2::new(pos.0 as f32, pos.1 as f32)); mat = mat * Matrix3::from_translation(Vector2::new(pos.x as f32, pos.y as f32));
mat = mat * Matrix3::from_nonuniform_scale(size.0 as f32, size.1 as f32); mat = mat * Matrix3::from_nonuniform_scale(size.0 as f32, size.1 as f32);
//apply surface transformation //apply surface transformation
@ -234,8 +236,7 @@ pub trait Renderer {
/// - (Renderers not implementing `Bind` always have a default target.) /// - (Renderers not implementing `Bind` always have a default target.)
fn render<F, R>( fn render<F, R>(
&mut self, &mut self,
width: u32, size: Size<i32, Physical>,
height: u32,
transform: Transform, transform: Transform,
rendering: F, rendering: F,
) -> Result<R, Self::Error> ) -> Result<R, Self::Error>
@ -265,7 +266,7 @@ pub trait ImportShm: Renderer {
&mut self, &mut self,
buffer: &wl_buffer::WlBuffer, buffer: &wl_buffer::WlBuffer,
surface: Option<&crate::wayland::compositor::SurfaceData>, surface: Option<&crate::wayland::compositor::SurfaceData>,
damage: &[Rectangle], damage: &[Rectangle<i32, Buffer>],
) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>; ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>;
/// Returns supported formats for shared memory buffers. /// Returns supported formats for shared memory buffers.
@ -405,7 +406,7 @@ pub trait ImportAll: Renderer {
&mut self, &mut self,
buffer: &wl_buffer::WlBuffer, buffer: &wl_buffer::WlBuffer,
surface: Option<&crate::wayland::compositor::SurfaceData>, surface: Option<&crate::wayland::compositor::SurfaceData>,
damage: &[Rectangle], damage: &[Rectangle<i32, Buffer>],
) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>>; ) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>>;
} }
@ -420,7 +421,7 @@ impl<R: Renderer + ImportShm + ImportEgl + ImportDma> ImportAll for R {
&mut self, &mut self,
buffer: &wl_buffer::WlBuffer, buffer: &wl_buffer::WlBuffer,
surface: Option<&SurfaceData>, surface: Option<&SurfaceData>,
damage: &[Rectangle], damage: &[Rectangle<i32, Buffer>],
) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>> { ) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>> {
match buffer_type(buffer) { match buffer_type(buffer) {
Some(BufferType::Shm) => Some(self.import_shm_buffer(buffer, surface, damage)), Some(BufferType::Shm) => Some(self.import_shm_buffer(buffer, surface, damage)),
@ -440,7 +441,7 @@ impl<R: Renderer + ImportShm + ImportDma> ImportAll for R {
&mut self, &mut self,
buffer: &wl_buffer::WlBuffer, buffer: &wl_buffer::WlBuffer,
surface: Option<&SurfaceData>, surface: Option<&SurfaceData>,
damage: &[Rectangle], damage: &[Rectangle<i32, Buffer>],
) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>> { ) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>> {
match buffer_type(buffer) { match buffer_type(buffer) {
Some(BufferType::Shm) => Some(self.import_shm_buffer(buffer, surface, damage)), Some(BufferType::Shm) => Some(self.import_shm_buffer(buffer, surface, damage)),
@ -497,29 +498,23 @@ pub fn buffer_type(buffer: &wl_buffer::WlBuffer) -> Option<BufferType> {
/// ///
/// *Note*: This will only return dimensions for buffer types known to smithay (see [`buffer_type`]) /// *Note*: This will only return dimensions for buffer types known to smithay (see [`buffer_type`])
#[cfg(feature = "wayland_frontend")] #[cfg(feature = "wayland_frontend")]
pub fn buffer_dimensions(buffer: &wl_buffer::WlBuffer) -> Option<(i32, i32)> { pub fn buffer_dimensions(buffer: &wl_buffer::WlBuffer) -> Option<Size<i32, Physical>> {
use crate::backend::allocator::Buffer; use crate::backend::allocator::Buffer;
if let Some(buf) = buffer.as_ref().user_data().get::<Dmabuf>() { if let Some(buf) = buffer.as_ref().user_data().get::<Dmabuf>() {
return Some((buf.width() as i32, buf.height() as i32)); return Some((buf.width() as i32, buf.height() as i32).into());
} }
#[cfg(all(feature = "backend_egl", feature = "use_system_lib"))] #[cfg(all(feature = "backend_egl", feature = "use_system_lib"))]
if let Some((w, h)) = BUFFER_READER if let Some(dim) = BUFFER_READER
.lock() .lock()
.unwrap() .unwrap()
.as_ref() .as_ref()
.and_then(|x| x.upgrade()) .and_then(|x| x.upgrade())
.and_then(|x| x.egl_buffer_dimensions(&buffer)) .and_then(|x| x.egl_buffer_dimensions(&buffer))
{ {
return Some((w, h)); return Some(dim);
} }
if let Ok((w, h)) = crate::wayland::shm::with_buffer_contents(&buffer, |_, data| (data.width, data.height).into()).ok()
crate::wayland::shm::with_buffer_contents(&buffer, |_, data| (data.width, data.height))
{
return Some((w, h));
}
None
} }

View File

@ -19,9 +19,11 @@
//! The other types in this module are the instances of the associated types of these //! The other types in this module are the instances of the associated types of these
//! two traits for the winit backend. //! two traits for the winit backend.
use crate::backend::egl::display::EGLDisplay; use crate::{
use crate::backend::{ backend::{
egl::{context::GlAttributes, native, EGLContext, EGLSurface, Error as EGLError}, egl::{
context::GlAttributes, display::EGLDisplay, native, EGLContext, EGLSurface, Error as EGLError,
},
input::{ input::{
Axis, AxisSource, ButtonState, Device, DeviceCapability, Event as BackendEvent, InputBackend, Axis, AxisSource, ButtonState, Device, DeviceCapability, Event as BackendEvent, InputBackend,
InputEvent, KeyState, KeyboardKeyEvent, MouseButton, PointerAxisEvent, PointerButtonEvent, InputEvent, KeyState, KeyboardKeyEvent, MouseButton, PointerAxisEvent, PointerButtonEvent,
@ -32,11 +34,13 @@ use crate::backend::{
gles2::{Gles2Error, Gles2Frame, Gles2Renderer}, gles2::{Gles2Error, Gles2Frame, Gles2Renderer},
Bind, Renderer, Transform, Unbind, Bind, Renderer, Transform, Unbind,
}, },
},
utils::{Logical, Physical, Size},
}; };
use std::{cell::RefCell, path::PathBuf, rc::Rc, time::Instant}; use std::{cell::RefCell, path::PathBuf, rc::Rc, time::Instant};
use wayland_egl as wegl; use wayland_egl as wegl;
use winit::{ use winit::{
dpi::{LogicalPosition, LogicalSize, PhysicalSize}, dpi::{LogicalPosition, LogicalSize},
event::{ event::{
ElementState, Event, KeyboardInput, MouseButton as WinitMouseButton, MouseScrollDelta, Touch, ElementState, Event, KeyboardInput, MouseButton as WinitMouseButton, MouseScrollDelta, Touch,
TouchPhase, WindowEvent, TouchPhase, WindowEvent,
@ -71,11 +75,17 @@ pub enum Error {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct WindowSize { pub struct WindowSize {
/// Pixel side of the window /// Pixel side of the window
pub physical_size: PhysicalSize<u32>, pub physical_size: Size<i32, Physical>,
/// Scaling factor of the window /// Scaling factor of the window
pub scale_factor: f64, pub scale_factor: f64,
} }
impl WindowSize {
fn logical_size(&self) -> Size<f64, Logical> {
self.physical_size.to_f64().to_logical(self.scale_factor)
}
}
/// Window with an active EGL Context created by `winit`. Implements the [`Renderer`] trait /// Window with an active EGL Context created by `winit`. Implements the [`Renderer`] trait
#[derive(Debug)] #[derive(Debug)]
pub struct WinitGraphicsBackend { pub struct WinitGraphicsBackend {
@ -84,7 +94,7 @@ pub struct WinitGraphicsBackend {
egl: Rc<EGLSurface>, egl: Rc<EGLSurface>,
window: Rc<WinitWindow>, window: Rc<WinitWindow>,
size: Rc<RefCell<WindowSize>>, size: Rc<RefCell<WindowSize>>,
resize_notification: Rc<Cell<Option<(u32, u32)>>>, resize_notification: Rc<Cell<Option<Size<i32, Physical>>>>,
} }
/// Abstracted event loop of a [`WinitWindow`] implementing the [`InputBackend`] trait /// Abstracted event loop of a [`WinitWindow`] implementing the [`InputBackend`] trait
@ -100,7 +110,7 @@ pub struct WinitInputBackend {
logger: ::slog::Logger, logger: ::slog::Logger,
initialized: bool, initialized: bool,
size: Rc<RefCell<WindowSize>>, size: Rc<RefCell<WindowSize>>,
resize_notification: Rc<Cell<Option<(u32, u32)>>>, resize_notification: Rc<Cell<Option<Size<i32, Physical>>>>,
} }
/// Create a new [`WinitGraphicsBackend`], which implements the [`Renderer`] trait and a corresponding [`WinitInputBackend`], /// Create a new [`WinitGraphicsBackend`], which implements the [`Renderer`] trait and a corresponding [`WinitInputBackend`],
@ -196,8 +206,9 @@ where
(display, context, surface) (display, context, surface)
}; };
let (w, h): (u32, u32) = winit_window.inner_size().into();
let size = Rc::new(RefCell::new(WindowSize { let size = Rc::new(RefCell::new(WindowSize {
physical_size: winit_window.inner_size(), // TODO: original code check if window is alive or not using inner_size().expect() physical_size: (w as i32, h as i32).into(),
scale_factor: winit_window.scale_factor(), scale_factor: winit_window.scale_factor(),
})); }));
@ -234,7 +245,7 @@ pub enum WinitEvent {
/// The window has been resized /// The window has been resized
Resized { Resized {
/// The new physical size (in pixels) /// The new physical size (in pixels)
size: (f64, f64), size: Size<i32, Physical>,
/// The new scale factor /// The new scale factor
scale_factor: f64, scale_factor: f64,
}, },
@ -267,19 +278,17 @@ impl WinitGraphicsBackend {
F: FnOnce(&mut Gles2Renderer, &mut Gles2Frame) -> R, F: FnOnce(&mut Gles2Renderer, &mut Gles2Frame) -> R,
{ {
// Were we told to resize? // Were we told to resize?
if let Some((width, height)) = self.resize_notification.take() { if let Some(size) = self.resize_notification.take() {
self.egl.resize(width as i32, height as i32, 0, 0); self.egl.resize(size.w, size.h, 0, 0);
} }
let (width, height) = { let size = {
let size = self.size.borrow(); let size = self.size.borrow();
size.physical_size.into() size.physical_size
}; };
self.renderer.bind(self.egl.clone())?; self.renderer.bind(self.egl.clone())?;
let result = self let result = self.renderer.render(size, Transform::Normal, rendering)?;
.renderer
.render(width, height, Transform::Normal, rendering)?;
self.egl.swap_buffers()?; self.egl.swap_buffers()?;
self.renderer.unbind()?; self.renderer.unbind()?;
Ok(result) Ok(result)
@ -390,13 +399,13 @@ impl PointerMotionAbsoluteEvent<WinitInputBackend> for WinitMouseMovedEvent {
fn x_transformed(&self, width: u32) -> f64 { fn x_transformed(&self, width: u32) -> f64 {
let wsize = self.size.borrow(); let wsize = self.size.borrow();
let w_width = wsize.physical_size.to_logical::<f64>(wsize.scale_factor).width; let w_width = wsize.logical_size().w;
f64::max(self.logical_position.x * width as f64 / w_width, 0.0) f64::max(self.logical_position.x * width as f64 / w_width, 0.0)
} }
fn y_transformed(&self, height: u32) -> f64 { fn y_transformed(&self, height: u32) -> f64 {
let wsize = self.size.borrow(); let wsize = self.size.borrow();
let w_height = wsize.physical_size.to_logical::<f64>(wsize.scale_factor).height; let w_height = wsize.logical_size().h;
f64::max(self.logical_position.y * height as f64 / w_height, 0.0) f64::max(self.logical_position.y * height as f64 / w_height, 0.0)
} }
} }
@ -476,7 +485,7 @@ impl PointerButtonEvent<WinitInputBackend> for WinitMouseInputEvent {
pub struct WinitTouchStartedEvent { pub struct WinitTouchStartedEvent {
size: Rc<RefCell<WindowSize>>, size: Rc<RefCell<WindowSize>>,
time: u32, time: u32,
location: (f64, f64), location: LogicalPosition<f64>,
id: u64, id: u64,
} }
@ -497,24 +506,24 @@ impl TouchDownEvent<WinitInputBackend> for WinitTouchStartedEvent {
fn x(&self) -> f64 { fn x(&self) -> f64 {
let wsize = self.size.borrow(); let wsize = self.size.borrow();
self.location.0 * wsize.scale_factor self.location.x * wsize.scale_factor
} }
fn y(&self) -> f64 { fn y(&self) -> f64 {
let wsize = self.size.borrow(); let wsize = self.size.borrow();
self.location.1 * wsize.scale_factor self.location.y * wsize.scale_factor
} }
fn x_transformed(&self, width: u32) -> f64 { fn x_transformed(&self, width: u32) -> f64 {
let wsize = self.size.borrow(); let wsize = self.size.borrow();
let w_width = wsize.physical_size.to_logical::<f64>(wsize.scale_factor).width; let w_width = wsize.logical_size().w;
f64::max(self.location.0 * width as f64 / w_width, 0.0) f64::max(self.location.x * width as f64 / w_width, 0.0)
} }
fn y_transformed(&self, height: u32) -> f64 { fn y_transformed(&self, height: u32) -> f64 {
let wsize = self.size.borrow(); let wsize = self.size.borrow();
let w_height = wsize.physical_size.to_logical::<f64>(wsize.scale_factor).height; let w_height = wsize.logical_size().h;
f64::max(self.location.1 * height as f64 / w_height, 0.0) f64::max(self.location.y * height as f64 / w_height, 0.0)
} }
} }
@ -523,7 +532,7 @@ impl TouchDownEvent<WinitInputBackend> for WinitTouchStartedEvent {
pub struct WinitTouchMovedEvent { pub struct WinitTouchMovedEvent {
size: Rc<RefCell<WindowSize>>, size: Rc<RefCell<WindowSize>>,
time: u32, time: u32,
location: (f64, f64), location: LogicalPosition<f64>,
id: u64, id: u64,
} }
@ -544,24 +553,24 @@ impl TouchMotionEvent<WinitInputBackend> for WinitTouchMovedEvent {
fn x(&self) -> f64 { fn x(&self) -> f64 {
let wsize = self.size.borrow(); let wsize = self.size.borrow();
self.location.0 * wsize.scale_factor self.location.x * wsize.scale_factor
} }
fn y(&self) -> f64 { fn y(&self) -> f64 {
let wsize = self.size.borrow(); let wsize = self.size.borrow();
self.location.1 * wsize.scale_factor self.location.y * wsize.scale_factor
} }
fn x_transformed(&self, width: u32) -> f64 { fn x_transformed(&self, width: u32) -> f64 {
let wsize = self.size.borrow(); let wsize = self.size.borrow();
let w_width = wsize.physical_size.to_logical::<f64>(wsize.scale_factor).width; let w_width = wsize.logical_size().w;
f64::max(self.location.0 * width as f64 / w_width, 0.0) f64::max(self.location.x * width as f64 / w_width, 0.0)
} }
fn y_transformed(&self, height: u32) -> f64 { fn y_transformed(&self, height: u32) -> f64 {
let wsize = self.size.borrow(); let wsize = self.size.borrow();
let w_height = wsize.physical_size.to_logical::<f64>(wsize.scale_factor).height; let w_height = wsize.logical_size().h;
f64::max(self.location.1 * height as f64 / w_height, 0.0) f64::max(self.location.y * height as f64 / w_height, 0.0)
} }
} }
@ -687,13 +696,14 @@ impl InputBackend for WinitInputBackend {
trace!(logger, "Resizing window to {:?}", psize); trace!(logger, "Resizing window to {:?}", psize);
let scale_factor = window.scale_factor(); let scale_factor = window.scale_factor();
let mut wsize = window_size.borrow_mut(); let mut wsize = window_size.borrow_mut();
wsize.physical_size = psize; let (pw, ph): (u32, u32) = psize.into();
wsize.physical_size = (pw as i32, ph as i32).into();
wsize.scale_factor = scale_factor; wsize.scale_factor = scale_factor;
resize_notification.set(Some((psize.width, psize.height))); resize_notification.set(Some(wsize.physical_size));
callback(InputEvent::Special(WinitEvent::Resized { callback(InputEvent::Special(WinitEvent::Resized {
size: psize.into(), size: wsize.physical_size,
scale_factor, scale_factor,
})); }));
} }
@ -708,11 +718,11 @@ impl InputBackend for WinitInputBackend {
let mut wsize = window_size.borrow_mut(); let mut wsize = window_size.borrow_mut();
wsize.scale_factor = scale_factor; wsize.scale_factor = scale_factor;
resize_notification.set(Some((new_psize.width, new_psize.height))); let (pw, ph): (u32, u32) = (*new_psize).into();
resize_notification.set(Some((pw as i32, ph as i32).into()));
let psize_f64: (f64, f64) = (new_psize.width.into(), new_psize.height.into());
callback(InputEvent::Special(WinitEvent::Resized { callback(InputEvent::Special(WinitEvent::Resized {
size: psize_f64, size: (pw as i32, ph as i32).into(),
scale_factor: wsize.scale_factor, scale_factor: wsize.scale_factor,
})); }));
} }
@ -761,11 +771,12 @@ impl InputBackend for WinitInputBackend {
id, id,
.. ..
}) => { }) => {
let location = location.to_logical(window_size.borrow().scale_factor);
callback(InputEvent::TouchDown { callback(InputEvent::TouchDown {
event: WinitTouchStartedEvent { event: WinitTouchStartedEvent {
size: window_size.clone(), size: window_size.clone(),
time, time,
location: location.into(), location,
id, id,
}, },
}); });
@ -776,11 +787,12 @@ impl InputBackend for WinitInputBackend {
id, id,
.. ..
}) => { }) => {
let location = location.to_logical(window_size.borrow().scale_factor);
callback(InputEvent::TouchMotion { callback(InputEvent::TouchMotion {
event: WinitTouchMovedEvent { event: WinitTouchMovedEvent {
size: window_size.clone(), size: window_size.clone(),
time, time,
location: location.into(), location,
id, id,
}, },
}); });
@ -792,11 +804,12 @@ impl InputBackend for WinitInputBackend {
id, id,
.. ..
}) => { }) => {
let location = location.to_logical(window_size.borrow().scale_factor);
callback(InputEvent::TouchMotion { callback(InputEvent::TouchMotion {
event: WinitTouchMovedEvent { event: WinitTouchMovedEvent {
size: window_size.clone(), size: window_size.clone(),
time, time,
location: location.into(), location,
id, id,
}, },
}); });

829
src/utils/geometry.rs Normal file
View File

@ -0,0 +1,829 @@
use std::fmt;
use std::ops::{Add, AddAssign, Sub, SubAssign};
/// Type-level marker for the logical coordinate space
#[derive(Debug)]
pub struct Logical;
/// Type-level marker for the physical coordinate space
#[derive(Debug)]
pub struct Physical;
/// Type-level marker for the buffer coordinate space
#[derive(Debug)]
pub struct Buffer;
/// Type-level marker for raw coordinate space, provided by input devices
#[derive(Debug)]
pub struct Raw;
pub trait Coordinate:
Sized + Add<Self, Output = Self> + Sub<Self, Output = Self> + PartialOrd + Default + Copy + std::fmt::Debug
{
fn downscale(self, scale: Self) -> Self;
fn upscale(self, scale: Self) -> Self;
fn to_f64(self) -> f64;
fn from_f64(v: f64) -> Self;
fn non_negative(self) -> bool;
fn abs(self) -> Self;
}
impl Coordinate for f64 {
#[inline]
fn downscale(self, scale: f64) -> f64 {
self / scale
}
#[inline]
fn upscale(self, scale: f64) -> f64 {
self * scale
}
#[inline]
fn to_f64(self) -> f64 {
self
}
#[inline]
fn from_f64(v: f64) -> f64 {
v
}
#[inline]
fn non_negative(self) -> bool {
self >= 0.0
}
#[inline]
fn abs(self) -> f64 {
self.abs()
}
}
impl Coordinate for i32 {
#[inline]
fn downscale(self, scale: i32) -> i32 {
self / scale
}
#[inline]
fn upscale(self, scale: i32) -> i32 {
self.saturating_mul(scale)
}
#[inline]
fn to_f64(self) -> f64 {
self as f64
}
#[inline]
fn from_f64(v: f64) -> i32 {
v as i32
}
#[inline]
fn non_negative(self) -> bool {
self >= 0
}
#[inline]
fn abs(self) -> i32 {
self.abs()
}
}
/*
* Point
*/
/// A point as defined by its x and y coordinates
pub struct Point<N, Kind> {
/// horizontal coordinate
pub x: N,
/// vertical coordinate
pub y: N,
_kind: std::marker::PhantomData<Kind>,
}
impl<N: Coordinate, Kind> Point<N, Kind> {
/// Convert this [`Point`] to a [`Size`] with the same coordinates
///
/// Checks that the coordinates are positive with a `debug_assert!()`.
#[inline]
pub fn to_size(self) -> Size<N, Kind> {
debug_assert!(
self.x.non_negative() && self.y.non_negative(),
"Attempting to create a `Size` of negative size: {:?}",
(self.x, self.y)
);
Size {
w: self.x,
h: self.y,
_kind: std::marker::PhantomData,
}
}
/// Convert this [`Point`] to a [`Size`] with the same coordinates
///
/// Ensures that the coordinates are positive by taking their absolute value
#[inline]
pub fn to_size_abs(self) -> Size<N, Kind> {
Size {
w: self.x.abs(),
h: self.y.abs(),
_kind: std::marker::PhantomData,
}
}
}
impl<N: Coordinate, Kind> Point<N, Kind> {
/// Convert the underlying numerical type to f64 for floating point manipulations
#[inline]
pub fn to_f64(self) -> Point<f64, Kind> {
Point {
x: self.x.to_f64(),
y: self.y.to_f64(),
_kind: std::marker::PhantomData,
}
}
}
impl<Kind> Point<f64, Kind> {
/// Convert to i32 for integer-space manipulations by rounding float values
#[inline]
pub fn to_i32_round<N: Coordinate>(self) -> Point<N, Kind> {
Point {
x: N::from_f64(self.x.round()),
y: N::from_f64(self.y.round()),
_kind: std::marker::PhantomData,
}
}
/// Convert to i32 for integer-space manipulations by flooring float values
#[inline]
pub fn to_i32_floor<N: Coordinate>(self) -> Point<N, Kind> {
Point {
x: N::from_f64(self.x.floor()),
y: N::from_f64(self.y.floor()),
_kind: std::marker::PhantomData,
}
}
/// Convert to i32 for integer-space manipulations by ceiling float values
#[inline]
pub fn to_i32_ceil<N: Coordinate>(self) -> Point<N, Kind> {
Point {
x: N::from_f64(self.x.ceil()),
y: N::from_f64(self.y.ceil()),
_kind: std::marker::PhantomData,
}
}
}
impl<N: fmt::Debug> fmt::Debug for Point<N, Logical> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Point<Logical>")
.field("x", &self.x)
.field("y", &self.y)
.finish()
}
}
impl<N: fmt::Debug> fmt::Debug for Point<N, Physical> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Point<Physical>")
.field("x", &self.x)
.field("y", &self.y)
.finish()
}
}
impl<N: fmt::Debug> fmt::Debug for Point<N, Raw> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Point<Raw>")
.field("x", &self.x)
.field("y", &self.y)
.finish()
}
}
impl<N: fmt::Debug> fmt::Debug for Point<N, Buffer> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Point<Buffer>")
.field("x", &self.x)
.field("y", &self.y)
.finish()
}
}
impl<N: Coordinate> Point<N, Logical> {
#[inline]
/// Convert this logical point to physical coordinate space according to given scale factor
pub fn to_physical(self, scale: N) -> Point<N, Physical> {
Point {
x: self.x.upscale(scale),
y: self.y.upscale(scale),
_kind: std::marker::PhantomData,
}
}
#[inline]
/// Convert this logical point to buffer coordinate space according to given scale factor
pub fn to_buffer(self, scale: N) -> Point<N, Buffer> {
Point {
x: self.x.upscale(scale),
y: self.y.upscale(scale),
_kind: std::marker::PhantomData,
}
}
}
impl<N: Coordinate> Point<N, Physical> {
#[inline]
/// Convert this physical point to logical coordinate space according to given scale factor
pub fn to_logical(self, scale: N) -> Point<N, Logical> {
Point {
x: self.x.downscale(scale),
y: self.y.downscale(scale),
_kind: std::marker::PhantomData,
}
}
}
impl<N: Coordinate> Point<N, Buffer> {
#[inline]
/// Convert this physical point to logical coordinate space according to given scale factor
pub fn to_logical(self, scale: N) -> Point<N, Logical> {
Point {
x: self.x.downscale(scale),
y: self.y.downscale(scale),
_kind: std::marker::PhantomData,
}
}
}
impl<N, Kind> From<(N, N)> for Point<N, Kind> {
#[inline]
fn from((x, y): (N, N)) -> Point<N, Kind> {
Point {
x,
y,
_kind: std::marker::PhantomData,
}
}
}
impl<N, Kind> From<Point<N, Kind>> for (N, N) {
#[inline]
fn from(point: Point<N, Kind>) -> (N, N) {
(point.x, point.y)
}
}
impl<N: Add<Output = N>, Kind> Add for Point<N, Kind> {
type Output = Point<N, Kind>;
#[inline]
fn add(self, other: Point<N, Kind>) -> Point<N, Kind> {
Point {
x: self.x + other.x,
y: self.y + other.y,
_kind: std::marker::PhantomData,
}
}
}
impl<N: AddAssign, Kind> AddAssign for Point<N, Kind> {
#[inline]
fn add_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y
}
}
impl<N: SubAssign, Kind> SubAssign for Point<N, Kind> {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
self.x -= rhs.x;
self.y -= rhs.y
}
}
impl<N: Sub<Output = N>, Kind> Sub for Point<N, Kind> {
type Output = Point<N, Kind>;
#[inline]
fn sub(self, other: Point<N, Kind>) -> Point<N, Kind> {
Point {
x: self.x - other.x,
y: self.y - other.y,
_kind: std::marker::PhantomData,
}
}
}
impl<N: Clone, Kind> Clone for Point<N, Kind> {
#[inline]
fn clone(&self) -> Self {
Point {
x: self.x.clone(),
y: self.y.clone(),
_kind: std::marker::PhantomData,
}
}
}
impl<N: Copy, Kind> Copy for Point<N, Kind> {}
impl<N: PartialEq, Kind> PartialEq for Point<N, Kind> {
fn eq(&self, other: &Self) -> bool {
self.x == other.x && self.y == other.y
}
}
impl<N: Eq, Kind> Eq for Point<N, Kind> {}
impl<N: Default, Kind> Default for Point<N, Kind> {
fn default() -> Self {
Point {
x: N::default(),
y: N::default(),
_kind: std::marker::PhantomData,
}
}
}
/*
* Size
*/
/// A size as defined by its width and height
///
/// Constructors of this type ensure that the values are always positive via
/// `debug_assert!()`, however manually changing the values of the fields
/// can break this invariant.
pub struct Size<N, Kind> {
/// horizontal coordinate
pub w: N,
/// vertical coordinate
pub h: N,
_kind: std::marker::PhantomData<Kind>,
}
impl<N: Coordinate, Kind> Size<N, Kind> {
/// Convert this [`Size`] to a [`Point`] with the same coordinates
#[inline]
pub fn to_point(self) -> Point<N, Kind> {
Point {
x: self.w,
y: self.h,
_kind: std::marker::PhantomData,
}
}
}
impl<N: Coordinate, Kind> Size<N, Kind> {
/// Convert the underlying numerical type to f64 for floating point manipulations
#[inline]
pub fn to_f64(self) -> Size<f64, Kind> {
Size {
w: self.w.to_f64(),
h: self.h.to_f64(),
_kind: std::marker::PhantomData,
}
}
}
impl<Kind> Size<f64, Kind> {
/// Convert to i32 for integer-space manipulations by rounding float values
#[inline]
pub fn to_i32_round<N: Coordinate>(self) -> Size<N, Kind> {
Size {
w: N::from_f64(self.w.round()),
h: N::from_f64(self.h.round()),
_kind: std::marker::PhantomData,
}
}
/// Convert to i32 for integer-space manipulations by flooring float values
#[inline]
pub fn to_i32_floor<N: Coordinate>(self) -> Size<N, Kind> {
Size {
w: N::from_f64(self.w.floor()),
h: N::from_f64(self.h.floor()),
_kind: std::marker::PhantomData,
}
}
/// Convert to i32 for integer-space manipulations by ceiling float values
#[inline]
pub fn to_i32_ceil<N: Coordinate>(self) -> Size<N, Kind> {
Size {
w: N::from_f64(self.w.ceil()),
h: N::from_f64(self.h.ceil()),
_kind: std::marker::PhantomData,
}
}
}
impl<N: fmt::Debug> fmt::Debug for Size<N, Logical> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Size<Logical>")
.field("w", &self.w)
.field("h", &self.h)
.finish()
}
}
impl<N: fmt::Debug> fmt::Debug for Size<N, Physical> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Size<Physical>")
.field("w", &self.w)
.field("h", &self.h)
.finish()
}
}
impl<N: fmt::Debug> fmt::Debug for Size<N, Raw> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Size<Raw>")
.field("w", &self.w)
.field("h", &self.h)
.finish()
}
}
impl<N: fmt::Debug> fmt::Debug for Size<N, Buffer> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Size<Buffer>")
.field("w", &self.w)
.field("h", &self.h)
.finish()
}
}
impl<N: Coordinate> Size<N, Logical> {
#[inline]
/// Convert this logical size to physical coordinate space according to given scale factor
pub fn to_physical(self, scale: N) -> Size<N, Physical> {
Size {
w: self.w.upscale(scale),
h: self.h.upscale(scale),
_kind: std::marker::PhantomData,
}
}
#[inline]
/// Convert this logical size to buffer coordinate space according to given scale factor
pub fn to_buffer(self, scale: N) -> Size<N, Buffer> {
Size {
w: self.w.upscale(scale),
h: self.h.upscale(scale),
_kind: std::marker::PhantomData,
}
}
}
impl<N: Coordinate> Size<N, Physical> {
#[inline]
/// Convert this physical point to logical coordinate space according to given scale factor
pub fn to_logical(self, scale: N) -> Size<N, Logical> {
Size {
w: self.w.downscale(scale),
h: self.h.downscale(scale),
_kind: std::marker::PhantomData,
}
}
}
impl<N: Coordinate> Size<N, Buffer> {
#[inline]
/// Convert this physical point to logical coordinate space according to given scale factor
pub fn to_logical(self, scale: N) -> Size<N, Logical> {
Size {
w: self.w.downscale(scale),
h: self.h.downscale(scale),
_kind: std::marker::PhantomData,
}
}
}
impl<N: Coordinate, Kind> From<(N, N)> for Size<N, Kind> {
#[inline]
fn from((w, h): (N, N)) -> Size<N, Kind> {
debug_assert!(
w.non_negative() && h.non_negative(),
"Attempting to create a `Size` of negative size: {:?}",
(w, h)
);
Size {
w,
h,
_kind: std::marker::PhantomData,
}
}
}
impl<N, Kind> From<Size<N, Kind>> for (N, N) {
#[inline]
fn from(point: Size<N, Kind>) -> (N, N) {
(point.w, point.h)
}
}
impl<N: Add<Output = N>, Kind> Add for Size<N, Kind> {
type Output = Size<N, Kind>;
#[inline]
fn add(self, other: Size<N, Kind>) -> Size<N, Kind> {
Size {
w: self.w + other.w,
h: self.h + other.h,
_kind: std::marker::PhantomData,
}
}
}
impl<N: AddAssign, Kind> AddAssign for Size<N, Kind> {
#[inline]
fn add_assign(&mut self, rhs: Self) {
self.w += rhs.w;
self.h += rhs.h
}
}
impl<N: Clone, Kind> Clone for Size<N, Kind> {
#[inline]
fn clone(&self) -> Self {
Size {
w: self.w.clone(),
h: self.h.clone(),
_kind: std::marker::PhantomData,
}
}
}
impl<N: Copy, Kind> Copy for Size<N, Kind> {}
impl<N: PartialEq, Kind> PartialEq for Size<N, Kind> {
fn eq(&self, other: &Self) -> bool {
self.w == other.w && self.h == other.h
}
}
impl<N: Eq, Kind> Eq for Size<N, Kind> {}
impl<N: Default, Kind> Default for Size<N, Kind> {
fn default() -> Self {
Size {
w: N::default(),
h: N::default(),
_kind: std::marker::PhantomData,
}
}
}
impl<N: Add<Output = N>, Kind> Add<Size<N, Kind>> for Point<N, Kind> {
type Output = Point<N, Kind>;
#[inline]
fn add(self, other: Size<N, Kind>) -> Point<N, Kind> {
Point {
x: self.x + other.w,
y: self.y + other.h,
_kind: std::marker::PhantomData,
}
}
}
impl<N: Sub<Output = N>, Kind> Sub<Size<N, Kind>> for Point<N, Kind> {
type Output = Point<N, Kind>;
#[inline]
fn sub(self, other: Size<N, Kind>) -> Point<N, Kind> {
Point {
x: self.x - other.w,
y: self.y - other.h,
_kind: std::marker::PhantomData,
}
}
}
/// A rectangle defined by its top-left corner and dimensions
pub struct Rectangle<N, Kind> {
/// Location of the top-left corner of the rectangle
pub loc: Point<N, Kind>,
/// Size of the rectangle, as (width, height)
pub size: Size<N, Kind>,
}
impl<N: Coordinate, Kind> Rectangle<N, Kind> {
/// Convert the underlying numerical type to another
pub fn to_f64(self) -> Rectangle<f64, Kind> {
Rectangle {
loc: self.loc.to_f64(),
size: self.size.to_f64(),
}
}
}
impl<N: Coordinate, Kind> Rectangle<N, Kind> {
/// Create a new [`Rectangle`] from the coordinates of its top-left corner and its dimensions
#[inline]
pub fn from_loc_and_size(loc: impl Into<Point<N, Kind>>, size: impl Into<Size<N, Kind>>) -> Self {
Rectangle {
loc: loc.into(),
size: size.into(),
}
}
/// Create a new [`Rectangle`] from the coordinates of its top-left corner and its dimensions
#[inline]
pub fn from_extemities(
topleft: impl Into<Point<N, Kind>>,
bottomright: impl Into<Point<N, Kind>>,
) -> Self {
let topleft = topleft.into();
let bottomright = bottomright.into();
Rectangle {
loc: topleft,
size: (bottomright - topleft).to_size(),
}
}
/// Checks whether given [`Point`] is inside the rectangle
#[inline]
pub fn contains<P: Into<Point<N, Kind>>>(self, point: P) -> bool {
let p: Point<N, Kind> = point.into();
(p.x >= self.loc.x)
&& (p.x < self.loc.x + self.size.w)
&& (p.y >= self.loc.y)
&& (p.y < self.loc.y + self.size.h)
}
/// Checks whether a given [`Rectangle`] overlaps with this one
#[inline]
pub fn overlaps(self, other: Rectangle<N, Kind>) -> bool {
// if the rectangle is not outside of the other
// they must overlap
!(
// self is left of other
self.loc.x + self.size.w < other.loc.x
// self is right of other
|| self.loc.x > other.loc.x + other.size.w
// self is above of other
|| self.loc.y + self.size.h < other.loc.y
// self is below of other
|| self.loc.y > other.loc.y + other.size.h
)
}
/// Compute the bounding box of a given set of points
pub fn bounding_box(points: impl IntoIterator<Item = Point<N, Kind>>) -> Self {
let ret = points.into_iter().fold(None, |acc, point| {
match acc {
None => Some((point, point)),
// we don't have cmp::{min,max} for f64 :(
Some((min_point, max_point)) => Some((
(
if min_point.x > point.x {
point.x
} else {
min_point.x
},
if min_point.y > point.y {
point.y
} else {
min_point.y
},
)
.into(),
(
if max_point.x < point.x {
point.x
} else {
max_point.x
},
if max_point.y < point.y {
point.y
} else {
max_point.y
},
)
.into(),
)),
}
});
match ret {
None => Rectangle::default(),
Some((min_point, max_point)) => Rectangle::from_extemities(min_point, max_point),
}
}
/// Merge two [`Rectangle`] by producing the smallest rectangle that contains both
#[inline]
pub fn merge(self, other: Self) -> Self {
Self::bounding_box([self.loc, self.loc + self.size, other.loc, other.loc + other.size])
}
}
impl<N: Coordinate> Rectangle<N, Logical> {
/// Convert this logical rectangle to physical coordinate space according to given scale factor
#[inline]
pub fn to_physical(self, scale: N) -> Rectangle<N, Physical> {
Rectangle {
loc: self.loc.to_physical(scale),
size: self.size.to_physical(scale),
}
}
/// Convert this logical rectangle to buffer coordinate space according to given scale factor
#[inline]
pub fn to_buffer(self, scale: N) -> Rectangle<N, Buffer> {
Rectangle {
loc: self.loc.to_buffer(scale),
size: self.size.to_buffer(scale),
}
}
}
impl<N: Coordinate> Rectangle<N, Physical> {
/// Convert this physical rectangle to logical coordinate space according to given scale factor
#[inline]
pub fn to_logical(self, scale: N) -> Rectangle<N, Logical> {
Rectangle {
loc: self.loc.to_logical(scale),
size: self.size.to_logical(scale),
}
}
}
impl<N: Coordinate> Rectangle<N, Buffer> {
/// Convert this physical rectangle to logical coordinate space according to given scale factor
#[inline]
pub fn to_logical(self, scale: N) -> Rectangle<N, Logical> {
Rectangle {
loc: self.loc.to_logical(scale),
size: self.size.to_logical(scale),
}
}
}
impl<N: fmt::Debug> fmt::Debug for Rectangle<N, Logical> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Rectangle<Logical>")
.field("x", &self.loc.x)
.field("y", &self.loc.y)
.field("width", &self.size.w)
.field("height", &self.size.h)
.finish()
}
}
impl<N: fmt::Debug> fmt::Debug for Rectangle<N, Physical> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Rectangle<Physical>")
.field("x", &self.loc.x)
.field("y", &self.loc.y)
.field("width", &self.size.w)
.field("height", &self.size.h)
.finish()
}
}
impl<N: fmt::Debug> fmt::Debug for Rectangle<N, Raw> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Rectangle<Raw>")
.field("x", &self.loc.x)
.field("y", &self.loc.y)
.field("width", &self.size.w)
.field("height", &self.size.h)
.finish()
}
}
impl<N: fmt::Debug> fmt::Debug for Rectangle<N, Buffer> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Rectangle<Buffer>")
.field("x", &self.loc.x)
.field("y", &self.loc.y)
.field("width", &self.size.w)
.field("height", &self.size.h)
.finish()
}
}
impl<N: Clone, Kind> Clone for Rectangle<N, Kind> {
#[inline]
fn clone(&self) -> Self {
Rectangle {
loc: self.loc.clone(),
size: self.size.clone(),
}
}
}
impl<N: Copy, Kind> Copy for Rectangle<N, Kind> {}
impl<N: PartialEq, Kind> PartialEq for Rectangle<N, Kind> {
fn eq(&self, other: &Self) -> bool {
self.loc == other.loc && self.size == other.size
}
}
impl<N: Eq, Kind> Eq for Rectangle<N, Kind> {}
impl<N: Default, Kind> Default for Rectangle<N, Kind> {
fn default() -> Self {
Rectangle {
loc: Default::default(),
size: Default::default(),
}
}
}

View File

@ -1,9 +1,9 @@
//! Various utilities functions and types //! Various utilities functions and types
mod rectangle; mod geometry;
pub mod signaling; pub mod signaling;
pub use self::rectangle::Rectangle; pub use self::geometry::{Buffer, Logical, Physical, Point, Raw, Rectangle, Size};
/// This resource is not managed by Smithay /// This resource is not managed by Smithay
#[derive(Debug)] #[derive(Debug)]

View File

@ -1,46 +0,0 @@
/// A rectangle defined by its top-left corner and dimensions
#[derive(Copy, Clone, Debug, Default, PartialEq)]
pub struct Rectangle {
/// horizontal position of the top-left corner of the rectangle, in surface coordinates
pub x: i32,
/// vertical position of the top-left corner of the rectangle, in surface coordinates
pub y: i32,
/// width of the rectangle
pub width: i32,
/// height of the rectangle
pub height: i32,
}
impl Rectangle {
/// Checks whether given point is inside a rectangle
pub fn contains(self, point: (i32, i32)) -> bool {
let (x, y) = point;
(x >= self.x) && (x < self.x + self.width) && (y >= self.y) && (y < self.y + self.height)
}
/// Checks whether a given rectangle overlaps with this one
pub fn overlaps(self, other: &Rectangle) -> bool {
// if the rectangle is not outside of the other
// they must overlap
!(
// self is left of other
self.x + self.width < other.x
// self is right of other
|| self.x > other.x + other.width
// self is above of other
|| self.y + self.height < other.y
// self is below of other
|| self.y > other.y + other.height
)
}
/// Scales the dimensions of this rectangle by given factor
pub fn scale(self, factor: i32) -> Rectangle {
Rectangle {
x: self.x * factor,
y: self.y * factor,
width: self.width * factor,
height: self.height * factor,
}
}
}

View File

@ -13,6 +13,8 @@ use wayland_server::{
DispatchData, Filter, Main, DispatchData, Filter, Main,
}; };
use crate::utils::{Logical, Point};
use super::{ use super::{
cache::Cacheable, cache::Cacheable,
tree::{Location, PrivateSurfaceData}, tree::{Location, PrivateSurfaceData},
@ -81,7 +83,7 @@ impl SurfaceImplem {
states.cached_state.pending::<SurfaceAttributes>().buffer = Some(match buffer { states.cached_state.pending::<SurfaceAttributes>().buffer = Some(match buffer {
Some(buffer) => BufferAssignment::NewBuffer { Some(buffer) => BufferAssignment::NewBuffer {
buffer, buffer,
delta: (x, y), delta: (x, y).into(),
}, },
None => BufferAssignment::Removed, None => BufferAssignment::Removed,
}) })
@ -93,7 +95,10 @@ impl SurfaceImplem {
.cached_state .cached_state
.pending::<SurfaceAttributes>() .pending::<SurfaceAttributes>()
.damage .damage
.push(Damage::Surface(Rectangle { x, y, width, height })); .push(Damage::Surface(Rectangle::from_loc_and_size(
(x, y),
(width, height),
)));
}); });
} }
wl_surface::Request::Frame { callback } => { wl_surface::Request::Frame { callback } => {
@ -153,7 +158,10 @@ impl SurfaceImplem {
.cached_state .cached_state
.pending::<SurfaceAttributes>() .pending::<SurfaceAttributes>()
.damage .damage
.push(Damage::Buffer(Rectangle { x, y, width, height })) .push(Damage::Buffer(Rectangle::from_loc_and_size(
(x, y),
(width, height),
)))
}); });
} }
wl_surface::Request::Destroy => { wl_surface::Request::Destroy => {
@ -226,12 +234,14 @@ fn region_implem(request: wl_region::Request, region: wl_region::WlRegion) {
.unwrap(); .unwrap();
let mut guard = attributes_mutex.lock().unwrap(); let mut guard = attributes_mutex.lock().unwrap();
match request { match request {
wl_region::Request::Add { x, y, width, height } => guard wl_region::Request::Add { x, y, width, height } => guard.rects.push((
.rects RectangleKind::Add,
.push((RectangleKind::Add, Rectangle { x, y, width, height })), Rectangle::from_loc_and_size((x, y), (width, height)),
wl_region::Request::Subtract { x, y, width, height } => guard )),
.rects wl_region::Request::Subtract { x, y, width, height } => guard.rects.push((
.push((RectangleKind::Subtract, Rectangle { x, y, width, height })), RectangleKind::Subtract,
Rectangle::from_loc_and_size((x, y), (width, height)),
)),
wl_region::Request::Destroy => { wl_region::Request::Destroy => {
// all is handled by our destructor // all is handled by our destructor
} }
@ -281,12 +291,14 @@ pub(crate) fn implement_subcompositor(
pub struct SubsurfaceCachedState { pub struct SubsurfaceCachedState {
/// Location of the top-left corner of this subsurface /// Location of the top-left corner of this subsurface
/// relative to its parent coordinate space /// relative to its parent coordinate space
pub location: (i32, i32), pub location: Point<i32, Logical>,
} }
impl Default for SubsurfaceCachedState { impl Default for SubsurfaceCachedState {
fn default() -> Self { fn default() -> Self {
SubsurfaceCachedState { location: (0, 0) } SubsurfaceCachedState {
location: (0, 0).into(),
}
} }
} }
@ -342,7 +354,7 @@ fn implement_subsurface(
match request { match request {
wl_subsurface::Request::SetPosition { x, y } => { wl_subsurface::Request::SetPosition { x, y } => {
PrivateSurfaceData::with_states(&surface, |state| { PrivateSurfaceData::with_states(&surface, |state| {
state.cached_state.pending::<SubsurfaceCachedState>().location = (x, y); state.cached_state.pending::<SubsurfaceCachedState>().location = (x, y).into();
}) })
} }
wl_subsurface::Request::PlaceAbove { sibling } => { wl_subsurface::Request::PlaceAbove { sibling } => {

View File

@ -93,7 +93,7 @@ pub use self::cache::{Cacheable, MultiCache};
pub use self::handlers::SubsurfaceCachedState; pub use self::handlers::SubsurfaceCachedState;
use self::tree::PrivateSurfaceData; use self::tree::PrivateSurfaceData;
pub use self::tree::{AlreadyHasRole, TraversalAction}; pub use self::tree::{AlreadyHasRole, TraversalAction};
use crate::utils::{DeadResource, Rectangle}; use crate::utils::{Buffer, DeadResource, Logical, Point, Rectangle};
use wayland_server::{ use wayland_server::{
protocol::{ protocol::{
wl_buffer, wl_callback, wl_compositor, wl_output, wl_region, wl_subcompositor, wl_surface::WlSurface, wl_buffer, wl_callback, wl_compositor, wl_output, wl_region, wl_subcompositor, wl_surface::WlSurface,
@ -106,11 +106,11 @@ use wayland_server::{
#[derive(Debug)] #[derive(Debug)]
pub enum Damage { pub enum Damage {
/// A rectangle containing the damaged zone, in surface coordinates /// A rectangle containing the damaged zone, in surface coordinates
Surface(Rectangle), Surface(Rectangle<i32, Logical>),
/// A rectangle containing the damaged zone, in buffer coordinates /// A rectangle containing the damaged zone, in buffer coordinates
/// ///
/// Note: Buffer scaling must be taken into consideration /// Note: Buffer scaling must be taken into consideration
Buffer(Rectangle), Buffer(Rectangle<i32, Buffer>),
} }
#[derive(Debug, Copy, Clone, Default)] #[derive(Debug, Copy, Clone, Default)]
@ -155,7 +155,7 @@ pub enum BufferAssignment {
/// The buffer object /// The buffer object
buffer: wl_buffer::WlBuffer, buffer: wl_buffer::WlBuffer,
/// location of the new buffer relative to the previous one /// location of the new buffer relative to the previous one
delta: (i32, i32), delta: Point<i32, Logical>,
}, },
} }
@ -227,29 +227,6 @@ impl Default for SurfaceAttributes {
} }
} }
/// Attributes defining the behaviour of a sub-surface relative to its parent
#[derive(Copy, Clone, Debug)]
pub struct SubsurfaceRole {
/// Location of the top-left corner of this sub-surface relative to
/// the top-left corner of its parent
pub location: (i32, i32),
/// Sync status of this sub-surface
///
/// If `true`, this surface should be repainted synchronously with its parent
/// if `false`, it should be considered independent of its parent regarding
/// repaint timings.
pub sync: bool,
}
impl Default for SubsurfaceRole {
fn default() -> SubsurfaceRole {
SubsurfaceRole {
location: (0, 0),
sync: true,
}
}
}
/// Kind of a rectangle part of a region /// Kind of a rectangle part of a region
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum RectangleKind { pub enum RectangleKind {
@ -270,7 +247,7 @@ pub enum RectangleKind {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct RegionAttributes { pub struct RegionAttributes {
/// List of rectangle part of this region /// List of rectangle part of this region
pub rects: Vec<(RectangleKind, Rectangle)>, pub rects: Vec<(RectangleKind, Rectangle<i32, Logical>)>,
} }
impl Default for RegionAttributes { impl Default for RegionAttributes {
@ -281,7 +258,8 @@ impl Default for RegionAttributes {
impl RegionAttributes { impl RegionAttributes {
/// Checks whether given point is inside the region. /// Checks whether given point is inside the region.
pub fn contains(&self, point: (i32, i32)) -> bool { pub fn contains<P: Into<Point<i32, Logical>>>(&self, point: P) -> bool {
let point: Point<i32, Logical> = point.into();
let mut contains = false; let mut contains = false;
for (kind, rect) in &self.rects { for (kind, rect) in &self.rects {
if rect.contains(point) { if rect.contains(point) {
@ -483,15 +461,7 @@ mod tests {
#[test] #[test]
fn region_attributes_add() { fn region_attributes_add() {
let region = RegionAttributes { let region = RegionAttributes {
rects: vec![( rects: vec![(RectangleKind::Add, Rectangle::from_loc_and_size((0, 0), (10, 10)))],
RectangleKind::Add,
Rectangle {
x: 0,
y: 0,
width: 10,
height: 10,
},
)],
}; };
assert_eq!(region.contains((0, 0)), true); assert_eq!(region.contains((0, 0)), true);
@ -501,23 +471,10 @@ mod tests {
fn region_attributes_add_subtract() { fn region_attributes_add_subtract() {
let region = RegionAttributes { let region = RegionAttributes {
rects: vec![ rects: vec![
( (RectangleKind::Add, Rectangle::from_loc_and_size((0, 0), (10, 10))),
RectangleKind::Add,
Rectangle {
x: 0,
y: 0,
width: 10,
height: 10,
},
),
( (
RectangleKind::Subtract, RectangleKind::Subtract,
Rectangle { Rectangle::from_loc_and_size((0, 0), (5, 5)),
x: 0,
y: 0,
width: 5,
height: 5,
},
), ),
], ],
}; };
@ -530,33 +487,12 @@ mod tests {
fn region_attributes_add_subtract_add() { fn region_attributes_add_subtract_add() {
let region = RegionAttributes { let region = RegionAttributes {
rects: vec![ rects: vec![
( (RectangleKind::Add, Rectangle::from_loc_and_size((0, 0), (10, 10))),
RectangleKind::Add,
Rectangle {
x: 0,
y: 0,
width: 10,
height: 10,
},
),
( (
RectangleKind::Subtract, RectangleKind::Subtract,
Rectangle { Rectangle::from_loc_and_size((0, 0), (5, 5)),
x: 0,
y: 0,
width: 5,
height: 5,
},
),
(
RectangleKind::Add,
Rectangle {
x: 2,
y: 2,
width: 2,
height: 2,
},
), ),
(RectangleKind::Add, Rectangle::from_loc_and_size((2, 2), (2, 2))),
], ],
}; };

View File

@ -5,9 +5,12 @@ use wayland_server::{
Main, Main,
}; };
use crate::wayland::{ use crate::{
utils::{Logical, Point},
wayland::{
seat::{AxisFrame, GrabStartData, PointerGrab, PointerInnerHandle, Seat}, seat::{AxisFrame, GrabStartData, PointerGrab, PointerInnerHandle, Seat},
Serial, Serial,
},
}; };
use super::{with_source_metadata, DataDeviceData, SeatData}; use super::{with_source_metadata, DataDeviceData, SeatData};
@ -51,12 +54,11 @@ impl PointerGrab for DnDGrab {
fn motion( fn motion(
&mut self, &mut self,
_handle: &mut PointerInnerHandle<'_>, _handle: &mut PointerInnerHandle<'_>,
location: (f64, f64), location: Point<f64, Logical>,
focus: Option<(wl_surface::WlSurface, (f64, f64))>, focus: Option<(wl_surface::WlSurface, Point<i32, Logical>)>,
serial: Serial, serial: Serial,
time: u32, time: u32,
) { ) {
let (x, y) = location;
let seat_data = self let seat_data = self
.seat .seat
.user_data() .user_data()
@ -81,12 +83,13 @@ impl PointerGrab for DnDGrab {
} }
} }
} }
if let Some((surface, (sx, sy))) = focus { if let Some((surface, surface_location)) = focus {
// early return if the surface is no longer valid // early return if the surface is no longer valid
let client = match surface.as_ref().client() { let client = match surface.as_ref().client() {
Some(c) => c, Some(c) => c,
None => return, None => return,
}; };
let (x, y) = (location - surface_location.to_f64()).into();
if self.current_focus.is_none() { if self.current_focus.is_none() {
// We entered a new surface, send the data offer if appropriate // We entered a new surface, send the data offer if appropriate
if let Some(ref source) = self.data_source { if let Some(ref source) = self.data_source {
@ -129,7 +132,7 @@ impl PointerGrab for DnDGrab {
offer.source_actions(meta.dnd_action); offer.source_actions(meta.dnd_action);
}) })
.unwrap(); .unwrap();
device.enter(serial.into(), &surface, x - sx, y - sy, Some(&offer)); device.enter(serial.into(), &surface, x, y, Some(&offer));
self.pending_offers.push(offer); self.pending_offers.push(offer);
} }
self.offer_data = Some(offer_data); self.offer_data = Some(offer_data);
@ -138,7 +141,7 @@ impl PointerGrab for DnDGrab {
if self.origin.as_ref().same_client_as(&surface.as_ref()) { if self.origin.as_ref().same_client_as(&surface.as_ref()) {
for device in &seat_data.known_devices { for device in &seat_data.known_devices {
if device.as_ref().same_client_as(&surface.as_ref()) { if device.as_ref().same_client_as(&surface.as_ref()) {
device.enter(serial.into(), &surface, x - sx, y - sy, None); device.enter(serial.into(), &surface, x, y, None);
} }
} }
} }
@ -149,7 +152,7 @@ impl PointerGrab for DnDGrab {
if self.data_source.is_some() || self.origin.as_ref().same_client_as(&surface.as_ref()) { if self.data_source.is_some() || self.origin.as_ref().same_client_as(&surface.as_ref()) {
for device in &seat_data.known_devices { for device in &seat_data.known_devices {
if device.as_ref().same_client_as(&surface.as_ref()) { if device.as_ref().same_client_as(&surface.as_ref()) {
device.motion(time, x - sx, y - sy); device.motion(time, x, y);
} }
} }
} }

View File

@ -5,8 +5,13 @@ use wayland_server::{
Main, Main,
}; };
use crate::wayland::seat::{AxisFrame, GrabStartData, PointerGrab, PointerInnerHandle, Seat}; use crate::{
use crate::wayland::Serial; utils::{Logical, Point},
wayland::{
seat::{AxisFrame, GrabStartData, PointerGrab, PointerInnerHandle, Seat},
Serial,
},
};
use super::{DataDeviceData, SeatData}; use super::{DataDeviceData, SeatData};
@ -72,12 +77,11 @@ where
fn motion( fn motion(
&mut self, &mut self,
_handle: &mut PointerInnerHandle<'_>, _handle: &mut PointerInnerHandle<'_>,
location: (f64, f64), location: Point<f64, Logical>,
focus: Option<(wl_surface::WlSurface, (f64, f64))>, focus: Option<(wl_surface::WlSurface, Point<i32, Logical>)>,
serial: Serial, serial: Serial,
time: u32, time: u32,
) { ) {
let (x, y) = location;
let seat_data = self let seat_data = self
.seat .seat
.user_data() .user_data()
@ -99,12 +103,13 @@ where
} }
} }
} }
if let Some((surface, (sx, sy))) = focus { if let Some((surface, surface_location)) = focus {
// early return if the surface is no longer valid // early return if the surface is no longer valid
let client = match surface.as_ref().client() { let client = match surface.as_ref().client() {
Some(c) => c, Some(c) => c,
None => return, None => return,
}; };
let (x, y) = (location - surface_location.to_f64()).into();
if self.current_focus.is_none() { if self.current_focus.is_none() {
// We entered a new surface, send the data offer // We entered a new surface, send the data offer
let offer_data = Rc::new(RefCell::new(OfferData { let offer_data = Rc::new(RefCell::new(OfferData {
@ -144,7 +149,7 @@ where
offer.offer(mime_type); offer.offer(mime_type);
} }
offer.source_actions(self.metadata.dnd_action); offer.source_actions(self.metadata.dnd_action);
device.enter(serial.into(), &surface, x - sx, y - sy, Some(&offer)); device.enter(serial.into(), &surface, x, y, Some(&offer));
self.pending_offers.push(offer); self.pending_offers.push(offer);
} }
self.offer_data = Some(offer_data); self.offer_data = Some(offer_data);
@ -153,7 +158,7 @@ where
// make a move // make a move
for device in &seat_data.known_devices { for device in &seat_data.known_devices {
if device.as_ref().same_client_as(&surface.as_ref()) { if device.as_ref().same_client_as(&surface.as_ref()) {
device.motion(time, x - sx, y - sy); device.motion(time, x, y);
} }
} }
} }

View File

@ -27,8 +27,7 @@
//! &mut display, // the display //! &mut display, // the display
//! "output-0".into(), // the name of this output, //! "output-0".into(), // the name of this output,
//! PhysicalProperties { //! PhysicalProperties {
//! width: 200, // width in mm //! size: (200, 150).into(), // dimensions (width, height) in mm
//! height: 150, // height in mm,
//! subpixel: wl_output::Subpixel::HorizontalRgb, // subpixel information //! subpixel: wl_output::Subpixel::HorizontalRgb, // subpixel information
//! make: "Screens Inc".into(), // make of the monitor //! make: "Screens Inc".into(), // make of the monitor
//! model: "Monitor Ultra".into(), // model of the monitor //! model: "Monitor Ultra".into(), // model of the monitor
@ -37,15 +36,15 @@
//! ); //! );
//! // Now you can configure it //! // Now you can configure it
//! output.change_current_state( //! output.change_current_state(
//! Some(Mode { width: 1902, height: 1080, refresh: 60000 }), // the resolution mode, //! Some(Mode { size: (1920, 1080).into(), refresh: 60000 }), // the resolution mode,
//! Some(wl_output::Transform::Normal), // global screen transformation //! Some(wl_output::Transform::Normal), // global screen transformation
//! Some(1), // global screen scaling factor //! Some(1), // global screen scaling factor
//! ); //! );
//! // set the preferred mode //! // set the preferred mode
//! output.set_preferred(Mode { width: 1920, height: 1080, refresh: 60000 }); //! output.set_preferred(Mode { size: (1920, 1080).into(), refresh: 60000 });
//! // add other supported modes //! // add other supported modes
//! output.add_mode(Mode { width: 800, height: 600, refresh: 60000 }); //! output.add_mode(Mode { size: (800, 600).into(), refresh: 60000 });
//! output.add_mode(Mode { width: 1024, height: 768, refresh: 60000 }); //! output.add_mode(Mode { size: (1024, 768).into(), refresh: 60000 });
//! ``` //! ```
use std::{ use std::{
@ -64,6 +63,8 @@ use wayland_server::{
use slog::{info, o, trace, warn}; use slog::{info, o, trace, warn};
use crate::utils::{Logical, Physical, Point, Raw, Size};
/// An output mode /// An output mode
/// ///
/// A possible combination of dimensions and refresh rate for an output. /// A possible combination of dimensions and refresh rate for an output.
@ -72,10 +73,8 @@ use slog::{info, o, trace, warn};
/// not taking into account any global scaling. /// not taking into account any global scaling.
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
pub struct Mode { pub struct Mode {
/// The width in pixels /// The size of the mode, in pixels
pub width: i32, pub size: Size<i32, Physical>,
/// The height in pixels
pub height: i32,
/// The refresh rate in millihertz /// The refresh rate in millihertz
/// ///
/// `1000` is one fps (frame per second), `2000` is 2 fps, etc... /// `1000` is one fps (frame per second), `2000` is 2 fps, etc...
@ -85,10 +84,8 @@ pub struct Mode {
/// The physical properties of an output /// The physical properties of an output
#[derive(Debug)] #[derive(Debug)]
pub struct PhysicalProperties { pub struct PhysicalProperties {
/// The width in millimeters /// The size of the monitor, in millimeters
pub width: i32, pub size: Size<i32, Raw>,
/// The height in millimeters
pub height: i32,
/// The subpixel geometry /// The subpixel geometry
pub subpixel: Subpixel, pub subpixel: Subpixel,
/// Textual representation of the make /// Textual representation of the make
@ -103,7 +100,7 @@ struct Inner {
log: ::slog::Logger, log: ::slog::Logger,
instances: Vec<WlOutput>, instances: Vec<WlOutput>,
physical: PhysicalProperties, physical: PhysicalProperties,
location: (i32, i32), location: Point<i32, Logical>,
transform: Transform, transform: Transform,
scale: i32, scale: i32,
modes: Vec<Mode>, modes: Vec<Mode>,
@ -134,7 +131,7 @@ impl Inner {
if Some(mode) == self.preferred_mode { if Some(mode) == self.preferred_mode {
flags |= WMode::Preferred; flags |= WMode::Preferred;
} }
output.mode(flags, mode.width, mode.height, mode.refresh); output.mode(flags, mode.size.w, mode.size.h, mode.refresh);
} }
if output.as_ref().version() >= 2 { if output.as_ref().version() >= 2 {
output.scale(self.scale); output.scale(self.scale);
@ -146,10 +143,10 @@ impl Inner {
fn send_geometry(&self, output: &WlOutput) { fn send_geometry(&self, output: &WlOutput) {
output.geometry( output.geometry(
self.location.0, self.location.x,
self.location.1, self.location.y,
self.physical.width, self.physical.size.w,
self.physical.height, self.physical.size.h,
self.physical.subpixel, self.physical.subpixel,
self.physical.make.clone(), self.physical.make.clone(),
self.physical.model.clone(), self.physical.model.clone(),
@ -191,7 +188,7 @@ impl Output {
log, log,
instances: Vec::new(), instances: Vec::new(),
physical, physical,
location: (0, 0), location: (0, 0).into(),
transform: Transform::Normal, transform: Transform::Normal,
scale: 1, scale: 1,
modes: Vec::new(), modes: Vec::new(),
@ -292,7 +289,7 @@ impl Output {
} }
for output in &inner.instances { for output in &inner.instances {
if let Some(mode) = new_mode { if let Some(mode) = new_mode {
output.mode(flags, mode.width, mode.height, mode.refresh); output.mode(flags, mode.size.w, mode.size.h, mode.refresh);
} }
if new_transform.is_some() { if new_transform.is_some() {
inner.send_geometry(output); inner.send_geometry(output);

View File

@ -8,8 +8,10 @@ use wayland_server::{
Filter, Main, Filter, Main,
}; };
use crate::wayland::compositor; use crate::{
use crate::wayland::Serial; utils::{Logical, Point},
wayland::{compositor, Serial},
};
static CURSOR_IMAGE_ROLE: &str = "cursor_image"; static CURSOR_IMAGE_ROLE: &str = "cursor_image";
@ -17,7 +19,7 @@ static CURSOR_IMAGE_ROLE: &str = "cursor_image";
#[derive(Debug, Default, Copy, Clone)] #[derive(Debug, Default, Copy, Clone)]
pub struct CursorImageAttributes { pub struct CursorImageAttributes {
/// Location of the hotspot of the pointer in the surface /// Location of the hotspot of the pointer in the surface
pub hotspot: (i32, i32), pub hotspot: Point<i32, Logical>,
} }
/// Possible status of a cursor as requested by clients /// Possible status of a cursor as requested by clients
@ -50,9 +52,9 @@ impl fmt::Debug for GrabStatus {
struct PointerInternal { struct PointerInternal {
known_pointers: Vec<WlPointer>, known_pointers: Vec<WlPointer>,
focus: Option<(WlSurface, (f64, f64))>, focus: Option<(WlSurface, Point<i32, Logical>)>,
pending_focus: Option<(WlSurface, (f64, f64))>, pending_focus: Option<(WlSurface, Point<i32, Logical>)>,
location: (f64, f64), location: Point<f64, Logical>,
grab: GrabStatus, grab: GrabStatus,
pressed_buttons: Vec<u32>, pressed_buttons: Vec<u32>,
image_callback: Box<dyn FnMut(CursorImageStatus)>, image_callback: Box<dyn FnMut(CursorImageStatus)>,
@ -82,7 +84,7 @@ impl PointerInternal {
known_pointers: Vec::new(), known_pointers: Vec::new(),
focus: None, focus: None,
pending_focus: None, pending_focus: None,
location: (0.0, 0.0), location: (0.0, 0.0).into(),
grab: GrabStatus::None, grab: GrabStatus::None,
pressed_buttons: Vec::new(), pressed_buttons: Vec::new(),
image_callback: Box::new(cb) as Box<_>, image_callback: Box::new(cb) as Box<_>,
@ -201,8 +203,8 @@ impl PointerHandle {
/// of enter/motion/leave events. /// of enter/motion/leave events.
pub fn motion( pub fn motion(
&self, &self,
location: (f64, f64), location: Point<f64, Logical>,
focus: Option<(WlSurface, (f64, f64))>, focus: Option<(WlSurface, Point<i32, Logical>)>,
serial: Serial, serial: Serial,
time: u32, time: u32,
) { ) {
@ -243,7 +245,7 @@ impl PointerHandle {
} }
/// Access the current location of this pointer in the global space /// Access the current location of this pointer in the global space
pub fn current_location(&self) -> (f64, f64) { pub fn current_location(&self) -> Point<f64, Logical> {
self.inner.borrow().location self.inner.borrow().location
} }
} }
@ -254,11 +256,11 @@ pub struct GrabStartData {
/// The focused surface and its location, if any, at the start of the grab. /// The focused surface and its location, if any, at the start of the grab.
/// ///
/// The location coordinates are in the global compositor space. /// The location coordinates are in the global compositor space.
pub focus: Option<(WlSurface, (f64, f64))>, pub focus: Option<(WlSurface, Point<i32, Logical>)>,
/// The button that initiated the grab. /// The button that initiated the grab.
pub button: u32, pub button: u32,
/// The location of the click that initiated the grab, in the global compositor space. /// The location of the click that initiated the grab, in the global compositor space.
pub location: (f64, f64), pub location: Point<f64, Logical>,
} }
/// A trait to implement a pointer grab /// A trait to implement a pointer grab
@ -281,8 +283,8 @@ pub trait PointerGrab {
fn motion( fn motion(
&mut self, &mut self,
handle: &mut PointerInnerHandle<'_>, handle: &mut PointerInnerHandle<'_>,
location: (f64, f64), location: Point<f64, Logical>,
focus: Option<(WlSurface, (f64, f64))>, focus: Option<(WlSurface, Point<i32, Logical>)>,
serial: Serial, serial: Serial,
time: u32, time: u32,
); );
@ -328,12 +330,12 @@ impl<'a> PointerInnerHandle<'a> {
} }
/// Access the current focus of this pointer /// Access the current focus of this pointer
pub fn current_focus(&self) -> Option<&(WlSurface, (f64, f64))> { pub fn current_focus(&self) -> Option<&(WlSurface, Point<i32, Logical>)> {
self.inner.focus.as_ref() self.inner.focus.as_ref()
} }
/// Access the current location of this pointer in the global space /// Access the current location of this pointer in the global space
pub fn current_location(&self) -> (f64, f64) { pub fn current_location(&self) -> Point<f64, Logical> {
self.inner.location self.inner.location
} }
@ -358,14 +360,14 @@ impl<'a> PointerInnerHandle<'a> {
/// of enter/motion/leave events. /// of enter/motion/leave events.
pub fn motion( pub fn motion(
&mut self, &mut self,
(x, y): (f64, f64), location: Point<f64, Logical>,
focus: Option<(WlSurface, (f64, f64))>, focus: Option<(WlSurface, Point<i32, Logical>)>,
serial: Serial, serial: Serial,
time: u32, time: u32,
) { ) {
// do we leave a surface ? // do we leave a surface ?
let mut leave = true; let mut leave = true;
self.inner.location = (x, y); self.inner.location = location;
if let Some((ref current_focus, _)) = self.inner.focus { if let Some((ref current_focus, _)) = self.inner.focus {
if let Some((ref surface, _)) = focus { if let Some((ref surface, _)) = focus {
if current_focus.as_ref().equals(surface.as_ref()) { if current_focus.as_ref().equals(surface.as_ref()) {
@ -385,14 +387,15 @@ impl<'a> PointerInnerHandle<'a> {
} }
// do we enter one ? // do we enter one ?
if let Some((surface, (sx, sy))) = focus { if let Some((surface, surface_location)) = focus {
let entered = self.inner.focus.is_none(); let entered = self.inner.focus.is_none();
// in all cases, update the focus, the coordinates of the surface // in all cases, update the focus, the coordinates of the surface
// might have changed // might have changed
self.inner.focus = Some((surface, (sx, sy))); self.inner.focus = Some((surface, surface_location));
let (x, y) = (location - surface_location.to_f64()).into();
if entered { if entered {
self.inner.with_focused_pointers(|pointer, surface| { self.inner.with_focused_pointers(|pointer, surface| {
pointer.enter(serial.into(), &surface, x - sx, y - sy); pointer.enter(serial.into(), &surface, x, y);
if pointer.as_ref().version() >= 5 { if pointer.as_ref().version() >= 5 {
pointer.frame(); pointer.frame();
} }
@ -400,7 +403,7 @@ impl<'a> PointerInnerHandle<'a> {
} else { } else {
// we were on top of a surface and remained on it // we were on top of a surface and remained on it
self.inner.with_focused_pointers(|pointer, _| { self.inner.with_focused_pointers(|pointer, _| {
pointer.motion(time, x - sx, y - sy); pointer.motion(time, x, y);
if pointer.as_ref().version() >= 5 { if pointer.as_ref().version() >= 5 {
pointer.frame(); pointer.frame();
} }
@ -600,7 +603,9 @@ pub(crate) fn implement_pointer(pointer: Main<WlPointer>, handle: Option<&Pointe
} }
compositor::with_states(&surface, |states| { compositor::with_states(&surface, |states| {
states.data_map.insert_if_missing_threadsafe(|| { states.data_map.insert_if_missing_threadsafe(|| {
Mutex::new(CursorImageAttributes { hotspot: (0, 0) }) Mutex::new(CursorImageAttributes {
hotspot: (0, 0).into(),
})
}); });
states states
.data_map .data_map
@ -608,7 +613,7 @@ pub(crate) fn implement_pointer(pointer: Main<WlPointer>, handle: Option<&Pointe
.unwrap() .unwrap()
.lock() .lock()
.unwrap() .unwrap()
.hotspot = (hotspot_x, hotspot_y); .hotspot = (hotspot_x, hotspot_y).into();
}) })
.unwrap(); .unwrap();
@ -653,8 +658,8 @@ impl PointerGrab for DefaultGrab {
fn motion( fn motion(
&mut self, &mut self,
handle: &mut PointerInnerHandle<'_>, handle: &mut PointerInnerHandle<'_>,
location: (f64, f64), location: Point<f64, Logical>,
focus: Option<(WlSurface, (f64, f64))>, focus: Option<(WlSurface, Point<i32, Logical>)>,
serial: Serial, serial: Serial,
time: u32, time: u32,
) { ) {
@ -701,8 +706,8 @@ impl PointerGrab for ClickGrab {
fn motion( fn motion(
&mut self, &mut self,
handle: &mut PointerInnerHandle<'_>, handle: &mut PointerInnerHandle<'_>,
location: (f64, f64), location: Point<f64, Logical>,
_focus: Option<(WlSurface, (f64, f64))>, _focus: Option<(WlSurface, Point<i32, Logical>)>,
serial: Serial, serial: Serial,
time: u32, time: u32,
) { ) {

View File

@ -49,7 +49,10 @@ use std::{
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use crate::wayland::{compositor, Serial}; use crate::{
utils::{Logical, Point, Size},
wayland::{compositor, Serial},
};
use wayland_server::{ use wayland_server::{
protocol::{wl_output, wl_seat, wl_shell, wl_shell_surface, wl_surface}, protocol::{wl_output, wl_seat, wl_shell, wl_shell_surface, wl_surface},
@ -132,8 +135,8 @@ impl ShellSurface {
} }
/// Send a configure event to this toplevel surface to suggest it a new configuration /// Send a configure event to this toplevel surface to suggest it a new configuration
pub fn send_configure(&self, size: (u32, u32), edges: wl_shell_surface::Resize) { pub fn send_configure(&self, size: Size<i32, Logical>, edges: wl_shell_surface::Resize) {
self.shell_surface.configure(edges, size.0 as i32, size.1 as i32) self.shell_surface.configure(edges, size.w, size.h)
} }
/// Signal a popup surface that it has lost focus /// Signal a popup surface that it has lost focus
@ -155,7 +158,7 @@ pub enum ShellSurfaceKind {
/// The surface considered as parent /// The surface considered as parent
parent: wl_surface::WlSurface, parent: wl_surface::WlSurface,
/// Location relative to the parent /// Location relative to the parent
location: (i32, i32), location: Point<i32, Logical>,
/// Wether this window should be marked as inactive /// Wether this window should be marked as inactive
inactive: bool, inactive: bool,
}, },
@ -181,7 +184,7 @@ pub enum ShellSurfaceKind {
/// Wether this popup should be marked as inactive /// Wether this popup should be marked as inactive
inactive: bool, inactive: bool,
/// Location of the popup relative to its parent /// Location of the popup relative to its parent
location: (i32, i32), location: Point<i32, Logical>,
/// Seat associated this the input that triggered the creation of the /// Seat associated this the input that triggered the creation of the
/// popup. Used to define when the "popup done" event is sent. /// popup. Used to define when the "popup done" event is sent.
seat: wl_seat::WlSeat, seat: wl_seat::WlSeat,

View File

@ -157,7 +157,7 @@ where
surface: make_handle(&shell_surface), surface: make_handle(&shell_surface),
kind: ShellSurfaceKind::Transient { kind: ShellSurfaceKind::Transient {
parent, parent,
location: (x, y), location: (x, y).into(),
inactive: flags.contains(wl_shell_surface::Transient::Inactive), inactive: flags.contains(wl_shell_surface::Transient::Inactive),
}, },
}, },
@ -194,7 +194,7 @@ where
parent, parent,
serial, serial,
seat, seat,
location: (x, y), location: (x, y).into(),
inactive: flags.contains(wl_shell_surface::Transient::Inactive), inactive: flags.contains(wl_shell_surface::Transient::Inactive),
}, },
}, },

View File

@ -62,7 +62,7 @@
//! that you are given (in an `Arc<Mutex<_>>`) as return value of the `init` function. //! that you are given (in an `Arc<Mutex<_>>`) as return value of the `init` function.
use crate::utils::DeadResource; use crate::utils::DeadResource;
use crate::utils::Rectangle; use crate::utils::{Logical, Point, Rectangle, Size};
use crate::wayland::compositor; use crate::wayland::compositor;
use crate::wayland::compositor::Cacheable; use crate::wayland::compositor::Cacheable;
use crate::wayland::{Serial, SERIAL_COUNTER}; use crate::wayland::{Serial, SERIAL_COUNTER};
@ -220,11 +220,11 @@ xdg_role!(
/// Minimum size requested for this surface /// Minimum size requested for this surface
/// ///
/// A value of 0 on an axis means this axis is not constrained /// A value of 0 on an axis means this axis is not constrained
pub min_size: (i32, i32), pub min_size: Size<i32, Logical>,
/// Maximum size requested for this surface /// Maximum size requested for this surface
/// ///
/// A value of 0 on an axis means this axis is not constrained /// A value of 0 on an axis means this axis is not constrained
pub max_size: (i32, i32), pub max_size: Size<i32, Logical>,
/// Holds the pending state as set by the server. /// Holds the pending state as set by the server.
pub server_pending: Option<ToplevelState>, pub server_pending: Option<ToplevelState>,
/// Holds the last server_pending state that has been acknowledged /// Holds the last server_pending state that has been acknowledged
@ -315,7 +315,7 @@ pub struct PopupState {
/// `Rectangle::x` and `Rectangle::y` holds the position of the popup /// `Rectangle::x` and `Rectangle::y` holds the position of the popup
/// The position is relative to the window geometry as defined by /// The position is relative to the window geometry as defined by
/// xdg_surface.set_window_geometry of the parent surface. /// xdg_surface.set_window_geometry of the parent surface.
pub geometry: Rectangle, pub geometry: Rectangle<i32, Logical>,
} }
impl Default for PopupState { impl Default for PopupState {
@ -330,10 +330,10 @@ impl Default for PopupState {
/// The state of a positioner, as set by the client /// The state of a positioner, as set by the client
pub struct PositionerState { pub struct PositionerState {
/// Size of the rectangle that needs to be positioned /// Size of the rectangle that needs to be positioned
pub rect_size: (i32, i32), pub rect_size: Size<i32, Logical>,
/// Anchor rectangle in the parent surface coordinates /// Anchor rectangle in the parent surface coordinates
/// relative to which the surface must be positioned /// relative to which the surface must be positioned
pub anchor_rect: Rectangle, pub anchor_rect: Rectangle<i32, Logical>,
/// Edges defining the anchor point /// Edges defining the anchor point
pub anchor_edges: xdg_positioner::Anchor, pub anchor_edges: xdg_positioner::Anchor,
/// Gravity direction for positioning the child surface /// Gravity direction for positioning the child surface
@ -343,7 +343,7 @@ pub struct PositionerState {
/// surface /// surface
pub constraint_adjustment: xdg_positioner::ConstraintAdjustment, pub constraint_adjustment: xdg_positioner::ConstraintAdjustment,
/// Offset placement relative to the anchor point /// Offset placement relative to the anchor point
pub offset: (i32, i32), pub offset: Point<i32, Logical>,
} }
impl Default for PositionerState { impl Default for PositionerState {
@ -353,29 +353,13 @@ impl Default for PositionerState {
anchor_rect: Default::default(), anchor_rect: Default::default(),
constraint_adjustment: xdg_positioner::ConstraintAdjustment::empty(), constraint_adjustment: xdg_positioner::ConstraintAdjustment::empty(),
gravity: xdg_positioner::Gravity::None, gravity: xdg_positioner::Gravity::None,
offset: (0, 0), offset: Default::default(),
rect_size: (0, 0), rect_size: Default::default(),
} }
} }
} }
impl PositionerState { impl PositionerState {
pub(crate) fn new() -> PositionerState {
PositionerState {
rect_size: (0, 0),
anchor_rect: Rectangle {
x: 0,
y: 0,
width: 0,
height: 0,
},
anchor_edges: xdg_positioner::Anchor::None,
gravity: xdg_positioner::Gravity::None,
constraint_adjustment: xdg_positioner::ConstraintAdjustment::None,
offset: (0, 0),
}
}
pub(crate) fn anchor_has_edge(&self, edge: xdg_positioner::Anchor) -> bool { pub(crate) fn anchor_has_edge(&self, edge: xdg_positioner::Anchor) -> bool {
match edge { match edge {
xdg_positioner::Anchor::Top => { xdg_positioner::Anchor::Top => {
@ -440,7 +424,7 @@ impl PositionerState {
/// The `constraint_adjustment` will not be considered by this /// The `constraint_adjustment` will not be considered by this
/// implementation and the position and size should be re-calculated /// implementation and the position and size should be re-calculated
/// in the compositor if the compositor implements `constraint_adjustment` /// in the compositor if the compositor implements `constraint_adjustment`
pub(crate) fn get_geometry(&self) -> Rectangle { pub(crate) fn get_geometry(&self) -> Rectangle<i32, Logical> {
// From the `xdg_shell` prococol specification: // From the `xdg_shell` prococol specification:
// //
// set_offset: // set_offset:
@ -451,10 +435,8 @@ impl PositionerState {
// has the gravity bottom|right, and the offset is (ox, oy), the calculated // has the gravity bottom|right, and the offset is (ox, oy), the calculated
// surface position will be (x + ox, y + oy) // surface position will be (x + ox, y + oy)
let mut geometry = Rectangle { let mut geometry = Rectangle {
x: self.offset.0, loc: self.offset,
y: self.offset.1, size: self.rect_size,
width: self.rect_size.0,
height: self.rect_size.1,
}; };
// Defines the anchor point for the anchor rectangle. The specified anchor // Defines the anchor point for the anchor rectangle. The specified anchor
@ -464,19 +446,19 @@ impl PositionerState {
// otherwise, the derived anchor point will be centered on the specified // otherwise, the derived anchor point will be centered on the specified
// edge, or in the center of the anchor rectangle if no edge is specified. // edge, or in the center of the anchor rectangle if no edge is specified.
if self.anchor_has_edge(xdg_positioner::Anchor::Top) { if self.anchor_has_edge(xdg_positioner::Anchor::Top) {
geometry.y += self.anchor_rect.y; geometry.loc.y += self.anchor_rect.loc.y;
} else if self.anchor_has_edge(xdg_positioner::Anchor::Bottom) { } else if self.anchor_has_edge(xdg_positioner::Anchor::Bottom) {
geometry.y += self.anchor_rect.y + self.anchor_rect.height; geometry.loc.y += self.anchor_rect.loc.y + self.anchor_rect.size.h;
} else { } else {
geometry.y += self.anchor_rect.y + self.anchor_rect.height / 2; geometry.loc.y += self.anchor_rect.loc.y + self.anchor_rect.size.h / 2;
} }
if self.anchor_has_edge(xdg_positioner::Anchor::Left) { if self.anchor_has_edge(xdg_positioner::Anchor::Left) {
geometry.x += self.anchor_rect.x; geometry.loc.x += self.anchor_rect.loc.x;
} else if self.anchor_has_edge(xdg_positioner::Anchor::Right) { } else if self.anchor_has_edge(xdg_positioner::Anchor::Right) {
geometry.x += self.anchor_rect.x + self.anchor_rect.width; geometry.loc.x += self.anchor_rect.loc.x + self.anchor_rect.size.w;
} else { } else {
geometry.x += self.anchor_rect.x + self.anchor_rect.width / 2; geometry.loc.x += self.anchor_rect.loc.x + self.anchor_rect.size.w / 2;
} }
// Defines in what direction a surface should be positioned, relative to // Defines in what direction a surface should be positioned, relative to
@ -486,15 +468,15 @@ impl PositionerState {
// surface will be centered over the anchor point on any axis that had no // surface will be centered over the anchor point on any axis that had no
// gravity specified. // gravity specified.
if self.gravity_has_edge(xdg_positioner::Gravity::Top) { if self.gravity_has_edge(xdg_positioner::Gravity::Top) {
geometry.y -= geometry.height; geometry.loc.y -= geometry.size.h;
} else if !self.gravity_has_edge(xdg_positioner::Gravity::Bottom) { } else if !self.gravity_has_edge(xdg_positioner::Gravity::Bottom) {
geometry.y -= geometry.height / 2; geometry.loc.y -= geometry.size.h / 2;
} }
if self.gravity_has_edge(xdg_positioner::Gravity::Left) { if self.gravity_has_edge(xdg_positioner::Gravity::Left) {
geometry.x -= geometry.width; geometry.loc.x -= geometry.size.w;
} else if !self.gravity_has_edge(xdg_positioner::Gravity::Right) { } else if !self.gravity_has_edge(xdg_positioner::Gravity::Right) {
geometry.x -= geometry.width / 2; geometry.loc.x -= geometry.size.w / 2;
} }
geometry geometry
@ -505,7 +487,7 @@ impl PositionerState {
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct ToplevelState { pub struct ToplevelState {
/// The suggested size of the surface /// The suggested size of the surface
pub size: Option<(i32, i32)>, pub size: Option<Size<i32, Logical>>,
/// The states for this surface /// The states for this surface
pub states: ToplevelStateSet, pub states: ToplevelStateSet,
@ -603,29 +585,29 @@ impl From<ToplevelStateSet> for Vec<xdg_toplevel::State> {
pub struct SurfaceCachedState { pub struct SurfaceCachedState {
/// Holds the double-buffered geometry that may be specified /// Holds the double-buffered geometry that may be specified
/// by xdg_surface.set_window_geometry. /// by xdg_surface.set_window_geometry.
pub geometry: Option<Rectangle>, pub geometry: Option<Rectangle<i32, Logical>>,
/// Minimum size requested for this surface /// Minimum size requested for this surface
/// ///
/// A value of 0 on an axis means this axis is not constrained /// A value of 0 on an axis means this axis is not constrained
/// ///
/// This is only relevant for xdg_toplevel, and will always be /// This is only relevant for xdg_toplevel, and will always be
/// `(0, 0)` for xdg_popup. /// `(0, 0)` for xdg_popup.
pub min_size: (i32, i32), pub min_size: Size<i32, Logical>,
/// Maximum size requested for this surface /// Maximum size requested for this surface
/// ///
/// A value of 0 on an axis means this axis is not constrained /// A value of 0 on an axis means this axis is not constrained
/// ///
/// This is only relevant for xdg_toplevel, and will always be /// This is only relevant for xdg_toplevel, and will always be
/// `(0, 0)` for xdg_popup. /// `(0, 0)` for xdg_popup.
pub max_size: (i32, i32), pub max_size: Size<i32, Logical>,
} }
impl Default for SurfaceCachedState { impl Default for SurfaceCachedState {
fn default() -> Self { fn default() -> Self {
Self { Self {
geometry: None, geometry: None,
min_size: (0, 0), min_size: Default::default(),
max_size: (0, 0), max_size: Default::default(),
} }
} }
} }
@ -1593,8 +1575,8 @@ pub enum XdgRequest {
seat: wl_seat::WlSeat, seat: wl_seat::WlSeat,
/// the grab serial /// the grab serial
serial: Serial, serial: Serial,
/// location of the menu request /// location of the menu request relative to the surface geometry
location: (i32, i32), location: Point<i32, Logical>,
}, },
/// A surface has acknowledged a configure serial. /// A surface has acknowledged a configure serial.
AckConfigure { AckConfigure {

View File

@ -132,7 +132,7 @@ fn implement_positioner(positioner: Main<xdg_positioner::XdgPositioner>) -> xdg_
"Invalid size for positioner.".into(), "Invalid size for positioner.".into(),
); );
} else { } else {
state.rect_size = (width, height); state.rect_size = (width, height).into();
} }
} }
xdg_positioner::Request::SetAnchorRect { x, y, width, height } => { xdg_positioner::Request::SetAnchorRect { x, y, width, height } => {
@ -142,7 +142,7 @@ fn implement_positioner(positioner: Main<xdg_positioner::XdgPositioner>) -> xdg_
"Invalid size for positioner's anchor rectangle.".into(), "Invalid size for positioner's anchor rectangle.".into(),
); );
} else { } else {
state.anchor_rect = Rectangle { x, y, width, height }; state.anchor_rect = Rectangle::from_loc_and_size((x, y), (width, height));
} }
} }
xdg_positioner::Request::SetAnchor { anchor } => { xdg_positioner::Request::SetAnchor { anchor } => {
@ -159,7 +159,7 @@ fn implement_positioner(positioner: Main<xdg_positioner::XdgPositioner>) -> xdg_
state.constraint_adjustment = constraint_adjustment; state.constraint_adjustment = constraint_adjustment;
} }
xdg_positioner::Request::SetOffset { x, y } => { xdg_positioner::Request::SetOffset { x, y } => {
state.offset = (x, y); state.offset = (x, y).into();
} }
_ => unreachable!(), _ => unreachable!(),
} }
@ -167,7 +167,7 @@ fn implement_positioner(positioner: Main<xdg_positioner::XdgPositioner>) -> xdg_
positioner positioner
.as_ref() .as_ref()
.user_data() .user_data()
.set(|| RefCell::new(PositionerState::new())); .set(|| RefCell::new(PositionerState::default()));
positioner.deref().clone() positioner.deref().clone()
} }
@ -363,7 +363,7 @@ fn xdg_surface_implementation(
compositor::with_states(surface, |states| { compositor::with_states(surface, |states| {
states.cached_state.pending::<SurfaceCachedState>().geometry = states.cached_state.pending::<SurfaceCachedState>().geometry =
Some(Rectangle { x, y, width, height }); Some(Rectangle::from_loc_and_size((x, y), (width, height)));
}) })
.unwrap(); .unwrap();
} }
@ -501,7 +501,7 @@ pub fn send_toplevel_configure(resource: &xdg_toplevel::XdgToplevel, configure:
.get::<ShellSurfaceUserData>() .get::<ShellSurfaceUserData>()
.unwrap(); .unwrap();
let (width, height) = configure.state.size.unwrap_or((0, 0)); let (width, height) = configure.state.size.unwrap_or_default().into();
// convert the Vec<State> (which is really a Vec<u32>) into Vec<u8> // convert the Vec<State> (which is really a Vec<u32>) into Vec<u8>
let states = { let states = {
let mut states: Vec<xdg_toplevel::State> = configure.state.states.into(); let mut states: Vec<xdg_toplevel::State> = configure.state.states.into();
@ -583,7 +583,7 @@ fn toplevel_implementation(
surface: handle, surface: handle,
seat, seat,
serial, serial,
location: (x, y), location: (x, y).into(),
}, },
dispatch_data, dispatch_data,
); );
@ -619,12 +619,12 @@ fn toplevel_implementation(
} }
xdg_toplevel::Request::SetMaxSize { width, height } => { xdg_toplevel::Request::SetMaxSize { width, height } => {
with_toplevel_pending_state(&toplevel, |toplevel_data| { with_toplevel_pending_state(&toplevel, |toplevel_data| {
toplevel_data.max_size = (width, height); toplevel_data.max_size = (width, height).into();
}); });
} }
xdg_toplevel::Request::SetMinSize { width, height } => { xdg_toplevel::Request::SetMinSize { width, height } => {
with_toplevel_pending_state(&toplevel, |toplevel_data| { with_toplevel_pending_state(&toplevel, |toplevel_data| {
toplevel_data.min_size = (width, height); toplevel_data.min_size = (width, height).into();
}); });
} }
xdg_toplevel::Request::SetMaximized => { xdg_toplevel::Request::SetMaximized => {
@ -697,7 +697,7 @@ pub(crate) fn send_popup_configure(resource: &xdg_popup::XdgPopup, configure: Po
let geometry = configure.state.geometry; let geometry = configure.state.geometry;
// Send the popup configure // Send the popup configure
resource.configure(geometry.x, geometry.y, geometry.width, geometry.height); resource.configure(geometry.loc.x, geometry.loc.y, geometry.size.w, geometry.size.h);
// Send the base xdg_surface configure event to mark // Send the base xdg_surface configure event to mark
// the configure as finished // the configure as finished

View File

@ -132,7 +132,7 @@ fn implement_positioner(
"Invalid size for positioner.".into(), "Invalid size for positioner.".into(),
); );
} else { } else {
state.rect_size = (width, height); state.rect_size = (width, height).into();
} }
} }
zxdg_positioner_v6::Request::SetAnchorRect { x, y, width, height } => { zxdg_positioner_v6::Request::SetAnchorRect { x, y, width, height } => {
@ -142,7 +142,7 @@ fn implement_positioner(
"Invalid size for positioner's anchor rectangle.".into(), "Invalid size for positioner's anchor rectangle.".into(),
); );
} else { } else {
state.anchor_rect = Rectangle { x, y, width, height }; state.anchor_rect = Rectangle::from_loc_and_size((x, y), (width, height));
} }
} }
zxdg_positioner_v6::Request::SetAnchor { anchor } => { zxdg_positioner_v6::Request::SetAnchor { anchor } => {
@ -173,7 +173,7 @@ fn implement_positioner(
state.constraint_adjustment = zxdg_constraints_adg_to_xdg(constraint_adjustment); state.constraint_adjustment = zxdg_constraints_adg_to_xdg(constraint_adjustment);
} }
zxdg_positioner_v6::Request::SetOffset { x, y } => { zxdg_positioner_v6::Request::SetOffset { x, y } => {
state.offset = (x, y); state.offset = (x, y).into();
} }
_ => unreachable!(), _ => unreachable!(),
} }
@ -181,7 +181,7 @@ fn implement_positioner(
positioner positioner
.as_ref() .as_ref()
.user_data() .user_data()
.set(|| RefCell::new(PositionerState::new())); .set(|| RefCell::new(PositionerState::default()));
positioner.deref().clone() positioner.deref().clone()
} }
@ -377,7 +377,7 @@ fn xdg_surface_implementation(
compositor::with_states(surface, |states| { compositor::with_states(surface, |states| {
states.cached_state.pending::<SurfaceCachedState>().geometry = states.cached_state.pending::<SurfaceCachedState>().geometry =
Some(Rectangle { x, y, width, height }); Some(Rectangle::from_loc_and_size((x, y), (width, height)));
}) })
.unwrap(); .unwrap();
} }
@ -516,7 +516,7 @@ pub fn send_toplevel_configure(resource: &zxdg_toplevel_v6::ZxdgToplevelV6, conf
.get::<ShellSurfaceUserData>() .get::<ShellSurfaceUserData>()
.unwrap(); .unwrap();
let (width, height) = configure.state.size.unwrap_or((0, 0)); let (width, height) = configure.state.size.unwrap_or_default().into();
// convert the Vec<State> (which is really a Vec<u32>) into Vec<u8> // convert the Vec<State> (which is really a Vec<u32>) into Vec<u8>
let states = { let states = {
let mut states: Vec<xdg_toplevel::State> = configure.state.states.into(); let mut states: Vec<xdg_toplevel::State> = configure.state.states.into();
@ -595,7 +595,7 @@ fn toplevel_implementation(
surface: handle, surface: handle,
seat, seat,
serial, serial,
location: (x, y), location: (x, y).into(),
}, },
dispatch_data, dispatch_data,
); );
@ -631,12 +631,12 @@ fn toplevel_implementation(
} }
zxdg_toplevel_v6::Request::SetMaxSize { width, height } => { zxdg_toplevel_v6::Request::SetMaxSize { width, height } => {
with_toplevel_pending_state(&toplevel, |toplevel_data| { with_toplevel_pending_state(&toplevel, |toplevel_data| {
toplevel_data.max_size = (width, height); toplevel_data.max_size = (width, height).into();
}); });
} }
zxdg_toplevel_v6::Request::SetMinSize { width, height } => { zxdg_toplevel_v6::Request::SetMinSize { width, height } => {
with_toplevel_pending_state(&toplevel, |toplevel_data| { with_toplevel_pending_state(&toplevel, |toplevel_data| {
toplevel_data.min_size = (width, height); toplevel_data.min_size = (width, height).into();
}); });
} }
zxdg_toplevel_v6::Request::SetMaximized => { zxdg_toplevel_v6::Request::SetMaximized => {
@ -709,7 +709,7 @@ pub(crate) fn send_popup_configure(resource: &zxdg_popup_v6::ZxdgPopupV6, config
let geometry = configure.state.geometry; let geometry = configure.state.geometry;
// Send the popup configure // Send the popup configure
resource.configure(geometry.x, geometry.y, geometry.width, geometry.height); resource.configure(geometry.loc.x, geometry.loc.y, geometry.size.w, geometry.size.h);
// Send the base xdg_surface configure event to mark // Send the base xdg_surface configure event to mark
// the configure as finished // the configure as finished

View File

@ -3,6 +3,7 @@ use std::sync::Mutex;
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
use crate::backend::input::{ButtonState, TabletToolCapabilitys, TabletToolDescriptor, TabletToolType}; use crate::backend::input::{ButtonState, TabletToolCapabilitys, TabletToolDescriptor, TabletToolType};
use crate::utils::{Logical, Point};
use crate::wayland::seat::{CursorImageAttributes, CursorImageStatus}; use crate::wayland::seat::{CursorImageAttributes, CursorImageStatus};
use wayland_protocols::unstable::tablet::v2::server::{ use wayland_protocols::unstable::tablet::v2::server::{
zwp_tablet_seat_v2::ZwpTabletSeatV2, zwp_tablet_seat_v2::ZwpTabletSeatV2,
@ -35,8 +36,8 @@ struct TabletTool {
impl TabletTool { impl TabletTool {
fn proximity_in( fn proximity_in(
&mut self, &mut self,
(x, y): (f64, f64), loc: Point<f64, Logical>,
(focus, (sx, sy)): (WlSurface, (f64, f64)), (focus, sloc): (WlSurface, Point<i32, Logical>),
tablet: &TabletHandle, tablet: &TabletHandle,
serial: Serial, serial: Serial,
time: u32, time: u32,
@ -50,7 +51,8 @@ impl TabletTool {
tablet.with_focused_tablet(&focus, |wl_tablet| { tablet.with_focused_tablet(&focus, |wl_tablet| {
wl_tool.proximity_in(serial.into(), wl_tablet, &focus); wl_tool.proximity_in(serial.into(), wl_tablet, &focus);
// proximity_in has to be followed by motion event (required by protocol) // proximity_in has to be followed by motion event (required by protocol)
wl_tool.motion(x - sx, y - sy); let srel_loc = loc - sloc.to_f64();
wl_tool.motion(srel_loc.x, srel_loc.y);
wl_tool.frame(time); wl_tool.frame(time);
}); });
} }
@ -114,8 +116,8 @@ impl TabletTool {
fn motion( fn motion(
&mut self, &mut self,
pos: (f64, f64), pos: Point<f64, Logical>,
focus: Option<(WlSurface, (f64, f64))>, focus: Option<(WlSurface, Point<i32, Logical>)>,
tablet: &TabletHandle, tablet: &TabletHandle,
serial: Serial, serial: Serial,
time: u32, time: u32,
@ -128,9 +130,8 @@ impl TabletTool {
.iter() .iter()
.find(|i| i.as_ref().same_client_as(focus.0.as_ref())) .find(|i| i.as_ref().same_client_as(focus.0.as_ref()))
{ {
let (x, y) = pos; let srel_loc = pos - focus.1.to_f64();
let (sx, sy) = focus.1; wl_tool.motion(srel_loc.x, srel_loc.y);
wl_tool.motion(x - sx, y - sy);
if let Some(pressure) = self.pending_pressure.take() { if let Some(pressure) = self.pending_pressure.take() {
wl_tool.pressure((pressure * 65535.0).round() as u32); wl_tool.pressure((pressure * 65535.0).round() as u32);
@ -271,7 +272,9 @@ impl TabletToolHandle {
compositor::with_states(&surface, |states| { compositor::with_states(&surface, |states| {
states.data_map.insert_if_missing_threadsafe(|| { states.data_map.insert_if_missing_threadsafe(|| {
Mutex::new(CursorImageAttributes { hotspot: (0, 0) }) Mutex::new(CursorImageAttributes {
hotspot: (0, 0).into(),
})
}); });
states states
.data_map .data_map
@ -279,7 +282,7 @@ impl TabletToolHandle {
.unwrap() .unwrap()
.lock() .lock()
.unwrap() .unwrap()
.hotspot = (hotspot_x, hotspot_y); .hotspot = (hotspot_x, hotspot_y).into();
}) })
.unwrap(); .unwrap();
@ -356,8 +359,8 @@ impl TabletToolHandle {
/// origin in the global compositor space. /// origin in the global compositor space.
pub fn proximity_in( pub fn proximity_in(
&self, &self,
pos: (f64, f64), pos: Point<f64, Logical>,
focus: (WlSurface, (f64, f64)), focus: (WlSurface, Point<i32, Logical>),
tablet: &TabletHandle, tablet: &TabletHandle,
serial: Serial, serial: Serial,
time: u32, time: u32,
@ -395,8 +398,8 @@ impl TabletToolHandle {
/// of proximity_in/proximity_out events. /// of proximity_in/proximity_out events.
pub fn motion( pub fn motion(
&self, &self,
pos: (f64, f64), pos: Point<f64, Logical>,
focus: Option<(WlSurface, (f64, f64))>, focus: Option<(WlSurface, Point<i32, Logical>)>,
tablet: &TabletHandle, tablet: &TabletHandle,
serial: Serial, serial: Serial,
time: u32, time: u32,