kdecore Library API Documentation

kwinmodule.cpp

00001 /*
00002     $Id: kwinmodule.cpp,v 1.62.2.1 2004/03/22 11:16:57 waba Exp $
00003 
00004     This file is part of the KDE libraries
00005     Copyright (C) 1999 Matthias Ettrich (ettrich@kde.org)
00006 
00007 
00008     This library is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU Library General Public
00010     License as published by the Free Software Foundation; either
00011     version 2 of the License, or (at your option) any later version.
00012 
00013     This library is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016     Library General Public License for more details.
00017 
00018     You should have received a copy of the GNU Library General Public License
00019     along with this library; see the file COPYING.LIB.  If not, write to
00020     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00021     Boston, MA 02111-1307, USA.
00022 */
00023 
00024 #include <qwidget.h>
00025 #ifdef Q_WS_X11 //FIXME
00026 #include "kwinmodule.h"
00027 #include "kwin.h"
00028 #include <X11/Xatom.h>
00029 #include "kapplication.h"
00030 #include "kdebug.h"
00031 #include <qtl.h>
00032 #include <qptrlist.h>
00033 #include <klocale.h>
00034 #include <dcopclient.h>
00035 #include "netwm.h"
00036 
00037 static KWinModulePrivate* static_d = 0;
00038 
00039 class KWinModulePrivate : public QWidget, public NETRootInfo
00040 {
00041 public:
00042     KWinModulePrivate(int _what)
00043     : QWidget(0,0), NETRootInfo( qt_xdisplay(),
00044                      ( _what >= KWinModule::INFO_WINDOWS ? 
00045                        (ClientList | ClientListStacking) : 0
00046                      ) |
00047                      NumberOfDesktops |
00048                      DesktopGeometry |
00049                      CurrentDesktop |
00050                      DesktopNames |
00051                      ActiveWindow |
00052                      WorkArea |
00053                      KDESystemTrayWindows,
00054                      -1, false
00055                      ),
00056           strutSignalConnected( false ),
00057           what( _what )
00058     {
00059     kapp->installX11EventFilter( this );
00060     (void ) kapp->desktop(); //trigger desktop widget creation to select root window events
00061         activate();
00062     updateStackingOrder();
00063     }
00064     ~KWinModulePrivate()
00065     {
00066     }
00067     QPtrList<KWinModule> modules;
00068 
00069     QValueList<WId> windows;
00070     QValueList<WId> stackingOrder;
00071     QValueList<WId> systemTrayWindows;
00072 
00073     struct StrutData
00074     {
00075         StrutData( WId window_, const NETStrut& strut_, int desktop_ )
00076             : window( window_ ), strut( strut_ ), desktop( desktop_ ) {};
00077         StrutData() {}; // for QValueList to be happy
00078         WId window;
00079         NETStrut strut;
00080         int desktop;
00081     };
00082     QValueList<StrutData> strutWindows;
00083     QValueList<WId> possibleStrutWindows;
00084     bool strutSignalConnected;
00085     int what;
00086 
00087     void addClient(Window);
00088     void removeClient(Window);
00089     void addSystemTrayWin(Window);
00090     void removeSystemTrayWin(Window);
00091 
00092     bool x11Event( XEvent * ev );
00093 
00094     void updateStackingOrder();
00095     bool removeStrutWindow( WId );
00096 };
00097 
00098 
00099 KWinModule::KWinModule( QObject* parent )
00100     : QObject( parent, "kwin_module" )
00101 {
00102     init(INFO_ALL);
00103 }
00104 
00105 KWinModule::KWinModule( QObject* parent, int what )
00106     : QObject( parent, "kwin_module" )
00107 {
00108     init(what);
00109 }
00110 
00111 void KWinModule::init(int what)
00112 {
00113     if (what >= INFO_WINDOWS)
00114        what = INFO_WINDOWS;
00115     else
00116        what = INFO_DESKTOP;
00117 
00118     if ( !static_d )
00119     {
00120         static_d = new KWinModulePrivate(what);
00121     }
00122     else if (static_d->what < what)
00123     {
00124         QPtrList<KWinModule> modules = static_d->modules;
00125         delete static_d;
00126         static_d = new KWinModulePrivate(what);
00127         static_d->modules = modules;
00128         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00129             (*mit)->d = static_d;
00130     }
00131     
00132     d = static_d;
00133     d->modules.append( this );
00134 }
00135 
00136 KWinModule::~KWinModule()
00137 {
00138     d->modules.removeRef( this );
00139     if ( d->modules.isEmpty() ) {
00140     delete d;
00141     static_d = 0;
00142     }
00143 }
00144 
00145 const QValueList<WId>& KWinModule::windows() const
00146 {
00147     return d->windows;
00148 }
00149 
00150 const QValueList<WId>& KWinModule::stackingOrder() const
00151 {
00152     return d->stackingOrder;
00153 }
00154 
00155 
00156 bool KWinModule::hasWId(WId w) const
00157 {
00158     return d->windows.contains( w );
00159 }
00160 
00161 const QValueList<WId>& KWinModule::systemTrayWindows() const
00162 {
00163     return d->systemTrayWindows;
00164 }
00165 
00166 bool KWinModulePrivate::x11Event( XEvent * ev )
00167 {
00168     if ( ev->xany.window == qt_xrootwin() ) {
00169     int m = NETRootInfo::event( ev );
00170 
00171     if ( m & CurrentDesktop )
00172         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00173         emit (*mit)->currentDesktopChanged( currentDesktop() );
00174     if ( m & ActiveWindow )
00175         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00176         emit (*mit)->activeWindowChanged( activeWindow() );
00177     if ( m & DesktopNames )
00178         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00179         emit (*mit)->desktopNamesChanged();
00180     if ( m & NumberOfDesktops )
00181         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00182         emit (*mit)->numberOfDesktopsChanged( numberOfDesktops() );
00183     if ( m & WorkArea )
00184         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00185         emit (*mit)->workAreaChanged();
00186     if ( m & ClientListStacking ) {
00187         updateStackingOrder();
00188         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00189         emit (*mit)->stackingOrderChanged();
00190     }
00191     } else  if ( windows.contains( ev->xany.window ) ){
00192     NETWinInfo ni( qt_xdisplay(), ev->xany.window, qt_xrootwin(), 0 );
00193         unsigned long dirty[ 2 ];
00194     ni.event( ev, dirty, 2 );
00195     if ( ev->type ==PropertyNotify ) {
00196             if( ev->xproperty.atom == XA_WM_HINTS )
00197             dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMIcon; // support for old icons
00198             else if( ev->xproperty.atom == XA_WM_NAME )
00199                 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMName; // support for old name
00200             else if( ev->xproperty.atom == XA_WM_ICON_NAME )
00201                 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMIconName; // support for old iconic name
00202         }
00203     if ( (dirty[ NETWinInfo::PROTOCOLS ] & NET::WMStrut) != 0 ) {
00204             removeStrutWindow( ev->xany.window );
00205             if ( !possibleStrutWindows.contains( ev->xany.window )  )
00206             possibleStrutWindows.append( ev->xany.window );
00207     }
00208     if ( dirty[ NETWinInfo::PROTOCOLS ] || dirty[ NETWinInfo::PROTOCOLS2 ] ) {
00209         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit ) {
00210         emit (*mit)->windowChanged( ev->xany.window );
00211                 emit (*mit)->windowChanged( ev->xany.window, dirty );
00212         emit (*mit)->windowChanged( ev->xany.window, dirty[ NETWinInfo::PROTOCOLS ] );
00213         if ( (dirty[ NETWinInfo::PROTOCOLS ] & NET::WMStrut) != 0 )
00214             emit (*mit)->strutChanged();
00215         }
00216     }
00217     }
00218 
00219     return false;
00220 }
00221 
00222 bool KWinModulePrivate::removeStrutWindow( WId w )
00223 {
00224     for( QValueList< StrutData >::Iterator it = strutWindows.begin();
00225          it != strutWindows.end();
00226          ++it )
00227         if( (*it).window == w ) {
00228             strutWindows.remove( it );
00229             return true;
00230         }
00231     return false;
00232 }
00233 
00234 void KWinModulePrivate::updateStackingOrder()
00235 {
00236     stackingOrder.clear();
00237     for ( int i = 0; i <  clientListStackingCount(); i++ )
00238     stackingOrder.append( clientListStacking()[i] );
00239 }
00240 
00241 void KWinModulePrivate::addClient(Window w)
00242 {
00243     if ( (what >= KWinModule::INFO_WINDOWS) && !QWidget::find( w ) )
00244     XSelectInput( qt_xdisplay(), w, PropertyChangeMask | StructureNotifyMask );
00245     bool emit_strutChanged = false;
00246     if( strutSignalConnected && modules.count() > 0 ) {
00247         NETWinInfo info( qt_xdisplay(), w, qt_xrootwin(), NET::WMStrut | NET::WMDesktop );
00248         NETStrut strut = info.strut();
00249         if ( strut.left || strut.top || strut.right || strut.bottom ) {
00250             strutWindows.append( StrutData( w, strut, info.desktop()));
00251             emit_strutChanged = true;
00252         }
00253     } else
00254         possibleStrutWindows.append( w );
00255     windows.append( w );
00256     for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit ) {
00257     emit (*mit)->windowAdded( w );
00258     if ( emit_strutChanged )
00259         emit (*mit)->strutChanged();
00260     }
00261 }
00262 
00263 void KWinModulePrivate::removeClient(Window w)
00264 {
00265     bool emit_strutChanged = removeStrutWindow( w );
00266     if( strutSignalConnected && possibleStrutWindows.contains( w ) && modules.count() > 0 ) {
00267         NETWinInfo info( qt_xdisplay(), w, qt_xrootwin(), NET::WMStrut );
00268         NETStrut strut = info.strut();
00269         if ( strut.left || strut.top || strut.right || strut.bottom ) {
00270             emit_strutChanged = true;
00271         }
00272     }
00273     possibleStrutWindows.remove( w );
00274     windows.remove( w );
00275     for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit ) {
00276     emit (*mit)->windowRemoved( w );
00277     if ( emit_strutChanged )
00278         emit (*mit)->strutChanged();
00279     }
00280 }
00281 
00282 void KWinModulePrivate::addSystemTrayWin(Window w)
00283 {
00284     systemTrayWindows.append( w );
00285     for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00286     emit (*mit)->systemTrayWindowAdded( w );
00287 }
00288 
00289 void KWinModulePrivate::removeSystemTrayWin(Window w)
00290 {
00291     systemTrayWindows.remove( w );
00292     for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00293     emit (*mit)->systemTrayWindowRemoved( w );
00294 }
00295 
00296 int KWinModule::currentDesktop() const
00297 {
00298     return d->currentDesktop();
00299 }
00300 
00301 int KWinModule::numberOfDesktops() const
00302 {
00303     return d->numberOfDesktops();
00304 }
00305 
00306 WId KWinModule::activeWindow() const
00307 {
00308     return d->activeWindow();
00309 }
00310 
00311 QRect KWinModule::workArea( int desktop ) const
00312 {
00313     int desk  = (desktop > 0 && desktop <= (int) d->numberOfDesktops() ) ? desktop : currentDesktop();
00314     if ( desk <= 0 )
00315     return QApplication::desktop()->geometry();
00316     NETRect r = d->workArea( desk );
00317     return QRect( r.pos.x, r.pos.y, r.size.width, r.size.height );
00318 }
00319 
00320 QRect KWinModule::workArea( const QValueList<WId>& exclude, int desktop ) const
00321 {
00322     QRect all = QApplication::desktop()->geometry();
00323     QRect a = all;
00324 
00325     if (desktop == -1)
00326     desktop = d->currentDesktop();
00327 
00328     QValueList<WId>::ConstIterator it1;
00329     for( it1 = d->windows.begin(); it1 != d->windows.end(); ++it1 ) {
00330 
00331     if(exclude.contains(*it1) > 0) continue;
00332         
00333 // Kicker (very) extensively calls this function, causing hundreds of roundtrips just
00334 // to repeatedly find out struts of all windows. Therefore strut values for strut
00335 // windows are cached here.
00336         NETStrut strut;
00337         QValueList< KWinModulePrivate::StrutData >::Iterator it2 = d->strutWindows.begin();
00338         for( ;
00339              it2 != d->strutWindows.end();
00340              ++it2 )
00341             if( (*it2).window == *it1 )
00342                 break;
00343         if( it2 != d->strutWindows.end()) {
00344             if(!((*it2).desktop == desktop || (*it2).desktop == NETWinInfo::OnAllDesktops ))
00345                 continue;
00346             strut = (*it2).strut;
00347         } else if( d->possibleStrutWindows.contains( *it1 )) {
00348             NETWinInfo info( qt_xdisplay(), (*it1), qt_xrootwin(), NET::WMStrut | NET::WMDesktop);
00349         strut = info.strut();
00350             d->possibleStrutWindows.remove( *it1 );
00351             d->strutWindows.append( KWinModulePrivate::StrutData( *it1, info.strut(), info.desktop()));
00352         if(!(info.desktop() == desktop || info.desktop() == NETWinInfo::OnAllDesktops))
00353                 continue;
00354         } else
00355             continue; // not a strut window
00356 
00357     QRect r = all;
00358     if ( strut.left > 0 )
00359         r.setLeft( r.left() + (int) strut.left );
00360     if ( strut.top > 0 )
00361         r.setTop( r.top() + (int) strut.top );
00362     if ( strut.right > 0  )
00363         r.setRight( r.right() - (int) strut.right );
00364     if ( strut.bottom > 0  )
00365         r.setBottom( r.bottom() - (int) strut.bottom );
00366 
00367     a = a.intersect(r);
00368     }
00369     return a;
00370 }
00371 
00372 void KWinModule::connectNotify( const char* signal )
00373 {
00374     if( !d->strutSignalConnected && qstrcmp( signal, SIGNAL(strutChanged())) == 0 )
00375         d->strutSignalConnected = true;
00376     QObject::connectNotify( signal );
00377 }
00378 
00379 QString KWinModule::desktopName( int desktop ) const
00380 {
00381     const char* name = d->desktopName( (desktop > 0 && desktop <= (int) d->numberOfDesktops() ) ? desktop : currentDesktop() );
00382     if ( name && name[0] )
00383     return QString::fromUtf8( name );
00384     return i18n("Desktop %1").arg( desktop );
00385 }
00386 
00387 void KWinModule::setDesktopName( int desktop, const QString& name )
00388 {
00389     if (desktop <= 0 || desktop > (int) d->numberOfDesktops() )
00390     desktop = currentDesktop();
00391     d->setDesktopName( desktop, name.utf8().data() );
00392 }
00393 
00394 
00395 void KWinModule::doNotManage( const QString& title )
00396 {
00397     if ( !kapp->dcopClient()->isAttached() )
00398     kapp->dcopClient()->attach();
00399     QByteArray data, replyData;
00400     QCString replyType;
00401     QDataStream arg(data, IO_WriteOnly);
00402     arg << title;
00403     kapp->dcopClient()->call("kwin", "", "doNotManage(QString)",
00404                  data, replyType, replyData);
00405 }
00406 
00407 #include "kwinmodule.moc"
00408 #endif
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Jan 21 09:57:11 2005 by doxygen 1.3.6 written by Dimitri van Heesch, © 1997-2003