fix(clipboard): clipboard message (#4009)
* fix clipboard message * fix clipboard message gitter * style(fmt): rustfmt
This commit is contained in:
parent
9edad32ee1
commit
f0680fdeb9
8 changed files with 241 additions and 90 deletions
|
|
@ -24,6 +24,8 @@ struct State {
|
||||||
active_tab_idx: usize,
|
active_tab_idx: usize,
|
||||||
mode_info: ModeInfo,
|
mode_info: ModeInfo,
|
||||||
tab_line: Vec<LinePart>,
|
tab_line: Vec<LinePart>,
|
||||||
|
text_copy_destination: Option<CopyDestination>,
|
||||||
|
display_system_clipboard_failure: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
static ARROW_SEPARATOR: &str = "";
|
static ARROW_SEPARATOR: &str = "";
|
||||||
|
|
@ -37,6 +39,9 @@ impl ZellijPlugin for State {
|
||||||
EventType::TabUpdate,
|
EventType::TabUpdate,
|
||||||
EventType::ModeUpdate,
|
EventType::ModeUpdate,
|
||||||
EventType::Mouse,
|
EventType::Mouse,
|
||||||
|
EventType::CopyToClipboard,
|
||||||
|
EventType::InputReceived,
|
||||||
|
EventType::SystemClipboardFailure,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,6 +82,32 @@ impl ZellijPlugin for State {
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
},
|
},
|
||||||
|
Event::CopyToClipboard(copy_destination) => {
|
||||||
|
match self.text_copy_destination {
|
||||||
|
Some(text_copy_destination) => {
|
||||||
|
if text_copy_destination != copy_destination {
|
||||||
|
should_render = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
should_render = true;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
self.text_copy_destination = Some(copy_destination);
|
||||||
|
},
|
||||||
|
Event::SystemClipboardFailure => {
|
||||||
|
should_render = true;
|
||||||
|
self.display_system_clipboard_failure = true;
|
||||||
|
},
|
||||||
|
Event::InputReceived => {
|
||||||
|
if self.text_copy_destination.is_some()
|
||||||
|
|| self.display_system_clipboard_failure == true
|
||||||
|
{
|
||||||
|
should_render = true;
|
||||||
|
}
|
||||||
|
self.text_copy_destination = None;
|
||||||
|
self.display_system_clipboard_failure = false;
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
eprintln!("Got unrecognized event: {:?}", event);
|
eprintln!("Got unrecognized event: {:?}", event);
|
||||||
},
|
},
|
||||||
|
|
@ -85,60 +116,110 @@ impl ZellijPlugin for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, _rows: usize, cols: usize) {
|
fn render(&mut self, _rows: usize, cols: usize) {
|
||||||
if self.tabs.is_empty() {
|
if let Some(copy_destination) = self.text_copy_destination {
|
||||||
return;
|
let hint = text_copied_hint(copy_destination).part;
|
||||||
}
|
|
||||||
let mut all_tabs: Vec<LinePart> = vec![];
|
let background = self.mode_info.style.colors.text_unselected.background;
|
||||||
let mut active_tab_index = 0;
|
match background {
|
||||||
let mut active_swap_layout_name = None;
|
PaletteColor::Rgb((r, g, b)) => {
|
||||||
let mut is_swap_layout_dirty = false;
|
print!("{}\u{1b}[48;2;{};{};{}m\u{1b}[0K", hint, r, g, b);
|
||||||
let mut is_alternate_tab = false;
|
},
|
||||||
for t in &mut self.tabs {
|
PaletteColor::EightBit(color) => {
|
||||||
let mut tabname = t.name.clone();
|
print!("{}\u{1b}[48;5;{}m\u{1b}[0K", hint, color);
|
||||||
if t.active && self.mode_info.mode == InputMode::RenameTab {
|
},
|
||||||
if tabname.is_empty() {
|
|
||||||
tabname = String::from("Enter name...");
|
|
||||||
}
|
|
||||||
active_tab_index = t.position;
|
|
||||||
} else if t.active {
|
|
||||||
active_tab_index = t.position;
|
|
||||||
is_swap_layout_dirty = t.is_swap_layout_dirty;
|
|
||||||
active_swap_layout_name = t.active_swap_layout_name.clone();
|
|
||||||
}
|
}
|
||||||
let tab = tab_style(
|
} else if self.display_system_clipboard_failure {
|
||||||
tabname,
|
let hint = system_clipboard_error().part;
|
||||||
t,
|
let background = self.mode_info.style.colors.text_unselected.background;
|
||||||
is_alternate_tab,
|
match background {
|
||||||
|
PaletteColor::Rgb((r, g, b)) => {
|
||||||
|
print!("{}\u{1b}[48;2;{};{};{}m\u{1b}[0K", hint, r, g, b);
|
||||||
|
},
|
||||||
|
PaletteColor::EightBit(color) => {
|
||||||
|
print!("{}\u{1b}[48;5;{}m\u{1b}[0K", hint, color);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if self.tabs.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut all_tabs: Vec<LinePart> = vec![];
|
||||||
|
let mut active_tab_index = 0;
|
||||||
|
let mut active_swap_layout_name = None;
|
||||||
|
let mut is_swap_layout_dirty = false;
|
||||||
|
let mut is_alternate_tab = false;
|
||||||
|
for t in &mut self.tabs {
|
||||||
|
let mut tabname = t.name.clone();
|
||||||
|
if t.active && self.mode_info.mode == InputMode::RenameTab {
|
||||||
|
if tabname.is_empty() {
|
||||||
|
tabname = String::from("Enter name...");
|
||||||
|
}
|
||||||
|
active_tab_index = t.position;
|
||||||
|
} else if t.active {
|
||||||
|
active_tab_index = t.position;
|
||||||
|
is_swap_layout_dirty = t.is_swap_layout_dirty;
|
||||||
|
active_swap_layout_name = t.active_swap_layout_name.clone();
|
||||||
|
}
|
||||||
|
let tab = tab_style(
|
||||||
|
tabname,
|
||||||
|
t,
|
||||||
|
is_alternate_tab,
|
||||||
|
self.mode_info.style.colors,
|
||||||
|
self.mode_info.capabilities,
|
||||||
|
);
|
||||||
|
is_alternate_tab = !is_alternate_tab;
|
||||||
|
all_tabs.push(tab);
|
||||||
|
}
|
||||||
|
self.tab_line = tab_line(
|
||||||
|
self.mode_info.session_name.as_deref(),
|
||||||
|
all_tabs,
|
||||||
|
active_tab_index,
|
||||||
|
cols.saturating_sub(1),
|
||||||
self.mode_info.style.colors,
|
self.mode_info.style.colors,
|
||||||
self.mode_info.capabilities,
|
self.mode_info.capabilities,
|
||||||
|
self.mode_info.style.hide_session_name,
|
||||||
|
self.mode_info.mode,
|
||||||
|
&active_swap_layout_name,
|
||||||
|
is_swap_layout_dirty,
|
||||||
);
|
);
|
||||||
is_alternate_tab = !is_alternate_tab;
|
let output = self
|
||||||
all_tabs.push(tab);
|
.tab_line
|
||||||
}
|
.iter()
|
||||||
self.tab_line = tab_line(
|
.fold(String::new(), |output, part| output + &part.part);
|
||||||
self.mode_info.session_name.as_deref(),
|
let background = self.mode_info.style.colors.text_unselected.background;
|
||||||
all_tabs,
|
match background {
|
||||||
active_tab_index,
|
PaletteColor::Rgb((r, g, b)) => {
|
||||||
cols.saturating_sub(1),
|
print!("{}\u{1b}[48;2;{};{};{}m\u{1b}[0K", output, r, g, b);
|
||||||
self.mode_info.style.colors,
|
},
|
||||||
self.mode_info.capabilities,
|
PaletteColor::EightBit(color) => {
|
||||||
self.mode_info.style.hide_session_name,
|
print!("{}\u{1b}[48;5;{}m\u{1b}[0K", output, color);
|
||||||
self.mode_info.mode,
|
},
|
||||||
&active_swap_layout_name,
|
}
|
||||||
is_swap_layout_dirty,
|
|
||||||
);
|
|
||||||
let output = self
|
|
||||||
.tab_line
|
|
||||||
.iter()
|
|
||||||
.fold(String::new(), |output, part| output + &part.part);
|
|
||||||
let background = self.mode_info.style.colors.text_unselected.background;
|
|
||||||
match background {
|
|
||||||
PaletteColor::Rgb((r, g, b)) => {
|
|
||||||
print!("{}\u{1b}[48;2;{};{};{}m\u{1b}[0K", output, r, g, b);
|
|
||||||
},
|
|
||||||
PaletteColor::EightBit(color) => {
|
|
||||||
print!("{}\u{1b}[48;5;{}m\u{1b}[0K", output, color);
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn text_copied_hint(copy_destination: CopyDestination) -> LinePart {
|
||||||
|
let hint = match copy_destination {
|
||||||
|
CopyDestination::Command => "Text piped to external command",
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
CopyDestination::Primary => "Text copied to system primary selection",
|
||||||
|
#[cfg(target_os = "macos")] // primary selection does not exist on macos
|
||||||
|
CopyDestination::Primary => "Text copied to system clipboard",
|
||||||
|
CopyDestination::System => "Text copied to system clipboard",
|
||||||
|
};
|
||||||
|
LinePart {
|
||||||
|
part: serialize_text(&Text::new(&hint).color_range(2, ..).opaque()),
|
||||||
|
len: hint.len(),
|
||||||
|
tab_index: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn system_clipboard_error() -> LinePart {
|
||||||
|
let hint = " Error using the system clipboard.";
|
||||||
|
LinePart {
|
||||||
|
part: serialize_text(&Text::new(&hint).color_range(2, ..).opaque()),
|
||||||
|
len: hint.len(),
|
||||||
|
tab_index: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -329,7 +329,7 @@ impl State {
|
||||||
let active_tab = self.tabs.iter().find(|t| t.active);
|
let active_tab = self.tabs.iter().find(|t| t.active);
|
||||||
|
|
||||||
if let Some(copy_destination) = self.text_copy_destination {
|
if let Some(copy_destination) = self.text_copy_destination {
|
||||||
text_copied_hint(&self.mode_info.style.colors, copy_destination)
|
text_copied_hint(copy_destination)
|
||||||
} else if self.display_system_clipboard_failure {
|
} else if self.display_system_clipboard_failure {
|
||||||
system_clipboard_error(&self.mode_info.style.colors)
|
system_clipboard_error(&self.mode_info.style.colors)
|
||||||
} else if let Some(active_tab) = active_tab {
|
} else if let Some(active_tab) = active_tab {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ pub fn one_line_ui(
|
||||||
clipboard_failure: bool,
|
clipboard_failure: bool,
|
||||||
) -> LinePart {
|
) -> LinePart {
|
||||||
if let Some(text_copied_to_clipboard_destination) = text_copied_to_clipboard_destination {
|
if let Some(text_copied_to_clipboard_destination) = text_copied_to_clipboard_destination {
|
||||||
return text_copied_hint(&help.style.colors, text_copied_to_clipboard_destination);
|
return text_copied_hint(text_copied_to_clipboard_destination);
|
||||||
}
|
}
|
||||||
if clipboard_failure {
|
if clipboard_failure {
|
||||||
return system_clipboard_error(&help.style.colors);
|
return system_clipboard_error(&help.style.colors);
|
||||||
|
|
|
||||||
|
|
@ -348,8 +348,7 @@ pub fn keybinds(help: &ModeInfo, tip_name: &str, max_width: usize) -> LinePart {
|
||||||
best_effort_shortcut_list(help, tip_body.short, max_width)
|
best_effort_shortcut_list(help, tip_body.short, max_width)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn text_copied_hint(palette: &Styling, copy_destination: CopyDestination) -> LinePart {
|
pub fn text_copied_hint(copy_destination: CopyDestination) -> LinePart {
|
||||||
let green_color = palette_match!(palette.text_unselected.emphasis_2);
|
|
||||||
let hint = match copy_destination {
|
let hint = match copy_destination {
|
||||||
CopyDestination::Command => "Text piped to external command",
|
CopyDestination::Command => "Text piped to external command",
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
|
@ -359,7 +358,7 @@ pub fn text_copied_hint(palette: &Styling, copy_destination: CopyDestination) ->
|
||||||
CopyDestination::System => "Text copied to system clipboard",
|
CopyDestination::System => "Text copied to system clipboard",
|
||||||
};
|
};
|
||||||
LinePart {
|
LinePart {
|
||||||
part: Style::new().fg(green_color).bold().paint(hint).to_string(),
|
part: serialize_text(&Text::new(&hint).color_range(2, ..).opaque()),
|
||||||
len: hint.len(),
|
len: hint.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,9 @@ pub(crate) fn route_action(
|
||||||
let mut should_break = false;
|
let mut should_break = false;
|
||||||
let err_context = || format!("failed to route action for client {client_id}");
|
let err_context = || format!("failed to route action for client {client_id}");
|
||||||
|
|
||||||
if !action.is_mouse_motion() {
|
if !action.is_mouse_action() {
|
||||||
|
// mouse actions should only send InputReceived to plugins
|
||||||
|
// if they do not result in text being marked, this is handled in Tab
|
||||||
senders
|
senders
|
||||||
.send_to_plugin(PluginInstruction::Update(vec![(
|
.send_to_plugin(PluginInstruction::Update(vec![(
|
||||||
None,
|
None,
|
||||||
|
|
|
||||||
|
|
@ -3858,12 +3858,22 @@ pub(crate) fn screen_thread_main(
|
||||||
screen.unblock_input()?;
|
screen.unblock_input()?;
|
||||||
},
|
},
|
||||||
ScreenInstruction::MouseEvent(event, client_id) => {
|
ScreenInstruction::MouseEvent(event, client_id) => {
|
||||||
let state_changed = screen
|
let mouse_effect = screen
|
||||||
.get_active_tab_mut(client_id)
|
.get_active_tab_mut(client_id)
|
||||||
.and_then(|tab| tab.handle_mouse_event(&event, client_id))?;
|
.and_then(|tab| tab.handle_mouse_event(&event, client_id))?;
|
||||||
if state_changed {
|
if mouse_effect.state_changed {
|
||||||
screen.log_and_report_session_state()?;
|
screen.log_and_report_session_state()?;
|
||||||
}
|
}
|
||||||
|
if !mouse_effect.leave_clipboard_message {
|
||||||
|
let _ = screen
|
||||||
|
.bus
|
||||||
|
.senders
|
||||||
|
.send_to_plugin(PluginInstruction::Update(vec![(
|
||||||
|
None,
|
||||||
|
Some(client_id),
|
||||||
|
Event::InputReceived,
|
||||||
|
)]));
|
||||||
|
}
|
||||||
screen.render(None)?;
|
screen.render(None)?;
|
||||||
},
|
},
|
||||||
ScreenInstruction::Copy(client_id) => {
|
ScreenInstruction::Copy(client_id) => {
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,33 @@ enum BufferedTabInstruction {
|
||||||
HoldPane(PaneId, Option<i32>, bool, RunCommand), // Option<i32> is the exit status, bool is is_first_run
|
HoldPane(PaneId, Option<i32>, bool, RunCommand), // Option<i32> is the exit status, bool is is_first_run
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct MouseEffect {
|
||||||
|
pub state_changed: bool,
|
||||||
|
pub leave_clipboard_message: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MouseEffect {
|
||||||
|
pub fn state_changed() -> Self {
|
||||||
|
MouseEffect {
|
||||||
|
state_changed: true,
|
||||||
|
leave_clipboard_message: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn leave_clipboard_message() -> Self {
|
||||||
|
MouseEffect {
|
||||||
|
state_changed: false,
|
||||||
|
leave_clipboard_message: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn state_changed_and_leave_clipboard_message() -> Self {
|
||||||
|
MouseEffect {
|
||||||
|
state_changed: true,
|
||||||
|
leave_clipboard_message: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct Tab {
|
pub(crate) struct Tab {
|
||||||
pub index: usize,
|
pub index: usize,
|
||||||
pub position: usize,
|
pub position: usize,
|
||||||
|
|
@ -3225,7 +3252,7 @@ impl Tab {
|
||||||
point: &Position,
|
point: &Position,
|
||||||
lines: usize,
|
lines: usize,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
) -> Result<bool> {
|
) -> Result<MouseEffect> {
|
||||||
let err_context = || {
|
let err_context = || {
|
||||||
format!("failed to handle scrollwheel up at position {point:?} for client {client_id}")
|
format!("failed to handle scrollwheel up at position {point:?} for client {client_id}")
|
||||||
};
|
};
|
||||||
|
|
@ -3246,7 +3273,7 @@ impl Tab {
|
||||||
pane.scroll_up(lines, client_id);
|
pane.scroll_up(lines, client_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(false)
|
Ok(MouseEffect::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_scrollwheel_down(
|
pub fn handle_scrollwheel_down(
|
||||||
|
|
@ -3254,7 +3281,7 @@ impl Tab {
|
||||||
point: &Position,
|
point: &Position,
|
||||||
lines: usize,
|
lines: usize,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
) -> Result<bool> {
|
) -> Result<MouseEffect> {
|
||||||
let err_context = || {
|
let err_context = || {
|
||||||
format!(
|
format!(
|
||||||
"failed to handle scrollwheel down at position {point:?} for client {client_id}"
|
"failed to handle scrollwheel down at position {point:?} for client {client_id}"
|
||||||
|
|
@ -3283,7 +3310,7 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(false)
|
Ok(MouseEffect::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pane_at(
|
fn get_pane_at(
|
||||||
|
|
@ -3353,7 +3380,11 @@ impl Tab {
|
||||||
|
|
||||||
// returns true if the mouse event caused some sort of tab/pane state change that needs to be
|
// returns true if the mouse event caused some sort of tab/pane state change that needs to be
|
||||||
// reported to plugins
|
// reported to plugins
|
||||||
pub fn handle_mouse_event(&mut self, event: &MouseEvent, client_id: ClientId) -> Result<bool> {
|
pub fn handle_mouse_event(
|
||||||
|
&mut self,
|
||||||
|
event: &MouseEvent,
|
||||||
|
client_id: ClientId,
|
||||||
|
) -> Result<MouseEffect> {
|
||||||
let err_context =
|
let err_context =
|
||||||
|| format!("failed to handle mouse event {event:?} for client {client_id}");
|
|| format!("failed to handle mouse event {event:?} for client {client_id}");
|
||||||
|
|
||||||
|
|
@ -3423,7 +3454,7 @@ impl Tab {
|
||||||
&mut self,
|
&mut self,
|
||||||
event: &MouseEvent,
|
event: &MouseEvent,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
) -> Result<bool> {
|
) -> Result<MouseEffect> {
|
||||||
let err_context =
|
let err_context =
|
||||||
|| format!("failed to handle mouse event {event:?} for client {client_id}");
|
|| format!("failed to handle mouse event {event:?} for client {client_id}");
|
||||||
let floating_panes_are_visible = self.floating_panes.panes_are_visible();
|
let floating_panes_are_visible = self.floating_panes.panes_are_visible();
|
||||||
|
|
@ -3436,7 +3467,7 @@ impl Tab {
|
||||||
let intercepted = pane_at_position.intercept_mouse_event_on_frame(&event, client_id);
|
let intercepted = pane_at_position.intercept_mouse_event_on_frame(&event, client_id);
|
||||||
if intercepted {
|
if intercepted {
|
||||||
self.set_force_render();
|
self.set_force_render();
|
||||||
return Ok(true);
|
return Ok(MouseEffect::state_changed());
|
||||||
} else if floating_panes_are_visible {
|
} else if floating_panes_are_visible {
|
||||||
// start moving if floating pane
|
// start moving if floating pane
|
||||||
let search_selectable = false;
|
let search_selectable = false;
|
||||||
|
|
@ -3446,7 +3477,7 @@ impl Tab {
|
||||||
{
|
{
|
||||||
self.swap_layouts.set_is_floating_damaged();
|
self.swap_layouts.set_is_floating_damaged();
|
||||||
self.set_force_render();
|
self.set_force_render();
|
||||||
return Ok(true);
|
return Ok(MouseEffect::state_changed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -3466,19 +3497,26 @@ impl Tab {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// start selection for copy/paste
|
// start selection for copy/paste
|
||||||
|
let mut leave_clipboard_message = false;
|
||||||
pane_at_position.start_selection(&relative_position, client_id);
|
pane_at_position.start_selection(&relative_position, client_id);
|
||||||
|
if pane_at_position.get_selected_text().is_some() {
|
||||||
|
leave_clipboard_message = true;
|
||||||
|
}
|
||||||
if let PaneId::Terminal(_) = pane_at_position.pid() {
|
if let PaneId::Terminal(_) = pane_at_position.pid() {
|
||||||
self.selecting_with_mouse_in_pane = Some(pane_at_position.pid());
|
self.selecting_with_mouse_in_pane = Some(pane_at_position.pid());
|
||||||
}
|
}
|
||||||
|
if leave_clipboard_message {
|
||||||
|
return Ok(MouseEffect::leave_clipboard_message());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(false)
|
Ok(MouseEffect::default())
|
||||||
}
|
}
|
||||||
fn handle_inactive_pane_left_mouse_press(
|
fn handle_inactive_pane_left_mouse_press(
|
||||||
&mut self,
|
&mut self,
|
||||||
event: &MouseEvent,
|
event: &MouseEvent,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
) -> Result<bool> {
|
) -> Result<MouseEffect> {
|
||||||
let err_context =
|
let err_context =
|
||||||
|| format!("failed to handle mouse event {event:?} for client {client_id}");
|
|| format!("failed to handle mouse event {event:?} for client {client_id}");
|
||||||
if !self.floating_panes.panes_are_visible() {
|
if !self.floating_panes.panes_are_visible() {
|
||||||
|
|
@ -3492,7 +3530,7 @@ impl Tab {
|
||||||
// focus it
|
// focus it
|
||||||
self.show_floating_panes();
|
self.show_floating_panes();
|
||||||
self.floating_panes.focus_pane(pane_id, client_id);
|
self.floating_panes.focus_pane(pane_id, client_id);
|
||||||
return Ok(true);
|
return Ok(MouseEffect::state_changed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let active_pane_id_before_click = self
|
let active_pane_id_before_click = self
|
||||||
|
|
@ -3514,25 +3552,30 @@ impl Tab {
|
||||||
// we do this because this might be the beginning of the user dragging a pane
|
// we do this because this might be the beginning of the user dragging a pane
|
||||||
// that was not focused
|
// that was not focused
|
||||||
// TODO: rename move_pane_with_mouse to "start_moving_pane_with_mouse"?
|
// TODO: rename move_pane_with_mouse to "start_moving_pane_with_mouse"?
|
||||||
return Ok(self
|
let moved_pane_with_mouse = self
|
||||||
.floating_panes
|
.floating_panes
|
||||||
.move_pane_with_mouse(event.position, search_selectable));
|
.move_pane_with_mouse(event.position, search_selectable);
|
||||||
|
if moved_pane_with_mouse {
|
||||||
|
return Ok(MouseEffect::state_changed());
|
||||||
|
} else {
|
||||||
|
return Ok(MouseEffect::default());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let active_pane_id_after_click = self
|
let active_pane_id_after_click = self
|
||||||
.get_active_pane_id(client_id)
|
.get_active_pane_id(client_id)
|
||||||
.ok_or_else(|| anyhow!("Failed to find pane at position"))?;
|
.ok_or_else(|| anyhow!("Failed to find pane at position"))?;
|
||||||
if active_pane_id_before_click != active_pane_id_after_click {
|
if active_pane_id_before_click != active_pane_id_after_click {
|
||||||
// focus changed, need to report it
|
// focus changed, need to report it
|
||||||
Ok(true)
|
Ok(MouseEffect::state_changed())
|
||||||
} else {
|
} else {
|
||||||
Ok(false)
|
Ok(MouseEffect::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn handle_left_mouse_motion(
|
fn handle_left_mouse_motion(
|
||||||
&mut self,
|
&mut self,
|
||||||
event: &MouseEvent,
|
event: &MouseEvent,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
) -> Result<bool> {
|
) -> Result<MouseEffect> {
|
||||||
let err_context =
|
let err_context =
|
||||||
|| format!("failed to handle mouse event {event:?} for client {client_id}");
|
|| format!("failed to handle mouse event {event:?} for client {client_id}");
|
||||||
let pane_is_being_moved_with_mouse = self.floating_panes.pane_is_being_moved_with_mouse();
|
let pane_is_being_moved_with_mouse = self.floating_panes.pane_is_being_moved_with_mouse();
|
||||||
|
|
@ -3547,7 +3590,7 @@ impl Tab {
|
||||||
{
|
{
|
||||||
self.swap_layouts.set_is_floating_damaged();
|
self.swap_layouts.set_is_floating_damaged();
|
||||||
self.set_force_render();
|
self.set_force_render();
|
||||||
return Ok(true);
|
return Ok(MouseEffect::state_changed());
|
||||||
}
|
}
|
||||||
} else if let Some(pane_id_with_selection) = self.selecting_with_mouse_in_pane {
|
} else if let Some(pane_id_with_selection) = self.selecting_with_mouse_in_pane {
|
||||||
if let Some(pane_with_selection) = self.get_pane_with_id_mut(pane_id_with_selection) {
|
if let Some(pane_with_selection) = self.get_pane_with_id_mut(pane_id_with_selection) {
|
||||||
|
|
@ -3563,15 +3606,16 @@ impl Tab {
|
||||||
self.write_mouse_event_to_active_pane(event, client_id)?;
|
self.write_mouse_event_to_active_pane(event, client_id)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(false)
|
Ok(MouseEffect::default())
|
||||||
}
|
}
|
||||||
fn handle_left_mouse_release(
|
fn handle_left_mouse_release(
|
||||||
&mut self,
|
&mut self,
|
||||||
event: &MouseEvent,
|
event: &MouseEvent,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
) -> Result<bool> {
|
) -> Result<MouseEffect> {
|
||||||
let err_context =
|
let err_context =
|
||||||
|| format!("failed to handle mouse event {event:?} for client {client_id}");
|
|| format!("failed to handle mouse event {event:?} for client {client_id}");
|
||||||
|
let mut leave_clipboard_message = false;
|
||||||
let floating_panes_are_visible = self.floating_panes.panes_are_visible();
|
let floating_panes_are_visible = self.floating_panes.panes_are_visible();
|
||||||
let copy_on_release = self.copy_on_select;
|
let copy_on_release = self.copy_on_select;
|
||||||
|
|
||||||
|
|
@ -3606,6 +3650,7 @@ impl Tab {
|
||||||
let selected_text = pane_with_selection.get_selected_text();
|
let selected_text = pane_with_selection.get_selected_text();
|
||||||
|
|
||||||
if let Some(selected_text) = selected_text {
|
if let Some(selected_text) = selected_text {
|
||||||
|
leave_clipboard_message = true;
|
||||||
self.write_selection_to_clipboard(&selected_text)
|
self.write_selection_to_clipboard(&selected_text)
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
}
|
}
|
||||||
|
|
@ -3621,10 +3666,18 @@ impl Tab {
|
||||||
} else {
|
} else {
|
||||||
self.write_mouse_event_to_active_pane(event, client_id)?;
|
self.write_mouse_event_to_active_pane(event, client_id)?;
|
||||||
}
|
}
|
||||||
Ok(false)
|
if leave_clipboard_message {
|
||||||
|
Ok(MouseEffect::leave_clipboard_message())
|
||||||
|
} else {
|
||||||
|
Ok(MouseEffect::default())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_right_click(&mut self, event: &MouseEvent, client_id: ClientId) -> Result<bool> {
|
pub fn handle_right_click(
|
||||||
|
&mut self,
|
||||||
|
event: &MouseEvent,
|
||||||
|
client_id: ClientId,
|
||||||
|
) -> Result<MouseEffect> {
|
||||||
let err_context = || format!("failed to handle mouse right click for client {client_id}");
|
let err_context = || format!("failed to handle mouse right click for client {client_id}");
|
||||||
|
|
||||||
let absolute_position = event.position;
|
let absolute_position = event.position;
|
||||||
|
|
@ -3655,10 +3708,14 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(false)
|
Ok(MouseEffect::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_middle_click(&mut self, event: &MouseEvent, client_id: ClientId) -> Result<bool> {
|
fn handle_middle_click(
|
||||||
|
&mut self,
|
||||||
|
event: &MouseEvent,
|
||||||
|
client_id: ClientId,
|
||||||
|
) -> Result<MouseEffect> {
|
||||||
let err_context = || format!("failed to handle mouse middle click for client {client_id}");
|
let err_context = || format!("failed to handle mouse middle click for client {client_id}");
|
||||||
let absolute_position = event.position;
|
let absolute_position = event.position;
|
||||||
|
|
||||||
|
|
@ -3687,10 +3744,14 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(false)
|
Ok(MouseEffect::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mouse_no_click(&mut self, event: &MouseEvent, client_id: ClientId) -> Result<bool> {
|
fn handle_mouse_no_click(
|
||||||
|
&mut self,
|
||||||
|
event: &MouseEvent,
|
||||||
|
client_id: ClientId,
|
||||||
|
) -> Result<MouseEffect> {
|
||||||
let err_context = || format!("failed to handle mouse no click for client {client_id}");
|
let err_context = || format!("failed to handle mouse no click for client {client_id}");
|
||||||
let absolute_position = event.position;
|
let absolute_position = event.position;
|
||||||
|
|
||||||
|
|
@ -3719,7 +3780,7 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(false)
|
Ok(MouseEffect::leave_clipboard_message())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unselectable_pane_at_position(&mut self, point: &Position) -> Option<&mut Box<dyn Pane>> {
|
fn unselectable_pane_at_position(&mut self, point: &Position) -> Option<&mut Box<dyn Pane>> {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use crate::data::{Direction, KeyWithModifier, PaneId, Resize};
|
||||||
use crate::data::{FloatingPaneCoordinates, InputMode};
|
use crate::data::{FloatingPaneCoordinates, InputMode};
|
||||||
use crate::home::{find_default_config_dir, get_layout_dir};
|
use crate::home::{find_default_config_dir, get_layout_dir};
|
||||||
use crate::input::config::{Config, ConfigError, KdlError};
|
use crate::input::config::{Config, ConfigError, KdlError};
|
||||||
use crate::input::mouse::{MouseEvent, MouseEventType};
|
use crate::input::mouse::MouseEvent;
|
||||||
use crate::input::options::OnForceClose;
|
use crate::input::options::OnForceClose;
|
||||||
use miette::{NamedSource, Report};
|
use miette::{NamedSource, Report};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
@ -800,11 +800,9 @@ impl Action {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn is_mouse_motion(&self) -> bool {
|
pub fn is_mouse_action(&self) -> bool {
|
||||||
if let Action::MouseEvent(mouse_event) = self {
|
if let Action::MouseEvent(_mouse_event) = self {
|
||||||
if let MouseEventType::Motion = mouse_event.event_type {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue