mirror of
https://github.com/Oibaf66/frodo-wii.git
synced 2024-11-26 13:34:22 +01:00
Handle real keyboard input for the virtual keyboard
This commit is contained in:
parent
2c359032c2
commit
224ec1dbe7
@ -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
|
||||
this->pushKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualKeyboard::pushKey(struct virtkey *vk)
|
||||
{
|
||||
int n_listeners = sizeof(this->listeners) / sizeof(*this->listeners);
|
||||
char c;
|
||||
|
||||
/* Add to buf */
|
||||
c = this->keycodeToChar( this->shift_on ? key->kc | 0x80 : key->kc );
|
||||
|
||||
this->buf[this->buf_head] = c;
|
||||
this->buf[this->buf_head] = *vk;
|
||||
|
||||
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... */
|
||||
for (int i = 0; i < n_listeners; i++)
|
||||
{
|
||||
if (this->listeners[i])
|
||||
this->listeners[i]->keyCallback(this->shift_on,
|
||||
key->name);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
|
@ -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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user