1
0
Fork 0
forked from wry/wry

autocommit 2022-02-11 02:28:11 CET

This commit is contained in:
Julian Orth 2022-02-11 02:28:11 +01:00
parent 83c3fb99f9
commit 9b8e1ac29f
63 changed files with 690 additions and 122 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
.*
!.gitignore
!/.cargo
/target

39
Cargo.lock generated
View file

@ -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"

View file

@ -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 = []

View file

@ -1,4 +1,5 @@
use crate::fixed::Fixed;
use std::fmt::Debug;
use std::rc::Rc;
linear_ids!(OutputIds, OutputId);

View file

@ -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,
}

View file

@ -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;

View file

@ -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();

View file

@ -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);

View file

@ -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);

View file

@ -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) {

View file

@ -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(())

View file

@ -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 {

View file

@ -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),
}
}

View file

@ -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(())

View file

@ -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) {

View file

@ -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 {

View file

@ -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(),
}
}

View file

@ -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(),
}
}

View file

@ -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(())

View file

@ -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(),
})
}

View file

@ -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(),
}
}

View file

@ -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(&region)?;
Ok(())
}

View file

@ -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(&registry)?;
self.client.state.globals.notify_all(&registry);
Ok(())

View file

@ -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 {

View file

@ -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;

View file

@ -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(),
}
}

View file

@ -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(),
}
}

View file

@ -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();

View file

@ -85,6 +85,8 @@ impl NodeSeatState {
if last.id() == node_id {
break;
}
last.seat_state().leave(&seat);
last.leave(&seat);
}
seat.state.tree_changed();
}

View file

@ -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;

View file

@ -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(),
}
}

View file

@ -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(),
}
}

View file

@ -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(),
}
}

View file

@ -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(())
}

View file

@ -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(())
}

View file

@ -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(())

View file

@ -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(())

View file

@ -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(),
}
}

View file

@ -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(),
}
}

View file

@ -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);
}
}

View file

@ -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(),
})
}

View file

@ -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();

View file

@ -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(),
}
}

View file

@ -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);

View file

@ -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 {

View file

@ -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(&params)?;
Ok(())
}

View file

@ -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(())

View file

@ -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
View 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
}
}
}

View file

@ -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(())
}

View file

@ -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;
}

View file

@ -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()

View file

@ -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);

View file

@ -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() {

View file

@ -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);
}

View file

@ -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 {

View file

@ -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);

View file

@ -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;

View file

@ -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 {

View file

@ -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
}
}
}

View file

@ -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());
}
}

View file

@ -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 {

View file

@ -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