config: add move-to-output action
This commit is contained in:
parent
2a517f437a
commit
fecfd24ba0
15 changed files with 357 additions and 76 deletions
2
.github/workflows/toml-spec.yml
vendored
2
.github/workflows/toml-spec.yml
vendored
|
|
@ -11,7 +11,7 @@ env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
rustfmt:
|
toml-spec:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
_private::{
|
_private::{
|
||||||
bincode_ops,
|
bincode_ops,
|
||||||
ipc::{ClientMessage, InitMessage, Response, ServerMessage},
|
ipc::{ClientMessage, InitMessage, Response, ServerMessage, WorkspaceSource},
|
||||||
logging, Config, ConfigEntry, ConfigEntryGen, PollableId, WireMode, VERSION,
|
logging, Config, ConfigEntry, ConfigEntryGen, PollableId, WireMode, VERSION,
|
||||||
},
|
},
|
||||||
exec::Command,
|
exec::Command,
|
||||||
|
|
@ -421,6 +421,13 @@ impl Client {
|
||||||
self.send(&ClientMessage::DisablePointerConstraint { seat });
|
self.send(&ClientMessage::DisablePointerConstraint { seat });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn move_to_output(&self, workspace: WorkspaceSource, connector: Connector) {
|
||||||
|
self.send(&ClientMessage::MoveToOutput {
|
||||||
|
workspace,
|
||||||
|
connector,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_fullscreen(&self, seat: Seat, fullscreen: bool) {
|
pub fn set_fullscreen(&self, seat: Seat, fullscreen: bool) {
|
||||||
self.send(&ClientMessage::SetFullscreen { seat, fullscreen });
|
self.send(&ClientMessage::SetFullscreen { seat, fullscreen });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -424,6 +424,16 @@ pub enum ClientMessage<'a> {
|
||||||
SetIdle {
|
SetIdle {
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
},
|
},
|
||||||
|
MoveToOutput {
|
||||||
|
workspace: WorkspaceSource,
|
||||||
|
connector: Connector,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub enum WorkspaceSource {
|
||||||
|
Seat(Seat),
|
||||||
|
Explicit(Workspace),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ use {
|
||||||
input::{acceleration::AccelProfile, capability::Capability},
|
input::{acceleration::AccelProfile, capability::Capability},
|
||||||
keyboard::Keymap,
|
keyboard::Keymap,
|
||||||
Axis, Direction, ModifiedKeySym, Workspace,
|
Axis, Direction, ModifiedKeySym, Workspace,
|
||||||
_private::DEFAULT_SEAT_NAME,
|
_private::{ipc::WorkspaceSource, DEFAULT_SEAT_NAME},
|
||||||
|
video::Connector,
|
||||||
},
|
},
|
||||||
serde::{Deserialize, Serialize},
|
serde::{Deserialize, Serialize},
|
||||||
std::time::Duration,
|
std::time::Duration,
|
||||||
|
|
@ -319,6 +320,11 @@ impl Seat {
|
||||||
pub fn disable_pointer_constraint(self) {
|
pub fn disable_pointer_constraint(self) {
|
||||||
get!().disable_pointer_constraint(self)
|
get!().disable_pointer_constraint(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Moves the currently focused workspace to another output.
|
||||||
|
pub fn move_to_output(self, connector: Connector) {
|
||||||
|
get!().move_to_output(WorkspaceSource::Seat(self), connector);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all seats.
|
/// Returns all seats.
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::keyboard::ModifiedKeySym,
|
crate::{_private::ipc::WorkspaceSource, keyboard::ModifiedKeySym, video::Connector},
|
||||||
serde::{Deserialize, Serialize},
|
serde::{Deserialize, Serialize},
|
||||||
std::{
|
std::{
|
||||||
fmt::{Debug, Display, Formatter},
|
fmt::{Debug, Display, Formatter},
|
||||||
|
|
@ -159,6 +159,13 @@ impl Workspace {
|
||||||
let get = get!();
|
let get = get!();
|
||||||
get.set_workspace_capture(self, !get.get_workspace_capture(self));
|
get.set_workspace_capture(self, !get.get_workspace_capture(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Moves this workspace to another output.
|
||||||
|
///
|
||||||
|
/// This has no effect if the workspace is not currently being shown.
|
||||||
|
pub fn move_to_output(self, output: Connector) {
|
||||||
|
get!().move_to_output(WorkspaceSource::Explicit(self), output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the workspace with the given name.
|
/// Returns the workspace with the given name.
|
||||||
|
|
|
||||||
|
|
@ -440,9 +440,8 @@ fn create_dummy_output(state: &Rc<State>) {
|
||||||
title_texture: Cell::new(None),
|
title_texture: Cell::new(None),
|
||||||
attention_requests: Default::default(),
|
attention_requests: Default::default(),
|
||||||
});
|
});
|
||||||
dummy_workspace.output_link.set(Some(
|
*dummy_workspace.output_link.borrow_mut() =
|
||||||
dummy_output.workspaces.add_last(dummy_workspace.clone()),
|
Some(dummy_output.workspaces.add_last(dummy_workspace.clone()));
|
||||||
));
|
|
||||||
dummy_output.show_workspace(&dummy_workspace);
|
dummy_output.show_workspace(&dummy_workspace);
|
||||||
state.dummy_output.set(Some(dummy_output));
|
state.dummy_output.set(Some(dummy_output));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,10 @@ use {
|
||||||
scale::Scale,
|
scale::Scale,
|
||||||
state::{ConnectorData, DeviceHandlerData, DrmDevData, OutputData, State},
|
state::{ConnectorData, DeviceHandlerData, DrmDevData, OutputData, State},
|
||||||
theme::{Color, ThemeSized, DEFAULT_FONT},
|
theme::{Color, ThemeSized, DEFAULT_FONT},
|
||||||
tree::{ContainerNode, ContainerSplit, FloatNode, Node, NodeVisitorBase, OutputNode},
|
tree::{
|
||||||
|
move_ws_to_output, ContainerNode, ContainerSplit, FloatNode, Node, NodeVisitorBase,
|
||||||
|
OutputNode, WsMoveConfig,
|
||||||
|
},
|
||||||
utils::{
|
utils::{
|
||||||
asyncevent::AsyncEvent,
|
asyncevent::AsyncEvent,
|
||||||
copyhashmap::CopyHashMap,
|
copyhashmap::CopyHashMap,
|
||||||
|
|
@ -29,7 +32,7 @@ use {
|
||||||
jay_config::{
|
jay_config::{
|
||||||
_private::{
|
_private::{
|
||||||
bincode_ops,
|
bincode_ops,
|
||||||
ipc::{ClientMessage, Response, ServerMessage},
|
ipc::{ClientMessage, Response, ServerMessage, WorkspaceSource},
|
||||||
PollableId, WireMode,
|
PollableId, WireMode,
|
||||||
},
|
},
|
||||||
input::{
|
input::{
|
||||||
|
|
@ -753,6 +756,45 @@ impl ConfigProxyHandler {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_move_to_output(
|
||||||
|
&self,
|
||||||
|
workspace: WorkspaceSource,
|
||||||
|
connector: Connector,
|
||||||
|
) -> Result<(), CphError> {
|
||||||
|
let output = self.get_output(connector)?;
|
||||||
|
let ws = match workspace {
|
||||||
|
WorkspaceSource::Explicit(ws) => {
|
||||||
|
let name = self.get_workspace(ws)?;
|
||||||
|
match self.state.workspaces.get(name.as_str()) {
|
||||||
|
Some(ws) => ws,
|
||||||
|
_ => return Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WorkspaceSource::Seat(s) => match self.get_seat(s)?.get_output().workspace.get() {
|
||||||
|
Some(ws) => ws,
|
||||||
|
_ => return Ok(()),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if ws.is_dummy || output.node.is_dummy {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
if ws.output.get().id == output.node.id {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let link = match &*ws.output_link.borrow() {
|
||||||
|
None => return Ok(()),
|
||||||
|
Some(l) => l.to_ref(),
|
||||||
|
};
|
||||||
|
let config = WsMoveConfig {
|
||||||
|
make_visible_if_empty: true,
|
||||||
|
source_is_destroyed: false,
|
||||||
|
};
|
||||||
|
move_ws_to_output(&link, &output.node, config);
|
||||||
|
self.state.tree_changed();
|
||||||
|
self.state.damage();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_set_idle(&self, timeout: Duration) {
|
fn handle_set_idle(&self, timeout: Duration) {
|
||||||
self.state.idle.set_timeout(timeout);
|
self.state.idle.set_timeout(timeout);
|
||||||
}
|
}
|
||||||
|
|
@ -1676,6 +1718,12 @@ impl ConfigProxyHandler {
|
||||||
.handle_get_input_device_devnode(device)
|
.handle_get_input_device_devnode(device)
|
||||||
.wrn("get_input_device_devnode")?,
|
.wrn("get_input_device_devnode")?,
|
||||||
ClientMessage::SetIdle { timeout } => self.handle_set_idle(timeout),
|
ClientMessage::SetIdle { timeout } => self.handle_set_idle(timeout),
|
||||||
|
ClientMessage::MoveToOutput {
|
||||||
|
workspace,
|
||||||
|
connector,
|
||||||
|
} => self
|
||||||
|
.handle_move_to_output(workspace, connector)
|
||||||
|
.wrn("move_to_output")?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -337,7 +337,7 @@ impl OutputNode {
|
||||||
stacked: Default::default(),
|
stacked: Default::default(),
|
||||||
seat_state: Default::default(),
|
seat_state: Default::default(),
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
output_link: Cell::new(None),
|
output_link: Default::default(),
|
||||||
visible: Cell::new(false),
|
visible: Cell::new(false),
|
||||||
fullscreen: Default::default(),
|
fullscreen: Default::default(),
|
||||||
visible_on_desired_output: Cell::new(false),
|
visible_on_desired_output: Cell::new(false),
|
||||||
|
|
@ -347,8 +347,7 @@ impl OutputNode {
|
||||||
title_texture: Default::default(),
|
title_texture: Default::default(),
|
||||||
attention_requests: Default::default(),
|
attention_requests: Default::default(),
|
||||||
});
|
});
|
||||||
ws.output_link
|
*ws.output_link.borrow_mut() = Some(self.workspaces.add_last(ws.clone()));
|
||||||
.set(Some(self.workspaces.add_last(ws.clone())));
|
|
||||||
self.state.workspaces.set(name.to_string(), ws.clone());
|
self.state.workspaces.set(name.to_string(), ws.clone());
|
||||||
if self.workspace.is_none() {
|
if self.workspace.is_none() {
|
||||||
self.show_workspace(&ws);
|
self.show_workspace(&ws);
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,12 @@ use {
|
||||||
},
|
},
|
||||||
wire::JayWorkspaceId,
|
wire::JayWorkspaceId,
|
||||||
},
|
},
|
||||||
std::{cell::Cell, fmt::Debug, ops::Deref, rc::Rc},
|
std::{
|
||||||
|
cell::{Cell, RefCell},
|
||||||
|
fmt::Debug,
|
||||||
|
ops::Deref,
|
||||||
|
rc::Rc,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
tree_id!(WorkspaceNodeId);
|
tree_id!(WorkspaceNodeId);
|
||||||
|
|
@ -38,7 +43,7 @@ pub struct WorkspaceNode {
|
||||||
pub stacked: LinkedList<Rc<dyn StackedNode>>,
|
pub stacked: LinkedList<Rc<dyn StackedNode>>,
|
||||||
pub seat_state: NodeSeatState,
|
pub seat_state: NodeSeatState,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub output_link: Cell<Option<LinkedNode<Rc<WorkspaceNode>>>>,
|
pub output_link: RefCell<Option<LinkedNode<Rc<WorkspaceNode>>>>,
|
||||||
pub visible: Cell<bool>,
|
pub visible: Cell<bool>,
|
||||||
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>,
|
||||||
|
|
@ -52,7 +57,7 @@ pub struct WorkspaceNode {
|
||||||
impl WorkspaceNode {
|
impl WorkspaceNode {
|
||||||
pub fn clear(&self) {
|
pub fn clear(&self) {
|
||||||
self.container.set(None);
|
self.container.set(None);
|
||||||
self.output_link.set(None);
|
*self.output_link.borrow_mut() = None;
|
||||||
self.fullscreen.set(None);
|
self.fullscreen.set(None);
|
||||||
self.jay_workspaces.clear();
|
self.jay_workspaces.clear();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ use {
|
||||||
status::MessageFormat,
|
status::MessageFormat,
|
||||||
theme::Color,
|
theme::Color,
|
||||||
video::{GfxApi, Transform},
|
video::{GfxApi, Transform},
|
||||||
Axis, Direction,
|
Axis, Direction, Workspace,
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
|
|
@ -53,26 +53,70 @@ pub enum SimpleCommand {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Action {
|
pub enum Action {
|
||||||
ConfigureConnector { con: ConfigConnector },
|
ConfigureConnector {
|
||||||
ConfigureDirectScanout { enabled: bool },
|
con: ConfigConnector,
|
||||||
ConfigureDrmDevice { dev: ConfigDrmDevice },
|
},
|
||||||
ConfigureIdle { idle: Duration },
|
ConfigureDirectScanout {
|
||||||
ConfigureInput { input: Input },
|
enabled: bool,
|
||||||
ConfigureOutput { out: Output },
|
},
|
||||||
Exec { exec: Exec },
|
ConfigureDrmDevice {
|
||||||
MoveToWorkspace { name: String },
|
dev: ConfigDrmDevice,
|
||||||
Multi { actions: Vec<Action> },
|
},
|
||||||
SetEnv { env: Vec<(String, String)> },
|
ConfigureIdle {
|
||||||
SetGfxApi { api: GfxApi },
|
idle: Duration,
|
||||||
SetKeymap { map: ConfigKeymap },
|
},
|
||||||
SetLogLevel { level: LogLevel },
|
ConfigureInput {
|
||||||
SetRenderDevice { dev: DrmDeviceMatch },
|
input: Input,
|
||||||
SetStatus { status: Option<Status> },
|
},
|
||||||
SetTheme { theme: Box<Theme> },
|
ConfigureOutput {
|
||||||
ShowWorkspace { name: String },
|
out: Output,
|
||||||
SimpleCommand { cmd: SimpleCommand },
|
},
|
||||||
SwitchToVt { num: u32 },
|
Exec {
|
||||||
UnsetEnv { env: Vec<String> },
|
exec: Exec,
|
||||||
|
},
|
||||||
|
MoveToWorkspace {
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
|
Multi {
|
||||||
|
actions: Vec<Action>,
|
||||||
|
},
|
||||||
|
SetEnv {
|
||||||
|
env: Vec<(String, String)>,
|
||||||
|
},
|
||||||
|
SetGfxApi {
|
||||||
|
api: GfxApi,
|
||||||
|
},
|
||||||
|
SetKeymap {
|
||||||
|
map: ConfigKeymap,
|
||||||
|
},
|
||||||
|
SetLogLevel {
|
||||||
|
level: LogLevel,
|
||||||
|
},
|
||||||
|
SetRenderDevice {
|
||||||
|
dev: DrmDeviceMatch,
|
||||||
|
},
|
||||||
|
SetStatus {
|
||||||
|
status: Option<Status>,
|
||||||
|
},
|
||||||
|
SetTheme {
|
||||||
|
theme: Box<Theme>,
|
||||||
|
},
|
||||||
|
ShowWorkspace {
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
|
SimpleCommand {
|
||||||
|
cmd: SimpleCommand,
|
||||||
|
},
|
||||||
|
SwitchToVt {
|
||||||
|
num: u32,
|
||||||
|
},
|
||||||
|
UnsetEnv {
|
||||||
|
env: Vec<String>,
|
||||||
|
},
|
||||||
|
MoveToOutput {
|
||||||
|
workspace: Option<Workspace>,
|
||||||
|
output: OutputMatch,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
|
|
|
||||||
|
|
@ -16,19 +16,24 @@ use {
|
||||||
keymap::{KeymapParser, KeymapParserError},
|
keymap::{KeymapParser, KeymapParserError},
|
||||||
log_level::{LogLevelParser, LogLevelParserError},
|
log_level::{LogLevelParser, LogLevelParserError},
|
||||||
output::{OutputParser, OutputParserError},
|
output::{OutputParser, OutputParserError},
|
||||||
|
output_match::{OutputMatchParser, OutputMatchParserError},
|
||||||
status::{StatusParser, StatusParserError},
|
status::{StatusParser, StatusParserError},
|
||||||
theme::{ThemeParser, ThemeParserError},
|
theme::{ThemeParser, ThemeParserError},
|
||||||
StringParser, StringParserError,
|
StringParser, StringParserError,
|
||||||
},
|
},
|
||||||
|
spanned::SpannedErrorExt,
|
||||||
Action,
|
Action,
|
||||||
},
|
},
|
||||||
toml::{
|
toml::{
|
||||||
toml_span::{Span, Spanned, SpannedExt},
|
toml_span::{DespanExt, Span, Spanned, SpannedExt},
|
||||||
toml_value::Value,
|
toml_value::Value,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexmap::IndexMap,
|
indexmap::IndexMap,
|
||||||
jay_config::Axis::{Horizontal, Vertical},
|
jay_config::{
|
||||||
|
get_workspace,
|
||||||
|
Axis::{Horizontal, Vertical},
|
||||||
|
},
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -45,31 +50,33 @@ pub enum ActionParserError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Extract(#[from] ExtractorError),
|
Extract(#[from] ExtractorError),
|
||||||
#[error("Could not parse the exec action")]
|
#[error("Could not parse the exec action")]
|
||||||
Exec(#[from] ExecParserError),
|
Exec(#[source] ExecParserError),
|
||||||
#[error("Could not parse the configure-connector action")]
|
#[error("Could not parse the configure-connector action")]
|
||||||
ConfigureConnector(#[from] ConnectorParserError),
|
ConfigureConnector(#[source] ConnectorParserError),
|
||||||
#[error("Could not parse the configure-input action")]
|
#[error("Could not parse the configure-input action")]
|
||||||
ConfigureInput(#[from] InputParserError),
|
ConfigureInput(#[source] InputParserError),
|
||||||
#[error("Could not parse the configure-output action")]
|
#[error("Could not parse the configure-output action")]
|
||||||
ConfigureOutput(#[from] OutputParserError),
|
ConfigureOutput(#[source] OutputParserError),
|
||||||
#[error("Could not parse the environment variables")]
|
#[error("Could not parse the environment variables")]
|
||||||
Env(#[from] EnvParserError),
|
Env(#[source] EnvParserError),
|
||||||
#[error("Could not parse a set-keymap action")]
|
#[error("Could not parse a set-keymap action")]
|
||||||
SetKeymap(#[from] KeymapParserError),
|
SetKeymap(#[source] KeymapParserError),
|
||||||
#[error("Could not parse a set-status action")]
|
#[error("Could not parse a set-status action")]
|
||||||
Status(#[from] StatusParserError),
|
Status(#[source] StatusParserError),
|
||||||
#[error("Could not parse a set-theme action")]
|
#[error("Could not parse a set-theme action")]
|
||||||
Theme(#[from] ThemeParserError),
|
Theme(#[source] ThemeParserError),
|
||||||
#[error("Could not parse a set-log-level action")]
|
#[error("Could not parse a set-log-level action")]
|
||||||
SetLogLevel(#[from] LogLevelParserError),
|
SetLogLevel(#[source] LogLevelParserError),
|
||||||
#[error("Could not parse a set-gfx-api action")]
|
#[error("Could not parse a set-gfx-api action")]
|
||||||
GfxApi(#[from] GfxApiParserError),
|
GfxApi(#[source] GfxApiParserError),
|
||||||
#[error("Could not parse a configure-drm-device action")]
|
#[error("Could not parse a configure-drm-device action")]
|
||||||
DrmDevice(#[from] DrmDeviceParserError),
|
DrmDevice(#[source] DrmDeviceParserError),
|
||||||
#[error("Could not parse a set-render-device action")]
|
#[error("Could not parse a set-render-device action")]
|
||||||
SetRenderDevice(#[from] DrmDeviceMatchParserError),
|
SetRenderDevice(#[source] DrmDeviceMatchParserError),
|
||||||
#[error("Could not parse a configure-idle action")]
|
#[error("Could not parse a configure-idle action")]
|
||||||
ConfigureIdle(#[from] IdleParserError),
|
ConfigureIdle(#[source] IdleParserError),
|
||||||
|
#[error("Could not parse a move-to-output action")]
|
||||||
|
MoveToOutput(#[source] OutputMatchParserError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ActionParser<'a>(pub &'a Context<'a>);
|
pub struct ActionParser<'a>(pub &'a Context<'a>);
|
||||||
|
|
@ -117,7 +124,8 @@ impl ActionParser<'_> {
|
||||||
fn parse_exec(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
fn parse_exec(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
let exec = ext
|
let exec = ext
|
||||||
.extract(val("exec"))?
|
.extract(val("exec"))?
|
||||||
.parse_map(&mut ExecParser(self.0))?;
|
.parse_map(&mut ExecParser(self.0))
|
||||||
|
.map_spanned_err(ActionParserError::Exec)?;
|
||||||
Ok(Action::Exec { exec })
|
Ok(Action::Exec { exec })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,35 +147,46 @@ impl ActionParser<'_> {
|
||||||
fn parse_configure_connector(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
fn parse_configure_connector(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
let con = ext
|
let con = ext
|
||||||
.extract(val("connector"))?
|
.extract(val("connector"))?
|
||||||
.parse_map(&mut ConnectorParser(self.0))?;
|
.parse_map(&mut ConnectorParser(self.0))
|
||||||
|
.map_spanned_err(ActionParserError::ConfigureConnector)?;
|
||||||
Ok(Action::ConfigureConnector { con })
|
Ok(Action::ConfigureConnector { con })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_configure_input(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
fn parse_configure_input(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
let input = ext.extract(val("input"))?.parse_map(&mut InputParser {
|
let input = ext
|
||||||
cx: self.0,
|
.extract(val("input"))?
|
||||||
tag_ok: false,
|
.parse_map(&mut InputParser {
|
||||||
})?;
|
cx: self.0,
|
||||||
|
tag_ok: false,
|
||||||
|
})
|
||||||
|
.map_spanned_err(ActionParserError::ConfigureInput)?;
|
||||||
Ok(Action::ConfigureInput { input })
|
Ok(Action::ConfigureInput { input })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_configure_idle(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
fn parse_configure_idle(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
let idle = ext
|
let idle = ext
|
||||||
.extract(val("idle"))?
|
.extract(val("idle"))?
|
||||||
.parse_map(&mut IdleParser(self.0))?;
|
.parse_map(&mut IdleParser(self.0))
|
||||||
|
.map_spanned_err(ActionParserError::ConfigureIdle)?;
|
||||||
Ok(Action::ConfigureIdle { idle })
|
Ok(Action::ConfigureIdle { idle })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_configure_output(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
fn parse_configure_output(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
let out = ext.extract(val("output"))?.parse_map(&mut OutputParser {
|
let out = ext
|
||||||
cx: self.0,
|
.extract(val("output"))?
|
||||||
name_ok: false,
|
.parse_map(&mut OutputParser {
|
||||||
})?;
|
cx: self.0,
|
||||||
|
name_ok: false,
|
||||||
|
})
|
||||||
|
.map_spanned_err(ActionParserError::ConfigureOutput)?;
|
||||||
Ok(Action::ConfigureOutput { out })
|
Ok(Action::ConfigureOutput { out })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_set_env(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
fn parse_set_env(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
let env = ext.extract(val("env"))?.parse_map(&mut EnvParser)?;
|
let env = ext
|
||||||
|
.extract(val("env"))?
|
||||||
|
.parse_map(&mut EnvParser)
|
||||||
|
.map_spanned_err(ActionParserError::Env)?;
|
||||||
Ok(Action::SetEnv { env })
|
Ok(Action::SetEnv { env })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,17 +214,23 @@ impl ActionParser<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_set_keymap(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
fn parse_set_keymap(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
let map = ext.extract(val("map"))?.parse_map(&mut KeymapParser {
|
let map = ext
|
||||||
cx: self.0,
|
.extract(val("map"))?
|
||||||
definition: false,
|
.parse_map(&mut KeymapParser {
|
||||||
})?;
|
cx: self.0,
|
||||||
|
definition: false,
|
||||||
|
})
|
||||||
|
.map_spanned_err(ActionParserError::SetKeymap)?;
|
||||||
Ok(Action::SetKeymap { map })
|
Ok(Action::SetKeymap { map })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_set_status(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
fn parse_set_status(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
let status = match ext.extract(opt(val("status")))? {
|
let status = match ext.extract(opt(val("status")))? {
|
||||||
None => None,
|
None => None,
|
||||||
Some(v) => Some(v.parse_map(&mut StatusParser(self.0))?),
|
Some(v) => Some(
|
||||||
|
v.parse_map(&mut StatusParser(self.0))
|
||||||
|
.map_spanned_err(ActionParserError::Status)?,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
Ok(Action::SetStatus { status })
|
Ok(Action::SetStatus { status })
|
||||||
}
|
}
|
||||||
|
|
@ -213,26 +238,34 @@ impl ActionParser<'_> {
|
||||||
fn parse_set_theme(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
fn parse_set_theme(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
let theme = ext
|
let theme = ext
|
||||||
.extract(val("theme"))?
|
.extract(val("theme"))?
|
||||||
.parse_map(&mut ThemeParser(self.0))?;
|
.parse_map(&mut ThemeParser(self.0))
|
||||||
|
.map_spanned_err(ActionParserError::Theme)?;
|
||||||
Ok(Action::SetTheme {
|
Ok(Action::SetTheme {
|
||||||
theme: Box::new(theme),
|
theme: Box::new(theme),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_set_log_level(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
fn parse_set_log_level(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
let level = ext.extract(val("level"))?.parse_map(&mut LogLevelParser)?;
|
let level = ext
|
||||||
|
.extract(val("level"))?
|
||||||
|
.parse_map(&mut LogLevelParser)
|
||||||
|
.map_spanned_err(ActionParserError::SetLogLevel)?;
|
||||||
Ok(Action::SetLogLevel { level })
|
Ok(Action::SetLogLevel { level })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_set_gfx_api(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
fn parse_set_gfx_api(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
let api = ext.extract(val("api"))?.parse_map(&mut GfxApiParser)?;
|
let api = ext
|
||||||
|
.extract(val("api"))?
|
||||||
|
.parse_map(&mut GfxApiParser)
|
||||||
|
.map_spanned_err(ActionParserError::GfxApi)?;
|
||||||
Ok(Action::SetGfxApi { api })
|
Ok(Action::SetGfxApi { api })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_set_render_device(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
fn parse_set_render_device(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
let dev = ext
|
let dev = ext
|
||||||
.extract(val("dev"))?
|
.extract(val("dev"))?
|
||||||
.parse_map(&mut DrmDeviceMatchParser(self.0))?;
|
.parse_map(&mut DrmDeviceMatchParser(self.0))
|
||||||
|
.map_spanned_err(ActionParserError::SetRenderDevice)?;
|
||||||
Ok(Action::SetRenderDevice { dev })
|
Ok(Action::SetRenderDevice { dev })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,12 +275,26 @@ impl ActionParser<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_configure_drm_device(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
fn parse_configure_drm_device(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
let dev = ext.extract(val("dev"))?.parse_map(&mut DrmDeviceParser {
|
let dev = ext
|
||||||
cx: self.0,
|
.extract(val("dev"))?
|
||||||
name_ok: false,
|
.parse_map(&mut DrmDeviceParser {
|
||||||
})?;
|
cx: self.0,
|
||||||
|
name_ok: false,
|
||||||
|
})
|
||||||
|
.map_spanned_err(ActionParserError::DrmDevice)?;
|
||||||
Ok(Action::ConfigureDrmDevice { dev })
|
Ok(Action::ConfigureDrmDevice { dev })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_move_to_output(&mut self, ext: &mut Extractor<'_>) -> ParseResult<Self> {
|
||||||
|
let (ws, output) = ext.extract((opt(str("workspace")), val("output")))?;
|
||||||
|
let output = output
|
||||||
|
.parse_map(&mut OutputMatchParser(self.0))
|
||||||
|
.map_spanned_err(ActionParserError::MoveToOutput)?;
|
||||||
|
Ok(Action::MoveToOutput {
|
||||||
|
workspace: ws.despan().map(get_workspace),
|
||||||
|
output,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Parser for ActionParser<'a> {
|
impl<'a> Parser for ActionParser<'a> {
|
||||||
|
|
@ -297,6 +344,7 @@ impl<'a> Parser for ActionParser<'a> {
|
||||||
"configure-drm-device" => self.parse_configure_drm_device(&mut ext),
|
"configure-drm-device" => self.parse_configure_drm_device(&mut ext),
|
||||||
"set-render-device" => self.parse_set_render_device(&mut ext),
|
"set-render-device" => self.parse_set_render_device(&mut ext),
|
||||||
"configure-idle" => self.parse_configure_idle(&mut ext),
|
"configure-idle" => self.parse_configure_idle(&mut ext),
|
||||||
|
"move-to-output" => self.parse_move_to_output(&mut ext),
|
||||||
v => {
|
v => {
|
||||||
ext.ignore_unused();
|
ext.ignore_unused();
|
||||||
return Err(ActionParserError::UnknownType(v.to_string()).spanned(ty.span));
|
return Err(ActionParserError::UnknownType(v.to_string()).spanned(ty.span));
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,23 @@ impl Action {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Action::ConfigureIdle { idle } => Box::new(move || set_idle(Some(idle))),
|
Action::ConfigureIdle { idle } => Box::new(move || set_idle(Some(idle))),
|
||||||
|
Action::MoveToOutput { output, workspace } => {
|
||||||
|
let state = state.clone();
|
||||||
|
Box::new(move || {
|
||||||
|
let output = 'get_output: {
|
||||||
|
for connector in connectors() {
|
||||||
|
if connector.connected() && output.matches(connector, &state) {
|
||||||
|
break 'get_output connector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
match workspace {
|
||||||
|
Some(ws) => ws.move_to_output(output),
|
||||||
|
None => s.move_to_output(output),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,27 @@
|
||||||
"name"
|
"name"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"description": "Moves a workspace to a different output.\n\n- Example 1:\n\n ```toml\n [shortcuts]\n alt-F1 = { type = \"move-to-output\", workspace = \"1\", output.name = \"right\" }\n ```\n\n- Example 2:\n\n ```toml\n [shortcuts]\n alt-F1 = { type = \"move-to-output\", output.name = \"right\" }\n ```\n",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"const": "move-to-output"
|
||||||
|
},
|
||||||
|
"workspace": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the workspace.\n\nIf this is omitted, the currently active workspace is moved.\n"
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"description": "The output to move to.\n\nIf multiple outputs match, the workspace is moved to the first matching\noutput.\n",
|
||||||
|
"$ref": "#/$defs/OutputMatch"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"output"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "Applies a configuration to connectors.\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-j = { type = \"configure-connector\", connector = { match.name = \"eDP-1\", enabled = false } }\n alt-k = { type = \"configure-connector\", connector = { match.name = \"eDP-1\", enabled = true } }\n ```\n",
|
"description": "Applies a configuration to connectors.\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-j = { type = \"configure-connector\", connector = { match.name = \"eDP-1\", enabled = false } }\n alt-k = { type = \"configure-connector\", connector = { match.name = \"eDP-1\", enabled = true } }\n ```\n",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,43 @@ This table is a tagged union. The variant is determined by the `type` field. It
|
||||||
|
|
||||||
The value of this field should be a string.
|
The value of this field should be a string.
|
||||||
|
|
||||||
|
- `move-to-output`:
|
||||||
|
|
||||||
|
Moves a workspace to a different output.
|
||||||
|
|
||||||
|
- Example 1:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[shortcuts]
|
||||||
|
alt-F1 = { type = "move-to-output", workspace = "1", output.name = "right" }
|
||||||
|
```
|
||||||
|
|
||||||
|
- Example 2:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[shortcuts]
|
||||||
|
alt-F1 = { type = "move-to-output", output.name = "right" }
|
||||||
|
```
|
||||||
|
|
||||||
|
The table has the following fields:
|
||||||
|
|
||||||
|
- `workspace` (optional):
|
||||||
|
|
||||||
|
The name of the workspace.
|
||||||
|
|
||||||
|
If this is omitted, the currently active workspace is moved.
|
||||||
|
|
||||||
|
The value of this field should be a string.
|
||||||
|
|
||||||
|
- `output` (required):
|
||||||
|
|
||||||
|
The output to move to.
|
||||||
|
|
||||||
|
If multiple outputs match, the workspace is moved to the first matching
|
||||||
|
output.
|
||||||
|
|
||||||
|
The value of this field should be a [OutputMatch](#types-OutputMatch).
|
||||||
|
|
||||||
- `configure-connector`:
|
- `configure-connector`:
|
||||||
|
|
||||||
Applies a configuration to connectors.
|
Applies a configuration to connectors.
|
||||||
|
|
|
||||||
|
|
@ -219,6 +219,39 @@ Action:
|
||||||
description: The name of the workspace.
|
description: The name of the workspace.
|
||||||
required: true
|
required: true
|
||||||
kind: string
|
kind: string
|
||||||
|
move-to-output:
|
||||||
|
description: |
|
||||||
|
Moves a workspace to a different output.
|
||||||
|
|
||||||
|
- Example 1:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[shortcuts]
|
||||||
|
alt-F1 = { type = "move-to-output", workspace = "1", output.name = "right" }
|
||||||
|
```
|
||||||
|
|
||||||
|
- Example 2:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[shortcuts]
|
||||||
|
alt-F1 = { type = "move-to-output", output.name = "right" }
|
||||||
|
```
|
||||||
|
fields:
|
||||||
|
workspace:
|
||||||
|
description: |
|
||||||
|
The name of the workspace.
|
||||||
|
|
||||||
|
If this is omitted, the currently active workspace is moved.
|
||||||
|
required: false
|
||||||
|
kind: string
|
||||||
|
output:
|
||||||
|
description: |
|
||||||
|
The output to move to.
|
||||||
|
|
||||||
|
If multiple outputs match, the workspace is moved to the first matching
|
||||||
|
output.
|
||||||
|
required: true
|
||||||
|
ref: OutputMatch
|
||||||
configure-connector:
|
configure-connector:
|
||||||
description: |
|
description: |
|
||||||
Applies a configuration to connectors.
|
Applies a configuration to connectors.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue