KDEUI
kwindowinfo_x11.cpp
Go to the documentation of this file.
00001 /* 00002 This file is part of the KDE libraries 00003 Copyright (C) 1999 Matthias Ettrich (ettrich@kde.org) 00004 Copyright (C) 2007 Lubos Lunak (l.lunak@kde.org) 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "kwindowinfo.h" 00023 #include "kwindowsystem.h" 00024 00025 #include <kiconloader.h> 00026 #include <klocale.h> 00027 #include <kdebug.h> 00028 #include <kxerrorhandler.h> 00029 #include <netwm.h> 00030 #include <QtGui/QBitmap> 00031 #include <QDesktopWidget> 00032 #include <QtGui/QDialog> 00033 #include <QtDBus/QtDBus> 00034 #include <QtGui/QX11Info> 00035 #include <X11/Xatom.h> 00036 00037 struct KWindowInfo::Private 00038 { 00039 Private() 00040 : info( NULL ) 00041 {} 00042 ~Private() { delete info; } 00043 NETWinInfo* info; 00044 WId win_; 00045 QString name_; 00046 QString iconic_name_; 00047 QRect geometry_; 00048 QRect frame_geometry_; 00049 int ref; 00050 bool valid; 00051 private: 00052 Private( const Private& ); 00053 void operator=( const Private& ); 00054 }; 00055 00056 // KWindowSystem::info() should be updated too if something has to be changed here 00057 KWindowInfo::KWindowInfo( WId _win, unsigned long properties, unsigned long properties2 ) : d(new Private) 00058 { 00059 KXErrorHandler handler; 00060 d->ref = 1; 00061 if( properties & NET::WMVisibleIconName ) 00062 properties |= NET::WMIconName | NET::WMVisibleName; // force, in case it will be used as a fallback 00063 if( properties & NET::WMVisibleName ) 00064 properties |= NET::WMName; // force, in case it will be used as a fallback 00065 if( properties2 & NET::WM2ExtendedStrut ) 00066 properties |= NET::WMStrut; // will be used as fallback 00067 if( properties & NET::WMWindowType ) 00068 properties2 |= NET::WM2TransientFor; // will be used when type is not set 00069 if( ( properties & NET::WMDesktop ) && KWindowSystem::mapViewport() ) 00070 properties |= NET::WMGeometry; // for viewports, the desktop (workspace) is determined from the geometry 00071 properties |= NET::XAWMState; // force to get error detection for valid() 00072 unsigned long props[ 2 ] = { properties, properties2 }; 00073 d->info = new NETWinInfo( QX11Info::display(), _win, QX11Info::appRootWindow(), props, 2 ); 00074 d->win_ = _win; 00075 if( properties & NET::WMName ) { 00076 if( d->info->name() && d->info->name()[ 0 ] != '\0' ) 00077 d->name_ = QString::fromUtf8( d->info->name() ); 00078 else 00079 d->name_ = KWindowSystem::readNameProperty( _win, XA_WM_NAME ); 00080 } 00081 if( properties & NET::WMIconName ) { 00082 if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' ) 00083 d->iconic_name_ = QString::fromUtf8( d->info->iconName()); 00084 else 00085 d->iconic_name_ = KWindowSystem::readNameProperty( _win, XA_WM_ICON_NAME ); 00086 } 00087 if( properties & ( NET::WMGeometry | NET::WMFrameExtents )) { 00088 NETRect frame, geom; 00089 d->info->kdeGeometry( frame, geom ); 00090 d->geometry_.setRect( geom.pos.x, geom.pos.y, geom.size.width, geom.size.height ); 00091 d->frame_geometry_.setRect( frame.pos.x, frame.pos.y, frame.size.width, frame.size.height ); 00092 } 00093 d->valid = !handler.error( false ); // no sync - NETWinInfo did roundtrips 00094 } 00095 00096 // this one is only to make QList<> or similar happy 00097 KWindowInfo::KWindowInfo() 00098 : d( NULL ) 00099 { 00100 } 00101 00102 KWindowInfo::~KWindowInfo() 00103 { 00104 if( d != NULL ) { 00105 if( --d->ref == 0 ) { 00106 delete d; 00107 } 00108 } 00109 } 00110 00111 KWindowInfo::KWindowInfo( const KWindowInfo& wininfo ) 00112 : d( wininfo.d ) 00113 { 00114 if( d != NULL ) 00115 ++d->ref; 00116 } 00117 00118 KWindowInfo& KWindowInfo::operator=( const KWindowInfo& wininfo ) 00119 { 00120 if( d != wininfo.d ) { 00121 if( d != NULL ) 00122 if( --d->ref == 0 ) 00123 delete d; 00124 d = wininfo.d; 00125 if( d != NULL ) 00126 ++d->ref; 00127 } 00128 return *this; 00129 } 00130 00131 bool KWindowInfo::valid( bool withdrawn_is_valid ) const 00132 { 00133 if( !d->valid ) 00134 return false; 00135 if( !withdrawn_is_valid && mappingState() == NET::Withdrawn ) 00136 return false; 00137 return true; 00138 } 00139 00140 WId KWindowInfo::win() const 00141 { 00142 return d->win_; 00143 } 00144 00145 unsigned long KWindowInfo::state() const 00146 { 00147 #if !defined(KDE_NO_WARNING_OUTPUT) 00148 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMState)) 00149 kWarning(176) << "Pass NET::WMState to KWindowInfo"; 00150 #endif 00151 return d->info->state(); 00152 } 00153 00154 bool KWindowInfo::hasState( unsigned long s ) const 00155 { 00156 return ( state() & s ) == s; 00157 } 00158 00159 NET::MappingState KWindowInfo::mappingState() const 00160 { 00161 #if !defined(KDE_NO_WARNING_OUTPUT) 00162 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::XAWMState)) 00163 kWarning(176) << "Pass NET::XAWMState to KWindowInfo"; 00164 #endif 00165 return d->info->mappingState(); 00166 } 00167 00168 NETExtendedStrut KWindowInfo::extendedStrut() const 00169 { 00170 #if !defined(KDE_NO_WARNING_OUTPUT) 00171 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ExtendedStrut)) 00172 kWarning(176) << "Pass NET::WM2ExtendedStrut to KWindowInfo"; 00173 #endif 00174 NETExtendedStrut ext = d->info->extendedStrut(); 00175 NETStrut str = d->info->strut(); 00176 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0 00177 && ( str.left != 0 || str.right != 0 || str.top != 0 || str.bottom != 0 )) { 00178 // build extended from simple 00179 if( str.left != 0 ) { 00180 ext.left_width = str.left; 00181 ext.left_start = 0; 00182 ext.left_end = XDisplayHeight( QX11Info::display(), DefaultScreen( QX11Info::display())); 00183 } 00184 if( str.right != 0 ) { 00185 ext.right_width = str.right; 00186 ext.right_start = 0; 00187 ext.right_end = XDisplayHeight( QX11Info::display(), DefaultScreen( QX11Info::display())); 00188 } 00189 if( str.top != 0 ) { 00190 ext.top_width = str.top; 00191 ext.top_start = 0; 00192 ext.top_end = XDisplayWidth( QX11Info::display(), DefaultScreen( QX11Info::display())); 00193 } 00194 if( str.bottom != 0 ) { 00195 ext.bottom_width = str.bottom; 00196 ext.bottom_start = 0; 00197 ext.bottom_end = XDisplayWidth( QX11Info::display(), DefaultScreen( QX11Info::display())); 00198 } 00199 } 00200 return ext; 00201 } 00202 00203 NET::WindowType KWindowInfo::windowType( int supported_types ) const 00204 { 00205 #if !defined(KDE_NO_WARNING_OUTPUT) 00206 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMWindowType)) 00207 kWarning(176) << "Pass NET::WMWindowType to KWindowInfo"; 00208 #endif 00209 if( !d->info->hasWindowType()) { // fallback, per spec recommendation 00210 if( transientFor() != None ) { // dialog 00211 if( supported_types & NET::DialogMask ) 00212 return NET::Dialog; 00213 } else { 00214 if( supported_types & NET::NormalMask ) 00215 return NET::Normal; 00216 } 00217 } 00218 return d->info->windowType( supported_types ); 00219 } 00220 00221 QString KWindowInfo::visibleNameWithState() const 00222 { 00223 QString s = visibleName(); 00224 if ( isMinimized() ) { 00225 s.prepend(QLatin1Char('(')); 00226 s.append(QLatin1Char(')')); 00227 } 00228 return s; 00229 } 00230 00231 QString KWindowInfo::visibleName() const 00232 { 00233 #if !defined(KDE_NO_WARNING_OUTPUT) 00234 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleName)) 00235 kWarning(176) << "Pass NET::WMVisibleName to KWindowInfo"; 00236 #endif 00237 return d->info->visibleName() && d->info->visibleName()[ 0 ] != '\0' 00238 ? QString::fromUtf8(d->info->visibleName()) : name(); 00239 } 00240 00241 QString KWindowInfo::name() const 00242 { 00243 #if !defined(KDE_NO_WARNING_OUTPUT) 00244 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMName)) 00245 kWarning(176) << "Pass NET::WMName to KWindowInfo"; 00246 #endif 00247 return d->name_; 00248 } 00249 00250 QString KWindowInfo::visibleIconNameWithState() const 00251 { 00252 QString s = visibleIconName(); 00253 if ( isMinimized() ) { 00254 s.prepend(QLatin1Char('(')); 00255 s.append(QLatin1Char(')')); 00256 } 00257 return s; 00258 } 00259 00260 QString KWindowInfo::visibleIconName() const 00261 { 00262 #if !defined(KDE_NO_WARNING_OUTPUT) 00263 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleIconName)) 00264 kWarning(176) << "Pass NET::WMVisibleIconName to KWindowInfo"; 00265 #endif 00266 if( d->info->visibleIconName() && d->info->visibleIconName()[ 0 ] != '\0' ) 00267 return QString::fromUtf8( d->info->visibleIconName()); 00268 if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' ) 00269 return QString::fromUtf8( d->info->iconName()); 00270 if( !d->iconic_name_.isEmpty()) 00271 return d->iconic_name_; 00272 return visibleName(); 00273 } 00274 00275 QString KWindowInfo::iconName() const 00276 { 00277 #if !defined(KDE_NO_WARNING_OUTPUT) 00278 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMIconName)) 00279 kWarning(176) << "Pass NET::WMIconName to KWindowInfo"; 00280 #endif 00281 if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' ) 00282 return QString::fromUtf8( d->info->iconName()); 00283 if( !d->iconic_name_.isEmpty()) 00284 return d->iconic_name_; 00285 return name(); 00286 } 00287 00288 bool KWindowInfo::isOnCurrentDesktop() const 00289 { 00290 return isOnDesktop( KWindowSystem::currentDesktop()); 00291 } 00292 00293 bool KWindowInfo::isOnDesktop( int _desktop ) const 00294 { 00295 #if !defined(KDE_NO_WARNING_OUTPUT) 00296 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop)) 00297 kWarning(176) << "Pass NET::WMDesktop to KWindowInfo"; 00298 #endif 00299 if( KWindowSystem::mapViewport()) { 00300 if( onAllDesktops()) 00301 return true; 00302 return KWindowSystem::viewportWindowToDesktop( d->geometry_ ) == _desktop; 00303 } 00304 return d->info->desktop() == _desktop || d->info->desktop() == NET::OnAllDesktops; 00305 } 00306 00307 bool KWindowInfo::onAllDesktops() const 00308 { 00309 #if !defined(KDE_NO_WARNING_OUTPUT) 00310 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop)) 00311 kWarning(176) << "Pass NET::WMDesktop to KWindowInfo"; 00312 #endif 00313 if( KWindowSystem::mapViewport()) { 00314 if( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMState ) 00315 return d->info->state() & NET::Sticky; 00316 NETWinInfo info( QX11Info::display(), d->win_, QX11Info::appRootWindow(), NET::WMState ); 00317 return info.state() & NET::Sticky; 00318 } 00319 return d->info->desktop() == NET::OnAllDesktops; 00320 } 00321 00322 int KWindowInfo::desktop() const 00323 { 00324 #if !defined(KDE_NO_WARNING_OUTPUT) 00325 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop)) 00326 kWarning(176) << "Pass NET::WMDesktop to KWindowInfo"; 00327 #endif 00328 if( KWindowSystem::mapViewport()) { 00329 if( onAllDesktops()) 00330 return NET::OnAllDesktops; 00331 return KWindowSystem::viewportWindowToDesktop( d->geometry_ ); 00332 } 00333 return d->info->desktop(); 00334 } 00335 00336 QRect KWindowInfo::geometry() const 00337 { 00338 #if !defined(KDE_NO_WARNING_OUTPUT) 00339 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMGeometry)) 00340 kWarning(176) << "Pass NET::WMGeometry to KWindowInfo"; 00341 #endif 00342 return d->geometry_; 00343 } 00344 00345 QRect KWindowInfo::frameGeometry() const 00346 { 00347 #if !defined(KDE_NO_WARNING_OUTPUT) 00348 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMFrameExtents)) 00349 kWarning(176) << "Pass NET::WMFrameExtents to KWindowInfo"; 00350 #endif 00351 return d->frame_geometry_; 00352 } 00353 00354 WId KWindowInfo::transientFor() const 00355 { 00356 #if !defined(KDE_NO_WARNING_OUTPUT) 00357 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2TransientFor)) 00358 kWarning(176) << "Pass NET::WM2TransientFor to KWindowInfo"; 00359 #endif 00360 return d->info->transientFor(); 00361 } 00362 00363 WId KWindowInfo::groupLeader() const 00364 { 00365 #if !defined(KDE_NO_WARNING_OUTPUT) 00366 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2GroupLeader)) 00367 kWarning(176) << "Pass NET::WM2GroupLeader to KWindowInfo"; 00368 #endif 00369 return d->info->groupLeader(); 00370 } 00371 00372 QByteArray KWindowInfo::windowClassClass() const 00373 { 00374 #if !defined(KDE_NO_WARNING_OUTPUT) 00375 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass)) 00376 kWarning(176) << "Pass NET::WM2WindowClass to KWindowInfo"; 00377 #endif 00378 return d->info->windowClassClass(); 00379 } 00380 00381 QByteArray KWindowInfo::windowClassName() 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"; 00386 #endif 00387 return d->info->windowClassName(); 00388 } 00389 00390 QByteArray KWindowInfo::windowRole() const 00391 { 00392 #if !defined(KDE_NO_WARNING_OUTPUT) 00393 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowRole)) 00394 kWarning(176) << "Pass NET::WM2WindowRole to KWindowInfo"; 00395 #endif 00396 return d->info->windowRole(); 00397 } 00398 00399 QByteArray KWindowInfo::clientMachine() const 00400 { 00401 #if !defined(KDE_NO_WARNING_OUTPUT) 00402 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ClientMachine)) 00403 kWarning(176) << "Pass NET::WM2ClientMachine to KWindowInfo"; 00404 #endif 00405 return d->info->clientMachine(); 00406 } 00407 00408 bool KWindowInfo::actionSupported( NET::Action action ) const 00409 { 00410 #if !defined(KDE_NO_WARNING_OUTPUT) 00411 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2AllowedActions)) 00412 kWarning(176) << "Pass NET::WM2AllowedActions to KWindowInfo"; 00413 #endif 00414 if( KWindowSystem::allowedActionsSupported()) 00415 return d->info->allowedActions() & action; 00416 else 00417 return true; // no idea if it's supported or not -> pretend it is 00418 } 00419 00420 // see NETWM spec section 7.6 00421 bool KWindowInfo::isMinimized() const 00422 { 00423 if( mappingState() != NET::Iconic ) 00424 return false; 00425 // NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows 00426 if(( state() & NET::Hidden ) != 0 00427 && ( state() & NET::Shaded ) == 0 ) // shaded may have NET::Hidden too 00428 return true; 00429 // older WMs use WithdrawnState for other virtual desktops 00430 // and IconicState only for minimized 00431 return KWindowSystem::icccmCompliantMappingState() ? false : true; 00432 } 00433
KDE 4.7 API Reference