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_idle_inhibitor_v1;
|
||||||
pub mod zwp_input_popup_surface_v2;
|
pub mod zwp_input_popup_surface_v2;
|
||||||
|
|
||||||
|
mod node;
|
||||||
|
mod presentation;
|
||||||
|
mod request;
|
||||||
|
|
||||||
|
pub use presentation::SyncobjRelease;
|
||||||
|
|
||||||
|
use presentation::{FrameRequest, SurfaceRelease};
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
backend::{ButtonState, KeyState},
|
backend::{ButtonState, KeyState},
|
||||||
|
|
@ -1008,167 +1016,6 @@ impl WlSurface {
|
||||||
|
|
||||||
const MAX_DAMAGE: usize = 32;
|
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 {
|
impl WlSurface {
|
||||||
fn apply_state(self: &Rc<Self>, pending: &mut PendingState) -> Result<(), WlSurfaceError> {
|
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);
|
dedicated_add_obj!(WlSurface, WlSurfaceId, surfaces);
|
||||||
|
|
||||||
tree_id!(SurfaceNodeId);
|
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)]
|
#[derive(Debug, Error)]
|
||||||
pub enum WlSurfaceError {
|
pub enum WlSurfaceError {
|
||||||
|
|
@ -2212,144 +1725,3 @@ efrom!(WlSurfaceError, ClientError);
|
||||||
efrom!(WlSurfaceError, XdgSurfaceError);
|
efrom!(WlSurfaceError, XdgSurfaceError);
|
||||||
efrom!(WlSurfaceError, ZwlrLayerSurfaceV1Error);
|
efrom!(WlSurfaceError, ZwlrLayerSurfaceV1Error);
|
||||||
efrom!(WlSurfaceError, CommitTimelineError);
|
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