1 // KeyUtil.cc for FbTk
2 // Copyright (c) 2003 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
21
22 // $Id: KeyUtil.cc 4199 2006-02-16 06:53:05Z mathias $
23
24 #include "KeyUtil.hh"
25 #include "App.hh"
26
27 #include <string>
28
29 namespace {
30
31 struct t_modlist{
32 char *str;
33 unsigned int mask;
operator ==__anon0cb963360111::t_modlist34 bool operator == (const char *modstr) const {
35 return (strcasecmp(str, modstr) == 0 && mask !=0);
36 }
37 };
38
39 const struct t_modlist modlist[] = {
40 {"SHIFT", ShiftMask},
41 {"LOCK", LockMask},
42 {"CONTROL", ControlMask},
43 {"MOD1", Mod1Mask},
44 {"MOD2", Mod2Mask},
45 {"MOD3", Mod3Mask},
46 {"MOD4", Mod4Mask},
47 {"MOD5", Mod5Mask},
48 {0, 0}
49 };
50
51 };
52
53 namespace FbTk {
54
55 std::auto_ptr<KeyUtil> KeyUtil::s_keyutil;
56
instance()57 KeyUtil &KeyUtil::instance() {
58 if (s_keyutil.get() == 0)
59 s_keyutil.reset(new KeyUtil());
60 return *s_keyutil.get();
61 }
62
63
KeyUtil()64 KeyUtil::KeyUtil()
65 : m_modmap(0)
66 {
67 init();
68 }
69
init()70 void KeyUtil::init() {
71 loadModmap();
72 }
73
~KeyUtil()74 KeyUtil::~KeyUtil() {
75 if (m_modmap)
76 XFreeModifiermap(m_modmap);
77 }
78
loadModmap()79 void KeyUtil::loadModmap() {
80 if (m_modmap)
81 XFreeModifiermap(m_modmap);
82
83 m_modmap = XGetModifierMapping(App::instance()->display());
84
85 // find modifiers and set them
86 for (int i=0, realkey=0; i<8; ++i) {
87 for (int key=0; key<m_modmap->max_keypermod; ++key, ++realkey) {
88
89 if (m_modmap->modifiermap[realkey] == 0)
90 continue;
91
92 KeySym ks = XKeycodeToKeysym(App::instance()->display(),
93 m_modmap->modifiermap[realkey], 0);
94
95 switch (ks) {
96 case XK_Caps_Lock:
97 m_capslock = modlist[i].mask;
98 break;
99 case XK_Scroll_Lock:
100 m_scrolllock = modlist[i].mask;
101 break;
102 case XK_Num_Lock:
103 m_numlock = modlist[i].mask;
104 break;
105 }
106 }
107 }
108 }
109
110
111 /**
112 Grabs a key with the modifier
113 and with numlock,capslock and scrollock
114 */
grabKey(unsigned int key,unsigned int mod)115 void KeyUtil::grabKey(unsigned int key, unsigned int mod) {
116 Display *display = App::instance()->display();
117 const unsigned int capsmod = instance().capslock();
118 const unsigned int nummod = instance().numlock();
119 const unsigned int scrollmod = instance().scrolllock();
120
121 for (int screen=0; screen<ScreenCount(display); screen++) {
122
123 Window root = RootWindow(display, screen);
124
125 XGrabKey(display, key, mod,
126 root, True,
127 GrabModeAsync, GrabModeAsync);
128
129 // Grab with numlock, capslock and scrlock
130
131 //numlock
132 XGrabKey(display, key, mod|nummod,
133 root, True,
134 GrabModeAsync, GrabModeAsync);
135 //scrolllock
136 XGrabKey(display, key, mod|scrollmod,
137 root, True,
138 GrabModeAsync, GrabModeAsync);
139 //capslock
140 XGrabKey(display, key, mod|capsmod,
141 root, True,
142 GrabModeAsync, GrabModeAsync);
143
144 //capslock+numlock
145 XGrabKey(display, key, mod|capsmod|nummod,
146 root, True,
147 GrabModeAsync, GrabModeAsync);
148
149 //capslock+scrolllock
150 XGrabKey(display, key, mod|capsmod|scrollmod,
151 root, True,
152 GrabModeAsync, GrabModeAsync);
153
154 //capslock+numlock+scrolllock
155 XGrabKey(display, key, mod|capsmod|scrollmod|nummod,
156 root, True,
157 GrabModeAsync, GrabModeAsync);
158
159 //numlock+scrollLock
160 XGrabKey(display, key, mod|nummod|scrollmod,
161 root, True,
162 GrabModeAsync, GrabModeAsync);
163
164 }
165
166 }
167
168 /**
169 @return keycode of keystr on success else 0
170 */
171
getKey(const char * keystr)172 unsigned int KeyUtil::getKey(const char *keystr) {
173 if (!keystr)
174 return 0;
175 return XKeysymToKeycode(App::instance()->display(),
176 XStringToKeysym(keystr));
177 }
178
179
180 /**
181 @return the modifier for the modstr else zero on failure.
182 */
getModifier(const char * modstr)183 unsigned int KeyUtil::getModifier(const char *modstr) {
184 if (!modstr)
185 return 0;
186
187 // find mod mask string
188 for (unsigned int i=0; modlist[i].str !=0; i++) {
189 if (modlist[i] == modstr)
190 return modlist[i].mask;
191 }
192
193 return 0;
194 }
195
196 /// Ungrabs the keys
ungrabKeys()197 void KeyUtil::ungrabKeys() {
198 Display * display = App::instance()->display();
199 for (int screen=0; screen<ScreenCount(display); screen++) {
200 XUngrabKey(display, AnyKey, AnyModifier,
201 RootWindow(display, screen));
202 }
203 }
204
keycodeToModmask(unsigned int keycode)205 unsigned int KeyUtil::keycodeToModmask(unsigned int keycode) {
206 XModifierKeymap *modmap = instance().m_modmap;
207
208 if (!modmap)
209 return 0;
210
211 // search through modmap for this keycode
212 for (int mod=0; mod < 8; mod++) {
213 for (int key=0; key < modmap->max_keypermod; ++key) {
214 // modifiermap is an array with 8 sets of keycodes
215 // each max_keypermod long, but in a linear array.
216 if (modmap->modifiermap[modmap->max_keypermod*mod + key] == keycode) {
217 return modlist[mod].mask;
218 }
219 }
220 }
221 // no luck
222 return 0;
223 }
224
225
226
227 } // end namespace FbTk
228