x11keyfaker.cpp

来自「Qt4.5 提供的qvfb,最新版本」· C++ 代码 · 共 627 行 · 第 1/2 页

CPP
627
字号
	case Qt::Key_Hangul: keysym = XK_Hangul; break;	case Qt::Key_Hangul_Start: keysym = XK_Hangul_Start; break;	case Qt::Key_Hangul_End: keysym = XK_Hangul_End; break;	case Qt::Key_Hangul_Hanja: keysym = XK_Hangul_Hanja; break;	case Qt::Key_Hangul_Jamo: keysym = XK_Hangul_Jamo; break;	case Qt::Key_Hangul_Romaja: keysym = XK_Hangul_Romaja; break;	case Qt::Key_Hangul_Jeonja: keysym = XK_Hangul_Jeonja; break;	case Qt::Key_Hangul_Banja: keysym = XK_Hangul_Banja; break;	case Qt::Key_Hangul_PreHanja: keysym = XK_Hangul_PreHanja; break;	case Qt::Key_Hangul_PostHanja: keysym = XK_Hangul_PostHanja; break;	case Qt::Key_Hangul_Special: keysym = XK_Hangul_Special; break;        case Qt::Key_Dead_Grave: keysym = XK_dead_grave; break;        case Qt::Key_Dead_Acute: keysym = XK_dead_acute; break;        case Qt::Key_Dead_Circumflex: keysym = XK_dead_circumflex; break;        case Qt::Key_Dead_Tilde: keysym = XK_dead_tilde; break;        case Qt::Key_Dead_Macron: keysym = XK_dead_macron; break;        case Qt::Key_Dead_Breve: keysym = XK_dead_breve; break;        case Qt::Key_Dead_Abovedot: keysym = XK_dead_abovedot; break;        case Qt::Key_Dead_Diaeresis: keysym = XK_dead_diaeresis; break;        case Qt::Key_Dead_Abovering: keysym = XK_dead_abovering; break;        case Qt::Key_Dead_Doubleacute: keysym = XK_dead_doubleacute; break;        case Qt::Key_Dead_Caron: keysym = XK_dead_caron; break;        case Qt::Key_Dead_Cedilla: keysym = XK_dead_cedilla; break;        case Qt::Key_Dead_Ogonek: keysym = XK_dead_ogonek; break;        case Qt::Key_Dead_Iota: keysym = XK_dead_iota; break;        case Qt::Key_Dead_Voiced_Sound: keysym = XK_dead_voiced_sound; break;        case Qt::Key_Dead_Semivoiced_Sound: keysym = XK_dead_semivoiced_sound; break;        case Qt::Key_Dead_Belowdot: keysym = XK_dead_belowdot; break;        case Qt::Key_Dead_Hook: keysym = XK_dead_hook; break;        case Qt::Key_Dead_Horn: keysym = XK_dead_horn; break;        case Qt::Key_Back: keysym = XF86XK_Back; break;        case Qt::Key_Forward: keysym = XF86XK_Forward; break;        case Qt::Key_Stop: keysym = XF86XK_Stop; break;        case Qt::Key_Refresh: keysym = XF86XK_Refresh; break;        case Qt::Key_VolumeDown: keysym = XF86XK_AudioLowerVolume; break;        case Qt::Key_VolumeMute: keysym = XF86XK_AudioMute; break;        case Qt::Key_VolumeUp: keysym = XF86XK_AudioRaiseVolume; break;        case Qt::Key_BassBoost: keysym = NoSymbol; break;	// ???        case Qt::Key_BassUp: keysym = NoSymbol; break;		// ???        case Qt::Key_BassDown: keysym = NoSymbol; break;	// ???        case Qt::Key_TrebleUp: keysym = NoSymbol; break;	// ???        case Qt::Key_TrebleDown: keysym = NoSymbol; break;	// ???        case Qt::Key_MediaPlay: keysym = XF86XK_AudioPlay; break;        case Qt::Key_MediaStop: keysym = XF86XK_AudioStop; break;        case Qt::Key_MediaPrevious: keysym = XF86XK_AudioPrev; break;        case Qt::Key_MediaNext: keysym = XF86XK_AudioNext; break;        case Qt::Key_MediaRecord: keysym = XF86XK_AudioRecord; break;        case Qt::Key_HomePage: keysym = XF86XK_HomePage; break;        case Qt::Key_Favorites: keysym = XF86XK_Favorites; break;        case Qt::Key_Search: keysym = XF86XK_Search; break;        case Qt::Key_Standby: keysym = XF86XK_Standby; break;        case Qt::Key_OpenUrl: keysym = XF86XK_OpenURL; break;        case Qt::Key_LaunchMail: keysym = XF86XK_Mail; break;        case Qt::Key_LaunchMedia: keysym = XF86XK_AudioMedia; break;        case Qt::Key_Launch0: keysym = XF86XK_Launch0; break;        case Qt::Key_Launch1: keysym = XF86XK_Launch1; break;        case Qt::Key_Launch2: keysym = XF86XK_Launch2; break;        case Qt::Key_Launch3: keysym = XF86XK_Launch3; break;        case Qt::Key_Launch4: keysym = XF86XK_Launch4; break;        case Qt::Key_Launch5: keysym = XF86XK_Launch5; break;        case Qt::Key_Launch6: keysym = XF86XK_Launch6; break;        case Qt::Key_Launch7: keysym = XF86XK_Launch7; break;        case Qt::Key_Launch8: keysym = XF86XK_Launch8; break;        case Qt::Key_Launch9: keysym = XF86XK_Launch9; break;        case Qt::Key_LaunchA: keysym = XF86XK_LaunchA; break;        case Qt::Key_LaunchB: keysym = XF86XK_LaunchB; break;        case Qt::Key_LaunchC: keysym = XF86XK_LaunchC; break;        case Qt::Key_LaunchD: keysym = XF86XK_LaunchD; break;        case Qt::Key_LaunchE: keysym = XF86XK_LaunchE; break;        case Qt::Key_LaunchF: keysym = XF86XK_LaunchF; break;        case Qt::Key_MediaLast: keysym = NoSymbol; break;   // ???        case Qt::Key_Select: keysym = QTOPIAXK_Select; break;        case Qt::Key_Yes: keysym = QTOPIAXK_Yes; break;        case Qt::Key_No: keysym = QTOPIAXK_No; break;        case Qt::Key_Cancel: keysym = QTOPIAXK_Cancel; break;        case Qt::Key_Printer: keysym = QTOPIAXK_Printer; break;        case Qt::Key_Execute: keysym = QTOPIAXK_Execute; break;        case Qt::Key_Sleep: keysym = QTOPIAXK_Sleep; break;        case Qt::Key_Play: keysym = QTOPIAXK_Play; break;        case Qt::Key_Zoom: keysym = QTOPIAXK_Zoom; break;        case Qt::Key_Context1: keysym = QTOPIAXK_Context1; break;        case Qt::Key_Context2: keysym = QTOPIAXK_Context2; break;        case Qt::Key_Context3: keysym = QTOPIAXK_Context3; break;        case Qt::Key_Context4: keysym = QTOPIAXK_Context4; break;        case Qt::Key_Call: keysym = QTOPIAXK_Call; break;        case Qt::Key_Hangup: keysym = QTOPIAXK_Hangup; break;        case Qt::Key_Flip: keysym = QTOPIAXK_Flip; break;        case Qt::Key_unknown: keysym = NoSymbol; break;    }    if (keysym == NoSymbol)	return;    // Convert the X keysym into an X keycode.    KeyCode keycode = XKeysymToKeycode(dpy, keysym);    if (keycode == NoSymbol)	return;    // Determine if we need to fake shift keys as well.    int index = 0;    while (index < 4 && XKeycodeToKeysym(dpy, keycode, index) != keysym)	++index;    int extraModifiers = 0;    if ((index & 1) != 0)	extraModifiers |= ShiftMask;    if ((index & 2) != 0)	extraModifiers |= Mod2Mask;    if ((modifiers & LockMask) != 0) {	// If Caps Lock is set, then flip the shift state for alphabetic keys.	if (qtCode >= Qt::Key_A && qtCode <= Qt::Key_Z)	    extraModifiers ^= ShiftMask;	if (qtCode >= Qt::Key_Agrave && qtCode <= Qt::Key_THORN &&	    qtCode != Qt::Key_multiply)	    extraModifiers ^= ShiftMask;    }    // Adjust modifier keys for the shift states.  This is needed for    // things like the * and # phone keys, which need Shift to be pressed    // when entering from a keyboard, but don't need Shift from a skin.    unsigned long delay = 0;    if (extraModifiers != 0) {	if ((extraModifiers & ShiftMask) != 0) {	    if ((modifiers & ShiftMask) == 0)		XTestFakeKeyEvent(dpy, shiftKeycode, true, delay++);	} else {	    if ((modifiers & ShiftMask) != 0)		XTestFakeKeyEvent(dpy, shiftKeycode, false, delay++);	}	if ((extraModifiers & Mod2Mask) != 0) {	    if ((modifiers & Mod2Mask) == 0)		XTestFakeKeyEvent(dpy, modeSwitchKeycode, true, delay++);	} else {	    if ((modifiers & Mod2Mask) != 0)		XTestFakeKeyEvent(dpy, modeSwitchKeycode, false, delay++);	}    }    // Fake the actual key.    XTestFakeKeyEvent(dpy, keycode, (Bool)isPress, delay++);    // Adjust the modifiers back.    if (extraModifiers != 0) {	if ((extraModifiers & ShiftMask) != 0) {	    if ((modifiers & ShiftMask) == 0)		XTestFakeKeyEvent(dpy, shiftKeycode, false, delay++);	} else {	    if ((modifiers & ShiftMask) != 0)		XTestFakeKeyEvent(dpy, shiftKeycode, true, delay++);	}	if ((extraModifiers & Mod2Mask) != 0) {	    if ((modifiers & Mod2Mask) == 0)		XTestFakeKeyEvent(dpy, modeSwitchKeycode, false, delay++);	} else {	    if ((modifiers & Mod2Mask) != 0)		XTestFakeKeyEvent(dpy, modeSwitchKeycode, true, delay++);	}    }    // Flush the key events.    XFlush(dpy);    // Update the modifiers if this was a shift key.    if (isPress) {	if (qtCode == Qt::Key_Shift)	    modifiers |= ShiftMask;	if (qtCode == Qt::Key_CapsLock)	    modifiers |= LockMask;	if (qtCode == Qt::Key_Mode_switch)	    modifiers |= Mod2Mask;    } else {	if (qtCode == Qt::Key_Shift)	    modifiers &= ~ShiftMask;	if (qtCode == Qt::Key_CapsLock)	    modifiers &= ~LockMask;	if (qtCode == Qt::Key_Mode_switch)	    modifiers &= ~Mod2Mask;    }}// Determine if an X11 keycode is currently mapped to one or more keysyms.static bool keycodeInUse(Display *dpy, int keycode){    for (int index = 0; index < 8; ++index) {	if (XKeycodeToKeysym(dpy, keycode, index) != NoSymbol)	    return true;    }    return false;}// Allocate a keycode for a special keysym.static bool allocateSpecialKeysym	(Display *dpy, int& min_keycode, int& max_keycode, KeySym key){    if (XKeysymToKeycode(dpy, key) != NoSymbol)	return true; // There is already a mapping for this key.  Good!    while (max_keycode >= min_keycode) {	if (!keycodeInUse(dpy, max_keycode))	    break;	--max_keycode;    }    if (max_keycode < min_keycode)	return false;    XChangeKeyboardMapping(dpy, max_keycode, 1, &key, 1);    --max_keycode;    return true;}void X11KeyFaker::connect(){    // Open the display.    dpy = XOpenDisplay(displayName.toLatin1().data());    if (!dpy) {	// Try again in a few milliseconds.  Xnest may not be alive yet.	// Give up after 10 seconds.	if (++retryCount < 50)	    QTimer::singleShot(200, this, SLOT(connect()));	else	    QTimer::singleShot(0, this, SIGNAL(couldNotConnect()));	return;    }    // Query the XTest extension, which we need to fake the key events.    int event_base, error_base, major, minor;    if (!XTestQueryExtension	    (dpy, &event_base, &error_base, &major, &minor)) {	XCloseDisplay(dpy);	dpy = 0;	QTimer::singleShot(0, this, SIGNAL(couldNotConnect()));	return;    }    // Modify the Xnest's keyboard mappings to add Qtopia's special keysyms.    int min_keycode = 1, max_keycode = 255;    XDisplayKeycodes(dpy, &min_keycode, &max_keycode);    bool ok = true;    for (KeySym key = QTOPIAXK_Max; key >= QTOPIAXK_Min; --key) {	// This is an extension keysym, not part of the standard X11 set.	if (!allocateSpecialKeysym(dpy, min_keycode, max_keycode, key)) {	    ok = false;	    break;	}    }    static const KeySym specials[] = {	XF86XK_Back,		    // Qt::Key_Back        XF86XK_AudioLowerVolume,    // Qt::Key_VolumeUp        XF86XK_AudioRaiseVolume,    // Qt::Key_VolumeDown	XK_F28,			    // Qt::Key_F28	NoSymbol    };    int index = 0;    while (ok && specials[index] != NoSymbol) {	// This is a standard X11/XFree86 keysym that Qtopia uses,	// but it may not be on the user's physical keyboard.	if (!allocateSpecialKeysym		(dpy, min_keycode, max_keycode, specials[index]))	    ok = false;	++index;    }    if (!ok)	qWarning() << "There are insufficient spare X11 keycodes to allocate the special Qtopia keys";    // Change the root cursor to something more reasonable than "X".    Cursor cursor = XCreateFontCursor(dpy, XC_left_ptr);    XDefineCursor(dpy, RootWindow(dpy, DefaultScreen(dpy)), cursor);    // Look up the shift keys.    shiftKeycode = XKeysymToKeycode(dpy, XK_Shift_L);    if (shiftKeycode == NoSymbol)	shiftKeycode = XKeysymToKeycode(dpy, XK_Shift_R);    modeSwitchKeycode = XKeysymToKeycode(dpy, XK_Mode_switch);    // Make sure all of the above changes are flushed.    XFlush(dpy);    // Set up event handling for the display.    QSocketNotifier *notifier = new QSocketNotifier	(ConnectionNumber(dpy), QSocketNotifier::Read, this);    QObject::connect(notifier, SIGNAL(activated(int)), this, SLOT(readyRead()));    // Make sure the file descriptor is not inherited across exec's.    fcntl(ConnectionNumber(dpy), F_SETFD, 1);    // Notify interested parties that we are now connected to the X display.    QTimer::singleShot(0, this, SIGNAL(connected()));}void X11KeyFaker::readyRead(){    if (dpy) {	// Read incoming events and discard them.  The only event	// we care about is keyboard mapping changes.  Since we	// don't have any active windows, there's nothing more to do.	while (XEventsQueued(dpy, QueuedAfterFlush)) {	    XEvent event;	    XNextEvent(dpy, &event);	    if (event.xany.type == MappingNotify)		XRefreshKeyboardMapping(&event.xmapping);	}    }}QT_END_NAMESPACE

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?