From 224ec1dbe70ffb73a412b5ed890144950559160e Mon Sep 17 00:00:00 2001 From: "simon.kagstrom" Date: Sat, 26 Dec 2009 13:43:42 +0000 Subject: [PATCH] Handle real keyboard input for the virtual keyboard --- virtual_keyboard.cpp | 151 +++++++++++++++++++++++++++++++++---------- virtual_keyboard.hh | 11 +++- 2 files changed, 127 insertions(+), 35 deletions(-) diff --git a/virtual_keyboard.cpp b/virtual_keyboard.cpp index cd67212..2dbba82 100644 --- a/virtual_keyboard.cpp +++ b/virtual_keyboard.cpp @@ -23,6 +23,13 @@ typedef struct virtkey bool is_done; } virtkey_t; +#define INVALID_VIRTKEY ((struct virtkey){NULL, -1, false, false}) + +static inline bool IS_INVALID_VIRTKEY(virtkey_t *k) +{ + return k->name == NULL && k->kc == -1 && + k->is_done == false && k->is_shift == false; +} /* C64 keyboard matrix: @@ -65,9 +72,9 @@ static virtkey_t keys[KEY_COLS * KEY_ROWS] = { static const char *shifted_names[KEY_COLS * KEY_ROWS] = { NULL, "!", "\"", "#", "$", "%", "&", "'", "(", ")", NULL, NULL, NULL, NULL, "Clr", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "[", "]", NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "<", ">", "?", "Up", "Lft", + NULL, "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", NULL, NULL, NULL, NULL, + NULL, NULL, "a", "s", "d", "f", "g", "h", "j", "k", "l", "[", "]", NULL, NULL, + NULL, NULL, NULL, "z", "x", "c", "v", "b", "n", "m", "<", ">", "?", "Up", "Lft", NULL, NULL, NULL, NULL, NULL, NULL, "f2", "f4", "f6", "f8", "Ins", NULL, NULL, NULL, NULL, }; @@ -80,8 +87,10 @@ VirtualKeyboard::VirtualKeyboard(Font *font) : GuiView() this->is_active = false; this->buf_head = 0; + this->buf_len = 255; + this->buf = (struct virtkey*)xmalloc(sizeof(struct virtkey) * this->buf_len); + memset(this->buf, 0, sizeof(struct virtkey) * this->buf_len); - memset(this->buf, 0, sizeof(this->buf)); this->flushListeners(); } @@ -205,6 +214,36 @@ int VirtualKeyboard::charToKeycode(char c) return -1; } +virtkey_t VirtualKeyboard::eventToVirtkey(event_t ev) +{ + char c = (char)ev; + + for (int i = 0; i < KEY_COLS * KEY_ROWS; i++) + { + virtkey_t key = keys[i]; + + if (key.name != NULL) + { + if (strlen(key.name) == 1) + { + if (key.name[0] == c) + return key; + if (shifted_names[i] && strlen(shifted_names[i]) == 1 && + shifted_names[i][0] == c) + return key; + } + + /* OK, ugly special cases, but these are pretty important */ + if ( (c == ' ' && strcmp(key.name, "space") == 0) || + (c == '\n' && strcmp(key.name, "Ret") == 0) ) + return key; + } + } + + return INVALID_VIRTKEY; +} + + const char VirtualKeyboard::keycodeToChar(int kc) { const char *s = this->keycodeToString(kc); @@ -253,7 +292,7 @@ void VirtualKeyboard::unregisterListener(KeyboardListener *kl) void VirtualKeyboard::activate() { this->is_active = true; - memset(this->buf, 0, sizeof(this->buf)); + memset(this->buf, 0, sizeof(struct virtkey) * this->buf_len); this->buf_head = 0; } @@ -261,6 +300,7 @@ void VirtualKeyboard::activate() void VirtualKeyboard::runLogic() { event_t ev; + virtkey_t ev_key; if (!this->is_active) return; @@ -269,6 +309,12 @@ void VirtualKeyboard::runLogic() if (ev == EVENT_NONE) return; + /* Something was typed on the keyboard */ + ev_key = this->eventToVirtkey(ev); + if ( !IS_INVALID_VIRTKEY(&ev_key) ) { + this->pushKey(&ev_key); + } + if (ev & KEY_UP) this->selectNext(0, -1); else if (ev & KEY_DOWN) @@ -288,46 +334,36 @@ void VirtualKeyboard::runLogic() if (key->is_shift == true) this->toggleShift(); - else if (key->is_done) - { - int n_listeners = sizeof(this->listeners) / sizeof(*this->listeners); - - for (int i = 0; i < n_listeners; i++) - { - if (this->listeners[i]) - this->listeners[i]->stringCallback(this->buf); - } - /* We're done! */ - this->deactivate(); - } + else if (key->is_done) /* We're done! */ + this->done(); else if (strcmp(key->name, "Del") == 0) { if (this->buf_head > 1) { - this->buf[this->buf_head - 1] = ' '; + this->buf[this->buf_head - 1] = (struct virtkey){NULL, -1, false, false}; this->buf_head -= 2; } } else - { - int n_listeners = sizeof(this->listeners) / sizeof(*this->listeners); - char c; + this->pushKey(key); + } +} - /* Add to buf */ - c = this->keycodeToChar( this->shift_on ? key->kc | 0x80 : key->kc ); +void VirtualKeyboard::pushKey(struct virtkey *vk) +{ + int n_listeners = sizeof(this->listeners) / sizeof(*this->listeners); - this->buf[this->buf_head] = c; + /* Add to buf */ + this->buf[this->buf_head] = *vk; - this->buf_head++; - if (this->buf_head >= sizeof(this->buf) - 1) - this->buf_head = 0; /* OK, not good, but well... */ - for (int i = 0; i < n_listeners; i++) - { - if (this->listeners[i]) - this->listeners[i]->keyCallback(this->shift_on, - key->name); - } - } + this->buf_head++; + if (this->buf_head >= this->buf_len - 1) + this->buf_head = 0; /* OK, not good, but well... */ + for (int i = 0; i < n_listeners; i++) + { + if (this->listeners[i]) + this->listeners[i]->keyCallback(this->shift_on, + vk->name); } } @@ -343,6 +379,23 @@ void VirtualKeyboard::deactivate() Gui::gui->popView(); } +void VirtualKeyboard::done() +{ + int n_listeners = sizeof(this->listeners) / sizeof(*this->listeners); + char *buf = (char *)xmalloc(this->buf_head + 1); + + for (unsigned i = 0; i < this->buf_head; i++) + buf[i] = this->keycodeToChar(this->buf[i].kc); + + for (int i = 0; i < n_listeners; i++) + { + if (this->listeners[i]) + this->listeners[i]->stringCallback(buf); + } + free(buf); + this->deactivate(); +} + void VirtualKeyboard::draw(SDL_Surface *where) { this->draw(where, 20, 240, 600, 240); @@ -353,6 +406,36 @@ void VirtualKeyboard::updateTheme() this->setFont(Gui::gui->small_font); } +void VirtualKeyboard::pushEvent(SDL_Event *ev) +{ + switch(ev->type) + { + case SDL_KEYDOWN: + switch (ev->key.keysym.sym) + { + case SDLK_UP: + case SDLK_DOWN: + case SDLK_LEFT: + case SDLK_RIGHT: + case SDLK_PAGEDOWN: + case SDLK_PAGEUP: + case SDLK_RETURN: + case SDLK_HOME: + case SDLK_ESCAPE: + /* Handle via the standard widget implementation (except for space) */ + Widget::pushEvent(ev); + return; + case SDLK_SPACE ... SDLK_z: + Widget::pushEvent((event_t)(ev->key.keysym.sym)); + default: + break; + } + default: + break; + + } +} + /* The singleton */ VirtualKeyboard *VirtualKeyboard::kbd; diff --git a/virtual_keyboard.hh b/virtual_keyboard.hh index fa20c23..fb11c47 100644 --- a/virtual_keyboard.hh +++ b/virtual_keyboard.hh @@ -48,6 +48,7 @@ public: const char keycodeToChar(int kc); int charToKeycode(char c); int stringToKeycode(const char *str); + struct virtkey eventToVirtkey(event_t ev); void activate(); @@ -71,14 +72,21 @@ public: void draw(SDL_Surface *where, int x, int y, int w, int h); + void pushEvent(SDL_Event *ev); + /* Singleton object */ static VirtualKeyboard *kbd; private: KeyboardListener *listeners[8]; void selectNext(int dx, int dy); + void toggleShift(); + void pushKey(struct virtkey *vk); + + void done(); + void flushListeners(); Font *font; @@ -87,8 +95,9 @@ private: bool shift_on; bool is_active; - char buf[255]; + struct virtkey *buf; unsigned buf_head; + size_t buf_len; }; #endif /* __VIRTUAL_KEYBORD_HH__ */