Lower the AC_PREREQ version 2.59
[bbkeys.git] / src / WindowlistMenu.cpp
blob801b51dc7e9b47548db4b043719361a7fb897e3b
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // -- WindowlistMenu.cpp --
3 // Copyright (c) 2001 - 2003 Jason 'vanRijn' Kasper <vR at movingparts dot net>
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
23 // E_O_H_VR
25 #include "WindowlistMenu.h"
26 //--------------------------------------------------------
27 // Constructor/Destructor
28 //--------------------------------------------------------
29 WindowlistMenu::WindowlistMenu (ScreenHandler * s) :
30 bt::Menu( s->getKeyClient().getMainApplication(),
31 s->getScreenNumber() ) {
32 _screen = s;
33 _keybindings = s->getKeyClient().getKeybindings();
34 _display = s->getKeyClient().XDisplay();
35 _config = s->getKeyClient().getConfig();
36 _debug = _config->getBoolValue("debug", false);
37 _screen_info = & s->getScreenInfo();
38 _honor_modifiers = _config->getBoolValue("honormodifiers", false);
39 _screen->getKeyClient().getLockModifiers(numLockMask, scrollLockMask);
40 _menu_title = _config->getStringValue("cyclemenutitle", "Switch To...");
43 void WindowlistMenu::keyPressEvent (const XKeyEvent * const e) {
45 unsigned int state = e->state;
47 if (_debug)
48 std::cout << BBTOOL << ": " << "WindowlistMenu: got keyPressEvent!" << std::endl;
50 if (!_honor_modifiers) {
51 state = e->state & ~(LockMask|scrollLockMask|numLockMask);
54 const Action *it = _keybindings->getAction(e, state, _screen);
56 if (it) {
57 switch (it->type()) {
59 case Action::nextWindow:
60 case Action::nextWindowOnAllWorkspaces:
61 case Action::nextWindowOnAllScreens:
62 case Action::nextWindowOfClass:
63 case Action::nextWindowOfClassOnAllWorkspaces:
64 selectNext();
65 break;
67 case Action::prevWindow:
68 case Action::prevWindowOnAllWorkspaces:
69 case Action::prevWindowOnAllScreens:
70 case Action::prevWindowOfClass:
71 case Action::prevWindowOfClassOnAllWorkspaces:
72 selectPrevious();
73 break;
75 default:
76 break;
80 // if the user is cancelling the menu/cycle, then set focus back on the
81 // window they started with.
82 if (e->keycode == XKeysymToKeycode(_display, XK_Escape)) {
83 XWindow * win = dynamic_cast<XWindow *>(*_windowList.begin());
84 win->focus();
85 } else if (e->keycode == XKeysymToKeycode(_display, XK_Up)) {
86 selectPrevious(false);
87 } else if (e->keycode == XKeysymToKeycode(_display, XK_Down)) {
88 selectNext(false);
91 bt::Menu::keyPressEvent(e);
95 void WindowlistMenu::keyReleaseEvent (const XKeyEvent * const e) {
97 if (_debug)
98 std::cout << BBTOOL << ": " << "WindowlistMenu: got keyReleaseEvent!" << std::endl;
100 if (_screen->nothingIsPressed() ){
101 // get what window is selected so we can focus it
102 XWindow * win = getSelectedWindow();
104 bt::Menu::hide();
105 _screen->keyReleaseEvent(e);
107 // if the user is ending his window-cycling adventure, then raise the window
108 // for him.
109 if (win)
110 win->focus();
113 bt::Menu::keyReleaseEvent(e);
117 void WindowlistMenu::showCycleMenu( WindowList theList ) {
119 bt::Menu::clear();
120 bt::Menu::setTitle(bt::toUnicode(_menu_title));
121 if (_menu_title.length() > 0)
122 bt::Menu::showTitle();
124 _windowList = theList;
126 WindowList::const_iterator it;
127 const WindowList::const_iterator end = theList.end();
129 // first, find out if we have any windows in our list for anything other
130 // than the current desktop
131 _desktop_nbr = _screen->getDesktopNumber();
132 bool onlyThisDesktop = true;
133 for (it = theList.begin(); it != end; it++) {
134 unsigned int dNbr = (*it)->desktop();
135 if ( (dNbr != _desktop_nbr) && (! (*it)->isSticky()) ) {
136 onlyThisDesktop = false;
137 break;
141 // now add the windows to our list
142 unsigned int i = 0;
144 for (it = theList.begin(); it != end; it++) {
145 XWindow *win = (*it);
146 bt::ustring title = win->title();
147 unsigned int dNbr = win->desktop();
148 bt::ustring newTitle = bt::ellideText(title, 100, bt::toUnicode(" ... "));
149 if (! onlyThisDesktop) {
150 bt::ustring suffix = _screen->getDesktopName(dNbr);
151 if (suffix.size() > 0) {
152 newTitle.append(bt::toUnicode(" ("));
153 newTitle.append(suffix);
154 newTitle.append(bt::toUnicode(")"));
157 if (win->iconic()) {
158 newTitle.insert(0, bt::toUnicode("("));
159 newTitle.append(bt::toUnicode(")"));
162 bt::Menu::insertItem( newTitle, i++ );
165 // this is our current window, before cycling. set it checked as a
166 // visual indicator
167 bt::Menu::setItemChecked(0, true);
169 int x = _config->getNumberValue("cyclemenux", 20);
170 int y = _config->getNumberValue("cyclemenuy", 20);
172 // now show the menu
173 bt::Menu::popup(x, y, false);
174 bt::Menu::move(x,y);
176 // reset our marker as we will increment it in selectNext...
177 _current_index = -1;
179 // we don't have anything selected initially, so we need to set the
180 // selection to the second one (the first one is the
181 // currently-selected window
182 selectNext();
183 selectNext();
187 void WindowlistMenu::itemClicked(unsigned int id, unsigned int button) {
189 WindowList::const_iterator it = _windowList.begin();
190 const WindowList::const_iterator end = _windowList.end();
192 unsigned int x = 0;
193 for (; it != end; ++it) {
194 XWindow * const win = dynamic_cast<XWindow *>(*it);
195 if ( id == x++ ) {
196 win->focus();
202 void WindowlistMenu::selectNext(bool manual) {
204 // keep track of where we are...
205 trackIndex(1);
207 XWindow * win = getSelectedWindow();
208 if (win) _screen->focusWindow(win);
210 if (manual) {
211 XKeyEvent neo;
212 KeyCode keyCode = XKeysymToKeycode(_display, XK_Down);
213 neo.keycode = keyCode;
214 bt::Menu::keyPressEvent(&neo);
219 void WindowlistMenu::selectPrevious(bool manual) {
221 // keep track of where we are now...
222 trackIndex(-1);
224 XWindow * win = getSelectedWindow();
225 if (win) _screen->focusWindow(win);
227 if (manual) {
228 XKeyEvent neo;
229 KeyCode keyCode = XKeysymToKeycode(_display, XK_Up);
230 neo.keycode = keyCode;
231 bt::Menu::keyPressEvent(&neo);
236 void WindowlistMenu::trackIndex (const int movement) {
238 if (movement > 0) {
239 if (static_cast<unsigned int>(++_current_index) >= _windowList.size() )
240 _current_index = 0;
241 } else {
242 if (--_current_index < 0)
243 _current_index = _windowList.size() -1;
248 XWindow * WindowlistMenu::getSelectedWindow() {
250 WindowList::const_iterator it = _windowList.begin();
251 const WindowList::const_iterator end = _windowList.end();
253 XWindow * win = 0;
255 unsigned int x = 0;
256 for (; it != end; it++) {
257 if ( static_cast<unsigned int>(_current_index) == x++ ) {
258 win = dynamic_cast<XWindow *>(*it);
262 if (0 == win)
263 std::cerr << BBTOOL << ": " << "WindowlistMenu: getSelectedWindow--couldn't get window. this won't turn out well.\n";
265 if (_debug && win)
266 std::cout << BBTOOL << ": " << "WindowlistMenu: getSelectedWindow: currently-selected window: ["
267 << bt::toLocale(win->title()) << "]\n";
268 return win;