1
0
Fork 0
forked from wry/wry

wayland: add jay_workspace

This commit is contained in:
Julian Orth 2022-07-30 11:22:40 +02:00
parent 53ca7b5b2a
commit 83baa6aadb
10 changed files with 183 additions and 28 deletions

View file

@ -7,6 +7,7 @@ use {
zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1, zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1,
}, },
jay_output::JayOutput, jay_output::JayOutput,
jay_workspace::JayWorkspace,
wl_buffer::WlBuffer, wl_buffer::WlBuffer,
wl_display::WlDisplay, wl_display::WlDisplay,
wl_output::WlOutput, wl_output::WlOutput,
@ -26,9 +27,9 @@ use {
copyhashmap::{CopyHashMap, Locked}, copyhashmap::{CopyHashMap, Locked},
}, },
wire::{ wire::{
JayOutputId, WlBufferId, WlDataSourceId, WlOutputId, WlPointerId, WlRegionId, JayOutputId, JayWorkspaceId, WlBufferId, WlDataSourceId, WlOutputId, WlPointerId,
WlRegistryId, WlSeatId, WlSurfaceId, XdgPositionerId, XdgSurfaceId, XdgToplevelId, WlRegionId, WlRegistryId, WlSeatId, WlSurfaceId, XdgPositionerId, XdgSurfaceId,
XdgWmBaseId, ZwpPrimarySelectionSourceV1Id, XdgToplevelId, XdgWmBaseId, ZwpPrimarySelectionSourceV1Id,
}, },
}, },
std::{cell::RefCell, mem, rc::Rc}, std::{cell::RefCell, mem, rc::Rc},
@ -49,6 +50,7 @@ pub struct Objects {
pub regions: CopyHashMap<WlRegionId, Rc<WlRegion>>, pub regions: CopyHashMap<WlRegionId, Rc<WlRegion>>,
pub buffers: CopyHashMap<WlBufferId, Rc<WlBuffer>>, pub buffers: CopyHashMap<WlBufferId, Rc<WlBuffer>>,
pub jay_outputs: CopyHashMap<JayOutputId, Rc<JayOutput>>, pub jay_outputs: CopyHashMap<JayOutputId, Rc<JayOutput>>,
pub jay_workspaces: CopyHashMap<JayWorkspaceId, Rc<JayWorkspace>>,
pub pointers: CopyHashMap<WlPointerId, Rc<WlPointer>>, pub pointers: CopyHashMap<WlPointerId, Rc<WlPointer>>,
pub xdg_wm_bases: CopyHashMap<XdgWmBaseId, Rc<XdgWmBase>>, pub xdg_wm_bases: CopyHashMap<XdgWmBaseId, Rc<XdgWmBase>>,
pub seats: CopyHashMap<WlSeatId, Rc<WlSeat>>, pub seats: CopyHashMap<WlSeatId, Rc<WlSeat>>,
@ -74,6 +76,7 @@ impl Objects {
regions: Default::default(), regions: Default::default(),
buffers: Default::default(), buffers: Default::default(),
jay_outputs: Default::default(), jay_outputs: Default::default(),
jay_workspaces: Default::default(),
pointers: Default::default(), pointers: Default::default(),
xdg_wm_bases: Default::default(), xdg_wm_bases: Default::default(),
seats: Default::default(), seats: Default::default(),
@ -103,6 +106,7 @@ impl Objects {
self.regions.clear(); self.regions.clear();
self.buffers.clear(); self.buffers.clear();
self.jay_outputs.clear(); self.jay_outputs.clear();
self.jay_workspaces.clear();
self.xdg_wm_bases.clear(); self.xdg_wm_bases.clear();
self.seats.clear(); self.seats.clear();
self.pointers.clear(); self.pointers.clear();

View file

@ -404,6 +404,7 @@ fn create_dummy_output(state: &Rc<State>) {
fullscreen: Default::default(), fullscreen: Default::default(),
visible_on_desired_output: Default::default(), visible_on_desired_output: Default::default(),
desired_output: CloneCell::new(dummy_output.global.output_id.clone()), desired_output: CloneCell::new(dummy_output.global.output_id.clone()),
jay_workspaces: Default::default(),
}); });
dummy_workspace.output_link.set(Some( dummy_workspace.output_link.set(Some(
dummy_output.workspaces.add_last(dummy_workspace.clone()), dummy_output.workspaces.add_last(dummy_workspace.clone()),

View file

@ -9,6 +9,7 @@ pub mod jay_pointer;
pub mod jay_render_ctx; pub mod jay_render_ctx;
pub mod jay_screenshot; pub mod jay_screenshot;
pub mod jay_seat_events; pub mod jay_seat_events;
pub mod jay_workspace;
pub mod org_kde_kwin_server_decoration; pub mod org_kde_kwin_server_decoration;
pub mod org_kde_kwin_server_decoration_manager; pub mod org_kde_kwin_server_decoration_manager;
pub mod wl_buffer; pub mod wl_buffer;

102
src/ifs/jay_workspace.rs Normal file
View 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);

View file

@ -434,15 +434,15 @@ impl State {
} }
pub fn show_workspace(&self, seat: &Rc<WlSeatGlobal>, name: &str) { 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) => { Some(ws) => {
let output = ws.output.get(); let output = ws.output.get();
let did_change = output.show_workspace(&ws); 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 { if !did_change {
return; return;
} }
output (output, ws)
} }
_ => { _ => {
let output = seat.get_output(); let output = seat.get_output();
@ -450,29 +450,12 @@ impl State {
log::warn!("Not showing workspace because seat is on dummy output"); log::warn!("Not showing workspace because seat is on dummy output");
return; return;
} }
let workspace = Rc::new(WorkspaceNode { let ws = output.create_workspace(name);
id: self.node_ids.next(), output.show_workspace(&ws);
is_dummy: false, (output, ws)
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
} }
}; };
ws.flush_jay_workspaces();
output.update_render_data(); output.update_render_data();
self.tree_changed(); self.tree_changed();
// let seats = self.globals.seats.lock(); // let seats = self.globals.seats.lock();

View file

@ -166,6 +166,7 @@ impl ConnectorHandler {
} else { } else {
ws.set_visible(false); ws.set_visible(false);
} }
ws.flush_jay_workspaces();
if let Some(visible) = source.node.workspace.get() { if let Some(visible) = source.node.workspace.get() {
if visible.id == ws.id { if visible.id == ws.id {
source.node.workspace.take(); source.node.workspace.take();
@ -175,6 +176,7 @@ impl ConnectorHandler {
if source.node.workspace.get().is_none() { if source.node.workspace.get().is_none() {
if let Some(ws) = source.node.workspaces.first() { if let Some(ws) = source.node.workspaces.first() {
source.node.show_workspace(&ws); source.node.show_workspace(&ws);
ws.flush_jay_workspaces();
} }
} }
source.node.update_render_data(); source.node.update_render_data();
@ -182,6 +184,7 @@ impl ConnectorHandler {
if on.workspace.get().is_none() { if on.workspace.get().is_none() {
if let Some(ws) = on.workspaces.first() { if let Some(ws) = on.workspaces.first() {
on.show_workspace(&ws); on.show_workspace(&ws);
ws.flush_jay_workspaces();
} }
} }
} }
@ -239,6 +242,7 @@ impl ConnectorHandler {
} else if ws.visible.get() { } else if ws.visible.get() {
ws.set_visible(false); ws.set_visible(false);
} }
ws.flush_jay_workspaces();
} }
target.update_render_data(); target.update_render_data();
self.state.tree_changed(); self.state.tree_changed();

View file

@ -237,6 +237,7 @@ impl OutputNode {
fullscreen: Default::default(), fullscreen: Default::default(),
visible_on_desired_output: Cell::new(false), visible_on_desired_output: Cell::new(false),
desired_output: CloneCell::new(self.global.output_id.clone()), desired_output: CloneCell::new(self.global.output_id.clone()),
jay_workspaces: Default::default(),
}); });
self.state.workspaces.set(name, workspace.clone()); self.state.workspaces.set(name, workspace.clone());
workspace workspace
@ -254,10 +255,16 @@ impl OutputNode {
return false; return false;
} }
collect_kb_foci2(old.clone(), &mut seats); collect_kb_foci2(old.clone(), &mut seats);
old.set_visible(false);
if old.is_empty() { if old.is_empty() {
for jw in old.jay_workspaces.lock().values() {
jw.send_destroyed();
jw.workspace.set(None);
}
old.clear(); old.clear();
self.state.workspaces.remove(&old.name); self.state.workspaces.remove(&old.name);
} else {
old.set_visible(false);
old.flush_jay_workspaces();
} }
} }
ws.set_visible(true); ws.set_visible(true);
@ -286,6 +293,7 @@ impl OutputNode {
fullscreen: Default::default(), fullscreen: Default::default(),
visible_on_desired_output: Cell::new(false), visible_on_desired_output: Cell::new(false),
desired_output: CloneCell::new(self.global.output_id.clone()), desired_output: CloneCell::new(self.global.output_id.clone()),
jay_workspaces: Default::default(),
}); });
ws.output_link ws.output_link
.set(Some(self.workspaces.add_last(ws.clone()))); .set(Some(self.workspaces.add_last(ws.clone())));
@ -581,6 +589,7 @@ impl Node for OutputNode {
return; return;
}; };
self.show_workspace(&ws); self.show_workspace(&ws);
ws.flush_jay_workspaces();
self.update_render_data(); self.update_render_data();
self.state.tree_changed(); self.state.tree_changed();
} }
@ -615,6 +624,7 @@ impl Node for OutputNode {
if !self.show_workspace(&ws) { if !self.show_workspace(&ws) {
return; return;
} }
ws.flush_jay_workspaces();
ws.deref() ws.deref()
.clone() .clone()
.node_do_focus(seat, Direction::Unspecified); .node_do_focus(seat, Direction::Unspecified);

View file

@ -316,6 +316,7 @@ impl ToplevelData {
fd.workspace.fullscreen.take(); fd.workspace.fullscreen.take();
if node.node_visible() { if node.node_visible() {
fd.workspace.set_visible(true); fd.workspace.set_visible(true);
fd.workspace.flush_jay_workspaces();
} }
if fd.placeholder.is_destroyed() { if fd.placeholder.is_destroyed() {
state.map_tiled(node); state.map_tiled(node);

View file

@ -1,7 +1,9 @@
use { use {
crate::{ crate::{
client::ClientId,
cursor::KnownCursor, cursor::KnownCursor,
ifs::{ ifs::{
jay_workspace::JayWorkspace,
wl_output::OutputId, wl_output::OutputId,
wl_seat::{NodeSeatState, WlSeatGlobal}, wl_seat::{NodeSeatState, WlSeatGlobal},
wl_surface::WlSurface, wl_surface::WlSurface,
@ -15,8 +17,10 @@ use {
}, },
utils::{ utils::{
clonecell::CloneCell, clonecell::CloneCell,
copyhashmap::CopyHashMap,
linkedlist::{LinkedList, LinkedNode}, linkedlist::{LinkedList, LinkedNode},
}, },
wire::JayWorkspaceId,
}, },
std::{cell::Cell, fmt::Debug, ops::Deref, rc::Rc}, std::{cell::Cell, fmt::Debug, ops::Deref, rc::Rc},
}; };
@ -37,6 +41,7 @@ pub struct WorkspaceNode {
pub fullscreen: CloneCell<Option<Rc<dyn ToplevelNode>>>, pub fullscreen: CloneCell<Option<Rc<dyn ToplevelNode>>>,
pub visible_on_desired_output: Cell<bool>, pub visible_on_desired_output: Cell<bool>,
pub desired_output: CloneCell<Rc<OutputId>>, pub desired_output: CloneCell<Rc<OutputId>>,
pub jay_workspaces: CopyHashMap<(ClientId, JayWorkspaceId), Rc<JayWorkspace>>,
} }
impl WorkspaceNode { impl WorkspaceNode {
@ -44,10 +49,14 @@ impl WorkspaceNode {
self.container.set(None); self.container.set(None);
self.output_link.set(None); self.output_link.set(None);
self.fullscreen.set(None); self.fullscreen.set(None);
self.jay_workspaces.clear();
} }
pub fn set_output(&self, output: &Rc<OutputNode>) { pub fn set_output(&self, output: &Rc<OutputNode>) {
self.output.set(output.clone()); self.output.set(output.clone());
for jw in self.jay_workspaces.lock().values() {
jw.send_output(output);
}
struct OutputSetter<'a>(&'a Rc<OutputNode>); struct OutputSetter<'a>(&'a Rc<OutputNode>);
impl NodeVisitorBase for OutputSetter<'_> { impl NodeVisitorBase for OutputSetter<'_> {
fn visit_surface(&mut self, node: &Rc<WlSurface>) { 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) { pub fn set_visible(&self, visible: bool) {
for jw in self.jay_workspaces.lock().values() {
jw.send_visible(visible);
}
self.visible.set(visible); self.visible.set(visible);
if let Some(fs) = self.fullscreen.get() { if let Some(fs) = self.fullscreen.get() {
fs.tl_set_visible(visible); fs.tl_set_visible(visible);

31
wire/jay_workspace.txt Normal file
View file

@ -0,0 +1,31 @@
# requests
msg destroy = 0 {
}
# events
msg linear_id = 0 {
linear_id: u32,
}
msg name = 1 {
name: str,
}
msg destroyed = 2 {
}
msg done = 3 {
}
msg output = 4 {
global_name: u32,
}
msg visible = 5 {
visible: u32,
}