autocommit 2022-02-11 02:28:11 CET
This commit is contained in:
parent
83c3fb99f9
commit
9b8e1ac29f
63 changed files with 690 additions and 122 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
|||
.*
|
||||
!.gitignore
|
||||
!/.cargo
|
||||
/target
|
||||
|
|
|
|||
39
Cargo.lock
generated
39
Cargo.lock
generated
|
|
@ -116,6 +116,19 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.9.0"
|
||||
|
|
@ -269,6 +282,7 @@ dependencies = [
|
|||
"bitflags",
|
||||
"bstr",
|
||||
"byteorder",
|
||||
"chrono",
|
||||
"env_logger",
|
||||
"futures",
|
||||
"isnt",
|
||||
|
|
@ -351,6 +365,16 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
|
|
@ -568,6 +592,17 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uapi"
|
||||
version = "0.2.4"
|
||||
|
|
@ -608,9 +643,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
|||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ panic = "abort"
|
|||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
codegen-units = 1
|
||||
|
||||
[dependencies]
|
||||
uapi = "0.2.4"
|
||||
|
|
@ -31,6 +32,7 @@ renderdoc = "0.10.1"
|
|||
smallvec = { version = "1.8.0", features = ["const_generics", "const_new", "union"] }
|
||||
backtrace = "0.3.64"
|
||||
byteorder = "1.4.3"
|
||||
chrono = "0.4.19"
|
||||
|
||||
[build-dependencies]
|
||||
repc = "0.1.1"
|
||||
|
|
@ -39,3 +41,6 @@ bstr = "0.2.17"
|
|||
|
||||
[profile.dev.build-override]
|
||||
opt-level = 3
|
||||
|
||||
[features]
|
||||
rc_tracking = []
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::fixed::Fixed;
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
linear_ids!(OutputIds, OutputId);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ pub static NONE: Bugs = Bugs {
|
|||
respect_min_max_size: false,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Bugs {
|
||||
pub respect_min_max_size: bool,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ use crate::client::objects::Objects;
|
|||
use crate::ifs::wl_callback::WlCallback;
|
||||
use crate::ifs::wl_display::WlDisplay;
|
||||
use crate::ifs::wl_registry::WlRegistry;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::{Interface, Object, ObjectId, WL_DISPLAY_ID};
|
||||
use crate::state::State;
|
||||
use crate::utils::asyncevent::AsyncEvent;
|
||||
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError, OutBufferSwapchain};
|
||||
use crate::utils::numcell::NumCell;
|
||||
use crate::utils::oneshot::{oneshot, OneshotTx};
|
||||
use crate::utils::queue::AsyncQueue;
|
||||
use crate::wire::WlRegistryId;
|
||||
use crate::ErrorFmt;
|
||||
|
|
@ -19,6 +19,7 @@ use std::cell::{Cell, RefCell, RefMut};
|
|||
use std::error::Error;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::mem;
|
||||
use std::ops::DerefMut;
|
||||
use std::rc::Rc;
|
||||
use uapi::{c, OwnedFd};
|
||||
|
||||
|
|
@ -50,6 +51,11 @@ impl Clients {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
mem::take(self.clients.borrow_mut().deref_mut());
|
||||
mem::take(self.shutdown_clients.borrow_mut().deref_mut());
|
||||
}
|
||||
|
||||
pub fn id(&self) -> ClientId {
|
||||
ClientId(self.next_client_id.fetch_add(1))
|
||||
}
|
||||
|
|
@ -86,7 +92,6 @@ impl Clients {
|
|||
}
|
||||
}
|
||||
};
|
||||
let (send, recv) = oneshot();
|
||||
let data = Rc::new(Client {
|
||||
id,
|
||||
state: global.clone(),
|
||||
|
|
@ -95,14 +100,17 @@ impl Clients {
|
|||
objects: Objects::new(),
|
||||
swapchain: Default::default(),
|
||||
flush_request: Default::default(),
|
||||
shutdown: Cell::new(Some(send)),
|
||||
shutdown: Default::default(),
|
||||
dispatch_frame_requests: AsyncQueue::new(),
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(data, data);
|
||||
let display = Rc::new(WlDisplay::new(&data));
|
||||
track!(data, display);
|
||||
data.objects.display.set(Some(display.clone()));
|
||||
data.objects.add_client_object(display).expect("");
|
||||
let client = ClientHolder {
|
||||
_handler: global.eng.spawn(tasks::client(data.clone(), recv)),
|
||||
_handler: global.eng.spawn(tasks::client(data.clone())),
|
||||
data,
|
||||
};
|
||||
log::info!(
|
||||
|
|
@ -126,7 +134,7 @@ impl Clients {
|
|||
pub fn shutdown(&self, client_id: ClientId) {
|
||||
if let Some(client) = self.clients.borrow_mut().remove(&client_id) {
|
||||
log::info!("Shutting down client {}", client.data.id.0);
|
||||
client.data.shutdown.replace(None).unwrap().send(());
|
||||
client.data.shutdown.trigger();
|
||||
client.data.flush_request.trigger();
|
||||
self.shutdown_clients.borrow_mut().insert(client_id, client);
|
||||
}
|
||||
|
|
@ -159,6 +167,8 @@ impl Drop for ClientHolder {
|
|||
fn drop(&mut self) {
|
||||
self.data.objects.destroy();
|
||||
self.data.dispatch_frame_requests.clear();
|
||||
self.data.flush_request.clear();
|
||||
self.data.shutdown.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -180,8 +190,9 @@ pub struct Client {
|
|||
pub objects: Objects,
|
||||
swapchain: Rc<RefCell<OutBufferSwapchain>>,
|
||||
flush_request: AsyncEvent,
|
||||
shutdown: Cell<Option<OneshotTx<()>>>,
|
||||
shutdown: AsyncEvent,
|
||||
pub dispatch_frame_requests: AsyncQueue<Rc<WlCallback>>,
|
||||
pub tracker: Tracker<Client>,
|
||||
}
|
||||
|
||||
const MAX_PENDING_BUFFERS: usize = 10;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ use crate::wire::{
|
|||
use ahash::AHashMap;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::mem;
|
||||
use std::ops::DerefMut;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Objects {
|
||||
|
|
@ -71,14 +72,14 @@ impl Objects {
|
|||
for obj in toplevel.values_mut() {
|
||||
obj.destroy_node(true);
|
||||
}
|
||||
toplevel.clear();
|
||||
mem::take(toplevel.deref_mut());
|
||||
}
|
||||
{
|
||||
let mut registry = self.registry.lock();
|
||||
for obj in registry.values_mut() {
|
||||
obj.break_loops();
|
||||
}
|
||||
registry.clear();
|
||||
mem::take(registry.deref_mut());
|
||||
}
|
||||
self.display.set(None);
|
||||
self.registries.clear();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::object::ObjectId;
|
||||
use crate::utils::buffd::{BufFdIn, BufFdOut, MsgParser};
|
||||
use crate::utils::oneshot::OneshotRx;
|
||||
use crate::utils::vec_ext::VecExt;
|
||||
use crate::ErrorFmt;
|
||||
use futures::{select, FutureExt};
|
||||
|
|
@ -9,14 +8,15 @@ use std::collections::VecDeque;
|
|||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub async fn client(data: Rc<Client>, shutdown: OneshotRx<()>) {
|
||||
pub async fn client(data: Rc<Client>) {
|
||||
let mut recv = data.state.eng.spawn(receive(data.clone())).fuse();
|
||||
let mut dispatch_fr = data.state.eng.spawn(dispatch_fr(data.clone())).fuse();
|
||||
let mut shutdown = data.shutdown.triggered().fuse();
|
||||
let _send = data.state.eng.spawn(send(data.clone()));
|
||||
select! {
|
||||
_ = recv => { },
|
||||
_ = dispatch_fr => { },
|
||||
_ = shutdown.fuse() => { },
|
||||
_ = shutdown => { },
|
||||
}
|
||||
drop(recv);
|
||||
drop(dispatch_fr);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ pub trait Vtable: Sized {
|
|||
dd: &Rc<Self::Device>,
|
||||
data: OfferData<Self>,
|
||||
id: ObjectId,
|
||||
) -> Self::Offer;
|
||||
) -> Rc<Self::Offer>;
|
||||
fn send_selection(dd: &Self::Device, offer: Self::OfferId);
|
||||
fn send_cancelled(source: &Self::Source);
|
||||
fn get_offer_id(offer: &Self::Offer) -> Self::OfferId;
|
||||
|
|
@ -215,7 +215,7 @@ pub fn offer_source_to<T: Vtable>(src: &Rc<T::Source>, client: &Rc<Client>) {
|
|||
client: client.clone(),
|
||||
shared: shared.clone(),
|
||||
};
|
||||
let offer = Rc::new(T::create_offer(client, dd, offer_data, id));
|
||||
let offer = T::create_offer(client, dd, offer_data, id);
|
||||
data.offers.insert(id.into(), offer.clone());
|
||||
let mt = data.mime_types.borrow_mut();
|
||||
T::send_offer(dd, &offer);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ use crate::ifs::ipc::{
|
|||
break_device_loops, destroy_device, DeviceData, OfferData, Role, SourceData, Vtable,
|
||||
};
|
||||
use crate::ifs::wl_seat::{WlSeat, WlSeatError, WlSeatGlobal};
|
||||
use crate::ifs::wl_surface::{SurfaceRole, WlSurfaceError};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::{Object, ObjectId};
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -15,7 +17,6 @@ use crate::wire::{WlDataDeviceId, WlDataOfferId, WlSurfaceId};
|
|||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use uapi::OwnedFd;
|
||||
use crate::ifs::wl_surface::{SurfaceRole, WlSurfaceError};
|
||||
|
||||
#[allow(dead_code)]
|
||||
const ROLE: u32 = 0;
|
||||
|
|
@ -25,6 +26,7 @@ pub struct WlDataDevice {
|
|||
pub manager: Rc<WlDataDeviceManager>,
|
||||
pub seat: Rc<WlSeat>,
|
||||
pub data: DeviceData<WlDataDevice>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlDataDevice {
|
||||
|
|
@ -34,6 +36,7 @@ impl WlDataDevice {
|
|||
manager: manager.clone(),
|
||||
seat: seat.clone(),
|
||||
data: Default::default(),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -153,13 +156,16 @@ impl Vtable for WlDataDevice {
|
|||
device: &Rc<WlDataDevice>,
|
||||
offer_data: OfferData<Self>,
|
||||
id: ObjectId,
|
||||
) -> Self::Offer {
|
||||
WlDataOffer {
|
||||
) -> Rc<Self::Offer> {
|
||||
let rc = Rc::new(WlDataOffer {
|
||||
id: id.into(),
|
||||
client: client.clone(),
|
||||
device: device.clone(),
|
||||
data: offer_data,
|
||||
}
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, rc);
|
||||
rc
|
||||
}
|
||||
|
||||
fn send_selection(dd: &Self::Device, offer: Self::OfferId) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::client::{Client, ClientError};
|
|||
use crate::globals::{Global, GlobalName};
|
||||
use crate::ifs::ipc::wl_data_device::WlDataDevice;
|
||||
use crate::ifs::ipc::wl_data_source::WlDataSource;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -27,6 +28,7 @@ pub struct WlDataDeviceManager {
|
|||
pub id: WlDataDeviceManagerId,
|
||||
pub client: Rc<Client>,
|
||||
pub version: u32,
|
||||
tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlDataDeviceManagerGlobal {
|
||||
|
|
@ -44,7 +46,9 @@ impl WlDataDeviceManagerGlobal {
|
|||
id,
|
||||
client: client.clone(),
|
||||
version,
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -54,6 +58,7 @@ impl WlDataDeviceManager {
|
|||
fn create_data_source(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateDataSourceError> {
|
||||
let req: CreateDataSource = self.client.parse(self, parser)?;
|
||||
let res = Rc::new(WlDataSource::new(req.id, &self.client));
|
||||
track!(self.client, res);
|
||||
self.client.add_client_obj(&res)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -65,6 +70,7 @@ impl WlDataDeviceManager {
|
|||
let req: GetDataDevice = self.client.parse(&**self, parser)?;
|
||||
let seat = self.client.lookup(req.seat)?;
|
||||
let dev = Rc::new(WlDataDevice::new(req.id, self, &seat));
|
||||
track!(self.client, dev);
|
||||
seat.add_data_device(&dev);
|
||||
self.client.add_client_obj(&dev)?;
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use crate::ifs::ipc::{
|
|||
break_offer_loops, destroy_offer, receive, OfferData, Role, OFFER_STATE_ACCEPTED,
|
||||
OFFER_STATE_DROPPED, OFFER_STATE_FINISHED, SOURCE_STATE_FINISHED,
|
||||
};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::bitflags::BitflagsExt;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
|
|
@ -28,6 +29,7 @@ pub struct WlDataOffer {
|
|||
pub client: Rc<Client>,
|
||||
pub device: Rc<WlDataDevice>,
|
||||
pub data: OfferData<WlDataDevice>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlDataOffer {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use crate::ifs::ipc::{
|
|||
add_mime_type, break_source_loops, cancel_offers, destroy_source, SharedState, SourceData,
|
||||
OFFER_STATE_ACCEPTED, OFFER_STATE_DROPPED,
|
||||
};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::bitflags::BitflagsExt;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
|
|
@ -24,12 +25,14 @@ const INVALID_SOURCE: u32 = 1;
|
|||
pub struct WlDataSource {
|
||||
pub id: WlDataSourceId,
|
||||
pub data: SourceData<WlDataDevice>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlDataSource {
|
||||
pub fn new(id: WlDataSourceId, client: &Rc<Client>) -> Self {
|
||||
Self {
|
||||
id,
|
||||
tracker: Default::default(),
|
||||
data: SourceData::new(client),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::client::{Client, ClientError};
|
|||
use crate::globals::{Global, GlobalName};
|
||||
use crate::ifs::ipc::zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1;
|
||||
use crate::ifs::ipc::zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -18,6 +19,7 @@ pub struct ZwpPrimarySelectionDeviceManagerV1 {
|
|||
pub id: ZwpPrimarySelectionDeviceManagerV1Id,
|
||||
pub client: Rc<Client>,
|
||||
pub version: u32,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl ZwpPrimarySelectionDeviceManagerV1Global {
|
||||
|
|
@ -35,7 +37,9 @@ impl ZwpPrimarySelectionDeviceManagerV1Global {
|
|||
id,
|
||||
client: client.clone(),
|
||||
version,
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -45,6 +49,7 @@ impl ZwpPrimarySelectionDeviceManagerV1 {
|
|||
fn create_source(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateSourceError> {
|
||||
let req: CreateSource = self.client.parse(self, parser)?;
|
||||
let res = Rc::new(ZwpPrimarySelectionSourceV1::new(req.id, &self.client));
|
||||
track!(self.client, res);
|
||||
self.client.add_client_obj(&res)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -53,6 +58,7 @@ impl ZwpPrimarySelectionDeviceManagerV1 {
|
|||
let req: GetDevice = self.client.parse(&**self, parser)?;
|
||||
let seat = self.client.lookup(req.seat)?;
|
||||
let dev = Rc::new(ZwpPrimarySelectionDeviceV1::new(req.id, self, &seat));
|
||||
track!(self.client, dev);
|
||||
seat.add_primary_selection_device(&dev);
|
||||
self.client.add_client_obj(&dev)?;
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use crate::ifs::ipc::{
|
|||
break_device_loops, destroy_device, DeviceData, OfferData, Role, SourceData, Vtable,
|
||||
};
|
||||
use crate::ifs::wl_seat::{WlSeat, WlSeatError, WlSeatGlobal};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::{Object, ObjectId};
|
||||
use crate::utils::buffd::{MsgParser, MsgParserError};
|
||||
use crate::wire::zwp_primary_selection_device_v1::*;
|
||||
|
|
@ -19,6 +20,7 @@ pub struct ZwpPrimarySelectionDeviceV1 {
|
|||
pub manager: Rc<ZwpPrimarySelectionDeviceManagerV1>,
|
||||
seat: Rc<WlSeat>,
|
||||
data: DeviceData<Self>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl ZwpPrimarySelectionDeviceV1 {
|
||||
|
|
@ -32,6 +34,7 @@ impl ZwpPrimarySelectionDeviceV1 {
|
|||
manager: manager.clone(),
|
||||
seat: seat.clone(),
|
||||
data: DeviceData::default(),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -104,12 +107,15 @@ impl Vtable for ZwpPrimarySelectionDeviceV1 {
|
|||
_device: &Rc<ZwpPrimarySelectionDeviceV1>,
|
||||
offer_data: OfferData<Self>,
|
||||
id: ObjectId,
|
||||
) -> Self::Offer {
|
||||
ZwpPrimarySelectionOfferV1 {
|
||||
) -> Rc<Self::Offer> {
|
||||
let rc = Rc::new(ZwpPrimarySelectionOfferV1 {
|
||||
id: id.into(),
|
||||
client: client.clone(),
|
||||
offer_data,
|
||||
}
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, rc);
|
||||
rc
|
||||
}
|
||||
|
||||
fn send_selection(dd: &Self::Device, offer: Self::OfferId) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::ifs::ipc::zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1;
|
||||
use crate::ifs::ipc::{break_offer_loops, destroy_offer, receive, OfferData};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::{MsgParser, MsgParserError};
|
||||
use crate::wire::zwp_primary_selection_offer_v1::*;
|
||||
|
|
@ -12,6 +13,7 @@ pub struct ZwpPrimarySelectionOfferV1 {
|
|||
pub id: ZwpPrimarySelectionOfferV1Id,
|
||||
pub client: Rc<Client>,
|
||||
pub offer_data: OfferData<ZwpPrimarySelectionDeviceV1>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl ZwpPrimarySelectionOfferV1 {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::ifs::ipc::zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1;
|
||||
use crate::ifs::ipc::{add_mime_type, break_source_loops, destroy_source, SourceData};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::{MsgParser, MsgParserError};
|
||||
use crate::wire::zwp_primary_selection_source_v1::*;
|
||||
|
|
@ -12,6 +13,7 @@ use uapi::OwnedFd;
|
|||
pub struct ZwpPrimarySelectionSourceV1 {
|
||||
pub id: ZwpPrimarySelectionSourceV1Id,
|
||||
pub data: SourceData<ZwpPrimarySelectionDeviceV1>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl ZwpPrimarySelectionSourceV1 {
|
||||
|
|
@ -19,6 +21,7 @@ impl ZwpPrimarySelectionSourceV1 {
|
|||
Self {
|
||||
id,
|
||||
data: SourceData::new(client),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -18,6 +19,7 @@ pub struct OrgKdeKwinServerDecoration {
|
|||
id: OrgKdeKwinServerDecorationId,
|
||||
client: Rc<Client>,
|
||||
requested: Cell<bool>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl OrgKdeKwinServerDecoration {
|
||||
|
|
@ -26,6 +28,7 @@ impl OrgKdeKwinServerDecoration {
|
|||
id,
|
||||
client: client.clone(),
|
||||
requested: Cell::new(false),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::globals::{Global, GlobalName};
|
||||
use crate::ifs::org_kde_kwin_server_decoration::OrgKdeKwinServerDecoration;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -33,7 +34,9 @@ impl OrgKdeKwinServerDecorationManagerGlobal {
|
|||
id,
|
||||
client: client.clone(),
|
||||
_version: version,
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
obj.send_default_mode(SERVER);
|
||||
Ok(())
|
||||
|
|
@ -62,6 +65,7 @@ pub struct OrgKdeKwinServerDecorationManager {
|
|||
id: OrgKdeKwinServerDecorationManagerId,
|
||||
client: Rc<Client>,
|
||||
_version: u32,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl OrgKdeKwinServerDecorationManager {
|
||||
|
|
@ -76,6 +80,7 @@ impl OrgKdeKwinServerDecorationManager {
|
|||
let req: Create = self.client.parse(self, parser)?;
|
||||
let _ = self.client.lookup(req.surface)?;
|
||||
let obj = Rc::new(OrgKdeKwinServerDecoration::new(req.id, &self.client));
|
||||
track!(self.client, obj);
|
||||
self.client.add_client_obj(&obj)?;
|
||||
obj.send_mode(SERVER);
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::clientmem::{ClientMem, ClientMemOffset};
|
||||
use crate::format::Format;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::rect::Rect;
|
||||
use crate::render::{Image, Texture};
|
||||
|
|
@ -29,6 +30,7 @@ pub struct WlBuffer {
|
|||
pub texture: CloneCell<Option<Rc<Texture>>>,
|
||||
width: i32,
|
||||
height: i32,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlBuffer {
|
||||
|
|
@ -55,6 +57,7 @@ impl WlBuffer {
|
|||
height,
|
||||
texture: CloneCell::new(None),
|
||||
storage: WlBufferStorage::Dmabuf(img.clone()),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -89,6 +92,7 @@ impl WlBuffer {
|
|||
width,
|
||||
height,
|
||||
texture: CloneCell::new(None),
|
||||
tracker: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::client::Client;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::wire::wl_callback::*;
|
||||
use crate::wire::WlCallbackId;
|
||||
|
|
@ -8,6 +9,7 @@ use thiserror::Error;
|
|||
pub struct WlCallback {
|
||||
client: Rc<Client>,
|
||||
id: WlCallbackId,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlCallback {
|
||||
|
|
@ -15,6 +17,7 @@ impl WlCallback {
|
|||
Self {
|
||||
client: client.clone(),
|
||||
id,
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::client::{Client, ClientError};
|
|||
use crate::globals::{Global, GlobalName};
|
||||
use crate::ifs::wl_region::WlRegion;
|
||||
use crate::ifs::wl_surface::WlSurface;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -18,6 +19,7 @@ pub struct WlCompositor {
|
|||
id: WlCompositorId,
|
||||
client: Rc<Client>,
|
||||
_version: u32,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlCompositorGlobal {
|
||||
|
|
@ -35,7 +37,9 @@ impl WlCompositorGlobal {
|
|||
id,
|
||||
client: client.clone(),
|
||||
_version: version,
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -45,6 +49,7 @@ impl WlCompositor {
|
|||
fn create_surface(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateSurfaceError> {
|
||||
let surface: CreateSurface = self.client.parse(self, parser)?;
|
||||
let surface = Rc::new(WlSurface::new(surface.id, &self.client));
|
||||
track!(self.client, surface);
|
||||
self.client.add_client_obj(&surface)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -52,6 +57,7 @@ impl WlCompositor {
|
|||
fn create_region(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateRegionError> {
|
||||
let region: CreateRegion = self.client.parse(self, parser)?;
|
||||
let region = Rc::new(WlRegion::new(region.id, &self.client));
|
||||
track!(self.client, region);
|
||||
self.client.add_client_obj(®ion)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::client::{Client, ClientError};
|
|||
use crate::globals::GlobalsError;
|
||||
use crate::ifs::wl_callback::WlCallback;
|
||||
use crate::ifs::wl_registry::WlRegistry;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::{Object, ObjectId, WL_DISPLAY_ID};
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -17,8 +18,9 @@ const NO_MEMORY: u32 = 2;
|
|||
const IMPLEMENTATION: u32 = 3;
|
||||
|
||||
pub struct WlDisplay {
|
||||
id: WlDisplayId,
|
||||
client: Rc<Client>,
|
||||
pub id: WlDisplayId,
|
||||
pub client: Rc<Client>,
|
||||
pub tracker: Tracker<WlDisplay>,
|
||||
}
|
||||
|
||||
impl WlDisplay {
|
||||
|
|
@ -26,12 +28,14 @@ impl WlDisplay {
|
|||
Self {
|
||||
id: WL_DISPLAY_ID,
|
||||
client: client.clone(),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn sync(&self, parser: MsgParser<'_, '_>) -> Result<(), SyncError> {
|
||||
let sync: Sync = self.client.parse(self, parser)?;
|
||||
let cb = Rc::new(WlCallback::new(sync.callback, &self.client));
|
||||
track!(self.client, cb);
|
||||
self.client.add_client_obj(&cb)?;
|
||||
cb.send_done();
|
||||
self.client.remove_obj(&*cb)?;
|
||||
|
|
@ -41,6 +45,7 @@ impl WlDisplay {
|
|||
fn get_registry(&self, parser: MsgParser<'_, '_>) -> Result<(), GetRegistryError> {
|
||||
let gr: GetRegistry = self.client.parse(self, parser)?;
|
||||
let registry = Rc::new(WlRegistry::new(gr.registry, &self.client));
|
||||
track!(self.client, registry);
|
||||
self.client.add_client_obj(®istry)?;
|
||||
self.client.state.globals.notify_all(®istry);
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::globals::{Global, GlobalName};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -31,7 +32,9 @@ impl WlDrmGlobal {
|
|||
id,
|
||||
client: client.clone(),
|
||||
_version: version,
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
if let Some(rc) = client.state.render_ctx.get() {
|
||||
obj.send_device(&rc.render_node());
|
||||
|
|
@ -59,6 +62,7 @@ pub struct WlDrm {
|
|||
id: WlDrmId,
|
||||
pub client: Rc<Client>,
|
||||
_version: u32,
|
||||
tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlDrm {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::backend::Output;
|
||||
use crate::client::{Client, ClientError, ClientId};
|
||||
use crate::globals::{Global, GlobalName};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -100,7 +101,9 @@ impl WlOutputGlobal {
|
|||
id,
|
||||
client: client.clone(),
|
||||
version,
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
self.bindings
|
||||
.borrow_mut()
|
||||
|
|
@ -142,6 +145,7 @@ pub struct WlOutput {
|
|||
pub id: WlOutputId,
|
||||
client: Rc<Client>,
|
||||
version: u32,
|
||||
tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
pub const SEND_DONE_SINCE: u32 = 2;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::pixman::Region;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
|
|
@ -13,6 +14,7 @@ pub struct WlRegion {
|
|||
id: WlRegionId,
|
||||
client: Rc<Client>,
|
||||
rect: RefCell<Region>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlRegion {
|
||||
|
|
@ -21,6 +23,7 @@ impl WlRegion {
|
|||
id,
|
||||
client: client.clone(),
|
||||
rect: RefCell::new(Region::new()),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::client::Client;
|
||||
use crate::globals::{Global, GlobalName, GlobalsError};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::{Interface, Object};
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -11,6 +12,7 @@ use thiserror::Error;
|
|||
pub struct WlRegistry {
|
||||
id: WlRegistryId,
|
||||
client: Rc<Client>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlRegistry {
|
||||
|
|
@ -18,6 +20,7 @@ impl WlRegistry {
|
|||
Self {
|
||||
id,
|
||||
client: client.clone(),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ use crate::ifs::wl_seat::wl_pointer::WlPointer;
|
|||
use crate::ifs::wl_seat::wl_touch::WlTouch;
|
||||
use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel;
|
||||
use crate::ifs::wl_surface::WlSurface;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::{Object, ObjectId};
|
||||
use crate::tree::{FloatNode, FoundNode, Node};
|
||||
use crate::utils::asyncevent::AsyncEvent;
|
||||
|
|
@ -41,6 +42,8 @@ pub use event_handling::NodeSeatState;
|
|||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::io::Write;
|
||||
use std::mem;
|
||||
use std::ops::DerefMut;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use uapi::{c, OwnedFd};
|
||||
|
|
@ -266,6 +269,11 @@ impl WlSeatGlobal {
|
|||
self.cursor.get()
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
mem::take(self.pointer_stack.borrow_mut().deref_mut());
|
||||
mem::take(self.found_tree.borrow_mut().deref_mut());
|
||||
}
|
||||
|
||||
pub fn id(&self) -> SeatId {
|
||||
self.seat.id()
|
||||
}
|
||||
|
|
@ -283,7 +291,9 @@ impl WlSeatGlobal {
|
|||
pointers: Default::default(),
|
||||
keyboards: Default::default(),
|
||||
version,
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
obj.send_capabilities();
|
||||
if version >= SEAT_NAME_SINCE {
|
||||
|
|
@ -323,6 +333,7 @@ pub struct WlSeat {
|
|||
pointers: CopyHashMap<WlPointerId, Rc<WlPointer>>,
|
||||
keyboards: CopyHashMap<WlKeyboardId, Rc<WlKeyboard>>,
|
||||
version: u32,
|
||||
tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlSeat {
|
||||
|
|
@ -381,6 +392,7 @@ impl WlSeat {
|
|||
fn get_pointer(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), GetPointerError> {
|
||||
let req: GetPointer = self.client.parse(&**self, parser)?;
|
||||
let p = Rc::new(WlPointer::new(req.id, self));
|
||||
track!(self.client, p);
|
||||
self.client.add_client_obj(&p)?;
|
||||
self.pointers.set(req.id, p);
|
||||
Ok(())
|
||||
|
|
@ -389,6 +401,7 @@ impl WlSeat {
|
|||
fn get_keyboard(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), GetKeyboardError> {
|
||||
let req: GetKeyboard = self.client.parse(&**self, parser)?;
|
||||
let p = Rc::new(WlKeyboard::new(req.id, self));
|
||||
track!(self.client, p);
|
||||
self.client.add_client_obj(&p)?;
|
||||
self.keyboards.set(req.id, p.clone());
|
||||
p.send_keymap(wl_keyboard::XKB_V1, p.keymap_fd()?, self.global.layout_size);
|
||||
|
|
@ -401,6 +414,7 @@ impl WlSeat {
|
|||
fn get_touch(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), GetTouchError> {
|
||||
let req: GetTouch = self.client.parse(&**self, parser)?;
|
||||
let p = Rc::new(WlTouch::new(req.id, self));
|
||||
track!(self.client, p);
|
||||
self.client.add_client_obj(&p)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -409,8 +423,11 @@ impl WlSeat {
|
|||
let _req: Release = self.client.parse(self, parser)?;
|
||||
{
|
||||
let mut bindings = self.global.bindings.borrow_mut();
|
||||
if let Some(hm) = bindings.get_mut(&self.client.id) {
|
||||
hm.remove(&self.id);
|
||||
if let Entry::Occupied(mut hm) = bindings.entry(self.client.id) {
|
||||
hm.get_mut().remove(&self.id);
|
||||
if hm.get().is_empty() {
|
||||
hm.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.client.remove_obj(self)?;
|
||||
|
|
@ -439,8 +456,11 @@ impl Object for WlSeat {
|
|||
fn break_loops(&self) {
|
||||
{
|
||||
let mut bindings = self.global.bindings.borrow_mut();
|
||||
if let Some(hm) = bindings.get_mut(&self.client.id) {
|
||||
hm.remove(&self.id);
|
||||
if let Entry::Occupied(mut hm) = bindings.entry(self.client.id) {
|
||||
hm.get_mut().remove(&self.id);
|
||||
if hm.get().is_empty() {
|
||||
hm.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.pointers.clear();
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ impl NodeSeatState {
|
|||
if last.id() == node_id {
|
||||
break;
|
||||
}
|
||||
last.seat_state().leave(&seat);
|
||||
last.leave(&seat);
|
||||
}
|
||||
seat.state.tree_changed();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use crate::ifs::ipc;
|
|||
use crate::ifs::ipc::wl_data_device::WlDataDevice;
|
||||
use crate::ifs::ipc::wl_data_source::WlDataSource;
|
||||
use crate::ifs::wl_seat::{Dnd, DroppedDnd, WlSeatError, WlSeatGlobal};
|
||||
use crate::ifs::wl_surface::{WlSurface};
|
||||
use crate::ifs::wl_surface::WlSurface;
|
||||
use crate::tree::{FoundNode, Node};
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
use crate::utils::smallmap::SmallMap;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::client::ClientError;
|
||||
use crate::ifs::wl_seat::WlSeat;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -21,6 +22,7 @@ pub(super) const PRESSED: u32 = 1;
|
|||
pub struct WlKeyboard {
|
||||
id: WlKeyboardId,
|
||||
seat: Rc<WlSeat>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlKeyboard {
|
||||
|
|
@ -28,6 +30,7 @@ impl WlKeyboard {
|
|||
Self {
|
||||
id,
|
||||
seat: seat.clone(),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use crate::cursor::Cursor;
|
|||
use crate::fixed::Fixed;
|
||||
use crate::ifs::wl_seat::WlSeat;
|
||||
use crate::ifs::wl_surface::WlSurfaceError;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -34,6 +35,7 @@ pub const POINTER_FRAME_SINCE_VERSION: u32 = 5;
|
|||
pub struct WlPointer {
|
||||
id: WlPointerId,
|
||||
seat: Rc<WlSeat>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlPointer {
|
||||
|
|
@ -41,6 +43,7 @@ impl WlPointer {
|
|||
Self {
|
||||
id,
|
||||
seat: seat.clone(),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::client::ClientError;
|
||||
use crate::ifs::wl_seat::WlSeat;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -26,6 +27,7 @@ const ORIENTATION: u32 = 6;
|
|||
pub struct WlTouch {
|
||||
id: WlTouchId,
|
||||
seat: Rc<WlSeat>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlTouch {
|
||||
|
|
@ -33,6 +35,7 @@ impl WlTouch {
|
|||
Self {
|
||||
id,
|
||||
seat: seat.clone(),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::client::{Client, ClientError};
|
|||
use crate::format::FORMATS;
|
||||
use crate::globals::{Global, GlobalName};
|
||||
use crate::ifs::wl_shm_pool::{WlShmPool, WlShmPoolError};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -18,6 +19,7 @@ pub struct WlShm {
|
|||
_global: Rc<WlShmGlobal>,
|
||||
id: WlShmId,
|
||||
client: Rc<Client>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlShmGlobal {
|
||||
|
|
@ -35,7 +37,9 @@ impl WlShmGlobal {
|
|||
_global: self,
|
||||
id,
|
||||
client: client.clone(),
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
for format in FORMATS {
|
||||
client.event(Format {
|
||||
|
|
@ -59,6 +63,7 @@ impl WlShm {
|
|||
create.fd,
|
||||
create.size as usize,
|
||||
)?);
|
||||
track!(self.client, pool);
|
||||
self.client.add_client_obj(&pool)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::client::{Client, ClientError};
|
|||
use crate::clientmem::ClientMem;
|
||||
use crate::format::{formats, map_wayland_format_id};
|
||||
use crate::ifs::wl_buffer::{WlBuffer, WlBufferError};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -18,6 +19,7 @@ pub struct WlShmPool {
|
|||
client: Rc<Client>,
|
||||
fd: Rc<OwnedFd>,
|
||||
mem: CloneCell<Rc<ClientMem>>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlShmPool {
|
||||
|
|
@ -32,6 +34,7 @@ impl WlShmPool {
|
|||
client: client.clone(),
|
||||
mem: CloneCell::new(Rc::new(ClientMem::new(fd.raw(), len)?)),
|
||||
fd,
|
||||
tracker: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -55,6 +58,7 @@ impl WlShmPool {
|
|||
format,
|
||||
&self.mem.get(),
|
||||
)?);
|
||||
track!(self.client, buffer);
|
||||
self.client.add_client_obj(&buffer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::globals::{Global, GlobalName};
|
||||
use crate::ifs::wl_surface::wl_subsurface::{WlSubsurface, WlSubsurfaceError};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -19,6 +20,7 @@ pub struct WlSubcompositorGlobal {
|
|||
pub struct WlSubcompositor {
|
||||
id: WlSubcompositorId,
|
||||
client: Rc<Client>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WlSubcompositorGlobal {
|
||||
|
|
@ -35,7 +37,9 @@ impl WlSubcompositorGlobal {
|
|||
let obj = Rc::new(WlSubcompositor {
|
||||
id,
|
||||
client: client.clone(),
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -53,6 +57,7 @@ impl WlSubcompositor {
|
|||
let surface = self.client.lookup(req.surface)?;
|
||||
let parent = self.client.lookup(req.parent)?;
|
||||
let subsurface = Rc::new(WlSubsurface::new(req.id, &surface, &parent));
|
||||
track!(self.client, subsurface);
|
||||
self.client.add_client_obj(&subsurface)?;
|
||||
subsurface.install()?;
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use crate::ifs::wl_seat::{Dnd, NodeSeatState, WlSeatGlobal};
|
|||
use crate::ifs::wl_surface::cursor::CursorSurface;
|
||||
use crate::ifs::wl_surface::wl_subsurface::WlSubsurface;
|
||||
use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceRole};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::pixman::Region;
|
||||
use crate::rect::Rect;
|
||||
|
|
@ -26,6 +27,7 @@ use crate::xkbcommon::ModifierState;
|
|||
use crate::NumCell;
|
||||
use ahash::AHashMap;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::rc::Rc;
|
||||
|
|
@ -80,6 +82,13 @@ pub struct WlSurface {
|
|||
xdg: CloneCell<Option<Rc<XdgSurface>>>,
|
||||
cursors: SmallMap<SeatId, Rc<CursorSurface>, 1>,
|
||||
pub dnd_icons: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl Debug for WlSurface {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("WlSurface").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
|
|
@ -176,6 +185,7 @@ impl WlSurface {
|
|||
xdg: Default::default(),
|
||||
cursors: Default::default(),
|
||||
dnd_icons: Default::default(),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +214,7 @@ impl WlSurface {
|
|||
}
|
||||
self.set_role(SurfaceRole::Cursor)?;
|
||||
let cursor = Rc::new(CursorSurface::new(seat, self));
|
||||
track!(self.client, cursor);
|
||||
cursor.handle_buffer_change();
|
||||
self.cursors.insert(seat.id(), cursor.clone());
|
||||
Ok(cursor)
|
||||
|
|
@ -335,6 +346,9 @@ impl WlSurface {
|
|||
}
|
||||
*children = None;
|
||||
}
|
||||
self.buffer.set(None);
|
||||
self.frame_requests.borrow_mut().clear();
|
||||
self.xdg.set(None);
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -358,6 +372,7 @@ impl WlSurface {
|
|||
fn frame(&self, parser: MsgParser<'_, '_>) -> Result<(), FrameError> {
|
||||
let req: Frame = self.parse(parser)?;
|
||||
let cb = Rc::new(WlCallback::new(req.callback, &self.client));
|
||||
track!(self.client, cb);
|
||||
self.client.add_client_obj(&cb)?;
|
||||
self.pending.frame_request.borrow_mut().push(cb);
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::cursor::Cursor;
|
||||
use crate::ifs::wl_seat::WlSeatGlobal;
|
||||
use crate::ifs::wl_surface::WlSurface;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::rect::Rect;
|
||||
use crate::render::Renderer;
|
||||
use std::cell::Cell;
|
||||
|
|
@ -12,6 +13,7 @@ pub struct CursorSurface {
|
|||
hotspot: Cell<(i32, i32)>,
|
||||
pos: Cell<(i32, i32)>,
|
||||
extents: Cell<Rect>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl CursorSurface {
|
||||
|
|
@ -22,6 +24,7 @@ impl CursorSurface {
|
|||
hotspot: Cell::new((0, 0)),
|
||||
pos: Cell::new((0, 0)),
|
||||
extents: Cell::new(Default::default()),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use crate::ifs::wl_surface::{
|
|||
CommitAction, CommitContext, StackElement, SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError,
|
||||
WlSurfaceId,
|
||||
};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::rect::Rect;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
|
|
@ -31,6 +32,7 @@ pub struct WlSubsurface {
|
|||
node: RefCell<Option<LinkedNode<StackElement>>>,
|
||||
depth: NumCell<u32>,
|
||||
pending: PendingSubsurfaceData,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -85,6 +87,7 @@ impl WlSubsurface {
|
|||
node: RefCell::new(None),
|
||||
depth: NumCell::new(0),
|
||||
pending: Default::default(),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use crate::ifs::wl_surface::{
|
|||
CommitAction, CommitContext, SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError,
|
||||
};
|
||||
use crate::ifs::xdg_wm_base::XdgWmBase;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::rect::Rect;
|
||||
use crate::tree::{FindTreeResult, FoundNode, Node, WorkspaceNode};
|
||||
|
|
@ -22,6 +23,7 @@ use crate::wire::xdg_surface::*;
|
|||
use crate::wire::{WlSurfaceId, XdgPopupId, XdgSurfaceId};
|
||||
use crate::NumCell;
|
||||
use std::cell::Cell;
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
|
||||
|
|
@ -64,14 +66,15 @@ pub struct XdgSurface {
|
|||
pub(super) focus_surface: SmallMap<SeatId, Rc<WlSurface>, 1>,
|
||||
seat_state: NodeSeatState,
|
||||
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Debug)]
|
||||
struct PendingXdgSurfaceData {
|
||||
geometry: Cell<Option<Rect>>,
|
||||
}
|
||||
|
||||
trait XdgSurfaceExt {
|
||||
pub trait XdgSurfaceExt: Debug {
|
||||
fn initial_configure(self: Rc<Self>) -> Result<(), XdgSurfaceError> {
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -111,6 +114,7 @@ impl XdgSurface {
|
|||
focus_surface: Default::default(),
|
||||
seat_state: Default::default(),
|
||||
workspace: Default::default(),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -214,6 +218,7 @@ impl XdgSurface {
|
|||
return Err(DestroyError::PopupsNotYetDestroyed);
|
||||
}
|
||||
}
|
||||
self.focus_surface.clear();
|
||||
self.surface.set_xdg_surface(None);
|
||||
self.surface.unset_ext();
|
||||
self.base.surfaces.remove(&self.id);
|
||||
|
|
@ -236,6 +241,7 @@ impl XdgSurface {
|
|||
return Err(GetToplevelError::AlreadyConstructed);
|
||||
}
|
||||
let toplevel = Rc::new(XdgToplevel::new(req.id, self));
|
||||
track!(self.surface.client, toplevel);
|
||||
self.surface.client.add_client_obj(&toplevel)?;
|
||||
self.ext.set(Some(toplevel));
|
||||
Ok(())
|
||||
|
|
@ -261,6 +267,7 @@ impl XdgSurface {
|
|||
return Err(GetPopupError::AlreadyConstructed);
|
||||
}
|
||||
let popup = Rc::new(XdgPopup::new(req.id, self, parent.as_ref(), &positioner)?);
|
||||
track!(self.surface.client, popup);
|
||||
self.surface.client.add_client_obj(&popup)?;
|
||||
if let Some(parent) = &parent {
|
||||
parent.popups.set(req.id, popup.clone());
|
||||
|
|
@ -341,6 +348,9 @@ impl Object for XdgSurface {
|
|||
|
||||
fn break_loops(&self) {
|
||||
self.focus_surface.take();
|
||||
self.ext.take();
|
||||
self.popups.clear();
|
||||
self.workspace.set(None);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use crate::fixed::Fixed;
|
|||
use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal};
|
||||
use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceExt};
|
||||
use crate::ifs::xdg_positioner::{XdgPositioned, XdgPositioner, CA};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::rect::Rect;
|
||||
use crate::render::Renderer;
|
||||
|
|
@ -15,6 +16,7 @@ use crate::utils::linkedlist::LinkedNode;
|
|||
use crate::wire::xdg_popup::*;
|
||||
use crate::wire::XdgPopupId;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
|
||||
|
|
@ -32,6 +34,13 @@ pub struct XdgPopup {
|
|||
display_link: RefCell<Option<LinkedNode<Rc<dyn Node>>>>,
|
||||
workspace_link: RefCell<Option<LinkedNode<Rc<dyn Node>>>>,
|
||||
pos: RefCell<XdgPositioned>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl Debug for XdgPopup {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("XdgPopup").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl XdgPopup {
|
||||
|
|
@ -54,6 +63,7 @@ impl XdgPopup {
|
|||
display_link: RefCell::new(None),
|
||||
workspace_link: RefCell::new(None),
|
||||
pos: RefCell::new(pos),
|
||||
tracker: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use crate::cursor::KnownCursor;
|
|||
use crate::fixed::Fixed;
|
||||
use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal};
|
||||
use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceExt};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::rect::Rect;
|
||||
use crate::render::Renderer;
|
||||
|
|
@ -21,7 +22,9 @@ use crate::{bugs, NumCell};
|
|||
use ahash::{AHashMap, AHashSet};
|
||||
use num_derive::FromPrimitive;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
|
||||
|
|
@ -78,6 +81,13 @@ pub struct XdgToplevel {
|
|||
min_height: Cell<Option<i32>>,
|
||||
max_width: Cell<Option<i32>>,
|
||||
max_height: Cell<Option<i32>>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl Debug for XdgToplevel {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("XdgToplevel").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl XdgToplevel {
|
||||
|
|
@ -103,6 +113,7 @@ impl XdgToplevel {
|
|||
min_height: Cell::new(None),
|
||||
max_width: Cell::new(None),
|
||||
max_height: Cell::new(None),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -158,19 +169,30 @@ impl XdgToplevel {
|
|||
})
|
||||
}
|
||||
|
||||
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
|
||||
let _req: Destroy = self.xdg.surface.client.parse(self, parser)?;
|
||||
fn destroy(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
|
||||
let _req: Destroy = self.xdg.surface.client.parse(self.deref(), parser)?;
|
||||
self.destroy_node(true);
|
||||
self.xdg.ext.set(None);
|
||||
if let Some(parent) = self.parent_node.take() {
|
||||
parent.remove_child(self);
|
||||
}
|
||||
{
|
||||
let mut children = self.children.borrow_mut();
|
||||
let parent = self.parent.get();
|
||||
let mut parent_children = match &parent {
|
||||
Some(p) => Some(p.children.borrow_mut()),
|
||||
_ => None,
|
||||
};
|
||||
for (_, child) in children.drain() {
|
||||
child.parent.set(self.parent.get());
|
||||
child.parent.set(parent.clone());
|
||||
if let Some(parent_children) = &mut parent_children {
|
||||
parent_children.insert(child.id, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
if let Some(parent) = self.parent.take() {
|
||||
parent.children.borrow_mut().remove(&self.id);
|
||||
}
|
||||
}
|
||||
self.xdg.surface.client.remove_obj(self.deref())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -388,9 +410,6 @@ impl Object for XdgToplevel {
|
|||
|
||||
fn break_loops(&self) {
|
||||
self.destroy_node(true);
|
||||
if let Some(parent) = self.parent_node.take() {
|
||||
parent.remove_child(self);
|
||||
}
|
||||
self.parent.set(None);
|
||||
let _children = mem::take(&mut *self.children.borrow_mut());
|
||||
}
|
||||
|
|
@ -411,6 +430,7 @@ impl Node for XdgToplevel {
|
|||
if let Some(parent) = self.parent_node.take() {
|
||||
if detach {
|
||||
parent.remove_child(self);
|
||||
self.xdg.surface.client.state.tree_changed();
|
||||
}
|
||||
}
|
||||
self.toplevel_history.take();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::ifs::xdg_wm_base::XdgWmBase;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::rect::Rect;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
|
|
@ -69,6 +70,7 @@ pub struct XdgPositioner {
|
|||
base: Rc<XdgWmBase>,
|
||||
client: Rc<Client>,
|
||||
position: RefCell<XdgPositioned>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
|
|
@ -146,6 +148,7 @@ impl XdgPositioner {
|
|||
client: client.clone(),
|
||||
base: base.clone(),
|
||||
position: RefCell::new(Default::default()),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::client::{Client, ClientError};
|
|||
use crate::globals::{Global, GlobalName};
|
||||
use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError};
|
||||
use crate::ifs::xdg_positioner::XdgPositioner;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -32,6 +33,7 @@ pub struct XdgWmBase {
|
|||
client: Rc<Client>,
|
||||
pub version: u32,
|
||||
pub(super) surfaces: CopyHashMap<XdgSurfaceId, Rc<XdgSurface>>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl XdgWmBaseGlobal {
|
||||
|
|
@ -50,7 +52,9 @@ impl XdgWmBaseGlobal {
|
|||
client: client.clone(),
|
||||
version,
|
||||
surfaces: Default::default(),
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -80,6 +84,7 @@ impl XdgWmBase {
|
|||
) -> Result<(), CreatePositionerError> {
|
||||
let req: CreatePositioner = self.client.parse(&**self, parser)?;
|
||||
let pos = Rc::new(XdgPositioner::new(self, req.id, &self.client));
|
||||
track!(self.client, pos);
|
||||
self.client.add_client_obj(&pos)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -91,6 +96,7 @@ impl XdgWmBase {
|
|||
let req: GetXdgSurface = self.client.parse(&**self, parser)?;
|
||||
let surface = self.client.lookup(req.surface)?;
|
||||
let xdg_surface = Rc::new(XdgSurface::new(self, req.id, &surface));
|
||||
track!(self.client, xdg_surface);
|
||||
self.client.add_client_obj(&xdg_surface)?;
|
||||
xdg_surface.install()?;
|
||||
self.surfaces.set(req.id, xdg_surface);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use crate::drm::dma::{DmaBuf, DmaBufPlane};
|
|||
use crate::drm::INVALID_MODIFIER;
|
||||
use crate::ifs::wl_buffer::WlBuffer;
|
||||
use crate::ifs::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -28,6 +29,7 @@ pub struct ZwpLinuxBufferParamsV1 {
|
|||
pub parent: Rc<ZwpLinuxDmabufV1>,
|
||||
planes: RefCell<AHashMap<u32, Add>>,
|
||||
used: Cell<bool>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl ZwpLinuxBufferParamsV1 {
|
||||
|
|
@ -37,6 +39,7 @@ impl ZwpLinuxBufferParamsV1 {
|
|||
parent: parent.clone(),
|
||||
planes: RefCell::new(Default::default()),
|
||||
used: Cell::new(false),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -120,6 +123,7 @@ impl ZwpLinuxBufferParamsV1 {
|
|||
format,
|
||||
&img,
|
||||
));
|
||||
track!(self.parent.client, buffer);
|
||||
if is_client_id {
|
||||
self.parent.client.add_client_obj(&buffer)?;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::client::{Client, ClientError};
|
|||
use crate::drm::INVALID_MODIFIER;
|
||||
use crate::globals::{Global, GlobalName};
|
||||
use crate::ifs::zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -29,7 +30,9 @@ impl ZwpLinuxDmabufV1Global {
|
|||
id,
|
||||
client: client.clone(),
|
||||
_version: version,
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
if let Some(ctx) = client.state.render_ctx.get() {
|
||||
let formats = ctx.formats();
|
||||
|
|
@ -68,6 +71,7 @@ pub struct ZwpLinuxDmabufV1 {
|
|||
id: ZwpLinuxDmabufV1Id,
|
||||
pub client: Rc<Client>,
|
||||
_version: u32,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl ZwpLinuxDmabufV1 {
|
||||
|
|
@ -96,6 +100,7 @@ impl ZwpLinuxDmabufV1 {
|
|||
fn create_params(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), CreateParamsError> {
|
||||
let req: CreateParams = self.client.parse(&**self, parser)?;
|
||||
let params = Rc::new(ZwpLinuxBufferParamsV1::new(req.params_id, self));
|
||||
track!(self.client, params);
|
||||
self.client.add_client_obj(¶ms)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::globals::{Global, GlobalName};
|
||||
use crate::ifs::zxdg_toplevel_decoration_v1::ZxdgToplevelDecorationV1;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::{MsgParser, MsgParserError};
|
||||
use crate::wire::zxdg_decoration_manager_v1::*;
|
||||
|
|
@ -26,7 +27,9 @@ impl ZxdgDecorationManagerV1Global {
|
|||
id,
|
||||
client: client.clone(),
|
||||
_version: version,
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -54,6 +57,7 @@ pub struct ZxdgDecorationManagerV1 {
|
|||
id: ZxdgDecorationManagerV1Id,
|
||||
client: Rc<Client>,
|
||||
_version: u32,
|
||||
tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl ZxdgDecorationManagerV1 {
|
||||
|
|
@ -70,6 +74,7 @@ impl ZxdgDecorationManagerV1 {
|
|||
let req: GetToplevelDecoration = self.client.parse(self, parser)?;
|
||||
let tl = self.client.lookup(req.toplevel)?;
|
||||
let obj = Rc::new(ZxdgToplevelDecorationV1::new(req.id, &self.client, &tl));
|
||||
track!(self.client, obj);
|
||||
self.client.add_client_obj(&obj)?;
|
||||
obj.do_send_configure();
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::{Decoration, XdgToplevel};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::{MsgParser, MsgParserError};
|
||||
use crate::wire::zxdg_toplevel_decoration_v1::*;
|
||||
|
|
@ -14,6 +15,7 @@ pub struct ZxdgToplevelDecorationV1 {
|
|||
pub id: ZxdgToplevelDecorationV1Id,
|
||||
pub client: Rc<Client>,
|
||||
pub toplevel: Rc<XdgToplevel>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl ZxdgToplevelDecorationV1 {
|
||||
|
|
@ -26,6 +28,7 @@ impl ZxdgToplevelDecorationV1 {
|
|||
id,
|
||||
client: client.clone(),
|
||||
toplevel: toplevel.clone(),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
267
src/leaks.rs
Normal file
267
src/leaks.rs
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
pub use leaks::*;
|
||||
|
||||
#[cfg(not(feature = "rc_tracking"))]
|
||||
#[macro_use]
|
||||
mod leaks {
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub fn init() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
pub fn log_leaked() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
pub struct Tracker<T> {
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Default for Tracker<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! track {
|
||||
($client:expr, $rc:expr) => {
|
||||
let _ = $rc.tracker;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "rc_tracking")]
|
||||
#[macro_use]
|
||||
mod leaks {
|
||||
use crate::client::ClientId;
|
||||
use crate::utils::ptr_ext::{MutPtrExt, PtrExt};
|
||||
use ahash::{AHashMap, AHashSet};
|
||||
use backtrace::Backtrace;
|
||||
use std::alloc::{GlobalAlloc, Layout};
|
||||
use std::marker::PhantomData;
|
||||
use std::{any, mem, ptr};
|
||||
use uapi::c;
|
||||
|
||||
#[thread_local]
|
||||
static mut MAP: *mut AHashMap<u64, Tracked> = ptr::null_mut();
|
||||
|
||||
#[thread_local]
|
||||
static mut ID: u64 = 0;
|
||||
|
||||
pub fn init() {
|
||||
unsafe {
|
||||
MAP = Box::into_raw(Box::new(AHashMap::new()));
|
||||
ALLOCATIONS = Box::into_raw(Box::new(AHashMap::new()));
|
||||
IN_ALLOCATOR = 0;
|
||||
INITIALIZED = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn log_containers(prefix: &str, allocation: &mut Allocation, offset: usize, logged: &mut AHashSet<*mut u8>) {
|
||||
log::info!(
|
||||
"{}Contained in allocation {:?} at offset {}. Backtrace:",
|
||||
prefix,
|
||||
allocation.addr,
|
||||
offset
|
||||
);
|
||||
allocation.backtrace.resolve();
|
||||
let bt = format!("{:?}", allocation.backtrace);
|
||||
for line in bt.lines() {
|
||||
log::info!("{} {}", prefix, line);
|
||||
}
|
||||
|
||||
if !logged.insert(allocation.addr) {
|
||||
log::error!("{} LOOP", prefix);
|
||||
} else {
|
||||
let containers = find_allocations_pointing_to(allocation.addr);
|
||||
if containers.is_empty() {
|
||||
log::error!("{} NO REFERENCES", prefix);
|
||||
}
|
||||
let new_prefix = format!("{} ", prefix);
|
||||
for (mut allocation, offset) in containers {
|
||||
log_containers(&new_prefix, &mut allocation, offset, logged);
|
||||
}
|
||||
logged.remove(&allocation.addr);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn log_leaked() {
|
||||
unsafe {
|
||||
IN_ALLOCATOR += 1;
|
||||
let mut map: AHashMap<ClientId, Vec<(u64, Tracked)>> = AHashMap::new();
|
||||
for (id, obj) in MAP.deref_mut().drain() {
|
||||
map.entry(obj.client).or_default().push((id, obj));
|
||||
}
|
||||
for (_, mut objs) in map.drain() {
|
||||
if objs.len() == 0 {
|
||||
continue;
|
||||
}
|
||||
objs.sort_by_key(|o| o.0);
|
||||
log::info!("Client {} leaked {} objects", objs[0].1.client, objs.len());
|
||||
for (_, obj) in objs {
|
||||
let time = chrono::NaiveDateTime::from_timestamp(obj.time.0, obj.time.1);
|
||||
log::info!(
|
||||
" [{}] {}",
|
||||
time.format("%H:%M:%S%.3f"),
|
||||
obj.ty,
|
||||
);
|
||||
match find_allocation_containing(obj.addr) {
|
||||
Some(mut alloc) => log_containers(" ", &mut alloc, 0, &mut AHashSet::new()),
|
||||
_ => log::error!(" Not contained in any allocation??"),
|
||||
}
|
||||
}
|
||||
}
|
||||
IN_ALLOCATOR -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Tracked {
|
||||
addr: usize,
|
||||
client: ClientId,
|
||||
ty: &'static str,
|
||||
time: (i64, u32),
|
||||
}
|
||||
|
||||
pub struct Tracker<T> {
|
||||
id: u64,
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Default for Tracker<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
id: unsafe {
|
||||
let id = ID;
|
||||
ID += 1;
|
||||
id
|
||||
},
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Tracker<T> {
|
||||
pub fn register(&self, client_id: ClientId) {
|
||||
unsafe {
|
||||
let mut time = c::timespec {
|
||||
tv_sec: 0,
|
||||
tv_nsec: 0,
|
||||
};
|
||||
uapi::clock_gettime(c::CLOCK_REALTIME, &mut time).unwrap();
|
||||
IN_ALLOCATOR += 1;
|
||||
MAP.deref_mut().insert(
|
||||
self.id,
|
||||
Tracked {
|
||||
addr: self as *const _ as usize,
|
||||
client: client_id,
|
||||
ty: any::type_name::<T>(),
|
||||
time: (time.tv_sec as i64, time.tv_nsec as u32),
|
||||
},
|
||||
);
|
||||
IN_ALLOCATOR -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for Tracker<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
MAP.deref_mut().remove(&self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! track {
|
||||
($client:expr, $rc:expr) => {
|
||||
($rc)
|
||||
.tracker
|
||||
.register($client.id);
|
||||
};
|
||||
}
|
||||
|
||||
struct TracingAllocator;
|
||||
|
||||
#[global_allocator]
|
||||
static GLOBAL: TracingAllocator = TracingAllocator;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Allocation {
|
||||
pub addr: *mut u8,
|
||||
pub len: usize,
|
||||
pub backtrace: Backtrace,
|
||||
}
|
||||
|
||||
#[thread_local]
|
||||
static mut ALLOCATIONS: *mut AHashMap<*mut u8, Allocation> = ptr::null_mut();
|
||||
|
||||
#[thread_local]
|
||||
static mut IN_ALLOCATOR: u32 = 1;
|
||||
|
||||
#[thread_local]
|
||||
static mut INITIALIZED: bool = false;
|
||||
|
||||
unsafe impl GlobalAlloc for TracingAllocator {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
let res = c::calloc(layout.size(), 1) as *mut u8;
|
||||
if IN_ALLOCATOR == 0 {
|
||||
IN_ALLOCATOR = 1;
|
||||
ALLOCATIONS.deref_mut().insert(
|
||||
res,
|
||||
Allocation {
|
||||
addr: res,
|
||||
len: layout.size(),
|
||||
backtrace: Backtrace::new_unresolved(),
|
||||
},
|
||||
);
|
||||
IN_ALLOCATOR = 0;
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||
if INITIALIZED {
|
||||
ALLOCATIONS.deref_mut().remove(&ptr);
|
||||
}
|
||||
c::memset(ptr as _, 0, layout.size());
|
||||
c::free(ptr as _);
|
||||
}
|
||||
}
|
||||
|
||||
fn find_allocations_pointing_to(addr: *mut u8) -> Vec<(Allocation, usize)> {
|
||||
unsafe {
|
||||
IN_ALLOCATOR += 1;
|
||||
let mut res = vec![];
|
||||
for allocation in ALLOCATIONS.deref().values() {
|
||||
let num = allocation.len / mem::size_of::<usize>();
|
||||
let elements = std::slice::from_raw_parts(allocation.addr as *const *mut u8, num);
|
||||
for (offset, pos) in elements.iter().enumerate() {
|
||||
if *pos == addr {
|
||||
res.push((allocation.clone(), offset * mem::size_of::<usize>()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
IN_ALLOCATOR -= 1;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
fn find_allocation_containing(addr: usize) -> Option<Allocation> {
|
||||
unsafe {
|
||||
IN_ALLOCATOR += 1;
|
||||
let mut res = None;
|
||||
for allocation in ALLOCATIONS.deref().values() {
|
||||
let aaddr = allocation.addr as usize;
|
||||
if aaddr <= addr && addr < aaddr + allocation.len {
|
||||
res = Some(allocation.clone());
|
||||
break;
|
||||
}
|
||||
}
|
||||
IN_ALLOCATOR -= 1;
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/main.rs
28
src/main.rs
|
|
@ -1,4 +1,11 @@
|
|||
#![feature(c_variadic, thread_local, label_break_value, ptr_metadata)]
|
||||
#![feature(
|
||||
c_variadic,
|
||||
thread_local,
|
||||
label_break_value,
|
||||
ptr_metadata,
|
||||
linkage,
|
||||
const_type_name
|
||||
)]
|
||||
#![allow(
|
||||
clippy::len_zero,
|
||||
clippy::needless_lifetimes,
|
||||
|
|
@ -32,14 +39,18 @@ use crate::wheel::WheelError;
|
|||
use acceptor::Acceptor;
|
||||
use async_engine::AsyncEngine;
|
||||
use event_loop::EventLoop;
|
||||
use isnt::std_1::primitive::IsntMutPtrExt;
|
||||
use log::LevelFilter;
|
||||
use std::cell::Cell;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use wheel::Wheel;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
#[macro_use]
|
||||
pub mod leaks;
|
||||
mod acceptor;
|
||||
mod async_engine;
|
||||
mod backend;
|
||||
|
|
@ -70,6 +81,15 @@ mod wire;
|
|||
mod xkbcommon;
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
extern "C" {
|
||||
#[linkage = "extern_weak"]
|
||||
static BYTEHOUND_REACHED_MAIN: *mut bool;
|
||||
}
|
||||
if BYTEHOUND_REACHED_MAIN.is_not_null() {
|
||||
*BYTEHOUND_REACHED_MAIN = true;
|
||||
}
|
||||
}
|
||||
env_logger::builder()
|
||||
.filter_level(LevelFilter::Info)
|
||||
.filter_level(LevelFilter::Debug)
|
||||
|
|
@ -102,6 +122,7 @@ enum MainError {
|
|||
}
|
||||
|
||||
fn main_() -> Result<(), MainError> {
|
||||
leaks::init();
|
||||
render::init()?;
|
||||
clientmem::init()?;
|
||||
let el = EventLoop::new()?;
|
||||
|
|
@ -136,5 +157,10 @@ fn main_() -> Result<(), MainError> {
|
|||
Acceptor::install(&state)?;
|
||||
let _backend = XorgBackend::new(&state)?;
|
||||
el.run()?;
|
||||
state.clients.clear();
|
||||
for (_, seat) in state.globals.seats.lock().deref() {
|
||||
seat.clear();
|
||||
}
|
||||
leaks::log_leaked();
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use crate::utils::linkedlist::{LinkedList, LinkedNode, NodeRef};
|
|||
use crate::{NumCell, State};
|
||||
use ahash::AHashMap;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::mem;
|
||||
use std::ops::DerefMut;
|
||||
use std::rc::Rc;
|
||||
|
|
@ -55,6 +56,12 @@ pub struct ContainerNode {
|
|||
seats: RefCell<AHashMap<SeatId, SeatState>>,
|
||||
}
|
||||
|
||||
impl Debug for ContainerNode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("ContainerNode").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ContainerChild {
|
||||
pub node: Rc<dyn Node>,
|
||||
pub body: Cell<Rect>,
|
||||
|
|
@ -318,7 +325,7 @@ impl ContainerNode {
|
|||
dist_left,
|
||||
dist_right,
|
||||
} => {
|
||||
let prev = op.child.prev();
|
||||
let prev = op.child.prev().unwrap();
|
||||
let prev_body = prev.body.get();
|
||||
let child_body = op.child.body.get();
|
||||
let (prev_factor, child_factor) = match self.split.get() {
|
||||
|
|
@ -458,7 +465,7 @@ impl Node for ContainerNode {
|
|||
if seat_data.x < body.x2() {
|
||||
let op = if seat_data.x < body.x1() {
|
||||
SeatOpKind::Resize {
|
||||
dist_left: seat_data.x - child.prev().body.get().x2(),
|
||||
dist_left: seat_data.x - child.prev().unwrap().body.get().x2(),
|
||||
dist_right: body.x1() - seat_data.x,
|
||||
}
|
||||
} else {
|
||||
|
|
@ -473,7 +480,7 @@ impl Node for ContainerNode {
|
|||
if seat_data.y < body.y1() {
|
||||
let op = if seat_data.y < body.y1() - CONTAINER_TITLE_HEIGHT {
|
||||
SeatOpKind::Resize {
|
||||
dist_left: seat_data.y - child.prev().body.get().y2(),
|
||||
dist_left: seat_data.y - child.prev().unwrap().body.get().y2(),
|
||||
dist_right: body.y1() - seat_data.y,
|
||||
}
|
||||
} else {
|
||||
|
|
@ -528,6 +535,7 @@ impl Node for ContainerNode {
|
|||
};
|
||||
let num_children = self.num_children.fetch_sub(1) - 1;
|
||||
if num_children == 0 {
|
||||
self.seats.borrow_mut().clear();
|
||||
self.parent.get().remove_child(self);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use crate::xkbcommon::ModifierState;
|
|||
use crate::NumCell;
|
||||
pub use container::*;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt::Display;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
pub use workspace::*;
|
||||
|
|
@ -306,6 +306,12 @@ pub struct OutputNode {
|
|||
pub seat_state: NodeSeatState,
|
||||
}
|
||||
|
||||
impl Debug for OutputNode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("OutputNode").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for OutputNode {
|
||||
fn id(&self) -> NodeId {
|
||||
self.id.into()
|
||||
|
|
@ -375,6 +381,12 @@ pub struct FloatNode {
|
|||
pub seat_state: NodeSeatState,
|
||||
}
|
||||
|
||||
impl Debug for FloatNode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("FloatNode").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for FloatNode {
|
||||
fn id(&self) -> NodeId {
|
||||
self.id.into()
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use crate::tree::container::ContainerNode;
|
|||
use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, OutputNode};
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
use crate::utils::linkedlist::LinkedList;
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
tree_id!(WorkspaceNodeId);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ pub struct AsyncEvent {
|
|||
}
|
||||
|
||||
impl AsyncEvent {
|
||||
pub fn clear(&self) {
|
||||
self.waker.take();
|
||||
}
|
||||
|
||||
pub fn trigger(&self) {
|
||||
self.triggers.fetch_add(1);
|
||||
if let Some(waker) = self.waker.take() {
|
||||
|
|
|
|||
|
|
@ -65,9 +65,7 @@ impl OutBufferSwapchain {
|
|||
|
||||
pub fn commit(&mut self) {
|
||||
if self.cur.write_pos > 0 {
|
||||
let new = self.free.pop().unwrap_or_else(|| {
|
||||
Default::default()
|
||||
});
|
||||
let new = self.free.pop().unwrap_or_else(|| Default::default());
|
||||
let old = mem::replace(&mut self.cur, new);
|
||||
self.pending.push_back(old);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::utils::linkedlist::NodeRef;
|
||||
use crate::utils::ptr_ext::{MutPtrExt, PtrExt};
|
||||
use std::cell::UnsafeCell;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
|
@ -8,6 +9,12 @@ pub struct CloneCell<T: UnsafeCellCloneSafe> {
|
|||
data: UnsafeCell<T>,
|
||||
}
|
||||
|
||||
impl<T: UnsafeCellCloneSafe + Debug> Debug for CloneCell<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
unsafe { self.data.get().deref().fmt(f) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: UnsafeCellCloneSafe> CloneCell<T> {
|
||||
pub fn new(t: T) -> Self {
|
||||
Self {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::utils::ptr_ext::PtrExt;
|
||||
use crate::NumCell;
|
||||
use std::cell::Cell;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::ops::Deref;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
|
|
@ -9,6 +9,12 @@ pub struct LinkedList<T> {
|
|||
root: LinkedNode<T>,
|
||||
}
|
||||
|
||||
impl<T: Debug> Debug for LinkedList<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_list().entries(self.iter()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for LinkedList<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
|
|
@ -18,10 +24,10 @@ impl<T> Default for LinkedList<T> {
|
|||
impl<T> LinkedList<T> {
|
||||
pub fn new() -> Self {
|
||||
let node = Box::into_raw(Box::new(NodeData {
|
||||
rc: NumCell::new(3),
|
||||
rc: NumCell::new(1),
|
||||
prev: Cell::new(NonNull::dangling()),
|
||||
next: Cell::new(NonNull::dangling()),
|
||||
data: MaybeUninit::uninit(),
|
||||
data: None,
|
||||
}));
|
||||
unsafe {
|
||||
node.deref().prev.set(NonNull::new_unchecked(node));
|
||||
|
|
@ -151,11 +157,17 @@ pub struct LinkedNode<T> {
|
|||
data: NonNull<NodeData<T>>,
|
||||
}
|
||||
|
||||
impl<T: Debug> Debug for LinkedNode<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
unsafe { self.data.as_ref().data.as_ref().unwrap_unchecked().fmt(f) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for LinkedNode<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { self.data.as_ref().data.assume_init_ref() }
|
||||
unsafe { self.data.as_ref().data.as_ref().unwrap_unchecked() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,11 +175,17 @@ pub struct NodeRef<T> {
|
|||
data: NonNull<NodeData<T>>,
|
||||
}
|
||||
|
||||
impl<T: Debug> Debug for NodeRef<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
unsafe { self.data.as_ref().data.as_ref().unwrap_unchecked().fmt(f) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for NodeRef<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { self.data.as_ref().data.assume_init_ref() }
|
||||
unsafe { self.data.as_ref().data.as_ref().unwrap_unchecked() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -197,22 +215,16 @@ impl<T> NodeRef<T> {
|
|||
unsafe { append(self.data, t) }
|
||||
}
|
||||
|
||||
pub fn prev(&self) -> NodeRef<T> {
|
||||
pub fn prev(&self) -> Option<NodeRef<T>> {
|
||||
unsafe {
|
||||
let data = self.data.as_ref();
|
||||
let other = data.prev.get();
|
||||
other.as_ref().rc.fetch_add(1);
|
||||
NodeRef { data: other }
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn next(&self) -> NodeRef<T> {
|
||||
unsafe {
|
||||
let data = self.data.as_ref();
|
||||
let other = data.next.get();
|
||||
other.as_ref().rc.fetch_add(1);
|
||||
NodeRef { data: other }
|
||||
if other.as_ref().data.is_some() {
|
||||
other.as_ref().rc.fetch_add(1);
|
||||
Some(NodeRef { data: other })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -221,7 +233,7 @@ struct NodeData<T> {
|
|||
rc: NumCell<usize>,
|
||||
prev: Cell<NonNull<NodeData<T>>>,
|
||||
next: Cell<NonNull<NodeData<T>>>,
|
||||
data: MaybeUninit<T>,
|
||||
data: Option<T>,
|
||||
}
|
||||
|
||||
unsafe fn dec_ref_count<T>(slf: NonNull<NodeData<T>>, n: usize) {
|
||||
|
|
@ -237,8 +249,10 @@ impl<T> Drop for LinkedNode<T> {
|
|||
let data = self.data.as_ref();
|
||||
data.prev.get().as_ref().next.set(data.next.get());
|
||||
data.next.get().as_ref().prev.set(data.prev.get());
|
||||
data.prev.set(self.data);
|
||||
data.next.set(self.data);
|
||||
}
|
||||
dec_ref_count(self.data, 3);
|
||||
dec_ref_count(self.data, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -263,10 +277,10 @@ impl<T> LinkedNode<T> {
|
|||
unsafe fn prepend<T>(data: NonNull<NodeData<T>>, t: T) -> LinkedNode<T> {
|
||||
let dref = data.as_ref();
|
||||
let node = NonNull::new_unchecked(Box::into_raw(Box::new(NodeData {
|
||||
rc: NumCell::new(3),
|
||||
rc: NumCell::new(1),
|
||||
prev: Cell::new(dref.prev.get()),
|
||||
next: Cell::new(data),
|
||||
data: MaybeUninit::new(t),
|
||||
data: Some(t),
|
||||
})));
|
||||
dref.prev.get().as_ref().next.set(node);
|
||||
dref.prev.set(node);
|
||||
|
|
@ -276,10 +290,10 @@ unsafe fn prepend<T>(data: NonNull<NodeData<T>>, t: T) -> LinkedNode<T> {
|
|||
unsafe fn append<T>(data: NonNull<NodeData<T>>, t: T) -> LinkedNode<T> {
|
||||
let dref = data.as_ref();
|
||||
let node = NonNull::new_unchecked(Box::into_raw(Box::new(NodeData {
|
||||
rc: NumCell::new(3),
|
||||
rc: NumCell::new(1),
|
||||
prev: Cell::new(data),
|
||||
next: Cell::new(dref.next.get()),
|
||||
data: MaybeUninit::new(t),
|
||||
data: Some(t),
|
||||
})));
|
||||
dref.next.get().as_ref().prev.set(node);
|
||||
dref.next.set(node);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ pub mod debug_fn;
|
|||
pub mod errorfmt;
|
||||
pub mod linkedlist;
|
||||
pub mod numcell;
|
||||
pub mod oneshot;
|
||||
pub mod ptr_ext;
|
||||
pub mod queue;
|
||||
pub mod smallmap;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use std::cell::Cell;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::ops::{Add, BitAnd, BitOr, Sub};
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -6,6 +7,12 @@ pub struct NumCell<T> {
|
|||
t: Cell<T>,
|
||||
}
|
||||
|
||||
impl<T: Copy + Debug> Debug for NumCell<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
self.t.get().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> NumCell<T> {
|
||||
#[inline(always)]
|
||||
pub fn new(t: T) -> Self {
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
use std::cell::Cell;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::task::{Context, Poll, Waker};
|
||||
|
||||
pub fn oneshot<T>() -> (OneshotTx<T>, OneshotRx<T>) {
|
||||
let os = Rc::new(Oneshot {
|
||||
data: Cell::new(None),
|
||||
waiter: Cell::new(None),
|
||||
});
|
||||
(OneshotTx { data: os.clone() }, OneshotRx { data: os })
|
||||
}
|
||||
|
||||
struct Oneshot<T> {
|
||||
data: Cell<Option<T>>,
|
||||
waiter: Cell<Option<Waker>>,
|
||||
}
|
||||
|
||||
pub struct OneshotTx<T> {
|
||||
data: Rc<Oneshot<T>>,
|
||||
}
|
||||
|
||||
pub struct OneshotRx<T> {
|
||||
data: Rc<Oneshot<T>>,
|
||||
}
|
||||
|
||||
impl<T> OneshotTx<T> {
|
||||
pub fn send(self, t: T) {
|
||||
self.data.data.set(Some(t));
|
||||
if let Some(waiter) = self.data.waiter.replace(None) {
|
||||
waiter.wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Future for OneshotRx<T> {
|
||||
type Output = T;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
if let Some(data) = self.data.data.replace(None) {
|
||||
Poll::Ready(data)
|
||||
} else {
|
||||
self.data.waiter.set(Some(cx.waker().clone()));
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -35,6 +35,7 @@ impl<T> AsyncQueue<T> {
|
|||
|
||||
pub fn clear(&self) {
|
||||
mem::take(&mut *self.data.borrow_mut());
|
||||
mem::take(&mut *self.waiters.borrow_mut());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,23 @@ use crate::utils::clonecell::UnsafeCellCloneSafe;
|
|||
use crate::utils::ptr_ext::{MutPtrExt, PtrExt};
|
||||
use smallvec::SmallVec;
|
||||
use std::cell::UnsafeCell;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::mem;
|
||||
|
||||
pub struct SmallMap<K, V, const N: usize> {
|
||||
m: UnsafeCell<SmallVec<[(K, V); N]>>,
|
||||
}
|
||||
|
||||
impl<K: Debug, V: Debug, const N: usize> Debug for SmallMap<K, V, N> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
unsafe {
|
||||
f.debug_map()
|
||||
.entries(self.m.get().deref().iter().map(|e| (&e.0, &e.1)))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, const N: usize> Default for SmallMap<K, V, N> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
|
|
|||
2
todo.md
2
todo.md
|
|
@ -9,7 +9,6 @@
|
|||
- Workspaces
|
||||
- Float moving
|
||||
- Highlighting active
|
||||
- dnd
|
||||
- presentation time
|
||||
- viewporter
|
||||
- session lock
|
||||
|
|
@ -19,3 +18,4 @@
|
|||
- Container resizing
|
||||
- clipboard
|
||||
- primary selection
|
||||
- dnd
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue