1 // bbkeys.cc for blackbox
2 // ------ note from the Gee-I'm-Sorry-The-Code-Looks-Ugly department-----
3 // ------ for vi users-- ":set ts=2" =:)
5 // Copyright (c) 1999-2001 by Jason Kasper (vanRijn) vR@movingparts.net
6 // Copyright (c) 2001 by Ben Jansens <xor@orodu.net>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 // (See the included file COPYING / GPL-2.0)
32 #endif // HAVE_STDIO_H
36 #endif // HAVE_CTYPE_H
41 #endif // STDC_HEADERS
47 #ifdef HAVE_SYS_TYPES_H
48 # include <sys/types.h>
49 #endif // HAVE_SYS_TYPES_H
51 #ifdef HAVE_SYS_WAIT_H
52 # include <sys/wait.h>
53 #endif // HAVE_SYS_WAIT_H
57 #endif // HAVE_ERRNO_H
61 #endif // HAVE_UNISTD_H
63 #ifdef HAVE_SYS_STAT_H
64 # include <sys/stat.h>
65 #endif // HAVE_SYS_STAT_H
68 #include <X11/Xproto.h>
69 #include <X11/keysym.h>
74 #include "Basemenu.hh"
76 /*--------------------------------------------------------------------*/
78 /* Ripped shamelessly from wmaker's xmodifier.c--converted for our use*/
80 /*--------------------------------------------------------------------*/
82 /* Grok X modifier mappings for shortcuts.
84 Most of this code was taken from src/event-Xt.c in XEmacs 20.3-b17.
85 The copyright(s) from the original XEmacs code are included below.
87 Perpetrator: Sudish Joseph <sj@eng.mindspring.net>, Sept. 1997. */
89 /* The event_stream interface for X11 with Xt, and/or tty frames.
90 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
91 Copyright (C) 1995 Sun Microsystems, Inc.
92 Copyright (C) 1996 Ben Wing.
94 This file is part of XEmacs.
96 XEmacs is free software; you can redistribute it and/or modify it
97 under the terms of the GNU General Public License as published by the
98 Free Software Foundation; either version 2, or (at your option) any
101 XEmacs is distributed in the hope that it will be useful, but WITHOUT
102 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
103 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
106 You should have received a copy of the GNU General Public License
107 along with XEmacs; see the file COPYING. If not, write to
108 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
109 Boston, MA 02111-1307, USA. */
111 /************************************************************************/
113 /* keymap handling */
115 /************************************************************************/
117 /* X bogusly doesn't define the interpretations of any bits besides
118 ModControl, ModShift, and ModLock; so the Interclient Communication
119 Conventions Manual says that we have to bend over backwards to figure
120 out what the other modifier bits mean. According to ICCCM:
122 - Any keycode which is assigned ModControl is a "control" key.
124 - Any modifier bit which is assigned to a keycode which generates Meta_L
125 or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper,
128 - Any keypress event which contains ModControl in its state should be
129 interpreted as a "control" character.
131 - Any keypress event which contains a modifier bit in its state which is
132 generated by a keycode whose corresponding keysym is Meta_L or Meta_R
133 should be interpreted as a "meta" character. Likewise for Super, Hyper,
136 - It is illegal for a keysym to be associated with more than one modifier
139 This means that the only thing that emacs can reasonably interpret as a
140 "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
141 one of the modifier bits Mod1-Mod5.
143 Unfortunately, many keyboards don't have Meta keys in their default
144 configuration. So, if there are no Meta keys, but there are "Alt" keys,
145 emacs will interpret Alt as Meta. If there are both Meta and Alt keys,
146 then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
147 mean "Symbol," but that just confused the hell out of way too many people).
149 This works with the default configurations of the 19 keyboard-types I've
152 Emacs detects keyboard configurations which violate the above rules, and
153 prints an error message on the standard-error-output. (Perhaps it should
154 use a pop-up-window instead.)
157 static int MetaMask
, HyperMask
, SuperMask
, AltMask
, ModeMask
;
158 static int NumLockMask
, ScrollLockMask
;
160 char *ToolWindow::index_to_name(int indice
)
167 case ControlMapIndex
:
184 void ToolWindow::x_reset_modifier_mapping(Display
* display
)
186 int modifier_index
, modifier_key
, column
, mkpm
;
187 int warned_about_overlapping_modifiers
= 0;
188 int warned_about_predefined_modifiers
= 0;
189 int warned_about_duplicate_modifiers
= 0;
195 int num_lock_bit
= 0;
196 int scroll_lock_bit
= 0;
197 XModifierKeymap
*x_modifier_keymap
= XGetModifierMapping(display
);
199 #define modwarn(name,old,other) \
200 warned_about_overlapping_modifiers = 1
202 #define modbarf(name,other) \
203 warned_about_predefined_modifiers = 1
205 #define check_modifier(name,mask) \
206 warned_about_predefined_modifiers = 1
208 #define store_modifier(name,old) \
209 if (old && old != modifier_index) \
210 warned_about_duplicate_modifiers = 1; \
211 if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift"); \
212 else if (modifier_index == LockMapIndex) modbarf (name,"ModLock"); \
213 else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \
214 else if (sym == XK_Mode_switch) \
215 mode_bit = modifier_index; /* Mode_switch is special, see below... */ \
216 else if (modifier_index == meta_bit && old != meta_bit) \
217 modwarn (name, meta_bit, "Meta"); \
218 else if (modifier_index == super_bit && old != super_bit) \
219 modwarn (name, super_bit, "Super"); \
220 else if (modifier_index == hyper_bit && old != hyper_bit) \
221 modwarn (name, hyper_bit, "Hyper"); \
222 else if (modifier_index == alt_bit && old != alt_bit) \
223 modwarn (name, alt_bit, "Alt"); \
225 old = modifier_index;
227 mkpm
= x_modifier_keymap
->max_keypermod
;
228 for (modifier_index
= 0; modifier_index
< 8; modifier_index
++)
229 for (modifier_key
= 0; modifier_key
< mkpm
; modifier_key
++) {
231 for (column
= 0; column
< 4; column
+= 2) {
233 x_modifier_keymap
->modifiermap
[modifier_index
* mkpm
+
236 (code
? XKeycodeToKeysym(display
, code
, column
) : 0);
242 store_modifier("Mode_switch", mode_bit
);
245 store_modifier("Meta_L", meta_bit
);
248 store_modifier("Meta_R", meta_bit
);
251 store_modifier("Super_L", super_bit
);
254 store_modifier("Super_R", super_bit
);
257 store_modifier("Hyper_L", hyper_bit
);
260 store_modifier("Hyper_R", hyper_bit
);
263 store_modifier("Alt_L", alt_bit
);
266 store_modifier("Alt_R", alt_bit
);
269 store_modifier("Num_Lock", num_lock_bit
);
272 store_modifier("Scroll_Lock", scroll_lock_bit
);
275 check_modifier("Control_L", ControlMask
);
278 check_modifier("Control_R", ControlMask
);
281 check_modifier("Shift_L", ShiftMask
);
284 check_modifier("Shift_R", ShiftMask
);
287 check_modifier("Shift_Lock", LockMask
);
290 check_modifier("Caps_Lock", LockMask
);
293 /* It probably doesn't make any sense for a modifier bit to be
294 assigned to a key that is not one of the above, but OpenWindows
295 assigns modifier bits to a couple of random function keys for
296 no reason that I can discern, so printing a warning here would
301 #undef store_modifier
302 #undef check_modifier
306 /* If there was no Meta key, then try using the Alt key instead.
307 If there is both a Meta key and an Alt key, then the Alt key
308 is not disturbed and remains an Alt key. */
309 if (!meta_bit
&& alt_bit
)
310 meta_bit
= alt_bit
, alt_bit
= 0;
312 /* mode_bit overrides everything, since it's processed down inside of
313 XLookupString() instead of by us. If Meta and Mode_switch both
314 generate the same modifier bit (which is an error), then we don't
315 interpret that bit as Meta, because we can't make XLookupString()
316 not interpret it as Mode_switch; and interpreting it as both would
319 const char *warn
= 0;
320 if (mode_bit
== meta_bit
)
321 warn
= "Meta", meta_bit
= 0;
322 else if (mode_bit
== hyper_bit
)
323 warn
= "Hyper", hyper_bit
= 0;
324 else if (mode_bit
== super_bit
)
325 warn
= "Super", super_bit
= 0;
326 else if (mode_bit
== alt_bit
)
327 warn
= "Alt", alt_bit
= 0;
329 warned_about_overlapping_modifiers
= 1;
333 MetaMask
= (meta_bit
? (1 << meta_bit
) : 0);
334 HyperMask
= (hyper_bit
? (1 << hyper_bit
) : 0);
335 SuperMask
= (super_bit
? (1 << super_bit
) : 0);
336 AltMask
= (alt_bit
? (1 << alt_bit
) : 0);
337 ModeMask
= (mode_bit
? (1 << mode_bit
) : 0); /* unused */
338 NumLockMask
= (num_lock_bit
? (1 << num_lock_bit
) : 0);
339 ScrollLockMask
= (scroll_lock_bit
? (1 << scroll_lock_bit
) : 0);
341 if (x_modifier_keymap
)
342 XFreeModifiermap(x_modifier_keymap
);
346 int ToolWindow::translateModifier(char *key
)
348 if (strcasecmp(key
, "SHIFT") == 0 && ShiftMask
!= 0)
350 else if (strcasecmp(key
, "CONTROL") == 0 && ControlMask
!= 0)
352 else if (strcasecmp(key
, "ALT") == 0 && AltMask
!= 0)
354 else if (strcasecmp(key
, "META") == 0 && MetaMask
!= 0)
356 else if (strcasecmp(key
, "SUPER") == 0 && SuperMask
!= 0)
358 else if (strcasecmp(key
, "HYPER") == 0 && HyperMask
!= 0)
360 else if (strcasecmp(key
, "MOD1") == 0 && Mod1Mask
!= 0)
362 else if (strcasecmp(key
, "MOD2") == 0 && Mod2Mask
!= 0)
364 else if (strcasecmp(key
, "MOD3") == 0 && Mod3Mask
!= 0)
366 else if (strcasecmp(key
, "MOD4") == 0 && Mod4Mask
!= 0)
368 else if (strcasecmp(key
, "MOD5") == 0 && Mod5Mask
!= 0)
370 else if (strcasecmp(key
, "NONE") == 0)
376 /* Wrapper so that we may fit our naming conventions, yet leave the
377 original XEmacs function name in place. */
378 void ToolWindow::InitializeModifiers(void)
380 x_reset_modifier_mapping(getXDisplay());
383 /*-----------------------------------------------------------------------*/
385 /*-- end of shameless rip. thank you for your support ---*/
387 /*-----------------------------------------------------------------------*/
389 void ToolWindow::CheckConfig()
391 struct stat file_status
;
393 if (stat(bbkeys_rcfile
, &file_status
) != 0) {
395 fprintf(stderr
, "Could not open config file ->%s<-\n",
398 } else if (file_status
.st_mtime
!= bbkeys_rcTime
) {
399 bbkeys_rcTime
= file_status
.st_mtime
;
405 void ToolWindow::activateKeygrabs(void)
409 if (grabSet
.instructCount
> 0)
410 XUngrabKey(getXDisplay(), AnyKey
, AnyModifier
,
411 getScreenInfo(0)->getRootWindow());
412 for (i
= 0; i
< grabSet
.instructCount
; i
++) {
413 if (grabSet
.KeyMap
[i
].keycode
== 0)
416 if (grabSet
.KeyMap
[i
].keycode
!= AnyModifier
) {
417 XGrabKey(getXDisplay(), grabSet
.KeyMap
[i
].keycode
,
418 grabSet
.KeyMap
[i
].modMask
| LockMask
,
419 getCurrentScreenInfo()->getRootWindow(), True
,
420 GrabModeAsync
, GrabModeAsync
);
422 /* Also grab all modifier combinations possible that include,
423 * LockMask, ScrollLockMask and NumLockMask, so that keygrabs
424 * work even if the NumLock/ScrollLock key is on.
427 wHackedGrabKey(grabSet
.KeyMap
[i
].keycode
,
428 grabSet
.KeyMap
[i
].modMask
,
429 getCurrentScreenInfo()->getRootWindow(), True
,
430 GrabModeAsync
, GrabModeAsync
);
433 XGrabKey(getXDisplay(), grabSet
.KeyMap
[i
].keycode
,
434 grabSet
.KeyMap
[i
].modMask
,
435 getCurrentScreenInfo()->getRootWindow(), True
,
436 GrabModeAsync
, GrabModeAsync
);
440 /*---------------------------------------------------------------------------*/
442 /*-- Snarfed shamelessly from WindowMaker's code-base once again.... --*/
444 /*---------------------------------------------------------------------------*/
445 void ToolWindow::wHackedGrabKey(int keycode
, unsigned int modifiers
,
446 Window grab_window
, Bool owner_events
,
447 int pointer_mode
, int keyboard_mode
)
449 if (modifiers
== AnyModifier
)
451 if (keycode
== AnyKey
)
454 /* grab all combinations of the modifier with CapsLock, NumLock and
455 * ScrollLock. How much memory/CPU does such a monstrosity consume
459 XGrabKey(getXDisplay(), keycode
, modifiers
| _NumLockMask
,
460 grab_window
, owner_events
, pointer_mode
, keyboard_mode
);
462 if (_ScrollLockMask
) {
463 XGrabKey(getXDisplay(), keycode
, modifiers
| _ScrollLockMask
,
464 grab_window
, owner_events
, pointer_mode
, keyboard_mode
);
466 if (_NumLockMask
&& _ScrollLockMask
) {
467 XGrabKey(getXDisplay(), keycode
,
468 modifiers
| _NumLockMask
| _ScrollLockMask
, grab_window
,
469 owner_events
, pointer_mode
, keyboard_mode
);
472 XGrabKey(getXDisplay(), keycode
,
473 modifiers
| _NumLockMask
| LockMask
, grab_window
,
474 owner_events
, pointer_mode
, keyboard_mode
);
476 if (_ScrollLockMask
) {
477 XGrabKey(getXDisplay(), keycode
,
478 modifiers
| _ScrollLockMask
| LockMask
, grab_window
,
479 owner_events
, pointer_mode
, keyboard_mode
);
481 if (_NumLockMask
&& _ScrollLockMask
) {
482 XGrabKey(getXDisplay(), keycode
,
483 modifiers
| _NumLockMask
| _ScrollLockMask
| LockMask
,
484 grab_window
, owner_events
, pointer_mode
, keyboard_mode
);
486 /* phew, I guess that's all, right? */
489 void ToolWindow::getOffendingModifiers(void)
492 XModifierKeymap
*modmap
;
493 KeyCode nlock
, slock
;
494 static int mask_table
[8] = {
495 ShiftMask
, LockMask
, ControlMask
, Mod1Mask
,
496 Mod2Mask
, Mod3Mask
, Mod4Mask
, Mod5Mask
499 nlock
= XKeysymToKeycode(getXDisplay(), XK_Num_Lock
);
500 slock
= XKeysymToKeycode(getXDisplay(), XK_Scroll_Lock
);
503 * Find out the masks for the NumLock and ScrollLock modifiers,
504 * so that we can bind the grabs for when they are enabled too.
506 modmap
= XGetModifierMapping(getXDisplay());
508 if (modmap
!= NULL
&& modmap
->max_keypermod
> 0) {
509 for (i
= 0; i
< 8 * modmap
->max_keypermod
; i
++) {
510 if (modmap
->modifiermap
[i
] == nlock
&& nlock
!= 0)
511 _NumLockMask
= mask_table
[i
/ modmap
->max_keypermod
];
512 else if (modmap
->modifiermap
[i
] == slock
&& slock
!= 0)
513 _ScrollLockMask
= mask_table
[i
/ modmap
->max_keypermod
];
518 XFreeModifiermap(modmap
);
521 /*-------------------------------------------------------------------------*/
523 /*-- End of shameful code-snarf..................................... --*/
525 /*-------------------------------------------------------------------------*/
527 int ToolWindow::translateAction(char *action
)
532 if (!strcasecmp(action
, "Minimize"))
534 if (!strcasecmp(action
, "Raise"))
536 if (!strcasecmp(action
, "Lower"))
538 if (!strcasecmp(action
, "Close"))
540 if (!strcasecmp(action
, "Workspace1"))
541 return grabWorkspace1
;
542 if (!strcasecmp(action
, "Workspace2"))
543 return grabWorkspace2
;
544 if (!strcasecmp(action
, "Workspace3"))
545 return grabWorkspace3
;
546 if (!strcasecmp(action
, "Workspace4"))
547 return grabWorkspace4
;
548 if (!strcasecmp(action
, "Workspace5"))
549 return grabWorkspace5
;
550 if (!strcasecmp(action
, "Workspace6"))
551 return grabWorkspace6
;
552 if (!strcasecmp(action
, "Workspace7"))
553 return grabWorkspace7
;
554 if (!strcasecmp(action
, "Workspace8"))
555 return grabWorkspace8
;
556 if (!strcasecmp(action
, "Workspace9"))
557 return grabWorkspace9
;
558 if (!strcasecmp(action
, "Workspace10"))
559 return grabWorkspace10
;
560 if (!strcasecmp(action
, "Workspace11"))
561 return grabWorkspace11
;
562 if (!strcasecmp(action
, "Workspace12"))
563 return grabWorkspace12
;
564 if (!strcasecmp(action
, "NextWorkspace"))
565 return grabNextWorkspace
;
566 if (!strcasecmp(action
, "PrevWorkspace"))
567 return grabPrevWorkspace
;
568 if (!strcasecmp(action
, "UpWorkspace"))
569 return grabUpWorkspace
;
570 if (!strcasecmp(action
, "DownWorkspace"))
571 return grabDownWorkspace
;
572 if (!strcasecmp(action
, "LeftWorkspace"))
573 return grabLeftWorkspace
;
574 if (!strcasecmp(action
, "RightWorkspace"))
575 return grabRightWorkspace
;
576 if (!strcasecmp(action
, "NextWindow"))
577 return grabNextWindow
;
578 if (!strcasecmp(action
, "PrevWindow"))
579 return grabPrevWindow
;
580 if (!strcasecmp(action
, "NextWindowAllWorkspaces"))
581 return grabNextWindowAllWorkspaces
;
582 if (!strcasecmp(action
, "ShadeWindow"))
584 if (!strcasecmp(action
, "MaximizeWindow"))
586 if (!strcasecmp(action
, "StickWindow"))
588 if (!strcasecmp(action
, "ExecCommand"))
590 if (!strcasecmp(action
, "MaximizeVertical"))
592 if (!strcasecmp(action
, "MaximizeHorizontal"))
594 if (!strcasecmp(action
, "NudgeRight"))
595 return grabNudgeRight
;
596 if (!strcasecmp(action
, "NudgeLeft"))
597 return grabNudgeLeft
;
598 if (!strcasecmp(action
, "NudgeUp"))
600 if (!strcasecmp(action
, "NudgeDown"))
601 return grabNudgeDown
;
602 if (!strcasecmp(action
, "BigNudgeRight"))
603 return grabBigNudgeRight
;
604 if (!strcasecmp(action
, "BigNudgeLeft"))
605 return grabBigNudgeLeft
;
606 if (!strcasecmp(action
, "BigNudgeUp"))
607 return grabBigNudgeUp
;
608 if (!strcasecmp(action
, "BigNudgeDown"))
609 return grabBigNudgeDown
;
610 if (!strcasecmp(action
, "HorizontalIncrement"))
612 if (!strcasecmp(action
, "VerticalIncrement"))
614 if (!strcasecmp(action
, "HorizontalDecrement"))
616 if (!strcasecmp(action
, "VerticalDecrement"))
618 if (!strcasecmp(action
, "ToggleDecor"))
619 return grabToggleDecor
;
625 void ToolWindow::execCommand(char *ptrCommand
)
628 extern char **environ
;
633 "bbkeys: Could not fork a process for execCommand.\n");
641 argv
[2] = ptrCommand
;
643 execve("/bin/sh", argv
, environ
);
648 void ToolWindow::setKeygrabs(void)
655 "bbkeys: Could not fork a process for configurator.\n");
661 // Make 'bbconf' automagically fail...
664 char *begin
="keybindings:loadfile=";
665 char *args
= new char[strlen(begin
) + strlen(bbkeys_rcfile
) +1];
666 sprintf(args
, "%s%s", begin
, bbkeys_rcfile
);
668 res
= execlp("bbconf", "bbconf", "--start-plugin", "key bindings",
669 "--args", args
, NULL
);
675 char *begin
="bbkeysconf.pl -rcfile ";
676 char *args
= new char[strlen(begin
) + strlen(bbkeys_rcfile
) +1];
677 sprintf(args
, "%s%s", begin
, bbkeys_rcfile
);
678 res
= execlp("rxvt", "rxvt", "-bg", "black", "-fg", "red",
681 execlp("xterm", "xterm", "-bg", "black", "-fg",
682 "red", "-e", args
, NULL
);
691 if (waitpid(pid, &status, 0) == -1) {
701 void ToolWindow::loadKeygrabs(void)
703 // free up pointers that we get with strdup for execCommand....
704 for (register int i
= 0; i
< grabSet
.instructCount
; i
++) {
705 if (grabSet
.KeyMap
[i
].execCommand
!= NULL
) {
706 free(grabSet
.KeyMap
[i
].execCommand
);
709 memset(&actionList
, 0, sizeof(actionList
));
711 /* re-initialize our grabSet count... */
712 grabSet
.instructCount
= 0;
719 char execCommand
[500];
720 char *KeytograbBegin
;
725 FILE *rc_file
= fopen(bbkeys_rcfile
, "r");
727 fprintf(stderr
, "\nDanger!!! Warning Will Robinson!!!\n"
728 "I can't open your bbkeys rc-file (%s).\n"
729 "Hmm. That means I don't have anything to do. Please run \n"
730 "the bbkeys configurator of your choice (click my keyhole) \n"
731 "to allow me to do stuff for ya. \n"
732 "'Cause otherwise, I just sit here feeling sad....\n\n"
737 memset(line
, '\0', 1024);
739 while (fgets(line
, 1024, rc_file
) && !feof(rc_file
) &&
740 count
< MaxInstructions
) {
741 if (line
[0] != '#' && strstr(line
, "WithModifier")) {
743 memset(Keytograb
, '\0', 80);
744 memset(Modifier
, '\0', 80);
745 memset(action
, '\0', 80);
746 memset(execCommand
, '\0', 500);
748 KeytograbBegin
= strchr(line
, '(');
749 ModifierBegin
= strchr(KeytograbBegin
+ 1, '(');
750 actionBegin
= strchr(ModifierBegin
+ 1, '(');
752 strncat(Keytograb
, KeytograbBegin
+ 1,
753 strcspn(KeytograbBegin
+ 1, ")"));
754 strncpy(Modifier
, ModifierBegin
+ 1,
755 strcspn(ModifierBegin
+ 1, ")"));
756 strncpy(action
, actionBegin
+ 1,
757 strcspn(actionBegin
+ 1, ")"));
759 grabSet
.KeyMap
[count
].keycode
= XKeysymToKeycode(getXDisplay(),
764 char *tmp
= (char *) Modifier
;
765 grabSet
.KeyMap
[count
].modMask
= 0;
766 while ((k
= strchr(tmp
, '+')) != NULL
) {
768 grabSet
.KeyMap
[count
].modMask
|= translateModifier(tmp
);
771 grabSet
.KeyMap
[count
].modMask
|= translateModifier(tmp
);
773 grabSet
.KeyMap
[count
].action
= translateAction(action
);
774 // save off a cross-reference for action->grabSet.KeyMap[index]
775 actionList
[grabSet
.KeyMap
[count
].action
] = count
;
777 /* if we're supposed to having an execCommand and we do have
778 * something to put into it */
779 if (grabSet
.KeyMap
[count
].action
== grabExecute
) {
780 execCmdBegin
= strchr(actionBegin
+ 1, '(');
782 strncpy(execCommand
, execCmdBegin
+ 1,
783 strcspn(execCmdBegin
+ 1, ")"));
784 grabSet
.KeyMap
[count
].execCommand
=
788 grabSet
.KeyMap
[count
].execCommand
= NULL
;
792 fprintf(stdout
, "Keysym ->%d<-, Modifier ->0x%lx<-, "
793 "action ->%d<-, execCommand ->%s<-\n",
794 grabSet
.KeyMap
[count
].keycode
,
795 grabSet
.KeyMap
[count
].modMask
,
796 grabSet
.KeyMap
[count
].action
,
797 grabSet
.KeyMap
[count
].execCommand
);
804 grabSet
.instructCount
= count
;
806 fprintf(stderr
, "loaded ->%d<- instructions.\n", count
);
810 /*****************************************
812 * END OF KEY GRABBING/HANDLING ROUTINES *
814 *****************************************/
816 ToolWindow::ToolWindow(int argc
, char **argv
, struct CMDOPTIONS
*options
):
817 Basewindow(argc
, argv
, options
), TimeoutHandler()
819 timer
= new BTimer(this, this);
820 timer
->setTimeout(100);
821 timer
->fireOnce(True
);
823 if (!(options
->bbkeysrc
)){
824 char *homedir
= getenv("HOME");
825 bbkeys_rcfile
= new char[strlen(homedir
) + 32];
826 sprintf(bbkeys_rcfile
, "%s/.bbkeysrc", homedir
);
828 bbkeys_rcfile
= options
->bbkeysrc
;
833 InitializeModifiers();
839 * Ignore CapsLock in modifiers
841 ValidModMask
= 0xff & ~LockMask
;
843 getOffendingModifiers();
845 * Ignore NumLock and ScrollLock too
847 ValidModMask
&= ~(_NumLockMask
| _ScrollLockMask
);
849 // initialize it so we don't run into problems later
850 grabSet
.instructCount
= 0;
854 resource
= new Resource(this);
855 wminterface
= new WMInterface(this);
856 windowList
= new LinkedList
< WindowList
>;
857 desktopList
= new LinkedList
< DesktopList
>;
859 // initialize variables
860 current_desktop
= NULL
;
862 doingCycling
= False
;
864 // make draw the bbkeys window
868 // pass control to the main loop
872 ToolWindow::~ToolWindow()
874 XUnmapWindow(getXDisplay(), win_frame
);
876 /* destroy pixmaps */
878 getImageControl()->removeImage(pixmap
.frame
);
879 if (pixmap
.pix_title
)
880 getImageControl()->removeImage(pixmap
.pix_title
);
882 getImageControl()->removeImage(pixmap
.pix_back
);
883 if (pixmap
.pix_configBtn
)
884 getImageControl()->removeImage(pixmap
.pix_configBtn
);
885 if (pixmap
.pix_closeBtn
)
886 getImageControl()->removeImage(pixmap
.pix_closeBtn
);
887 if (pixmap
.pix_pressedBtn
)
888 getImageControl()->removeImage(pixmap
.pix_pressedBtn
);
890 /* destroy windows */
891 XDestroyWindow(getXDisplay(), win_frame
);
892 XDestroyWindow(getXDisplay(), win_back
);
893 XDestroyWindow(getXDisplay(), win_title
);
894 XDestroyWindow(getXDisplay(), win_configBtn
);
895 XDestroyWindow(getXDisplay(), win_closeBtn
);
898 if (frameGC
) XFreeGC(getXDisplay(),frameGC
);
899 if (menuGC
) XFreeGC(getXDisplay(),menuGC
);
900 if (menuHiBGGC
) XFreeGC(getXDisplay(),menuHiBGGC
);
901 if (menuHiGC
) XFreeGC(getXDisplay(),menuHiGC
);
902 if (menuFrameGC
) XFreeGC(getXDisplay(),menuFrameGC
);
910 void ToolWindow::reconfigure(void)
912 /* destroy pixmaps */
914 getImageControl()->removeImage(pixmap
.frame
);
915 if (pixmap
.pix_title
)
916 getImageControl()->removeImage(pixmap
.pix_title
);
918 getImageControl()->removeImage(pixmap
.pix_back
);
919 if (pixmap
.pix_configBtn
)
920 getImageControl()->removeImage(pixmap
.pix_configBtn
);
921 if (pixmap
.pix_closeBtn
)
922 getImageControl()->removeImage(pixmap
.pix_closeBtn
);
923 if (pixmap
.pix_pressedBtn
)
924 getImageControl()->removeImage(pixmap
.pix_pressedBtn
);
929 stackMenu
->reconfigure();
931 XClearWindow(getXDisplay(), win_frame
);
932 XClearWindow(getXDisplay(), win_back
);
936 void ToolWindow::MakeWindow(bool reconfigure
)
938 XSetWindowAttributes attrib
;
940 XClassHint classhints
;
941 XTextProperty windowname
;
943 unsigned long create_mask
= CWBackPixmap
| CWBorderPixel
|
944 CWOverrideRedirect
| CWCursor
| CWEventMask
;
946 // geometry for our windows...................................
948 geom_title
.height
= resource
->label
.font
->ascent
+
949 resource
->label
.font
->descent
+ 2;
950 if (geom_title
.height
< 20 && (miniMe
|| tinyMe
))
951 geom_title
.height
= 20;
952 geom_title
.width
= XTextWidth(resource
->label
.font
, "bbkeys",
953 strlen("bbkeys")) + (geom_title
.height
+
957 geom_back
.width
= geom_title
.width
+ 4;
960 geom_closeBtn
.height
= geom_title
.height
* 7 / 10;
961 geom_closeBtn
.width
= geom_closeBtn
.height
;
965 geom_back
.height
= geom_title
.height
+ 2;
966 geom_closeBtn
.y
= 80; /* put it out of sight. */
967 geom_closeBtn
.x
= 80;
968 geom_configBtn
.height
= geom_title
.height
- 1;
969 geom_configBtn
.width
= geom_configBtn
.height
;
970 geom_configBtn
.x
= geom_title
.width
- geom_configBtn
.width
;
971 geom_configBtn
.y
= geom_title
.y
;
975 geom_title
.height
= 22;
976 geom_title
.width
= 22;
979 geom_back
.width
= 22;
980 geom_back
.height
= 22;
981 geom_closeBtn
.y
= 80; /* put it out of sight. */
982 geom_closeBtn
.x
= 80;
983 geom_configBtn
.height
= 20;
984 geom_configBtn
.width
= geom_configBtn
.height
;
985 geom_configBtn
.x
= 1;
986 geom_configBtn
.y
= 1;
990 geom_back
.height
= 3 * (geom_title
.height
) + 6;
991 geom_closeBtn
.x
= geom_title
.width
- geom_closeBtn
.width
- 1;
992 geom_closeBtn
.y
= geom_title
.y
+
993 ((geom_title
.height
- geom_closeBtn
.height
) / 2);
994 geom_configBtn
.height
= (geom_title
.height
* 2);
995 geom_configBtn
.width
= geom_title
.width
- 4;
996 geom_configBtn
.x
= geom_title
.x
+ 2;
997 geom_configBtn
.y
= geom_title
.height
+ geom_title
.y
+ 2;
1001 frame
.height
= geom_back
.height
;
1002 frame
.width
= geom_back
.width
;
1003 frame
.x
= resource
->position
.x
;
1004 frame
.y
= resource
->position
.y
;
1006 // end geometry for our windows...................................
1008 if (resource
->position
.mask
& XNegative
) {
1009 frame
.x
= getCurrentScreenInfo()->getWidth() +
1010 resource
->position
.x
- frame
.width
;
1013 if (resource
->position
.mask
& YNegative
) {
1014 frame
.y
= getCurrentScreenInfo()->getHeight() +
1015 resource
->position
.y
- frame
.height
;
1020 attrib
.override_redirect
= False
;
1021 wmhints
.initial_state
= WithdrawnState
;
1022 } else if (iconic
) {
1023 attrib
.override_redirect
= False
;
1024 wmhints
.initial_state
= IconicState
;
1026 attrib
.override_redirect
= False
;
1027 wmhints
.initial_state
= NormalState
;
1030 attrib
.background_pixmap
= ParentRelative
;
1033 getImageControl()->renderImage(frame
.width
, frame
.height
,
1034 &resource
->frame
.texture
);
1037 getImageControl()->renderImage(geom_back
.width
,
1039 &resource
->frame
.texture
);
1041 getImageControl()->renderImage(geom_title
.width
, geom_title
.height
,
1042 &resource
->label
.texture
);
1044 pixmap
.pix_configBtn
=
1045 getImageControl()->renderImage(geom_configBtn
.width
,
1046 geom_configBtn
.height
,
1047 &resource
->button
.texture
);
1049 pixmap
.pix_closeBtn
=
1050 getImageControl()->renderImage(geom_closeBtn
.width
,
1051 geom_closeBtn
.height
,
1052 &resource
->button
.texture
);
1053 pixmap
.pix_pressedBtn
=
1054 getImageControl()->renderImage(geom_configBtn
.width
,
1055 geom_configBtn
.height
,
1056 &resource
->button
.texture_pressed
);
1058 attrib
.cursor
= getSessionCursor();
1060 ButtonPressMask
| ButtonReleaseMask
| ExposureMask
|
1061 FocusChangeMask
| KeyPressMask
| KeyReleaseMask
| StructureNotifyMask
|
1062 SubstructureRedirectMask
;
1065 win_frame
= XCreateWindow(getXDisplay(),
1066 getCurrentScreenInfo()->getRootWindow(),
1067 frame
.x
, frame
.y
, frame
.width
,
1069 getCurrentScreenInfo()->getDepth(),
1071 getCurrentScreenInfo()->getVisual(),
1072 create_mask
, &attrib
);
1073 win_back
= XCreateWindow(getXDisplay(),
1078 geom_back
.height
, 0,
1079 getCurrentScreenInfo
1080 ()->getDepth(), InputOutput
,
1081 getCurrentScreenInfo
1082 ()->getVisual(), create_mask
, &attrib
);
1084 XCreateWindow(getXDisplay(), win_frame
, geom_title
.x
,
1085 geom_title
.y
, geom_title
.width
,
1086 geom_title
.height
, 0,
1087 getCurrentScreenInfo()->getDepth(), InputOutput
,
1088 getCurrentScreenInfo()->getVisual(), create_mask
,
1091 XCreateWindow(getXDisplay(), win_frame
, geom_configBtn
.x
,
1092 geom_configBtn
.y
, geom_configBtn
.width
,
1093 geom_configBtn
.height
, 0,
1094 getCurrentScreenInfo()->getDepth(), InputOutput
,
1095 getCurrentScreenInfo()->getVisual(), create_mask
,
1098 XCreateWindow(getXDisplay(), win_frame
, geom_closeBtn
.x
,
1099 geom_closeBtn
.y
, geom_closeBtn
.width
,
1100 geom_closeBtn
.height
, 0,
1101 getCurrentScreenInfo()->getDepth(), InputOutput
,
1102 getCurrentScreenInfo()->getVisual(), create_mask
,
1104 } else if (!withdrawn
) {
1105 XMoveResizeWindow(getXDisplay(), win_frame
, frame
.x
, frame
.y
,
1106 frame
.width
, frame
.height
);
1107 XMoveResizeWindow(getXDisplay(), win_back
,
1108 geom_back
.x
, geom_back
.y
,
1109 geom_back
.width
, geom_back
.height
);
1110 XMoveResizeWindow(getXDisplay(), win_title
, geom_title
.x
,
1111 geom_title
.y
, geom_title
.width
,
1113 XMoveResizeWindow(getXDisplay(), win_configBtn
, geom_configBtn
.x
,
1114 geom_configBtn
.y
, geom_configBtn
.width
,
1115 geom_configBtn
.height
);
1116 XMoveResizeWindow(getXDisplay(), win_closeBtn
, geom_closeBtn
.x
,
1117 geom_closeBtn
.y
, geom_closeBtn
.width
,
1118 geom_closeBtn
.height
);
1121 XResizeWindow(getXDisplay(), win_frame
, frame
.width
, frame
.height
);
1122 XResizeWindow(getXDisplay(), win_back
,
1123 geom_back
.width
, geom_back
.height
);
1124 XResizeWindow(getXDisplay(), win_title
, geom_title
.width
,
1126 XMoveResizeWindow(getXDisplay(), win_configBtn
, geom_configBtn
.x
,
1127 geom_configBtn
.y
, geom_configBtn
.width
,
1128 geom_configBtn
.height
);
1129 XMoveResizeWindow(getXDisplay(), win_closeBtn
, geom_closeBtn
.x
,
1130 geom_closeBtn
.y
, geom_closeBtn
.width
,
1131 geom_closeBtn
.height
);
1134 char *name
= BBTOOL
;
1135 XSizeHints sizehints
;
1137 wmhints
.flags
= StateHint
;
1139 classhints
.res_name
= BBTOOL
;
1140 classhints
.res_class
= "bbtools";
1142 sizehints
.x
= frame
.x
; //getResource()->position.x;
1143 sizehints
.y
= frame
.y
; //getResource()->position.y;
1145 sizehints
.max_width
= sizehints
.min_width
= frame
.width
;
1146 sizehints
.max_height
= sizehints
.min_height
= frame
.height
;
1147 sizehints
.flags
= USPosition
| PMinSize
| PMaxSize
;
1149 XStringListToTextProperty(&name
, 1, &windowname
);
1150 XSetWMProperties(getXDisplay(), win_frame
, &windowname
, NULL
, getArgv(),
1151 getArgc(), &sizehints
, &wmhints
, &classhints
);
1153 // free up allocated memory in XStringListToTextProperty
1154 XFree(windowname
.value
);
1158 wmproto
[0] = wm_delete_window
;
1159 wmproto
[1] = getBlackboxStructureMessagesAtom();
1160 XSetWMProtocols(getXDisplay(), win_frame
, wmproto
, 2);
1163 if (!decorated
&& !withdrawn
) {
1164 BlackboxHints net_hints
;
1165 net_hints
.decoration
= DecorNone
;
1166 net_hints
.attrib
= AttribOmnipresent
;
1167 net_hints
.flags
= AttribDecoration
| AttribOmnipresent
;
1168 XChangeProperty(getXDisplay(), win_frame
, getBlackboxHintsAtom(),
1169 getBlackboxHintsAtom(), 32, PropModeReplace
,
1170 (unsigned char *) &net_hints
,
1171 PropBlackboxHintsElements
);
1175 XSetWindowBackgroundPixmap(getXDisplay(), win_frame
, pixmap
.frame
);
1178 XSetWindowBackgroundPixmap(getXDisplay(), win_title
, pixmap
.pix_title
);
1179 XSetWindowBackgroundPixmap(getXDisplay(), win_back
, pixmap
.pix_back
);
1180 XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn
,
1181 pixmap
.pix_configBtn
);
1182 XSetWindowBackgroundPixmap(getXDisplay(), win_closeBtn
,
1183 pixmap
.pix_closeBtn
);
1187 gcv
.font
= resource
->label
.font
->fid
;
1188 gcv
.foreground
= resource
->label
.textColor
.getPixel();
1190 XCreateGC(getXDisplay(), win_frame
, GCFont
| GCForeground
, &gcv
);
1192 gcv
.font
= resource
->menu
.font
->fid
;
1193 gcv
.foreground
= resource
->menu
.texture
.getColor()->getPixel();
1194 menuGC
= XCreateGC(getXDisplay(), win_frame
,GCFont
|GCForeground
, &gcv
);
1196 gcv
.foreground
= resource
->menu
.highlightColor
.getPixel();
1197 gcv
.arc_mode
= ArcChord
;
1198 gcv
.fill_style
= FillSolid
;
1199 menuHiBGGC
= XCreateGC(getXDisplay(), win_frame
,GCForeground
|
1200 GCFillStyle
|GCArcMode
, &gcv
);
1202 gcv
.foreground
= resource
->menu
.hiTextColor
.getPixel();
1203 menuHiGC
= XCreateGC(getXDisplay(), win_frame
, GCFont
|GCForeground
, &gcv
);
1205 gcv
.foreground
= resource
->menu
.textColor
.getPixel();
1206 menuFrameGC
= XCreateGC(getXDisplay(), win_frame
,GCFont
|GCForeground
, &gcv
);
1208 stackMenu
= new Stackmenu(this);
1209 stackMenu
->update();
1211 gcv
.font
= resource
->label
.font
->fid
;
1212 gcv
.foreground
= resource
->label
.textColor
.getPixel();
1213 XChangeGC(getXDisplay(), frameGC
, GCFont
| GCForeground
, &gcv
);
1215 gcv
.font
= resource
->menu
.font
->fid
;
1216 gcv
.foreground
= resource
->menu
.texture
.getColor()->getPixel();
1217 XChangeGC(getXDisplay(), menuGC
, GCFont
| GCForeground
, &gcv
);
1219 gcv
.foreground
= resource
->menu
.highlightColor
.getPixel();
1220 XChangeGC(getXDisplay(), menuHiBGGC
, GCFont
| GCForeground
, &gcv
);
1222 gcv
.foreground
= resource
->menu
.hiTextColor
.getPixel();
1223 XChangeGC(getXDisplay(), menuHiGC
, GCFont
| GCForeground
, &gcv
);
1225 gcv
.foreground
= resource
->menu
.textColor
.getPixel();
1226 XChangeGC(getXDisplay(), menuFrameGC
, GCFont
| GCForeground
, &gcv
);
1232 XClearWindow(getXDisplay(), win_frame
);
1233 XMapWindow(getXDisplay(), win_frame
);
1234 XMapSubwindows(getXDisplay(), win_frame
);
1235 XSetIconName(getXDisplay(), win_frame
, "bbkeys");
1239 void ToolWindow::Redraw()
1241 XClearWindow(getXDisplay(), win_title
);
1242 XClearWindow(getXDisplay(), win_configBtn
);
1243 XClearWindow(getXDisplay(), win_closeBtn
);
1245 char *title
= "bbkeys";
1246 XDrawString(getXDisplay(), win_title
, frameGC
, geom_title
.x
- 1,
1247 (geom_title
.height
+ resource
->label
.font
->ascent
-
1248 resource
->label
.font
->descent
) / 2, title
, strlen(title
));
1252 if (miniMe
|| tinyMe
) {
1253 pts
[0].x
= (geom_configBtn
.width
/ 2);
1254 pts
[0].y
= (geom_configBtn
.height
/ 2) - 2;
1255 pts
[1].x
= -(geom_configBtn
.width
/ 4);
1256 pts
[1].y
= (geom_configBtn
.height
- pts
[0].y
) - 1;
1257 pts
[2].x
= (geom_configBtn
.width
/ 2);
1260 XFillPolygon(getXDisplay(), win_configBtn
, frameGC
, pts
, 3,
1261 Convex
, CoordModePrevious
);
1262 XFillArc(getXDisplay(), win_configBtn
, frameGC
,
1263 geom_configBtn
.width
/ 2 - geom_configBtn
.width
/ 4, 1, // x, y
1264 geom_configBtn
.width
/ 2, geom_configBtn
.height
/ 2, //width,height
1267 pts
[0].x
= (geom_configBtn
.width
/ 2);
1268 pts
[0].y
= (geom_configBtn
.height
/ 2) - 2;
1269 pts
[1].x
= -(geom_configBtn
.width
/ 4);
1270 pts
[1].y
= (geom_configBtn
.height
- pts
[0].y
) - 2;
1271 pts
[2].x
= (geom_configBtn
.width
/ 2);
1274 XFillPolygon(getXDisplay(), win_configBtn
, frameGC
, pts
, 3,
1275 Convex
, CoordModePrevious
);
1276 XFillArc(getXDisplay(), win_configBtn
, frameGC
,
1277 geom_configBtn
.width
/ 2 - geom_configBtn
.width
/ 4, 1, // x, y
1278 geom_configBtn
.width
/ 2, geom_configBtn
.height
* 5 / 8, //width,height
1282 /* Our little close button (drawn twice for a nice thickness) */
1283 XDrawLine(getXDisplay(), win_closeBtn
, frameGC
, 1, 1,
1284 geom_closeBtn
.width
- 2, geom_closeBtn
.height
- 1);
1285 XDrawLine(getXDisplay(), win_closeBtn
, frameGC
, 1,
1286 geom_closeBtn
.height
- 1, geom_closeBtn
.width
- 2, 1);
1288 XDrawLine(getXDisplay(), win_closeBtn
, frameGC
, 2, 1,
1289 geom_closeBtn
.width
- 1, geom_closeBtn
.height
- 1);
1290 XDrawLine(getXDisplay(), win_closeBtn
, frameGC
, 2,
1291 geom_closeBtn
.height
- 1, geom_closeBtn
.width
- 1, 1);
1295 unsigned int ToolWindow::KeycodeToModmask(unsigned int code
)
1297 switch (XKeycodeToKeysym(getXDisplay(), code
, 0)) {
1312 return AltMask
? AltMask
: MetaMask
;
1329 case XK_Scroll_Lock
:
1330 return ScrollLockMask
;
1332 return (unsigned int)-1;
1335 void ToolWindow::process_event(XEvent
* e
)
1338 case PropertyNotify
:
1339 windowAttributeChange(e
->xproperty
.window
);
1342 case VisibilityNotify
:
1343 // **** This will need to change to a better method of keeping the **** //
1344 // **** menu on top when blackbox provides another way! **** //
1345 if (e
->xvisibility
.window
== stackMenu
->getWindowID())
1346 if (e
->xvisibility
.state
!= VisibilityUnobscured
)
1347 XRaiseWindow(getXDisplay(), stackMenu
->getWindowID());
1351 // if stacked cycling is going on..
1353 unsigned int mask
= KeycodeToModmask(e
->xkey
.keycode
);
1354 unsigned int state
= e
->xkey
.state
;
1356 // get the index for grabSet.KeyMay's prev/next entries, but make
1357 // sure we're not just getting 0 because we don't have keybindings
1358 // for one of them--also, we can't use > 0 as a test for next/prev
1359 // because 0 might very well be the valid index for those bindings
1360 int i
= actionList
[grabNextWindow
];
1361 int next
= grabSet
.KeyMap
[i
].action
== grabNextWindow
? i
: -1;
1362 int j
= actionList
[grabNextWindowAllWorkspaces
];
1363 int nextAll
= grabSet
.KeyMap
[j
].action
== grabNextWindowAllWorkspaces
? j
: -1;
1364 int k
= actionList
[grabPrevWindow
];
1365 int prev
= grabSet
.KeyMap
[k
].action
== grabPrevWindow
? k
: -1;
1367 // if the key released was the last modifier being held
1368 // and being a member of the nextMask or PrevMask, then select
1369 // the item in the menu that is currently focued.
1370 if (next
> -1 && ((state
& grabSet
.KeyMap
[next
].modMask
) == mask
))
1371 stackMenu
->selectFocused(True
);
1372 else if (nextAll
> -1 && ((state
& grabSet
.KeyMap
[nextAll
].modMask
) == mask
))
1373 stackMenu
->selectFocused(True
);
1374 else if (prev
> -1 && ((state
& grabSet
.KeyMap
[prev
].modMask
) == mask
))
1375 stackMenu
->selectFocused(True
);
1384 Window fw_root
, fw_child
;
1386 unsigned int fw_w
, fw_h
, fw_b
, fw_d
;
1388 /* Need to take out this next bit when nyz has 0.60.0 ready, as
1389 we'll then get our focus_window in a ClientMessage */
1390 int revert_to
= RevertToPointerRoot
;
1391 if (!focus_window
) {
1392 XGetInputFocus(getXDisplay(), &focus_window
, &revert_to
);
1395 /* end temporary focus_window fix */
1397 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1398 XGetGeometry(getXDisplay(), focus_window
, &fw_root
, &fw_x
,
1399 &fw_y
, &fw_w
, &fw_h
, &fw_b
, &fw_d
);
1400 XTranslateCoordinates(getXDisplay(), focus_window
, fw_root
,
1401 fw_x
, fw_y
, &fw_x
, &fw_y
, &fw_child
);
1404 // if our user wants to grab his keystrokes, even though one
1405 // or more of the Lock-Modifiers are pressed, alter the mask
1408 // to make this possible....
1410 if (!honor_modifiers
) {
1411 e
->xkey
.state
&= ~_NumLockMask
& ~_ScrollLockMask
& ~LockMask
;
1414 for (i
= 0; i
< grabSet
.instructCount
; i
++) {
1415 if ((e
->xkey
.keycode
== grabSet
.KeyMap
[i
].keycode
) &&
1416 (e
->xkey
.state
== grabSet
.KeyMap
[i
].modMask
)) {
1423 if (e
->xkey
.keycode
== XKeysymToKeycode(getXDisplay(), XK_Escape
)) {
1425 // reset focus to the window we were focused on before window
1427 wminterface
->setWindowFocus(focus_window
);
1428 } else if (e
->xkey
.keycode
== XKeysymToKeycode(getXDisplay(), XK_Return
))
1429 stackMenu
->selectFocused(True
);
1431 stackMenu
->key_press(grabSet
.KeyMap
[grabInt
].action
);
1432 } else if (grabInt
> -1) {
1434 /* play with colors for nyz =:) */
1435 XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn
,
1436 pixmap
.pix_pressedBtn
);
1439 switch (grabSet
.KeyMap
[grabInt
].action
) {
1441 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1442 XIconifyWindow(getXDisplay(), focus_window
, 0);
1447 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1448 XRaiseWindow(getXDisplay(), focus_window
);
1453 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1454 XLowerWindow(getXDisplay(), focus_window
);
1462 ce
.xclient
.type
= ClientMessage
;
1463 ce
.xclient
.message_type
= getWMProtocolsAtom();
1464 ce
.xclient
.display
= getXDisplay();
1465 ce
.xclient
.window
= focus_window
;
1466 ce
.xclient
.format
= 32;
1467 ce
.xclient
.data
.l
[0] = getWMDeleteAtom();
1468 ce
.xclient
.data
.l
[1] = CurrentTime
;
1469 ce
.xclient
.data
.l
[2] = ce
.xclient
.data
.l
[3] =
1470 ce
.xclient
.data
.l
[4] = 0l;
1471 XSendEvent(getXDisplay(), focus_window
, False
, NoEventMask
, &ce
);
1474 case grabWorkspace1
:
1475 wminterface
->changeDesktop(0);
1478 case grabWorkspace2
:
1479 wminterface
->changeDesktop(1);
1482 case grabWorkspace3
:
1483 wminterface
->changeDesktop(2);
1486 case grabWorkspace4
:
1487 wminterface
->changeDesktop(3);
1490 case grabWorkspace5
:
1491 wminterface
->changeDesktop(4);
1494 case grabWorkspace6
:
1495 wminterface
->changeDesktop(5);
1498 case grabWorkspace7
:
1499 wminterface
->changeDesktop(6);
1502 case grabWorkspace8
:
1503 wminterface
->changeDesktop(7);
1506 case grabWorkspace9
:
1507 wminterface
->changeDesktop(8);
1510 case grabWorkspace10
:
1511 wminterface
->changeDesktop(9);
1514 case grabWorkspace11
:
1515 wminterface
->changeDesktop(10);
1518 case grabWorkspace12
:
1519 wminterface
->changeDesktop(11);
1522 case grabNextWorkspace
:
1523 if (current_desktop
->number
< (desktop_count
-1))
1524 wminterface
->changeDesktop(current_desktop
->number
+ 1);
1526 wminterface
->changeDesktop(0);
1529 case grabPrevWorkspace
:
1530 if (current_desktop
->number
> 0)
1531 wminterface
->changeDesktop(current_desktop
->number
- 1);
1533 wminterface
->changeDesktop(desktop_count
- 1);
1536 case grabUpWorkspace
:
1537 if (resource
->columns
> 1) { //ie columns given
1538 if (getCurrentDesktopNr()-resource
->columns
<0) {
1539 if (getDesktopCount()-1-(getDesktopCount()-1)%resource
->columns
+
1540 getCurrentDesktopNr()%resource
->columns
> getDesktopCount() - 1) {
1542 wminterface
->changeDesktop(getDesktopCount() - 1 -
1543 (getDesktopCount() - 1)%resource
->columns
+
1544 getCurrentDesktopNr()%resource
->columns
-resource
->columns
);
1547 wminterface
->changeDesktop(getDesktopCount() - 1 -
1548 (getDesktopCount() - 1)%resource
->columns
+
1549 getCurrentDesktopNr()%resource
->columns
);
1552 wminterface
->changeDesktop(getCurrentDesktopNr() - resource
->columns
);
1554 } else if (resource
->rows
> 1) { //ie rows given
1555 if (getCurrentDesktopNr()%resource
->rows
==0) {// if row=1
1556 if (getCurrentDesktopNr() + resource
->rows
> getDesktopCount())
1557 //incomplete last col?
1558 wminterface
->changeDesktop(getDesktopCount() - 1); //last desktop
1560 wminterface
->changeDesktop(getCurrentDesktopNr() +resource
->rows
- 1);
1563 wminterface
->changeDesktop(getCurrentDesktopNr() - 1);
1564 } else {} //no arrangement -> insert fallback solution here
1568 case grabDownWorkspace
:
1569 if (resource
->columns
> 1) { //ie columns given
1570 if (getCurrentDesktopNr() + resource
->columns
> getDesktopCount() - 1)
1571 wminterface
->changeDesktop(getCurrentDesktopNr()%resource
->columns
);
1573 wminterface
->changeDesktop(getCurrentDesktopNr() +resource
->columns
);
1574 } else if (resource
->rows
> 1) { //ie rows given
1575 if (getCurrentDesktopNr()%resource
->rows
+ 1 == resource
->rows
||
1576 getCurrentDesktopNr() + 1 == getDesktopCount()) {
1577 //last row or last in incomplete col
1578 wminterface
->changeDesktop(getCurrentDesktopNr() -
1579 getCurrentDesktopNr()%resource
->rows
);
1582 wminterface
->changeDesktop(getCurrentDesktopNr() + 1);
1583 } else {} //no arrangement -> fallback solution
1588 case grabLeftWorkspace
:
1589 if (resource
->columns
> 1) { //ie columns given
1590 if (getCurrentDesktopNr()%resource
->columns
==0) {
1591 if (getCurrentDesktopNr() + resource
->columns
> getDesktopCount())
1592 wminterface
->changeDesktop(getDesktopCount() -1);
1594 wminterface
->changeDesktop(getCurrentDesktopNr() + resource
->columns
- 1);
1596 wminterface
->changeDesktop(getCurrentDesktopNr() - 1);
1597 } else if (resource
->rows
> 1) { //ie rows given
1598 if (getCurrentDesktopNr() - resource
->rows
<0) {// first col
1599 if (getDesktopCount() - 1 - (getDesktopCount()-1)%resource
->rows
+
1600 getCurrentDesktopNr()%resource
->rows
> getDesktopCount() - 1)
1602 wminterface
->changeDesktop(getDesktopCount() - 1 -
1603 (getDesktopCount() - 1)%resource
->rows
+
1604 getCurrentDesktopNr()%resource
->rows
- resource
->rows
);
1606 wminterface
->changeDesktop(getDesktopCount() - 1 -
1607 (getDesktopCount() - 1)%resource
->rows
+
1608 getCurrentDesktopNr()%resource
->rows
);
1610 wminterface
->changeDesktop(getCurrentDesktopNr() - resource
->rows
);
1611 } else {} //no arrangement -> fallback solution
1616 case grabRightWorkspace
:
1617 if (resource
->columns
> 1) { //ie columns given
1618 if (getCurrentDesktopNr()%resource
->columns
+ 1 == resource
->columns
||
1619 getCurrentDesktopNr() + 1 == getDesktopCount())
1620 wminterface
->changeDesktop(getCurrentDesktopNr() -
1621 getCurrentDesktopNr()%resource
->columns
);
1623 wminterface
->changeDesktop(getCurrentDesktopNr() + 1);
1624 } else if (resource
->rows
> 1) { //ie rows given
1625 if (getCurrentDesktopNr() + resource
->rows
> getDesktopCount() - 1)
1627 wminterface
->changeDesktop(getCurrentDesktopNr()%resource
->rows
);
1630 wminterface
->changeDesktop(getCurrentDesktopNr() + resource
->rows
);
1631 } else {} //no arrangement -> fallback solution
1635 case grabNextWindow
:
1636 showAllWorkspaces
=false;
1637 cycleWindowFocus(True
);
1640 case grabNextWindowAllWorkspaces
:
1641 showAllWorkspaces
=true;
1642 cycleWindowFocus(True
);
1645 case grabPrevWindow
:
1646 cycleWindowFocus(False
);
1650 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1651 wminterface
->shadeWindow(focus_window
);
1656 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1657 wminterface
->stickWindow(focus_window
);
1662 execCommand(grabSet
.KeyMap
[grabInt
].execCommand
);
1666 if (focus_window
&& focus_window
!= (int)PointerRoot
)
1667 wminterface
->maximizeWindow(focus_window
, True
, True
);
1671 if (focus_window
&& focus_window
!= (int)PointerRoot
)
1672 wminterface
->maximizeWindow(focus_window
, False
, True
);
1676 if (focus_window
&& focus_window
!= (int)PointerRoot
)
1677 wminterface
->maximizeWindow(focus_window
, True
, False
);
1680 case grabNudgeRight
:
1681 if (focus_window
&& focus_window
!= (int)PointerRoot
)
1682 XMoveWindow(getXDisplay(), focus_window
, fw_x
+ 1, fw_y
);
1686 if (focus_window
&& focus_window
!= (int)PointerRoot
)
1687 XMoveWindow(getXDisplay(), focus_window
, fw_x
- 1, fw_y
);
1691 if (focus_window
&& focus_window
!= (int)PointerRoot
)
1692 XMoveWindow(getXDisplay(), focus_window
, fw_x
, fw_y
- 1);
1696 if (focus_window
&& focus_window
!= (int)PointerRoot
)
1697 XMoveWindow(getXDisplay(), focus_window
, fw_x
, fw_y
+ 1);
1700 case grabBigNudgeRight
:
1701 if (focus_window
&& focus_window
!= (int)PointerRoot
)
1702 XMoveWindow(getXDisplay(), focus_window
, fw_x
+ 10, fw_y
);
1705 case grabBigNudgeLeft
:
1706 if (focus_window
&& focus_window
!= (int)PointerRoot
)
1707 XMoveWindow(getXDisplay(), focus_window
, fw_x
- 10, fw_y
);
1710 case grabBigNudgeUp
:
1711 if (focus_window
&& focus_window
!= (int)PointerRoot
)
1712 XMoveWindow(getXDisplay(), focus_window
, fw_x
, fw_y
- 10);
1715 case grabBigNudgeDown
:
1716 if (focus_window
&& focus_window
!= (int)PointerRoot
)
1717 XMoveWindow(getXDisplay(), focus_window
, fw_x
, fw_y
+ 10);
1721 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1722 XWindowAttributes foo
;
1723 XGetWindowAttributes(getXDisplay(), focus_window
, &foo
);
1724 XResizeWindow(getXDisplay(), focus_window
,
1725 foo
.width
+ 10, foo
.height
);
1730 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1731 XWindowAttributes foo
;
1732 XGetWindowAttributes(getXDisplay(), focus_window
, &foo
);
1733 XResizeWindow(getXDisplay(), focus_window
,
1734 foo
.width
, foo
.height
+ 10);
1739 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1740 XWindowAttributes foo
;
1741 XGetWindowAttributes(getXDisplay(), focus_window
, &foo
);
1744 XResizeWindow(getXDisplay(), focus_window
,
1745 foo
.width
- 10, foo
.height
);
1750 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1751 XWindowAttributes foo
;
1752 XGetWindowAttributes(getXDisplay(), focus_window
, &foo
);
1753 if (foo
.height
< 11)
1755 XResizeWindow(getXDisplay(), focus_window
,
1756 foo
.width
, foo
.height
- 10);
1760 case grabToggleDecor
:
1761 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1762 wminterface
->decorateToggleWindow(focus_window
);
1772 if ((unsigned) e
->xclient
.data
.l
[0] == wm_delete_window
)
1774 wminterface
->handleNETEvents(*e
);
1778 if (!e
->xexpose
.count
)
1783 if (e
->xbutton
.button
== LEFT_BUTTON
1784 || e
->xbutton
.button
== RIGHT_BUTTON
) {
1785 if (e
->xbutton
.window
== win_configBtn
) {
1786 XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn
,
1787 pixmap
.pix_pressedBtn
);
1789 } else if (e
->xbutton
.window
== win_closeBtn
) {
1790 XSetWindowBackgroundPixmap(getXDisplay(), win_closeBtn
,
1791 pixmap
.pix_pressedBtn
);
1793 } else if (e
->xbutton
.window
== win_title
) {
1795 XRaiseWindow(getXDisplay(), win_frame
);
1798 } else if (e
->xbutton
.button
== MIDDLE_BUTTON
) {
1800 XLowerWindow(getXDisplay(), win_frame
);
1806 if (e
->xbutton
.button
== LEFT_BUTTON
1807 || e
->xbutton
.button
== RIGHT_BUTTON
) {
1808 if (e
->xbutton
.window
== win_configBtn
) {
1809 if ((e
->xbutton
.x
> 0)
1810 && (e
->xbutton
.x
< geom_configBtn
.width
)
1811 && (e
->xbutton
.y
> 0)
1812 && (e
->xbutton
.y
< geom_configBtn
.height
)) {
1813 if (grabSet
.instructCount
> 0) {
1814 XUngrabKey(getXDisplay(), AnyKey
, AnyModifier
,
1815 getScreenInfo(0)->getRootWindow());
1816 XSync(getXDisplay(), False
);
1820 // discard all XEvents (was causing us to go bananas on the
1821 // user before, since we were executing all keygrabs at once
1822 // that the user did when the configuration app was running)
1823 // *cough* undocumented feature *cough*
1827 while (XPending(getXDisplay())) {
1828 XNextEvent(getXDisplay(), &event
);
1831 // carry on then, little soldier
1838 XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn
,
1839 pixmap
.pix_configBtn
);
1841 } else if (e
->xbutton
.window
== win_closeBtn
) {
1842 if ((e
->xbutton
.x
> 0)
1843 && (e
->xbutton
.x
< geom_closeBtn
.width
)
1844 && (e
->xbutton
.y
> 0)
1845 && (e
->xbutton
.y
< geom_closeBtn
.height
)) {
1846 if (e
->xbutton
.button
== LEFT_BUTTON
) {
1848 } else if (e
->xbutton
.button
== RIGHT_BUTTON
) {
1850 XUnmapWindow(getXDisplay(), win_frame
);
1855 wmhints
.initial_state
= IconicState
;
1856 wmhints
.flags
= StateHint
;
1857 XSetWMHints(getXDisplay(), win_frame
, &wmhints
);
1858 XMapWindow(getXDisplay(), win_frame
);
1860 // this should work but doesn't seem to. *shrug*
1863 XIconifyWindow(getXDisplay(), win_frame
, 0);
1867 XSetWindowBackgroundPixmap(getXDisplay(), win_closeBtn
,
1868 pixmap
.pix_configBtn
);
1874 case ConfigureNotify
:
1875 if ((e
->xconfigure
.window
== win_frame
) && e
->xconfigure
.send_event
) {
1879 int parent_x
, parent_y
;
1881 unsigned int parent_width
, parent_height
, parent_border_width
;
1882 unsigned int parent_depth
;
1885 XGetGeometry(getXDisplay(), e
->xconfigure
.above
,
1886 &parent_root
, &parent_x
, &parent_y
,
1887 &parent_width
, &parent_height
,
1888 &parent_border_width
, &parent_depth
);
1889 frame
.x
= e
->xconfigure
.x
+ parent_x
;
1890 frame
.y
= e
->xconfigure
.y
+ parent_y
;
1897 void ToolWindow::timeout(void)
1899 XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn
,
1900 pixmap
.pix_configBtn
);
1904 /*--------------------------------*/
1906 /*- window modifying functions -*/
1908 /*--------------------------------*/
1910 void ToolWindow::raiseWindow(Window win
)
1914 void ToolWindow::lowerWindow(Window win
)
1918 /*---------------------------------------*/
1920 /*- desktop list management functions -*/
1922 /*---------------------------------------*/
1924 void ToolWindow::addDesktop(void)
1926 DesktopList
*tmp
= new DesktopList
;
1928 // get the highest in the list
1930 LinkedListIterator
<DesktopList
> it(desktopList
);
1931 for (; it
.current(); it
++)
1932 if (it
.current()->number
> highest
) {
1933 highest
= it
.current()->number
;
1936 tmp
->number
= highest
+ 1;
1938 desktopList
->insert(tmp
, -1); // add to the end of the list
1942 // add sticky windows to this desktop
1943 LinkedListIterator
<WindowList
> it_win(windowList
);
1944 for (; it_win
.current(); it_win
++)
1945 // only look for sticky windows on desktop 0, this will give us one
1946 // copy of each sticky window
1947 if ((it_win
.current()->desktop
== 0) && (it_win
.current()->sticky
)) {
1948 WindowList
*win
= new WindowList
;
1949 win
->win
= it_win
.current()->win
;
1950 win
->iconic
= it_win
.current()->iconic
;
1951 win
->shaded
= False
;
1953 win
->desktop
= tmp
->number
;
1954 windowList
->insert(win
, -1); // add to the end of the list
1958 void ToolWindow::removeDesktop(int desktop
)
1960 LinkedListIterator
<DesktopList
> it(desktopList
);
1961 LinkedListIterator
<WindowList
> it_win(windowList
);
1963 // remove sticky windows from this desktop
1964 for (; it_win
.current(); it_win
++)
1965 if ((it_win
.current()->desktop
== desktop
)
1966 && (it_win
.current()->sticky
))
1967 windowList
->remove(it_win
.current()); // remove just this window
1968 // removeWindow() would remove all
1969 // of the sticky windows.
1971 // remove the desktop from the linked list
1972 for (; it
.current(); it
++)
1973 if (it
.current()->number
== desktop
) {
1974 desktopList
->remove(it
.current());
1980 // shift the rest to fill in the hole if not the last desktop was rm'd
1986 for (; it
.current(); it
++)
1987 if (it
.current()->number
== check
) {
1993 // check is on the new hole, or desktop_count if there is no hole
1994 // plug the hole by moving all the desktops above down one
1995 while (check
< desktop_count
) {
1997 for (; it
.current(); it
++)
1998 if(it
.current()->number
== (check
+ 1)) {
1999 it
.current()->number
= check
++;
2005 void ToolWindow::focusDesktop(int desktop
)
2007 LinkedListIterator
<DesktopList
> it(desktopList
);
2008 for (; it
.current(); it
++)
2009 if (it
.current()->number
== desktop
)
2010 current_desktop
= it
.current();
2013 void ToolWindow::setDesktopCount(int count
)
2015 int oldcount
= desktop_count
;
2016 int delta
= count
- oldcount
;
2018 if (delta
> 0) { // added desktops
2022 else { // removed desktops
2024 removeDesktop(desktop_count
- 1); // remove the last desktop
2028 /*--------------------------------------*/
2030 /*- window list management functions -*/
2032 /*--------------------------------------*/
2034 void ToolWindow::removeWindow(Window win
)
2036 if (focus_window
== win
)
2038 LinkedListIterator
<WindowList
> it(windowList
);
2039 for (; it
.current(); it
++)
2040 if (it
.current()->win
== win
) {
2041 windowList
->remove(it
.current());
2045 void ToolWindow::focusWindow(Window win
)
2047 // have to only do this when the menu isn't visible, because we're
2048 // setting focus while we're cycling.... Unfortunately, a side-effect
2049 // of this is that we don't get a final focusWindow hit when we raise
2050 // the selected window when done cycling, so we do an explicit
2051 // bbtool->focusWindow() call from Stackmenu::selectFocused() after we
2052 // XRaise the window....
2054 if (! doingCycling
) {
2056 if (resource
->getMenuStackedCycling())
2061 void ToolWindow::moveWinToDesktop(Window win
, int desktop
)
2063 LinkedListIterator
<WindowList
> it(windowList
);
2064 for (; it
.current(); it
++)
2065 if (it
.current()->win
== win
) {
2066 if (!it
.current()->sticky
) {
2067 it
.current()->desktop
= desktop
;
2073 void ToolWindow::addSticky(WindowList
*win
) {
2075 LinkedListIterator
<DesktopList
> it(desktopList
);
2076 for (; it
.current(); it
++)
2077 if (win
->desktop
!= it
.current()->number
) {
2078 WindowList
*copy
= new WindowList
;
2079 copy
->win
= win
->win
;
2080 copy
->iconic
= win
->iconic
;
2081 copy
->shaded
= win
->shaded
;
2082 copy
->sticky
= True
;
2083 copy
->desktop
= it
.current()->number
;
2084 windowList
->insert(copy
, -1);
2088 void ToolWindow::removeSticky(const Window win
, const int desktop
) {
2089 LinkedListIterator
<WindowList
> it(windowList
);
2090 for (register int i
=0; i
< desktop_count
; i
++) {
2092 for (; it
.current(); it
++)
2093 if (it
.current()->win
== win
)
2094 if (it
.current()->desktop
!= desktop
)
2095 windowList
->remove(it
.current());
2097 it
.current()->sticky
= False
;
2101 void ToolWindow::windowAttributeChange(Window win
) {
2104 unsigned long n
, extra
;
2105 WindowList
*window
= NULL
;
2106 BlackboxHints
*net_hint
;
2107 LinkedListIterator
<WindowList
> it(windowList
);
2109 for (; it
.current(); it
++) // find the window that's changed
2110 if (it
.current()->win
== win
)
2111 window
= it
.current();
2114 if (!(XGetWindowProperty(getXDisplay(), window
->win
,
2115 getBlackboxAttributesAtom(), 0L,
2116 PropBlackboxHintsElements
, False
,
2117 getBlackboxAttributesAtom(), &real_type
,
2118 &format
, &n
, &extra
, (unsigned char**)&net_hint
)
2119 == Success
&& net_hint
))
2121 if (n
!= PropBlackboxHintsElements
)
2124 if (net_hint
->flags
& AttribShaded
) {
2125 if (net_hint
->attrib
& AttribShaded
)
2126 window
->shaded
= True
;
2127 } else if (window
->shaded
)
2128 window
->shaded
= False
;
2130 if (wminterface
->isIconicState(window
->win
) != window
->iconic
&&
2132 window
->iconic
= !window
->iconic
;
2134 if (net_hint
->flags
& AttribOmnipresent
) {
2135 if (net_hint
->attrib
& AttribOmnipresent
)
2136 if (!window
->sticky
) addSticky(window
);
2137 } else if (window
->sticky
)
2138 if (window
->sticky
) removeSticky(window
->win
, getCurrentDesktopNr());
2141 void ToolWindow::addWindow(Window win
, int desktop
)
2143 WindowList
*newwin
= new WindowList
;
2145 newwin
->iconic
= wminterface
->isIconicState(win
);
2146 newwin
->shaded
= False
;
2147 newwin
->sticky
= False
;
2148 newwin
->desktop
= desktop
;
2149 XSelectInput(getXDisplay(),newwin
->win
,
2150 PropertyChangeMask
);
2151 if (resource
->getMenuStackedCycling())
2157 void ToolWindow::cycleWindowFocus(bool forward
)
2159 if (resource
->getMenuStackedCycling())
2160 cycle_stack(forward
);
2162 cycle_linear(forward
);
2165 /*******************************************************************************
2167 LINEAR CYCLING FUNCTIONS
2169 *******************************************************************************/
2171 void ToolWindow::add_linear(WindowList
*newwin
)
2174 int index
= 0; // where the new window will be placed (defaults to the
2176 // insert after the focused window
2177 LinkedListIterator
<WindowList
> it(windowList
);
2178 for (i
=0; i
<windowList
->count(); i
++) {
2180 if (it
.current()->win
== focus_window
) {
2181 // get the index of the focused window
2186 windowList
->insert(newwin
, index
);
2189 void ToolWindow::cycle_linear(bool forward
)
2191 /*******************************************
2192 This does the oldschool straight rotation
2193 order of cycling windows.
2194 ********************************************/
2197 WindowList
*next
= NULL
;
2200 LinkedListIterator
<WindowList
> it(windowList
);
2201 max
= windowList
->count();
2202 for (i
=0; i
<max
; i
++) {
2208 // find the window after the focused one
2209 if (it
.current()->desktop
== desktop
) {
2210 next
= it
.current();
2214 if (it
.current()->win
== focus_window
) {
2216 desktop
= it
.current()->desktop
;
2219 // if the next window wasn't found, start over at the beginning once more
2222 for (i
=0; i
<max
; i
++) {
2227 if (it
.current()->desktop
== desktop
) {
2228 next
= it
.current();
2235 wminterface
->setWindowFocus(next
->win
);
2236 XRaiseWindow(getXDisplay(), next
->win
);
2240 /*******************************************************************************
2242 STACK CYCLING FUNCTIONS
2244 *******************************************************************************/
2246 void ToolWindow::add_stack(WindowList
*newwin
) {
2247 windowList
->insert(newwin
, 0); // insert at the top of the list
2248 stackMenu
->setMenuItems();
2251 void ToolWindow::cycle_stack(bool forward
) {
2252 register bool showMenu
= resource
->getMenuShowCycleMenu() ? True
: False
;
2253 stackMenu
->show(forward
, showMenu
);
2256 void ToolWindow::focus_stack(Window win
)
2258 WindowList
*window
= new WindowList
;
2259 LinkedListIterator
<WindowList
> it(windowList
);
2260 for (; it
.current(); it
++) {
2261 if (it
.current()->win
== win
)
2262 if ((!it
.current()->sticky
) ||
2263 (it
.current()->desktop
== getCurrentDesktopNr()))
2267 window
->win
= it
.current()->win
;
2268 window
->shaded
= it
.current()->shaded
;
2269 window
->sticky
= it
.current()->sticky
;
2270 window
->iconic
= it
.current()->iconic
;
2271 window
->desktop
= it
.current()->desktop
;
2272 windowList
->remove(it
.current()); // remove it
2273 windowList
->insert(window
, 0); // add it to the top
2277 void ToolWindow::saveMenuSearch(Window window
, Basemenu
*menu
)
2282 void ToolWindow::removeMenuSearch(Window window
)
2284 menuWin
= (Window
)NULL
;
2287 void ToolWindow::p()
2289 printf("window | stick | shade | icon | desk\n");
2290 LinkedListIterator
<WindowList
> it(windowList
);
2291 for (; it
.current(); it
++)
2292 printf("%010i | %d | %d | %d | %d\n", (int)it
.current()->win
,
2293 it
.current()->sticky
, it
.current()->shaded
, it
.current()->iconic
,
2294 it
.current()->desktop
);