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