working!
This commit is contained in:
parent
d37ef516f3
commit
bf24020a7a
4 changed files with 85 additions and 22 deletions
17
rust/Cargo.lock
generated
17
rust/Cargo.lock
generated
|
|
@ -151,6 +151,21 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
|
@ -610,7 +625,9 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||||
name = "rust_lib_flight"
|
name = "rust_lib_flight"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
"flutter_rust_bridge",
|
"flutter_rust_bridge",
|
||||||
|
"libc",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,5 @@ wayland-client = "0.31"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
wayland-protocols = { version = "0.32.12", features = ["client", "staging"] }
|
wayland-protocols = { version = "0.32.12", features = ["client", "staging"] }
|
||||||
|
libc = "0.2.185"
|
||||||
|
crossbeam-channel = "0.5.15"
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,34 @@
|
||||||
use crate::{frb_generated::StreamSink, internal::wayland::AppState};
|
use crate::{frb_generated::StreamSink, internal::wayland::AppState};
|
||||||
use flutter_rust_bridge::RustAutoOpaqueNom;
|
|
||||||
use serde_json::Result;
|
use serde_json::Result;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use wayland_client::Connection;
|
use wayland_client::Connection;
|
||||||
use wayland_protocols::ext::workspace::v1::client::{
|
use std::sync::{OnceLock, mpsc::Sender};
|
||||||
ext_workspace_handle_v1::ExtWorkspaceHandleV1, ext_workspace_manager_v1::ExtWorkspaceManagerV1,
|
use std::os::fd::AsRawFd;
|
||||||
};
|
|
||||||
|
static CONTROLLER: OnceLock<Sender<u32>> = OnceLock::new();
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Workspace {
|
pub struct Workspace {
|
||||||
pub activated: bool,
|
pub activated: bool,
|
||||||
pub id: u32,
|
pub id: u32,
|
||||||
pub coords: Option<(u8, u8)>,
|
pub coords: Option<(u8, u8)>,
|
||||||
pub handle: RustAutoOpaqueNom<ExtWorkspaceHandleV1>,
|
|
||||||
pub manager_handle: RustAutoOpaqueNom<ExtWorkspaceManagerV1>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Workspace {
|
impl Workspace {
|
||||||
pub fn activate(&self) {
|
pub fn activate(&self) {
|
||||||
self.handle.try_read().unwrap().clone().activate();
|
if let Some(tx) = CONTROLLER.get() {
|
||||||
self.manager_handle.try_read().unwrap().clone().commit();
|
tx.send(self.id).expect("Sending activate command failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listen_workspaces(sink: StreamSink<Vec<Vec<Workspace>>>) -> Result<()> {
|
pub fn listen_workspaces(sink: StreamSink<Vec<Vec<Workspace>>>) -> Result<()> {
|
||||||
|
use std::sync::mpsc;
|
||||||
|
|
||||||
|
let (tx, rx) = mpsc::channel::<u32>();
|
||||||
|
|
||||||
|
CONTROLLER.set(tx).unwrap();
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
let conn = Connection::connect_to_env().expect("Failed to connect to Wayland");
|
let conn = Connection::connect_to_env().expect("Failed to connect to Wayland");
|
||||||
|
|
||||||
|
|
@ -32,17 +37,44 @@ pub fn listen_workspaces(sink: StreamSink<Vec<Vec<Workspace>>>) -> Result<()> {
|
||||||
|
|
||||||
let mut state = AppState {
|
let mut state = AppState {
|
||||||
workspaces: HashMap::new(),
|
workspaces: HashMap::new(),
|
||||||
workspace_group: HashMap::new(),
|
workspace_groups: HashMap::new(),
|
||||||
|
workspace_handles: HashMap::new(),
|
||||||
sink,
|
sink,
|
||||||
};
|
};
|
||||||
|
|
||||||
conn.display().get_registry(&qh, ());
|
conn.display().get_registry(&qh, ());
|
||||||
|
|
||||||
loop {
|
|
||||||
event_queue
|
loop {
|
||||||
.blocking_dispatch(&mut state)
|
event_queue.flush().unwrap();
|
||||||
.expect("Wayland dispatch failed");
|
|
||||||
|
let read_guard = event_queue.prepare_read().unwrap();
|
||||||
|
let fd = read_guard.connection_fd().as_raw_fd();
|
||||||
|
|
||||||
|
let mut fds = [libc::pollfd {
|
||||||
|
fd,
|
||||||
|
events: libc::POLLIN,
|
||||||
|
revents: 0,
|
||||||
|
}];
|
||||||
|
|
||||||
|
let timeout = 10;
|
||||||
|
|
||||||
|
let res = unsafe { libc::poll(fds.as_mut_ptr(), 1, timeout) };
|
||||||
|
|
||||||
|
if res > 0 && (fds[0].revents & libc::POLLIN) != 0 {
|
||||||
|
read_guard.read().unwrap();
|
||||||
|
event_queue.dispatch_pending(&mut state).unwrap();
|
||||||
|
} else {
|
||||||
|
drop(read_guard);
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Ok(id) = rx.try_recv() {
|
||||||
|
if let Some(ws) = state.workspace_handles.get(&id) {
|
||||||
|
ws.handle.activate();
|
||||||
|
ws.manager_handle.commit();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::{frb_generated::StreamSink, workspace_api::Workspace};
|
use crate::{frb_generated::StreamSink, workspace_api::Workspace};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use flutter_rust_bridge::RustAutoOpaqueNom;
|
|
||||||
use wayland_client::{
|
use wayland_client::{
|
||||||
self, event_created_child, protocol::wl_registry, Connection, Dispatch, Proxy, QueueHandle,
|
self, event_created_child, protocol::wl_registry, Connection, Dispatch, Proxy, QueueHandle,
|
||||||
};
|
};
|
||||||
|
|
@ -10,9 +9,15 @@ use wayland_protocols::ext::workspace::v1::client::{
|
||||||
ext_workspace_group_handle_v1, ext_workspace_handle_v1, ext_workspace_manager_v1,
|
ext_workspace_group_handle_v1, ext_workspace_handle_v1, ext_workspace_manager_v1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub struct WorkspaceHandles {
|
||||||
|
pub handle: ext_workspace_handle_v1::ExtWorkspaceHandleV1,
|
||||||
|
pub manager_handle: ext_workspace_manager_v1::ExtWorkspaceManagerV1,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
pub workspaces: HashMap<u32, Workspace>,
|
pub workspaces: HashMap<u32, Workspace>,
|
||||||
pub workspace_group: HashMap<u32, u32>,
|
pub workspace_groups: HashMap<u32, u32>,
|
||||||
|
pub workspace_handles: HashMap<u32, WorkspaceHandles>,
|
||||||
pub sink: StreamSink<Vec<Vec<Workspace>>>,
|
pub sink: StreamSink<Vec<Vec<Workspace>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -21,7 +26,7 @@ impl AppState {
|
||||||
let mut groups: HashMap<u32, Vec<(&u32, &Workspace)>> = HashMap::new();
|
let mut groups: HashMap<u32, Vec<(&u32, &Workspace)>> = HashMap::new();
|
||||||
|
|
||||||
for (ws_id, ws) in &self.workspaces {
|
for (ws_id, ws) in &self.workspaces {
|
||||||
if let Some(group_id) = self.workspace_group.get(ws_id) {
|
if let Some(group_id) = self.workspace_groups.get(ws_id) {
|
||||||
groups
|
groups
|
||||||
.entry(group_id.clone())
|
.entry(group_id.clone())
|
||||||
.or_insert_with(Vec::new)
|
.or_insert_with(Vec::new)
|
||||||
|
|
@ -85,15 +90,21 @@ impl Dispatch<ext_workspace_manager_v1::ExtWorkspaceManagerV1, ()> for AppState
|
||||||
match event {
|
match event {
|
||||||
ext_workspace_manager_v1::Event::Workspace { workspace } => {
|
ext_workspace_manager_v1::Event::Workspace { workspace } => {
|
||||||
state.workspaces.insert(
|
state.workspaces.insert(
|
||||||
workspace.id().protocol_id().clone(),
|
workspace.id().protocol_id(),
|
||||||
Workspace {
|
Workspace {
|
||||||
activated: false,
|
activated: false,
|
||||||
id: workspace.id().protocol_id(),
|
id: workspace.id().protocol_id(),
|
||||||
handle: RustAutoOpaqueNom::new(workspace.clone()),
|
|
||||||
manager_handle: RustAutoOpaqueNom::new(proxy.clone()),
|
|
||||||
coords: None,
|
coords: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
state.workspace_handles.insert(
|
||||||
|
workspace.id().protocol_id(),
|
||||||
|
WorkspaceHandles {
|
||||||
|
handle: workspace,
|
||||||
|
manager_handle: proxy.clone(),
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
@ -156,7 +167,8 @@ impl Dispatch<ext_workspace_handle_v1::ExtWorkspaceHandleV1, ()> for AppState {
|
||||||
|
|
||||||
ext_workspace_handle_v1::Event::Removed => {
|
ext_workspace_handle_v1::Event::Removed => {
|
||||||
state.workspaces.remove(&id.protocol_id());
|
state.workspaces.remove(&id.protocol_id());
|
||||||
state.workspace_group.remove(&id.protocol_id());
|
state.workspace_groups.remove(&id.protocol_id());
|
||||||
|
state.workspace_handles.remove(&id.protocol_id());
|
||||||
state.emit();
|
state.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,13 +191,13 @@ impl Dispatch<ext_workspace_group_handle_v1::ExtWorkspaceGroupHandleV1, ()> for
|
||||||
match event {
|
match event {
|
||||||
ext_workspace_group_handle_v1::Event::WorkspaceEnter { workspace } => {
|
ext_workspace_group_handle_v1::Event::WorkspaceEnter { workspace } => {
|
||||||
state
|
state
|
||||||
.workspace_group
|
.workspace_groups
|
||||||
.insert(workspace.id().protocol_id(), group_id.protocol_id());
|
.insert(workspace.id().protocol_id(), group_id.protocol_id());
|
||||||
state.emit();
|
state.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
ext_workspace_group_handle_v1::Event::WorkspaceLeave { workspace } => {
|
ext_workspace_group_handle_v1::Event::WorkspaceLeave { workspace } => {
|
||||||
state.workspace_group.remove(&workspace.id().protocol_id());
|
state.workspace_groups.remove(&workspace.id().protocol_id());
|
||||||
state.emit();
|
state.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue