// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
// -- WindowlistMenu.cpp --
// Copyright (c) 2001 - 2003 Jason 'vanRijn' Kasper <vR at movingparts dot net>
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// E_O_H_VR
#include "WindowlistMenu.h"
//--------------------------------------------------------
// Constructor/Destructor
//--------------------------------------------------------
WindowlistMenu::WindowlistMenu (ScreenHandler * s) :
bt::Menu( s->getKeyClient().getMainApplication(),
s->getScreenNumber() ) {
_screen = s;
_keybindings = s->getKeyClient().getKeybindings();
_display = s->getKeyClient().XDisplay();
_config = s->getKeyClient().getConfig();
_debug = _config->getBoolValue("debug", false);
_screen_info = & s->getScreenInfo();
_honor_modifiers = _config->getBoolValue("honormodifiers", false);
_screen->getKeyClient().getLockModifiers(numLockMask, scrollLockMask);
_menu_title = _config->getStringValue("cyclemenutitle", "Switch To...");
}
void WindowlistMenu::keyPressEvent (const XKeyEvent * const e) {
unsigned int state = e->state;
if (_debug)
std::cout << BBTOOL << ": " << "WindowlistMenu: got keyPressEvent!" << std::endl;
if (!_honor_modifiers) {
state = e->state & ~(LockMask|scrollLockMask|numLockMask);
}
const Action *it = _keybindings->getAction(e, state, _screen);
if (it) {
switch (it->type()) {
case Action::nextWindow:
case Action::nextWindowOnAllWorkspaces:
case Action::nextWindowOnAllScreens:
case Action::nextWindowOfClass:
case Action::nextWindowOfClassOnAllWorkspaces:
selectNext();
break;
case Action::prevWindow:
case Action::prevWindowOnAllWorkspaces:
case Action::prevWindowOnAllScreens:
case Action::prevWindowOfClass:
case Action::prevWindowOfClassOnAllWorkspaces:
selectPrevious();
break;
default:
break;
}
}
// if the user is cancelling the menu/cycle, then set focus back on the
// window they started with.
if (e->keycode == XKeysymToKeycode(_display, XK_Escape)) {
XWindow * win = dynamic_cast<XWindow *>(*_windowList.begin());
win->focus();
} else if (e->keycode == XKeysymToKeycode(_display, XK_Up)) {
selectPrevious(false);
} else if (e->keycode == XKeysymToKeycode(_display, XK_Down)) {
selectNext(false);
}
bt::Menu::keyPressEvent(e);
}
void WindowlistMenu::keyReleaseEvent (const XKeyEvent * const e) {
if (_debug)
std::cout << BBTOOL << ": " << "WindowlistMenu: got keyReleaseEvent!" << std::endl;
if (_screen->nothingIsPressed() ){
// get what window is selected so we can focus it
XWindow * win = getSelectedWindow();
bt::Menu::hide();
_screen->keyReleaseEvent(e);
// if the user is ending his window-cycling adventure, then raise the window
// for him.
if (win)
win->focus();
}
bt::Menu::keyReleaseEvent(e);
}
void WindowlistMenu::showCycleMenu( WindowList theList ) {
bt::Menu::clear();
bt::Menu::setTitle(bt::toUnicode(_menu_title));
if (_menu_title.length() > 0)
bt::Menu::showTitle();
_windowList = theList;
WindowList::const_iterator it;
const WindowList::const_iterator end = theList.end();
// first, find out if we have any windows in our list for anything other
// than the current desktop
_desktop_nbr = _screen->getDesktopNumber();
bool onlyThisDesktop = true;
for (it = theList.begin(); it != end; it++) {
unsigned int dNbr = (*it)->desktop();
if ( (dNbr != _desktop_nbr) && (! (*it)->isSticky()) ) {
onlyThisDesktop = false;
break;
}
}
// now add the windows to our list
unsigned int i = 0;
for (it = theList.begin(); it != end; it++) {
bt::ustring title = (*it)->title();
unsigned int dNbr = (*it)->desktop();
bt::ustring newTitle = bt::ellideText(title, 100, bt::toUnicode(" ... "));
if (! onlyThisDesktop) {
bt::ustring suffix = _screen->getDesktopName(dNbr);
if (suffix.size() > 0) {
newTitle += ' ';
newTitle += '(';
newTitle += suffix;
newTitle += ')';
}
}
bt::Menu::insertItem( newTitle, i++ );
}
// this is our current window, before cycling. set it checked as a
// visual indicator
bt::Menu::setItemChecked(0, true);
int x = _config->getNumberValue("cyclemenux", 20);
int y = _config->getNumberValue("cyclemenuy", 20);
// now show the menu
bt::Menu::popup(x, y, false);
bt::Menu::move(x,y);
// reset our marker as we will increment it in selectNext...
_current_index = -1;
// we don't have anything selected initially, so we need to set the
// selection to the second one (the first one is the
// currently-selected window
selectNext();
selectNext();
}
void WindowlistMenu::itemClicked(unsigned int id, unsigned int button) {
WindowList::const_iterator it = _windowList.begin();
const WindowList::const_iterator end = _windowList.end();
unsigned int x = 0;
for (; it != end; ++it) {
XWindow * const win = dynamic_cast<XWindow *>(*it);
if ( id == x++ ) {
win->focus();
}
}
}
void WindowlistMenu::selectNext(bool manual) {
// keep track of where we are...
trackIndex(1);
XWindow * win = getSelectedWindow();
if (win) _screen->focusWindow(win);
if (manual) {
XKeyEvent neo;
KeyCode keyCode = XKeysymToKeycode(_display, XK_Down);
neo.keycode = keyCode;
bt::Menu::keyPressEvent(&neo);
}
}
void WindowlistMenu::selectPrevious(bool manual) {
// keep track of where we are now...
trackIndex(-1);
XWindow * win = getSelectedWindow();
if (win) _screen->focusWindow(win);
if (manual) {
XKeyEvent neo;
KeyCode keyCode = XKeysymToKeycode(_display, XK_Up);
neo.keycode = keyCode;
bt::Menu::keyPressEvent(&neo);
}
}
void WindowlistMenu::trackIndex (const int movement) {
if (movement > 0) {
if (static_cast<unsigned int>(++_current_index) >= _windowList.size() )
_current_index = 0;
} else {
if (--_current_index < 0)
_current_index = _windowList.size() -1;
}
}
XWindow * WindowlistMenu::getSelectedWindow() {
WindowList::const_iterator it = _windowList.begin();
const WindowList::const_iterator end = _windowList.end();
XWindow * win = 0;
unsigned int x = 0;
for (; it != end; it++) {
if ( static_cast<unsigned int>(_current_index) == x++ ) {
win = dynamic_cast<XWindow *>(*it);
}
}
if (0 == win)
std::cerr << BBTOOL << ": " << "WindowlistMenu: getSelectedWindow--couldn't get window. this won't turn out well.\n";
if (_debug && win)
std::cout << BBTOOL << ": " << "WindowlistMenu: getSelectedWindow: currently-selected window: ["
<< bt::toLocale(win->title()) << "]\n";
return win;
}
syntax highlighted by Code2HTML, v. 0.9.1