wayland: ext_workspace fixes

This commit is contained in:
Victoria Brekenfeld 2022-05-02 17:40:02 +02:00
parent 7803259949
commit 6096b8114e
2 changed files with 275 additions and 127 deletions

View file

@ -3,6 +3,4 @@ mod drm;
pub use drm::*; pub use drm::*;
#[cfg(feature = "experimental")] #[cfg(feature = "experimental")]
mod workspace; pub mod workspace;
#[cfg(feature = "experimental")]
pub use workspace::*;

View file

@ -5,7 +5,9 @@
// and avoid exposing internal details. // and avoid exposing internal details.
// //
// You can use all the types from my_protocol as if they went from `wayland_client::protocol`. // You can use all the types from my_protocol as if they went from `wayland_client::protocol`.
pub use generated::server::{zext_workspace_manager_v1, zext_workspace_group_handle_v1, zext_workspace_handle_v1}; pub use generated::server::{
zext_workspace_group_handle_v1, zext_workspace_handle_v1, zext_workspace_manager_v1,
};
mod generated { mod generated {
// The generated code tends to trigger a lot of warnings // The generated code tends to trigger a lot of warnings
@ -28,20 +30,21 @@ mod generated {
} }
} }
use std::{ pub use self::generated::server::zext_workspace_handle_v1::State;
cell::RefCell, use self::generated::server::{
collections::HashSet, zext_workspace_group_handle_v1::ZextWorkspaceGroupHandleV1,
fmt, zext_workspace_handle_v1::ZextWorkspaceHandleV1,
sync::{Arc, Mutex, Weak}, zext_workspace_manager_v1::ZextWorkspaceManagerV1,
}; };
use smithay::{ use smithay::{
reexports::wayland_server::{Client, DispatchData, Display, Filter, Global, Main}, reexports::wayland_server::{Client, DispatchData, Display, Filter, Global, Main},
wayland::output::Output, wayland::output::Output,
}; };
use self::generated::server::{ use std::{
zext_workspace_manager_v1::ZextWorkspaceManagerV1, cell::RefCell,
zext_workspace_group_handle_v1::ZextWorkspaceGroupHandleV1, collections::HashSet,
zext_workspace_handle_v1::{ZextWorkspaceHandleV1, State}, fmt,
sync::{Arc, Mutex, Weak},
}; };
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -52,7 +55,10 @@ pub struct WorkspaceManager {
struct WorkspaceManagerInner { struct WorkspaceManagerInner {
instances: Vec<Main<ZextWorkspaceManagerV1>>, instances: Vec<Main<ZextWorkspaceManagerV1>>,
groups: Vec<Arc<Mutex<WorkspaceGroupInner>>>, groups: Vec<Arc<Mutex<WorkspaceGroupInner>>>,
commit: Box<dyn FnMut(&WorkspaceGroup, Vec<(&Workspace, Vec<PendingOperation>)>, DispatchData) + 'static>, commit: Box<
dyn FnMut(&WorkspaceGroup, Vec<(&Workspace, Vec<PendingOperation>)>, DispatchData)
+ 'static,
>,
} }
impl fmt::Debug for WorkspaceManagerInner { impl fmt::Debug for WorkspaceManagerInner {
@ -64,7 +70,7 @@ impl fmt::Debug for WorkspaceManagerInner {
} }
} }
pub fn init_ext_workspace<C,F>( pub fn init_ext_workspace<C, F>(
display: &mut Display, display: &mut Display,
commit: C, commit: C,
client_filter: F, client_filter: F,
@ -80,27 +86,41 @@ where
})); }));
let inner_clone = inner.clone(); let inner_clone = inner.clone();
let filter = Filter::new(move |(main, _version): (Main<ZextWorkspaceManagerV1>, u32), _, _| { let filter = Filter::new(
let inner = inner_clone.clone(); move |(main, _version): (Main<ZextWorkspaceManagerV1>, u32), _, _| {
main.quick_assign(move |main, request, mut ddata| { let inner = inner_clone.clone();
match request { main.quick_assign(move |main, request, mut ddata| match request {
zext_workspace_manager_v1::Request::Commit => { zext_workspace_manager_v1::Request::Commit => {
if let Some(client) = main.as_ref().client() { if let Some(client) = main.as_ref().client() {
let mut inner_guard = inner.lock().unwrap(); let mut inner_guard = inner.lock().unwrap();
let inner = &mut *inner_guard; let inner = &mut *inner_guard;
for group in inner.groups.iter() { for group in inner.groups.iter() {
let group_inner = group.lock().unwrap(); let group_inner = group.lock().unwrap();
let mut changes = group_inner.workspaces let mut changes = group_inner
.workspaces
.iter() .iter()
.flat_map(|x| x.upgrade()) .flat_map(|x| x.upgrade())
.flat_map(|w| { .flat_map(|w| {
let workspace_inner = w.lock().unwrap(); let workspace_inner = w.lock().unwrap();
let operations = workspace_inner.instances let operations = workspace_inner
.instances
.iter() .iter()
.find(|w_instance| w_instance.as_ref().client().map(|c| c == client).unwrap_or(false)) .find(|w_instance| {
.and_then(|w_instance| w_instance.as_ref().user_data().get::<WorkspaceUserdata>()) w_instance
.as_ref()
.client()
.map(|c| c == client)
.unwrap_or(false)
})
.and_then(|w_instance| {
w_instance
.as_ref()
.user_data()
.get::<WorkspaceUserdata>()
})
.and_then(|user_data| { .and_then(|user_data| {
let operations = std::mem::take( &mut *user_data.borrow_mut()); let operations =
std::mem::take(&mut *user_data.borrow_mut());
if !operations.is_empty() { if !operations.is_empty() {
Some(operations) Some(operations)
} else { } else {
@ -109,7 +129,7 @@ where
}); });
if let Some(ops) = operations { if let Some(ops) = operations {
std::mem::drop(workspace_inner); std::mem::drop(workspace_inner);
Some((Workspace{ inner: w }, ops)) Some((Workspace { inner: w }, ops))
} else { } else {
None None
} }
@ -120,56 +140,73 @@ where
let group = WorkspaceGroup { let group = WorkspaceGroup {
inner: group.clone(), inner: group.clone(),
}; };
let borrowed_changes = changes.iter_mut().map(|(w, p)| (&*w, std::mem::take(p))).collect(); let borrowed_changes = changes
.iter_mut()
.map(|(w, p)| (&*w, std::mem::take(p)))
.collect();
(inner.commit)(&group, borrowed_changes, ddata.reborrow()); (inner.commit)(&group, borrowed_changes, ddata.reborrow());
} }
} }
}, }
zext_workspace_manager_v1::Request::Stop => { zext_workspace_manager_v1::Request::Stop => {
let mut inner = inner.lock().unwrap(); let mut inner = inner.lock().unwrap();
inner.instances.retain(|m| **m != *main); inner.instances.retain(|m| **m != *main);
}, }
} });
});
let inner_guard = inner_clone.lock().unwrap(); let mut inner_guard = inner_clone.lock().unwrap();
if let Some(client) = main.as_ref().client() { if let Some(client) = main.as_ref().client() {
for group in inner_guard.groups.iter() { for group in inner_guard.groups.iter() {
if let Some(new_instance) = WorkspaceGroup::create_instance(&client, group.clone()) { if let Some(new_instance) =
main.workspace_group(&*new_instance); WorkspaceGroup::create_instance(&client, group.clone())
{
main.workspace_group(&*new_instance);
let mut group_inner_guard = group.lock().unwrap(); let mut group_inner_guard = group.lock().unwrap();
group_inner_guard.instances.push(new_instance); for output in group_inner_guard.outputs.iter() {
for workspace in group_inner_guard.workspaces.iter() { output.with_client_outputs(client.clone(), |output| {
if let Some(workspace) = workspace.upgrade() { new_instance.output_enter(output)
let workspace_clone = workspace.clone(); });
if let Some(new_instance) = Workspace::create_instance(&client, workspace_clone) { }
let mut inner = workspace.lock().unwrap(); for workspace in group_inner_guard.workspaces.iter() {
inner.instances.push(new_instance); if let Some(workspace) = workspace.upgrade() {
inner.send(&client); let workspace_clone = workspace.clone();
if let Some(new_ws_instance) =
Workspace::create_instance(&client, workspace_clone)
{
new_instance.workspace(&*new_ws_instance);
let mut inner = workspace.lock().unwrap();
inner.instances.push(new_ws_instance);
inner.send(&client);
}
} }
} }
group_inner_guard.instances.push(new_instance);
} }
} }
main.done();
} }
}
}); inner_guard.instances.push(main);
},
);
let global = display.create_global_with_filter(1, filter, client_filter); let global = display.create_global_with_filter(1, filter, client_filter);
( (WorkspaceManager { inner }, global)
WorkspaceManager {
inner,
}, global
)
} }
impl WorkspaceManager { impl WorkspaceManager {
pub fn new_group<F>(&self, create_new_workspace: F, outputs: impl Iterator<Item=Output>) -> WorkspaceGroup pub fn new_group<F>(
&self,
create_new_workspace: F,
outputs: impl Iterator<Item = Output>,
) -> WorkspaceGroup
where where
F: Fn(&WorkspaceGroup, String, DispatchData) + 'static, F: Fn(&WorkspaceGroup, String, DispatchData) + 'static,
{ {
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.lock().unwrap();
let create_new_workspace = Arc::new(Box::new(create_new_workspace) as Box<dyn Fn(&WorkspaceGroup, String, DispatchData) + 'static>); let create_new_workspace = Arc::new(Box::new(create_new_workspace)
as Box<dyn Fn(&WorkspaceGroup, String, DispatchData) + 'static>);
let group_inner = Arc::new(Mutex::new(WorkspaceGroupInner { let group_inner = Arc::new(Mutex::new(WorkspaceGroupInner {
instances: Vec::new(), instances: Vec::new(),
outputs: outputs.collect(), outputs: outputs.collect(),
@ -181,21 +218,25 @@ impl WorkspaceManager {
if let Some(client) = instance.as_ref().client() { if let Some(client) = instance.as_ref().client() {
if let Some(group) = WorkspaceGroup::create_instance(&client, group_inner.clone()) { if let Some(group) = WorkspaceGroup::create_instance(&client, group_inner.clone()) {
instance.workspace_group(&*group); instance.workspace_group(&*group);
group_inner.lock().unwrap().instances.push(group); let mut group_inner_guard = group_inner.lock().unwrap();
for output in group_inner_guard.outputs.iter() {
output.with_client_outputs(client.clone(), |output| {
group.output_enter(output)
});
}
group_inner_guard.instances.push(group);
} }
} }
instance.done(); instance.done();
} }
inner.groups.push(group_inner.clone()); inner.groups.push(group_inner.clone());
WorkspaceGroup { WorkspaceGroup { inner: group_inner }
inner: group_inner,
}
} }
pub fn update_outputs<F>(&self, mut update: F) pub fn update_outputs<F>(&self, mut update: F)
where where
F: FnMut(&WorkspaceGroup, &mut HashSet<Output>) F: FnMut(&WorkspaceGroup, &mut HashSet<Output>),
{ {
let inner = self.inner.lock().unwrap(); let inner = self.inner.lock().unwrap();
for group in inner.groups.iter() { for group in inner.groups.iter() {
@ -210,14 +251,18 @@ impl WorkspaceManager {
for output in previous_outputs.difference(&group_inner.outputs) { for output in previous_outputs.difference(&group_inner.outputs) {
for instance in group_inner.instances.iter() { for instance in group_inner.instances.iter() {
if let Some(client) = instance.as_ref().client() { if let Some(client) = instance.as_ref().client() {
output.with_client_outputs(client.clone(), |output| instance.output_leave(output)); output.with_client_outputs(client.clone(), |output| {
instance.output_leave(output)
});
} }
} }
} }
for output in group_inner.outputs.difference(&previous_outputs) { for output in group_inner.outputs.difference(&previous_outputs) {
for instance in group_inner.instances.iter() { for instance in group_inner.instances.iter() {
if let Some(client) = instance.as_ref().client() { if let Some(client) = instance.as_ref().client() {
output.with_client_outputs(client.clone(), |output| instance.output_enter(output)); output.with_client_outputs(client.clone(), |output| {
instance.output_enter(output)
});
} }
} }
} }
@ -230,7 +275,11 @@ impl WorkspaceManager {
pub fn remove_group(&self, group: &WorkspaceGroup) { pub fn remove_group(&self, group: &WorkspaceGroup) {
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.lock().unwrap();
// grr I want drain_filter // grr I want drain_filter
if let Some(pos) = inner.groups.iter().position(|x| Arc::ptr_eq(x, &group.inner)) { if let Some(pos) = inner
.groups
.iter()
.position(|x| Arc::ptr_eq(x, &group.inner))
{
let group = inner.groups.remove(pos); let group = inner.groups.remove(pos);
let inner = group.lock().unwrap(); let inner = group.lock().unwrap();
for instance in inner.instances.iter() { for instance in inner.instances.iter() {
@ -238,6 +287,12 @@ impl WorkspaceManager {
} }
} }
} }
pub fn done(&self) {
for instance in self.inner.lock().unwrap().instances.iter() {
instance.done();
}
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -245,6 +300,12 @@ pub struct WorkspaceGroup {
inner: Arc<Mutex<WorkspaceGroupInner>>, inner: Arc<Mutex<WorkspaceGroupInner>>,
} }
impl PartialEq for WorkspaceGroup {
fn eq(&self, other: &WorkspaceGroup) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}
}
struct WorkspaceGroupInner { struct WorkspaceGroupInner {
instances: Vec<Main<ZextWorkspaceGroupHandleV1>>, instances: Vec<Main<ZextWorkspaceGroupHandleV1>>,
outputs: HashSet<Output>, outputs: HashSet<Output>,
@ -263,8 +324,7 @@ impl fmt::Debug for WorkspaceGroupInner {
} }
impl WorkspaceGroup { impl WorkspaceGroup {
pub fn create_workspace(&self, name: String) -> Workspace pub fn create_workspace(&self, name: String) -> Workspace {
{
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.lock().unwrap();
let workspace_inner = Arc::new(Mutex::new(WorkspaceInner { let workspace_inner = Arc::new(Mutex::new(WorkspaceInner {
instances: Vec::new(), instances: Vec::new(),
@ -278,7 +338,9 @@ impl WorkspaceGroup {
for instance in inner.instances.iter() { for instance in inner.instances.iter() {
if let Some(client) = instance.as_ref().client() { if let Some(client) = instance.as_ref().client() {
let workspace_inner_clone = workspace_inner.clone(); let workspace_inner_clone = workspace_inner.clone();
if let Some(workspace) = Workspace::create_instance(&client, workspace_inner_clone) { if let Some(workspace) = Workspace::create_instance(&client, workspace_inner_clone)
{
instance.workspace(&*workspace);
let mut workspace_inner_guard = workspace_inner.lock().unwrap(); let mut workspace_inner_guard = workspace_inner.lock().unwrap();
workspace_inner_guard.instances.push(workspace); workspace_inner_guard.instances.push(workspace);
workspace_inner_guard.send(&client); workspace_inner_guard.send(&client);
@ -291,26 +353,40 @@ impl WorkspaceGroup {
} }
} }
fn create_instance(client: &Client, group_inner: Arc<Mutex<WorkspaceGroupInner>>) -> Option<Main<ZextWorkspaceGroupHandleV1>> { pub fn belongs(&self, workspace: &Workspace) -> bool {
if let Some(group) = client.create_resource::<ZextWorkspaceGroupHandleV1>(1) { self.inner
let group_inner_guard = group_inner.lock().unwrap(); .lock()
for output in group_inner_guard.outputs.iter() { .unwrap()
output.with_client_outputs(client.clone(), |output| group.output_enter(output)); .workspaces
} .iter()
.flat_map(|x| x.upgrade())
.any(|w| Arc::ptr_eq(&w, &workspace.inner))
}
fn create_instance(
client: &Client,
group_inner: Arc<Mutex<WorkspaceGroupInner>>,
) -> Option<Main<ZextWorkspaceGroupHandleV1>> {
if let Some(group) = client.create_resource::<ZextWorkspaceGroupHandleV1>(1) {
let group_inner_clone = group_inner.clone(); let group_inner_clone = group_inner.clone();
group.quick_assign(move |group, request, ddata| { group.quick_assign(move |group, request, ddata| match request {
match request { zext_workspace_group_handle_v1::Request::CreateWorkspace { workspace } => {
zext_workspace_group_handle_v1::Request::CreateWorkspace { workspace } => { let callback = group_inner_clone
let callback = group_inner_clone.lock().unwrap().create_new_workspace.clone(); .lock()
let group = WorkspaceGroup { .unwrap()
inner: group_inner_clone.clone(), .create_new_workspace
}; .clone();
callback(&group, workspace, ddata); let group = WorkspaceGroup {
}, inner: group_inner_clone.clone(),
zext_workspace_group_handle_v1::Request::Destroy => { };
group_inner_clone.lock().unwrap().instances.retain(|g| *g != group); callback(&group, workspace, ddata);
} }
zext_workspace_group_handle_v1::Request::Destroy => {
group_inner_clone
.lock()
.unwrap()
.instances
.retain(|g| *g != group);
} }
}); });
Some(group) Some(group)
@ -325,17 +401,22 @@ pub struct Workspace {
inner: Arc<Mutex<WorkspaceInner>>, inner: Arc<Mutex<WorkspaceInner>>,
} }
impl PartialEq for Workspace {
fn eq(&self, other: &Workspace) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}
}
#[derive(Debug)] #[derive(Debug)]
struct WorkspaceInner { struct WorkspaceInner {
instances: Vec<Main<ZextWorkspaceHandleV1>>, instances: Vec<Main<ZextWorkspaceHandleV1>>,
name: String, name: String,
states: Vec<State>, states: Vec<State>,
coordinates: Vec<u8>, coordinates: Vec<u32>,
} }
type WorkspaceUserdata = RefCell<Vec<PendingOperation>>; type WorkspaceUserdata = RefCell<Vec<PendingOperation>>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum PendingOperation { pub enum PendingOperation {
Activate, Activate,
@ -364,35 +445,67 @@ impl Workspace {
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.lock().unwrap();
inner.states.push(state); inner.states.push(state);
for instance in inner.instances.iter() { for instance in inner.instances.iter() {
instance.state(inner.states.iter().map(|s| s.to_raw() as u8).collect()); let states = {
}; let mut states = inner.states.clone();
let ptr = states.as_mut_ptr();
let len = states.len();
let cap = states.capacity();
::std::mem::forget(states);
unsafe { Vec::from_raw_parts(ptr as *mut u8, len * 4, cap * 4) }
};
instance.state(states);
}
} }
pub fn remove_state(&self, state: State) { pub fn remove_state(&self, state: State) {
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.lock().unwrap();
inner.states.retain(|s| *s != state); inner.states.retain(|s| *s != state);
for instance in inner.instances.iter() { for instance in inner.instances.iter() {
instance.state(inner.states.iter().map(|s| s.to_raw() as u8).collect()); let states = {
}; let mut states = inner.states.clone();
} let ptr = states.as_mut_ptr();
let len = states.len();
pub fn set_states(&self, states: impl Iterator<Item=State>) { let cap = states.capacity();
let mut inner = self.inner.lock().unwrap(); ::std::mem::forget(states);
inner.states = states.collect(); unsafe { Vec::from_raw_parts(ptr as *mut u8, len * 4, cap * 4) }
for instance in inner.instances.iter() { };
instance.state(inner.states.iter().map(|s| s.to_raw() as u8).collect()); instance.state(states);
} }
} }
pub fn coordinates(&self) -> Vec<u8> { pub fn set_states(&self, states: impl Iterator<Item = State>) {
let mut inner = self.inner.lock().unwrap();
inner.states = states.collect();
for instance in inner.instances.iter() {
let states = {
let mut states = inner.states.clone();
let ptr = states.as_mut_ptr();
let len = states.len();
let cap = states.capacity();
::std::mem::forget(states);
unsafe { Vec::from_raw_parts(ptr as *mut u8, len * 4, cap * 4) }
};
instance.state(states);
}
}
pub fn coordinates(&self) -> Vec<u32> {
self.inner.lock().unwrap().coordinates.clone() self.inner.lock().unwrap().coordinates.clone()
} }
pub fn set_coordinates(&self, coordinates: impl Iterator<Item=u8>) { pub fn set_coordinates(&self, coordinates: impl Iterator<Item = u32>) {
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.lock().unwrap();
inner.coordinates = coordinates.collect(); inner.coordinates = coordinates.collect();
for instances in inner.instances.iter() { for instances in inner.instances.iter() {
instances.coordinates(inner.coordinates.clone()); let coords = {
let mut coords = inner.coordinates.clone();
let ptr = coords.as_mut_ptr();
let len = coords.len();
let cap = coords.capacity();
::std::mem::forget(coords);
unsafe { Vec::from_raw_parts(ptr as *mut u8, len * 4, cap * 4) }
};
instances.coordinates(coords);
} }
} }
@ -402,28 +515,45 @@ impl Workspace {
} }
} }
fn create_instance(client: &Client, workspace_inner_clone: Arc<Mutex<WorkspaceInner>>) -> Option<Main<ZextWorkspaceHandleV1>> { fn create_instance(
client: &Client,
workspace_inner_clone: Arc<Mutex<WorkspaceInner>>,
) -> Option<Main<ZextWorkspaceHandleV1>> {
if let Some(workspace) = client.create_resource::<ZextWorkspaceHandleV1>(1) { if let Some(workspace) = client.create_resource::<ZextWorkspaceHandleV1>(1) {
workspace.quick_assign(move |workspace, request, _| { workspace.quick_assign(move |workspace, request, _| match request {
match request { zext_workspace_handle_v1::Request::Activate => {
zext_workspace_handle_v1::Request::Activate => { let user_data = workspace.as_ref().user_data();
let user_data = workspace.as_ref().user_data(); user_data.set(|| -> WorkspaceUserdata { RefCell::new(Vec::new()) });
user_data.set(|| -> WorkspaceUserdata { RefCell::new(Vec::new()) }); user_data
user_data.get::<WorkspaceUserdata>().unwrap().borrow_mut().push(PendingOperation::Activate); .get::<WorkspaceUserdata>()
}, .unwrap()
zext_workspace_handle_v1::Request::Deactivate => { .borrow_mut()
let user_data = workspace.as_ref().user_data(); .push(PendingOperation::Activate);
user_data.set(|| -> WorkspaceUserdata { RefCell::new(Vec::new()) }); }
user_data.get::<WorkspaceUserdata>().unwrap().borrow_mut().push(PendingOperation::Deactivate); zext_workspace_handle_v1::Request::Deactivate => {
}, let user_data = workspace.as_ref().user_data();
zext_workspace_handle_v1::Request::Remove => { user_data.set(|| -> WorkspaceUserdata { RefCell::new(Vec::new()) });
let user_data = workspace.as_ref().user_data(); user_data
user_data.set(|| -> WorkspaceUserdata { RefCell::new(Vec::new()) }); .get::<WorkspaceUserdata>()
user_data.get::<WorkspaceUserdata>().unwrap().borrow_mut().push(PendingOperation::Remove); .unwrap()
}, .borrow_mut()
zext_workspace_handle_v1::Request::Destroy => { .push(PendingOperation::Deactivate);
workspace_inner_clone.lock().unwrap().instances.retain(|w| **w != *workspace); }
}, zext_workspace_handle_v1::Request::Remove => {
let user_data = workspace.as_ref().user_data();
user_data.set(|| -> WorkspaceUserdata { RefCell::new(Vec::new()) });
user_data
.get::<WorkspaceUserdata>()
.unwrap()
.borrow_mut()
.push(PendingOperation::Remove);
}
zext_workspace_handle_v1::Request::Destroy => {
workspace_inner_clone
.lock()
.unwrap()
.instances
.retain(|w| **w != *workspace);
} }
}); });
Some(workspace) Some(workspace)
@ -435,10 +565,30 @@ impl Workspace {
impl WorkspaceInner { impl WorkspaceInner {
fn send(&self, client: &Client) { fn send(&self, client: &Client) {
if let Some(instance) = self.instances.iter().find(|w| w.as_ref().client().map(|c| &c == client).unwrap_or(false)) { if let Some(instance) = self
.instances
.iter()
.find(|w| w.as_ref().client().map(|c| &c == client).unwrap_or(false))
{
instance.name(self.name.clone()); instance.name(self.name.clone());
instance.state(self.states.iter().map(|x| x.to_raw() as u8).collect()); let states = {
instance.coordinates(self.coordinates.clone()); let mut states = self.states.clone();
let ptr = states.as_mut_ptr();
let len = states.len();
let cap = states.capacity();
::std::mem::forget(states);
unsafe { Vec::from_raw_parts(ptr as *mut u8, len * 4, cap * 4) }
};
instance.state(states);
let coords = {
let mut coords = self.coordinates.clone();
let ptr = coords.as_mut_ptr();
let len = coords.len();
let cap = coords.capacity();
::std::mem::forget(coords);
unsafe { Vec::from_raw_parts(ptr as *mut u8, len * 4, cap * 4) }
};
instance.coordinates(coords);
} }
} }
} }