almost working
This commit is contained in:
parent
97a7c43a93
commit
58ef623f7c
7 changed files with 130 additions and 118 deletions
|
|
@ -1,12 +1,12 @@
|
||||||
import "package:flight/src/rust/api/workspace_api.dart";
|
import "package:flight/src/rust/api/workspace_api.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
|
|
||||||
class WorkspacesController extends StreamNotifier<List<List<Workspace>>> {
|
class WorkspacesController extends StreamNotifier<List<List<WorkspaceDto>>> {
|
||||||
@override
|
@override
|
||||||
Stream<List<List<Workspace>>> build() => listenWorkspaces();
|
Stream<List<List<WorkspaceDto>>> build() => listenWorkspaces();
|
||||||
|
|
||||||
static final provider =
|
static final provider =
|
||||||
StreamNotifierProvider<WorkspacesController, List<List<Workspace>>>(
|
StreamNotifierProvider<WorkspacesController, List<List<WorkspaceDto>>>(
|
||||||
WorkspacesController.new,
|
WorkspacesController.new,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ class Bar extends ConsumerWidget {
|
||||||
children: group
|
children: group
|
||||||
.map(
|
.map(
|
||||||
(workspace) => IconButton(
|
(workspace) => IconButton(
|
||||||
onPressed: () {},
|
onPressed: () => workspace.activate(),
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
workspace.activated
|
workspace.activated
|
||||||
? Icons.circle
|
? Icons.circle
|
||||||
|
|
|
||||||
52
rust/Cargo.lock
generated
52
rust/Cargo.lock
generated
|
|
@ -611,10 +611,8 @@ name = "rust_lib_flight"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"flutter_rust_bridge",
|
"flutter_rust_bridge",
|
||||||
"futures",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio",
|
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
"wayland-protocols",
|
"wayland-protocols",
|
||||||
]
|
]
|
||||||
|
|
@ -638,12 +636,6 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ryu"
|
|
||||||
version = "1.0.23"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
|
@ -652,18 +644,28 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.193"
|
version = "1.0.228"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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 = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.193"
|
version = "1.0.228"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -672,13 +674,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.109"
|
version = "1.0.149"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9"
|
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"memchr",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
"zmij",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -725,18 +729,6 @@ dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"pin-project-lite",
|
"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]]
|
[[package]]
|
||||||
|
|
@ -904,3 +896,9 @@ checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zmij"
|
||||||
|
version = "1.0.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,6 @@ crate-type = ["cdylib", "staticlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
flutter_rust_bridge = "=2.11.1"
|
flutter_rust_bridge = "=2.11.1"
|
||||||
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
|
|
||||||
futures = "0.3"
|
|
||||||
wayland-client = "0.31"
|
wayland-client = "0.31"
|
||||||
|
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
|
||||||
|
|
@ -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 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)]
|
||||||
#[derive(Clone, Debug)]
|
pub struct WorkspaceDto {
|
||||||
pub struct Workspace {
|
|
||||||
pub activated: bool,
|
pub activated: bool,
|
||||||
|
pub id: u32,
|
||||||
|
pub handle: RustAutoOpaqueNom<ExtWorkspaceHandleV1>,
|
||||||
|
pub manager_handle: RustAutoOpaqueNom<ExtWorkspaceManagerV1>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listen_workspaces(sink: StreamSink<Vec<Vec<Workspace>>>) -> 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<Vec<Vec<WorkspaceDto>>>) -> Result<()> {
|
||||||
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");
|
||||||
|
|
||||||
let mut event_queue: EventQueue<AppState> = conn.new_event_queue();
|
let mut event_queue = conn.new_event_queue();
|
||||||
let qh = event_queue.handle();
|
let qh = event_queue.handle();
|
||||||
|
|
||||||
let mut state = AppState {
|
let mut state = AppState {
|
||||||
workspaces: HashMap::new(),
|
workspaces: HashMap::new(),
|
||||||
workspace_group: HashMap::new(),
|
workspace_group: HashMap::new(),
|
||||||
workspace_coords: HashMap::new(),
|
|
||||||
sink,
|
sink,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -32,5 +44,5 @@ pub fn listen_workspaces(sink: StreamSink<Vec<Vec<Workspace>>>) -> Result<()> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(()) // Return struct with stream?bb
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 std::collections::HashMap;
|
||||||
|
|
||||||
|
use flutter_rust_bridge::RustAutoOpaqueNom;
|
||||||
use wayland_client::{
|
use wayland_client::{
|
||||||
self, backend::ObjectId, Proxy, Connection, Dispatch, QueueHandle, event_created_child,
|
self, event_created_child, protocol::wl_registry, Connection, Dispatch, Proxy, QueueHandle,
|
||||||
protocol::wl_registry,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use wayland_protocols::ext::workspace::v1::client::{
|
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 Workspace {
|
||||||
// App State
|
pub dto: WorkspaceDto,
|
||||||
// ------------------------
|
pub coords: Option<(u8, u8)>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
pub workspaces: HashMap<ObjectId, Workspace>,
|
pub workspaces: HashMap<u32, Workspace>,
|
||||||
pub workspace_group: HashMap<ObjectId, ObjectId>, // workspace -> group
|
pub workspace_group: HashMap<u32, u32>,
|
||||||
pub workspace_coords: HashMap<ObjectId, (u8, u8)>,
|
pub sink: StreamSink<Vec<Vec<WorkspaceDto>>>,
|
||||||
pub sink: StreamSink<Vec<Vec<Workspace>>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
fn emit(&self) {
|
fn emit(&self) {
|
||||||
let mut groups: HashMap<ObjectId, Vec<(&ObjectId, &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_group.get(ws_id) {
|
||||||
groups
|
groups
|
||||||
.entry(group_id.clone())
|
.entry(group_id.clone())
|
||||||
.or_insert_with(Vec::new)
|
.or_insert_with(Vec::new)
|
||||||
.push((ws_id, ws));
|
.push((ws_id, ws));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut grouped: Vec<(ObjectId, Vec<(&ObjectId, &Workspace)>)> =
|
let mut grouped: Vec<(u32, Vec<(&u32, &Workspace)>)> = groups.into_iter().collect();
|
||||||
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<Vec<Workspace>> = grouped
|
let result = grouped
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, mut entries)| {
|
.map(|(_, mut entries)| {
|
||||||
entries.sort_by_key(|(id, _)| {
|
entries.sort_by_key(|(_, value)| value.coords);
|
||||||
self.workspace_coords
|
|
||||||
.get(id)
|
|
||||||
.copied()
|
|
||||||
.unwrap_or((0, 0))
|
|
||||||
});
|
|
||||||
|
|
||||||
entries
|
entries.into_iter().map(|(_, ws)| ws.dto.clone()).collect()
|
||||||
.into_iter()
|
})
|
||||||
.map(|(_, ws)| ws.clone())
|
.collect();
|
||||||
.collect()
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let _ = self.sink.add(result);
|
let _ = self.sink.add(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dispatch<wl_registry::WlRegistry, ()> for AppState {
|
impl Dispatch<wl_registry::WlRegistry, ()> for AppState {
|
||||||
|
|
@ -89,13 +80,31 @@ impl Dispatch<wl_registry::WlRegistry, ()> for AppState {
|
||||||
|
|
||||||
impl Dispatch<ext_workspace_manager_v1::ExtWorkspaceManagerV1, ()> for AppState {
|
impl Dispatch<ext_workspace_manager_v1::ExtWorkspaceManagerV1, ()> for AppState {
|
||||||
fn event(
|
fn event(
|
||||||
_state: &mut Self,
|
state: &mut Self,
|
||||||
_proxy: &ext_workspace_manager_v1::ExtWorkspaceManagerV1,
|
proxy: &ext_workspace_manager_v1::ExtWorkspaceManagerV1,
|
||||||
_event: ext_workspace_manager_v1::Event,
|
event: ext_workspace_manager_v1::Event,
|
||||||
_data: &(),
|
_data: &(),
|
||||||
_conn: &Connection,
|
_conn: &Connection,
|
||||||
_qh: &QueueHandle<Self>,
|
_qh: &QueueHandle<Self>,
|
||||||
) {}
|
) {
|
||||||
|
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!(
|
event_created_child!(
|
||||||
AppState,
|
AppState,
|
||||||
|
|
@ -125,41 +134,36 @@ impl Dispatch<ext_workspace_handle_v1::ExtWorkspaceHandleV1, ()> for AppState {
|
||||||
let id = proxy.id();
|
let id = proxy.id();
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
ext_workspace_handle_v1::Event::Id { .. } => {
|
ext_workspace_handle_v1::Event::Coordinates { coordinates } => {
|
||||||
state.workspaces.insert(
|
let id = proxy.id();
|
||||||
id,
|
proxy.activate();
|
||||||
Workspace { activated: false },
|
|
||||||
);
|
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();
|
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 } => {
|
ext_workspace_handle_v1::Event::State { state: flags } => {
|
||||||
let active = matches!(
|
let active = matches!(
|
||||||
flags,
|
flags,
|
||||||
wayland_client::WEnum::Value(ext_workspace_handle_v1::State::Active)
|
wayland_client::WEnum::Value(ext_workspace_handle_v1::State::Active)
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(ws) = state.workspaces.get_mut(&id) {
|
if let Some(ws) = state.workspaces.get_mut(&id.protocol_id()) {
|
||||||
ws.activated = active;
|
ws.dto.activated = active;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.emit();
|
state.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
ext_workspace_handle_v1::Event::Removed => {
|
ext_workspace_handle_v1::Event::Removed => {
|
||||||
state.workspaces.remove(&id);
|
state.workspaces.remove(&id.protocol_id());
|
||||||
state.workspace_group.remove(&id);
|
state.workspace_group.remove(&id.protocol_id());
|
||||||
state.emit();
|
state.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -183,16 +187,16 @@ impl Dispatch<ext_workspace_group_handle_v1::ExtWorkspaceGroupHandleV1, ()> for
|
||||||
ext_workspace_group_handle_v1::Event::WorkspaceEnter { workspace } => {
|
ext_workspace_group_handle_v1::Event::WorkspaceEnter { workspace } => {
|
||||||
state
|
state
|
||||||
.workspace_group
|
.workspace_group
|
||||||
.insert(workspace.id(), group_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());
|
state.workspace_group.remove(&workspace.id().protocol_id());
|
||||||
state.emit();
|
state.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 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;
|
mod internal;
|
||||||
|
|
||||||
pub use api::*;
|
pub use api::*;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue