| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kwinmodule.cpp

    00001 /*
    00002     $Id: kwinmodule.cpp 367029 2004-11-29 00:18:01Z aseigo $
    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.findIndex( w ) != -1;
    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 old_current_desktop = currentDesktop();
    00170         WId old_active_window = activeWindow();
    00171         int old_number_of_desktops = numberOfDesktops();
    00172     int m = NETRootInfo::event( ev );
    00173
    00174     if (( m & CurrentDesktop ) && currentDesktop() != old_current_desktop )
    00175         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
    00176         emit (*mit)->currentDesktopChanged( currentDesktop() );
    00177     if (( m & ActiveWindow ) && activeWindow() != old_active_window )
    00178         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
    00179         emit (*mit)->activeWindowChanged( activeWindow() );
    00180     if ( m & DesktopNames )
    00181         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
    00182         emit (*mit)->desktopNamesChanged();
    00183     if (( m & NumberOfDesktops ) && numberOfDesktops() != old_number_of_desktops )
    00184         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
    00185         emit (*mit)->numberOfDesktopsChanged( numberOfDesktops() );
    00186     if ( m & WorkArea )
    00187         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
    00188         emit (*mit)->workAreaChanged();
    00189     if ( m & ClientListStacking ) {
    00190         updateStackingOrder();
    00191         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
    00192         emit (*mit)->stackingOrderChanged();
    00193     }
    00194     } else  if ( windows.findIndex( ev->xany.window ) != -1 ){
    00195     NETWinInfo ni( qt_xdisplay(), ev->xany.window, qt_xrootwin(), 0 );
    00196         unsigned long dirty[ 2 ];
    00197     ni.event( ev, dirty, 2 );
    00198     if ( ev->type ==PropertyNotify ) {
    00199             if( ev->xproperty.atom == XA_WM_HINTS )
    00200             dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMIcon; // support for old icons
    00201             else if( ev->xproperty.atom == XA_WM_NAME )
    00202                 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMName; // support for old name
    00203             else if( ev->xproperty.atom == XA_WM_ICON_NAME )
    00204                 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMIconName; // support for old iconic name
    00205         }
    00206     if ( (dirty[ NETWinInfo::PROTOCOLS ] & NET::WMStrut) != 0 ) {
    00207             removeStrutWindow( ev->xany.window );
    00208             if ( !possibleStrutWindows.findIndex( ev->xany.window ) != -1  )
    00209             possibleStrutWindows.append( ev->xany.window );
    00210     }
    00211     if ( dirty[ NETWinInfo::PROTOCOLS ] || dirty[ NETWinInfo::PROTOCOLS2 ] ) {
    00212         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit ) {
    00213         emit (*mit)->windowChanged( ev->xany.window );
    00214                 emit (*mit)->windowChanged( ev->xany.window, dirty );
    00215         emit (*mit)->windowChanged( ev->xany.window, dirty[ NETWinInfo::PROTOCOLS ] );
    00216         if ( (dirty[ NETWinInfo::PROTOCOLS ] & NET::WMStrut) != 0 )
    00217             emit (*mit)->strutChanged();
    00218         }
    00219     }
    00220     }
    00221
    00222     return false;
    00223 }
    00224
    00225 bool KWinModulePrivate::removeStrutWindow( WId w )
    00226 {
    00227     for( QValueList< StrutData >::Iterator it = strutWindows.begin();
    00228          it != strutWindows.end();
    00229          ++it )
    00230         if( (*it).window == w ) {
    00231             strutWindows.remove( it );
    00232             return true;
    00233         }
    00234     return false;
    00235 }
    00236
    00237 void KWinModulePrivate::updateStackingOrder()
    00238 {
    00239     stackingOrder.clear();
    00240     for ( int i = 0; i <  clientListStackingCount(); i++ )
    00241     stackingOrder.append( clientListStacking()[i] );
    00242 }
    00243
    00244 void KWinModulePrivate::addClient(Window w)
    00245 {
    00246     if ( (what >= KWinModule::INFO_WINDOWS) && !QWidget::find( w ) )
    00247     XSelectInput( qt_xdisplay(), w, PropertyChangeMask | StructureNotifyMask );
    00248     bool emit_strutChanged = false;
    00249     if( strutSignalConnected && modules.count() > 0 ) {
    00250         NETWinInfo info( qt_xdisplay(), w, qt_xrootwin(), NET::WMStrut | NET::WMDesktop );
    00251         NETStrut strut = info.strut();
    00252         if ( strut.left || strut.top || strut.right || strut.bottom ) {
    00253             strutWindows.append( StrutData( w, strut, info.desktop()));
    00254             emit_strutChanged = true;
    00255         }
    00256     } else
    00257         possibleStrutWindows.append( w );
    00258     windows.append( w );
    00259     for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit ) {
    00260     emit (*mit)->windowAdded( w );
    00261     if ( emit_strutChanged )
    00262         emit (*mit)->strutChanged();
    00263     }
    00264 }
    00265
    00266 void KWinModulePrivate::removeClient(Window w)
    00267 {
    00268     bool emit_strutChanged = removeStrutWindow( w );
    00269     if( strutSignalConnected && possibleStrutWindows.findIndex( w ) != -1 && modules.count() > 0 ) {
    00270         NETWinInfo info( qt_xdisplay(), w, qt_xrootwin(), NET::WMStrut );
    00271         NETStrut strut = info.strut();
    00272         if ( strut.left || strut.top || strut.right || strut.bottom ) {
    00273             emit_strutChanged = true;
    00274         }
    00275     }
    00276     possibleStrutWindows.remove( w );
    00277     windows.remove( w );
    00278     for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit ) {
    00279     emit (*mit)->windowRemoved( w );
    00280     if ( emit_strutChanged )
    00281         emit (*mit)->strutChanged();
    00282     }
    00283 }
    00284
    00285 void KWinModulePrivate::addSystemTrayWin(Window w)
    00286 {
    00287     systemTrayWindows.append( w );
    00288     for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
    00289     emit (*mit)->systemTrayWindowAdded( w );
    00290 }
    00291
    00292 void KWinModulePrivate::removeSystemTrayWin(Window w)
    00293 {
    00294     systemTrayWindows.remove( w );
    00295     for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
    00296     emit (*mit)->systemTrayWindowRemoved( w );
    00297 }
    00298
    00299 int KWinModule::currentDesktop() const
    00300 {
    00301     return d->currentDesktop();
    00302 }
    00303
    00304 int KWinModule::numberOfDesktops() const
    00305 {
    00306     return d->numberOfDesktops();
    00307 }
    00308
    00309 WId KWinModule::activeWindow() const
    00310 {
    00311     return d->activeWindow();
    00312 }
    00313
    00314 QRect KWinModule::workArea( int desktop ) const
    00315 {
    00316     int desk  = (desktop > 0 && desktop <= (int) d->numberOfDesktops() ) ? desktop : currentDesktop();
    00317     if ( desk <= 0 )
    00318     return QApplication::desktop()->geometry();
    00319     NETRect r = d->workArea( desk );
    00320     if( r.size.width <= 0 || r.size.height <= 0 ) // not set
    00321     return QApplication::desktop()->geometry();
    00322     return QRect( r.pos.x, r.pos.y, r.size.width, r.size.height );
    00323 }
    00324
    00325 QRect KWinModule::workArea( const QValueList<WId>& exclude, int desktop ) const
    00326 {
    00327     QRect all = QApplication::desktop()->geometry();
    00328     QRect a = all;
    00329
    00330     if (desktop == -1)
    00331     desktop = d->currentDesktop();
    00332
    00333     QValueList<WId>::ConstIterator it1;
    00334     for( it1 = d->windows.begin(); it1 != d->windows.end(); ++it1 ) {
    00335
    00336     if(exclude.findIndex(*it1) != -1) continue;
    00337
    00338 // Kicker (very) extensively calls this function, causing hundreds of roundtrips just
    00339 // to repeatedly find out struts of all windows. Therefore strut values for strut
    00340 // windows are cached here.
    00341         NETStrut strut;
    00342         QValueList< KWinModulePrivate::StrutData >::Iterator it2 = d->strutWindows.begin();
    00343         for( ;
    00344              it2 != d->strutWindows.end();
    00345              ++it2 )
    00346             if( (*it2).window == *it1 )
    00347                 break;
    00348         if( it2 != d->strutWindows.end()) {
    00349             if(!((*it2).desktop == desktop || (*it2).desktop == NETWinInfo::OnAllDesktops ))
    00350                 continue;
    00351             strut = (*it2).strut;
    00352         } else if( d->possibleStrutWindows.findIndex( *it1 ) != -1 ) {
    00353             NETWinInfo info( qt_xdisplay(), (*it1), qt_xrootwin(), NET::WMStrut | NET::WMDesktop);
    00354         strut = info.strut();
    00355             d->possibleStrutWindows.remove( *it1 );
    00356             d->strutWindows.append( KWinModulePrivate::StrutData( *it1, info.strut(), info.desktop()));
    00357         if(!(info.desktop() == desktop || info.desktop() == NETWinInfo::OnAllDesktops))
    00358                 continue;
    00359         } else
    00360             continue; // not a strut window
    00361
    00362     QRect r = all;
    00363     if ( strut.left > 0 )
    00364         r.setLeft( r.left() + (int) strut.left );
    00365     if ( strut.top > 0 )
    00366         r.setTop( r.top() + (int) strut.top );
    00367     if ( strut.right > 0  )
    00368         r.setRight( r.right() - (int) strut.right );
    00369     if ( strut.bottom > 0  )
    00370         r.setBottom( r.bottom() - (int) strut.bottom );
    00371
    00372     a = a.intersect(r);
    00373     }
    00374     return a;
    00375 }
    00376
    00377 void KWinModule::connectNotify( const char* signal )
    00378 {
    00379     if( !d->strutSignalConnected && qstrcmp( signal, SIGNAL(strutChanged())) == 0 )
    00380         d->strutSignalConnected = true;
    00381     QObject::connectNotify( signal );
    00382 }
    00383
    00384 QString KWinModule::desktopName( int desktop ) const
    00385 {
    00386     const char* name = d->desktopName( (desktop > 0 && desktop <= (int) d->numberOfDesktops() ) ? desktop : currentDesktop() );
    00387     if ( name && name[0] )
    00388     return QString::fromUtf8( name );
    00389     return i18n("Desktop %1").arg( desktop );
    00390 }
    00391
    00392 void KWinModule::setDesktopName( int desktop, const QString& name )
    00393 {
    00394     if (desktop <= 0 || desktop > (int) d->numberOfDesktops() )
    00395     desktop = currentDesktop();
    00396     d->setDesktopName( desktop, name.utf8().data() );
    00397 }
    00398
    00399
    00400 void KWinModule::doNotManage( const QString& title )
    00401 {
    00402     if ( !kapp->dcopClient()->isAttached() )
    00403     kapp->dcopClient()->attach();
    00404     QByteArray data, replyData;
    00405     QCString replyType;
    00406     QDataStream arg(data, IO_WriteOnly);
    00407     arg << title;
    00408     kapp->dcopClient()->call("kwin", "", "doNotManage(QString)",
    00409                  data, replyType, replyData);
    00410 }
    00411
    00412 #include "kwinmodule.moc"
    00413 #endif

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:12 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003