Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
- Work on `ConnectorSavedState`
- Keyboard focus in Idea Xwayland is weird when creating a new Java file

Snowcap
- Add `send_message` for layers
- Snowcap crashes when a window opens and immediately closes because the foreign toplevel handle is no longer valid
- Cursor position when scaled is wrong

Testing
- Test layout mode changing and how it interacts with client fullscreen/maximized requests
Expand Down
22 changes: 17 additions & 5 deletions src/backend/udev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ use smithay::{
protocol::{wl_shm, wl_surface::WlSurface},
},
},
utils::{DeviceFd, Rectangle, Transform},
utils::{DeviceFd, Point, Rectangle, Transform},
wayland::{
dmabuf::{self, DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal},
presentation::Refresh,
Expand Down Expand Up @@ -121,7 +121,7 @@ pub struct Udev {
pub session: LibSeatSession,
udev_dispatcher: Dispatcher<'static, UdevBackend, State>,
display_handle: DisplayHandle,
pub(super) primary_gpu: DrmNode,
pub primary_gpu: DrmNode,
pub(super) gpu_manager: GpuManager<GbmGlesBackend<GlesRenderer, DrmDeviceFd>>,
devices: HashMap<DrmNode, Device>,
/// The global corresponding to the primary gpu
Expand Down Expand Up @@ -1384,6 +1384,11 @@ impl Udev {
return;
}

let Some(output_geo) = pinnacle.space.output_geometry(output) else {
make_idle(&mut surface.render_state, &pinnacle.loop_handle);
return;
};

assert_matches!(
surface.render_state,
RenderState::Scheduled | RenderState::WaitingForEstimatedVblankAndScheduled(_)
Expand Down Expand Up @@ -1419,12 +1424,19 @@ impl Udev {
|| (pinnacle.lock_state.is_locked()
&& output.with_state(|state| state.lock_surface.is_none()));

let scale = output.current_scale().fractional_scale();

let cursor_hotspot = pinnacle
.cursor_state
.cursor_hotspot(pinnacle.clock.now(), scale)
.unwrap_or_default();

let (pointer_render_elements, cursor_ids) = pointer_render_elements(
output,
(pointer_location - output_geo.loc.to_f64()).to_physical_precise_round(scale)
- Point::new(cursor_hotspot.x, cursor_hotspot.y),
scale,
&mut renderer,
&mut pinnacle.cursor_state,
&pinnacle.space,
pointer_location,
pinnacle.dnd_icon.as_ref(),
&pinnacle.clock,
);
Expand Down
16 changes: 12 additions & 4 deletions src/backend/winit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use smithay::{
window::{Icon, WindowAttributes},
},
},
utils::{Rectangle, Transform},
utils::{Point, Rectangle, Transform},
wayland::{dmabuf, presentation::Refresh},
};
use tracing::{debug, error, info, trace, warn};
Expand Down Expand Up @@ -243,12 +243,20 @@ impl Winit {
.map(|ptr| ptr.current_location())
.unwrap_or((0.0, 0.0).into());

let output_loc = pinnacle.space.output_geometry(&self.output).unwrap().loc;
let scale = self.output.current_scale().fractional_scale();

let cursor_hotspot = pinnacle
.cursor_state
.cursor_hotspot(pinnacle.clock.now(), scale)
.unwrap_or_default();

let (pointer_render_elements, _cursor_ids) = pointer_render_elements(
&self.output,
(pointer_location - output_loc.to_f64()).to_physical_precise_round(scale)
- Point::new(cursor_hotspot.x, cursor_hotspot.y),
scale,
self.backend.renderer(),
&mut pinnacle.cursor_state,
&pinnacle.space,
pointer_location,
pinnacle.dnd_icon.as_ref(),
&pinnacle.clock,
);
Expand Down
61 changes: 60 additions & 1 deletion src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use std::{collections::HashMap, rc::Rc};

use anyhow::Context;
use smithay::backend::allocator::Fourcc;
use smithay::utils::IsAlive;
use smithay::desktop::utils::bbox_from_surface_tree;
use smithay::input::pointer::CursorImageSurfaceData;
use smithay::utils::{Buffer, IsAlive, Monotonic, Point, Rectangle, Time};
use smithay::wayland::compositor;
use smithay::{
backend::renderer::element::memory::MemoryRenderBuffer,
input::pointer::{CursorIcon, CursorImageStatus},
Expand Down Expand Up @@ -143,6 +146,62 @@ impl CursorState {
}
}

pub fn cursor_geometry(
&mut self,
time: Time<Monotonic>,
scale: f64,
) -> Option<Rectangle<i32, Buffer>> {
match self.pointer_element() {
PointerElement::Hidden => None,
PointerElement::Named { cursor, size } => {
let image = cursor.image(time.into(), size * scale.ceil() as u32);
let geo = Rectangle::from_size((image.width as i32, image.height as i32).into());
Some(geo)
}
PointerElement::Surface { surface } => {
let geo = bbox_from_surface_tree(&surface, (0, 0));
let buffer_geo = Rectangle::new(
(geo.loc.x, geo.loc.y).into(),
geo.size
.to_f64()
.to_buffer(scale, Transform::Normal)
.to_i32_round(),
);
Some(buffer_geo)
}
}
}

pub fn cursor_hotspot(
&mut self,
time: Time<Monotonic>,
scale: f64,
) -> Option<Point<i32, Buffer>> {
match self.pointer_element() {
PointerElement::Hidden => None,
PointerElement::Named { cursor, size } => {
let image = cursor.image(time.into(), size * scale.ceil() as u32);
let hotspot = (image.xhot as i32, image.yhot as i32);
Some(Point::from(hotspot).downscale(scale.ceil() as i32))
}
PointerElement::Surface { surface } => {
let hotspot: Point<i32, _> = compositor::with_states(&surface, |states| {
states
.data_map
.get::<CursorImageSurfaceData>()
.unwrap()
.lock()
.unwrap()
.hotspot
})
.to_f64()
.upscale(scale)
.to_i32_round();
Some((hotspot.x, hotspot.y).into())
}
}
}

pub fn is_current_cursor_animated(&mut self) -> bool {
let _span = tracy_client::span!("CursorState::is_current_cursor_animated");

Expand Down
5 changes: 5 additions & 0 deletions src/decoration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ impl DecorationSurface {
self.cached_state().z_index
}

pub fn offset(&self) -> Point<i32, Logical> {
let bounds = self.bounds();
Point::new(bounds.left as i32, bounds.top as i32)
}

pub fn bbox(&self) -> Rectangle<i32, Logical> {
bbox_from_surface_tree(self.0.surface.wl_surface(), (0, 0))
}
Expand Down
1 change: 0 additions & 1 deletion src/focus/pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ impl PointerFocusTarget {
});
}

#[cfg(feature = "snowcap")]
if !found {
win.with_state(|state| {
for deco in state.decoration_surfaces.iter() {
Expand Down
Loading
Loading