aboutsummaryrefslogtreecommitdiff
path: root/src/Keys.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Keys.cc')
-rw-r--r--src/Keys.cc95
1 files changed, 72 insertions, 23 deletions
diff --git a/src/Keys.cc b/src/Keys.cc
index e7b7acd..dbcff67 100644
--- a/src/Keys.cc
+++ b/src/Keys.cc
@@ -114,6 +114,7 @@ Keys::Keys():
114 114
115Keys::~Keys() { 115Keys::~Keys() {
116 ungrabKeys(); 116 ungrabKeys();
117 ungrabButtons();
117 deleteTree(); 118 deleteTree();
118} 119}
119 120
@@ -140,6 +141,23 @@ void Keys::ungrabKeys() {
140 FbTk::KeyUtil::ungrabKeys(*it); 141 FbTk::KeyUtil::ungrabKeys(*it);
141} 142}
142 143
144void Keys::grabButton(unsigned int button, unsigned int mod) {
145 std::list<Window>::iterator it = m_window_list.begin();
146 std::list<Window>::iterator it_end = m_window_list.end();
147
148 for (; it != it_end; ++it)
149 FbTk::KeyUtil::grabButton(button, mod, *it,
150 ButtonPressMask|ButtonReleaseMask);
151}
152
153void Keys::ungrabButtons() {
154 std::list<Window>::iterator it = m_window_list.begin();
155 std::list<Window>::iterator it_end = m_window_list.end();
156
157 for (; it != it_end; ++it)
158 FbTk::KeyUtil::ungrabButtons(*it);
159}
160
143/** 161/**
144 Load and grab keys 162 Load and grab keys
145 TODO: error checking 163 TODO: error checking
@@ -152,7 +170,7 @@ bool Keys::load(const char *filename) {
152 //free memory of previous grabs 170 //free memory of previous grabs
153 deleteTree(); 171 deleteTree();
154 172
155 m_map["default:"] = new t_key(0,0); 173 m_map["default:"] = new t_key(0,0,0,0);
156 174
157 FbTk::App::instance()->sync(false); 175 FbTk::App::instance()->sync(false);
158 176
@@ -211,6 +229,7 @@ bool Keys::addBinding(const string &linebuffer) {
211 return true; // still a valid line. 229 return true; // still a valid line.
212 230
213 unsigned int key = 0, mod = 0; 231 unsigned int key = 0, mod = 0;
232 int type = 0, context = 0;
214 size_t argc = 0; 233 size_t argc = 0;
215 t_key *current_key=m_map["default:"]; 234 t_key *current_key=m_map["default:"];
216 t_key *first_new_keylist = current_key, *first_new_key=0; 235 t_key *first_new_keylist = current_key, *first_new_key=0;
@@ -219,7 +238,7 @@ bool Keys::addBinding(const string &linebuffer) {
219 argc++; 238 argc++;
220 keyspace_t::iterator it = m_map.find(val[0]); 239 keyspace_t::iterator it = m_map.find(val[0]);
221 if (it == m_map.end()) 240 if (it == m_map.end())
222 m_map[val[0]] = new t_key(0,0); 241 m_map[val[0]] = new t_key(0,0,0,0);
223 current_key = m_map[val[0]]; 242 current_key = m_map[val[0]];
224 } 243 }
225 // for each argument 244 // for each argument
@@ -230,41 +249,53 @@ bool Keys::addBinding(const string &linebuffer) {
230 int tmpmod = FbTk::KeyUtil::getModifier(val[argc].c_str()); 249 int tmpmod = FbTk::KeyUtil::getModifier(val[argc].c_str());
231 if(tmpmod) 250 if(tmpmod)
232 mod |= tmpmod; //If it's a modifier 251 mod |= tmpmod; //If it's a modifier
252 else if (strcasecmp("ondesktop", val[argc].c_str()) == 0)
253 context |= ON_DESKTOP;
233 else if (strcasecmp("NONE",val[argc].c_str())) { 254 else if (strcasecmp("NONE",val[argc].c_str())) {
255 // check if it's a mouse button
256 if (!strcasecmp(val[argc].substr(0,5).c_str(), "mouse") &&
257 val[argc].length() > 5) {
258 type = ButtonPress;
259 key = atoi(val[argc].substr(5,val[argc].length()-5).c_str());
234 // keycode covers the following three two-byte cases: 260 // keycode covers the following three two-byte cases:
235 // 0x - hex 261 // 0x - hex
236 // +[1-9] - number between +1 and +9 262 // +[1-9] - number between +1 and +9
237 // numbers 10 and above 263 // numbers 10 and above
238 // 264 //
239 if (val[argc].size() > 1 && (isdigit(val[argc][0]) && 265 } else if (val[argc].size() > 1 && (isdigit(val[argc][0]) &&
240 (isdigit(val[argc][1]) || val[argc][1] == 'x') || 266 (isdigit(val[argc][1]) || val[argc][1] == 'x') ||
241 val[argc][0] == '+' && isdigit(val[argc][1])) ) { 267 val[argc][0] == '+' && isdigit(val[argc][1])) ) {
242 268
243 key = strtoul(val[argc].c_str(), NULL, 0); 269 key = strtoul(val[argc].c_str(), NULL, 0);
270 type = KeyPress;
244 271
245 if (errno == EINVAL || errno == ERANGE) 272 if (errno == EINVAL || errno == ERANGE)
246 key = 0; 273 key = 0;
247 274
248 } else // convert from string symbol 275 } else { // convert from string symbol
249 key = FbTk::KeyUtil::getKey(val[argc].c_str()); 276 key = FbTk::KeyUtil::getKey(val[argc].c_str());
277 type = KeyPress;
278 }
250 279
251 if (key == 0) 280 if (key == 0)
252 return false; 281 return false;
253 if (!first_new_key) { 282 if (!first_new_key) {
254 first_new_keylist = current_key; 283 first_new_keylist = current_key;
255 current_key = current_key->find(key, mod); 284 current_key = current_key->find(type, mod, key, context);
256 if (!current_key) { 285 if (!current_key) {
257 first_new_key = new t_key(key, mod); 286 first_new_key = new t_key(type, mod, key, context);
258 current_key = first_new_key; 287 current_key = first_new_key;
259 } else if (*current_key->m_command) // already being used 288 } else if (*current_key->m_command) // already being used
260 return false; 289 return false;
261 } else { 290 } else {
262 t_key *temp_key = new t_key(key, mod); 291 t_key *temp_key = new t_key(type, mod, key, context);
263 current_key->keylist.push_back(temp_key); 292 current_key->keylist.push_back(temp_key);
264 current_key = temp_key; 293 current_key = temp_key;
265 } 294 }
266 mod = 0; 295 mod = 0;
267 key = 0; 296 key = 0;
297 type = 0;
298 context = 0;
268 } 299 }
269 300
270 } else { // parse command line 301 } else { // parse command line
@@ -291,36 +322,43 @@ bool Keys::addBinding(const string &linebuffer) {
291} 322}
292 323
293// return true if bound to a command, else false 324// return true if bound to a command, else false
294bool Keys::doAction(XKeyEvent &ke) { 325bool Keys::doAction(int type, unsigned int mods, unsigned int key) {
295
296 ke.state = FbTk::KeyUtil::instance().cleanMods(ke.state);
297 326
298 static t_key* next_key = m_keylist; 327 static t_key* next_key = m_keylist;
299 if (!next_key) 328 if (!next_key)
300 next_key = m_keylist; 329 next_key = m_keylist;
301 t_key *temp_key = next_key->find(ke);
302 330
331 mods = FbTk::KeyUtil::instance().cleanMods(mods);
332 // at the moment, any key/button that gets here is on root window
333 // context will need to be added as an argument to doAction, though
334 t_key *temp_key = next_key->find(type, mods, key, ON_DESKTOP|GLOBAL);
303 335
304 // need to save this for emacs-style keybindings 336 // need to save this for emacs-style keybindings
305 static t_key *saved_keymode = 0; 337 static t_key *saved_keymode = 0;
306 338
339 // grab "None Escape" to exit keychain in the middle
340 unsigned int esc = FbTk::KeyUtil::getKey("Escape");
341
307 if (temp_key && temp_key->keylist.size()) { // emacs-style 342 if (temp_key && temp_key->keylist.size()) { // emacs-style
308 saved_keymode = m_keylist; 343 if (!saved_keymode)
344 saved_keymode = m_keylist;
309 next_key = temp_key; 345 next_key = temp_key;
310 setKeyMode(next_key); 346 setKeyMode(next_key);
311 // grab "None Escape" to exit keychain in the middle
312 unsigned int esc = FbTk::KeyUtil::getKey("Escape");
313 grabKey(esc,0); 347 grabKey(esc,0);
314 return true; 348 return true;
315 } 349 }
316 if (!temp_key || *temp_key->m_command == 0) { 350 if (!temp_key || *temp_key->m_command == 0) {
317 next_key = 0; 351 if (type == KeyPress && key == esc && mods == 0) {
318 if (saved_keymode) { 352 // if we're in the middle of an emacs-style keychain, exit it
319 setKeyMode(saved_keymode); 353 next_key = 0;
320 saved_keymode = 0; 354 if (saved_keymode) {
355 setKeyMode(saved_keymode);
356 saved_keymode = 0;
357 }
321 } 358 }
322 return false; 359 return false;
323 } 360 }
361
324 temp_key->m_command->execute(); 362 temp_key->m_command->execute();
325 if (saved_keymode) { 363 if (saved_keymode) {
326 if (next_key == m_keylist) // don't reset keymode if command changed it 364 if (next_key == m_keylist) // don't reset keymode if command changed it
@@ -349,22 +387,33 @@ void Keys::keyMode(string keyMode) {
349 387
350void Keys::setKeyMode(t_key *keyMode) { 388void Keys::setKeyMode(t_key *keyMode) {
351 ungrabKeys(); 389 ungrabKeys();
390 ungrabButtons();
352 keylist_t::iterator it = keyMode->keylist.begin(); 391 keylist_t::iterator it = keyMode->keylist.begin();
353 keylist_t::iterator it_end = keyMode->keylist.end(); 392 keylist_t::iterator it_end = keyMode->keylist.end();
354 for (; it != it_end; ++it) 393 for (; it != it_end; ++it) {
355 grabKey((*it)->key,(*it)->mod); 394 if ((*it)->type == KeyPress)
395 grabKey((*it)->key,(*it)->mod);
396 else if ((*it)->context == GLOBAL)
397 grabButton((*it)->key,(*it)->mod);
398 // we must use root window's event mask to get ON_DESKTOP events
399 }
356 m_keylist = keyMode; 400 m_keylist = keyMode;
357} 401}
358 402
359Keys::t_key::t_key(unsigned int key_, unsigned int mod_, FbTk::RefCount<FbTk::Command> command) { 403Keys::t_key::t_key(int type_, unsigned int mod_, unsigned int key_,
404 int context_, FbTk::RefCount<FbTk::Command> command) {
360 key = key_; 405 key = key_;
361 mod = mod_; 406 mod = mod_;
407 type = type_;
408 context = context_ ? context_ : GLOBAL;
362 m_command = command; 409 m_command = command;
363} 410}
364 411
365Keys::t_key::t_key(t_key *k) { 412Keys::t_key::t_key(t_key *k) {
366 key = k->key; 413 key = k->key;
367 mod = k->mod; 414 mod = k->mod;
415 type = k->type;
416 context = k->context;
368 m_command = k->m_command; 417 m_command = k->m_command;
369} 418}
370 419