mirror of https://github.com/adamdruppe/arsd.git
new KeyboardEvent which will phase out the old CharacterEvent and NonCharacterKeyEvent
This commit is contained in:
parent
048a3b39d7
commit
55915e4611
115
terminal.d
115
terminal.d
|
@ -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"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue