KDEUI
kwindowinfo_mac.cpp
Go to the documentation of this file.
00001 /* 00002 This file is part of the KDE libraries 00003 Copyright (C) 2008 Marijn Kruisselbrink (m.kruisselbrink@student.tue.nl) 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "kwindowinfo_mac_p.h" 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 00035 KWindowInfo::Private::Private() 00036 : ref(0), win(0), isLocal(false), loadedData(false), m_axWin(0), parent(), m_pid(-1) 00037 { 00038 } 00039 00040 void KWindowInfo::Private::setAxElement(const AXUIElementRef& axWin) 00041 { 00042 m_axWin = axWin; 00043 CFRetain(m_axWin); 00044 } 00045 00046 void KWindowInfo::Private::setProcessSerialNumber(const ProcessSerialNumber& psn) 00047 { 00048 m_psn = psn; 00049 GetProcessPID(&psn, &m_pid); 00050 } 00051 00052 KWindowInfo::Private::~Private() 00053 { 00054 CFRelease(m_axWin); 00055 } 00056 00057 void KWindowInfo::Private::updateData() 00058 { 00059 ProcessInfoRec pinfo; 00060 char processName[512]; 00061 #ifdef Q_OS_MAC32 00062 FSSpec appSpec; 00063 #else 00064 FSRef ref; 00065 #endif 00066 pinfo.processInfoLength = sizeof pinfo; 00067 pinfo.processName = (unsigned char*) processName; 00068 #ifdef Q_OS_MAC32 00069 pinfo.processAppSpec = &appSpec; 00070 #else 00071 pinfo.processAppRef = &ref; 00072 #endif 00073 GetProcessInformation(&m_psn, &pinfo); 00074 name = QString::fromAscii(processName+1, processName[0]); 00075 00076 if (m_axWin) { 00077 CFStringRef title; 00078 if (AXUIElementCopyAttributeValue(m_axWin, kAXTitleAttribute, (CFTypeRef*)&title) == noErr) { 00079 CFStringGetCString(title, processName, sizeof processName, kCFStringEncodingUTF8); 00080 name = QString::fromUtf8(processName); 00081 } 00082 } 00083 00084 #ifdef Q_OS_MAC32 00085 iconSpec = appSpec; 00086 00087 FSRef ref; 00088 FSpMakeFSRef(&appSpec, &ref); 00089 #else 00090 iconSpec = ref; 00091 #endif 00092 // check if it is in an application bundle (foo.app/Contents/MacOS/plasma) 00093 HFSUniStr255 name; 00094 FSRef parentRef; 00095 FSGetCatalogInfo(&ref, kFSCatInfoNone, 0, &name, 0, &parentRef); 00096 ref = parentRef; 00097 FSGetCatalogInfo(&ref, kFSCatInfoNone, 0, &name, 0, &parentRef); 00098 if (QString::fromUtf16(name.unicode, name.length) == "MacOS") { 00099 ref = parentRef; 00100 FSGetCatalogInfo(&ref, kFSCatInfoNone, 0, &name, 0, &parentRef); 00101 if (QString::fromUtf16(name.unicode, name.length) == "Contents") { 00102 #ifdef Q_OS_MAC32 00103 FSSpec spec; 00104 ref = parentRef; 00105 FSGetCatalogInfo(&ref, kFSCatInfoNone, 0, &name, &spec, &parentRef); 00106 iconSpec = spec; 00107 #else 00108 iconSpec = parentRef; 00109 #endif 00110 } 00111 } 00112 00113 loadedData = true; 00114 } 00115 00116 KWindowInfo::KWindowInfo( WId win, unsigned long, unsigned long ) : d(new Private) 00117 { 00118 d->ref = 1; 00119 d->win = win; 00120 d->isLocal = true; 00121 if (!win) { 00122 d->win = (WId) d; 00123 d->isLocal = false; 00124 } 00125 } 00126 00127 00128 // this one is only to make QList<> or similar happy 00129 KWindowInfo::KWindowInfo() 00130 : d( NULL ) 00131 { 00132 } 00133 00134 KWindowInfo::~KWindowInfo() 00135 { 00136 if( d != NULL ) { 00137 if( --d->ref == 0 ) { 00138 delete d; 00139 } 00140 } 00141 } 00142 00143 KWindowInfo::KWindowInfo( const KWindowInfo& wininfo ) 00144 : d( wininfo.d ) 00145 { 00146 if( d != NULL ) 00147 ++d->ref; 00148 } 00149 00150 KWindowInfo& KWindowInfo::operator=( const KWindowInfo& wininfo ) 00151 { 00152 if( d != wininfo.d ) { 00153 if( d != NULL ) 00154 if( --d->ref == 0 ) 00155 delete d; 00156 d = wininfo.d; 00157 if( d != NULL ) 00158 ++d->ref; 00159 } 00160 return *this; 00161 } 00162 00163 bool KWindowInfo::valid( bool withdrawn_is_valid ) const 00164 { 00165 return d->pid() >= 0; 00166 } 00167 00168 WId KWindowInfo::win() const 00169 { 00170 return d->win; 00171 } 00172 00173 unsigned long KWindowInfo::state() const 00174 { 00175 return 0; 00176 } 00177 00178 bool KWindowInfo::hasState( unsigned long s ) const 00179 { 00180 return false; 00181 } 00182 00183 bool KWindowInfo::isMinimized() const 00184 { 00185 if (d->axElement()) { 00186 CFBooleanRef val; 00187 if (AXUIElementCopyAttributeValue(d->axElement(), kAXMinimizedAttribute, (CFTypeRef*)&val) == noErr) { 00188 return CFBooleanGetValue(val); 00189 } else { 00190 return false; 00191 } 00192 } else { 00193 return false; 00194 } 00195 } 00196 00197 NET::MappingState KWindowInfo::mappingState() const 00198 { 00199 return (NET::MappingState) 0; 00200 } 00201 00202 NETExtendedStrut KWindowInfo::extendedStrut() const 00203 { 00204 NETExtendedStrut ext; 00205 return ext; 00206 } 00207 00208 NET::WindowType KWindowInfo::windowType( int supported_types ) const 00209 { 00210 return (NET::WindowType) 0; 00211 } 00212 00213 QString KWindowInfo::visibleNameWithState() const 00214 { 00215 QString s = visibleName(); 00216 if ( isMinimized() ) { 00217 s.prepend(QLatin1Char('(')); 00218 s.append(QLatin1Char(')')); 00219 } 00220 return s; 00221 } 00222 00223 QString KWindowInfo::visibleName() const 00224 { 00225 return name(); 00226 } 00227 00228 QString KWindowInfo::name() const 00229 { 00230 if (!d->loadedData) { 00231 d->updateData(); 00232 } 00233 return d->name; 00234 } 00235 00236 QString KWindowInfo::visibleIconNameWithState() const 00237 { 00238 QString s = visibleIconName(); 00239 if ( isMinimized() ) { 00240 s.prepend(QLatin1Char('(')); 00241 s.append(QLatin1Char(')')); 00242 } 00243 return s; 00244 } 00245 00246 QString KWindowInfo::visibleIconName() const 00247 { 00248 return visibleName(); 00249 } 00250 00251 QString KWindowInfo::iconName() const 00252 { 00253 return name(); 00254 } 00255 00256 bool KWindowInfo::isOnCurrentDesktop() const 00257 { 00258 return isOnDesktop( KWindowSystem::currentDesktop()); 00259 } 00260 00261 bool KWindowInfo::isOnDesktop( int _desktop ) const 00262 { 00263 return true; 00264 } 00265 00266 bool KWindowInfo::onAllDesktops() const 00267 { 00268 return false; 00269 } 00270 00271 int KWindowInfo::desktop() const 00272 { 00273 return 0; 00274 } 00275 00276 QRect KWindowInfo::geometry() const 00277 { 00278 return QRect(); 00279 } 00280 00281 QRect KWindowInfo::frameGeometry() const 00282 { 00283 return QRect(); 00284 } 00285 00286 bool KWindowInfo::actionSupported( NET::Action action ) const 00287 { 00288 return true; // no idea if it's supported or not -> pretend it is 00289 } 00290 00291 #if 0 00292 WId KWindowInfo::transientFor() const 00293 { 00294 kWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2TransientFor ) == 0, 176 ) 00295 << "Pass NET::WM2TransientFor to KWindowInfo"; 00296 return d->info->transientFor(); 00297 } 00298 00299 WId KWindowInfo::groupLeader() const 00300 { 00301 kWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2GroupLeader ) == 0, 176 ) 00302 << "Pass NET::WM2GroupLeader to KWindowInfo"; 00303 return d->info->groupLeader(); 00304 } 00305 00306 QByteArray KWindowInfo::windowClassClass() const 00307 { 00308 kWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass ) == 0, 176 ) 00309 << "Pass NET::WM2WindowClass to KWindowInfo"; 00310 return d->info->windowClassClass(); 00311 } 00312 00313 QByteArray KWindowInfo::windowClassName() const 00314 { 00315 kWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass ) == 0, 176 ) 00316 << "Pass NET::WM2WindowClass to KWindowInfo"; 00317 return d->info->windowClassName(); 00318 } 00319 00320 QByteArray KWindowInfo::windowRole() const 00321 { 00322 kWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowRole ) == 0, 176 ) 00323 << "Pass NET::WM2WindowRole to KWindowInfo"; 00324 return d->info->windowRole(); 00325 } 00326 00327 QByteArray KWindowInfo::clientMachine() const 00328 { 00329 kWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ClientMachine ) == 0, 176 ) 00330 << "Pass NET::WM2ClientMachine to KWindowInfo"; 00331 return d->info->clientMachine(); 00332 } 00333 00334 bool KWindowInfo::actionSupported( NET::Action action ) const 00335 { 00336 kWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2AllowedActions ) == 0, 176 ) 00337 << "Pass NET::WM2AllowedActions to KWindowInfo"; 00338 if( KWindowSystem::allowedActionsSupported()) 00339 return d->info->allowedActions() & action; 00340 else 00341 return true; // no idea if it's supported or not -> pretend it is 00342 } 00343 00344 // see NETWM spec section 7.6 00345 bool KWindowInfo::isMinimized() const 00346 { 00347 if( mappingState() != NET::Iconic ) 00348 return false; 00349 // NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows 00350 if(( state() & NET::Hidden ) != 0 00351 && ( state() & NET::Shaded ) == 0 ) // shaded may have NET::Hidden too 00352 return true; 00353 // older WMs use WithdrawnState for other virtual desktops 00354 // and IconicState only for minimized 00355 return KWindowSystem::icccmCompliantMappingState() ? false : true; 00356 } 00357 #endif
KDE 4.7 API Reference