all: fix memory leaks
This commit is contained in:
parent
56e3eee629
commit
e5c0916a25
15 changed files with 147 additions and 54 deletions
|
|
@ -158,10 +158,21 @@ impl<T, F: Future<Output = T>> Task<T, F> {
|
||||||
let task = data as *const Self;
|
let task = data as *const Self;
|
||||||
if run {
|
if run {
|
||||||
task.deref().run();
|
task.deref().run();
|
||||||
|
} else {
|
||||||
|
Self::task_runnable_dropped(task);
|
||||||
}
|
}
|
||||||
Self::dec_ref_count(task);
|
Self::dec_ref_count(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cold]
|
||||||
|
unsafe fn task_runnable_dropped(task: *const Self) {
|
||||||
|
let task = task.deref();
|
||||||
|
task.state.and_assign(!RUNNING);
|
||||||
|
if task.state.get() & CANCELLED != 0 {
|
||||||
|
task.drop_data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn dec_ref_count(slf: *const Self) {
|
unsafe fn dec_ref_count(slf: *const Self) {
|
||||||
if slf.deref().ref_count.fetch_sub(1) == 1 {
|
if slf.deref().ref_count.fetch_sub(1) == 1 {
|
||||||
Box::from_raw(slf as *mut Self);
|
Box::from_raw(slf as *mut Self);
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@ use {
|
||||||
ffi::{CStr, CString},
|
ffi::{CStr, CString},
|
||||||
fmt::{Debug, Formatter},
|
fmt::{Debug, Formatter},
|
||||||
future::pending,
|
future::pending,
|
||||||
mem,
|
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
},
|
},
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
|
|
@ -293,14 +292,6 @@ struct MetalInputDevice {
|
||||||
transform_matrix: Cell<Option<TransformMatrix>>,
|
transform_matrix: Cell<Option<TransformMatrix>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for MetalInputDevice {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if let Some(fd) = self.fd.take() {
|
|
||||||
mem::forget(fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum MetalDevice {
|
enum MetalDevice {
|
||||||
Input(Rc<MetalInputDevice>),
|
Input(Rc<MetalInputDevice>),
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,9 @@ pub const MAX_EXTENTS: i32 = (1 << 22) - 1;
|
||||||
pub fn start_compositor(global: GlobalArgs, args: RunArgs) {
|
pub fn start_compositor(global: GlobalArgs, args: RunArgs) {
|
||||||
let forker = create_forker();
|
let forker = create_forker();
|
||||||
let logger = Logger::install_compositor(global.log_level.into());
|
let logger = Logger::install_compositor(global.log_level.into());
|
||||||
if let Err(e) = start_compositor2(forker, Some(logger.clone()), args, None) {
|
let res = start_compositor2(Some(forker), Some(logger.clone()), args, None);
|
||||||
|
leaks::log_leaked();
|
||||||
|
if let Err(e) = res {
|
||||||
let e = ErrorFmt(e);
|
let e = ErrorFmt(e);
|
||||||
log::error!("A fatal error occurred: {}", e);
|
log::error!("A fatal error occurred: {}", e);
|
||||||
eprintln!("A fatal error occurred: {}", e);
|
eprintln!("A fatal error occurred: {}", e);
|
||||||
|
|
@ -60,8 +62,9 @@ pub fn start_compositor(global: GlobalArgs, args: RunArgs) {
|
||||||
|
|
||||||
#[cfg(feature = "it")]
|
#[cfg(feature = "it")]
|
||||||
pub fn start_compositor_for_test(future: TestFuture) -> Result<(), CompositorError> {
|
pub fn start_compositor_for_test(future: TestFuture) -> Result<(), CompositorError> {
|
||||||
let forker = create_forker();
|
let res = start_compositor2(None, None, RunArgs::default(), Some(future));
|
||||||
start_compositor2(forker, None, RunArgs::default(), Some(future))
|
leaks::log_leaked();
|
||||||
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_forker() -> Rc<ForkerProxy> {
|
fn create_forker() -> Rc<ForkerProxy> {
|
||||||
|
|
@ -99,7 +102,7 @@ const STATIC_VARS: &[(&str, &str)] = &[
|
||||||
pub type TestFuture = Box<dyn Fn(&Rc<State>) -> Box<dyn Future<Output = ()>>>;
|
pub type TestFuture = Box<dyn Fn(&Rc<State>) -> Box<dyn Future<Output = ()>>>;
|
||||||
|
|
||||||
fn start_compositor2(
|
fn start_compositor2(
|
||||||
forker: Rc<ForkerProxy>,
|
forker: Option<Rc<ForkerProxy>>,
|
||||||
logger: Option<Arc<Logger>>,
|
logger: Option<Arc<Logger>>,
|
||||||
run_args: RunArgs,
|
run_args: RunArgs,
|
||||||
test_future: Option<TestFuture>,
|
test_future: Option<TestFuture>,
|
||||||
|
|
@ -183,28 +186,20 @@ fn start_compositor2(
|
||||||
});
|
});
|
||||||
state.tracker.register(ClientId::from_raw(0));
|
state.tracker.register(ClientId::from_raw(0));
|
||||||
create_dummy_output(&state);
|
create_dummy_output(&state);
|
||||||
let (acceptor, acceptor_future) = Acceptor::install(&state)?;
|
let (acceptor, _acceptor_future) = Acceptor::install(&state)?;
|
||||||
forker.install(&state);
|
if let Some(forker) = forker {
|
||||||
forker.setenv(
|
forker.install(&state);
|
||||||
WAYLAND_DISPLAY.as_bytes(),
|
forker.setenv(
|
||||||
acceptor.socket_name().as_bytes(),
|
WAYLAND_DISPLAY.as_bytes(),
|
||||||
);
|
acceptor.socket_name().as_bytes(),
|
||||||
for (key, val) in STATIC_VARS {
|
);
|
||||||
forker.setenv(key.as_bytes(), val.as_bytes());
|
for (key, val) in STATIC_VARS {
|
||||||
|
forker.setenv(key.as_bytes(), val.as_bytes());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let compositor = engine.spawn(start_compositor3(state.clone(), test_future));
|
let _compositor = engine.spawn(start_compositor3(state.clone(), test_future));
|
||||||
ring.run()?;
|
ring.run()?;
|
||||||
drop(compositor);
|
|
||||||
drop(acceptor_future);
|
|
||||||
drop(acceptor);
|
|
||||||
drop(forker);
|
|
||||||
engine.clear();
|
|
||||||
state.clear();
|
state.clear();
|
||||||
for (_, seat) in state.globals.seats.lock().deref() {
|
|
||||||
seat.clear();
|
|
||||||
}
|
|
||||||
drop(state);
|
|
||||||
leaks::log_leaked();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -352,6 +347,7 @@ fn create_dummy_output(state: &Rc<State>) {
|
||||||
connected: Cell::new(true),
|
connected: Cell::new(true),
|
||||||
name: "Dummy".to_string(),
|
name: "Dummy".to_string(),
|
||||||
drm_dev: None,
|
drm_dev: None,
|
||||||
|
async_event: Default::default(),
|
||||||
}),
|
}),
|
||||||
0,
|
0,
|
||||||
&backend::Mode {
|
&backend::Mode {
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ impl ForkerProxy {
|
||||||
self.task_in.take();
|
self.task_in.take();
|
||||||
self.task_out.take();
|
self.task_out.take();
|
||||||
self.task_proc.take();
|
self.task_proc.take();
|
||||||
|
self.outgoing.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create() -> Result<Self, ForkerError> {
|
pub fn create() -> Result<Self, ForkerError> {
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,13 @@ impl NodeSeatState {
|
||||||
self.dnd_targets.remove(&seat.id);
|
self.dnd_targets.remove(&seat.id);
|
||||||
self.pointer_grabs.remove(&seat.id);
|
self.pointer_grabs.remove(&seat.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.kb_foci.clear();
|
||||||
|
self.pointer_foci.clear();
|
||||||
|
self.dnd_targets.clear();
|
||||||
|
self.pointer_grabs.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WlSeatGlobal {
|
impl WlSeatGlobal {
|
||||||
|
|
|
||||||
|
|
@ -697,6 +697,8 @@ impl Object for WlSurface {
|
||||||
self.buffer.set(None);
|
self.buffer.set(None);
|
||||||
self.toplevel.set(None);
|
self.toplevel.set(None);
|
||||||
self.idle_inhibitors.clear();
|
self.idle_inhibitors.clear();
|
||||||
|
self.pending.presentation_feedback.borrow_mut().clear();
|
||||||
|
self.presentation_feedback.borrow_mut().clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ impl WlSubsurface {
|
||||||
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), WlSubsurfaceError> {
|
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), WlSubsurfaceError> {
|
||||||
let _req: Destroy = self.surface.client.parse(self, parser)?;
|
let _req: Destroy = self.surface.client.parse(self, parser)?;
|
||||||
self.surface.unset_ext();
|
self.surface.unset_ext();
|
||||||
|
*self.pending.node.borrow_mut() = None;
|
||||||
*self.node.borrow_mut() = None;
|
*self.node.borrow_mut() = None;
|
||||||
{
|
{
|
||||||
let mut children = self.parent.children.borrow_mut();
|
let mut children = self.parent.children.borrow_mut();
|
||||||
|
|
@ -257,6 +258,11 @@ impl Object for WlSubsurface {
|
||||||
fn num_requests(&self) -> u32 {
|
fn num_requests(&self) -> u32 {
|
||||||
SET_DESYNC + 1
|
SET_DESYNC + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn break_loops(&self) {
|
||||||
|
*self.pending.node.borrow_mut() = None;
|
||||||
|
*self.node.borrow_mut() = None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
simple_add_obj!(WlSubsurface);
|
simple_add_obj!(WlSubsurface);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use {
|
||||||
testrun::TestRun,
|
testrun::TestRun,
|
||||||
tests::TestCase,
|
tests::TestCase,
|
||||||
},
|
},
|
||||||
|
leaks,
|
||||||
utils::{errorfmt::ErrorFmt, num_cpus::num_cpus},
|
utils::{errorfmt::ErrorFmt, num_cpus::num_cpus},
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
|
|
@ -45,6 +46,7 @@ mod tests;
|
||||||
const SINGLE_THREAD: bool = false;
|
const SINGLE_THREAD: bool = false;
|
||||||
|
|
||||||
pub fn run_tests() {
|
pub fn run_tests() {
|
||||||
|
leaks::init();
|
||||||
test_logger::install();
|
test_logger::install();
|
||||||
test_logger::set_level(Level::Trace);
|
test_logger::set_level(Level::Trace);
|
||||||
let it_run = Arc::new(ItRun {
|
let it_run = Arc::new(ItRun {
|
||||||
|
|
|
||||||
64
src/leaks.rs
64
src/leaks.rs
|
|
@ -42,7 +42,10 @@ mod leaks {
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
client::ClientId,
|
client::ClientId,
|
||||||
utils::ptr_ext::{MutPtrExt, PtrExt},
|
utils::{
|
||||||
|
ptr_ext::{MutPtrExt, PtrExt},
|
||||||
|
windows::WindowsExt,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
ahash::{AHashMap, AHashSet},
|
ahash::{AHashMap, AHashSet},
|
||||||
backtrace::Backtrace,
|
backtrace::Backtrace,
|
||||||
|
|
@ -63,6 +66,9 @@ mod leaks {
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
if INITIALIZED {
|
||||||
|
return;
|
||||||
|
}
|
||||||
MAP = Box::into_raw(Box::new(AHashMap::new()));
|
MAP = Box::into_raw(Box::new(AHashMap::new()));
|
||||||
ALLOCATIONS = Box::into_raw(Box::new(AHashMap::new()));
|
ALLOCATIONS = Box::into_raw(Box::new(AHashMap::new()));
|
||||||
IN_ALLOCATOR = 0;
|
IN_ALLOCATOR = 0;
|
||||||
|
|
@ -93,7 +99,47 @@ mod leaks {
|
||||||
} else {
|
} else {
|
||||||
let containers = find_allocations_pointing_to(allocation.addr);
|
let containers = find_allocations_pointing_to(allocation.addr);
|
||||||
if containers.is_empty() {
|
if containers.is_empty() {
|
||||||
log::error!("{} NO REFERENCES", prefix);
|
let mut frames = vec![];
|
||||||
|
backtrace::trace(|frame| {
|
||||||
|
frames.push((frame.ip() as usize, frame.sp() as usize));
|
||||||
|
true
|
||||||
|
});
|
||||||
|
let mut frames2 = vec![];
|
||||||
|
for [l, r] in frames.array_windows_ext::<2>() {
|
||||||
|
frames2.push((l.0, l.1, r.1));
|
||||||
|
}
|
||||||
|
let mut referenced_on_stack = false;
|
||||||
|
for (ip, lo, hi) in frames2 {
|
||||||
|
if lo % 8 != 0 {
|
||||||
|
log::error!("lo % 8 != 0");
|
||||||
|
}
|
||||||
|
let slice = unsafe {
|
||||||
|
std::slice::from_raw_parts(
|
||||||
|
lo as *const *mut u8,
|
||||||
|
(hi - lo) / mem::size_of::<usize>(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
for addr in slice {
|
||||||
|
if *addr == allocation.addr {
|
||||||
|
let mut name = String::new();
|
||||||
|
backtrace::resolve(ip as _, |sym| {
|
||||||
|
let symname = match sym.name() {
|
||||||
|
Some(s) => s.to_string(),
|
||||||
|
_ => String::new(),
|
||||||
|
};
|
||||||
|
name =
|
||||||
|
format!("{} {:?}:{:?}", symname, sym.filename(), sym.lineno())
|
||||||
|
});
|
||||||
|
if !name.starts_with("jay::leaks::") {
|
||||||
|
log::info!("{} REFERENCED ON THE STACK: {}", prefix, name);
|
||||||
|
referenced_on_stack = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !referenced_on_stack {
|
||||||
|
log::error!("{} NO REFERENCES", prefix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let new_prefix = format!("{} ", prefix);
|
let new_prefix = format!("{} ", prefix);
|
||||||
for (mut allocation, offset) in containers {
|
for (mut allocation, offset) in containers {
|
||||||
|
|
@ -133,6 +179,19 @@ mod leaks {
|
||||||
IN_ALLOCATOR -= 1;
|
IN_ALLOCATOR -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// pub fn log_allocations(w: &mut dyn Write) {
|
||||||
|
// log::info!("remaining allocations:");
|
||||||
|
// unsafe {
|
||||||
|
// IN_ALLOCATOR += 1;
|
||||||
|
// for (_, a) in ALLOCATIONS.deref() {
|
||||||
|
// let mut bt = a.backtrace.clone();
|
||||||
|
// bt.resolve();
|
||||||
|
// write!(w, "[{:?}, {:?}), allocated at\n{:?}", a.addr, a.addr.add(a.len), bt);
|
||||||
|
// }
|
||||||
|
// IN_ALLOCATOR -= 1;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct Tracked {
|
struct Tracked {
|
||||||
|
|
@ -225,6 +284,7 @@ mod leaks {
|
||||||
backtrace: Backtrace::new_unresolved(),
|
backtrace: Backtrace::new_unresolved(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
// log::info!("allocated [0x{:x}, 0x{:x})", res as usize, res as usize + layout.size());
|
||||||
IN_ALLOCATOR = 0;
|
IN_ALLOCATOR = 0;
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
|
|
|
||||||
22
src/state.rs
22
src/state.rs
|
|
@ -161,6 +161,7 @@ pub struct InputDeviceData {
|
||||||
pub handler: SpawnedFuture<()>,
|
pub handler: SpawnedFuture<()>,
|
||||||
pub id: InputDeviceId,
|
pub id: InputDeviceId,
|
||||||
pub data: Rc<DeviceHandlerData>,
|
pub data: Rc<DeviceHandlerData>,
|
||||||
|
pub async_event: Rc<AsyncEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DeviceHandlerData {
|
pub struct DeviceHandlerData {
|
||||||
|
|
@ -174,6 +175,7 @@ pub struct ConnectorData {
|
||||||
pub connected: Cell<bool>,
|
pub connected: Cell<bool>,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub drm_dev: Option<Rc<DrmDevData>>,
|
pub drm_dev: Option<Rc<DrmDevData>>,
|
||||||
|
pub async_event: Rc<AsyncEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OutputData {
|
pub struct OutputData {
|
||||||
|
|
@ -491,20 +493,19 @@ impl State {
|
||||||
if let Some(forker) = self.forker.set(None) {
|
if let Some(forker) = self.forker.set(None) {
|
||||||
forker.clear();
|
forker.clear();
|
||||||
}
|
}
|
||||||
if let Some(output) = self.dummy_output.set(None) {
|
|
||||||
output.clear();
|
|
||||||
}
|
|
||||||
self.acceptor.set(None);
|
self.acceptor.set(None);
|
||||||
self.backend.set(Rc::new(DummyBackend));
|
self.backend.set(Rc::new(DummyBackend));
|
||||||
self.run_toplevel.clear();
|
self.run_toplevel.clear();
|
||||||
self.xwayland.handler.borrow_mut().take();
|
self.xwayland.handler.borrow_mut().take();
|
||||||
self.xwayland.queue.clear();
|
self.xwayland.queue.clear();
|
||||||
self.idle.inhibitors.clear();
|
self.idle.inhibitors.clear();
|
||||||
|
self.idle.change.clear();
|
||||||
for (_, drm_dev) in self.drm_devs.lock().drain() {
|
for (_, drm_dev) in self.drm_devs.lock().drain() {
|
||||||
drm_dev.handler.take();
|
drm_dev.handler.take();
|
||||||
}
|
}
|
||||||
for (_, connector) in self.connectors.lock().drain() {
|
for (_, connector) in self.connectors.lock().drain() {
|
||||||
connector.handler.take();
|
connector.handler.take();
|
||||||
|
connector.async_event.clear();
|
||||||
}
|
}
|
||||||
for (_, output) in self.outputs.lock().drain() {
|
for (_, output) in self.outputs.lock().drain() {
|
||||||
output.node.clear();
|
output.node.clear();
|
||||||
|
|
@ -515,17 +516,24 @@ impl State {
|
||||||
self.pending_float_layout.clear();
|
self.pending_float_layout.clear();
|
||||||
self.pending_float_titles.clear();
|
self.pending_float_titles.clear();
|
||||||
self.slow_clients.clear();
|
self.slow_clients.clear();
|
||||||
self.input_device_handlers.borrow_mut().clear();
|
for (_, h) in self.input_device_handlers.borrow_mut().drain() {
|
||||||
|
h.async_event.clear();
|
||||||
|
}
|
||||||
self.backend_events.clear();
|
self.backend_events.clear();
|
||||||
self.workspaces.clear();
|
self.workspaces.clear();
|
||||||
self.globals.clear();
|
|
||||||
self.render_ctx.set(None);
|
|
||||||
self.root.clear();
|
|
||||||
{
|
{
|
||||||
let seats = mem::take(self.globals.seats.lock().deref_mut());
|
let seats = mem::take(self.globals.seats.lock().deref_mut());
|
||||||
for seat in seats.values() {
|
for seat in seats.values() {
|
||||||
seat.clear();
|
seat.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.globals.clear();
|
||||||
|
self.render_ctx.set(None);
|
||||||
|
self.root.clear();
|
||||||
|
if let Some(output) = self.dummy_output.set(None) {
|
||||||
|
output.clear();
|
||||||
|
}
|
||||||
|
self.wheel.clear();
|
||||||
|
self.eng.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ pub fn handle(state: &Rc<State>, connector: &Rc<dyn Connector>) {
|
||||||
connected: Cell::new(false),
|
connected: Cell::new(false),
|
||||||
name: connector.kernel_id().to_string(),
|
name: connector.kernel_id().to_string(),
|
||||||
drm_dev: drm_dev.clone(),
|
drm_dev: drm_dev.clone(),
|
||||||
|
async_event: Rc::new(AsyncEvent::default()),
|
||||||
});
|
});
|
||||||
if let Some(dev) = drm_dev {
|
if let Some(dev) = drm_dev {
|
||||||
dev.connectors.set(id, data.clone());
|
dev.connectors.set(id, data.clone());
|
||||||
|
|
@ -51,9 +52,8 @@ struct ConnectorHandler {
|
||||||
|
|
||||||
impl ConnectorHandler {
|
impl ConnectorHandler {
|
||||||
async fn handle(self) {
|
async fn handle(self) {
|
||||||
let ae = Rc::new(AsyncEvent::default());
|
|
||||||
{
|
{
|
||||||
let ae = ae.clone();
|
let ae = self.data.async_event.clone();
|
||||||
self.data.connector.on_change(Rc::new(move || ae.trigger()));
|
self.data.connector.on_change(Rc::new(move || ae.trigger()));
|
||||||
}
|
}
|
||||||
if let Some(config) = self.state.config.get() {
|
if let Some(config) = self.state.config.get() {
|
||||||
|
|
@ -63,11 +63,11 @@ impl ConnectorHandler {
|
||||||
while let Some(event) = self.data.connector.event() {
|
while let Some(event) = self.data.connector.event() {
|
||||||
match event {
|
match event {
|
||||||
ConnectorEvent::Removed => break 'outer,
|
ConnectorEvent::Removed => break 'outer,
|
||||||
ConnectorEvent::Connected(mi) => self.handle_connected(&ae, mi).await,
|
ConnectorEvent::Connected(mi) => self.handle_connected(mi).await,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ae.triggered().await;
|
self.data.async_event.triggered().await;
|
||||||
}
|
}
|
||||||
if let Some(config) = self.state.config.get() {
|
if let Some(config) = self.state.config.get() {
|
||||||
config.del_connector(self.id);
|
config.del_connector(self.id);
|
||||||
|
|
@ -76,7 +76,7 @@ impl ConnectorHandler {
|
||||||
self.state.connectors.remove(&self.id);
|
self.state.connectors.remove(&self.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_connected(&self, ae: &Rc<AsyncEvent>, info: MonitorInfo) {
|
async fn handle_connected(&self, info: MonitorInfo) {
|
||||||
log::info!("Connector {} connected", self.data.connector.kernel_id());
|
log::info!("Connector {} connected", self.data.connector.kernel_id());
|
||||||
self.data.connected.set(true);
|
self.data.connected.set(true);
|
||||||
let name = self.state.globals.name();
|
let name = self.state.globals.name();
|
||||||
|
|
@ -151,7 +151,7 @@ impl ConnectorHandler {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ae.triggered().await;
|
self.data.async_event.triggered().await;
|
||||||
}
|
}
|
||||||
log::info!("Connector {} disconnected", self.data.connector.kernel_id());
|
log::info!("Connector {} disconnected", self.data.connector.kernel_id());
|
||||||
if let Some(config) = self.state.config.get() {
|
if let Some(config) = self.state.config.get() {
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,12 @@ pub fn handle(state: &Rc<State>, dev: Rc<dyn InputDevice>) {
|
||||||
seat: Default::default(),
|
seat: Default::default(),
|
||||||
device: dev.clone(),
|
device: dev.clone(),
|
||||||
});
|
});
|
||||||
|
let ae = Rc::new(AsyncEvent::default());
|
||||||
let oh = DeviceHandler {
|
let oh = DeviceHandler {
|
||||||
state: state.clone(),
|
state: state.clone(),
|
||||||
dev: dev.clone(),
|
dev: dev.clone(),
|
||||||
data: data.clone(),
|
data: data.clone(),
|
||||||
|
ae: ae.clone(),
|
||||||
};
|
};
|
||||||
let handler = state.eng.spawn(oh.handle());
|
let handler = state.eng.spawn(oh.handle());
|
||||||
state.input_device_handlers.borrow_mut().insert(
|
state.input_device_handlers.borrow_mut().insert(
|
||||||
|
|
@ -24,21 +26,22 @@ pub fn handle(state: &Rc<State>, dev: Rc<dyn InputDevice>) {
|
||||||
handler,
|
handler,
|
||||||
id: dev.id(),
|
id: dev.id(),
|
||||||
data,
|
data,
|
||||||
|
async_event: ae,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DeviceHandler {
|
struct DeviceHandler {
|
||||||
pub state: Rc<State>,
|
state: Rc<State>,
|
||||||
pub dev: Rc<dyn InputDevice>,
|
dev: Rc<dyn InputDevice>,
|
||||||
pub data: Rc<DeviceHandlerData>,
|
data: Rc<DeviceHandlerData>,
|
||||||
|
ae: Rc<AsyncEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeviceHandler {
|
impl DeviceHandler {
|
||||||
pub async fn handle(self) {
|
pub async fn handle(self) {
|
||||||
let ae = Rc::new(AsyncEvent::default());
|
|
||||||
{
|
{
|
||||||
let ae = ae.clone();
|
let ae = self.ae.clone();
|
||||||
self.dev.on_change(Rc::new(move || ae.trigger()));
|
self.dev.on_change(Rc::new(move || ae.trigger()));
|
||||||
}
|
}
|
||||||
if let Some(config) = self.state.config.get() {
|
if let Some(config) = self.state.config.get() {
|
||||||
|
|
@ -63,7 +66,7 @@ impl DeviceHandler {
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ae.triggered().await;
|
self.ae.triggered().await;
|
||||||
}
|
}
|
||||||
if let Some(config) = self.state.config.get() {
|
if let Some(config) = self.state.config.get() {
|
||||||
config.del_input_device(self.dev.id());
|
config.del_input_device(self.dev.id());
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ impl DisplayNode {
|
||||||
|
|
||||||
pub fn clear(&self) {
|
pub fn clear(&self) {
|
||||||
self.outputs.clear();
|
self.outputs.clear();
|
||||||
|
self.seat_state.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_extents(&self) {
|
pub fn update_extents(&self) {
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ impl OutputNode {
|
||||||
for workspace in workspaces {
|
for workspace in workspaces {
|
||||||
workspace.clear();
|
workspace.clear();
|
||||||
}
|
}
|
||||||
|
self.render_data.borrow_mut().titles.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_spaces_changed(self: &Rc<Self>) {
|
pub fn on_spaces_changed(self: &Rc<Self>) {
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,10 @@ impl Wheel {
|
||||||
Ok(Rc::new(Wheel { data }))
|
Ok(Rc::new(Wheel { data }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.data.kill();
|
||||||
|
}
|
||||||
|
|
||||||
fn future(&self) -> WheelTimeoutFuture {
|
fn future(&self) -> WheelTimeoutFuture {
|
||||||
let data = self.data.cached_futures.pop().unwrap_or_else(|| {
|
let data = self.data.cached_futures.pop().unwrap_or_else(|| {
|
||||||
Rc::new(WheelTimeoutData {
|
Rc::new(WheelTimeoutData {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue