"Fossies" - the Fresh Open Source Software Archive 
Member "bbkeys-0.9.1/src/keytree.cc" (6 Dec 2007, 7936 Bytes) of package /linux/privat/old/bbkeys-0.9.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "keytree.cc" see the
Fossies "Dox" file reference documentation.
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // keytree.cc for Epistrophy - a key handler for NETWM/EWMH window managers.
3 // Copyright (c) 2002 - 2002 Ben Jansens <ben at orodu.net>
4 //
5 // Modified for use and inclusion in bbkeys by Jason 'vanRijn' Kasper
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a
8 // copy of this software and associated documentation files (the "Software"),
9 // to deal in the Software without restriction, including without limitation
10 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 // and/or sell copies of the Software, and to permit persons to whom the
12 // Software is furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 // DEALINGS IN THE SOFTWARE.
24
25 #include "keytree.hh"
26
27 #include <string>
28 #include <sstream>
29 #include <iostream>
30
31 keytree::keytree(Display *display): _display(display)
32 {
33 _head = new keynode;
34 _head->parent = NULL;
35 _head->action = NULL; // head's action is always NULL
36 _current = _head;
37 // for complete initialization, initialize() has to be called as well. We
38 // call initialize() when we are certain that the config object (which the
39 // timer uses) has been fully initialized. (see parser::parse())
40 }
41
42 keytree::~keytree()
43 {
44 clearTree(_head);
45 }
46
47 void keytree::unloadBindings()
48 {
49 ChildList::iterator it, end = _head->children.end();
50 for (it = _head->children.begin(); it != end; ++it)
51 clearTree(*it);
52
53 _head->children.clear();
54 reset();
55 }
56
57 void keytree::clearTree(keynode *node)
58 {
59 if (!node)
60 return;
61
62 ChildList::iterator it, end = node->children.end();
63 for (it = node->children.begin(); it != end; ++it)
64 clearTree(*it);
65
66 node->children.clear();
67
68 if (node->action)
69 delete node->action;
70 delete node;
71 node = NULL;
72 }
73
74 void keytree::grabDefaults(ScreenHandler *scr)
75 {
76 grabChildren(_head, scr);
77 }
78
79 void keytree::ungrabDefaults(ScreenHandler *scr)
80 {
81 Action *act;
82
83 ChildList::const_iterator it, end = _head->children.end();
84 for (it = _head->children.begin(); it != end; ++it) {
85 act = (*it)->action;
86 if (act && act->type() != Action::toggleGrabs)
87 scr->ungrabKey(act->keycode(), act->modifierMask());
88 }
89 }
90
91 void keytree::grabChildren(keynode *node, ScreenHandler *scr)
92 {
93 Action *act;
94
95 ChildList::const_iterator it, end = node->children.end();
96 for (it = node->children.begin(); it != end; ++it) {
97 act = (*it)->action;
98 if (act) {
99 bool ret = scr->grabKey(act->keycode(), act->modifierMask());
100 if (!ret) {
101 string key;
102 KeySym _sym = XKeycodeToKeysym(_display, act->keycode(), 0);
103
104 if (_sym == NoSymbol) key="key not found";
105 else key = XKeysymToString(_sym);
106
107 cerr << BBTOOL << ": keytree : grabChildren : "
108 << "could not activate keybinding for "
109 << "key: [" << key
110 << "], mask: [" << act->modifierMask()
111 << "], action: [" << act->getActionName() << "]\n";
112 }
113 }
114 }
115 }
116
117 void keytree::ungrabChildren(keynode *node, ScreenHandler *scr)
118 {
119 ChildList::const_iterator head_it, head_end = _head->children.end();
120 ChildList::const_iterator it, end = node->children.end();
121 bool ungrab = true;
122
123 // when ungrabbing children, make sure that we don't ungrab any topmost keys
124 // (children of the head node) This would render those topmost keys useless.
125 // Topmost keys are _never_ ungrabbed, since they are only grabbed at startup
126
127 for (it = node->children.begin(); it != end; ++it) {
128 if ( (*it)->action ) {
129 for (head_it = _head->children.begin(); head_it != head_end; ++head_it) {
130 if ( (*it)->action->modifierMask() == (*head_it)->action->modifierMask() &&
131 (*it)->action->keycode() == (*head_it)->action->keycode())
132 {
133 ungrab = false;
134 break;
135 }
136 }
137
138 if (ungrab)
139 scr->ungrabKey( (*it)->action->keycode(), (*it)->action->modifierMask());
140
141 ungrab = true;
142 }
143 }
144 }
145
146 Action * keytree::getAction(const XKeyEvent * const e, unsigned int & state,
147 ScreenHandler *scr)
148 {
149 Action *act;
150
151 // we're done with the children. ungrab them
152 if (_current != _head)
153 ungrabChildren(_current, scr);
154
155 // With XKB e->xkey.state can hold the group index in high bits, in
156 // addition to the standard modifier bits. This does not happen on the
157 // first grabbed event, but happens when doing stacked cycling (when
158 // XGrabKeyboard is active). In order to recognize subsequent keypresses,
159 // we must clear all unneeded bits in the state field.
160
161 state &= (ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
162
163 ChildList::const_iterator it, end = _current->children.end();
164 for (it = _current->children.begin(); it != end; ++it) {
165 act = (*it)->action;
166
167 if (e->keycode == act->keycode() && state == act->modifierMask()) {
168
169 if (act->type() == Action::cancelChain ) {
170 // user is cancelling the chain explicitly
171 _current = _head;
172 return act;
173 }
174 else if ( isLeaf(*it) ) {
175 // node is a leaf, so an action will be executed
176 _current = _head;
177 return act;
178 }
179 else {
180 // node is not a leaf, so we advance down the tree, and grab the
181 // children of the new current node. no action is executed
182 _current = *it;
183 grabChildren(_current, scr);
184 return act;
185 }
186 }
187 }
188
189 // action not found. back to the head
190 _current = _head;
191 return (Action *)NULL;
192 }
193
194 void keytree::addAction(Action::ActionType action, unsigned int mask,
195 string key, string arg)
196 {
197 if (action == Action::toggleGrabs && _current != _head) {
198 // the toggleGrabs key can only be set up as a root key, since if
199 // it was a chain key, we'd have to not ungrab the whole chain up
200 // to that key. which kinda defeats the purpose of this function.
201 return;
202 }
203
204 KeySym sym = XStringToKeysym(key.c_str());
205 KeyCode keyCode = XKeysymToKeycode(_display, sym);
206
207 if (keyCode == 0) {
208 cerr << BBTOOL << ": " << "keytree::addAction: keyCode for key: [" << key
209 << "] not found. can't add it. skipping.\n";
210 return;
211 }
212
213 keynode *tmp = new keynode;
214
215 tmp->action = new Action(action, _display, keyCode, mask, arg);
216 tmp->parent = _current;
217 _current->children.push_back(tmp);
218 }
219
220 void keytree::advanceOnNewNode()
221 {
222 keynode *tmp = new keynode;
223 tmp->action = NULL;
224 tmp->parent = _current;
225 _current->children.push_back(tmp);
226 _current = tmp;
227 }
228
229 void keytree::retract()
230 {
231 if (_current != _head)
232 _current = _current->parent;
233 }
234
235 void keytree::setCurrentNodeProps(Action::ActionType action, unsigned int mask,
236 string key, string arg)
237 {
238 if (_current->action)
239 delete _current->action;
240
241 KeySym sym = XStringToKeysym(key.c_str());
242 _current->action = new Action(action, _display,
243 XKeysymToKeycode(_display, sym),
244 mask, arg);
245 }
246
247 void keytree::showTree(keynode *node) {
248 if (!node)
249 return;
250
251 ChildList::iterator it, end = node->children.end();
252 for (it = node->children.begin(); it != end; ++it)
253 showTree(*it);
254
255 if (node->action) {
256 cout << BBTOOL << ": " << "showTree: [" << node->action->toString() << "]" << endl;
257 }
258
259 }
260