Some updates to the tabbox.

Provide a pair of methods, setCurrentClient() and setCurrentDesktop(),
to allow effects to select items in the tabbox without activating them.

Insulate effects from having to know the order of desktops, with
currentDesktopList().  DesktopMode and DesktopListMode should be
effectively identical as far as how effects work.

Some changes to how the tabbox refcounting is done, should work a little
better.  Other small cosmetic changes.

Update BoxSwitchEffect.


svn path=/branches/work/kwin_composite/; revision=647594
This commit is contained in:
Philip Falkner 2007-03-28 20:29:45 +00:00
parent d809643245
commit 574e562906
5 changed files with 345 additions and 216 deletions

View file

@ -10,10 +10,11 @@ License. See the file "COPYING" for the exact licensing terms.
#include "boxswitch.h" #include "boxswitch.h"
#include <tabbox.h> #include "tabbox.h"
#include <client.h> #include "client.h"
#include <scene_xrender.h> #include "scene_xrender.h"
#include <scene_opengl.h> #include "scene_opengl.h"
#include <QSize> #include <QSize>
#ifdef HAVE_OPENGL #ifdef HAVE_OPENGL
@ -96,7 +97,7 @@ void BoxSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da
{ {
paintFrame(); paintFrame();
for( painting_desktop = 1; painting_desktop <= desktops.count(); painting_desktop++ ) foreach( painting_desktop, desktops.keys())
{ {
if( painting_desktop == selected_desktop ) if( painting_desktop == selected_desktop )
{ {
@ -120,7 +121,7 @@ void BoxSwitchEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Wi
{ {
if( windows.contains( w ) && w != selected_window ) if( windows.contains( w ) && w != selected_window )
{ {
data.opacity *= 0.1; data.opacity *= 0.2;
} }
} }
} }
@ -142,28 +143,17 @@ void BoxSwitchEffect::windowInputMouseEvent( Window w, QEvent* e )
{ {
if( windows[ w ]->clickable.contains( pos )) if( windows[ w ]->clickable.contains( pos ))
{ {
if( Client* c = static_cast< Client* >( w->window())) Workspace::self()->setTabBoxClient( static_cast< Client* >( w->window()));
{
Workspace::self()->activateClient( c );
if( c->isShade() && options->shadeHover )
c->setShade( ShadeActivated );
Workspace::self()->unrefTabBox();
setInactive();
break;
}
} }
} }
} }
else else
{ {
for( int i = 1; i <= desktops.count(); i++ ) foreach( int i, desktops.keys())
{ {
if( desktops[ i ]->clickable.contains( pos )) if( desktops[ i ]->clickable.contains( pos ))
{ {
Workspace::self()->setCurrentDesktop( i ); Workspace::self()->setTabBoxDesktop( i );
Workspace::self()->unrefTabBox();
setInactive();
break;
} }
} }
} }
@ -235,8 +225,8 @@ void BoxSwitchEffect::tabBoxAdded( int mode )
} }
} }
else else
{ // DesktopMode or DesktopListMode { // DesktopMode
if( Workspace::self()->numberOfDesktops() > 0 ) if( Workspace::self()->currentTabBoxDesktopList().count() > 0 )
{ {
mMode = mode; mMode = mode;
painting_desktop = 0; painting_desktop = 0;
@ -269,19 +259,20 @@ void BoxSwitchEffect::tabBoxUpdated()
if( windows.contains( selected_window )) if( windows.contains( selected_window ))
workspace()->addRepaint( windows.value( selected_window )->area ); workspace()->addRepaint( windows.value( selected_window )->area );
selected_window->window()->addRepaintFull(); selected_window->window()->addRepaintFull();
if( Workspace::self()->currentTabBoxClientList() == tab_clients ) if( Workspace::self()->currentTabBoxClientList() == original_windows )
return; return;
tab_clients = Workspace::self()->currentTabBoxClientList(); original_windows = Workspace::self()->currentTabBoxClientList();
} }
else else
{ { // DesktopMode
if( desktops.contains( selected_desktop )) if( desktops.contains( selected_desktop ))
workspace()->addRepaint( desktops.value( selected_desktop )->area ); workspace()->addRepaint( desktops.value( selected_desktop )->area );
selected_desktop = Workspace::self()->currentTabBoxDesktop(); selected_desktop = Workspace::self()->currentTabBoxDesktop();
if( desktops.contains( selected_desktop )) if( desktops.contains( selected_desktop ))
workspace()->addRepaint( desktops.value( selected_desktop )->area ); workspace()->addRepaint( desktops.value( selected_desktop )->area );
if( Workspace::self()->numberOfDesktops() == desktops.count()) if( Workspace::self()->currentTabBoxDesktopList() == original_desktops )
return; return;
original_desktops = Workspace::self()->currentTabBoxDesktopList();
} }
workspace()->addRepaint( frame_area ); workspace()->addRepaint( frame_area );
calculateFrameSize(); calculateFrameSize();
@ -296,11 +287,12 @@ void BoxSwitchEffect::setActive()
mActivated = true; mActivated = true;
if( mMode == TabBox::WindowsMode ) if( mMode == TabBox::WindowsMode )
{ {
tab_clients = Workspace::self()->currentTabBoxClientList(); original_windows = Workspace::self()->currentTabBoxClientList();
selected_window = Workspace::self()->currentTabBoxClient()->effectWindow(); selected_window = Workspace::self()->currentTabBoxClient()->effectWindow();
} }
else else
{ {
original_desktops = Workspace::self()->currentTabBoxDesktopList();
selected_desktop = Workspace::self()->currentTabBoxDesktop(); selected_desktop = Workspace::self()->currentTabBoxDesktop();
} }
calculateFrameSize(); calculateFrameSize();
@ -321,6 +313,7 @@ void BoxSwitchEffect::setActive()
void BoxSwitchEffect::setInactive() void BoxSwitchEffect::setInactive()
{ {
mActivated = false; mActivated = false;
Workspace::self()->unrefTabBox();
if( mInput != None ) if( mInput != None )
{ {
effects->destroyInputWindow( mInput ); effects->destroyInputWindow( mInput );
@ -369,13 +362,13 @@ void BoxSwitchEffect::calculateFrameSize()
if( mMode == TabBox::WindowsMode ) if( mMode == TabBox::WindowsMode )
{ {
itemcount = tab_clients.count(); itemcount = original_windows.count();
item_max_size.setWidth( 200 ); item_max_size.setWidth( 200 );
item_max_size.setHeight( 200 ); item_max_size.setHeight( 200 );
} }
else else
{ {
itemcount = Workspace::self()->numberOfDesktops(); itemcount = original_desktops.count();
item_max_size.setWidth( 200 ); item_max_size.setWidth( 200 );
item_max_size.setHeight( 200 ); item_max_size.setHeight( 200 );
} }
@ -395,9 +388,9 @@ void BoxSwitchEffect::calculateItemSizes()
if( mMode == TabBox::WindowsMode ) if( mMode == TabBox::WindowsMode )
{ {
windows.clear(); windows.clear();
for( int i = 0; i < tab_clients.count(); i++ ) for( int i = 0; i < original_windows.count(); i++ )
{ {
EffectWindow* w = tab_clients.at( i )->effectWindow(); EffectWindow* w = original_windows.at( i )->effectWindow();
windows[ w ] = new ItemInfo(); windows[ w ] = new ItemInfo();
windows[ w ]->area = QRect( frame_area.x() + frame_margin windows[ w ]->area = QRect( frame_area.x() + frame_margin
@ -410,21 +403,16 @@ void BoxSwitchEffect::calculateItemSizes()
else else
{ {
desktops.clear(); desktops.clear();
int iDesktop = ( mMode == TabBox::DesktopMode ) ? Workspace::self()->currentDesktop() : 1; for( int i = 0; i < original_desktops.count(); i++ )
for( int i = 1; i <= Workspace::self()->numberOfDesktops(); i++ )
{ {
desktops[ iDesktop ] = new ItemInfo(); int it = original_desktops.at( i );
desktops[ it ] = new ItemInfo();
desktops[ iDesktop ]->area = QRect( frame_area.x() + frame_margin desktops[ it ]->area = QRect( frame_area.x() + frame_margin
+ ( i - 1 ) * item_max_size.width(), + i * item_max_size.width(),
frame_area.y() + frame_margin, frame_area.y() + frame_margin,
item_max_size.width(), item_max_size.height()); item_max_size.width(), item_max_size.height());
desktops[ iDesktop ]->clickable = desktops[ iDesktop ]->area; desktops[ it ]->clickable = desktops[ it ]->area;
if( mMode == TabBox::DesktopMode )
iDesktop = Workspace::self()->nextDesktopFocusChain( iDesktop );
else
iDesktop++;
} }
} }
} }
@ -439,12 +427,17 @@ void BoxSwitchEffect::paintFrame()
glEnable( GL_BLEND ); glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glColor4f( 0, 0, 0, alpha ); glColor4f( 0, 0, 0, alpha );
glBegin( GL_QUADS ); glEnableClientState( GL_VERTEX_ARRAY );
glVertex2i( frame_area.x(), frame_area.y()); int verts[ 4 * 2 ] =
glVertex2i( frame_area.x() + frame_area.width(), frame_area.y()); {
glVertex2i( frame_area.x() + frame_area.width(), frame_area.y() + frame_area.height()); frame_area.x(), frame_area.y(),
glVertex2i( frame_area.x(), frame_area.y() + frame_area.height()); frame_area.x(), frame_area.y() + frame_area.height(),
glEnd(); frame_area.x() + frame_area.width(), frame_area.y() + frame_area.height(),
frame_area.x() + frame_area.width(), frame_area.y()
};
glVertexPointer( 2, GL_INT, 0, verts );
glDrawArrays( GL_QUADS, 0, 4 );
glDisableClientState( GL_VERTEX_ARRAY );
glPopAttrib(); glPopAttrib();
} }
else else
@ -480,12 +473,17 @@ void BoxSwitchEffect::paintHighlight( QRect area, QString text )
glEnable( GL_BLEND ); glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glColor4f( 1, 1, 1, alpha ); glColor4f( 1, 1, 1, alpha );
glBegin( GL_QUADS ); glEnableClientState( GL_VERTEX_ARRAY );
glVertex2i( area.x(), area.y()); int verts[ 4 * 2 ] =
glVertex2i( area.x() + area.width(), area.y()); {
glVertex2i( area.x() + area.width(), area.y() + area.height()); area.x(), area.y(),
glVertex2i( area.x(), area.y() + area.height()); area.x(), area.y() + area.height(),
glEnd(); area.x() + area.width(), area.y() + area.height(),
area.x() + area.width(), area.y()
};
glVertexPointer( 2, GL_INT, 0, verts );
glDrawArrays( GL_QUADS, 0, 4 );
glDisableClientState( GL_VERTEX_ARRAY );
glPopAttrib(); glPopAttrib();
} }
else else
@ -512,6 +510,22 @@ void BoxSwitchEffect::paintHighlight( QRect area, QString text )
// kDebug() << text << endl; // TODO draw this nicely on screen // kDebug() << text << endl; // TODO draw this nicely on screen
} }
void BoxSwitchEffect::paintWindowThumbnail( EffectWindow* w )
{
if( !windows.contains( w ))
return;
WindowPaintData data;
setPositionTransformations( data,
windows[ w ]->thumbnail, w,
windows[ w ]->area.adjusted( highlight_margin, highlight_margin, -highlight_margin, -highlight_margin ),
Qt::KeepAspectRatio );
effects->drawWindow( w,
Scene::PAINT_WINDOW_OPAQUE | Scene::PAINT_WINDOW_TRANSFORMED,
windows[ w ]->thumbnail, data );
}
void BoxSwitchEffect::paintDesktopThumbnail( int iDesktop ) void BoxSwitchEffect::paintDesktopThumbnail( int iDesktop )
{ {
if( !desktops.contains( iDesktop )) if( !desktops.contains( iDesktop ))
@ -538,22 +552,6 @@ void BoxSwitchEffect::paintDesktopThumbnail( int iDesktop )
region, data ); region, data );
} }
void BoxSwitchEffect::paintWindowThumbnail( EffectWindow* w )
{
if( !windows.contains( w ))
return;
WindowPaintData data;
setPositionTransformations( data,
windows[ w ]->thumbnail, w,
windows[ w ]->area.adjusted( highlight_margin, highlight_margin, -highlight_margin, -highlight_margin ),
Qt::KeepAspectRatio );
effects->drawWindow( w,
Scene::PAINT_WINDOW_OPAQUE | Scene::PAINT_WINDOW_TRANSFORMED,
windows[ w ]->thumbnail, data );
}
void BoxSwitchEffect::paintWindowIcon( EffectWindow* w ) void BoxSwitchEffect::paintWindowIcon( EffectWindow* w )
{ {
if( !windows.contains( w )) if( !windows.contains( w ))
@ -586,23 +584,32 @@ void BoxSwitchEffect::paintWindowIcon( EffectWindow* w )
#ifdef HAVE_OPENGL #ifdef HAVE_OPENGL
if( dynamic_cast< SceneOpenGL* >( scene )) if( dynamic_cast< SceneOpenGL* >( scene ))
{ {
glPushMatrix(); glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT );
glPushAttrib( GL_ENABLE_BIT );
glEnable( GL_BLEND ); glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
windows[ w ]->iconTexture.bind(); windows[ w ]->iconTexture.bind();
glBegin( GL_QUADS ); glEnableClientState( GL_VERTEX_ARRAY );
glTexCoord2i( 0, 1 ); int verts[ 4 * 2 ] =
glVertex2i( x, y ); {
glTexCoord2i( 1, 1 ); x, y,
glVertex2i( x + width, y ); x, y + height,
glTexCoord2i( 1, 0 ); x + width, y + height,
glVertex2i( x + width, y + height ); x + width, y
glTexCoord2i( 0, 0 ); };
glVertex2i( x, y + height ); glVertexPointer( 2, GL_INT, 0, verts );
glEnd(); glEnableClientState( GL_TEXTURE_COORD_ARRAY );
int texcoords[ 4 * 2 ] =
{
0, 1,
0, 0,
1, 0,
1, 1
};
glTexCoordPointer( 2, GL_INT, 0, texcoords );
glDrawArrays( GL_QUADS, 0, 4 );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisableClientState( GL_VERTEX_ARRAY );
windows[ w ]->iconTexture.unbind(); windows[ w ]->iconTexture.unbind();
glPopMatrix();
glPopAttrib(); glPopAttrib();
} }
else else

View file

@ -12,8 +12,8 @@ License. See the file "COPYING" for the exact licensing terms.
#define KWIN_BOXSWITCH_H #define KWIN_BOXSWITCH_H
#include <effects.h> #include <effects.h>
#include <scene_xrender.h> #include "scene_xrender.h"
#include <scene_opengl.h> #include "scene_opengl.h"
#include <QHash> #include <QHash>
#include <QPixmap> #include <QPixmap>
@ -52,8 +52,8 @@ class BoxSwitchEffect
void paintFrame(); void paintFrame();
void paintHighlight( QRect area, QString text ); void paintHighlight( QRect area, QString text );
void paintDesktopThumbnail( int iDesktop );
void paintWindowThumbnail( EffectWindow* w ); void paintWindowThumbnail( EffectWindow* w );
void paintDesktopThumbnail( int iDesktop );
void paintWindowIcon( EffectWindow* w ); void paintWindowIcon( EffectWindow* w );
bool mActivated; bool mActivated;
@ -61,17 +61,16 @@ class BoxSwitchEffect
int mMode; int mMode;
QRect frame_area; QRect frame_area;
int frame_margin; int frame_margin; // TODO graphical background
int highlight_margin; // TODO graphical background
QSize item_max_size; // maximum item display size (including highlight) QSize item_max_size; // maximum item display size (including highlight)
int highlight_margin; // TODO graphical background, highlight
QHash< int, ItemInfo* > desktops;
QHash< EffectWindow*, ItemInfo* > windows; QHash< EffectWindow*, ItemInfo* > windows;
ClientList original_windows;
int selected_desktop;
ClientList tab_clients;
EffectWindow* selected_window; EffectWindow* selected_window;
QHash< int, ItemInfo* > desktops;
QList< int > original_desktops;
int selected_desktop;
int painting_desktop; int painting_desktop;

View file

@ -45,11 +45,13 @@ extern QPixmap* kwin_get_menu_pix_hack();
TabBox::TabBox( Workspace *ws ) TabBox::TabBox( Workspace *ws )
: QFrame( 0, Qt::X11BypassWindowManagerHint ) : QFrame( 0, Qt::X11BypassWindowManagerHint )
, client(0)
, wspace(ws) , wspace(ws)
, client(0)
, display_refcount( 0 ) , display_refcount( 0 )
{ {
setFrameStyle(QFrame::StyledPanel | QFrame::Plain); setFrameStyle(QFrame::StyledPanel);
setFrameShadow(QFrame::Plain);
setBackgroundRole(QPalette::Base);
setLineWidth(2); setLineWidth(2);
setContentsMargins( 2, 2, 2, 2 ); setContentsMargins( 2, 2, 2, 2 );
@ -91,7 +93,7 @@ void TabBox::createClientList(ClientList &list, int desktop /*-1 = all*/, Client
Client* start = c; Client* start = c;
if ( chain ) if ( chain )
c = workspace()->nextFocusChainClient(c); c = workspace()->nextClientFocusChain(c);
else else
c = workspace()->stackingOrder().first(); c = workspace()->stackingOrder().first();
@ -118,7 +120,7 @@ void TabBox::createClientList(ClientList &list, int desktop /*-1 = all*/, Client
} }
if ( chain ) if ( chain )
c = workspace()->nextFocusChainClient( c ); c = workspace()->nextClientFocusChain( c );
else else
{ {
if ( idx >= (workspace()->stackingOrder().size()-1) ) if ( idx >= (workspace()->stackingOrder().size()-1) )
@ -133,6 +135,30 @@ void TabBox::createClientList(ClientList &list, int desktop /*-1 = all*/, Client
} }
/*!
Create list of desktops, starting with desktop start
*/
void TabBox::createDesktopList(QList< int > &list, int start, SortOrder order)
{
list.clear();
int iDesktop = start;
for( int i = 1; i <= workspace()->numberOfDesktops(); i++ )
{
list.append( iDesktop );
if ( order == StaticOrder )
{
iDesktop = workspace()->nextDesktopStatic( iDesktop );
}
else
{ // MostRecentlyUsedOrder
iDesktop = workspace()->nextDesktopFocusChain( iDesktop );
}
}
}
/*! /*!
Resets the tab box to display the active client in WindowsMode, or the Resets the tab box to display the active client in WindowsMode, or the
current desktop in DesktopListMode current desktop in DesktopListMode
@ -158,18 +184,16 @@ void TabBox::reset( bool partial_reset )
// get all clients to show // get all clients to show
createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), starting_client, true); createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), starting_client, true);
displayed_clients = clients;
// calculate maximum caption width // calculate maximum caption width
cw = fontMetrics().width(no_tasks)+20; cw = fontMetrics().width(no_tasks)+20;
for (ClientList::ConstIterator it = displayed_clients.begin(); it != displayed_clients.end(); ++it) for (ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
{ {
cw = fontMetrics().width( (*it)->caption() ); cw = fontMetrics().width( (*it)->caption() );
if ( cw > wmax ) wmax = cw; if ( cw > wmax ) wmax = cw;
} }
// calculate height for the popup // calculate height for the popup
if ( displayed_clients.count() == 0 ) // height for the "not tasks" text if ( clients.count() == 0 ) // height for the "not tasks" text
{ {
QFont f = font(); QFont f = font();
f.setBold( true ); f.setBold( true );
@ -180,7 +204,7 @@ void TabBox::reset( bool partial_reset )
else else
{ {
showMiniIcon = false; showMiniIcon = false;
h = displayed_clients.count() * lineHeight; h = clients.count() * lineHeight;
if ( h > (r.height()-(2*frameWidth())) ) // if too high, use mini icons if ( h > (r.height()-(2*frameWidth())) ) // if too high, use mini icons
{ {
@ -188,33 +212,47 @@ void TabBox::reset( bool partial_reset )
// fontheight + 1 pixel above + 1 pixel below, or 16x16 icon + 1 pixel above + below // fontheight + 1 pixel above + 1 pixel below, or 16x16 icon + 1 pixel above + below
lineHeight = qMax(fontMetrics().height() + 2, 16 + 2); lineHeight = qMax(fontMetrics().height() + 2, 16 + 2);
h = displayed_clients.count() * lineHeight; h = clients.count() * lineHeight;
if ( h > (r.height()-(2*frameWidth())) ) // if still too high, remove some clients if ( h > (r.height()-(2*frameWidth())) ) // if still too high, remove some clients
{ {
// how many clients to remove // how many clients to remove
int howMany = (h - (r.height()-(2*frameWidth())))/lineHeight; int howMany = (h - (r.height()-(2*frameWidth())))/lineHeight;
for (; howMany; howMany--) for (; howMany; howMany--)
displayed_clients.removeAll(displayed_clients.last()); clients.removeAll(clients.last());
h = displayed_clients.count() * lineHeight; h = clients.count() * lineHeight;
} }
} }
} }
} }
else else
{ // DesktopListMode {
showMiniIcon = false; int starting_desktop;
if( mode() == DesktopListMode )
{
starting_desktop = 1;
createDesktopList(desktops, starting_desktop, StaticOrder );
}
else
{ // DesktopMode
starting_desktop = workspace()->currentDesktop();
createDesktopList(desktops, starting_desktop, MostRecentlyUsedOrder );
}
if( !partial_reset )
desk = workspace()->currentDesktop(); desk = workspace()->currentDesktop();
for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ ) showMiniIcon = false;
foreach (int it, desktops)
{ {
cw = fontMetrics().width( workspace()->desktopName(i) ); cw = fontMetrics().width( workspace()->desktopName(it) );
if ( cw > wmax ) wmax = cw; if ( cw > wmax ) wmax = cw;
} }
// calculate height for the popup (max. 16 desktops always fit in a 800x600 screen) // calculate height for the popup (max. 16 desktops always fit in a 800x600 screen)
h = workspace()->numberOfDesktops() * lineHeight; h = desktops.count() * lineHeight;
} }
// height, width for the popup // height, width for the popup
@ -239,47 +277,37 @@ void TabBox::nextPrev( bool next)
if ( mode() == WindowsMode ) if ( mode() == WindowsMode )
{ {
Client* firstClient = 0; Client* firstClient = 0;
Client* newClient = client;
do do
{ {
if ( next ) if ( next )
client = workspace()->nextFocusChainClient(client); newClient = workspace()->nextClientFocusChain(newClient);
else else
client = workspace()->previousFocusChainClient(client); newClient = workspace()->previousClientFocusChain(newClient);
if (!firstClient) if (!firstClient)
{ {
// When we see our first client for the second time, // When we see our first client for the second time,
// it's time to stop. // it's time to stop.
firstClient = client; firstClient = newClient;
} }
else if (client == firstClient) else if (newClient == firstClient)
{ {
// No candidates found. // No candidates found.
client = 0; newClient = 0;
break; break;
} }
} while ( client && !clients.contains( client )); } while ( newClient && !clients.contains( newClient ));
setCurrentClient( newClient );
} }
else if( mode() == DesktopMode ) else if( mode() == DesktopMode )
{ {
if ( next ) setCurrentDesktop ( next ? workspace()->nextDesktopFocusChain( desk )
desk = workspace()->nextDesktopFocusChain( desk ); : workspace()->previousDesktopFocusChain( desk ) );
else
desk = workspace()->previousDesktopFocusChain( desk );
} }
else else
{ // DesktopListMode { // DesktopListMode
if ( next ) setCurrentDesktop ( next ? workspace()->nextDesktopStatic( desk )
{ : workspace()->previousDesktopStatic( desk )) ;
desk++;
if ( desk > workspace()->numberOfDesktops() )
desk = 1;
}
else
{
desk--;
if ( desk < 1 )
desk = workspace()->numberOfDesktops();
}
} }
if( effects ) if( effects )
@ -324,11 +352,47 @@ int TabBox::currentDesktop()
{ {
if ( mode() == DesktopListMode || mode() == DesktopMode ) if ( mode() == DesktopListMode || mode() == DesktopMode )
return desk; return desk;
else
return -1; return -1;
} }
/*!
Returns the list of desktops potentially displayed ( only works in
DesktopListMode )
Returns an empty list if no desktops are available.
*/
QList< int > TabBox::currentDesktopList()
{
if ( mode() == DesktopListMode || mode() == DesktopMode )
return desktops;
return QList< int >();
}
/*!
Change the currently selected client, and notify the effects.
\sa setCurrentDesktop()
*/
void TabBox::setCurrentClient( Client* newClient )
{
client = newClient;
if( effects )
effects->tabBoxUpdated();
}
/*!
Change the currently selected desktop, and notify the effects.
\sa setCurrentClient()
*/
void TabBox::setCurrentDesktop( int newDesktop )
{
desk = newDesktop;
if( effects )
effects->tabBoxUpdated();
}
/*! /*!
Reimplemented to raise the tab box as well Reimplemented to raise the tab box as well
*/ */
@ -374,7 +438,7 @@ void TabBox::paintEvent( QPaintEvent* e )
} }
else else
{ {
for (ClientList::ConstIterator it = displayed_clients.begin(); it != displayed_clients.end(); ++it) for (ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
{ {
if ( workspace()->hasClient( *it ) ) // safety if ( workspace()->hasClient( *it ) ) // safety
{ {
@ -458,22 +522,19 @@ void TabBox::paintEvent( QPaintEvent* e )
QFontMetrics fm(f); QFontMetrics fm(f);
int wmax = 0; int wmax = 0;
for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ ) foreach (int it, desktops)
{ {
wmax = qMax(wmax, fontMetrics().width(workspace()->desktopName(i))); wmax = qMax(wmax, fontMetrics().width(workspace()->desktopName(it)));
// calculate max width of desktop-number text // calculate max width of desktop-number text
QString num = QString::number(i); QString num = QString::number(it);
iconWidth = qMax(iconWidth - 4, fm.boundingRect(num).width()) + 4; iconWidth = qMax(iconWidth - 4, fm.boundingRect(num).width()) + 4;
} }
// In DesktopMode, start at the current desktop foreach (int it, desktops)
// In DesktopListMode, start at desktop #1
int iDesktop = (mode() == DesktopMode) ? workspace()->currentDesktop() : 1;
for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ )
{ {
// draw highlight background // draw highlight background
if ( iDesktop == desk ) // current desktop if ( it == desk ) // current desktop
p.fillRect(x, y, r.width(), lineHeight, palette().brush( QPalette::Highlight )); p.fillRect(x, y, r.width(), lineHeight, palette().brush( QPalette::Highlight ));
p.save(); p.save();
@ -485,26 +546,26 @@ void TabBox::paintEvent( QPaintEvent* e )
// draw desktop-number // draw desktop-number
p.setFont(f); p.setFont(f);
QString num = QString::number(iDesktop); QString num = QString::number(it);
p.drawText(x+5, y+2, iconWidth, iconHeight, Qt::AlignCenter, num); p.drawText(x+5, y+2, iconWidth, iconHeight, Qt::AlignCenter, num);
p.restore(); p.restore();
// draw desktop name text // draw desktop name text
if ( iDesktop == desk ) if ( it == desk )
p.setPen(palette().color( QPalette::HighlightedText )); p.setPen(palette().color( QPalette::HighlightedText ));
else else
p.setPen(palette().color( QPalette::Text )); p.setPen(palette().color( QPalette::Text ));
p.drawText(x+5 + iconWidth + 8, y, r.width() - 5 - iconWidth - 8, lineHeight, p.drawText(x+5 + iconWidth + 8, y, r.width() - 5 - iconWidth - 8, lineHeight,
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine,
workspace()->desktopName(iDesktop)); workspace()->desktopName(it));
// show mini icons from that desktop aligned to each other // show mini icons from that desktop aligned to each other
int x1 = x + 5 + iconWidth + 8 + wmax + 5; int x1 = x + 5 + iconWidth + 8 + wmax + 5;
ClientList list; ClientList list;
createClientList(list, iDesktop, 0, false); createClientList(list, it, 0, false);
// clients are in reversed stacking order // clients are in reversed stacking order
for ( int i = list.size() - 1; i>=0; i-- ) for ( int i = list.size() - 1; i>=0; i-- )
{ {
@ -521,29 +582,38 @@ void TabBox::paintEvent( QPaintEvent* e )
// next desktop // next desktop
y += lineHeight; y += lineHeight;
if ( y >= r.height() ) break; if ( y >= r.height() ) break;
if( mode() == DesktopMode )
iDesktop = workspace()->nextDesktopFocusChain( iDesktop );
else
iDesktop++;
} }
} }
} }
/*!
Notify effects that the tab box is being shown, and only display the
default tab box QFrame if no effect has referenced the tab box.
*/
void TabBox::show() void TabBox::show()
{ {
if( display_refcount > 0 )
return;
display_refcount = 0;
if( effects ) if( effects )
effects->tabBoxAdded( mode()); effects->tabBoxAdded( mode());
if( display_refcount == 0 ) // no effects have claimed TabBox if( isDisplayed())
return;
refDisplay();
QWidget::show(); QWidget::show();
} }
/*!
Notify effects that the tab box is being hidden.
*/
void TabBox::hide() void TabBox::hide()
{ {
delayedShowTimer.stop(); delayedShowTimer.stop();
if( isVisible())
unrefDisplay();
if( effects )
effects->tabBoxClosed();
if( isDisplayed())
kDebug( 1212 ) << "Tab box was not properly closed by an effect" << endl;
QWidget::hide(); QWidget::hide();
QApplication::syncX(); QApplication::syncX();
XEvent otherEvent; XEvent otherEvent;
@ -553,13 +623,12 @@ void TabBox::hide()
/*! /*!
Reduce the reference count, eventually closing the tabbox. Decrease the reference count. Only when the reference count is 0 will
the default tab box be shown.
*/ */
void TabBox::unrefTabBox() void TabBox::unrefDisplay()
{ {
if( --display_refcount > 0 ) --display_refcount;
return;
workspace()->closeTabBox();
} }
void TabBox::reconfigure() void TabBox::reconfigure()
@ -607,33 +676,34 @@ void TabBox::delayedShow()
void TabBox::handleMouseEvent( XEvent* e ) void TabBox::handleMouseEvent( XEvent* e )
{ {
XAllowEvents( display(), AsyncPointer, xTime() ); XAllowEvents( display(), AsyncPointer, xTime() );
if( display_refcount > 0 ) // tabbox has been replaced, check effects if( !isVisible() && isDisplayed())
{ { // tabbox has been replaced, check effects
if( effects && !effects->checkInputWindowEvent( e ) && e->type == ButtonPress ) if( effects && effects->checkInputWindowEvent( e ))
unrefTabBox();
return; return;
} }
if( e->type != ButtonPress ) if( e->type != ButtonPress )
return; return;
QPoint pos( e->xbutton.x_root, e->xbutton.y_root ); QPoint pos( e->xbutton.x_root, e->xbutton.y_root );
if( !geometry().contains( pos )) QPoint widgetPos = mapFromGlobal( pos ); // inside tabbox
if(( !isVisible() && isDisplayed())
|| !geometry().contains( pos ))
{ {
unrefTabBox(); // click outside closes tab workspace()->closeTabBox(); // click outside closes tab
return; return;
} }
pos.rx() -= x(); // pos is now inside tabbox
pos.ry() -= y(); int num = (widgetPos.y()-frameWidth()) / lineHeight;
int num = (pos.y()-frameWidth()) / lineHeight;
if( mode() == WindowsMode ) if( mode() == WindowsMode )
{ {
for( ClientList::ConstIterator it = displayed_clients.begin(); for( ClientList::ConstIterator it = clients.begin();
it != displayed_clients.end(); it != clients.end();
++it) ++it)
{ {
if( workspace()->hasClient( *it ) && (num == 0) ) // safety if( workspace()->hasClient( *it ) && (num == 0) ) // safety
{ {
client = *it; setCurrentClient( *it );
break; break;
} }
num--; num--;
@ -641,21 +711,14 @@ void TabBox::handleMouseEvent( XEvent* e )
} }
else else
{ {
int iDesktop = (mode() == DesktopMode) ? workspace()->currentDesktop() : 1; foreach( int it, desktops )
for( int i = 1;
i <= workspace()->numberOfDesktops();
++i )
{ {
if( num == 0 ) if( num == 0 )
{ {
desk = iDesktop; setCurrentDesktop( it );
break; break;
} }
num--; num--;
if( mode() == DesktopMode )
iDesktop = workspace()->nextDesktopFocusChain( iDesktop );
else
iDesktop++;
} }
} }
update(); update();
@ -996,7 +1059,7 @@ void Workspace::CDEWalkThroughWindows( bool forward )
Client* firstClient = 0; Client* firstClient = 0;
do do
{ {
nc = forward ? nextStaticClient(nc) : previousStaticClient(nc); nc = forward ? nextClientStatic(nc) : previousClientStatic(nc);
if (!firstClient) if (!firstClient)
{ {
// When we see our first client for the second time, // When we see our first client for the second time,
@ -1097,7 +1160,7 @@ void Workspace::tabBoxKeyPress( int keyQt )
if ( ((keyQt & ~Qt::KeyboardModifierMask) == Qt::Key_Escape) if ( ((keyQt & ~Qt::KeyboardModifierMask) == Qt::Key_Escape)
&& !(forward || backward) ) && !(forward || backward) )
{ // if Escape is part of the shortcut, don't cancel { // if Escape is part of the shortcut, don't cancel
unrefTabBox(); closeTabBox();
} }
} }
} }
@ -1105,21 +1168,19 @@ void Workspace::tabBoxKeyPress( int keyQt )
void Workspace::refTabBox() void Workspace::refTabBox()
{ {
if( tab_box ) if( tab_box )
tab_box->refTabBox(); tab_box->refDisplay();
} }
void Workspace::unrefTabBox() void Workspace::unrefTabBox()
{ {
if( tab_box ) if( tab_box )
tab_box->unrefTabBox(); tab_box->unrefDisplay();
} }
void Workspace::closeTabBox() void Workspace::closeTabBox()
{ {
removeTabBoxGrab(); removeTabBoxGrab();
tab_box->hide(); tab_box->hide();
if( effects )
effects->tabBoxClosed();
keys->setEnabled( true ); keys->setEnabled( true );
disable_shortcuts_keys->setEnabled( true ); disable_shortcuts_keys->setEnabled( true );
client_keys->setEnabled( true ); client_keys->setEnabled( true );
@ -1168,7 +1229,7 @@ void Workspace::tabBoxKeyRelease( const XKeyEvent& ev )
if (tab_grab) if (tab_grab)
{ {
bool old_control_grab = control_grab; bool old_control_grab = control_grab;
unrefTabBox(); closeTabBox();
control_grab = old_control_grab; control_grab = old_control_grab;
if( Client* c = tab_box->currentClient()) if( Client* c = tab_box->currentClient())
{ {
@ -1180,7 +1241,7 @@ void Workspace::tabBoxKeyRelease( const XKeyEvent& ev )
if (control_grab) if (control_grab)
{ {
bool old_tab_grab = tab_grab; bool old_tab_grab = tab_grab;
unrefTabBox(); closeTabBox();
tab_grab = old_tab_grab; tab_grab = old_tab_grab;
if ( tab_box->currentDesktop() != -1 ) if ( tab_box->currentDesktop() != -1 )
{ {
@ -1212,11 +1273,27 @@ int Workspace::previousDesktopFocusChain( int iDesktop ) const
return numberOfDesktops(); return numberOfDesktops();
} }
int Workspace::nextDesktopStatic( int iDesktop ) const
{
int i = ++iDesktop;
if( i > numberOfDesktops())
i = 1;
return i;
}
int Workspace::previousDesktopStatic( int iDesktop ) const
{
int i = --iDesktop;
if( i < 1 )
i = numberOfDesktops();
return i;
}
/*! /*!
auxiliary functions to travers all clients according the focus auxiliary functions to travers all clients according the focus
order. Useful for kwms Alt-tab feature. order. Useful for kwms Alt-tab feature.
*/ */
Client* Workspace::nextFocusChainClient( Client* c ) const Client* Workspace::nextClientFocusChain( Client* c ) const
{ {
if ( global_focus_chain.isEmpty() ) if ( global_focus_chain.isEmpty() )
return 0; return 0;
@ -1233,7 +1310,7 @@ Client* Workspace::nextFocusChainClient( Client* c ) const
auxiliary functions to travers all clients according the focus auxiliary functions to travers all clients according the focus
order. Useful for kwms Alt-tab feature. order. Useful for kwms Alt-tab feature.
*/ */
Client* Workspace::previousFocusChainClient( Client* c ) const Client* Workspace::previousClientFocusChain( Client* c ) const
{ {
if ( global_focus_chain.isEmpty() ) if ( global_focus_chain.isEmpty() )
return 0; return 0;
@ -1250,7 +1327,7 @@ Client* Workspace::previousFocusChainClient( Client* c ) const
auxiliary functions to travers all clients according the static auxiliary functions to travers all clients according the static
order. Useful for the CDE-style Alt-tab feature. order. Useful for the CDE-style Alt-tab feature.
*/ */
Client* Workspace::nextStaticClient( Client* c ) const Client* Workspace::nextClientStatic( Client* c ) const
{ {
if ( !c || clients.isEmpty() ) if ( !c || clients.isEmpty() )
return 0; return 0;
@ -1266,7 +1343,7 @@ Client* Workspace::nextStaticClient( Client* c ) const
auxiliary functions to travers all clients according the static auxiliary functions to travers all clients according the static
order. Useful for the CDE-style Alt-tab feature. order. Useful for the CDE-style Alt-tab feature.
*/ */
Client* Workspace::previousStaticClient( Client* c ) const Client* Workspace::previousClientStatic( Client* c ) const
{ {
if ( !c || clients.isEmpty() ) if ( !c || clients.isEmpty() )
return 0; return 0;
@ -1300,6 +1377,25 @@ int Workspace::currentTabBoxDesktop() const
return tab_box->currentDesktop(); return tab_box->currentDesktop();
} }
QList< int > Workspace::currentTabBoxDesktopList() const
{
if( !tab_box )
return QList< int >();
return tab_box->currentDesktopList();
}
void Workspace::setTabBoxClient( Client* c )
{
if( tab_box )
tab_box->setCurrentClient( c );
}
void Workspace::setTabBoxDesktop( int iDesktop )
{
if( tab_box )
tab_box->setCurrentDesktop( iDesktop );
}
bool Workspace::establishTabBoxGrab() bool Workspace::establishTabBoxGrab()
{ {
if( XGrabKeyboard( display(), root, false, if( XGrabKeyboard( display(), root, false,

View file

@ -34,11 +34,16 @@ class TabBox : public QFrame
Client* currentClient(); Client* currentClient();
ClientList currentClientList(); ClientList currentClientList();
int currentDesktop(); int currentDesktop();
QList< int > currentDesktopList();
void setCurrentClient( Client* newClient );
void setCurrentDesktop( int newDesktop );
// DesktopMode and WindowsMode are based on the order in which the desktop // DesktopMode and WindowsMode are based on the order in which the desktop
// or window were viewed. // or window were viewed.
// DesktopListMode lists them in the order created. // DesktopListMode lists them in the order created.
enum Mode { DesktopMode, DesktopListMode, WindowsMode }; enum Mode { DesktopMode, DesktopListMode, WindowsMode };
enum SortOrder { StaticOrder, MostRecentlyUsedOrder };
void setMode( Mode mode ); void setMode( Mode mode );
Mode mode() const; Mode mode() const;
@ -48,8 +53,9 @@ class TabBox : public QFrame
void delayedShow(); void delayedShow();
void hide(); void hide();
void refTabBox(); void refDisplay();
void unrefTabBox(); void unrefDisplay();
bool isDisplayed() const;
void handleMouseEvent( XEvent* ); void handleMouseEvent( XEvent* );
@ -68,19 +74,22 @@ class TabBox : public QFrame
private: private:
void createClientList(ClientList &list, int desktop /*-1 = all*/, Client *start, bool chain); void createClientList(ClientList &list, int desktop /*-1 = all*/, Client *start, bool chain);
void createDesktopList(QList< int > &list, int start, SortOrder order);
private: private:
Client* client;
Mode m;
Workspace* wspace; Workspace* wspace;
ClientList clients, displayed_clients; Mode m;
ClientList clients;
Client* client;
QList< int > desktops;
int desk; int desk;
QTimer delayedShowTimer;
int display_refcount;
QString no_tasks;
int lineHeight; int lineHeight;
bool showMiniIcon; bool showMiniIcon;
QTimer delayedShowTimer;
QString no_tasks;
bool options_traverse_all; bool options_traverse_all;
int display_refcount;
}; };
@ -104,12 +113,25 @@ inline TabBox::Mode TabBox::mode() const
/*! /*!
Increase the reference count, preventing the default tabbox from showing. Increase the reference count, preventing the default tabbox from showing.
\sa unrefDisplay(), isDisplayed()
*/ */
inline void TabBox::refTabBox() inline void TabBox::refDisplay()
{ {
++display_refcount; ++display_refcount;
} }
/*!
Returns whether the tab box is being displayed, either natively or by an
effect.
\sa refDisplay(), unrefDisplay()
*/
inline bool TabBox::isDisplayed() const
{
return display_refcount > 0;
}
} // namespace } // namespace
#endif #endif

View file

@ -172,12 +172,17 @@ class Workspace : public QObject, public KDecorationDefines
Client* currentTabBoxClient() const; Client* currentTabBoxClient() const;
ClientList currentTabBoxClientList() const; ClientList currentTabBoxClientList() const;
int currentTabBoxDesktop() const; int currentTabBoxDesktop() const;
Client* nextFocusChainClient(Client*) const; QList< int > currentTabBoxDesktopList() const;
Client* previousFocusChainClient(Client*) const; void setTabBoxClient(Client*);
Client* nextStaticClient(Client*) const; void setTabBoxDesktop(int);
Client* previousStaticClient(Client*) const; Client* nextClientFocusChain(Client*) const;
Client* previousClientFocusChain(Client*) const;
Client* nextClientStatic(Client*) const;
Client* previousClientStatic(Client*) const;
int nextDesktopFocusChain( int iDesktop ) const; int nextDesktopFocusChain( int iDesktop ) const;
int previousDesktopFocusChain( int iDesktop ) const; int previousDesktopFocusChain( int iDesktop ) const;
int nextDesktopStatic( int iDesktop ) const;
int previousDesktopStatic( int iDesktop ) const;
void refTabBox(); void refTabBox();
void unrefTabBox(); void unrefTabBox();
void closeTabBox(); void closeTabBox();