00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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();
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() {};
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;
00198 else if( ev->xproperty.atom == XA_WM_NAME )
00199 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMName;
00200 else if( ev->xproperty.atom == XA_WM_ICON_NAME )
00201 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMIconName;
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
00334
00335
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;
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