kwin/tabbox.cpp
Luboš Luňák bd81e83d55 Override-redirect windows in the window manager itself don't make any
difference, and Keith Packard said it's better without it for some
translucency toy or whatever it is, so let's get rid of WX11BypassWM in KWin.

svn path=/trunk/kdebase/kwin/; revision=266398
2003-11-11 18:38:19 +00:00

1023 lines
29 KiB
C++
Raw Blame History

/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
//#define QT_CLEAN_NAMESPACE
#include "tabbox.h"
#include "workspace.h"
#include "client.h"
#include <qpainter.h>
#include <qlabel.h>
#include <qdrawutil.h>
#include <qstyle.h>
#include <kglobal.h>
#include <fixx11h.h>
#include <kconfig.h>
#include <klocale.h>
#include <qapplication.h>
#include <qdesktopwidget.h>
#include <qcursor.h>
#include <kstringhandler.h>
#include <stdarg.h>
#include <kdebug.h>
#include <kglobalaccel.h>
#include <kkeynative.h>
#include <kglobalsettings.h>
#include <X11/keysym.h>
#include <X11/keysymdef.h>
// specify externals before namespace
extern Time qt_x_time;
namespace KWinInternal
{
extern QPixmap* kwin_get_menu_pix_hack();
TabBox::TabBox( Workspace *ws, const char *name )
: QWidget( 0, name )
{
no_tasks = i18n("*** No Tasks ***");
m = DesktopMode; // init variables
wspace = ws;
reconfigure();
reset();
connect(&delayedShowTimer, SIGNAL(timeout()), this, SLOT(show()));
}
TabBox::~TabBox()
{
}
/*!
Sets the current mode to \a mode, either DesktopListMode or WindowsMode
\sa mode()
*/
void TabBox::setMode( Mode mode )
{
m = mode;
}
/*!
Resets the tab box to display the active client in WindowsMode, or the
current desktop in DesktopListMode
*/
void TabBox::reset()
{
QFont f = font();
f.setBold( TRUE );
f.setPointSize( 14 );
setFont( f );
wmax = 0;
if ( mode() == WindowsMode )
{
client = workspace()->activeClient();
clients.clear();
Client* c = workspace()->nextFocusChainClient( client );
Client* stop = c;
QFontMetrics fm( fontMetrics() );
int cw = fm.width(no_tasks)+20;
while ( c )
{
if ( (options_traverse_all ||c->isOnDesktop(workspace()->currentDesktop()))
&& (!c->isMinimized() || !c->isTransient() || c->isUtility()) )
{
if ( client == c )
{
clients.remove( c );
clients.prepend( c );
}
else
{ // don't add windows that have modal dialogs
Client* modal = c->findModal();
if( modal == NULL || modal == c )
clients += c;
else if( !clients.contains( modal ))
clients += modal;
else
; // nothing
}
cw = fm.width( c->caption() ) + 40;
if ( cw > wmax )
wmax = cw;
}
c = workspace()->nextFocusChainClient( c );
if ( c == stop )
break;
}
wmax = QMAX( wmax, int(clients.count())*20 );
}
else
{ // DesktopListMode
desk = workspace()->currentDesktop();
}
QRect r = KGlobalSettings::desktopGeometry(QCursor::pos());
int w = QMIN( QMAX( wmax + 20, r.width()/3 ), r.width() );
setGeometry( (r.width()-w)/2 + r.x(),
r.height()/2-fontMetrics().height()*2-10 + r.y(),
w, fontMetrics().height()*4 + 20 );
wmax = QMIN( wmax, width() - 12 );
}
/*!
Shows the next or previous item, depending on \a next
*/
void TabBox::nextPrev( bool next)
{
if ( mode() == WindowsMode )
{
Client* firstClient = 0;
do
{
if ( next )
client = workspace()->nextFocusChainClient(client);
else
client = workspace()->previousFocusChainClient(client);
if (!firstClient)
{
// When we see our first client for the second time,
// it's time to stop.
firstClient = client;
}
else if (client == firstClient)
{
// No candidates found.
client = 0;
break;
}
} while ( client && !clients.contains( client ));
}
else if( mode() == DesktopMode )
{
if ( next )
desk = workspace()->nextDesktopFocusChain( desk );
else
desk = workspace()->previousDesktopFocusChain( desk );
}
else
{ // DesktopListMode
if ( next )
{
desk++;
if ( desk > workspace()->numberOfDesktops() )
desk = 1;
}
else
{
desk--;
if ( desk < 1 )
desk = workspace()->numberOfDesktops();
}
}
paintContents();
}
/*!
Returns the currently displayed client ( only works in WindowsMode ).
Returns 0 if no client is displayed.
*/
Client* TabBox::currentClient()
{
if ( mode() != WindowsMode )
return 0;
if (!workspace()->hasClient( client ))
return 0;
return client;
}
/*!
Returns the currently displayed virtual desktop ( only works in
DesktopListMode )
Returns -1 if no desktop is displayed.
*/
int TabBox::currentDesktop()
{
if ( mode() == DesktopListMode || mode() == DesktopMode )
return desk;
else
return -1;
}
/*!
Reimplemented to raise the tab box as well
*/
void TabBox::showEvent( QShowEvent* )
{
raise();
}
/*!
hide the icon box if necessary
*/
void TabBox::hideEvent( QHideEvent* )
{
}
/*!
Paints the tab box
*/
void TabBox::paintEvent( QPaintEvent* )
{
{
QPainter p( this );
style().drawPrimitive( QStyle::PE_Panel, &p, QRect( 0, 0, width(), height() ),
colorGroup(), QStyle::Style_Default );
style().drawPrimitive( QStyle::PE_Panel, &p, QRect( 4, 4, width()-8, height()-8 ),
colorGroup(), QStyle::Style_Sunken );
}
paintContents();
}
/*!
Paints the contents of the tab box. Used in paintEvent() and
whenever the contents changes.
*/
void TabBox::paintContents()
{
QPixmap* menu_pix = kwin_get_menu_pix_hack();
QPainter p( this );
QRect r( 6, 6, width()-12, height()-32 );
p.fillRect( r, colorGroup().brush( QColorGroup::Background ) );
if ( mode () == WindowsMode )
{
if ( currentClient() )
{
int textw, maxlen = client->caption().length();
int icon = client->icon().isNull() ? 0 : 42;
QString s;
do
{
s = QString();
if (!client->isOnDesktop(workspace()->currentDesktop()))
{
s.append(": ");
}
if (client->isMinimized())
s += QString("(")+KStringHandler::csqueeze(client->caption(), maxlen)+")";
else
s += KStringHandler::csqueeze(client->caption(), maxlen);
textw = fontMetrics().width( s );
maxlen--;
} while (textw > r.width() - icon);
r.setLeft( r.left() + (r.width() - textw)/2);
if ( icon )
{
int py = r.center().y() - 16;
r.setLeft( r.left() + 20 );
if( client->icon().mask() != NULL )
p.fillRect( r.left()-42, py, client->icon().width(), client->icon().height(),
colorGroup().brush( QColorGroup::Background ));
p.drawPixmap( r.left()-42, py, client->icon() );
}
p.drawText( r, AlignVCenter, s );
}
else
{
r.setBottom( r.bottom() + 20 );
p.drawText( r, AlignCenter, no_tasks);
}
int x = (width() - clients.count() * 20 )/2;
int y = height() - 26;
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
{
if ( workspace()->hasClient( *it ) )
{ // safety
if ( !(*it)->miniIcon().isNull() )
{
if( (*it)->miniIcon().mask() != NULL )
p.fillRect( x, y, 16, 16, colorGroup().brush( QColorGroup::Background ));
p.drawPixmap( x, y, (*it)->miniIcon() );
}
else if ( menu_pix )
{
if( menu_pix->mask() != NULL )
p.fillRect( x, y, 16, 16, colorGroup().brush( QColorGroup::Background ));
p.drawPixmap( x, y, *menu_pix );
}
p.setPen( (*it)==currentClient()?
colorGroup().highlight():colorGroup().background() );
p.drawRect( x-2, y-2, 20, 20 );
p.setPen( colorGroup().foreground() );
x += 20;
}
}
}
else
{ // DesktopMode || DesktopListMode
p.drawText( r, AlignCenter, workspace()->desktopName(desk) );
int x = (width() - workspace()->numberOfDesktops() * 20 )/2;
int y = height() - 26;
QFont f( font() );
f.setPointSize( 12 );
f.setBold( FALSE );
p.setFont(f );
// In DesktopMode, start at the current desktop
// In DesktopListMode, start at desktop #1
int iDesktop = (mode() == DesktopMode) ? workspace()->currentDesktop() : 1;
for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ )
{
p.setPen( iDesktop == desk?
colorGroup().highlight():colorGroup().background() );
p.drawRect( x-2, y-2, 20, 20 );
qDrawWinPanel( &p, QRect( x, y, 16, 16), colorGroup(), FALSE,
&colorGroup().brush(QColorGroup::Base ) );
p.setPen( colorGroup().text() );
p.drawText( x, y, 16, 16, AlignCenter, QString::number(iDesktop) );
x += 20;
if( mode() == DesktopMode )
iDesktop = workspace()->nextDesktopFocusChain( iDesktop );
else
iDesktop++;
}
}
}
void TabBox::hide()
{
delayedShowTimer.stop();
QWidget::hide();
QApplication::syncX();
XEvent otherEvent;
while (XCheckTypedEvent (qt_xdisplay(), EnterNotify, &otherEvent ) )
;
}
void TabBox::reconfigure()
{
KConfig * c(KGlobal::config());
c->setGroup("TabBox");
options_traverse_all = c->readNumEntry("TraverseAll", false );
}
/*!
Rikkus: please document! (Matthias)
Ok, here's the docs :)
You call delayedShow() instead of show() directly.
If the 'ShowDelay' setting is false, show() is simply called.
Otherwise, we start a timer for the delay given in the settings and only
do a show() when it times out.
This means that you can alt-tab between windows and you don't see the
tab box immediately. Not only does this make alt-tabbing faster, it gives
less 'flicker' to the eyes. You don't need to see the tab box if you're
just quickly switching between 2 or 3 windows. It seems to work quite
nicely.
*/
void TabBox::delayedShow()
{
KConfig * c(KGlobal::config());
c->setGroup("TabBox");
bool delay = c->readNumEntry("ShowDelay", true);
if (!delay)
{
show();
return;
}
int delayTime = c->readNumEntry("DelayTime", 90);
delayedShowTimer.start(delayTime, true);
}
void TabBox::handleMouseEvent( XEvent* e )
{
XAllowEvents( qt_xdisplay(), AsyncPointer, qt_x_time );
if( e->type != ButtonPress )
return;
QPoint pos( e->xbutton.x_root, e->xbutton.y_root );
if( !geometry().contains( pos ))
return;
pos.rx() -= x(); // pos is now inside tabbox
pos.ry() -= y();
if( mode() == WindowsMode )
{
int x = (width() - clients.count() * 20 )/2;
int y = height() - 26;
if( pos.x() < x || pos.y() < y - 2 || pos.y() > y - 2 + 20 )
return;
for( ClientList::ConstIterator it = clients.begin();
it != clients.end();
++it)
{
if( workspace()->hasClient( *it ) // safety
&& pos.x() < x + 20 )
{
client = *it;
break;
}
x += 20;
}
}
else
{
int x = (width() - workspace()->numberOfDesktops() * 20 )/2;
int y = height() - 26;
if( pos.x() < x || pos.y() < y - 2 || pos.y() > y - 2 + 20 )
return;
int iDesktop = (mode() == DesktopMode) ? workspace()->currentDesktop() : 1;
for( int i = 1;
i <= workspace()->numberOfDesktops();
++i )
{
if( pos.x() < x + 20 )
{
desk = iDesktop;
break;
}
x += 20;
if( mode() == DesktopMode )
iDesktop = workspace()->nextDesktopFocusChain( iDesktop );
else
iDesktop++;
}
}
paintContents();
}
//*******************************
// Workspace
//*******************************
/*!
Handles alt-tab / control-tab
*/
static
bool areKeySymXsDepressed( bool bAll, int nKeySyms, ... )
{
va_list args;
char keymap[32];
kdDebug(125) << "areKeySymXsDepressed: " << (bAll ? "all of " : "any of ") << nKeySyms << endl;
va_start( args, nKeySyms );
XQueryKeymap( qt_xdisplay(), keymap );
for( int iKeySym = 0; iKeySym < nKeySyms; iKeySym++ )
{
uint keySymX = va_arg( args, uint );
uchar keyCodeX = XKeysymToKeycode( qt_xdisplay(), keySymX );
int i = keyCodeX / 8;
char mask = 1 << (keyCodeX - (i * 8));
kdDebug(125) << iKeySym << ": keySymX=0x" << QString::number( keySymX, 16 )
<< " i=" << i << " mask=0x" << QString::number( mask, 16 )
<< " keymap[i]=0x" << QString::number( keymap[i], 16 ) << endl;
// Abort if bad index value,
if( i < 0 || i >= 32 )
return false;
// If ALL keys passed need to be depressed,
if( bAll )
{
if( (keymap[i] & mask) == 0 )
return false;
}
else
{
// If we are looking for ANY key press, and this key is depressed,
if( keymap[i] & mask )
return true;
}
}
// If we were looking for ANY key press, then none was found, return false,
// If we were looking for ALL key presses, then all were found, return true.
return bAll;
}
static
bool areModKeysDepressed( const KShortcut& cut )
{
uint rgKeySyms[10];
int nKeySyms = 0;
int mod = cut.seq(0).key(0).modFlags();
if ( mod & KKey::SHIFT )
{
rgKeySyms[nKeySyms++] = XK_Shift_L;
rgKeySyms[nKeySyms++] = XK_Shift_R;
}
if ( mod & KKey::CTRL )
{
rgKeySyms[nKeySyms++] = XK_Control_L;
rgKeySyms[nKeySyms++] = XK_Control_R;
}
if( mod & KKey::ALT )
{
rgKeySyms[nKeySyms++] = XK_Alt_L;
rgKeySyms[nKeySyms++] = XK_Alt_R;
}
if( mod & KKey::WIN )
{
// HACK: it would take a lot of code to determine whether the Win key
// is associated with Super or Meta, so check for both
rgKeySyms[nKeySyms++] = XK_Super_L;
rgKeySyms[nKeySyms++] = XK_Super_R;
rgKeySyms[nKeySyms++] = XK_Meta_L;
rgKeySyms[nKeySyms++] = XK_Meta_R;
}
// Is there a better way to push all 8 integer onto the stack?
return areKeySymXsDepressed( false, nKeySyms,
rgKeySyms[0], rgKeySyms[1], rgKeySyms[2], rgKeySyms[3],
rgKeySyms[4], rgKeySyms[5], rgKeySyms[6], rgKeySyms[7] );
}
void Workspace::slotWalkThroughWindows()
{
if ( root != qt_xrootwin() )
return;
if ( tab_grab || control_grab )
return;
if ( options->altTabStyle == Options::CDE || !options->focusPolicyIsReasonable() )
{
//XUngrabKeyboard(qt_xdisplay(), qt_x_time); // need that because of accelerator raw mode
// CDE style raise / lower
CDEWalkThroughWindows( true );
}
else
{
if ( areModKeysDepressed( cutWalkThroughWindows ) )
{
if ( startKDEWalkThroughWindows() )
KDEWalkThroughWindows( true );
}
else
// if the shortcut has no modifiers, don't show the tabbox,
// don't grab, but simply go to the next window
// use the CDE style, because with KDE style it would cycle
// between the active and previously active window
CDEWalkThroughWindows( true );
}
}
void Workspace::slotWalkBackThroughWindows()
{
if ( root != qt_xrootwin() )
return;
if( tab_grab || control_grab )
return;
if ( options->altTabStyle == Options::CDE || !options->focusPolicyIsReasonable() )
{
// CDE style raise / lower
CDEWalkThroughWindows( false );
}
else
{
if ( areModKeysDepressed( cutWalkThroughWindowsReverse ) )
{
if ( startKDEWalkThroughWindows() )
KDEWalkThroughWindows( false );
}
else
{
CDEWalkThroughWindows( false );
}
}
}
void Workspace::slotWalkThroughDesktops()
{
if ( root != qt_xrootwin() )
return;
if( tab_grab || control_grab )
return;
if ( areModKeysDepressed( cutWalkThroughDesktops ) )
{
if ( startWalkThroughDesktops() )
walkThroughDesktops( true );
}
else
{
oneStepThroughDesktops( true );
}
}
void Workspace::slotWalkBackThroughDesktops()
{
if ( root != qt_xrootwin() )
return;
if( tab_grab || control_grab )
return;
if ( areModKeysDepressed( cutWalkThroughDesktopsReverse ) )
{
if ( startWalkThroughDesktops() )
walkThroughDesktops( false );
}
else
{
oneStepThroughDesktops( false );
}
}
void Workspace::slotWalkThroughDesktopList()
{
if ( root != qt_xrootwin() )
return;
if( tab_grab || control_grab )
return;
if ( areModKeysDepressed( cutWalkThroughDesktopList ) )
{
if ( startWalkThroughDesktopList() )
walkThroughDesktops( true );
}
else
{
oneStepThroughDesktopList( true );
}
}
void Workspace::slotWalkBackThroughDesktopList()
{
if ( root != qt_xrootwin() )
return;
if( tab_grab || control_grab )
return;
if ( areModKeysDepressed( cutWalkThroughDesktopListReverse ) )
{
if ( startWalkThroughDesktopList() )
walkThroughDesktops( false );
}
else
{
oneStepThroughDesktopList( false );
}
}
bool Workspace::startKDEWalkThroughWindows()
{
if ( XGrabKeyboard(qt_xdisplay(),
root, FALSE,
GrabModeAsync, GrabModeAsync,
qt_x_time) != GrabSuccess )
{
return FALSE;
}
tab_grab = TRUE;
keys->setEnabled( false );
tab_box->setMode( TabBox::WindowsMode );
tab_box->reset();
return TRUE;
}
bool Workspace::startWalkThroughDesktops( int mode )
{
if ( XGrabKeyboard(qt_xdisplay(),
root, FALSE,
GrabModeAsync, GrabModeAsync,
qt_x_time) != GrabSuccess )
{
return FALSE;
}
control_grab = TRUE;
keys->setEnabled( false );
tab_box->setMode( (TabBox::Mode) mode );
tab_box->reset();
return TRUE;
}
bool Workspace::startWalkThroughDesktops()
{
return startWalkThroughDesktops( TabBox::DesktopMode );
}
bool Workspace::startWalkThroughDesktopList()
{
return startWalkThroughDesktops( TabBox::DesktopListMode );
}
void Workspace::KDEWalkThroughWindows( bool forward )
{
tab_box->nextPrev( forward );
tab_box->delayedShow();
}
void Workspace::walkThroughDesktops( bool forward )
{
tab_box->nextPrev( forward );
tab_box->delayedShow();
}
void Workspace::CDEWalkThroughWindows( bool forward )
{
Client* c = topClientOnDesktop( currentDesktop());
Client* nc = c;
bool options_traverse_all;
{
KConfigGroupSaver saver( KGlobal::config(), "TabBox" );
options_traverse_all = KGlobal::config()->readNumEntry("TraverseAll", false );
}
if ( !forward )
{
do
{
nc = previousStaticClient(nc);
} while (nc && nc != c &&
(( !options_traverse_all && !nc->isOnDesktop(currentDesktop())) ||
nc->isMinimized() || !nc->wantsTabFocus() ) );
}
else
{
do
{
nc = nextStaticClient(nc);
} while (nc && nc != c &&
(( !options_traverse_all && !nc->isOnDesktop(currentDesktop())) ||
nc->isMinimized() || !nc->wantsTabFocus() ) );
}
if (c && c != nc)
lowerClient( c );
if (nc)
{
if ( options->focusPolicyIsReasonable() )
{
activateClient( nc );
if( nc->isShade())
nc->setShade( Client::ShadeActivated );
}
else
{
if( !nc->isOnDesktop( currentDesktop()))
setCurrentDesktop( nc->desktop());
raiseClient( nc );
}
}
}
void Workspace::KDEOneStepThroughWindows( bool forward )
{
tab_box->setMode( TabBox::WindowsMode );
tab_box->reset();
tab_box->nextPrev( forward );
if( Client* c = tab_box->currentClient() )
{
activateClient( c );
if( c->isShade())
c->setShade( Client::ShadeActivated );
}
}
void Workspace::oneStepThroughDesktops( bool forward, int mode )
{
tab_box->setMode( (TabBox::Mode) mode );
tab_box->reset();
tab_box->nextPrev( forward );
if ( tab_box->currentDesktop() != -1 )
setCurrentDesktop( tab_box->currentDesktop() );
}
void Workspace::oneStepThroughDesktops( bool forward )
{
oneStepThroughDesktops( forward, TabBox::DesktopMode );
}
void Workspace::oneStepThroughDesktopList( bool forward )
{
oneStepThroughDesktops( forward, TabBox::DesktopListMode );
}
/*!
Handles holding alt-tab / control-tab
*/
void Workspace::tabBoxKeyPress( const KKeyNative& keyX )
{
bool forward = false;
bool backward = false;
if (tab_grab)
{
forward = cutWalkThroughWindows.contains( keyX );
backward = cutWalkThroughWindowsReverse.contains( keyX );
if (forward || backward)
{
kdDebug(125) << "== " << cutWalkThroughWindows.toStringInternal()
<< " or " << cutWalkThroughWindowsReverse.toStringInternal() << endl;
KDEWalkThroughWindows( forward );
}
}
else if (control_grab)
{
forward = cutWalkThroughDesktops.contains( keyX ) ||
cutWalkThroughDesktopList.contains( keyX );
backward = cutWalkThroughDesktopsReverse.contains( keyX ) ||
cutWalkThroughDesktopListReverse.contains( keyX );
if (forward || backward)
walkThroughDesktops(forward);
}
if (control_grab || tab_grab)
{
uint keyQt = keyX.keyCodeQt();
if ( ((keyQt & 0xffff) == Qt::Key_Escape)
&& !(forward || backward) )
{ // if Escape is part of the shortcut, don't cancel
XUngrabKeyboard(qt_xdisplay(), qt_x_time);
tab_box->hide();
keys->setEnabled( true );
tab_grab = FALSE;
control_grab = FALSE;
}
}
}
/*!
Handles alt-tab / control-tab releasing
*/
void Workspace::tabBoxKeyRelease( const XKeyEvent& ev )
{
unsigned int mk = ev.state &
(KKeyNative::modX(KKey::SHIFT) |
KKeyNative::modX(KKey::CTRL) |
KKeyNative::modX(KKey::ALT) |
KKeyNative::modX(KKey::WIN));
// ev.state is state before the key release, so just checking mk being 0 isn't enough
// using XQueryPointer() also doesn't seem to work well, so the check that all
// modifiers are released: only one modifier is active and the currently released
// key is this modifier - if yes, release the grab
int mod_index = -1;
for( int i = ShiftMapIndex;
i <= Mod5MapIndex;
++i )
if(( mk & ( 1 << i )) != 0 )
{
if( mod_index >= 0 )
return;
mod_index = i;
}
bool release = false;
if( mod_index == -1 )
release = true;
else
{
XModifierKeymap* xmk = XGetModifierMapping(qt_xdisplay());
for (int i=0; i<xmk->max_keypermod; i++)
if (xmk->modifiermap[xmk->max_keypermod * mod_index + i]
== ev.keycode)
release = true;
XFreeModifiermap(xmk);
}
if( !release )
return;
if (tab_grab)
{
XUngrabKeyboard(qt_xdisplay(), qt_x_time);
tab_box->hide();
keys->setEnabled( true );
tab_grab = false;
if( Client* c = tab_box->currentClient())
{
activateClient( c );
if( c->isShade())
c->setShade( Client::ShadeActivated );
}
}
if (control_grab)
{
XUngrabKeyboard(qt_xdisplay(), qt_x_time);
tab_box->hide();
keys->setEnabled( true );
control_grab = False;
if ( tab_box->currentDesktop() != -1 )
{
setCurrentDesktop( tab_box->currentDesktop() );
// popupinfo->showInfo( desktopName(currentDesktop()) ); // AK - not sure
}
}
}
int Workspace::nextDesktopFocusChain( int iDesktop ) const
{
int i = desktop_focus_chain.find( iDesktop );
if( i >= 0 && i+1 < (int)desktop_focus_chain.size() )
return desktop_focus_chain[i+1];
else if( desktop_focus_chain.size() > 0 )
return desktop_focus_chain[ 0 ];
else
return 1;
}
int Workspace::previousDesktopFocusChain( int iDesktop ) const
{
int i = desktop_focus_chain.find( iDesktop );
if( i-1 >= 0 )
return desktop_focus_chain[i-1];
else if( desktop_focus_chain.size() > 0 )
return desktop_focus_chain[desktop_focus_chain.size()-1];
else
return numberOfDesktops();
}
/*!
auxiliary functions to travers all clients according the focus
order. Useful for kwm<77>s Alt-tab feature.
*/
Client* Workspace::nextFocusChainClient( Client* c ) const
{
if ( focus_chain.isEmpty() )
return 0;
ClientList::ConstIterator it = focus_chain.find( c );
if ( it == focus_chain.end() )
return focus_chain.last();
if ( it == focus_chain.begin() )
return focus_chain.last();
--it;
return *it;
}
/*!
auxiliary functions to travers all clients according the focus
order. Useful for kwm<77>s Alt-tab feature.
*/
Client* Workspace::previousFocusChainClient( Client* c ) const
{
if ( focus_chain.isEmpty() )
return 0;
ClientList::ConstIterator it = focus_chain.find( c );
if ( it == focus_chain.end() )
return focus_chain.first();
++it;
if ( it == focus_chain.end() )
return focus_chain.first();
return *it;
}
/*!
auxiliary functions to travers all clients according the static
order. Useful for the CDE-style Alt-tab feature.
*/
Client* Workspace::nextStaticClient( Client* c ) const
{
if ( !c || clients.isEmpty() )
return 0;
ClientList::ConstIterator it = clients.find( c );
if ( it == clients.end() )
return clients.first();
++it;
if ( it == clients.end() )
return clients.first();
return *it;
}
/*!
auxiliary functions to travers all clients according the static
order. Useful for the CDE-style Alt-tab feature.
*/
Client* Workspace::previousStaticClient( Client* c ) const
{
if ( !c || clients.isEmpty() )
return 0;
ClientList::ConstIterator it = clients.find( c );
if ( it == clients.end() )
return clients.last();
if ( it == clients.begin() )
return clients.last();
--it;
return *it;
}
} // namespace
#include "tabbox.moc"