wayland: ext_workspace fixes
This commit is contained in:
parent
7803259949
commit
6096b8114e
2 changed files with 275 additions and 127 deletions
|
|
@ -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::*;
|
|
||||||
|
|
|
||||||
|
|
@ -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,67 +129,84 @@ 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
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<(Workspace, Vec<PendingOperation>)>>();
|
.collect::<Vec<(Workspace, Vec<PendingOperation>)>>();
|
||||||
|
|
||||||
std::mem::drop(group_inner);
|
std::mem::drop(group_inner);
|
||||||
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();
|
|
||||||
inner.instances.push(new_instance);
|
|
||||||
inner.send(&client);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
for workspace in group_inner_guard.workspaces.iter() {
|
||||||
|
if let Some(workspace) = workspace.upgrade() {
|
||||||
|
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,11 +338,13 @@ 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 {
|
||||||
|
self.inner
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.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) {
|
if let Some(group) = client.create_resource::<ZextWorkspaceGroupHandleV1>(1) {
|
||||||
let 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
||||||
|
|
@ -347,7 +428,7 @@ impl Workspace {
|
||||||
pub fn name(&self) -> String {
|
pub fn name(&self) -> String {
|
||||||
self.inner.lock().unwrap().name.clone()
|
self.inner.lock().unwrap().name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_name(&self, name: String) {
|
pub fn set_name(&self, name: String) {
|
||||||
let mut inner = self.inner.lock().unwrap();
|
let mut inner = self.inner.lock().unwrap();
|
||||||
for instance in inner.instances.iter() {
|
for instance in inner.instances.iter() {
|
||||||
|
|
@ -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,31 +515,48 @@ 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)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue