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