image-copy: Move duplicate code to a cursor_capture_constraints()
This ensures we avoid advertising a `0,0` buffer size (which will protocol error to actually allocate), and avoids defining the supported formats for cursor capture buffers in a bunch of places.
This commit is contained in:
parent
27956e6e00
commit
2648aea0df
3 changed files with 68 additions and 82 deletions
|
|
@ -11,7 +11,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
input::gestures::{GestureState, SwipeAction},
|
input::gestures::{GestureState, SwipeAction},
|
||||||
shell::{
|
shell::{
|
||||||
CursorGeometry, LastModifierChange, SeatExt, Trigger,
|
LastModifierChange, SeatExt, Trigger,
|
||||||
focus::{
|
focus::{
|
||||||
Stage, render_input_order,
|
Stage, render_input_order,
|
||||||
target::{KeyboardFocusTarget, PointerFocusTarget},
|
target::{KeyboardFocusTarget, PointerFocusTarget},
|
||||||
|
|
@ -25,7 +25,8 @@ use crate::{
|
||||||
},
|
},
|
||||||
utils::{prelude::*, quirks::workspace_overview_is_open},
|
utils::{prelude::*, quirks::workspace_overview_is_open},
|
||||||
wayland::handlers::{
|
wayland::handlers::{
|
||||||
image_copy_capture::SessionHolder, xwayland_keyboard_grab::XWaylandGrabSeat,
|
image_copy_capture::{SessionHolder, cursor_capture_constraints},
|
||||||
|
xwayland_keyboard_grab::XWaylandGrabSeat,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use calloop::{
|
use calloop::{
|
||||||
|
|
@ -60,15 +61,12 @@ use smithay::{
|
||||||
output::Output,
|
output::Output,
|
||||||
reexports::{
|
reexports::{
|
||||||
input::Device as InputDevice,
|
input::Device as InputDevice,
|
||||||
wayland_server::{
|
wayland_server::{Resource as _, protocol::wl_surface::WlSurface},
|
||||||
Resource as _,
|
|
||||||
protocol::{wl_shm::Format as ShmFormat, wl_surface::WlSurface},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
utils::{Logical, Point, Rectangle, SERIAL_COUNTER, Serial, Size},
|
utils::{Logical, Point, Rectangle, SERIAL_COUNTER, Serial},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::CompositorHandler,
|
compositor::CompositorHandler,
|
||||||
image_copy_capture::{BufferConstraints, CursorSessionRef},
|
image_copy_capture::CursorSessionRef,
|
||||||
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat,
|
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat,
|
||||||
pointer_constraints::{PointerConstraint, with_pointer_constraint},
|
pointer_constraints::{PointerConstraint, with_pointer_constraint},
|
||||||
seat::WaylandFocus,
|
seat::WaylandFocus,
|
||||||
|
|
@ -651,7 +649,7 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
for session in cursor_sessions_for_output(&shell, &output) {
|
for session in cursor_sessions_for_output(&shell, &output) {
|
||||||
if let Some(CursorGeometry { geometry, hotspot }) = seat.cursor_geometry(
|
if let Some(cursor_geometry) = seat.cursor_geometry(
|
||||||
(position - output_geometry.loc.to_f64())
|
(position - output_geometry.loc.to_f64())
|
||||||
.as_logical()
|
.as_logical()
|
||||||
.to_buffer(
|
.to_buffer(
|
||||||
|
|
@ -661,24 +659,18 @@ impl State {
|
||||||
),
|
),
|
||||||
self.common.clock.now(),
|
self.common.clock.now(),
|
||||||
) {
|
) {
|
||||||
|
let constraints = cursor_capture_constraints(Some(cursor_geometry));
|
||||||
if session
|
if session
|
||||||
.current_constraints()
|
.current_constraints()
|
||||||
.map(|constraint| constraint.size != geometry.size)
|
.map(|current_constraints| {
|
||||||
|
current_constraints.size != constraints.size
|
||||||
|
})
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
{
|
{
|
||||||
let mut cursor_size = geometry.size;
|
session.update_constraints(constraints);
|
||||||
// Client shouldn't try to allocate 0x0 buffer
|
|
||||||
if cursor_size == Size::new(0, 0) {
|
|
||||||
cursor_size = Size::new(1, 1);
|
|
||||||
}
|
|
||||||
session.update_constraints(BufferConstraints {
|
|
||||||
size: cursor_size,
|
|
||||||
shm: vec![ShmFormat::Argb8888],
|
|
||||||
dma: None,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
session.set_cursor_hotspot(hotspot);
|
session.set_cursor_hotspot(cursor_geometry.hotspot);
|
||||||
session.set_cursor_pos(Some(geometry.loc));
|
session.set_cursor_pos(Some(cursor_geometry.geometry.loc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -720,7 +712,7 @@ impl State {
|
||||||
|
|
||||||
let shell = self.common.shell.read();
|
let shell = self.common.shell.read();
|
||||||
for session in cursor_sessions_for_output(&shell, &output) {
|
for session in cursor_sessions_for_output(&shell, &output) {
|
||||||
if let Some(CursorGeometry { geometry, hotspot }) = seat.cursor_geometry(
|
if let Some(cursor_geometry) = seat.cursor_geometry(
|
||||||
(position - output_geometry.loc.to_f64())
|
(position - output_geometry.loc.to_f64())
|
||||||
.as_logical()
|
.as_logical()
|
||||||
.to_buffer(
|
.to_buffer(
|
||||||
|
|
@ -730,24 +722,18 @@ impl State {
|
||||||
),
|
),
|
||||||
self.common.clock.now(),
|
self.common.clock.now(),
|
||||||
) {
|
) {
|
||||||
|
let constraints = cursor_capture_constraints(Some(cursor_geometry));
|
||||||
if session
|
if session
|
||||||
.current_constraints()
|
.current_constraints()
|
||||||
.map(|constraint| constraint.size != geometry.size)
|
.map(|current_constraints| {
|
||||||
|
current_constraints.size != constraints.size
|
||||||
|
})
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
{
|
{
|
||||||
let mut cursor_size = geometry.size;
|
session.update_constraints(constraints);
|
||||||
// Client shouldn't try to allocate 0x0 buffer
|
|
||||||
if cursor_size == Size::new(0, 0) {
|
|
||||||
cursor_size = Size::new(1, 1);
|
|
||||||
}
|
|
||||||
session.update_constraints(BufferConstraints {
|
|
||||||
size: cursor_size,
|
|
||||||
shm: vec![ShmFormat::Argb8888],
|
|
||||||
dma: None,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
session.set_cursor_hotspot(hotspot);
|
session.set_cursor_hotspot(cursor_geometry.hotspot);
|
||||||
session.set_cursor_pos(Some(geometry.loc));
|
session.set_cursor_pos(Some(cursor_geometry.geometry.loc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2482,7 +2468,7 @@ impl State {
|
||||||
|
|
||||||
let output_geometry = output.geometry();
|
let output_geometry = output.geometry();
|
||||||
for session in cursor_sessions_for_output(&shell, &output) {
|
for session in cursor_sessions_for_output(&shell, &output) {
|
||||||
if let Some(CursorGeometry { geometry, hotspot }) = seat.cursor_geometry(
|
if let Some(cursor_geometry) = seat.cursor_geometry(
|
||||||
point.to_buffer(
|
point.to_buffer(
|
||||||
output.current_scale().fractional_scale(),
|
output.current_scale().fractional_scale(),
|
||||||
output.current_transform(),
|
output.current_transform(),
|
||||||
|
|
@ -2490,19 +2476,16 @@ impl State {
|
||||||
),
|
),
|
||||||
self.common.clock.now(),
|
self.common.clock.now(),
|
||||||
) {
|
) {
|
||||||
|
let constraints = cursor_capture_constraints(Some(cursor_geometry));
|
||||||
if session
|
if session
|
||||||
.current_constraints()
|
.current_constraints()
|
||||||
.map(|constraint| constraint.size != geometry.size)
|
.map(|current_constraints| current_constraints.size != constraints.size)
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
{
|
{
|
||||||
session.update_constraints(BufferConstraints {
|
session.update_constraints(constraints);
|
||||||
size: geometry.size,
|
|
||||||
shm: vec![ShmFormat::Argb8888],
|
|
||||||
dma: None,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
session.set_cursor_hotspot(hotspot);
|
session.set_cursor_hotspot(cursor_geometry.hotspot);
|
||||||
session.set_cursor_pos(Some(geometry.loc));
|
session.set_cursor_pos(Some(cursor_geometry.geometry.loc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,10 @@ pub use self::render::*;
|
||||||
use self::user_data::*;
|
use self::user_data::*;
|
||||||
pub use self::user_data::{FrameHolder, ImageCopySessions, SessionData, SessionHolder};
|
pub use self::user_data::{FrameHolder, ImageCopySessions, SessionData, SessionHolder};
|
||||||
|
|
||||||
|
fn default_cursor_size() -> Size<i32, BufferCoords> {
|
||||||
|
Size::new(64, 64)
|
||||||
|
}
|
||||||
|
|
||||||
fn seat_for_wl_pointer<'a>(shell: &'a Shell, pointer: &WlPointer) -> Option<&'a Seat<State>> {
|
fn seat_for_wl_pointer<'a>(shell: &'a Shell, pointer: &WlPointer) -> Option<&'a Seat<State>> {
|
||||||
let pointer_handle = PointerHandle::<State>::from_resource(pointer)?;
|
let pointer_handle = PointerHandle::<State>::from_resource(pointer)?;
|
||||||
shell
|
shell
|
||||||
|
|
@ -53,6 +57,24 @@ fn seat_for_wl_pointer<'a>(shell: &'a Shell, pointer: &WlPointer) -> Option<&'a
|
||||||
.find(|seat| seat.get_pointer().is_some_and(|p| p == pointer_handle))
|
.find(|seat| seat.get_pointer().is_some_and(|p| p == pointer_handle))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cursor_capture_constraints(cursor_geometry: Option<CursorGeometry>) -> BufferConstraints {
|
||||||
|
let size = if let Some(cursor_geometry) = cursor_geometry {
|
||||||
|
let mut size = cursor_geometry.geometry.size;
|
||||||
|
// Client shouldn't try to allocate 0x0 buffer
|
||||||
|
if size == Size::new(0, 0) {
|
||||||
|
size = Size::new(1, 1);
|
||||||
|
}
|
||||||
|
size
|
||||||
|
} else {
|
||||||
|
default_cursor_size()
|
||||||
|
};
|
||||||
|
BufferConstraints {
|
||||||
|
size,
|
||||||
|
shm: vec![ShmFormat::Argb8888],
|
||||||
|
dma: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ImageCopyCaptureHandler for State {
|
impl ImageCopyCaptureHandler for State {
|
||||||
fn image_copy_capture_state(&mut self) -> &mut ImageCopyCaptureState {
|
fn image_copy_capture_state(&mut self) -> &mut ImageCopyCaptureState {
|
||||||
&mut self.common.image_copy_capture_state
|
&mut self.common.image_copy_capture_state
|
||||||
|
|
@ -86,19 +108,8 @@ impl ImageCopyCaptureHandler for State {
|
||||||
) -> Option<BufferConstraints> {
|
) -> Option<BufferConstraints> {
|
||||||
let shell = self.common.shell.read();
|
let shell = self.common.shell.read();
|
||||||
let seat = seat_for_wl_pointer(&shell, pointer)?;
|
let seat = seat_for_wl_pointer(&shell, pointer)?;
|
||||||
let size = if let Some(CursorGeometry { geometry, .. }) =
|
let cursor_geometry = seat.cursor_geometry((0.0, 0.0), self.common.clock.now());
|
||||||
seat.cursor_geometry((0.0, 0.0), self.common.clock.now())
|
Some(cursor_capture_constraints(cursor_geometry))
|
||||||
{
|
|
||||||
geometry.size
|
|
||||||
} else {
|
|
||||||
Size::from((64, 64))
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(BufferConstraints {
|
|
||||||
size,
|
|
||||||
shm: vec![ShmFormat::Argb8888],
|
|
||||||
dma: None,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_session(&mut self, session: Session) {
|
fn new_session(&mut self, session: Session) {
|
||||||
|
|
@ -165,12 +176,12 @@ impl ImageCopyCaptureHandler for State {
|
||||||
{
|
{
|
||||||
(geometry.size, hotspot)
|
(geometry.size, hotspot)
|
||||||
} else {
|
} else {
|
||||||
(Size::from((64, 64)), Point::from((0, 0)))
|
(default_cursor_size(), Point::from((0, 0)))
|
||||||
};
|
};
|
||||||
|
|
||||||
(pointer_loc, pointer_size, hotspot)
|
(pointer_loc, pointer_size, hotspot)
|
||||||
} else {
|
} else {
|
||||||
(Point::new(0, 0), Size::from((64, 64)), Point::from((0, 0)))
|
(Point::new(0, 0), default_cursor_size(), Point::from((0, 0)))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,16 +20,14 @@ use smithay::{
|
||||||
desktop::space::SpaceElement,
|
desktop::space::SpaceElement,
|
||||||
input::Seat,
|
input::Seat,
|
||||||
output::{Output, OutputNoMode},
|
output::{Output, OutputNoMode},
|
||||||
reexports::wayland_server::protocol::{wl_buffer::WlBuffer, wl_shm::Format as ShmFormat},
|
reexports::wayland_server::protocol::wl_buffer::WlBuffer,
|
||||||
utils::{
|
utils::{
|
||||||
Buffer as BufferCoords, IsAlive, Logical, Physical, Point, Rectangle, Scale, Size,
|
Buffer as BufferCoords, IsAlive, Logical, Physical, Point, Rectangle, Scale, Size,
|
||||||
Transform,
|
Transform,
|
||||||
},
|
},
|
||||||
wayland::{
|
wayland::{
|
||||||
dmabuf::get_dmabuf,
|
dmabuf::get_dmabuf,
|
||||||
image_copy_capture::{
|
image_copy_capture::{CaptureFailureReason, CursorSessionRef, Frame, SessionRef},
|
||||||
BufferConstraints, CaptureFailureReason, CursorSessionRef, Frame, SessionRef,
|
|
||||||
},
|
|
||||||
seat::WaylandFocus,
|
seat::WaylandFocus,
|
||||||
shm::{shm_format_to_fourcc, with_buffer_contents, with_buffer_contents_mut},
|
shm::{shm_format_to_fourcc, with_buffer_contents, with_buffer_contents_mut},
|
||||||
},
|
},
|
||||||
|
|
@ -45,7 +43,7 @@ use crate::{
|
||||||
render_workspace,
|
render_workspace,
|
||||||
wayland::SurfaceRenderElement,
|
wayland::SurfaceRenderElement,
|
||||||
},
|
},
|
||||||
shell::{CosmicMappedRenderElement, CosmicSurface, CursorGeometry, WorkspaceRenderElement},
|
shell::{CosmicMappedRenderElement, CosmicSurface, WorkspaceRenderElement},
|
||||||
state::{Common, KmsNodes, State},
|
state::{Common, KmsNodes, State},
|
||||||
utils::prelude::{PointExt, PointGlobalExt, RectExt, RectLocalExt, SeatExt},
|
utils::prelude::{PointExt, PointGlobalExt, RectExt, RectLocalExt, SeatExt},
|
||||||
wayland::{
|
wayland::{
|
||||||
|
|
@ -56,7 +54,9 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{super::data_device::get_dnd_icon, user_data::SessionHolder};
|
use super::{
|
||||||
|
super::data_device::get_dnd_icon, cursor_capture_constraints, user_data::SessionHolder,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn render_element_buffers<R, E>(
|
pub fn render_element_buffers<R, E>(
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
|
|
@ -802,25 +802,17 @@ pub fn render_cursor_to_buffer(
|
||||||
seat: &Seat<State>,
|
seat: &Seat<State>,
|
||||||
) {
|
) {
|
||||||
let buffer = frame.buffer();
|
let buffer = frame.buffer();
|
||||||
let mut cursor_size = seat
|
let cursor_geometry = seat.cursor_geometry((0.0, 0.0), state.common.clock.now());
|
||||||
.cursor_geometry((0.0, 0.0), state.common.clock.now())
|
let constraints = cursor_capture_constraints(cursor_geometry);
|
||||||
.map(|CursorGeometry { geometry, .. }| geometry.size)
|
|
||||||
.unwrap_or_else(|| Size::from((64, 64)));
|
|
||||||
let buffer_size = buffer_dimensions(&buffer).unwrap();
|
let buffer_size = buffer_dimensions(&buffer).unwrap();
|
||||||
// Client shouldn't try to allocate 0x0 buffer
|
if buffer_size != constraints.size {
|
||||||
if cursor_size == Size::new(0, 0) {
|
session.update_constraints(constraints.clone());
|
||||||
cursor_size = Size::new(1, 1);
|
|
||||||
}
|
|
||||||
if buffer_size != cursor_size {
|
|
||||||
let constraints = BufferConstraints {
|
|
||||||
size: cursor_size,
|
|
||||||
shm: vec![ShmFormat::Argb8888],
|
|
||||||
dma: None,
|
|
||||||
};
|
|
||||||
session.update_constraints(constraints);
|
|
||||||
if let Some(data) = session.user_data().get::<SessionData>() {
|
if let Some(data) = session.user_data().get::<SessionData>() {
|
||||||
*data.lock().unwrap() = SessionUserData::new(OutputDamageTracker::new(
|
*data.lock().unwrap() = SessionUserData::new(OutputDamageTracker::new(
|
||||||
cursor_size.to_logical(1, Transform::Normal).to_physical(1),
|
constraints
|
||||||
|
.size
|
||||||
|
.to_logical(1, Transform::Normal)
|
||||||
|
.to_physical(1),
|
||||||
1.0,
|
1.0,
|
||||||
Transform::Normal,
|
Transform::Normal,
|
||||||
));
|
));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue