• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

kwinmodule.cpp

Go to the documentation of this file.
00001 /*
00002     $Id: kwinmodule.cpp 629176 2007-02-01 18:55:16Z dfaure $
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., 51 Franklin Street, Fifth Floor,
00021     Boston, MA 02110-1301, 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 static unsigned long windows_properties[ 2 ] = { NET::ClientList | NET::ClientListStacking |
00040                      NET::NumberOfDesktops |
00041                      NET::DesktopGeometry |
00042                                      NET::DesktopViewport |
00043                      NET::CurrentDesktop |
00044                      NET::DesktopNames |
00045                      NET::ActiveWindow |
00046                      NET::WorkArea |
00047                      NET::KDESystemTrayWindows,
00048                                      NET::WM2ShowingDesktop };
00049 
00050 static unsigned long desktop_properties[ 2 ] = { 
00051                      NET::NumberOfDesktops |
00052                      NET::DesktopGeometry |
00053                                      NET::DesktopViewport |
00054                      NET::CurrentDesktop |
00055                      NET::DesktopNames |
00056                      NET::ActiveWindow |
00057                      NET::WorkArea |
00058                      NET::KDESystemTrayWindows,
00059                                      NET::WM2ShowingDesktop };
00060 
00061 class KWinModulePrivate : public QWidget, public NETRootInfo4
00062 {
00063 public:
00064     KWinModulePrivate(int _what)
00065     : QWidget(0,0), NETRootInfo4( qt_xdisplay(),
00066                                      _what >= KWinModule::INFO_WINDOWS ?
00067                                      windows_properties : desktop_properties,
00068                                      2,
00069                      -1, false
00070                      ),
00071           strutSignalConnected( false ),
00072           what( _what )
00073     {
00074     kapp->installX11EventFilter( this );
00075     (void ) kapp->desktop(); //trigger desktop widget creation to select root window events
00076         activate();
00077     updateStackingOrder();
00078     }
00079     ~KWinModulePrivate()
00080     {
00081     }
00082     QPtrList<KWinModule> modules;
00083 
00084     QValueList<WId> windows;
00085     QValueList<WId> stackingOrder;
00086     QValueList<WId> systemTrayWindows;
00087 
00088     struct StrutData
00089     {
00090         StrutData( WId window_, const NETStrut& strut_, int desktop_ )
00091             : window( window_ ), strut( strut_ ), desktop( desktop_ ) {};
00092         StrutData() {}; // for QValueList to be happy
00093         WId window;
00094         NETStrut strut;
00095         int desktop;
00096     };
00097     QValueList<StrutData> strutWindows;
00098     QValueList<WId> possibleStrutWindows;
00099     bool strutSignalConnected;
00100     int what;
00101 
00102     void addClient(Window);
00103     void removeClient(Window);
00104     void addSystemTrayWin(Window);
00105     void removeSystemTrayWin(Window);
00106 
00107     bool x11Event( XEvent * ev );
00108 
00109     void updateStackingOrder();
00110     bool removeStrutWindow( WId );
00111 
00112     QSize numberOfViewports(int desktop) const;
00113     QPoint currentViewport(int desktop) const;
00114 };
00115 
00116 KWinModule::KWinModule( QObject* parent )
00117     : QObject( parent, "kwin_module" )
00118 {
00119     init(INFO_ALL);
00120 }
00121 
00122 KWinModule::KWinModule( QObject* parent, int what )
00123     : QObject( parent, "kwin_module" )
00124 {
00125     init(what);
00126 }
00127 
00128 void KWinModule::init(int what)
00129 {
00130     if (what >= INFO_WINDOWS)
00131        what = INFO_WINDOWS;
00132     else
00133        what = INFO_DESKTOP;
00134 
00135     if ( !static_d )
00136     {
00137         static_d = new KWinModulePrivate(what);
00138     }
00139     else if (static_d->what < what)
00140     {
00141         QPtrList<KWinModule> modules = static_d->modules;
00142         delete static_d;
00143         static_d = new KWinModulePrivate(what);
00144         static_d->modules = modules;
00145         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00146             (*mit)->d = static_d;
00147     }
00148     
00149     d = static_d;
00150     d->modules.append( this );
00151 }
00152 
00153 KWinModule::~KWinModule()
00154 {
00155     d->modules.removeRef( this );
00156     if ( d->modules.isEmpty() ) {
00157     delete d;
00158     static_d = 0;
00159     }
00160 }
00161 
00162 const QValueList<WId>& KWinModule::windows() const
00163 {
00164     return d->windows;
00165 }
00166 
00167 const QValueList<WId>& KWinModule::stackingOrder() const
00168 {
00169     return d->stackingOrder;
00170 }
00171 
00172 
00173 bool KWinModule::hasWId(WId w) const
00174 {
00175     return d->windows.findIndex( w ) != -1;
00176 }
00177 
00178 const QValueList<WId>& KWinModule::systemTrayWindows() const
00179 {
00180     return d->systemTrayWindows;
00181 }
00182 
00183 QSize KWinModulePrivate::numberOfViewports(int desktop) const
00184 {
00185     NETSize netdesktop = desktopGeometry(desktop);
00186     QSize s(netdesktop.width / QApplication::desktop()->width(),
00187             netdesktop.height / QApplication::desktop()->height());
00188 
00189     // workaround some kwin bugs
00190     if (s.width() < 1) s.setWidth(1);
00191     if (s.height() < 1) s.setHeight(1);
00192     return s;
00193 }
00194 
00195 QPoint KWinModulePrivate::currentViewport(int desktop) const
00196 {
00197     NETPoint netviewport = desktopViewport(desktop);
00198 
00199     return QPoint(1+(netviewport.x / QApplication::desktop()->width()),
00200             1+(netviewport.y / QApplication::desktop()->height()));
00201 }
00202 
00203 bool KWinModulePrivate::x11Event( XEvent * ev )
00204 {
00205     if ( ev->xany.window == qt_xrootwin() ) {
00206         int old_current_desktop = currentDesktop();
00207         WId old_active_window = activeWindow();
00208         int old_number_of_desktops = numberOfDesktops();
00209         bool old_showing_desktop = showingDesktop();
00210         unsigned long m[ 5 ];
00211     NETRootInfo::event( ev, m, 5 );
00212 
00213     if (( m[ PROTOCOLS ] & CurrentDesktop ) && currentDesktop() != old_current_desktop )
00214         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00215         emit (*mit)->currentDesktopChanged( currentDesktop() );
00216     if (( m[ PROTOCOLS ] & ActiveWindow ) && activeWindow() != old_active_window )
00217         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00218         emit (*mit)->activeWindowChanged( activeWindow() );
00219     if ( m[ PROTOCOLS ] & DesktopViewport ) {
00220         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00221         emit (*mit)->currentDesktopViewportChanged(currentDesktop(),
00222                         currentViewport(currentDesktop()));
00223         }
00224     if ( m[ PROTOCOLS ] & DesktopGeometry ) {
00225         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00226         emit (*mit)->desktopGeometryChanged(currentDesktop());
00227     }
00228     if ( m[ PROTOCOLS ] & DesktopNames )
00229         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00230         emit (*mit)->desktopNamesChanged();
00231     if (( m[ PROTOCOLS ] & NumberOfDesktops ) && numberOfDesktops() != old_number_of_desktops )
00232         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00233         emit (*mit)->numberOfDesktopsChanged( numberOfDesktops() );
00234     if ( m[ PROTOCOLS ] & WorkArea )
00235         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00236         emit (*mit)->workAreaChanged();
00237     if ( m[ PROTOCOLS ] & ClientListStacking ) {
00238         updateStackingOrder();
00239         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00240         emit (*mit)->stackingOrderChanged();
00241     }
00242         if(( m[ PROTOCOLS2 ] & WM2ShowingDesktop ) && showingDesktop() != old_showing_desktop ) {
00243         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00244         emit (*mit)->showingDesktopChanged( showingDesktop());
00245         }
00246     } else  if ( windows.findIndex( ev->xany.window ) != -1 ){
00247     NETWinInfo ni( qt_xdisplay(), ev->xany.window, qt_xrootwin(), 0 );
00248         unsigned long dirty[ 2 ];
00249     ni.event( ev, dirty, 2 );
00250     if ( ev->type ==PropertyNotify ) {
00251             if( ev->xproperty.atom == XA_WM_HINTS )
00252             dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMIcon; // support for old icons
00253             else if( ev->xproperty.atom == XA_WM_NAME )
00254                 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMName; // support for old name
00255             else if( ev->xproperty.atom == XA_WM_ICON_NAME )
00256                 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMIconName; // support for old iconic name
00257         }
00258     if ( (dirty[ NETWinInfo::PROTOCOLS ] & NET::WMStrut) != 0 ) {
00259             removeStrutWindow( ev->xany.window );
00260             if ( possibleStrutWindows.findIndex( ev->xany.window ) == -1 )
00261             possibleStrutWindows.append( ev->xany.window );
00262     }
00263     if ( dirty[ NETWinInfo::PROTOCOLS ] || dirty[ NETWinInfo::PROTOCOLS2 ] ) {
00264         for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit ) {
00265         emit (*mit)->windowChanged( ev->xany.window );
00266                 emit (*mit)->windowChanged( ev->xany.window, dirty );
00267         emit (*mit)->windowChanged( ev->xany.window, dirty[ NETWinInfo::PROTOCOLS ] );
00268         if ( (dirty[ NETWinInfo::PROTOCOLS ] & NET::WMStrut) != 0 )
00269             emit (*mit)->strutChanged();
00270         }
00271     }
00272     }
00273 
00274     return false;
00275 }
00276 
00277 bool KWinModulePrivate::removeStrutWindow( WId w )
00278 {
00279     for( QValueList< StrutData >::Iterator it = strutWindows.begin();
00280          it != strutWindows.end();
00281          ++it )
00282         if( (*it).window == w ) {
00283             strutWindows.remove( it );
00284             return true;
00285         }
00286     return false;
00287 }
00288 
00289 void KWinModulePrivate::updateStackingOrder()
00290 {
00291     stackingOrder.clear();
00292     for ( int i = 0; i <  clientListStackingCount(); i++ )
00293     stackingOrder.append( clientListStacking()[i] );
00294 }
00295 
00296 void KWinModulePrivate::addClient(Window w)
00297 {
00298     if ( (what >= KWinModule::INFO_WINDOWS) && !QWidget::find( w ) )
00299     XSelectInput( qt_xdisplay(), w, PropertyChangeMask | StructureNotifyMask );
00300     bool emit_strutChanged = false;
00301     if( strutSignalConnected && modules.count() > 0 ) {
00302         NETWinInfo info( qt_xdisplay(), w, qt_xrootwin(), NET::WMStrut | NET::WMDesktop );
00303         NETStrut strut = info.strut();
00304         if ( strut.left || strut.top || strut.right || strut.bottom ) {
00305             strutWindows.append( StrutData( w, strut, info.desktop()));
00306             emit_strutChanged = true;
00307         }
00308     } else
00309         possibleStrutWindows.append( w );
00310     windows.append( w );
00311     for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit ) {
00312     emit (*mit)->windowAdded( w );
00313     if ( emit_strutChanged )
00314         emit (*mit)->strutChanged();
00315     }
00316 }
00317 
00318 void KWinModulePrivate::removeClient(Window w)
00319 {
00320     bool emit_strutChanged = removeStrutWindow( w );
00321     if( strutSignalConnected && possibleStrutWindows.findIndex( w ) != -1 && modules.count() > 0 ) {
00322         NETWinInfo info( qt_xdisplay(), w, qt_xrootwin(), NET::WMStrut );
00323         NETStrut strut = info.strut();
00324         if ( strut.left || strut.top || strut.right || strut.bottom ) {
00325             emit_strutChanged = true;
00326         }
00327     }
00328     possibleStrutWindows.remove( w );
00329     windows.remove( w );
00330     for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit ) {
00331     emit (*mit)->windowRemoved( w );
00332     if ( emit_strutChanged )
00333         emit (*mit)->strutChanged();
00334     }
00335 }
00336 
00337 void KWinModulePrivate::addSystemTrayWin(Window w)
00338 {
00339     systemTrayWindows.append( w );
00340     for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00341     emit (*mit)->systemTrayWindowAdded( w );
00342 }
00343 
00344 void KWinModulePrivate::removeSystemTrayWin(Window w)
00345 {
00346     systemTrayWindows.remove( w );
00347     for ( QPtrListIterator<KWinModule> mit( modules ); mit.current(); ++mit )
00348     emit (*mit)->systemTrayWindowRemoved( w );
00349 }
00350 
00351 int KWinModule::currentDesktop() const
00352 {
00353     return d->currentDesktop();
00354 }
00355 
00356 int KWinModule::numberOfDesktops() const
00357 {
00358     return d->numberOfDesktops();
00359 }
00360 
00361 QSize KWinModule::numberOfViewports(int desktop) const
00362 {
00363     return d->numberOfViewports(desktop);
00364 }
00365 
00366 QPoint KWinModule::currentViewport(int desktop) const
00367 {
00368     return d->currentViewport(desktop);
00369 }
00370 
00371 WId KWinModule::activeWindow() const
00372 {
00373     return d->activeWindow();
00374 }
00375 
00376 bool KWinModule::showingDesktop() const
00377 {
00378     return d->showingDesktop();
00379 }
00380 
00381 QRect KWinModule::workArea( int desktop ) const
00382 {
00383     int desk  = (desktop > 0 && desktop <= (int) d->numberOfDesktops() ) ? desktop : currentDesktop();
00384     if ( desk <= 0 )
00385     return QApplication::desktop()->geometry();
00386     NETRect r = d->workArea( desk );
00387     if( r.size.width <= 0 || r.size.height <= 0 ) // not set
00388     return QApplication::desktop()->geometry();
00389     return QRect( r.pos.x, r.pos.y, r.size.width, r.size.height );
00390 }
00391 
00392 QRect KWinModule::workArea( const QValueList<WId>& exclude, int desktop ) const
00393 {
00394     QRect all = QApplication::desktop()->geometry();
00395     QRect a = all;
00396 
00397     if (desktop == -1)
00398     desktop = d->currentDesktop();
00399 
00400     QValueList<WId>::ConstIterator it1;
00401     for( it1 = d->windows.begin(); it1 != d->windows.end(); ++it1 ) {
00402 
00403     if(exclude.findIndex(*it1) != -1) continue;
00404         
00405 // Kicker (very) extensively calls this function, causing hundreds of roundtrips just
00406 // to repeatedly find out struts of all windows. Therefore strut values for strut
00407 // windows are cached here.
00408         NETStrut strut;
00409         QValueList< KWinModulePrivate::StrutData >::Iterator it2 = d->strutWindows.begin();
00410         for( ;
00411              it2 != d->strutWindows.end();
00412              ++it2 )
00413             if( (*it2).window == *it1 )
00414                 break;
00415         if( it2 != d->strutWindows.end()) {
00416             if(!((*it2).desktop == desktop || (*it2).desktop == NETWinInfo::OnAllDesktops ))
00417                 continue;
00418             strut = (*it2).strut;
00419         } else if( d->possibleStrutWindows.findIndex( *it1 ) != -1 ) {
00420             NETWinInfo info( qt_xdisplay(), (*it1), qt_xrootwin(), NET::WMStrut | NET::WMDesktop);
00421         strut = info.strut();
00422             d->possibleStrutWindows.remove( *it1 );
00423             d->strutWindows.append( KWinModulePrivate::StrutData( *it1, info.strut(), info.desktop()));
00424         if(!(info.desktop() == desktop || info.desktop() == NETWinInfo::OnAllDesktops))
00425                 continue;
00426         } else
00427             continue; // not a strut window
00428 
00429     QRect r = all;
00430     if ( strut.left > 0 )
00431         r.setLeft( r.left() + (int) strut.left );
00432     if ( strut.top > 0 )
00433         r.setTop( r.top() + (int) strut.top );
00434     if ( strut.right > 0  )
00435         r.setRight( r.right() - (int) strut.right );
00436     if ( strut.bottom > 0  )
00437         r.setBottom( r.bottom() - (int) strut.bottom );
00438 
00439     a = a.intersect(r);
00440     }
00441     return a;
00442 }
00443 
00444 void KWinModule::connectNotify( const char* signal )
00445 {
00446     if( !d->strutSignalConnected && qstrcmp( signal, SIGNAL(strutChanged())) == 0 )
00447         d->strutSignalConnected = true;
00448     QObject::connectNotify( signal );
00449 }
00450 
00451 QString KWinModule::desktopName( int desktop ) const
00452 {
00453     const char* name = d->desktopName( (desktop > 0 && desktop <= (int) d->numberOfDesktops() ) ? desktop : currentDesktop() );
00454     if ( name && name[0] )
00455     return QString::fromUtf8( name );
00456     return i18n("Desktop %1").arg( desktop );
00457 }
00458 
00459 void KWinModule::setDesktopName( int desktop, const QString& name )
00460 {
00461     if (desktop <= 0 || desktop > (int) d->numberOfDesktops() )
00462     desktop = currentDesktop();
00463     d->setDesktopName( desktop, name.utf8().data() );
00464 }
00465 
00466 
00467 void KWinModule::doNotManage( const QString& title )
00468 {
00469     if ( !kapp->dcopClient()->isAttached() )
00470     kapp->dcopClient()->attach();
00471     QByteArray data, replyData;
00472     QCString replyType;
00473     QDataStream arg(data, IO_WriteOnly);
00474     arg << title;
00475     kapp->dcopClient()->call("kwin", "", "doNotManage(QString)",
00476                  data, replyType, replyData);
00477 }
00478 
00479 #include "kwinmodule.moc"
00480 #endif

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal