static inline void map_key(gii_key_event * ge, Visual_Key_Event_Type * ve) { switch(GII_KTYP(ge->sym)) { case GII_KT_FN : ve->state = 0; /* FIXME: CTRL and ALT */ switch(ge->sym) { case GIIK_F1 : case GIIK_F2 : case GIIK_F3 : case GIIK_F4 : case GIIK_F5 : case GIIK_F6 : case GIIK_F7 : case GIIK_F8 : case GIIK_F9 : case GIIK_F10 : ve->keycode = GII_KVAL(ge->sym) - GII_KVAL(GIIK_F1) + VDI_KSCAN(VDI_K_F1); break; case GIIK_F11 : case GIIK_F12 : case GIIK_F13 : case GIIK_F14 : case GIIK_F15 : case GIIK_F16 : case GIIK_F17 : case GIIK_F18 : case GIIK_F19 : case GIIK_F20 : ve->keycode = GII_KVAL(ge->sym) - GII_KVAL(GIIK_F11) + VDI_KSCAN(VDI_K_F11); break; default : ; /* FIXME */ } ve->ascii = 0; break; default : ve->state = 0; ve->keycode = ge->label; ve->ascii = GII_KVAL(ge->sym); } }
static inline void handle_modifier(linkbd_priv *priv, gii_event *ev) { uint32_t mask, old_label; /* Handle AltGr properly */ if (ev->key.label == GIIK_AltR) { if (ev->key.sym == GIIK_VOID) { ev->key.sym = GIIK_AltGr; } mask = 1 << (ev->key.sym & GII_KM_MASK); } else { mask = 1 << (ev->key.label & GII_KM_MASK); } /* Handle CapsShift properly: shift keys undo CapsLock */ if ((ev->key.label == GIIK_ShiftL || ev->key.label == GIIK_ShiftR) && ev->key.sym == GIIK_CapsLock) { if (priv->lockedmod & GII_MOD_CAPS) { old_label = ev->key.label; ev->key.label = GIIK_CapsLock; handle_modifier(priv, ev); ev->key.label = old_label; } ev->key.sym = GIIK_Shift; } if (GII_KVAL(ev->key.label) & GII_KM_LOCK) { if (ev->key.type == evKeyPress) { if (!(priv->lockedmod & mask)) { priv->lockedmod |= mask; ioctl(priv->fd, KDSKBLED, MASK2LED(priv->lockedmod)); } else { ev->key.sym = GIIK_VOID; } } else { if ((priv->lockedmod & mask)) { if (!(priv->lockedmod2 & mask)) { priv->lockedmod2 |= mask; ev->key.sym = GIIK_VOID; } else { priv->lockedmod2 &= ~mask; priv->lockedmod &= ~mask; ioctl(priv->fd, KDSKBLED, MASK2LED(priv->lockedmod)); } } } } else { if (ev->key.type == evKeyRelease) { priv->normalmod &= ~mask; } else { priv->normalmod |= mask; } } priv->modifiers = priv->lockedmod | priv->normalmod; }
static inline gii_event_mask GII_keyboard_handle_data(gii_input *inp, int code) { linkbd_priv *priv = LINKBD_PRIV(inp); gii_event ev; struct kbentry entry; int symval, labelval; gii_event_mask mask; _giiEventBlank(&ev, sizeof(gii_key_event)); if (code & 0x80) { code &= 0x7f; ev.key.type = evKeyRelease; priv->keydown_buf[code] = 0; } else if (priv->keydown_buf[code] == 0) { ev.key.type = evKeyPress; priv->keydown_buf[code] = 1; } else { ev.key.type = evKeyRepeat; } ev.key.button = code; /* First update modifiers here so linkey.c can use the value */ ev.key.modifiers = priv->modifiers; if (ev.key.type == evKeyRelease && GII_KTYP(priv->keydown_sym[code]) != GII_KT_MOD && priv->keydown_sym[code] != GIIK_VOID) { /* We can use the cached values */ ev.key.sym = priv->keydown_sym[code]; ev.key.label = priv->keydown_label[code]; } else { /* Temporarily switch back to the old mode because unicodes aren't available through table lookup in MEDIUMRAW */ if (ioctl(priv->fd, KDSKBMODE, priv->old_mode) < 0) { DPRINT_MISC("Linux-kbd: ioctl(KDSKBMODE) failed.\n"); return 0; } /* Look up the keysym without modifiers, which will give us * the key label (more or less). */ entry.kb_table = 0; entry.kb_index = code; if (ioctl(priv->fd, KDGKBENT, &entry) < 0) { DPRINT_MISC("Linux-kbd: ioctl(KDGKBENT) failed.\n"); return 0; } labelval = entry.kb_value; if (priv->old_mode == K_UNICODE) labelval &= 0x0fff; /* Now look up the full keysym in the kernel's table */ /* calculate kernel-like shift value */ entry.kb_table = ((priv->modifiers & GII_MOD_SHIFT) ? (1<<KG_SHIFT) : 0) | ((priv->modifiers & GII_MOD_CTRL) ? (1<<KG_CTRL) : 0) | ((priv->modifiers & GII_MOD_ALT) ? (1<<KG_ALT) : 0) | ((priv->modifiers & GII_MOD_ALTGR) ? (1<<KG_ALTGR) : 0) | ((priv->modifiers & GII_MOD_META) ? (1<<KG_ALT) : 0) | ((priv->modifiers & GII_MOD_CAPS) ? (1<<KG_CAPSSHIFT) : 0); entry.kb_index = code; if (ioctl(priv->fd, KDGKBENT, &entry) < 0) { DPRINT_MISC("Linux-kbd: ioctl(KDGKBENT) failed.\n"); return 0; } /* Switch back to MEDIUMRAW */ if (ioctl(priv->fd, KDSKBMODE, K_MEDIUMRAW) < 0) { DPRINT_MISC("Linux-kbd: ioctl(KDSKBMODE) failed.\n"); return 0; } switch (entry.kb_value) { case K_HOLE: DPRINT_EVENTS("Linux-kbd: NOSUCHKEY\n"); break; case K_NOSUCHMAP: DPRINT_EVENTS("Linux-kbd: NOSUCHMAP\n"); entry.kb_value = K_HOLE; break; } symval = entry.kb_value; if (priv->old_mode == K_UNICODE) symval &= 0x0fff; _gii_linkey_trans(code, labelval, symval, &ev.key); if (ev.key.type == evKeyPress) { if (priv->accent) { if (GII_KTYP(ev.key.sym) != GII_KT_MOD) { handle_accent(priv, symval, &ev); } } else if (KTYP(symval) == KT_DEAD) { priv->accent = GII_KVAL(ev.key.sym); } } if (GII_KTYP(ev.key.sym) == GII_KT_DEAD) { ev.key.sym = GIIK_VOID; } } /* Keep track of modifier state */ if (GII_KTYP(ev.key.label) == GII_KT_MOD) { /* Modifers don't repeat */ if (ev.key.type == evKeyRepeat) return 0; handle_modifier(priv, &ev); } /* Now update modifiers again to get the value _after_ the current event */ ev.key.modifiers = priv->modifiers; if (ev.any.type == evKeyPress) { priv->keydown_sym[code] = ev.key.sym; priv->keydown_label[code] = ev.key.label; } DPRINT_EVENTS("KEY-%s button=0x%02x modifiers=0x%02x " "sym=0x%04x label=0x%04x\n", (ev.key.type == evKeyRelease) ? "UP" : ((ev.key.type == evKeyPress) ? "DN" : "RP"), ev.key.button, ev.key.modifiers, ev.key.sym, ev.key.label); if (priv->call_vtswitch) { if (ev.key.label == GIIK_CtrlL && priv->needctrl2switch) { if (ev.key.type == evKeyRelease) { priv->ctrlstate = 0; } else if (ev.key.type == evKeyPress) { priv->ctrlstate = 1; } } /* Check for console switch. Unfortunately, the kernel doesn't * recognize KT_CONS when the keyboard is in RAW or MEDIUMRAW * mode, so _we_ have to. Sigh. */ if ((ev.key.type == evKeyPress) && (KTYP(entry.kb_value) == KT_CONS) && priv->ctrlstate) { int rc; int new_cons = 1+KVAL(entry.kb_value); /* Clear the keydown buffer, since we'll never know what keys the user pressed (or released) while they were away. */ DPRINT_MISC("Flushing all keys.\n"); rc = GII_keyboard_flush_keys(inp); DPRINT_MISC("Switching to console %d.\n", new_cons); if (ioctl(priv->fd, VT_ACTIVATE, new_cons) < 0) { perror("ioctl(VT_ACTIVATE)"); } return rc; } } mask = (1 << ev.any.type); if (! (inp->curreventmask & mask)) return 0; /* finally queue the key event */ ev.any.size = sizeof(gii_key_event); ev.any.origin = inp->origin; _giiEvQueueAdd(inp, &ev); return (1 << ev.any.type); }
static int XLateKey (ggi_key_event * ev) { int key = 0; if (GII_KTYP (ev->label) == GII_KT_DEAD) { ev->label = GII_KVAL (ev->label); } switch (ev->label) { case GIIK_P9: key = KP_PGUP; break; case GIIK_PageUp: key = K_PGUP; break; case GIIK_P3: key = KP_PGDN; break; case GIIK_PageDown: key = K_PGDN; break; case GIIK_P7: key = KP_HOME; break; case GIIK_Home: key = K_HOME; break; case GIIK_P1: key = KP_END; break; case GIIK_End: key = K_END; break; case GIIK_P4: key = KP_LEFTARROW; break; case GIIK_Left: key = K_LEFTARROW; break; case GIIK_P6: key = KP_RIGHTARROW; break; case GIIK_Right: key = K_RIGHTARROW; break; case GIIK_P2: key = KP_DOWNARROW; break; case GIIK_Down: key = K_DOWNARROW; break; case GIIK_P8: key = KP_UPARROW; break; case GIIK_Up: key = K_UPARROW; break; case GIIK_P5: key = KP_5; break; case GIIK_PBegin: key = K_AUX32; break; case GIIK_P0: key = KP_INS; break; case GIIK_Insert: key = K_INS; break; case GIIK_PSeparator: case GIIK_PDecimal: key = KP_DEL; break; case GIIUC_Delete: key = K_DEL; break; case GIIK_PStar: key = KP_MULTIPLY; break; case GIIK_PPlus: key = KP_PLUS; break; case GIIK_PMinus: key = KP_MINUS; break; case GIIK_PSlash: key = KP_DIVIDE; break; case GIIK_PEnter: key = KP_ENTER; break; case GIIUC_Return: key = K_ENTER; break; case GIIUC_Escape: key = K_ESCAPE; break; case GIIUC_Tab: key = K_TAB; break; case GIIK_F1: key = K_F1; break; case GIIK_F2: key = K_F2; break; case GIIK_F3: key = K_F3; break; case GIIK_F4: key = K_F4; break; case GIIK_F5: key = K_F5; break; case GIIK_F6: key = K_F6; break; case GIIK_F7: key = K_F7; break; case GIIK_F8: key = K_F8; break; case GIIK_F9: key = K_F9; break; case GIIK_F10: key = K_F10; break; case GIIK_F11: key = K_F11; break; case GIIK_F12: key = K_F12; break; case GIIUC_BackSpace: key = K_BACKSPACE; break; case GIIK_ShiftL: case GIIK_ShiftR: key = K_SHIFT; break; case GIIK_Execute: case GIIK_CtrlL: case GIIK_CtrlR: key = K_CTRL; break; case GIIK_AltL: case GIIK_MetaL: case GIIK_AltR: case GIIK_MetaR: case GIIK_AltGr: case GIIK_ModeSwitch: key = K_ALT; break; case GIIK_Caps: key = K_CAPSLOCK; break; case GIIK_PrintScreen: key = K_PRNTSCR; break; case GIIK_ScrollLock: key = K_SCRLCK; break; case GIIK_Pause: key = K_PAUSE; break; case GIIK_NumLock: key = KP_NUMLCK; break; case GIIUC_Comma: case GIIUC_Minus: case GIIUC_Period: key = ev->label; break; case GIIUC_Section: key = '~'; break; default: if (ev->label >= 0 && ev->label <= 9) return ev->label; if (ev->label >= 'A' && ev->label <= 'Z') { return ev->label - 'A' + 'a'; } if (ev->label >= 'a' && ev->label <= 'z') return ev->label; if (ev->sym <= 0x7f) { key = ev->sym; if (key >= 'A' && key <= 'Z') { key = key - 'A' + 'a'; } return key; } if (ev->label <= 0x7f) { return ev->label; } break; } return key; }