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-2000 by Jason Kasper (vanRijn) vR@movingparts.net
6 // Copyright (c) 2001 by Ben Jansens <xor@x-o-r.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)
31 #endif // HAVE_STDIO_H
35 #endif // HAVE_CTYPE_H
40 #endif // STDC_HEADERS
46 #ifdef HAVE_SYS_TYPES_H
47 # include <sys/types.h>
48 #endif // HAVE_SYS_TYPES_H
50 #ifdef HAVE_SYS_WAIT_H
51 # include <sys/wait.h>
52 #endif // HAVE_SYS_WAIT_H
56 #endif // HAVE_ERRNO_H
60 #endif // HAVE_UNISTD_H
62 #ifdef HAVE_SYS_STAT_H
63 # include <sys/stat.h>
64 #endif // HAVE_SYS_STAT_H
67 #include <X11/Xproto.h>
68 #include <X11/keysym.h>
75 /*--------------------------------------------------------------------*/
77 /* Ripped shamelessly from wmaker's xmodifier.c--converted for our use*/
79 /*--------------------------------------------------------------------*/
81 /* Grok X modifier mappings for shortcuts.
83 Most of this code was taken from src/event-Xt.c in XEmacs 20.3-b17.
84 The copyright(s) from the original XEmacs code are included below.
86 Perpetrator: Sudish Joseph <sj@eng.mindspring.net>, Sept. 1997. */
88 /* The event_stream interface for X11 with Xt, and/or tty frames.
89 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
90 Copyright (C) 1995 Sun Microsystems, Inc.
91 Copyright (C) 1996 Ben Wing.
93 This file is part of XEmacs.
95 XEmacs is free software; you can redistribute it and/or modify it
96 under the terms of the GNU General Public License as published by the
97 Free Software Foundation; either version 2, or (at your option) any
100 XEmacs is distributed in the hope that it will be useful, but WITHOUT
101 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
102 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
105 You should have received a copy of the GNU General Public License
106 along with XEmacs; see the file COPYING. If not, write to
107 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
108 Boston, MA 02111-1307, USA. */
110 /************************************************************************/
112 /* keymap handling */
114 /************************************************************************/
116 /* X bogusly doesn't define the interpretations of any bits besides
117 ModControl, ModShift, and ModLock; so the Interclient Communication
118 Conventions Manual says that we have to bend over backwards to figure
119 out what the other modifier bits mean. According to ICCCM:
121 - Any keycode which is assigned ModControl is a "control" key.
123 - Any modifier bit which is assigned to a keycode which generates Meta_L
124 or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper,
127 - Any keypress event which contains ModControl in its state should be
128 interpreted as a "control" character.
130 - Any keypress event which contains a modifier bit in its state which is
131 generated by a keycode whose corresponding keysym is Meta_L or Meta_R
132 should be interpreted as a "meta" character. Likewise for Super, Hyper,
135 - It is illegal for a keysym to be associated with more than one modifier
138 This means that the only thing that emacs can reasonably interpret as a
139 "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
140 one of the modifier bits Mod1-Mod5.
142 Unfortunately, many keyboards don't have Meta keys in their default
143 configuration. So, if there are no Meta keys, but there are "Alt" keys,
144 emacs will interpret Alt as Meta. If there are both Meta and Alt keys,
145 then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
146 mean "Symbol," but that just confused the hell out of way too many people).
148 This works with the default configurations of the 19 keyboard-types I've
151 Emacs detects keyboard configurations which violate the above rules, and
152 prints an error message on the standard-error-output. (Perhaps it should
153 use a pop-up-window instead.)
156 static int MetaMask
, HyperMask
, SuperMask
, AltMask
, ModeMask
;
158 char *ToolWindow::index_to_name(int indice
)
165 case ControlMapIndex
:
182 void ToolWindow::x_reset_modifier_mapping(Display
* display
)
184 int modifier_index
, modifier_key
, column
, mkpm
;
185 int warned_about_overlapping_modifiers
= 0;
186 int warned_about_predefined_modifiers
= 0;
187 int warned_about_duplicate_modifiers
= 0;
193 XModifierKeymap
*x_modifier_keymap
= XGetModifierMapping(display
);
195 #define modwarn(name,old,other) \
196 warned_about_overlapping_modifiers = 1
198 #define modbarf(name,other) \
199 warned_about_predefined_modifiers = 1
201 #define check_modifier(name,mask) \
202 warned_about_predefined_modifiers = 1
204 #define store_modifier(name,old) \
205 if (old && old != modifier_index) \
206 warned_about_duplicate_modifiers = 1; \
207 if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift"); \
208 else if (modifier_index == LockMapIndex) modbarf (name,"ModLock"); \
209 else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \
210 else if (sym == XK_Mode_switch) \
211 mode_bit = modifier_index; /* Mode_switch is special, see below... */ \
212 else if (modifier_index == meta_bit && old != meta_bit) \
213 modwarn (name, meta_bit, "Meta"); \
214 else if (modifier_index == super_bit && old != super_bit) \
215 modwarn (name, super_bit, "Super"); \
216 else if (modifier_index == hyper_bit && old != hyper_bit) \
217 modwarn (name, hyper_bit, "Hyper"); \
218 else if (modifier_index == alt_bit && old != alt_bit) \
219 modwarn (name, alt_bit, "Alt"); \
221 old = modifier_index;
223 mkpm
= x_modifier_keymap
->max_keypermod
;
224 for (modifier_index
= 0; modifier_index
< 8; modifier_index
++)
225 for (modifier_key
= 0; modifier_key
< mkpm
; modifier_key
++) {
227 for (column
= 0; column
< 4; column
+= 2) {
229 x_modifier_keymap
->modifiermap
[modifier_index
* mkpm
+
232 (code
? XKeycodeToKeysym(display
, code
, column
) : 0);
238 store_modifier("Mode_switch", mode_bit
);
241 store_modifier("Meta_L", meta_bit
);
244 store_modifier("Meta_R", meta_bit
);
247 store_modifier("Super_L", super_bit
);
250 store_modifier("Super_R", super_bit
);
253 store_modifier("Hyper_L", hyper_bit
);
256 store_modifier("Hyper_R", hyper_bit
);
259 store_modifier("Alt_L", alt_bit
);
262 store_modifier("Alt_R", alt_bit
);
265 check_modifier("Control_L", ControlMask
);
268 check_modifier("Control_R", ControlMask
);
271 check_modifier("Shift_L", ShiftMask
);
274 check_modifier("Shift_R", ShiftMask
);
277 check_modifier("Shift_Lock", LockMask
);
280 check_modifier("Caps_Lock", LockMask
);
283 /* It probably doesn't make any sense for a modifier bit to be
284 assigned to a key that is not one of the above, but OpenWindows
285 assigns modifier bits to a couple of random function keys for
286 no reason that I can discern, so printing a warning here would
291 #undef store_modifier
292 #undef check_modifier
296 /* If there was no Meta key, then try using the Alt key instead.
297 If there is both a Meta key and an Alt key, then the Alt key
298 is not disturbed and remains an Alt key. */
299 if (!meta_bit
&& alt_bit
)
300 meta_bit
= alt_bit
, alt_bit
= 0;
302 /* mode_bit overrides everything, since it's processed down inside of
303 XLookupString() instead of by us. If Meta and Mode_switch both
304 generate the same modifier bit (which is an error), then we don't
305 interpret that bit as Meta, because we can't make XLookupString()
306 not interpret it as Mode_switch; and interpreting it as both would
309 const char *warn
= 0;
310 if (mode_bit
== meta_bit
)
311 warn
= "Meta", meta_bit
= 0;
312 else if (mode_bit
== hyper_bit
)
313 warn
= "Hyper", hyper_bit
= 0;
314 else if (mode_bit
== super_bit
)
315 warn
= "Super", super_bit
= 0;
316 else if (mode_bit
== alt_bit
)
317 warn
= "Alt", alt_bit
= 0;
319 warned_about_overlapping_modifiers
= 1;
323 MetaMask
= (meta_bit
? (1 << meta_bit
) : 0);
324 HyperMask
= (hyper_bit
? (1 << hyper_bit
) : 0);
325 SuperMask
= (super_bit
? (1 << super_bit
) : 0);
326 AltMask
= (alt_bit
? (1 << alt_bit
) : 0);
327 ModeMask
= (mode_bit
? (1 << mode_bit
) : 0); /* unused */
329 if (x_modifier_keymap
)
330 XFreeModifiermap(x_modifier_keymap
);
334 int ToolWindow::translateModifier(char *key
)
336 if (strcasecmp(key
, "SHIFT") == 0 && ShiftMask
!= 0)
338 else if (strcasecmp(key
, "CONTROL") == 0 && ControlMask
!= 0)
340 else if (strcasecmp(key
, "ALT") == 0 && AltMask
!= 0)
342 else if (strcasecmp(key
, "META") == 0 && MetaMask
!= 0)
344 else if (strcasecmp(key
, "SUPER") == 0 && SuperMask
!= 0)
346 else if (strcasecmp(key
, "HYPER") == 0 && HyperMask
!= 0)
348 else if (strcasecmp(key
, "MOD1") == 0 && Mod1Mask
!= 0)
350 else if (strcasecmp(key
, "MOD2") == 0 && Mod2Mask
!= 0)
352 else if (strcasecmp(key
, "MOD3") == 0 && Mod3Mask
!= 0)
354 else if (strcasecmp(key
, "MOD4") == 0 && Mod4Mask
!= 0)
356 else if (strcasecmp(key
, "MOD5") == 0 && Mod5Mask
!= 0)
358 else if (strcasecmp(key
, "NONE") == 0)
364 /* Wrapper so that we may fit our naming conventions, yet leave the
365 original XEmacs function name in place. */
366 void ToolWindow::InitializeModifiers(void)
368 x_reset_modifier_mapping(getXDisplay());
371 /*-----------------------------------------------------------------------*/
373 /*-- end of shameless rip. thank you for your support ---*/
375 /*-----------------------------------------------------------------------*/
377 void ToolWindow::CheckConfig()
379 struct stat file_status
;
381 if (stat(bbkeys_rcfile
, &file_status
) != 0) {
383 fprintf(stderr
, "Could not open config file ->%s<-\n",
386 } else if (file_status
.st_mtime
!= bbkeys_rcTime
) {
387 bbkeys_rcTime
= file_status
.st_mtime
;
393 void ToolWindow::activateKeygrabs(void)
397 if (grabSet
.instructCount
> 0)
398 XUngrabKey(getXDisplay(), AnyKey
, AnyModifier
,
399 getScreenInfo(0)->getRootWindow());
400 for (i
= 0; i
< grabSet
.instructCount
; i
++) {
401 if (grabSet
.KeyMap
[i
].keycode
== 0)
404 if (grabSet
.KeyMap
[i
].keycode
!= AnyModifier
) {
405 XGrabKey(getXDisplay(), grabSet
.KeyMap
[i
].keycode
,
406 grabSet
.KeyMap
[i
].modMask
| LockMask
,
407 getScreenInfo(0)->getRootWindow(), True
,
408 GrabModeAsync
, GrabModeAsync
);
410 /* Also grab all modifier combinations possible that include,
411 * LockMask, ScrollLockMask and NumLockMask, so that keygrabs
412 * work even if the NumLock/ScrollLock key is on.
415 wHackedGrabKey(grabSet
.KeyMap
[i
].keycode
,
416 grabSet
.KeyMap
[i
].modMask
,
417 getScreenInfo(0)->getRootWindow(), True
,
418 GrabModeAsync
, GrabModeAsync
);
421 XGrabKey(getXDisplay(), grabSet
.KeyMap
[i
].keycode
,
422 grabSet
.KeyMap
[i
].modMask
,
423 getScreenInfo(0)->getRootWindow(), True
, GrabModeAsync
,
428 /*---------------------------------------------------------------------------*/
430 /*-- Snarfed shamelessly from WindowMaker's code-base once again.... --*/
432 /*---------------------------------------------------------------------------*/
433 void ToolWindow::wHackedGrabKey(int keycode
, unsigned int modifiers
,
434 Window grab_window
, Bool owner_events
,
435 int pointer_mode
, int keyboard_mode
)
437 if (modifiers
== AnyModifier
)
439 if (keycode
== AnyKey
)
442 /* grab all combinations of the modifier with CapsLock, NumLock and
443 * ScrollLock. How much memory/CPU does such a monstrosity consume
447 XGrabKey(getXDisplay(), keycode
, modifiers
| _NumLockMask
,
448 grab_window
, owner_events
, pointer_mode
, keyboard_mode
);
450 if (_ScrollLockMask
) {
451 XGrabKey(getXDisplay(), keycode
, modifiers
| _ScrollLockMask
,
452 grab_window
, owner_events
, pointer_mode
, keyboard_mode
);
454 if (_NumLockMask
&& _ScrollLockMask
) {
455 XGrabKey(getXDisplay(), keycode
,
456 modifiers
| _NumLockMask
| _ScrollLockMask
, grab_window
,
457 owner_events
, pointer_mode
, keyboard_mode
);
460 XGrabKey(getXDisplay(), keycode
,
461 modifiers
| _NumLockMask
| LockMask
, grab_window
,
462 owner_events
, pointer_mode
, keyboard_mode
);
464 if (_ScrollLockMask
) {
465 XGrabKey(getXDisplay(), keycode
,
466 modifiers
| _ScrollLockMask
| LockMask
, grab_window
,
467 owner_events
, pointer_mode
, keyboard_mode
);
469 if (_NumLockMask
&& _ScrollLockMask
) {
470 XGrabKey(getXDisplay(), keycode
,
471 modifiers
| _NumLockMask
| _ScrollLockMask
| LockMask
,
472 grab_window
, owner_events
, pointer_mode
, keyboard_mode
);
474 /* phew, I guess that's all, right? */
477 void ToolWindow::getOffendingModifiers(void)
480 XModifierKeymap
*modmap
;
481 KeyCode nlock
, slock
;
482 static int mask_table
[8] = {
483 ShiftMask
, LockMask
, ControlMask
, Mod1Mask
,
484 Mod2Mask
, Mod3Mask
, Mod4Mask
, Mod5Mask
487 nlock
= XKeysymToKeycode(getXDisplay(), XK_Num_Lock
);
488 slock
= XKeysymToKeycode(getXDisplay(), XK_Scroll_Lock
);
491 * Find out the masks for the NumLock and ScrollLock modifiers,
492 * so that we can bind the grabs for when they are enabled too.
494 modmap
= XGetModifierMapping(getXDisplay());
496 if (modmap
!= NULL
&& modmap
->max_keypermod
> 0) {
497 for (i
= 0; i
< 8 * modmap
->max_keypermod
; i
++) {
498 if (modmap
->modifiermap
[i
] == nlock
&& nlock
!= 0)
499 _NumLockMask
= mask_table
[i
/ modmap
->max_keypermod
];
500 else if (modmap
->modifiermap
[i
] == slock
&& slock
!= 0)
501 _ScrollLockMask
= mask_table
[i
/ modmap
->max_keypermod
];
506 XFreeModifiermap(modmap
);
509 /*-------------------------------------------------------------------------*/
511 /*-- End of shameful code-snarf..................................... --*/
513 /*-------------------------------------------------------------------------*/
515 int ToolWindow::translateAction(char *action
)
520 if (!strcasecmp(action
, "Minimize"))
522 if (!strcasecmp(action
, "Raise"))
524 if (!strcasecmp(action
, "Lower"))
526 if (!strcasecmp(action
, "Close"))
528 if (!strcasecmp(action
, "Workspace1"))
529 return grabWorkspace1
;
530 if (!strcasecmp(action
, "Workspace2"))
531 return grabWorkspace2
;
532 if (!strcasecmp(action
, "Workspace3"))
533 return grabWorkspace3
;
534 if (!strcasecmp(action
, "Workspace4"))
535 return grabWorkspace4
;
536 if (!strcasecmp(action
, "Workspace5"))
537 return grabWorkspace5
;
538 if (!strcasecmp(action
, "Workspace6"))
539 return grabWorkspace6
;
540 if (!strcasecmp(action
, "Workspace7"))
541 return grabWorkspace7
;
542 if (!strcasecmp(action
, "Workspace8"))
543 return grabWorkspace8
;
544 if (!strcasecmp(action
, "Workspace9"))
545 return grabWorkspace9
;
546 if (!strcasecmp(action
, "Workspace10"))
547 return grabWorkspace10
;
548 if (!strcasecmp(action
, "Workspace11"))
549 return grabWorkspace11
;
550 if (!strcasecmp(action
, "Workspace12"))
551 return grabWorkspace12
;
552 if (!strcasecmp(action
, "NextWorkspace"))
553 return grabNextWorkspace
;
554 if (!strcasecmp(action
, "PrevWorkspace"))
555 return grabPrevWorkspace
;
556 if (!strcasecmp(action
, "NextWindow"))
557 return grabNextWindow
;
558 if (!strcasecmp(action
, "PrevWindow"))
559 return grabPrevWindow
;
560 if (!strcasecmp(action
, "ShadeWindow"))
562 if (!strcasecmp(action
, "MaximizeWindow"))
564 if (!strcasecmp(action
, "StickWindow"))
566 if (!strcasecmp(action
, "ExecCommand"))
568 if (!strcasecmp(action
, "MaximizeVertical"))
570 if (!strcasecmp(action
, "MaximizeHorizontal"))
572 if (!strcasecmp(action
, "NudgeRight"))
573 return grabNudgeRight
;
574 if (!strcasecmp(action
, "NudgeLeft"))
575 return grabNudgeLeft
;
576 if (!strcasecmp(action
, "NudgeUp"))
578 if (!strcasecmp(action
, "NudgeDown"))
579 return grabNudgeDown
;
580 if (!strcasecmp(action
, "BigNudgeRight"))
581 return grabBigNudgeRight
;
582 if (!strcasecmp(action
, "BigNudgeLeft"))
583 return grabBigNudgeLeft
;
584 if (!strcasecmp(action
, "BigNudgeUp"))
585 return grabBigNudgeUp
;
586 if (!strcasecmp(action
, "BigNudgeDown"))
587 return grabBigNudgeDown
;
588 if (!strcasecmp(action
, "HorizontalIncrement"))
590 if (!strcasecmp(action
, "VerticalIncrement"))
592 if (!strcasecmp(action
, "HorizontalDecrement"))
594 if (!strcasecmp(action
, "VerticalDecrement"))
596 if (!strcasecmp(action
, "ToggleDecor"))
597 return grabToggleDecor
;
603 void ToolWindow::execCommand(char *ptrCommand
)
606 extern char **environ
;
611 "bbkeys: Could not fork a process for execCommand.\n");
619 argv
[2] = ptrCommand
;
621 execve("/bin/sh", argv
, environ
);
626 void ToolWindow::setKeygrabs(void)
628 int res
, pid
, status
;
633 "bbkeys: Could not fork a process for configurator.\n");
639 // Make 'bbkeysconf' automagically fail...
642 res
= execlp("bbkeysconf", "bbkeysconf", NULL
);
646 res
= execlp("bbkeysConfigGtk", "bbkeysConfigGtk", NULL
);
649 execlp("rxvt", "rxvt", "-bg", "black", "-fg", "green",
650 "-e", "bbkeysConfigC", NULL
);
652 execlp("xterm", "xterm", "-bg", "black", "-fg",
653 "green", "-e", "bbkeysConfigC", NULL
);
661 if (waitpid(pid
, &status
, 0) == -1) {
670 void ToolWindow::loadKeygrabs(void)
672 // free up pointers that we get with strdup for execCommand....
674 for (i
= 0; i
< grabSet
.instructCount
; i
++) {
675 if (grabSet
.KeyMap
[i
].execCommand
!= NULL
) {
676 free(grabSet
.KeyMap
[i
].execCommand
);
680 /* re-initialize our grabSet count... */
681 grabSet
.instructCount
= 0;
688 char execCommand
[500];
689 char *KeytograbBegin
;
694 FILE *rc_file
= fopen(bbkeys_rcfile
, "r");
696 /* fprintf(stderr, "Can't open bbkeys rc-file (%s)\n", bbkeys_rcfile); */
700 memset(line
, '\0', 1024);
702 while (fgets(line
, 1024, rc_file
) && !feof(rc_file
) &&
703 count
< MaxInstructions
) {
704 if (line
[0] != '#' && strstr(line
, "WithModifier")) {
706 memset(Keytograb
, '\0', 80);
707 memset(Modifier
, '\0', 80);
708 memset(action
, '\0', 80);
709 memset(execCommand
, '\0', 500);
711 KeytograbBegin
= strchr(line
, '(');
712 ModifierBegin
= strchr(KeytograbBegin
+ 1, '(');
713 actionBegin
= strchr(ModifierBegin
+ 1, '(');
715 strncat(Keytograb
, KeytograbBegin
+ 1,
716 strcspn(KeytograbBegin
+ 1, ")"));
717 strncpy(Modifier
, ModifierBegin
+ 1,
718 strcspn(ModifierBegin
+ 1, ")"));
719 strncpy(action
, actionBegin
+ 1,
720 strcspn(actionBegin
+ 1, ")"));
722 grabSet
.KeyMap
[count
].keycode
= XKeysymToKeycode(getXDisplay(),
727 char *tmp
= (char *) Modifier
;
728 grabSet
.KeyMap
[count
].modMask
= 0;
729 while ((k
= strchr(tmp
, '+')) != NULL
) {
731 grabSet
.KeyMap
[count
].modMask
|= translateModifier(tmp
);
734 grabSet
.KeyMap
[count
].modMask
|= translateModifier(tmp
);
736 grabSet
.KeyMap
[count
].action
= translateAction(action
);
738 /* if we're supposed to having an execCommand and we do have
739 * something to put into it */
740 if (grabSet
.KeyMap
[count
].action
== grabExecute
) {
741 execCmdBegin
= strchr(actionBegin
+ 1, '(');
743 strncpy(execCommand
, execCmdBegin
+ 1,
744 strcspn(execCmdBegin
+ 1, ")"));
745 grabSet
.KeyMap
[count
].execCommand
=
749 grabSet
.KeyMap
[count
].execCommand
= NULL
;
753 fprintf(stdout
, "Keysym ->%d<-, Modifier ->0x%lx<-, "
754 "action ->%d<-, execCommand ->%s<-\n",
755 grabSet
.KeyMap
[count
].keycode
,
756 grabSet
.KeyMap
[count
].modMask
,
757 grabSet
.KeyMap
[count
].action
,
758 grabSet
.KeyMap
[count
].execCommand
);
765 grabSet
.instructCount
= count
;
767 fprintf(stderr
, "loaded ->%d<- instructions.\n", count
);
771 /*****************************************
773 * END OF KEY GRABBING/HANDLING ROUTINES *
775 *****************************************/
777 ToolWindow::ToolWindow(int argc
, char **argv
, struct CMDOPTIONS
*options
):
778 Basewindow(argc
, argv
, options
), TimeoutHandler()
780 timer
= new BTimer(this, this);
781 timer
->setTimeout(100);
782 timer
->fireOnce(True
);
784 char *homedir
= getenv("HOME");
785 bbkeys_rcfile
= new char[strlen(homedir
) + 32];
786 sprintf(bbkeys_rcfile
, "%s/.bbkeysrc", homedir
);
790 InitializeModifiers();
796 * Ignore CapsLock in modifiers
798 ValidModMask
= 0xff & ~LockMask
;
800 getOffendingModifiers();
802 * Ignore NumLock and ScrollLock too
804 ValidModMask
&= ~(_NumLockMask
| _ScrollLockMask
);
806 // initialize it so we don't run into problems later
807 grabSet
.instructCount
= 0;
811 resource
= new Resource(this);
812 wminterface
= new WMInterface(this);
813 windowList
= new LinkedList
< WindowList
>;
814 desktopList
= new LinkedList
< DesktopList
>;
816 // initialize variables
817 current_desktop
= NULL
;
820 // make draw the bbkeys window
824 // pass control to the main loop
828 ToolWindow::~ToolWindow()
830 XUnmapWindow(getXDisplay(), win_frame
);
832 /* destroy pixmaps */
834 getImageControl()->removeImage(pixmap
.frame
);
835 if (pixmap
.pix_title
)
836 getImageControl()->removeImage(pixmap
.pix_title
);
838 getImageControl()->removeImage(pixmap
.pix_back
);
839 if (pixmap
.pix_configBtn
)
840 getImageControl()->removeImage(pixmap
.pix_configBtn
);
841 if (pixmap
.pix_closeBtn
)
842 getImageControl()->removeImage(pixmap
.pix_closeBtn
);
843 if (pixmap
.pix_pressedBtn
)
844 getImageControl()->removeImage(pixmap
.pix_pressedBtn
);
846 /* destroy windows */
847 XDestroyWindow(getXDisplay(), win_frame
);
848 XDestroyWindow(getXDisplay(), win_back
);
849 XDestroyWindow(getXDisplay(), win_title
);
850 XDestroyWindow(getXDisplay(), win_configBtn
);
851 XDestroyWindow(getXDisplay(), win_closeBtn
);
858 void ToolWindow::reconfigure(void)
860 /* destroy pixmaps */
862 getImageControl()->removeImage(pixmap
.frame
);
863 if (pixmap
.pix_title
)
864 getImageControl()->removeImage(pixmap
.pix_title
);
866 getImageControl()->removeImage(pixmap
.pix_back
);
867 if (pixmap
.pix_configBtn
)
868 getImageControl()->removeImage(pixmap
.pix_configBtn
);
869 if (pixmap
.pix_closeBtn
)
870 getImageControl()->removeImage(pixmap
.pix_closeBtn
);
871 if (pixmap
.pix_pressedBtn
)
872 getImageControl()->removeImage(pixmap
.pix_pressedBtn
);
878 XClearWindow(getXDisplay(), win_frame
);
879 XClearWindow(getXDisplay(), win_back
);
883 void ToolWindow::MakeWindow(bool reconfigure
)
885 XSetWindowAttributes attrib
;
887 XClassHint classhints
;
888 XTextProperty windowname
;
890 unsigned long create_mask
= CWBackPixmap
| CWBorderPixel
|
891 CWOverrideRedirect
| CWCursor
| CWEventMask
;
893 // geometry for our windows...................................
895 geom_title
.height
= resource
->label
.font
->ascent
+
896 resource
->label
.font
->descent
+ 2;
897 if (geom_title
.height
< 20 && (miniMe
|| tinyMe
))
898 geom_title
.height
= 20;
899 geom_title
.width
= XTextWidth(resource
->label
.font
, "bbkeys",
900 strlen("bbkeys")) + (geom_title
.height
+
904 geom_back
.width
= geom_title
.width
+ 4;
907 geom_closeBtn
.height
= geom_title
.height
* 7 / 10;
908 geom_closeBtn
.width
= geom_closeBtn
.height
;
912 geom_back
.height
= geom_title
.height
+ 2;
913 geom_closeBtn
.y
= 80; /* put it out of sight. */
914 geom_closeBtn
.x
= 80;
915 geom_configBtn
.height
= geom_title
.height
- 1;
916 geom_configBtn
.width
= geom_configBtn
.height
;
917 geom_configBtn
.x
= geom_title
.width
- geom_configBtn
.width
;
918 geom_configBtn
.y
= geom_title
.y
;
922 geom_title
.height
= 22;
923 geom_title
.width
= 22;
926 geom_back
.width
= 22;
927 geom_back
.height
= 22;
928 geom_closeBtn
.y
= 80; /* put it out of sight. */
929 geom_closeBtn
.x
= 80;
930 geom_configBtn
.height
= 20;
931 geom_configBtn
.width
= geom_configBtn
.height
;
932 geom_configBtn
.x
= 1;
933 geom_configBtn
.y
= 1;
937 geom_back
.height
= 3 * (geom_title
.height
) + 6;
938 geom_closeBtn
.x
= geom_title
.width
- geom_closeBtn
.width
- 1;
939 geom_closeBtn
.y
= geom_title
.y
+
940 ((geom_title
.height
- geom_closeBtn
.height
) / 2);
941 geom_configBtn
.height
= (geom_title
.height
* 2);
942 geom_configBtn
.width
= geom_title
.width
- 4;
943 geom_configBtn
.x
= geom_title
.x
+ 2;
944 geom_configBtn
.y
= geom_title
.height
+ geom_title
.y
+ 2;
948 frame
.height
= geom_back
.height
;
949 frame
.width
= geom_back
.width
;
950 frame
.x
= resource
->position
.x
;
951 frame
.y
= resource
->position
.y
;
953 // end geometry for our windows...................................
955 if (resource
->position
.mask
& XNegative
) {
956 frame
.x
= getCurrentScreenInfo()->getWidth() +
957 resource
->position
.x
- frame
.width
;
960 if (resource
->position
.mask
& YNegative
) {
961 frame
.y
= getCurrentScreenInfo()->getHeight() +
962 resource
->position
.y
- frame
.height
;
967 attrib
.override_redirect
= False
;
968 wmhints
.initial_state
= WithdrawnState
;
970 attrib
.override_redirect
= False
;
971 wmhints
.initial_state
= IconicState
;
973 attrib
.override_redirect
= False
;
974 wmhints
.initial_state
= NormalState
;
977 attrib
.background_pixmap
= ParentRelative
;
980 getImageControl()->renderImage(frame
.width
, frame
.height
,
981 &resource
->frame
.texture
);
984 getImageControl()->renderImage(geom_back
.width
,
986 &resource
->frame
.texture
);
988 getImageControl()->renderImage(geom_title
.width
, geom_title
.height
,
989 &resource
->label
.texture
);
991 pixmap
.pix_configBtn
=
992 getImageControl()->renderImage(geom_configBtn
.width
,
993 geom_configBtn
.height
,
994 &resource
->button
.texture
);
996 pixmap
.pix_closeBtn
=
997 getImageControl()->renderImage(geom_closeBtn
.width
,
998 geom_closeBtn
.height
,
999 &resource
->button
.texture
);
1000 pixmap
.pix_pressedBtn
=
1001 getImageControl()->renderImage(geom_configBtn
.width
,
1002 geom_configBtn
.height
,
1003 &resource
->button
.texture_pressed
);
1005 attrib
.cursor
= getSessionCursor();
1007 ButtonPressMask
| ButtonReleaseMask
| ExposureMask
|
1008 FocusChangeMask
| KeyPressMask
| StructureNotifyMask
|
1009 SubstructureRedirectMask
;
1012 win_frame
= XCreateWindow(getXDisplay(),
1013 getCurrentScreenInfo()->getRootWindow(),
1014 frame
.x
, frame
.y
, frame
.width
,
1016 getCurrentScreenInfo()->getDepth(),
1018 getCurrentScreenInfo()->getVisual(),
1019 create_mask
, &attrib
);
1020 win_back
= XCreateWindow(getXDisplay(),
1025 geom_back
.height
, 0,
1026 getCurrentScreenInfo
1027 ()->getDepth(), InputOutput
,
1028 getCurrentScreenInfo
1029 ()->getVisual(), create_mask
, &attrib
);
1031 XCreateWindow(getXDisplay(), win_frame
, geom_title
.x
,
1032 geom_title
.y
, geom_title
.width
,
1033 geom_title
.height
, 0,
1034 getCurrentScreenInfo()->getDepth(), InputOutput
,
1035 getCurrentScreenInfo()->getVisual(), create_mask
,
1038 XCreateWindow(getXDisplay(), win_frame
, geom_configBtn
.x
,
1039 geom_configBtn
.y
, geom_configBtn
.width
,
1040 geom_configBtn
.height
, 0,
1041 getCurrentScreenInfo()->getDepth(), InputOutput
,
1042 getCurrentScreenInfo()->getVisual(), create_mask
,
1045 XCreateWindow(getXDisplay(), win_frame
, geom_closeBtn
.x
,
1046 geom_closeBtn
.y
, geom_closeBtn
.width
,
1047 geom_closeBtn
.height
, 0,
1048 getCurrentScreenInfo()->getDepth(), InputOutput
,
1049 getCurrentScreenInfo()->getVisual(), create_mask
,
1051 } else if (!withdrawn
) {
1052 XMoveResizeWindow(getXDisplay(), win_frame
, frame
.x
, frame
.y
,
1053 frame
.width
, frame
.height
);
1054 XMoveResizeWindow(getXDisplay(), win_back
,
1055 geom_back
.x
, geom_back
.y
,
1056 geom_back
.width
, geom_back
.height
);
1057 XMoveResizeWindow(getXDisplay(), win_title
, geom_title
.x
,
1058 geom_title
.y
, geom_title
.width
,
1060 XMoveResizeWindow(getXDisplay(), win_configBtn
, geom_configBtn
.x
,
1061 geom_configBtn
.y
, geom_configBtn
.width
,
1062 geom_configBtn
.height
);
1063 XMoveResizeWindow(getXDisplay(), win_closeBtn
, geom_closeBtn
.x
,
1064 geom_closeBtn
.y
, geom_closeBtn
.width
,
1065 geom_closeBtn
.height
);
1068 XResizeWindow(getXDisplay(), win_frame
, frame
.width
, frame
.height
);
1069 XResizeWindow(getXDisplay(), win_back
,
1070 geom_back
.width
, geom_back
.height
);
1071 XResizeWindow(getXDisplay(), win_title
, geom_title
.width
,
1073 XMoveResizeWindow(getXDisplay(), win_configBtn
, geom_configBtn
.x
,
1074 geom_configBtn
.y
, geom_configBtn
.width
,
1075 geom_configBtn
.height
);
1076 XMoveResizeWindow(getXDisplay(), win_closeBtn
, geom_closeBtn
.x
,
1077 geom_closeBtn
.y
, geom_closeBtn
.width
,
1078 geom_closeBtn
.height
);
1081 char *name
= BBTOOL
;
1082 XSizeHints sizehints
;
1084 wmhints
.flags
= StateHint
;
1086 classhints
.res_name
= BBTOOL
;
1087 classhints
.res_class
= "bbtools";
1089 sizehints
.x
= frame
.x
; //getResource()->position.x;
1090 sizehints
.y
= frame
.y
; //getResource()->position.y;
1092 sizehints
.max_width
= sizehints
.min_width
= frame
.width
;
1093 sizehints
.max_height
= sizehints
.min_height
= frame
.height
;
1094 sizehints
.flags
= USPosition
| PMinSize
| PMaxSize
;
1096 XStringListToTextProperty(&name
, 1, &windowname
);
1097 XSetWMProperties(getXDisplay(), win_frame
, &windowname
, NULL
, getArgv(),
1098 getArgc(), &sizehints
, &wmhints
, &classhints
);
1100 // free up allocated memory in XStringListToTextProperty
1101 XFree(windowname
.value
);
1105 wmproto
[0] = wm_delete_window
;
1106 wmproto
[1] = getBlackboxStructureMessagesAtom();
1107 XSetWMProtocols(getXDisplay(), win_frame
, wmproto
, 2);
1110 if (!decorated
&& !withdrawn
) {
1111 BlackboxHints net_hints
;
1112 net_hints
.decoration
= DecorNone
;
1113 net_hints
.attrib
= AttribOmnipresent
;
1114 net_hints
.flags
= AttribDecoration
| AttribOmnipresent
;
1115 XChangeProperty(getXDisplay(), win_frame
, getBlackboxHintsAtom(),
1116 getBlackboxHintsAtom(), 32, PropModeReplace
,
1117 (unsigned char *) &net_hints
,
1118 PropBlackboxHintsElements
);
1122 XSetWindowBackgroundPixmap(getXDisplay(), win_frame
, pixmap
.frame
);
1125 XSetWindowBackgroundPixmap(getXDisplay(), win_title
, pixmap
.pix_title
);
1126 XSetWindowBackgroundPixmap(getXDisplay(), win_back
, pixmap
.pix_back
);
1127 XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn
,
1128 pixmap
.pix_configBtn
);
1129 XSetWindowBackgroundPixmap(getXDisplay(), win_closeBtn
,
1130 pixmap
.pix_closeBtn
);
1133 if (!withdrawn
&& resource
->report
.auto_raise
)
1134 XRaiseWindow(getXDisplay(), win_frame
);
1137 gcv
.font
= resource
->label
.font
->fid
;
1138 gcv
.foreground
= resource
->label
.textColor
.getPixel();
1140 XCreateGC(getXDisplay(), win_frame
, GCFont
| GCForeground
,
1143 gcv
.font
= resource
->label
.font
->fid
;
1144 gcv
.foreground
= resource
->label
.textColor
.getPixel();
1145 XChangeGC(getXDisplay(), frameGC
, GCFont
| GCForeground
, &gcv
);
1150 XClearWindow(getXDisplay(), win_frame
);
1151 XMapWindow(getXDisplay(), win_frame
);
1152 XMapSubwindows(getXDisplay(), win_frame
);
1153 XSetIconName(getXDisplay(), win_frame
, "bbkeys");
1157 void ToolWindow::Redraw()
1159 XClearWindow(getXDisplay(), win_title
);
1160 XClearWindow(getXDisplay(), win_configBtn
);
1161 XClearWindow(getXDisplay(), win_closeBtn
);
1163 char *title
= "bbkeys";
1164 XDrawString(getXDisplay(), win_title
, frameGC
, geom_title
.x
- 1,
1165 (geom_title
.height
+ resource
->label
.font
->ascent
-
1166 resource
->label
.font
->descent
) / 2, title
, strlen(title
));
1170 if (miniMe
|| tinyMe
) {
1171 pts
[0].x
= (geom_configBtn
.width
/ 2);
1172 pts
[0].y
= (geom_configBtn
.height
/ 2) - 2;
1173 pts
[1].x
= -(geom_configBtn
.width
/ 4);
1174 pts
[1].y
= (geom_configBtn
.height
- pts
[0].y
) - 1;
1175 pts
[2].x
= (geom_configBtn
.width
/ 2);
1178 XFillPolygon(getXDisplay(), win_configBtn
, frameGC
, pts
, 3,
1179 Convex
, CoordModePrevious
);
1180 XFillArc(getXDisplay(), win_configBtn
, frameGC
,
1181 geom_configBtn
.width
/ 2 - geom_configBtn
.width
/ 4, 1, // x, y
1182 geom_configBtn
.width
/ 2, geom_configBtn
.height
/ 2, //width,height
1185 pts
[0].x
= (geom_configBtn
.width
/ 2);
1186 pts
[0].y
= (geom_configBtn
.height
/ 2) - 2;
1187 pts
[1].x
= -(geom_configBtn
.width
/ 4);
1188 pts
[1].y
= (geom_configBtn
.height
- pts
[0].y
) - 2;
1189 pts
[2].x
= (geom_configBtn
.width
/ 2);
1192 XFillPolygon(getXDisplay(), win_configBtn
, frameGC
, pts
, 3,
1193 Convex
, CoordModePrevious
);
1194 XFillArc(getXDisplay(), win_configBtn
, frameGC
,
1195 geom_configBtn
.width
/ 2 - geom_configBtn
.width
/ 4, 1, // x, y
1196 geom_configBtn
.width
/ 2, geom_configBtn
.height
* 5 / 8, //width,height
1200 /* Our little close button (drawn twice for a nice thickness) */
1201 XDrawLine(getXDisplay(), win_closeBtn
, frameGC
, 1, 1,
1202 geom_closeBtn
.width
- 2, geom_closeBtn
.height
- 1);
1203 XDrawLine(getXDisplay(), win_closeBtn
, frameGC
, 1,
1204 geom_closeBtn
.height
- 1, geom_closeBtn
.width
- 2, 1);
1206 XDrawLine(getXDisplay(), win_closeBtn
, frameGC
, 2, 1,
1207 geom_closeBtn
.width
- 1, geom_closeBtn
.height
- 1);
1208 XDrawLine(getXDisplay(), win_closeBtn
, frameGC
, 2,
1209 geom_closeBtn
.height
- 1, geom_closeBtn
.width
- 1, 1);
1213 void ToolWindow::process_event(XEvent
* e
)
1216 case PropertyNotify
:
1223 Window fw_root
, fw_child
;
1225 unsigned int fw_w
, fw_h
, fw_b
, fw_d
;
1227 /* Need to take out this next bit when nyz has 0.60.0 ready, as
1228 we'll then get our focus_window in a ClientMessage */
1229 int revert_to
= RevertToPointerRoot
;
1230 if (!focus_window
) {
1231 XGetInputFocus(getXDisplay(), &focus_window
, &revert_to
);
1234 /* end temporary focus_window fix */
1236 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1237 XGetGeometry(getXDisplay(), focus_window
, &fw_root
, &fw_x
,
1238 &fw_y
, &fw_w
, &fw_h
, &fw_b
, &fw_d
);
1239 XTranslateCoordinates(getXDisplay(), focus_window
, fw_root
,
1240 fw_x
, fw_y
, &fw_x
, &fw_y
, &fw_child
);
1243 // if our user wants to grab his keystrokes, even though one
1244 // or more of the Lock-Modifiers are pressed, alter the mask
1247 // to make this possible....
1249 if (!honor_modifiers
) {
1250 e
->xkey
.state
&= ~_NumLockMask
& ~_ScrollLockMask
& ~LockMask
;
1253 for (i
= 0; i
< grabSet
.instructCount
; i
++) {
1254 if ((e
->xkey
.keycode
== grabSet
.KeyMap
[i
].keycode
) &&
1255 (e
->xkey
.state
== grabSet
.KeyMap
[i
].modMask
)) {
1262 /* play with colors for nyz =:) */
1263 XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn
,
1264 pixmap
.pix_pressedBtn
);
1267 switch (grabSet
.KeyMap
[grabInt
].action
) {
1269 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1270 XIconifyWindow(getXDisplay(), focus_window
, 0);
1275 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1276 XRaiseWindow(getXDisplay(), focus_window
);
1281 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1282 XLowerWindow(getXDisplay(), focus_window
);
1291 ce
.xclient
.type
= ClientMessage
;
1292 ce
.xclient
.message_type
= getWMProtocolsAtom();
1293 ce
.xclient
.display
= getXDisplay();
1294 ce
.xclient
.window
= focus_window
;
1295 ce
.xclient
.format
= 32;
1296 ce
.xclient
.data
.l
[0] = getWMDeleteAtom();
1297 ce
.xclient
.data
.l
[1] = CurrentTime
;
1298 ce
.xclient
.data
.l
[2] = ce
.xclient
.data
.l
[3] =
1299 ce
.xclient
.data
.l
[4] = 0l;
1301 XSendEvent(getXDisplay(), focus_window
, False
, NoEventMask
, &ce
);
1304 case grabWorkspace1
:
1305 wminterface
->changeDesktop(0);
1308 case grabWorkspace2
:
1309 wminterface
->changeDesktop(1);
1312 case grabWorkspace3
:
1313 wminterface
->changeDesktop(2);
1316 case grabWorkspace4
:
1317 wminterface
->changeDesktop(3);
1320 case grabWorkspace5
:
1321 wminterface
->changeDesktop(4);
1324 case grabWorkspace6
:
1325 wminterface
->changeDesktop(5);
1328 case grabWorkspace7
:
1329 wminterface
->changeDesktop(6);
1332 case grabWorkspace8
:
1333 wminterface
->changeDesktop(7);
1336 case grabWorkspace9
:
1337 wminterface
->changeDesktop(8);
1340 case grabWorkspace10
:
1341 wminterface
->changeDesktop(9);
1344 case grabWorkspace11
:
1345 wminterface
->changeDesktop(10);
1348 case grabWorkspace12
:
1349 wminterface
->changeDesktop(11);
1352 case grabNextWorkspace
:
1353 if (current_desktop
->number
< (desktop_count
-1))
1354 wminterface
->changeDesktop(current_desktop
->number
+ 1);
1356 wminterface
->changeDesktop(0);
1359 case grabPrevWorkspace
:
1360 if (current_desktop
->number
> 0)
1361 wminterface
->changeDesktop(current_desktop
->number
- 1);
1363 wminterface
->changeDesktop(desktop_count
- 1);
1366 case grabNextWindow
:
1367 cycleWindowFocus(True
);
1370 case grabPrevWindow
:
1371 cycleWindowFocus(False
);
1375 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1376 wminterface
->shadeWindow(focus_window
);
1381 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1382 wminterface
->stickWindow(focus_window
);
1387 execCommand(grabSet
.KeyMap
[grabInt
].execCommand
);
1391 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1392 wminterface
->maximizeWindow(focus_window
, True
, True
);
1397 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1398 wminterface
->maximizeWindow(focus_window
, False
, True
);
1403 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1404 wminterface
->maximizeWindow(focus_window
, True
, False
);
1408 case grabNudgeRight
:
1409 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1410 XMoveWindow(getXDisplay(), focus_window
, fw_x
+ 1, fw_y
);
1415 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1416 XMoveWindow(getXDisplay(), focus_window
, fw_x
- 1, fw_y
);
1421 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1422 XMoveWindow(getXDisplay(), focus_window
, fw_x
, fw_y
- 1);
1427 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1428 XMoveWindow(getXDisplay(), focus_window
, fw_x
, fw_y
+ 1);
1432 case grabBigNudgeRight
:
1433 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1434 XMoveWindow(getXDisplay(), focus_window
, fw_x
+ 10, fw_y
);
1438 case grabBigNudgeLeft
:
1439 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1440 XMoveWindow(getXDisplay(), focus_window
, fw_x
- 10, fw_y
);
1444 case grabBigNudgeUp
:
1445 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1446 XMoveWindow(getXDisplay(), focus_window
, fw_x
, fw_y
- 10);
1450 case grabBigNudgeDown
:
1451 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1452 XMoveWindow(getXDisplay(), focus_window
, fw_x
, fw_y
+ 10);
1457 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1458 XWindowAttributes foo
;
1459 XGetWindowAttributes(getXDisplay(), focus_window
, &foo
);
1460 XResizeWindow(getXDisplay(), focus_window
,
1461 foo
.width
+ 10, foo
.height
);
1466 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1467 XWindowAttributes foo
;
1468 XGetWindowAttributes(getXDisplay(), focus_window
, &foo
);
1469 XResizeWindow(getXDisplay(), focus_window
,
1470 foo
.width
, foo
.height
+ 10);
1475 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1476 XWindowAttributes foo
;
1477 XGetWindowAttributes(getXDisplay(), focus_window
, &foo
);
1480 XResizeWindow(getXDisplay(), focus_window
,
1481 foo
.width
- 10, foo
.height
);
1486 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1487 XWindowAttributes foo
;
1488 XGetWindowAttributes(getXDisplay(), focus_window
, &foo
);
1489 if (foo
.height
< 11)
1491 XResizeWindow(getXDisplay(), focus_window
,
1492 foo
.width
, foo
.height
- 10);
1496 case grabToggleDecor
:
1497 if (focus_window
&& focus_window
!= (int)PointerRoot
) {
1498 wminterface
->decorateToggleWindow(focus_window
);
1508 if ((unsigned) e
->xclient
.data
.l
[0] == wm_delete_window
)
1510 wminterface
->handleNETEvents(*e
);
1514 if (!e
->xexpose
.count
)
1519 if (e
->xbutton
.button
== LEFT_BUTTON
1520 || e
->xbutton
.button
== RIGHT_BUTTON
) {
1521 if (e
->xbutton
.window
== win_configBtn
) {
1522 XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn
,
1523 pixmap
.pix_pressedBtn
);
1525 } else if (e
->xbutton
.window
== win_closeBtn
) {
1526 XSetWindowBackgroundPixmap(getXDisplay(), win_closeBtn
,
1527 pixmap
.pix_pressedBtn
);
1529 } else if (e
->xbutton
.window
== win_title
) {
1531 XRaiseWindow(getXDisplay(), win_frame
);
1534 } else if (e
->xbutton
.button
== MIDDLE_BUTTON
) {
1536 XLowerWindow(getXDisplay(), win_frame
);
1542 if (e
->xbutton
.button
== LEFT_BUTTON
1543 || e
->xbutton
.button
== RIGHT_BUTTON
) {
1544 if (e
->xbutton
.window
== win_configBtn
) {
1545 if ((e
->xbutton
.x
> 0)
1546 && (e
->xbutton
.x
< geom_configBtn
.width
)
1547 && (e
->xbutton
.y
> 0)
1548 && (e
->xbutton
.y
< geom_configBtn
.height
)) {
1549 if (grabSet
.instructCount
> 0) {
1550 XUngrabKey(getXDisplay(), AnyKey
, AnyModifier
,
1551 getScreenInfo(0)->getRootWindow());
1552 XSync(getXDisplay(), False
);
1556 // discard all XEvents (was causing us to go bananas on the
1557 // user before, since we were executing all keygrabs at once
1558 // that the user did when the configuration app was running)
1559 // *cough* undocumented feature *cough*
1563 while (XPending(getXDisplay())) {
1564 XNextEvent(getXDisplay(), &event
);
1567 // carry on then, little soldier
1574 XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn
,
1575 pixmap
.pix_configBtn
);
1577 } else if (e
->xbutton
.window
== win_closeBtn
) {
1578 if ((e
->xbutton
.x
> 0)
1579 && (e
->xbutton
.x
< geom_closeBtn
.width
)
1580 && (e
->xbutton
.y
> 0)
1581 && (e
->xbutton
.y
< geom_closeBtn
.height
)) {
1582 if (e
->xbutton
.button
== LEFT_BUTTON
) {
1584 } else if (e
->xbutton
.button
== RIGHT_BUTTON
) {
1586 XUnmapWindow(getXDisplay(), win_frame
);
1591 wmhints
.initial_state
= IconicState
;
1592 wmhints
.flags
= StateHint
;
1593 XSetWMHints(getXDisplay(), win_frame
, &wmhints
);
1594 XMapWindow(getXDisplay(), win_frame
);
1596 // this should work but doesn't seem to. *shrug*
1599 XIconifyWindow(getXDisplay(), win_frame
, 0);
1603 XSetWindowBackgroundPixmap(getXDisplay(), win_closeBtn
,
1604 pixmap
.pix_configBtn
);
1610 case ConfigureNotify
:
1611 if ((e
->xconfigure
.window
== win_frame
) && e
->xconfigure
.send_event
) {
1615 int parent_x
, parent_y
;
1617 unsigned int parent_width
, parent_height
, parent_border_width
;
1618 unsigned int parent_depth
;
1621 XGetGeometry(getXDisplay(), e
->xconfigure
.above
,
1622 &parent_root
, &parent_x
, &parent_y
,
1623 &parent_width
, &parent_height
,
1624 &parent_border_width
, &parent_depth
);
1625 frame
.x
= e
->xconfigure
.x
+ parent_x
;
1626 frame
.y
= e
->xconfigure
.y
+ parent_y
;
1633 void ToolWindow::timeout(void)
1635 XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn
,
1636 pixmap
.pix_configBtn
);
1640 /*--------------------------------*/
1642 /*- window modifying functions -*/
1644 /*--------------------------------*/
1646 void ToolWindow::raiseWindow(Window win
)
1650 void ToolWindow::lowerWindow(Window win
)
1654 /*---------------------------------------*/
1656 /*- desktop list management functions -*/
1658 /*---------------------------------------*/
1660 void ToolWindow::addDesktop(void)
1662 DesktopList
*tmp
= new DesktopList
;
1664 // get the highest in the list
1666 LinkedListIterator
<DesktopList
> it(desktopList
);
1667 for (; it
.current(); it
++)
1668 if (it
.current()->number
> highest
) {
1669 highest
= it
.current()->number
;
1672 tmp
->number
= highest
+ 1;
1674 desktopList
->insert(tmp
, -1); // add to the end of the list
1678 // add sticky windows to this desktop
1679 LinkedListIterator
<WindowList
> it_win(windowList
);
1680 for (; it_win
.current(); it_win
++)
1681 // only look for sticky windows on desktop 0, this will give us one
1682 // copy of each sticky window
1683 if ((it_win
.current()->desktop
== 0) && (it_win
.current()->sticky
)) {
1684 WindowList
*win
= new WindowList
;
1685 win
->win
= it_win
.current()->win
;
1686 win
->iconic
= it_win
.current()->iconic
;
1687 win
->shaded
= False
;
1689 win
->desktop
= tmp
->number
;
1690 windowList
->insert(win
, -1); // add to the end of the list
1694 void ToolWindow::removeDesktop(int desktop
)
1696 LinkedListIterator
<DesktopList
> it(desktopList
);
1697 LinkedListIterator
<WindowList
> it_win(windowList
);
1699 // remove sticky windows from this desktop
1700 for (; it_win
.current(); it_win
++)
1701 if ((it_win
.current()->desktop
== desktop
)
1702 && (it_win
.current()->sticky
))
1703 windowList
->remove(it_win
.current()); // remove just this window
1704 // removeWindow() would remove all
1705 // of the sticky windows.
1707 // remove the desktop from the linked list
1708 for (; it
.current(); it
++)
1709 if (it
.current()->number
== desktop
) {
1710 desktopList
->remove(it
.current());
1716 // shift the rest to fill in the hole if not the last desktop was rm'd
1722 for (; it
.current(); it
++)
1723 if (it
.current()->number
== check
) {
1729 // check is on the new hole, or desktop_count if there is no hole
1730 // plug the hole by moving all the desktops above down one
1731 while (check
< desktop_count
) {
1733 for (; it
.current(); it
++)
1734 if(it
.current()->number
== (check
+ 1)) {
1735 it
.current()->number
= check
++;
1741 void ToolWindow::focusDesktop(int desktop
)
1743 LinkedListIterator
<DesktopList
> it(desktopList
);
1744 for (; it
.current(); it
++)
1745 if (it
.current()->number
== desktop
)
1746 current_desktop
= it
.current();
1749 void ToolWindow::setDesktopCount(int count
)
1751 int oldcount
= desktop_count
;
1752 int delta
= count
- oldcount
;
1754 if (delta
> 0) { // added desktops
1758 else { // removed desktops
1760 removeDesktop(desktop_count
- 1); // remove the last desktop
1764 /*--------------------------------------*/
1766 /*- window list management functions -*/
1768 /*--------------------------------------*/
1770 void ToolWindow::addWindow(Window win
, int desktop
)
1772 int index
= 0; // where the new window will be placed (defaults to the
1775 WindowList
*newwin
= new WindowList
;
1777 newwin
->iconic
= wminterface
->isIconicState(win
);
1778 newwin
->shaded
= False
;
1779 newwin
->sticky
= False
;
1780 newwin
->desktop
= desktop
;
1781 // insert after the focused window
1782 LinkedListIterator
<WindowList
> it(windowList
);
1783 for (i
=0; i
<windowList
->count(); i
++) {
1785 if ((it
.current()->win
== focus_window
)
1786 && (it
.current()->desktop
== desktop
)) {
1787 // get the index of the focused window
1792 windowList
->insert(newwin
, index
);
1795 void ToolWindow::removeWindow(Window win
)
1797 LinkedListIterator
<WindowList
> it(windowList
);
1798 for (; it
.current(); it
++)
1799 if (it
.current()->win
== win
) {
1800 windowList
->remove(it
.current());
1804 void ToolWindow::focusWindow(Window win
)
1809 void ToolWindow::moveWinToDesktop(Window win
, int desktop
)
1811 LinkedListIterator
<WindowList
> it(windowList
);
1812 for (; it
.current(); it
++)
1813 if (it
.current()->win
== win
) {
1814 if (!it
.current()->sticky
) {
1815 it
.current()->desktop
= desktop
;
1821 void ToolWindow::windowAttributeChange(Window win
)
1825 void ToolWindow::cycleWindowFocus(bool forward
)
1827 /*******************************************
1828 This does the oldschool straight rotation
1829 order of cycling windows.
1830 ********************************************/
1833 WindowList
*next
= NULL
;
1836 LinkedListIterator
<WindowList
> it(windowList
);
1837 max
= windowList
->count();
1838 for (i
=0; i
<max
; i
++) {
1844 // find the window after the focused one
1845 if (it
.current()->desktop
== desktop
) {
1846 next
= it
.current();
1850 if (it
.current()->win
== focus_window
) {
1852 desktop
= it
.current()->desktop
;
1855 // if the next window wasn't found, start over at the beginning once more
1858 for (i
=0; i
<max
; i
++) {
1863 if (it
.current()->desktop
== desktop
) {
1864 next
= it
.current();
1871 wminterface
->setWindowFocus(next
->win
);
1872 XRaiseWindow(getXDisplay(), next
->win
);