wayland: implement xwayland_shell_v1
This commit is contained in:
parent
1f64fefc86
commit
335677bbcd
11 changed files with 332 additions and 7 deletions
|
|
@ -2,14 +2,14 @@ use {
|
|||
crate::{
|
||||
async_engine::SpawnedFuture,
|
||||
client::{error::LookupError, objects::Objects},
|
||||
ifs::{wl_display::WlDisplay, wl_registry::WlRegistry},
|
||||
ifs::{wl_display::WlDisplay, wl_registry::WlRegistry, wl_surface::WlSurface},
|
||||
leaks::Tracker,
|
||||
object::{Interface, Object, ObjectId, WL_DISPLAY_ID},
|
||||
state::State,
|
||||
utils::{
|
||||
asyncevent::AsyncEvent,
|
||||
buffd::{MsgFormatter, MsgParser, MsgParserError, OutBufferSwapchain},
|
||||
copyhashmap::Locked,
|
||||
copyhashmap::{CopyHashMap, Locked},
|
||||
errorfmt::ErrorFmt,
|
||||
numcell::NumCell,
|
||||
trim::AsciiTrim,
|
||||
|
|
@ -145,6 +145,8 @@ impl Clients {
|
|||
pid_info: get_pid_info(uid, pid),
|
||||
serials: Default::default(),
|
||||
symmetric_delete: Cell::new(false),
|
||||
last_xwayland_serial: Cell::new(0),
|
||||
surfaces_by_xwayland_serial: Default::default(),
|
||||
});
|
||||
track!(data, data);
|
||||
let display = Rc::new(WlDisplay::new(&data));
|
||||
|
|
@ -214,6 +216,7 @@ impl Drop for ClientHolder {
|
|||
self.data.objects.destroy();
|
||||
self.data.flush_request.clear();
|
||||
self.data.shutdown.clear();
|
||||
self.data.surfaces_by_xwayland_serial.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -251,6 +254,8 @@ pub struct Client {
|
|||
pub pid_info: PidInfo,
|
||||
pub serials: RefCell<VecDeque<SerialRange>>,
|
||||
pub symmetric_delete: Cell<bool>,
|
||||
pub last_xwayland_serial: Cell<u64>,
|
||||
pub surfaces_by_xwayland_serial: CopyHashMap<u64, Rc<WlSurface>>,
|
||||
}
|
||||
|
||||
pub const NUM_CACHED_SERIAL_RANGES: usize = 64;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use {
|
|||
},
|
||||
wl_shm::WlShmGlobal,
|
||||
wl_subcompositor::WlSubcompositorGlobal,
|
||||
wl_surface::xwayland_shell_v1::XwaylandShellV1Global,
|
||||
wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1Global,
|
||||
wp_presentation::WpPresentationGlobal,
|
||||
wp_viewporter::WpViewporterGlobal,
|
||||
|
|
@ -152,6 +153,7 @@ impl Globals {
|
|||
add_singleton!(WpViewporterGlobal);
|
||||
add_singleton!(WpFractionalScaleManagerV1Global);
|
||||
add_singleton!(ZwpPointerConstraintsV1Global);
|
||||
add_singleton!(XwaylandShellV1Global);
|
||||
}
|
||||
|
||||
pub fn add_backend_singletons(&self, backend: &Rc<dyn Backend>) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ pub mod wp_fractional_scale_v1;
|
|||
pub mod wp_viewport;
|
||||
pub mod x_surface;
|
||||
pub mod xdg_surface;
|
||||
pub mod xwayland_shell_v1;
|
||||
pub mod zwlr_layer_surface_v1;
|
||||
pub mod zwp_idle_inhibitor_v1;
|
||||
|
||||
|
|
@ -50,6 +51,7 @@ use {
|
|||
},
|
||||
wire::{wl_surface::*, WlOutputId, WlSurfaceId, ZwpIdleInhibitorV1Id},
|
||||
xkbcommon::ModifierState,
|
||||
xwayland::XWaylandEvent,
|
||||
},
|
||||
ahash::AHashMap,
|
||||
std::{
|
||||
|
|
@ -258,6 +260,7 @@ pub struct WlSurface {
|
|||
output: CloneCell<Rc<OutputNode>>,
|
||||
fractional_scale: CloneCell<Option<Rc<WpFractionalScaleV1>>>,
|
||||
pub constraints: SmallMap<SeatId, Rc<SeatConstraint>, 1>,
|
||||
xwayland_serial: Cell<Option<u64>>,
|
||||
}
|
||||
|
||||
impl Debug for WlSurface {
|
||||
|
|
@ -349,6 +352,7 @@ struct PendingState {
|
|||
dst_size: Cell<Option<Option<(i32, i32)>>>,
|
||||
scale: Cell<Option<i32>>,
|
||||
transform: Cell<Option<Transform>>,
|
||||
xwayland_serial: Cell<Option<u64>>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -400,6 +404,7 @@ impl WlSurface {
|
|||
output: CloneCell::new(client.state.dummy_output.get().unwrap()),
|
||||
fractional_scale: Default::default(),
|
||||
constraints: Default::default(),
|
||||
xwayland_serial: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -410,6 +415,7 @@ impl WlSurface {
|
|||
let xsurface = Rc::new(XSurface {
|
||||
surface: self.clone(),
|
||||
xwindow: Default::default(),
|
||||
xwayland_surface: Default::default(),
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(self.client, xsurface);
|
||||
|
|
@ -449,6 +455,10 @@ impl WlSurface {
|
|||
self.toplevel.get()
|
||||
}
|
||||
|
||||
pub fn xwayland_serial(&self) -> Option<u64> {
|
||||
self.xwayland_serial.get()
|
||||
}
|
||||
|
||||
fn set_absolute_position(&self, x1: i32, y1: i32) {
|
||||
self.buffer_abs_pos
|
||||
.set(self.buffer_abs_pos.get().at_point(x1, y1));
|
||||
|
|
@ -621,6 +631,11 @@ impl WlSurface {
|
|||
buffer.send_release();
|
||||
}
|
||||
}
|
||||
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)?;
|
||||
|
|
@ -856,6 +871,17 @@ impl WlSurface {
|
|||
self.opaque_region.set(region);
|
||||
}
|
||||
}
|
||||
if let Some(xwayland_serial) = self.pending.xwayland_serial.take() {
|
||||
self.xwayland_serial.set(Some(xwayland_serial));
|
||||
self.client
|
||||
.surfaces_by_xwayland_serial
|
||||
.set(xwayland_serial, self.clone());
|
||||
self.client
|
||||
.state
|
||||
.xwayland
|
||||
.queue
|
||||
.push(XWaylandEvent::SurfaceSerialAssigned(self.id));
|
||||
}
|
||||
if self.need_extents_update.get() {
|
||||
self.calculate_extents();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
use {
|
||||
crate::{
|
||||
ifs::wl_surface::{x_surface::xwindow::Xwindow, SurfaceExt, WlSurface, WlSurfaceError},
|
||||
ifs::wl_surface::{
|
||||
x_surface::{xwayland_surface_v1::XwaylandSurfaceV1, xwindow::Xwindow},
|
||||
SurfaceExt, WlSurface, WlSurfaceError,
|
||||
},
|
||||
leaks::Tracker,
|
||||
tree::ToplevelNode,
|
||||
utils::clonecell::CloneCell,
|
||||
|
|
@ -9,11 +12,13 @@ use {
|
|||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub mod xwayland_surface_v1;
|
||||
pub mod xwindow;
|
||||
|
||||
pub struct XSurface {
|
||||
pub surface: Rc<WlSurface>,
|
||||
pub xwindow: CloneCell<Option<Rc<Xwindow>>>,
|
||||
pub xwayland_surface: CloneCell<Option<Rc<XwaylandSurfaceV1>>>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
|
|
@ -25,6 +30,9 @@ impl SurfaceExt for XSurface {
|
|||
}
|
||||
|
||||
fn on_surface_destroy(&self) -> Result<(), WlSurfaceError> {
|
||||
if self.xwayland_surface.get().is_some() {
|
||||
return Err(WlSurfaceError::ReloObjectStillExists);
|
||||
}
|
||||
self.surface.unset_ext();
|
||||
if let Some(xwindow) = self.xwindow.take() {
|
||||
xwindow.tl_destroy();
|
||||
|
|
@ -35,7 +43,10 @@ impl SurfaceExt for XSurface {
|
|||
.state
|
||||
.xwayland
|
||||
.queue
|
||||
.push(XWaylandEvent::SurfaceDestroyed(self.surface.id));
|
||||
.push(XWaylandEvent::SurfaceDestroyed(
|
||||
self.surface.id,
|
||||
self.surface.xwayland_serial.get(),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
77
src/ifs/wl_surface/x_surface/xwayland_surface_v1.rs
Normal file
77
src/ifs/wl_surface/x_surface/xwayland_surface_v1.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
use {
|
||||
crate::{
|
||||
client::{Client, ClientError},
|
||||
ifs::wl_surface::{x_surface::XSurface, WlSurfaceError},
|
||||
leaks::Tracker,
|
||||
object::Object,
|
||||
utils::buffd::{MsgParser, MsgParserError},
|
||||
wire::{xwayland_surface_v1::*, XwaylandSurfaceV1Id},
|
||||
},
|
||||
std::rc::Rc,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct XwaylandSurfaceV1 {
|
||||
pub id: XwaylandSurfaceV1Id,
|
||||
pub client: Rc<Client>,
|
||||
pub x: Rc<XSurface>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl XwaylandSurfaceV1 {
|
||||
fn set_serial(&self, parser: MsgParser<'_, '_>) -> Result<(), XwaylandSurfaceV1Error> {
|
||||
let req: SetSerial = self.client.parse(self, parser)?;
|
||||
if self.x.surface.xwayland_serial.get().is_some() {
|
||||
return Err(XwaylandSurfaceV1Error::SerialAlreadySet);
|
||||
}
|
||||
let serial = req.serial_lo as u64 | ((req.serial_hi as u64) << 32);
|
||||
if self.client.last_xwayland_serial.get() >= serial {
|
||||
return Err(XwaylandSurfaceV1Error::NonMonotonicSerial);
|
||||
}
|
||||
self.client.last_xwayland_serial.set(serial);
|
||||
self.x.surface.pending.xwayland_serial.set(Some(serial));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), XwaylandSurfaceV1Error> {
|
||||
let _req: Destroy = self.client.parse(self, parser)?;
|
||||
self.x.xwayland_surface.set(None);
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
XwaylandSurfaceV1;
|
||||
|
||||
SET_SERIAL => set_serial,
|
||||
DESTROY => destroy,
|
||||
}
|
||||
|
||||
impl Object for XwaylandSurfaceV1 {
|
||||
fn num_requests(&self) -> u32 {
|
||||
DESTROY + 1
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.x.xwayland_surface.set(None);
|
||||
}
|
||||
}
|
||||
|
||||
simple_add_obj!(XwaylandSurfaceV1);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum XwaylandSurfaceV1Error {
|
||||
#[error("The serial for this surface is already set")]
|
||||
SerialAlreadySet,
|
||||
#[error("The serial is not larger than the previously used serial")]
|
||||
NonMonotonicSerial,
|
||||
#[error(transparent)]
|
||||
WlSurfaceError(#[from] WlSurfaceError),
|
||||
#[error("Parsing failed")]
|
||||
MsgParserError(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(XwaylandSurfaceV1Error, MsgParserError);
|
||||
efrom!(XwaylandSurfaceV1Error, ClientError);
|
||||
|
|
@ -117,6 +117,7 @@ pub struct XwindowData {
|
|||
pub window_id: u32,
|
||||
pub client: Rc<Client>,
|
||||
pub surface_id: Cell<Option<WlSurfaceId>>,
|
||||
pub surface_serial: Cell<Option<u64>>,
|
||||
pub window: CloneCell<Option<Rc<Xwindow>>>,
|
||||
pub info: XwindowInfo,
|
||||
pub children: CopyHashMap<u32, Rc<XwindowData>>,
|
||||
|
|
@ -152,6 +153,7 @@ impl XwindowData {
|
|||
window_id: event.window,
|
||||
client: client.clone(),
|
||||
surface_id: Cell::new(None),
|
||||
surface_serial: Cell::new(None),
|
||||
window: Default::default(),
|
||||
info: XwindowInfo {
|
||||
override_redirect: Cell::new(event.override_redirect != 0),
|
||||
|
|
|
|||
120
src/ifs/wl_surface/xwayland_shell_v1.rs
Normal file
120
src/ifs/wl_surface/xwayland_shell_v1.rs
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
use {
|
||||
crate::{
|
||||
client::{Client, ClientError},
|
||||
globals::{Global, GlobalName},
|
||||
ifs::wl_surface::{x_surface::xwayland_surface_v1::XwaylandSurfaceV1, WlSurfaceError},
|
||||
leaks::Tracker,
|
||||
object::Object,
|
||||
utils::buffd::{MsgParser, MsgParserError},
|
||||
wire::{xwayland_shell_v1::*, WlSurfaceId, XwaylandShellV1Id},
|
||||
},
|
||||
std::rc::Rc,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct XwaylandShellV1Global {
|
||||
name: GlobalName,
|
||||
}
|
||||
|
||||
pub struct XwaylandShellV1 {
|
||||
id: XwaylandShellV1Id,
|
||||
client: Rc<Client>,
|
||||
pub version: u32,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl XwaylandShellV1Global {
|
||||
pub fn new(name: GlobalName) -> Self {
|
||||
Self { name }
|
||||
}
|
||||
|
||||
fn bind_(
|
||||
self: Rc<Self>,
|
||||
id: XwaylandShellV1Id,
|
||||
client: &Rc<Client>,
|
||||
version: u32,
|
||||
) -> Result<(), XwaylandShellV1Error> {
|
||||
let obj = Rc::new(XwaylandShellV1 {
|
||||
id,
|
||||
client: client.clone(),
|
||||
version,
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl XwaylandShellV1 {
|
||||
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), XwaylandShellV1Error> {
|
||||
let _req: Destroy = self.client.parse(self, parser)?;
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_xwayland_surface(&self, parser: MsgParser<'_, '_>) -> Result<(), XwaylandShellV1Error> {
|
||||
let req: GetXwaylandSurface = self.client.parse(self, parser)?;
|
||||
let surface = self.client.lookup(req.surface)?;
|
||||
let xsurface = surface.get_xsurface()?;
|
||||
if xsurface.xwayland_surface.get().is_some() {
|
||||
return Err(XwaylandShellV1Error::AlreadyAttached(surface.id));
|
||||
}
|
||||
let xws = Rc::new(XwaylandSurfaceV1 {
|
||||
id: req.id,
|
||||
client: self.client.clone(),
|
||||
x: xsurface,
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(self.client, xws);
|
||||
xws.x.xwayland_surface.set(Some(xws.clone()));
|
||||
self.client.add_client_obj(&xws)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
global_base!(XwaylandShellV1Global, XwaylandShellV1, XwaylandShellV1Error);
|
||||
|
||||
impl Global for XwaylandShellV1Global {
|
||||
fn singleton(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn version(&self) -> u32 {
|
||||
1
|
||||
}
|
||||
|
||||
fn xwayland_only(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
simple_add_global!(XwaylandShellV1Global);
|
||||
|
||||
object_base! {
|
||||
XwaylandShellV1;
|
||||
|
||||
DESTROY => destroy,
|
||||
GET_XWAYLAND_SURFACE => get_xwayland_surface,
|
||||
}
|
||||
|
||||
impl Object for XwaylandShellV1 {
|
||||
fn num_requests(&self) -> u32 {
|
||||
GET_XWAYLAND_SURFACE + 1
|
||||
}
|
||||
}
|
||||
|
||||
simple_add_obj!(XwaylandShellV1);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum XwaylandShellV1Error {
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
#[error("Parsing failed")]
|
||||
MsgParserError(#[source] Box<MsgParserError>),
|
||||
#[error("The `wl_surface` {0} already has an extension object")]
|
||||
AlreadyAttached(WlSurfaceId),
|
||||
#[error(transparent)]
|
||||
WlSurfaceError(#[from] WlSurfaceError),
|
||||
}
|
||||
efrom!(XwaylandShellV1Error, ClientError);
|
||||
efrom!(XwaylandShellV1Error, MsgParserError);
|
||||
|
|
@ -271,7 +271,8 @@ async fn log_xwayland(state: Rc<State>, stderr: OwnedFd) {
|
|||
|
||||
pub enum XWaylandEvent {
|
||||
SurfaceCreated(WlSurfaceId),
|
||||
SurfaceDestroyed(WlSurfaceId),
|
||||
SurfaceSerialAssigned(WlSurfaceId),
|
||||
SurfaceDestroyed(WlSurfaceId, Option<u64>),
|
||||
Configure(Rc<Xwindow>),
|
||||
Activate(Rc<XwindowData>),
|
||||
ActivateRoot,
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ atoms! {
|
|||
WINDOW,
|
||||
_WL_SELECTION,
|
||||
WL_SURFACE_ID,
|
||||
WL_SURFACE_SERIAL,
|
||||
WM_CHANGE_STATE,
|
||||
WM_DELETE_WINDOW,
|
||||
WM_HINTS,
|
||||
|
|
@ -236,6 +237,8 @@ pub struct Wm {
|
|||
client: Rc<Client>,
|
||||
windows: AHashMap<u32, Rc<XwindowData>>,
|
||||
windows_by_surface_id: AHashMap<WlSurfaceId, Rc<XwindowData>>,
|
||||
windows_by_surface_serial: AHashMap<u64, Rc<XwindowData>>,
|
||||
last_surface_serial: u64,
|
||||
focus_window: Option<Rc<XwindowData>>,
|
||||
last_input_serial: u64,
|
||||
atom_cache: AHashMap<String, u32>,
|
||||
|
|
@ -514,6 +517,8 @@ impl Wm {
|
|||
client,
|
||||
windows: Default::default(),
|
||||
windows_by_surface_id: Default::default(),
|
||||
windows_by_surface_serial: Default::default(),
|
||||
last_surface_serial: 0,
|
||||
focus_window: Default::default(),
|
||||
last_input_serial: 0,
|
||||
atom_cache: Default::default(),
|
||||
|
|
@ -592,8 +597,13 @@ impl Wm {
|
|||
XWaylandEvent::SurfaceCreated(event) => {
|
||||
self.handle_xwayland_surface_created(event).await
|
||||
}
|
||||
XWaylandEvent::SurfaceSerialAssigned(event) => {
|
||||
self.handle_xwayland_surface_serial_assigned(event).await
|
||||
}
|
||||
XWaylandEvent::Configure(event) => self.handle_xwayland_configure(event).await,
|
||||
XWaylandEvent::SurfaceDestroyed(event) => self.handle_xwayland_surface_destroyed(event),
|
||||
XWaylandEvent::SurfaceDestroyed(surface_id, serial) => {
|
||||
self.handle_xwayland_surface_destroyed(surface_id, serial)
|
||||
}
|
||||
XWaylandEvent::Activate(window) => {
|
||||
self.activate_window(Some(&window), Initiator::Wayland)
|
||||
.await
|
||||
|
|
@ -1433,8 +1443,27 @@ impl Wm {
|
|||
self.create_window(&data, surface).await;
|
||||
}
|
||||
|
||||
fn handle_xwayland_surface_destroyed(&mut self, surface: WlSurfaceId) {
|
||||
async fn handle_xwayland_surface_serial_assigned(&mut self, surface: WlSurfaceId) {
|
||||
let surface = match self.client.lookup(surface) {
|
||||
Ok(s) => s,
|
||||
_ => return,
|
||||
};
|
||||
let serial = match surface.xwayland_serial() {
|
||||
Some(s) => s,
|
||||
_ => return,
|
||||
};
|
||||
let data = match self.windows_by_surface_serial.get(&serial) {
|
||||
Some(w) => w.clone(),
|
||||
_ => return,
|
||||
};
|
||||
self.create_window(&data, surface).await;
|
||||
}
|
||||
|
||||
fn handle_xwayland_surface_destroyed(&mut self, surface: WlSurfaceId, serial: Option<u64>) {
|
||||
self.windows_by_surface_id.remove(&surface);
|
||||
if let Some(serial) = serial {
|
||||
self.windows_by_surface_serial.remove(&serial);
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_event(&mut self, event: &Event) {
|
||||
|
|
@ -1895,6 +1924,9 @@ impl Wm {
|
|||
if let Some(sid) = data.surface_id.take() {
|
||||
self.windows_by_surface_id.remove(&sid);
|
||||
}
|
||||
if let Some(serial) = data.surface_serial.take() {
|
||||
self.windows_by_surface_serial.remove(&serial);
|
||||
}
|
||||
if let Some(window) = data.window.take() {
|
||||
window.destroy();
|
||||
}
|
||||
|
|
@ -1961,6 +1993,8 @@ impl Wm {
|
|||
self.handle_wm_change_state(&event).await?;
|
||||
} else if event.ty == self.atoms._NET_WM_MOVERESIZE {
|
||||
self.handle_net_wm_moveresize(&event).await?;
|
||||
} else if event.ty == self.atoms.WL_SURFACE_SERIAL {
|
||||
self.handle_wl_surface_serial(&event).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -2334,6 +2368,37 @@ impl Wm {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_wl_surface_serial(
|
||||
&mut self,
|
||||
event: &ClientMessage<'_>,
|
||||
) -> Result<(), XWaylandError> {
|
||||
let serial = event.data[0] as u64 | ((event.data[1] as u64) << 32);
|
||||
if serial <= self.last_surface_serial {
|
||||
log::error!(
|
||||
"Surface serial is not monotonic: {} <= {}",
|
||||
serial,
|
||||
self.last_surface_serial
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
self.last_surface_serial = serial;
|
||||
let data = match self.windows.get(&event.window) {
|
||||
Some(d) => d.clone(),
|
||||
_ => return Ok(()),
|
||||
};
|
||||
if let Some(old) = data.surface_serial.replace(Some(serial)) {
|
||||
self.windows_by_surface_serial.remove(&old);
|
||||
}
|
||||
if let Some(old) = data.window.take() {
|
||||
old.break_loops();
|
||||
}
|
||||
self.windows_by_surface_serial.insert(serial, data.clone());
|
||||
if let Some(surface) = self.client.surfaces_by_xwayland_serial.get(&serial) {
|
||||
self.create_window(&data, surface).await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_wl_surface_id(
|
||||
&mut self,
|
||||
event: &ClientMessage<'_>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue