- changing MaxInstructions to 100 for cthulhain (crazy nut) =:)
[bbkeys.git] / src / stackmenu.cc
bloba6a76639c3226616ffdf4fd852e0900d2eeed444
1 // cycling.cc for bbkeys
2 //
3 // Copyright (c) 2001 by Ben Jansens <xor@orodu.net>
4 // Copyright (c) 2001 by Jason Kasper (vanRijn) <vR@movingparts.net>
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 // (See the included file COPYING / GPL-2.0)
22 // $Id$
24 #include "bbkeys.hh"
25 #include "LinkedList.hh"
27 #include <X11/Xutil.h>
29 #ifdef HAVE_CONFIG_H
30 # include "../config.h"
31 #endif // HAVE_CONFIG_H
33 Stackmenu::Stackmenu(ToolWindow *tool) :
34 Basemenu(tool)
36 bbtool = tool;
38 setTitleVisibility(False);
39 setMovable(False);
40 setAlignment(AlignBottom);
41 XSelectInput(bbtool->getXDisplay(), getWindowID(), VisibilityChangeMask);
44 Stackmenu::~Stackmenu() {
47 void Stackmenu::itemSelected(int,int) {
50 void Stackmenu::reconfigure()
52 Basemenu::reconfigure();
55 void Stackmenu::setMenuItems() {
56 XTextProperty text_prop;
57 char **list;
58 char *title=0;
59 int num;
61 LinkedListIterator<WindowList> it(bbtool->windowList);
63 clearMenu();
64 for (; it.current(); it++) {
65 if (((bbtool->getShowAllWorkspaces()) &&
66 ((!it.current()->sticky) ||
67 (it.current()->desktop == bbtool->getCurrentDesktopNr())))
69 ((!bbtool->getShowAllWorkspaces()) &&
70 (it.current()->desktop == bbtool->getCurrentDesktopNr()))) {
72 if (title) {
73 delete [] title;
74 title = 0;
77 // what's our window name?
78 if (XGetWMName(bbtool->getXDisplay(), it.current()->win, &text_prop)) {
79 if (text_prop.value && text_prop.nitems > 0) {
80 if (text_prop.encoding != XA_STRING) {
81 text_prop.nitems = strlen((char *) text_prop.value);
83 if ((XmbTextPropertyToTextList(bbtool->getXDisplay(), &text_prop,
84 &list, &num) == Success) &&
85 (num > 0) && *list) {
86 title = bstrdup(*list);
87 XFreeStringList(list);
88 } else
89 title = bstrdup((char *) text_prop.value);
90 } else
91 title = bstrdup((char *) text_prop.value);
93 XFree((char *) text_prop.value);
94 } else
95 title = bstrdup( "Unnamed");
96 } else
97 title = bstrdup( "Unnamed");
99 // now tack on the workspace name if we need to
100 if (bbtool->getShowAllWorkspaces()) {
101 int size = strlen(title) + strlen(" (workspace )") + 2;
102 char *workspace = (char*) malloc(size);
103 if (workspace) {
104 snprintf(workspace, size, "%s (workspace %i)", title,
105 it.current()->desktop+1);
106 insert(workspace);
107 free(workspace);
109 } else
110 insert(title);
115 void Stackmenu::clearMenu() {
116 while (getCount())
117 remove(0);
120 void Stackmenu::selectFocused(bool raise)
122 int selected = menuPosition;
123 LinkedListIterator<WindowList> it(bbtool->windowList);
124 for(; it.current(); it++)
125 if (((bbtool->getShowAllWorkspaces()) &&
126 ((!it.current()->sticky) ||
127 (it.current()->desktop == bbtool->getCurrentDesktopNr())))
129 ((!bbtool->getShowAllWorkspaces()) &&
130 (it.current()->desktop == bbtool->getCurrentDesktopNr()))) {
131 if(!selected--) {
132 bbtool->wminterface->setWindowFocus(it.current()->win);
133 if ( raise ) {
134 // okay, an explanation is in order... First, we have to
135 // hide our window so that focusWindow() actually does
136 // anything.
137 // Next, if the window to focus is on a different desktop than
138 // the current one, we need to switch there.
139 // Then we XRaiseWindow, because if we did
140 // focusWindow() first, we'd then XRaise() the wrong window.
141 // Lastly, we update bbkey's stack with what we just
142 // raised...
143 hide();
144 if (bbtool->getCurrentDesktopNr() != it.current()->desktop)
145 bbtool->wminterface->changeDesktop(it.current()->desktop, False);
146 XRaiseWindow(bbtool->getXDisplay(), it.current()->win);
147 bbtool->focusWindow(it.current()->win);
151 if ( raise ) {
152 hide();
156 void Stackmenu::key_press(int grabInt)
158 switch (grabInt) {
159 case grabNextWindow:
160 case grabNextWindowAllWorkspaces:
161 if(++menuPosition >= getCount())
162 menuPosition = 0;
163 setSelected(menuPosition);
164 selectFocused(False);
165 break;
166 case grabPrevWindow:
167 if(--menuPosition < 0)
168 menuPosition = getCount() - 1;
169 setSelected(menuPosition);
170 selectFocused(False);
171 break;
172 default:
173 break;
177 void Stackmenu::hide()
179 XUngrabKeyboard(bbtool->getXDisplay(), CurrentTime);
180 Basemenu::hide();
181 bbtool->setCycling(False);
184 void Stackmenu::show(bool forward, bool showMenu)
186 setMenuItems();
187 if (getCount() < 1) return; // no windows, just return
188 if (getCount() == 1) {
189 // only 1 window, focus it and leave
190 LinkedListIterator<WindowList> it(bbtool->windowList);
191 for (; it.current(); it++)
192 if (it.current()->desktop == bbtool->getCurrentDesktopNr())
193 bbtool->wminterface->setWindowFocus(it.current()->win);
194 return;
197 XRaiseWindow(bbtool->getXDisplay(), getWindowID());
198 XGrabKeyboard(bbtool->getXDisplay(),
199 bbtool->getScreenInfo(0)->getRootWindow(), True,
200 GrabModeAsync, GrabModeAsync, CurrentTime);
202 menuPosition = 0;
203 key_press(forward?grabNextWindow:grabPrevWindow);
205 bbtool->setCycling(True);
207 if (showMenu) {
208 Basemenu::show();
209 centerPosition();
213 void Stackmenu::centerPosition()
215 int x = (bbtool->getCurrentScreenInfo()->getWidth()>>1) - (getWidth()>>1);
216 int y = (bbtool->getCurrentScreenInfo()->getHeight()>>1) - (getHeight()>>1);
217 if (x>0 && y>0)
218 Basemenu::move(x, y);
221 void Stackmenu::setSelected(int sel)
223 if ((sel<0) || (sel>=getCount())) return;
224 setHighlight(sel);
225 update();