kdecore Library API Documentation

kwinmodule.cpp

00001 /* 00002 $Id: kwinmodule.cpp,v 1.62.2.2 2004/04/19 16:10:50 lunakl 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 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.contains( ev->xany.window ) ){ 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.contains( ev->xany.window ) ) 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.contains( w ) && 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 return QRect( r.pos.x, r.pos.y, r.size.width, r.size.height ); 00321 } 00322 00323 QRect KWinModule::workArea( const QValueList<WId>& exclude, int desktop ) const 00324 { 00325 QRect all = QApplication::desktop()->geometry(); 00326 QRect a = all; 00327 00328 if (desktop == -1) 00329 desktop = d->currentDesktop(); 00330 00331 QValueList<WId>::ConstIterator it1; 00332 for( it1 = d->windows.begin(); it1 != d->windows.end(); ++it1 ) { 00333 00334 if(exclude.contains(*it1) > 0) continue; 00335 00336 // Kicker (very) extensively calls this function, causing hundreds of roundtrips just 00337 // to repeatedly find out struts of all windows. Therefore strut values for strut 00338 // windows are cached here. 00339 NETStrut strut; 00340 QValueList< KWinModulePrivate::StrutData >::Iterator it2 = d->strutWindows.begin(); 00341 for( ; 00342 it2 != d->strutWindows.end(); 00343 ++it2 ) 00344 if( (*it2).window == *it1 ) 00345 break; 00346 if( it2 != d->strutWindows.end()) { 00347 if(!((*it2).desktop == desktop || (*it2).desktop == NETWinInfo::OnAllDesktops )) 00348 continue; 00349 strut = (*it2).strut; 00350 } else if( d->possibleStrutWindows.contains( *it1 )) { 00351 NETWinInfo info( qt_xdisplay(), (*it1), qt_xrootwin(), NET::WMStrut | NET::WMDesktop); 00352 strut = info.strut(); 00353 d->possibleStrutWindows.remove( *it1 ); 00354 d->strutWindows.append( KWinModulePrivate::StrutData( *it1, info.strut(), info.desktop())); 00355 if(!(info.desktop() == desktop || info.desktop() == NETWinInfo::OnAllDesktops)) 00356 continue; 00357 } else 00358 continue; // not a strut window 00359 00360 QRect r = all; 00361 if ( strut.left > 0 ) 00362 r.setLeft( r.left() + (int) strut.left ); 00363 if ( strut.top > 0 ) 00364 r.setTop( r.top() + (int) strut.top ); 00365 if ( strut.right > 0 ) 00366 r.setRight( r.right() - (int) strut.right ); 00367 if ( strut.bottom > 0 ) 00368 r.setBottom( r.bottom() - (int) strut.bottom ); 00369 00370 a = a.intersect(r); 00371 } 00372 return a; 00373 } 00374 00375 void KWinModule::connectNotify( const char* signal ) 00376 { 00377 if( !d->strutSignalConnected && qstrcmp( signal, SIGNAL(strutChanged())) == 0 ) 00378 d->strutSignalConnected = true; 00379 QObject::connectNotify( signal ); 00380 } 00381 00382 QString KWinModule::desktopName( int desktop ) const 00383 { 00384 const char* name = d->desktopName( (desktop > 0 && desktop <= (int) d->numberOfDesktops() ) ? desktop : currentDesktop() ); 00385 if ( name && name[0] ) 00386 return QString::fromUtf8( name ); 00387 return i18n("Desktop %1").arg( desktop ); 00388 } 00389 00390 void KWinModule::setDesktopName( int desktop, const QString& name ) 00391 { 00392 if (desktop <= 0 || desktop > (int) d->numberOfDesktops() ) 00393 desktop = currentDesktop(); 00394 d->setDesktopName( desktop, name.utf8().data() ); 00395 } 00396 00397 00398 void KWinModule::doNotManage( const QString& title ) 00399 { 00400 if ( !kapp->dcopClient()->isAttached() ) 00401 kapp->dcopClient()->attach(); 00402 QByteArray data, replyData; 00403 QCString replyType; 00404 QDataStream arg(data, IO_WriteOnly); 00405 arg << title; 00406 kapp->dcopClient()->call("kwin", "", "doNotManage(QString)", 00407 data, replyType, replyData); 00408 } 00409 00410 #include "kwinmodule.moc" 00411 #endif
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 20 09:48:27 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003