Skip to content

Commit

Permalink
handle role specific buffer offset
Browse files Browse the repository at this point in the history
  • Loading branch information
cmeissl authored and YaLTeR committed Sep 30, 2024
1 parent 80bb0d5 commit 42b898d
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 38 deletions.
12 changes: 2 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 41 additions & 2 deletions src/handlers/compositor.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::hash_map::Entry;

use smithay::backend::renderer::utils::{on_commit_buffer_handler, with_renderer_surface_state};
use smithay::input::pointer::CursorImageStatus;
use smithay::input::pointer::{CursorImageStatus, CursorImageSurfaceData};
use smithay::reexports::calloop::Interest;
use smithay::reexports::wayland_server::protocol::wl_buffer;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
Expand Down Expand Up @@ -297,13 +297,52 @@ impl CompositorHandler for State {
&self.niri.cursor_manager.cursor_image(),
CursorImageStatus::Surface(s) if s == &root_surface
) {
// In case the cursor surface has been committed handle the role specific
// buffer offset by applying the offset on the cursor image hotspot
if surface == &root_surface {
with_states(surface, |states| {
let cursor_image_attributes = states.data_map.get::<CursorImageSurfaceData>();

if let Some(mut cursor_image_attributes) =
cursor_image_attributes.map(|attrs| attrs.lock().unwrap())
{
let buffer_delta = states
.cached_state
.get::<SurfaceAttributes>()
.current()
.buffer_delta
.take();
if let Some(buffer_delta) = buffer_delta {
cursor_image_attributes.hotspot -= buffer_delta;
}
}
});
}

// FIXME: granular redraws for cursors.
self.niri.queue_redraw_all();
return;
}

// This might be a DnD icon surface.
if self.niri.dnd_icon.as_ref() == Some(&root_surface) {
if matches!(&self.niri.dnd_icon, Some(icon) if icon.surface == root_surface) {
let dnd_icon = self.niri.dnd_icon.as_mut().unwrap();

// In case the dnd surface has been committed handle the role specific
// buffer offset by applying the offset on the dnd icon offset
if surface == &dnd_icon.surface {
with_states(&dnd_icon.surface, |states| {
let buffer_delta = states
.cached_state
.get::<SurfaceAttributes>()
.current()
.buffer_delta
.take()
.unwrap_or_default();
dnd_icon.offset += buffer_delta;
});
}

// FIXME: granular redraws for cursors.
self.niri.queue_redraw_all();
return;
Expand Down
26 changes: 22 additions & 4 deletions src/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ use smithay::backend::allocator::dmabuf::Dmabuf;
use smithay::backend::drm::DrmNode;
use smithay::backend::input::TabletToolDescriptor;
use smithay::desktop::{PopupKind, PopupManager};
use smithay::input::pointer::{CursorIcon, CursorImageStatus, PointerHandle};
use smithay::input::pointer::{
CursorIcon, CursorImageStatus, CursorImageSurfaceData, PointerHandle,
};
use smithay::input::{keyboard, Seat, SeatHandler, SeatState};
use smithay::output::Output;
use smithay::reexports::rustix::fs::{fcntl_setfl, OFlags};
Expand All @@ -22,7 +24,7 @@ use smithay::reexports::wayland_server::protocol::wl_data_source::WlDataSource;
use smithay::reexports::wayland_server::protocol::wl_output::WlOutput;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::reexports::wayland_server::Resource;
use smithay::utils::{Logical, Rectangle, Size};
use smithay::utils::{Logical, Point, Rectangle, Size};
use smithay::wayland::compositor::with_states;
use smithay::wayland::dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier};
use smithay::wayland::drm_lease::{
Expand Down Expand Up @@ -64,7 +66,7 @@ use smithay::{
};

pub use crate::handlers::xdg_shell::KdeDecorationsModeState;
use crate::niri::{ClientState, State};
use crate::niri::{ClientState, DndIcon, State};
use crate::protocols::foreign_toplevel::{
self, ForeignToplevelHandler, ForeignToplevelManagerState,
};
Expand Down Expand Up @@ -225,7 +227,23 @@ impl ClientDndGrabHandler for State {
icon: Option<WlSurface>,
_seat: Seat<Self>,
) {
self.niri.dnd_icon = icon;
let offset = if let CursorImageStatus::Surface(ref surface) =
self.niri.cursor_manager.cursor_image()
{
with_states(surface, |states| {
let hotspot = states
.data_map
.get::<CursorImageSurfaceData>()
.unwrap()
.lock()
.unwrap()
.hotspot;
Point::from((-hotspot.x, -hotspot.y))
})
} else {
(0, 0).into()
};
self.niri.dnd_icon = icon.map(|surface| DndIcon { surface, offset });
// FIXME: more granular
self.niri.queue_redraw_all();
}
Expand Down
14 changes: 7 additions & 7 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use niri_ipc::LayoutSwitchTarget;
use smithay::backend::input::{
AbsolutePositionEvent, Axis, AxisSource, ButtonState, Device, DeviceCapability, Event,
GestureBeginEvent, GestureEndEvent, GesturePinchUpdateEvent as _, GestureSwipeUpdateEvent as _,
InputBackend, InputEvent, KeyState, KeyboardKeyEvent, MouseButton, PointerAxisEvent,
InputBackend, InputEvent, KeyState, KeyboardKeyEvent, Keycode, MouseButton, PointerAxisEvent,
PointerButtonEvent, PointerMotionEvent, ProximityState, TabletToolButtonEvent, TabletToolEvent,
TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, TouchEvent,
};
Expand Down Expand Up @@ -2305,10 +2305,10 @@ impl State {
/// to them from being delivered.
#[allow(clippy::too_many_arguments)]
fn should_intercept_key(
suppressed_keys: &mut HashSet<u32>,
suppressed_keys: &mut HashSet<Keycode>,
bindings: &Binds,
comp_mod: CompositorMod,
key_code: u32,
key_code: Keycode,
modified: Keysym,
raw: Option<Keysym>,
pressed: bool,
Expand Down Expand Up @@ -2754,8 +2754,8 @@ mod tests {
// The key_code we pick is arbitrary, the only thing
// that matters is that they are different between cases.

let close_key_code = close_keysym.into();
let close_key_event = |suppr: &mut HashSet<u32>, mods: ModifiersState, pressed| {
let close_key_code = Keycode::from(close_keysym.raw() + 8u32);
let close_key_event = |suppr: &mut HashSet<Keycode>, mods: ModifiersState, pressed| {
should_intercept_key(
suppr,
&bindings,
Expand All @@ -2771,12 +2771,12 @@ mod tests {
};

// Key event with the code which can't trigger any action.
let none_key_event = |suppr: &mut HashSet<u32>, mods: ModifiersState, pressed| {
let none_key_event = |suppr: &mut HashSet<Keycode>, mods: ModifiersState, pressed| {
should_intercept_key(
suppr,
&bindings,
comp_mod,
Keysym::l.into(),
Keycode::from(Keysym::l.raw() + 8),
Keysym::l,
Some(Keysym::l),
pressed,
Expand Down
40 changes: 25 additions & 15 deletions src/niri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use niri_config::{
DEFAULT_BACKGROUND_COLOR,
};
use smithay::backend::allocator::Fourcc;
use smithay::backend::input::Keycode;
use smithay::backend::renderer::damage::OutputDamageTracker;
use smithay::backend::renderer::element::memory::MemoryRenderBufferRenderElement;
use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
Expand Down Expand Up @@ -248,7 +249,7 @@ pub struct Niri {

pub seat: Seat<State>,
/// Scancodes of the keys to suppress.
pub suppressed_keys: HashSet<u32>,
pub suppressed_keys: HashSet<Keycode>,
pub bind_cooldown_timers: HashMap<Key, RegistrationToken>,
pub bind_repeat_timer: Option<RegistrationToken>,
pub keyboard_focus: KeyboardFocus,
Expand All @@ -259,7 +260,7 @@ pub struct Niri {
pub cursor_manager: CursorManager,
pub cursor_texture_cache: CursorTextureCache,
pub cursor_shape_manager_state: CursorShapeManagerState,
pub dnd_icon: Option<WlSurface>,
pub dnd_icon: Option<DndIcon>,
pub pointer_focus: PointerFocus,
/// Whether the pointer is hidden, for example due to a previous touch input.
///
Expand Down Expand Up @@ -304,6 +305,12 @@ pub struct Niri {
pub mapped_cast_output: HashMap<Window, Output>,
}

#[derive(Debug)]
pub struct DndIcon {
pub surface: WlSurface,
pub offset: Point<i32, Logical>,
}

pub struct OutputState {
pub global: GlobalId,
pub frame_clock: FrameClock,
Expand Down Expand Up @@ -2588,8 +2595,8 @@ impl Niri {

let output_scale = Scale::from(output.current_scale().fractional_scale());

let (mut pointer_elements, pointer_pos) = match render_cursor {
RenderCursor::Hidden => (vec![], pointer_pos.to_physical_precise_round(output_scale)),
let mut pointer_elements = match render_cursor {
RenderCursor::Hidden => vec![],
RenderCursor::Surface { surface, hotspot } => {
let pointer_pos =
(pointer_pos - hotspot.to_f64()).to_physical_precise_round(output_scale);
Expand All @@ -2603,7 +2610,7 @@ impl Niri {
Kind::Cursor,
);

(pointer_elements, pointer_pos)
pointer_elements
}
RenderCursor::Named {
icon,
Expand All @@ -2619,7 +2626,7 @@ impl Niri {
let mut pointer_elements = vec![];
let pointer_element = match MemoryRenderBufferRenderElement::from_buffer(
renderer,
pointer_pos.to_f64(),
pointer_pos,
&texture,
None,
None,
Expand All @@ -2636,14 +2643,16 @@ impl Niri {
pointer_elements.push(OutputRenderElements::NamedPointer(element));
}

(pointer_elements, pointer_pos)
pointer_elements
}
};

if let Some(dnd_icon) = &self.dnd_icon {
if let Some(dnd_icon) = self.dnd_icon.as_ref() {
let pointer_pos =
(pointer_pos + dnd_icon.offset.to_f64()).to_physical_precise_round(output_scale);
pointer_elements.extend(render_elements_from_surface_tree(
renderer,
dnd_icon,
&dnd_icon.surface,
pointer_pos,
output_scale,
1.,
Expand Down Expand Up @@ -2684,6 +2693,7 @@ impl Niri {
let dnd = self
.dnd_icon
.as_ref()
.map(|icon| &icon.surface)
.map(|surface| (surface, bbox_from_surface_tree(surface, surface_pos)));

// FIXME we basically need to pick the largest scale factor across the overlapping
Expand Down Expand Up @@ -2745,7 +2755,7 @@ impl Niri {
}
cursor_image => {
// There's no cursor surface, but there might be a DnD icon.
let Some(surface) = &self.dnd_icon else {
let Some(surface) = self.dnd_icon.as_ref().map(|icon| &icon.surface) else {
return;
};

Expand Down Expand Up @@ -3267,7 +3277,7 @@ impl Niri {
);
}

if let Some(surface) = &self.dnd_icon {
if let Some(surface) = self.dnd_icon.as_ref().map(|icon| &icon.surface) {
with_surface_tree_downward(
surface,
(),
Expand Down Expand Up @@ -3405,7 +3415,7 @@ impl Niri {
);
}

if let Some(surface) = &self.dnd_icon {
if let Some(surface) = self.dnd_icon.as_ref().map(|icon| &icon.surface) {
send_dmabuf_feedback_surface_tree(
surface,
output,
Expand Down Expand Up @@ -3507,7 +3517,7 @@ impl Niri {
);
}

if let Some(surface) = &self.dnd_icon {
if let Some(surface) = self.dnd_icon.as_ref().map(|icon| &icon.surface) {
send_frames_surface_tree(
surface,
output,
Expand Down Expand Up @@ -3575,7 +3585,7 @@ impl Niri {
}
}

if let Some(surface) = &self.dnd_icon {
if let Some(surface) = &self.dnd_icon.as_ref().map(|icon| &icon.surface) {
send_frames_surface_tree(
surface,
output,
Expand Down Expand Up @@ -3614,7 +3624,7 @@ impl Niri {
);
}

if let Some(surface) = &self.dnd_icon {
if let Some(surface) = self.dnd_icon.as_ref().map(|icon| &icon.surface) {
take_presentation_feedback_surface_tree(
surface,
&mut feedback,
Expand Down

0 comments on commit 42b898d

Please sign in to comment.