diff --git a/lib/controllers/workspaces_controller.dart b/lib/controllers/workspaces_controller.dart index 3a9b145..a53d67e 100644 --- a/lib/controllers/workspaces_controller.dart +++ b/lib/controllers/workspaces_controller.dart @@ -1,12 +1,12 @@ import "package:flight/src/rust/api/workspace_api.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; -class WorkspacesController extends StreamNotifier>> { +class WorkspacesController extends StreamNotifier>> { @override - Stream>> build() => listenWorkspaces(); + Stream>> build() => listenWorkspaces(); static final provider = - StreamNotifierProvider>>( + StreamNotifierProvider>>( WorkspacesController.new, ); } diff --git a/lib/widgets/bar.dart b/lib/widgets/bar.dart index e614820..66eeb10 100644 --- a/lib/widgets/bar.dart +++ b/lib/widgets/bar.dart @@ -26,7 +26,7 @@ class Bar extends ConsumerWidget { children: group .map( (workspace) => IconButton( - onPressed: () {}, + onPressed: () => workspace.activate(), icon: Icon( workspace.activated ? Icons.circle diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 34ad3cc..d1f3231 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -611,10 +611,8 @@ name = "rust_lib_flight" version = "0.1.0" dependencies = [ "flutter_rust_bridge", - "futures", "serde", "serde_json", - "tokio", "wayland-client", "wayland-protocols", ] @@ -638,12 +636,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "ryu" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" - [[package]] name = "scopeguard" version = "1.2.0" @@ -652,18 +644,28 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -672,13 +674,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.109" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", - "ryu", + "memchr", "serde", + "serde_core", + "zmij", ] [[package]] @@ -725,18 +729,6 @@ dependencies = [ "backtrace", "num_cpus", "pin-project-lite", - "tokio-macros", -] - -[[package]] -name = "tokio-macros" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -904,3 +896,9 @@ checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ "windows-link", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index f10a9c9..9da6ce3 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -8,8 +8,6 @@ crate-type = ["cdylib", "staticlib"] [dependencies] flutter_rust_bridge = "=2.11.1" -tokio = { version = "1", features = ["rt-multi-thread", "macros"] } -futures = "0.3" wayland-client = "0.31" serde = { version = "1", features = ["derive"] } diff --git a/rust/src/api/workspace_api.rs b/rust/src/api/workspace_api.rs index 997d82d..f5668c3 100644 --- a/rust/src/api/workspace_api.rs +++ b/rust/src/api/workspace_api.rs @@ -1,25 +1,37 @@ -use serde_json::Result; -use wayland_client::{Connection, EventQueue}; -use std::collections::HashMap; use crate::{frb_generated::StreamSink, internal::wayland::AppState}; +use flutter_rust_bridge::RustAutoOpaqueNom; +use serde_json::Result; +use std::collections::HashMap; +use wayland_client::Connection; +use wayland_protocols::ext::workspace::v1::client::{ + ext_workspace_handle_v1::ExtWorkspaceHandleV1, ext_workspace_manager_v1::ExtWorkspaceManagerV1, +}; - -#[derive(Clone, Debug)] -pub struct Workspace { +#[derive(Clone)] +pub struct WorkspaceDto { pub activated: bool, + pub id: u32, + pub handle: RustAutoOpaqueNom, + pub manager_handle: RustAutoOpaqueNom, } -pub fn listen_workspaces(sink: StreamSink>>) -> Result<()> { +impl WorkspaceDto { + pub fn activate(&self) { + self.handle.try_read().unwrap().clone().activate(); + self.manager_handle.try_read().unwrap().clone().commit(); + } +} + +pub fn listen_workspaces(sink: StreamSink>>) -> Result<()> { std::thread::spawn(move || { let conn = Connection::connect_to_env().expect("Failed to connect to Wayland"); - let mut event_queue: EventQueue = conn.new_event_queue(); + let mut event_queue = conn.new_event_queue(); let qh = event_queue.handle(); let mut state = AppState { workspaces: HashMap::new(), - workspace_group: HashMap::new(), - workspace_coords: HashMap::new(), + workspace_group: HashMap::new(), sink, }; @@ -32,5 +44,5 @@ pub fn listen_workspaces(sink: StreamSink>>) -> Result<()> { } }); - Ok(()) -} \ No newline at end of file + Ok(()) // Return struct with stream?bb +} diff --git a/rust/src/internal/wayland.rs b/rust/src/internal/wayland.rs index ff06598..e297d55 100644 --- a/rust/src/internal/wayland.rs +++ b/rust/src/internal/wayland.rs @@ -1,63 +1,54 @@ -use crate::{frb_generated::StreamSink, workspace_api::Workspace}; +use crate::{frb_generated::StreamSink, workspace_api::WorkspaceDto}; use std::collections::HashMap; +use flutter_rust_bridge::RustAutoOpaqueNom; use wayland_client::{ - self, backend::ObjectId, Proxy, Connection, Dispatch, QueueHandle, event_created_child, - protocol::wl_registry, + self, event_created_child, protocol::wl_registry, Connection, Dispatch, Proxy, QueueHandle, }; use wayland_protocols::ext::workspace::v1::client::{ ext_workspace_group_handle_v1, ext_workspace_handle_v1, ext_workspace_manager_v1, }; -// ------------------------ -// App State -// ------------------------ +pub struct Workspace { + pub dto: WorkspaceDto, + pub coords: Option<(u8, u8)>, +} pub struct AppState { - pub workspaces: HashMap, - pub workspace_group: HashMap, // workspace -> group - pub workspace_coords: HashMap, - pub sink: StreamSink>>, + pub workspaces: HashMap, + pub workspace_group: HashMap, + pub sink: StreamSink>>, } impl AppState { - fn emit(&self) { - let mut groups: HashMap> = HashMap::new(); + fn emit(&self) { + let mut groups: HashMap> = HashMap::new(); - for (ws_id, ws) in &self.workspaces { - if let Some(group_id) = self.workspace_group.get(ws_id) { - groups - .entry(group_id.clone()) - .or_insert_with(Vec::new) - .push((ws_id, ws)); - } - } + for (ws_id, ws) in &self.workspaces { + if let Some(group_id) = self.workspace_group.get(ws_id) { + groups + .entry(group_id.clone()) + .or_insert_with(Vec::new) + .push((ws_id, ws)); + } + } - let mut grouped: Vec<(ObjectId, Vec<(&ObjectId, &Workspace)>)> = - groups.into_iter().collect(); + let mut grouped: Vec<(u32, Vec<(&u32, &Workspace)>)> = groups.into_iter().collect(); - grouped.sort_by_key(|(group_id, _)| group_id.protocol_id()); + grouped.sort_by_key(|(group_id, _)| group_id.clone()); - let result: Vec> = grouped - .into_iter() - .map(|(_, mut entries)| { - entries.sort_by_key(|(id, _)| { - self.workspace_coords - .get(id) - .copied() - .unwrap_or((0, 0)) - }); + let result = grouped + .into_iter() + .map(|(_, mut entries)| { + entries.sort_by_key(|(_, value)| value.coords); - entries - .into_iter() - .map(|(_, ws)| ws.clone()) - .collect() - }) - .collect(); + entries.into_iter().map(|(_, ws)| ws.dto.clone()).collect() + }) + .collect(); - let _ = self.sink.add(result); - } + let _ = self.sink.add(result); + } } impl Dispatch for AppState { @@ -89,13 +80,31 @@ impl Dispatch for AppState { impl Dispatch for AppState { fn event( - _state: &mut Self, - _proxy: &ext_workspace_manager_v1::ExtWorkspaceManagerV1, - _event: ext_workspace_manager_v1::Event, + state: &mut Self, + proxy: &ext_workspace_manager_v1::ExtWorkspaceManagerV1, + event: ext_workspace_manager_v1::Event, _data: &(), _conn: &Connection, _qh: &QueueHandle, - ) {} + ) { + match event { + ext_workspace_manager_v1::Event::Workspace { workspace } => { + state.workspaces.insert( + workspace.id().protocol_id().clone(), + Workspace { + dto: WorkspaceDto { + activated: false, + id: workspace.id().protocol_id(), + handle: RustAutoOpaqueNom::new(workspace.clone()), + manager_handle: RustAutoOpaqueNom::new(proxy.clone()), + }, + coords: None, + }, + ); + } + _ => {} + } + } event_created_child!( AppState, @@ -125,41 +134,36 @@ impl Dispatch for AppState { let id = proxy.id(); match event { - ext_workspace_handle_v1::Event::Id { .. } => { - state.workspaces.insert( - id, - Workspace { activated: false }, - ); + ext_workspace_handle_v1::Event::Coordinates { coordinates } => { + let id = proxy.id(); + proxy.activate(); + + if coordinates.len() >= 2 { + let coords: (u8, u8) = (coordinates[0], coordinates[1]); + if let Some(ws) = state.workspaces.get_mut(&id.protocol_id()) { + ws.coords = Some(coords); + } + } state.emit(); } - ext_workspace_handle_v1::Event::Coordinates { coordinates } => { - let id = proxy.id(); - - if coordinates.len() >= 2 { - state.workspace_coords.insert(id, (coordinates[0], coordinates[1])); - } - - state.emit(); - } - ext_workspace_handle_v1::Event::State { state: flags } => { let active = matches!( flags, wayland_client::WEnum::Value(ext_workspace_handle_v1::State::Active) ); - if let Some(ws) = state.workspaces.get_mut(&id) { - ws.activated = active; + if let Some(ws) = state.workspaces.get_mut(&id.protocol_id()) { + ws.dto.activated = active; } state.emit(); } ext_workspace_handle_v1::Event::Removed => { - state.workspaces.remove(&id); - state.workspace_group.remove(&id); + state.workspaces.remove(&id.protocol_id()); + state.workspace_group.remove(&id.protocol_id()); state.emit(); } @@ -183,16 +187,16 @@ impl Dispatch for ext_workspace_group_handle_v1::Event::WorkspaceEnter { workspace } => { state .workspace_group - .insert(workspace.id(), group_id); + .insert(workspace.id().protocol_id(), group_id.protocol_id()); state.emit(); } ext_workspace_group_handle_v1::Event::WorkspaceLeave { workspace } => { - state.workspace_group.remove(&workspace.id()); + state.workspace_group.remove(&workspace.id().protocol_id()); state.emit(); } _ => {} } } -} \ No newline at end of file +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 5985a31..b52f117 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1,5 +1,5 @@ -mod frb_generated; /* AUTO INJECTED BY flutter_rust_bridge. This line may not be accurate, and you can change it according to your needs. */ mod api; +mod frb_generated; /* AUTO INJECTED BY flutter_rust_bridge. This line may not be accurate, and you can change it according to your needs. */ mod internal; -pub use api::*; \ No newline at end of file +pub use api::*;