source: psi/trunk/src/tools/globalaccel/globalaccelman_win.cpp

Last change on this file was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 6.3 KB
Line 
1/*
2 * globalaccelman_win.cpp - manager for global hotkeys
3 * Copyright (C) 2003 Justin Karneges
4 *
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.
9 *
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.
14 *
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
18 *
19 */
20
21// TODO:
22// - don't invoke hotkey if there is a modal dialog?
23// - do multi-mapping, like the x11 version
24
25#include"globalaccelman.h"
26
27#include<qkeysequence.h>
28#include<qwidget.h>
29#include<qptrlist.h>
30
31#include<windows.h>
32
33// We'll start our hotkeys at offset 0x1000 in the Windows hotkey table (no real reason)
34#define HOTKEY_START 0x1000
35
36struct QT_VK_KEYMAP
37{
38 int key;
39 UINT vk;
40} qt_vk_table[] = {
41 { Qt::Key_Escape, VK_ESCAPE },
42 { Qt::Key_Tab, VK_TAB },
43 { Qt::Key_Backtab, 0 },
44 { Qt::Key_Backspace, VK_BACK },
45 { Qt::Key_Return, VK_RETURN },
46 { Qt::Key_Enter, VK_RETURN },
47 { Qt::Key_Insert, VK_INSERT },
48 { Qt::Key_Delete, VK_DELETE },
49 { Qt::Key_Pause, VK_PAUSE },
50 { Qt::Key_Print, VK_PRINT },
51 { Qt::Key_SysReq, 0 },
52 { Qt::Key_Clear, VK_CLEAR },
53 { Qt::Key_Home, VK_HOME },
54 { Qt::Key_End, VK_END },
55 { Qt::Key_Left, VK_LEFT },
56 { Qt::Key_Up, VK_UP },
57 { Qt::Key_Right, VK_RIGHT },
58 { Qt::Key_Down, VK_DOWN },
59 { Qt::Key_Prior, VK_PRIOR },
60 { Qt::Key_Next, VK_NEXT },
61 { Qt::Key_Shift, VK_SHIFT },
62 { Qt::Key_Control, VK_CONTROL },
63 { Qt::Key_Meta, VK_LWIN },
64 { Qt::Key_Alt, VK_MENU },
65 { Qt::Key_CapsLock, VK_CAPITAL },
66 { Qt::Key_NumLock, VK_NUMLOCK },
67 { Qt::Key_ScrollLock, VK_SCROLL },
68 { Qt::Key_F1, VK_F1 },
69 { Qt::Key_F2, VK_F2 },
70 { Qt::Key_F3, VK_F3 },
71 { Qt::Key_F4, VK_F4 },
72 { Qt::Key_F5, VK_F5 },
73 { Qt::Key_F6, VK_F6 },
74 { Qt::Key_F7, VK_F7 },
75 { Qt::Key_F8, VK_F8 },
76 { Qt::Key_F9, VK_F9 },
77 { Qt::Key_F10, VK_F10 },
78 { Qt::Key_F11, VK_F11 },
79 { Qt::Key_F12, VK_F12 },
80 { Qt::Key_F13, VK_F13 },
81 { Qt::Key_F14, VK_F14 },
82 { Qt::Key_F15, VK_F15 },
83 { Qt::Key_F16, VK_F16 },
84 { Qt::Key_F17, VK_F17 },
85 { Qt::Key_F18, VK_F18 },
86 { Qt::Key_F19, VK_F19 },
87 { Qt::Key_F20, VK_F20 },
88 { Qt::Key_F21, VK_F21 },
89 { Qt::Key_F22, VK_F22 },
90 { Qt::Key_F23, VK_F23 },
91 { Qt::Key_F24, VK_F24 },
92 { Qt::Key_F25, 0 },
93 { Qt::Key_F26, 0 },
94 { Qt::Key_F27, 0 },
95 { Qt::Key_F28, 0 },
96 { Qt::Key_F29, 0 },
97 { Qt::Key_F30, 0 },
98 { Qt::Key_F31, 0 },
99 { Qt::Key_F32, 0 },
100 { Qt::Key_F33, 0 },
101 { Qt::Key_F34, 0 },
102 { Qt::Key_F35, 0 },
103 { Qt::Key_Super_L, 0 },
104 { Qt::Key_Super_R, 0 },
105 { Qt::Key_Menu, 0 },
106 { Qt::Key_Hyper_L, 0 },
107 { Qt::Key_Hyper_R, 0 },
108 { Qt::Key_Help, 0 },
109 { Qt::Key_Direction_L,0 },
110 { Qt::Key_Direction_R,0 },
111
112 { Qt::Key_unknown, 0 },
113};
114
115static bool convertKeySequence(const QKeySequence &ks, UINT *_mod, UINT *_key)
116{
117 int code = ks;
118
119 UINT mod = 0;
120 if(code & Qt::META)
121 mod |= MOD_WIN;
122 if(code & Qt::SHIFT)
123 mod |= MOD_SHIFT;
124 if(code & Qt::CTRL)
125 mod |= MOD_CONTROL;
126 if(code & Qt::ALT)
127 mod |= MOD_ALT;
128
129 UINT key = 0;
130 code &= 0xffff;
131 if(code >= 0x20 && code <= 0x7f)
132 key = code;
133 else {
134 for(int n = 0; qt_vk_table[n].key != Qt::Key_unknown; ++n) {
135 if(qt_vk_table[n].key == code) {
136 key = qt_vk_table[n].vk;
137 break;
138 }
139 }
140 if(!key)
141 return false;
142 }
143
144 if(_mod)
145 *_mod = mod;
146 if(_key)
147 *_key = key;
148
149 return true;
150}
151
152class WindowsHotKey
153{
154public:
155 WindowsHotKey(HWND _w, int _win_key_id, int _id)
156 {
157 w = _w;
158 win_key_id = _win_key_id;
159 id = _id;
160 }
161
162 ~WindowsHotKey()
163 {
164 UnregisterHotKey(w, win_key_id);
165 }
166
167 HWND w;
168 int win_key_id; // Windows hotkey slot number
169 int id; // GlobalAccelManager unique ID for this hotkey
170};
171
172class GlobalAccelManager::Private
173{
174public:
175 Private(GlobalAccelManager *par)
176 {
177 manager = par;
178 id_at = 1;
179 hidden = new HiddenWidget(this);
180 list.setAutoDelete(true);
181 }
182
183 ~Private()
184 {
185 delete hidden;
186 }
187
188 int getFreeSlot() const
189 {
190 QPtrListIterator<WindowsHotKey> it(list);
191 // find first non-match
192 int n = HOTKEY_START;
193 for(WindowsHotKey *hk = 0; (hk = it.current()); ++it) {
194 if(hk->win_key_id != n)
195 break;
196 ++n;
197 }
198 return n;
199 }
200
201 int insertHotKey(int win_key_id)
202 {
203 WindowsHotKey *hk = new WindowsHotKey(hidden->winId(), win_key_id, id_at++);
204 if(win_key_id >= (int)list.count())
205 list.append(hk);
206 else
207 list.insert(win_key_id - HOTKEY_START, hk);
208 return hk->id;
209 }
210
211 void hotkeyActivated(int win_key_id)
212 {
213 QPtrListIterator<WindowsHotKey> it(list);
214 for(WindowsHotKey *hk = 0; (hk = it.current()); ++it) {
215 if(hk->win_key_id == win_key_id)
216 manager->triggerActivated(hk->id);
217 }
218 }
219
220 class HiddenWidget : public QWidget
221 {
222 public:
223 HiddenWidget(Private *_p)
224 {
225 p = _p;
226 }
227
228 protected:
229 bool winEvent(MSG *m)
230 {
231 m->message &= 0xffff;
232 if(m->message == WM_HOTKEY) {
233 p->hotkeyActivated(m->wParam);
234 return true;
235 }
236 return QWidget::winEvent(m);
237 }
238
239 private:
240 Private *p;
241 };
242
243 GlobalAccelManager *manager;
244 int id_at;
245 HiddenWidget *hidden;
246 QPtrList<WindowsHotKey> list;
247};
248
249GlobalAccelManager::GlobalAccelManager()
250{
251 d = new Private(this);
252}
253
254GlobalAccelManager::~GlobalAccelManager()
255{
256 delete d;
257}
258
259int GlobalAccelManager::setAccel(const QKeySequence &ks)
260{
261 UINT mod, key;
262 if(!convertKeySequence(ks, &mod, &key))
263 return 0;
264
265 int win_key_id = d->getFreeSlot();
266
267 if(!RegisterHotKey(d->hidden->winId(), win_key_id, mod, key))
268 return 0;
269
270 return d->insertHotKey(win_key_id);
271}
272
273void GlobalAccelManager::removeAccel(int id)
274{
275 QPtrListIterator<WindowsHotKey> it(d->list);
276 for(WindowsHotKey *hk = 0; (hk = it.current()); ++it) {
277 if(hk->id == id) {
278 d->list.removeRef(hk);
279 return;
280 }
281 }
282}
Note: See TracBrowser for help on using the repository browser.