Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add method for importing external proxies #731

Merged
merged 7 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
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
Loading