From d28c63a53c9312d169fae0d250d2844de370a3cf Mon Sep 17 00:00:00 2001 From: Jason Kasper Date: Sun, 19 Jan 2003 17:49:33 +0000 Subject: [PATCH] last bit of fiddling before removing everything for bbkeys-ng --- src/bbkeys.cc | 4754 ++++++++++++++++++++++++++-------------------------- src/stackmenu.cc | 472 +++--- src/wminterface.cc | 654 ++++---- 3 files changed, 2940 insertions(+), 2940 deletions(-) rewrite src/bbkeys.cc (83%) rewrite src/stackmenu.cc (73%) rewrite src/wminterface.cc (72%) diff --git a/src/bbkeys.cc b/src/bbkeys.cc dissimilarity index 83% index c733005..c9b34c7 100644 --- a/src/bbkeys.cc +++ b/src/bbkeys.cc @@ -1,2377 +1,2377 @@ -// bbkeys.cc for blackbox -// ------ note from the Gee-I'm-Sorry-The-Code-Looks-Ugly department----- -// ------ for vi users-- ":set ts=2" =:) -// -// Copyright (c) 1999-2001 by Jason Kasper (vanRijn) vR@movingparts.net -// Copyright (c) 2001 by Ben Jansens -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// -// (See the included file COPYING / GPL-2.0) -// -// $Id$ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_STDIO_H -# include -#endif // HAVE_STDIO_H - -#ifdef HAVE_CTYPE_H -# include -#endif // HAVE_CTYPE_H - -#ifdef STDC_HEADERS -# include -# include -#endif // STDC_HEADERS - -#if HAVE_STRINGS_H -# include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif // HAVE_SYS_TYPES_H - -#ifdef HAVE_SYS_WAIT_H -# include -#endif // HAVE_SYS_WAIT_H - -#ifdef HAVE_ERRNO_H -# include -#endif // HAVE_ERRNO_H - -#ifdef HAVE_UNISTD_H -# include -#endif // HAVE_UNISTD_H - -#ifdef HAVE_SYS_STAT_H -# include -#endif // HAVE_SYS_STAT_H - -extern "C" { -#include -#include -#include -} - -#include "bbkeys.hh" -#include "stackmenu.hh" -#include "resource.hh" -#include "main.hh" -#include "Timer.hh" -#include "Basemenu.hh" -#include "wminterface.hh" - -#include - -using std::string; - -/*--------------------------------------------------------------------*/ - -/* Ripped shamelessly from wmaker's xmodifier.c--converted for our use*/ - -/*--------------------------------------------------------------------*/ - -/* Grok X modifier mappings for shortcuts. - - Most of this code was taken from src/event-Xt.c in XEmacs 20.3-b17. - The copyright(s) from the original XEmacs code are included below. - - Perpetrator: Sudish Joseph , Sept. 1997. */ - -/* The event_stream interface for X11 with Xt, and/or tty frames. - Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 1996 Ben Wing. - -This file is part of XEmacs. - -XEmacs is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -XEmacs is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with XEmacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/************************************************************************/ - -/* keymap handling */ - -/************************************************************************/ - -/* X bogusly doesn't define the interpretations of any bits besides - ModControl, ModShift, and ModLock; so the Interclient Communication - Conventions Manual says that we have to bend over backwards to figure - out what the other modifier bits mean. According to ICCCM: - - - Any keycode which is assigned ModControl is a "control" key. - - - Any modifier bit which is assigned to a keycode which generates Meta_L - or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper, - etc. - - - Any keypress event which contains ModControl in its state should be - interpreted as a "control" character. - - - Any keypress event which contains a modifier bit in its state which is - generated by a keycode whose corresponding keysym is Meta_L or Meta_R - should be interpreted as a "meta" character. Likewise for Super, Hyper, - etc. - - - It is illegal for a keysym to be associated with more than one modifier - bit. - - This means that the only thing that emacs can reasonably interpret as a - "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates - one of the modifier bits Mod1-Mod5. - - Unfortunately, many keyboards don't have Meta keys in their default - configuration. So, if there are no Meta keys, but there are "Alt" keys, - emacs will interpret Alt as Meta. If there are both Meta and Alt keys, - then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to - mean "Symbol," but that just confused the hell out of way too many people). - - This works with the default configurations of the 19 keyboard-types I've - checked. - - Emacs detects keyboard configurations which violate the above rules, and - prints an error message on the standard-error-output. (Perhaps it should - use a pop-up-window instead.) - */ - -static int MetaMask, HyperMask, SuperMask, AltMask, ModeMask; -static int NumLockMask, ScrollLockMask; - -const char *ToolWindow::index_to_name(int indice) -{ - switch (indice) { - case ShiftMapIndex: - return "ModShift"; - case LockMapIndex: - return "ModLock"; - case ControlMapIndex: - return "ModControl"; - case Mod1MapIndex: - return "Mod1"; - case Mod2MapIndex: - return "Mod2"; - case Mod3MapIndex: - return "Mod3"; - case Mod4MapIndex: - return "Mod4"; - case Mod5MapIndex: - return "Mod5"; - default: - return "???"; - } -} - -void ToolWindow::x_reset_modifier_mapping(Display * d) -{ - int modifier_index, modifier_key, column, mkpm; - int warned_about_overlapping_modifiers = 0; - int warned_about_predefined_modifiers = 0; - int warned_about_duplicate_modifiers = 0; - int meta_bit = 0; - int hyper_bit = 0; - int super_bit = 0; - int alt_bit = 0; - int mode_bit = 0; - int num_lock_bit = 0; - int scroll_lock_bit = 0; - XModifierKeymap *x_modifier_keymap = XGetModifierMapping(d); - -#define modwarn(name,old,other) \ - warned_about_overlapping_modifiers = 1 - -#define modbarf(name,other) \ - warned_about_predefined_modifiers = 1 - -#define check_modifier(name,mask) \ - warned_about_predefined_modifiers = 1 - -#define store_modifier(name,old) \ - if (old && old != modifier_index) \ - warned_about_duplicate_modifiers = 1; \ - if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift"); \ - else if (modifier_index == LockMapIndex) modbarf (name,"ModLock"); \ - else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \ - else if (sym == XK_Mode_switch) \ - mode_bit = modifier_index; /* Mode_switch is special, see below... */ \ - else if (modifier_index == meta_bit && old != meta_bit) \ - modwarn (name, meta_bit, "Meta"); \ - else if (modifier_index == super_bit && old != super_bit) \ - modwarn (name, super_bit, "Super"); \ - else if (modifier_index == hyper_bit && old != hyper_bit) \ - modwarn (name, hyper_bit, "Hyper"); \ - else if (modifier_index == alt_bit && old != alt_bit) \ - modwarn (name, alt_bit, "Alt"); \ - else \ - old = modifier_index; - - mkpm = x_modifier_keymap->max_keypermod; - for (modifier_index = 0; modifier_index < 8; modifier_index++) - for (modifier_key = 0; modifier_key < mkpm; modifier_key++) { - KeySym last_sym = 0; - for (column = 0; column < 4; column += 2) { - KeyCode code = - x_modifier_keymap->modifiermap[modifier_index * mkpm + - modifier_key]; - KeySym sym = - (code ? XKeycodeToKeysym(d, code, column) : 0); - if (sym == last_sym) - continue; - last_sym = sym; - switch (sym) { - case XK_Mode_switch: - store_modifier("Mode_switch", mode_bit); - break; - case XK_Meta_L: - store_modifier("Meta_L", meta_bit); - break; - case XK_Meta_R: - store_modifier("Meta_R", meta_bit); - break; - case XK_Super_L: - store_modifier("Super_L", super_bit); - break; - case XK_Super_R: - store_modifier("Super_R", super_bit); - break; - case XK_Hyper_L: - store_modifier("Hyper_L", hyper_bit); - break; - case XK_Hyper_R: - store_modifier("Hyper_R", hyper_bit); - break; - case XK_Alt_L: - store_modifier("Alt_L", alt_bit); - break; - case XK_Alt_R: - store_modifier("Alt_R", alt_bit); - break; - case XK_Num_Lock: - store_modifier("Num_Lock", num_lock_bit); - break; - case XK_Scroll_Lock: - store_modifier("Scroll_Lock", scroll_lock_bit); - break; - case XK_Control_L: - check_modifier("Control_L", ControlMask); - break; - case XK_Control_R: - check_modifier("Control_R", ControlMask); - break; - case XK_Shift_L: - check_modifier("Shift_L", ShiftMask); - break; - case XK_Shift_R: - check_modifier("Shift_R", ShiftMask); - break; - case XK_Shift_Lock: - check_modifier("Shift_Lock", LockMask); - break; - case XK_Caps_Lock: - check_modifier("Caps_Lock", LockMask); - break; - - /* It probably doesn't make any sense for a modifier bit to be - assigned to a key that is not one of the above, but OpenWindows - assigns modifier bits to a couple of random function keys for - no reason that I can discern, so printing a warning here would - be annoying. */ - } - } - } -#undef store_modifier -#undef check_modifier -#undef modwarn -#undef modbarf - - /* If there was no Meta key, then try using the Alt key instead. - If there is both a Meta key and an Alt key, then the Alt key - is not disturbed and remains an Alt key. */ - if (!meta_bit && alt_bit) - meta_bit = alt_bit, alt_bit = 0; - - /* mode_bit overrides everything, since it's processed down inside of - XLookupString() instead of by us. If Meta and Mode_switch both - generate the same modifier bit (which is an error), then we don't - interpret that bit as Meta, because we can't make XLookupString() - not interpret it as Mode_switch; and interpreting it as both would - be totally wrong. */ - if (mode_bit) { - const char *warn = 0; - if (mode_bit == meta_bit) - warn = "Meta", meta_bit = 0; - else if (mode_bit == hyper_bit) - warn = "Hyper", hyper_bit = 0; - else if (mode_bit == super_bit) - warn = "Super", super_bit = 0; - else if (mode_bit == alt_bit) - warn = "Alt", alt_bit = 0; - if (warn) { - warned_about_overlapping_modifiers = 1; - } - } - - MetaMask = (meta_bit ? (1 << meta_bit) : 0); - HyperMask = (hyper_bit ? (1 << hyper_bit) : 0); - SuperMask = (super_bit ? (1 << super_bit) : 0); - AltMask = (alt_bit ? (1 << alt_bit) : 0); - ModeMask = (mode_bit ? (1 << mode_bit) : 0); /* unused */ - NumLockMask = (num_lock_bit ? (1 << num_lock_bit) : 0); - ScrollLockMask = (scroll_lock_bit ? (1 << scroll_lock_bit) : 0); - - if (x_modifier_keymap) - XFreeModifiermap(x_modifier_keymap); -} - - -int ToolWindow::translateModifier(char *key) -{ - if (strcasecmp(key, "SHIFT") == 0 && ShiftMask != 0) - return ShiftMask; - else if (strcasecmp(key, "CONTROL") == 0 && ControlMask != 0) - return ControlMask; - else if (strcasecmp(key, "ALT") == 0 && AltMask != 0) - return AltMask; - else if (strcasecmp(key, "META") == 0 && MetaMask != 0) - return MetaMask; - else if (strcasecmp(key, "SUPER") == 0 && SuperMask != 0) - return SuperMask; - else if (strcasecmp(key, "HYPER") == 0 && HyperMask != 0) - return HyperMask; - else if (strcasecmp(key, "MOD1") == 0 && Mod1Mask != 0) - return Mod1Mask; - else if (strcasecmp(key, "MOD2") == 0 && Mod2Mask != 0) - return Mod2Mask; - else if (strcasecmp(key, "MOD3") == 0 && Mod3Mask != 0) - return Mod3Mask; - else if (strcasecmp(key, "MOD4") == 0 && Mod4Mask != 0) - return Mod4Mask; - else if (strcasecmp(key, "MOD5") == 0 && Mod5Mask != 0) - return Mod5Mask; - else if (strcasecmp(key, "NONE") == 0) - return None; - else - return -1; -} - -/* Wrapper so that we may fit our naming conventions, yet leave the - original XEmacs function name in place. */ -void ToolWindow::InitializeModifiers(void) -{ - x_reset_modifier_mapping(getXDisplay()); -} - -/*-----------------------------------------------------------------------*/ - -/*-- end of shameless rip. thank you for your support ---*/ - -/*-----------------------------------------------------------------------*/ - -void ToolWindow::CheckConfig() -{ - struct stat file_status; - - if (stat(bbkeys_rcfile, &file_status) != 0) { -#ifdef DEBUG - fprintf(stderr, "Could not open config file ->%s<-\n", - bbkeys_rcfile); -#endif - } else if (file_status.st_mtime != bbkeys_rcTime) { - bbkeys_rcTime = file_status.st_mtime; - loadKeygrabs(); - activateKeygrabs(); - } -} - -void ToolWindow::activateKeygrabs(void) -{ - int i = 0; - - if (grabSet.instructCount > 0) - XUngrabKey(getXDisplay(), AnyKey, AnyModifier, - getCurrentScreenInfo()->getRootWindow()); - for (i = 0; i < grabSet.instructCount; i++) { - if (grabSet.KeyMap[i].keycode == 0) - continue; - - if (grabSet.KeyMap[i].keycode != AnyModifier) { - XGrabKey(getXDisplay(), grabSet.KeyMap[i].keycode, - grabSet.KeyMap[i].modMask | LockMask, - getCurrentScreenInfo()->getRootWindow(), True, - GrabModeAsync, GrabModeAsync); - - /* Also grab all modifier combinations possible that include, - * LockMask, ScrollLockMask and NumLockMask, so that keygrabs - * work even if the NumLock/ScrollLock key is on. - */ - - wHackedGrabKey(grabSet.KeyMap[i].keycode, - grabSet.KeyMap[i].modMask, - getCurrentScreenInfo()->getRootWindow(), True, - GrabModeAsync, GrabModeAsync); - } - - XGrabKey(getXDisplay(), grabSet.KeyMap[i].keycode, - grabSet.KeyMap[i].modMask, - getCurrentScreenInfo()->getRootWindow(), True, - GrabModeAsync, GrabModeAsync); - } -} - -/*---------------------------------------------------------------------------*/ - -/*-- Snarfed shamelessly from WindowMaker's code-base once again.... --*/ - -/*---------------------------------------------------------------------------*/ -void ToolWindow::wHackedGrabKey(int keycode, unsigned int modifiers, - Window grab_window, Bool owner_events, - int pointer_mode, int keyboard_mode) -{ - if (modifiers == AnyModifier) - return; - if (keycode == AnyKey) - return; - - /* grab all combinations of the modifier with CapsLock, NumLock and - * ScrollLock. How much memory/CPU does such a monstrosity consume - * in the server? - */ - if (_NumLockMask) { - XGrabKey(getXDisplay(), keycode, modifiers | _NumLockMask, - grab_window, owner_events, pointer_mode, keyboard_mode); - } - if (_ScrollLockMask) { - XGrabKey(getXDisplay(), keycode, modifiers | _ScrollLockMask, - grab_window, owner_events, pointer_mode, keyboard_mode); - } - if (_NumLockMask && _ScrollLockMask) { - XGrabKey(getXDisplay(), keycode, - modifiers | _NumLockMask | _ScrollLockMask, grab_window, - owner_events, pointer_mode, keyboard_mode); - } - if (_NumLockMask) { - XGrabKey(getXDisplay(), keycode, - modifiers | _NumLockMask | LockMask, grab_window, - owner_events, pointer_mode, keyboard_mode); - } - if (_ScrollLockMask) { - XGrabKey(getXDisplay(), keycode, - modifiers | _ScrollLockMask | LockMask, grab_window, - owner_events, pointer_mode, keyboard_mode); - } - if (_NumLockMask && _ScrollLockMask) { - XGrabKey(getXDisplay(), keycode, - modifiers | _NumLockMask | _ScrollLockMask | LockMask, - grab_window, owner_events, pointer_mode, keyboard_mode); - } - /* phew, I guess that's all, right? */ -} - -void ToolWindow::getOffendingModifiers(void) -{ - int i; - XModifierKeymap *modmap; - KeyCode nlock, slock; - static int mask_table[8] = { - ShiftMask, LockMask, ControlMask, Mod1Mask, - Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask - }; - - nlock = XKeysymToKeycode(getXDisplay(), XK_Num_Lock); - slock = XKeysymToKeycode(getXDisplay(), XK_Scroll_Lock); - - /* - * Find out the masks for the NumLock and ScrollLock modifiers, - * so that we can bind the grabs for when they are enabled too. - */ - modmap = XGetModifierMapping(getXDisplay()); - - if (modmap != NULL && modmap->max_keypermod > 0) { - for (i = 0; i < 8 * modmap->max_keypermod; i++) { - if (modmap->modifiermap[i] == nlock && nlock != 0) - _NumLockMask = mask_table[i / modmap->max_keypermod]; - else if (modmap->modifiermap[i] == slock && slock != 0) - _ScrollLockMask = mask_table[i / modmap->max_keypermod]; - } - } - - if (modmap) - XFreeModifiermap(modmap); -} - -/*-------------------------------------------------------------------------*/ - -/*-- End of shameful code-snarf..................................... --*/ - -/*-------------------------------------------------------------------------*/ - -int ToolWindow::translateAction(char *action) -{ - if (!action) - return 0; - - if (!strcasecmp(action, "Minimize")) - return grabIconify; - if (!strcasecmp(action, "Raise")) - return grabRaise; - if (!strcasecmp(action, "Lower")) - return grabLower; - if (!strcasecmp(action, "Close")) - return grabClose; - if (!strcasecmp(action, "Workspace1")) - return grabWorkspace1; - if (!strcasecmp(action, "Workspace2")) - return grabWorkspace2; - if (!strcasecmp(action, "Workspace3")) - return grabWorkspace3; - if (!strcasecmp(action, "Workspace4")) - return grabWorkspace4; - if (!strcasecmp(action, "Workspace5")) - return grabWorkspace5; - if (!strcasecmp(action, "Workspace6")) - return grabWorkspace6; - if (!strcasecmp(action, "Workspace7")) - return grabWorkspace7; - if (!strcasecmp(action, "Workspace8")) - return grabWorkspace8; - if (!strcasecmp(action, "Workspace9")) - return grabWorkspace9; - if (!strcasecmp(action, "Workspace10")) - return grabWorkspace10; - if (!strcasecmp(action, "Workspace11")) - return grabWorkspace11; - if (!strcasecmp(action, "Workspace12")) - return grabWorkspace12; - if (!strcasecmp(action, "NextWorkspace")) - return grabNextWorkspace; - if (!strcasecmp(action, "PrevWorkspace")) - return grabPrevWorkspace; - if (!strcasecmp(action, "UpWorkspace")) - return grabUpWorkspace; - if (!strcasecmp(action, "DownWorkspace")) - return grabDownWorkspace; - if (!strcasecmp(action, "LeftWorkspace")) - return grabLeftWorkspace; - if (!strcasecmp(action, "RightWorkspace")) - return grabRightWorkspace; - if (!strcasecmp(action, "NextWindow")) - return grabNextWindow; - if (!strcasecmp(action, "PrevWindow")) - return grabPrevWindow; - if (!strcasecmp(action, "NextWindowAllWorkspaces")) - return grabNextWindowAllWorkspaces; - if (!strcasecmp(action, "ShadeWindow")) - return grabShade; - if (!strcasecmp(action, "MaximizeWindow")) - return grabMaximize; - if (!strcasecmp(action, "StickWindow")) - return grabStick; - if (!strcasecmp(action, "ExecCommand")) - return grabExecute; - if (!strcasecmp(action, "MaximizeVertical")) - return grabVertMax; - if (!strcasecmp(action, "MaximizeHorizontal")) - return grabHorizMax; - if (!strcasecmp(action, "NudgeRight")) - return grabNudgeRight; - if (!strcasecmp(action, "NudgeLeft")) - return grabNudgeLeft; - if (!strcasecmp(action, "NudgeUp")) - return grabNudgeUp; - if (!strcasecmp(action, "NudgeDown")) - return grabNudgeDown; - if (!strcasecmp(action, "BigNudgeRight")) - return grabBigNudgeRight; - if (!strcasecmp(action, "BigNudgeLeft")) - return grabBigNudgeLeft; - if (!strcasecmp(action, "BigNudgeUp")) - return grabBigNudgeUp; - if (!strcasecmp(action, "BigNudgeDown")) - return grabBigNudgeDown; - if (!strcasecmp(action, "HorizontalIncrement")) - return grabHorizInc; - if (!strcasecmp(action, "VerticalIncrement")) - return grabVertInc; - if (!strcasecmp(action, "HorizontalDecrement")) - return grabHorizDec; - if (!strcasecmp(action, "VerticalDecrement")) - return grabVertDec; - if (!strcasecmp(action, "ToggleDecor")) - return grabToggleDecor; - - - return 0; -} - -void ToolWindow::execCommand(char *const ptrCommand) -{ - int pid; - extern char **environ; - - pid = fork(); - if (pid == -1) { - fprintf(stderr, - "bbkeys: Could not fork a process for execCommand.\n"); - return; - } - - if (pid == 0) { - const char *const argv[] = { - "sh", - "-c", - ptrCommand, - 0 - }; - execve("/bin/sh", (char *const *)argv, environ); - exit(127); - } -} - -void ToolWindow::setKeygrabs(void) -{ - int res, pid; - - pid = fork(); - - if (pid == -1) { - fprintf(stderr, - "bbkeys: Could not fork a process for configurator.\n"); - return; - } - - if (pid == 0) { - if (noQt) { - // Make 'bbconf' automagically fail... - res = 1; - } else { - string ost = (string)"keybindings:loadfile=" + bbkeys_rcfile; - - res = execlp("bbconf", "bbconf", "--start-plugin", "key bindings", - "--args", ost.c_str(), NULL); - - } - - if (res != 0) { - string ost = (string)"bbkeysconf.pl -rcfile " + bbkeys_rcfile; - - res = execlp("rxvt", "rxvt", "-bg", "black", "-fg", "green", - "-e", "sh", "-c", ost.c_str(), NULL); - if (res != 0) { - execlp("xterm", "xterm", "-bg", "black", "-fg", "green", - "-e", "sh", "-c", ost.c_str(), NULL); - } - } - exit(0); - } - -} - -void ToolWindow::loadKeygrabs(void) -{ - // free up pointers that we get with strdup for execCommand.... - for (register int i = 0; i < grabSet.instructCount; i++) { - if (grabSet.KeyMap[i].execCommand != NULL) { - free(grabSet.KeyMap[i].execCommand); - } - } - memset(&actionList, 0, sizeof(actionList)); - - /* re-initialize our grabSet count... */ - grabSet.instructCount = 0; - - int count = 0; - char line[1024]; - char Keytograb[80]; - char Modifier[80]; - char action[80]; - char execCommand[500]; - char *KeytograbBegin; - char *ModifierBegin; - char *actionBegin; - char *execCmdBegin; - - FILE *rc_file = fopen(bbkeys_rcfile, "r"); - if (!rc_file) { - fprintf(stderr, "\nDanger!!! Warning Will Robinson!!!\n" - "I can't open your bbkeys rc-file (%s).\n" - "Hmm. That means I don't have anything to do. Please run \n" - "the bbkeys configurator of your choice (click my keyhole) \n" - "to allow me to do stuff for ya. \n" - "'Cause otherwise, I just sit here feeling sad....\n\n" - , bbkeys_rcfile); - return; - } - - memset(line, '\0', 1024); - - while (fgets(line, 1024, rc_file) && !feof(rc_file) && - count < MaxInstructions) { - if (line[0] != '#' && strstr(line, "WithModifier")) { - - memset(Keytograb, '\0', 80); - memset(Modifier, '\0', 80); - memset(action, '\0', 80); - memset(execCommand, '\0', 500); - - KeytograbBegin = strchr(line, '('); - ModifierBegin = strchr(KeytograbBegin + 1, '('); - actionBegin = strchr(ModifierBegin + 1, '('); - - strncat(Keytograb, KeytograbBegin + 1, - strcspn(KeytograbBegin + 1, ")")); - strncpy(Modifier, ModifierBegin + 1, - strcspn(ModifierBegin + 1, ")")); - strncpy(action, actionBegin + 1, - strcspn(actionBegin + 1, ")")); - - grabSet.KeyMap[count].keycode = XKeysymToKeycode(getXDisplay(), - XStringToKeysym - (Keytograb)); - - char *k; - char *tmp = (char *) Modifier; - grabSet.KeyMap[count].modMask = 0; - while ((k = strchr(tmp, '+')) != NULL) { - *k = 0; - grabSet.KeyMap[count].modMask |= translateModifier(tmp); - tmp = k + 1; - } - grabSet.KeyMap[count].modMask |= translateModifier(tmp); - - grabSet.KeyMap[count].action = translateAction(action); - // save off a cross-reference for action->grabSet.KeyMap[index] - actionList[grabSet.KeyMap[count].action] = count; - - /* if we're supposed to having an execCommand and we do have - * something to put into it */ - if (grabSet.KeyMap[count].action == grabExecute) { - execCmdBegin = strchr(actionBegin + 1, '('); - if (execCmdBegin) { - strncpy(execCommand, execCmdBegin + 1, - strrchr(execCmdBegin, ')') - execCmdBegin - 1); - grabSet.KeyMap[count].execCommand = - strdup(execCommand); - } - } else { - grabSet.KeyMap[count].execCommand = NULL; - } - -#ifdef DEBUG - fprintf(stdout, "Keysym ->%d<-, Modifier ->0x%lx<-, " - "action ->%d<-, execCommand ->%s<-\n", - grabSet.KeyMap[count].keycode, - grabSet.KeyMap[count].modMask, - grabSet.KeyMap[count].action, - grabSet.KeyMap[count].execCommand); -#endif - count++; - - } - } - fclose(rc_file); - grabSet.instructCount = count; -#ifdef DEBUG - fprintf(stderr, "loaded ->%d<- instructions.\n", count); -#endif -} - -/***************************************** - * * - * END OF KEY GRABBING/HANDLING ROUTINES * - * * - *****************************************/ - -ToolWindow::ToolWindow(int argc, char **argv, struct CMDOPTIONS *options): - Basewindow(argc, argv, options), TimeoutHandler() -{ - timer = new BTimer(this, this); - timer->setTimeout(100); - timer->fireOnce(True); - - if (!(options->bbkeysrc)){ - char *homedir = getenv("HOME"); - bbkeys_rcfile = new char[strlen(homedir) + 32]; - sprintf(bbkeys_rcfile, "%s/.bbkeysrc", homedir); - } else { - bbkeys_rcfile = options->bbkeysrc; - } - - XrmInitialize(); - - InitializeModifiers(); - - _NumLockMask = 0; - _ScrollLockMask = 0; - - /* - * Ignore CapsLock in modifiers - */ - ValidModMask = 0xff & ~LockMask; - - getOffendingModifiers(); - /* - * Ignore NumLock and ScrollLock too - */ - ValidModMask &= ~(_NumLockMask | _ScrollLockMask); - - // initialize it so we don't run into problems later - grabSet.instructCount = 0; - loadKeygrabs(); - activateKeygrabs(); - - resource = new Resource(this); - wminterface = new WMInterface(this); - windowList = new LinkedList < WindowList >; - desktopList = new LinkedList < DesktopList >; - - // initialize variables - current_desktop = NULL; - desktop_count = 0; - doingCycling = False; - - // make draw the bbkeys window - MakeWindow(False); - Redraw(); - - // pass control to the main loop - eventLoop(); -} - -ToolWindow::~ToolWindow() -{ - XUnmapWindow(getXDisplay(), win_frame); - - /* destroy pixmaps */ - if (pixmap.frame) - getImageControl()->removeImage(pixmap.frame); - if (pixmap.pix_title) - getImageControl()->removeImage(pixmap.pix_title); - if (pixmap.pix_back) - getImageControl()->removeImage(pixmap.pix_back); - if (pixmap.pix_configBtn) - getImageControl()->removeImage(pixmap.pix_configBtn); - if (pixmap.pix_closeBtn) - getImageControl()->removeImage(pixmap.pix_closeBtn); - if (pixmap.pix_pressedBtn) - getImageControl()->removeImage(pixmap.pix_pressedBtn); - - /* destroy windows */ - XDestroyWindow(getXDisplay(), win_frame); - XDestroyWindow(getXDisplay(), win_back); - XDestroyWindow(getXDisplay(), win_title); - XDestroyWindow(getXDisplay(), win_configBtn); - XDestroyWindow(getXDisplay(), win_closeBtn); - - /* destroy GC's */ - if (frameGC) XFreeGC(getXDisplay(),frameGC); - if (menuGC) XFreeGC(getXDisplay(),menuGC); - if (menuHiBGGC) XFreeGC(getXDisplay(),menuHiBGGC); - if (menuHiGC) XFreeGC(getXDisplay(),menuHiGC); - if (menuFrameGC) XFreeGC(getXDisplay(),menuFrameGC); - - - /* destroy lists */ - delete windowList; - delete desktopList; -} - -void ToolWindow::reconfigure(void) -{ - /* destroy pixmaps */ - if (pixmap.frame) - getImageControl()->removeImage(pixmap.frame); - if (pixmap.pix_title) - getImageControl()->removeImage(pixmap.pix_title); - if (pixmap.pix_back) - getImageControl()->removeImage(pixmap.pix_back); - if (pixmap.pix_configBtn) - getImageControl()->removeImage(pixmap.pix_configBtn); - if (pixmap.pix_closeBtn) - getImageControl()->removeImage(pixmap.pix_closeBtn); - if (pixmap.pix_pressedBtn) - getImageControl()->removeImage(pixmap.pix_pressedBtn); - - resource->Reload(); - MakeWindow(True); - - stackMenu->reconfigure(); - - XClearWindow(getXDisplay(), win_frame); - XClearWindow(getXDisplay(), win_back); - Redraw(); -} - -void ToolWindow::MakeWindow(bool reconfigure) -{ - XSetWindowAttributes attrib; - XWMHints wmhints; - XClassHint classhints; - XTextProperty windowname; - - unsigned long create_mask = CWBackPixmap | CWBorderPixel | - CWOverrideRedirect | CWCursor | CWEventMask; - - // geometry for our windows................................... - - geom_title.height = resource->label.font->ascent + - resource->label.font->descent + 2; - if (geom_title.height < 20 && (miniMe || tinyMe)) - geom_title.height = 20; - geom_title.width = XTextWidth(resource->label.font, "bbkeys", - strlen("bbkeys")) + (geom_title.height + - 5); - geom_title.x = 2; - geom_title.y = 2; - geom_back.width = geom_title.width + 4; - geom_back.x = 0; - geom_back.y = 0; - geom_closeBtn.height = geom_title.height * 7 / 10; - geom_closeBtn.width = geom_closeBtn.height; - - if (miniMe) { - - geom_back.height = geom_title.height + 2; - geom_closeBtn.y = 80; /* put it out of sight. */ - geom_closeBtn.x = 80; - geom_configBtn.height = geom_title.height - 1; - geom_configBtn.width = geom_configBtn.height; - geom_configBtn.x = geom_title.width - geom_configBtn.width; - geom_configBtn.y = geom_title.y; - - } else if (tinyMe) { - - geom_title.height = 22; - geom_title.width = 22; - geom_title.x = 80; - geom_title.y = 80; - geom_back.width = 22; - geom_back.height = 22; - geom_closeBtn.y = 80; /* put it out of sight. */ - geom_closeBtn.x = 80; - geom_configBtn.height = 20; - geom_configBtn.width = geom_configBtn.height; - geom_configBtn.x = 1; - geom_configBtn.y = 1; - - } else { - - geom_back.height = 3 * (geom_title.height) + 6; - geom_closeBtn.x = geom_title.width - geom_closeBtn.width - 1; - geom_closeBtn.y = geom_title.y + - ((geom_title.height - geom_closeBtn.height) / 2); - geom_configBtn.height = (geom_title.height * 2); - geom_configBtn.width = geom_title.width - 4; - geom_configBtn.x = geom_title.x + 2; - geom_configBtn.y = geom_title.height + geom_title.y + 2; - - } - - frame.height = geom_back.height; - frame.width = geom_back.width; - frame.x = resource->position.x; - frame.y = resource->position.y; - - // end geometry for our windows................................... - - if (resource->position.mask & XNegative) { - frame.x = getCurrentScreenInfo()->getWidth() + - resource->position.x - frame.width; - } - - if (resource->position.mask & YNegative) { - frame.y = getCurrentScreenInfo()->getHeight() + - resource->position.y - frame.height; - - } - - if (withdrawn) { - attrib.override_redirect = False; - wmhints.initial_state = WithdrawnState; - } else if (iconic) { - attrib.override_redirect = False; - wmhints.initial_state = IconicState; - } else { - attrib.override_redirect = False; - wmhints.initial_state = NormalState; - } - - attrib.background_pixmap = ParentRelative; - - pixmap.frame = - getImageControl()->renderImage(frame.width, frame.height, - &resource->frame.texture); - - pixmap.pix_back = - getImageControl()->renderImage(geom_back.width, - geom_back.height, - &resource->frame.texture); - pixmap.pix_title = - getImageControl()->renderImage(geom_title.width, geom_title.height, - &resource->label.texture); - - pixmap.pix_configBtn = - getImageControl()->renderImage(geom_configBtn.width, - geom_configBtn.height, - &resource->button.texture); - - pixmap.pix_closeBtn = - getImageControl()->renderImage(geom_closeBtn.width, - geom_closeBtn.height, - &resource->button.texture); - pixmap.pix_pressedBtn = - getImageControl()->renderImage(geom_configBtn.width, - geom_configBtn.height, - &resource->button.texture_pressed); - - attrib.cursor = getSessionCursor(); - attrib.event_mask = - ButtonPressMask | ButtonReleaseMask | ExposureMask | - FocusChangeMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask | - SubstructureRedirectMask; - - if (!reconfigure) { - win_frame = XCreateWindow(getXDisplay(), - getCurrentScreenInfo()->getRootWindow(), - frame.x, frame.y, frame.width, - frame.height, 0, - getCurrentScreenInfo()->getDepth(), - InputOutput, - getCurrentScreenInfo()->getVisual(), - create_mask, &attrib); - win_back = XCreateWindow(getXDisplay(), - win_frame, - geom_back.x, - geom_back.y, - geom_back.width, - geom_back.height, 0, - getCurrentScreenInfo - ()->getDepth(), InputOutput, - getCurrentScreenInfo - ()->getVisual(), create_mask, &attrib); - win_title = - XCreateWindow(getXDisplay(), win_frame, geom_title.x, - geom_title.y, geom_title.width, - geom_title.height, 0, - getCurrentScreenInfo()->getDepth(), InputOutput, - getCurrentScreenInfo()->getVisual(), create_mask, - &attrib); - win_configBtn = - XCreateWindow(getXDisplay(), win_frame, geom_configBtn.x, - geom_configBtn.y, geom_configBtn.width, - geom_configBtn.height, 0, - getCurrentScreenInfo()->getDepth(), InputOutput, - getCurrentScreenInfo()->getVisual(), create_mask, - &attrib); - win_closeBtn = - XCreateWindow(getXDisplay(), win_frame, geom_closeBtn.x, - geom_closeBtn.y, geom_closeBtn.width, - geom_closeBtn.height, 0, - getCurrentScreenInfo()->getDepth(), InputOutput, - getCurrentScreenInfo()->getVisual(), create_mask, - &attrib); - } else if (!withdrawn) { - XMoveResizeWindow(getXDisplay(), win_frame, frame.x, frame.y, - frame.width, frame.height); - XMoveResizeWindow(getXDisplay(), win_back, - geom_back.x, geom_back.y, - geom_back.width, geom_back.height); - XMoveResizeWindow(getXDisplay(), win_title, geom_title.x, - geom_title.y, geom_title.width, - geom_title.height); - XMoveResizeWindow(getXDisplay(), win_configBtn, geom_configBtn.x, - geom_configBtn.y, geom_configBtn.width, - geom_configBtn.height); - XMoveResizeWindow(getXDisplay(), win_closeBtn, geom_closeBtn.x, - geom_closeBtn.y, geom_closeBtn.width, - geom_closeBtn.height); - - } else { - XResizeWindow(getXDisplay(), win_frame, frame.width, frame.height); - XResizeWindow(getXDisplay(), win_back, - geom_back.width, geom_back.height); - XResizeWindow(getXDisplay(), win_title, geom_title.width, - geom_title.height); - XMoveResizeWindow(getXDisplay(), win_configBtn, geom_configBtn.x, - geom_configBtn.y, geom_configBtn.width, - geom_configBtn.height); - XMoveResizeWindow(getXDisplay(), win_closeBtn, geom_closeBtn.x, - geom_closeBtn.y, geom_closeBtn.width, - geom_closeBtn.height); - } - - char *name = (char *)BBTOOL; - XSizeHints sizehints; - - wmhints.flags = StateHint; - - classhints.res_name = (char *)BBTOOL; - classhints.res_class = (char *)"bbtools"; - - sizehints.x = frame.x; //getResource()->position.x; - sizehints.y = frame.y; //getResource()->position.y; - - sizehints.max_width = sizehints.min_width = frame.width; - sizehints.max_height = sizehints.min_height = frame.height; - sizehints.flags = USPosition | PMinSize | PMaxSize; - - XStringListToTextProperty(&name, 1, &windowname); - XSetWMProperties(getXDisplay(), win_frame, &windowname, NULL, getArgv(), - getArgc(), &sizehints, &wmhints, &classhints); - - // free up allocated memory in XStringListToTextProperty - XFree(windowname.value); - - if (!reconfigure) { - Atom wmproto[2]; - wmproto[0] = wm_delete_window; - wmproto[1] = getBlackboxStructureMessagesAtom(); - XSetWMProtocols(getXDisplay(), win_frame, wmproto, 2); - } - - if (!decorated && !withdrawn) { - BlackboxHints net_hints; - net_hints.decoration = DecorNone; - net_hints.attrib = AttribOmnipresent; - net_hints.flags = AttribDecoration | AttribOmnipresent; - XChangeProperty(getXDisplay(), win_frame, getBlackboxHintsAtom(), - getBlackboxHintsAtom(), 32, PropModeReplace, - (unsigned char *) &net_hints, - PropBlackboxHintsElements); - } - - if (!shape) { - XSetWindowBackgroundPixmap(getXDisplay(), win_frame, pixmap.frame); - } - - XSetWindowBackgroundPixmap(getXDisplay(), win_title, pixmap.pix_title); - XSetWindowBackgroundPixmap(getXDisplay(), win_back, pixmap.pix_back); - XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn, - pixmap.pix_configBtn); - XSetWindowBackgroundPixmap(getXDisplay(), win_closeBtn, - pixmap.pix_closeBtn); - - - if (!reconfigure) { - gcv.font = resource->label.font->fid; - gcv.foreground = resource->label.textColor.getPixel(); - frameGC = - XCreateGC(getXDisplay(), win_frame, GCFont | GCForeground, &gcv); - - gcv.font = resource->menu.font->fid; - gcv.foreground = resource->menu.texture.getColor()->getPixel(); - menuGC = XCreateGC(getXDisplay(), win_frame,GCFont|GCForeground, &gcv); - - gcv.foreground = resource->menu.highlightColor.getPixel(); - gcv.arc_mode = ArcChord; - gcv.fill_style = FillSolid; - menuHiBGGC = XCreateGC(getXDisplay(), win_frame,GCForeground| - GCFillStyle|GCArcMode, &gcv); - - gcv.foreground = resource->menu.hiTextColor.getPixel(); - menuHiGC = XCreateGC(getXDisplay(), win_frame, GCFont|GCForeground, &gcv); - - gcv.foreground = resource->menu.textColor.getPixel(); - menuFrameGC = XCreateGC(getXDisplay(), win_frame,GCFont|GCForeground, &gcv); - - stackMenu = new Stackmenu(this); - stackMenu->update(); - } else { - gcv.font = resource->label.font->fid; - gcv.foreground = resource->label.textColor.getPixel(); - XChangeGC(getXDisplay(), frameGC, GCFont | GCForeground, &gcv); - - gcv.font = resource->menu.font->fid; - gcv.foreground = resource->menu.texture.getColor()->getPixel(); - XChangeGC(getXDisplay(), menuGC, GCFont | GCForeground, &gcv); - - gcv.foreground = resource->menu.highlightColor.getPixel(); - XChangeGC(getXDisplay(), menuHiBGGC, GCFont | GCForeground, &gcv); - - gcv.foreground = resource->menu.hiTextColor.getPixel(); - XChangeGC(getXDisplay(), menuHiGC, GCFont | GCForeground, &gcv); - - gcv.foreground = resource->menu.textColor.getPixel(); - XChangeGC(getXDisplay(), menuFrameGC, GCFont | GCForeground, &gcv); - - } - - - if (!reconfigure) { - XClearWindow(getXDisplay(), win_frame); - XMapWindow(getXDisplay(), win_frame); - XMapSubwindows(getXDisplay(), win_frame); - XSetIconName(getXDisplay(), win_frame, "bbkeys"); - } -} - -void ToolWindow::Redraw() -{ - XClearWindow(getXDisplay(), win_title); - XClearWindow(getXDisplay(), win_configBtn); - XClearWindow(getXDisplay(), win_closeBtn); - - char *title = (char *)"bbkeys"; - XDrawString(getXDisplay(), win_title, frameGC, geom_title.x - 1, - (geom_title.height + resource->label.font->ascent - - resource->label.font->descent) / 2, title, strlen(title)); - - XPoint pts[3]; - - if (miniMe || tinyMe) { - pts[0].x = (geom_configBtn.width / 2); - pts[0].y = (geom_configBtn.height / 2) - 2; - pts[1].x = -(geom_configBtn.width / 4); - pts[1].y = (geom_configBtn.height - pts[0].y) - 1; - pts[2].x = (geom_configBtn.width / 2); - pts[2].y = 0; - - XFillPolygon(getXDisplay(), win_configBtn, frameGC, pts, 3, - Convex, CoordModePrevious); - XFillArc(getXDisplay(), win_configBtn, frameGC, - geom_configBtn.width / 2 - geom_configBtn.width / 4, 1, // x, y - geom_configBtn.width / 2, geom_configBtn.height / 2, //width,height - 0, 360 * 64); - } else { - pts[0].x = (geom_configBtn.width / 2); - pts[0].y = (geom_configBtn.height / 2) - 2; - pts[1].x = -(geom_configBtn.width / 4); - pts[1].y = (geom_configBtn.height - pts[0].y) - 2; - pts[2].x = (geom_configBtn.width / 2); - pts[2].y = 0; - - XFillPolygon(getXDisplay(), win_configBtn, frameGC, pts, 3, - Convex, CoordModePrevious); - XFillArc(getXDisplay(), win_configBtn, frameGC, - geom_configBtn.width / 2 - geom_configBtn.width / 4, 1, // x, y - geom_configBtn.width / 2, geom_configBtn.height * 5 / 8, //width,height - 0, 360 * 64); - } - - /* Our little close button (drawn twice for a nice thickness) */ - XDrawLine(getXDisplay(), win_closeBtn, frameGC, 1, 1, - geom_closeBtn.width - 2, geom_closeBtn.height - 1); - XDrawLine(getXDisplay(), win_closeBtn, frameGC, 1, - geom_closeBtn.height - 1, geom_closeBtn.width - 2, 1); - - XDrawLine(getXDisplay(), win_closeBtn, frameGC, 2, 1, - geom_closeBtn.width - 1, geom_closeBtn.height - 1); - XDrawLine(getXDisplay(), win_closeBtn, frameGC, 2, - geom_closeBtn.height - 1, geom_closeBtn.width - 1, 1); - -} - -unsigned int ToolWindow::KeycodeToModmask(unsigned int code) -{ - switch (XKeycodeToKeysym(getXDisplay(), code, 0)) { - case XK_Shift_L: - case XK_Shift_R: - return ShiftMask; - - case XK_Caps_Lock: - case XK_Shift_Lock: - return LockMask; - - case XK_Control_L: - case XK_Control_R: - return ControlMask; - - case XK_Alt_L: - case XK_Alt_R: - return AltMask ? AltMask : MetaMask; - - case XK_Num_Lock: - return NumLockMask; - - case XK_Super_L: - case XK_Super_R: - return SuperMask; - - case XK_Hyper_L: - case XK_Hyper_R: - return HyperMask; - - case XK_Meta_L: - case XK_Meta_R: - return MetaMask; - - case XK_Scroll_Lock: - return ScrollLockMask; - } - return (unsigned int)-1; -} - - -void ToolWindow::findFramePosition(Window window, int &x, int &y) { - Window win = window, parent, root, last = None; - Window *children = 0; - unsigned int nchildren; - int gravity, top, bottom, left, right; - XWindowAttributes wattr; - XSizeHints size; - long ret; - unsigned int cwidth, cheight; - - // get the location, size and gravity of the client window - if (! XGetWindowAttributes(getXDisplay(), window, &wattr)) return; - cwidth = wattr.width; - cheight = wattr.height; - if (! XGetWMNormalHints(getXDisplay(), window, &size, &ret)) return; - if (size.flags & PWinGravity) - gravity = size.win_gravity; - else - gravity = NorthWestGravity; - - while (XQueryTree(getXDisplay(), win, &root, &parent, &children, - &nchildren)) { - if (children && nchildren > 0) - XFree(children); // don't care about the children - - if (! parent) // no parent!? - return; - - // if the parent window is the root window, stop here - if (parent == root) - break; - - last = win; - win = parent; - } - - if (! (XTranslateCoordinates(getXDisplay(), last, win, 0, 0, &left, &top, - &parent) && - XGetWindowAttributes(getXDisplay(), win, &wattr))) - return; - - right = wattr.width - cwidth - left; - bottom = wattr.height - cheight - top; - - left += wattr.border_width; - right += wattr.border_width; - top += wattr.border_width; - bottom += wattr.border_width; - - // find the client's location - x = wattr.x + left; - y = wattr.y + top; - - // this makes things work. why? i don't know. but you need them. - right -= 2; - bottom -= 2; - - // find the frame's reference position based on the window's gravity - switch (gravity) { - case NorthWestGravity: - x -= left; - y -= top; - break; - case NorthGravity: - x += (left + right) / 2; - y -= top; - break; - case NorthEastGravity: - x += right; - y -= top; - case WestGravity: - x -= left; - y += (top + bottom) / 2; - break; - case CenterGravity: - x += (left + right) / 2; - y += (top + bottom) / 2; - break; - case EastGravity: - x += right; - y += (top + bottom) / 2; - case SouthWestGravity: - x -= left; - y += bottom; - break; - case SouthGravity: - x += (left + right) / 2; - y += bottom; - break; - case SouthEastGravity: - x += right; - y += bottom; - break; - default: - break; - } -} - - -void ToolWindow::process_event(XEvent * e) -{ - switch (e->type) { - case PropertyNotify: - windowAttributeChange(e->xproperty.window); - break; - - case VisibilityNotify: - // **** This will need to change to a better method of keeping the **** // - // **** menu on top when blackbox provides another way! **** // - if (e->xvisibility.window == stackMenu->getWindowID()) - if (e->xvisibility.state != VisibilityUnobscured) - XRaiseWindow(getXDisplay(), stackMenu->getWindowID()); - break; - - case KeyRelease: { - // if stacked cycling is going on.. - if (doingCycling) { - unsigned int mask = KeycodeToModmask(e->xkey.keycode); - unsigned int state = e->xkey.state; - - // get the index for grabSet.KeyMay's prev/next entries, but make - // sure we're not just getting 0 because we don't have keybindings - // for one of them--also, we can't use > 0 as a test for next/prev - // because 0 might very well be the valid index for those bindings - int i = actionList[grabNextWindow]; - int next = grabSet.KeyMap[i].action == grabNextWindow ? i : -1; - int j = actionList[grabNextWindowAllWorkspaces]; - int nextAll = grabSet.KeyMap[j].action == grabNextWindowAllWorkspaces ? j : -1; - int k = actionList[grabPrevWindow]; - int prev = grabSet.KeyMap[k].action == grabPrevWindow ? k : -1; - - // if the key released was the last modifier being held - // and being a member of the nextMask or PrevMask, then select - // the item in the menu that is currently focued. - if (next > -1 && ((state & grabSet.KeyMap[next].modMask) == mask)) - stackMenu->selectFocused(True); - else if (nextAll > -1 && ((state & grabSet.KeyMap[nextAll].modMask) == mask)) - stackMenu->selectFocused(True); - else if (prev > -1 && ((state & grabSet.KeyMap[prev].modMask) == mask)) - stackMenu->selectFocused(True); - } - break; - } - - case KeyPress: { - - int i = 0; - int grabInt = -1; - int fw_y, fw_x; - - if (focus_window) { - findFramePosition(focus_window, fw_x, fw_y); - } - - // if our user wants to grab his keystrokes, even though one - // or more of the Lock-Modifiers are pressed, alter the mask - - - // to make this possible.... - - if (!honor_modifiers) { - e->xkey.state &= ~_NumLockMask & ~_ScrollLockMask & ~LockMask; - } - - for (i = 0; i < grabSet.instructCount; i++) { - if ((e->xkey.keycode == grabSet.KeyMap[i].keycode) && - (e->xkey.state == grabSet.KeyMap[i].modMask)) { - grabInt = i; - break; - } - } - - if (doingCycling) { - if (e->xkey.keycode == XKeysymToKeycode(getXDisplay(), XK_Escape)) { - stackMenu->hide(); - // reset focus to the window we were focused on before window - // cycling began - wminterface->setWindowFocus(focus_window); - } else if (e->xkey.keycode == XKeysymToKeycode(getXDisplay(), XK_Return)) - stackMenu->selectFocused(True); - else - stackMenu->key_press(grabSet.KeyMap[grabInt].action); - } else if (grabInt > -1) { - - /* play with colors for nyz =:) */ - XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn, - pixmap.pix_pressedBtn); - Redraw(); - - switch (grabSet.KeyMap[grabInt].action) { - case grabIconify: - if (focus_window) - XIconifyWindow(getXDisplay(), focus_window, 0); - break; - - case grabRaise: - if (focus_window) - XRaiseWindow(getXDisplay(), focus_window); - break; - - case grabLower: - if (focus_window) - XLowerWindow(getXDisplay(), focus_window); - break; - - case grabClose: - if (!focus_window) - break; - XEvent ce; - ce.xclient.type = ClientMessage; - ce.xclient.message_type = getWMProtocolsAtom(); - ce.xclient.display = getXDisplay(); - ce.xclient.window = focus_window; - ce.xclient.format = 32; - ce.xclient.data.l[0] = getWMDeleteAtom(); - ce.xclient.data.l[1] = CurrentTime; - ce.xclient.data.l[2] = ce.xclient.data.l[3] = - ce.xclient.data.l[4] = 0l; - XSendEvent(getXDisplay(), focus_window, False, NoEventMask, &ce); - break; - - case grabWorkspace1: - wminterface->changeDesktop(0); - break; - - case grabWorkspace2: - wminterface->changeDesktop(1); - break; - - case grabWorkspace3: - wminterface->changeDesktop(2); - break; - - case grabWorkspace4: - wminterface->changeDesktop(3); - break; - - case grabWorkspace5: - wminterface->changeDesktop(4); - break; - - case grabWorkspace6: - wminterface->changeDesktop(5); - break; - - case grabWorkspace7: - wminterface->changeDesktop(6); - break; - - case grabWorkspace8: - wminterface->changeDesktop(7); - break; - - case grabWorkspace9: - wminterface->changeDesktop(8); - break; - - case grabWorkspace10: - wminterface->changeDesktop(9); - break; - - case grabWorkspace11: - wminterface->changeDesktop(10); - break; - - case grabWorkspace12: - wminterface->changeDesktop(11); - break; - - case grabNextWorkspace: - if (current_desktop->number < (desktop_count-1)) - wminterface->changeDesktop(current_desktop->number + 1); - else - wminterface->changeDesktop(0); - break; - - case grabPrevWorkspace: - if (current_desktop->number > 0) - wminterface->changeDesktop(current_desktop->number - 1); - else - wminterface->changeDesktop(desktop_count - 1); - break; - - case grabUpWorkspace: - if (resource->columns > 1) { //ie columns given - if (getCurrentDesktopNr()-resource->columns<0) { - if (getDesktopCount()-1-(getDesktopCount()-1)%resource->columns + - getCurrentDesktopNr()%resource->columns > getDesktopCount() - 1) { - - wminterface->changeDesktop(getDesktopCount() - 1 - - (getDesktopCount() - 1)%resource->columns + - getCurrentDesktopNr()%resource->columns -resource->columns); - - } else { - wminterface->changeDesktop(getDesktopCount() - 1 - - (getDesktopCount() - 1)%resource->columns + - getCurrentDesktopNr()%resource->columns ); - } - } else { - wminterface->changeDesktop(getCurrentDesktopNr() - resource->columns); - } - } else if (resource->rows > 1) { //ie rows given - if (getCurrentDesktopNr()%resource->rows==0) {// if row=1 - if (getCurrentDesktopNr() + resource->rows > getDesktopCount()) - //incomplete last col? - wminterface->changeDesktop(getDesktopCount() - 1); //last desktop - else //complete col - wminterface->changeDesktop(getCurrentDesktopNr() +resource->rows - 1); - //last in column - } else // row>1 - wminterface->changeDesktop(getCurrentDesktopNr() - 1); - } else {} //no arrangement -> insert fallback solution here - - break; - - case grabDownWorkspace: - if (resource->columns > 1) { //ie columns given - if (getCurrentDesktopNr() + resource->columns > getDesktopCount() - 1) - wminterface->changeDesktop(getCurrentDesktopNr()%resource->columns); - else - wminterface->changeDesktop(getCurrentDesktopNr() +resource->columns); - } else if (resource->rows > 1) { //ie rows given - if (getCurrentDesktopNr()%resource->rows + 1 == resource->rows || - getCurrentDesktopNr() + 1 == getDesktopCount()) { - //last row or last in incomplete col - wminterface->changeDesktop(getCurrentDesktopNr() - - getCurrentDesktopNr()%resource->rows); - //first in col - } else - wminterface->changeDesktop(getCurrentDesktopNr() + 1); - } else {} //no arrangement -> fallback solution - - break; - - - case grabLeftWorkspace: - if (resource->columns > 1) { //ie columns given - if (getCurrentDesktopNr()%resource->columns==0) { - if (getCurrentDesktopNr() + resource->columns > getDesktopCount()) - wminterface->changeDesktop(getDesktopCount() -1); - else - wminterface->changeDesktop(getCurrentDesktopNr() + resource->columns - 1); - } else - wminterface->changeDesktop(getCurrentDesktopNr() - 1); - } else if (resource->rows > 1) { //ie rows given - if (getCurrentDesktopNr() - resource->rows<0) {// first col - if (getDesktopCount() - 1 - (getDesktopCount()-1)%resource->rows + - getCurrentDesktopNr()%resource->rows > getDesktopCount() - 1) - //incomplete row - wminterface->changeDesktop(getDesktopCount() - 1 - - (getDesktopCount() - 1)%resource->rows + - getCurrentDesktopNr()%resource->rows - resource->rows); - else - wminterface->changeDesktop(getDesktopCount() - 1 - - (getDesktopCount() - 1)%resource->rows + - getCurrentDesktopNr()%resource->rows ); - } else - wminterface->changeDesktop(getCurrentDesktopNr() - resource->rows); - } else {} //no arrangement -> fallback solution - - break; - - - case grabRightWorkspace: - if (resource->columns > 1) { //ie columns given - if (getCurrentDesktopNr()%resource->columns + 1 == resource->columns || - getCurrentDesktopNr() + 1 == getDesktopCount()) - wminterface->changeDesktop(getCurrentDesktopNr() - - getCurrentDesktopNr()%resource->columns); - else - wminterface->changeDesktop(getCurrentDesktopNr() + 1); - } else if (resource->rows > 1) { //ie rows given - if (getCurrentDesktopNr() + resource->rows > getDesktopCount() - 1) - // last in row - wminterface->changeDesktop(getCurrentDesktopNr()%resource->rows); - // first col - else - wminterface->changeDesktop(getCurrentDesktopNr() + resource->rows); - } else {} //no arrangement -> fallback solution - - break; - - case grabNextWindow: - showAllWorkspaces=false; - cycleWindowFocus(True); - break; - - case grabNextWindowAllWorkspaces: - showAllWorkspaces=true; - cycleWindowFocus(True); - break; - - case grabPrevWindow: - cycleWindowFocus(False); - break; - - case grabShade: - if (focus_window) - wminterface->shadeWindow(focus_window); - break; - - case grabStick: - if (focus_window) - wminterface->stickWindow(focus_window); - break; - - case grabExecute: - execCommand((char *const)grabSet.KeyMap[grabInt].execCommand); - break; - - case grabMaximize: - if (focus_window) - wminterface->maximizeWindow(focus_window, True, True); - break; - - case grabVertMax: - if (focus_window) - wminterface->maximizeWindow(focus_window, False, True); - break; - - case grabHorizMax: - if (focus_window) - wminterface->maximizeWindow(focus_window, True, False); - break; - - case grabNudgeRight: - if (focus_window) - XMoveWindow(getXDisplay(), focus_window, fw_x + 1, fw_y); - break; - - case grabNudgeLeft: - if (focus_window) - XMoveWindow(getXDisplay(), focus_window, fw_x - 1, fw_y); - break; - - case grabNudgeUp: - if (focus_window) - XMoveWindow(getXDisplay(), focus_window, fw_x, fw_y - 1); - break; - - case grabNudgeDown: - if (focus_window) - XMoveWindow(getXDisplay(), focus_window, fw_x, fw_y + 1); - break; - - case grabBigNudgeRight: - if (focus_window) - XMoveWindow(getXDisplay(), focus_window, fw_x + 10, fw_y); - break; - - case grabBigNudgeLeft: - if (focus_window) - XMoveWindow(getXDisplay(), focus_window, fw_x - 10, fw_y); - break; - - case grabBigNudgeUp: - if (focus_window) - XMoveWindow(getXDisplay(), focus_window, fw_x, fw_y - 10); - break; - - case grabBigNudgeDown: - if (focus_window) - XMoveWindow(getXDisplay(), focus_window, fw_x, fw_y + 10); - break; - - case grabHorizInc: - if (focus_window) { - XWindowAttributes foo; - XGetWindowAttributes(getXDisplay(), focus_window, &foo); - XResizeWindow(getXDisplay(), focus_window, - foo.width + 10, foo.height); - } - break; - - case grabVertInc: - if (focus_window) { - XWindowAttributes foo; - XGetWindowAttributes(getXDisplay(), focus_window, &foo); - XResizeWindow(getXDisplay(), focus_window, - foo.width, foo.height + 10); - } - break; - - case grabHorizDec: - if (focus_window) { - XWindowAttributes foo; - XGetWindowAttributes(getXDisplay(), focus_window, &foo); - if (foo.width < 11) - foo.width = 11; - XResizeWindow(getXDisplay(), focus_window, - foo.width - 10, foo.height); - } - break; - - case grabVertDec: - if (focus_window) { - XWindowAttributes foo; - XGetWindowAttributes(getXDisplay(), focus_window, &foo); - if (foo.height < 11) - foo.height = 11; - XResizeWindow(getXDisplay(), focus_window, - foo.width, foo.height - 10); - } - break; - - case grabToggleDecor: - if (focus_window) - wminterface->decorateToggleWindow(focus_window); - break; - } - } - timer->start(); - break; - } - - case ClientMessage: - if ((unsigned) e->xclient.data.l[0] == wm_delete_window) - shutdown(); - wminterface->handleNETEvents(*e); - break; - - case Expose: - if (!e->xexpose.count) - reconfigure(); - break; - - case ButtonPress: - if (e->xbutton.button == LEFT_BUTTON - || e->xbutton.button == RIGHT_BUTTON) { - if (e->xbutton.window == win_configBtn) { - XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn, - pixmap.pix_pressedBtn); - Redraw(); - } else if (e->xbutton.window == win_closeBtn) { - XSetWindowBackgroundPixmap(getXDisplay(), win_closeBtn, - pixmap.pix_pressedBtn); - Redraw(); - } else if (e->xbutton.window == win_title) { -// if (!raised) - XRaiseWindow(getXDisplay(), win_frame); -// raised = True; - } - } else if (e->xbutton.button == MIDDLE_BUTTON) { -// if (raised) - XLowerWindow(getXDisplay(), win_frame); -// raised = False; - } - break; - - case ButtonRelease: - if (e->xbutton.button == LEFT_BUTTON - || e->xbutton.button == RIGHT_BUTTON) { - if (e->xbutton.window == win_configBtn) { - if ((e->xbutton.x > 0) - && (e->xbutton.x < geom_configBtn.width) - && (e->xbutton.y > 0) - && (e->xbutton.y < geom_configBtn.height)) { - if (grabSet.instructCount > 0) { - XUngrabKey(getXDisplay(), AnyKey, AnyModifier, - getScreenInfo(0)->getRootWindow()); - XSync(getXDisplay(), False); - } - setKeygrabs(); - - // discard all XEvents (was causing us to go bananas on the - // user before, since we were executing all keygrabs at once - // that the user did when the configuration app was running) - // *cough* undocumented feature *cough* - // - - XEvent event; - while (XPending(getXDisplay())) { - XNextEvent(getXDisplay(), &event); - } - - // carry on then, little soldier - - loadKeygrabs(); - activateKeygrabs(); - timer->start(); - } - - XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn, - pixmap.pix_configBtn); - Redraw(); - } else if (e->xbutton.window == win_closeBtn) { - if ((e->xbutton.x > 0) - && (e->xbutton.x < geom_closeBtn.width) - && (e->xbutton.y > 0) - && (e->xbutton.y < geom_closeBtn.height)) { - if (e->xbutton.button == LEFT_BUTTON) { - shutdown(); - } else if (e->xbutton.button == RIGHT_BUTTON) { - if (withdrawn) { - XUnmapWindow(getXDisplay(), win_frame); - withdrawn = False; - iconic = True; - - XWMHints wmhints; - wmhints.initial_state = IconicState; - wmhints.flags = StateHint; - XSetWMHints(getXDisplay(), win_frame, &wmhints); - XMapWindow(getXDisplay(), win_frame); - - // this should work but doesn't seem to. *shrug* - // reconfigure(); - } else { - XIconifyWindow(getXDisplay(), win_frame, 0); - } - } - } - XSetWindowBackgroundPixmap(getXDisplay(), win_closeBtn, - pixmap.pix_configBtn); - Redraw(); - } - } - break; - - case ConfigureNotify: - if ((e->xconfigure.window == win_frame) && e->xconfigure.send_event) { - if (withdrawn) - reconfigure(); - - int parent_x, parent_y; - Window parent_root; - unsigned int parent_width, parent_height, parent_border_width; - unsigned int parent_depth; - - if (withdrawn) { - XGetGeometry(getXDisplay(), e->xconfigure.above, - &parent_root, &parent_x, &parent_y, - &parent_width, &parent_height, - &parent_border_width, &parent_depth); - frame.x = e->xconfigure.x + parent_x; - frame.y = e->xconfigure.y + parent_y; - } - } - break; - } -} - -void ToolWindow::timeout(void) -{ - XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn, - pixmap.pix_configBtn); - Redraw(); -} - -/*--------------------------------*/ - -/*- window modifying functions -*/ - -/*--------------------------------*/ - -void ToolWindow::raiseWindow(Window) -{ -} - -void ToolWindow::lowerWindow(Window) -{ -} - -/*---------------------------------------*/ - -/*- desktop list management functions -*/ - -/*---------------------------------------*/ - -void ToolWindow::addDesktop(void) -{ - DesktopList *tmp = new DesktopList; - - // get the highest in the list - int highest = -1; - LinkedListIterator it(desktopList); - for (; it.current(); it++) - if (it.current()->number > highest) { - highest = it.current()->number; - it.reset(); - } - tmp->number = highest + 1; - - desktopList->insert(tmp, -1); // add to the end of the list - - desktop_count++; - - // add sticky windows to this desktop - LinkedListIterator it_win(windowList); - for (; it_win.current(); it_win++) - // only look for sticky windows on desktop 0, this will give us one - // copy of each sticky window - if ((it_win.current()->desktop == 0) && (it_win.current()->sticky)) { - WindowList *win = new WindowList; - win->win = it_win.current()->win; - win->iconic = it_win.current()->iconic; - win->shaded = False; - win->sticky = True; - win->desktop = tmp->number; - windowList->insert(win, -1); // add to the end of the list - } -} - -void ToolWindow::removeDesktop(int desktop) -{ - LinkedListIterator it(desktopList); - LinkedListIterator it_win(windowList); - - // remove sticky windows from this desktop - for (; it_win.current(); it_win++) - if ((it_win.current()->desktop == desktop) - && (it_win.current()->sticky)) - windowList->remove(it_win.current()); // remove just this window - // removeWindow() would remove all - // of the sticky windows. - - // remove the desktop from the linked list - for (; it.current(); it++) - if (it.current()->number == desktop) { - desktopList->remove(it.current()); - break; - } - - desktop_count--; - - // shift the rest to fill in the hole if not the last desktop was rm'd - int check=0; - bool found; - do { - found=False; - it.reset(); - for (; it.current(); it++) - if (it.current()->number == check) { - ++check; - found=True; - } - } while (found); - - // check is on the new hole, or desktop_count if there is no hole - // plug the hole by moving all the desktops above down one - while (check < desktop_count) { - it.reset(); - for (; it.current(); it++) - if(it.current()->number == (check + 1)) { - it.current()->number = check++; - break; - } - } -} - -void ToolWindow::focusDesktop(int desktop) -{ - LinkedListIterator it(desktopList); - for (; it.current(); it++) - if (it.current()->number == desktop) - current_desktop = it.current(); -} - -void ToolWindow::setDesktopCount(int count) -{ - int oldcount = desktop_count; - int delta = count - oldcount; - - if (delta > 0) { // added desktops - while(delta-- > 0) - addDesktop(); - } - else { // removed desktops - while(delta++ < 0) - removeDesktop(desktop_count - 1); // remove the last desktop - } -} - -/*--------------------------------------*/ - -/*- window list management functions -*/ - -/*--------------------------------------*/ - -void ToolWindow::clearWindows(void) -{ - focusWindow(0); - while (! windowList->empty()) - windowList->remove(0); -} - -void ToolWindow::removeWindow(Window win) -{ - if (focus_window == win) - focusWindow(0); - for (int i = 0; i < windowList->count(); ++i) - if (windowList->find(i)->win == win) - windowList->remove(i--); -} - -void ToolWindow::focusWindow(Window win) -{ - // have to only do this when the menu isn't visible, because we're - // setting focus while we're cycling.... Unfortunately, a side-effect - // of this is that we don't get a final focusWindow hit when we raise - // the selected window when done cycling, so we do an explicit - // bbtool->focusWindow() call from Stackmenu::selectFocused() after we - // XRaise the window.... - - if (! doingCycling ) { - focus_window = win; - if (resource->getMenuStackedCycling()) - focus_stack(win); - } -} - -void ToolWindow::moveWinToDesktop(Window win, int desktop) -{ - LinkedListIterator it(windowList); - for (; it.current(); it++) - if (it.current()->win == win) { - if (!it.current()->sticky) { - it.current()->desktop = desktop; - } - break; - } -} - -void ToolWindow::addSticky(WindowList *win) { - win->sticky = True; - LinkedListIterator it(desktopList); - for (; it.current(); it++) - if (win->desktop != it.current()->number) { - WindowList *copy = new WindowList; - copy->win = win->win; - copy->iconic = win->iconic; - copy->shaded = win->shaded; - copy->sticky = True; - copy->desktop = it.current()->number; - windowList->insert(copy, -1); - } -} - -void ToolWindow::removeSticky(const Window win, const int desktop) { - LinkedListIterator it(windowList); - for (register int i=0; i < desktop_count; i++) { - it.reset(); - for (; it.current(); it++) - if (it.current()->win == win) - if (it.current()->desktop != desktop) - windowList->remove(it.current()); - else - it.current()->sticky = False; - } -} - -void ToolWindow::windowAttributeChange(Window win) { - Atom real_type; - int format; - unsigned long n, extra; - WindowList *window = NULL; - BlackboxHints *net_hint; - LinkedListIterator it(windowList); - - for (; it.current(); it++) // find the window that's changed - if (it.current()->win == win) - window = it.current(); - if (!window) - return; - if (!(XGetWindowProperty(getXDisplay(), window->win, - getBlackboxAttributesAtom(), 0L, - PropBlackboxHintsElements, False, - getBlackboxAttributesAtom(), &real_type, - &format, &n, &extra, (unsigned char**)&net_hint) - == Success && net_hint)) - return; - if (n != PropBlackboxHintsElements) - return; - - if (net_hint->flags & AttribShaded) { - if (net_hint->attrib & AttribShaded) - window->shaded = True; - } else if (window->shaded) - window->shaded = False; - - if (wminterface->isIconicState(window->win) != window->iconic && - !window->shaded) - window->iconic = !window->iconic; - - if (net_hint->flags & AttribOmnipresent) { - if (net_hint->attrib & AttribOmnipresent) - if (!window->sticky) addSticky(window); - } else if (window->sticky) - if (window->sticky) removeSticky(window->win, getCurrentDesktopNr()); -} - -void ToolWindow::addWindow(Window win, int desktop) -{ - WindowList *newwin = new WindowList; - newwin->win = win; - newwin->iconic = wminterface->isIconicState(win); - newwin->shaded = False; - newwin->sticky = False; - newwin->desktop = desktop; - XSelectInput(getXDisplay(),newwin->win, - PropertyChangeMask); - if (resource->getMenuStackedCycling()) - add_stack(newwin); - else - add_linear(newwin); -} - -void ToolWindow::cycleWindowFocus(bool forward) -{ - if (resource->getMenuStackedCycling()) - cycle_stack(forward); - else - cycle_linear(forward); -} - -/******************************************************************************* - - LINEAR CYCLING FUNCTIONS - -*******************************************************************************/ - -void ToolWindow::add_linear(WindowList *newwin) -{ - int i; - int index = 0; // where the new window will be placed (defaults to the - // top of the list) - // insert after the focused window - LinkedListIterator it(windowList); - for (i=0; icount(); i++) { - it.set(i); - if (it.current()->win == focus_window) { - // get the index of the focused window - index = i+1; - break; - } - } - windowList->insert(newwin, index); -} - -void ToolWindow::cycle_linear(bool forward) -{ -/******************************************* - This does the oldschool straight rotation - order of cycling windows. -********************************************/ - int desktop = -1; - bool found = False; - WindowList *next = NULL; - int i, max; - - LinkedListIterator it(windowList); - max = windowList->count(); - for (i=0; idesktop == desktop) { - next = it.current(); - break; - } - } - if (it.current()->win == focus_window) { - found = True; - desktop = it.current()->desktop; - } - } - // if the next window wasn't found, start over at the beginning once more - if (!next) - { - for (i=0; idesktop == desktop) { - next = it.current(); - break; - } - } - } - - if (next) { - wminterface->setWindowFocus(next->win); - XRaiseWindow(getXDisplay(), next->win); - } -} - -/******************************************************************************* - - STACK CYCLING FUNCTIONS - -*******************************************************************************/ - -void ToolWindow::add_stack(WindowList *newwin) { - windowList->insert(newwin, 0); // insert at the top of the list - stackMenu->setMenuItems(); -} - -void ToolWindow::cycle_stack(bool forward) { - register bool showMenu = resource->getMenuShowCycleMenu() ? True : False; - stackMenu->show(forward, showMenu); -} - -void ToolWindow::focus_stack(Window win) -{ - WindowList *window = new WindowList; - LinkedListIterator it(windowList); - for (; it.current(); it++) { - if (it.current()->win == win) - if ((!it.current()->sticky) || - (it.current()->desktop == getCurrentDesktopNr())) - break; - } - if (it.current()) { - window->win = it.current()->win; - window->shaded = it.current()->shaded; - window->sticky = it.current()->sticky; - window->iconic = it.current()->iconic; - window->desktop = it.current()->desktop; - windowList->remove(it.current()); // remove it - windowList->insert(window, 0); // add it to the top - } -} - -void ToolWindow::saveMenuSearch(Window window, Basemenu *) -{ - menuWin = window; -} - -void ToolWindow::removeMenuSearch(Window) -{ - menuWin = (Window)NULL; -} - -void ToolWindow::p() -{ -printf("window | stick | shade | icon | desk\n"); -LinkedListIterator it(windowList); -for (; it.current(); it++) - printf("%010i | %d | %d | %d | %d\n", (int)it.current()->win, - it.current()->sticky, it.current()->shaded, it.current()->iconic, - it.current()->desktop); -} - +// bbkeys.cc for blackbox +// ------ note from the Gee-I'm-Sorry-The-Code-Looks-Ugly department----- +// ------ for vi users-- ":set ts=2" =:) +// +// Copyright (c) 1999-2001 by Jason Kasper (vanRijn) vR@movingparts.net +// Copyright (c) 2001 by Ben Jansens +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// (See the included file COPYING / GPL-2.0) +// +// $Id$ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STDIO_H +# include +#endif // HAVE_STDIO_H + +#ifdef HAVE_CTYPE_H +# include +#endif // HAVE_CTYPE_H + +#ifdef STDC_HEADERS +# include +# include +#endif // STDC_HEADERS + +#if HAVE_STRINGS_H +# include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif // HAVE_SYS_TYPES_H + +#ifdef HAVE_SYS_WAIT_H +# include +#endif // HAVE_SYS_WAIT_H + +#ifdef HAVE_ERRNO_H +# include +#endif // HAVE_ERRNO_H + +#ifdef HAVE_UNISTD_H +# include +#endif // HAVE_UNISTD_H + +#ifdef HAVE_SYS_STAT_H +# include +#endif // HAVE_SYS_STAT_H + +extern "C" { +#include +#include +#include +} + +#include "bbkeys.hh" +#include "stackmenu.hh" +#include "resource.hh" +#include "main.hh" +#include "Timer.hh" +#include "Basemenu.hh" +#include "wminterface.hh" + +#include + +using std::string; + +/*--------------------------------------------------------------------*/ + +/* Ripped shamelessly from wmaker's xmodifier.c--converted for our use*/ + +/*--------------------------------------------------------------------*/ + +/* Grok X modifier mappings for shortcuts. + +Most of this code was taken from src/event-Xt.c in XEmacs 20.3-b17. +The copyright(s) from the original XEmacs code are included below. + +Perpetrator: Sudish Joseph , Sept. 1997. */ + +/* The event_stream interface for X11 with Xt, and/or tty frames. + Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1995 Sun Microsystems, Inc. + Copyright (C) 1996 Ben Wing. + + This file is part of XEmacs. + + XEmacs is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + XEmacs is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with XEmacs; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/************************************************************************/ + +/* keymap handling */ + +/************************************************************************/ + +/* X bogusly doesn't define the interpretations of any bits besides + ModControl, ModShift, and ModLock; so the Interclient Communication + Conventions Manual says that we have to bend over backwards to figure + out what the other modifier bits mean. According to ICCCM: + + - Any keycode which is assigned ModControl is a "control" key. + + - Any modifier bit which is assigned to a keycode which generates Meta_L + or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper, + etc. + + - Any keypress event which contains ModControl in its state should be + interpreted as a "control" character. + + - Any keypress event which contains a modifier bit in its state which is + generated by a keycode whose corresponding keysym is Meta_L or Meta_R + should be interpreted as a "meta" character. Likewise for Super, Hyper, + etc. + + - It is illegal for a keysym to be associated with more than one modifier + bit. + + This means that the only thing that emacs can reasonably interpret as a + "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates + one of the modifier bits Mod1-Mod5. + + Unfortunately, many keyboards don't have Meta keys in their default + configuration. So, if there are no Meta keys, but there are "Alt" keys, + emacs will interpret Alt as Meta. If there are both Meta and Alt keys, + then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to + mean "Symbol," but that just confused the hell out of way too many people). + + This works with the default configurations of the 19 keyboard-types I've + checked. + + Emacs detects keyboard configurations which violate the above rules, and + prints an error message on the standard-error-output. (Perhaps it should + use a pop-up-window instead.) +*/ + +static int MetaMask, HyperMask, SuperMask, AltMask, ModeMask; +static int NumLockMask, ScrollLockMask; + +const char *ToolWindow::index_to_name(int indice) +{ + switch (indice) { + case ShiftMapIndex: + return "ModShift"; + case LockMapIndex: + return "ModLock"; + case ControlMapIndex: + return "ModControl"; + case Mod1MapIndex: + return "Mod1"; + case Mod2MapIndex: + return "Mod2"; + case Mod3MapIndex: + return "Mod3"; + case Mod4MapIndex: + return "Mod4"; + case Mod5MapIndex: + return "Mod5"; + default: + return "???"; + } +} + +void ToolWindow::x_reset_modifier_mapping(Display * d) +{ + int modifier_index, modifier_key, column, mkpm; + int warned_about_overlapping_modifiers = 0; + int warned_about_predefined_modifiers = 0; + int warned_about_duplicate_modifiers = 0; + int meta_bit = 0; + int hyper_bit = 0; + int super_bit = 0; + int alt_bit = 0; + int mode_bit = 0; + int num_lock_bit = 0; + int scroll_lock_bit = 0; + XModifierKeymap *x_modifier_keymap = XGetModifierMapping(d); + +#define modwarn(name,old,other) \ + warned_about_overlapping_modifiers = 1 + +#define modbarf(name,other) \ + warned_about_predefined_modifiers = 1 + +#define check_modifier(name,mask) \ + warned_about_predefined_modifiers = 1 + +#define store_modifier(name,old) \ + if (old && old != modifier_index) \ + warned_about_duplicate_modifiers = 1; \ + if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift"); \ + else if (modifier_index == LockMapIndex) modbarf (name,"ModLock"); \ + else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \ + else if (sym == XK_Mode_switch) \ + mode_bit = modifier_index; /* Mode_switch is special, see below... */ \ + else if (modifier_index == meta_bit && old != meta_bit) \ + modwarn (name, meta_bit, "Meta"); \ + else if (modifier_index == super_bit && old != super_bit) \ + modwarn (name, super_bit, "Super"); \ + else if (modifier_index == hyper_bit && old != hyper_bit) \ + modwarn (name, hyper_bit, "Hyper"); \ + else if (modifier_index == alt_bit && old != alt_bit) \ + modwarn (name, alt_bit, "Alt"); \ + else \ + old = modifier_index; + + mkpm = x_modifier_keymap->max_keypermod; + for (modifier_index = 0; modifier_index < 8; modifier_index++) + for (modifier_key = 0; modifier_key < mkpm; modifier_key++) { + KeySym last_sym = 0; + for (column = 0; column < 4; column += 2) { + KeyCode code = + x_modifier_keymap->modifiermap[modifier_index * mkpm + + modifier_key]; + KeySym sym = + (code ? XKeycodeToKeysym(d, code, column) : 0); + if (sym == last_sym) + continue; + last_sym = sym; + switch (sym) { + case XK_Mode_switch: + store_modifier("Mode_switch", mode_bit); + break; + case XK_Meta_L: + store_modifier("Meta_L", meta_bit); + break; + case XK_Meta_R: + store_modifier("Meta_R", meta_bit); + break; + case XK_Super_L: + store_modifier("Super_L", super_bit); + break; + case XK_Super_R: + store_modifier("Super_R", super_bit); + break; + case XK_Hyper_L: + store_modifier("Hyper_L", hyper_bit); + break; + case XK_Hyper_R: + store_modifier("Hyper_R", hyper_bit); + break; + case XK_Alt_L: + store_modifier("Alt_L", alt_bit); + break; + case XK_Alt_R: + store_modifier("Alt_R", alt_bit); + break; + case XK_Num_Lock: + store_modifier("Num_Lock", num_lock_bit); + break; + case XK_Scroll_Lock: + store_modifier("Scroll_Lock", scroll_lock_bit); + break; + case XK_Control_L: + check_modifier("Control_L", ControlMask); + break; + case XK_Control_R: + check_modifier("Control_R", ControlMask); + break; + case XK_Shift_L: + check_modifier("Shift_L", ShiftMask); + break; + case XK_Shift_R: + check_modifier("Shift_R", ShiftMask); + break; + case XK_Shift_Lock: + check_modifier("Shift_Lock", LockMask); + break; + case XK_Caps_Lock: + check_modifier("Caps_Lock", LockMask); + break; + + /* It probably doesn't make any sense for a modifier bit to be + assigned to a key that is not one of the above, but OpenWindows + assigns modifier bits to a couple of random function keys for + no reason that I can discern, so printing a warning here would + be annoying. */ + } + } + } +#undef store_modifier +#undef check_modifier +#undef modwarn +#undef modbarf + + /* If there was no Meta key, then try using the Alt key instead. + If there is both a Meta key and an Alt key, then the Alt key + is not disturbed and remains an Alt key. */ + if (!meta_bit && alt_bit) + meta_bit = alt_bit, alt_bit = 0; + + /* mode_bit overrides everything, since it's processed down inside of + XLookupString() instead of by us. If Meta and Mode_switch both + generate the same modifier bit (which is an error), then we don't + interpret that bit as Meta, because we can't make XLookupString() + not interpret it as Mode_switch; and interpreting it as both would + be totally wrong. */ + if (mode_bit) { + const char *warn = 0; + if (mode_bit == meta_bit) + warn = "Meta", meta_bit = 0; + else if (mode_bit == hyper_bit) + warn = "Hyper", hyper_bit = 0; + else if (mode_bit == super_bit) + warn = "Super", super_bit = 0; + else if (mode_bit == alt_bit) + warn = "Alt", alt_bit = 0; + if (warn) { + warned_about_overlapping_modifiers = 1; + } + } + + MetaMask = (meta_bit ? (1 << meta_bit) : 0); + HyperMask = (hyper_bit ? (1 << hyper_bit) : 0); + SuperMask = (super_bit ? (1 << super_bit) : 0); + AltMask = (alt_bit ? (1 << alt_bit) : 0); + ModeMask = (mode_bit ? (1 << mode_bit) : 0); /* unused */ + NumLockMask = (num_lock_bit ? (1 << num_lock_bit) : 0); + ScrollLockMask = (scroll_lock_bit ? (1 << scroll_lock_bit) : 0); + + if (x_modifier_keymap) + XFreeModifiermap(x_modifier_keymap); +} + + +int ToolWindow::translateModifier(char *key) +{ + if (strcasecmp(key, "SHIFT") == 0 && ShiftMask != 0) + return ShiftMask; + else if (strcasecmp(key, "CONTROL") == 0 && ControlMask != 0) + return ControlMask; + else if (strcasecmp(key, "ALT") == 0 && AltMask != 0) + return AltMask; + else if (strcasecmp(key, "META") == 0 && MetaMask != 0) + return MetaMask; + else if (strcasecmp(key, "SUPER") == 0 && SuperMask != 0) + return SuperMask; + else if (strcasecmp(key, "HYPER") == 0 && HyperMask != 0) + return HyperMask; + else if (strcasecmp(key, "MOD1") == 0 && Mod1Mask != 0) + return Mod1Mask; + else if (strcasecmp(key, "MOD2") == 0 && Mod2Mask != 0) + return Mod2Mask; + else if (strcasecmp(key, "MOD3") == 0 && Mod3Mask != 0) + return Mod3Mask; + else if (strcasecmp(key, "MOD4") == 0 && Mod4Mask != 0) + return Mod4Mask; + else if (strcasecmp(key, "MOD5") == 0 && Mod5Mask != 0) + return Mod5Mask; + else if (strcasecmp(key, "NONE") == 0) + return None; + else + return -1; +} + +/* Wrapper so that we may fit our naming conventions, yet leave the + original XEmacs function name in place. */ +void ToolWindow::InitializeModifiers(void) +{ + x_reset_modifier_mapping(getXDisplay()); +} + +/*-----------------------------------------------------------------------*/ + +/*-- end of shameless rip. thank you for your support ---*/ + +/*-----------------------------------------------------------------------*/ + +void ToolWindow::CheckConfig() +{ + struct stat file_status; + + if (stat(bbkeys_rcfile, &file_status) != 0) { +#ifdef DEBUG + fprintf(stderr, "Could not open config file ->%s<-\n", + bbkeys_rcfile); +#endif + } else if (file_status.st_mtime != bbkeys_rcTime) { + bbkeys_rcTime = file_status.st_mtime; + loadKeygrabs(); + activateKeygrabs(); + } +} + +void ToolWindow::activateKeygrabs(void) +{ + int i = 0; + + if (grabSet.instructCount > 0) + XUngrabKey(getXDisplay(), AnyKey, AnyModifier, + getCurrentScreenInfo()->getRootWindow()); + for (i = 0; i < grabSet.instructCount; i++) { + if (grabSet.KeyMap[i].keycode == 0) + continue; + + if (grabSet.KeyMap[i].keycode != AnyModifier) { + XGrabKey(getXDisplay(), grabSet.KeyMap[i].keycode, + grabSet.KeyMap[i].modMask | LockMask, + getCurrentScreenInfo()->getRootWindow(), True, + GrabModeAsync, GrabModeAsync); + + /* Also grab all modifier combinations possible that include, + * LockMask, ScrollLockMask and NumLockMask, so that keygrabs + * work even if the NumLock/ScrollLock key is on. + */ + + wHackedGrabKey(grabSet.KeyMap[i].keycode, + grabSet.KeyMap[i].modMask, + getCurrentScreenInfo()->getRootWindow(), True, + GrabModeAsync, GrabModeAsync); + } + + XGrabKey(getXDisplay(), grabSet.KeyMap[i].keycode, + grabSet.KeyMap[i].modMask, + getCurrentScreenInfo()->getRootWindow(), True, + GrabModeAsync, GrabModeAsync); + } +} + +/*---------------------------------------------------------------------------*/ + +/*-- Snarfed shamelessly from WindowMaker's code-base once again.... --*/ + +/*---------------------------------------------------------------------------*/ +void ToolWindow::wHackedGrabKey(int keycode, unsigned int modifiers, + Window grab_window, Bool owner_events, + int pointer_mode, int keyboard_mode) +{ + if (modifiers == AnyModifier) + return; + if (keycode == AnyKey) + return; + + /* grab all combinations of the modifier with CapsLock, NumLock and + * ScrollLock. How much memory/CPU does such a monstrosity consume + * in the server? + */ + if (_NumLockMask) { + XGrabKey(getXDisplay(), keycode, modifiers | _NumLockMask, + grab_window, owner_events, pointer_mode, keyboard_mode); + } + if (_ScrollLockMask) { + XGrabKey(getXDisplay(), keycode, modifiers | _ScrollLockMask, + grab_window, owner_events, pointer_mode, keyboard_mode); + } + if (_NumLockMask && _ScrollLockMask) { + XGrabKey(getXDisplay(), keycode, + modifiers | _NumLockMask | _ScrollLockMask, grab_window, + owner_events, pointer_mode, keyboard_mode); + } + if (_NumLockMask) { + XGrabKey(getXDisplay(), keycode, + modifiers | _NumLockMask | LockMask, grab_window, + owner_events, pointer_mode, keyboard_mode); + } + if (_ScrollLockMask) { + XGrabKey(getXDisplay(), keycode, + modifiers | _ScrollLockMask | LockMask, grab_window, + owner_events, pointer_mode, keyboard_mode); + } + if (_NumLockMask && _ScrollLockMask) { + XGrabKey(getXDisplay(), keycode, + modifiers | _NumLockMask | _ScrollLockMask | LockMask, + grab_window, owner_events, pointer_mode, keyboard_mode); + } + /* phew, I guess that's all, right? */ +} + +void ToolWindow::getOffendingModifiers(void) +{ + int i; + XModifierKeymap *modmap; + KeyCode nlock, slock; + static int mask_table[8] = { + ShiftMask, LockMask, ControlMask, Mod1Mask, + Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask + }; + + nlock = XKeysymToKeycode(getXDisplay(), XK_Num_Lock); + slock = XKeysymToKeycode(getXDisplay(), XK_Scroll_Lock); + + /* + * Find out the masks for the NumLock and ScrollLock modifiers, + * so that we can bind the grabs for when they are enabled too. + */ + modmap = XGetModifierMapping(getXDisplay()); + + if (modmap != NULL && modmap->max_keypermod > 0) { + for (i = 0; i < 8 * modmap->max_keypermod; i++) { + if (modmap->modifiermap[i] == nlock && nlock != 0) + _NumLockMask = mask_table[i / modmap->max_keypermod]; + else if (modmap->modifiermap[i] == slock && slock != 0) + _ScrollLockMask = mask_table[i / modmap->max_keypermod]; + } + } + + if (modmap) + XFreeModifiermap(modmap); +} + +/*-------------------------------------------------------------------------*/ + +/*-- End of shameful code-snarf..................................... --*/ + +/*-------------------------------------------------------------------------*/ + +int ToolWindow::translateAction(char *action) +{ + if (!action) + return 0; + + if (!strcasecmp(action, "Minimize")) + return grabIconify; + if (!strcasecmp(action, "Raise")) + return grabRaise; + if (!strcasecmp(action, "Lower")) + return grabLower; + if (!strcasecmp(action, "Close")) + return grabClose; + if (!strcasecmp(action, "Workspace1")) + return grabWorkspace1; + if (!strcasecmp(action, "Workspace2")) + return grabWorkspace2; + if (!strcasecmp(action, "Workspace3")) + return grabWorkspace3; + if (!strcasecmp(action, "Workspace4")) + return grabWorkspace4; + if (!strcasecmp(action, "Workspace5")) + return grabWorkspace5; + if (!strcasecmp(action, "Workspace6")) + return grabWorkspace6; + if (!strcasecmp(action, "Workspace7")) + return grabWorkspace7; + if (!strcasecmp(action, "Workspace8")) + return grabWorkspace8; + if (!strcasecmp(action, "Workspace9")) + return grabWorkspace9; + if (!strcasecmp(action, "Workspace10")) + return grabWorkspace10; + if (!strcasecmp(action, "Workspace11")) + return grabWorkspace11; + if (!strcasecmp(action, "Workspace12")) + return grabWorkspace12; + if (!strcasecmp(action, "NextWorkspace")) + return grabNextWorkspace; + if (!strcasecmp(action, "PrevWorkspace")) + return grabPrevWorkspace; + if (!strcasecmp(action, "UpWorkspace")) + return grabUpWorkspace; + if (!strcasecmp(action, "DownWorkspace")) + return grabDownWorkspace; + if (!strcasecmp(action, "LeftWorkspace")) + return grabLeftWorkspace; + if (!strcasecmp(action, "RightWorkspace")) + return grabRightWorkspace; + if (!strcasecmp(action, "NextWindow")) + return grabNextWindow; + if (!strcasecmp(action, "PrevWindow")) + return grabPrevWindow; + if (!strcasecmp(action, "NextWindowAllWorkspaces")) + return grabNextWindowAllWorkspaces; + if (!strcasecmp(action, "ShadeWindow")) + return grabShade; + if (!strcasecmp(action, "MaximizeWindow")) + return grabMaximize; + if (!strcasecmp(action, "StickWindow")) + return grabStick; + if (!strcasecmp(action, "ExecCommand")) + return grabExecute; + if (!strcasecmp(action, "MaximizeVertical")) + return grabVertMax; + if (!strcasecmp(action, "MaximizeHorizontal")) + return grabHorizMax; + if (!strcasecmp(action, "NudgeRight")) + return grabNudgeRight; + if (!strcasecmp(action, "NudgeLeft")) + return grabNudgeLeft; + if (!strcasecmp(action, "NudgeUp")) + return grabNudgeUp; + if (!strcasecmp(action, "NudgeDown")) + return grabNudgeDown; + if (!strcasecmp(action, "BigNudgeRight")) + return grabBigNudgeRight; + if (!strcasecmp(action, "BigNudgeLeft")) + return grabBigNudgeLeft; + if (!strcasecmp(action, "BigNudgeUp")) + return grabBigNudgeUp; + if (!strcasecmp(action, "BigNudgeDown")) + return grabBigNudgeDown; + if (!strcasecmp(action, "HorizontalIncrement")) + return grabHorizInc; + if (!strcasecmp(action, "VerticalIncrement")) + return grabVertInc; + if (!strcasecmp(action, "HorizontalDecrement")) + return grabHorizDec; + if (!strcasecmp(action, "VerticalDecrement")) + return grabVertDec; + if (!strcasecmp(action, "ToggleDecor")) + return grabToggleDecor; + + + return 0; +} + +void ToolWindow::execCommand(char *const ptrCommand) +{ + int pid; + extern char **environ; + + pid = fork(); + if (pid == -1) { + fprintf(stderr, + "bbkeys: Could not fork a process for execCommand.\n"); + return; + } + + if (pid == 0) { + const char *const argv[] = { + "sh", + "-c", + ptrCommand, + 0 + }; + execve("/bin/sh", (char *const *)argv, environ); + exit(127); + } +} + +void ToolWindow::setKeygrabs(void) +{ + int res, pid; + + pid = fork(); + + if (pid == -1) { + fprintf(stderr, + "bbkeys: Could not fork a process for configurator.\n"); + return; + } + + if (pid == 0) { + if (noQt) { + // Make 'bbconf' automagically fail... + res = 1; + } else { + string ost = (string)"keybindings:loadfile=" + bbkeys_rcfile; + + res = execlp("bbconf", "bbconf", "--start-plugin", "key bindings", + "--args", ost.c_str(), NULL); + + } + + if (res != 0) { + string ost = (string)"bbkeysconf.pl -rcfile " + bbkeys_rcfile; + + res = execlp("rxvt", "rxvt", "-bg", "black", "-fg", "green", + "-e", "sh", "-c", ost.c_str(), NULL); + if (res != 0) { + execlp("xterm", "xterm", "-bg", "black", "-fg", "green", + "-e", "sh", "-c", ost.c_str(), NULL); + } + } + exit(0); + } + +} + +void ToolWindow::loadKeygrabs(void) +{ + // free up pointers that we get with strdup for execCommand.... + for (register int i = 0; i < grabSet.instructCount; i++) { + if (grabSet.KeyMap[i].execCommand != NULL) { + free(grabSet.KeyMap[i].execCommand); + } + } + memset(&actionList, 0, sizeof(actionList)); + + /* re-initialize our grabSet count... */ + grabSet.instructCount = 0; + + int count = 0; + char line[1024]; + char Keytograb[80]; + char Modifier[80]; + char action[80]; + char execCommand[500]; + char *KeytograbBegin; + char *ModifierBegin; + char *actionBegin; + char *execCmdBegin; + + FILE *rc_file = fopen(bbkeys_rcfile, "r"); + if (!rc_file) { + fprintf(stderr, "\nDanger!!! Warning Will Robinson!!!\n" + "I can't open your bbkeys rc-file (%s).\n" + "Hmm. That means I don't have anything to do. Please run \n" + "the bbkeys configurator of your choice (click my keyhole) \n" + "to allow me to do stuff for ya. \n" + "'Cause otherwise, I just sit here feeling sad....\n\n" + , bbkeys_rcfile); + return; + } + + memset(line, '\0', 1024); + + while (fgets(line, 1024, rc_file) && !feof(rc_file) && + count < MaxInstructions) { + if (line[0] != '#' && strstr(line, "WithModifier")) { + + memset(Keytograb, '\0', 80); + memset(Modifier, '\0', 80); + memset(action, '\0', 80); + memset(execCommand, '\0', 500); + + KeytograbBegin = strchr(line, '('); + ModifierBegin = strchr(KeytograbBegin + 1, '('); + actionBegin = strchr(ModifierBegin + 1, '('); + + strncat(Keytograb, KeytograbBegin + 1, + strcspn(KeytograbBegin + 1, ")")); + strncpy(Modifier, ModifierBegin + 1, + strcspn(ModifierBegin + 1, ")")); + strncpy(action, actionBegin + 1, + strcspn(actionBegin + 1, ")")); + + grabSet.KeyMap[count].keycode = XKeysymToKeycode(getXDisplay(), + XStringToKeysym + (Keytograb)); + + char *k; + char *tmp = (char *) Modifier; + grabSet.KeyMap[count].modMask = 0; + while ((k = strchr(tmp, '+')) != NULL) { + *k = 0; + grabSet.KeyMap[count].modMask |= translateModifier(tmp); + tmp = k + 1; + } + grabSet.KeyMap[count].modMask |= translateModifier(tmp); + + grabSet.KeyMap[count].action = translateAction(action); + // save off a cross-reference for action->grabSet.KeyMap[index] + actionList[grabSet.KeyMap[count].action] = count; + + /* if we're supposed to having an execCommand and we do have + * something to put into it */ + if (grabSet.KeyMap[count].action == grabExecute) { + execCmdBegin = strchr(actionBegin + 1, '('); + if (execCmdBegin) { + strncpy(execCommand, execCmdBegin + 1, + strrchr(execCmdBegin, ')') - execCmdBegin - 1); + grabSet.KeyMap[count].execCommand = + strdup(execCommand); + } + } else { + grabSet.KeyMap[count].execCommand = NULL; + } + +#ifdef DEBUG + fprintf(stdout, "Keysym ->%d<-, Modifier ->0x%lx<-, " + "action ->%d<-, execCommand ->%s<-\n", + grabSet.KeyMap[count].keycode, + grabSet.KeyMap[count].modMask, + grabSet.KeyMap[count].action, + grabSet.KeyMap[count].execCommand); +#endif + count++; + + } + } + fclose(rc_file); + grabSet.instructCount = count; +#ifdef DEBUG + fprintf(stderr, "loaded ->%d<- instructions.\n", count); +#endif +} + +/***************************************** + * * + * END OF KEY GRABBING/HANDLING ROUTINES * + * * + *****************************************/ + +ToolWindow::ToolWindow(int argc, char **argv, struct CMDOPTIONS *options): + Basewindow(argc, argv, options), TimeoutHandler() +{ + timer = new BTimer(this, this); + timer->setTimeout(100); + timer->fireOnce(True); + + if (!(options->bbkeysrc)){ + char *homedir = getenv("HOME"); + bbkeys_rcfile = new char[strlen(homedir) + 32]; + sprintf(bbkeys_rcfile, "%s/.bbkeysrc", homedir); + } else { + bbkeys_rcfile = options->bbkeysrc; + } + + XrmInitialize(); + + InitializeModifiers(); + + _NumLockMask = 0; + _ScrollLockMask = 0; + + /* + * Ignore CapsLock in modifiers + */ + ValidModMask = 0xff & ~LockMask; + + getOffendingModifiers(); + /* + * Ignore NumLock and ScrollLock too + */ + ValidModMask &= ~(_NumLockMask | _ScrollLockMask); + + // initialize it so we don't run into problems later + grabSet.instructCount = 0; + loadKeygrabs(); + activateKeygrabs(); + + resource = new Resource(this); + wminterface = new WMInterface(this); + windowList = new LinkedList < WindowList >; + desktopList = new LinkedList < DesktopList >; + + // initialize variables + current_desktop = NULL; + desktop_count = 0; + doingCycling = False; + + // make draw the bbkeys window + MakeWindow(False); + Redraw(); + + // pass control to the main loop + eventLoop(); +} + +ToolWindow::~ToolWindow() +{ + XUnmapWindow(getXDisplay(), win_frame); + + /* destroy pixmaps */ + if (pixmap.frame) + getImageControl()->removeImage(pixmap.frame); + if (pixmap.pix_title) + getImageControl()->removeImage(pixmap.pix_title); + if (pixmap.pix_back) + getImageControl()->removeImage(pixmap.pix_back); + if (pixmap.pix_configBtn) + getImageControl()->removeImage(pixmap.pix_configBtn); + if (pixmap.pix_closeBtn) + getImageControl()->removeImage(pixmap.pix_closeBtn); + if (pixmap.pix_pressedBtn) + getImageControl()->removeImage(pixmap.pix_pressedBtn); + + /* destroy windows */ + XDestroyWindow(getXDisplay(), win_frame); + XDestroyWindow(getXDisplay(), win_back); + XDestroyWindow(getXDisplay(), win_title); + XDestroyWindow(getXDisplay(), win_configBtn); + XDestroyWindow(getXDisplay(), win_closeBtn); + + /* destroy GC's */ + if (frameGC) XFreeGC(getXDisplay(),frameGC); + if (menuGC) XFreeGC(getXDisplay(),menuGC); + if (menuHiBGGC) XFreeGC(getXDisplay(),menuHiBGGC); + if (menuHiGC) XFreeGC(getXDisplay(),menuHiGC); + if (menuFrameGC) XFreeGC(getXDisplay(),menuFrameGC); + + + /* destroy lists */ + delete windowList; + delete desktopList; +} + +void ToolWindow::reconfigure(void) +{ + /* destroy pixmaps */ + if (pixmap.frame) + getImageControl()->removeImage(pixmap.frame); + if (pixmap.pix_title) + getImageControl()->removeImage(pixmap.pix_title); + if (pixmap.pix_back) + getImageControl()->removeImage(pixmap.pix_back); + if (pixmap.pix_configBtn) + getImageControl()->removeImage(pixmap.pix_configBtn); + if (pixmap.pix_closeBtn) + getImageControl()->removeImage(pixmap.pix_closeBtn); + if (pixmap.pix_pressedBtn) + getImageControl()->removeImage(pixmap.pix_pressedBtn); + + resource->Reload(); + MakeWindow(True); + + stackMenu->reconfigure(); + + XClearWindow(getXDisplay(), win_frame); + XClearWindow(getXDisplay(), win_back); + Redraw(); +} + +void ToolWindow::MakeWindow(bool reconfigure) +{ + XSetWindowAttributes attrib; + XWMHints wmhints; + XClassHint classhints; + XTextProperty windowname; + + unsigned long create_mask = CWBackPixmap | CWBorderPixel | + CWOverrideRedirect | CWCursor | CWEventMask; + + // geometry for our windows................................... + + geom_title.height = resource->label.font->ascent + + resource->label.font->descent + 2; + if (geom_title.height < 20 && (miniMe || tinyMe)) + geom_title.height = 20; + geom_title.width = XTextWidth(resource->label.font, "bbkeys", + strlen("bbkeys")) + (geom_title.height + + 5); + geom_title.x = 2; + geom_title.y = 2; + geom_back.width = geom_title.width + 4; + geom_back.x = 0; + geom_back.y = 0; + geom_closeBtn.height = geom_title.height * 7 / 10; + geom_closeBtn.width = geom_closeBtn.height; + + if (miniMe) { + + geom_back.height = geom_title.height + 2; + geom_closeBtn.y = 80; /* put it out of sight. */ + geom_closeBtn.x = 80; + geom_configBtn.height = geom_title.height - 1; + geom_configBtn.width = geom_configBtn.height; + geom_configBtn.x = geom_title.width - geom_configBtn.width; + geom_configBtn.y = geom_title.y; + + } else if (tinyMe) { + + geom_title.height = 22; + geom_title.width = 22; + geom_title.x = 80; + geom_title.y = 80; + geom_back.width = 22; + geom_back.height = 22; + geom_closeBtn.y = 80; /* put it out of sight. */ + geom_closeBtn.x = 80; + geom_configBtn.height = 20; + geom_configBtn.width = geom_configBtn.height; + geom_configBtn.x = 1; + geom_configBtn.y = 1; + + } else { + + geom_back.height = 3 * (geom_title.height) + 6; + geom_closeBtn.x = geom_title.width - geom_closeBtn.width - 1; + geom_closeBtn.y = geom_title.y + + ((geom_title.height - geom_closeBtn.height) / 2); + geom_configBtn.height = (geom_title.height * 2); + geom_configBtn.width = geom_title.width - 4; + geom_configBtn.x = geom_title.x + 2; + geom_configBtn.y = geom_title.height + geom_title.y + 2; + + } + + frame.height = geom_back.height; + frame.width = geom_back.width; + frame.x = resource->position.x; + frame.y = resource->position.y; + + // end geometry for our windows................................... + + if (resource->position.mask & XNegative) { + frame.x = getCurrentScreenInfo()->getWidth() + + resource->position.x - frame.width; + } + + if (resource->position.mask & YNegative) { + frame.y = getCurrentScreenInfo()->getHeight() + + resource->position.y - frame.height; + + } + + if (withdrawn) { + attrib.override_redirect = False; + wmhints.initial_state = WithdrawnState; + } else if (iconic) { + attrib.override_redirect = False; + wmhints.initial_state = IconicState; + } else { + attrib.override_redirect = False; + wmhints.initial_state = NormalState; + } + + attrib.background_pixmap = ParentRelative; + + pixmap.frame = + getImageControl()->renderImage(frame.width, frame.height, + &resource->frame.texture); + + pixmap.pix_back = + getImageControl()->renderImage(geom_back.width, + geom_back.height, + &resource->frame.texture); + pixmap.pix_title = + getImageControl()->renderImage(geom_title.width, geom_title.height, + &resource->label.texture); + + pixmap.pix_configBtn = + getImageControl()->renderImage(geom_configBtn.width, + geom_configBtn.height, + &resource->button.texture); + + pixmap.pix_closeBtn = + getImageControl()->renderImage(geom_closeBtn.width, + geom_closeBtn.height, + &resource->button.texture); + pixmap.pix_pressedBtn = + getImageControl()->renderImage(geom_configBtn.width, + geom_configBtn.height, + &resource->button.texture_pressed); + + attrib.cursor = getSessionCursor(); + attrib.event_mask = + ButtonPressMask | ButtonReleaseMask | ExposureMask | + FocusChangeMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask | + SubstructureRedirectMask; + + if (!reconfigure) { + win_frame = XCreateWindow(getXDisplay(), + getCurrentScreenInfo()->getRootWindow(), + frame.x, frame.y, frame.width, + frame.height, 0, + getCurrentScreenInfo()->getDepth(), + InputOutput, + getCurrentScreenInfo()->getVisual(), + create_mask, &attrib); + win_back = XCreateWindow(getXDisplay(), + win_frame, + geom_back.x, + geom_back.y, + geom_back.width, + geom_back.height, 0, + getCurrentScreenInfo + ()->getDepth(), InputOutput, + getCurrentScreenInfo + ()->getVisual(), create_mask, &attrib); + win_title = + XCreateWindow(getXDisplay(), win_frame, geom_title.x, + geom_title.y, geom_title.width, + geom_title.height, 0, + getCurrentScreenInfo()->getDepth(), InputOutput, + getCurrentScreenInfo()->getVisual(), create_mask, + &attrib); + win_configBtn = + XCreateWindow(getXDisplay(), win_frame, geom_configBtn.x, + geom_configBtn.y, geom_configBtn.width, + geom_configBtn.height, 0, + getCurrentScreenInfo()->getDepth(), InputOutput, + getCurrentScreenInfo()->getVisual(), create_mask, + &attrib); + win_closeBtn = + XCreateWindow(getXDisplay(), win_frame, geom_closeBtn.x, + geom_closeBtn.y, geom_closeBtn.width, + geom_closeBtn.height, 0, + getCurrentScreenInfo()->getDepth(), InputOutput, + getCurrentScreenInfo()->getVisual(), create_mask, + &attrib); + } else if (!withdrawn) { + XMoveResizeWindow(getXDisplay(), win_frame, frame.x, frame.y, + frame.width, frame.height); + XMoveResizeWindow(getXDisplay(), win_back, + geom_back.x, geom_back.y, + geom_back.width, geom_back.height); + XMoveResizeWindow(getXDisplay(), win_title, geom_title.x, + geom_title.y, geom_title.width, + geom_title.height); + XMoveResizeWindow(getXDisplay(), win_configBtn, geom_configBtn.x, + geom_configBtn.y, geom_configBtn.width, + geom_configBtn.height); + XMoveResizeWindow(getXDisplay(), win_closeBtn, geom_closeBtn.x, + geom_closeBtn.y, geom_closeBtn.width, + geom_closeBtn.height); + + } else { + XResizeWindow(getXDisplay(), win_frame, frame.width, frame.height); + XResizeWindow(getXDisplay(), win_back, + geom_back.width, geom_back.height); + XResizeWindow(getXDisplay(), win_title, geom_title.width, + geom_title.height); + XMoveResizeWindow(getXDisplay(), win_configBtn, geom_configBtn.x, + geom_configBtn.y, geom_configBtn.width, + geom_configBtn.height); + XMoveResizeWindow(getXDisplay(), win_closeBtn, geom_closeBtn.x, + geom_closeBtn.y, geom_closeBtn.width, + geom_closeBtn.height); + } + + char *name = (char *)BBTOOL; + XSizeHints sizehints; + + wmhints.flags = StateHint; + + classhints.res_name = (char *)BBTOOL; + classhints.res_class = (char *)"bbtools"; + + sizehints.x = frame.x; //getResource()->position.x; + sizehints.y = frame.y; //getResource()->position.y; + + sizehints.max_width = sizehints.min_width = frame.width; + sizehints.max_height = sizehints.min_height = frame.height; + sizehints.flags = USPosition | PMinSize | PMaxSize; + + XStringListToTextProperty(&name, 1, &windowname); + XSetWMProperties(getXDisplay(), win_frame, &windowname, NULL, getArgv(), + getArgc(), &sizehints, &wmhints, &classhints); + + // free up allocated memory in XStringListToTextProperty + XFree(windowname.value); + + if (!reconfigure) { + Atom wmproto[2]; + wmproto[0] = wm_delete_window; + wmproto[1] = getBlackboxStructureMessagesAtom(); + XSetWMProtocols(getXDisplay(), win_frame, wmproto, 2); + } + + if (!decorated && !withdrawn) { + BlackboxHints net_hints; + net_hints.decoration = DecorNone; + net_hints.attrib = AttribOmnipresent; + net_hints.flags = AttribDecoration | AttribOmnipresent; + XChangeProperty(getXDisplay(), win_frame, getBlackboxHintsAtom(), + getBlackboxHintsAtom(), 32, PropModeReplace, + (unsigned char *) &net_hints, + PropBlackboxHintsElements); + } + + if (!shape) { + XSetWindowBackgroundPixmap(getXDisplay(), win_frame, pixmap.frame); + } + + XSetWindowBackgroundPixmap(getXDisplay(), win_title, pixmap.pix_title); + XSetWindowBackgroundPixmap(getXDisplay(), win_back, pixmap.pix_back); + XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn, + pixmap.pix_configBtn); + XSetWindowBackgroundPixmap(getXDisplay(), win_closeBtn, + pixmap.pix_closeBtn); + + + if (!reconfigure) { + gcv.font = resource->label.font->fid; + gcv.foreground = resource->label.textColor.getPixel(); + frameGC = + XCreateGC(getXDisplay(), win_frame, GCFont | GCForeground, &gcv); + + gcv.font = resource->menu.font->fid; + gcv.foreground = resource->menu.texture.getColor()->getPixel(); + menuGC = XCreateGC(getXDisplay(), win_frame,GCFont|GCForeground, &gcv); + + gcv.foreground = resource->menu.highlightColor.getPixel(); + gcv.arc_mode = ArcChord; + gcv.fill_style = FillSolid; + menuHiBGGC = XCreateGC(getXDisplay(), win_frame,GCForeground| + GCFillStyle|GCArcMode, &gcv); + + gcv.foreground = resource->menu.hiTextColor.getPixel(); + menuHiGC = XCreateGC(getXDisplay(), win_frame, GCFont|GCForeground, &gcv); + + gcv.foreground = resource->menu.textColor.getPixel(); + menuFrameGC = XCreateGC(getXDisplay(), win_frame,GCFont|GCForeground, &gcv); + + stackMenu = new Stackmenu(this); + stackMenu->update(); + } else { + gcv.font = resource->label.font->fid; + gcv.foreground = resource->label.textColor.getPixel(); + XChangeGC(getXDisplay(), frameGC, GCFont | GCForeground, &gcv); + + gcv.font = resource->menu.font->fid; + gcv.foreground = resource->menu.texture.getColor()->getPixel(); + XChangeGC(getXDisplay(), menuGC, GCFont | GCForeground, &gcv); + + gcv.foreground = resource->menu.highlightColor.getPixel(); + XChangeGC(getXDisplay(), menuHiBGGC, GCFont | GCForeground, &gcv); + + gcv.foreground = resource->menu.hiTextColor.getPixel(); + XChangeGC(getXDisplay(), menuHiGC, GCFont | GCForeground, &gcv); + + gcv.foreground = resource->menu.textColor.getPixel(); + XChangeGC(getXDisplay(), menuFrameGC, GCFont | GCForeground, &gcv); + + } + + + if (!reconfigure) { + XClearWindow(getXDisplay(), win_frame); + XMapWindow(getXDisplay(), win_frame); + XMapSubwindows(getXDisplay(), win_frame); + XSetIconName(getXDisplay(), win_frame, "bbkeys"); + } +} + +void ToolWindow::Redraw() +{ + XClearWindow(getXDisplay(), win_title); + XClearWindow(getXDisplay(), win_configBtn); + XClearWindow(getXDisplay(), win_closeBtn); + + char *title = (char *)"bbkeys"; + XDrawString(getXDisplay(), win_title, frameGC, geom_title.x - 1, + (geom_title.height + resource->label.font->ascent - + resource->label.font->descent) / 2, title, strlen(title)); + + XPoint pts[3]; + + if (miniMe || tinyMe) { + pts[0].x = (geom_configBtn.width / 2); + pts[0].y = (geom_configBtn.height / 2) - 2; + pts[1].x = -(geom_configBtn.width / 4); + pts[1].y = (geom_configBtn.height - pts[0].y) - 1; + pts[2].x = (geom_configBtn.width / 2); + pts[2].y = 0; + + XFillPolygon(getXDisplay(), win_configBtn, frameGC, pts, 3, + Convex, CoordModePrevious); + XFillArc(getXDisplay(), win_configBtn, frameGC, + geom_configBtn.width / 2 - geom_configBtn.width / 4, 1, // x, y + geom_configBtn.width / 2, geom_configBtn.height / 2, //width,height + 0, 360 * 64); + } else { + pts[0].x = (geom_configBtn.width / 2); + pts[0].y = (geom_configBtn.height / 2) - 2; + pts[1].x = -(geom_configBtn.width / 4); + pts[1].y = (geom_configBtn.height - pts[0].y) - 2; + pts[2].x = (geom_configBtn.width / 2); + pts[2].y = 0; + + XFillPolygon(getXDisplay(), win_configBtn, frameGC, pts, 3, + Convex, CoordModePrevious); + XFillArc(getXDisplay(), win_configBtn, frameGC, + geom_configBtn.width / 2 - geom_configBtn.width / 4, 1, // x, y + geom_configBtn.width / 2, geom_configBtn.height * 5 / 8, //width,height + 0, 360 * 64); + } + + /* Our little close button (drawn twice for a nice thickness) */ + XDrawLine(getXDisplay(), win_closeBtn, frameGC, 1, 1, + geom_closeBtn.width - 2, geom_closeBtn.height - 1); + XDrawLine(getXDisplay(), win_closeBtn, frameGC, 1, + geom_closeBtn.height - 1, geom_closeBtn.width - 2, 1); + + XDrawLine(getXDisplay(), win_closeBtn, frameGC, 2, 1, + geom_closeBtn.width - 1, geom_closeBtn.height - 1); + XDrawLine(getXDisplay(), win_closeBtn, frameGC, 2, + geom_closeBtn.height - 1, geom_closeBtn.width - 1, 1); + +} + +unsigned int ToolWindow::KeycodeToModmask(unsigned int code) +{ + switch (XKeycodeToKeysym(getXDisplay(), code, 0)) { + case XK_Shift_L: + case XK_Shift_R: + return ShiftMask; + + case XK_Caps_Lock: + case XK_Shift_Lock: + return LockMask; + + case XK_Control_L: + case XK_Control_R: + return ControlMask; + + case XK_Alt_L: + case XK_Alt_R: + return AltMask ? AltMask : MetaMask; + + case XK_Num_Lock: + return NumLockMask; + + case XK_Super_L: + case XK_Super_R: + return SuperMask; + + case XK_Hyper_L: + case XK_Hyper_R: + return HyperMask; + + case XK_Meta_L: + case XK_Meta_R: + return MetaMask; + + case XK_Scroll_Lock: + return ScrollLockMask; + } + return (unsigned int)-1; +} + + +void ToolWindow::findFramePosition(Window window, int &x, int &y) { + Window win = window, parent, root, last = None; + Window *children = 0; + unsigned int nchildren; + int gravity, top, bottom, left, right; + XWindowAttributes wattr; + XSizeHints size; + long ret; + unsigned int cwidth, cheight; + + // get the location, size and gravity of the client window + if (! XGetWindowAttributes(getXDisplay(), window, &wattr)) return; + cwidth = wattr.width; + cheight = wattr.height; + if (! XGetWMNormalHints(getXDisplay(), window, &size, &ret)) return; + if (size.flags & PWinGravity) + gravity = size.win_gravity; + else + gravity = NorthWestGravity; + + while (XQueryTree(getXDisplay(), win, &root, &parent, &children, + &nchildren)) { + if (children && nchildren > 0) + XFree(children); // don't care about the children + + if (! parent) // no parent!? + return; + + // if the parent window is the root window, stop here + if (parent == root) + break; + + last = win; + win = parent; + } + + if (! (XTranslateCoordinates(getXDisplay(), last, win, 0, 0, &left, &top, + &parent) && + XGetWindowAttributes(getXDisplay(), win, &wattr))) + return; + + right = wattr.width - cwidth - left; + bottom = wattr.height - cheight - top; + + left += wattr.border_width; + right += wattr.border_width; + top += wattr.border_width; + bottom += wattr.border_width; + + // find the client's location + x = wattr.x + left; + y = wattr.y + top; + + // this makes things work. why? i don't know. but you need them. + right -= 2; + bottom -= 2; + + // find the frame's reference position based on the window's gravity + switch (gravity) { + case NorthWestGravity: + x -= left; + y -= top; + break; + case NorthGravity: + x += (left + right) / 2; + y -= top; + break; + case NorthEastGravity: + x += right; + y -= top; + case WestGravity: + x -= left; + y += (top + bottom) / 2; + break; + case CenterGravity: + x += (left + right) / 2; + y += (top + bottom) / 2; + break; + case EastGravity: + x += right; + y += (top + bottom) / 2; + case SouthWestGravity: + x -= left; + y += bottom; + break; + case SouthGravity: + x += (left + right) / 2; + y += bottom; + break; + case SouthEastGravity: + x += right; + y += bottom; + break; + default: + break; + } +} + + +void ToolWindow::process_event(XEvent * e) +{ + switch (e->type) { + case PropertyNotify: + windowAttributeChange(e->xproperty.window); + break; + + case VisibilityNotify: + // **** This will need to change to a better method of keeping the **** // + // **** menu on top when blackbox provides another way! **** // + if (e->xvisibility.window == stackMenu->getWindowID()) + if (e->xvisibility.state != VisibilityUnobscured) + XRaiseWindow(getXDisplay(), stackMenu->getWindowID()); + break; + + case KeyRelease: { + // if stacked cycling is going on.. + if (doingCycling) { + unsigned int mask = KeycodeToModmask(e->xkey.keycode); + unsigned int state = e->xkey.state; + + // get the index for grabSet.KeyMay's prev/next entries, but make + // sure we're not just getting 0 because we don't have keybindings + // for one of them--also, we can't use > 0 as a test for next/prev + // because 0 might very well be the valid index for those bindings + int i = actionList[grabNextWindow]; + int next = grabSet.KeyMap[i].action == grabNextWindow ? i : -1; + int j = actionList[grabNextWindowAllWorkspaces]; + int nextAll = grabSet.KeyMap[j].action == grabNextWindowAllWorkspaces ? j : -1; + int k = actionList[grabPrevWindow]; + int prev = grabSet.KeyMap[k].action == grabPrevWindow ? k : -1; + + // if the key released was the last modifier being held + // and being a member of the nextMask or PrevMask, then select + // the item in the menu that is currently focued. + if (next > -1 && ((state & grabSet.KeyMap[next].modMask) == mask)) + stackMenu->selectFocused(True); + else if (nextAll > -1 && ((state & grabSet.KeyMap[nextAll].modMask) == mask)) + stackMenu->selectFocused(True); + else if (prev > -1 && ((state & grabSet.KeyMap[prev].modMask) == mask)) + stackMenu->selectFocused(True); + } + break; + } + + case KeyPress: { + + int i = 0; + int grabInt = -1; + int fw_y, fw_x; + + if (focus_window) { + findFramePosition(focus_window, fw_x, fw_y); + } + + // if our user wants to grab his keystrokes, even though one + // or more of the Lock-Modifiers are pressed, alter the mask + + + // to make this possible.... + + if (!honor_modifiers) { + e->xkey.state &= ~_NumLockMask & ~_ScrollLockMask & ~LockMask; + } + + for (i = 0; i < grabSet.instructCount; i++) { + if ((e->xkey.keycode == grabSet.KeyMap[i].keycode) && + (e->xkey.state == grabSet.KeyMap[i].modMask)) { + grabInt = i; + break; + } + } + + if (doingCycling) { + if (e->xkey.keycode == XKeysymToKeycode(getXDisplay(), XK_Escape)) { + stackMenu->hide(); + // reset focus to the window we were focused on before window + // cycling began + wminterface->setWindowFocus(focus_window); + } else if (e->xkey.keycode == XKeysymToKeycode(getXDisplay(), XK_Return)) + stackMenu->selectFocused(True); + else + stackMenu->key_press(grabSet.KeyMap[grabInt].action); + } else if (grabInt > -1) { + + /* play with colors for nyz =:) */ + XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn, + pixmap.pix_pressedBtn); + Redraw(); + + switch (grabSet.KeyMap[grabInt].action) { + case grabIconify: + if (focus_window) + XIconifyWindow(getXDisplay(), focus_window, 0); + break; + + case grabRaise: + if (focus_window) + XRaiseWindow(getXDisplay(), focus_window); + break; + + case grabLower: + if (focus_window) + XLowerWindow(getXDisplay(), focus_window); + break; + + case grabClose: + if (!focus_window) + break; + XEvent ce; + ce.xclient.type = ClientMessage; + ce.xclient.message_type = getWMProtocolsAtom(); + ce.xclient.display = getXDisplay(); + ce.xclient.window = focus_window; + ce.xclient.format = 32; + ce.xclient.data.l[0] = getWMDeleteAtom(); + ce.xclient.data.l[1] = CurrentTime; + ce.xclient.data.l[2] = ce.xclient.data.l[3] = + ce.xclient.data.l[4] = 0l; + XSendEvent(getXDisplay(), focus_window, False, NoEventMask, &ce); + break; + + case grabWorkspace1: + wminterface->changeDesktop(0); + break; + + case grabWorkspace2: + wminterface->changeDesktop(1); + break; + + case grabWorkspace3: + wminterface->changeDesktop(2); + break; + + case grabWorkspace4: + wminterface->changeDesktop(3); + break; + + case grabWorkspace5: + wminterface->changeDesktop(4); + break; + + case grabWorkspace6: + wminterface->changeDesktop(5); + break; + + case grabWorkspace7: + wminterface->changeDesktop(6); + break; + + case grabWorkspace8: + wminterface->changeDesktop(7); + break; + + case grabWorkspace9: + wminterface->changeDesktop(8); + break; + + case grabWorkspace10: + wminterface->changeDesktop(9); + break; + + case grabWorkspace11: + wminterface->changeDesktop(10); + break; + + case grabWorkspace12: + wminterface->changeDesktop(11); + break; + + case grabNextWorkspace: + if (current_desktop->number < (desktop_count-1)) + wminterface->changeDesktop(current_desktop->number + 1); + else + wminterface->changeDesktop(0); + break; + + case grabPrevWorkspace: + if (current_desktop->number > 0) + wminterface->changeDesktop(current_desktop->number - 1); + else + wminterface->changeDesktop(desktop_count - 1); + break; + + case grabUpWorkspace: + if (resource->columns > 1) { //ie columns given + if (getCurrentDesktopNr()-resource->columns<0) { + if (getDesktopCount()-1-(getDesktopCount()-1)%resource->columns + + getCurrentDesktopNr()%resource->columns > getDesktopCount() - 1) { + + wminterface->changeDesktop(getDesktopCount() - 1 - + (getDesktopCount() - 1)%resource->columns + + getCurrentDesktopNr()%resource->columns -resource->columns); + + } else { + wminterface->changeDesktop(getDesktopCount() - 1 - + (getDesktopCount() - 1)%resource->columns + + getCurrentDesktopNr()%resource->columns ); + } + } else { + wminterface->changeDesktop(getCurrentDesktopNr() - resource->columns); + } + } else if (resource->rows > 1) { //ie rows given + if (getCurrentDesktopNr()%resource->rows==0) {// if row=1 + if (getCurrentDesktopNr() + resource->rows > getDesktopCount()) + //incomplete last col? + wminterface->changeDesktop(getDesktopCount() - 1); //last desktop + else //complete col + wminterface->changeDesktop(getCurrentDesktopNr() +resource->rows - 1); + //last in column + } else // row>1 + wminterface->changeDesktop(getCurrentDesktopNr() - 1); + } else {} //no arrangement -> insert fallback solution here + + break; + + case grabDownWorkspace: + if (resource->columns > 1) { //ie columns given + if (getCurrentDesktopNr() + resource->columns > getDesktopCount() - 1) + wminterface->changeDesktop(getCurrentDesktopNr()%resource->columns); + else + wminterface->changeDesktop(getCurrentDesktopNr() +resource->columns); + } else if (resource->rows > 1) { //ie rows given + if (getCurrentDesktopNr()%resource->rows + 1 == resource->rows || + getCurrentDesktopNr() + 1 == getDesktopCount()) { + //last row or last in incomplete col + wminterface->changeDesktop(getCurrentDesktopNr() - + getCurrentDesktopNr()%resource->rows); + //first in col + } else + wminterface->changeDesktop(getCurrentDesktopNr() + 1); + } else {} //no arrangement -> fallback solution + + break; + + + case grabLeftWorkspace: + if (resource->columns > 1) { //ie columns given + if (getCurrentDesktopNr()%resource->columns==0) { + if (getCurrentDesktopNr() + resource->columns > getDesktopCount()) + wminterface->changeDesktop(getDesktopCount() -1); + else + wminterface->changeDesktop(getCurrentDesktopNr() + resource->columns - 1); + } else + wminterface->changeDesktop(getCurrentDesktopNr() - 1); + } else if (resource->rows > 1) { //ie rows given + if (getCurrentDesktopNr() - resource->rows<0) {// first col + if (getDesktopCount() - 1 - (getDesktopCount()-1)%resource->rows + + getCurrentDesktopNr()%resource->rows > getDesktopCount() - 1) + //incomplete row + wminterface->changeDesktop(getDesktopCount() - 1 - + (getDesktopCount() - 1)%resource->rows + + getCurrentDesktopNr()%resource->rows - resource->rows); + else + wminterface->changeDesktop(getDesktopCount() - 1 - + (getDesktopCount() - 1)%resource->rows + + getCurrentDesktopNr()%resource->rows ); + } else + wminterface->changeDesktop(getCurrentDesktopNr() - resource->rows); + } else {} //no arrangement -> fallback solution + + break; + + + case grabRightWorkspace: + if (resource->columns > 1) { //ie columns given + if (getCurrentDesktopNr()%resource->columns + 1 == resource->columns || + getCurrentDesktopNr() + 1 == getDesktopCount()) + wminterface->changeDesktop(getCurrentDesktopNr() - + getCurrentDesktopNr()%resource->columns); + else + wminterface->changeDesktop(getCurrentDesktopNr() + 1); + } else if (resource->rows > 1) { //ie rows given + if (getCurrentDesktopNr() + resource->rows > getDesktopCount() - 1) + // last in row + wminterface->changeDesktop(getCurrentDesktopNr()%resource->rows); + // first col + else + wminterface->changeDesktop(getCurrentDesktopNr() + resource->rows); + } else {} //no arrangement -> fallback solution + + break; + + case grabNextWindow: + showAllWorkspaces=false; + cycleWindowFocus(True); + break; + + case grabNextWindowAllWorkspaces: + showAllWorkspaces=true; + cycleWindowFocus(True); + break; + + case grabPrevWindow: + cycleWindowFocus(False); + break; + + case grabShade: + if (focus_window) + wminterface->shadeWindow(focus_window); + break; + + case grabStick: + if (focus_window) + wminterface->stickWindow(focus_window); + break; + + case grabExecute: + execCommand((char *const)grabSet.KeyMap[grabInt].execCommand); + break; + + case grabMaximize: + if (focus_window) + wminterface->maximizeWindow(focus_window, True, True); + break; + + case grabVertMax: + if (focus_window) + wminterface->maximizeWindow(focus_window, False, True); + break; + + case grabHorizMax: + if (focus_window) + wminterface->maximizeWindow(focus_window, True, False); + break; + + case grabNudgeRight: + if (focus_window) + XMoveWindow(getXDisplay(), focus_window, fw_x + 1, fw_y); + break; + + case grabNudgeLeft: + if (focus_window) + XMoveWindow(getXDisplay(), focus_window, fw_x - 1, fw_y); + break; + + case grabNudgeUp: + if (focus_window) + XMoveWindow(getXDisplay(), focus_window, fw_x, fw_y - 1); + break; + + case grabNudgeDown: + if (focus_window) + XMoveWindow(getXDisplay(), focus_window, fw_x, fw_y + 1); + break; + + case grabBigNudgeRight: + if (focus_window) + XMoveWindow(getXDisplay(), focus_window, fw_x + 10, fw_y); + break; + + case grabBigNudgeLeft: + if (focus_window) + XMoveWindow(getXDisplay(), focus_window, fw_x - 10, fw_y); + break; + + case grabBigNudgeUp: + if (focus_window) + XMoveWindow(getXDisplay(), focus_window, fw_x, fw_y - 10); + break; + + case grabBigNudgeDown: + if (focus_window) + XMoveWindow(getXDisplay(), focus_window, fw_x, fw_y + 10); + break; + + case grabHorizInc: + if (focus_window) { + XWindowAttributes foo; + XGetWindowAttributes(getXDisplay(), focus_window, &foo); + XResizeWindow(getXDisplay(), focus_window, + foo.width + 10, foo.height); + } + break; + + case grabVertInc: + if (focus_window) { + XWindowAttributes foo; + XGetWindowAttributes(getXDisplay(), focus_window, &foo); + XResizeWindow(getXDisplay(), focus_window, + foo.width, foo.height + 10); + } + break; + + case grabHorizDec: + if (focus_window) { + XWindowAttributes foo; + XGetWindowAttributes(getXDisplay(), focus_window, &foo); + if (foo.width < 11) + foo.width = 11; + XResizeWindow(getXDisplay(), focus_window, + foo.width - 10, foo.height); + } + break; + + case grabVertDec: + if (focus_window) { + XWindowAttributes foo; + XGetWindowAttributes(getXDisplay(), focus_window, &foo); + if (foo.height < 11) + foo.height = 11; + XResizeWindow(getXDisplay(), focus_window, + foo.width, foo.height - 10); + } + break; + + case grabToggleDecor: + if (focus_window) + wminterface->decorateToggleWindow(focus_window); + break; + } + } + timer->start(); + break; + } + + case ClientMessage: + if ((unsigned) e->xclient.data.l[0] == wm_delete_window) + shutdown(); + wminterface->handleNETEvents(*e); + break; + + case Expose: + if (!e->xexpose.count) + reconfigure(); + break; + + case ButtonPress: + if (e->xbutton.button == LEFT_BUTTON + || e->xbutton.button == RIGHT_BUTTON) { + if (e->xbutton.window == win_configBtn) { + XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn, + pixmap.pix_pressedBtn); + Redraw(); + } else if (e->xbutton.window == win_closeBtn) { + XSetWindowBackgroundPixmap(getXDisplay(), win_closeBtn, + pixmap.pix_pressedBtn); + Redraw(); + } else if (e->xbutton.window == win_title) { +// if (!raised) + XRaiseWindow(getXDisplay(), win_frame); +// raised = True; + } + } else if (e->xbutton.button == MIDDLE_BUTTON) { +// if (raised) + XLowerWindow(getXDisplay(), win_frame); +// raised = False; + } + break; + + case ButtonRelease: + if (e->xbutton.button == LEFT_BUTTON + || e->xbutton.button == RIGHT_BUTTON) { + if (e->xbutton.window == win_configBtn) { + if ((e->xbutton.x > 0) + && (e->xbutton.x < geom_configBtn.width) + && (e->xbutton.y > 0) + && (e->xbutton.y < geom_configBtn.height)) { + if (grabSet.instructCount > 0) { + XUngrabKey(getXDisplay(), AnyKey, AnyModifier, + getScreenInfo(0)->getRootWindow()); + XSync(getXDisplay(), False); + } + setKeygrabs(); + + // discard all XEvents (was causing us to go bananas on the + // user before, since we were executing all keygrabs at once + // that the user did when the configuration app was running) + // *cough* undocumented feature *cough* + // + + XEvent event; + while (XPending(getXDisplay())) { + XNextEvent(getXDisplay(), &event); + } + + // carry on then, little soldier + + loadKeygrabs(); + activateKeygrabs(); + timer->start(); + } + + XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn, + pixmap.pix_configBtn); + Redraw(); + } else if (e->xbutton.window == win_closeBtn) { + if ((e->xbutton.x > 0) + && (e->xbutton.x < geom_closeBtn.width) + && (e->xbutton.y > 0) + && (e->xbutton.y < geom_closeBtn.height)) { + if (e->xbutton.button == LEFT_BUTTON) { + shutdown(); + } else if (e->xbutton.button == RIGHT_BUTTON) { + if (withdrawn) { + XUnmapWindow(getXDisplay(), win_frame); + withdrawn = False; + iconic = True; + + XWMHints wmhints; + wmhints.initial_state = IconicState; + wmhints.flags = StateHint; + XSetWMHints(getXDisplay(), win_frame, &wmhints); + XMapWindow(getXDisplay(), win_frame); + + // this should work but doesn't seem to. *shrug* + // reconfigure(); + } else { + XIconifyWindow(getXDisplay(), win_frame, 0); + } + } + } + XSetWindowBackgroundPixmap(getXDisplay(), win_closeBtn, + pixmap.pix_configBtn); + Redraw(); + } + } + break; + + case ConfigureNotify: + if ((e->xconfigure.window == win_frame) && e->xconfigure.send_event) { + if (withdrawn) + reconfigure(); + + int parent_x, parent_y; + Window parent_root; + unsigned int parent_width, parent_height, parent_border_width; + unsigned int parent_depth; + + if (withdrawn) { + XGetGeometry(getXDisplay(), e->xconfigure.above, + &parent_root, &parent_x, &parent_y, + &parent_width, &parent_height, + &parent_border_width, &parent_depth); + frame.x = e->xconfigure.x + parent_x; + frame.y = e->xconfigure.y + parent_y; + } + } + break; + } +} + +void ToolWindow::timeout(void) +{ + XSetWindowBackgroundPixmap(getXDisplay(), win_configBtn, + pixmap.pix_configBtn); + Redraw(); +} + +/*--------------------------------*/ + +/*- window modifying functions -*/ + +/*--------------------------------*/ + +void ToolWindow::raiseWindow(Window) +{ +} + +void ToolWindow::lowerWindow(Window) +{ +} + +/*---------------------------------------*/ + +/*- desktop list management functions -*/ + +/*---------------------------------------*/ + +void ToolWindow::addDesktop(void) +{ + DesktopList *tmp = new DesktopList; + + // get the highest in the list + int highest = -1; + LinkedListIterator it(desktopList); + for (; it.current(); it++) + if (it.current()->number > highest) { + highest = it.current()->number; + it.reset(); + } + tmp->number = highest + 1; + + desktopList->insert(tmp, -1); // add to the end of the list + + desktop_count++; + + // add sticky windows to this desktop + LinkedListIterator it_win(windowList); + for (; it_win.current(); it_win++) + // only look for sticky windows on desktop 0, this will give us one + // copy of each sticky window + if ((it_win.current()->desktop == 0) && (it_win.current()->sticky)) { + WindowList *win = new WindowList; + win->win = it_win.current()->win; + win->iconic = it_win.current()->iconic; + win->shaded = False; + win->sticky = True; + win->desktop = tmp->number; + windowList->insert(win, -1); // add to the end of the list + } +} + +void ToolWindow::removeDesktop(int desktop) +{ + LinkedListIterator it(desktopList); + LinkedListIterator it_win(windowList); + + // remove sticky windows from this desktop + for (; it_win.current(); it_win++) + if ((it_win.current()->desktop == desktop) + && (it_win.current()->sticky)) + windowList->remove(it_win.current()); // remove just this window + // removeWindow() would remove all + // of the sticky windows. + + // remove the desktop from the linked list + for (; it.current(); it++) + if (it.current()->number == desktop) { + desktopList->remove(it.current()); + break; + } + + desktop_count--; + + // shift the rest to fill in the hole if not the last desktop was rm'd + int check=0; + bool found; + do { + found=False; + it.reset(); + for (; it.current(); it++) + if (it.current()->number == check) { + ++check; + found=True; + } + } while (found); + + // check is on the new hole, or desktop_count if there is no hole + // plug the hole by moving all the desktops above down one + while (check < desktop_count) { + it.reset(); + for (; it.current(); it++) + if(it.current()->number == (check + 1)) { + it.current()->number = check++; + break; + } + } +} + +void ToolWindow::focusDesktop(int desktop) +{ + LinkedListIterator it(desktopList); + for (; it.current(); it++) + if (it.current()->number == desktop) + current_desktop = it.current(); +} + +void ToolWindow::setDesktopCount(int count) +{ + int oldcount = desktop_count; + int delta = count - oldcount; + + if (delta > 0) { // added desktops + while(delta-- > 0) + addDesktop(); + } + else { // removed desktops + while(delta++ < 0) + removeDesktop(desktop_count - 1); // remove the last desktop + } +} + +/*--------------------------------------*/ + +/*- window list management functions -*/ + +/*--------------------------------------*/ + +void ToolWindow::clearWindows(void) +{ + focusWindow(0); + while (! windowList->empty()) + windowList->remove(0); +} + +void ToolWindow::removeWindow(Window win) +{ + if (focus_window == win) + focusWindow(0); + for (int i = 0; i < windowList->count(); ++i) + if (windowList->find(i)->win == win) + windowList->remove(i--); +} + +void ToolWindow::focusWindow(Window win) +{ + // have to only do this when the menu isn't visible, because we're + // setting focus while we're cycling.... Unfortunately, a side-effect + // of this is that we don't get a final focusWindow hit when we raise + // the selected window when done cycling, so we do an explicit + // bbtool->focusWindow() call from Stackmenu::selectFocused() after we + // XRaise the window.... + + if (! doingCycling ) { + focus_window = win; + if (resource->getMenuStackedCycling()) + focus_stack(win); + } +} + +void ToolWindow::moveWinToDesktop(Window win, int desktop) +{ + LinkedListIterator it(windowList); + for (; it.current(); it++) + if (it.current()->win == win) { + if (!it.current()->sticky) { + it.current()->desktop = desktop; + } + break; + } +} + +void ToolWindow::addSticky(WindowList *win) { + win->sticky = True; + LinkedListIterator it(desktopList); + for (; it.current(); it++) + if (win->desktop != it.current()->number) { + WindowList *copy = new WindowList; + copy->win = win->win; + copy->iconic = win->iconic; + copy->shaded = win->shaded; + copy->sticky = True; + copy->desktop = it.current()->number; + windowList->insert(copy, -1); + } +} + +void ToolWindow::removeSticky(const Window win, const int desktop) { + LinkedListIterator it(windowList); + for (register int i=0; i < desktop_count; i++) { + it.reset(); + for (; it.current(); it++) + if (it.current()->win == win) + if (it.current()->desktop != desktop) + windowList->remove(it.current()); + else + it.current()->sticky = False; + } +} + +void ToolWindow::windowAttributeChange(Window win) { + Atom real_type; + int format; + unsigned long n, extra; + WindowList *window = NULL; + BlackboxHints *net_hint; + LinkedListIterator it(windowList); + + for (; it.current(); it++) // find the window that's changed + if (it.current()->win == win) + window = it.current(); + if (!window) + return; + if (!(XGetWindowProperty(getXDisplay(), window->win, + getBlackboxAttributesAtom(), 0L, + PropBlackboxHintsElements, False, + getBlackboxAttributesAtom(), &real_type, + &format, &n, &extra, (unsigned char**)&net_hint) + == Success && net_hint)) + return; + if (n != PropBlackboxHintsElements) + return; + + if (net_hint->flags & AttribShaded) { + if (net_hint->attrib & AttribShaded) + window->shaded = True; + } else if (window->shaded) + window->shaded = False; + + if (wminterface->isIconicState(window->win) != window->iconic && + !window->shaded) + window->iconic = !window->iconic; + + if (net_hint->flags & AttribOmnipresent) { + if (net_hint->attrib & AttribOmnipresent) + if (!window->sticky) addSticky(window); + } else if (window->sticky) + if (window->sticky) removeSticky(window->win, getCurrentDesktopNr()); +} + +void ToolWindow::addWindow(Window win, int desktop) +{ + WindowList *newwin = new WindowList; + newwin->win = win; + newwin->iconic = wminterface->isIconicState(win); + newwin->shaded = False; + newwin->sticky = False; + newwin->desktop = desktop; + XSelectInput(getXDisplay(),newwin->win, + PropertyChangeMask); + if (resource->getMenuStackedCycling()) + add_stack(newwin); + else + add_linear(newwin); +} + +void ToolWindow::cycleWindowFocus(bool forward) +{ + if (resource->getMenuStackedCycling()) + cycle_stack(forward); + else + cycle_linear(forward); +} + +/******************************************************************************* + + LINEAR CYCLING FUNCTIONS + +*******************************************************************************/ + +void ToolWindow::add_linear(WindowList *newwin) +{ + int i; + int index = 0; // where the new window will be placed (defaults to the + // top of the list) + // insert after the focused window + LinkedListIterator it(windowList); + for (i=0; icount(); i++) { + it.set(i); + if (it.current()->win == focus_window) { + // get the index of the focused window + index = i+1; + break; + } + } + windowList->insert(newwin, index); +} + +void ToolWindow::cycle_linear(bool forward) +{ +/******************************************* + This does the oldschool straight rotation + order of cycling windows. +********************************************/ + int desktop = -1; + bool found = False; + WindowList *next = NULL; + int i, max; + + LinkedListIterator it(windowList); + max = windowList->count(); + for (i=0; idesktop == desktop) { + next = it.current(); + break; + } + } + if (it.current()->win == focus_window) { + found = True; + desktop = it.current()->desktop; + } + } + // if the next window wasn't found, start over at the beginning once more + if (!next) + { + for (i=0; idesktop == desktop) { + next = it.current(); + break; + } + } + } + + if (next) { + wminterface->setWindowFocus(next->win); + XRaiseWindow(getXDisplay(), next->win); + } +} + +/******************************************************************************* + + STACK CYCLING FUNCTIONS + +*******************************************************************************/ + +void ToolWindow::add_stack(WindowList *newwin) { + windowList->insert(newwin, 0); // insert at the top of the list + stackMenu->setMenuItems(); +} + +void ToolWindow::cycle_stack(bool forward) { + register bool showMenu = resource->getMenuShowCycleMenu() ? True : False; + stackMenu->show(forward, showMenu); +} + +void ToolWindow::focus_stack(Window win) +{ + WindowList *window = new WindowList; + LinkedListIterator it(windowList); + for (; it.current(); it++) { + if (it.current()->win == win) + if ((!it.current()->sticky) || + (it.current()->desktop == getCurrentDesktopNr())) + break; + } + if (it.current()) { + window->win = it.current()->win; + window->shaded = it.current()->shaded; + window->sticky = it.current()->sticky; + window->iconic = it.current()->iconic; + window->desktop = it.current()->desktop; + windowList->remove(it.current()); // remove it + windowList->insert(window, 0); // add it to the top + } +} + +void ToolWindow::saveMenuSearch(Window window, Basemenu *) +{ + menuWin = window; +} + +void ToolWindow::removeMenuSearch(Window) +{ + menuWin = (Window)NULL; +} + +void ToolWindow::p() +{ + printf("window | stick | shade | icon | desk\n"); + LinkedListIterator it(windowList); + for (; it.current(); it++) + printf("%010i | %d | %d | %d | %d\n", (int)it.current()->win, + it.current()->sticky, it.current()->shaded, it.current()->iconic, + it.current()->desktop); +} + diff --git a/src/stackmenu.cc b/src/stackmenu.cc dissimilarity index 73% index 3d0f53f..9376fd4 100644 --- a/src/stackmenu.cc +++ b/src/stackmenu.cc @@ -1,236 +1,236 @@ -// cycling.cc for bbkeys -// -// Copyright (c) 2001 by Ben Jansens -// Copyright (c) 2001 by Jason Kasper (vanRijn) -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// -// (See the included file COPYING / GPL-2.0) -// -// $Id$ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif // HAVE_CONFIG_H - -#include "stackmenu.hh" -#include "bbkeys.hh" -#include "LinkedList.hh" -#include "wminterface.hh" - -extern "C" { -#include -} - -Stackmenu::Stackmenu(ToolWindow *tool) : - Basemenu(tool) -{ - bbtool = tool; - - setTitleVisibility(False); - setMovable(False); - setAlignment(AlignBottom); - XSelectInput(bbtool->getXDisplay(), getWindowID(), VisibilityChangeMask); -} - -Stackmenu::~Stackmenu() { -} - -void Stackmenu::itemSelected(int,int) { -} - -void Stackmenu::reconfigure() -{ - Basemenu::reconfigure(); -} - -void Stackmenu::setMenuItems() { - XTextProperty text_prop; - char **list; - char *title=0; - int num; - - LinkedListIterator it(bbtool->windowList); - - clearMenu(); - for (; it.current(); it++) { - if (((bbtool->getShowAllWorkspaces()) && - ((!it.current()->sticky) || - (it.current()->desktop == bbtool->getCurrentDesktopNr()))) - || - ((!bbtool->getShowAllWorkspaces()) && - (it.current()->desktop == bbtool->getCurrentDesktopNr()))) { - - if (title) { - delete [] title; - title = 0; - } - - // what's our window name? - if (XGetWMName(bbtool->getXDisplay(), it.current()->win, &text_prop)) { - if (text_prop.value && text_prop.nitems > 0) { - if (text_prop.encoding != XA_STRING) { - text_prop.nitems = strlen((char *) text_prop.value); - - if ((XmbTextPropertyToTextList(bbtool->getXDisplay(), &text_prop, - &list, &num) == Success) && - (num > 0) && *list) { - title = bstrdup(*list); - XFreeStringList(list); - } else - title = bstrdup((char *) text_prop.value); - } else - title = bstrdup((char *) text_prop.value); - - XFree((char *) text_prop.value); - } else - title = bstrdup( "Unnamed"); - } else - title = bstrdup( "Unnamed"); - - // now tack on the workspace name if we need to - if (bbtool->getShowAllWorkspaces()) { - int size = strlen(title) + strlen(" (workspace )") + 2; - char *workspace = (char*) malloc(size); - if (workspace) { - snprintf(workspace, size, "%s (workspace %i)", title, - it.current()->desktop+1); - insert(workspace); - free(workspace); - } - } else - insert(title); - } - } -} - -void Stackmenu::clearMenu() { - while (getCount()) - remove(0); -} - -void Stackmenu::selectFocused(bool raise) -{ - if ( raise ) - hide(); - - int selected = menuPosition; - LinkedListIterator it(bbtool->windowList); - for(; it.current(); it++) - if (((bbtool->getShowAllWorkspaces()) && - ((!it.current()->sticky) || - (it.current()->desktop == bbtool->getCurrentDesktopNr()))) - || - ((!bbtool->getShowAllWorkspaces()) && - (it.current()->desktop == bbtool->getCurrentDesktopNr()))) { - if(!selected--) { - bbtool->wminterface->setWindowFocus(it.current()->win); - if ( raise ) { - // okay, an explanation is in order... First, we have to - // hide our window so that focusWindow() actually does - // anything. - // Next, if the window to focus is on a different desktop than - // the current one, we need to switch there. - // Then we XRaiseWindow, because if we did - // focusWindow() first, we'd then XRaise() the wrong window. - // Lastly, we update bbkey's stack with what we just - // raised... - if (bbtool->getCurrentDesktopNr() != it.current()->desktop) - bbtool->wminterface->changeDesktop(it.current()->desktop, False); - XRaiseWindow(bbtool->getXDisplay(), it.current()->win); - bbtool->focusWindow(it.current()->win); - } - } - } -} - -void Stackmenu::key_press(int grabInt) -{ - switch (grabInt) { - case grabNextWindow: - case grabNextWindowAllWorkspaces: - if(++menuPosition >= getCount()) - menuPosition = 0; - setSelected(menuPosition); - selectFocused(False); - break; - case grabPrevWindow: - if(--menuPosition < 0) - menuPosition = getCount() - 1; - setSelected(menuPosition); - selectFocused(False); - break; - default: - break; - } -} - -void Stackmenu::hide() -{ - XUngrabKeyboard(bbtool->getXDisplay(), CurrentTime); - Basemenu::hide(); - bbtool->setCycling(False); -} - - -void Stackmenu::show(void) -{ - Basemenu::show(); -} - - -void Stackmenu::show(bool forward, bool showMenu) -{ - setMenuItems(); - if (getCount() < 1) return; // no windows, just return - if (getCount() == 1) { - // only 1 window, focus it and leave - LinkedListIterator it(bbtool->windowList); - for (; it.current(); it++) - if (it.current()->desktop == bbtool->getCurrentDesktopNr()) - bbtool->wminterface->setWindowFocus(it.current()->win); - return; - } - - XRaiseWindow(bbtool->getXDisplay(), getWindowID()); - XGrabKeyboard(bbtool->getXDisplay(), - bbtool->getScreenInfo(0)->getRootWindow(), True, - GrabModeAsync, GrabModeAsync, CurrentTime); - - menuPosition = 0; - key_press(forward?grabNextWindow:grabPrevWindow); - - bbtool->setCycling(True); - - if (showMenu) { - show(); - centerPosition(); - } -} - -void Stackmenu::centerPosition() -{ - int x = (bbtool->getCurrentScreenInfo()->getWidth()>>1) - (getWidth()>>1); - int y = (bbtool->getCurrentScreenInfo()->getHeight()>>1) - (getHeight()>>1); - if (x>0 && y>0) - Basemenu::move(x, y); -} - -void Stackmenu::setSelected(int sel) -{ - if ((sel<0) || (sel>=getCount())) return; - setHighlight(sel); - update(); -} +// cycling.cc for bbkeys +// +// Copyright (c) 2001 by Ben Jansens +// Copyright (c) 2001 by Jason Kasper (vanRijn) +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// (See the included file COPYING / GPL-2.0) +// +// $Id$ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif // HAVE_CONFIG_H + +#include "stackmenu.hh" +#include "bbkeys.hh" +#include "LinkedList.hh" +#include "wminterface.hh" + +extern "C" { +#include +} + +Stackmenu::Stackmenu(ToolWindow *tool) : + Basemenu(tool) +{ + bbtool = tool; + + setTitleVisibility(False); + setMovable(False); + setAlignment(AlignBottom); + XSelectInput(bbtool->getXDisplay(), getWindowID(), VisibilityChangeMask); +} + +Stackmenu::~Stackmenu() { +} + +void Stackmenu::itemSelected(int,int) { +} + +void Stackmenu::reconfigure() +{ + Basemenu::reconfigure(); +} + +void Stackmenu::setMenuItems() { + XTextProperty text_prop; + char **list; + char *title=0; + int num; + + LinkedListIterator it(bbtool->windowList); + + clearMenu(); + for (; it.current(); it++) { + if (((bbtool->getShowAllWorkspaces()) && + ((!it.current()->sticky) || + (it.current()->desktop == bbtool->getCurrentDesktopNr()))) + || + ((!bbtool->getShowAllWorkspaces()) && + (it.current()->desktop == bbtool->getCurrentDesktopNr()))) { + + if (title) { + delete [] title; + title = 0; + } + + // what's our window name? + if (XGetWMName(bbtool->getXDisplay(), it.current()->win, &text_prop)) { + if (text_prop.value && text_prop.nitems > 0) { + if (text_prop.encoding != XA_STRING) { + text_prop.nitems = strlen((char *) text_prop.value); + + if ((XmbTextPropertyToTextList(bbtool->getXDisplay(), &text_prop, + &list, &num) == Success) && + (num > 0) && *list) { + title = bstrdup(*list); + XFreeStringList(list); + } else + title = bstrdup((char *) text_prop.value); + } else + title = bstrdup((char *) text_prop.value); + + XFree((char *) text_prop.value); + } else + title = bstrdup( "Unnamed"); + } else + title = bstrdup( "Unnamed"); + + // now tack on the workspace name if we need to + if (bbtool->getShowAllWorkspaces()) { + int size = strlen(title) + strlen(" (workspace )") + 2; + char *workspace = (char*) malloc(size); + if (workspace) { + snprintf(workspace, size, "%s (workspace %i)", title, + it.current()->desktop+1); + insert(workspace); + free(workspace); + } + } else + insert(title); + } + } +} + +void Stackmenu::clearMenu() { + while (getCount()) + remove(0); +} + +void Stackmenu::selectFocused(bool raise) +{ + if ( raise ) + hide(); + + int selected = menuPosition; + LinkedListIterator it(bbtool->windowList); + for(; it.current(); it++) + if (((bbtool->getShowAllWorkspaces()) && + ((!it.current()->sticky) || + (it.current()->desktop == bbtool->getCurrentDesktopNr()))) + || + ((!bbtool->getShowAllWorkspaces()) && + (it.current()->desktop == bbtool->getCurrentDesktopNr()))) { + if(!selected--) { + bbtool->wminterface->setWindowFocus(it.current()->win); + if ( raise ) { + // okay, an explanation is in order... First, we have to + // hide our window so that focusWindow() actually does + // anything. + // Next, if the window to focus is on a different desktop than + // the current one, we need to switch there. + // Then we XRaiseWindow, because if we did + // focusWindow() first, we'd then XRaise() the wrong window. + // Lastly, we update bbkey's stack with what we just + // raised... + if (bbtool->getCurrentDesktopNr() != it.current()->desktop) + bbtool->wminterface->changeDesktop(it.current()->desktop, False); + XRaiseWindow(bbtool->getXDisplay(), it.current()->win); + bbtool->focusWindow(it.current()->win); + } + } + } +} + +void Stackmenu::key_press(int grabInt) +{ + switch (grabInt) { + case grabNextWindow: + case grabNextWindowAllWorkspaces: + if(++menuPosition >= getCount()) + menuPosition = 0; + setSelected(menuPosition); + selectFocused(False); + break; + case grabPrevWindow: + if(--menuPosition < 0) + menuPosition = getCount() - 1; + setSelected(menuPosition); + selectFocused(False); + break; + default: + break; + } +} + +void Stackmenu::hide() +{ + XUngrabKeyboard(bbtool->getXDisplay(), CurrentTime); + Basemenu::hide(); + bbtool->setCycling(False); +} + + +void Stackmenu::show(void) +{ + Basemenu::show(); +} + + +void Stackmenu::show(bool forward, bool showMenu) +{ + setMenuItems(); + if (getCount() < 1) return; // no windows, just return + if (getCount() == 1) { + // only 1 window, focus it and leave + LinkedListIterator it(bbtool->windowList); + for (; it.current(); it++) + if (it.current()->desktop == bbtool->getCurrentDesktopNr()) + bbtool->wminterface->setWindowFocus(it.current()->win); + return; + } + + XRaiseWindow(bbtool->getXDisplay(), getWindowID()); + XGrabKeyboard(bbtool->getXDisplay(), + bbtool->getScreenInfo(0)->getRootWindow(), True, + GrabModeAsync, GrabModeAsync, CurrentTime); + + menuPosition = 0; + key_press(forward?grabNextWindow:grabPrevWindow); + + bbtool->setCycling(True); + + if (showMenu) { + show(); + centerPosition(); + } +} + +void Stackmenu::centerPosition() +{ + int x = (bbtool->getCurrentScreenInfo()->getWidth()>>1) - (getWidth()>>1); + int y = (bbtool->getCurrentScreenInfo()->getHeight()>>1) - (getHeight()>>1); + if (x>0 && y>0) + Basemenu::move(x, y); +} + +void Stackmenu::setSelected(int sel) +{ + if ((sel<0) || (sel>=getCount())) return; + setHighlight(sel); + update(); +} diff --git a/src/wminterface.cc b/src/wminterface.cc dissimilarity index 72% index 0669fc3..7d8d9e0 100644 --- a/src/wminterface.cc +++ b/src/wminterface.cc @@ -1,327 +1,327 @@ -// wminterface.cc for bbtools. -// -// Copyright (c) 1998-1999 by John Kennis, jkennis@chello.nl -// Copyright (c) 2001 by Ben Jansens -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// -// (See the included file COPYING / GPL-2.0) -// -// $Id$ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif // HAVE_CONFIG_H - -#include "wminterface.hh" -#include "bbkeys.hh" - -WMInterface::WMInterface(ToolWindow *toolwindow) : NETInterface(toolwindow) { - bbtool=toolwindow; -} - -WMInterface::~WMInterface() { -} - -void WMInterface::sendClientMessage(Atom atom, XID data) { - XEvent e; - unsigned long mask; - - e.xclient.type = ClientMessage; - e.xclient.window = bbtool->getCurrentScreenInfo()->getRootWindow(); - e.xclient.message_type = atom; - e.xclient.format = 32; - e.xclient.data.l[0] = (unsigned long) data; - e.xclient.data.l[1] = 0; - - mask = SubstructureRedirectMask; - XSendEvent(bbtool->getXDisplay(), - bbtool->getCurrentScreenInfo()->getRootWindow(), - False, mask, &e); -} - -void WMInterface::changeDesktop(int desk_number, bool) { - sendClientMessage(bbtool->getBlackboxChangeWorkspaceAtom(), - static_cast(desk_number)); -} - -void WMInterface::sendWindowToDesktop(Window win, int desk_number) { - XEvent e; - unsigned long mask; - - e.xclient.type = ClientMessage; - e.xclient.window = win; - e.xclient.message_type = bbtool->getBlackboxChangeAttributesAtom(); - e.xclient.format = 32; - e.xclient.data.l[0] = AttribWorkspace; - e.xclient.data.l[2] = desk_number; - e.xclient.data.l[1] = e.xclient.data.l[3] = 0; - e.xclient.data.l[4] = e.xclient.data.l[5] = 0; - - mask = SubstructureRedirectMask; - XSendEvent(bbtool->getXDisplay(), - bbtool->getCurrentScreenInfo()->getRootWindow(), - False, mask, &e); - bbtool->moveWinToDesktop(win, desk_number); -} - -void WMInterface::decorateToggleWindow(Window win) -{ - XEvent e; - e.xclient.type = ClientMessage; - e.xclient.message_type = bbtool->getBlackboxChangeAttributesAtom(); - e.xclient.window = win; - e.xclient.format = 32; - e.xclient.data.l[0] = e.xclient.data.l[1] = - e.xclient.data.l[2] = e.xclient.data.l[3] = - e.xclient.data.l[4] = e.xclient.data.l[5] = 0l; - e.xclient.data.l[0] |= AttribDecoration; - - int format; - Atom atom_return; - unsigned long num, len; - BlackboxAttributes *net_attributes; - - if (XGetWindowProperty(bbtool->getXDisplay(), win, - bbtool->getBlackboxAttributesAtom(), 0, - PropBlackboxAttributesElements, False, - bbtool->getBlackboxAttributesAtom(), &atom_return, - &format, &num, &len, (unsigned char **) &net_attributes) - == - Success && net_attributes) { - if(num == PropBlackboxAttributesElements) { - if (net_attributes->decoration == DecorNone) - e.xclient.data.l[4] = DecorNormal; - else - e.xclient.data.l[4] = DecorNone; - } - XFree((void *) net_attributes); - } else - e.xclient.data.l[4] = DecorNone; - - XSendEvent(bbtool->getXDisplay(), bbtool->getScreenInfo(0)->getRootWindow(), False, - SubstructureRedirectMask, &e); -} - -void WMInterface::setWindowFocus(Window win) { - XEvent e; - unsigned long mask; - - e.xclient.type = ClientMessage; - e.xclient.window = win; - - e.xclient.message_type = bbtool->getBlackboxChangeWindowFocusAtom(); - e.xclient.format = 32; - e.xclient.data.l[0] = 0; - e.xclient.data.l[1] = 0; - - mask = SubstructureRedirectMask; - XSendEvent(bbtool->getXDisplay(), - bbtool->getCurrentScreenInfo()->getRootWindow(), - False, mask, &e); -} - -void WMInterface::shadeWindow(Window win) { - XEvent e; - e.xclient.type = ClientMessage; - e.xclient.message_type = bbtool->getBlackboxChangeAttributesAtom(); - e.xclient.window = win; - e.xclient.format = 32; - e.xclient.data.l[0] = AttribShaded; - e.xclient.data.l[2] = e.xclient.data.l[3] = e.xclient.data.l[4] = 0l; - - Atom atom_return; - int foo; - unsigned long ulfoo, nitems; - BlackboxAttributes *net; - if (XGetWindowProperty(bbtool->getXDisplay(), win, - bbtool->getBlackboxAttributesAtom(), - 0l, - PropBlackboxAttributesElements, - False, - bbtool->getBlackboxAttributesAtom(), - &atom_return, &foo, &nitems, &ulfoo, (unsigned char **) &net) - == - Success && net && nitems - == - PropBlackboxAttributesElements) - { - e.xclient.data.l[1] = net->attrib ^ AttribShaded; - XFree((void *) net); - } else - e.xclient.data.l[1] = AttribShaded; - - XSendEvent(bbtool->getXDisplay(), bbtool->getScreenInfo(0)->getRootWindow(), False, - SubstructureRedirectMask, &e); -} - -void WMInterface::maximizeWindow(Window win, bool maxhorz, bool maxvert) { - XEvent e; - e.xclient.type = ClientMessage; - e.xclient.message_type = bbtool->getBlackboxChangeAttributesAtom(); - e.xclient.window = win; - e.xclient.format = 32; - e.xclient.data.l[0] = (maxhorz?AttribMaxHoriz:0) | (maxvert?AttribMaxVert:0); - e.xclient.data.l[2] = e.xclient.data.l[3] = e.xclient.data.l[4] = 0l; - - Atom atom_return; - int foo; - unsigned long ulfoo, nitems; - BlackboxAttributes *net; - if (XGetWindowProperty(bbtool->getXDisplay(), - win, - bbtool->getBlackboxAttributesAtom(), - 0l, - PropBlackboxAttributesElements, - False, - bbtool->getBlackboxAttributesAtom(), - &atom_return, &foo, &nitems, &ulfoo, (unsigned char **) &net) - == - Success && net && nitems - == - PropBlackboxAttributesElements) { - e.xclient.data.l[1] = - net->attrib ^ ((maxhorz?AttribMaxHoriz:0) | (maxvert?AttribMaxVert:0)); - XFree((void *) net); - } else - e.xclient.data.l[1] = (maxhorz?AttribMaxHoriz:0) | (maxvert?AttribMaxVert:0); - - XSendEvent(bbtool->getXDisplay(), bbtool->getScreenInfo(0)->getRootWindow(), - False, SubstructureRedirectMask, &e); -} - -void WMInterface::stickWindow(Window win) -{ - XEvent e; - e.xclient.type = ClientMessage; - e.xclient.message_type = bbtool->getBlackboxChangeAttributesAtom(); - e.xclient.window = win; - e.xclient.format = 32; - e.xclient.data.l[0] = AttribOmnipresent; - e.xclient.data.l[2] = e.xclient.data.l[3] = e.xclient.data.l[4] = 0l; - - Atom atom_return; - int foo; - unsigned long ulfoo, nitems; - BlackboxAttributes *net; - if (XGetWindowProperty(bbtool->getXDisplay(), - win, - bbtool->getBlackboxAttributesAtom(), - 0l, - PropBlackboxAttributesElements, - False, - bbtool->getBlackboxAttributesAtom(), - &atom_return, &foo, &nitems, &ulfoo, (unsigned char **) &net) - == - Success && net && nitems - == - PropBlackboxAttributesElements) { - e.xclient.data.l[1] = net->attrib ^ AttribOmnipresent; - XFree((void *) net); - } else - e.xclient.data.l[1] = AttribOmnipresent; - - XSendEvent(bbtool->getXDisplay(), bbtool->getScreenInfo(0)->getRootWindow(), False, - SubstructureRedirectMask, &e); -} - -int WMInterface::isIconicState(Window win) { - Atom real_type; - int format; - unsigned long n, extra; - int status; - long *p=0; - int y=0; - - status = XGetWindowProperty(bbtool->getXDisplay(), win, - bbtool->getWMStateAtom(), 0L, 1L, - False, bbtool->getWMStateAtom(), &real_type, - &format, &n, &extra, (unsigned char**)&p); - if (!status) { - if (p) { - y=(int)p[0]; - XFree(p); - return (y==IconicState) ? 1 : 0; - } else { - return 0; - } - } - - return -1; -} - -int WMInterface::getAttributes(Window win) { - Atom real_type; - int format; - unsigned long n, extra; - int status; - long *p=0; - int y=0; - - - status = XGetWindowProperty(bbtool->getXDisplay(), win, - bbtool->getBlackboxAttributesAtom(), 0L, 1L, - False, bbtool->getBlackboxAttributesAtom(), - &real_type, &format,&n, &extra, - (unsigned char**)&p); - if (!status) { - if (p) { - y=(int)p[0]; - XFree(p); - return y; - } else { - return 0; - } - } - - return -1; -} - -void WMInterface::NETNotifyStartup() { -// bbtool->setNETInit(); - - /* - * We clear all windows from our internal window lists when we get this - * message because its quite possible that blackbox is restarting and deleted - * us before deleting other windows, leaving rogue windows behind in our - * window lists. - */ - bbtool->clearWindows(); -} - -void WMInterface::NETNotifyWindowAdd(Window win,int desktop_nr) { - bbtool->addWindow(win, desktop_nr); -} - -void WMInterface::NETNotifyDel(Window win) { - bbtool->removeWindow(win); -} - -void WMInterface::NETNotifyAttributes(Window win) -{ - bbtool->windowAttributeChange(win); -} - -void WMInterface::NETNotifyFocus(Window win) { - bbtool->focusWindow(win); -} - -void WMInterface::NETNotifyCurrentWorkspace(int desktop_nr) { - bbtool->focusDesktop(desktop_nr); -} - -void WMInterface::NETNotifyWorkspaceCount(int count) { - bbtool->setDesktopCount(count); -} +// wminterface.cc for bbtools. +// +// Copyright (c) 1998-1999 by John Kennis, jkennis@chello.nl +// Copyright (c) 2001 by Ben Jansens +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// (See the included file COPYING / GPL-2.0) +// +// $Id$ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif // HAVE_CONFIG_H + +#include "wminterface.hh" +#include "bbkeys.hh" + +WMInterface::WMInterface(ToolWindow *toolwindow) : NETInterface(toolwindow) { + bbtool=toolwindow; +} + +WMInterface::~WMInterface() { +} + +void WMInterface::sendClientMessage(Atom atom, XID data) { + XEvent e; + unsigned long mask; + + e.xclient.type = ClientMessage; + e.xclient.window = bbtool->getCurrentScreenInfo()->getRootWindow(); + e.xclient.message_type = atom; + e.xclient.format = 32; + e.xclient.data.l[0] = (unsigned long) data; + e.xclient.data.l[1] = 0; + + mask = SubstructureRedirectMask; + XSendEvent(bbtool->getXDisplay(), + bbtool->getCurrentScreenInfo()->getRootWindow(), + False, mask, &e); +} + +void WMInterface::changeDesktop(int desk_number, bool) { + sendClientMessage(bbtool->getBlackboxChangeWorkspaceAtom(), + static_cast(desk_number)); +} + +void WMInterface::sendWindowToDesktop(Window win, int desk_number) { + XEvent e; + unsigned long mask; + + e.xclient.type = ClientMessage; + e.xclient.window = win; + e.xclient.message_type = bbtool->getBlackboxChangeAttributesAtom(); + e.xclient.format = 32; + e.xclient.data.l[0] = AttribWorkspace; + e.xclient.data.l[2] = desk_number; + e.xclient.data.l[1] = e.xclient.data.l[3] = 0; + e.xclient.data.l[4] = e.xclient.data.l[5] = 0; + + mask = SubstructureRedirectMask; + XSendEvent(bbtool->getXDisplay(), + bbtool->getCurrentScreenInfo()->getRootWindow(), + False, mask, &e); + bbtool->moveWinToDesktop(win, desk_number); +} + +void WMInterface::decorateToggleWindow(Window win) +{ + XEvent e; + e.xclient.type = ClientMessage; + e.xclient.message_type = bbtool->getBlackboxChangeAttributesAtom(); + e.xclient.window = win; + e.xclient.format = 32; + e.xclient.data.l[0] = e.xclient.data.l[1] = + e.xclient.data.l[2] = e.xclient.data.l[3] = + e.xclient.data.l[4] = e.xclient.data.l[5] = 0l; + e.xclient.data.l[0] |= AttribDecoration; + + int format; + Atom atom_return; + unsigned long num, len; + BlackboxAttributes *net_attributes; + + if (XGetWindowProperty(bbtool->getXDisplay(), win, + bbtool->getBlackboxAttributesAtom(), 0, + PropBlackboxAttributesElements, False, + bbtool->getBlackboxAttributesAtom(), &atom_return, + &format, &num, &len, (unsigned char **) &net_attributes) + == + Success && net_attributes) { + if(num == PropBlackboxAttributesElements) { + if (net_attributes->decoration == DecorNone) + e.xclient.data.l[4] = DecorNormal; + else + e.xclient.data.l[4] = DecorNone; + } + XFree((void *) net_attributes); + } else + e.xclient.data.l[4] = DecorNone; + + XSendEvent(bbtool->getXDisplay(), bbtool->getScreenInfo(0)->getRootWindow(), False, + SubstructureRedirectMask, &e); +} + +void WMInterface::setWindowFocus(Window win) { + XEvent e; + unsigned long mask; + + e.xclient.type = ClientMessage; + e.xclient.window = win; + + e.xclient.message_type = bbtool->getBlackboxChangeWindowFocusAtom(); + e.xclient.format = 32; + e.xclient.data.l[0] = 0; + e.xclient.data.l[1] = 0; + + mask = SubstructureRedirectMask; + XSendEvent(bbtool->getXDisplay(), + bbtool->getCurrentScreenInfo()->getRootWindow(), + False, mask, &e); +} + +void WMInterface::shadeWindow(Window win) { + XEvent e; + e.xclient.type = ClientMessage; + e.xclient.message_type = bbtool->getBlackboxChangeAttributesAtom(); + e.xclient.window = win; + e.xclient.format = 32; + e.xclient.data.l[0] = AttribShaded; + e.xclient.data.l[2] = e.xclient.data.l[3] = e.xclient.data.l[4] = 0l; + + Atom atom_return; + int foo; + unsigned long ulfoo, nitems; + BlackboxAttributes *net; + if (XGetWindowProperty(bbtool->getXDisplay(), win, + bbtool->getBlackboxAttributesAtom(), + 0l, + PropBlackboxAttributesElements, + False, + bbtool->getBlackboxAttributesAtom(), + &atom_return, &foo, &nitems, &ulfoo, (unsigned char **) &net) + == + Success && net && nitems + == + PropBlackboxAttributesElements) + { + e.xclient.data.l[1] = net->attrib ^ AttribShaded; + XFree((void *) net); + } else + e.xclient.data.l[1] = AttribShaded; + + XSendEvent(bbtool->getXDisplay(), bbtool->getScreenInfo(0)->getRootWindow(), False, + SubstructureRedirectMask, &e); +} + +void WMInterface::maximizeWindow(Window win, bool maxhorz, bool maxvert) { + XEvent e; + e.xclient.type = ClientMessage; + e.xclient.message_type = bbtool->getBlackboxChangeAttributesAtom(); + e.xclient.window = win; + e.xclient.format = 32; + e.xclient.data.l[0] = (maxhorz?AttribMaxHoriz:0) | (maxvert?AttribMaxVert:0); + e.xclient.data.l[2] = e.xclient.data.l[3] = e.xclient.data.l[4] = 0l; + + Atom atom_return; + int foo; + unsigned long ulfoo, nitems; + BlackboxAttributes *net; + if (XGetWindowProperty(bbtool->getXDisplay(), + win, + bbtool->getBlackboxAttributesAtom(), + 0l, + PropBlackboxAttributesElements, + False, + bbtool->getBlackboxAttributesAtom(), + &atom_return, &foo, &nitems, &ulfoo, (unsigned char **) &net) + == + Success && net && nitems + == + PropBlackboxAttributesElements) { + e.xclient.data.l[1] = + net->attrib ^ ((maxhorz?AttribMaxHoriz:0) | (maxvert?AttribMaxVert:0)); + XFree((void *) net); + } else + e.xclient.data.l[1] = (maxhorz?AttribMaxHoriz:0) | (maxvert?AttribMaxVert:0); + + XSendEvent(bbtool->getXDisplay(), bbtool->getScreenInfo(0)->getRootWindow(), + False, SubstructureRedirectMask, &e); +} + +void WMInterface::stickWindow(Window win) +{ + XEvent e; + e.xclient.type = ClientMessage; + e.xclient.message_type = bbtool->getBlackboxChangeAttributesAtom(); + e.xclient.window = win; + e.xclient.format = 32; + e.xclient.data.l[0] = AttribOmnipresent; + e.xclient.data.l[2] = e.xclient.data.l[3] = e.xclient.data.l[4] = 0l; + + Atom atom_return; + int foo; + unsigned long ulfoo, nitems; + BlackboxAttributes *net; + if (XGetWindowProperty(bbtool->getXDisplay(), + win, + bbtool->getBlackboxAttributesAtom(), + 0l, + PropBlackboxAttributesElements, + False, + bbtool->getBlackboxAttributesAtom(), + &atom_return, &foo, &nitems, &ulfoo, (unsigned char **) &net) + == + Success && net && nitems + == + PropBlackboxAttributesElements) { + e.xclient.data.l[1] = net->attrib ^ AttribOmnipresent; + XFree((void *) net); + } else + e.xclient.data.l[1] = AttribOmnipresent; + + XSendEvent(bbtool->getXDisplay(), bbtool->getScreenInfo(0)->getRootWindow(), False, + SubstructureRedirectMask, &e); +} + +int WMInterface::isIconicState(Window win) { + Atom real_type; + int format; + unsigned long n, extra; + int status; + long *p=0; + int y=0; + + status = XGetWindowProperty(bbtool->getXDisplay(), win, + bbtool->getWMStateAtom(), 0L, 1L, + False, bbtool->getWMStateAtom(), &real_type, + &format, &n, &extra, (unsigned char**)&p); + if (!status) { + if (p) { + y=(int)p[0]; + XFree(p); + return (y==IconicState) ? 1 : 0; + } else { + return 0; + } + } + + return -1; +} + +int WMInterface::getAttributes(Window win) { + Atom real_type; + int format; + unsigned long n, extra; + int status; + long *p=0; + int y=0; + + + status = XGetWindowProperty(bbtool->getXDisplay(), win, + bbtool->getBlackboxAttributesAtom(), 0L, 1L, + False, bbtool->getBlackboxAttributesAtom(), + &real_type, &format,&n, &extra, + (unsigned char**)&p); + if (!status) { + if (p) { + y=(int)p[0]; + XFree(p); + return y; + } else { + return 0; + } + } + + return -1; +} + +void WMInterface::NETNotifyStartup() { +// bbtool->setNETInit(); + + /* + * We clear all windows from our internal window lists when we get this + * message because its quite possible that blackbox is restarting and deleted + * us before deleting other windows, leaving rogue windows behind in our + * window lists. + */ + bbtool->clearWindows(); +} + +void WMInterface::NETNotifyWindowAdd(Window win,int desktop_nr) { + bbtool->addWindow(win, desktop_nr); +} + +void WMInterface::NETNotifyDel(Window win) { + bbtool->removeWindow(win); +} + +void WMInterface::NETNotifyAttributes(Window win) +{ + bbtool->windowAttributeChange(win); +} + +void WMInterface::NETNotifyFocus(Window win) { + bbtool->focusWindow(win); +} + +void WMInterface::NETNotifyCurrentWorkspace(int desktop_nr) { + bbtool->focusDesktop(desktop_nr); +} + +void WMInterface::NETNotifyWorkspaceCount(int count) { + bbtool->setDesktopCount(count); +} -- 2.11.4.GIT