2
* globalaccelman_x11.cpp - manager for global hotkeys
3
* Copyright (C) 2003 Justin Karneges
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
#include"globalaccelman.h"
23
#include<qkeysequence.h>
25
#include<qapplication.h>
29
#include<X11/keysym.h>
32
// defined by X11 headers
33
const int XKeyPress = KeyPress;
34
const int XKeyRelease = KeyRelease;
49
{ Qt::Key_Escape, {1, { XK_Escape }}},
50
{ Qt::Key_Tab, {2, { XK_Tab, XK_KP_Tab }}},
51
{ Qt::Key_Backtab, {1, { XK_ISO_Left_Tab }}},
52
{ Qt::Key_Backspace, {1, { XK_BackSpace }}},
53
{ Qt::Key_Return, {1, { XK_Return }}},
54
{ Qt::Key_Enter, {1, { XK_KP_Enter }}},
55
{ Qt::Key_Insert, {2, { XK_Insert, XK_KP_Insert }}},
56
{ Qt::Key_Delete, {3, { XK_Delete, XK_KP_Delete, XK_Clear }}},
57
{ Qt::Key_Pause, {1, { XK_Pause }}},
58
{ Qt::Key_Print, {1, { XK_Print }}},
59
{ Qt::Key_SysReq, {1, { XK_Sys_Req }}},
60
{ Qt::Key_Clear, {1, { XK_KP_Begin }}},
61
{ Qt::Key_Home, {2, { XK_Home, XK_KP_Home }}},
62
{ Qt::Key_End, {2, { XK_End, XK_KP_End }}},
63
{ Qt::Key_Left, {2, { XK_Left, XK_KP_Left }}},
64
{ Qt::Key_Up, {2, { XK_Up, XK_KP_Up }}},
65
{ Qt::Key_Right, {2, { XK_Right, XK_KP_Right }}},
66
{ Qt::Key_Down, {2, { XK_Down, XK_KP_Down }}},
67
{ Qt::Key_Prior, {2, { XK_Prior, XK_KP_Prior }}},
68
{ Qt::Key_Next, {2, { XK_Next, XK_KP_Next }}},
69
{ Qt::Key_Shift, {3, { XK_Shift_L, XK_Shift_R, XK_Shift_Lock }}},
70
{ Qt::Key_Control, {2, { XK_Control_L, XK_Control_R }}},
71
{ Qt::Key_Meta, {2, { XK_Meta_L, XK_Meta_R }}},
72
{ Qt::Key_Alt, {2, { XK_Alt_L, XK_Alt_R }}},
73
{ Qt::Key_CapsLock, {1, { XK_Caps_Lock }}},
74
{ Qt::Key_NumLock, {1, { XK_Num_Lock }}},
75
{ Qt::Key_ScrollLock, {1, { XK_Scroll_Lock }}},
76
{ Qt::Key_Space, {2, { XK_space, XK_KP_Space }}},
77
{ Qt::Key_Equal, {2, { XK_equal, XK_KP_Equal }}},
78
{ Qt::Key_Asterisk, {2, { XK_asterisk, XK_KP_Multiply }}},
79
{ Qt::Key_Plus, {2, { XK_plus, XK_KP_Add }}},
80
{ Qt::Key_Comma, {2, { XK_comma, XK_KP_Separator }}},
81
{ Qt::Key_Minus, {2, { XK_minus, XK_KP_Subtract }}},
82
{ Qt::Key_Period, {2, { XK_period, XK_KP_Decimal }}},
83
{ Qt::Key_Slash, {2, { XK_slash, XK_KP_Divide }}},
84
{ Qt::Key_F1, {1, { XK_F1 }}},
85
{ Qt::Key_F2, {1, { XK_F2 }}},
86
{ Qt::Key_F3, {1, { XK_F3 }}},
87
{ Qt::Key_F4, {1, { XK_F4 }}},
88
{ Qt::Key_F5, {1, { XK_F5 }}},
89
{ Qt::Key_F6, {1, { XK_F6 }}},
90
{ Qt::Key_F7, {1, { XK_F7 }}},
91
{ Qt::Key_F8, {1, { XK_F8 }}},
92
{ Qt::Key_F9, {1, { XK_F9 }}},
93
{ Qt::Key_F10, {1, { XK_F10 }}},
94
{ Qt::Key_F11, {1, { XK_F11 }}},
95
{ Qt::Key_F12, {1, { XK_F12 }}},
96
{ Qt::Key_F13, {1, { XK_F13 }}},
97
{ Qt::Key_F14, {1, { XK_F14 }}},
98
{ Qt::Key_F15, {1, { XK_F15 }}},
99
{ Qt::Key_F16, {1, { XK_F16 }}},
100
{ Qt::Key_F17, {1, { XK_F17 }}},
101
{ Qt::Key_F18, {1, { XK_F18 }}},
102
{ Qt::Key_F19, {1, { XK_F19 }}},
103
{ Qt::Key_F20, {1, { XK_F20 }}},
104
{ Qt::Key_F21, {1, { XK_F21 }}},
105
{ Qt::Key_F22, {1, { XK_F22 }}},
106
{ Qt::Key_F23, {1, { XK_F23 }}},
107
{ Qt::Key_F24, {1, { XK_F24 }}},
108
{ Qt::Key_F25, {1, { XK_F25 }}},
109
{ Qt::Key_F26, {1, { XK_F26 }}},
110
{ Qt::Key_F27, {1, { XK_F27 }}},
111
{ Qt::Key_F28, {1, { XK_F28 }}},
112
{ Qt::Key_F29, {1, { XK_F29 }}},
113
{ Qt::Key_F30, {1, { XK_F30 }}},
114
{ Qt::Key_F31, {1, { XK_F31 }}},
115
{ Qt::Key_F32, {1, { XK_F32 }}},
116
{ Qt::Key_F33, {1, { XK_F33 }}},
117
{ Qt::Key_F34, {1, { XK_F34 }}},
118
{ Qt::Key_F35, {1, { XK_F35 }}},
119
{ Qt::Key_Super_L, {1, { XK_Super_L }}},
120
{ Qt::Key_Super_R, {1, { XK_Super_R }}},
121
{ Qt::Key_Menu, {1, { XK_Menu }}},
122
{ Qt::Key_Hyper_L, {1, { XK_Hyper_L }}},
123
{ Qt::Key_Hyper_R, {1, { XK_Hyper_R }}},
124
{ Qt::Key_Help, {1, { XK_Help }}},
125
{ Qt::Key_Direction_L,{0, { 0 }}},
126
{ Qt::Key_Direction_R,{0, { 0 }}},
128
{ Qt::Key_unknown, {0, { 0 }}},
131
static long alt_mask = 0;
132
static long meta_mask = 0;
133
static bool haveMods = false;
135
// adapted from qapplication_x11.cpp
136
static void ensureModifiers()
141
Display *appDpy = qt_xdisplay();
142
XModifierKeymap *map = XGetModifierMapping(appDpy);
144
int i, maskIndex = 0, mapIndex = 0;
145
for (maskIndex = 0; maskIndex < 8; maskIndex++) {
146
for (i = 0; i < map->max_keypermod; i++) {
147
if (map->modifiermap[mapIndex]) {
148
KeySym sym = XKeycodeToKeysym(appDpy, map->modifiermap[mapIndex], 0);
149
if ( alt_mask == 0 && ( sym == XK_Alt_L || sym == XK_Alt_R ) ) {
150
alt_mask = 1 << maskIndex;
152
if ( meta_mask == 0 && (sym == XK_Meta_L || sym == XK_Meta_R ) ) {
153
meta_mask = 1 << maskIndex;
160
XFreeModifiermap(map);
165
meta_mask = Mod4Mask;
171
static bool convertKeySequence(const QKeySequence &ks, unsigned int *_mod, QT_XK_KEYGROUP *_kg)
176
unsigned int mod = 0;
189
// see if it is in our table
191
for(int n = 0; qt_xk_table[n].key != Qt::Key_unknown; ++n) {
192
if(qt_xk_table[n].key == code) {
193
kg = qt_xk_table[n].xk;
201
if(code >= 0x20 && code <= 0x7f) {
223
XUngrabKey(dsp, code, mod, grab);
227
static int XGrabErrorHandler(Display *, XErrorEvent *)
233
static X11HotKey * bind(int keysym, unsigned int mod)
235
Display *dsp = qt_xdisplay();
236
Window grab = qt_xrootwin();
237
int code = XKeysymToKeycode(dsp, keysym);
239
XErrorHandler savedErrorHandler = XSetErrorHandler(XGrabErrorHandler);
240
XGrabKey(dsp, code, mod, grab, False, GrabModeAsync, GrabModeAsync);
242
XSetErrorHandler(savedErrorHandler);
245
X11HotKey *k = new X11HotKey;
253
Display *dsp; // X11 display
254
Window grab; // Window (root window, in our case)
256
unsigned int mod; // modifiers (shift/alt/etc)
259
bool X11HotKey::failed;
266
list.setAutoDelete(true);
273
static X11HotKeyGroup * bind(const QT_XK_KEYGROUP &kg, unsigned int mod, int qkey, int id)
275
QPtrList<X11HotKey> list;
276
for(int n = 0; n < kg.num; ++n) {
277
X11HotKey *k = X11HotKey::bind(kg.sym[n], mod);
283
X11HotKeyGroup *h = new X11HotKeyGroup;
290
QPtrList<X11HotKey> list; // Associated X11HotKeys
291
int qkey; // Qt keycode (with modifiers)
292
int id; // GlobalAccelManager unique ID for this hotkey
295
class GlobalAccelManager::Private
298
Private(GlobalAccelManager *_man)
302
list.setAutoDelete(true);
303
f = new Filter(this);
304
qApp->installEventFilter(f);
309
qApp->removeEventFilter(f);
313
bool isThisYours(int qkey)
315
QPtrListIterator<X11HotKeyGroup> it(list);
316
for(X11HotKeyGroup *k; (k = it.current()); ++it) {
317
if(k->qkey == qkey) {
318
man->triggerActivated(k->id);
325
class Filter : public QObject
334
bool eventFilter(QObject *o, QEvent *e)
336
if(e->type() == QEvent::KeyPress) {
337
QKeyEvent *k = (QKeyEvent *)e;
339
if(k->state() & ShiftButton)
341
if(k->state() & ControlButton)
343
if(k->state() & AltButton)
345
if(k->state() & MetaButton)
348
if(p->isThisYours(qkey))
351
return QObject::eventFilter(o, e);
358
GlobalAccelManager *man;
361
QPtrList<X11HotKeyGroup> list;
364
GlobalAccelManager::GlobalAccelManager()
366
d = new Private(this);
369
GlobalAccelManager::~GlobalAccelManager()
374
int GlobalAccelManager::setAccel(const QKeySequence &ks)
378
if(!convertKeySequence(ks, &mod, &kg))
381
X11HotKeyGroup *h = X11HotKeyGroup::bind(kg, mod, ks, d->id_at++);
389
void GlobalAccelManager::removeAccel(int id)
391
QPtrListIterator<X11HotKeyGroup> it(d->list);
392
for(X11HotKeyGroup *hk = 0; (hk = it.current()); ++it) {
394
d->list.removeRef(hk);