Warning, file /frameworks/kwindowsystem/src/platforms/osx/kwindowinfo.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2008 Marijn Kruisselbrink <m.kruisselbrink@student.tue.nl> 0004 0005 SPDX-License-Identifier: LGPL-2.1-or-later 0006 */ 0007 0008 #include "kwindowinfo.h" 0009 #include "kwindowinfo_mac_p.h" 0010 #include "kwindowsystem.h" 0011 0012 #include <KXErrorHandler> 0013 #include <QBitmap> 0014 #include <QDebug> 0015 #include <QDesktopWidget> 0016 #include <QDialog> 0017 #include <netwm.h> 0018 0019 KWindowInfo::Private::Private() 0020 : ref(0) 0021 , win(0) 0022 , isLocal(false) 0023 , loadedData(false) 0024 , m_axWin(0) 0025 , parent() 0026 , m_pid(-1) 0027 { 0028 } 0029 0030 void KWindowInfo::Private::setAxElement(const AXUIElementRef &axWin) 0031 { 0032 m_axWin = axWin; 0033 CFRetain(m_axWin); 0034 } 0035 0036 void KWindowInfo::Private::setProcessSerialNumber(const ProcessSerialNumber &psn) 0037 { 0038 m_psn = psn; 0039 GetProcessPID(&psn, &m_pid); 0040 } 0041 0042 KWindowInfo::Private::~Private() 0043 { 0044 if (m_axWin) { 0045 CFRelease(m_axWin); 0046 } 0047 } 0048 0049 void KWindowInfo::Private::updateData() 0050 { 0051 ProcessInfoRec pinfo; 0052 char processName[512]; 0053 #ifdef Q_OS_MAC32 0054 FSSpec appSpec; 0055 #else 0056 FSRef ref; 0057 #endif 0058 pinfo.processInfoLength = sizeof pinfo; 0059 pinfo.processName = (unsigned char *)processName; 0060 #ifdef Q_OS_MAC32 0061 pinfo.processAppSpec = &appSpec; 0062 #else 0063 pinfo.processAppRef = &ref; 0064 #endif 0065 GetProcessInformation(&m_psn, &pinfo); 0066 name = QString::fromLatin1(processName + 1, processName[0]); 0067 0068 if (m_axWin) { 0069 CFStringRef title; 0070 if (AXUIElementCopyAttributeValue(m_axWin, kAXTitleAttribute, (CFTypeRef *)&title) == noErr) { 0071 CFStringGetCString(title, processName, sizeof processName, kCFStringEncodingUTF8); 0072 name = QString::fromUtf8(processName); 0073 } 0074 } 0075 0076 #ifdef Q_OS_MAC32 0077 iconSpec = appSpec; 0078 0079 FSRef ref; 0080 FSpMakeFSRef(&appSpec, &ref); 0081 #else 0082 iconSpec = ref; 0083 #endif 0084 // check if it is in an application bundle (foo.app/Contents/MacOS/plasma) 0085 HFSUniStr255 name; 0086 FSRef parentRef; 0087 FSGetCatalogInfo(&ref, kFSCatInfoNone, 0, &name, 0, &parentRef); 0088 ref = parentRef; 0089 FSGetCatalogInfo(&ref, kFSCatInfoNone, 0, &name, 0, &parentRef); 0090 if (QString::fromUtf16(name.unicode, name.length) == "MacOS") { 0091 ref = parentRef; 0092 FSGetCatalogInfo(&ref, kFSCatInfoNone, 0, &name, 0, &parentRef); 0093 if (QString::fromUtf16(name.unicode, name.length) == "Contents") { 0094 #ifdef Q_OS_MAC32 0095 FSSpec spec; 0096 ref = parentRef; 0097 FSGetCatalogInfo(&ref, kFSCatInfoNone, 0, &name, &spec, &parentRef); 0098 iconSpec = spec; 0099 #else 0100 iconSpec = parentRef; 0101 #endif 0102 } 0103 } 0104 0105 loadedData = true; 0106 } 0107 0108 KWindowInfo::KWindowInfo(WId win, unsigned long, unsigned long) 0109 : d(new Private) 0110 { 0111 d->ref = 1; 0112 d->win = win; 0113 d->isLocal = true; 0114 if (!win) { 0115 d->win = (WId)d; 0116 d->isLocal = false; 0117 } 0118 } 0119 0120 // this one is only to make QList<> or similar happy 0121 KWindowInfo::KWindowInfo() 0122 : d(nullptr) 0123 { 0124 } 0125 0126 KWindowInfo::~KWindowInfo() 0127 { 0128 if (d != nullptr) { 0129 if (--d->ref == 0) { 0130 delete d; 0131 } 0132 } 0133 } 0134 0135 KWindowInfo::KWindowInfo(const KWindowInfo &wininfo) 0136 : d(wininfo.d) 0137 { 0138 if (d != nullptr) { 0139 ++d->ref; 0140 } 0141 } 0142 0143 KWindowInfo &KWindowInfo::operator=(const KWindowInfo &wininfo) 0144 { 0145 if (d != wininfo.d) { 0146 if (d != nullptr) 0147 if (--d->ref == 0) { 0148 delete d; 0149 } 0150 d = wininfo.d; 0151 if (d != nullptr) { 0152 ++d->ref; 0153 } 0154 } 0155 return *this; 0156 } 0157 0158 bool KWindowInfo::valid(bool withdrawn_is_valid) const 0159 { 0160 return d->pid() >= 0; 0161 } 0162 0163 WId KWindowInfo::win() const 0164 { 0165 return d->win; 0166 } 0167 0168 unsigned long KWindowInfo::state() const 0169 { 0170 return 0; 0171 } 0172 0173 bool KWindowInfo::hasState(unsigned long s) const 0174 { 0175 return false; 0176 } 0177 0178 bool KWindowInfo::isMinimized() const 0179 { 0180 if (d->axElement()) { 0181 CFBooleanRef val; 0182 if (AXUIElementCopyAttributeValue(d->axElement(), kAXMinimizedAttribute, (CFTypeRef *)&val) == noErr) { 0183 return CFBooleanGetValue(val); 0184 } else { 0185 return false; 0186 } 0187 } else { 0188 return false; 0189 } 0190 } 0191 0192 NET::MappingState KWindowInfo::mappingState() const 0193 { 0194 return (NET::MappingState)0; 0195 } 0196 0197 NETExtendedStrut KWindowInfo::extendedStrut() const 0198 { 0199 NETExtendedStrut ext; 0200 return ext; 0201 } 0202 0203 NET::WindowType KWindowInfo::windowType(int supported_types) const 0204 { 0205 return (NET::WindowType)0; 0206 } 0207 0208 QString KWindowInfo::visibleNameWithState() const 0209 { 0210 QString s = visibleName(); 0211 if (isMinimized()) { 0212 s.prepend(QLatin1Char('(')); 0213 s.append(QLatin1Char(')')); 0214 } 0215 return s; 0216 } 0217 0218 QString KWindowInfo::visibleName() const 0219 { 0220 return name(); 0221 } 0222 0223 QString KWindowInfo::name() const 0224 { 0225 if (!d->loadedData) { 0226 d->updateData(); 0227 } 0228 return d->name; 0229 } 0230 0231 QString KWindowInfo::visibleIconNameWithState() const 0232 { 0233 QString s = visibleIconName(); 0234 if (isMinimized()) { 0235 s.prepend(QLatin1Char('(')); 0236 s.append(QLatin1Char(')')); 0237 } 0238 return s; 0239 } 0240 0241 QString KWindowInfo::visibleIconName() const 0242 { 0243 return visibleName(); 0244 } 0245 0246 QString KWindowInfo::iconName() const 0247 { 0248 return name(); 0249 } 0250 0251 bool KWindowInfo::isOnCurrentDesktop() const 0252 { 0253 return isOnDesktop(KWindowSystem::currentDesktop()); 0254 } 0255 0256 bool KWindowInfo::isOnDesktop(int _desktop) const 0257 { 0258 return true; 0259 } 0260 0261 bool KWindowInfo::onAllDesktops() const 0262 { 0263 return false; 0264 } 0265 0266 int KWindowInfo::desktop() const 0267 { 0268 return 0; 0269 } 0270 0271 QRect KWindowInfo::geometry() const 0272 { 0273 return QRect(); 0274 } 0275 0276 QRect KWindowInfo::frameGeometry() const 0277 { 0278 return QRect(); 0279 } 0280 0281 bool KWindowInfo::actionSupported(NET::Action action) const 0282 { 0283 return true; // no idea if it's supported or not -> pretend it is 0284 } 0285 0286 #if 0 0287 WId KWindowInfo::transientFor() const 0288 { 0289 kWarning((d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2TransientFor) == 0, 176) 0290 << "Pass NET::WM2TransientFor to KWindowInfo"; 0291 return d->info->transientFor(); 0292 } 0293 0294 WId KWindowInfo::groupLeader() const 0295 { 0296 kWarning((d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2GroupLeader) == 0, 176) 0297 << "Pass NET::WM2GroupLeader to KWindowInfo"; 0298 return d->info->groupLeader(); 0299 } 0300 0301 QByteArray KWindowInfo::windowClassClass() const 0302 { 0303 kWarning((d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass) == 0, 176) 0304 << "Pass NET::WM2WindowClass to KWindowInfo"; 0305 return d->info->windowClassClass(); 0306 } 0307 0308 QByteArray KWindowInfo::windowClassName() const 0309 { 0310 kWarning((d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass) == 0, 176) 0311 << "Pass NET::WM2WindowClass to KWindowInfo"; 0312 return d->info->windowClassName(); 0313 } 0314 0315 QByteArray KWindowInfo::windowRole() const 0316 { 0317 kWarning((d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowRole) == 0, 176) 0318 << "Pass NET::WM2WindowRole to KWindowInfo"; 0319 return d->info->windowRole(); 0320 } 0321 0322 QByteArray KWindowInfo::clientMachine() const 0323 { 0324 kWarning((d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ClientMachine) == 0, 176) 0325 << "Pass NET::WM2ClientMachine to KWindowInfo"; 0326 return d->info->clientMachine(); 0327 } 0328 0329 bool KWindowInfo::actionSupported(NET::Action action) const 0330 { 0331 kWarning((d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2AllowedActions) == 0, 176) 0332 << "Pass NET::WM2AllowedActions to KWindowInfo"; 0333 if (KWindowSystem::allowedActionsSupported()) { 0334 return d->info->allowedActions() & action; 0335 } else { 0336 return true; // no idea if it's supported or not -> pretend it is 0337 } 0338 } 0339 0340 // see NETWM spec section 7.6 0341 bool KWindowInfo::isMinimized() const 0342 { 0343 if (mappingState() != NET::Iconic) { 0344 return false; 0345 } 0346 // NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows 0347 if ((state() & NET::Hidden) != 0 0348 && (state() & NET::Shaded) == 0) { // shaded may have NET::Hidden too 0349 return true; 0350 } 0351 // older WMs use WithdrawnState for other virtual desktops 0352 // and IconicState only for minimized 0353 return KWindowSystem::icccmCompliantMappingState() ? false : true; 0354 } 0355 #endif