summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Linford <tlinford@users.noreply.github.com>2022-10-31 17:04:38 +0100
committerGitHub <noreply@github.com>2022-10-31 17:04:38 +0100
commit855711ebb8ab2a726b27880c1f1d64414bf3ddba (patch)
tree4a4e583ec0fbf41784d851d4c721fd019ac3c4a8
parent5c2f5f84708fa6fe7076189f262b6ec62a29363a (diff)
feat(mouse): allow toggling mouse mode at runtime (#1883)
-rw-r--r--zellij-client/src/input_handler.rs16
-rw-r--r--zellij-client/src/lib.rs5
-rw-r--r--zellij-client/src/os_input_output.rs31
-rw-r--r--zellij-client/src/unit/stdin_tests.rs9
-rw-r--r--zellij-server/src/route.rs1
-rw-r--r--zellij-utils/src/input/actions.rs1
-rw-r--r--zellij-utils/src/kdl/mod.rs4
7 files changed, 49 insertions, 18 deletions
diff --git a/zellij-client/src/input_handler.rs b/zellij-client/src/input_handler.rs
index a4c4988c9..03cb57dc5 100644
--- a/zellij-client/src/input_handler.rs
+++ b/zellij-client/src/input_handler.rs
@@ -6,7 +6,7 @@ use crate::{
use zellij_utils::{
channels::{Receiver, SenderWithContext, OPENCALLS},
data::{InputMode, Key},
- errors::{ContextType, ErrorContext},
+ errors::{ContextType, ErrorContext, FatalError},
input::{
actions::Action,
cast_termwiz_key,
@@ -44,6 +44,7 @@ struct InputHandler {
should_exit: bool,
receive_input_instructions: Receiver<(InputInstruction, ErrorContext)>,
holding_mouse: Option<HeldMouseButton>,
+ mouse_mode_active: bool,
}
impl InputHandler {
@@ -67,6 +68,7 @@ impl InputHandler {
should_exit: false,
receive_input_instructions,
holding_mouse: None,
+ mouse_mode_active: false,
}
}
@@ -78,7 +80,8 @@ impl InputHandler {
let bracketed_paste_start = vec![27, 91, 50, 48, 48, 126]; // \u{1b}[200~
let bracketed_paste_end = vec![27, 91, 50, 48, 49, 126]; // \u{1b}[201~
if self.options.mouse_mode.unwrap_or(true) {
- self.os_input.enable_mouse();
+ self.os_input.enable_mouse().non_fatal();
+ self.mouse_mode_active = true;
}
loop {
if self.should_exit {
@@ -284,6 +287,15 @@ impl InputHandler {
self.command_is_executing
.wait_until_input_thread_is_unblocked();
},
+ Action::ToggleMouseMode => {
+ if self.mouse_mode_active {
+ self.os_input.disable_mouse().non_fatal();
+ self.mouse_mode_active = false;
+ } else {
+ self.os_input.enable_mouse().non_fatal();
+ self.mouse_mode_active = true;
+ }
+ },
_ => self
.os_input
.send_to_server(ClientToServerMsg::Action(action, client_id)),
diff --git a/zellij-client/src/lib.rs b/zellij-client/src/lib.rs
index c48fd5575..bc9355ceb 100644
--- a/zellij-client/src/lib.rs
+++ b/zellij-client/src/lib.rs
@@ -14,6 +14,7 @@ use std::path::Path;
use std::process::Command;
use std::sync::{Arc, Mutex};
use std::thread;
+use zellij_utils::errors::FatalError;
use crate::stdin_ansi_parser::{AnsiStdinInstruction, StdinAnsiParser};
use crate::{
@@ -324,7 +325,7 @@ pub fn start_client(
os_input.unset_raw_mode(0).unwrap();
let goto_start_of_last_line = format!("\u{1b}[{};{}H", full_screen_ws.rows, 1);
let restore_snapshot = "\u{1b}[?1049l";
- os_input.disable_mouse();
+ os_input.disable_mouse().non_fatal();
let error = format!(
"{}\n{}{}\n",
restore_snapshot, goto_start_of_last_line, backtrace
@@ -389,7 +390,7 @@ pub fn start_client(
goto_start_of_last_line, restore_snapshot, reset_style, show_cursor, exit_msg
);
- os_input.disable_mouse();
+ os_input.disable_mouse().non_fatal();
info!("{}", exit_msg);
os_input.unset_raw_mode(0).unwrap();
let mut stdout = os_input.get_stdout_writer();
diff --git a/zellij-client/src/os_input_output.rs b/zellij-client/src/os_input_output.rs
index 1caf78721..8004b8ad2 100644
--- a/zellij-client/src/os_input_output.rs
+++ b/zellij-client/src/os_input_output.rs
@@ -1,3 +1,4 @@
+use zellij_utils::anyhow::{Context, Result};
use zellij_utils::pane_size::Size;
use zellij_utils::{interprocess, libc, nix, signal_hook};
@@ -106,8 +107,8 @@ pub trait ClientOsApi: Send + Sync {
/// Establish a connection with the server socket.
fn connect_to_server(&self, path: &Path);
fn load_palette(&self) -> Palette;
- fn enable_mouse(&self);
- fn disable_mouse(&self);
+ fn enable_mouse(&self) -> Result<()>;
+ fn disable_mouse(&self) -> Result<()>;
// Repeatedly send action, until stdin is readable again
fn stdin_poller(&self) -> StdinPoller;
}
@@ -215,18 +216,24 @@ impl ClientOsApi for ClientOsInputOutput {
// };
default_palette()
}
- fn enable_mouse(&self) {
- let _ = self
- .get_stdout_writer()
- .write(ENABLE_MOUSE_SUPPORT.as_bytes())
- .unwrap();
+ fn enable_mouse(&self) -> Result<()> {
+ let err_context = "failed to enable mouse mode";
+ let mut stdout = self.get_stdout_writer();
+ stdout
+ .write_all(ENABLE_MOUSE_SUPPORT.as_bytes())
+ .context(err_context)?;
+ stdout.flush().context(err_context)?;
+ Ok(())
}
- fn disable_mouse(&self) {
- let _ = self
- .get_stdout_writer()
- .write(DISABLE_MOUSE_SUPPORT.as_bytes())
- .unwrap();
+ fn disable_mouse(&self) -> Result<()> {
+ let err_context = "failed to enable mouse mode";
+ let mut stdout = self.get_stdout_writer();
+ stdout
+ .write_all(DISABLE_MOUSE_SUPPORT.as_bytes())
+ .context(err_context)?;
+ stdout.flush().context(err_context)?;
+ Ok(())
}
fn stdin_poller(&self) -> StdinPoller {
diff --git a/zellij-client/src/unit/stdin_tests.rs b/zellij-client/src/unit/stdin_tests.rs
index d51734acf..aa1bd59ce 100644
--- a/zellij-client/src/unit/stdin_tests.rs
+++ b/zellij-client/src/unit/stdin_tests.rs
@@ -1,6 +1,7 @@
use super::input_loop;
use crate::stdin_ansi_parser::StdinAnsiParser;
use crate::stdin_loop;
+use zellij_utils::anyhow::Result;
use zellij_utils::data::{InputMode, Palette};
use zellij_utils::input::actions::{Action, Direction};
use zellij_utils::input::config::Config;
@@ -181,8 +182,12 @@ impl ClientOsApi for FakeClientOsApi {
fn load_palette(&self) -> Palette {
unimplemented!()
}
- fn enable_mouse(&self) {}
- fn disable_mouse(&self) {}
+ fn enable_mouse(&self) -> Result<()> {
+ Ok(())
+ }
+ fn disable_mouse(&self) -> Result<()> {
+ Ok(())
+ }
fn stdin_poller(&self) -> StdinPoller {
unimplemented!()
}
diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs
index 015b00108..0d2da7b7d 100644
--- a/zellij-server/src/route.rs
+++ b/zellij-server/src/route.rs
@@ -611,6 +611,7 @@ pub(crate) fn route_action(
.send_to_screen(instruction)
.with_context(err_context)?;
},
+ Action::ToggleMouseMode => {}, // Handled client side
}
Ok(should_break)
}
diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs
index 51ead67b3..f63390ad7 100644
--- a/zellij-utils/src/input/actions.rs
+++ b/zellij-utils/src/input/actions.rs
@@ -224,6 +224,7 @@ pub enum Action {
Search(SearchDirection),
/// Toggle case sensitivity of search
SearchToggleOption(SearchOption),
+ ToggleMouseMode,
}
impl Action {
diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs
index d37463d4c..92abcac18 100644
--- a/zellij-utils/src/kdl/mod.rs
+++ b/zellij-utils/src/kdl/mod.rs
@@ -65,6 +65,7 @@ macro_rules! parse_kdl_action_arguments {
"Copy" => Ok(Action::Copy),
"Confirm" => Ok(Action::Confirm),
"Deny" => Ok(Action::Deny),
+ "ToggleMouseMode" => Ok(Action::ToggleMouseMode),
_ => Err(ConfigError::new_kdl_error(
format!("Unsupported action: {:?}", $action_name),
$action_node.span().offset(),
@@ -653,6 +654,9 @@ impl TryFrom<&KdlNode> for Action {
"UndoRenameTab" => {
parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
},
+ "ToggleMouseMode" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
"Detach" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
"Copy" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
"Confirm" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),