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 <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 // KWindowSystem::info() should be updated too if something has to be changed here 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; // force, in case it will be used as a fallback 00064 if( properties & NET::WMVisibleName ) 00065 properties |= NET::WMName; // force, in case it will be used as a fallback 00066 if( properties2 & NET::WM2ExtendedStrut ) 00067 properties |= NET::WMStrut; // will be used as fallback 00068 if( properties & NET::WMWindowType ) 00069 properties2 |= NET::WM2TransientFor; // will be used when type is not set 00070 if( ( properties & NET::WMDesktop ) && KWindowSystem::mapViewport() ) 00071 properties |= NET::WMGeometry; // for viewports, the desktop (workspace) is determined from the geometry 00072 properties |= NET::XAWMState; // force to get error detection for valid() 00073 unsigned long props[ 2 ] = { properties, properties2 }; 00074 d->info = new NETWinInfo( QX11Info::display(), _win, QX11Info::appRootWindow(), props, 2 ); 00075 d->win_ = _win; 00076 if( properties & NET::WMName ) { 00077 if( d->info->name() && d->info->name()[ 0 ] != '\0' ) 00078 d->name_ = QString::fromUtf8( d->info->name() ); 00079 else 00080 d->name_ = KWindowSystem::readNameProperty( _win, XA_WM_NAME ); 00081 } 00082 if( properties & NET::WMIconName ) { 00083 if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' ) 00084 d->iconic_name_ = QString::fromUtf8( d->info->iconName()); 00085 else 00086 d->iconic_name_ = KWindowSystem::readNameProperty( _win, XA_WM_ICON_NAME ); 00087 } 00088 if( properties & ( NET::WMGeometry | NET::WMFrameExtents )) { 00089 NETRect frame, geom; 00090 d->info->kdeGeometry( frame, geom ); 00091 d->geometry_.setRect( geom.pos.x, geom.pos.y, geom.size.width, geom.size.height ); 00092 d->frame_geometry_.setRect( frame.pos.x, frame.pos.y, frame.size.width, frame.size.height ); 00093 } 00094 d->valid = !handler.error( false ); // no sync - NETWinInfo did roundtrips 00095 } 00096 00097 // this one is only to make QList<> or similar happy 00098 KWindowInfo::KWindowInfo() 00099 : d( NULL ) 00100 { 00101 } 00102 00103 KWindowInfo::~KWindowInfo() 00104 { 00105 if( d != NULL ) { 00106 if( --d->ref == 0 ) { 00107 delete d; 00108 } 00109 } 00110 } 00111 00112 KWindowInfo::KWindowInfo( const KWindowInfo& wininfo ) 00113 : d( wininfo.d ) 00114 { 00115 if( d != NULL ) 00116 ++d->ref; 00117 } 00118 00119 KWindowInfo& KWindowInfo::operator=( const KWindowInfo& wininfo ) 00120 { 00121 if( d != wininfo.d ) { 00122 if( d != NULL ) 00123 if( --d->ref == 0 ) 00124 delete d; 00125 d = wininfo.d; 00126 if( d != NULL ) 00127 ++d->ref; 00128 } 00129 return *this; 00130 } 00131 00132 bool KWindowInfo::valid( bool withdrawn_is_valid ) const 00133 { 00134 if( !d->valid ) 00135 return false; 00136 if( !withdrawn_is_valid && mappingState() == NET::Withdrawn ) 00137 return false; 00138 return true; 00139 } 00140 00141 WId KWindowInfo::win() const 00142 { 00143 return d->win_; 00144 } 00145 00146 unsigned long KWindowInfo::state() const 00147 { 00148 #if !defined(KDE_NO_WARNING_OUTPUT) 00149 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMState)) 00150 kWarning(176) << "Pass NET::WMState to KWindowInfo"; 00151 #endif 00152 return d->info->state(); 00153 } 00154 00155 bool KWindowInfo::hasState( unsigned long s ) const 00156 { 00157 return ( state() & s ) == s; 00158 } 00159 00160 NET::MappingState KWindowInfo::mappingState() const 00161 { 00162 #if !defined(KDE_NO_WARNING_OUTPUT) 00163 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::XAWMState)) 00164 kWarning(176) << "Pass NET::XAWMState to KWindowInfo"; 00165 #endif 00166 return d->info->mappingState(); 00167 } 00168 00169 NETExtendedStrut KWindowInfo::extendedStrut() const 00170 { 00171 #if !defined(KDE_NO_WARNING_OUTPUT) 00172 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ExtendedStrut)) 00173 kWarning(176) << "Pass NET::WM2ExtendedStrut to KWindowInfo"; 00174 #endif 00175 NETExtendedStrut ext = d->info->extendedStrut(); 00176 NETStrut str = d->info->strut(); 00177 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0 00178 && ( str.left != 0 || str.right != 0 || str.top != 0 || str.bottom != 0 )) { 00179 // build extended from simple 00180 if( str.left != 0 ) { 00181 ext.left_width = str.left; 00182 ext.left_start = 0; 00183 ext.left_end = XDisplayHeight( QX11Info::display(), DefaultScreen( QX11Info::display())); 00184 } 00185 if( str.right != 0 ) { 00186 ext.right_width = str.right; 00187 ext.right_start = 0; 00188 ext.right_end = XDisplayHeight( QX11Info::display(), DefaultScreen( QX11Info::display())); 00189 } 00190 if( str.top != 0 ) { 00191 ext.top_width = str.top; 00192 ext.top_start = 0; 00193 ext.top_end = XDisplayWidth( QX11Info::display(), DefaultScreen( QX11Info::display())); 00194 } 00195 if( str.bottom != 0 ) { 00196 ext.bottom_width = str.bottom; 00197 ext.bottom_start = 0; 00198 ext.bottom_end = XDisplayWidth( QX11Info::display(), DefaultScreen( QX11Info::display())); 00199 } 00200 } 00201 return ext; 00202 } 00203 00204 NET::WindowType KWindowInfo::windowType( int supported_types ) const 00205 { 00206 #if !defined(KDE_NO_WARNING_OUTPUT) 00207 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMWindowType)) 00208 kWarning(176) << "Pass NET::WMWindowType to KWindowInfo"; 00209 #endif 00210 if( !d->info->hasWindowType()) { // fallback, per spec recommendation 00211 if( transientFor() != None ) { // dialog 00212 if( supported_types & NET::DialogMask ) 00213 return NET::Dialog; 00214 } else { 00215 if( supported_types & NET::NormalMask ) 00216 return NET::Normal; 00217 } 00218 } 00219 return d->info->windowType( supported_types ); 00220 } 00221 00222 QString KWindowInfo::visibleNameWithState() const 00223 { 00224 QString s = visibleName(); 00225 if ( isMinimized() ) { 00226 s.prepend(QLatin1Char('(')); 00227 s.append(QLatin1Char(')')); 00228 } 00229 return s; 00230 } 00231 00232 QString KWindowInfo::visibleName() const 00233 { 00234 #if !defined(KDE_NO_WARNING_OUTPUT) 00235 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleName)) 00236 kWarning(176) << "Pass NET::WMVisibleName to KWindowInfo"; 00237 #endif 00238 return d->info->visibleName() && d->info->visibleName()[ 0 ] != '\0' 00239 ? QString::fromUtf8(d->info->visibleName()) : name(); 00240 } 00241 00242 QString KWindowInfo::name() const 00243 { 00244 #if !defined(KDE_NO_WARNING_OUTPUT) 00245 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMName)) 00246 kWarning(176) << "Pass NET::WMName to KWindowInfo"; 00247 #endif 00248 return d->name_; 00249 } 00250 00251 QString KWindowInfo::visibleIconNameWithState() const 00252 { 00253 QString s = visibleIconName(); 00254 if ( isMinimized() ) { 00255 s.prepend(QLatin1Char('(')); 00256 s.append(QLatin1Char(')')); 00257 } 00258 return s; 00259 } 00260 00261 QString KWindowInfo::visibleIconName() const 00262 { 00263 #if !defined(KDE_NO_WARNING_OUTPUT) 00264 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleIconName)) 00265 kWarning(176) << "Pass NET::WMVisibleIconName to KWindowInfo"; 00266 #endif 00267 if( d->info->visibleIconName() && d->info->visibleIconName()[ 0 ] != '\0' ) 00268 return QString::fromUtf8( d->info->visibleIconName()); 00269 if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' ) 00270 return QString::fromUtf8( d->info->iconName()); 00271 if( !d->iconic_name_.isEmpty()) 00272 return d->iconic_name_; 00273 return visibleName(); 00274 } 00275 00276 QString KWindowInfo::iconName() const 00277 { 00278 #if !defined(KDE_NO_WARNING_OUTPUT) 00279 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMIconName)) 00280 kWarning(176) << "Pass NET::WMIconName to KWindowInfo"; 00281 #endif 00282 if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' ) 00283 return QString::fromUtf8( d->info->iconName()); 00284 if( !d->iconic_name_.isEmpty()) 00285 return d->iconic_name_; 00286 return name(); 00287 } 00288 00289 bool KWindowInfo::isOnCurrentDesktop() const 00290 { 00291 return isOnDesktop( KWindowSystem::currentDesktop()); 00292 } 00293 00294 bool KWindowInfo::isOnDesktop( int _desktop ) const 00295 { 00296 #if !defined(KDE_NO_WARNING_OUTPUT) 00297 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop)) 00298 kWarning(176) << "Pass NET::WMDesktop to KWindowInfo"; 00299 #endif 00300 if( KWindowSystem::mapViewport()) { 00301 if( onAllDesktops()) 00302 return true; 00303 return KWindowSystem::viewportWindowToDesktop( d->geometry_ ) == _desktop; 00304 } 00305 return d->info->desktop() == _desktop || d->info->desktop() == NET::OnAllDesktops; 00306 } 00307 00308 bool KWindowInfo::onAllDesktops() const 00309 { 00310 #if !defined(KDE_NO_WARNING_OUTPUT) 00311 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop)) 00312 kWarning(176) << "Pass NET::WMDesktop to KWindowInfo"; 00313 #endif 00314 if( KWindowSystem::mapViewport()) { 00315 if( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMState ) 00316 return d->info->state() & NET::Sticky; 00317 NETWinInfo info( QX11Info::display(), d->win_, QX11Info::appRootWindow(), NET::WMState ); 00318 return info.state() & NET::Sticky; 00319 } 00320 return d->info->desktop() == NET::OnAllDesktops; 00321 } 00322 00323 int KWindowInfo::desktop() const 00324 { 00325 #if !defined(KDE_NO_WARNING_OUTPUT) 00326 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop)) 00327 kWarning(176) << "Pass NET::WMDesktop to KWindowInfo"; 00328 #endif 00329 if( KWindowSystem::mapViewport()) { 00330 if( onAllDesktops()) 00331 return NET::OnAllDesktops; 00332 return KWindowSystem::viewportWindowToDesktop( d->geometry_ ); 00333 } 00334 return d->info->desktop(); 00335 } 00336 00337 QRect KWindowInfo::geometry() const 00338 { 00339 #if !defined(KDE_NO_WARNING_OUTPUT) 00340 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMGeometry)) 00341 kWarning(176) << "Pass NET::WMGeometry to KWindowInfo"; 00342 #endif 00343 return d->geometry_; 00344 } 00345 00346 QRect KWindowInfo::frameGeometry() const 00347 { 00348 #if !defined(KDE_NO_WARNING_OUTPUT) 00349 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMFrameExtents)) 00350 kWarning(176) << "Pass NET::WMFrameExtents to KWindowInfo"; 00351 #endif 00352 return d->frame_geometry_; 00353 } 00354 00355 WId KWindowInfo::transientFor() const 00356 { 00357 #if !defined(KDE_NO_WARNING_OUTPUT) 00358 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2TransientFor)) 00359 kWarning(176) << "Pass NET::WM2TransientFor to KWindowInfo"; 00360 #endif 00361 return d->info->transientFor(); 00362 } 00363 00364 WId KWindowInfo::groupLeader() const 00365 { 00366 #if !defined(KDE_NO_WARNING_OUTPUT) 00367 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2GroupLeader)) 00368 kWarning(176) << "Pass NET::WM2GroupLeader to KWindowInfo"; 00369 #endif 00370 return d->info->groupLeader(); 00371 } 00372 00373 QByteArray KWindowInfo::windowClassClass() const 00374 { 00375 #if !defined(KDE_NO_WARNING_OUTPUT) 00376 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass)) 00377 kWarning(176) << "Pass NET::WM2WindowClass to KWindowInfo"; 00378 #endif 00379 return d->info->windowClassClass(); 00380 } 00381 00382 QByteArray KWindowInfo::windowClassName() const 00383 { 00384 #if !defined(KDE_NO_WARNING_OUTPUT) 00385 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass)) 00386 kWarning(176) << "Pass NET::WM2WindowClass to KWindowInfo"; 00387 #endif 00388 return d->info->windowClassName(); 00389 } 00390 00391 QByteArray KWindowInfo::windowRole() const 00392 { 00393 #if !defined(KDE_NO_WARNING_OUTPUT) 00394 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowRole)) 00395 kWarning(176) << "Pass NET::WM2WindowRole to KWindowInfo"; 00396 #endif 00397 return d->info->windowRole(); 00398 } 00399 00400 QByteArray KWindowInfo::clientMachine() const 00401 { 00402 #if !defined(KDE_NO_WARNING_OUTPUT) 00403 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ClientMachine)) 00404 kWarning(176) << "Pass NET::WM2ClientMachine to KWindowInfo"; 00405 #endif 00406 return d->info->clientMachine(); 00407 } 00408 00409 bool KWindowInfo::actionSupported( NET::Action action ) const 00410 { 00411 #if !defined(KDE_NO_WARNING_OUTPUT) 00412 if (!(d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2AllowedActions)) 00413 kWarning(176) << "Pass NET::WM2AllowedActions to KWindowInfo"; 00414 #endif 00415 if( KWindowSystem::allowedActionsSupported()) 00416 return d->info->allowedActions() & action; 00417 else 00418 return true; // no idea if it's supported or not -> pretend it is 00419 } 00420 00421 // see NETWM spec section 7.6 00422 bool KWindowInfo::isMinimized() const 00423 { 00424 if( mappingState() != NET::Iconic ) 00425 return false; 00426 // NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows 00427 if(( state() & NET::Hidden ) != 0 00428 && ( state() & NET::Shaded ) == 0 ) // shaded may have NET::Hidden too 00429 return true; 00430 // older WMs use WithdrawnState for other virtual desktops 00431 // and IconicState only for minimized 00432 return KWindowSystem::icccmCompliantMappingState() ? false : true; 00433 } 00434
KDE 4.6 API Reference