GUI: Alt/Tab shows list of icon+window title; Ctrl/Tab shows

list of desktop number+name+icon of apps

svn path=/trunk/kdebase/kwin/; revision=285419
icc-effect-5.14.5
Martin Koller 2004-02-05 21:58:22 +00:00
parent 42e26ff608
commit 3c26c240fe
2 changed files with 285 additions and 172 deletions

View File

@ -43,11 +43,16 @@ namespace KWinInternal
extern QPixmap* kwin_get_menu_pix_hack(); extern QPixmap* kwin_get_menu_pix_hack();
TabBox::TabBox( Workspace *ws, const char *name ) TabBox::TabBox( Workspace *ws, const char *name )
: QWidget( 0, name ) : QFrame( 0, name, Qt::WNoAutoErase ), client(0), wspace(ws)
{ {
setFrameStyle(QFrame::StyledPanel | QFrame::Plain);
setLineWidth(2);
setMargin(2);
showMiniIcon = false;
no_tasks = i18n("*** No Tasks ***"); no_tasks = i18n("*** No Tasks ***");
m = DesktopMode; // init variables m = DesktopMode; // init variables
wspace = ws;
reconfigure(); reconfigure();
reset(); reset();
connect(&delayedShowTimer, SIGNAL(timeout()), this, SLOT(show())); connect(&delayedShowTimer, SIGNAL(timeout()), this, SLOT(show()));
@ -69,70 +74,147 @@ void TabBox::setMode( Mode mode )
} }
/*!
Create list of clients on specified desktop, starting with client c
*/
void TabBox::createClientList(ClientList &list, int desktop /*-1 = all*/, Client *c, bool chain)
{
ClientList::size_type idx = 0;
list.clear();
Client* start = c;
if ( chain )
c = workspace()->nextFocusChainClient(c);
else
c = workspace()->stackingOrder().first();
Client* stop = c;
while ( c )
{
if ( ((desktop == -1) || c->isOnDesktop(desktop))
&& (!c->isMinimized() || !c->isTransient() || c->isUtility()) && c->wantsTabFocus() )
{
if ( start == c )
{
list.remove( c );
list.prepend( c );
}
else
{ // don't add windows that have modal dialogs
Client* modal = c->findModal();
if( modal == NULL || modal == c )
list += c;
else if( !list.contains( modal ))
list += modal;
else
; // nothing
}
}
if ( chain )
c = workspace()->nextFocusChainClient( c );
else
{
if ( idx >= (workspace()->stackingOrder().size()-1) )
c = 0;
else
c = workspace()->stackingOrder()[++idx];
}
if ( c == stop )
break;
}
}
/*! /*!
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
*/ */
void TabBox::reset() void TabBox::reset()
{ {
QFont f = font(); int w, h, cw = 0, wmax = 0;
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()); QRect r = KGlobalSettings::desktopGeometry(QCursor::pos());
int w = QMIN( QMAX( wmax + 20, r.width()/3 ), r.width() ); // calculate height of 1 line
setGeometry( (r.width()-w)/2 + r.x(), // fontheight + 1 pixel above + 1 pixel below, or 32x32 icon + 2 pixel above + below
r.height()/2-fontMetrics().height()*2-10 + r.y(), lineHeight = QMAX(fontMetrics().height() + 2, 32 + 4);
w, fontMetrics().height()*4 + 20 );
wmax = QMIN( wmax, width() - 12 ); if ( mode() == WindowsMode )
{
client = workspace()->activeClient();
// get all clients to show
createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), client, true);
// calculate maximum caption width
cw = fontMetrics().width(no_tasks)+20;
for (ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
{
cw = fontMetrics().width( (*it)->caption() );
if ( cw > wmax ) wmax = cw;
}
// calculate height for the popup
if ( clients.count() == 0 ) // height for the "not tasks" text
{
QFont f = font();
f.setBold( TRUE );
f.setPointSize( 14 );
h = QFontMetrics(f).height()*4;
}
else
{
showMiniIcon = false;
h = clients.count() * lineHeight;
if ( h > (r.height()-(2*frameWidth())) ) // if too high, use mini icons
{
showMiniIcon = true;
// fontheight + 1 pixel above + 1 pixel below, or 16x16 icon + 1 pixel above + below
lineHeight = QMAX(fontMetrics().height() + 2, 16 + 2);
h = clients.count() * lineHeight;
if ( h > (r.height()-(2*frameWidth())) ) // if still too high, remove some clients
{
// how many clients to remove
int howMany = (h - (r.height()-(2*frameWidth())))/lineHeight;
for (; howMany; howMany--)
clients.remove(clients.last());
h = clients.count() * lineHeight;
}
}
}
}
else
{ // DesktopListMode
showMiniIcon = false;
desk = workspace()->currentDesktop();
for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ )
{
cw = fontMetrics().width( workspace()->desktopName(i) );
if ( cw > wmax ) wmax = cw;
}
// calculate height for the popup (max. 16 desktops always fit in a 800x600 screen)
h = workspace()->numberOfDesktops() * lineHeight;
}
// height, width for the popup
h += 2 * frameWidth();
w = QMIN( QMAX( 5 + (showMiniIcon ? 16 : 32) + 8 +wmax, r.width()/3 ), r.width() ); // 5=space, ()=icon, 8=space between icon+text
setGeometry( (r.width()-w)/2 + r.x(),
(r.height()-h)/2+ r.y(),
w, h );
} }
@ -187,7 +269,7 @@ void TabBox::nextPrev( bool next)
} }
} }
paintContents(); update();
} }
@ -235,125 +317,159 @@ void TabBox::hideEvent( QHideEvent* )
{ {
} }
/*! /*!
Paints the tab box Paints the tab box
*/ */
void TabBox::paintEvent( QPaintEvent* ) void TabBox::drawContents( QPainter * )
{ {
{ QRect r(contentsRect());
QPainter p( this ); QPixmap pix(r.size()); // do double buffering to avoid flickers
style().drawPrimitive( QStyle::PE_Panel, &p, QRect( 0, 0, width(), height() ), pix.fill(this, 0, 0);
colorGroup(), QStyle::Style_Default );
style().drawPrimitive( QStyle::PE_Panel, &p, QRect( 4, 4, width()-8, height()-8 ),
colorGroup(), QStyle::Style_Sunken );
}
paintContents();
}
QPainter p;
p.begin(&pix, this);
/*!
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(); QPixmap* menu_pix = kwin_get_menu_pix_hack();
QPainter p( this );
QRect r( 6, 6, width()-12, height()-32 ); int iconWidth = showMiniIcon ? 16 : 32;
p.fillRect( r, colorGroup().brush( QColorGroup::Background ) ); int x = 0;
int y = 0;
if ( mode () == WindowsMode ) if ( mode () == WindowsMode )
{ {
if ( currentClient() ) if ( !currentClient() )
{ {
int textw, maxlen = client->caption().length(); QFont f = font();
int icon = client->icon().isNull() ? 0 : 42; f.setBold( TRUE );
QString s; f.setPointSize( 14 );
do
{
s = QString();
if (!client->isOnDesktop(workspace()->currentDesktop()))
{
s.append(": ");
}
if (client->isMinimized()) p.setFont(f);
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); p.drawText( r, AlignCenter, no_tasks);
} }
else
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 ) ) for (ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
{ // safety {
if ( !(*it)->miniIcon().isNull() ) if ( workspace()->hasClient( *it ) ) // safety
{
// draw highlight background
if ( (*it) == currentClient() )
p.fillRect(x, y, r.width(), lineHeight, colorGroup().highlight());
// draw icon
if ( showMiniIcon )
{ {
if( (*it)->miniIcon().mask() != NULL ) if ( !(*it)->miniIcon().isNull() )
p.fillRect( x, y, 16, 16, colorGroup().brush( QColorGroup::Background )); p.drawPixmap( x+5, y + (lineHeight - iconWidth)/2, (*it)->miniIcon() );
p.drawPixmap( x, y, (*it)->miniIcon() );
} }
else if ( menu_pix ) else
{ if ( !(*it)->icon().isNull() )
if( menu_pix->mask() != NULL ) p.drawPixmap( x+5, y + (lineHeight - iconWidth)/2, (*it)->icon() );
p.fillRect( x, y, 16, 16, colorGroup().brush( QColorGroup::Background )); else if ( menu_pix )
p.drawPixmap( x, y, *menu_pix ); p.drawPixmap( x, y + (lineHeight - iconWidth)/2, *menu_pix );
}
p.setPen( (*it)==currentClient()? // generate text to display
colorGroup().highlight():colorGroup().background() ); QString s;
p.drawRect( x-2, y-2, 20, 20 );
p.setPen( colorGroup().foreground() ); if ( !(*it)->isOnDesktop(workspace()->currentDesktop()) )
x += 20; s = workspace()->desktopName((*it)->desktop()) + ": ";
}
if ( (*it)->isMinimized() )
s += QString("(") + (*it)->caption() + ")";
else
s += (*it)->caption();
s = KStringHandler::cPixelSqueeze(s, fontMetrics(), r.width() - 5 - iconWidth - 8);
// draw text
if ( (*it) == currentClient() )
p.setPen(colorGroup().highlightedText());
else
p.setPen(colorGroup().text());
p.drawText(x+5 + iconWidth + 8, y, r.width() - 5 - iconWidth - 8, lineHeight,
Qt::AlignLeft | Qt::AlignVCenter | Qt::SingleLine, s);
y += lineHeight;
}
if ( y >= r.height() ) break;
}
} }
} }
else else
{ // DesktopMode || DesktopListMode { // DesktopMode || DesktopListMode
p.drawText( r, AlignCenter, workspace()->desktopName(desk) ); int iconHeight = iconWidth;
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 // get widest desktop name/number
// In DesktopListMode, start at desktop #1 QFont f(font());
f.setBold(true);
f.setPixelSize(iconHeight - 4); // pixel, not point because I need to know the pixels
QFontMetrics fm(f);
int wmax = 0;
for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ )
{
wmax = QMAX(wmax, fontMetrics().width(workspace()->desktopName(i)));
// calculate max width of desktop-number text
QString num = QString::number(i);
iconWidth = QMAX(iconWidth - 4, fm.boundingRect(num).width()) + 4;
}
// In DesktopMode, start at the current desktop
// In DesktopListMode, start at desktop #1
int iDesktop = (mode() == DesktopMode) ? workspace()->currentDesktop() : 1; int iDesktop = (mode() == DesktopMode) ? workspace()->currentDesktop() : 1;
for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ ) for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ )
{ {
p.setPen( iDesktop == desk? // draw highlight background
colorGroup().highlight():colorGroup().background() ); if ( iDesktop == desk ) // current desktop
p.drawRect( x-2, y-2, 20, 20 ); p.fillRect(x, y, r.width(), lineHeight, colorGroup().highlight());
qDrawWinPanel( &p, QRect( x, y, 16, 16), colorGroup(), FALSE,
&colorGroup().brush(QColorGroup::Base ) ); p.save();
p.setPen( colorGroup().text() );
p.drawText( x, y, 16, 16, AlignCenter, QString::number(iDesktop) ); // draw "icon" (here: number of desktop)
x += 20; p.fillRect(x+5, y+2, iconWidth, iconHeight, colorGroup().base());
p.setPen(colorGroup().text());
p.drawRect(x+5, y+2, iconWidth, iconHeight);
// draw desktop-number
p.setFont(f);
QString num = QString::number(iDesktop);
p.drawText(x+5, y+2, iconWidth, iconHeight, Qt::AlignCenter, num);
p.restore();
// draw desktop name text
if ( iDesktop == desk )
p.setPen(colorGroup().highlightedText());
else
p.setPen(colorGroup().text());
p.drawText(x+5 + iconWidth + 8, y, r.width() - 5 - iconWidth - 8, lineHeight,
Qt::AlignLeft | Qt::AlignVCenter | Qt::SingleLine,
workspace()->desktopName(iDesktop));
// show mini icons from that desktop aligned to each other
int x1 = x + 5 + iconWidth + 8 + wmax + 5;
ClientList list;
createClientList(list, iDesktop, 0, false);
// clients are in reversed stacking order
for (ClientList::ConstIterator it = list.fromLast(); it != list.end(); --it)
{
if ( !(*it)->miniIcon().isNull() )
{
if ( x1+18 >= x+r.width() ) // only show full icons
break;
p.drawPixmap( x1, y + (lineHeight - 16)/2, (*it)->miniIcon() );
x1 += 18;
}
}
// next desktop
y += lineHeight;
if ( y >= r.height() ) break;
if( mode() == DesktopMode ) if( mode() == DesktopMode )
iDesktop = workspace()->nextDesktopFocusChain( iDesktop ); iDesktop = workspace()->nextDesktopFocusChain( iDesktop );
@ -361,6 +477,8 @@ void TabBox::paintContents()
iDesktop++; iDesktop++;
} }
} }
p.end();
bitBlt(this, r.x(), r.y(), &pix);
} }
void TabBox::hide() void TabBox::hide()
@ -426,49 +544,42 @@ void TabBox::handleMouseEvent( XEvent* e )
return; return;
pos.rx() -= x(); // pos is now inside tabbox pos.rx() -= x(); // pos is now inside tabbox
pos.ry() -= y(); pos.ry() -= y();
int num = (pos.y()-frameWidth()) / lineHeight;
if( mode() == WindowsMode ) 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(); for( ClientList::ConstIterator it = clients.begin();
it != clients.end(); it != clients.end();
++it) ++it)
{ {
if( workspace()->hasClient( *it ) // safety if( workspace()->hasClient( *it ) && (num == 0) ) // safety
&& pos.x() < x + 20 )
{ {
client = *it; client = *it;
break; break;
} }
x += 20; num--;
} }
} }
else 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; int iDesktop = (mode() == DesktopMode) ? workspace()->currentDesktop() : 1;
for( int i = 1; for( int i = 1;
i <= workspace()->numberOfDesktops(); i <= workspace()->numberOfDesktops();
++i ) ++i )
{ {
if( pos.x() < x + 20 ) if( num == 0 )
{ {
desk = iDesktop; desk = iDesktop;
break; break;
} }
x += 20; num--;
if( mode() == DesktopMode ) if( mode() == DesktopMode )
iDesktop = workspace()->nextDesktopFocusChain( iDesktop ); iDesktop = workspace()->nextDesktopFocusChain( iDesktop );
else else
iDesktop++; iDesktop++;
} }
} }
paintContents(); update();
} }
//******************************* //*******************************

View File

@ -12,7 +12,7 @@ License. See the file "COPYING" for the exact licensing terms.
#ifndef KWIN_TABBOX_H #ifndef KWIN_TABBOX_H
#define KWIN_TABBOX_H #define KWIN_TABBOX_H
#include <qwidget.h> #include <qframe.h>
#include <qtimer.h> #include <qtimer.h>
#include <qvaluelist.h> #include <qvaluelist.h>
#include "utils.h" #include "utils.h"
@ -25,7 +25,7 @@ namespace KWinInternal
class Workspace; class Workspace;
class Client; class Client;
class TabBox : public QWidget class TabBox : public QFrame
{ {
Q_OBJECT Q_OBJECT
public: public:
@ -55,10 +55,12 @@ class TabBox : public QWidget
void reconfigure(); void reconfigure();
protected: protected:
void paintEvent( QPaintEvent* );
void showEvent( QShowEvent* ); void showEvent( QShowEvent* );
void hideEvent( QHideEvent* ); void hideEvent( QHideEvent* );
void paintContents(); void drawContents( QPainter * );
private:
void createClientList(ClientList &list, int desktop /*-1 = all*/, Client *start, bool chain);
private: private:
Client* client; Client* client;
@ -66,8 +68,8 @@ class TabBox : public QWidget
Workspace* wspace; Workspace* wspace;
ClientList clients; ClientList clients;
int desk; int desk;
QLabel* icon; int lineHeight;
int wmax; bool showMiniIcon;
QTimer delayedShowTimer; QTimer delayedShowTimer;
QString no_tasks; QString no_tasks;
bool options_traverse_all; bool options_traverse_all;