# What key did I press?

The task is to write code to identify which key is pressed on the keyboard. You can assume that only one key is pressed at a time and that there is a standard US keyboard layout. That is the layout with the @ over the 2.

Your code should output a unique identifier for any key pressed. This includes PrtScn, Scroll Lock, Pause, left Shift, right Shift, left Ctrl, right Ctrl, Caps Lock, Tab, Enter, Enter on the number pad, Num Lock, Insert, Ins on the number pad, Backspace, Del, F1...F12, Esc, left Windows key, right Windows key, Alt, AltGr, application key (context menu) and so on.

Your code should carry on waiting for key presses and outputting their identity until it is killed. It should output the identifier as soon as a key is released however. It shouldn't carry out any other action from the key presses it receives and it shouldn't output anything apart from the unique identifier.

In your answer, please show what you code outputs for the following key presses: Tab, Pause, Enter, Enter on the number pad, left Windows key, right Windows key, Insert and Ins on the number pad.

If you have a very different keyboard, the challenge is still to output a different identifier for every single key on your keyboard.

• In JS (browser JS, anyway), it is impossible to check whether certain keys are pressed (e.g. Caps Lock, Num Lock, Scroll Lock, PrtScn). Does this mean that JS cannot answer? – ETHproductions Jul 13 '17 at 14:58
• @ETHproductions It does indeed. Apologies to JS lovers everywhere. – user9206 Jul 13 '17 at 14:59
• Requirements modified after 5 answers are provided (including one now deleted). That's not really fair... – Olivier Grégoire Jul 13 '17 at 15:33
• I don't think it's fair/right to request output for keys that aren't on many keyboards such as Windows key etc. – Notts90 Jul 13 '17 at 19:18
• @Notts90 Aren't they part of the standard US keyboard layout? upload.wikimedia.org/wikipedia/commons/thumb/5/51/… – user9206 Jul 13 '17 at 20:21

## x86 machine code, DOS executable, 29* 28 bytes

FAE464D0E873FAE460D0E073F4D41005212192B402CD2188F2CD21EBE3


This is a COM executable for MS-DOS, it requires a IBM PC compatible hardware.
Particularly an 8042 PS/2 controller or more likely an emulation of it through SMM.
Long story short, it should work out of the box in any mainstream PC.

The source code is

BITS 16

;Disable the interrupts so we don't compete with the IRQ 1 (the 8042 main
;device IRQ) handler (the ISR n. 9 by default) for the reading of the codes.
cli

_wait:

;Is 'Output buffer full (OBF)' bit set?

in al, 64h                ;Read the 8042 status register
shr al, 1                 ;Move bit 0 (OBF) into the carry flag

jnc _wait                  ;Keep spinning if CF = OBF not set

in al, 60h

;Is S a break code?

shl al, 1                 ;Bit 7 is set if it is
jnc _wait

;PART 2

;AL = S mod 10h := y, AH = S / 10h := x
aam 16
add ax, 2121h             ;Make both quantities in the printable ASCII range (skip space though)

;Print y
xchg dx, ax
mov ah, 02h
int 21h                   ;int 21/ah=02 prints the char in DL

;DH is still valid here, it holds x. We print it now
mov dl, dh
int 21h

;Never terminate
jmp _wait


I've divided the program into two parts.

The first part deals with the reading of the scancodes. Scancodes are numeric values associated with every key.
Note that these are hardware code, they don't depend on the OS or the charset. They are like an encoded pair (column, row) of the key.
Every key has a scancode, even those non-standard weird function keys found on some keyboard (e.g. the "open calc" key).
Some key has multi-byte scancode, they have prefixes designed to make the stream decodificable by just looking at the sequence of bytes.
So each key gets its unique identifier, even CTRL, SHIFT, WinKeys and so on.

Only the "break codes", sent when a key is released, are processed, the "make codes" are ignored.
The formers have the higher bit (bit 7 for a byte) set, so it's easy to recognise them.

The second part deals with the printing of a byte.
Printing is always lengthy in assembly, we have no builtins.
To keep it short, and since it was required to write an identifier of the key, I abandoned decimal or hex numerals in favour of a personal encoding.

A byte xy, where x is the higher nibble and y the lower is printed as two successive chars c0 and c1 defined as:

c0 = 0x21 + y
c1 = 0x21 + x

Note that the lower nibble is printed first (this spared me a swap).
The rationale is to map the each one of the 16 possible values of a nibble into consecutive ASCII characters from '!'.
Simply put this is a hex numeral but with

1. The nibbles swapped
2. !"#$%&'()*+,-./01 as digit(als) instead of 0123456789abcdef Running it in DOSBox and pressing some random key (some of which is a special key but note that as a Windows process DOSBox can't capture all the keys) yields Note that this program never terminates (further, it takes complete control of the PC by disabling the interrupts) as I believe was intended by the question (simply there is no killing of processes in DOS). * Reduced thank to CodyGray. • Did using the IN instruction work out to be smaller in terms of bytes than calling the ROM BIOS interrupts (e.g., int 16h, function 10h)? – Cody Gray Jul 14 '17 at 3:54 • @CodyGray Most likely not, the whole loop could be skipped. Somehow I just jumped straight to the in instruction. That's actually a very good point you have. If you haven't already, why not post it as an answer? :) – Margaret Bloom Jul 14 '17 at 7:40 • Well now you're talking crazy! That sounds like a lot more work than just commenting on your existing answer. :-p I'm playing with putting something together. Fun tip, though: when code golfing, xchg with the accumulator as one of the registers is 1 byte, so that's better than a 2-byte mov. – Cody Gray Jul 14 '17 at 8:30 • Okay, the problem with int 16h is that I don't get scan codes for the shift keys, scroll lock, or pause/break (perhaps others), and that is required by the challenge. Your solution of reading the input directly from the I/O works, although it looks like to me it returns the same value for all of the keys in the Ins/Del/Home/End/PgUp/PgDown cluster. – Cody Gray Jul 14 '17 at 9:30 • @PeterCordes: also PAUSE has some strange behavior, IIUC sending the break code together with the make code on key press, and not sending anything on key release. Or that's what I understood from the PC Game Programming Encyclopedia. – ninjalj Jul 14 '17 at 21:40 # Java 7 or Higher, 246 228 bytes import java.awt.event.*;class K{public static void main(String[]a){new java.awt.Frame(){{addKeyListener(new KeyAdapter(){public void keyPressed(KeyEvent e){System.out.println(e);}});show();setFocusTraversalKeysEnabled(0<0);}};}}  Ungolfed: import java.awt.event.*; class K{ static void main(String[]a){ new java.awt.Frame(){ { addKeyListener(new KeyAdapter(){ public void keyPressed(KeyEvent e){ System.out.println(e); } }); show(); setFocusTraversalKeysEnabled(0<0); } }; } }  -18 thanks to @OlivierGrégoire for show(), 0<0 and import java.awt.event.*; Which results in: Even handles shift-presses for capitalized characters, the windows key, cap locks, etc... You can see it printing the 'modifiers' as well, which are 'held keys'. java.awt.event.KeyEvent[KEY_PRESSED,keyCode=27,keyText=Escape,keyChar=Escape,keyLocation=KEY_LOCATION_STANDARD,rawCode=27,primaryLevelUnicode=27,scancode=1,extendedKeyCode=0x1b] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=192,keyText=Back Quote,keyChar='',keyLocation=KEY_LOCATION_STANDARD,rawCode=192,primaryLevelUnicode=96,scancode=41,extendedKeyCode=0xc0] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=9,keyText=Tab,keyChar=Tab,keyLocation=KEY_LOCATION_STANDARD,rawCode=9,primaryLevelUnicode=9,scancode=15,extendedKeyCode=0x9] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=20,keyText=Caps Lock,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=20,primaryLevelUnicode=0,scancode=58,extendedKeyCode=0x14] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=16,keyText=Shift,keyChar=Undefined keyChar,modifiers=Shift,extModifiers=Shift,keyLocation=KEY_LOCATION_LEFT,rawCode=16,primaryLevelUnicode=0,scancode=42,extendedKeyCode=0x10] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=17,keyText=Ctrl,keyChar=Undefined keyChar,modifiers=Ctrl,extModifiers=Ctrl,keyLocation=KEY_LOCATION_LEFT,rawCode=17,primaryLevelUnicode=0,scancode=29,extendedKeyCode=0x11] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=524,keyText=Windows,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_LEFT,rawCode=91,primaryLevelUnicode=0,scancode=91,extendedKeyCode=0x20c] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=18,keyText=Alt,keyChar=Undefined keyChar,modifiers=Alt,extModifiers=Alt,keyLocation=KEY_LOCATION_LEFT,rawCode=18,primaryLevelUnicode=0,scancode=56,extendedKeyCode=0x12] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=32,keyText=Space,keyChar=' ',keyLocation=KEY_LOCATION_STANDARD,rawCode=32,primaryLevelUnicode=32,scancode=57,extendedKeyCode=0x20] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=18,keyText=Alt,keyChar=Undefined keyChar,modifiers=Alt,extModifiers=Alt,keyLocation=KEY_LOCATION_RIGHT,rawCode=18,primaryLevelUnicode=0,scancode=56,extendedKeyCode=0x12] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=17,keyText=Ctrl,keyChar=Undefined keyChar,modifiers=Ctrl,extModifiers=Ctrl,keyLocation=KEY_LOCATION_RIGHT,rawCode=17,primaryLevelUnicode=0,scancode=29,extendedKeyCode=0x11] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=37,keyText=Left,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=37,primaryLevelUnicode=0,scancode=75,extendedKeyCode=0x25] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=16,keyText=Shift,keyChar=Undefined keyChar,modifiers=Shift,extModifiers=Shift,keyLocation=KEY_LOCATION_RIGHT,rawCode=16,primaryLevelUnicode=0,scancode=42,extendedKeyCode=0x10] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=38,keyText=Up,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=38,primaryLevelUnicode=0,scancode=72,extendedKeyCode=0x26] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=39,keyText=Right,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=39,primaryLevelUnicode=0,scancode=77,extendedKeyCode=0x27] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=96,keyText=NumPad-0,keyChar='0',keyLocation=KEY_LOCATION_NUMPAD,rawCode=96,primaryLevelUnicode=48,scancode=82,extendedKeyCode=0x60] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=110,keyText=NumPad .,keyChar='.',keyLocation=KEY_LOCATION_NUMPAD,rawCode=110,primaryLevelUnicode=46,scancode=83,extendedKeyCode=0x6e] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=10,keyText=Enter,keyChar=Enter,keyLocation=KEY_LOCATION_NUMPAD,rawCode=13,primaryLevelUnicode=13,scancode=28,extendedKeyCode=0xa] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=107,keyText=NumPad +,keyChar='+',keyLocation=KEY_LOCATION_NUMPAD,rawCode=107,primaryLevelUnicode=43,scancode=78,extendedKeyCode=0x6b] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=109,keyText=NumPad -,keyChar='-',keyLocation=KEY_LOCATION_NUMPAD,rawCode=109,primaryLevelUnicode=45,scancode=74,extendedKeyCode=0x6d] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=106,keyText=NumPad *,keyChar='*',keyLocation=KEY_LOCATION_NUMPAD,rawCode=106,primaryLevelUnicode=42,scancode=55,extendedKeyCode=0x6a] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=34,keyText=Page Down,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=34,primaryLevelUnicode=0,scancode=81,extendedKeyCode=0x22] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=33,keyText=Page Up,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=33,primaryLevelUnicode=0,scancode=73,extendedKeyCode=0x21] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=35,keyText=End,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=35,primaryLevelUnicode=0,scancode=79,extendedKeyCode=0x23] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=36,keyText=Home,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=36,primaryLevelUnicode=0,scancode=71,extendedKeyCode=0x24] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=127,keyText=Delete,keyChar=Delete,keyLocation=KEY_LOCATION_STANDARD,rawCode=46,primaryLevelUnicode=0,scancode=83,extendedKeyCode=0x7f] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=155,keyText=Insert,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=45,primaryLevelUnicode=0,scancode=82,extendedKeyCode=0x9b] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=123,keyText=F12,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=123,primaryLevelUnicode=0,scancode=88,extendedKeyCode=0x7b] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=122,keyText=F11,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=122,primaryLevelUnicode=0,scancode=87,extendedKeyCode=0x7a] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=121,keyText=F10,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=121,primaryLevelUnicode=0,scancode=68,extendedKeyCode=0x79] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=120,keyText=F9,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=120,primaryLevelUnicode=0,scancode=67,extendedKeyCode=0x78] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=119,keyText=F8,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=119,primaryLevelUnicode=0,scancode=66,extendedKeyCode=0x77] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=118,keyText=F7,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=118,primaryLevelUnicode=0,scancode=65,extendedKeyCode=0x76] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=117,keyText=F6,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=117,primaryLevelUnicode=0,scancode=64,extendedKeyCode=0x75] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=116,keyText=F5,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=116,primaryLevelUnicode=0,scancode=63,extendedKeyCode=0x74] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=115,keyText=F4,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=115,primaryLevelUnicode=0,scancode=62,extendedKeyCode=0x73] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=114,keyText=F3,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=114,primaryLevelUnicode=0,scancode=61,extendedKeyCode=0x72] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=113,keyText=F2,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=113,primaryLevelUnicode=0,scancode=60,extendedKeyCode=0x71] on frame0 java.awt.event.KeyEvent[KEY_PRESSED,keyCode=112,keyText=F1,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_STANDARD,rawCode=112,primaryLevelUnicode=0,scancode=59,extendedKeyCode=0x70] on frame0  • Comments are not for extended discussion; this conversation has been moved to chat. – Dennis Jul 14 '17 at 1:09 # HTML (with Javascript), 46 31 chars, 46 31 bytes Using this to differentiate numpad enter and return, LControl and RControl... Not anymore since apsillers found a way to do it with a signle function call. <body onkeyup=alert(event.code)  Specific outputs: OUTPUTS THAT ARE STILL WITH THE NUMBERS ARE THOSE I CAN'T TEST ON MY LAPTOP PLEASE WAIT FOR ME TO HAVE ACCESS TO THOSE KEYS PrtScn -> PrintScreen Scroll Lock -> ScrollLock Pause -> Pause left Shift -> ShiftLeft right Shift -> ShiftRight left Ctrl -> ContrlLeft right Ctrl -> ControlRight Caps Lock -> CapsLock Tab -> Tab Enter -> Enter Enter on the number pad -> NumpadEnter Num Lock -> NumLock Insert -> Insert Ins on the number pad -> Numpad0 Backspace -> Backspace Del -> Delete F1...F12 -> F1 to F12 Esc -> Escape left Windows key -> MetaLeft right Windows key -> MetaRight Alt -> AltLeft AltGr -> AltRight (kind of buggy, it detects ControlLeft and then AltRight, but it is indeed AltRight) application key (context menu) -> ContextMenu EDITs : 1 byte saved on ; after func call 18 bytes saved thanks to Lil' Bits and ETHproductions, they noticed I forgot to shorten func and var names. 32 bytes saved thanks to RogerSpielker, he noticed I was doing sparated code for no reason; and again -2 bytes : onkeydown -> onkeyup 1 byte saved : no need for final slash 2 bytes saved thanks to CraigAyre : with() function 2 bytes saved thanks to ASCII-only : key in place of which 4 bytes saved, since we have text, there is no need for '-'+ (every identifier is unique without this) 1 byte saved thanks to ASCII-only (again) : no more closing symbol > 15 bytes saved thanks to apsillers, as said at the top of my answer. <body onkeyup=alert(event.code) • Wait... how is... Caps Lock... detected? I thought that was impossible... Huh, oh well. PrtScn and SysRq don't work for me, but I'm on a laptop with a small keyboard that uses Fn+End and Fn+Home for those two keys. – ETHproductions Jul 13 '17 at 15:05 • I like this answer but it seems to have some problems. Tab doesn't report anything for me when I test it at codepen.io/anon/pen/MoLPQM . Also F12, PrtScn don't follow this rule "It shouldn't carry out any other action from the key presses it receives and it shouldn't output anything apart from the unique identifier." – user9206 Jul 14 '17 at 10:23 • @Lembik using html, it is not really possible to prevent system from using the key. You need to force it not recognizing key inputs with a machine (or system) effective language (like C maybe). And for tab, I don't know what conditions it for working (I mean, it works sometimes and sometimes it doesn't, I don't know how my answer treats traversable keys. – V. Courtois Jul 14 '17 at 11:20 • @Lembik If you view the code in a standalone (not a snippet or fiddle or similar), fullscreen page (e.g., with F11) then it captures Tabs; the fact that it doesn't capture tabs is a function of the state of larger browser environment, not the code being run on the page. As for preventing default behaviors, <body onkeydown=return!!alert(event.code)> should do the trick by returning false on keydown – apsillers Jul 14 '17 at 19:19 # Tcl/Tk, 22 characters bind . <Key> {puts %K}  Sample run: Notes: • No right Windows key on my keyboard ☹ (clever designer put the backlight switch in its place) • The numeric pad's Insert generates different code based on NumLock's status • The volume knob generates X.org specific codes, all other are just regular keysyms # Bash with X.org, 21 bytes xev|awk 'NR%2&&/\(k/'  Unfortunately, I can't test it since I'm on MacBook on Linux - no PrntScr, no numeric keyboard &all. xev is a tool that outputs mouse and keyboard events under X.org. I pipe it to awk, filter even lines (since every key is shown when key is pressed, and then when it's released), and select only those that contain (k - this string is in every line that describes pressed key. • Could you add the example outputs listed in the question please. – user9206 Jul 13 '17 at 14:28 • @Lembik all output appears after exiting. – enedil Jul 13 '17 at 14:29 • Ah. That isn't what the spec asks for. I will clear that up now. – user9206 Jul 13 '17 at 14:31 • This gives a syntax error now. – user9206 Jul 13 '17 at 15:31 • Note that Linux doesn't imply X11. e.g. this wouldn't work on a text console (use showkey -s there :P), or on a pure Wayland GUI desktop. This is really a bash + Xorg answer. – Peter Cordes Jul 14 '17 at 17:49 # C and Win32, 240224216205202194 191 bytes #include<d3d.h> #include<stdio.h> w[9];p(x,y,a,b){printf("%X",a^b);}main(){w[1]=p;w[9]=p;CreateWindow(RegisterClass(w),0,1<<28,0,0,0,0,0,0,0,0);for(;GetMessage(w,0,16,0);)DispatchMessage(w);}  ## Outputs TAB: F0008C00F0008 PAUSE: 450012C0450012 ENTER: 1C000CC01C000C NUMPAD-ENTER: 11C000CC11C000C WINDOWS-LEFT: 15B005AC15B005A WINDOWS-RIGHT: 15C005DC15C005D INSERT: 152002CC152002C NUMPAD-INSERT: 52002CC052002C ## Explanation #include <d3d.h> // shortest built-in header that includes windows.h #include <stdio.h> // for printf w[9]; // space for wndclass-data array // function castable to the signature of WNDPROC p(x,y,a,b) { // key and state are encoded in the last two 4-byte arguments to wndproc printf("%X",a^b); } main(m) { // set minimal window class equivalent data pointing to wndproc above w[1]=p;w[9]=p; // create the window using the class, with WS_VISIBLE flag CreateWindow(RegisterClass(w),0,1<<28,0,0,0,0,0,0,0,0) for(;GetMessage(w,0,16,0);) // filter messages 15 and lower, which fire without input DispatchMessage(w); }  ## Edits -16 thanks to @ugoren -8: changed WNDCLASS to int array since all 10 members are 4 bytes -11: partial initialization of wndclass-data array, reduced to 9 elements -3: use implicit int decl for wndclass-data array -8: remove newline from output format (not required in spec and printf flushes immediately without it); move RegisterClass into CreateWindow arg, using returned ATOM; set wndclass name to m which just needs a zero-byte in it to be a valid string. -3: reuse w var for MSG data • Doing the same thing with C++ by using cout wouldn't be much shorter ? – onurcanbektas Jul 14 '17 at 7:35 • @Leth No. <iostream> + std::cout<<a^b<<"\n" is longer. Plus I think you'd need to add return types to the function decls, and m couldn't be an implicit int. – MooseBoys Jul 14 '17 at 7:39 • Save a char with for(;GetMessage(&m,0,16,0);)DispatchMessage(&m); – ugoren Jul 14 '17 at 11:31 • Also, p(x,y,a,b) and (void*)p should save some. – ugoren Jul 14 '17 at 11:44 # Java (OpenJDK 8), 369 bytes import java.awt.event.*;import javax.swing.*;class F{public static void main(String[] a){JFrame f=new JFrame();f.addKeyListener(new KeyListener(){public void keyPressed(KeyEvent e){System.out.print(e.getKeyCode()*8+e.getKeyLocation());}public void keyTyped(KeyEvent e){}public void keyReleased(KeyEvent e){}});f.setVisible(true);f.setFocusTraversalKeysEnabled(false);}}  This cannot be run with TIO because it uses a graphical interface, but it works on my computer. Pause: 153 Enter: 81 Enter on NumPad: 84 Left Super key: 193 (After disabling the Menu shortcut for my desktop) Right Super key: 201 Insert: 241 Insert on Numpad: 522948 (I don't have one, but that's what you get when you press 5 with Num lock off. When Num lock is on, you get 812.)  # Ungolfed / Explanation: import java.awt.event.*; // KeyListener, KeyEvent import javax.swing.*; // JFrame class F implements KeyListener { public static void main(String[] a) { JFrame f=new JFrame(); // creates a new GUI frame f.addKeyListener(new KeyListener() { // puts a KeyListener in the frame with the following properties: // Method that runs whenever a key is pressed public void keyPressed(KeyEvent e) { // getKeyCode returns an integer that uniquely identifies the key, // but not the location (e.g. LShift and RShift have the same key code) // To fix this, I scale up the key code by 8 and add the location, // which is always 0-4 (Standard, Left, Right, NumPad, or Unknown) // I could have scaled by 5 instead but I wasn't really thinking System.out.print(e.getKeyCode() * 8 + e.getKeyLocation()); // If you want nicer-looking output, just change "print" to "println" } // Method that runs whenever a printable character is typed (does nothing) public void keyTyped(KeyEvent e){} // Method that runs whenever a keyboard key is released (does nothing) public void keyReleased(KeyEvent e){} }); f.setVisible(true); // the frame will only except key presses if it is visible f.setFocusTraversalKeysEnabled(false); // disables "focus traversal" keys (such as Tab) from actually traversing focus } }  • Doesn't look like it works for the tab key? – Poke Jul 13 '17 at 14:40 • setFocusTraversalKeysEnabled(false); in your answer will fix this. – Magic Octopus Urn Jul 13 '17 at 14:43 • @MagicOctopusUrn I don't know what that does and I don't think I want to :P – musicman523 Jul 13 '17 at 14:44 • It makes your answer work for the TAB key, as it stands your answer is invalid without it. – Magic Octopus Urn Jul 13 '17 at 14:45 • Ohhhhh I see - Tab is a "focus traversal key" – musicman523 Jul 13 '17 at 14:46 # Scala 2.10+, 279 chars, 279 bytes Now this is a scala response :) even though it feels like I'm doing Java. Anyway we can't test it on TIO. import scala.swing._ import java.awt.event._ object M extends SimpleSwingApplication{def top=new MainFrame{this.peer.addKeyListener(new KeyListener(){def keyPressed(e:KeyEvent){print(e.getKeyCode+"-"+e.getKeyLocation)} def keyReleased(e:KeyEvent){} def keyTyped(e:KeyEvent){}})}}  It's sad we need to declare all inherited methods even if we don't use them :l can I remove them from byte count, since some compiler flags can permit not declaring them? This prints (as for my html-js response) the keyPressed, "-" and then its "location". For instance : PrtScn -> not verifyable Scroll Lock -> 145-1 Pause -> 19-1 left Shift -> 16-2 right Shift -> 16-3 left Ctrl -> 17-2 right Ctrl -> 17-3 Caps Lock -> 20-1 Tab -> not verifyable Enter -> 10-1 Enter on the number pad -> 10-4 Num Lock -> 144-4 Insert -> 96-1 Ins on the number pad -> 96-4 Backspace -> 8-1 Del -> 127-1 F1...F12 -> 112-1 to 123-1 Esc -> 27-1 left Windows key -> 524-2 right Windows key -> 524-3 Alt -> 18-2 AltGr -> 18-3 (kind of buggy, it detects 17-2 and then 18-3, but it is indeed 18-3) application key (context menu) -> 525-1 Though I think it depends on the computer :/ I'm on an azerty laptop right now. • If you want to not count the unneeded declarations, you might have to include the length of the non-standard compiler flags. Unless old compilers used to default to that? C answers usually need to be compiled with -std=c89 since modern compilers default to c99 or c11, but don't need to count that. So I'm not sure what the ruling would be from code-golf meta. – Peter Cordes Jul 14 '17 at 19:46 # TI-BASIC, 19 bytes PROGRAM:S If Ans Disp Ans getKey prgmS  • Enter: 105, • Left key: 24, • Right key: 26, • Ins[ert] is a little different because it would normally take two key presses to get to, but those would be 21 followed by 23. Here's an illustration of the rest of the keys: Explanation: PROGRAM:S The editor displays the name at the top apart from the code; the name is "S" If Ans // If the last input isn't zero Disp Ans // Display the last input getKey // Input a key press prgmS // Call the same program in a recursive fashion  This, unfortunately, isn't possible to do in Arnold C, so I had to stick to TI-BASIC. • Does it work for every key in that picture? If not which keys does it fail for? – user9206 Jul 15 '17 at 15:10 • Yes, it works for every key except the on button, reserved for killing the program without popping a battery out of the calculator. – bearacuda13 Jul 15 '17 at 15:11 • @bearacuda13: I have an equal calculator that I bought 18 years ago and didn't knew the ON key detail for years. I had being using it since end of university (11 years ago), but who knows... – sergiol Oct 24 '17 at 18:31 # C#, 144 + 601 = 745 bytes Consists of two classes, I couldn't manage to successfully combine them into one class. Main class: namespace System.Windows.Forms{class P:Form{static void Main(){Application.Run(new P());}P(){new Reflection.M().U+=k=>Console.Write(k.f+k.v);}}}  Hook class: namespace System.Reflection{using Runtime.InteropServices;public class M{public delegate void d(s s);event d u;public event d U{add{if(h<1){j=m;h=SetWindowsHookEx(13,j,Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0);}u+=value;}remove{u-=value;}}public struct s{public int v;public int c;public int f;}[DllImport("user32.dll")]static extern int SetWindowsHookEx(int idHook,p lpfn,IntPtr hMod,int dwThreadId);delegate int p(int c,int w,IntPtr l);p j;int h;int m(int c,int w,IntPtr l){if(c>=0&u!=null&(w==257|w==261))u.Invoke((s)Marshal.PtrToStructure(l,typeof(s)));return -1;}}}  Outputs: • Tab: 137 • Pause: 147 • Enter: 141 • NumPad Enter: 142 • Left Windows: 220 • Right Windows: 221 • Insert: 174 • NumPad Insert: 224 • I can get the bytes down a bit by changing || to | and other similar golfs but my brain needs a rest after doing that! – TheLethalCoder Jul 13 '17 at 15:59 • In the Hook class, I think public int v;public int c;public int f; could be shortened to public int v,c,f; – Question Marks Jul 14 '17 at 20:29 • @QuestionMarks Good idea will golf when I get back to a computer – TheLethalCoder Jul 16 '17 at 9:33 # AutoHotkey, 26 Bytes loop{ input,x,L1M send %x% }  Can't test (win-only), but the M option says M: Modified keystrokes such as Control-A through Control-Z are recognized and transcribed if they correspond to real ASCII characters. So it should do fine. # WinApi C (gcc), 156 bytes #include <d3d.h> #define b GetStdHandle(-10) BYTE i[20];main(){SetConsoleMode(b,0);a:ReadConsoleInput(b,i,1,i+5);*i^1||*(i+4)||printf("%X\n",i[10]);goto a;}  This program prints out the Windows Virtual-Key Code assciocated with each keyboard key of input. The \n in the printf format-string is optional (but makes output human-friendly) and can be dropped for a total score of 154 bytes. An easy way to kill the program (without taskmgr) is with CTRL + PAUSE. If you have a keyboard with a Fn key, this program cannot pick it up since it isn't even noticed by Windows. • Credit to MooseBoys's answer for the #include <d3d.h> trick and inspiration for the BYTE array. The program with local variables, readability, and without compiler warnings looks like this: #include <windows.h> #include <stdio.h> int main(void) { HANDLE conIn = GetStdHandle(STD_INPUT_HANDLE); INPUT_RECORD ir; DWORD useless; SetConsoleMode(conIn, 0); for(;;) { ReadConsoleInput(conIn, &ir, 1, &useless); if(ir.EventType == KEY_EVENT && !ir.Event.KeyEvent.bKeyDown) printf("%X\n", ir.Event.KeyEvent.wVirtualKeyCode); } return 0; }  # C (gcc) + Win32, 94 9598105107110 bytes #import"d3d.h" j;f(){for(;;)for(j=191;j--;)GetAsyncKeyState(j)&(j<16||j>18)?printf("%d",j):0;}  The code captures keys even after focus is lost. The following screenshots are recorded adding spaces between outputs (printf("%d ",j); +1 byte) for better readibility: Left-ctrl Left-win Left-alt Space Right-alt Right-win Right-menu Right-ctrl Left-shift Z X C Right-shift Left-shift 1 2 3 Num 1 Num 2 Num 3 Left-shift +/= (on the main part) Num + Left-alt PrtScn The code uses GetAsyncKeyState to query key state without checking message queue, usually more real-time than other user-mode approaches (except DirectInput). This approach is widely used in keyloggers. (j<16||j>18) filters regular Ctrl/Alt/Shift. 16/17/18 is triggered whenever left or right one is pressed, along with location-specified vkey value. # PowerShell, 34 bytes $Host.UI.RawUI.ReadKey().Character
`

Outputs on the same line as the input, which can be a tad confusing.