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 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;
00201
else if( ev->xproperty.atom == XA_WM_NAME )
00202 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMName;
00203
else if( ev->xproperty.atom == XA_WM_ICON_NAME )
00204 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMIconName;
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
if( r.
size.
width <= 0 || r.
size.
height <= 0 )
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.contains(*it1) > 0)
continue;
00337
00338
00339
00340
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.contains( *it1 )) {
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;
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