diff options
author | Mathias Gumz <akira at fluxbox dot org> | 2009-12-18 07:05:07 (GMT) |
---|---|---|
committer | Mathias Gumz <akira at fluxbox dot org> | 2009-12-18 07:05:07 (GMT) |
commit | 46261a8284730a16d664fa89423fc5728ed284b4 (patch) | |
tree | c81d7962fe924f5bfca44dc0254304cb537544b9 | |
parent | 79859c94482e4602eb22c35b988027ab199734a6 (diff) | |
download | fluxbox-46261a8284730a16d664fa89423fc5728ed284b4.zip fluxbox-46261a8284730a16d664fa89423fc5728ed284b4.tar.bz2 |
implemented 'MoveN' and 'ClickN' support in keys file.
the hardcoded 'OnTitlebar Mouse1 :Raise' (see Window.cc, FluxboxWindow::buttonPressEvent())
is disabled for now, should be added to fluxbox-update_configs
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | doc/asciidoc/fluxbox-keys.txt | 22 | ||||
-rw-r--r-- | doc/fluxbox-keys.5.in | 31 | ||||
-rw-r--r-- | src/CurrentWindowCmd.cc | 47 | ||||
-rw-r--r-- | src/FbTk/KeyUtil.cc | 56 | ||||
-rw-r--r-- | src/Keys.cc | 110 | ||||
-rw-r--r-- | src/Window.cc | 43 | ||||
-rw-r--r-- | src/Window.hh | 1 |
8 files changed, 216 insertions, 98 deletions
@@ -1,6 +1,10 @@ | |||
1 | (Format: Year/Month/Day) | 1 | (Format: Year/Month/Day) |
2 | Changes for 1.1.2 | 2 | Changes for 1.1.2 |
3 | 3 | ||
4 | *09/12/18: | ||
5 | * Implemented new 'MoveN' and 'ClickN' support for keys file (Mathias) | ||
6 | Keys.cc Window.cc/hh CurrentWindowCmd.cc FbTk/KeyUtil.cc | ||
7 | |||
4 | *09/12/15: | 8 | *09/12/15: |
5 | * Updated fluxbox-keys documentation, added 'Fullscreen' (thanx Paul Tagliamonte) | 9 | * Updated fluxbox-keys documentation, added 'Fullscreen' (thanx Paul Tagliamonte) |
6 | 10 | ||
diff --git a/doc/asciidoc/fluxbox-keys.txt b/doc/asciidoc/fluxbox-keys.txt index ed69a57..3f3431d 100644 --- a/doc/asciidoc/fluxbox-keys.txt +++ b/doc/asciidoc/fluxbox-keys.txt | |||
@@ -55,7 +55,7 @@ are most commonly used: | |||
55 | where *Mod1* is the Alt key on the PC keyboard and *Mod4* is usually a key | 55 | where *Mod1* is the Alt key on the PC keyboard and *Mod4* is usually a key |
56 | branded with a familiar company logo. | 56 | branded with a familiar company logo. |
57 | 57 | ||
58 | There are also some special modifiers that refer to mouse button presses::: | 58 | There are also some special modifiers that refer to mouse button events::: |
59 | *OnDesktop*;; | 59 | *OnDesktop*;; |
60 | The mouse cursor is over the desktop (root window), and not any | 60 | The mouse cursor is over the desktop (root window), and not any |
61 | window. | 61 | window. |
@@ -84,13 +84,21 @@ the key, and see the name in the output. If you have some "special" keys that | |||
84 | do not produce a key name in the output of *xev(1)*, you can just use the | 84 | do not produce a key name in the output of *xev(1)*, you can just use the |
85 | keycode (NOT the keysym!) in your keys file. | 85 | keycode (NOT the keysym!) in your keys file. |
86 | 86 | ||
87 | Commands can also be bound to mouse button presses, for which the proper "key" | 87 | Commands can also be bound to mouse events ('N' denotes the number of the |
88 | name is *Mouse*'n' where 'n' is the number of the mouse button. For example, | 88 | button, eg. '1' is the primary button, '4'/'5' are the wheel buttons): |
89 | *Mouse1* is the primary button, and *Mouse4* / *Mouse5* are the scroll wheel | 89 | |
90 | events, in normal configurations. *xev(1)* can also be used to tell the button | 90 | *MouseN*;; |
91 | number. | 91 | The mouse button 'N' is pressed down and holded. |
92 | *ClickN*;; | ||
93 | The mouse button 'N' is clicked (pressed and released with no | ||
94 | movement in between) | ||
95 | *MoveN*;; | ||
96 | The mouse button 'N' is currently holded, the binded action is triggered | ||
97 | as often as the mouse moves. | ||
98 | |||
99 | |||
100 | There are some special "keys" that let you bind events to non-keyboard events: | ||
92 | 101 | ||
93 | There are some special "keys" that let you bind events to non-keyboard events::: | ||
94 | *ChangeWorkspace*;; | 102 | *ChangeWorkspace*;; |
95 | Fires when the workspace changes. This can be used to change backgrounds or | 103 | Fires when the workspace changes. This can be used to change backgrounds or |
96 | do anything else you like when you switch to a new workspace. See the | 104 | do anything else you like when you switch to a new workspace. See the |
diff --git a/doc/fluxbox-keys.5.in b/doc/fluxbox-keys.5.in index 6e641f9..2b29891 100644 --- a/doc/fluxbox-keys.5.in +++ b/doc/fluxbox-keys.5.in | |||
@@ -2,12 +2,12 @@ | |||
2 | .\" Title: fluxbox-keys | 2 | .\" Title: fluxbox-keys |
3 | .\" Author: [see the "AUTHORS" section] | 3 | .\" Author: [see the "AUTHORS" section] |
4 | .\" Generator: DocBook XSL Stylesheets v1.75.1 <http://docbook.sf.net/> | 4 | .\" Generator: DocBook XSL Stylesheets v1.75.1 <http://docbook.sf.net/> |
5 | .\" Date: 12/14/2009 | 5 | .\" Date: 12/17/2009 |
6 | .\" Manual: Fluxbox Manual | 6 | .\" Manual: Fluxbox Manual |
7 | .\" Source: fluxbox-keys.txt | 7 | .\" Source: fluxbox-keys.txt |
8 | .\" Language: English | 8 | .\" Language: English |
9 | .\" | 9 | .\" |
10 | .TH "FLUXBOX\-KEYS" "5" "12/14/2009" "fluxbox\-keys\&.txt" "Fluxbox Manual" | 10 | .TH "FLUXBOX\-KEYS" "5" "12/17/2009" "fluxbox\-keys\&.txt" "Fluxbox Manual" |
11 | .\" ----------------------------------------------------------------- | 11 | .\" ----------------------------------------------------------------- |
12 | .\" * set default formatting | 12 | .\" * set default formatting |
13 | .\" ----------------------------------------------------------------- | 13 | .\" ----------------------------------------------------------------- |
@@ -53,7 +53,7 @@ You can get a list of possible modifiers by calling \(oqxmodmap \-pm\(cq\&. This | |||
53 | .sp | 53 | .sp |
54 | where \fBMod1\fR is the Alt key on the PC keyboard and \fBMod4\fR is usually a key branded with a familiar company logo\&. | 54 | where \fBMod1\fR is the Alt key on the PC keyboard and \fBMod4\fR is usually a key branded with a familiar company logo\&. |
55 | .PP | 55 | .PP |
56 | There are also some special modifiers that refer to mouse button presses | 56 | There are also some special modifiers that refer to mouse button events |
57 | .RS 4 | 57 | .RS 4 |
58 | .PP | 58 | .PP |
59 | \fBOnDesktop\fR | 59 | \fBOnDesktop\fR |
@@ -90,10 +90,30 @@ You may specify a key by its key name (for example, \fBa\fR or \fBspace\fR) or b | |||
90 | .sp | 90 | .sp |
91 | If you don\(cqt know the name of a key, you can run \fBxev(1)\fR in a terminal, push the key, and see the name in the output\&. If you have some "special" keys that do not produce a key name in the output of \fBxev(1)\fR, you can just use the keycode (NOT the keysym!) in your keys file\&. | 91 | If you don\(cqt know the name of a key, you can run \fBxev(1)\fR in a terminal, push the key, and see the name in the output\&. If you have some "special" keys that do not produce a key name in the output of \fBxev(1)\fR, you can just use the keycode (NOT the keysym!) in your keys file\&. |
92 | .sp | 92 | .sp |
93 | Commands can also be bound to mouse button presses, for which the proper "key" name is \fBMouse\fR\fIn\fR where \fIn\fR is the number of the mouse button\&. For example, \fBMouse1\fR is the primary button, and \fBMouse4\fR / \fBMouse5\fR are the scroll wheel events, in normal configurations\&. \fBxev(1)\fR can also be used to tell the button number\&. | 93 | Commands can also be bound to mouse events (\fIN\fR denotes the number of the button, eg\&. \fI1\fR is the primary button, \fI4\fR/\fI5\fR are the wheel buttons): |
94 | .PP | 94 | .PP |
95 | There are some special "keys" that let you bind events to non\-keyboard events | 95 | \fBMouseN\fR |
96 | .RS 4 | 96 | .RS 4 |
97 | The mouse button | ||
98 | \fIN\fR | ||
99 | is pressed down and holded\&. | ||
100 | .RE | ||
101 | .PP | ||
102 | \fBClickN\fR | ||
103 | .RS 4 | ||
104 | The mouse button | ||
105 | \fIN\fR | ||
106 | is clicked (pressed and released with no movement in between) | ||
107 | .RE | ||
108 | .PP | ||
109 | \fBMoveN\fR | ||
110 | .RS 4 | ||
111 | The mouse button | ||
112 | \fIN\fR | ||
113 | is currently holded, the binded action is triggered as often as the mouse moves\&. | ||
114 | .RE | ||
115 | .sp | ||
116 | There are some special "keys" that let you bind events to non\-keyboard events: | ||
97 | .PP | 117 | .PP |
98 | \fBChangeWorkspace\fR | 118 | \fBChangeWorkspace\fR |
99 | .RS 4 | 119 | .RS 4 |
@@ -101,7 +121,6 @@ Fires when the workspace changes\&. This can be used to change backgrounds or do | |||
101 | \fBEXAMPLES\fR | 121 | \fBEXAMPLES\fR |
102 | below for one idea\&. | 122 | below for one idea\&. |
103 | .RE | 123 | .RE |
104 | .RE | ||
105 | .if n \{\ | 124 | .if n \{\ |
106 | .sp | 125 | .sp |
107 | .\} | 126 | .\} |
diff --git a/src/CurrentWindowCmd.cc b/src/CurrentWindowCmd.cc index b73de01..f896009 100644 --- a/src/CurrentWindowCmd.cc +++ b/src/CurrentWindowCmd.cc | |||
@@ -262,11 +262,26 @@ void GoToTabCmd::real_execute() { | |||
262 | REGISTER_COMMAND(startmoving, StartMovingCmd, void); | 262 | REGISTER_COMMAND(startmoving, StartMovingCmd, void); |
263 | 263 | ||
264 | void StartMovingCmd::real_execute() { | 264 | void StartMovingCmd::real_execute() { |
265 | |||
266 | int x; | ||
267 | int y; | ||
265 | const XEvent &last = Fluxbox::instance()->lastEvent(); | 268 | const XEvent &last = Fluxbox::instance()->lastEvent(); |
266 | if (last.type == ButtonPress) { | 269 | switch (last.type) { |
267 | const XButtonEvent &be = last.xbutton; | 270 | case ButtonPress: |
268 | fbwindow().startMoving(be.x_root, be.y_root); | 271 | x = last.xbutton.x_root; |
272 | y = last.xbutton.y_root; | ||
273 | break; | ||
274 | |||
275 | case MotionNotify: | ||
276 | x = last.xmotion.x_root; | ||
277 | y = last.xmotion.y_root; | ||
278 | break; | ||
279 | |||
280 | default: | ||
281 | return; | ||
269 | } | 282 | } |
283 | |||
284 | fbwindow().startMoving(x, y); | ||
270 | } | 285 | } |
271 | 286 | ||
272 | FbTk::Command<void> *StartResizingCmd::parse(const string &cmd, const string &args, | 287 | FbTk::Command<void> *StartResizingCmd::parse(const string &cmd, const string &args, |
@@ -305,15 +320,27 @@ FbTk::Command<void> *StartResizingCmd::parse(const string &cmd, const string &ar | |||
305 | REGISTER_COMMAND_PARSER(startresizing, StartResizingCmd::parse, void); | 320 | REGISTER_COMMAND_PARSER(startresizing, StartResizingCmd::parse, void); |
306 | 321 | ||
307 | void StartResizingCmd::real_execute() { | 322 | void StartResizingCmd::real_execute() { |
323 | |||
324 | int x; | ||
325 | int y; | ||
308 | const XEvent &last = Fluxbox::instance()->lastEvent(); | 326 | const XEvent &last = Fluxbox::instance()->lastEvent(); |
309 | if (last.type == ButtonPress) { | 327 | switch (last.type) { |
310 | const XButtonEvent &be = last.xbutton; | 328 | case ButtonPress: |
311 | int x = be.x_root - fbwindow().x() | 329 | x = last.xbutton.x_root; |
312 | - fbwindow().frame().window().borderWidth(); | 330 | y = last.xbutton.y_root; |
313 | int y = be.y_root - fbwindow().y() | 331 | break; |
314 | - fbwindow().frame().window().borderWidth(); | 332 | case MotionNotify: |
315 | fbwindow().startResizing(x, y, fbwindow().getResizeDirection(x, y, m_mode)); | 333 | x = last.xmotion.x_root; |
334 | y = last.xmotion.y_root; | ||
335 | break; | ||
336 | default: | ||
337 | return; | ||
316 | } | 338 | } |
339 | |||
340 | x -= fbwindow().x() - fbwindow().frame().window().borderWidth(); | ||
341 | y -= fbwindow().y() - fbwindow().frame().window().borderWidth(); | ||
342 | |||
343 | fbwindow().startResizing(x, y, fbwindow().getResizeDirection(x, y, m_mode)); | ||
317 | } | 344 | } |
318 | 345 | ||
319 | REGISTER_COMMAND(starttabbing, StartTabbingCmd, void); | 346 | REGISTER_COMMAND(starttabbing, StartTabbingCmd, void); |
diff --git a/src/FbTk/KeyUtil.cc b/src/FbTk/KeyUtil.cc index 0578b9c..6ffe2a2 100644 --- a/src/FbTk/KeyUtil.cc +++ b/src/FbTk/KeyUtil.cc | |||
@@ -42,16 +42,16 @@ struct t_modlist{ | |||
42 | }; | 42 | }; |
43 | 43 | ||
44 | const struct t_modlist modlist[] = { | 44 | const struct t_modlist modlist[] = { |
45 | {"SHIFT", ShiftMask}, | 45 | {"shift", ShiftMask}, |
46 | {"LOCK", LockMask}, | 46 | {"lock", LockMask}, |
47 | {"CONTROL", ControlMask}, | 47 | {"control", ControlMask}, |
48 | {"MOD1", Mod1Mask}, | 48 | {"mod1", Mod1Mask}, |
49 | {"MOD2", Mod2Mask}, | 49 | {"mod2", Mod2Mask}, |
50 | {"MOD3", Mod3Mask}, | 50 | {"mod3", Mod3Mask}, |
51 | {"MOD4", Mod4Mask}, | 51 | {"mod4", Mod4Mask}, |
52 | {"MOD5", Mod5Mask}, | 52 | {"mod5", Mod5Mask}, |
53 | {"ALT", Mod1Mask}, | 53 | {"alt", Mod1Mask}, |
54 | {"CTRL", ControlMask}, | 54 | {"ctrl", ControlMask}, |
55 | {0, 0} | 55 | {0, 0} |
56 | }; | 56 | }; |
57 | 57 | ||
@@ -88,7 +88,7 @@ void KeyUtil::loadModmap() { | |||
88 | XFreeModifiermap(m_modmap); | 88 | XFreeModifiermap(m_modmap); |
89 | 89 | ||
90 | m_modmap = XGetModifierMapping(App::instance()->display()); | 90 | m_modmap = XGetModifierMapping(App::instance()->display()); |
91 | 91 | ||
92 | // find modifiers and set them | 92 | // find modifiers and set them |
93 | for (int i=0, realkey=0; i<8; ++i) { | 93 | for (int i=0, realkey=0; i<8; ++i) { |
94 | for (int key=0; key<m_modmap->max_keypermod; ++key, ++realkey) { | 94 | for (int key=0; key<m_modmap->max_keypermod; ++key, ++realkey) { |
@@ -96,7 +96,7 @@ void KeyUtil::loadModmap() { | |||
96 | if (m_modmap->modifiermap[realkey] == 0) | 96 | if (m_modmap->modifiermap[realkey] == 0) |
97 | continue; | 97 | continue; |
98 | 98 | ||
99 | KeySym ks = XKeycodeToKeysym(App::instance()->display(), | 99 | KeySym ks = XKeycodeToKeysym(App::instance()->display(), |
100 | m_modmap->modifiermap[realkey], 0); | 100 | m_modmap->modifiermap[realkey], 0); |
101 | 101 | ||
102 | switch (ks) { | 102 | switch (ks) { |
@@ -154,12 +154,18 @@ void KeyUtil::grabButton(unsigned int button, unsigned int mod, Window win, | |||
154 | */ | 154 | */ |
155 | 155 | ||
156 | unsigned int KeyUtil::getKey(const char *keystr) { | 156 | unsigned int KeyUtil::getKey(const char *keystr) { |
157 | if (!keystr) | 157 | |
158 | return 0; | 158 | KeyCode code = 0; |
159 | KeySym sym = XStringToKeysym(keystr); | 159 | |
160 | if (sym==NoSymbol) | 160 | if (keystr) { |
161 | return 0; | 161 | |
162 | return XKeysymToKeycode(App::instance()->display(), sym); | 162 | KeySym sym = XStringToKeysym(keystr); |
163 | if (sym != NoSymbol) { | ||
164 | code = XKeysymToKeycode(App::instance()->display(), sym); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | return code; | ||
163 | } | 169 | } |
164 | 170 | ||
165 | 171 | ||
@@ -169,14 +175,14 @@ unsigned int KeyUtil::getKey(const char *keystr) { | |||
169 | unsigned int KeyUtil::getModifier(const char *modstr) { | 175 | unsigned int KeyUtil::getModifier(const char *modstr) { |
170 | if (!modstr) | 176 | if (!modstr) |
171 | return 0; | 177 | return 0; |
172 | 178 | ||
173 | // find mod mask string | 179 | // find mod mask string |
174 | for (unsigned int i=0; modlist[i].str !=0; i++) { | 180 | for (unsigned int i=0; modlist[i].str !=0; i++) { |
175 | if (modlist[i] == modstr) | 181 | if (modlist[i] == modstr) |
176 | return modlist[i].mask; | 182 | return modlist[i].mask; |
177 | } | 183 | } |
178 | 184 | ||
179 | return 0; | 185 | return 0; |
180 | } | 186 | } |
181 | 187 | ||
182 | /// Ungrabs the keys | 188 | /// Ungrabs the keys |
@@ -193,7 +199,7 @@ void KeyUtil::ungrabButtons(Window win) { | |||
193 | unsigned int KeyUtil::keycodeToModmask(unsigned int keycode) { | 199 | unsigned int KeyUtil::keycodeToModmask(unsigned int keycode) { |
194 | XModifierKeymap *modmap = instance().m_modmap; | 200 | XModifierKeymap *modmap = instance().m_modmap; |
195 | 201 | ||
196 | if (!modmap) | 202 | if (!modmap) |
197 | return 0; | 203 | return 0; |
198 | 204 | ||
199 | // search through modmap for this keycode | 205 | // search through modmap for this keycode |
@@ -204,7 +210,7 @@ unsigned int KeyUtil::keycodeToModmask(unsigned int keycode) { | |||
204 | if (modmap->modifiermap[modmap->max_keypermod*mod + key] == keycode) { | 210 | if (modmap->modifiermap[modmap->max_keypermod*mod + key] == keycode) { |
205 | return modlist[mod].mask; | 211 | return modlist[mod].mask; |
206 | } | 212 | } |
207 | } | 213 | } |
208 | } | 214 | } |
209 | // no luck | 215 | // no luck |
210 | return 0; | 216 | return 0; |
diff --git a/src/Keys.cc b/src/Keys.cc index 0b8efe5..935d54b 100644 --- a/src/Keys.cc +++ b/src/Keys.cc | |||
@@ -106,6 +106,28 @@ using std::pair; | |||
106 | 106 | ||
107 | using FbTk::STLUtil::destroyAndClearSecond; | 107 | using FbTk::STLUtil::destroyAndClearSecond; |
108 | 108 | ||
109 | namespace { | ||
110 | |||
111 | // candidate for FbTk::StringUtil ? | ||
112 | int extractKeyFromString(const std::string& in, const char* start_pattern, unsigned int& key) { | ||
113 | |||
114 | int ret = 0; | ||
115 | |||
116 | if (strstr(in.c_str(), start_pattern) != 0) { | ||
117 | |||
118 | unsigned int tmp_key = 0; | ||
119 | if (FbTk::StringUtil::extractNumber(in.substr(strlen(start_pattern)), tmp_key)) { | ||
120 | |||
121 | key = tmp_key; | ||
122 | ret = 1; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | return ret; | ||
127 | } | ||
128 | |||
129 | } // end of anonymouse namespace | ||
130 | |||
109 | // helper class 'keytree' | 131 | // helper class 'keytree' |
110 | class Keys::t_key { | 132 | class Keys::t_key { |
111 | public: | 133 | public: |
@@ -254,10 +276,12 @@ void Keys::grabWindow(Window win) { | |||
254 | if ((win_it->second & Keys::GLOBAL) > 0 && (*it)->type == KeyPress) | 276 | if ((win_it->second & Keys::GLOBAL) > 0 && (*it)->type == KeyPress) |
255 | FbTk::KeyUtil::grabKey((*it)->key, (*it)->mod, win); | 277 | FbTk::KeyUtil::grabKey((*it)->key, (*it)->mod, win); |
256 | // ON_DESKTOP buttons don't need to be grabbed | 278 | // ON_DESKTOP buttons don't need to be grabbed |
257 | else if ((win_it->second & (*it)->context & ~Keys::ON_DESKTOP) > 0 && | 279 | else if ((win_it->second & (*it)->context & ~Keys::ON_DESKTOP) > 0) { |
258 | (*it)->type == ButtonPress) | 280 | |
259 | FbTk::KeyUtil::grabButton((*it)->key, (*it)->mod, win, | 281 | if ((*it)->type == ButtonPress || (*it)->type == ButtonRelease || (*it)->type == MotionNotify) { |
260 | ButtonPressMask|ButtonReleaseMask); | 282 | FbTk::KeyUtil::grabButton((*it)->key, (*it)->mod, win, ButtonPressMask|ButtonReleaseMask|ButtonMotionMask); |
283 | } | ||
284 | } | ||
261 | } | 285 | } |
262 | } | 286 | } |
263 | 287 | ||
@@ -363,85 +387,84 @@ bool Keys::addBinding(const string &linebuffer) { | |||
363 | // for each argument | 387 | // for each argument |
364 | for (; argc < val.size(); argc++) { | 388 | for (; argc < val.size(); argc++) { |
365 | 389 | ||
366 | if (val[argc][0] != ':') { // parse key(s) | 390 | std::string arg = FbTk::StringUtil::toLower(val[argc]); |
391 | |||
392 | if (arg[0] != ':') { // parse key(s) | ||
367 | 393 | ||
368 | int tmpmod = FbTk::KeyUtil::getModifier(val[argc].c_str()); | 394 | int tmpmod = FbTk::KeyUtil::getModifier(arg.c_str()); |
369 | if(tmpmod) | 395 | if(tmpmod) |
370 | mod |= tmpmod; //If it's a modifier | 396 | mod |= tmpmod; //If it's a modifier |
371 | else if (strcasecmp("ondesktop", val[argc].c_str()) == 0) | 397 | else if (arg == "ondesktop") |
372 | context |= ON_DESKTOP; | 398 | context |= ON_DESKTOP; |
373 | else if (strcasecmp("ontoolbar", val[argc].c_str()) == 0) | 399 | else if (arg == "ontoolbar") |
374 | context |= ON_TOOLBAR; | 400 | context |= ON_TOOLBAR; |
375 | else if (strcasecmp("onwindow", val[argc].c_str()) == 0) | 401 | else if (arg == "onwindow") |
376 | context |= ON_WINDOW; | 402 | context |= ON_WINDOW; |
377 | else if (strcasecmp("ontitlebar", val[argc].c_str()) == 0) | 403 | else if (arg == "ontitlebar") |
378 | context |= ON_TITLEBAR; | 404 | context |= ON_TITLEBAR; |
379 | else if (strcasecmp("double", val[argc].c_str()) == 0) | 405 | else if (arg == "double") |
380 | isdouble = true; | 406 | isdouble = true; |
381 | else if (strcasecmp("NONE",val[argc].c_str())) { | 407 | else if (arg != "none") { |
382 | // check if it's a mouse button | 408 | if (arg == "focusin") { |
383 | if (strcasecmp("focusin", val[argc].c_str()) == 0) { | ||
384 | context = ON_WINDOW; | 409 | context = ON_WINDOW; |
385 | mod = key = 0; | 410 | mod = key = 0; |
386 | type = FocusIn; | 411 | type = FocusIn; |
387 | } else if (strcasecmp("focusout", val[argc].c_str()) == 0) { | 412 | } else if (arg == "focusout") { |
388 | context = ON_WINDOW; | 413 | context = ON_WINDOW; |
389 | mod = key = 0; | 414 | mod = key = 0; |
390 | type = FocusOut; | 415 | type = FocusOut; |
391 | } else if (strcasecmp("changeworkspace", | 416 | } else if (arg == "changeworkspace") { |
392 | val[argc].c_str()) == 0) { | ||
393 | context = ON_DESKTOP; | 417 | context = ON_DESKTOP; |
394 | mod = key = 0; | 418 | mod = key = 0; |
395 | type = FocusIn; | 419 | type = FocusIn; |
396 | } else if (strcasecmp("mouseover", val[argc].c_str()) == 0) { | 420 | } else if (arg == "mouseover") { |
397 | type = EnterNotify; | 421 | type = EnterNotify; |
398 | if (!(context & (ON_WINDOW|ON_TOOLBAR))) | 422 | if (!(context & (ON_WINDOW|ON_TOOLBAR))) |
399 | context |= ON_WINDOW; | 423 | context |= ON_WINDOW; |
400 | key = 0; | 424 | key = 0; |
401 | } else if (strcasecmp("mouseout", val[argc].c_str()) == 0) { | 425 | } else if (arg == "mouseout") { |
402 | type = LeaveNotify; | 426 | type = LeaveNotify; |
403 | if (!(context & (ON_WINDOW|ON_TOOLBAR))) | 427 | if (!(context & (ON_WINDOW|ON_TOOLBAR))) |
404 | context |= ON_WINDOW; | 428 | context |= ON_WINDOW; |
405 | key = 0; | 429 | key = 0; |
406 | } else if (strcasecmp(val[argc].substr(0,5).c_str(), | 430 | |
407 | "mouse") == 0 && | 431 | // check if it's a mouse button |
408 | val[argc].length() > 5) { | 432 | } else if (extractKeyFromString(arg, "mouse", key)) { |
409 | type = ButtonPress; | 433 | type = ButtonPress; |
410 | key = atoi(val[argc].substr(5, | 434 | |
411 | val[argc].length()-5).c_str()); | ||
412 | // fluxconf mangles things like OnWindow Mouse# to Mouse#ow | 435 | // fluxconf mangles things like OnWindow Mouse# to Mouse#ow |
413 | if (strstr(val[argc].c_str(), "top")) | 436 | if (strstr(arg.c_str(), "top")) |
414 | context = ON_DESKTOP; | 437 | context = ON_DESKTOP; |
415 | else if (strstr(val[argc].c_str(), "ebar")) | 438 | else if (strstr(arg.c_str(), "ebar")) |
416 | context = ON_TITLEBAR; | 439 | context = ON_TITLEBAR; |
417 | else if (strstr(val[argc].c_str(), "bar")) | 440 | else if (strstr(arg.c_str(), "bar")) |
418 | context = ON_TOOLBAR; | 441 | context = ON_TOOLBAR; |
419 | else if (strstr(val[argc].c_str(), "ow")) | 442 | else if (strstr(arg.c_str(), "ow")) |
420 | context = ON_WINDOW; | 443 | context = ON_WINDOW; |
444 | } else if (extractKeyFromString(arg, "click", key)) { | ||
445 | type = ButtonRelease; | ||
446 | } else if (extractKeyFromString(arg, "move", key)) { | ||
447 | type = MotionNotify; | ||
448 | |||
449 | } else if (key = FbTk::KeyUtil::getKey(val[argc].c_str())) { // convert from string symbol | ||
450 | type = KeyPress; | ||
451 | |||
421 | // keycode covers the following three two-byte cases: | 452 | // keycode covers the following three two-byte cases: |
422 | // 0x - hex | 453 | // 0x - hex |
423 | // +[1-9] - number between +1 and +9 | 454 | // +[1-9] - number between +1 and +9 |
424 | // numbers 10 and above | 455 | // numbers 10 and above |
425 | // | 456 | // |
426 | } else if (!val[argc].empty() && ((isdigit(val[argc][0]) && | 457 | } else { |
427 | (isdigit(val[argc][1]) || val[argc][1] == 'x')) || | 458 | FbTk::StringUtil::extractNumber(arg, key); |
428 | (val[argc][0] == '+' && isdigit(val[argc][1])))) { | ||
429 | |||
430 | key = strtoul(val[argc].c_str(), NULL, 0); | ||
431 | type = KeyPress; | ||
432 | |||
433 | if (errno == EINVAL || errno == ERANGE) | ||
434 | key = 0; | ||
435 | |||
436 | } else { // convert from string symbol | ||
437 | key = FbTk::KeyUtil::getKey(val[argc].c_str()); | ||
438 | type = KeyPress; | 459 | type = KeyPress; |
439 | } | 460 | } |
440 | 461 | ||
441 | if (key == 0 && (type == KeyPress || type == ButtonPress)) | 462 | if (key == 0 && (type == KeyPress || type == ButtonPress || type == ButtonRelease)) |
442 | return false; | 463 | return false; |
464 | |||
443 | if (type != ButtonPress) | 465 | if (type != ButtonPress) |
444 | isdouble = false; | 466 | isdouble = false; |
467 | |||
445 | if (!first_new_key) { | 468 | if (!first_new_key) { |
446 | first_new_keylist = current_key; | 469 | first_new_keylist = current_key; |
447 | current_key = current_key->find(type, mod, key, context, | 470 | current_key = current_key->find(type, mod, key, context, |
@@ -470,7 +493,7 @@ bool Keys::addBinding(const string &linebuffer) { | |||
470 | return false; | 493 | return false; |
471 | 494 | ||
472 | const char *str = FbTk::StringUtil::strcasestr(linebuffer.c_str(), | 495 | const char *str = FbTk::StringUtil::strcasestr(linebuffer.c_str(), |
473 | val[argc].c_str()); | 496 | val[argc].c_str()); |
474 | if (str) // +1 to skip ':' | 497 | if (str) // +1 to skip ':' |
475 | current_key->m_command = FbTk::CommandParser<void>::instance().parse(str + 1); | 498 | current_key->m_command = FbTk::CommandParser<void>::instance().parse(str + 1); |
476 | 499 | ||
@@ -504,10 +527,11 @@ bool Keys::doAction(int type, unsigned int mods, unsigned int key, | |||
504 | bool isdouble = false; | 527 | bool isdouble = false; |
505 | 528 | ||
506 | if (type == ButtonPress) { | 529 | if (type == ButtonPress) { |
507 | if (time > last_button_time) | 530 | if (time > last_button_time) { |
508 | double_click = (time - last_button_time < | 531 | double_click = (time - last_button_time < |
509 | Fluxbox::instance()->getDoubleClickInterval()) && | 532 | Fluxbox::instance()->getDoubleClickInterval()) && |
510 | last_button == key; | 533 | last_button == key; |
534 | } | ||
511 | last_button_time = time; | 535 | last_button_time = time; |
512 | last_button = key; | 536 | last_button = key; |
513 | isdouble = double_click; | 537 | isdouble = double_click; |
diff --git a/src/Window.cc b/src/Window.cc index c03447c..0fb674c 100644 --- a/src/Window.cc +++ b/src/Window.cc | |||
@@ -280,6 +280,7 @@ FluxboxWindow::FluxboxWindow(WinClient &client): | |||
280 | m_button_grab_x(0), m_button_grab_y(0), | 280 | m_button_grab_x(0), m_button_grab_y(0), |
281 | m_last_move_x(0), m_last_move_y(0), | 281 | m_last_move_x(0), m_last_move_y(0), |
282 | m_last_resize_h(1), m_last_resize_w(1), | 282 | m_last_resize_h(1), m_last_resize_w(1), |
283 | m_last_pressed_button(0), | ||
283 | m_workspace_number(0), | 284 | m_workspace_number(0), |
284 | m_current_state(0), | 285 | m_current_state(0), |
285 | m_old_decoration_mask(0), | 286 | m_old_decoration_mask(0), |
@@ -1073,7 +1074,6 @@ void FluxboxWindow::grabButtons() { | |||
1073 | GrabModeSync, GrabModeSync, None, None); | 1074 | GrabModeSync, GrabModeSync, None, None); |
1074 | XUngrabButton(display, Button1, Mod1Mask|Mod2Mask|Mod3Mask, | 1075 | XUngrabButton(display, Button1, Mod1Mask|Mod2Mask|Mod3Mask, |
1075 | frame().window().window()); | 1076 | frame().window().window()); |
1076 | |||
1077 | } | 1077 | } |
1078 | 1078 | ||
1079 | 1079 | ||
@@ -1478,7 +1478,7 @@ void FluxboxWindow::setFullscreenLayer() { | |||
1478 | FluxboxWindow *foc = FocusControl::focusedFbWindow(); | 1478 | FluxboxWindow *foc = FocusControl::focusedFbWindow(); |
1479 | // if another window on the same head is focused, make sure we can see it | 1479 | // if another window on the same head is focused, make sure we can see it |
1480 | if (isFocused() || !foc || &foc->screen() != &screen() || | 1480 | if (isFocused() || !foc || &foc->screen() != &screen() || |
1481 | getOnHead() != foc->getOnHead() || | 1481 | getOnHead() != foc->getOnHead() || |
1482 | (foc->winClient().isTransient() && | 1482 | (foc->winClient().isTransient() && |
1483 | foc->winClient().transientFor()->fbwindow() == this)) { | 1483 | foc->winClient().transientFor()->fbwindow() == this)) { |
1484 | moveToLayer(::Layer::ABOVE_DOCK); | 1484 | moveToLayer(::Layer::ABOVE_DOCK); |
@@ -2370,13 +2370,16 @@ bool FluxboxWindow::isTyping() const { | |||
2370 | void FluxboxWindow::buttonPressEvent(XButtonEvent &be) { | 2370 | void FluxboxWindow::buttonPressEvent(XButtonEvent &be) { |
2371 | m_last_button_x = be.x_root; | 2371 | m_last_button_x = be.x_root; |
2372 | m_last_button_y = be.y_root; | 2372 | m_last_button_y = be.y_root; |
2373 | m_last_pressed_button = be.button; | ||
2373 | 2374 | ||
2374 | bool onTitlebar = | 2375 | bool onTitlebar = |
2375 | frame().insideTitlebar( be.window ) && | 2376 | frame().insideTitlebar( be.window ) && |
2376 | frame().handle().window() != be.window; | 2377 | frame().handle().window() != be.window; |
2377 | 2378 | ||
2379 | #if 0 // disabled | ||
2378 | if (onTitlebar && be.button == 1) | 2380 | if (onTitlebar && be.button == 1) |
2379 | raise(); | 2381 | raise(); |
2382 | #endif | ||
2380 | 2383 | ||
2381 | // check keys file first | 2384 | // check keys file first |
2382 | Keys *k = Fluxbox::instance()->keys(); | 2385 | Keys *k = Fluxbox::instance()->keys(); |
@@ -2412,19 +2415,27 @@ void FluxboxWindow::buttonPressEvent(XButtonEvent &be) { | |||
2412 | 2415 | ||
2413 | void FluxboxWindow::buttonReleaseEvent(XButtonEvent &re) { | 2416 | void FluxboxWindow::buttonReleaseEvent(XButtonEvent &re) { |
2414 | 2417 | ||
2418 | if (m_last_pressed_button == re.button) { | ||
2419 | m_last_pressed_button = 0; | ||
2420 | } | ||
2421 | |||
2415 | if (isMoving()) | 2422 | if (isMoving()) |
2416 | stopMoving(); | 2423 | stopMoving(); |
2417 | else if (isResizing()) | 2424 | else if (isResizing()) |
2418 | stopResizing(); | 2425 | stopResizing(); |
2419 | else if (m_attaching_tab) | 2426 | else if (m_attaching_tab) |
2420 | attachTo(re.x_root, re.y_root); | 2427 | attachTo(re.x_root, re.y_root); |
2421 | else | 2428 | else if (!frame().tabcontainer().tryButtonReleaseEvent(re)) { |
2422 | frame().tabcontainer().tryButtonReleaseEvent(re); | ||
2423 | 2429 | ||
2430 | if (m_last_button_x == re.x_root && m_last_button_y == re.y_root) { | ||
2431 | Fluxbox::instance()->keys()->doAction(re.type, re.state, re.button, Keys::ON_WINDOW, &winClient(), re.time); | ||
2432 | } | ||
2433 | } | ||
2424 | } | 2434 | } |
2425 | 2435 | ||
2426 | 2436 | ||
2427 | void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) { | 2437 | void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) { |
2438 | |||
2428 | if (isMoving() && me.window == parent()) { | 2439 | if (isMoving() && me.window == parent()) { |
2429 | me.window = frame().window().window(); | 2440 | me.window = frame().window().window(); |
2430 | } | 2441 | } |
@@ -2452,6 +2463,13 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) { | |||
2452 | } | 2463 | } |
2453 | } | 2464 | } |
2454 | 2465 | ||
2466 | |||
2467 | // in case someone put MoveX :StartMoving etc into keys, we have | ||
2468 | // to activate it before doing the actual motionNotify code | ||
2469 | Fluxbox::instance()->keys()->doAction(me.type, me.state, m_last_pressed_button, | ||
2470 | inside_titlebar ? Keys::ON_TITLEBAR : Keys::ON_WINDOW, | ||
2471 | &winClient(), me.time); | ||
2472 | |||
2455 | if (moving || ((me.state & Button1Mask) && functions.move && | 2473 | if (moving || ((me.state & Button1Mask) && functions.move && |
2456 | inside_titlebar && !isResizing() && m_attaching_tab == 0)) { | 2474 | inside_titlebar && !isResizing() && m_attaching_tab == 0)) { |
2457 | 2475 | ||
@@ -2818,8 +2836,14 @@ void FluxboxWindow::setDecorationMask(unsigned int mask, bool apply) { | |||
2818 | } | 2836 | } |
2819 | 2837 | ||
2820 | void FluxboxWindow::startMoving(int x, int y) { | 2838 | void FluxboxWindow::startMoving(int x, int y) { |
2821 | if (s_num_grabs > 0) | 2839 | |
2840 | if (isMoving()) { | ||
2841 | return; | ||
2842 | } | ||
2843 | |||
2844 | if (s_num_grabs > 0) { | ||
2822 | return; | 2845 | return; |
2846 | } | ||
2823 | 2847 | ||
2824 | if (isMaximized() && screen().getMaxDisableMove()) | 2848 | if (isMaximized() && screen().getMaxDisableMove()) |
2825 | return; | 2849 | return; |
@@ -3062,6 +3086,7 @@ void FluxboxWindow::doSnapping(int &orig_left, int &orig_top) { | |||
3062 | 3086 | ||
3063 | FluxboxWindow::ReferenceCorner FluxboxWindow::getResizeDirection(int x, int y, | 3087 | FluxboxWindow::ReferenceCorner FluxboxWindow::getResizeDirection(int x, int y, |
3064 | ResizeModel model) const { | 3088 | ResizeModel model) const { |
3089 | |||
3065 | int cx = frame().width() / 2; | 3090 | int cx = frame().width() / 2; |
3066 | int cy = frame().height() / 2; | 3091 | int cy = frame().height() / 2; |
3067 | if (model == CENTERRESIZE) | 3092 | if (model == CENTERRESIZE) |
@@ -3088,6 +3113,9 @@ FluxboxWindow::ReferenceCorner FluxboxWindow::getResizeDirection(int x, int y, | |||
3088 | 3113 | ||
3089 | void FluxboxWindow::startResizing(int x, int y, ReferenceCorner dir) { | 3114 | void FluxboxWindow::startResizing(int x, int y, ReferenceCorner dir) { |
3090 | 3115 | ||
3116 | if (isResizing()) | ||
3117 | return; | ||
3118 | |||
3091 | if (s_num_grabs > 0 || isShaded() || isIconic() ) | 3119 | if (s_num_grabs > 0 || isShaded() || isIconic() ) |
3092 | return; | 3120 | return; |
3093 | 3121 | ||
@@ -3550,7 +3578,7 @@ void FluxboxWindow::updateButtons() { | |||
3550 | need_update = true; | 3578 | need_update = true; |
3551 | } | 3579 | } |
3552 | } | 3580 | } |
3553 | 3581 | ||
3554 | } | 3582 | } |
3555 | 3583 | ||
3556 | if (!need_update) | 3584 | if (!need_update) |
@@ -3680,6 +3708,7 @@ void FluxboxWindow::grabPointer(Window grab_window, | |||
3680 | Window confine_to, | 3708 | Window confine_to, |
3681 | Cursor cursor, | 3709 | Cursor cursor, |
3682 | Time time) { | 3710 | Time time) { |
3711 | |||
3683 | XGrabPointer(FbTk::App::instance()->display(), | 3712 | XGrabPointer(FbTk::App::instance()->display(), |
3684 | grab_window, | 3713 | grab_window, |
3685 | owner_events, | 3714 | owner_events, |
@@ -3870,7 +3899,7 @@ void FluxboxWindow::setWindowType(WindowState::WindowType type) { | |||
3870 | */ | 3899 | */ |
3871 | } | 3900 | } |
3872 | 3901 | ||
3873 | void FluxboxWindow::focusedWindowChanged(BScreen &screen, | 3902 | void FluxboxWindow::focusedWindowChanged(BScreen &screen, |
3874 | FluxboxWindow *focused_win, WinClient* client) { | 3903 | FluxboxWindow *focused_win, WinClient* client) { |
3875 | if (focused_win) { | 3904 | if (focused_win) { |
3876 | setFullscreenLayer(); | 3905 | setFullscreenLayer(); |
diff --git a/src/Window.hh b/src/Window.hh index 92d20d7..9cefd55 100644 --- a/src/Window.hh +++ b/src/Window.hh | |||
@@ -547,6 +547,7 @@ private: | |||
547 | int m_last_resize_x, m_last_resize_y; // handles last button press event for resize | 547 | int m_last_resize_x, m_last_resize_y; // handles last button press event for resize |
548 | int m_last_move_x, m_last_move_y; // handles last pos for non opaque moving | 548 | int m_last_move_x, m_last_move_y; // handles last pos for non opaque moving |
549 | int m_last_resize_h, m_last_resize_w; // handles height/width for resize "window" | 549 | int m_last_resize_h, m_last_resize_w; // handles height/width for resize "window" |
550 | int m_last_pressed_button; | ||
550 | 551 | ||
551 | timeval m_last_keypress_time; | 552 | timeval m_last_keypress_time; |
552 | 553 | ||