|
|
452870 |
|
|
|
452870 |
#include "app.h"
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
|
|
|
843e7a |
int keyInit(Key *k, Layout *l) {
|
|
|
843e7a |
k->l = l;
|
|
|
452870 |
k->down = 0;
|
|
|
843e7a |
k->downKeycode = 0;
|
|
|
843e7a |
k->mx = k->my = 0;
|
|
|
63daec |
k->isLetter = k->isKeypad = 0;
|
|
|
061fcf |
k->x = k->y = k->w = k->h = 0;
|
|
|
63daec |
|
|
|
63daec |
inputPrepareKeysyms(&k->keySym, &k->keySym2, &k->isLetter, &k->isKeypad);
|
|
|
63daec |
if (!k->label[0]) keysymString(k->keySym, k->label);
|
|
|
63daec |
if (!k->label2[0]) keysymString(k->keySym2, k->label2);
|
|
|
63daec |
|
|
|
843e7a |
textLayoutInit(&k->tl, &k->l->kbd->app->graph, k->label);
|
|
|
061fcf |
textLayoutInit(&k->tl2, &k->l->kbd->app->graph, k->label2);
|
|
|
452870 |
|
|
|
452870 |
return 1;
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
void keyDeinit(Key *k) {
|
|
|
843e7a |
keyUp(k, 1);
|
|
|
843e7a |
textLayoutDeinit(&k->tl);
|
|
|
843e7a |
textLayoutDeinit(&k->tl2);
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
void keyDraw(Key *k, int cx, int cy, int cw, int ch) {
|
|
|
452870 |
if ( k->x + k->w <= cx || k->x >= cx + cw
|
|
|
452870 |
|| k->y + k->h <= cy || k->y >= cy + ch ) return;
|
|
|
843e7a |
|
|
|
63daec |
App *app = k->l->kbd->app;
|
|
|
63daec |
|
|
|
63daec |
int active = k->down;
|
|
|
63daec |
if (k->flags & KF_MOD)
|
|
|
63daec |
active = (app->input.modifiers & (unsigned int)k->optValue);
|
|
|
843e7a |
|
|
|
843e7a |
graphDrawButton(&k->l->kbd->app->graph, k->x, k->y, k->w, k->h, active);
|
|
|
843e7a |
|
|
|
843e7a |
TextLayout *tl = &k->tl;
|
|
|
843e7a |
TextLayout *tl2 = &k->tl2;
|
|
|
63daec |
if (inputChooseKeysym(app->input.modifiers, k->keySym, k->keySym2, k->isLetter, k->isKeypad))
|
|
|
63daec |
tl = tl2, tl2 = &k->tl; // swap labels
|
|
|
843e7a |
|
|
|
061fcf |
int lx, lx2, ly, ly2;
|
|
|
061fcf |
lx = lx2 = k->x + k->w/2;
|
|
|
061fcf |
ly = ly2 = k->y + k->h/2;
|
|
|
061fcf |
if (!k->isLetter && k->label2[0]) {
|
|
|
061fcf |
int dx = k->w/6;
|
|
|
061fcf |
int dy = k->h/6;
|
|
|
061fcf |
lx -= dx;
|
|
|
061fcf |
ly += dy;
|
|
|
061fcf |
lx2 += dx;
|
|
|
061fcf |
ly2 -= dy;
|
|
|
843e7a |
}
|
|
|
061fcf |
|
|
|
061fcf |
textLayoutDraw(tl, lx, ly, active);
|
|
|
061fcf |
if (!k->isLetter)
|
|
|
061fcf |
textLayoutDraw(tl2, lx2, ly2, active);
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
843e7a |
void keyDown(Key *k, int x, int y) {
|
|
|
843e7a |
if (k->down == 2) k->down = 1;
|
|
|
843e7a |
if (k->down) return;
|
|
|
843e7a |
|
|
|
843e7a |
Keyboard *kbd = k->l->kbd;
|
|
|
452870 |
k->down = 1;
|
|
|
843e7a |
|
|
|
63daec |
if (k->flags & KF_MOVE) {
|
|
|
63daec |
k->mx = x;
|
|
|
63daec |
k->my = y;
|
|
|
63daec |
} else
|
|
|
63daec |
if (k->flags & KF_SIZE) {
|
|
|
63daec |
k->mx = kbd->app->w - x;
|
|
|
63daec |
k->my = kbd->app->h - y;
|
|
|
843e7a |
}
|
|
|
63daec |
|
|
|
843e7a |
if (k->flags & KF_HOLD) {
|
|
|
843e7a |
k->down = 2;
|
|
|
843e7a |
// insert to held list
|
|
|
843e7a |
if (!k->prevHeld && !k->nextHeld && kbd->firstHeld != k) {
|
|
|
843e7a |
k->nextHeld = kbd->firstHeld;
|
|
|
843e7a |
if (k->nextHeld) k->nextHeld->prevHeld = k;
|
|
|
843e7a |
kbd->firstHeld = k;
|
|
|
843e7a |
}
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
// choose keySym
|
|
|
63daec |
unsigned int keySym = inputChooseKeysym(kbd->app->input.modifiers, k->keySym, k->keySym2, k->isLetter, k->isKeypad)
|
|
|
63daec |
? k->keySym2 : k->keySym;
|
|
|
843e7a |
|
|
|
63daec |
// press
|
|
|
843e7a |
if (keySym) {
|
|
|
843e7a |
k->downKeycode = inputKeycode(&kbd->app->input, keySym);
|
|
|
843e7a |
if (k->downKeycode) inputEvent(&kbd->app->input, k->downKeycode, 1);
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
// redraw
|
|
|
843e7a |
appInvalidateRect(kbd->app, k->x, k->y, k->w, k->h);
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
843e7a |
void keyMotion(Key *k, int x, int y) {
|
|
|
843e7a |
App *app = k->l->kbd->app;
|
|
|
843e7a |
if (k->flags & KF_MOVE) {
|
|
|
63daec |
appMove(app, app->x + x - k->mx, app->y + y - k->my, app->w, app->h);
|
|
|
843e7a |
} else
|
|
|
843e7a |
if (k->flags & KF_SIZE) {
|
|
|
63daec |
appMove(app, app->x, app->y, x + k->mx, y + k->my);
|
|
|
843e7a |
}
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
843e7a |
void keyUp(Key *k, int force) {
|
|
|
843e7a |
if (!force && k->down != 1) return;
|
|
|
843e7a |
|
|
|
843e7a |
Keyboard *kbd = k->l->kbd;
|
|
|
843e7a |
int wasDown = k->down;
|
|
|
452870 |
k->down = 0;
|
|
|
843e7a |
|
|
|
843e7a |
// release key
|
|
|
843e7a |
if (k->downKeycode) {
|
|
|
843e7a |
inputEvent(&kbd->app->input, k->downKeycode, 0);
|
|
|
843e7a |
k->downKeycode = 0;
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
// remove from held list
|
|
|
843e7a |
if (k->prevHeld || k->nextHeld || kbd->firstHeld == k) {
|
|
|
843e7a |
if (k->nextHeld) k->nextHeld->prevHeld = k->prevHeld;
|
|
|
843e7a |
if (k->prevHeld) k->prevHeld->nextHeld = k; else kbd->firstHeld = k->nextHeld;
|
|
|
843e7a |
k->nextHeld = k->prevHeld = NULL;
|
|
|
843e7a |
}
|
|
|
63daec |
|
|
|
63daec |
// following action should be done only for real button up
|
|
|
63daec |
if (!wasDown)
|
|
|
63daec |
return;
|
|
|
63daec |
|
|
|
63daec |
if (k->flags & KF_CLOSE)
|
|
|
63daec |
appStop(kbd->app, 0);
|
|
|
63daec |
if (k->flags & KF_LAYOUT)
|
|
|
63daec |
keyboardSwitchLayout(kbd, k->optValue);
|
|
|
843e7a |
|
|
|
843e7a |
// on releasing a regular key release all held special keys
|
|
|
63daec |
if (!force && !k->flags)
|
|
|
843e7a |
keyboardRelaseHeld(kbd);
|
|
|
843e7a |
|
|
|
843e7a |
// redraw
|
|
|
63daec |
appInvalidateRect(kbd->app, k->x, k->y, k->w, k->h);
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
843e7a |
int layoutInit(Layout *l, Keyboard *kbd) {
|
|
|
843e7a |
LOGDBG("layout: init");
|
|
|
843e7a |
l->kbd = kbd;
|
|
|
843e7a |
l->prev = NULL;
|
|
|
843e7a |
l->downKey = NULL;
|
|
|
061fcf |
l->w = l->h = 0;
|
|
|
63daec |
|
|
|
63daec |
if (!l->keysCount)
|
|
|
63daec |
return 1;
|
|
|
63daec |
|
|
|
63daec |
// fix keys coords
|
|
|
63daec |
Key *k = &l->keys[0];
|
|
|
061fcf |
int x0 = k->ox;
|
|
|
061fcf |
int y0 = k->oy;
|
|
|
061fcf |
int x1 = x0 + k->ow;
|
|
|
061fcf |
int y1 = y0 + k->oh;
|
|
|
63daec |
for(int i = 1; i < l->keysCount; ++i) {
|
|
|
63daec |
k = &l->keys[i];
|
|
|
63daec |
Key *p = k - 1;
|
|
|
63daec |
|
|
|
63daec |
// coord < 0 means relative offset from previos key -1
|
|
|
63daec |
// zero coord of size means copy value from previous key
|
|
|
061fcf |
if (!k->ox) k->ox = p->ox; else
|
|
|
061fcf |
if (k->ox < 0) k->ox = p->ox + p->ow - k->ox - 1;
|
|
|
061fcf |
if (!k->oy) k->oy = p->oy; else
|
|
|
061fcf |
if (k->oy < 0) k->oy = p->oy + p->oh - k->oy - 1;
|
|
|
061fcf |
if (!k->ow) k->ow = p->ow;
|
|
|
061fcf |
if (!k->oh) k->oh = p->oh;
|
|
|
63daec |
|
|
|
63daec |
// calc bounds
|
|
|
061fcf |
if (x0 > k->ox) x0 = k->ox;
|
|
|
061fcf |
if (y0 > k->oy) y0 = k->oy;
|
|
|
061fcf |
if (x1 < k->ox + k->ow) x1 = k->ox + k->ow;
|
|
|
061fcf |
if (y1 < k->oy + k->oh) y1 = k->oy + k->oh;
|
|
|
63daec |
}
|
|
|
63daec |
|
|
|
63daec |
// fix layout size
|
|
|
061fcf |
if (!l->ow) l->ow = x1 + x0;
|
|
|
061fcf |
if (!l->oh) l->oh = y1 + y0;
|
|
|
061fcf |
LOGDBG("layout: init: size x0=%d y0=%d x1=%d y1=%d w=%d h=%d", x0, y0, x1, y1, l->ow, l->oh);
|
|
|
63daec |
|
|
|
63daec |
// init keys
|
|
|
061fcf |
for(int i = 0; i < l->keysCount; ++i) {
|
|
|
843e7a |
if (!keyInit(&l->keys[i], l)) {
|
|
|
843e7a |
for(--i; i >= 0; --i) keyDeinit(&l->keys[i]);
|
|
|
843e7a |
return 0;
|
|
|
843e7a |
}
|
|
|
061fcf |
}
|
|
|
061fcf |
|
|
|
843e7a |
return 1;
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
843e7a |
void layoutDeinit(Layout *l) {
|
|
|
843e7a |
LOGDBG("layout: deinit");
|
|
|
843e7a |
layoutMouseUp(l);
|
|
|
843e7a |
for(int i = 0; i < l->keysCount; ++i)
|
|
|
843e7a |
keyDeinit(&l->keys[i]);
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
061fcf |
void layoutResize(Layout *l) {
|
|
|
061fcf |
if (l->w == l->kbd->app->w && l->h == l->kbd->app->h) return;
|
|
|
061fcf |
LOGDBG("layout: resize w=%d h=%d", l->kbd->app->w, l->kbd->app->h);
|
|
|
061fcf |
l->w = l->kbd->app->w;
|
|
|
061fcf |
l->h = l->kbd->app->h;
|
|
|
061fcf |
float kx = l->w/(float)l->ow;
|
|
|
061fcf |
float ky = l->h/(float)l->oh;
|
|
|
061fcf |
for(int i = 0; i < l->keysCount; ++i) {
|
|
|
061fcf |
Key *k = &l->keys[i];
|
|
|
061fcf |
k->x = (int)(k->ox*kx + 0.5f);
|
|
|
061fcf |
k->y = (int)(k->oy*ky + 0.5f);
|
|
|
061fcf |
k->w = (int)(k->ow*kx + 0.5f);
|
|
|
061fcf |
k->h = (int)(k->oh*ky + 0.5f);
|
|
|
061fcf |
}
|
|
|
061fcf |
}
|
|
|
061fcf |
|
|
|
061fcf |
|
|
|
843e7a |
void layoutDraw(Layout *l, int cx, int cy, int cw, int ch) {
|
|
|
843e7a |
for(int i = 0; i < l->keysCount; ++i)
|
|
|
843e7a |
keyDraw(&l->keys[i], cx, cy, cw, ch);
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
843e7a |
void layoutMouseDown(Layout *l, int x, int y) {
|
|
|
843e7a |
LOGDBG("layout: mouse down: x=%d y=%d", x, y);
|
|
|
843e7a |
for(int i = l->keysCount - 1; i >= 0; --i) {
|
|
|
843e7a |
Key *k = &l->keys[i];
|
|
|
843e7a |
if ( k->x <= x && x < k->x + k->w
|
|
|
843e7a |
&& k->y <= y && y < k->y + k->h )
|
|
|
843e7a |
{
|
|
|
843e7a |
if (l->downKey != k) {
|
|
|
843e7a |
layoutMouseUp(l);
|
|
|
843e7a |
l->downKey = k;
|
|
|
843e7a |
keyDown(k, x, y);
|
|
|
843e7a |
}
|
|
|
843e7a |
break;
|
|
|
843e7a |
}
|
|
|
843e7a |
}
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
843e7a |
void layoutMouseMotion(Layout *l, int x, int y) {
|
|
|
843e7a |
LOGDBG("layout: mouse motion: x=%d y=%d", x, y);
|
|
|
843e7a |
if (!l->downKey) return;
|
|
|
843e7a |
keyMotion(l->downKey, x, y);
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
843e7a |
void layoutMouseUp(Layout *l) {
|
|
|
843e7a |
LOGDBG("layout: mouse up");
|
|
|
843e7a |
if (!l->downKey) return;
|
|
|
843e7a |
keyUp(l->downKey, 0);
|
|
|
843e7a |
l->downKey = NULL;
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
int keyboardInit(Keyboard *kbd, App *app) {
|
|
|
452870 |
LOGDBG("keyboard: init");
|
|
|
452870 |
kbd->app = app;
|
|
|
843e7a |
kbd->firstHeld = NULL;
|
|
|
061fcf |
kbd->lastModifiers = kbd->app->input.modifiers;
|
|
|
843e7a |
kbd->current = kbd->layoutsCount > 0 ? kbd->layouts : NULL;
|
|
|
63daec |
|
|
|
843e7a |
for(int i = 0; i < kbd->layoutsCount; ++i) {
|
|
|
843e7a |
if (!layoutInit(&kbd->layouts[i], kbd)) {
|
|
|
843e7a |
for(--i; i >= 0; --i) layoutDeinit(&kbd->layouts[i]);
|
|
|
452870 |
return 0;
|
|
|
452870 |
}
|
|
|
843e7a |
}
|
|
|
63daec |
|
|
|
63daec |
// fix size
|
|
|
63daec |
for(int i = 0; i < kbd->layoutsCount; ++i) {
|
|
|
061fcf |
if (kbd->ow < kbd->layouts[i].ow) kbd->ow = kbd->layouts[i].ow;
|
|
|
061fcf |
if (kbd->oh < kbd->layouts[i].oh) kbd->oh = kbd->layouts[i].oh;
|
|
|
63daec |
}
|
|
|
061fcf |
LOGDBG("keyboard: init: size ow=%d oh=%d", kbd->ow, kbd->oh);
|
|
|
63daec |
|
|
|
061fcf |
//appMove(app, app->x, app->y, kbd->ow, kbd->oh);
|
|
|
452870 |
return 1;
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
void keyboardDeinit(Keyboard *kbd) {
|
|
|
452870 |
LOGDBG("keyboard: deinit");
|
|
|
452870 |
keyboardMouseUp(kbd);
|
|
|
843e7a |
for(int i = 0; i < kbd->layoutsCount; ++i)
|
|
|
843e7a |
layoutDeinit(&kbd->layouts[i]);
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
843e7a |
void keyboardResize(Keyboard *kbd) {
|
|
|
061fcf |
if (kbd->current)
|
|
|
061fcf |
layoutResize(kbd->current);
|
|
|
061fcf |
}
|
|
|
061fcf |
|
|
|
061fcf |
|
|
|
061fcf |
void keyboardUpdateModifiers(Keyboard* kbd) {
|
|
|
061fcf |
if (kbd->lastModifiers == kbd->app->input.modifiers) return;
|
|
|
061fcf |
LOGDBG("keyboard: update modifiers");
|
|
|
061fcf |
kbd->lastModifiers = kbd->app->input.modifiers;
|
|
|
061fcf |
appInvalidateRect(kbd->app, 0, 0, kbd->app->w, kbd->app->h);
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
void keyboardDraw(Keyboard *kbd, int cx, int cy, int cw, int ch) {
|
|
|
843e7a |
if (!kbd->current) return;
|
|
|
843e7a |
layoutDraw(kbd->current, cx, cy, cw, ch);
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
void keyboardMouseDown(Keyboard *kbd, int x, int y) {
|
|
|
843e7a |
LOGDBG("keyboard: mouse down: x=%d y=%d", x, y);
|
|
|
843e7a |
if (!kbd->current) return;
|
|
|
843e7a |
layoutMouseDown(kbd->current, x, y);
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
843e7a |
void keyboardMouseMotion(Keyboard *kbd, int x, int y) {
|
|
|
843e7a |
LOGDBG("keyboard: mouse motion: x=%d y=%d", x, y);
|
|
|
843e7a |
if (!kbd->current) return;
|
|
|
843e7a |
layoutMouseMotion(kbd->current, x, y);
|
|
|
452870 |
}
|
|
|
452870 |
|
|
|
452870 |
|
|
|
452870 |
void keyboardMouseUp(Keyboard *kbd) {
|
|
|
843e7a |
LOGDBG("keyboard: mouse up");
|
|
|
843e7a |
if (!kbd->current) return;
|
|
|
843e7a |
layoutMouseUp(kbd->current);
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
843e7a |
void keyboardRelaseHeld(Keyboard *kbd) {
|
|
|
843e7a |
LOGDBG("keyboard: release held");
|
|
|
843e7a |
while(kbd->firstHeld) keyUp(kbd->firstHeld, 1);
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
|
|
|
843e7a |
void keyboardSwitchLayout(Keyboard *kbd, int index) {
|
|
|
843e7a |
LOGDBG("keyboard: switch layout");
|
|
|
843e7a |
|
|
|
843e7a |
if (!kbd->layoutsCount) return;
|
|
|
843e7a |
|
|
|
843e7a |
if (index == LI_PREV) {
|
|
|
843e7a |
index = kbd->current ? kbd->current - kbd->layouts - 1: 0;
|
|
|
d3e9d7 |
if (index < 0) index = kbd->layoutsCount - 1;
|
|
|
843e7a |
} else
|
|
|
843e7a |
if (index == LI_NEXT) {
|
|
|
d3e9d7 |
index = kbd->current ? kbd->current - kbd->layouts + 1: 0;
|
|
|
d3e9d7 |
if (index >= kbd->layoutsCount) index = 0;
|
|
|
843e7a |
} else
|
|
|
843e7a |
if (index == LI_REVERT) {
|
|
|
843e7a |
if (kbd->current && kbd->current->prev)
|
|
|
843e7a |
kbd->current = kbd->current->prev;
|
|
|
061fcf |
keyboardResize(kbd);
|
|
|
061fcf |
appInvalidateRect(kbd->app, 0, 0, kbd->app->w, kbd->app->h);
|
|
|
843e7a |
return;
|
|
|
843e7a |
}
|
|
|
843e7a |
|
|
|
843e7a |
if (index < 0 || index >= kbd->layoutsCount) {
|
|
|
843e7a |
LOGWRN("keyboard: switch layout: bad index %d", index);
|
|
|
843e7a |
return;
|
|
|
452870 |
}
|
|
|
843e7a |
|
|
|
843e7a |
kbd->layouts[index].prev = kbd->current;
|
|
|
843e7a |
kbd->current = &kbd->layouts[index];
|
|
|
061fcf |
|
|
|
061fcf |
keyboardResize(kbd);
|
|
|
061fcf |
appInvalidateRect(kbd->app, 0, 0, kbd->app->w, kbd->app->h);
|
|
|
452870 |
}
|
|
|
843e7a |
|