Introduce Logical/Physical Point/Rectangle
This commit is contained in:
parent
aa647c636e
commit
54ea0d3a74
|
@ -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,13 +162,12 @@ 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,
|
||||||
) {
|
) {
|
||||||
result = Err(err.into());
|
result = Err(err.into());
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,24 +19,28 @@
|
||||||
//! 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::{
|
||||||
input::{
|
context::GlAttributes, display::EGLDisplay, native, EGLContext, EGLSurface, Error as EGLError,
|
||||||
Axis, AxisSource, ButtonState, Device, DeviceCapability, Event as BackendEvent, InputBackend,
|
},
|
||||||
InputEvent, KeyState, KeyboardKeyEvent, MouseButton, PointerAxisEvent, PointerButtonEvent,
|
input::{
|
||||||
PointerMotionAbsoluteEvent, TouchCancelEvent, TouchDownEvent, TouchMotionEvent, TouchSlot,
|
Axis, AxisSource, ButtonState, Device, DeviceCapability, Event as BackendEvent, InputBackend,
|
||||||
TouchUpEvent, UnusedEvent,
|
InputEvent, KeyState, KeyboardKeyEvent, MouseButton, PointerAxisEvent, PointerButtonEvent,
|
||||||
},
|
PointerMotionAbsoluteEvent, TouchCancelEvent, TouchDownEvent, TouchMotionEvent, TouchSlot,
|
||||||
renderer::{
|
TouchUpEvent, UnusedEvent,
|
||||||
gles2::{Gles2Error, Gles2Frame, Gles2Renderer},
|
},
|
||||||
Bind, Renderer, Transform, Unbind,
|
renderer::{
|
||||||
|
gles2::{Gles2Error, Gles2Frame, Gles2Renderer},
|
||||||
|
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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)]
|
||||||
|
|
|
@ -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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 } => {
|
||||||
|
|
|
@ -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))),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,12 @@ use wayland_server::{
|
||||||
Main,
|
Main,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::wayland::{
|
use crate::{
|
||||||
seat::{AxisFrame, GrabStartData, PointerGrab, PointerInnerHandle, Seat},
|
utils::{Logical, Point},
|
||||||
Serial,
|
wayland::{
|
||||||
|
seat::{AxisFrame, GrabStartData, PointerGrab, PointerInnerHandle, Seat},
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue