cockpit-project / cockpit

Cockpit is a web-based graphical interface for servers.

Home Page:http://www.cockpit-project.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Terminal: Provide way to input Ctrl+W

Subnet-Masked opened this issue · comments

Cockpit version: 225
OS: Windows 10
Page: Terminal

When using the terminal, trying to use CTRL + W pops up a window asking if I am sure I want to close the tab and does not pass the keystroke into the terminal.

Steps to reproduce

  1. Open the terminal page in Cockpit.
  2. Load up a CLI application that requires CTRL + W (Nano in my case)
  3. Attempt to use CTRL + W

From testing, this applies to Chrome and Firefox.

Update: This also applies to other keystrokes such as CTRL + K and likely more

Technically, the ctrl+w isn't closing the tab (default behavior), but getting caught so that a native dialog gets in the way to prevent the tab from being closed via beforeUnload. Same applies to several other browser keystrokes.

@marusak: FWIW, I wrote a lot about this topic three years ago in #7956.

The result was implementing the beforeUnload event in https://github.com/cockpit-project/cockpit/pull/7985/files#diff-69d5f18370238cd010ba0c0230bcd1b3R171-R179

I suggested workarounds in the thread in the first link in this comment. Some options were sticky keys (usually an accessibility feature), chording with alt (and stripping out alt when it is sent), and so on. We could use one or more of these methods as work-arounds.

The big problem is that we're in a browser and browsers eat certain keypresses. Only some of them can be overridden. Many cannot. (Here's a list of common shortcuts: https://unboxhow.com/list-of-common-keyboard-shortcuts-that-work-in-all-web-browsers)

Once upon a time, over a decade ago, I did make a web-based terminal that proxied commands through a connector based on a Java applet and then, later, Flash to get around these restrictions. (Or was it Flash first, then Java? It doesn't matter though, both have been deprecated and are no longer possible to use.) I don't think there's a similar workaround these days.

I wonder if there might be a way to add a button on the terminal window in the browser, similar to how Android apps add a CTRL button via an option in terminal apps?

So, at the top of the window, maybe you click a button "hold CTRL" and then press your key. Then pass the fake CTRL + [key] into the terminal?

See mock up image

Screenshot_2020-09-10 Terminal - cody capston

If I understand it correctly: That's similar to the sticky keys solution, but only works for control, and I guess is a 1-time toggle (so you have to switch to the mouse, click it, then switch back to the keyboard for your key combo)?


"Sticky Keys" is an accessibility feature of most OSes (some Linux desktops, like GNOME have this; macOS and Windows also have it). But it should work here as well.

From WikiPedia @ https://en.wikipedia.org/wiki/Sticky_keys:

Sticky keys is an accessibility feature of some graphical user interfaces to assist users who have physical disabilities or help users reduce repetitive strain injury (or a syndrome called the Emacs Pinky). It serializes keystrokes instead of pressing multiple keys at a time, allowing the user to press and release a modifier key, such as Shift, Ctrl, Alt, or the Windows key, and have it remain active until any other key is pressed.

For general sticky keys support, there should be:

  1. a UI toggle to enable it (on the right side of the terminal bar?)
  2. a status on what modifier keys are currently being "pressed" (on the left side of the terminal bar, as PF4 labels/badges?)

Additionally, there should be:

  • auto-cancellation on a successful keystroke (so pressing chords still works as expected)
  • toggling the keypress off (hitting control a second time would disable it)

The main idea is that you can use the keyboard for all of the input, instead of having to switch to the mouse and back to the keyboard for some of the keypresses.

If you do (out of habit) hit control-w or one of the other reserved keypresses, you could tap control, a status indicator shows up that you're pressing ctrl, and then you tap w.

and I guess is a 1-time toggle (so you have to switch to the mouse, click it, then switch back to the keyboard for your key combo)?

Yes, Not necessarily a great solution but an idea...

I tried using sticky keys on my Gnome desktop at home and win10 at work, but both still resulted in the browser catching the keystroke and it not getting into the web terminal.

Maybe there is an obvious way that I am missing here though. My thought with the "Hold CTRL" button is that it would allow you to completely avoid passing CTRL + [key] through the browser and instead using the button and letting the JS (Or otherwise) catch the next key you press, then send the CTRL + [key] using the Javascript instead, thus avoiding conflicting keystrokes in the browser itself.

For general sticky keys support, there should be:

  1. a UI toggle to enable it (on the right side of the terminal bar?)
  2. a status on what modifier keys are currently being "pressed" (on the left side of the terminal bar, as PF4 labels/badges?)

Additionally, there should be:

  • auto-cancellation on a successful keystroke (so pressing chords still works as expected)
  • toggling the keypress off (hitting control a second time would disable it)

You nailed it with this.

The main idea is that you can use the keyboard for all of the input, instead of having to switch to the mouse and back to the keyboard for some of the keypresses.

If you do (out of habit) hit control-w or one of the other reserved keypresses, you could tap control, a status indicator shows up that you're pressing ctrl, and then you tap w.

I do really like this idea, tapping control instead of holding it, if that is possible to catch in a browser that would be a much preferred solution over the button!

Is anyone working on this? We still wait till we decide what solution we want?

Is anyone working on this?

Not to my knowledge. But I don't like the 'click on the button to hold key'. It is barely usable. I would look through https://xtermjs.org/docs/ to see if there is no better way. For example https://xtermjs.org/docs/api/terminal/classes/terminal/#attachcustomkeyeventhandler might help us. But as mentioned above, not all keys combinations can be caught, some never reach us as browser keeps them for itself. I think we might go with ctrl+shift+ instead of ctrl+. But really no good ideas here.
When we go with button that is keyboard toggable, then it should be easily discoverable how it works.

I don't like the 'click on the button to hold key'.

Me neither. However I do like the tap ctrl then tap key approach as that could even work with hold ctrl and tap key for key combinations that aren't blocked by the browser.

I don't like the ctrl+shift+ as that will get blocked as well since browsers (generally) use it for enhanced functionaly. Eg. ctrl+shift+t opens previously closed tab, ctrl+shift+w closes the browser (firefox at least, not sure about others) itself.

Another idea is to use alt/alt gr instead of ctrl (or alt instead of shift in the ctrl+shift+ approach, but that might invoke OS functions instead)

I think we might go with ctrl+shift+ instead of ctrl+

That was what I was originally going to suggest before I went off trying to find another solution, but, in Chrome at least, ctrl+shift+ still does the same as ctrl+ in a lot of cases, such as crtl+shift+w as @DejfCold mentioned...

Another idea is to use alt/alt gr instead of ctrl (or alt instead of shift in the ctrl+shift+ approach, but that might invoke OS functions instead)

I can confirm that my system catches a lot of ctrl+alt+ as system commands... Not sure if Windows or Mac do this though.

alt/alt gr instead of ctrl

Which doesn't on many keyboards, including ANSI (EN-US) keyboards.

As mentioned before, I've researched all the solutions and the only one that really works as transparently as possible (without a plugin-based approach, which wouldn't be supported now in browsers anyway) is to use a form of Sticky Keys, as I suggested above.

More detail on how Sticky Keys could be implemented

We'd need to use keydown and keyup events:

With the sticky keys feature on:

  1. On keydown, push the keypress to a stack.
  2. On keyup, if the stack only contains modifier key(s), then toggle the sticky state. (This is tapping the key without holding it plus anything else.)
  3. If sticky state is on: Next keydown should have preventDefault() and should send modifier(s) + keydown instead.
  4. Toggle sticky state off and clear the stack.

This should transparently handle chords and not be noticed unless someone taps modifier keys.

We should probably consider having this on by default.

Note: keydown & keyup handle taps of modifier keys, whereas keypress and other key related JS does not (and are deprecated anyway).

Not to interfere with the research / implementation, but one more (maybe drastic) way would be to run Cockpit in a dedicated window (at least using Chrome). Quoting FAQ from Chrome extension called Secure Shell:

https://chromium.googlesource.com/apps/libapps/+/HEAD/nassh/doc/FAQ.md#how-do-i-send-ctrl_w_ctrl_n-or-ctrl_t-to-the-terminal

How do I send Ctrl+W, Ctrl+N or Ctrl+T to the terminal?

Chrome blocks tab contents from getting access to these (and a few other) shortcuts. You can open Secure Shell in a dedicated window to get around this limitation. The exact method depends on a few factors.

If you're running the app (not the extension), right-click on the Secure Shell icon and enable “Open as Window”. After that, any time you launch Secure Shell it will open in a new window and handle these directly.

This is what I get if I run this app/extension:
image

And it indeed catches the Ctrl-W here.

Not sure if the regular page can summon such browser window.
Also not sure if such feature is available on Firefox.

Keyboard shortcuts also work in Cockpit Client, the desktop app on Flathub. https://flathub.org/apps/details/org.cockpit_project.CockpitClient (It's for Linux only, as it has parts of Cockpit embedded within and uses ssh to contact remote hosts that have Cockpit installed.)

It's definitely a problem with browsers themselves handling the keyboard shortcuts.

There's not really a way to solve this without a lot of hacky workarounds on Windows and macOS. (For Linux, there's our official app on Flathub.) As for workarounds that we could use in-browser, I've detailed them above.

There's really not much more that we can do, aside from implement what I suggested.