1
0
Fork 0
forked from wry/wry
wry/src/state.rs
2022-04-13 12:58:04 +02:00

293 lines
9.8 KiB
Rust

use {
crate::{
async_engine::{AsyncEngine, SpawnedFuture},
backend::{
Backend, BackendEvent, Connector, ConnectorId, ConnectorIds, InputDevice,
InputDeviceId, InputDeviceIds, MonitorInfo,
},
client::{Client, Clients},
config::ConfigProxy,
cursor::ServerCursors,
dbus::Dbus,
event_loop::EventLoop,
forker::ForkerProxy,
globals::{Globals, GlobalsError, WaylandGlobal},
ifs::{
wl_seat::{SeatIds, WlSeatGlobal},
wl_surface::NoneSurfaceExt,
},
logger::Logger,
rect::Rect,
render::RenderContext,
theme::Theme,
tree::{
ContainerNode, ContainerSplit, DisplayNode, FloatNode, Node, NodeIds, NodeVisitorBase,
OutputNode, SizedNode, WorkspaceNode,
},
utils::{
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, fdcloser::FdCloser,
linkedlist::LinkedList, queue::AsyncQueue,
},
wheel::Wheel,
xkbcommon::{XkbContext, XkbKeymap},
},
ahash::AHashMap,
jay_config::Direction,
std::{
cell::{Cell, RefCell},
rc::Rc,
sync::Arc,
},
};
pub struct State {
pub xkb_ctx: XkbContext,
pub backend: CloneCell<Option<Rc<dyn Backend>>>,
pub forker: CloneCell<Option<Rc<ForkerProxy>>>,
pub default_keymap: Rc<XkbKeymap>,
pub eng: Rc<AsyncEngine>,
pub el: Rc<EventLoop>,
pub render_ctx: CloneCell<Option<Rc<RenderContext>>>,
pub cursors: CloneCell<Option<Rc<ServerCursors>>>,
pub wheel: Rc<Wheel>,
pub clients: Clients,
pub globals: Globals,
pub connector_ids: ConnectorIds,
pub seat_ids: SeatIds,
pub input_device_ids: InputDeviceIds,
pub node_ids: NodeIds,
pub root: Rc<DisplayNode>,
pub workspaces: CopyHashMap<String, Rc<WorkspaceNode>>,
pub dummy_output: CloneCell<Option<Rc<OutputNode>>>,
pub backend_events: AsyncQueue<BackendEvent>,
pub input_device_handlers: RefCell<AHashMap<InputDeviceId, InputDeviceData>>,
pub seat_queue: LinkedList<Rc<WlSeatGlobal>>,
pub slow_clients: AsyncQueue<Rc<Client>>,
pub none_surface_ext: Rc<NoneSurfaceExt>,
pub tree_changed_sent: Cell<bool>,
pub config: CloneCell<Option<Rc<ConfigProxy>>>,
pub theme: Theme,
pub pending_container_layout: AsyncQueue<Rc<ContainerNode>>,
pub pending_container_render_data: AsyncQueue<Rc<ContainerNode>>,
pub pending_float_layout: AsyncQueue<Rc<FloatNode>>,
pub pending_float_titles: AsyncQueue<Rc<FloatNode>>,
pub dbus: Dbus,
pub fdcloser: Arc<FdCloser>,
pub logger: Arc<Logger>,
pub connectors: CopyHashMap<ConnectorId, Rc<ConnectorData>>,
pub outputs: CopyHashMap<ConnectorId, Rc<OutputData>>,
pub status: CloneCell<Rc<String>>,
}
pub struct InputDeviceData {
pub handler: SpawnedFuture<()>,
pub id: InputDeviceId,
pub data: Rc<DeviceHandlerData>,
}
pub struct DeviceHandlerData {
pub seat: CloneCell<Option<Rc<WlSeatGlobal>>>,
pub device: Rc<dyn InputDevice>,
}
pub struct ConnectorData {
pub connector: Rc<dyn Connector>,
pub handler: Cell<Option<SpawnedFuture<()>>>,
pub connected: Cell<bool>,
pub name: String,
}
pub struct OutputData {
pub connector: Rc<ConnectorData>,
pub monitor_info: MonitorInfo,
pub node: Rc<OutputNode>,
}
impl State {
pub fn set_render_ctx(&self, ctx: &Rc<RenderContext>) {
let cursors = match ServerCursors::load(ctx) {
Ok(c) => Some(Rc::new(c)),
Err(e) => {
log::error!("Could not load the cursors: {}", ErrorFmt(e));
None
}
};
self.cursors.set(cursors);
self.render_ctx.set(Some(ctx.clone()));
struct Walker;
impl NodeVisitorBase for Walker {
fn visit_container(&mut self, node: &Rc<ContainerNode>) {
node.schedule_compute_render_data();
node.node_visit_children(self);
}
fn visit_output(&mut self, node: &Rc<OutputNode>) {
node.update_render_data();
node.node_visit_children(self);
}
fn visit_float(&mut self, node: &Rc<FloatNode>) {
node.schedule_render_titles();
node.node_visit_children(self);
}
}
self.root.visit(&mut Walker);
let seats = self.globals.seats.lock();
for seat in seats.values() {
seat.render_ctx_changed();
}
}
pub fn add_global<T: WaylandGlobal>(&self, global: &Rc<T>) {
self.globals.add_global(self, global)
}
pub fn remove_global<T: WaylandGlobal>(&self, global: &T) -> Result<(), GlobalsError> {
self.globals.remove(self, global)
}
pub fn tree_changed(&self) {
if self.tree_changed_sent.replace(true) {
return;
}
let seats = self.globals.seats.lock();
for seat in seats.values() {
seat.trigger_tree_changed();
}
}
pub fn map_tiled(self: &Rc<Self>, node: Rc<dyn Node>) {
let seat = self.seat_queue.last();
if let Some(seat) = &seat {
if let Some(prev) = seat.last_tiled_keyboard_toplevel(&*node) {
if let Some(container) = prev.parent() {
if let Some(container) = container.node_into_container() {
container.add_child_after(prev.as_node(), node);
return;
}
}
}
}
let mut output = seat.map(|s| s.get_output());
if output.is_none() {
let outputs = self.root.outputs.lock();
output = outputs.values().next().cloned();
}
let output = match output {
Some(output) => output,
_ => self.dummy_output.get().unwrap(),
};
let workspace = output.ensure_workspace();
if let Some(container) = workspace.container.get() {
container.append_child(node);
} else {
let container = ContainerNode::new(
self,
&workspace,
workspace.clone(),
node,
ContainerSplit::Horizontal,
);
workspace.set_container(&container);
};
}
pub fn map_floating(
self: &Rc<Self>,
node: Rc<dyn Node>,
mut width: i32,
mut height: i32,
workspace: &Rc<WorkspaceNode>,
) {
node.clone().node_set_workspace(workspace);
width += 2 * self.theme.border_width.get();
height += 2 * self.theme.border_width.get() + self.theme.title_height.get();
let output = workspace.output.get();
let output_rect = output.global.pos.get();
let position = {
let mut x1 = output_rect.x1();
let mut y1 = output_rect.y1();
if width < output_rect.width() {
x1 += (output_rect.width() - width) as i32 / 2;
} else {
width = output_rect.width();
}
if height < output_rect.height() {
y1 += (output_rect.height() - height) as i32 / 2;
} else {
height = output_rect.height();
}
Rect::new_sized(x1, y1, width, height).unwrap()
};
FloatNode::new(self, workspace, position, node);
}
pub fn show_workspace(&self, seat: &Rc<WlSeatGlobal>, name: &str) {
let output = match self.workspaces.get(name) {
Some(ws) => {
let output = ws.output.get();
let did_change = output.show_workspace(&ws);
ws.last_active_child()
.node_do_focus(seat, Direction::Unspecified);
if !did_change {
return;
}
output
}
_ => {
let output = seat.get_output();
if output.is_dummy {
log::warn!("Not showing workspace because seat is on dummy output");
return;
}
let workspace = Rc::new(WorkspaceNode {
id: self.node_ids.next(),
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),
});
workspace
.output_link
.set(Some(output.workspaces.add_last(workspace.clone())));
output.show_workspace(&workspace);
self.workspaces.set(name.to_string(), workspace);
output
}
};
output.update_render_data();
self.tree_changed();
// let seats = self.globals.seats.lock();
// for seat in seats.values() {
// seat.workspace_changed(&output);
// }
}
pub fn float_map_ws(&self) -> Rc<WorkspaceNode> {
if let Some(seat) = self.seat_queue.last() {
let output = seat.get_output();
if !output.is_dummy {
return output.ensure_workspace();
}
}
if let Some(output) = self.root.outputs.lock().values().cloned().next() {
return output.ensure_workspace();
}
self.dummy_output.get().unwrap().ensure_workspace()
}
pub fn set_status(&self, status: &str) {
let status = Rc::new(status.to_owned());
self.status.set(status.clone());
let outputs = self.root.outputs.lock();
for output in outputs.values() {
output.set_status(&status);
}
}
}