wayland: add jay_workspace
This commit is contained in:
parent
53ca7b5b2a
commit
83baa6aadb
10 changed files with 183 additions and 28 deletions
|
|
@ -7,6 +7,7 @@ use {
|
|||
zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1,
|
||||
},
|
||||
jay_output::JayOutput,
|
||||
jay_workspace::JayWorkspace,
|
||||
wl_buffer::WlBuffer,
|
||||
wl_display::WlDisplay,
|
||||
wl_output::WlOutput,
|
||||
|
|
@ -26,9 +27,9 @@ use {
|
|||
copyhashmap::{CopyHashMap, Locked},
|
||||
},
|
||||
wire::{
|
||||
JayOutputId, WlBufferId, WlDataSourceId, WlOutputId, WlPointerId, WlRegionId,
|
||||
WlRegistryId, WlSeatId, WlSurfaceId, XdgPositionerId, XdgSurfaceId, XdgToplevelId,
|
||||
XdgWmBaseId, ZwpPrimarySelectionSourceV1Id,
|
||||
JayOutputId, JayWorkspaceId, WlBufferId, WlDataSourceId, WlOutputId, WlPointerId,
|
||||
WlRegionId, WlRegistryId, WlSeatId, WlSurfaceId, XdgPositionerId, XdgSurfaceId,
|
||||
XdgToplevelId, XdgWmBaseId, ZwpPrimarySelectionSourceV1Id,
|
||||
},
|
||||
},
|
||||
std::{cell::RefCell, mem, rc::Rc},
|
||||
|
|
@ -49,6 +50,7 @@ pub struct Objects {
|
|||
pub regions: CopyHashMap<WlRegionId, Rc<WlRegion>>,
|
||||
pub buffers: CopyHashMap<WlBufferId, Rc<WlBuffer>>,
|
||||
pub jay_outputs: CopyHashMap<JayOutputId, Rc<JayOutput>>,
|
||||
pub jay_workspaces: CopyHashMap<JayWorkspaceId, Rc<JayWorkspace>>,
|
||||
pub pointers: CopyHashMap<WlPointerId, Rc<WlPointer>>,
|
||||
pub xdg_wm_bases: CopyHashMap<XdgWmBaseId, Rc<XdgWmBase>>,
|
||||
pub seats: CopyHashMap<WlSeatId, Rc<WlSeat>>,
|
||||
|
|
@ -74,6 +76,7 @@ impl Objects {
|
|||
regions: Default::default(),
|
||||
buffers: Default::default(),
|
||||
jay_outputs: Default::default(),
|
||||
jay_workspaces: Default::default(),
|
||||
pointers: Default::default(),
|
||||
xdg_wm_bases: Default::default(),
|
||||
seats: Default::default(),
|
||||
|
|
@ -103,6 +106,7 @@ impl Objects {
|
|||
self.regions.clear();
|
||||
self.buffers.clear();
|
||||
self.jay_outputs.clear();
|
||||
self.jay_workspaces.clear();
|
||||
self.xdg_wm_bases.clear();
|
||||
self.seats.clear();
|
||||
self.pointers.clear();
|
||||
|
|
|
|||
|
|
@ -404,6 +404,7 @@ fn create_dummy_output(state: &Rc<State>) {
|
|||
fullscreen: Default::default(),
|
||||
visible_on_desired_output: Default::default(),
|
||||
desired_output: CloneCell::new(dummy_output.global.output_id.clone()),
|
||||
jay_workspaces: Default::default(),
|
||||
});
|
||||
dummy_workspace.output_link.set(Some(
|
||||
dummy_output.workspaces.add_last(dummy_workspace.clone()),
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ pub mod jay_pointer;
|
|||
pub mod jay_render_ctx;
|
||||
pub mod jay_screenshot;
|
||||
pub mod jay_seat_events;
|
||||
pub mod jay_workspace;
|
||||
pub mod org_kde_kwin_server_decoration;
|
||||
pub mod org_kde_kwin_server_decoration_manager;
|
||||
pub mod wl_buffer;
|
||||
|
|
|
|||
102
src/ifs/jay_workspace.rs
Normal file
102
src/ifs/jay_workspace.rs
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
use {
|
||||
crate::{
|
||||
client::{Client, ClientError},
|
||||
leaks::Tracker,
|
||||
object::Object,
|
||||
tree::{OutputNode, WorkspaceNode},
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
},
|
||||
wire::{jay_workspace::*, JayWorkspaceId},
|
||||
},
|
||||
std::rc::Rc,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct JayWorkspace {
|
||||
pub id: JayWorkspaceId,
|
||||
pub client: Rc<Client>,
|
||||
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl JayWorkspace {
|
||||
pub fn send_linear_id(&self, ws: &WorkspaceNode) {
|
||||
self.client.event(LinearId {
|
||||
self_id: self.id,
|
||||
linear_id: ws.id.raw(),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_name(&self, ws: &WorkspaceNode) {
|
||||
self.client.event(Name {
|
||||
self_id: self.id,
|
||||
name: &ws.name,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_destroyed(&self) {
|
||||
self.client.event(Destroyed { self_id: self.id });
|
||||
}
|
||||
|
||||
pub fn send_done(&self) {
|
||||
self.client.event(Done { self_id: self.id });
|
||||
}
|
||||
|
||||
pub fn send_output(&self, output: &OutputNode) {
|
||||
self.client.event(Output {
|
||||
self_id: self.id,
|
||||
global_name: output.global.name.raw(),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_visible(&self, visible: bool) {
|
||||
self.client.event(Visible {
|
||||
self_id: self.id,
|
||||
visible: visible as _,
|
||||
});
|
||||
}
|
||||
|
||||
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), JayWorkspaceError> {
|
||||
let _req: Destroy = self.client.parse(self, parser)?;
|
||||
self.remove_from_node();
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_from_node(&self) {
|
||||
if let Some(ws) = self.workspace.take() {
|
||||
ws.jay_workspaces.remove(&(self.client.id, self.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
JayWorkspace;
|
||||
|
||||
DESTROY => destroy,
|
||||
}
|
||||
|
||||
impl Object for JayWorkspace {
|
||||
fn num_requests(&self) -> u32 {
|
||||
DESTROY + 1
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.remove_from_node();
|
||||
}
|
||||
}
|
||||
|
||||
dedicated_add_obj!(JayWorkspace, JayWorkspaceId, jay_workspaces);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum JayWorkspaceError {
|
||||
#[error("Parsing failed")]
|
||||
MsgParserError(Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(JayWorkspaceError, MsgParserError);
|
||||
efrom!(JayWorkspaceError, ClientError);
|
||||
31
src/state.rs
31
src/state.rs
|
|
@ -434,15 +434,15 @@ impl State {
|
|||
}
|
||||
|
||||
pub fn show_workspace(&self, seat: &Rc<WlSeatGlobal>, name: &str) {
|
||||
let output = match self.workspaces.get(name) {
|
||||
let (output, ws) = match self.workspaces.get(name) {
|
||||
Some(ws) => {
|
||||
let output = ws.output.get();
|
||||
let did_change = output.show_workspace(&ws);
|
||||
ws.node_do_focus(seat, Direction::Unspecified);
|
||||
ws.clone().node_do_focus(seat, Direction::Unspecified);
|
||||
if !did_change {
|
||||
return;
|
||||
}
|
||||
output
|
||||
(output, ws)
|
||||
}
|
||||
_ => {
|
||||
let output = seat.get_output();
|
||||
|
|
@ -450,29 +450,12 @@ impl State {
|
|||
log::warn!("Not showing workspace because seat is on dummy output");
|
||||
return;
|
||||
}
|
||||
let workspace = Rc::new(WorkspaceNode {
|
||||
id: self.node_ids.next(),
|
||||
is_dummy: false,
|
||||
output: CloneCell::new(output.clone()),
|
||||
position: Cell::new(Default::default()),
|
||||
container: Default::default(),
|
||||
stacked: Default::default(),
|
||||
seat_state: Default::default(),
|
||||
name: name.to_string(),
|
||||
output_link: Cell::new(None),
|
||||
visible: Cell::new(false),
|
||||
fullscreen: Default::default(),
|
||||
visible_on_desired_output: Cell::new(false),
|
||||
desired_output: CloneCell::new(output.global.output_id.clone()),
|
||||
});
|
||||
workspace
|
||||
.output_link
|
||||
.set(Some(output.workspaces.add_last(workspace.clone())));
|
||||
output.show_workspace(&workspace);
|
||||
self.workspaces.set(name.to_string(), workspace);
|
||||
output
|
||||
let ws = output.create_workspace(name);
|
||||
output.show_workspace(&ws);
|
||||
(output, ws)
|
||||
}
|
||||
};
|
||||
ws.flush_jay_workspaces();
|
||||
output.update_render_data();
|
||||
self.tree_changed();
|
||||
// let seats = self.globals.seats.lock();
|
||||
|
|
|
|||
|
|
@ -166,6 +166,7 @@ impl ConnectorHandler {
|
|||
} else {
|
||||
ws.set_visible(false);
|
||||
}
|
||||
ws.flush_jay_workspaces();
|
||||
if let Some(visible) = source.node.workspace.get() {
|
||||
if visible.id == ws.id {
|
||||
source.node.workspace.take();
|
||||
|
|
@ -175,6 +176,7 @@ impl ConnectorHandler {
|
|||
if source.node.workspace.get().is_none() {
|
||||
if let Some(ws) = source.node.workspaces.first() {
|
||||
source.node.show_workspace(&ws);
|
||||
ws.flush_jay_workspaces();
|
||||
}
|
||||
}
|
||||
source.node.update_render_data();
|
||||
|
|
@ -182,6 +184,7 @@ impl ConnectorHandler {
|
|||
if on.workspace.get().is_none() {
|
||||
if let Some(ws) = on.workspaces.first() {
|
||||
on.show_workspace(&ws);
|
||||
ws.flush_jay_workspaces();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -239,6 +242,7 @@ impl ConnectorHandler {
|
|||
} else if ws.visible.get() {
|
||||
ws.set_visible(false);
|
||||
}
|
||||
ws.flush_jay_workspaces();
|
||||
}
|
||||
target.update_render_data();
|
||||
self.state.tree_changed();
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@ impl OutputNode {
|
|||
fullscreen: Default::default(),
|
||||
visible_on_desired_output: Cell::new(false),
|
||||
desired_output: CloneCell::new(self.global.output_id.clone()),
|
||||
jay_workspaces: Default::default(),
|
||||
});
|
||||
self.state.workspaces.set(name, workspace.clone());
|
||||
workspace
|
||||
|
|
@ -254,10 +255,16 @@ impl OutputNode {
|
|||
return false;
|
||||
}
|
||||
collect_kb_foci2(old.clone(), &mut seats);
|
||||
old.set_visible(false);
|
||||
if old.is_empty() {
|
||||
for jw in old.jay_workspaces.lock().values() {
|
||||
jw.send_destroyed();
|
||||
jw.workspace.set(None);
|
||||
}
|
||||
old.clear();
|
||||
self.state.workspaces.remove(&old.name);
|
||||
} else {
|
||||
old.set_visible(false);
|
||||
old.flush_jay_workspaces();
|
||||
}
|
||||
}
|
||||
ws.set_visible(true);
|
||||
|
|
@ -286,6 +293,7 @@ impl OutputNode {
|
|||
fullscreen: Default::default(),
|
||||
visible_on_desired_output: Cell::new(false),
|
||||
desired_output: CloneCell::new(self.global.output_id.clone()),
|
||||
jay_workspaces: Default::default(),
|
||||
});
|
||||
ws.output_link
|
||||
.set(Some(self.workspaces.add_last(ws.clone())));
|
||||
|
|
@ -581,6 +589,7 @@ impl Node for OutputNode {
|
|||
return;
|
||||
};
|
||||
self.show_workspace(&ws);
|
||||
ws.flush_jay_workspaces();
|
||||
self.update_render_data();
|
||||
self.state.tree_changed();
|
||||
}
|
||||
|
|
@ -615,6 +624,7 @@ impl Node for OutputNode {
|
|||
if !self.show_workspace(&ws) {
|
||||
return;
|
||||
}
|
||||
ws.flush_jay_workspaces();
|
||||
ws.deref()
|
||||
.clone()
|
||||
.node_do_focus(seat, Direction::Unspecified);
|
||||
|
|
|
|||
|
|
@ -316,6 +316,7 @@ impl ToplevelData {
|
|||
fd.workspace.fullscreen.take();
|
||||
if node.node_visible() {
|
||||
fd.workspace.set_visible(true);
|
||||
fd.workspace.flush_jay_workspaces();
|
||||
}
|
||||
if fd.placeholder.is_destroyed() {
|
||||
state.map_tiled(node);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
use {
|
||||
crate::{
|
||||
client::ClientId,
|
||||
cursor::KnownCursor,
|
||||
ifs::{
|
||||
jay_workspace::JayWorkspace,
|
||||
wl_output::OutputId,
|
||||
wl_seat::{NodeSeatState, WlSeatGlobal},
|
||||
wl_surface::WlSurface,
|
||||
|
|
@ -15,8 +17,10 @@ use {
|
|||
},
|
||||
utils::{
|
||||
clonecell::CloneCell,
|
||||
copyhashmap::CopyHashMap,
|
||||
linkedlist::{LinkedList, LinkedNode},
|
||||
},
|
||||
wire::JayWorkspaceId,
|
||||
},
|
||||
std::{cell::Cell, fmt::Debug, ops::Deref, rc::Rc},
|
||||
};
|
||||
|
|
@ -37,6 +41,7 @@ pub struct WorkspaceNode {
|
|||
pub fullscreen: CloneCell<Option<Rc<dyn ToplevelNode>>>,
|
||||
pub visible_on_desired_output: Cell<bool>,
|
||||
pub desired_output: CloneCell<Rc<OutputId>>,
|
||||
pub jay_workspaces: CopyHashMap<(ClientId, JayWorkspaceId), Rc<JayWorkspace>>,
|
||||
}
|
||||
|
||||
impl WorkspaceNode {
|
||||
|
|
@ -44,10 +49,14 @@ impl WorkspaceNode {
|
|||
self.container.set(None);
|
||||
self.output_link.set(None);
|
||||
self.fullscreen.set(None);
|
||||
self.jay_workspaces.clear();
|
||||
}
|
||||
|
||||
pub fn set_output(&self, output: &Rc<OutputNode>) {
|
||||
self.output.set(output.clone());
|
||||
for jw in self.jay_workspaces.lock().values() {
|
||||
jw.send_output(output);
|
||||
}
|
||||
struct OutputSetter<'a>(&'a Rc<OutputNode>);
|
||||
impl NodeVisitorBase for OutputSetter<'_> {
|
||||
fn visit_surface(&mut self, node: &Rc<WlSurface>) {
|
||||
|
|
@ -85,7 +94,16 @@ impl WorkspaceNode {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn flush_jay_workspaces(&self) {
|
||||
for jw in self.jay_workspaces.lock().values() {
|
||||
jw.send_done();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_visible(&self, visible: bool) {
|
||||
for jw in self.jay_workspaces.lock().values() {
|
||||
jw.send_visible(visible);
|
||||
}
|
||||
self.visible.set(visible);
|
||||
if let Some(fs) = self.fullscreen.get() {
|
||||
fs.tl_set_visible(visible);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue