v86 icon indicating copy to clipboard operation
v86 copied to clipboard

Add function to paste from clipboard and add support for non-US locales

Open chschnell opened this issue 3 months ago • 5 comments

To paste text from the system clipboard into the emulator support for international keyboard layout mappings is needed for non-US users (in text mode, support for non-US codepages is additionally needed). This problem is laid out in detail in issue #1406.

User interface changes

  • added "Locale" setting to emulator setup (us, uk, de, default: us), each locale defines a codepage and a keyboard layout mapping
  • added "Send clipboard" function button to paste current system clipboard content into the emulator (can be aborted by pressing Esc)

API changes

  • removed delay argument from V86.keyboard_send_scancodes() and V86.keyboard_send_text(), not needed any more (moved to KeyboardAdapter config)
  • removed V86.keyboard_send_keys(codes, delay), this isn't supported any more (deprecated and wasn't used in the source tree anyway)
  • added V86.keyboard_send_keypress(keys, hold_time) as a replacement, keys is an array of strings in KeyboardEvent.code naming convention
  • added V86 configuration option options.locale to set the Locale at startup (default: us)

Changes to class KeyboardAdapter

  • split implementation into separate DesktopKeyboard and DataKeyboard classes
  • DesktopKeyboard handles interactive keyboard input from the system keyboard in desktop browser environments
  • DataKeyboard handles all other cases in which we feed an arbitrary large amount of data into the keyboard pipeline programatically, which can be a unicode string, a synthetic key-press event or a sequence of raw scancodes
  • for consistency, DesktopKeyboard is muted whenever DataKeyboard is feeding scancodes into the keyboard pipeline
  • removed dependencies on deprecated KeyboardEvent.keyCode (as much as possible, help needed)
  • removed charmap[] and asciimap[]
  • added KEYMAPS[], maps unicode characters to scancode combinations for selected keyboard layouts
  • moved away from using raw scancode numbers in the source tree in favour of string-typed key names from the KeyboardEvent.code naming convention

Demos

Use case 1: Pasting all extended German keys into nano (Debian 12 German in text console mode):

https://github.com/user-attachments/assets/b5ff3a9d-d71f-4842-897d-466498773688

Use case 2: Mobile screenshot FreeDOS 1.4 German:

freedos14-de-android-kbdgr

Use case 3: German keyboard layout mapping and copdepage in vga2tty with FreeDOS 1.4 German:

See vga2tty.

https://github.com/user-attachments/assets/b363dfb3-6f46-4067-8772-ac1a9e68ddd3

TODO

  • tooling: keyboard layout mappings are currently generated by an external python script, this could be moved to ./tools/ in the source tree. The same is true for the generation of codepage mappings. Both scripts need a bit of work and discussion before though.
  • CapsLock: the CapsLock state of the system keyboard is currently ignored (the key itself is handled correctly, but its active/inactive state is not handled), haven't really looked into this yet
  • internal mapping objects for codepages, keyboard layouts and locales are currently scattered across lib.js, browser/keyboard.js and browser/starter.js (respectively), maybe these should be at the same place because they are related, but where?

chschnell avatar Sep 20 '25 09:09 chschnell

Apologies about the delay in reviewing. Overall this looks great, but I am struggling a bit with this PR for several reasons:

  1. The highly oop-style with several classes, exceptions and async code. I would prefer a much more direct, imperative style, where most of the code is written in a single function.
  2. The current UI of asking for a locale before starting emulation is confusing. It's not clear which keyboard layout is being asked for, the one from the guest OS or the one from the host OS (or both). It's not clear that this is only used for pasting or mobile input and that it only affects special characters (if I understand correctly). I think a good starting point would be moving this to the runtime options and changing the default to "raw / untranslated"
  3. I am not thrilled by the idea of shipping many possible keyboard maps. Maybe this sort of information could be obtained from https://developer.mozilla.org/en-US/docs/Web/API/Keyboard/getLayoutMap

copy avatar Nov 26 '25 13:11 copy

I agree that these are all valid points.

The highly oop-style with several classes, exceptions and async code. I would prefer a much more direct, imperative style, where most of the code is written in a single function.

The style (OO, exceptions and async) could be changed of course, but my general problem currently is that I'm too busy at work right now, and this will be the case throughout December.

The current UI of asking for a locale before starting emulation is confusing. It's not clear which keyboard layout is being asked for, the one from the guest OS or the one from the host OS (or both).

The "locale" is the same, shared locale of host AND guest OS.

It's not clear that this is only used for pasting or mobile input and that it only affects special characters (if I understand correctly).

It's used for typing and pasting on desktop browsers and for typing on mobile browsers (never tried to paste into a mobile device, this might work).

It may affect any character. Keyboard layouts are open and completely arbitrary, there are no rules. For example, on my German keyboard layout, the letters "y" and "z" are swapped (compared to the US-layout), and almost all non-alphanumeric characters are shuffled. The US-layout is not a complete subset of all layouts, the Italian layout lacks the tilde and backtick keys, for example. I think on all modern OSes, you can freely design keyboard layouts as you please. They even have their own subreddit for keyboard layouts, and it's actually quite active: https://www.reddit.com/r/KeyboardLayouts/. So there are no rules, only mappings for more or less popular keyboard layouts.

I think a good starting point would be moving this to the runtime options and changing the default to "raw / untranslated"

Agree (this currently is the US-layout, which is conceptually the same).

I am not thrilled by the idea of shipping many possible keyboard maps. Maybe this sort of information could be obtained from https://developer.mozilla.org/en-US/docs/Web/API/Keyboard/getLayoutMap

I know, but unfortunately neither Firefox nor Safari support this feature, that's why I didn't use it (and my guess is that they will never support it because of the problem with browser fingerprinting).

chschnell avatar Dec 02 '25 12:12 chschnell

I am not thrilled by the idea of shipping many possible keyboard maps.

How about providing additional keyboard maps as JSON files or modules?

import custom_keymap from "./de-keymap.mjs";

const emulator = new V86({
    ...
    keymap: custom_keymap,
});

// or

const emulator = new V86({
    ...
    keymap_url: "./de_keymap.json", 
});

SuperMaxusa avatar Dec 04 '25 11:12 SuperMaxusa

I am not thrilled by the idea of shipping many possible keyboard maps.

How about providing additional keyboard maps as JSON files or modules?

import custom_keymap from "./de-keymap.mjs";

const emulator = new V86({
    ...
    keymap: custom_keymap,
});

// or

const emulator = new V86({
    ...
    keymap_url: "./de_keymap.json", 
});

Yes, that should be a nice way to solve this issue.

The Python script import_kbd.py that generates Javascript keyboard layout mappings would need to be added to /tools, and a bit of user documentation on how to use it for a given keyboard layout (in case it would be insisted upon I could rewrite that into a node.js application). That mapping file could also be imported through the web ui, correct?

An extreme option would be to not include any foreign keyboard layout mappings in the v86 main repository, just to support them technically.

chschnell avatar Dec 05 '25 10:12 chschnell

That mapping file could also be imported through the web ui, correct?

Like a file input section (along with some built-in layouts)?

SuperMaxusa avatar Dec 05 '25 17:12 SuperMaxusa