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

Presses of special keys are not detectable by Deno on Windows #5945

Closed
dd-pardal opened this issue May 29, 2020 · 9 comments · Fixed by #16904
Closed

Presses of special keys are not detectable by Deno on Windows #5945

dd-pardal opened this issue May 29, 2020 · 9 comments · Fixed by #16904
Assignees
Labels
bug Something isn't working correctly cli related to cli/ dir windows Related to Windows platform

Comments

@dd-pardal
Copy link

dd-pardal commented May 29, 2020

It is currently impossible to know when the user presses a special key in Console Window Host (the default terminal, conhost.exe) or Windows Terminal.

Here's a test script (needs --unstable because of Deno.setRaw()):

const stdinRid = Deno.stdin.rid;
if (Deno.isatty(stdinRid))
    Deno.setRaw(stdinRid, true);

(async () => {
    for await (const data of Deno.iter(Deno.stdin)) {
        if (data[0] === 0x03) // Ctrl+C
            Deno.exit();
        console.log(data);
    }
})();

This could log an escape sequence when the user presses, for example, the arrow keys (I think it does on Linux), but it logs nothing.

@apatrida
Copy link

apatrida commented Jun 14, 2020

@dd-pardal I get odd behavior from yours as well on Mac, have you tried:

if (!Deno.isatty(Deno.stdin.rid)) {
  console.log("Cannot do raw input when not tty");
  Deno.exit(-1);
}

Deno.setRaw(Deno.stdin.rid, true);

while (true) {
    const buf = new Uint8Array(512);
    const bytesRead = await Deno.read(Deno.stdin.rid, buf);
    console.log(bytesRead);
    console.log(buf);
    if (bytesRead === 1 && buf[0] === 0x03) {
        break;
    }
}

Deno.setRaw(Deno.stdin.rid, false);

@bartlomieju bartlomieju added bug Something isn't working correctly cli related to cli/ dir windows Related to Windows platform labels Jun 16, 2020
@prcdpr
Copy link

prcdpr commented Sep 22, 2020

Any updates on that? Is there at least some workaround?

@ebebbington
Copy link
Contributor

Can reproduce the issue windows for me - arrow keys arent being logged

@denyncrawford
Copy link

Any update about this issue? seems like in 1.8.x it is not possible still

@kitsonk
Copy link
Contributor

kitsonk commented Apr 8, 2021

The issue is still open, which means it isn't fixed.

@x7y62
Copy link

x7y62 commented Aug 27, 2021

Running into this issue as well. Is there any working progress?

@denyncrawford
Copy link

denyncrawford commented Aug 27, 2021

Hi @x7y62 I did this module for handling native input events, check it out if you need to solve this https://github.com/denyncrawford/deno-gkm It's in dippers but it can do the job. Hope it helps.

@dale-roberts
Copy link

Until this issue is resolved, here is yet another quick work-around using Deno's new FFI capability. No other libraries are required, but you do need the Windows command line C/C++ 64-bit complier CL (could probably instead call Windows DLL functions directly, if anyone wants to try that route). This is not async, and uses the old Windows console function getch(). kbhit() is also provided, if needed, to check whether a keypress is available, since getch() is blocking. Save this as getch.c, and compile from x64 Visual Studio command prompt with cl /LD getch.c to generate getch.dll:

#include <conio.h>
__declspec(dllexport) int __getch() {return _getch();}
__declspec(dllexport) int __kbhit() {return _kbhit();}

Example JS/TS code for testing, save as getch.js (or ts), and invoke with deno run --allow-ffi --unstable getch.js:

const dylib = Deno.dlopen("getch.dll", {
  "__getch": { parameters: [], result: "i32" },
  "__kbhit": { parameters: [], result: "i32" },
});

while(true) {
	let ch = dylib.symbols.__getch();
	console.log(`Key pressed: ${ch}`);
	if(ch == 3) break;
}

Now you will get the 2-byte codes for keypad, arrow, and function keys. This works identically on Console, Windows Terminal, PowerShell, etc.

@dale-roberts
Copy link

dale-roberts commented Sep 20, 2021

Well, Duh, you can also simply use c:\windows\system32\msvcrt.dll (the C runtime DLL) directly, and avoid needing the compiler:

const dylib = Deno.dlopen("c:\\windows\\system32\\msvcrt.dll", {
  "_getch": { parameters: [], result: "i32" },
  "_kbhit": { parameters: [], result: "i32" },
});

Or use the standard environment variable to find system root (then must add --allow-env to deno command line):

const SysRoot = Deno.env.get("SystemRoot");
const dylib = Deno.dlopen(`${SysRoot}\\system32\\msvcrt.dll`, {
  "_getch": { parameters: [], result: "i32" },
  "_kbhit": { parameters: [], result: "i32" },
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working correctly cli related to cli/ dir windows Related to Windows platform
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants