summaryrefslogtreecommitdiff
path: root/src/Keys.cc
diff options
context:
space:
mode:
authorsimonb <simonb>2006-04-12 15:51:37 (GMT)
committersimonb <simonb>2006-04-12 15:51:37 (GMT)
commit33079d2593a7a598446cc837fc39eb2a914ebb1f (patch)
tree40c8793a180835ee46dfdae0e336340df9788c69 /src/Keys.cc
parent48579408d19fe0042a32f9634e6518b2eca3671c (diff)
downloadfluxbox_lack-33079d2593a7a598446cc837fc39eb2a914ebb1f.zip
fluxbox_lack-33079d2593a7a598446cc837fc39eb2a914ebb1f.tar.bz2
add "key modes" - thanks to Mark Tiefenbruck, mark at tiefenbruck dot org
Diffstat (limited to 'src/Keys.cc')
-rw-r--r--src/Keys.cc193
1 files changed, 109 insertions, 84 deletions
diff --git a/src/Keys.cc b/src/Keys.cc
index 5e30726..c4099f6 100644
--- a/src/Keys.cc
+++ b/src/Keys.cc
@@ -86,6 +86,7 @@
86#include <iostream> 86#include <iostream>
87#include <fstream> 87#include <fstream>
88#include <vector> 88#include <vector>
89#include <map>
89#ifdef HAVE_CASSERT 90#ifdef HAVE_CASSERT
90 #include <cassert> 91 #include <cassert>
91#else 92#else
@@ -95,12 +96,10 @@
95 96
96using namespace std; 97using namespace std;
97 98
98Keys::Keys(const char *filename): 99Keys::Keys():
99 m_display(FbTk::App::instance()->display()) 100 m_display(FbTk::App::instance()->display())
100{ 101{
101 102
102 if (filename != 0)
103 load(filename);
104} 103}
105 104
106Keys::~Keys() { 105Keys::~Keys() {
@@ -111,11 +110,15 @@ Keys::~Keys() {
111 110
112/// Destroys the keytree 111/// Destroys the keytree
113void Keys::deleteTree() { 112void Keys::deleteTree() {
114 keylist_t::iterator it = m_keylist.begin(); 113 for (keyspace_t::iterator map_it = m_map.begin(); map_it != m_map.end(); ++map_it) {
115 const keylist_t::iterator end = m_keylist.end(); 114 keylist_t::iterator it = map_it->second->begin();
116 for ( ; it != end; it++) 115 const keylist_t::iterator it_end = map_it->second->end();
117 delete *it; 116 for ( ; it != it_end; it++)
118 m_keylist.clear(); 117 delete *it;
118 map_it->second->clear();
119 delete map_it->second;
120 m_map.erase(map_it->first);
121 }
119} 122}
120 123
121/** 124/**
@@ -133,6 +136,8 @@ bool Keys::load(const char *filename) {
133 //free memory of previous grabs 136 //free memory of previous grabs
134 deleteTree(); 137 deleteTree();
135 138
139 m_map["default:"] = new keylist_t;
140
136 FbTk::App::instance()->sync(false); 141 FbTk::App::instance()->sync(false);
137 142
138 //open the file 143 //open the file
@@ -154,6 +159,7 @@ bool Keys::load(const char *filename) {
154 159
155 m_current_line = 0; 160 m_current_line = 0;
156 m_filename = filename; 161 m_filename = filename;
162 m_keylist = m_map["default:"];
157 return true; 163 return true;
158} 164}
159 165
@@ -184,55 +190,60 @@ bool Keys::addBinding(const std::string &linebuffer) {
184 return true; // still a valid line. 190 return true; // still a valid line.
185 191
186 unsigned int key = 0, mod = 0; 192 unsigned int key = 0, mod = 0;
187 char keyarg = 0;
188 t_key *current_key=0, *last_key=0; 193 t_key *current_key=0, *last_key=0;
189 194 size_t argc = 0;
195 std::string keyMode = "default:";
196
197 if (val[0][val[0].length()-1] == ':') {
198 argc++;
199 keyspace_t::iterator it = m_map.find(val[0]);
200 if (it == m_map.end())
201 m_map[val[0]] = new keylist_t;
202 keyMode = val[0];
203 }
190 _FB_USES_NLS; 204 _FB_USES_NLS;
191 // for each argument 205 // for each argument
192 for (size_t argc = 0; argc < val.size(); argc++) { 206 for (; argc < val.size(); argc++) {
193 207
194 if (val[argc][0] != ':') { // parse key(s) 208 if (val[argc][0] != ':') { // parse key(s)
195 keyarg++; 209
196 if (keyarg==1) //first arg is modifier 210 int tmpmod = FbTk::KeyUtil::getModifier(val[argc].c_str());
197 mod = FbTk::KeyUtil::getModifier(val[argc].c_str()); 211 if(tmpmod)
198 else if (keyarg > 1) { 212 mod |= tmpmod; //If it's a modifier
199 213 else if (strcasecmp("NONE",val[argc].c_str()) == 0)
200 int tmpmod = FbTk::KeyUtil::getModifier(val[argc].c_str()); 214 mod = 0;
201 if(tmpmod) 215 else {
202 mod |= tmpmod; //If it's a modifier 216 // keycode covers the following three two-byte cases:
203 else { 217 // 0x - hex
204 // keycode covers the following three two-byte cases: 218 // +[1-9] - number between +1 and +9
205 // 0x - hex 219 // numbers 10 and above
206 // +[1-9] - number between +1 and +9 220 //
207 // numbers 10 and above 221 if (val[argc].size() > 1 && (isdigit(val[argc][0]) &&
208 // 222 (isdigit(val[argc][1]) || val[argc][1] == 'x') ||
209 if (val[argc].size() > 1 && (isdigit(val[argc][0]) && 223 val[argc][0] == '+' && isdigit(val[argc][1])) ) {
210 (isdigit(val[argc][1]) || val[argc][1] == 'x') ||
211 val[argc][0] == '+' && isdigit(val[argc][1])) ) {
212 224
213 key = strtoul(val[argc].c_str(), NULL, 0); 225 key = strtoul(val[argc].c_str(), NULL, 0);
214 226
215 if (errno == EINVAL || errno == ERANGE) 227 if (errno == EINVAL || errno == ERANGE)
216 key = 0; 228 key = 0;
217 229
218 } else // convert from string symbol 230 } else // convert from string symbol
219 key = FbTk::KeyUtil::getKey(val[argc].c_str()); 231 key = FbTk::KeyUtil::getKey(val[argc].c_str());
220 232
221 if (key == 0) { 233 if (key == 0) {
222 cerr<<_FBTEXT(Keys, InvalidKeyMod, 234 cerr<<_FBTEXT(Keys, InvalidKeyMod,
223 "Keys: Invalid key/modifier on line", 235 "Keys: Invalid key/modifier on line",
224 "A bad key/modifier string was found on line (number following)")<<" "<< 236 "A bad key/modifier string was found on line (number following)")<<" "<<
225 m_current_line<<"): "<<linebuffer<<endl; 237 m_current_line<<"): "<<linebuffer<<endl;
226 return false; 238 return false;
227 } 239 }
228 if (!current_key) { 240 if (!current_key) {
229 current_key = new t_key(key, mod); 241 current_key = new t_key(key, mod);
230 last_key = current_key; 242 last_key = current_key;
231 } else { 243 } else {
232 t_key *temp_key = new t_key(key, mod); 244 t_key *temp_key = new t_key(key, mod);
233 last_key->keylist.push_back(temp_key); 245 last_key->keylist.push_back(temp_key);
234 last_key = temp_key; 246 last_key = temp_key;
235 }
236 } 247 }
237 } 248 }
238 249
@@ -258,6 +269,8 @@ bool Keys::addBinding(const std::string &linebuffer) {
258 cerr<<_FBTEXT(Keys, BadLine, "Keys: Error on line", "Error on line (number following)")<<": "<<m_current_line<<endl; 269 cerr<<_FBTEXT(Keys, BadLine, "Keys: Error on line", "Error on line (number following)")<<": "<<m_current_line<<endl;
259 cerr<<"> "<<linebuffer<<endl; 270 cerr<<"> "<<linebuffer<<endl;
260 } else { 271 } else {
272 // need to change keymode here so it doesn't get changed by CommandParser
273 m_keylist = m_map[keyMode];
261 // Add the keychain to list 274 // Add the keychain to list
262 if (!mergeTree(current_key)) { 275 if (!mergeTree(current_key)) {
263 cerr<<_FBTEXT(Keys, BadMerge, "Keys: Failed to merge keytree!", "relatively technical error message. Key bindings are stored in a tree structure")<<endl; 276 cerr<<_FBTEXT(Keys, BadMerge, "Keys: Failed to merge keytree!", "relatively technical error message. Key bindings are stored in a tree structure")<<endl;
@@ -279,46 +292,50 @@ bool Keys::addBinding(const std::string &linebuffer) {
279 292
280 293
281/** 294/**
282 @return the KeyAction of the XKeyEvent 295 @return the KeyAction of the XKeyEvent; return false if not bound
283*/ 296*/
284void Keys::doAction(XKeyEvent &ke) { 297bool Keys::doAction(XKeyEvent &ke) {
285 298
286 ke.state = FbTk::KeyUtil::instance().cleanMods(ke.state); 299 ke.state = FbTk::KeyUtil::instance().cleanMods(ke.state);
287 300
288 static struct t_key* next_key = 0; 301 static struct t_key* next_key = 0;
289 302
290 if (!next_key) { 303 if (!next_key) {
291 304 bool retval = false;
292 for (size_t i = 0; i < m_keylist.size(); i++) { 305 // need a local keylist, in case m_command->execute() changes it
293 if (*m_keylist[i] == ke) { 306 keylist_t *keylist = m_keylist;
294 if (m_keylist[i]->keylist.size()) { 307 for (size_t i = 0; i < keylist->size(); i++) {
295 next_key = m_keylist[i]; 308 if (*(*keylist)[i] == ke) {
296 break; //end for-loop 309 if ((*keylist)[i]->keylist.size()) {
297 } else { 310 next_key = (*keylist)[i];
298 if (*m_keylist[i]->m_command != 0) 311 return true; //still counts as being grabbed
299 m_keylist[i]->m_command->execute(); 312 }
313 if (*(*keylist)[i]->m_command != 0) {
314 (*keylist)[i]->m_command->execute();
315 retval = true;
300 } 316 }
301 } 317 }
302 } 318 }
303 319 return retval;
304 } else { //check the nextkey 320 }
305 t_key *temp_key = next_key->find(ke); 321 t_key *temp_key = next_key->find(ke);
306 if (temp_key) { 322 if (temp_key) {
307 if (temp_key->keylist.size()) { 323 if (temp_key->keylist.size()) {
308 next_key = temp_key; 324 next_key = temp_key;
309 } else { 325 return true;
310 next_key = 0;
311 if (*temp_key->m_command != 0)
312 temp_key->m_command->execute();
313 }
314 } else {
315 temp_key = next_key;
316 next_key = 0;
317 if (*temp_key->m_command != 0)
318 temp_key->m_command->execute();
319
320 } 326 }
327 next_key = 0;
328 if (*temp_key->m_command == 0)
329 return false;
330 temp_key->m_command->execute();
331 return true;
321 } 332 }
333 temp_key = next_key;
334 next_key = 0;
335 if (*temp_key->m_command == 0)
336 return false;
337 temp_key->m_command->execute();
338 return true;
322} 339}
323 340
324/** 341/**
@@ -337,22 +354,22 @@ bool Keys::reconfigure(const char *filename) {
337bool Keys::mergeTree(t_key *newtree, t_key *basetree) { 354bool Keys::mergeTree(t_key *newtree, t_key *basetree) {
338 size_t baselist_i = 0; 355 size_t baselist_i = 0;
339 if (basetree==0) { 356 if (basetree==0) {
340 for (; baselist_i<m_keylist.size(); baselist_i++) { 357 for (; baselist_i<m_keylist->size(); baselist_i++) {
341 if (m_keylist[baselist_i]->mod == newtree->mod && 358 if ((*m_keylist)[baselist_i]->mod == newtree->mod &&
342 m_keylist[baselist_i]->key == newtree->key) { 359 (*m_keylist)[baselist_i]->key == newtree->key) {
343 if (newtree->keylist.size() && *m_keylist[baselist_i]->m_command == 0) { 360 if (newtree->keylist.size() && *(*m_keylist)[baselist_i]->m_command == 0) {
344 //assumes the newtree only have one branch 361 //assumes the newtree only have one branch
345 return mergeTree(newtree->keylist[0], m_keylist[baselist_i]); 362 return mergeTree(newtree->keylist[0], (*m_keylist)[baselist_i]);
346 } else 363 } else
347 break; 364 break;
348 } 365 }
349 } 366 }
350 367
351 if (baselist_i == m_keylist.size()) { 368 if (baselist_i == m_keylist->size()) {
352 FbTk::KeyUtil::grabKey(newtree->key, newtree->mod); 369 FbTk::KeyUtil::grabKey(newtree->key, newtree->mod);
353 m_keylist.push_back(new t_key(newtree)); 370 m_keylist->push_back(new t_key(newtree));
354 if (newtree->keylist.size()) 371 if (newtree->keylist.size())
355 return mergeTree(newtree->keylist[0], m_keylist.back()); 372 return mergeTree(newtree->keylist[0], m_keylist->back());
356 return true; 373 return true;
357 } 374 }
358 375
@@ -380,6 +397,14 @@ bool Keys::mergeTree(t_key *newtree, t_key *basetree) {
380 return false; 397 return false;
381} 398}
382 399
400void Keys::keyMode(std::string keyMode = "default") {
401 keyspace_t::iterator it = m_map.find(keyMode + ":");
402 if (it == m_map.end())
403 m_keylist = m_map["default:"];
404 else
405 m_keylist = it->second;
406}
407
383Keys::t_key::t_key(unsigned int key_, unsigned int mod_, FbTk::RefCount<FbTk::Command> command) { 408Keys::t_key::t_key(unsigned int key_, unsigned int mod_, FbTk::RefCount<FbTk::Command> command) {
384 key = key_; 409 key = key_;
385 mod = mod_; 410 mod = mod_;