Update to workspace v2, based on ext-workspace
In the workspace applet, this now uses `Workspace` in the front-end code instead of a tuple with unnamed fields. Handling of scrolling is also moved to the frontend, which uses less code and seems more natural. It would be good to have a helper in libcosmic for this. It also changes `ObjectId` to `ExtWorkspaceHandleV1`, which is a little simpler and I see no reason here to avoid the more strongly typed object. At some point we may want a shared subscription for workspaces in multiple applets. As well as a higher-level abstraction for screen capture.
This commit is contained in:
parent
f08d80a891
commit
7ba2ed0c53
12 changed files with 196 additions and 269 deletions
|
|
@ -10,35 +10,29 @@ use cctk::{
|
|||
calloop,
|
||||
calloop_wayland_source::WaylandSource,
|
||||
client::{self as wayland_client},
|
||||
protocols::ext::workspace::v1::client::ext_workspace_handle_v1::ExtWorkspaceHandleV1,
|
||||
},
|
||||
registry::{ProvidesRegistryState, RegistryState},
|
||||
},
|
||||
workspace::{WorkspaceHandler, WorkspaceState},
|
||||
workspace::{Workspace, WorkspaceHandler, WorkspaceState},
|
||||
};
|
||||
use cosmic_protocols::workspace::v1::client::zcosmic_workspace_handle_v1;
|
||||
use futures::{channel::mpsc, executor::block_on, SinkExt};
|
||||
use std::{
|
||||
os::{
|
||||
fd::{FromRawFd, RawFd},
|
||||
unix::net::UnixStream,
|
||||
},
|
||||
time::{Duration, Instant},
|
||||
use std::os::{
|
||||
fd::{FromRawFd, RawFd},
|
||||
unix::net::UnixStream,
|
||||
};
|
||||
use wayland_client::{
|
||||
backend::ObjectId,
|
||||
globals::registry_queue_init,
|
||||
protocol::wl_output::{self, WlOutput},
|
||||
Connection, Proxy, QueueHandle, WEnum,
|
||||
Connection, QueueHandle,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum WorkspaceEvent {
|
||||
Activate(ObjectId),
|
||||
Scroll(f64, bool),
|
||||
Activate(ExtWorkspaceHandleV1),
|
||||
}
|
||||
pub type WorkspaceList = Vec<(String, Option<zcosmic_workspace_handle_v1::State>, ObjectId)>;
|
||||
|
||||
pub fn spawn_workspaces(tx: mpsc::Sender<WorkspaceList>) -> SyncSender<WorkspaceEvent> {
|
||||
pub fn spawn_workspaces(tx: mpsc::Sender<Vec<Workspace>>) -> SyncSender<WorkspaceEvent> {
|
||||
let (workspaces_tx, workspaces_rx) = calloop::channel::sync_channel(100);
|
||||
|
||||
let socket = std::env::var("X_PRIVILEGED_WAYLAND_SOCKET")
|
||||
|
|
@ -81,100 +75,18 @@ pub fn spawn_workspaces(tx: mpsc::Sender<WorkspaceList>) -> SyncSender<Workspace
|
|||
tx,
|
||||
running: true,
|
||||
have_workspaces: false,
|
||||
scroll: 0.0,
|
||||
next_scroll: None,
|
||||
last_scroll: Instant::now(),
|
||||
};
|
||||
let loop_handle = event_loop.handle();
|
||||
loop_handle
|
||||
.insert_source(workspaces_rx, |e, _, state| match e {
|
||||
Event::Msg(WorkspaceEvent::Activate(id)) => {
|
||||
if let Some(w) = state
|
||||
Event::Msg(WorkspaceEvent::Activate(handle)) => {
|
||||
handle.activate();
|
||||
state
|
||||
.workspace_state
|
||||
.workspace_groups()
|
||||
.iter()
|
||||
.find_map(|g| g.workspaces.iter().find(|w| w.handle.id() == id))
|
||||
{
|
||||
w.handle.activate();
|
||||
state
|
||||
.workspace_state
|
||||
.workspace_manager()
|
||||
.get()
|
||||
.unwrap()
|
||||
.commit();
|
||||
}
|
||||
}
|
||||
Event::Msg(WorkspaceEvent::Scroll(v, debounce)) => {
|
||||
let dur = if debounce {
|
||||
Duration::from_millis(350)
|
||||
} else {
|
||||
Duration::from_millis(200)
|
||||
};
|
||||
if state.last_scroll.elapsed() > Duration::from_millis(100)
|
||||
|| state.scroll * v < 0.0
|
||||
{
|
||||
state.next_scroll = None;
|
||||
state.scroll = 0.0;
|
||||
}
|
||||
state.last_scroll = Instant::now();
|
||||
|
||||
state.scroll += v;
|
||||
if let Some(next) = state.next_scroll {
|
||||
if next > Instant::now() {
|
||||
return;
|
||||
}
|
||||
state.next_scroll = None;
|
||||
}
|
||||
|
||||
if state.scroll.abs() < 1.0 {
|
||||
return;
|
||||
}
|
||||
state.next_scroll = Some(Instant::now() + dur);
|
||||
if let Some((w_g, w_i)) = state
|
||||
.workspace_state
|
||||
.workspace_groups()
|
||||
.iter()
|
||||
.find_map(|g| {
|
||||
if !g
|
||||
.outputs
|
||||
.iter()
|
||||
.any(|o| Some(o) == state.expected_output.as_ref())
|
||||
{
|
||||
return None;
|
||||
}
|
||||
g.workspaces
|
||||
.iter()
|
||||
.position(|w| {
|
||||
w.state.contains(&WEnum::Value(
|
||||
zcosmic_workspace_handle_v1::State::Active,
|
||||
))
|
||||
})
|
||||
.map(|w_i| (g, w_i))
|
||||
})
|
||||
{
|
||||
let max_w = w_g.workspaces.len().wrapping_sub(1);
|
||||
let d_i = if state.scroll > 0.0 {
|
||||
if w_i == 0 {
|
||||
max_w
|
||||
} else {
|
||||
w_i.wrapping_sub(1)
|
||||
}
|
||||
} else if w_i == max_w {
|
||||
0
|
||||
} else {
|
||||
w_i.wrapping_add(1)
|
||||
};
|
||||
state.scroll = 0.0;
|
||||
if let Some(w) = w_g.workspaces.get(d_i) {
|
||||
w.handle.activate();
|
||||
state
|
||||
.workspace_state
|
||||
.workspace_manager()
|
||||
.get()
|
||||
.unwrap()
|
||||
.commit();
|
||||
}
|
||||
}
|
||||
.workspace_manager()
|
||||
.get()
|
||||
.unwrap()
|
||||
.commit();
|
||||
}
|
||||
Event::Closed => {
|
||||
if let Ok(workspace_manager) =
|
||||
|
|
@ -203,62 +115,30 @@ pub fn spawn_workspaces(tx: mpsc::Sender<WorkspaceList>) -> SyncSender<Workspace
|
|||
#[derive(Debug)]
|
||||
pub struct State {
|
||||
running: bool,
|
||||
tx: mpsc::Sender<WorkspaceList>,
|
||||
tx: mpsc::Sender<Vec<Workspace>>,
|
||||
configured_output: String,
|
||||
expected_output: Option<WlOutput>,
|
||||
output_state: OutputState,
|
||||
registry_state: RegistryState,
|
||||
workspace_state: WorkspaceState,
|
||||
have_workspaces: bool,
|
||||
scroll: f64,
|
||||
next_scroll: Option<Instant>,
|
||||
last_scroll: Instant,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn workspace_list(
|
||||
&self,
|
||||
) -> Vec<(String, Option<zcosmic_workspace_handle_v1::State>, ObjectId)> {
|
||||
pub fn workspace_list(&self) -> Vec<Workspace> {
|
||||
self.workspace_state
|
||||
.workspace_groups()
|
||||
.iter()
|
||||
.filter_map(|g| {
|
||||
if g.outputs
|
||||
.filter(|g| {
|
||||
g.outputs
|
||||
.iter()
|
||||
.any(|o| Some(o) == self.expected_output.as_ref())
|
||||
{
|
||||
Some(g.workspaces.iter().map(|w| {
|
||||
(
|
||||
w.name.clone(),
|
||||
match &w.state {
|
||||
x if x.contains(&WEnum::Value(
|
||||
zcosmic_workspace_handle_v1::State::Active,
|
||||
)) =>
|
||||
{
|
||||
Some(zcosmic_workspace_handle_v1::State::Active)
|
||||
}
|
||||
x if x.contains(&WEnum::Value(
|
||||
zcosmic_workspace_handle_v1::State::Urgent,
|
||||
)) =>
|
||||
{
|
||||
Some(zcosmic_workspace_handle_v1::State::Urgent)
|
||||
}
|
||||
x if x.contains(&WEnum::Value(
|
||||
zcosmic_workspace_handle_v1::State::Hidden,
|
||||
)) =>
|
||||
{
|
||||
Some(zcosmic_workspace_handle_v1::State::Hidden)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
w.handle.id(),
|
||||
)
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.flat_map(|g| {
|
||||
g.workspaces
|
||||
.iter()
|
||||
.filter_map(|handle| self.workspace_state.workspace_info(handle))
|
||||
})
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue