Skip to content

Commit

Permalink
[WIP] Keys and fix mouse input coordinates
Browse files Browse the repository at this point in the history
Signed-off-by: Squareys <squareys@googlemail.com>
  • Loading branch information
Squareys committed Apr 26, 2019
1 parent d8c65d4 commit cb6eb58
Show file tree
Hide file tree
Showing 3 changed files with 333 additions and 234 deletions.
334 changes: 129 additions & 205 deletions src/Magnum/Platform/EmscriptenApplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,13 @@ void EmscriptenApplication::setupCallbacks() {
};
emscripten_set_mousemove_callback("#canvas", this, false, mouseMoveCallback);

// TODO: Trying to map touch to mouse opened quite a can of worms:
// 1. Tap is already mapped via click by emscripten => mouse press, mouse move, mouse release
// 2. Touch down, move, up is not a tap
// 3. If single touch, everything is clear, second touch-down could be handled with canceling, but
// would require a manual mouse release event. Or we could continue just following the first touch?
//
// Map first touch as left mouse, yes or no?
/*
emscripten_set_touchstart_callback("#canvas", this, false,
[](int, const EmscriptenTouchEvent* event, void* userData) -> Int {
Expand All @@ -214,263 +221,180 @@ void EmscriptenApplication::setupCallbacks() {
reinterpret_cast<EmscriptenApplication*>(userData)->mouseMoveEvent(e);
return e.isAccepted();
});
// TODO: touchcancel event?
// TODO: multiTouchGesture event?
*/

*/
/* Key events on canvas do not get fired since the canvas does not get focussed.
* We listen to window key events instead. */
auto keyPressCallback =
/* keypress_callback does not fire for most of the keys and the modifiers don't seem to work,
* keydown on the other hand works fine for all */
auto keyDownCallback =
[](int, const EmscriptenKeyboardEvent* event, void* userData) -> Int {
KeyEvent e{event};
Debug() << "keypress";
reinterpret_cast<EmscriptenApplication*>(userData)->keyPressEvent(e);
return e.isAccepted();
};
emscripten_set_keypress_callback("#window", this, false, keyPressCallback);
emscripten_set_keydown_callback("#canvas", this, false, keyDownCallback);

auto keyReleaseCallback =
[](int, const EmscriptenKeyboardEvent* event, void* userData) -> Int {
KeyEvent e{event};
reinterpret_cast<EmscriptenApplication*>(userData)->keyReleaseEvent(e);
return e.isAccepted();
};
emscripten_set_keyup_callback("#window", this, false, keyReleaseCallback);
emscripten_set_keyup_callback("#canvas", this, false, keyReleaseCallback);
}

EmscriptenApplication::KeyEvent::Key EmscriptenApplication::KeyEvent::toKey(const EM_UTF8* keyCode) {
Debug() << "keyCode:" << keyCode;
/* A - Z */
if(Utility::String::beginsWith(keyCode, "Key")) {
return Key(keyCode[3] - Int(Key::A));
}
/* Zero - Nine */
if(Utility::String::beginsWith(keyCode, "Digit")) {
return Key(keyCode[5] - Int(Key::Zero));
EmscriptenApplication::KeyEvent::Key EmscriptenApplication::KeyEvent::toKey(const EM_UTF8* key, const EM_UTF8* code) {
// FIXME (Discuss with @mosra)
//
// This code does not seem very pretty
// 1. It's pretty similar to linear search through an array
// 2. It's branchy and hard to read
// 3. Given the event.key() == ? pattern, this would make sense to do _once_
// in the constructor of KeyEvent rather than every key() call
//
// Maybe putting all in a std::unordered_map is better?

const size_t keyLength = strlen(key);
if(keyLength == 0) {
return Key::Unknown;
}
/* ArrowDown - ArrowUp */
if(Utility::String::beginsWith(keyCode, "Arrow")) {
switch(keyCode[5]) {
case 'D': return Key::Down;
case 'L': return Key::Left;
case 'R': return Key::Right;
case 'U': return Key::Up;
default: CORRADE_ASSERT_UNREACHABLE();

/* We use key for a-z as it gives us a keyboard layout respecting
representation of the key, i.e. we get `z` for z depending on layout
where code may give us `y` independent of the layout. */
if(keyLength == 1) {
if(key[0] >= 'a' && key[0] <= 'z') {
return Key(key[0]);

} else if(key[0] >= 'A' && key[0] <= 'Z') {
return Key(key[0] + 32);
}
}

/* We use code for 0-9 as it allows us to differentiate towards Numpad digits.
For digits independent of numpad or not, key is e.g. '0' for Zero */
if(Utility::String::beginsWith(code, "Digit")) {
return Key(code[5]);

/* ArrowDown - ArrowUp */
} else if(Utility::String::beginsWith(code, "Arrow")) {
if(key[5] == 'D') return Key::Down;
if(key[5] == 'L') return Key::Left;
if(key[5] == 'R') return Key::Right;
if(key[5] == 'U') return Key::Up;

/* Numpad keys */
if(Utility::String::beginsWith(keyCode, "Numpad")) {
std::string numKey(keyCode + 6);
} else if(Utility::String::beginsWith(code, "Numpad")) {
std::string numKey(code + 6);
if(numKey == "Add") {
return Key::NumAdd;
}
/* Backspace is not NumBackspace
if(numKey == "Backspace") {
return Key::NumBackspace;
}
if(numKey == "Clear") {
return Key::NumClear;
}
if(numKey == "ClearEntry") {
return Key::NumClearEntry;
}
if(numKey == "Comma") {
return Key::NumComma;
}
*/
if(numKey == "Decimal") {

} else if(numKey == "Decimal") {
return Key::NumDecimal;
}
if(numKey == "Divide") {

} else if(numKey == "Divide") {
return Key::NumDivide;
}
if(numKey == "Enter") {

} else if(numKey == "Enter") {
return Key::NumEnter;
}
if(numKey == "Equal") {

} else if(numKey == "Equal") {
return Key::NumEqual;
}
/*
if(numKey == "Hash") {
return Key::NumHash;
}
if(numKey == "MemoryAdd") {
return Key::NumMemoryAdd;
}
if(numKey == "MemoryClear") {
return Key::NumMemoryClear;
}
if(numKey == "MemoryRecall") {
return Key::NumMemoryRecall;
}
if(numKey == "MemoryStore") {
return Key::NumMemoryStore;
}
if(numKey == "MemorySubtract") {
return Key::NumMemorySubtract;
}
if(numKey == "ParenLeft") {
return Key::NumParenLeft;
}
if(numKey == "ParenRight") {
return Key::NumParenRight;
}
if(numKey == "Star") {
return Key::NumStar;
}
*/
if(numKey == "Multiply") {

} else if(numKey == "Multiply") {
return Key::NumMultiply;
}
if(numKey == "Subtract") {

} else if(numKey == "Subtract") {
return Key::NumSubtract;
}
/* Num0 - Num9 */
Int num = numKey[6] - '0';
if(num >= 0 && num < 9) {
return Key(num + Int(Key::Zero));

/* Numpad0 - Numpad9 */
const Int num = numKey[0] - '0';
if(num >= 0 && num <= 9) {
return Key(num + Int(Key::NumZero));
}

return Key::Unknown;

} else if(strcmp(code, "NumLock") == 0) {
return Key::NumLock;
}

// Uh... I don't know these... map?
if(strcmp(code, "Comma") == 0) return Key::Comma;
if(strcmp(code, "Equal") == 0) return Key::Equal;
if(strcmp(code, "Plus") == 0) return Key::Plus;
if(strcmp(code, "Minus") == 0) return Key::Minus;
if(strcmp(code, "Period") == 0) return Key::Period;
if(strcmp(code, "Quote") == 0) return Key::Quote;
if(strcmp(code, "Slash") == 0) return Key::Slash;
if(strcmp(code, "Backslash") == 0) return Key::Backslash;

// TODO: else if is a thing also
if(strcmp(keyCode, "Backspace") == 0) {
return Key::Backspace;
}
/*
if(strcmp(keyCode, "Backquote") == 0) {
return Key::Backquote;
}
if(strcmp(keyCode, "Backslash") == 0) {
return Key::Backslash;
}
if(strcmp(keyCode, "BracketLeft") == 0) {
return Key::BracketLeft;
}
if(strcmp(keyCode, "BracketRight") == 0) {
return Key::BracketRight;
}
if(strcmp(keyCode, "IntlRo") == 0) {
return Key::IntlRo;
}
if(strcmp(keyCode, "IntlYen") == 0) {
return Key::IntlYen;
}
*/
if(strcmp(keyCode, "Comma") == 0) {
return Key::Comma;
}
if(strcmp(keyCode, "Equal") == 0) {
return Key::Equal;
}
if(strcmp(keyCode, "Minus") == 0) {
return Key::Minus;
}
if(strcmp(keyCode, "Period") == 0) {
return Key::Period;
}
/*
if(strcmp(keyCode, "Quote") == 0) {
return Key::Quote;
}
*/
if(strcmp(keyCode, "Semicolon") == 0) {
return Key::Semicolon;
}
if(strcmp(keyCode, "Slash") == 0) {
return Key::Slash;
}
if(strcmp(keyCode, "AltLeft") == 0) {
return Key::LeftAlt;
}
if(strcmp(keyCode, "AltRight") == 0) {
return Key::RightAlt;
}
if(strcmp(keyCode, "CapsLock") == 0) {
/* Code gives us additional information, e.g. key is "Alt" where code is
"AltLeft" */
if(Utility::String::beginsWith(code, "Alt")) {
return (code[3] == 'L') ? Key::LeftAlt : Key::RightAlt;

} else if(Utility::String::beginsWith(code, "Control")) {
return (code[7] == 'L') ? Key::LeftCtrl : Key::RightCtrl;

} else if(Utility::String::beginsWith(code, "Meta")) {
return (code[4] == 'L') ? Key::LeftSuper : Key::RightSuper;

} else if(Utility::String::beginsWith(code, "Shift")) {
return (code[5] == 'L') ? Key::LeftShift : Key::RightShift;

} else if(strcmp(code, "CapsLock") == 0) {
return Key::CapsLock;
}
if(strcmp(keyCode, "ContextMenu") == 0) {

} else if(strcmp(code, "ContextMenu") == 0) {
return Key::Menu;
}
if(strcmp(keyCode, "ControlLeft") == 0) {
return Key::LeftCtrl;
}
if(strcmp(keyCode, "ControlRight") == 0) {
return Key::RightCtrl;
}
if(strcmp(keyCode, "Enter") == 0) {

} else if(strcmp(code, "Enter") == 0) {
return Key::Enter;
}
if(strcmp(keyCode, "MetaLeft") == 0) {
return Key::LeftSuper;
}
if(strcmp(keyCode, "MetaRight") == 0) {
return Key::RightSuper;
}
if(strcmp(keyCode, "ShiftLeft") == 0) {
return Key::LeftShift;
}
if(strcmp(keyCode, "ShiftRight") == 0) {
return Key::RightShift;
}
if(strcmp(keyCode, "Space") == 0) {

} else if(strcmp(code, "Space") == 0) {
return Key::Space;
}
if(strcmp(keyCode, "Tab") == 0) {

} else if(strcmp(code, "Tab") == 0) {
return Key::Tab;
}
if(strcmp(keyCode, "Delete") == 0) {

} else if(strcmp(code, "Delete") == 0) {
return Key::Delete;
}
if(strcmp(keyCode, "End") == 0) {

} else if(strcmp(code, "End") == 0) {
return Key::End;
}
/*
if(strcmp(keyCode, "Help") == 0) {
return Key::Help;
}
*/
if(strcmp(keyCode, "Home") == 0) {

} else if(strcmp(code, "Home") == 0) {
return Key::Home;
}
if(strcmp(keyCode, "Insert") == 0) {

} else if(strcmp(code, "Insert") == 0) {
return Key::Insert;
}
if(strcmp(keyCode, "PageDown") == 0) {

} else if(strcmp(code, "PageDown") == 0) {
return Key::PageDown;
}
if(strcmp(keyCode, "PageUp") == 0) {

} else if(strcmp(code, "PageUp") == 0) {
return Key::PageUp;
}
if(strcmp(keyCode, "Escape") == 0) {

} else if(strcmp(code, "Escape") == 0) {
return Key::Esc;
}
/*
if(strcmp(keyCode, "Fn") == 0) {
return Key::Fn;
}
if(strcmp(keyCode, "FnLock") == 0) {
return Key::FnLock;
}
*/
if(strcmp(keyCode, "PrintScreen") == 0) {

} else if(strcmp(code, "PrintScreen") == 0) {
return Key::PrintScreen;
}
if(strcmp(keyCode, "ScrollLock") == 0) {

} else if(strcmp(code, "ScrollLock") == 0) {
return Key::ScrollLock;
}
if(strcmp(keyCode, "Pause") == 0) {

} else if(strcmp(code, "Pause") == 0) {
return Key::Pause;
}

/* F1 - F12 */
if(Utility::String::beginsWith(keyCode, "F")) {
if(keyCode[2] != '\0') {
const Int num = keyCode[2] - '0';
if(Utility::String::beginsWith(code, "F")) {
if(code[2] != '\0') {
const Int num = code[2] - '0';
return Key(Int(Key::F10) + num);
}
const Int num = keyCode[1] - '1';
const Int num = code[1] - '1';
return Key(Int(Key::F1) + num);
}

Expand Down
Loading

0 comments on commit cb6eb58

Please sign in to comment.