void XWindow::OnKeyRelease(WindowEventKey *e) { XkbStateRec s; Status st = XkbGetState(e->Handle()->display, XkbUseCoreKbd, &s); if (st != XkbOD_Success) throw new XException("Error getting xkb keyboard state", __FILE__, __LINE__, __func__); int shift = (s.mods & ShiftMask) != 0 ? 1 : 0; if (shift == 0) shift = (s.mods & Mod5Mask) != 0 ? 2 : 0; //int lock = (s.mods & LockMask) != 0 ? 1 : 0; //int ctrl = (s.mods & ControlMask) != 0 ? 1 : 0; //int mod1 = (s.mods & Mod1Mask) != 0 ? 1 : 0; //int mod2 = (s.mods & Mod2Mask) != 0 ? 1 : 0; //int mod3 = (s.mods & Mod3Mask) != 0 ? 1 : 0; //int mod4 = (s.mods & Mod4Mask) != 0 ? 1 : 0; //int mod5 = (s.mods & Mod5Mask) != 0 ? 1 : 0; KeySym keySym = XkbKeycodeToKeysym(e->Handle()->display, e->Handle()->keycode, 0, shift); char cadena[10]; int overflow = 0; int nbytes = XkbTranslateKeySym(e->Handle()->display, &keySym, s.mods, cadena, 10, &overflow); Text keyText = nbytes > 0 ? cadena : ""; ControlEventKey kr(*e, KeyCompositionSymbol(keySym, keyText)); // Key redirection until the focused control catches it bool redirected = false; for (int i=0; i<controls->Count() && !redirected; i++) redirected = (*controls)[i]->OnKeyRelease(&kr); DelegationOnKeyRelease().Execute(e); }
static void Keyaction(Widget w, XEvent *e, String *p, Cardinal *np) { static unsigned char compose[5]; static int composing = -2; int kind = Kraw; int c, len, minmod; KeySym k, mk; Charfunc f; Modifiers md; char buf[100] = {0}; c = 0; len = 0; /* Translate the keycode into a key symbol. */ if(e->xany.type != KeyPress) return; XkbTranslateKeyCode(xkb, (KeyCode)e->xkey.keycode, e->xkey.state, &md, &k); XkbTranslateKeySym(e->xany.display, &k, e->xkey.state, buf, sizeof(buf) - 1, &len); /* Check to see if it's a specially-handled key first. */ for (Keymapping *m = keymappings; m; m = m->next){ KeySym u = NoSymbol; KeySym l = NoSymbol; XConvertCase(k, &l, &u); /* Note that magic bit manipulation here - we want to check that the * modifiers that are specified for the binding are all pressed, but * we allow other modifiers to be as well. This is because when NumLock * is on, it's always added to the modifier mask. */ if (l == m->s || m->s == XK_VoidSymbol){ if (m->m == 0 || (m->m & ~e->xkey.state) == 0){ switch (m->c){ case Cnone: return; case Cdefault: continue; default: f = ((GwinWidget)w)->gwin.gotchar; if (f) (*f)(m->c, m->k, Tcurrent, 0, 0, m->a); return; } } } } /* * The following song and dance is so we can have our chosen * modifier key behave like a compose key, i.e, press and release * and then type the compose sequence, like Plan 9. We have * to find out which key is the compose key first though. */ if (IsModifierKey(k) && ((GwinWidget)w)->gwin.compose && composing == -2 && modmap) { minmod = (((GwinWidget)w)->gwin.compose+2)*keypermod; for (c = minmod; c < minmod+keypermod; c++) { XtTranslateKeycode(e->xany.display, modmap->modifiermap[c], e->xkey.state, &md, &mk); if (k == mk) { composing = -1; break; } } return; } /* Handle Multi_key separately, since it isn't a modifier */ if(k == XK_Multi_key) { composing = -1; return; } if(k == NoSymbol || k > 0xff00) return; /* Check to see if we are in a composition sequence */ if (!((GwinWidget)w)->gwin.compose && (e->xkey.state & Mod1Mask) && composing == -2) composing = -1; if (composing > -2) { compose[++composing] = k; if ((*compose == 'X') && (composing > 0)) { if ((k < '0') || (k > 'f') || ((k > '9') && (k < 'a'))) { STUFFCOMPOSE(); c = (uint16_t)k; composing = -2; } else if (composing == 4) { c = unicode(compose); if (c == -1) { STUFFCOMPOSE(); c = (uint16_t)compose[4]; } composing = -2; } } else if (composing == 1) { c = (int)latin1(compose); if (c == -1) { STUFFCOMPOSE(); c = (uint16_t)compose[1]; } composing = -2; } } else { if (composing >= 0) { composing++; STUFFCOMPOSE(); } c = keysymtoshort(k); composing = -2; } if (composing >= -1) return; f = ((GwinWidget)w)->gwin.gotchar; if(f) (*f)(c, kind, Tcurrent, 0, 0, NULL); }
void XWindow::OnKeyPress(WindowEventKey *e) { // ******************************************************************** // Calculate keySym and keyText XkbStateRec s; Status st = XkbGetState(e->Handle()->display, XkbUseCoreKbd, &s); if (st != XkbOD_Success) throw new XException("Error getting xkb keyboard state", __FILE__, __LINE__, __func__); int shift = (s.mods & ShiftMask) != 0 ? 1 : 0; if (shift == 0) shift = (s.mods & Mod5Mask) != 0 ? 2 : 0; //int lock = (s.mods & LockMask) != 0 ? 1 : 0; //int ctrl = (s.mods & ControlMask) != 0 ? 1 : 0; //int mod1 = (s.mods & Mod1Mask) != 0 ? 1 : 0; //int mod2 = (s.mods & Mod2Mask) != 0 ? 1 : 0; //int mod3 = (s.mods & Mod3Mask) != 0 ? 1 : 0; //int mod4 = (s.mods & Mod4Mask) != 0 ? 1 : 0; //int mod5 = (s.mods & Mod5Mask) != 0 ? 1 : 0; KeySym keySym = XkbKeycodeToKeysym(e->Handle()->display, e->Handle()->keycode, 0, shift); char cadena[10]; int overflow = 0; int nbytes = XkbTranslateKeySym(e->Handle()->display, &keySym, s.mods, cadena, 10, &overflow); Text keyText = nbytes > 0 ? cadena : ""; // ******************************************************************** // Manage KeyPreview and KeyPress events ControlEventKey ek(*e, KeyCompositionSymbol(keySym, keyText)); // Key preview to every control for (int i=0; i<controls->Count(); i++) (*controls)[i]->OnKeyPreview(&ek); // OnKeyPress until the focused control catches it bool redirected = false; for (int i=0; i<controls->Count() && !redirected; i++) redirected = (*controls)[i]->OnKeyPress(&ek); // Noone catched the event? if (!redirected) { if (keySym == KeySymbols::Tab) { // Window focus rotate if (!e->PressedShift()) ControlFocusNext(); else ControlFocusPrevious(); } else if (keySym == KeySymbols::Return) { // Return: Window Accept } else if (keySym == KeySymbols::Escape) { // Escape: Window Cancel } else if (keySym == KeySymbols::Space) { // Return: Window Accept } } DelegationOnKeyPress().Execute(e); // ******************************************************************** // Manage KeySymbol event bool continueComposing = false; Text t = KeyCompositionManager::Default().GetComposedKeySym(*composeKeySymBuffer + keyText, continueComposing); *composeKeySymBuffer = continueComposing ? *composeKeySymBuffer + keyText : ""; // Send Key Symbol Event if (!continueComposing) { KeyCompositionSymbol symbol(t == keyText ? keySym : 0, t); WindowEventKeySymbol weks(symbol); OnKeySymbol(&weks); } }
int XLookupString ( register XKeyEvent * event, char * buffer, int nbytes, KeySym * keysym, XComposeStatus * status) { KeySym dummy; int rtrnLen; unsigned int new_mods; Display *dpy = event->display; if (keysym==NULL) keysym= &dummy; if (!XkbLookupKeySym(dpy,event->keycode,event->state, &new_mods,keysym)) return 0; new_mods= (event->state&(~new_mods)); /* find the group where a symbol can be converted to control one */ if (new_mods&ControlMask && *keysym > 0x7F && (dpy->xkb_info->xlib_ctrls & XkbLC_ControlFallback)) { XKeyEvent tmp_ev = *event; KeySym tmp_keysym; unsigned int tmp_new_mods; if (_XkbUnavailable(dpy)) { tmp_ev.state= event->state ^ dpy->mode_switch; if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, &tmp_new_mods, &tmp_keysym) && tmp_keysym != NoSymbol && tmp_keysym < 0x80 ) { *keysym = tmp_keysym; } } else { int n = XkbKeyNumGroups(dpy->xkb_info->desc, tmp_ev.keycode); int i; for (i = 0; i < n; i++) { if (XkbGroupForCoreState(event->state) == i) continue; tmp_ev.state= XkbBuildCoreState(tmp_ev.state, i); if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, &tmp_new_mods, &tmp_keysym) && tmp_keysym != NoSymbol && tmp_keysym < 0x80 ) { *keysym = tmp_keysym; new_mods= (event->state&(~tmp_new_mods)); break; } } } } #ifdef USE_OWN_COMPOSE if ( status ) { static int been_here= 0; if ( !been_here ) { XimCompInitTables(); been_here = 1; } if ( !XimCompLegalStatus(status) ) { status->compose_ptr = NULL; status->chars_matched = 0; } if ( ((status->chars_matched>0)&&(status->compose_ptr!=NULL)) || XimCompIsComposeKey(*keysym,event->keycode,status) ) { XimCompRtrn rtrn; switch (XimCompProcessSym(status,*keysym,&rtrn)) { case XIM_COMP_IGNORE: break; case XIM_COMP_IN_PROGRESS: if ( keysym!=NULL ) *keysym = NoSymbol; #ifndef NO_COMPOSE_LED if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) { XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED, True,True,False,NULL); } #endif return 0; case XIM_COMP_FAIL: { static Atom _ComposeFail= None; int n = 0, len= 0; #ifndef NO_COMPOSE_LED if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) { XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED, True,False,False,NULL); } #endif #ifndef NO_BELL_ON_COMPOSE_FAIL if (dpy->xkb_info->xlib_ctrls&XkbLC_BeepOnComposeFail) { if (_ComposeFail==None) _ComposeFail= XInternAtom(dpy,"ComposeFail",0); XkbBell(dpy,event->window,0,_ComposeFail); } #endif for (n=len=0;rtrn.sym[n]!=XK_VoidSymbol;n++) { if ( nbytes-len > 0 ) { len+= XkbTranslateKeySym(dpy,&rtrn.sym[n],new_mods, buffer+len,nbytes-len, NULL); } } if ( keysym!=NULL ) { if ( n==1 ) *keysym = rtrn.sym[0]; else *keysym = NoSymbol; } return len; } case XIM_COMP_SUCCEED: { int len,n = 0; #ifndef NO_COMPOSE_LED if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) { XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED, True,False,False,NULL); } #endif *keysym = rtrn.matchSym; if ( rtrn.str[0]!='\0' ) { strncpy(buffer,rtrn.str,nbytes-1); buffer[nbytes-1]= '\0'; len = (int)strlen(buffer); } else { len = XkbTranslateKeySym(dpy,keysym,new_mods, buffer,nbytes, NULL); } for (n=0;rtrn.sym[n]!=XK_VoidSymbol;n++) { if ( nbytes-len > 0 ) { len+= XkbTranslateKeySym(dpy,&rtrn.sym[n], event->state, buffer+len,nbytes-len, NULL); } } return len; } } } } #endif /* We *should* use the new_mods (which does not contain any modifiers */ /* that were used to compute the symbol here, but pre-XKB XLookupString */ /* did not and we have to remain compatible. Sigh. */ if (_XkbUnavailable(dpy) || (dpy->xkb_info->xlib_ctrls&XkbLC_ConsumeLookupMods)==0) new_mods= event->state; rtrnLen= XkbLookupKeyBinding(dpy,*keysym,new_mods,buffer,nbytes,NULL); if (rtrnLen>0) return rtrnLen; return XkbTranslateKeySym(dpy,keysym,new_mods,buffer,nbytes,NULL); }