00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "kwindowinfo.h"
00023 #include "kwindowsystem.h"
00024
00025 #include <kiconloader.h>
00026 #include <klocale.h>
00027 #include <kuniqueapplication.h>
00028 #include <kdebug.h>
00029 #include <kxerrorhandler.h>
00030 #include <netwm.h>
00031 #include <QtGui/QBitmap>
00032 #include <QDesktopWidget>
00033 #include <QtGui/QDialog>
00034 #include <QtDBus/QtDBus>
00035 #include <QtGui/QX11Info>
00036 #include <X11/Xatom.h>
00037
00038 struct KWindowInfo::Private
00039 {
00040 Private()
00041 : info( NULL )
00042 {}
00043 ~Private() { delete info; }
00044 NETWinInfo* info;
00045 WId win_;
00046 QString name_;
00047 QString iconic_name_;
00048 QRect geometry_;
00049 QRect frame_geometry_;
00050 int ref;
00051 bool valid;
00052 private:
00053 Private( const Private& );
00054 void operator=( const Private& );
00055 };
00056
00057
00058 KWindowInfo::KWindowInfo( WId _win, unsigned long properties, unsigned long properties2 ) : d(new Private)
00059 {
00060 KXErrorHandler handler;
00061 d->ref = 1;
00062 if( properties & NET::WMVisibleIconName )
00063 properties |= NET::WMIconName | NET::WMVisibleName;
00064 if( properties & NET::WMVisibleName )
00065 properties |= NET::WMName;
00066 if( properties2 & NET::WM2ExtendedStrut )
00067 properties |= NET::WMStrut;
00068 if( properties & NET::WMWindowType )
00069 properties2 |= NET::WM2TransientFor;
00070 properties |= NET::XAWMState;
00071 unsigned long props[ 2 ] = { properties, properties2 };
00072 d->info = new NETWinInfo( QX11Info::display(), _win, QX11Info::appRootWindow(), props, 2 );
00073 d->win_ = _win;
00074 if( properties & NET::WMName ) {
00075 if( d->info->name() && d->info->name()[ 0 ] != '\0' )
00076 d->name_ = QString::fromUtf8( d->info->name() );
00077 else
00078 d->name_ = KWindowSystem::readNameProperty( _win, XA_WM_NAME );
00079 }
00080 if( properties & NET::WMIconName ) {
00081 if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
00082 d->iconic_name_ = QString::fromUtf8( d->info->iconName());
00083 else
00084 d->iconic_name_ = KWindowSystem::readNameProperty( _win, XA_WM_ICON_NAME );
00085 }
00086 if( properties & ( NET::WMGeometry | NET::WMFrameExtents )) {
00087 NETRect frame, geom;
00088 d->info->kdeGeometry( frame, geom );
00089 d->geometry_.setRect( geom.pos.x, geom.pos.y, geom.size.width, geom.size.height );
00090 d->frame_geometry_.setRect( frame.pos.x, frame.pos.y, frame.size.width, frame.size.height );
00091 }
00092 d->valid = !handler.error( false );
00093 }
00094
00095
00096 KWindowInfo::KWindowInfo()
00097 : d( NULL )
00098 {
00099 }
00100
00101 KWindowInfo::~KWindowInfo()
00102 {
00103 if( d != NULL ) {
00104 if( --d->ref == 0 ) {
00105 delete d;
00106 }
00107 }
00108 }
00109
00110 KWindowInfo::KWindowInfo( const KWindowInfo& wininfo )
00111 : d( wininfo.d )
00112 {
00113 if( d != NULL )
00114 ++d->ref;
00115 }
00116
00117 KWindowInfo& KWindowInfo::operator=( const KWindowInfo& wininfo )
00118 {
00119 if( d != wininfo.d ) {
00120 if( d != NULL )
00121 if( --d->ref == 0 )
00122 delete d;
00123 d = wininfo.d;
00124 if( d != NULL )
00125 ++d->ref;
00126 }
00127 return *this;
00128 }
00129
00130 bool KWindowInfo::valid( bool withdrawn_is_valid ) const
00131 {
00132 if( !d->valid )
00133 return false;
00134 if( !withdrawn_is_valid && mappingState() == NET::Withdrawn )
00135 return false;
00136 return true;
00137 }
00138
00139 WId KWindowInfo::win() const
00140 {
00141 return d->win_;
00142 }
00143
00144 unsigned long KWindowInfo::state() const
00145 {
00146 #if !defined(KDE_NO_WARNING_OUTPUT)
00147 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMState))
00148 kWarning(176) << "Pass NET::WMState to KWindowInfo" << endl;
00149 #endif
00150 return d->info->state();
00151 }
00152
00153 bool KWindowInfo::hasState( unsigned long s ) const
00154 {
00155 return ( state() & s ) == s;
00156 }
00157
00158 NET::MappingState KWindowInfo::mappingState() const
00159 {
00160 #if !defined(KDE_NO_WARNING_OUTPUT)
00161 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::XAWMState))
00162 kWarning(176) << "Pass NET::XAWMState to KWindowInfo" << endl;
00163 #endif
00164 return d->info->mappingState();
00165 }
00166
00167 NETExtendedStrut KWindowInfo::extendedStrut() const
00168 {
00169 #if !defined(KDE_NO_WARNING_OUTPUT)
00170 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ExtendedStrut))
00171 kWarning(176) << "Pass NET::WM2ExtendedStrut to KWindowInfo" << endl;
00172 #endif
00173 NETExtendedStrut ext = d->info->extendedStrut();
00174 NETStrut str = d->info->strut();
00175 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
00176 && ( str.left != 0 || str.right != 0 || str.top != 0 || str.bottom != 0 )) {
00177
00178 if( str.left != 0 ) {
00179 ext.left_width = str.left;
00180 ext.left_start = 0;
00181 ext.left_end = XDisplayHeight( QX11Info::display(), DefaultScreen( QX11Info::display()));
00182 }
00183 if( str.right != 0 ) {
00184 ext.right_width = str.right;
00185 ext.right_start = 0;
00186 ext.right_end = XDisplayHeight( QX11Info::display(), DefaultScreen( QX11Info::display()));
00187 }
00188 if( str.top != 0 ) {
00189 ext.top_width = str.top;
00190 ext.top_start = 0;
00191 ext.top_end = XDisplayWidth( QX11Info::display(), DefaultScreen( QX11Info::display()));
00192 }
00193 if( str.bottom != 0 ) {
00194 ext.bottom_width = str.bottom;
00195 ext.bottom_start = 0;
00196 ext.bottom_end = XDisplayWidth( QX11Info::display(), DefaultScreen( QX11Info::display()));
00197 }
00198 }
00199 return ext;
00200 }
00201
00202 NET::WindowType KWindowInfo::windowType( int supported_types ) const
00203 {
00204 #if !defined(KDE_NO_WARNING_OUTPUT)
00205 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMWindowType))
00206 kWarning(176) << "Pass NET::WMWindowType to KWindowInfo" << endl;
00207 #endif
00208 if( !d->info->hasWindowType()) {
00209 if( transientFor() != None ) {
00210 if( supported_types & NET::DialogMask )
00211 return NET::Dialog;
00212 } else {
00213 if( supported_types & NET::NormalMask )
00214 return NET::Normal;
00215 }
00216 }
00217 return d->info->windowType( supported_types );
00218 }
00219
00220 QString KWindowInfo::visibleNameWithState() const
00221 {
00222 QString s = visibleName();
00223 if ( isMinimized() ) {
00224 s.prepend(QLatin1Char('('));
00225 s.append(QLatin1Char(')'));
00226 }
00227 return s;
00228 }
00229
00230 QString KWindowInfo::visibleName() const
00231 {
00232 #if !defined(KDE_NO_WARNING_OUTPUT)
00233 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleName))
00234 kWarning(176) << "Pass NET::WMVisibleName to KWindowInfo" << endl;
00235 #endif
00236 return d->info->visibleName() && d->info->visibleName()[ 0 ] != '\0'
00237 ? QString::fromUtf8(d->info->visibleName()) : name();
00238 }
00239
00240 QString KWindowInfo::name() const
00241 {
00242 #if !defined(KDE_NO_WARNING_OUTPUT)
00243 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMName))
00244 kWarning(176) << "Pass NET::WMName to KWindowInfo" << endl;
00245 #endif
00246 return d->name_;
00247 }
00248
00249 QString KWindowInfo::visibleIconNameWithState() const
00250 {
00251 QString s = visibleIconName();
00252 if ( isMinimized() ) {
00253 s.prepend(QLatin1Char('('));
00254 s.append(QLatin1Char(')'));
00255 }
00256 return s;
00257 }
00258
00259 QString KWindowInfo::visibleIconName() const
00260 {
00261 #if !defined(KDE_NO_WARNING_OUTPUT)
00262 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleIconName))
00263 kWarning(176) << "Pass NET::WMVisibleIconName to KWindowInfo" << endl;
00264 #endif
00265 if( d->info->visibleIconName() && d->info->visibleIconName()[ 0 ] != '\0' )
00266 return QString::fromUtf8( d->info->visibleIconName());
00267 if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
00268 return QString::fromUtf8( d->info->iconName());
00269 if( !d->iconic_name_.isEmpty())
00270 return d->iconic_name_;
00271 return visibleName();
00272 }
00273
00274 QString KWindowInfo::iconName() const
00275 {
00276 #if !defined(KDE_NO_WARNING_OUTPUT)
00277 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMIconName))
00278 kWarning(176) << "Pass NET::WMIconName to KWindowInfo" << endl;
00279 #endif
00280 if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
00281 return QString::fromUtf8( d->info->iconName());
00282 if( !d->iconic_name_.isEmpty())
00283 return d->iconic_name_;
00284 return name();
00285 }
00286
00287 bool KWindowInfo::isOnCurrentDesktop() const
00288 {
00289 return isOnDesktop( KWindowSystem::currentDesktop());
00290 }
00291
00292 bool KWindowInfo::isOnDesktop( int _desktop ) const
00293 {
00294 #if !defined(KDE_NO_WARNING_OUTPUT)
00295 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop))
00296 kWarning(176) << "Pass NET::WMDesktop to KWindowInfo" << endl;
00297 #endif
00298 if( KWindowSystem::mapViewport()) {
00299 if( onAllDesktops())
00300 return true;
00301 Window dummy;
00302 int x, y;
00303 unsigned int w, h, b, dp;
00304 XGetGeometry( QX11Info::display(), d->win_, &dummy, &x, &y, &w, &h, &b, &dp );
00305
00306 XTranslateCoordinates( QX11Info::display(), d->win_, QX11Info::appRootWindow(), 0, 0, &x, &y, &dummy );
00307 return KWindowSystem::viewportWindowToDesktop( QRect( x, y, w, h )) == _desktop;
00308 }
00309 return d->info->desktop() == _desktop || d->info->desktop() == NET::OnAllDesktops;
00310 }
00311
00312 bool KWindowInfo::onAllDesktops() const
00313 {
00314 #if !defined(KDE_NO_WARNING_OUTPUT)
00315 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop))
00316 kWarning(176) << "Pass NET::WMDesktop to KWindowInfo" << endl;
00317 #endif
00318 if( KWindowSystem::mapViewport()) {
00319 if( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMState )
00320 return d->info->state() & NET::Sticky;
00321 NETWinInfo info( QX11Info::display(), d->win_, QX11Info::appRootWindow(), NET::WMState );
00322 return info.state() & NET::Sticky;
00323 }
00324 return d->info->desktop() == NET::OnAllDesktops;
00325 }
00326
00327 int KWindowInfo::desktop() const
00328 {
00329 #if !defined(KDE_NO_WARNING_OUTPUT)
00330 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop))
00331 kWarning(176) << "Pass NET::WMDesktop to KWindowInfo" << endl;
00332 #endif
00333 if( KWindowSystem::mapViewport()) {
00334 if( onAllDesktops())
00335 return NET::OnAllDesktops;
00336 Window r;
00337 int x, y;
00338 unsigned int w, h, b, dp;
00339 XGetGeometry( QX11Info::display(), d->win_, &r, &x, &y, &w, &h, &b, &dp );
00340 return KWindowSystem::viewportWindowToDesktop( QRect( x, y, w, h ));
00341 }
00342 return d->info->desktop();
00343 }
00344
00345 QRect KWindowInfo::geometry() const
00346 {
00347 #if !defined(KDE_NO_WARNING_OUTPUT)
00348 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop))
00349 kWarning(176) << "Pass NET::WMDesktop to KWindowInfo" << endl;
00350 #endif
00351 return d->geometry_;
00352 }
00353
00354 QRect KWindowInfo::frameGeometry() const
00355 {
00356 #if !defined(KDE_NO_WARNING_OUTPUT)
00357 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMFrameExtents))
00358 kWarning(176) << "Pass NET::WMFrameExtents to KWindowInfo" << endl;
00359 #endif
00360 return d->frame_geometry_;
00361 }
00362
00363 WId KWindowInfo::transientFor() const
00364 {
00365 #if !defined(KDE_NO_WARNING_OUTPUT)
00366 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2TransientFor))
00367 kWarning(176) << "Pass NET::WM2TransientFor to KWindowInfo" << endl;
00368 #endif
00369 return d->info->transientFor();
00370 }
00371
00372 WId KWindowInfo::groupLeader() const
00373 {
00374 #if !defined(KDE_NO_WARNING_OUTPUT)
00375 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2GroupLeader))
00376 kWarning(176) << "Pass NET::WM2GroupLeader to KWindowInfo" << endl;
00377 #endif
00378 return d->info->groupLeader();
00379 }
00380
00381 QByteArray KWindowInfo::windowClassClass() const
00382 {
00383 #if !defined(KDE_NO_WARNING_OUTPUT)
00384 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass))
00385 kWarning(176) << "Pass NET::WM2WindowClass to KWindowInfo" << endl;
00386 #endif
00387 return d->info->windowClassClass();
00388 }
00389
00390 QByteArray KWindowInfo::windowClassName() const
00391 {
00392 #if !defined(KDE_NO_WARNING_OUTPUT)
00393 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass))
00394 kWarning(176) << "Pass NET::WM2WindowClass to KWindowInfo" << endl;
00395 #endif
00396 return d->info->windowClassName();
00397 }
00398
00399 QByteArray KWindowInfo::windowRole() const
00400 {
00401 #if !defined(KDE_NO_WARNING_OUTPUT)
00402 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowRole))
00403 kWarning(176) << "Pass NET::WM2WindowRole to KWindowInfo" << endl;
00404 #endif
00405 return d->info->windowRole();
00406 }
00407
00408 QByteArray KWindowInfo::clientMachine() const
00409 {
00410 #if !defined(KDE_NO_WARNING_OUTPUT)
00411 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ClientMachine))
00412 kWarning(176) << "Pass NET::WM2ClientMachine to KWindowInfo" << endl;
00413 #endif
00414 return d->info->clientMachine();
00415 }
00416
00417 bool KWindowInfo::actionSupported( NET::Action action ) const
00418 {
00419 #if !defined(KDE_NO_WARNING_OUTPUT)
00420 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2AllowedActions))
00421 kWarning(176) << "Pass NET::WM2AllowedActions to KWindowInfo" << endl;
00422 #endif
00423 if( KWindowSystem::allowedActionsSupported())
00424 return d->info->allowedActions() & action;
00425 else
00426 return true;
00427 }
00428
00429
00430 bool KWindowInfo::isMinimized() const
00431 {
00432 if( mappingState() != NET::Iconic )
00433 return false;
00434
00435 if(( state() & NET::Hidden ) != 0
00436 && ( state() & NET::Shaded ) == 0 )
00437 return true;
00438
00439
00440 return KWindowSystem::icccmCompliantMappingState() ? false : true;
00441 }
00442