Skip to content

Commit

Permalink
Merge pull request #731 from chrisduerr/import_external
Browse files Browse the repository at this point in the history
Add method for importing external proxies
  • Loading branch information
elinorbgr authored Jun 18, 2024
2 parents 7669047 + 46e208d commit 41bab57
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 28 deletions.
8 changes: 6 additions & 2 deletions wayland-backend/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

## Unreleased

#### Additions

- `Backend::manage_object` for handling foreign proxies with the sys backend

## 0.3.4 -- 2024-05-30

### Additions
#### Additions

- Add `rwh_06` feature for `raw-window-handle` 0.6

Expand All @@ -14,7 +18,7 @@

## 0.3.3 -- 2024-01-29

### Additions
#### Additions
- client: Implement `Eq` for `Backend`

#### Bugfixes
Expand Down
79 changes: 54 additions & 25 deletions wayland-backend/src/sys/client_impl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,19 +690,8 @@ impl InnerBackend {

// initialize the proxy
let child_id = if let Some((child_interface, _)) = child_spec {
let child_alive = Arc::new(AtomicBool::new(true));
let child_id = ObjectId {
id: InnerObjectId {
ptr: ret,
alive: Some(child_alive.clone()),
id: unsafe { ffi_dispatch!(wayland_client_handle(), wl_proxy_get_id, ret) },
interface: child_interface,
},
};
let child_udata = match data {
Some(data) => {
Box::new(ProxyUserData { alive: child_alive, data, interface: child_interface })
}
let data = match data {
Some(data) => data,
None => {
// we destroy this proxy before panicking to avoid a leak, as it cannot be destroyed by the
// main destructor given it does not yet have a proper user-data
Expand All @@ -714,18 +703,8 @@ impl InnerBackend {
);
}
};
guard.known_proxies.insert(ret);
unsafe {
ffi_dispatch!(
wayland_client_handle(),
wl_proxy_add_dispatcher,
ret,
dispatcher_func,
&RUST_MANAGED as *const u8 as *const c_void,
Box::into_raw(child_udata) as *mut c_void
);
}
child_id

unsafe { self.manage_object_internal(child_interface, ret, data, &mut guard) }
} else {
Self::null_id()
};
Expand All @@ -750,7 +729,9 @@ impl InnerBackend {
alive.store(false, Ordering::Release);
udata.data.destroyed(ObjectId { id: id.clone() });
}

guard.known_proxies.remove(&id.ptr);

unsafe {
ffi_dispatch!(wayland_client_handle(), wl_proxy_destroy, id.ptr);
}
Expand Down Expand Up @@ -799,6 +780,54 @@ impl InnerBackend {

Ok(())
}

/// Start managing a Wayland object.
pub unsafe fn manage_object(
&self,
interface: &'static Interface,
proxy: *mut wl_proxy,
data: Arc<dyn ObjectData>,
) -> ObjectId {
let mut guard = self.lock_state();
unsafe { self.manage_object_internal(interface, proxy, data, &mut guard) }
}

/// Start managing a Wayland object.
///
/// Opposed to [`Self::manage_object`], this does not acquire any guards.
unsafe fn manage_object_internal(
&self,
interface: &'static Interface,
proxy: *mut wl_proxy,
data: Arc<dyn ObjectData>,
guard: &mut MutexGuard<ConnectionState>,
) -> ObjectId {
let alive = Arc::new(AtomicBool::new(true));
let object_id = ObjectId {
id: InnerObjectId {
ptr: proxy,
alive: Some(alive.clone()),
id: unsafe { ffi_dispatch!(wayland_client_handle(), wl_proxy_get_id, proxy) },
interface,
},
};

guard.known_proxies.insert(proxy);

let udata = Box::new(ProxyUserData { alive, data, interface });
unsafe {
ffi_dispatch!(
wayland_client_handle(),
wl_proxy_add_dispatcher,
proxy,
dispatcher_func,
&RUST_MANAGED as *const u8 as *const c_void,
Box::into_raw(udata) as *mut c_void
);
}

object_id
}
}

unsafe extern "C" fn dispatcher_func(
Expand Down
26 changes: 25 additions & 1 deletion wayland-backend/src/sys/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
//! Implementations of the Wayland backends using the system `libwayland`
use crate::protocol::ArgumentType;
use std::sync::Arc;

Check warning on line 3 in wayland-backend/src/sys/mod.rs

View workflow job for this annotation

GitHub Actions / coverage-tests (server_system)

unused import: `std::sync::Arc`

use wayland_sys::client::wl_proxy;

Check warning on line 5 in wayland-backend/src/sys/mod.rs

View workflow job for this annotation

GitHub Actions / coverage-tests (server_system)

unused import: `wayland_sys::client::wl_proxy`
use wayland_sys::common::{wl_argument, wl_array};

use crate::client::{ObjectData, ObjectId};

Check warning on line 8 in wayland-backend/src/sys/mod.rs

View workflow job for this annotation

GitHub Actions / coverage-tests (server_system)

unused import: `ObjectId`

Check warning on line 8 in wayland-backend/src/sys/mod.rs

View workflow job for this annotation

GitHub Actions / coverage-tests (server_system)

unused import: `ObjectData`
use crate::protocol::{ArgumentType, Interface};

Check warning on line 9 in wayland-backend/src/sys/mod.rs

View workflow job for this annotation

GitHub Actions / coverage-tests (server_system)

unused import: `Interface`

#[cfg(any(test, feature = "client_system"))]
mod client_impl;
#[cfg(any(test, feature = "server_system"))]
Expand Down Expand Up @@ -90,6 +95,25 @@ impl client::Backend {
pub fn display_ptr(&self) -> *mut wayland_sys::client::wl_display {
self.backend.display_ptr()
}

/// Take over handling for a proxy created by a third party.
///
/// # Safety
///
/// There must never be more than one party managing an object. This is only
/// safe to call when a third party gave you ownership of an unmanaged proxy.
///
/// The caller is also responsible for making sure the passed interface matches
/// the proxy.
#[inline]
pub unsafe fn manage_object(
&self,
interface: &'static Interface,
proxy: *mut wl_proxy,
data: Arc<dyn ObjectData>,
) -> ObjectId {
unsafe { self.backend.manage_object(interface, proxy, data) }
}
}

// SAFETY:
Expand Down

0 comments on commit 41bab57

Please sign in to comment.