int read_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len) { XEvent ev; int nbytes; /* Read a key from the keyboard. */ do { XMaskEvent (dpy, KeyPressMask|KeyRelease, &ev); *modifiers = ev.xkey.state; nbytes = cook_keycode (&ev.xkey, keysym, modifiers, keysym_name, len, 0); } while (IsModifierKey (*keysym) || ev.xkey.type == KeyRelease); return nbytes; }
bool wxGetKeyState(wxKeyCode key) { wxASSERT_MSG(key != WXK_LBUTTON && key != WXK_RBUTTON && key != WXK_MBUTTON, wxT("can't use wxGetKeyState() for mouse buttons")); Display *pDisplay = (Display*) wxGetDisplay(); int iKey = wxCharCodeWXToX(key); int iKeyMask = 0; Window wDummy1, wDummy2; int iDummy3, iDummy4, iDummy5, iDummy6; unsigned int iMask; KeyCode keyCode = XKeysymToKeycode(pDisplay,iKey); if (keyCode == NoSymbol) return false; if ( IsModifierKey(iKey) ) // If iKey is a modifier key, use a different method { XModifierKeymap *map = XGetModifierMapping(pDisplay); wxCHECK_MSG( map, false, wxT("failed to get X11 modifiers map") ); for (int i = 0; i < 8; ++i) { if ( map->modifiermap[map->max_keypermod * i] == keyCode) { iKeyMask = 1 << i; } } XQueryPointer(pDisplay, DefaultRootWindow(pDisplay), &wDummy1, &wDummy2, &iDummy3, &iDummy4, &iDummy5, &iDummy6, &iMask ); XFreeModifiermap(map); return (iMask & iKeyMask) != 0; } // From the XLib manual: // The XQueryKeymap() function returns a bit vector for the logical state of the keyboard, // where each bit set to 1 indicates that the corresponding key is currently pressed down. // The vector is represented as 32 bytes. Byte N (from 0) contains the bits for keys 8N to 8N + 7 // with the least-significant bit in the byte representing key 8N. char key_vector[32]; XQueryKeymap(pDisplay, key_vector); return key_vector[keyCode >> 3] & (1 << (keyCode & 7)); }
bool UINativeHotKey::isValidKey(int iKeyCode) { #ifdef Q_WS_WIN return ((iKeyCode >= VK_SHIFT && iKeyCode <= VK_CAPITAL) || (iKeyCode >= VK_LSHIFT && iKeyCode <= VK_RMENU) || (iKeyCode >= VK_F1 && iKeyCode <= VK_F24) || iKeyCode == VK_NUMLOCK || iKeyCode == VK_SCROLL || iKeyCode == VK_LWIN || iKeyCode == VK_RWIN || iKeyCode == VK_APPS || iKeyCode == VK_PRINT); #endif /* Q_WS_WIN */ #ifdef Q_WS_X11 return (IsModifierKey(iKeyCode) /* allow modifiers */ || IsFunctionKey(iKeyCode) /* allow function keys */ || IsMiscFunctionKey(iKeyCode) /* allow miscellaneous function keys */ || iKeyCode == XK_Scroll_Lock /* allow 'Scroll Lock' missed in IsModifierKey() */) && (iKeyCode != NoSymbol /* ignore some special symbol */ && iKeyCode != XK_Insert /* ignore 'insert' included into IsMiscFunctionKey */); #endif /* Q_WS_X11 */ #ifdef Q_WS_MAC UInt32 modMask = ::DarwinKeyCodeToDarwinModifierMask(iKeyCode); switch (modMask) { case shiftKey: case optionKey: case controlKey: case rightShiftKey: case rightOptionKey: case rightControlKey: case cmdKey: case kEventKeyModifierRightCmdKeyMask: return true; default: return false; } #endif /* Q_WS_MAC */ return false; }
static int handleKey(unsigned int xkeysym, unsigned int xkeystate, int is_push, IMUIMContext *uic) { DefTree *p; DefTree *m_top = uic->compose->m_top; DefTree *m_context = uic->compose->m_context; if ((is_push == 0) || m_top == NULL) return 0; if (IsModifierKey(xkeysym)) return 0; for (p = m_context; p ; p = p->next) { if (((xkeystate & p->modifier_mask) == p->modifier) && (xkeysym == p->keysym)) { break; } } if (p) { /* Matched */ if (p->succession) { /* Intermediate */ uic->compose->m_context = p->succession; return 1; } else { /* Terminate (reached to leaf) */ uic->compose->m_composed = p; /* commit string here */ im_uim_commit_string(uic, uic->compose->m_composed->utf8); /* initialize internal state for next key sequence */ uic->compose->m_context = m_top; return 1; } } else { /* Unmatched */ if (m_context == m_top) return 0; /* Error (Sequence Unmatch occurred) */ uic->compose->m_context = m_top; return 1; } }
bool Compose::handleKey(KeySym xkeysym, int xkeystate, bool is_push) { DefTree *p; if ((is_push == false) || m_top == NULL) return false; if (IsModifierKey(xkeysym)) return false; for (p = m_context; p ; p = p->next) { if (((xkeystate & p->modifier_mask) == p->modifier) && (xkeysym == p->keysym)) { break; } } if (p) { // Matched if (p->succession) { // Intermediate m_context = p->succession; return true; } else { // Terminate (reached to leaf) m_composed = p; // commit string here m_xic->commit_string(m_composed->utf8); // initialize internal state for next key sequence m_context = m_top; return true; } } else { // Unmatched if (m_context == m_top) return false; // Error (Sequence Unmatch occurred) m_context = m_top; return true; } }
static gboolean accel_button_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer userdata) { char *accelerator; if(!accel_button_is_recording(GTK_BUTTON(widget))) { return FALSE; } if(event->type==GDK_KEY_RELEASE) { if(event->keyval==GDK_BackSpace || event->keyval==GDK_Escape || event->keyval==GDK_Delete) { accel_button_set_label(GTK_BUTTON(widget)); } else { if(!IsModifierKey(event->keyval)) { accelerator= gtk_accelerator_name(event->keyval, event->state); gconf_client_set_string(ocha_gconf_get_client(), OCHA_GCONF_ACCELERATOR_KEY, accelerator, NULL/*err*/); g_free(accelerator); } } } return TRUE; }
/* * Process a keypress event * * Also appears in "main-x11.c". */ static void react_keypress(XKeyEvent *xev) { int i, n, mc, ms, mo, mx; uint ks1; XKeyEvent *ev = (XKeyEvent*)(xev); KeySym ks; char buf[128]; char msg[128]; /* Check for "normal" keypresses */ n = XLookupString(ev, buf, 125, &ks, NULL); /* Terminate */ buf[n] = '\0'; /* Hack -- Ignore "modifier keys" */ if (IsModifierKey(ks)) return; /* Hack -- convert into an unsigned int */ ks1 = (uint)(ks); /* Extract four "modifier flags" */ mc = (ev->state & ControlMask) ? TRUE : FALSE; ms = (ev->state & ShiftMask) ? TRUE : FALSE; mo = (ev->state & Mod1Mask) ? TRUE : FALSE; mx = (ev->state & Mod2Mask) ? TRUE : FALSE; /* Normal keys with no modifiers */ if (n && !mo && !mx && !IsSpecialKey(ks)) { /* Enqueue the normal key(s) */ for (i = 0; buf[i]; i++) Term_keypress(buf[i]); /* All done */ return; } /* Handle a few standard keys (bypass modifiers) XXX XXX XXX */ switch (ks1) { case XK_Escape: { Term_keypress(ESCAPE); return; } case XK_Return: { Term_keypress('\r'); return; } case XK_Tab: { Term_keypress('\t'); return; } case XK_Delete: case XK_BackSpace: { Term_keypress('\010'); return; } } /* Hack -- Use the KeySym */ if (ks) { sprintf(msg, "%c%s%s%s%s_%lX%c", 31, mc ? "N" : "", ms ? "S" : "", mo ? "O" : "", mx ? "M" : "", (unsigned long)(ks), 13); } /* Hack -- Use the Keycode */ else { sprintf(msg, "%c%s%s%s%sK_%X%c", 31, mc ? "N" : "", ms ? "S" : "", mo ? "O" : "", mx ? "M" : "", ev->keycode, 13); } /* Enqueue the "macro trigger" string */ for (i = 0; msg[i]; i++) Term_keypress(msg[i]); /* Hack -- auto-define macros as needed */ if (n && (macro_find_exact(msg) < 0)) { /* Create a macro */ macro_add(msg, buf); } }
uni_t dpy_getchar(int timeout) { while (numqueued == 0) { /* If a timeout was asked for, wait that long for an event. */ if ((timeout != -1) && !XPending(display)) { struct pollfd pfd = { .fd = ConnectionNumber(display), .events = POLLIN, .revents = 0 }; poll(&pfd, 1, timeout*1000); if (!pfd.revents) return -VK_TIMEOUT; } XEvent e; XNextEvent(display, &e); if (XFilterEvent(&e, window)) continue; switch (e.type) { case MapNotify: break; case Expose: { /* Mark some of the screen as needing redrawing. */ if (frontbuffer) { for (int y=0; y<screenheight; y++) { unsigned int* p = &frontbuffer[y * screenwidth]; for (int x=0; x<screenwidth; x++) p[x] = 0; } } redraw(); break; } case ConfigureNotify: { XConfigureEvent* xce = &e.xconfigure; int w = xce->width / fontwidth; int h = xce->height / fontheight; if ((w != screenwidth) || (h != screenheight)) { screenwidth = w; screenheight = h; if (frontbuffer) free(frontbuffer); frontbuffer = NULL; if (backbuffer) free(backbuffer); backbuffer = calloc(screenwidth * screenheight, sizeof(unsigned int)); push_key(-VK_RESIZE); } break; } case MappingNotify: case KeymapNotify: XRefreshKeyboardMapping(&e.xmapping); break; case KeyPress: { XKeyPressedEvent* xke = &e.xkey; KeySym keysym; char buffer[32]; Status status = 0; int charcount = Xutf8LookupString(xic, xke, buffer, sizeof(buffer)-1, &keysym, &status); int mods = 0; if (xke->state & ShiftMask) mods |= VKM_SHIFT; if (xke->state & ControlMask) mods |= VKM_CTRL; if ((keysym & 0xffffff00) == 0xff00) { /* Special function key. */ if (!IsModifierKey(keysym)) push_key(-(keysym | mods)); } else { const char* p = buffer; while ((p-buffer) < charcount) { uni_t c = readu8(&p); if (c < 32) { /* Ctrl + letter key */ push_key(-(VKM_CTRLASCII | c | mods)); } else { if (xke->state & Mod1Mask) push_key(-XK_Escape); push_key(c); } } } break; } } } return dequeue(); } const char* dpy_getkeyname(uni_t k) { static char buffer[32]; switch (-k) { case VK_RESIZE: return "KEY_RESIZE"; case VK_TIMEOUT: return "KEY_TIMEOUT"; case VK_REDRAW: return "KEY_REDRAW"; } int key = -k & ~VKM__MASK; int mods = -k & VKM__MASK; if (mods & VKM_CTRLASCII) { sprintf(buffer, "KEY_%s^%c", (mods & VKM_SHIFT) ? "S" : "", key + 64); return buffer; } const char* template = NULL;
BOOLEAN CSoftHIDInputKbdMapper::GenInputReport( USHORT usUsageID, USHORT usFlag) /*++ Routine Description: Generates new input report based on new keyboard event Synchronization: None Arguments: usUsageID - HID Usage ID of key pressed/released. usFlag - Flag that specifies whether key was pressed or released. Return Value: TRUE Success FALSE Could not generate new input report --*/ { BOOLEAN fRet = TRUE; // Treat modifier keys separately if (IsModifierKey(usUsageID)) { if (KEY_MAKE == (usFlag & KEY_MAKE)) { // Set modifier key m_InputReport.bModifier |= XlateModifierKey(usUsageID); } else { // Clear modifier key m_InputReport.bModifier &= ~XlateModifierKey(usUsageID); } } // Regular keys write to the array else { // New key was pressed: add it to the array if (KEY_MAKE == (usFlag & KEY_MAKE)) { if (m_bKeySeqLen < MAX_KEYSEQ) { // This keyboard supports only one-byte Usage IDs m_InputReport.bUsageID[m_bKeySeqLen++] = (BYTE)usUsageID; } else fRet = FALSE; } // Old key was released: delete it from the array else { // Find key in the array for(BYTE i = 0; i < m_bKeySeqLen; i++) { if (m_InputReport.bUsageID[i] == usUsageID) { // Delete key from the array for(BYTE j = i; j < m_bKeySeqLen-1; j++) { m_InputReport.bUsageID[j] = m_InputReport.bUsageID[j+1]; } m_InputReport.bUsageID[--m_bKeySeqLen] = 0; break; } } } } return fRet; } // CSoftHIDInputKbdMapper::GenInputReport
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); }
/* ARGSUSED */ static void InsertChar ( Widget ctxw, XEvent *event, String *params, Cardinal *num_params) { LoginWidget ctx = (LoginWidget)ctxw; char strbuf[128]; #ifndef XPM int len; #else int len,pixels; #endif /* XPM */ KeySym keysym = 0; if (ctx->login.xic) { static Status status; len = XmbLookupString(ctx->login.xic, &event->xkey, strbuf, sizeof (strbuf), &keysym, &status); } else { static XComposeStatus compose_status = {NULL, 0}; len = XLookupString (&event->xkey, strbuf, sizeof (strbuf), &keysym, &compose_status); } strbuf[len] = '\0'; #ifdef XPM pixels = 3 + ctx->login.font->max_bounds.width * len + XTextWidth(ctx->login.font, ctx->login.data.name, strlen(ctx->login.data.name)); /* pixels to be added */ #endif /* XPM */ /* * Note: You can override this default key handling * by the settings in the translation table * loginActionsTable at the end of this file. */ switch (keysym) { case XK_Return: case XK_KP_Enter: case XK_Linefeed: case XK_Execute: FinishField(ctxw, event, params, num_params); return; case XK_BackSpace: DeleteBackwardChar(ctxw, event, params, num_params); return; case XK_Delete: case XK_KP_Delete: case DXK_Remove: /* Sorry, it's not a telex machine, it's a terminal */ DeleteForwardChar(ctxw, event, params, num_params); return; case XK_Left: case XK_KP_Left: MoveBackwardChar(ctxw, event, params, num_params); return; case XK_Right: case XK_KP_Right: MoveForwardChar(ctxw, event, params, num_params); return; case XK_End: case XK_KP_End: MoveToEnd(ctxw, event, params, num_params); return; case XK_Home: case XK_KP_Home: MoveToBegining(ctxw, event, params, num_params); return; default: if (len == 0) { if (!IsModifierKey(keysym)) /* it's not a modifier */ XBell(XtDisplay(ctxw), 60); return; } else break; } switch (ctx->login.state) { case GET_NAME: #ifndef XPM if (len + (int)strlen(ctx->login.data.name) >= NAME_LEN - 1) #else if ( (len + (int)strlen(ctx->login.data.name) >= NAME_LEN - 1)/* && (pixels <= LOGIN_W(ctx) - PROMPT_W(ctx))*/ ) #endif /* XPM */ len = NAME_LEN - strlen(ctx->login.data.name) - 2; case GET_PASSWD: if (len + (int)strlen(ctx->login.data.passwd) >= PASSWORD_LEN - 1) len = PASSWORD_LEN - strlen(ctx->login.data.passwd) - 2; } #ifndef XPM if (len == 0) #else if (len == 0 || pixels >= LOGIN_W(ctx) - PROMPT_W(ctx)) #endif /* XPM */ return; XorCursor (ctx); RemoveFail (ctx); switch (ctx->login.state) { case GET_NAME: EraseName (ctx, ctx->login.cursor); memmove( ctx->login.data.name + ctx->login.cursor + len, ctx->login.data.name + ctx->login.cursor, strlen (ctx->login.data.name + ctx->login.cursor) + 1); memmove( ctx->login.data.name + ctx->login.cursor, strbuf, len); DrawName (ctx, ctx->login.cursor); ctx->login.cursor += len; break; case GET_PASSWD: memmove( ctx->login.data.passwd + ctx->login.cursor + len, ctx->login.data.passwd + ctx->login.cursor, strlen (ctx->login.data.passwd + ctx->login.cursor) + 1); memmove( ctx->login.data.passwd + ctx->login.cursor, strbuf, len); ctx->login.cursor += len; #ifdef XPM /*as good a place as any Caolan begin*/ ctx->login.lastEventTime = time(NULL); /*as good a place as any Caolan end*/ #endif /* XPM */ break; } XorCursor (ctx); }
static eventFilterStatus clientCycleEventFilter (XfwmEvent *event, gpointer data) { ScreenInfo *screen_info; DisplayInfo *display_info; ClientCycleData *passdata; Client *c, *removed; Client *c2 = NULL; eventFilterStatus status; KeyCode cancel, left, right, up, down; int key, modifiers; gboolean cycling; GList *li; TRACE ("entering"); passdata = (ClientCycleData *) data; c = tabwinGetSelected(passdata->tabwin); if (c == NULL) { return EVENT_FILTER_CONTINUE; } screen_info = c->screen_info; display_info = screen_info->display_info; cancel = screen_info->params->keys[KEY_CANCEL].keycode; left = screen_info->params->keys[KEY_LEFT].keycode; right = screen_info->params->keys[KEY_RIGHT].keycode; up = screen_info->params->keys[KEY_UP].keycode; down = screen_info->params->keys[KEY_DOWN].keycode; modifiers = (screen_info->params->keys[KEY_CYCLE_WINDOWS].modifier | screen_info->params->keys[KEY_CYCLE_REVERSE_WINDOWS].modifier); status = EVENT_FILTER_CONTINUE; removed = NULL; cycling = TRUE; /* Update the display time */ myDisplayUpdateCurrentTime (display_info, event); switch (event->meta.type) { case XFWM_EVENT_KEY: if (event->key.pressed) { key = myScreenGetKeyPressed (screen_info, &event->key); /* * We cannot simply check for key == KEY_CANCEL here because of the * modidier being pressed, so we need to look at the keycode directly. */ if (event->key.keycode == cancel) { c2 = tabwinSelectHead (passdata->tabwin); cycling = FALSE; } else if (event->key.keycode == up) { c2 = tabwinSelectDelta(passdata->tabwin, -1, 0); } else if (event->key.keycode == down) { c2 = tabwinSelectDelta(passdata->tabwin, 1, 0); } else if (event->key.keycode == left) { c2 = tabwinSelectDelta(passdata->tabwin, 0, -1); } else if (event->key.keycode == right) { c2 = tabwinSelectDelta(passdata->tabwin, -0, 1); } else if (key == KEY_CYCLE_REVERSE_WINDOWS) { TRACE ("cycle: previous"); c2 = tabwinSelectPrev(passdata->tabwin); } else if (key == KEY_CYCLE_WINDOWS) { TRACE ("cycle: next"); c2 = tabwinSelectNext(passdata->tabwin); } if (c2) { clientCycleUpdateWireframe (c2, passdata); } /* If last key press event had not our modifiers pressed, finish cycling */ if (!(event->key.state & modifiers)) { cycling = FALSE; } status = EVENT_FILTER_STOP; } else { int keysym = XkbKeycodeToKeysym (event->meta.xevent->xany.display, event->key.keycode, 0, 0); if (IsModifierKey(keysym)) { if (!(myScreenGetModifierPressed (screen_info) & modifiers)) { cycling = FALSE; } } } status = EVENT_FILTER_STOP; break; case XFWM_EVENT_BUTTON: if (event->button.pressed) { /* only accept events for the tab windows */ for (li = passdata->tabwin->tabwin_list; li != NULL; li = li->next) { if (GDK_WINDOW_XID (gtk_widget_get_window (li->data)) == event->meta.window) { if (event->button.button == Button1) { c2 = tabwinSelectHovered (passdata->tabwin); cycling = FALSE; break; } else if (event->button.button == Button4) { /* Mouse wheel scroll up */ TRACE ("cycle: previous"); c2 = tabwinSelectPrev(passdata->tabwin); } else if (event->button.button == Button5) { /* Mouse wheel scroll down */ TRACE ("cycle: next"); c2 = tabwinSelectNext(passdata->tabwin); } } if (c2) { clientCycleUpdateWireframe (c2, passdata); } } } status = EVENT_FILTER_STOP; break; case XFWM_EVENT_MOTION: break; case XFWM_EVENT_CROSSING: /* Track whether the pointer is inside one of the tab-windows */ for (li = passdata->tabwin->tabwin_list; li != NULL; li = li->next) { if (GDK_WINDOW_XID (gtk_widget_get_window (li->data)) == event->meta.window) { passdata->inside = event->crossing.enter; } } status = EVENT_FILTER_STOP; break; case XFWM_EVENT_XEVENT: switch (event->meta.xevent->type) { case DestroyNotify: status = EVENT_FILTER_CONTINUE; removed = myScreenGetClientFromWindow (screen_info, ((XDestroyWindowEvent *) event->meta.xevent)->window, SEARCH_WINDOW); if (removed == NULL) { break; /* No need to go any further */ } FALLTHROUGH; case UnmapNotify: status = EVENT_FILTER_CONTINUE; if (!removed) { removed = myScreenGetClientFromWindow (screen_info, ((XUnmapEvent *) event->meta.xevent)->window, SEARCH_WINDOW); if (removed == NULL) { break; /* No need to go any further */ } } c = tabwinRemoveClient(passdata->tabwin, removed); cycling = clientCycleUpdateWireframe (c, passdata); break; } break; } if (!cycling) { TRACE ("event loop now finished"); gtk_main_quit (); } return status; }
static eventFilterStatus clientCycleEventFilter (XEvent * xevent, gpointer data) { ScreenInfo *screen_info; DisplayInfo *display_info; ClientCycleData *passdata; Client *c, *removed; Client *c2 = NULL; eventFilterStatus status; KeyCode cancel, left, right, up, down; int key, modifiers; gboolean key_pressed, cycling, gone; GList *li; Window mouse_window = 0; XButtonEvent ev; TRACE ("entering clientCycleEventFilter"); passdata = (ClientCycleData *) data; c = tabwinGetSelected(passdata->tabwin); if (c == NULL) { return EVENT_FILTER_CONTINUE; } screen_info = c->screen_info; display_info = screen_info->display_info; cancel = screen_info->params->keys[KEY_CANCEL].keycode; left = screen_info->params->keys[KEY_LEFT].keycode; right = screen_info->params->keys[KEY_RIGHT].keycode; up = screen_info->params->keys[KEY_UP].keycode; down = screen_info->params->keys[KEY_DOWN].keycode; modifiers = (screen_info->params->keys[KEY_CYCLE_WINDOWS].modifier | screen_info->params->keys[KEY_CYCLE_REVERSE_WINDOWS].modifier); status = EVENT_FILTER_STOP; removed = NULL; cycling = TRUE; gone = FALSE; /* Update the display time */ myDisplayUpdateCurrentTime (display_info, xevent); switch (xevent->type) { case DestroyNotify: status = EVENT_FILTER_CONTINUE; if ((removed = myScreenGetClientFromWindow (screen_info, ((XDestroyWindowEvent *) xevent)->window, SEARCH_WINDOW)) == NULL) break; /* No need to go any further */ gone |= (c == removed); /* Walk through */ case UnmapNotify: status = EVENT_FILTER_CONTINUE; if (!removed && (removed = myScreenGetClientFromWindow (screen_info, ((XUnmapEvent *) xevent)->window, SEARCH_WINDOW)) == NULL) break; /* No need to go any further */ gone |= (c == removed); c = tabwinRemoveClient(passdata->tabwin, removed); /* Walk through */ case KeyPress: key_pressed = (xevent->type == KeyPress); if (gone || key_pressed) { if (key_pressed) { key = myScreenGetKeyPressed (screen_info, (XKeyEvent *) xevent); /* * We cannot simply check for key == KEY_CANCEL here because of the * modidier being pressed, so we need to look at the keycode directly. */ if (xevent->xkey.keycode == cancel) { c2 = tabwinSelectHead (passdata->tabwin); cycling = FALSE; } else if (xevent->xkey.keycode == up) { c2 = tabwinSelectDelta(passdata->tabwin, -1, 0); } else if (xevent->xkey.keycode == down) { c2 = tabwinSelectDelta(passdata->tabwin, 1, 0); } else if (xevent->xkey.keycode == left) { c2 = tabwinSelectDelta(passdata->tabwin, 0, -1); } else if (xevent->xkey.keycode == right) { c2 = tabwinSelectDelta(passdata->tabwin, -0, 1); } else if (key == KEY_CYCLE_REVERSE_WINDOWS) { TRACE ("Cycle: previous"); c2 = tabwinSelectPrev(passdata->tabwin); } else if (key == KEY_CYCLE_WINDOWS) { TRACE ("Cycle: next"); c2 = tabwinSelectNext(passdata->tabwin); } if (c2) { c = c2; } /* If last key press event had not our modifiers pressed, finish cycling */ if (!(xevent->xkey.state & modifiers)) { cycling = FALSE; } } } break; case KeyRelease: { int keysym = XLookupKeysym (&xevent->xkey, 0); if (IsModifierKey(keysym)) { if (!(myScreenGetModifierPressed (screen_info) & modifiers)) { cycling = FALSE; } } } break; case ButtonPress: status = EVENT_FILTER_STOP; ev = xevent->xbutton; /* window of the event, we might accept it later */ mouse_window = xevent->xbutton.window; if (mouse_window != 0) { /* only accept events for the tab windows */ for (li = passdata->tabwin->tabwin_list; li != NULL; li = li->next) { if (GDK_WINDOW_XID (gtk_widget_get_window (li->data)) == mouse_window) { if (ev.button == Button1) { cycling = FALSE; c = tabwinSelectHoveredWidget (passdata->tabwin); break; } else if (ev.button == Button4) { /* Mouse wheel scroll up */ TRACE ("Cycle: previous"); c2 = tabwinSelectPrev(passdata->tabwin); } else if (ev.button == Button5) { /* Mouse wheel scroll down */ TRACE ("Cycle: next"); c2 = tabwinSelectNext(passdata->tabwin); } } } if (c2) { c = c2; } } break; default: status = EVENT_FILTER_CONTINUE; break; } if (!cycling) { TRACE ("event loop now finished"); gtk_main_quit (); } if (status == EVENT_FILTER_STOP) { if (cycling) { if (c) { if (passdata->wireframe) { wireframeUpdate (c, passdata->wireframe); } } else { cycling = FALSE; } } } return status; }
static void Keyaction(Widget w, XEvent *e, String *p, Cardinal *np) { static unsigned char compose[5]; static int composing = -2; int composed = 0; int c, minmod; KeySym k, mk; Charfunc f; Modifiers md; /* * I tried using XtGetActionKeysym, but it didn't seem to * do case conversion properly * (at least, with Xterminal servers and R4 intrinsics) */ if(e->xany.type != KeyPress) return; XtTranslateKeycode(e->xany.display, (KeyCode)e->xkey.keycode, e->xkey.state, &md, &k); /* * 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) return; if(k&0xFF00){ switch(k){ case XK_BackSpace: case XK_Tab: case XK_Escape: case XK_Delete: case XK_KP_0: case XK_KP_1: case XK_KP_2: case XK_KP_3: case XK_KP_4: case XK_KP_5: case XK_KP_6: case XK_KP_7: case XK_KP_8: case XK_KP_9: case XK_KP_Divide: case XK_KP_Multiply: case XK_KP_Subtract: case XK_KP_Add: case XK_KP_Decimal: k &= 0x7F; break; case XK_Linefeed: k = '\r'; break; case XK_KP_Enter: case XK_Return: k = '\n'; break; case XK_Left: case XK_Down: case XK_Right: case XK_Next: k = 0x80; /* VIEW -- "Scroll" */ break; case XK_Up: case XK_Prior: k = 0x81; /* PREVIEW -- "Scroll back" */ break; default: return; /* not ISO-1 or tty control */ } } /* Compensate for servers that call a minus a hyphen */ if(k == XK_hyphen) k = XK_minus; /* Do control mapping ourselves if translator doesn't */ if((e->xkey.state&ControlMask) && !(md&ControlMask)) k &= 0x9f; if(k == NoSymbol) 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 = (unsigned short)k; composing = -2; } else if (composing == 4) { c = unicode(compose); if (c == -1) { STUFFCOMPOSE(); c = (unsigned short)compose[4]; } else composed = 1; composing = -2; } } else if (composing == 1) { c = (int)latin1(compose); if (c == -1) { STUFFCOMPOSE(); c = (unsigned short)compose[1]; } else composed = 1; composing = -2; } } else { if (composing >= 0) { composing++; STUFFCOMPOSE(); } c = (unsigned short)k; composing = -2; } if (composing >= -1) return; f = ((GwinWidget)w)->gwin.gotchar; if(f) (*f)(c, composed); }