// Convert gdk key event keyvals to char codes if printable, 0 otherwise PRUint32 nsConvertCharCodeToUnicode(GdkEventKey* aEvent) { // Anything above 0xf000 is considered a non-printable // Exception: directly encoded UCS characters if (aEvent->keyval > 0xf000 && (aEvent->keyval & 0xff000000) != 0x01000000) { // Keypad keys are an exception: they return a value different // from their non-keypad equivalents, but mozilla doesn't distinguish. switch (aEvent->keyval) { case GDK_KP_Space: return ' '; case GDK_KP_Equal: return '='; case GDK_KP_Multiply: return '*'; case GDK_KP_Add: return '+'; case GDK_KP_Separator: return ','; case GDK_KP_Subtract: return '-'; case GDK_KP_Decimal: return '.'; case GDK_KP_Divide: return '/'; case GDK_KP_0: return '0'; case GDK_KP_1: return '1'; case GDK_KP_2: return '2'; case GDK_KP_3: return '3'; case GDK_KP_4: return '4'; case GDK_KP_5: return '5'; case GDK_KP_6: return '6'; case GDK_KP_7: return '7'; case GDK_KP_8: return '8'; case GDK_KP_9: return '9'; } // non-printables return 0; } // we're supposedly printable, let's try to convert long ucs = keysym2ucs(aEvent->keyval); if ((ucs != -1) && (ucs < MAX_UNICODE)) return ucs; // I guess we couldn't convert return 0; }
void SkOSWindow::loop() { Display* dsp = fUnixWindow.fDisplay; if (NULL == dsp) { return; } XSelectInput(dsp, fUnixWindow.fWin, EVENT_MASK); bool loop = true; XEvent evt; while (loop) { XNextEvent(dsp, &evt); switch (evt.type) { case Expose: if (evt.xexpose.count == 0) this->inval(NULL); break; case ConfigureNotify: this->resize(evt.xconfigure.width, evt.xconfigure.height); break; case ButtonPress: if (evt.xbutton.button == Button1) this->handleClick(evt.xbutton.x, evt.xbutton.y, SkView::Click::kDown_State); break; case ButtonRelease: if (evt.xbutton.button == Button1) this->handleClick(evt.xbutton.x, evt.xbutton.y, SkView::Click::kUp_State); break; case MotionNotify: this->handleClick(evt.xmotion.x, evt.xmotion.y, SkView::Click::kMoved_State); break; case KeyPress: { KeySym keysym = XkbKeycodeToKeysym(dsp, evt.xkey.keycode, 0, 0); //SkDebugf("pressed key %i!\n\tKeySym:%i\n", evt.xkey.keycode, XKeycodeToKeysym(dsp, evt.xkey.keycode, 0)); if (keysym == XK_Escape) { loop = false; break; } this->handleKey(XKeyToSkKey(keysym)); long uni = keysym2ucs(keysym); if (uni != -1) { this->handleChar((SkUnichar) uni); } break; } case KeyRelease: //SkDebugf("released key %i\n", evt.xkey.keycode); this->handleKeyUp(XKeyToSkKey(XkbKeycodeToKeysym(dsp, evt.xkey.keycode, 0, 0))); break; case ClientMessage: if (SkEvent::ProcessEvent()) { this->post_linuxevent(); } break; default: // Do nothing for other events break; } } }
SkOSWindow::NextXEventResult SkOSWindow::nextXEvent() { XEvent evt; Display* dsp = fUnixWindow.fDisplay; if (!MyXNextEventWithDelay(dsp, &evt)) { return kContinue_NextXEventResult; } switch (evt.type) { case Expose: if (0 == evt.xexpose.count) { return kPaintRequest_NextXEventResult; } break; case ConfigureNotify: this->resize(evt.xconfigure.width, evt.xconfigure.height); break; case ButtonPress: if (evt.xbutton.button == Button1) this->handleClick(evt.xbutton.x, evt.xbutton.y, SkView::Click::kDown_State, NULL, getModi(evt)); break; case ButtonRelease: if (evt.xbutton.button == Button1) this->handleClick(evt.xbutton.x, evt.xbutton.y, SkView::Click::kUp_State, NULL, getModi(evt)); break; case MotionNotify: this->handleClick(evt.xmotion.x, evt.xmotion.y, SkView::Click::kMoved_State, NULL, getModi(evt)); break; case KeyPress: { int shiftLevel = (evt.xkey.state & ShiftMask) ? 1 : 0; KeySym keysym = XkbKeycodeToKeysym(dsp, evt.xkey.keycode, 0, shiftLevel); if (keysym == XK_Escape) { return kQuitRequest_NextXEventResult; } this->handleKey(XKeyToSkKey(keysym)); long uni = keysym2ucs(keysym); if (uni != -1) { this->handleChar((SkUnichar) uni); } break; } case KeyRelease: this->handleKeyUp(XKeyToSkKey(XkbKeycodeToKeysym(dsp, evt.xkey.keycode, 0, 0))); break; case ClientMessage: if ((Atom)evt.xclient.data.l[0] == wm_delete_window_message) { return kQuitRequest_NextXEventResult; } // fallthrough default: // Do nothing for other events break; } return kContinue_NextXEventResult; }
QString KeySymHelper::getKeySymbol(const QString &opton) { if (keySymbolMap.contains(opton)) { return keySymbolMap[opton]; } const char *str = opton.toAscii().data(); #if 0 //TODO: figure out how to use this so we don't need our own symkey2ucs mapping int res = Xutf8LookupString(XIC ic, XKeyPressedEvent * event, char *buffer_return, int bytes_buffer, KeySym * keysym_return, Status * status_return); #else KeySym keysym = XStringToKeysym(str); //TODO: make it more generic // if( keysym == 0xfe03 ) // return "L3"; long ucs = keysym2ucs(keysym); // if( ucs == -1 && (keysym >= 0xFE50 && keysym <= 0xFE5F) ) { // ucs = 0x0300 + (keysym & 0x000F); // qWarning() << "Got dead symbol" << QString("0x%1").arg(keysym, 0, 16) << "named" << opton << "will use" << QString("0x%1").arg(ucs, 0, 16) << "as UCS"; // } if (ucs == -1) { nill++; qWarning() << "No mapping from keysym:" << QStringLiteral("0x%1").arg(keysym, 0, 16) << "named:" << opton << "to UCS"; } QString ucsStr = QString(QChar((int)ucs)); // Combining Diacritical Marks if (ucs >= 0x0300 && ucs <= 0x036F) { ucsStr = " " + ucsStr + " "; } // qWarning() << "--" << opton << "keysym: " << keysym << QString("0x%1").arg(keysym, 0, 16) << "keysym2string" << XKeysymToString(keysym) // << "---" << QString("0x%1").arg(ucs, 0, 16) << ucsStr; keySymbolMap[opton] = ucsStr; return ucsStr; #endif }
static void handle_key(XGenericEventCookie *cookie) { XIDeviceEvent *ev = (XIDeviceEvent *)cookie->data; qboolean down = cookie->evtype == XI_KeyPress; int keycode = ev->detail; unsigned time = Sys_XTimeToSysTime(ev->time); // Ignore shift_level for game key press KeySym keysym = XkbKeycodeToKeysym(x11display.dpy, keycode, 0, 0); int key = XLateKey( keysym ); // Set or clear 1 in the shift_level bitmask if ( keysym == XK_Shift_L || keysym == XK_Shift_R ) shift_level ^= (-down ^ shift_level) & 1; // Set or clear 2 in the shift_level bitmask else if( keysym == XK_ISO_Level3_Shift ) shift_level ^= (-down ^ shift_level) & 2; Key_Event(key, down, time); if( down ) { // Use shift_level for chat and console input qwchar wc = keysym2ucs(XkbKeycodeToKeysym(x11display.dpy, keycode, 0, shift_level)); if( wc == -1 && key > K_NUMLOCK && key <= KP_EQUAL ) wc = ( qwchar )key; // Convert ctrl-c / ctrl-v combinations to the expected events if( Key_IsDown(K_LCTRL) || Key_IsDown(K_RCTRL) ) { if( key == 'v' ) { key = CTRLV; wc = CTRLV; } else if( key == 'c' ) { key = CTRLC; wc = CTRLC; } } Key_CharEvent( key, wc ); } }
static void DP_Xutf8LookupString(XKeyEvent * ev, Uchar *uch, KeySym * keysym_return, Status * status_return) { int rc; KeySym keysym; int codepoint; char buffer[64]; int nbytes = sizeof(buffer); rc = XLookupString(ev, buffer, nbytes, &keysym, NULL); if (rc > 0) { codepoint = buffer[0] & 0xFF; } else { codepoint = keysym2ucs(keysym); } if (codepoint < 0) { if (keysym == None) { *status_return = XLookupNone; } else { *status_return = XLookupKeySym; *keysym_return = keysym; } *uch = 0; return; } *uch = codepoint; if (keysym != None) { *keysym_return = keysym; *status_return = XLookupBoth; } else { *status_return = XLookupChars; } }
bool Window_mac::handleEvent(const XEvent& event) { switch (event.type) { case MapNotify: if (!fGC) { fGC = XCreateGC(fDisplay, fWindow, 0, nullptr); } break; case ClientMessage: if ((Atom)event.xclient.data.l[0] == fWmDeleteMessage && gWindowMap.count() == 1) { return true; } break; case ButtonPress: if (event.xbutton.button == Button1) { this->onMouse(event.xbutton.x, event.xbutton.y, Window::kDown_InputState, get_modifiers(event)); } break; case ButtonRelease: if (event.xbutton.button == Button1) { this->onMouse(event.xbutton.x, event.xbutton.y, Window::kUp_InputState, get_modifiers(event)); } break; case MotionNotify: // only track if left button is down if (event.xmotion.state & Button1Mask) { this->onMouse(event.xmotion.x, event.xmotion.y, Window::kMove_InputState, get_modifiers(event)); } break; case KeyPress: { int shiftLevel = (event.xkey.state & ShiftMask) ? 1 : 0; KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode, 0, shiftLevel); if (keysym == XK_Escape) { return true; } Window::Key key = get_key(keysym); if (key != Window::Key::kNONE) { (void) this->onKey(key, Window::kDown_InputState, get_modifiers(event)); } else { long uni = keysym2ucs(keysym); if (uni != -1) { (void) this->onChar((SkUnichar) uni, get_modifiers(event)); } } } break; case KeyRelease: { int shiftLevel = (event.xkey.state & ShiftMask) ? 1 : 0; KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode, 0, shiftLevel); Window::Key key = get_key(keysym); (void) this->onKey(key, Window::kUp_InputState, get_modifiers(event)); } break; default: // these events should be handled in the main event loop SkASSERT(event.type != Expose && event.type != ConfigureNotify); break; } return false; }
/* * drawevents2 calls flush to display anything that was drawn. */ static Input * drawevents2(int block, int *ninp) { static int flushing; if(!flushing){ if(screen.dirty){ drawflush(screen.r); flushing = 1; screen.dirty = 0; } ninputs = 0; } while((block && (flushing || ninputs == 0)) || XPending(display)){ XEvent ev; XNextEvent(display, &ev); switch(ev.type){ case MapNotify: case ReparentNotify: addredraw(); continue; case Expose: addredraw(); continue; case KeyPress: case KeyRelease: { XKeyEvent *ep = &ev.xkey; if(0)fprintf( stderr, "key %s %d (%x) '%c' at (%d,%d) state %x\n", ev.type == KeyPress ? "pressed" : "released", ep->keycode, ep->keycode, isprint(ep->keycode) ? ep->keycode : '.', ep->x, ep->y, ep->state ); u64int mod; KeySym keysym; int code; char keystr[8] = {0}; keysym = XLookupKeysym(ep, ep->state & (ShiftMask|LockMask)); if((code = keysym2ucs(keysym)) != -1) utf8encode(keystr, sizeof keystr-1, code); else keystr[0] = '\0'; switch(keysym){ case XK_Return: case XK_KP_Enter: strncpy(keystr, "\n", sizeof keystr-1); mod = KeyStr; break; case XK_Tab: case XK_KP_Tab: case XK_ISO_Left_Tab: strncpy(keystr, "\t", sizeof keystr-1); mod = KeyStr; break; case XK_Break: mod = KeyBreak; break; case XK_BackSpace: mod = KeyBackSpace; break; case XK_Down: mod = KeyDown; break; case XK_End: mod = KeyEnd; break; case XK_Home: mod = KeyHome; break; case XK_Left: mod = KeyLeft; break; case XK_Page_Down: mod = KeyPageDown; break; case XK_Page_Up: mod = KeyPageUp; break; case XK_Right: mod = KeyRight; break; case XK_Up: mod = KeyUp; break; case XK_Shift_L: case XK_Shift_R: mod = KeyShift; break; case XK_Control_L: case XK_Control_R: mod = KeyControl; break; case XK_Meta_L: case XK_Meta_R: mod = KeyMeta; /* mac command key */ break; case XK_Alt_L: case XK_Alt_R: mod = KeyAlt; break; case XK_Super_L: case XK_Super_R: fprintf(stderr, "super\n"); mod = KeySuper; break; case XK_Hyper_L: case XK_Hyper_R: fprintf(stderr, "hyper\n"); mod = KeyHyper; break; case XK_KP_Insert: case XK_Insert: mod = KeyIns; break; case XK_KP_Delete: case XK_Delete: mod = KeyDel; break; case XK_Caps_Lock: mod = KeyCapsLock; break; default: mod = 0; break; } addinput( 0, 0, keystr, mod, ev.type == KeyPress, ev.type == KeyRelease ); } continue; case ButtonPress: case ButtonRelease: { XButtonEvent *ep = &ev.xbutton; u64int mod; switch(ep->button){ case 0:case 1:case 2:case 3:case 4: case 5:case 6:case 7:case 9:case 10: mod = Mouse0 << ep->button; break; default: fprintf(stderr, "unsupported mouse button %d\n", ep->button); mod = 0; break; } if(mod != 0){ addinput( ep->x, ep->y, NULL, mod, ev.type == ButtonPress, ev.type == ButtonRelease ); } } continue; case EnterNotify: case LeaveNotify: fprintf(stderr, "enter/leave\n"); continue; case MotionNotify: if(input_prevmod != 0){ XMotionEvent *ep = &ev.xmotion; u64int m; if(0)fprintf( stderr, "motion at (%d,%d) state %x\n", ep->x, ep->y, ep->state ); for(m = Mouse0; m <= LastMouse; m <<= 1){ addinput( ep->x, ep->y, NULL, m, 0,0 ); } } continue; case ConfigureNotify: { XConfigureEvent *ce = &ev.xconfigure; if(ce->width != width || ce->height != height){ shmfree(); width = ce->width; height = ce->height; if(shminit() == -1){ *ninp = 0; return NULL; } addredraw(); } continue; } } if(ev.type == XShmGetEventBase(display) + ShmCompletion){ flushing = 0; if(animating){ addredraw(); } continue; } fprintf(stderr, "unknown xevent %d\n", ev.type); } if(!flushing && ninputs > 0){ *ninp = ninputs; return inputs; } *ninp = 0; return NULL; }
/* * Handles keypresses by converting the keycodes to keysymbols, then the * keysymbols to UCS-2. If the conversion succeeded, the glyph is saved in the * internal buffers and displayed in the input window. * * Also handles backspace (deleting one character) and return (sending the * command to i3). * */ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press_event_t *event) { printf("Keypress %d, state raw = %d\n", event->detail, event->state); // TODO: port the input handling code from i3lock once libxkbcommon ≥ 0.5.0 // is available in distros. /* See the documentation of xcb_key_symbols_get_keysym for this one. * Basically: We get either col 0 or col 1, depending on whether shift is * pressed. */ int col = (event->state & XCB_MOD_MASK_SHIFT); /* If modeswitch is currently active, we need to look in group 2 or 3, * respectively. */ if (modeswitch_active) col += 2; xcb_keysym_t sym = xcb_key_press_lookup_keysym(symbols, event, col); if (sym == XK_Mode_switch) { printf("Mode switch enabled\n"); modeswitch_active = true; return 1; } if (sym == XK_Return) finish_input(); if (sym == XK_BackSpace) { if (input_position == 0) return 1; input_position--; free(glyphs_utf8[input_position]); handle_expose(NULL, conn, NULL); return 1; } if (sym == XK_Escape) { exit(0); } /* TODO: handle all of these? */ printf("is_keypad_key = %d\n", xcb_is_keypad_key(sym)); printf("is_private_keypad_key = %d\n", xcb_is_private_keypad_key(sym)); printf("xcb_is_cursor_key = %d\n", xcb_is_cursor_key(sym)); printf("xcb_is_pf_key = %d\n", xcb_is_pf_key(sym)); printf("xcb_is_function_key = %d\n", xcb_is_function_key(sym)); printf("xcb_is_misc_function_key = %d\n", xcb_is_misc_function_key(sym)); printf("xcb_is_modifier_key = %d\n", xcb_is_modifier_key(sym)); if (xcb_is_modifier_key(sym) || xcb_is_cursor_key(sym)) return 1; printf("sym = %c (%d)\n", sym, sym); /* convert the keysym to UCS */ uint16_t ucs = keysym2ucs(sym); if ((int16_t)ucs == -1) { fprintf(stderr, "Keysym could not be converted to UCS, skipping\n"); return 1; } xcb_char2b_t inp; inp.byte1 = (ucs & 0xff00) >> 2; inp.byte2 = (ucs & 0x00ff) >> 0; printf("inp.byte1 = %02x, inp.byte2 = %02x\n", inp.byte1, inp.byte2); /* convert it to UTF-8 */ char *out = convert_ucs2_to_utf8(&inp, 1); printf("converted to %s\n", out); glyphs_ucs[input_position] = inp; glyphs_utf8[input_position] = out; input_position++; if (input_position == limit) finish_input(); handle_expose(NULL, conn, NULL); return 1; }
static Accessibility_DeviceEvent spi_keystroke_from_x_key_event (XKeyEvent *x_key_event) { Accessibility_DeviceEvent key_event; KeySym keysym; const int cbuf_bytes = 20; char cbuf [21]; int nbytes; nbytes = XLookupString (x_key_event, cbuf, cbuf_bytes, &keysym, NULL); key_event.id = (dbus_int32_t)(keysym); key_event.hw_code = (dbus_int16_t) x_key_event->keycode; if (((XEvent *) x_key_event)->type == KeyPress) { key_event.type = Accessibility_KEY_PRESSED_EVENT; } else { key_event.type = Accessibility_KEY_RELEASED_EVENT; } key_event.modifiers = (dbus_uint16_t)(x_key_event->state); key_event.is_text = FALSE; switch (keysym) { case ' ': key_event.event_string = g_strdup ("space"); break; case XK_Tab: key_event.event_string = g_strdup ("Tab"); break; case XK_BackSpace: key_event.event_string = g_strdup ("Backspace"); break; case XK_Return: key_event.event_string = g_strdup ("Return"); break; case XK_Home: key_event.event_string = g_strdup ("Home"); break; case XK_Page_Down: key_event.event_string = g_strdup ("Page_Down"); break; case XK_Page_Up: key_event.event_string = g_strdup ("Page_Up"); break; case XK_F1: key_event.event_string = g_strdup ("F1"); break; case XK_F2: key_event.event_string = g_strdup ("F2"); break; case XK_F3: key_event.event_string = g_strdup ("F3"); break; case XK_F4: key_event.event_string = g_strdup ("F4"); break; case XK_F5: key_event.event_string = g_strdup ("F5"); break; case XK_F6: key_event.event_string = g_strdup ("F6"); break; case XK_F7: key_event.event_string = g_strdup ("F7"); break; case XK_F8: key_event.event_string = g_strdup ("F8"); break; case XK_F9: key_event.event_string = g_strdup ("F9"); break; case XK_F10: key_event.event_string = g_strdup ("F10"); break; case XK_F11: key_event.event_string = g_strdup ("F11"); break; case XK_F12: key_event.event_string = g_strdup ("F12"); break; case XK_End: key_event.event_string = g_strdup ("End"); break; case XK_Escape: key_event.event_string = g_strdup ("Escape"); break; case XK_Up: key_event.event_string = g_strdup ("Up"); break; case XK_Down: key_event.event_string = g_strdup ("Down"); break; case XK_Left: key_event.event_string = g_strdup ("Left"); break; case XK_Right: key_event.event_string = g_strdup ("Right"); break; default: if (nbytes > 0) { gunichar c; cbuf[nbytes] = '\0'; /* OK since length is cbuf_bytes+1 */ key_event.event_string = g_strdup (cbuf); c = keysym2ucs (keysym); if (c > 0 && !g_unichar_iscntrl (c)) { key_event.is_text = TRUE; /* incorrect for some composed chars? */ } } else { key_event.event_string = g_strdup (""); } } key_event.timestamp = (dbus_uint32_t) x_key_event->time; #ifdef SPI_KEYEVENT_DEBUG { char *pressed_str = "pressed"; char *released_str = "released"; char *state_ptr; if (key_event.type == Accessibility_KEY_PRESSED_EVENT) state_ptr = pressed_str; else state_ptr = released_str; fprintf (stderr, "Key %lu %s (%c), modifiers %d; string=%s [%x] %s\n", (unsigned long) keysym, state_ptr, keysym ? (int) keysym : '*', (int) x_key_event->state, key_event.event_string, key_event.event_string[0], (key_event.is_text == TRUE) ? "(text)" : "(not text)"); } #endif #ifdef SPI_DEBUG fprintf (stderr, "%s%c\n", (x_key_event->state & Mod1Mask)?"Alt-":"", ((x_key_event->state & ShiftMask)^(x_key_event->state & LockMask))? g_ascii_toupper (keysym) : g_ascii_tolower (keysym)); fprintf (stderr, "serial: %x Time: %x\n", x_key_event->serial, x_key_event->time); #endif /* SPI_DEBUG */ return key_event; }