Allow effects to replace the tabbox.

svn path=/branches/work/kwin_composite/; revision=640628
This commit is contained in:
Philip Falkner 2007-03-08 16:49:44 +00:00
parent db53353349
commit ce89ed0716
5 changed files with 237 additions and 43 deletions

View file

@ -96,6 +96,18 @@ void Effect::windowGeometryShapeChanged( EffectWindow*, const QRect& )
{
}
void Effect::tabBoxAdded( int )
{
}
void Effect::tabBoxClosed()
{
}
void Effect::tabBoxUpdated()
{
}
void Effect::prePaintScreen( int* mask, QRegion* region, int time )
{
effects->prePaintScreen( mask, region, time );
@ -259,6 +271,8 @@ void EffectsHandler::desktopChanged( int old )
void EffectsHandler::windowDamaged( EffectWindow* w, const QRect& r )
{
if( w == NULL )
return;
foreach( EffectPair ep, loaded_effects )
ep.second->windowDamaged( w, r );
}
@ -271,6 +285,24 @@ void EffectsHandler::windowGeometryShapeChanged( EffectWindow* w, const QRect& o
ep.second->windowGeometryShapeChanged( w, old );
}
void EffectsHandler::tabBoxAdded( int mode )
{
foreach( EffectPair ep, loaded_effects )
ep.second->tabBoxAdded( mode );
}
void EffectsHandler::tabBoxClosed()
{
foreach( EffectPair ep, loaded_effects )
ep.second->tabBoxClosed();
}
void EffectsHandler::tabBoxUpdated()
{
foreach( EffectPair ep, loaded_effects )
ep.second->tabBoxUpdated();
}
// start another painting pass
void EffectsHandler::startPaint()
{

View file

@ -88,6 +88,9 @@ class Effect
virtual void desktopChanged( int old );
virtual void windowDamaged( EffectWindow* w, const QRect& r );
virtual void windowGeometryShapeChanged( EffectWindow* w, const QRect& old );
virtual void tabBoxAdded( int mode );
virtual void tabBoxClosed();
virtual void tabBoxUpdated();
// Interpolates between x and y
static float interpolate(float x, float y, float a)
@ -161,6 +164,9 @@ class EffectsHandler
void desktopChanged( int old );
void windowDamaged( EffectWindow* w, const QRect& r );
void windowGeometryShapeChanged( EffectWindow* w, const QRect& old );
void tabBoxAdded( int mode );
void tabBoxClosed();
void tabBoxUpdated();
void registerEffect( const QString& name, EffectFactory* factory );
void loadEffect( const QString& name );

View file

@ -12,6 +12,7 @@ License. See the file "COPYING" for the exact licensing terms.
//#define QT_CLEAN_NAMESPACE
#include "tabbox.h"
#include "workspace.h"
#include "effects.h"
#include "client.h"
#include <QPainter>
#include <QLabel>
@ -46,6 +47,7 @@ TabBox::TabBox( Workspace *ws )
: QFrame( 0, Qt::X11BypassWindowManagerHint )
, client(0)
, wspace(ws)
, display_refcount( 0 )
{
setFrameStyle(QFrame::StyledPanel | QFrame::Plain);
setLineWidth(2);
@ -156,16 +158,18 @@ void TabBox::reset( bool partial_reset )
// get all clients to show
createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), starting_client, true);
displayed_clients = clients;
// calculate maximum caption width
cw = fontMetrics().width(no_tasks)+20;
for (ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
for (ClientList::ConstIterator it = displayed_clients.begin(); it != displayed_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
if ( displayed_clients.count() == 0 ) // height for the "not tasks" text
{
QFont f = font();
f.setBold( true );
@ -176,7 +180,7 @@ void TabBox::reset( bool partial_reset )
else
{
showMiniIcon = false;
h = clients.count() * lineHeight;
h = displayed_clients.count() * lineHeight;
if ( h > (r.height()-(2*frameWidth())) ) // if too high, use mini icons
{
@ -184,16 +188,16 @@ void TabBox::reset( bool partial_reset )
// 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;
h = displayed_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.removeAll(clients.last());
displayed_clients.removeAll(displayed_clients.last());
h = clients.count() * lineHeight;
h = displayed_clients.count() * lineHeight;
}
}
}
@ -221,6 +225,9 @@ void TabBox::reset( bool partial_reset )
setGeometry( (r.width()-w)/2 + r.x(),
(r.height()-h)/2+ r.y(),
w, h );
if( effects )
effects->tabBoxUpdated();
}
@ -275,6 +282,8 @@ void TabBox::nextPrev( bool next)
}
}
if( effects )
effects->tabBoxUpdated();
update();
}
@ -293,6 +302,19 @@ Client* TabBox::currentClient()
return client;
}
/*!
Returns the list of clients potentially displayed ( only works in
WindowsMode ).
Returns an empty list if no clients are available.
*/
ClientList TabBox::currentClientList()
{
if( mode() != WindowsMode )
return ClientList();
return clients;
}
/*!
Returns the currently displayed virtual desktop ( only works in
DesktopListMode )
@ -352,7 +374,7 @@ void TabBox::paintEvent( QPaintEvent* e )
}
else
{
for (ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
for (ClientList::ConstIterator it = displayed_clients.begin(); it != displayed_clients.end(); ++it)
{
if ( workspace()->hasClient( *it ) ) // safety
{
@ -508,6 +530,17 @@ void TabBox::paintEvent( QPaintEvent* e )
}
}
void TabBox::show()
{
if( display_refcount > 0 )
return;
display_refcount = 0;
if( effects )
effects->tabBoxAdded( mode());
if( display_refcount == 0 ) // no effects have claimed TabBox
QWidget::show();
}
void TabBox::hide()
{
delayedShowTimer.stop();
@ -519,6 +552,16 @@ void TabBox::hide()
}
/*!
Reduce the reference count, eventually closing the tabbox.
*/
void TabBox::unrefTabBox()
{
if( --display_refcount > 0 )
return;
workspace()->closeTabBox();
}
void TabBox::reconfigure()
{
KSharedConfigPtr c(KGlobal::config());
@ -564,12 +607,18 @@ void TabBox::delayedShow()
void TabBox::handleMouseEvent( XEvent* e )
{
XAllowEvents( display(), AsyncPointer, xTime() );
if( display_refcount > 0 ) // tabbox has been replaced, check effects
{
if( effects && !effects->checkInputWindowEvent( e ) && e->type == ButtonPress )
unrefTabBox();
return;
}
if( e->type != ButtonPress )
return;
QPoint pos( e->xbutton.x_root, e->xbutton.y_root );
if( !geometry().contains( pos ))
{
workspace()->closeTabBox(); // click outside closes tab
unrefTabBox(); // click outside closes tab
return;
}
pos.rx() -= x(); // pos is now inside tabbox
@ -578,8 +627,8 @@ void TabBox::handleMouseEvent( XEvent* e )
if( mode() == WindowsMode )
{
for( ClientList::ConstIterator it = clients.begin();
it != clients.end();
for( ClientList::ConstIterator it = displayed_clients.begin();
it != displayed_clients.end();
++it)
{
if( workspace()->hasClient( *it ) && (num == 0) ) // safety
@ -1048,15 +1097,29 @@ void Workspace::tabBoxKeyPress( int keyQt )
if ( ((keyQt & ~Qt::KeyboardModifierMask) == Qt::Key_Escape)
&& !(forward || backward) )
{ // if Escape is part of the shortcut, don't cancel
closeTabBox();
unrefTabBox();
}
}
}
void Workspace::refTabBox()
{
if( tab_box )
tab_box->refTabBox();
}
void Workspace::unrefTabBox()
{
if( tab_box )
tab_box->unrefTabBox();
}
void Workspace::closeTabBox()
{
removeTabBoxGrab();
tab_box->hide();
if( effects )
effects->tabBoxClosed();
keys->setEnabled( true );
disable_shortcuts_keys->setEnabled( true );
client_keys->setEnabled( true );
@ -1104,12 +1167,9 @@ void Workspace::tabBoxKeyRelease( const XKeyEvent& ev )
return;
if (tab_grab)
{
removeTabBoxGrab();
tab_box->hide();
keys->setEnabled( true );
disable_shortcuts_keys->setEnabled( true );
client_keys->setEnabled( true );
tab_grab = false;
bool old_control_grab = control_grab;
unrefTabBox();
control_grab = old_control_grab;
if( Client* c = tab_box->currentClient())
{
activateClient( c );
@ -1119,12 +1179,9 @@ void Workspace::tabBoxKeyRelease( const XKeyEvent& ev )
}
if (control_grab)
{
removeTabBoxGrab();
tab_box->hide();
keys->setEnabled( true );
disable_shortcuts_keys->setEnabled( true );
client_keys->setEnabled( true );
control_grab = False;
bool old_tab_grab = tab_grab;
unrefTabBox();
tab_grab = old_tab_grab;
if ( tab_box->currentDesktop() != -1 )
{
setCurrentDesktop( tab_box->currentDesktop() );
@ -1222,6 +1279,27 @@ Client* Workspace::previousStaticClient( Client* c ) const
return clients[ pos ];
}
Client* Workspace::currentTabBoxClient() const
{
if( !tab_box )
return 0;
return tab_box->currentClient();
}
ClientList Workspace::currentTabBoxClientList() const
{
if( !tab_box )
return ClientList();
return tab_box->currentClientList();
}
int Workspace::currentTabBoxDesktop() const
{
if( !tab_box )
return -1;
return tab_box->currentDesktop();
}
bool Workspace::establishTabBoxGrab()
{
if( XGrabKeyboard( display(), root, false,

View file

@ -32,6 +32,7 @@ class TabBox : public QFrame
~TabBox();
Client* currentClient();
ClientList currentClientList();
int currentDesktop();
// DesktopMode and WindowsMode are based on the order in which the desktop
@ -47,6 +48,9 @@ class TabBox : public QFrame
void delayedShow();
void hide();
void refTabBox();
void unrefTabBox();
void handleMouseEvent( XEvent* );
Workspace* workspace() const;
@ -54,6 +58,9 @@ class TabBox : public QFrame
void reconfigure();
void updateKeyMapping();
public slots:
void show();
protected:
void showEvent( QShowEvent* );
void hideEvent( QHideEvent* );
@ -66,13 +73,14 @@ class TabBox : public QFrame
Client* client;
Mode m;
Workspace* wspace;
ClientList clients;
ClientList clients, displayed_clients;
int desk;
int lineHeight;
bool showMiniIcon;
QTimer delayedShowTimer;
QString no_tasks;
bool options_traverse_all;
int display_refcount;
};
@ -94,6 +102,14 @@ inline TabBox::Mode TabBox::mode() const
return m;
}
/*!
Increase the reference count, preventing the default tabbox from showing.
*/
inline void TabBox::refTabBox()
{
++display_refcount;
}
} // namespace
#endif

View file

@ -18,6 +18,8 @@ License. See the file "COPYING" for the exact licensing terms.
#include <QCursor>
#include <netwm.h>
#include <kxmessages.h>
#include <qdatetime.h>
#include <kmanagerselection.h>
#include "utils.h"
#include "kdecoration.h"
@ -77,7 +79,7 @@ class Workspace : public QObject, public KDecorationDefines
virtual ~Workspace();
static Workspace * self() { return _self; }
bool workspaceEvent( XEvent * );
KDecoration* createDecoration( KDecorationBridge* bridge );
@ -87,6 +89,9 @@ class Workspace : public QObject, public KDecorationDefines
template< typename T > Client* findClient( T predicate );
template< typename T1, typename T2 > void forEachClient( T1 procedure, T2 predicate );
template< typename T > void forEachClient( T procedure );
template< typename T > Unmanaged* findUnmanaged( T predicate );
template< typename T1, typename T2 > void forEachUnmanaged( T1 procedure, T2 predicate );
template< typename T > void forEachUnmanaged( T procedure );
QRect clientArea( clientAreaOption, const QPoint& p, int desktop ) const;
QRect clientArea( clientAreaOption, const Client* c ) const;
@ -165,12 +170,17 @@ class Workspace : public QObject, public KDecorationDefines
QWidget* desktopWidget();
// for TabBox
Client* currentTabBoxClient() const;
ClientList currentTabBoxClientList() const;
int currentTabBoxDesktop() const;
Client* nextFocusChainClient(Client*) const;
Client* previousFocusChainClient(Client*) const;
Client* nextStaticClient(Client*) const;
Client* previousStaticClient(Client*) const;
int nextDesktopFocusChain( int iDesktop ) const;
int previousDesktopFocusChain( int iDesktop ) const;
void refTabBox();
void unrefTabBox();
void closeTabBox();
/**
@ -181,7 +191,7 @@ class Workspace : public QObject, public KDecorationDefines
ClientList ensureStackingOrder( const ClientList& clients ) const;
Client* topClientOnDesktop( int desktop, bool unconstrained = false, bool only_normal = true ) const;
Client* topClientOnDesktop( int desktop, bool unconstrained = false ) const;
Client* findDesktop( bool topmost, int desktop ) const;
void sendClientToDesktop( Client* c, int desktop, bool dont_activate );
void windowToPreviousDesktop( Client* c );
@ -190,6 +200,10 @@ class Workspace : public QObject, public KDecorationDefines
// KDE4 remove me - and it's also in the DCOP interface :(
void showWindowMenuAt( unsigned long id, int x, int y );
void loadEffect( const QString& name );
void unloadEffect( const QString& name );
/**
* Shows the menu operations menu for the client and makes it active if
* it's not already.
@ -224,7 +238,7 @@ class Workspace : public QObject, public KDecorationDefines
void circulateDesktopApplications();
QString desktopName( int desk ) const;
void setDesktopLayout(NET::Orientation o, int x, int y, NET::DesktopLayoutCorner c);
void setDesktopLayout(int o, int x, int y);
void setShowingDesktop( bool showing );
void resetShowingDesktop( bool keep_hidden );
bool showingDesktop() const;
@ -234,14 +248,17 @@ class Workspace : public QObject, public KDecorationDefines
void sendPingToWindow( Window w, Time timestamp ); // called from Client::pingWindow()
void sendTakeActivity( Client* c, Time timestamp, long flags ); // called from Client::takeActivity()
// only called from Client::destroyClient() or Client::releaseWindow()
void removeClient( Client*, allowed_t );
void removeClient( Client*, allowed_t ); // only called from Client::destroyClient() or Client::releaseWindow()
void setActiveClient( Client*, allowed_t );
Group* findGroup( Window leader ) const;
void addGroup( Group* group, allowed_t );
void removeGroup( Group* group, allowed_t );
Group* findClientLeaderGroup( const Client* c ) const;
void removeUnmanaged( Unmanaged*, allowed_t ); // only called from Unmanaged::release()
void removeDeleted( Deleted*, allowed_t );
void addDeleted( Deleted*, allowed_t );
bool checkStartupNotification( Window w, KStartupInfoId& id, KStartupInfoData& data );
void focusToNull(); // SELI public?
@ -276,6 +293,17 @@ class Workspace : public QObject, public KDecorationDefines
void requestDelayFocus( Client* );
void toggleTopDockShadows(bool on);
void addRepaint( const QRect& r );
void addRepaint( int x, int y, int w, int h );
void addRepaintFull();
// creates XComposite overlay window, call initOverlay() afterwards
bool createOverlay();
// init overlay and the destination window in it
void setupOverlay( Window window );
// destroys XComposite overlay window
void destroyOverlay();
Window overlayWindow();
public slots:
void refresh();
@ -406,15 +434,14 @@ class Workspace : public QObject, public KDecorationDefines
void cleanupTemporaryRules();
void writeWindowRules();
void slotBlockShortcuts(int data);
void slotReloadConfig();
// kompmgr
void setPopupClientOpacity(int v);
void resetClientOpacity();
void setTransButtonText(int value);
// end
void setPopupClientOpacity( QAction* action );
void setupCompositing();
void performCompositing();
void lostCMSelection();
protected:
bool keyPressMouseEmulation( XKeyEvent& ev );
bool netCheck( XEvent* e );
private:
void init();
@ -458,6 +485,8 @@ class Workspace : public QObject, public KDecorationDefines
// this is the right way to create a new client
Client* createClient( Window w, bool is_mapped );
void addClient( Client* c, allowed_t );
Unmanaged* createUnmanaged( Window w );
void addUnmanaged( Unmanaged* c, allowed_t );
Window findSpecialEventWindow( XEvent* e );
@ -499,6 +528,9 @@ class Workspace : public QObject, public KDecorationDefines
void closeActivePopup();
void updateClientArea( bool force );
void finishCompositing();
bool windowRepaintsPending() const;
SystemTrayWindowList systemTrayWins;
@ -535,10 +567,12 @@ class Workspace : public QObject, public KDecorationDefines
ClientList clients;
ClientList desktops;
UnmanagedList unmanaged;
DeletedList deleted;
ClientList unconstrained_stacking_order; // topmost last
ClientList stacking_order; // topmost last
QVector< ClientList > focus_chain; // currently ative last
ClientList unconstrained_stacking_order;
ClientList stacking_order;
QVector< ClientList > focus_chain;
ClientList global_focus_chain; // this one is only for things like tabbox's MRU
ClientList should_get_focus; // last is most recent
ClientList attention_chain;
@ -572,6 +606,7 @@ class Workspace : public QObject, public KDecorationDefines
QMenu *popup;
QMenu *advanced_popup;
QMenu *trans_popup;
QMenu *desk_popup;
int desk_popup_index;
@ -655,12 +690,14 @@ class Workspace : public QObject, public KDecorationDefines
bool forced_global_mouse_grab;
friend class StackingUpdatesBlocker;
//kompmgr
KSelectionOwner* cm_selection;
QTimer compositeTimer;
QTime lastCompositePaint;
int compositeRate;
QRegion repaints_region;
Window overlay; // XComposite overlay window
QSlider *transSlider;
QPushButton *transButton;
private:
friend bool performTransiencyCheck();
};
// helper for Workspace::blockStackingUpdates() being called in pairs (true/false)
@ -803,6 +840,11 @@ inline bool Workspace::globalShortcutsDisabled() const
return global_shortcuts_disabled || global_shortcuts_disabled_for_client;
}
inline Window Workspace::overlayWindow()
{
return overlay;
}
template< typename T >
inline Client* Workspace::findClient( T predicate )
{
@ -830,7 +872,27 @@ inline void Workspace::forEachClient( T procedure )
return forEachClient( procedure, TruePredicate());
}
KWIN_COMPARE_PREDICATE( ClientMatchPredicate, const Client*, cl == value );
template< typename T >
inline Unmanaged* Workspace::findUnmanaged( T predicate )
{
return findUnmanagedInList( unmanaged, predicate );
}
template< typename T1, typename T2 >
inline void Workspace::forEachUnmanaged( T1 procedure, T2 predicate )
{
for ( UnmanagedList::ConstIterator it = unmanaged.begin(); it != unmanaged.end(); ++it)
if ( predicate( const_cast< const Unmanaged* >( *it)))
procedure( *it );
}
template< typename T >
inline void Workspace::forEachUnmanaged( T procedure )
{
return forEachUnmanaged( procedure, TruePredicate());
}
KWIN_COMPARE_PREDICATE( ClientMatchPredicate, Client, const Client*, cl == value );
inline bool Workspace::hasClient( const Client* c )
{
return findClient( ClientMatchPredicate( c ));