Handle real keyboard input for the virtual keyboard

This commit is contained in:
simon.kagstrom 2009-12-26 13:43:42 +00:00
parent 2c359032c2
commit 224ec1dbe7
2 changed files with 127 additions and 35 deletions

View File

@ -23,6 +23,13 @@ typedef struct virtkey
bool is_done; bool is_done;
} virtkey_t; } 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: C64 keyboard matrix:
@ -65,9 +72,9 @@ static virtkey_t keys[KEY_COLS * KEY_ROWS] = {
static const char *shifted_names[KEY_COLS * KEY_ROWS] = { static const char *shifted_names[KEY_COLS * KEY_ROWS] = {
NULL, "!", "\"", "#", "$", "%", "&", "'", "(", ")", NULL, NULL, NULL, NULL, "Clr", NULL, "!", "\"", "#", "$", "%", "&", "'", "(", ")", NULL, NULL, NULL, NULL, "Clr",
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "[", "]", NULL, NULL, NULL, NULL, "a", "s", "d", "f", "g", "h", "j", "k", "l", "[", "]", NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "<", ">", "?", "Up", "Lft", 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, 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->is_active = false;
this->buf_head = 0; 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(); this->flushListeners();
} }
@ -205,6 +214,36 @@ int VirtualKeyboard::charToKeycode(char c)
return -1; 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 VirtualKeyboard::keycodeToChar(int kc)
{ {
const char *s = this->keycodeToString(kc); const char *s = this->keycodeToString(kc);
@ -253,7 +292,7 @@ void VirtualKeyboard::unregisterListener(KeyboardListener *kl)
void VirtualKeyboard::activate() void VirtualKeyboard::activate()
{ {
this->is_active = true; 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; this->buf_head = 0;
} }
@ -261,6 +300,7 @@ void VirtualKeyboard::activate()
void VirtualKeyboard::runLogic() void VirtualKeyboard::runLogic()
{ {
event_t ev; event_t ev;
virtkey_t ev_key;
if (!this->is_active) if (!this->is_active)
return; return;
@ -269,6 +309,12 @@ void VirtualKeyboard::runLogic()
if (ev == EVENT_NONE) if (ev == EVENT_NONE)
return; 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) if (ev & KEY_UP)
this->selectNext(0, -1); this->selectNext(0, -1);
else if (ev & KEY_DOWN) else if (ev & KEY_DOWN)
@ -288,46 +334,36 @@ void VirtualKeyboard::runLogic()
if (key->is_shift == true) if (key->is_shift == true)
this->toggleShift(); this->toggleShift();
else if (key->is_done) else if (key->is_done) /* We're done! */
{ this->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 (strcmp(key->name, "Del") == 0) else if (strcmp(key->name, "Del") == 0)
{ {
if (this->buf_head > 1) 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; this->buf_head -= 2;
} }
} }
else else
{ this->pushKey(key);
int n_listeners = sizeof(this->listeners) / sizeof(*this->listeners); }
char c; }
/* Add to buf */ void VirtualKeyboard::pushKey(struct virtkey *vk)
c = this->keycodeToChar( this->shift_on ? key->kc | 0x80 : key->kc ); {
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++; this->buf_head++;
if (this->buf_head >= sizeof(this->buf) - 1) if (this->buf_head >= this->buf_len - 1)
this->buf_head = 0; /* OK, not good, but well... */ this->buf_head = 0; /* OK, not good, but well... */
for (int i = 0; i < n_listeners; i++) for (int i = 0; i < n_listeners; i++)
{ {
if (this->listeners[i]) if (this->listeners[i])
this->listeners[i]->keyCallback(this->shift_on, this->listeners[i]->keyCallback(this->shift_on,
key->name); vk->name);
}
}
} }
} }
@ -343,6 +379,23 @@ void VirtualKeyboard::deactivate()
Gui::gui->popView(); 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) void VirtualKeyboard::draw(SDL_Surface *where)
{ {
this->draw(where, 20, 240, 600, 240); this->draw(where, 20, 240, 600, 240);
@ -353,6 +406,36 @@ void VirtualKeyboard::updateTheme()
this->setFont(Gui::gui->small_font); 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 */ /* The singleton */
VirtualKeyboard *VirtualKeyboard::kbd; VirtualKeyboard *VirtualKeyboard::kbd;

View File

@ -48,6 +48,7 @@ public:
const char keycodeToChar(int kc); const char keycodeToChar(int kc);
int charToKeycode(char c); int charToKeycode(char c);
int stringToKeycode(const char *str); int stringToKeycode(const char *str);
struct virtkey eventToVirtkey(event_t ev);
void activate(); void activate();
@ -71,14 +72,21 @@ public:
void draw(SDL_Surface *where, int x, int y, int w, int h); void draw(SDL_Surface *where, int x, int y, int w, int h);
void pushEvent(SDL_Event *ev);
/* Singleton object */ /* Singleton object */
static VirtualKeyboard *kbd; static VirtualKeyboard *kbd;
private: private:
KeyboardListener *listeners[8]; KeyboardListener *listeners[8];
void selectNext(int dx, int dy); void selectNext(int dx, int dy);
void toggleShift(); void toggleShift();
void pushKey(struct virtkey *vk);
void done();
void flushListeners(); void flushListeners();
Font *font; Font *font;
@ -87,8 +95,9 @@ private:
bool shift_on; bool shift_on;
bool is_active; bool is_active;
char buf[255]; struct virtkey *buf;
unsigned buf_head; unsigned buf_head;
size_t buf_len;
}; };
#endif /* __VIRTUAL_KEYBORD_HH__ */ #endif /* __VIRTUAL_KEYBORD_HH__ */