feat: compose client cursor surfaces
This commit is contained in:
1 parent
bf10a2f838
commit
ee9da5d8c9
5 files changed
+67
-11
No files matched your search
@@ -50,10 +50,10 @@ impl CompositorHandler for Ferese {
|
||||
if let Some(window) = window {
|
||||
window.on_commit();
|
||||
self.record_client_commit(&window);
|
||||
crate::backends::direct::render_all(self);
|
||||
}
|
||||
}
|
||||
xdg_shell::handle_commit(&mut self.popups, &mut self.space, surface);
|
||||
crate::backends::direct::render_all(self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,10 @@ impl SeatHandler for Ferese {
|
||||
&mut self.seat_state
|
||||
}
|
||||
|
||||
fn cursor_image(&mut self, _seat: &Seat<Self>, _image: CursorImageStatus) {}
|
||||
fn cursor_image(&mut self, _seat: &Seat<Self>, image: CursorImageStatus) {
|
||||
self.cursor_status = image;
|
||||
crate::backends::direct::render_all(self);
|
||||
}
|
||||
|
||||
fn focus_changed(&mut self, seat: &Seat<Self>, focused: Option<&WlSurface>) {
|
||||
let client = focused.and_then(|surface| self.display_handle.get_client(surface.id()).ok());
|
||||
|
||||
@@ -132,6 +132,7 @@ impl Ferese {
|
||||
);
|
||||
pointer.frame(self);
|
||||
self.activate_focused_pointer_constraint(&pointer);
|
||||
crate::backends::direct::render_all(self);
|
||||
}
|
||||
InputEvent::PointerMotion { event, .. } => {
|
||||
let pointer = self.seat.get_pointer().expect("seat has a pointer");
|
||||
@@ -167,6 +168,7 @@ impl Ferese {
|
||||
);
|
||||
pointer.frame(self);
|
||||
self.activate_focused_pointer_constraint(&pointer);
|
||||
crate::backends::direct::render_all(self);
|
||||
}
|
||||
InputEvent::PointerButton { event, .. } => {
|
||||
let pointer = self.seat.get_pointer().expect("seat has a pointer");
|
||||
|
||||
@@ -13,7 +13,7 @@ use ferese_layout::{Axis, Direction, GapConfig, LayoutResult, Rect, SizeConstrai
|
||||
use smithay::{
|
||||
backend::drm::DrmEventTime,
|
||||
desktop::{PopupManager, Space, Window, WindowSurfaceType},
|
||||
input::{Seat, SeatState},
|
||||
input::{Seat, SeatState, pointer::CursorImageStatus},
|
||||
reexports::{
|
||||
calloop::{EventLoop, Interest, LoopSignal, Mode, PostAction, generic::Generic},
|
||||
wayland_protocols::xdg::shell::server::xdg_toplevel,
|
||||
@@ -51,6 +51,7 @@ pub struct Ferese {
|
||||
pub window_ids: HashMap<Window, WindowId>,
|
||||
pub window_geometry: HashMap<WindowId, WindowGeometry>,
|
||||
pub focused_window: Option<WindowId>,
|
||||
pub cursor_status: CursorImageStatus,
|
||||
pub intercepted_keys: HashSet<smithay::input::keyboard::Keycode>,
|
||||
pub direct_backend: Option<crate::backends::direct::DirectBackendState>,
|
||||
next_window_id: u64,
|
||||
@@ -111,6 +112,7 @@ impl Ferese {
|
||||
window_ids: HashMap::new(),
|
||||
window_geometry: HashMap::new(),
|
||||
focused_window: None,
|
||||
cursor_status: CursorImageStatus::default_named(),
|
||||
intercepted_keys: HashSet::new(),
|
||||
direct_backend: None,
|
||||
next_window_id: 1,
|
||||
|
||||
+57
-8
@@ -8,9 +8,10 @@ use smithay::{
|
||||
renderer::{
|
||||
damage::OutputDamageTracker,
|
||||
element::{
|
||||
surface::WaylandSurfaceRenderElement,
|
||||
Kind as RenderElementKind,
|
||||
surface::{WaylandSurfaceRenderElement, render_elements_from_surface_tree},
|
||||
utils::{
|
||||
ConstrainAlign, ConstrainScaleBehavior, CropRenderElement,
|
||||
ConstrainAlign, ConstrainScaleBehavior, CropRenderElement, Relocate,
|
||||
RelocateRenderElement, RescaleRenderElement,
|
||||
},
|
||||
},
|
||||
@@ -22,11 +23,12 @@ use smithay::{
|
||||
space::{ConstrainBehavior, ConstrainReference, constrain_space_element},
|
||||
utils::OutputPresentationFeedback,
|
||||
},
|
||||
input::pointer::{CursorImageStatus, CursorImageSurfaceData},
|
||||
output::{Mode, Output, PhysicalProperties, Scale, Subpixel},
|
||||
reexports::calloop::EventLoop,
|
||||
reexports::wayland_protocols::wp::presentation_time::server::wp_presentation_feedback::Kind,
|
||||
utils::{Clock, Logical, Monotonic, Rectangle, Transform},
|
||||
wayland::presentation::Refresh,
|
||||
reexports::wayland_protocols::wp::presentation_time::server::wp_presentation_feedback::Kind as PresentationKind,
|
||||
utils::{Clock, Logical, Monotonic, Physical, Point, Rectangle, Transform},
|
||||
wayland::{compositor::with_states, presentation::Refresh},
|
||||
};
|
||||
|
||||
use crate::Ferese;
|
||||
@@ -98,7 +100,7 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
||||
window.take_presentation_feedback(
|
||||
&mut presentation,
|
||||
|_, _| Some(output.clone()),
|
||||
|_, _| Kind::Vsync,
|
||||
|_, _| PresentationKind::Vsync,
|
||||
);
|
||||
});
|
||||
let rendered = (|| -> Result<(), Box<dyn Error>> {
|
||||
@@ -126,7 +128,7 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
||||
clock.now(),
|
||||
Refresh::fixed(Duration::from_nanos(1_000_000_000 / 60)),
|
||||
sequence,
|
||||
Kind::Vsync,
|
||||
PresentationKind::Vsync,
|
||||
);
|
||||
state.space.elements().for_each(|window| {
|
||||
window.send_frame(
|
||||
@@ -159,6 +161,8 @@ pub(crate) fn animated_window_elements(
|
||||
};
|
||||
let scale = output.current_scale().fractional_scale();
|
||||
|
||||
let mut elements = cursor_elements(state, renderer, output_geometry, scale);
|
||||
elements.extend(
|
||||
state
|
||||
.space
|
||||
.elements()
|
||||
@@ -197,7 +201,52 @@ pub(crate) fn animated_window_elements(
|
||||
},
|
||||
))
|
||||
})
|
||||
.flatten()
|
||||
.flatten(),
|
||||
);
|
||||
elements
|
||||
}
|
||||
|
||||
fn cursor_elements(
|
||||
state: &Ferese,
|
||||
renderer: &mut GlesRenderer,
|
||||
output_geometry: Rectangle<i32, Logical>,
|
||||
scale: f64,
|
||||
) -> Vec<AnimatedWindowRenderElement> {
|
||||
let CursorImageStatus::Surface(surface) = &state.cursor_status else {
|
||||
return Vec::new();
|
||||
};
|
||||
let Some(pointer) = state.seat.get_pointer() else {
|
||||
return Vec::new();
|
||||
};
|
||||
let hotspot = with_states(surface, |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<CursorImageSurfaceData>()
|
||||
.map(|attributes| attributes.lock().unwrap().hotspot)
|
||||
.unwrap_or_default()
|
||||
});
|
||||
let logical_location =
|
||||
pointer.current_location() - output_geometry.loc.to_f64() - hotspot.to_f64();
|
||||
let physical_location = logical_location.to_physical_precise_round(scale);
|
||||
let output_crop =
|
||||
Rectangle::<i32, Logical>::from_size(output_geometry.size).to_physical_precise_round(scale);
|
||||
let origin = Point::<i32, Physical>::default();
|
||||
|
||||
render_elements_from_surface_tree::<GlesRenderer, WaylandSurfaceRenderElement<GlesRenderer>>(
|
||||
renderer,
|
||||
surface,
|
||||
physical_location,
|
||||
scale,
|
||||
1.0,
|
||||
RenderElementKind::Cursor,
|
||||
)
|
||||
.into_iter()
|
||||
.filter_map(|element| {
|
||||
let element = RescaleRenderElement::from_element(element, origin, 1.0);
|
||||
let element = RelocateRenderElement::from_element(element, origin, Relocate::Relative);
|
||||
|
||||
CropRenderElement::from_element(element, scale, output_crop)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user