Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle buffer offset #230

Merged
merged 1 commit into from
Sep 30, 2024
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
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