new KeyboardEvent which will phase out the old CharacterEvent and NonCharacterKeyEvent

This commit is contained in:
Adam D. Ruppe 2015-11-23 17:10:31 -05:00
parent 048a3b39d7
commit 55915e4611
1 changed files with 105 additions and 10 deletions

View File

@ -1611,29 +1611,43 @@ struct RealTimeConsoleInput {
switch(record.EventType) { switch(record.EventType) {
case KEY_EVENT: case KEY_EVENT:
auto ev = record.KeyEvent; auto ev = record.KeyEvent;
KeyboardEvent ke;
CharacterEvent e; CharacterEvent e;
NonCharacterKeyEvent ne; NonCharacterKeyEvent ne;
e.eventType = ev.bKeyDown ? CharacterEvent.Type.Pressed : CharacterEvent.Type.Released; e.eventType = ev.bKeyDown ? CharacterEvent.Type.Pressed : CharacterEvent.Type.Released;
ne.eventType = ev.bKeyDown ? NonCharacterKeyEvent.Type.Pressed : NonCharacterKeyEvent.Type.Released; ne.eventType = ev.bKeyDown ? NonCharacterKeyEvent.Type.Pressed : NonCharacterKeyEvent.Type.Released;
ke.pressed = ev.bKeyDown ? true : false;
// only send released events when specifically requested // only send released events when specifically requested
if(!(flags & ConsoleInputFlags.releasedKeys) && !ev.bKeyDown) if(!(flags & ConsoleInputFlags.releasedKeys) && !ev.bKeyDown)
break; break;
e.modifierState = ev.dwControlKeyState; e.modifierState = ev.dwControlKeyState;
ne.modifierState = ev.dwControlKeyState; ne.modifierState = ev.dwControlKeyState;
ke.modifierState = ev.dwControlKeyState;
if(ev.UnicodeChar) { if(ev.UnicodeChar) {
// new style event goes first
ke.which = cast(dchar) cast(wchar) ev.UnicodeChar;
newEvents ~= InputEvent(ke, terminal);
// old style event then follows as the fallback
e.character = cast(dchar) cast(wchar) ev.UnicodeChar; e.character = cast(dchar) cast(wchar) ev.UnicodeChar;
newEvents ~= InputEvent(e, terminal); newEvents ~= InputEvent(e, terminal);
} else { } else {
// old style event
ne.key = cast(NonCharacterKeyEvent.Key) ev.wVirtualKeyCode; ne.key = cast(NonCharacterKeyEvent.Key) ev.wVirtualKeyCode;
// new style event. See comment on KeyboardEvent.Key
ke.which = cast(KeyboardEvent.Key) (ev.wVirtualKeyCode + 0xF0000);
// FIXME: make this better. the goal is to make sure the key code is a valid enum member // FIXME: make this better. the goal is to make sure the key code is a valid enum member
// Windows sends more keys than Unix and we're doing lowest common denominator here // Windows sends more keys than Unix and we're doing lowest common denominator here
foreach(member; __traits(allMembers, NonCharacterKeyEvent.Key)) foreach(member; __traits(allMembers, NonCharacterKeyEvent.Key))
if(__traits(getMember, NonCharacterKeyEvent.Key, member) == ne.key) { if(__traits(getMember, NonCharacterKeyEvent.Key, member) == ne.key) {
newEvents ~= InputEvent(ke, terminal);
newEvents ~= InputEvent(ne, terminal); newEvents ~= InputEvent(ne, terminal);
break; break;
} }
@ -1729,18 +1743,36 @@ struct RealTimeConsoleInput {
InputEvent[] charPressAndRelease(dchar character) { InputEvent[] charPressAndRelease(dchar character) {
if((flags & ConsoleInputFlags.releasedKeys)) if((flags & ConsoleInputFlags.releasedKeys))
return [ return [
// new style event
InputEvent(KeyboardEvent(true, character, 0), terminal),
InputEvent(KeyboardEvent(false, character, 0), terminal),
// old style event
InputEvent(CharacterEvent(CharacterEvent.Type.Pressed, character, 0), terminal), InputEvent(CharacterEvent(CharacterEvent.Type.Pressed, character, 0), terminal),
InputEvent(CharacterEvent(CharacterEvent.Type.Released, character, 0), terminal), InputEvent(CharacterEvent(CharacterEvent.Type.Released, character, 0), terminal),
]; ];
else return [ InputEvent(CharacterEvent(CharacterEvent.Type.Pressed, character, 0), terminal) ]; else return [
// new style event
InputEvent(KeyboardEvent(true, character, 0), terminal),
// old style event
InputEvent(CharacterEvent(CharacterEvent.Type.Pressed, character, 0), terminal)
];
} }
InputEvent[] keyPressAndRelease(NonCharacterKeyEvent.Key key, uint modifiers = 0) { InputEvent[] keyPressAndRelease(NonCharacterKeyEvent.Key key, uint modifiers = 0) {
if((flags & ConsoleInputFlags.releasedKeys)) if((flags & ConsoleInputFlags.releasedKeys))
return [ return [
// new style event FIXME: when the old events are removed, kill the +0xF0000 from here!
InputEvent(KeyboardEvent(true, cast(dchar)(key) + 0xF0000, modifiers), terminal),
InputEvent(KeyboardEvent(false, cast(dchar)(key) + 0xF0000, modifiers), terminal),
// old style event
InputEvent(NonCharacterKeyEvent(NonCharacterKeyEvent.Type.Pressed, key, modifiers), terminal), InputEvent(NonCharacterKeyEvent(NonCharacterKeyEvent.Type.Pressed, key, modifiers), terminal),
InputEvent(NonCharacterKeyEvent(NonCharacterKeyEvent.Type.Released, key, modifiers), terminal), InputEvent(NonCharacterKeyEvent(NonCharacterKeyEvent.Type.Released, key, modifiers), terminal),
]; ];
else return [ InputEvent(NonCharacterKeyEvent(NonCharacterKeyEvent.Type.Pressed, key, modifiers), terminal) ]; else return [
// new style event FIXME: when the old events are removed, kill the +0xF0000 from here!
InputEvent(KeyboardEvent(true, cast(dchar)(key) + 0xF0000, modifiers), terminal),
// old style event
InputEvent(NonCharacterKeyEvent(NonCharacterKeyEvent.Type.Pressed, key, modifiers), terminal)
];
} }
char[30] sequenceBuffer; char[30] sequenceBuffer;
@ -2072,6 +2104,49 @@ struct RealTimeConsoleInput {
} }
} }
/// The new style of keyboard event
struct KeyboardEvent {
bool pressed;
dchar which;
uint modifierState;
bool isCharacter() {
return !(which >= Key.min && which <= Key.max);
}
// these match Windows virtual key codes numerically for simplicity of translation there
// but are plus a unicode private use area offset so i can cram them in the dchar
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
/// .
enum Key : dchar {
escape = 0x1b + 0xF0000, /// .
F1 = 0x70 + 0xF0000, /// .
F2 = 0x71 + 0xF0000, /// .
F3 = 0x72 + 0xF0000, /// .
F4 = 0x73 + 0xF0000, /// .
F5 = 0x74 + 0xF0000, /// .
F6 = 0x75 + 0xF0000, /// .
F7 = 0x76 + 0xF0000, /// .
F8 = 0x77 + 0xF0000, /// .
F9 = 0x78 + 0xF0000, /// .
F10 = 0x79 + 0xF0000, /// .
F11 = 0x7A + 0xF0000, /// .
F12 = 0x7B + 0xF0000, /// .
LeftArrow = 0x25 + 0xF0000, /// .
RightArrow = 0x27 + 0xF0000, /// .
UpArrow = 0x26 + 0xF0000, /// .
DownArrow = 0x28 + 0xF0000, /// .
Insert = 0x2d + 0xF0000, /// .
Delete = 0x2e + 0xF0000, /// .
Home = 0x24 + 0xF0000, /// .
End = 0x23 + 0xF0000, /// .
PageUp = 0x21 + 0xF0000, /// .
PageDown = 0x22 + 0xF0000, /// .
}
}
/// Input event for characters /// Input event for characters
struct CharacterEvent { struct CharacterEvent {
/// . /// .
@ -2211,6 +2286,7 @@ enum ModifierState : uint {
struct InputEvent { struct InputEvent {
/// . /// .
enum Type { enum Type {
KeyboardEvent, ///.
CharacterEvent, ///. CharacterEvent, ///.
NonCharacterKeyEvent, /// . NonCharacterKeyEvent, /// .
PasteEvent, /// The user pasted some text. Not always available, the pasted text might come as a series of character events instead. PasteEvent, /// The user pasted some text. Not always available, the pasted text might come as a series of character events instead.
@ -2237,6 +2313,8 @@ struct InputEvent {
throw new Exception("Wrong event type"); throw new Exception("Wrong event type");
static if(T == Type.CharacterEvent) static if(T == Type.CharacterEvent)
return characterEvent; return characterEvent;
else static if(T == Type.KeyboardEvent)
return keyboardEvent;
else static if(T == Type.NonCharacterKeyEvent) else static if(T == Type.NonCharacterKeyEvent)
return nonCharacterKeyEvent; return nonCharacterKeyEvent;
else static if(T == Type.PasteEvent) else static if(T == Type.PasteEvent)
@ -2267,6 +2345,10 @@ struct InputEvent {
t = Type.CharacterEvent; t = Type.CharacterEvent;
characterEvent = c; characterEvent = c;
} }
this(KeyboardEvent c, Terminal* p) {
t = Type.KeyboardEvent;
keyboardEvent = c;
}
this(NonCharacterKeyEvent c, Terminal* p) { this(NonCharacterKeyEvent c, Terminal* p) {
t = Type.NonCharacterKeyEvent; t = Type.NonCharacterKeyEvent;
nonCharacterKeyEvent = c; nonCharacterKeyEvent = c;
@ -2300,6 +2382,7 @@ struct InputEvent {
Terminal* term; Terminal* term;
union { union {
KeyboardEvent keyboardEvent;
CharacterEvent characterEvent; CharacterEvent characterEvent;
NonCharacterKeyEvent nonCharacterKeyEvent; NonCharacterKeyEvent nonCharacterKeyEvent;
PasteEvent pasteEvent; PasteEvent pasteEvent;
@ -2367,10 +2450,12 @@ void main() {
auto ev = event.get!(InputEvent.Type.SizeChangedEvent); auto ev = event.get!(InputEvent.Type.SizeChangedEvent);
terminal.writeln(ev); terminal.writeln(ev);
break; break;
case InputEvent.Type.CharacterEvent: case InputEvent.Type.KeyboardEvent:
auto ev = event.get!(InputEvent.Type.CharacterEvent); auto ev = event.get!(InputEvent.Type.KeyboardEvent);
terminal.writef("\t%s\n", ev); terminal.writef("\t%s", ev);
if(ev.character == 'Q') { terminal.writef(" (%s)", cast(KeyboardEvent.Key) ev.which);
terminal.writeln();
if(ev.which == 'Q') {
timeToBreak = true; timeToBreak = true;
version(with_eventloop) { version(with_eventloop) {
import arsd.eventloop; import arsd.eventloop;
@ -2378,10 +2463,14 @@ void main() {
} }
} }
if(ev.character == 'C') if(ev.which == 'C')
terminal.clear(); terminal.clear();
break; break;
case InputEvent.Type.NonCharacterKeyEvent: case InputEvent.Type.CharacterEvent: // obsolete
auto ev = event.get!(InputEvent.Type.CharacterEvent);
terminal.writef("\t%s\n", ev);
break;
case InputEvent.Type.NonCharacterKeyEvent: // obsolete
terminal.writef("\t%s\n", event.get!(InputEvent.Type.NonCharacterKeyEvent)); terminal.writef("\t%s\n", event.get!(InputEvent.Type.NonCharacterKeyEvent));
break; break;
case InputEvent.Type.PasteEvent: case InputEvent.Type.PasteEvent:
@ -3060,11 +3149,11 @@ class LineGetter {
break; break;
case InputEvent.Type.UserInterruptionEvent: case InputEvent.Type.UserInterruptionEvent:
/* I'll take this as canceling the line. */ /* I'll take this as canceling the line. */
throw new Exception("user canceled"); // FIXME throw new UserInterruptionException();
//break; //break;
case InputEvent.Type.HangupEvent: case InputEvent.Type.HangupEvent:
/* I'll take this as canceling the line. */ /* I'll take this as canceling the line. */
throw new Exception("user hanged up"); // FIXME throw new HangupException();
//break; //break;
default: default:
/* ignore. ideally it wouldn't be passed to us anyway! */ /* ignore. ideally it wouldn't be passed to us anyway! */
@ -3336,6 +3425,12 @@ struct ScrollbackBuffer {
} }
class UserInterruptionException : Exception {
this() { super("Ctrl+C"); }
}
class HangupException : Exception {
this() { super("Hup"); }
}