wl-surface: split interface handlers
This commit is contained in:
parent
d36ec3b7d3
commit
054a3a919f
4 changed files with 649 additions and 636 deletions
|
|
@ -22,6 +22,14 @@ pub mod zwlr_layer_surface_v1;
|
|||
pub mod zwp_idle_inhibitor_v1;
|
||||
pub mod zwp_input_popup_surface_v2;
|
||||
|
||||
mod node;
|
||||
mod presentation;
|
||||
mod request;
|
||||
|
||||
pub use presentation::SyncobjRelease;
|
||||
|
||||
use presentation::{FrameRequest, SurfaceRelease};
|
||||
|
||||
use {
|
||||
crate::{
|
||||
backend::{ButtonState, KeyState},
|
||||
|
|
@ -1008,167 +1016,6 @@ impl WlSurface {
|
|||
|
||||
const MAX_DAMAGE: usize = 32;
|
||||
|
||||
impl WlSurfaceRequestHandler for WlSurface {
|
||||
type Error = WlSurfaceError;
|
||||
|
||||
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.commit_timeline.clear(ClearReason::Destroy);
|
||||
self.unset_dnd_icons();
|
||||
self.unset_cursors();
|
||||
self.ext.get().on_surface_destroy()?;
|
||||
self.destroy_node();
|
||||
{
|
||||
let mut children = self.children.borrow_mut();
|
||||
if let Some(children) = &mut *children {
|
||||
for ss in children.subsurfaces.values() {
|
||||
ss.surface.unset_ext();
|
||||
}
|
||||
}
|
||||
*children = None;
|
||||
}
|
||||
self.buffer.set(None);
|
||||
self.reset_shm_textures();
|
||||
if let Some(xwayland_serial) = self.xwayland_serial.get() {
|
||||
self.client
|
||||
.surfaces_by_xwayland_serial
|
||||
.remove(&xwayland_serial);
|
||||
}
|
||||
self.frame_requests.borrow_mut().clear();
|
||||
self.toplevel.set(None);
|
||||
self.client.remove_obj(self)?;
|
||||
self.idle_inhibitors.clear();
|
||||
self.constraints.take();
|
||||
self.destroyed.set(true);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn attach(&self, req: Attach, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let pending = &mut *self.pending.borrow_mut();
|
||||
if self.version >= OFFSET_SINCE {
|
||||
if req.x != 0 || req.y != 0 {
|
||||
return Err(WlSurfaceError::OffsetInAttach);
|
||||
}
|
||||
} else {
|
||||
pending.offset = (req.x, req.y);
|
||||
}
|
||||
let buf = if req.buffer.is_some() {
|
||||
Some(self.client.lookup(req.buffer)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
pending.buffer = Some(buf.map(|buf| AttachedBuffer {
|
||||
send_release: false,
|
||||
buf,
|
||||
}));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn damage(&self, req: Damage, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.do_damage(req.x, req.y, req.width, req.height, |p| {
|
||||
&mut p.surface_damage
|
||||
})
|
||||
}
|
||||
|
||||
fn frame(&self, req: Frame, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let cb = Rc::new(WlCallback::new(req.callback, &self.client));
|
||||
track!(self.client, cb);
|
||||
self.client.add_client_obj(&cb)?;
|
||||
self.pending
|
||||
.borrow_mut()
|
||||
.frame_request
|
||||
.push(FrameRequest { now: 0, cb });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_opaque_region(
|
||||
&self,
|
||||
region: SetOpaqueRegion,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
let region = if region.region.is_some() {
|
||||
Some(self.client.lookup(region.region)?.region())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.pending.borrow_mut().opaque_region = Some(region);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_input_region(&self, req: SetInputRegion, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let region = if req.region.is_some() {
|
||||
Some(self.client.lookup(req.region)?.region())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.pending.borrow_mut().input_region = Some(region);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn commit(&self, _req: Commit, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let ext = self.ext.get();
|
||||
let pending = &mut *self.pending.borrow_mut();
|
||||
if let Some(Some(buffer)) = &mut pending.buffer
|
||||
&& pending.release_point.is_none()
|
||||
&& pending.sync_file_release.is_none()
|
||||
{
|
||||
buffer.send_release = true;
|
||||
}
|
||||
if let Some(release) = &mut pending.release_point {
|
||||
release.committed = true;
|
||||
}
|
||||
self.verify_syncobj_sync(pending)?;
|
||||
if pending.surface_release.is_not_empty() && not_matches!(pending.buffer, Some(Some(_))) {
|
||||
return Err(WlSurfaceError::SurfaceReleaseWithoutAttach);
|
||||
}
|
||||
if pending.sync_file_release.is_some() && not_matches!(pending.buffer, Some(Some(_))) {
|
||||
return Err(WlSurfaceError::SyncFileReleaseWithoutAttach);
|
||||
}
|
||||
if ext.commit_requested(pending) == CommitAction::ContinueCommit {
|
||||
self.commit_timeline.commit(slf, pending)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_buffer_transform(
|
||||
&self,
|
||||
req: SetBufferTransform,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
let Some(tf) = Transform::from_wl(req.transform) else {
|
||||
return Err(WlSurfaceError::UnknownBufferTransform(req.transform));
|
||||
};
|
||||
self.pending.borrow_mut().transform = Some(tf);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_buffer_scale(&self, req: SetBufferScale, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if req.scale < 1 {
|
||||
return Err(WlSurfaceError::NonPositiveBufferScale);
|
||||
}
|
||||
self.pending.borrow_mut().scale = Some(req.scale);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn damage_buffer(&self, req: DamageBuffer, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.do_damage(req.x, req.y, req.width, req.height, |p| {
|
||||
&mut p.buffer_damage
|
||||
})
|
||||
}
|
||||
|
||||
fn offset(&self, req: Offset, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.pending.borrow_mut().offset = (req.x, req.y);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_release(&self, req: GetRelease, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let cb = Rc::new(WlCallback::new(req.callback, &self.client));
|
||||
track!(self.client, cb);
|
||||
self.client.add_client_obj(&cb)?;
|
||||
let release = SurfaceRelease { cb };
|
||||
self.pending.borrow_mut().surface_release.push(release);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl WlSurface {
|
||||
fn apply_state(self: &Rc<Self>, pending: &mut PendingState) -> Result<(), WlSurfaceError> {
|
||||
|
|
@ -1826,340 +1673,6 @@ impl Object for WlSurface {
|
|||
dedicated_add_obj!(WlSurface, WlSurfaceId, surfaces);
|
||||
|
||||
tree_id!(SurfaceNodeId);
|
||||
impl Node for WlSurface {
|
||||
fn node_id(&self) -> NodeId {
|
||||
self.node_id.into()
|
||||
}
|
||||
|
||||
fn node_seat_state(&self) -> &NodeSeatState {
|
||||
&self.seat_state
|
||||
}
|
||||
|
||||
fn node_visit(self: Rc<Self>, visitor: &mut dyn NodeVisitor) {
|
||||
visitor.visit_surface(&self);
|
||||
}
|
||||
|
||||
fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) {
|
||||
let children = self.children.borrow_mut();
|
||||
if let Some(c) = children.deref() {
|
||||
for child in c.subsurfaces.values() {
|
||||
visitor.visit_surface(&child.surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn node_visible(&self) -> bool {
|
||||
self.visible.get()
|
||||
}
|
||||
|
||||
fn node_absolute_position(&self) -> Rect {
|
||||
self.buffer_abs_pos.get()
|
||||
}
|
||||
|
||||
fn node_output(&self) -> Option<Rc<OutputNode>> {
|
||||
Some(self.output.get())
|
||||
}
|
||||
|
||||
fn node_location(&self) -> Option<NodeLocation> {
|
||||
Some(self.location.get())
|
||||
}
|
||||
|
||||
fn node_layer(&self) -> NodeLayerLink {
|
||||
self.ext.get().node_layer()
|
||||
}
|
||||
|
||||
fn node_active_changed(&self, active: bool) {
|
||||
if let Some(tl) = self.toplevel.get() {
|
||||
tl.tl_surface_active_changed(active);
|
||||
}
|
||||
}
|
||||
|
||||
fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32, bounds: Option<&Rect>) {
|
||||
renderer.render_surface(self, x, y, bounds);
|
||||
}
|
||||
|
||||
fn node_client(&self) -> Option<Rc<Client>> {
|
||||
Some(self.client.clone())
|
||||
}
|
||||
|
||||
fn node_toplevel(self: Rc<Self>) -> Option<Rc<dyn ToplevelNode>> {
|
||||
self.toplevel.get()
|
||||
}
|
||||
|
||||
fn node_tray_item(&self) -> Option<TrayItemId> {
|
||||
self.ext.get().tray_item()
|
||||
}
|
||||
|
||||
fn node_make_visible(self: Rc<Self>) {
|
||||
if let Some(tl) = self.toplevel.get() {
|
||||
tl.node_make_visible();
|
||||
}
|
||||
}
|
||||
|
||||
fn node_on_key(
|
||||
&self,
|
||||
seat: &WlSeatGlobal,
|
||||
time_usec: u64,
|
||||
key: u32,
|
||||
state: KeyState,
|
||||
kb_state: &KeyboardState,
|
||||
) {
|
||||
seat.key_surface(self, time_usec, key, state, kb_state);
|
||||
}
|
||||
|
||||
fn node_on_mods(&self, seat: &WlSeatGlobal, kb_state: &KeyboardState) {
|
||||
seat.mods_surface(self, kb_state);
|
||||
}
|
||||
|
||||
fn node_on_touch_down(
|
||||
self: Rc<Self>,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
time_usec: u64,
|
||||
id: i32,
|
||||
x: Fixed,
|
||||
y: Fixed,
|
||||
) {
|
||||
seat.touch_down_surface(&self, time_usec, id, x, y)
|
||||
}
|
||||
|
||||
fn node_on_touch_up(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, time_usec: u64, id: i32) {
|
||||
seat.touch_up_surface(&self, time_usec, id)
|
||||
}
|
||||
|
||||
fn node_on_touch_motion(
|
||||
self: Rc<Self>,
|
||||
seat: &WlSeatGlobal,
|
||||
time_usec: u64,
|
||||
id: i32,
|
||||
x: Fixed,
|
||||
y: Fixed,
|
||||
) {
|
||||
seat.touch_motion_surface(&self, time_usec, id, x, y)
|
||||
}
|
||||
|
||||
fn node_on_touch_frame(&self, seat: &WlSeatGlobal) {
|
||||
seat.touch_frame_surface(&self)
|
||||
}
|
||||
|
||||
fn node_on_touch_cancel(&self, seat: &WlSeatGlobal) {
|
||||
seat.touch_cancel_surface(&self)
|
||||
}
|
||||
|
||||
fn node_on_button(
|
||||
self: Rc<Self>,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
time_usec: u64,
|
||||
button: u32,
|
||||
state: ButtonState,
|
||||
serial: u64,
|
||||
) {
|
||||
seat.button_surface(&self, time_usec, button, state, serial);
|
||||
}
|
||||
|
||||
fn node_on_axis_event(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, event: &PendingScroll) {
|
||||
seat.scroll_surface(&self, event);
|
||||
}
|
||||
|
||||
fn node_on_focus(self: Rc<Self>, seat: &WlSeatGlobal) {
|
||||
if let Some(xsurface) = self.ext.get().into_xsurface()
|
||||
&& let Some(window) = xsurface.xwindow.get()
|
||||
{
|
||||
self.client
|
||||
.state
|
||||
.xwayland
|
||||
.queue
|
||||
.push(XWaylandEvent::Activate(window.data.clone()));
|
||||
}
|
||||
seat.focus_surface(&self);
|
||||
}
|
||||
|
||||
fn node_on_unfocus(&self, seat: &WlSeatGlobal) {
|
||||
seat.unfocus_surface(self);
|
||||
}
|
||||
|
||||
fn node_on_leave(&self, seat: &WlSeatGlobal) {
|
||||
seat.leave_surface(self);
|
||||
}
|
||||
|
||||
fn node_on_pointer_enter(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||
seat.enter_surface(&self, x, y)
|
||||
}
|
||||
|
||||
fn node_on_pointer_motion(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||
seat.motion_surface(&self, x, y)
|
||||
}
|
||||
|
||||
fn node_on_pointer_relative_motion(
|
||||
&self,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
time_usec: u64,
|
||||
dx: Fixed,
|
||||
dy: Fixed,
|
||||
dx_unaccelerated: Fixed,
|
||||
dy_unaccelerated: Fixed,
|
||||
) {
|
||||
seat.relative_motion_surface(self, time_usec, dx, dy, dx_unaccelerated, dy_unaccelerated);
|
||||
}
|
||||
|
||||
fn node_on_dnd_drop(&self, dnd: &Dnd) {
|
||||
dnd.seat.dnd_surface_drop(self, dnd);
|
||||
}
|
||||
|
||||
fn node_on_dnd_leave(&self, dnd: &Dnd) {
|
||||
dnd.seat.dnd_surface_leave(self, dnd);
|
||||
}
|
||||
|
||||
fn node_on_dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed, serial: u64) {
|
||||
dnd.seat.dnd_surface_enter(self, dnd, x, y, serial);
|
||||
}
|
||||
|
||||
fn node_on_dnd_motion(&self, dnd: &Dnd, time_usec: u64, x: Fixed, y: Fixed) {
|
||||
dnd.seat.dnd_surface_motion(self, dnd, time_usec, x, y);
|
||||
}
|
||||
|
||||
fn node_on_swipe_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
|
||||
seat.swipe_begin_surface(self, time_usec, finger_count)
|
||||
}
|
||||
|
||||
fn node_on_swipe_update(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, dx: Fixed, dy: Fixed) {
|
||||
seat.swipe_update_surface(self, time_usec, dx, dy)
|
||||
}
|
||||
|
||||
fn node_on_swipe_end(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
|
||||
seat.swipe_end_surface(self, time_usec, cancelled)
|
||||
}
|
||||
|
||||
fn node_on_pinch_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
|
||||
seat.pinch_begin_surface(self, time_usec, finger_count)
|
||||
}
|
||||
|
||||
fn node_on_pinch_update(
|
||||
&self,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
time_usec: u64,
|
||||
dx: Fixed,
|
||||
dy: Fixed,
|
||||
scale: Fixed,
|
||||
rotation: Fixed,
|
||||
) {
|
||||
seat.pinch_update_surface(self, time_usec, dx, dy, scale, rotation)
|
||||
}
|
||||
|
||||
fn node_on_pinch_end(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
|
||||
seat.pinch_end_surface(self, time_usec, cancelled)
|
||||
}
|
||||
|
||||
fn node_on_hold_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
|
||||
seat.hold_begin_surface(self, time_usec, finger_count)
|
||||
}
|
||||
|
||||
fn node_on_hold_end(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
|
||||
seat.hold_end_surface(self, time_usec, cancelled)
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_enter(&self, pad: &Rc<TabletPad>) {
|
||||
pad.surface_enter(self);
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_leave(&self, pad: &Rc<TabletPad>) {
|
||||
pad.surface_leave(self);
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_button(
|
||||
&self,
|
||||
pad: &Rc<TabletPad>,
|
||||
time_usec: u64,
|
||||
button: u32,
|
||||
state: PadButtonState,
|
||||
) {
|
||||
pad.surface_button(self, time_usec, button, state);
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_mode_switch(
|
||||
&self,
|
||||
pad: &Rc<TabletPad>,
|
||||
group: &Rc<TabletPadGroup>,
|
||||
time_usec: u64,
|
||||
mode: u32,
|
||||
) {
|
||||
pad.surface_mode_switch(self, group, time_usec, mode);
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_ring(
|
||||
&self,
|
||||
pad: &Rc<TabletPad>,
|
||||
ring: &Rc<TabletPadRing>,
|
||||
source: Option<TabletRingEventSource>,
|
||||
angle: Option<f64>,
|
||||
time_usec: u64,
|
||||
) {
|
||||
pad.surface_ring(self, ring, source, angle, time_usec);
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_strip(
|
||||
&self,
|
||||
pad: &Rc<TabletPad>,
|
||||
strip: &Rc<TabletPadStrip>,
|
||||
source: Option<TabletStripEventSource>,
|
||||
position: Option<f64>,
|
||||
time_usec: u64,
|
||||
) {
|
||||
pad.surface_strip(self, strip, source, position, time_usec);
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_dial(
|
||||
&self,
|
||||
pad: &Rc<TabletPad>,
|
||||
dial: &Rc<TabletPadDial>,
|
||||
value120: i32,
|
||||
time_usec: u64,
|
||||
) {
|
||||
pad.surface_dial(self, dial, value120, time_usec);
|
||||
}
|
||||
|
||||
fn node_on_tablet_tool_leave(&self, tool: &Rc<TabletTool>, time_usec: u64) {
|
||||
tool.surface_leave(self, time_usec);
|
||||
}
|
||||
|
||||
fn node_on_tablet_tool_enter(
|
||||
self: Rc<Self>,
|
||||
tool: &Rc<TabletTool>,
|
||||
time_usec: u64,
|
||||
x: Fixed,
|
||||
y: Fixed,
|
||||
) {
|
||||
tool.surface_enter(&self, time_usec, x, y);
|
||||
}
|
||||
|
||||
fn node_on_tablet_tool_button(
|
||||
&self,
|
||||
tool: &Rc<TabletTool>,
|
||||
time_usec: u64,
|
||||
button: u32,
|
||||
state: ToolButtonState,
|
||||
) {
|
||||
tool.surface_button(self, time_usec, button, state);
|
||||
}
|
||||
|
||||
fn node_on_tablet_tool_apply_changes(
|
||||
self: Rc<Self>,
|
||||
tool: &Rc<TabletTool>,
|
||||
time_usec: u64,
|
||||
changes: Option<&TabletToolChanges>,
|
||||
x: Fixed,
|
||||
y: Fixed,
|
||||
) {
|
||||
tool.surface_apply_changes(&self, time_usec, changes, x, y);
|
||||
}
|
||||
|
||||
fn node_into_surface(self: Rc<Self>) -> Option<Rc<WlSurface>> {
|
||||
Some(self.clone())
|
||||
}
|
||||
|
||||
fn node_is_xwayland_surface(&self) -> bool {
|
||||
self.client.is_xwayland
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WlSurfaceError {
|
||||
|
|
@ -2212,144 +1725,3 @@ efrom!(WlSurfaceError, ClientError);
|
|||
efrom!(WlSurfaceError, XdgSurfaceError);
|
||||
efrom!(WlSurfaceError, ZwlrLayerSurfaceV1Error);
|
||||
efrom!(WlSurfaceError, CommitTimelineError);
|
||||
|
||||
impl VblankListener for WlSurface {
|
||||
fn after_vblank(self: Rc<Self>) {
|
||||
if self.visible.get() {
|
||||
let now = self.client.state.now_msec() as u32;
|
||||
for mut fr in self.frame_requests.borrow_mut().drain(..) {
|
||||
fr.now = now;
|
||||
drop(fr);
|
||||
}
|
||||
}
|
||||
if self.clear_fifo_on_vblank.take() {
|
||||
self.commit_timeline.clear_fifo_barrier();
|
||||
}
|
||||
self.vblank_listener.detach();
|
||||
}
|
||||
}
|
||||
|
||||
impl BeforeLatchListener for WlSurface {
|
||||
fn before_latch(self: Rc<Self>, present: u64) -> BeforeLatchResult {
|
||||
self.commit_timeline.before_latch(&self, present)
|
||||
}
|
||||
}
|
||||
|
||||
impl LatchListener for WlSurface {
|
||||
fn after_latch(self: Rc<Self>, _on: &OutputNode, tearing: bool) {
|
||||
if self.visible.get() {
|
||||
if self.latched_commit_version.get() < self.commit_version.get() {
|
||||
let latched = &mut *self.latched_presentation_feedback.borrow_mut();
|
||||
latched.clear();
|
||||
latched.append(&mut self.presentation_feedback.borrow_mut());
|
||||
if latched.is_not_empty() {
|
||||
self.presentation_listener
|
||||
.attach(&self.output.get().presentation_event);
|
||||
}
|
||||
self.latched_commit_version.set(self.commit_version.get());
|
||||
}
|
||||
}
|
||||
if tearing && self.visible.get() {
|
||||
if self.commit_timeline.has_fifo_barrier() {
|
||||
self.vblank_listener.attach(&self.output.get().vblank_event);
|
||||
self.clear_fifo_on_vblank.set(true);
|
||||
}
|
||||
} else {
|
||||
self.commit_timeline.clear_fifo_barrier();
|
||||
}
|
||||
self.latch_listener.detach();
|
||||
}
|
||||
}
|
||||
|
||||
impl PresentationListener for WlSurface {
|
||||
fn presented(
|
||||
self: Rc<Self>,
|
||||
output: &OutputNode,
|
||||
tv_sec: u64,
|
||||
tv_nsec: u32,
|
||||
refresh: u32,
|
||||
seq: u64,
|
||||
flags: u32,
|
||||
vrr: bool,
|
||||
) {
|
||||
let bindings = output.global.bindings.borrow();
|
||||
let bindings = bindings.get(&self.client.id);
|
||||
for pf in self.latched_presentation_feedback.borrow_mut().drain(..) {
|
||||
pf.presented(bindings, tv_sec, tv_nsec, refresh, seq, flags, vrr);
|
||||
}
|
||||
self.presentation_listener.detach();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FrameRequest {
|
||||
now: u32,
|
||||
cb: Rc<WlCallback>,
|
||||
}
|
||||
|
||||
impl Drop for FrameRequest {
|
||||
fn drop(&mut self) {
|
||||
self.cb.send_done(self.now);
|
||||
let _ = self.cb.client.remove_obj(&*self.cb);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SyncobjRelease {
|
||||
state: Rc<State>,
|
||||
committed: bool,
|
||||
syncobj: Option<Rc<Syncobj>>,
|
||||
point: SyncobjPoint,
|
||||
}
|
||||
|
||||
impl SyncobjRelease {
|
||||
fn signal(&mut self, syncs: Option<&SmallVec<[(BufferResvUser, FdSync); 1]>>) {
|
||||
if !self.committed {
|
||||
return;
|
||||
}
|
||||
let Some(syncobj) = self.syncobj.take() else {
|
||||
return;
|
||||
};
|
||||
let Some(ctx) = self.state.render_ctx.get() else {
|
||||
log::error!("Cannot signal release point because there is no render context");
|
||||
return;
|
||||
};
|
||||
let Some(ctx) = ctx.syncobj_ctx() else {
|
||||
log::error!("Cannot signal release point because there is no syncobj context");
|
||||
return;
|
||||
};
|
||||
if let Some(syncs) = syncs
|
||||
&& syncs.is_not_empty()
|
||||
{
|
||||
let res = ctx.import_sync_files(
|
||||
&syncobj,
|
||||
self.point,
|
||||
syncs.iter().flat_map(|f| f.1.get_sync_file()),
|
||||
);
|
||||
match res {
|
||||
Ok(_) => return,
|
||||
Err(e) => {
|
||||
log::error!("Could not import sync files into syncobj: {}", ErrorFmt(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Err(e) = ctx.signal(&syncobj, self.point) {
|
||||
log::error!("Could not signal release point: {}", ErrorFmt(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SyncobjRelease {
|
||||
fn drop(&mut self) {
|
||||
self.signal(None);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SurfaceRelease {
|
||||
cb: Rc<WlCallback>,
|
||||
}
|
||||
|
||||
impl Drop for SurfaceRelease {
|
||||
fn drop(&mut self) {
|
||||
self.cb.send_done(0);
|
||||
let _ = self.cb.client.remove_obj(&*self.cb);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
336
src/ifs/wl_surface/node.rs
Normal file
336
src/ifs/wl_surface/node.rs
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
use super::*;
|
||||
|
||||
impl Node for WlSurface {
|
||||
fn node_id(&self) -> NodeId {
|
||||
self.node_id.into()
|
||||
}
|
||||
|
||||
fn node_seat_state(&self) -> &NodeSeatState {
|
||||
&self.seat_state
|
||||
}
|
||||
|
||||
fn node_visit(self: Rc<Self>, visitor: &mut dyn NodeVisitor) {
|
||||
visitor.visit_surface(&self);
|
||||
}
|
||||
|
||||
fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) {
|
||||
let children = self.children.borrow_mut();
|
||||
if let Some(c) = children.deref() {
|
||||
for child in c.subsurfaces.values() {
|
||||
visitor.visit_surface(&child.surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn node_visible(&self) -> bool {
|
||||
self.visible.get()
|
||||
}
|
||||
|
||||
fn node_absolute_position(&self) -> Rect {
|
||||
self.buffer_abs_pos.get()
|
||||
}
|
||||
|
||||
fn node_output(&self) -> Option<Rc<OutputNode>> {
|
||||
Some(self.output.get())
|
||||
}
|
||||
|
||||
fn node_location(&self) -> Option<NodeLocation> {
|
||||
Some(self.location.get())
|
||||
}
|
||||
|
||||
fn node_layer(&self) -> NodeLayerLink {
|
||||
self.ext.get().node_layer()
|
||||
}
|
||||
|
||||
fn node_active_changed(&self, active: bool) {
|
||||
if let Some(tl) = self.toplevel.get() {
|
||||
tl.tl_surface_active_changed(active);
|
||||
}
|
||||
}
|
||||
|
||||
fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32, bounds: Option<&Rect>) {
|
||||
renderer.render_surface(self, x, y, bounds);
|
||||
}
|
||||
|
||||
fn node_client(&self) -> Option<Rc<Client>> {
|
||||
Some(self.client.clone())
|
||||
}
|
||||
|
||||
fn node_toplevel(self: Rc<Self>) -> Option<Rc<dyn ToplevelNode>> {
|
||||
self.toplevel.get()
|
||||
}
|
||||
|
||||
fn node_tray_item(&self) -> Option<TrayItemId> {
|
||||
self.ext.get().tray_item()
|
||||
}
|
||||
|
||||
fn node_make_visible(self: Rc<Self>) {
|
||||
if let Some(tl) = self.toplevel.get() {
|
||||
tl.node_make_visible();
|
||||
}
|
||||
}
|
||||
|
||||
fn node_on_key(
|
||||
&self,
|
||||
seat: &WlSeatGlobal,
|
||||
time_usec: u64,
|
||||
key: u32,
|
||||
state: KeyState,
|
||||
kb_state: &KeyboardState,
|
||||
) {
|
||||
seat.key_surface(self, time_usec, key, state, kb_state);
|
||||
}
|
||||
|
||||
fn node_on_mods(&self, seat: &WlSeatGlobal, kb_state: &KeyboardState) {
|
||||
seat.mods_surface(self, kb_state);
|
||||
}
|
||||
|
||||
fn node_on_touch_down(
|
||||
self: Rc<Self>,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
time_usec: u64,
|
||||
id: i32,
|
||||
x: Fixed,
|
||||
y: Fixed,
|
||||
) {
|
||||
seat.touch_down_surface(&self, time_usec, id, x, y)
|
||||
}
|
||||
|
||||
fn node_on_touch_up(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, time_usec: u64, id: i32) {
|
||||
seat.touch_up_surface(&self, time_usec, id)
|
||||
}
|
||||
|
||||
fn node_on_touch_motion(
|
||||
self: Rc<Self>,
|
||||
seat: &WlSeatGlobal,
|
||||
time_usec: u64,
|
||||
id: i32,
|
||||
x: Fixed,
|
||||
y: Fixed,
|
||||
) {
|
||||
seat.touch_motion_surface(&self, time_usec, id, x, y)
|
||||
}
|
||||
|
||||
fn node_on_touch_frame(&self, seat: &WlSeatGlobal) {
|
||||
seat.touch_frame_surface(&self)
|
||||
}
|
||||
|
||||
fn node_on_touch_cancel(&self, seat: &WlSeatGlobal) {
|
||||
seat.touch_cancel_surface(&self)
|
||||
}
|
||||
|
||||
fn node_on_button(
|
||||
self: Rc<Self>,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
time_usec: u64,
|
||||
button: u32,
|
||||
state: ButtonState,
|
||||
serial: u64,
|
||||
) {
|
||||
seat.button_surface(&self, time_usec, button, state, serial);
|
||||
}
|
||||
|
||||
fn node_on_axis_event(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, event: &PendingScroll) {
|
||||
seat.scroll_surface(&self, event);
|
||||
}
|
||||
|
||||
fn node_on_focus(self: Rc<Self>, seat: &WlSeatGlobal) {
|
||||
if let Some(xsurface) = self.ext.get().into_xsurface()
|
||||
&& let Some(window) = xsurface.xwindow.get()
|
||||
{
|
||||
self.client
|
||||
.state
|
||||
.xwayland
|
||||
.queue
|
||||
.push(XWaylandEvent::Activate(window.data.clone()));
|
||||
}
|
||||
seat.focus_surface(&self);
|
||||
}
|
||||
|
||||
fn node_on_unfocus(&self, seat: &WlSeatGlobal) {
|
||||
seat.unfocus_surface(self);
|
||||
}
|
||||
|
||||
fn node_on_leave(&self, seat: &WlSeatGlobal) {
|
||||
seat.leave_surface(self);
|
||||
}
|
||||
|
||||
fn node_on_pointer_enter(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||
seat.enter_surface(&self, x, y)
|
||||
}
|
||||
|
||||
fn node_on_pointer_motion(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||
seat.motion_surface(&self, x, y)
|
||||
}
|
||||
|
||||
fn node_on_pointer_relative_motion(
|
||||
&self,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
time_usec: u64,
|
||||
dx: Fixed,
|
||||
dy: Fixed,
|
||||
dx_unaccelerated: Fixed,
|
||||
dy_unaccelerated: Fixed,
|
||||
) {
|
||||
seat.relative_motion_surface(self, time_usec, dx, dy, dx_unaccelerated, dy_unaccelerated);
|
||||
}
|
||||
|
||||
fn node_on_dnd_drop(&self, dnd: &Dnd) {
|
||||
dnd.seat.dnd_surface_drop(self, dnd);
|
||||
}
|
||||
|
||||
fn node_on_dnd_leave(&self, dnd: &Dnd) {
|
||||
dnd.seat.dnd_surface_leave(self, dnd);
|
||||
}
|
||||
|
||||
fn node_on_dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed, serial: u64) {
|
||||
dnd.seat.dnd_surface_enter(self, dnd, x, y, serial);
|
||||
}
|
||||
|
||||
fn node_on_dnd_motion(&self, dnd: &Dnd, time_usec: u64, x: Fixed, y: Fixed) {
|
||||
dnd.seat.dnd_surface_motion(self, dnd, time_usec, x, y);
|
||||
}
|
||||
|
||||
fn node_on_swipe_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
|
||||
seat.swipe_begin_surface(self, time_usec, finger_count)
|
||||
}
|
||||
|
||||
fn node_on_swipe_update(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, dx: Fixed, dy: Fixed) {
|
||||
seat.swipe_update_surface(self, time_usec, dx, dy)
|
||||
}
|
||||
|
||||
fn node_on_swipe_end(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
|
||||
seat.swipe_end_surface(self, time_usec, cancelled)
|
||||
}
|
||||
|
||||
fn node_on_pinch_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
|
||||
seat.pinch_begin_surface(self, time_usec, finger_count)
|
||||
}
|
||||
|
||||
fn node_on_pinch_update(
|
||||
&self,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
time_usec: u64,
|
||||
dx: Fixed,
|
||||
dy: Fixed,
|
||||
scale: Fixed,
|
||||
rotation: Fixed,
|
||||
) {
|
||||
seat.pinch_update_surface(self, time_usec, dx, dy, scale, rotation)
|
||||
}
|
||||
|
||||
fn node_on_pinch_end(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
|
||||
seat.pinch_end_surface(self, time_usec, cancelled)
|
||||
}
|
||||
|
||||
fn node_on_hold_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
|
||||
seat.hold_begin_surface(self, time_usec, finger_count)
|
||||
}
|
||||
|
||||
fn node_on_hold_end(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
|
||||
seat.hold_end_surface(self, time_usec, cancelled)
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_enter(&self, pad: &Rc<TabletPad>) {
|
||||
pad.surface_enter(self);
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_leave(&self, pad: &Rc<TabletPad>) {
|
||||
pad.surface_leave(self);
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_button(
|
||||
&self,
|
||||
pad: &Rc<TabletPad>,
|
||||
time_usec: u64,
|
||||
button: u32,
|
||||
state: PadButtonState,
|
||||
) {
|
||||
pad.surface_button(self, time_usec, button, state);
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_mode_switch(
|
||||
&self,
|
||||
pad: &Rc<TabletPad>,
|
||||
group: &Rc<TabletPadGroup>,
|
||||
time_usec: u64,
|
||||
mode: u32,
|
||||
) {
|
||||
pad.surface_mode_switch(self, group, time_usec, mode);
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_ring(
|
||||
&self,
|
||||
pad: &Rc<TabletPad>,
|
||||
ring: &Rc<TabletPadRing>,
|
||||
source: Option<TabletRingEventSource>,
|
||||
angle: Option<f64>,
|
||||
time_usec: u64,
|
||||
) {
|
||||
pad.surface_ring(self, ring, source, angle, time_usec);
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_strip(
|
||||
&self,
|
||||
pad: &Rc<TabletPad>,
|
||||
strip: &Rc<TabletPadStrip>,
|
||||
source: Option<TabletStripEventSource>,
|
||||
position: Option<f64>,
|
||||
time_usec: u64,
|
||||
) {
|
||||
pad.surface_strip(self, strip, source, position, time_usec);
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_dial(
|
||||
&self,
|
||||
pad: &Rc<TabletPad>,
|
||||
dial: &Rc<TabletPadDial>,
|
||||
value120: i32,
|
||||
time_usec: u64,
|
||||
) {
|
||||
pad.surface_dial(self, dial, value120, time_usec);
|
||||
}
|
||||
|
||||
fn node_on_tablet_tool_leave(&self, tool: &Rc<TabletTool>, time_usec: u64) {
|
||||
tool.surface_leave(self, time_usec);
|
||||
}
|
||||
|
||||
fn node_on_tablet_tool_enter(
|
||||
self: Rc<Self>,
|
||||
tool: &Rc<TabletTool>,
|
||||
time_usec: u64,
|
||||
x: Fixed,
|
||||
y: Fixed,
|
||||
) {
|
||||
tool.surface_enter(&self, time_usec, x, y);
|
||||
}
|
||||
|
||||
fn node_on_tablet_tool_button(
|
||||
&self,
|
||||
tool: &Rc<TabletTool>,
|
||||
time_usec: u64,
|
||||
button: u32,
|
||||
state: ToolButtonState,
|
||||
) {
|
||||
tool.surface_button(self, time_usec, button, state);
|
||||
}
|
||||
|
||||
fn node_on_tablet_tool_apply_changes(
|
||||
self: Rc<Self>,
|
||||
tool: &Rc<TabletTool>,
|
||||
time_usec: u64,
|
||||
changes: Option<&TabletToolChanges>,
|
||||
x: Fixed,
|
||||
y: Fixed,
|
||||
) {
|
||||
tool.surface_apply_changes(&self, time_usec, changes, x, y);
|
||||
}
|
||||
|
||||
fn node_into_surface(self: Rc<Self>) -> Option<Rc<WlSurface>> {
|
||||
Some(self.clone())
|
||||
}
|
||||
|
||||
fn node_is_xwayland_surface(&self) -> bool {
|
||||
self.client.is_xwayland
|
||||
}
|
||||
}
|
||||
142
src/ifs/wl_surface/presentation.rs
Normal file
142
src/ifs/wl_surface/presentation.rs
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
use super::*;
|
||||
|
||||
impl VblankListener for WlSurface {
|
||||
fn after_vblank(self: Rc<Self>) {
|
||||
if self.visible.get() {
|
||||
let now = self.client.state.now_msec() as u32;
|
||||
for mut fr in self.frame_requests.borrow_mut().drain(..) {
|
||||
fr.now = now;
|
||||
drop(fr);
|
||||
}
|
||||
}
|
||||
if self.clear_fifo_on_vblank.take() {
|
||||
self.commit_timeline.clear_fifo_barrier();
|
||||
}
|
||||
self.vblank_listener.detach();
|
||||
}
|
||||
}
|
||||
|
||||
impl BeforeLatchListener for WlSurface {
|
||||
fn before_latch(self: Rc<Self>, present: u64) -> BeforeLatchResult {
|
||||
self.commit_timeline.before_latch(&self, present)
|
||||
}
|
||||
}
|
||||
|
||||
impl LatchListener for WlSurface {
|
||||
fn after_latch(self: Rc<Self>, _on: &OutputNode, tearing: bool) {
|
||||
if self.visible.get() {
|
||||
if self.latched_commit_version.get() < self.commit_version.get() {
|
||||
let latched = &mut *self.latched_presentation_feedback.borrow_mut();
|
||||
latched.clear();
|
||||
latched.append(&mut self.presentation_feedback.borrow_mut());
|
||||
if latched.is_not_empty() {
|
||||
self.presentation_listener
|
||||
.attach(&self.output.get().presentation_event);
|
||||
}
|
||||
self.latched_commit_version.set(self.commit_version.get());
|
||||
}
|
||||
}
|
||||
if tearing && self.visible.get() {
|
||||
if self.commit_timeline.has_fifo_barrier() {
|
||||
self.vblank_listener.attach(&self.output.get().vblank_event);
|
||||
self.clear_fifo_on_vblank.set(true);
|
||||
}
|
||||
} else {
|
||||
self.commit_timeline.clear_fifo_barrier();
|
||||
}
|
||||
self.latch_listener.detach();
|
||||
}
|
||||
}
|
||||
|
||||
impl PresentationListener for WlSurface {
|
||||
fn presented(
|
||||
self: Rc<Self>,
|
||||
output: &OutputNode,
|
||||
tv_sec: u64,
|
||||
tv_nsec: u32,
|
||||
refresh: u32,
|
||||
seq: u64,
|
||||
flags: u32,
|
||||
vrr: bool,
|
||||
) {
|
||||
let bindings = output.global.bindings.borrow();
|
||||
let bindings = bindings.get(&self.client.id);
|
||||
for pf in self.latched_presentation_feedback.borrow_mut().drain(..) {
|
||||
pf.presented(bindings, tv_sec, tv_nsec, refresh, seq, flags, vrr);
|
||||
}
|
||||
self.presentation_listener.detach();
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct FrameRequest {
|
||||
pub(super) now: u32,
|
||||
pub(super) cb: Rc<WlCallback>,
|
||||
}
|
||||
|
||||
impl Drop for FrameRequest {
|
||||
fn drop(&mut self) {
|
||||
self.cb.send_done(self.now);
|
||||
let _ = self.cb.client.remove_obj(&*self.cb);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SyncobjRelease {
|
||||
pub(super) state: Rc<State>,
|
||||
pub(super) committed: bool,
|
||||
pub(super) syncobj: Option<Rc<Syncobj>>,
|
||||
pub(super) point: SyncobjPoint,
|
||||
}
|
||||
|
||||
impl SyncobjRelease {
|
||||
pub(super) fn signal(&mut self, syncs: Option<&SmallVec<[(BufferResvUser, FdSync); 1]>>) {
|
||||
if !self.committed {
|
||||
return;
|
||||
}
|
||||
let Some(syncobj) = self.syncobj.take() else {
|
||||
return;
|
||||
};
|
||||
let Some(ctx) = self.state.render_ctx.get() else {
|
||||
log::error!("Cannot signal release point because there is no render context");
|
||||
return;
|
||||
};
|
||||
let Some(ctx) = ctx.syncobj_ctx() else {
|
||||
log::error!("Cannot signal release point because there is no syncobj context");
|
||||
return;
|
||||
};
|
||||
if let Some(syncs) = syncs
|
||||
&& syncs.is_not_empty()
|
||||
{
|
||||
let res = ctx.import_sync_files(
|
||||
&syncobj,
|
||||
self.point,
|
||||
syncs.iter().flat_map(|f| f.1.get_sync_file()),
|
||||
);
|
||||
match res {
|
||||
Ok(_) => return,
|
||||
Err(e) => {
|
||||
log::error!("Could not import sync files into syncobj: {}", ErrorFmt(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Err(e) = ctx.signal(&syncobj, self.point) {
|
||||
log::error!("Could not signal release point: {}", ErrorFmt(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SyncobjRelease {
|
||||
fn drop(&mut self) {
|
||||
self.signal(None);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SurfaceRelease {
|
||||
pub(super) cb: Rc<WlCallback>,
|
||||
}
|
||||
|
||||
impl Drop for SurfaceRelease {
|
||||
fn drop(&mut self) {
|
||||
self.cb.send_done(0);
|
||||
let _ = self.cb.client.remove_obj(&*self.cb);
|
||||
}
|
||||
}
|
||||
163
src/ifs/wl_surface/request.rs
Normal file
163
src/ifs/wl_surface/request.rs
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
use super::*;
|
||||
|
||||
impl WlSurfaceRequestHandler for WlSurface {
|
||||
type Error = WlSurfaceError;
|
||||
|
||||
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.commit_timeline.clear(ClearReason::Destroy);
|
||||
self.unset_dnd_icons();
|
||||
self.unset_cursors();
|
||||
self.ext.get().on_surface_destroy()?;
|
||||
self.destroy_node();
|
||||
{
|
||||
let mut children = self.children.borrow_mut();
|
||||
if let Some(children) = &mut *children {
|
||||
for ss in children.subsurfaces.values() {
|
||||
ss.surface.unset_ext();
|
||||
}
|
||||
}
|
||||
*children = None;
|
||||
}
|
||||
self.buffer.set(None);
|
||||
self.reset_shm_textures();
|
||||
if let Some(xwayland_serial) = self.xwayland_serial.get() {
|
||||
self.client
|
||||
.surfaces_by_xwayland_serial
|
||||
.remove(&xwayland_serial);
|
||||
}
|
||||
self.frame_requests.borrow_mut().clear();
|
||||
self.toplevel.set(None);
|
||||
self.client.remove_obj(self)?;
|
||||
self.idle_inhibitors.clear();
|
||||
self.constraints.take();
|
||||
self.destroyed.set(true);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn attach(&self, req: Attach, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let pending = &mut *self.pending.borrow_mut();
|
||||
if self.version >= OFFSET_SINCE {
|
||||
if req.x != 0 || req.y != 0 {
|
||||
return Err(WlSurfaceError::OffsetInAttach);
|
||||
}
|
||||
} else {
|
||||
pending.offset = (req.x, req.y);
|
||||
}
|
||||
let buf = if req.buffer.is_some() {
|
||||
Some(self.client.lookup(req.buffer)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
pending.buffer = Some(buf.map(|buf| AttachedBuffer {
|
||||
send_release: false,
|
||||
buf,
|
||||
}));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn damage(&self, req: Damage, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.do_damage(req.x, req.y, req.width, req.height, |p| {
|
||||
&mut p.surface_damage
|
||||
})
|
||||
}
|
||||
|
||||
fn frame(&self, req: Frame, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let cb = Rc::new(WlCallback::new(req.callback, &self.client));
|
||||
track!(self.client, cb);
|
||||
self.client.add_client_obj(&cb)?;
|
||||
self.pending
|
||||
.borrow_mut()
|
||||
.frame_request
|
||||
.push(FrameRequest { now: 0, cb });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_opaque_region(
|
||||
&self,
|
||||
region: SetOpaqueRegion,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
let region = if region.region.is_some() {
|
||||
Some(self.client.lookup(region.region)?.region())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.pending.borrow_mut().opaque_region = Some(region);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_input_region(&self, req: SetInputRegion, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let region = if req.region.is_some() {
|
||||
Some(self.client.lookup(req.region)?.region())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.pending.borrow_mut().input_region = Some(region);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn commit(&self, _req: Commit, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let ext = self.ext.get();
|
||||
let pending = &mut *self.pending.borrow_mut();
|
||||
if let Some(Some(buffer)) = &mut pending.buffer
|
||||
&& pending.release_point.is_none()
|
||||
&& pending.sync_file_release.is_none()
|
||||
{
|
||||
buffer.send_release = true;
|
||||
}
|
||||
if let Some(release) = &mut pending.release_point {
|
||||
release.committed = true;
|
||||
}
|
||||
self.verify_syncobj_sync(pending)?;
|
||||
if pending.surface_release.is_not_empty() && not_matches!(pending.buffer, Some(Some(_))) {
|
||||
return Err(WlSurfaceError::SurfaceReleaseWithoutAttach);
|
||||
}
|
||||
if pending.sync_file_release.is_some() && not_matches!(pending.buffer, Some(Some(_))) {
|
||||
return Err(WlSurfaceError::SyncFileReleaseWithoutAttach);
|
||||
}
|
||||
if ext.commit_requested(pending) == CommitAction::ContinueCommit {
|
||||
self.commit_timeline.commit(slf, pending)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_buffer_transform(
|
||||
&self,
|
||||
req: SetBufferTransform,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
let Some(tf) = Transform::from_wl(req.transform) else {
|
||||
return Err(WlSurfaceError::UnknownBufferTransform(req.transform));
|
||||
};
|
||||
self.pending.borrow_mut().transform = Some(tf);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_buffer_scale(&self, req: SetBufferScale, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if req.scale < 1 {
|
||||
return Err(WlSurfaceError::NonPositiveBufferScale);
|
||||
}
|
||||
self.pending.borrow_mut().scale = Some(req.scale);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn damage_buffer(&self, req: DamageBuffer, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.do_damage(req.x, req.y, req.width, req.height, |p| {
|
||||
&mut p.buffer_damage
|
||||
})
|
||||
}
|
||||
|
||||
fn offset(&self, req: Offset, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.pending.borrow_mut().offset = (req.x, req.y);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_release(&self, req: GetRelease, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let cb = Rc::new(WlCallback::new(req.callback, &self.client));
|
||||
track!(self.client, cb);
|
||||
self.client.add_client_obj(&cb)?;
|
||||
let release = SurfaceRelease { cb };
|
||||
self.pending.borrow_mut().surface_release.push(release);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue