File indexing completed on 2024-04-28 05:52:14
0001 // SPDX-License-Identifier: LGPL-2.1-only 0002 0003 #include "qglobalshortcut.h" 0004 #include <QKeySequence> 0005 #include <QX11Info> 0006 #include <QApplication> 0007 #include <xcb/xcb.h> 0008 #include <X11/Xlib.h> 0009 #include <X11/keysym.h> 0010 0011 bool QGlobalShortcut::QGlobalShortcutEventFilter::nativeEventFilter( 0012 const QByteArray& eventType, void* message, long* result) 0013 { 0014 if (eventType != "xcb_generic_event_t") { 0015 return false; 0016 } 0017 0018 xcb_generic_event_t* e = static_cast<xcb_generic_event_t*>(message); 0019 if ((e->response_type & ~0x80) == XCB_KEY_PRESS) { 0020 xcb_key_press_event_t* ke = (xcb_key_press_event_t*)e; 0021 xcb_get_keyboard_mapping_reply_t rep; 0022 xcb_keysym_t* k = xcb_get_keyboard_mapping_keysyms(&rep); 0023 quint32 keycode = ke->detail; 0024 quint32 mods = ke->state & (ShiftMask|ControlMask|Mod1Mask|Mod3Mask); 0025 return activate(calcId(keycode, mods)); 0026 } 0027 return false; 0028 } 0029 0030 quint32 QGlobalShortcut::calcId(quint32 k, quint32 m) { 0031 return k | (m << 16); 0032 } 0033 0034 quint32 QGlobalShortcut::toNativeKeycode(Qt::Key k) { 0035 if (qApp->closingDown()) { 0036 return 0; 0037 } 0038 /* keysymdef.h */ 0039 quint32 key = 0; 0040 if (k >= Qt::Key_F1 && k <= Qt::Key_F35) { 0041 key = XK_F1 + (k - Qt::Key_F1); 0042 } else if (k >= Qt::Key_Space && k <= Qt::Key_QuoteLeft) { 0043 key = k; 0044 } else if (k >= Qt::Key_BraceLeft && k <= Qt::Key_AsciiTilde) { 0045 key = k; 0046 } else if (k >= Qt::Key_nobreakspace && k <= Qt::Key_ydiaeresis) { 0047 key = k; 0048 } else { 0049 switch (k) { 0050 case Qt::Key_Escape: 0051 key = XK_Escape; 0052 break; 0053 case Qt::Key_Tab: 0054 case Qt::Key_Backtab: 0055 key = XK_Tab; 0056 break; 0057 case Qt::Key_Backspace: 0058 key = XK_BackSpace; 0059 break; 0060 case Qt::Key_Return: 0061 case Qt::Key_Enter: 0062 key = XK_Return; 0063 break; 0064 case Qt::Key_Insert: 0065 key = XK_Insert; 0066 break; 0067 case Qt::Key_Delete: 0068 key = XK_Delete; 0069 break; 0070 case Qt::Key_Pause: 0071 key = XK_Pause; 0072 break; 0073 case Qt::Key_Print: 0074 key = XK_Print; 0075 break; 0076 case Qt::Key_SysReq: 0077 key = XK_Sys_Req; 0078 break; 0079 case Qt::Key_Clear: 0080 key = XK_Clear; 0081 break; 0082 case Qt::Key_Home: 0083 key = XK_Home; 0084 break; 0085 case Qt::Key_End: 0086 key = XK_End; 0087 break; 0088 case Qt::Key_Left: 0089 key = XK_Left; 0090 break; 0091 case Qt::Key_Up: 0092 key = XK_Up; 0093 break; 0094 case Qt::Key_Right: 0095 key = XK_Right; 0096 break; 0097 case Qt::Key_Down: 0098 key = XK_Down; 0099 break; 0100 case Qt::Key_PageUp: 0101 key = XK_Page_Up; 0102 break; 0103 case Qt::Key_PageDown: 0104 key = XK_Page_Down; 0105 break; 0106 default: 0107 key = 0; 0108 } 0109 } 0110 return XKeysymToKeycode(QX11Info::display(), key); 0111 } 0112 0113 quint32 QGlobalShortcut::toNativeModifiers(Qt::KeyboardModifiers m) { 0114 quint32 mods = Qt::NoModifier; 0115 if (m & Qt::ShiftModifier) 0116 mods |= ShiftMask; 0117 if (m & Qt::ControlModifier) 0118 mods |= ControlMask; 0119 if (m & Qt::AltModifier) 0120 mods |= Mod1Mask; 0121 if (m & Qt::MetaModifier) 0122 mods |= Mod4Mask; 0123 return mods; 0124 } 0125 0126 void QGlobalShortcut::registerKey(quint32 k, quint32 m, quint32 id) { 0127 if (qApp->closingDown()) { 0128 return; 0129 } 0130 0131 xcb_grab_key(QX11Info::connection(), 1, QX11Info::appRootWindow(), 0132 m, k, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); 0133 } 0134 0135 void QGlobalShortcut::unregisterKey(quint32 k, quint32 m, quint32 id) { 0136 // this function is called in the destructor, and if that is called during 0137 // quitting QX11Info has already been destroyed. 0138 if (qApp->closingDown()) { 0139 return; 0140 } 0141 xcb_ungrab_key(QX11Info::connection(), k, QX11Info::appRootWindow(), m); 0142 }