autocommit 2022-04-02 00:31:30 CEST
This commit is contained in:
parent
2dd433aa04
commit
6ad6d83b7e
34 changed files with 446 additions and 161 deletions
|
|
@ -3,9 +3,7 @@ mod monitor;
|
|||
mod video;
|
||||
|
||||
use crate::async_engine::{AsyncError, AsyncFd};
|
||||
use crate::backend::{
|
||||
Backend, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, InputEvent,
|
||||
};
|
||||
use crate::backend::{Backend, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, InputEvent, KeyState};
|
||||
use crate::backends::metal::video::{MetalDrmDevice, PendingDrmDevice};
|
||||
use crate::dbus::DbusError;
|
||||
use crate::drm::drm::DrmError;
|
||||
|
|
@ -30,9 +28,11 @@ use crate::utils::syncqueue::SyncQueue;
|
|||
use std::cell::{Cell, RefCell};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::future::pending;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use uapi::{c, OwnedFd};
|
||||
use crate::utils::smallmap::SmallMap;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum MetalError {
|
||||
|
|
@ -198,6 +198,10 @@ struct MetalInputDevice {
|
|||
vscroll: Cell<f64>,
|
||||
name: CloneCell<Rc<String>>,
|
||||
|
||||
// state
|
||||
pressed_keys: SmallMap<u32, (), 5>,
|
||||
pressed_buttons: SmallMap<u32, (), 2>,
|
||||
|
||||
// config
|
||||
left_handed: Cell<Option<bool>>,
|
||||
accel_profile: Cell<Option<AccelProfile>>,
|
||||
|
|
@ -205,6 +209,14 @@ struct MetalInputDevice {
|
|||
transform_matrix: Cell<Option<[[f64; 2]; 2]>>,
|
||||
}
|
||||
|
||||
impl Drop for MetalInputDevice {
|
||||
fn drop(&mut self) {
|
||||
if let Some(fd) = self.fd.take() {
|
||||
mem::forget(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum MetalDevice {
|
||||
Input(Rc<MetalInputDevice>),
|
||||
|
|
@ -250,6 +262,15 @@ impl MetalInputDevice {
|
|||
dev.device().set_accel_speed(speed);
|
||||
}
|
||||
}
|
||||
|
||||
fn pre_pause(&self) {
|
||||
for (key, _) in self.pressed_keys.take() {
|
||||
self.event(InputEvent::Key(key, KeyState::Released));
|
||||
}
|
||||
for (button, _) in self.pressed_buttons.take() {
|
||||
self.event(InputEvent::Button(button, KeyState::Released));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InputDevice for MetalInputDevice {
|
||||
|
|
|
|||
|
|
@ -93,8 +93,14 @@ impl MetalBackend {
|
|||
fn handle_keyboard_key(self: &Rc<Self>, event: LibInputEvent) {
|
||||
let (event, dev) = unpack!(self, event, keyboard_event);
|
||||
let state = if event.key_state() == LIBINPUT_KEY_STATE_PRESSED {
|
||||
if dev.pressed_keys.insert(event.key(), ()).is_some() {
|
||||
return;
|
||||
}
|
||||
KeyState::Pressed
|
||||
} else {
|
||||
if dev.pressed_keys.remove(&event.key()).is_none() {
|
||||
return;
|
||||
}
|
||||
KeyState::Released
|
||||
};
|
||||
dev.event(InputEvent::Key(event.key(), state));
|
||||
|
|
@ -132,8 +138,14 @@ impl MetalBackend {
|
|||
fn handle_pointer_button(self: &Rc<Self>, event: LibInputEvent) {
|
||||
let (event, dev) = unpack!(self, event, pointer_event);
|
||||
let state = if event.button_state() == LIBINPUT_BUTTON_STATE_PRESSED {
|
||||
if dev.pressed_buttons.insert(event.button(), ()).is_some() {
|
||||
return;
|
||||
}
|
||||
KeyState::Pressed
|
||||
} else {
|
||||
if dev.pressed_buttons.remove(&event.button()).is_none() {
|
||||
return;
|
||||
}
|
||||
KeyState::Released
|
||||
};
|
||||
dev.event(InputEvent::Button(event.button(), state));
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ impl MetalBackend {
|
|||
}
|
||||
|
||||
fn handle_input_device_removed(self: &Rc<Self>, dev: &Rc<MetalInputDevice>) {
|
||||
dev.pre_pause();
|
||||
log::info!("Device removed: {}", dev.devnode.to_bytes().as_bstr());
|
||||
self.device_holder.input_devices.borrow_mut()[dev.slot] = None;
|
||||
dev.fd.set(None);
|
||||
|
|
@ -148,6 +149,7 @@ impl MetalBackend {
|
|||
|
||||
fn handle_input_device_paused(self: &Rc<Self>, dev: &Rc<MetalInputDevice>) {
|
||||
log::info!("Device paused: {}", dev.devnode.to_bytes().as_bstr());
|
||||
dev.pre_pause();
|
||||
if let Some(rd) = dev.inputdev.take() {
|
||||
rd.device().unset_slot();
|
||||
}
|
||||
|
|
@ -282,6 +284,8 @@ impl MetalBackend {
|
|||
hscroll: Cell::new(0.0),
|
||||
vscroll: Cell::new(0.0),
|
||||
name: Default::default(),
|
||||
pressed_keys: Default::default(),
|
||||
pressed_buttons: Default::default(),
|
||||
left_handed: Default::default(),
|
||||
accel_profile: Default::default(),
|
||||
accel_speed: Default::default(),
|
||||
|
|
|
|||
11
src/cli.rs
11
src/cli.rs
|
|
@ -1,6 +1,7 @@
|
|||
mod generate;
|
||||
mod log;
|
||||
mod quit;
|
||||
mod set_log_level;
|
||||
|
||||
use crate::compositor::start_compositor;
|
||||
use ::log::Level;
|
||||
|
|
@ -31,6 +32,8 @@ pub enum Cmd {
|
|||
GenerateCompletion(GenerateArgs),
|
||||
/// Open the log file.
|
||||
Log(LogArgs),
|
||||
/// Sets the log level.
|
||||
SetLogLevel(SetLogArgs),
|
||||
/// Stop the compositor.
|
||||
Quit,
|
||||
}
|
||||
|
|
@ -61,6 +64,13 @@ pub struct LogArgs {
|
|||
pager_end: bool,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct SetLogArgs {
|
||||
/// The new log level.
|
||||
#[clap(arg_enum)]
|
||||
level: CliLogLevel,
|
||||
}
|
||||
|
||||
#[derive(ArgEnum, Debug, Copy, Clone, Hash)]
|
||||
pub enum CliBackend {
|
||||
X11,
|
||||
|
|
@ -108,5 +118,6 @@ pub fn main() {
|
|||
Cmd::GenerateCompletion(g) => generate::main(g),
|
||||
Cmd::Log(a) => log::main(cli.global, a),
|
||||
Cmd::Quit => quit::main(cli.global),
|
||||
Cmd::SetLogLevel(a) => set_log_level::main(cli.global, a),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
28
src/cli/set_log_level.rs
Normal file
28
src/cli/set_log_level.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
use std::rc::Rc;
|
||||
use crate::cli::{GlobalArgs, SetLogArgs};
|
||||
use crate::tools::tool_client::ToolClient;
|
||||
use crate::wire::jay_compositor::SetLogLevel;
|
||||
|
||||
pub fn main(global: GlobalArgs, args: SetLogArgs) {
|
||||
let tc = ToolClient::new(global.log_level.into());
|
||||
let logger = Rc::new(Log {
|
||||
tc: tc.clone(),
|
||||
args,
|
||||
});
|
||||
tc.run(run(logger));
|
||||
}
|
||||
|
||||
struct Log {
|
||||
tc: Rc<ToolClient>,
|
||||
args: SetLogArgs,
|
||||
}
|
||||
|
||||
async fn run(log: Rc<Log>) {
|
||||
let tc = &log.tc;
|
||||
let comp = tc.jay_compositor().await;
|
||||
tc.send(SetLogLevel {
|
||||
self_id: comp,
|
||||
level: log.args.level as u32,
|
||||
});
|
||||
tc.round_trip().await;
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::acceptor::{Acceptor, AcceptorError};
|
||||
use crate::async_engine::{AsyncEngine, AsyncError, Phase};
|
||||
use crate::backends::dummy::DummyOutput;
|
||||
use crate::cli::{GlobalArgs, RunArgs};
|
||||
use crate::client::Clients;
|
||||
use crate::clientmem::ClientMemError;
|
||||
|
|
@ -8,12 +9,17 @@ use crate::dbus::Dbus;
|
|||
use crate::event_loop::{EventLoop, EventLoopError};
|
||||
use crate::forker::ForkerError;
|
||||
use crate::globals::Globals;
|
||||
use crate::ifs::wl_output::WlOutputGlobal;
|
||||
use crate::ifs::wl_surface::NoneSurfaceExt;
|
||||
use crate::logger::Logger;
|
||||
use crate::render::RenderError;
|
||||
use crate::sighand::SighandError;
|
||||
use crate::state::State;
|
||||
use crate::tree::{container_layout, container_render_data, float_layout, float_titles, DisplayNode, NodeIds, OutputNode, WorkspaceNode};
|
||||
use crate::tree::{
|
||||
container_layout, container_render_data, float_layout, float_titles, DisplayNode, NodeIds,
|
||||
OutputNode, WorkspaceNode,
|
||||
};
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
use crate::utils::errorfmt::ErrorFmt;
|
||||
use crate::utils::fdcloser::FdCloser;
|
||||
use crate::utils::numcell::NumCell;
|
||||
|
|
@ -23,14 +29,11 @@ use crate::wheel::{Wheel, WheelError};
|
|||
use crate::xkbcommon::XkbContext;
|
||||
use crate::{clientmem, forker, leaks, render, sighand, tasks, xwayland};
|
||||
use forker::ForkerProxy;
|
||||
use std::cell::{Cell};
|
||||
use std::cell::Cell;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
use crate::backends::dummy::DummyOutput;
|
||||
use crate::ifs::wl_output::WlOutputGlobal;
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
|
||||
pub fn start_compositor(global: GlobalArgs, args: RunArgs) {
|
||||
let logger = Logger::install_compositor(global.log_level.into());
|
||||
|
|
@ -118,9 +121,12 @@ fn main_(logger: Arc<Logger>, _args: &RunArgs) -> Result<(), MainError> {
|
|||
let dummy_output = Rc::new(OutputNode {
|
||||
id: state.node_ids.next(),
|
||||
position: Default::default(),
|
||||
global: Rc::new(WlOutputGlobal::new(state.globals.name(), Rc::new(DummyOutput {
|
||||
id: state.output_ids.next(),
|
||||
}))),
|
||||
global: Rc::new(WlOutputGlobal::new(
|
||||
state.globals.name(),
|
||||
Rc::new(DummyOutput {
|
||||
id: state.output_ids.next(),
|
||||
}),
|
||||
)),
|
||||
workspaces: Default::default(),
|
||||
workspace: Default::default(),
|
||||
seat_state: Default::default(),
|
||||
|
|
@ -132,13 +138,17 @@ fn main_(logger: Arc<Logger>, _args: &RunArgs) -> Result<(), MainError> {
|
|||
let dummy_workspace = Rc::new(WorkspaceNode {
|
||||
id: state.node_ids.next(),
|
||||
output: CloneCell::new(dummy_output.clone()),
|
||||
position: Default::default(),
|
||||
container: Default::default(),
|
||||
stacked: Default::default(),
|
||||
seat_state: Default::default(),
|
||||
name: "dummy".to_string()
|
||||
name: "dummy".to_string(),
|
||||
output_link: Default::default(),
|
||||
});
|
||||
dummy_output.workspace.set(Some(dummy_workspace.clone()));
|
||||
dummy_output.workspaces.borrow_mut().push(dummy_workspace);
|
||||
dummy_workspace.output_link.set(Some(
|
||||
dummy_output.workspaces.add_last(dummy_workspace.clone()),
|
||||
));
|
||||
dummy_output.show_workspace(&dummy_workspace);
|
||||
state.dummy_output.set(Some(dummy_output));
|
||||
}
|
||||
forker.install(&state);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use crate::backend::{InputDeviceAccelProfile, InputDeviceCapability, InputDevice
|
|||
use crate::ifs::wl_seat::{SeatId, WlSeatGlobal};
|
||||
use crate::state::{DeviceHandlerData, State};
|
||||
use crate::tree::walker::NodeVisitorBase;
|
||||
use crate::tree::{ContainerNode, ContainerSplit, FloatNode, Node, WorkspaceNode};
|
||||
use crate::tree::{ContainerNode, ContainerSplit, FloatNode, Node};
|
||||
use crate::utils::copyhashmap::CopyHashMap;
|
||||
use crate::utils::debug_fn::debug_fn;
|
||||
use crate::utils::errorfmt::ErrorFmt;
|
||||
|
|
@ -13,9 +13,13 @@ use crate::xkbcommon::XkbKeymap;
|
|||
use bincode::error::DecodeError;
|
||||
use jay_config::_private::bincode_ops;
|
||||
use jay_config::_private::ipc::{ClientMessage, Response, ServerMessage};
|
||||
use jay_config::input::acceleration::{AccelProfile, ACCEL_PROFILE_ADAPTIVE, ACCEL_PROFILE_FLAT};
|
||||
use jay_config::input::capability::{
|
||||
Capability, CAP_GESTURE, CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD,
|
||||
CAP_TABLET_TOOL, CAP_TOUCH,
|
||||
};
|
||||
use jay_config::input::{
|
||||
AccelProfile, Capability, InputDevice, ACCEL_PROFILE_ADAPTIVE, ACCEL_PROFILE_FLAT, CAP_GESTURE,
|
||||
CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD, CAP_TABLET_TOOL, CAP_TOUCH,
|
||||
InputDevice,
|
||||
};
|
||||
use jay_config::keyboard::keymap::Keymap;
|
||||
use jay_config::keyboard::mods::Modifiers;
|
||||
|
|
@ -26,7 +30,6 @@ use log::Level;
|
|||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
|
||||
pub(super) struct ConfigProxyHandler {
|
||||
pub client_data: Cell<*const u8>,
|
||||
|
|
@ -163,7 +166,7 @@ impl ConfigProxyHandler {
|
|||
fn get_workspace(&self, ws: Workspace) -> Result<Rc<String>, CphError> {
|
||||
match self.workspaces_by_id.get(&ws.0) {
|
||||
Some(ws) => Ok(ws),
|
||||
_ => Err(CphError::WorkspaceDoesNotExist(ws))
|
||||
_ => Err(CphError::WorkspaceDoesNotExist(ws)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -283,33 +286,7 @@ impl ConfigProxyHandler {
|
|||
fn handle_show_workspace(&self, seat: Seat, ws: Workspace) -> Result<(), ShowWorkspaceError> {
|
||||
let seat = self.get_seat(seat)?;
|
||||
let name = self.get_workspace(ws)?;
|
||||
let output = match self.state.workspaces.get(name.as_str()) {
|
||||
Some(ws) => {
|
||||
let output = ws.output.get();
|
||||
output.workspace.set(Some(ws.clone()));
|
||||
output
|
||||
}
|
||||
None => {
|
||||
let output = seat.get_output();
|
||||
if output.is_dummy {
|
||||
return Ok(());
|
||||
}
|
||||
let ws = Rc::new(WorkspaceNode {
|
||||
id: self.state.node_ids.next(),
|
||||
output: CloneCell::new(output.clone()),
|
||||
container: Default::default(),
|
||||
stacked: Default::default(),
|
||||
seat_state: Default::default(),
|
||||
name: name.to_string(),
|
||||
});
|
||||
output.workspaces.borrow_mut().push(ws.clone());
|
||||
output.workspace.set(Some(ws.clone()));
|
||||
self.state.workspaces.set(name.to_string(), ws);
|
||||
output
|
||||
}
|
||||
};
|
||||
output.update_render_data();
|
||||
self.state.tree_changed();
|
||||
self.state.show_workspace(&seat, &name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -653,7 +630,9 @@ impl ConfigProxyHandler {
|
|||
}
|
||||
ClientMessage::GetDeviceName { device } => self.handle_get_device_name(device)?,
|
||||
ClientMessage::GetWorkspace { name } => self.handle_get_workspace(name),
|
||||
ClientMessage::ShowWorkspace { seat, workspace } => self.handle_show_workspace(seat, workspace)?,
|
||||
ClientMessage::ShowWorkspace { seat, workspace } => {
|
||||
self.handle_show_workspace(seat, workspace)?
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ use crate::utils::buffd::{MsgParser, MsgParserError};
|
|||
use crate::wire::jay_compositor::*;
|
||||
use crate::wire::JayCompositorId;
|
||||
use std::rc::Rc;
|
||||
use log::Level;
|
||||
use thiserror::Error;
|
||||
use crate::cli::CliLogLevel;
|
||||
|
||||
pub struct JayCompositorGlobal {
|
||||
name: GlobalName,
|
||||
|
|
@ -81,6 +83,25 @@ impl JayCompositor {
|
|||
self.client.state.el.stop();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_log_level(&self, parser: MsgParser<'_, '_>) -> Result<(), SetLogLevelError> {
|
||||
let req: SetLogLevel = self.client.parse(self, parser)?;
|
||||
const ERROR: u32 = CliLogLevel::Error as u32;
|
||||
const WARN: u32 = CliLogLevel::Warn as u32;
|
||||
const INFO: u32 = CliLogLevel::Info as u32;
|
||||
const DEBUG: u32 = CliLogLevel::Debug as u32;
|
||||
const TRACE: u32 = CliLogLevel::Trace as u32;
|
||||
let level = match req.level {
|
||||
ERROR => Level::Error,
|
||||
WARN => Level::Warn,
|
||||
INFO => Level::Info,
|
||||
DEBUG => Level::Debug,
|
||||
TRACE => Level::Trace,
|
||||
_ => return Err(SetLogLevelError::UnknownLogLevel(req.level)),
|
||||
};
|
||||
self.client.state.logger.set_level(level);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
|
|
@ -89,11 +110,12 @@ object_base! {
|
|||
DESTROY => destroy,
|
||||
GET_LOG_FILE => get_log_file,
|
||||
QUIT => quit,
|
||||
SET_LOG_LEVEL => set_log_level,
|
||||
}
|
||||
|
||||
impl Object for JayCompositor {
|
||||
fn num_requests(&self) -> u32 {
|
||||
QUIT + 1
|
||||
SET_LOG_LEVEL + 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -107,6 +129,8 @@ pub enum JayCompositorError {
|
|||
GetLogFileError(#[from] GetLogFileError),
|
||||
#[error("Could not process a `quit` request")]
|
||||
QuitError(#[from] QuitError),
|
||||
#[error("Could not process a `set_log_level` request")]
|
||||
SetLogLevelError(#[from] SetLogLevelError),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
|
|
@ -138,3 +162,12 @@ pub enum QuitError {
|
|||
MsgParserError(#[source] Box<MsgParserError>),
|
||||
}
|
||||
efrom!(QuitError, MsgParserError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetLogLevelError {
|
||||
#[error("Parsing failed")]
|
||||
MsgParserError(#[source] Box<MsgParserError>),
|
||||
#[error("Unknown log level {0}")]
|
||||
UnknownLogLevel(u32),
|
||||
}
|
||||
efrom!(SetLogLevelError, MsgParserError);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ use jay_config::Direction;
|
|||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::mem;
|
||||
use std::ops::{DerefMut};
|
||||
use std::ops::DerefMut;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use uapi::{c, Errno, OwnedFd};
|
||||
|
|
@ -373,6 +373,10 @@ impl WlSeatGlobal {
|
|||
self.id
|
||||
}
|
||||
|
||||
pub fn workspace_changed(self: &Rc<Self>, output: &Rc<OutputNode>) {
|
||||
self.kb_owner.workspace_changed(self, output);
|
||||
}
|
||||
|
||||
fn bind_(
|
||||
self: Rc<Self>,
|
||||
id: WlSeatId,
|
||||
|
|
|
|||
|
|
@ -192,8 +192,14 @@ impl WlSeatGlobal {
|
|||
}
|
||||
|
||||
pub fn last_tiled_keyboard_toplevel(&self, new: &dyn Node) -> Option<Rc<dyn ToplevelNode>> {
|
||||
let output = self.output.get();
|
||||
let workspace = output.workspace.get().unwrap();
|
||||
let is_container = new.is_container();
|
||||
for tl in self.toplevel_focus_history.rev_iter() {
|
||||
match tl.as_node().get_workspace() {
|
||||
Some(ws) if ws.id == workspace.id => { },
|
||||
_ => continue,
|
||||
};
|
||||
let parent_is_float = match tl.parent() {
|
||||
Some(pn) => pn.is_float(),
|
||||
_ => false,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::ops::Deref;
|
||||
use crate::ifs::wl_seat::WlSeatGlobal;
|
||||
use crate::tree::Node;
|
||||
use crate::tree::{Node, OutputNode};
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
|
@ -29,6 +30,10 @@ impl KbOwnerHolder {
|
|||
pub fn set_kb_node(&self, seat: &Rc<WlSeatGlobal>, node: Rc<dyn Node>) {
|
||||
self.owner.get().set_kb_node(seat, node);
|
||||
}
|
||||
|
||||
pub fn workspace_changed(&self, seat: &Rc<WlSeatGlobal>, output: &Rc<OutputNode>) {
|
||||
self.owner.get().workspace_changed(seat, output);
|
||||
}
|
||||
}
|
||||
|
||||
struct DefaultKbOwner;
|
||||
|
|
@ -39,6 +44,7 @@ trait KbOwner {
|
|||
fn grab(&self, seat: &Rc<WlSeatGlobal>, node: Rc<dyn Node>) -> bool;
|
||||
fn ungrab(&self, seat: &Rc<WlSeatGlobal>);
|
||||
fn set_kb_node(&self, seat: &Rc<WlSeatGlobal>, node: Rc<dyn Node>);
|
||||
fn workspace_changed(&self, seat: &Rc<WlSeatGlobal>, output: &Rc<OutputNode>);
|
||||
}
|
||||
|
||||
impl KbOwner for DefaultKbOwner {
|
||||
|
|
@ -68,6 +74,31 @@ impl KbOwner for DefaultKbOwner {
|
|||
node.clone().focus(seat);
|
||||
seat.keyboard_node.set(node.clone());
|
||||
}
|
||||
|
||||
fn workspace_changed(&self, seat: &Rc<WlSeatGlobal>, output: &Rc<OutputNode>) {
|
||||
let new_ws = match output.workspace.get() {
|
||||
Some(ws) => ws,
|
||||
_ => return,
|
||||
};
|
||||
let node = seat.keyboard_node.get();
|
||||
let ws = match node.get_workspace() {
|
||||
None => return,
|
||||
Some(ws) => ws,
|
||||
};
|
||||
let ws_output = ws.output.get();
|
||||
if ws_output.id != output.id {
|
||||
return;
|
||||
}
|
||||
for tl in seat.toplevel_focus_history.rev_iter() {
|
||||
if let Some(tl_ws) = tl.as_node().get_workspace() {
|
||||
if tl_ws.id == new_ws.id {
|
||||
self.set_kb_node(seat, tl.deref().clone().into_node());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.set_kb_node(seat, seat.state.root.clone());
|
||||
}
|
||||
}
|
||||
|
||||
impl KbOwner for GrabKbOwner {
|
||||
|
|
@ -82,4 +113,8 @@ impl KbOwner for GrabKbOwner {
|
|||
fn set_kb_node(&self, _seat: &Rc<WlSeatGlobal>, _node: Rc<dyn Node>) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
fn workspace_changed(&self, _seat: &Rc<WlSeatGlobal>, _output: &Rc<OutputNode>) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use crate::rect::Rect;
|
|||
use crate::render::Renderer;
|
||||
use crate::tree::toplevel::ToplevelNode;
|
||||
use crate::tree::walker::NodeVisitor;
|
||||
use crate::tree::{ContainerNode, ContainerSplit, Node, NodeId};
|
||||
use crate::tree::{ContainerNode, ContainerSplit, Node, NodeId, WorkspaceNode};
|
||||
use crate::utils::buffd::{MsgParser, MsgParserError};
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
use crate::utils::linkedlist::LinkedList;
|
||||
|
|
@ -643,6 +643,13 @@ impl Node for WlSurface {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_workspace(&self) -> Option<Rc<WorkspaceNode>> {
|
||||
if let Some(tl) = self.toplevel.get() {
|
||||
return tl.as_node().get_workspace();
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn get_parent_mono(&self) -> Option<bool> {
|
||||
self.toplevel
|
||||
.get()
|
||||
|
|
@ -679,7 +686,7 @@ impl Node for WlSurface {
|
|||
Some(tl) => tl,
|
||||
_ => return,
|
||||
};
|
||||
let ws = match tl.workspace() {
|
||||
let ws = match tl.as_node().get_workspace() {
|
||||
Some(ws) => ws,
|
||||
_ => return,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -289,6 +289,10 @@ impl SurfaceExt for WlSubsurface {
|
|||
fn into_subsurface(self: Rc<Self>) -> Option<Rc<WlSubsurface>> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
fn accepts_kb_focus(&self) -> bool {
|
||||
self.parent.accepts_kb_focus()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
|
|
|||
|
|
@ -356,6 +356,10 @@ impl SurfaceExt for XdgSurface {
|
|||
fn extents_changed(&self) {
|
||||
self.update_extents();
|
||||
}
|
||||
|
||||
fn accepts_kb_focus(&self) -> bool {
|
||||
self.role.get() == XdgSurfaceRole::XdgToplevel
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::cursor::KnownCursor;
|
||||
use crate::fixed::Fixed;
|
||||
use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal};
|
||||
use crate::ifs::wl_seat::{ NodeSeatState, WlSeatGlobal};
|
||||
use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceExt};
|
||||
use crate::ifs::xdg_positioner::{XdgPositioned, XdgPositioner, CA};
|
||||
use crate::leaks::Tracker;
|
||||
|
|
@ -281,6 +281,10 @@ impl Node for XdgPopup {
|
|||
visitor.visit_surface(&self.xdg.surface);
|
||||
}
|
||||
|
||||
fn get_workspace(&self) -> Option<Rc<WorkspaceNode>> {
|
||||
self.xdg.workspace.get()
|
||||
}
|
||||
|
||||
fn absolute_position(&self) -> Rect {
|
||||
self.xdg.absolute_desired_extents.get()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use crate::rect::Rect;
|
|||
use crate::render::Renderer;
|
||||
use crate::tree::toplevel::{ToplevelData, ToplevelNode};
|
||||
use crate::tree::walker::NodeVisitor;
|
||||
use crate::tree::FindTreeResult;
|
||||
use crate::tree::{FindTreeResult};
|
||||
use crate::tree::{FoundNode, Node, NodeId, ToplevelNodeId, WorkspaceNode};
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
|
|
@ -374,6 +374,10 @@ impl Node for XdgToplevel {
|
|||
visitor.visit_surface(&self.xdg.surface);
|
||||
}
|
||||
|
||||
fn get_workspace(&self) -> Option<Rc<WorkspaceNode>> {
|
||||
self.xdg.workspace.get()
|
||||
}
|
||||
|
||||
fn is_contained_in(&self, other: NodeId) -> bool {
|
||||
if let Some(parent) = self.parent_node.get() {
|
||||
if parent.id() == other {
|
||||
|
|
@ -443,10 +447,6 @@ impl ToplevelNode for XdgToplevel {
|
|||
self.parent_node.get()
|
||||
}
|
||||
|
||||
fn workspace(&self) -> Option<Rc<WorkspaceNode>> {
|
||||
self.xdg.workspace.get()
|
||||
}
|
||||
|
||||
fn as_node(&self) -> &dyn Node {
|
||||
self
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::client::Client;
|
||||
use crate::client::{Client};
|
||||
use crate::cursor::KnownCursor;
|
||||
use crate::fixed::Fixed;
|
||||
use crate::ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal};
|
||||
|
|
@ -353,6 +353,10 @@ impl Node for Xwindow {
|
|||
visitor.visit_surface(&self.surface);
|
||||
}
|
||||
|
||||
fn get_workspace(&self) -> Option<Rc<WorkspaceNode>> {
|
||||
self.workspace.get()
|
||||
}
|
||||
|
||||
fn is_contained_in(&self, other: NodeId) -> bool {
|
||||
if let Some(parent) = self.parent_node.get() {
|
||||
if parent.id() == other {
|
||||
|
|
@ -429,10 +433,6 @@ impl ToplevelNode for Xwindow {
|
|||
self.parent_node.get()
|
||||
}
|
||||
|
||||
fn workspace(&self) -> Option<Rc<WorkspaceNode>> {
|
||||
self.workspace.get()
|
||||
}
|
||||
|
||||
fn as_node(&self) -> &dyn Node {
|
||||
self
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::ifs::wl_seat::NodeSeatState;
|
||||
use crate::ifs::wl_seat::{NodeSeatState};
|
||||
use crate::ifs::wl_surface::{
|
||||
CommitAction, CommitContext, SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError,
|
||||
};
|
||||
|
|
@ -359,10 +359,6 @@ impl Node for ZwlrLayerSurfaceV1 {
|
|||
self.surface.clone().visit(visitor);
|
||||
}
|
||||
|
||||
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
|
||||
renderer.render_layer_surface(self, x, y);
|
||||
}
|
||||
|
||||
fn absolute_position(&self) -> Rect {
|
||||
self.pos.get()
|
||||
}
|
||||
|
|
@ -376,6 +372,10 @@ impl Node for ZwlrLayerSurfaceV1 {
|
|||
self.surface.find_tree_at(x, y, tree)
|
||||
}
|
||||
|
||||
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
|
||||
renderer.render_layer_surface(self, x, y);
|
||||
}
|
||||
|
||||
fn change_extents(self: Rc<Self>, _rect: &Rect) {
|
||||
self.compute_position();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,10 @@ xkb_keymap {
|
|||
<83> = 91; # KPDOT
|
||||
<87> = 95; # F11
|
||||
<88> = 96; # F12
|
||||
<89> = 97; # RO
|
||||
<92> = 100; # HENKAN
|
||||
<93> = 101; # KATAKANAHIRAGANA
|
||||
<94> = 102; # MUHENKAN
|
||||
<96> = 104; # KPENTER
|
||||
<97> = 105; # RIGHTCTRL
|
||||
<98> = 106; # KPSLASH
|
||||
|
|
@ -103,6 +107,7 @@ xkb_keymap {
|
|||
<111> = 119; # DELETE
|
||||
<117> = 125; # KPEQUAL
|
||||
<119> = 127; # PAUSE
|
||||
<124> = 132; # YEN
|
||||
<125> = 133; # LEFTMETA
|
||||
<126> = 134; # RIGHTMETA
|
||||
<139> = 147; # MENU
|
||||
|
|
@ -311,6 +316,12 @@ xkb_keymap {
|
|||
key <9> { [ 8, asterisk ] };
|
||||
key <10> { [ 9, parenleft ] };
|
||||
key <11> { [ 0, parenright ] };
|
||||
|
||||
key <89> { [ dollar , asciitilde ] };
|
||||
key <93> { [ ampersand , percent ] };
|
||||
key <94> { [ equal , asterisk ] };
|
||||
key <124> { [ at , asciicircum ] };
|
||||
key <92> { [ numbersign , grave ] };
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
|||
89
src/state.rs
89
src/state.rs
|
|
@ -136,7 +136,7 @@ impl State {
|
|||
|
||||
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(seat) = &seat {
|
||||
if let Some(prev) = seat.last_tiled_keyboard_toplevel(&*node) {
|
||||
if let Some(container) = prev.parent() {
|
||||
if let Some(container) = container.into_container() {
|
||||
|
|
@ -146,28 +146,31 @@ impl State {
|
|||
}
|
||||
}
|
||||
}
|
||||
let output = {
|
||||
let mut output = seat.map(|s| s.get_output());
|
||||
if output.is_none() {
|
||||
let outputs = self.root.outputs.lock();
|
||||
outputs.values().next().cloned()
|
||||
};
|
||||
if let Some(output) = output {
|
||||
if let Some(workspace) = output.workspace.get() {
|
||||
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);
|
||||
};
|
||||
return;
|
||||
}
|
||||
output = outputs.values().next().cloned();
|
||||
}
|
||||
todo!("map_tiled");
|
||||
let output = match output {
|
||||
Some(output) => output,
|
||||
_ => self.dummy_output.get().unwrap(),
|
||||
};
|
||||
if let Some(workspace) = output.workspace.get() {
|
||||
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);
|
||||
};
|
||||
return;
|
||||
}
|
||||
log::warn!("Output has no workspace set");
|
||||
}
|
||||
|
||||
pub fn map_floating(
|
||||
|
|
@ -199,4 +202,48 @@ impl State {
|
|||
};
|
||||
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();
|
||||
if let Some(old) = output.workspace.get() {
|
||||
if old.id == ws.id {
|
||||
return;
|
||||
}
|
||||
}
|
||||
output.show_workspace(&ws);
|
||||
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),
|
||||
});
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ impl OutputHandler {
|
|||
let global = Rc::new(WlOutputGlobal::new(name, self.output.clone()));
|
||||
let on = Rc::new(OutputNode {
|
||||
id: self.state.node_ids.next(),
|
||||
workspaces: RefCell::new(vec![]),
|
||||
workspaces: Default::default(),
|
||||
position: Cell::new(Default::default()),
|
||||
workspace: CloneCell::new(None),
|
||||
seat_state: Default::default(),
|
||||
|
|
@ -51,14 +51,18 @@ impl OutputHandler {
|
|||
let workspace = Rc::new(WorkspaceNode {
|
||||
id: self.state.node_ids.next(),
|
||||
output: CloneCell::new(on.clone()),
|
||||
position: Cell::new(Default::default()),
|
||||
container: Default::default(),
|
||||
stacked: Default::default(),
|
||||
seat_state: Default::default(),
|
||||
name: name.clone(),
|
||||
output_link: Default::default(),
|
||||
});
|
||||
self.state.workspaces.set(name, workspace.clone());
|
||||
on.workspaces.borrow_mut().push(workspace.clone());
|
||||
on.workspace.set(Some(workspace));
|
||||
workspace
|
||||
.output_link
|
||||
.set(Some(on.workspaces.add_last(workspace.clone())));
|
||||
on.show_workspace(&workspace);
|
||||
on.update_render_data();
|
||||
self.state.root.outputs.set(self.output.id(), on.clone());
|
||||
self.state.add_global(&global);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,10 @@ pub trait Node {
|
|||
fn visit(self: Rc<Self>, visitor: &mut dyn NodeVisitor);
|
||||
fn visit_children(&self, visitor: &mut dyn NodeVisitor);
|
||||
|
||||
fn get_workspace(&self) -> Option<Rc<WorkspaceNode>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn is_contained_in(&self, other: NodeId) -> bool {
|
||||
let _ = other;
|
||||
false
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::backend::KeyState;
|
||||
use crate::backend::{KeyState};
|
||||
use crate::cursor::KnownCursor;
|
||||
use crate::fixed::Fixed;
|
||||
use crate::ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT};
|
||||
|
|
@ -693,6 +693,10 @@ impl Node for ContainerNode {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_workspace(&self) -> Option<Rc<WorkspaceNode>> {
|
||||
Some(self.workspace.get())
|
||||
}
|
||||
|
||||
fn is_contained_in(&self, other: NodeId) -> bool {
|
||||
let parent = self.parent.get();
|
||||
if parent.id() == other {
|
||||
|
|
@ -1055,9 +1059,23 @@ impl Node for ContainerNode {
|
|||
|
||||
fn remove_child(self: Rc<Self>, child: &dyn Node) {
|
||||
let node = match self.child_nodes.borrow_mut().remove(&child.id()) {
|
||||
Some(c) => c.to_ref(),
|
||||
Some(c) => c,
|
||||
None => return,
|
||||
};
|
||||
let mut mono_child = None;
|
||||
if let Some(mono) = self.mono_child.get() {
|
||||
if mono.node.id() == child.id() {
|
||||
self.mono_child.take();
|
||||
mono_child = node.next();
|
||||
if mono_child.is_none() {
|
||||
mono_child = node.prev();
|
||||
}
|
||||
}
|
||||
}
|
||||
let node = {
|
||||
let node = node;
|
||||
node.to_ref()
|
||||
};
|
||||
let num_children = self.num_children.fetch_sub(1) - 1;
|
||||
if num_children == 0 {
|
||||
self.seats.borrow_mut().clear();
|
||||
|
|
@ -1080,6 +1098,9 @@ impl Node for ContainerNode {
|
|||
sum += factor;
|
||||
}
|
||||
}
|
||||
if mono_child.is_some() {
|
||||
self.mono_child.set(mono_child);
|
||||
}
|
||||
self.sum_factors.set(sum);
|
||||
self.update_title();
|
||||
self.schedule_layout();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::backend::KeyState;
|
||||
use crate::backend::{KeyState};
|
||||
use crate::cursor::KnownCursor;
|
||||
use crate::fixed::Fixed;
|
||||
use crate::ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT};
|
||||
|
|
@ -343,6 +343,10 @@ impl Node for FloatNode {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_workspace(&self) -> Option<Rc<WorkspaceNode>> {
|
||||
Some(self.workspace.get())
|
||||
}
|
||||
|
||||
fn child_title_changed(self: Rc<Self>, _child: &dyn Node, title: &str) {
|
||||
let mut t = self.title.borrow_mut();
|
||||
if t.deref() != title {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::cursor::KnownCursor;
|
||||
use crate::fixed::Fixed;
|
||||
use crate::ifs::wl_output::WlOutputGlobal;
|
||||
use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal};
|
||||
use crate::ifs::wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
|
||||
|
|
@ -16,14 +17,13 @@ use std::cell::{Cell, RefCell};
|
|||
use std::fmt::{Debug, Formatter};
|
||||
use std::ops::{Deref, Sub};
|
||||
use std::rc::Rc;
|
||||
use crate::fixed::Fixed;
|
||||
|
||||
tree_id!(OutputNodeId);
|
||||
pub struct OutputNode {
|
||||
pub id: OutputNodeId,
|
||||
pub position: Cell<Rect>,
|
||||
pub global: Rc<WlOutputGlobal>,
|
||||
pub workspaces: RefCell<Vec<Rc<WorkspaceNode>>>,
|
||||
pub workspaces: LinkedList<Rc<WorkspaceNode>>,
|
||||
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
|
||||
pub seat_state: NodeSeatState,
|
||||
pub layers: [LinkedList<Rc<ZwlrLayerSurfaceV1>>; 4],
|
||||
|
|
@ -37,12 +37,11 @@ impl OutputNode {
|
|||
let mut rd = self.render_data.borrow_mut();
|
||||
rd.titles.clear();
|
||||
rd.inactive_workspaces.clear();
|
||||
let workspaces = self.workspaces.borrow_mut();
|
||||
let mut pos = 0;
|
||||
let font = self.state.theme.font.borrow_mut();
|
||||
let th = self.state.theme.title_height.get();
|
||||
let active_id = self.workspace.get().map(|w| w.id);
|
||||
for ws in workspaces.deref() {
|
||||
for ws in self.workspaces.iter() {
|
||||
let mut title_width = th;
|
||||
'create_texture: {
|
||||
if let Some(ctx) = self.state.render_ctx.get() {
|
||||
|
|
@ -78,6 +77,23 @@ impl OutputNode {
|
|||
pos += title_width;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show_workspace(&self, ws: &Rc<WorkspaceNode>) {
|
||||
self.workspace.set(Some(ws.clone()));
|
||||
ws.clone().change_extents(&self.workspace_rect());
|
||||
}
|
||||
|
||||
fn workspace_rect(&self) -> Rect {
|
||||
let rect = self.position.get();
|
||||
let th = self.state.theme.title_height.get();
|
||||
Rect::new_sized(
|
||||
rect.x1(),
|
||||
rect.y1() + th,
|
||||
rect.width(),
|
||||
rect.height().sub(th).max(0),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OutputTitle {
|
||||
|
|
@ -100,14 +116,6 @@ impl Debug for OutputNode {
|
|||
}
|
||||
|
||||
impl Node for OutputNode {
|
||||
fn pointer_enter(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _x: Fixed, _y: Fixed) {
|
||||
seat.enter_output(&self)
|
||||
}
|
||||
|
||||
fn leave(&self, seat: &WlSeatGlobal) {
|
||||
seat.leave_output();
|
||||
}
|
||||
|
||||
fn id(&self) -> NodeId {
|
||||
self.id.into()
|
||||
}
|
||||
|
|
@ -120,8 +128,9 @@ impl Node for OutputNode {
|
|||
if detach {
|
||||
self.state.root.clone().remove_child(self);
|
||||
}
|
||||
let mut workspaces = self.workspaces.borrow_mut();
|
||||
for workspace in workspaces.drain(..) {
|
||||
self.workspace.set(None);
|
||||
let workspaces: Vec<_> = self.workspaces.iter().map(|e| e.deref().clone()).collect();
|
||||
for workspace in workspaces {
|
||||
workspace.destroy_node(false);
|
||||
}
|
||||
self.seat_state.destroy_node(self);
|
||||
|
|
@ -132,9 +141,8 @@ impl Node for OutputNode {
|
|||
}
|
||||
|
||||
fn visit_children(&self, visitor: &mut dyn NodeVisitor) {
|
||||
let ws = self.workspaces.borrow_mut();
|
||||
for ws in ws.deref() {
|
||||
visitor.visit_workspace(ws);
|
||||
for ws in self.workspaces.iter() {
|
||||
visitor.visit_workspace(ws.deref());
|
||||
}
|
||||
for layers in &self.layers {
|
||||
for surface in layers.iter() {
|
||||
|
|
@ -147,20 +155,32 @@ impl Node for OutputNode {
|
|||
self.position.get()
|
||||
}
|
||||
|
||||
fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
|
||||
if let Some(ws) = self.workspace.get() {
|
||||
tree.push(FoundNode {
|
||||
node: ws.clone(),
|
||||
x,
|
||||
y,
|
||||
});
|
||||
ws.find_tree_at(x, y, tree);
|
||||
fn find_tree_at(&self, x: i32, mut y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
|
||||
let th = self.state.theme.title_height.get();
|
||||
if y > th {
|
||||
y -= th;
|
||||
if let Some(ws) = self.workspace.get() {
|
||||
tree.push(FoundNode {
|
||||
node: ws.clone(),
|
||||
x,
|
||||
y,
|
||||
});
|
||||
ws.find_tree_at(x, y, tree);
|
||||
}
|
||||
}
|
||||
FindTreeResult::AcceptsInput
|
||||
}
|
||||
|
||||
fn remove_child(self: Rc<Self>, _child: &dyn Node) {
|
||||
self.workspace.set(None);
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn leave(&self, seat: &WlSeatGlobal) {
|
||||
seat.leave_output();
|
||||
}
|
||||
|
||||
fn pointer_enter(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _x: Fixed, _y: Fixed) {
|
||||
seat.enter_output(&self)
|
||||
}
|
||||
|
||||
fn pointer_focus(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
|
|
@ -180,17 +200,9 @@ impl Node for OutputNode {
|
|||
}
|
||||
|
||||
fn change_extents(self: Rc<Self>, rect: &Rect) {
|
||||
let th = self.state.theme.title_height.get();
|
||||
self.position.set(*rect);
|
||||
if let Some(c) = self.workspace.get() {
|
||||
let wrect = Rect::new_sized(
|
||||
rect.x1(),
|
||||
rect.y1() + th,
|
||||
rect.width(),
|
||||
rect.height().sub(th).max(0),
|
||||
)
|
||||
.unwrap();
|
||||
c.change_extents(&wrect);
|
||||
c.change_extents(&self.workspace_rect());
|
||||
}
|
||||
for layer in &self.layers {
|
||||
for surface in layer.iter() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::ifs::wl_seat::SeatId;
|
||||
use crate::ifs::wl_surface::WlSurface;
|
||||
use crate::tree::{Node, WorkspaceNode};
|
||||
use crate::tree::{Node};
|
||||
use crate::utils::linkedlist::LinkedNode;
|
||||
use crate::utils::numcell::NumCell;
|
||||
use crate::utils::smallmap::SmallMap;
|
||||
|
|
@ -9,7 +9,6 @@ use std::rc::Rc;
|
|||
pub trait ToplevelNode {
|
||||
fn data(&self) -> &ToplevelData;
|
||||
fn parent(&self) -> Option<Rc<dyn Node>>;
|
||||
fn workspace(&self) -> Option<Rc<WorkspaceNode>>;
|
||||
fn as_node(&self) -> &dyn Node;
|
||||
fn into_node(self: Rc<Self>) -> Rc<dyn Node>;
|
||||
fn accepts_keyboard_focus(&self) -> bool;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ use crate::tree::container::ContainerNode;
|
|||
use crate::tree::walker::NodeVisitor;
|
||||
use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, OutputNode};
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
use crate::utils::linkedlist::LinkedList;
|
||||
use crate::utils::linkedlist::{LinkedList, LinkedNode};
|
||||
use std::cell::Cell;
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
|
@ -15,16 +16,18 @@ tree_id!(WorkspaceNodeId);
|
|||
pub struct WorkspaceNode {
|
||||
pub id: WorkspaceNodeId,
|
||||
pub output: CloneCell<Rc<OutputNode>>,
|
||||
pub position: Cell<Rect>,
|
||||
pub container: CloneCell<Option<Rc<ContainerNode>>>,
|
||||
pub stacked: LinkedList<Rc<dyn Node>>,
|
||||
pub seat_state: NodeSeatState,
|
||||
pub name: String,
|
||||
pub output_link: Cell<Option<LinkedNode<Rc<WorkspaceNode>>>>,
|
||||
}
|
||||
|
||||
impl WorkspaceNode {
|
||||
pub fn set_container(self: &Rc<Self>, container: &Rc<ContainerNode>) {
|
||||
let output = self.output.get().position.get();
|
||||
container.clone().change_extents(&output);
|
||||
let pos = self.position.get();
|
||||
container.clone().change_extents(&pos);
|
||||
container.clone().set_workspace(self);
|
||||
self.container.set(Some(container.clone()));
|
||||
}
|
||||
|
|
@ -43,16 +46,13 @@ impl Node for WorkspaceNode {
|
|||
if detach {
|
||||
self.output.get().remove_child(self);
|
||||
}
|
||||
self.output_link.set(None);
|
||||
if let Some(container) = self.container.take() {
|
||||
container.destroy_node(false);
|
||||
}
|
||||
self.seat_state.destroy_node(self);
|
||||
}
|
||||
|
||||
fn accepts_child(&self, node: &dyn Node) -> bool {
|
||||
node.is_container()
|
||||
}
|
||||
|
||||
fn visit(self: Rc<Self>, visitor: &mut dyn NodeVisitor) {
|
||||
visitor.visit_workspace(&self);
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ impl Node for WorkspaceNode {
|
|||
}
|
||||
|
||||
fn absolute_position(&self) -> Rect {
|
||||
self.output.get().position.get()
|
||||
self.position.get()
|
||||
}
|
||||
|
||||
fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
|
||||
|
|
@ -91,11 +91,16 @@ impl Node for WorkspaceNode {
|
|||
renderer.render_workspace(self, x, y);
|
||||
}
|
||||
|
||||
fn accepts_child(&self, node: &dyn Node) -> bool {
|
||||
node.is_container()
|
||||
}
|
||||
|
||||
fn is_workspace(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn change_extents(self: Rc<Self>, rect: &Rect) {
|
||||
self.position.set(*rect);
|
||||
if let Some(c) = self.container.get() {
|
||||
c.change_extents(rect);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue