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

cannot map <A-...> on macos #579

Closed
zgpio opened this issue Sep 1, 2019 · 10 comments
Closed

cannot map <A-...> on macos #579

zgpio opened this issue Sep 1, 2019 · 10 comments

Comments

@zgpio
Copy link

zgpio commented Sep 1, 2019

Environment

  • os: macos 10.14
  • nvim-qt version: 5979623
  • nvim version: v0.4.0-1860-g0ec80d5f6

Reproduce Step

  1. /Applications/nvim-qt.app/Contents/MacOS/nvim-qt -- -u NONE
  2. :map <A-k> :echo "hello"<CR>
  3. try to input <A-k>

By the way, I found <c-a-k> can be mapped.

@zgpio
Copy link
Author

zgpio commented Sep 1, 2019

#510 (comment) He also mentioned such problems.

@zgpio
Copy link
Author

zgpio commented Sep 3, 2019

I found that was internally converted to <A- ̊>.

@justinmk
Copy link
Contributor

justinmk commented Sep 3, 2019

I found that was internally converted to <A- ̊>.

That is the macOS default behavior. Though I would expect Qt to give nvim-qt the proper flags, and then nvim-qt just composes a <A-x> string as usual, rather than the default macOS behavior.

@jgehrig
Copy link
Collaborator

jgehrig commented Dec 14, 2019

This is interesting behavior from MacOS... From my tests, nvim behaves the same way.

From qDebug() statements injected into shell.cpp:

QKeyEvent: QKeyEvent(KeyPress, Key_K, AltModifier, text="˚")
  convertKey: "<A-˚>"
QKeyEvent: QKeyEvent(KeyPress, Key_K, text="k")
  convertKey: "k"
QKeyEvent: QKeyEvent(KeyPress, Key_S, AltModifier, text="ß")
  convertKey: "<A-ß>"

The input is handled this way because MacOS generates ˚, and Qt passes this along in text to our input layer.

I'm not sure it is possible to handle this case. How can we identify the user's intent as ˚ or <A-k>?

You could change the keyboard layout to Unicode Hex Input:
https://apple.stackexchange.com/a/350065

However, even with the alternate layout MacOS still generates odd key events

MacOS:
  QKeyEvent: QKeyEvent(KeyPress, Key_K)
    convertKey: ""

Linux:
  QKeyEvent: QKeyEvent(KeyPress, Key_K, AltModifier, text="k")
    convertKey: "<A-k>"

@jgehrig
Copy link
Collaborator

jgehrig commented Dec 28, 2019

@mikew Moving the discussion from Pull Request 612 here.

I am still somewhat hesitant on this issue... The current behavior isn't strictly invalid. I wonder if there is a good way to make the Unicode Hex Input keyboard work and preserve the Alt - Unicode Symbol input?

The best approach so far:

QString GetTextFromQKeyEvent(QKeyEvent *ev) noexcept
{
	const QString text = ev->text();
	const int key = ev->key();
	const Qt::KeyboardModifiers modifiers = ev->modifiers();

        // Convert macOS Alt+ mappings back to their normal characters.
	if (
		!text.isEmpty()
		&& modifiers & Qt::KeyboardModifier::AltModifier
		&& !(
			modifiers & CmdModifier()
			&& modifiers & ControlModifier()
		)
	) {
		return QString(key);
	}

        // On macOS, QKeyEvent::text() is empty when pressing control or command.
        // https://doc.qt.io/qt-5/qkeyevent.html#text
	if (
		text.isEmpty()
		&& (
			modifiers & ControlModifier()
			|| modifiers & CmdModifier()
		)
	) {
		return QString(key);
	}

	return text;
}

We can define such a function for each platform in input_{platform}.cpp, and replace calls to QKeyEvent::text() with GetTextFromQKeyEvent(...).

For platforms where the existing behavior is good, we can simply use:

QString GetTextFromQKeyEvent(QKeyEvent *ev) noexcept
{
	return ev->text();
}

@mikew
Copy link

mikew commented Dec 28, 2019

The current behavior isn't strictly invalid.

It's still super weird though. With Alt+X, I'd expect vim to receive <A-X>, or simply , not <A-≈>. Case in point: Shift+Alt+X sends <A-˛> to vim, not <S-A-˛>. We can't tell people "well the alt key is technically correct" while not also acknowledging the shift key.

The best approach so far.

The second if statement in there, setting text where Qt otherwise removes it on macOS, doesn't have parity with QKeyEvent::text() if it's not doing toLower. It's also not needed when the Ignore all modifier-only key events is moved outside of the check for text.isEmpty() in input.cpp 😂.

@jgehrig
Copy link
Collaborator

jgehrig commented Dec 28, 2019

We can't tell people "well the alt key is technically correct" while not also acknowledging the shift key.

Agreed, sending <A-≈> is odd. We will do something about this issue.

After investigating 510 further, I think the correct behavior is to send . If users want to map <A-X> or similar, they should modify the keyboard layout to disable the Alt behavior.

This is an oversimplified fix for 510:

diff -r a4b43d295f61 src/gui/shell.cpp
--- a/src/gui/shell.cpp Mon Dec 16 02:23:57 2019 -0500
+++ b/src/gui/shell.cpp Thu Dec 26 10:58:19 2019 -0500
@@ -1070,6 +1070,8 @@
                this->setCursor(Qt::BlankCursor);
        }
 
+       qDebug() << "QKeyEvent ev:" << ev;
+
        const QString inp = Input::convertKey(ev->text(), ev->key(), ev->modifiers());
        if (inp.isEmpty()) {
                QWidget::keyPressEvent(ev);

Even with modification, the fix for 510 will impact this scenario. I hope we can fix this issue (579) by finding a keyboard layout like Hex Unicode Input, that will send the desired events from the OS layer. I suspect we would still need something like GetTextFromQKeyEvent above in that case to convert Key_? to ?.

It's also not needed when the Ignore all modifier-only key events is moved outside of the check for text.isEmpty() in input.cpp.

LOL, that is obvious in hindsight. I was too focused on carefully refactoring the existing code.

@jgehrig
Copy link
Collaborator

jgehrig commented Jul 31, 2020

This issue is resolved with the latest release v0.2.16.

The default behavior of Alt + K is ̊. Since MacOS maps a character, we display the character. Issue #510.

However with System Preferences > Keyboard > Input Sources set as Unicode Hex Input, the Alt + K sequence will map to <A-K>.

@jgehrig jgehrig closed this as completed Jul 31, 2020
@craigmac
Copy link

craigmac commented Oct 2, 2022

For others who find this looking for an answer, in addition to @jgehrig excellent suggestion above, which works wonderfully, you should also consider turning on System Preferences > Keyboard > Input Sources > Automatically switch to a document's input source. This will tell macos to remember your preference per app, so you can start up nvim-qt, switch to Unicode Hex Input as the input source and then shutdown nvim-qt - you'll go back to US (or whatever you had set before for normal input source) and when you restart nvim-qt it should switch Unicode Hex Input back on again. Now you can use your regular input source and option key as you normally would, and when you launch nvim-qt it will seamlessly enable Unicode Hex Input so that <M-..> mappings work correctly. If you'd also like available to bind you'll have to unbind it in Keyboard Preferences > Keyboard > Shortcuts > Input Sources (it's bound to switch input sources by default, so nvim-qt can't bind it until you turn this off. Cheers!

@xiehuc
Copy link

xiehuc commented Oct 13, 2023

For others who find this looking for an answer, in addition to @jgehrig excellent suggestion above, which works wonderfully, you should also consider turning on System Preferences > Keyboard > Input Sources > Automatically switch to a document's input source. This will tell macos to remember your preference per app, so you can start up nvim-qt, switch to Unicode Hex Input as the input source and then shutdown nvim-qt - you'll go back to US (or whatever you had set before for normal input source) and when you restart nvim-qt it should switch Unicode Hex Input back on again. Now you can use your regular input source and option key as you normally would, and when you launch nvim-qt it will seamlessly enable Unicode Hex Input so that <M-..> mappings work correctly. If you'd also like available to bind you'll have to unbind it in Keyboard Preferences > Keyboard > Shortcuts > Input Sources (it's bound to switch input sources by default, so nvim-qt can't bind it until you turn this off. Cheers!

that's awesome

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

No branches or pull requests

6 participants