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>
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.
25 #include "WindowlistMenu.h"
26 //--------------------------------------------------------
27 // Constructor/Destructor
28 //--------------------------------------------------------
29 WindowlistMenu::WindowlistMenu (ScreenHandler
* s
) :
30 bt::Menu( s
->getKeyClient().getMainApplication(),
31 s
->getScreenNumber() ) {
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
;
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
);
59 case Action::nextWindow
:
60 case Action::nextWindowOnAllWorkspaces
:
61 case Action::nextWindowOnAllScreens
:
62 case Action::nextWindowOfClass
:
63 case Action::nextWindowOfClassOnAllWorkspaces
:
67 case Action::prevWindow
:
68 case Action::prevWindowOnAllWorkspaces
:
69 case Action::prevWindowOnAllScreens
:
70 case Action::prevWindowOfClass
:
71 case Action::prevWindowOfClassOnAllWorkspaces
:
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());
85 } else if (e
->keycode
== XKeysymToKeycode(_display
, XK_Up
)) {
86 selectPrevious(false);
87 } else if (e
->keycode
== XKeysymToKeycode(_display
, XK_Down
)) {
91 bt::Menu::keyPressEvent(e
);
95 void WindowlistMenu::keyReleaseEvent (const XKeyEvent
* const e
) {
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();
105 _screen
->keyReleaseEvent(e
);
107 // if the user is ending his window-cycling adventure, then raise the window
113 bt::Menu::keyReleaseEvent(e
);
117 void WindowlistMenu::showCycleMenu( WindowList theList
) {
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;
141 // now add the windows to our list
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(")"));
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
167 bt::Menu::setItemChecked(0, true);
169 int x
= _config
->getNumberValue("cyclemenux", 20);
170 int y
= _config
->getNumberValue("cyclemenuy", 20);
173 bt::Menu::popup(x
, y
, false);
176 // reset our marker as we will increment it in selectNext...
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
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();
193 for (; it
!= end
; ++it
) {
194 XWindow
* const win
= dynamic_cast<XWindow
*>(*it
);
202 void WindowlistMenu::selectNext(bool manual
) {
204 // keep track of where we are...
207 XWindow
* win
= getSelectedWindow();
208 if (win
) _screen
->focusWindow(win
);
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...
224 XWindow
* win
= getSelectedWindow();
225 if (win
) _screen
->focusWindow(win
);
229 KeyCode keyCode
= XKeysymToKeycode(_display
, XK_Up
);
230 neo
.keycode
= keyCode
;
231 bt::Menu::keyPressEvent(&neo
);
236 void WindowlistMenu::trackIndex (const int movement
) {
239 if (static_cast<unsigned int>(++_current_index
) >= _windowList
.size() )
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();
256 for (; it
!= end
; it
++) {
257 if ( static_cast<unsigned int>(_current_index
) == x
++ ) {
258 win
= dynamic_cast<XWindow
*>(*it
);
263 std::cerr
<< BBTOOL
<< ": " << "WindowlistMenu: getSelectedWindow--couldn't get window. this won't turn out well.\n";
266 std::cout
<< BBTOOL
<< ": " << "WindowlistMenu: getSelectedWindow: currently-selected window: ["
267 << bt::toLocale(win
->title()) << "]\n";