mathlive
mathlive copied to clipboard
Strange issue with Italian keyboard layout
Description
Hello, we are using mathlive with the react wrapper by ShaMan123 https://github.com/ShaMan123/react-math-view and we are experiencing a strange issue with the keyboard mappings using the Italian keyboard layout.
I've prepared a minimal environment reproducing our setup here: https://glitch.com/edit/#!/confirmed-bristle-digestion?path=src%2Fapp.jsx%3A56%3A45
Steps to Reproduce
In the test environment (https://confirmed-bristle-digestion.glitch.me):
-
configure your machine with the Italian keyboard layout
-
type
y ^ 2 -
-
the layout is recognized as
spanish
(which is fine as it is functionally equivalent to the Italian layout, at least for mathlive) -
click the "Re-mount component" link in the page (this simulates the remount of the mathlive component)
-
focus the mathfield and delete all the text ( either using
Ctrl+A and backspace
or with multiplebackspace
) -
type again
y ^ 2 -
Actual Behavior
The second time you type y ^ 2 -
, the -
is mapped as if the keyboard layout was set to english and produces a fraction as output.
(note: the layout chosen by mathlive mapping logic is indeed
english
)
Expected Behavior
The keyboard layout should be correctly identified also the 2nd time we type y ^ 2 -
Possible solution
We tried to analyze the issue and found that here https://github.com/arnog/mathlive/blob/d459adf1756d1b459362733d1a49f52adee64ca9/src/editor/keyboard-layout.ts#L657 the layouts sorting is done in-place and it doesn't account for the initial layouts ordering. We added some logic that keeps the ordering stable with regard to the initial ordering (ie if two layouts have the same score they are sorted using the initial layouts order) and this seems to solve our issue.
src/editor/keyboard-layout.ts | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/editor/keyboard-layout.ts b/src/editor/keyboard-layout.ts
index f9548e94..595085f7 100644
--- a/src/editor/keyboard-layout.ts
+++ b/src/editor/keyboard-layout.ts
@@ -492,6 +492,7 @@ const BASE_LAYOUT_MAPPING = {
};
const gKeyboardLayouts: KeyboardLayout[] = [];
+const gKeyboardLayoutsIDs: KeyboardLayoutId[] = [];
let gKeyboardLayout: KeyboardLayout | undefined;
@@ -512,6 +513,7 @@ export function platform(): 'apple' | 'windows' | 'linux' {
export function register(layout: KeyboardLayout): void {
if (!layout.platform || layout.platform === platform()) {
gKeyboardLayouts.push(layout);
+ gKeyboardLayoutsIDs.push(layout.id);
}
}
@@ -654,7 +656,13 @@ export function validateKeyboardLayout(evt?: KeyboardEvent): void {
}
}
- gKeyboardLayouts.sort((a, b) => b.score - a.score);
+ gKeyboardLayouts.sort((a, b) =>
+ (b.score === a.score) ?
+ // sort by original order when the score is equal
+ gKeyboardLayoutsIDs.indexOf(a.id) - gKeyboardLayoutsIDs.indexOf(b.id) :
+ // sort by decreasing score
+ b.score - a.score
+ );
}
export function setKeyboardLayoutLocale(locale: string): void {
We could open a PR with this solution but we would really appreciate your feedback first, since we don't know if this is an isolated issue or if it's part of a bigger problem and we still have doubt on the root cause of this issue.
Thank you, have a nice day!
Environment
MathLive version: 0.68.1
Operating System: macOS, Windows, Linux
Browser: Chrome, Firefox
Thanks for reporting this and for taking the time to write an excellent report and to build a reproducible case.
Your fix can work, but I don't think it's quite right.
I think the problem is that when the mathfield is remounted the keyboard layouts get re-registered, the new ones override the previous ones and the score they had accumulated. Instead, the keyboard layout registration should avoid registering keyboards that are already known, i.e. in register()
, if gKeyboardLayouts
already has a matching ID, skip the registration.
Could you give that a try? I unfortunately have some problems fully debugging through your example and it might be easier for you to make that change and validate that it works. If it does, I'd be happy to merge a PR for it.
Thank you for the hint!
I've tried implementing your suggestion in src/editor/keyboard-layout.ts
export function register(layout: KeyboardLayout): void {
if (!layout.platform || layout.platform === platform()) {
if (gKeyboardLayouts.findIndex(({ id }) => id === layout.id) === -1) {
gKeyboardLayouts.push(layout);
}
}
}
but, in our test case, the register function is not called again during re-rendering. I will investigate this further to see if the issue is react-specific.
Any update to this? I'm having the same problem where re-rendered layout changes and the "-" symbol is interpreted as a fraction.
I tried to add event handlers in different hook to avoid remounting without success. I also tried to create new mathfield element, but for some reason that didn't help either.
Is there any workaround for this?
Managed to reproduce the issue: https://codesandbox.io/s/layout-bug-v9udw?file=/src/Mathfield.tsx
Finnish keyboard layout: http://kbdlayout.info/KBDFI/
The bug happens also without remounting the Mathfield. I was not able to reproduce that in the codesandbox but I added the video with console logs to prove that (It only gets mounted once in logs).
https://user-images.githubusercontent.com/46352445/134766193-97266791-32df-4206-a94d-889fd194fdf2.mp4
@Temez1 I'm not sure the issue you're describing is the same as the original issue. The original issue is specifically an issue when remounting a component and the previously inferred layout is not preserved. Your issue seems to be that the incorrect keyboard layout is used? It's hard to tell from the video without knowing which keys you press. Could you file a separate issue to track this?
@arnog Sure, see #1194
This looks to have been abandonned