Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Float Pane #5576

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft

Float Pane #5576

wants to merge 22 commits into from

Conversation

e82eric
Copy link

@e82eric e82eric commented Jun 17, 2024

Hi, I wanted to make an attempt at #270

This probably needs quite a bit of iteration (this is my first attempt at rust), but wanted to create the pull request to see if this is something you would be open to adding and to see if I am on the right track.

float_pane

@e82eric e82eric force-pushed the float-pane branch 3 times, most recently from 9bd3c95 to 03eabc7 Compare June 23, 2024 16:38
@derekthecool
Copy link
Contributor

Nice work! Demo video looks good.

@mathjiajia
Copy link

it would be nice to have a border for this floating pane

@e82eric
Copy link
Author

e82eric commented Jul 3, 2024

Updated with border.

float_pane_with_border2

Configs:

config.float_pane_padding = {
  left = '10%',
  right = '10%',
  top = '10%',
  bottom = '10%',
}
config.float_pane_border = {
  left_width = '0.5cell',
  right_width = '0.5cell',
  bottom_height = '0.25cell',
  top_height = '0.25cell',
  left_color = '#665c54',
  right_color = '#665c54',
  bottom_color = '#665c54',
  top_color = '#665c54',
}

@e82eric
Copy link
Author

e82eric commented Jul 6, 2024

I think this is ready to be reviewed now.

@Pajn
Copy link

Pajn commented Jul 13, 2024

Thanks a lot, this is the one feature I've been missing since transition from tmux to wezterm mux 🙏🏼

Tested this and it works really well, just commenting with some small issues I've seen:

  • The float panes all open in my home directory instead of the current directory like split panes and new tabs do
  • The pane selection UI is hard to read if having no split panes and one floating since the underlying pane and the float panes letter overlaps
  • If moving all non floating panes to a new tab or window the floating pane is shown on an otherwise invisible window, would be nice to either disallow this or de-float the floating pane

Screenshot from 2024-07-13 10-26-29
Screenshot from 2024-07-13 10-26-51

A very nice action to have but definitely not required for this to be super useful on its own, is to be able to toggle the floating status of a pane so you can transition a floating pane to a split pane and vice verse.

@e82eric
Copy link
Author

e82eric commented Jul 14, 2024

@Pajn I think I have the working directory issue fixed now.

For the pane selection my intention was to treat the float like a overlay and turn any selection operations into no-ops and prevent the mouse from selecting a pane (I think there were some scenarios that I missed like the selection UI). I pushed an update that I think turn those into nops now. This may not be the right strategy, is there a scenario where you would want to be able to select/interact with the panes underneath the float?

I think I have it updated so that closing the pane underneath the float is blocked now. Which I think will prevent the scenario where only the float is showing.

I tried out being able to move the float to a split today. It seemed to work, I pushed it to this branch if you want to give it a try. I didn't want to include it in this pull request to keep the scope down.
https://github.com/e82eric/wezterm/tree/move-float-to-split

This is what it looked like.
move_float_to_split

@Pajn
Copy link

Pajn commented Jul 14, 2024

Wow! I was just starting to familiarize myself with the code to see if I could help but not at that speed :)
Very quick testing have all the issues I experienced fixed.

This may not be the right strategy, is there a scenario where you would want to be able to select/interact with the panes underneath the float?

I was mostly just trying to break it to see where the limitations where. The one possible usecase I can see is to move one background pane to another tab/window if you need access to it after realizing the float pane was longer lived than you intended. However I think that's better solved by being able to transition the float pane to a split anyway. And disabling those actions when in a float definitely avoids a whole class of potential problems.

I didn't want to include it in this pull request to keep the scope down.

Totes! I was just excited. Thanks a lot for the branch though, will definitely start playing with it.
And if there is anything I can do to help get this merged, let me know.

@Suri312006
Copy link

i really like the work man, good stuff been wanting this feature, as im coming from zellij that has a really nice implementation of floating panes

@e82eric
Copy link
Author

e82eric commented Aug 9, 2024

Thanks! updated

@dev-lop36
Copy link

What is the status of this PR? Really great feature&work btw!

@e82eric
Copy link
Author

e82eric commented Sep 18, 2024

Thanks! I think this is more or less still pending review. I am happy to put in the work to get this across the the finish line, but don't want bug Wez about it, I am sure he has a million priorities. In the mean time if anyone wants to give it a try and notice any issues or want to review the code, I can work through those.

Copy link
Owner

@wez wez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many thanks for diving into this, and doing so deeply!

I haven't had the bandwidth to look at this in a great deal of detail, just skimmed here on GH without trying to run it, but have a few comments/suggestions.

There are a number of places with TODOs and comments about refactoring to reduce duplication: I would like to avoid having duplicate or almost identical code for the floating pane stuff, so I would appreciate seeing that tackled before we get to merging this.

I think there are perhaps some other bigger picture or weird edge-case questions around this that I think it would be good to have answers for; there may be more of these in the long run, but these are the ones more or less off of the top of my head:

  • How does and how should the floating pane be reflected in wezterm cli list?
  • If you create a floating pane against a multiplexer and detach, does re-attaching preserve the float?
  • If you have one wezterm connected to a mux, then attach a second wezterm instance to that same mux and spawn a float in one, does the float instantly appear in the other one?
  • How does the scrollbar UI/UX work with the floating pane? I'm OK if "it doesn't" is the answer if we document that it doesn't, and ensure that it is well-behaved.
  • Are there any special gotchas when it comes to using the floating pane?
  • Is it necessary to add an explicit kill-floating-pane action, or are the existing actions sufficient?
  • How does the floating pane get exposed to the various window/tab styling events in lua, and is it likely to cause problems with existing setups?

mux/src/tab.rs Outdated
@@ -1861,6 +1945,42 @@ impl TabInner {
None
}

fn get_float_size(&self) -> TerminalSize {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me, get_float_size implies getting the size of the current float, but this is computing the desired size, so I think it should be renamed to make it more clear

Suggested change
fn get_float_size(&self) -> TerminalSize {
fn compute_float_size(&self) -> TerminalSize {

mux/src/tab.rs Outdated
Comment on lines 2089 to 2093
{
pane.resize(float_size)?;
}

Ok(())
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{
pane.resize(float_size)?;
}
Ok(())
pane.resize(float_size)?;
Ok(())

domain: SpawnTabDomain::CurrentPaneDomain,
..
}) => CommandDef {
brief: label_string(action, "Create a float pane".to_string()).into(),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
brief: label_string(action, "Create a float pane".to_string()).into(),
brief: label_string(action, "Create a floating pane".to_string()).into(),

..
}) => CommandDef {
brief: label_string(action, "Create a float pane".to_string()).into(),
doc: "Create a float pane"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
doc: "Create a float pane"
doc: "Create a floating pane"

@@ -1501,6 +1518,15 @@ pub fn derive_command_from_key_assignment(action: &KeyAssignment) -> Option<Comm
menubar: &[],
icon: Some("cod_split_vertical"),
},
FloatPane(_) => CommandDef {
brief: label_string(action, "Create a float pane".to_string()).into(),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
brief: label_string(action, "Create a float pane".to_string()).into(),
brief: label_string(action, "Create a floating pane".to_string()).into(),

@@ -1501,6 +1518,15 @@ pub fn derive_command_from_key_assignment(action: &KeyAssignment) -> Option<Comm
menubar: &[],
icon: Some("cod_split_vertical"),
},
FloatPane(_) => CommandDef {
brief: label_string(action, "Create a float pane".to_string()).into(),
doc: "Create a float pane"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
doc: "Create a float pane"
doc: "Create a floating pane"

Comment on lines 544 to 547
if let Some(pane) = self.get_active_pane_or_overlay() {
pane.focus_changed(focused);
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing this logic is probably a regression?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reverted. (sorry, I should have caught this).

&& position.row as usize >= float_pane.top && position.row as usize <= float_pane.top + float_pane.height {
vec![float_pane]
} else {
return
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this return prevent mouse handling from working in the other panes when a float is present?
Is that intentional? If so, please add a comment around this block to explain this, as it isn't clear from the code.

Also, I prefer an early return style to avoid lots of nested blocks, something like this:

let mouse_in_float = position.column >= float_pane.left && 
    position.column <= float_pane.left + float_pane.width &&
    position.row as usize >= float_pane.top &&
    position.row as usize <= float_pane.top + float_pane.height;

if !mouse_in_float {
  // Mouse events are not dispatched to the other panes when
  // a floating pane is active, because REASON
  return;
}
vec![float_pane]

name = "float-pane",
rename_all = "kebab",
trailing_var_arg = true,
about = "spawn a float pane"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
about = "spawn a float pane"
about = "spawn a floating pane"


#[derive(Debug, Parser, Clone)]
pub struct FloatPane {
/// Specify the pane that should be split.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment doesn't seem to fit the action

@e82eric
Copy link
Author

e82eric commented Sep 22, 2024

Thanks Wez! I pushed a commit to address the initial feedback.

I think the multiplexing, scrollbar and lua events are probably all gaps. Will start working through those and will @ you when I get through them. Marking the PR as draft until I get through them.

@e82eric e82eric marked this pull request as draft September 22, 2024 00:42
Open questions
- Is (PaneNode, PaneNode) ok? Or should it be a type?
  - I think the tuple matches what Zellij has.
- Does the output need anything to indicate that the pane is a float?
  - I don't think Zellij supports list panes (It looked like there is a
    PR)
  - It looked like tmux popups are not persistent so I don't think it is
    applicable here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants