23 #include "kwindowinfo_mac_p.h"
28 #include <QtGui/QBitmap>
29 #include <QDesktopWidget>
30 #include <QtGui/QDialog>
31 #include <QtDBus/QtDBus>
34 #include <Carbon/Carbon.h>
42 static bool operator<(
const ProcessSerialNumber& a,
const ProcessSerialNumber& b)
44 if (a.lowLongOfPSN != b.lowLongOfPSN)
return a.lowLongOfPSN < b.lowLongOfPSN;
45 return a.highLongOfPSN < b.highLongOfPSN;
48 class KWindowSystemPrivate :
QObject
50 #ifdef EXPERIMENTAL_WINDOW_TRACKING
54 KWindowSystemPrivate();
61 #ifdef EXPERIMENTAL_WINDOW_TRACKING
62 QList<KWindowInfo> nonProcessedWindows;
65 EventTargetRef m_eventTarget;
66 EventHandlerUPP m_eventHandler;
67 EventTypeSpec m_eventType[2];
68 EventHandlerRef m_curHandler;
70 void applicationLaunched(
const ProcessSerialNumber& psn);
71 void applicationTerminated(
const ProcessSerialNumber& psn);
76 #ifdef EXPERIMENTAL_WINDOW_TRACKING
77 void newWindow(AXUIElementRef element,
void* windowInfoPrivate);
78 void windowClosed(AXUIElementRef element,
void* windowInfoPrivate);
81 static KWindowSystemPrivate*
self() {
return KWindowSystem::s_d_func(); }
82 #ifdef EXPERIMENTAL_WINDOW_TRACKING
84 void tryRegisterProcess();
88 class KWindowSystemStaticContainer {
90 KWindowSystemStaticContainer() : d (new KWindowSystemPrivate) { }
92 KWindowSystemPrivate* d;
99 KWindowSystemPrivate* d = (KWindowSystemPrivate*) inUserData;
103 kind = GetEventKind(inEvent);
104 ProcessSerialNumber psn;
105 if (GetEventParameter(inEvent, kEventParamProcessID, typeProcessSerialNumber, NULL,
sizeof psn, NULL, &psn) != noErr) {
106 kWarning() <<
"Error getting event parameter in application event";
107 return eventNotHandledErr;
110 if (kind == kEventAppLaunched) {
111 d->applicationLaunched(psn);
112 }
else if (kind == kEventAppTerminated) {
113 d->applicationTerminated(psn);
119 #ifdef EXPERIMENTAL_WINDOW_TRACKING
120 static void windowClosedObserver(AXObserverRef observer, AXUIElementRef element, CFStringRef notification,
void* refcon)
122 KWindowSystemPrivate::self()->windowClosed(element, refcon);
125 static void newWindowObserver(AXObserverRef observer, AXUIElementRef element, CFStringRef notification,
void* refcon)
127 KWindowSystemPrivate::self()->newWindow(element, refcon);
131 KWindowSystemPrivate::KWindowSystemPrivate()
132 :
QObject(0), m_noEmit(true), waitingForTimer(false)
135 ProcessSerialNumber psn = {0, kNoProcess};
136 while (GetNextProcess(&psn) == noErr) {
137 kDebug(240) <<
"calling appLaunched for " << psn.lowLongOfPSN <<
":" << psn.highLongOfPSN;
138 applicationLaunched(psn);
145 m_eventTarget = GetApplicationEventTarget();
147 m_eventType[0].eventClass = kEventClassApplication;
148 m_eventType[0].eventKind = kEventAppLaunched;
149 m_eventType[1].eventClass = kEventClassApplication;
150 m_eventType[1].eventKind = kEventAppTerminated;
151 if (InstallEventHandler(m_eventTarget, m_eventHandler, 2, m_eventType,
this, &m_curHandler) != noErr) {
152 kDebug(240) <<
"Installing event handler failed!\n";
155 #warning port me to Mac64
159 void KWindowSystemPrivate::applicationLaunched(
const ProcessSerialNumber& psn) {
161 kDebug(240) <<
"new app: " << psn.lowLongOfPSN <<
":" << psn.highLongOfPSN;
162 ProcessInfoRec pinfo;
164 pinfo.processInfoLength =
sizeof pinfo;
165 pinfo.processName = 0;
166 pinfo.processAppSpec = &appSpec;
167 GetProcessInformation(&psn, &pinfo);
168 if ((pinfo.processMode & modeOnlyBackground) != 0)
return;
172 windows[winfo.win()] = winfo;
173 winids.append(winfo.win());
174 winfo.d->setProcessSerialNumber(psn);
175 pid_t pid = winfo.d->pid();
176 processes[psn] = winfo.win();
177 kDebug(240) <<
" pid:" << pid;
178 AXUIElementRef app = AXUIElementCreateApplication(pid);
179 winfo.d->setAxElement(app);
182 #ifdef EXPERIMENTAL_WINDOW_TRACKING
184 AXObserverRef observer, newObserver;
186 if (AXObserverCreate(pid, windowClosedObserver, &observer) == noErr) {
187 CFRunLoopAddSource(CFRunLoopGetCurrent(), AXObserverGetRunLoopSource(observer), kCFRunLoopCommonModes);
188 windowClosedObservers[pid] = observer;
190 if ((err = AXObserverCreate(pid, newWindowObserver, &newObserver)) == noErr) {
191 CFRunLoopAddSource(CFRunLoopGetCurrent(), AXObserverGetRunLoopSource(newObserver), kCFRunLoopCommonModes);
192 newWindowObservers[pid] = newObserver;
193 if ((err = AXObserverAddNotification(newObserver, app, kAXWindowCreatedNotification, winfo.d)) != noErr) {
194 kDebug(240) <<
"Error " << err <<
" adding notification to observer";
197 QTimer::singleShot(500,
this, SLOT(tryRegisterProcess()));
198 nonProcessedWindows.append(winfo);
201 kDebug(240) <<
"Added notification and observer";
203 kDebug(240) <<
"Error creating observer";
207 CFIndex windowsInApp;
208 AXUIElementGetAttributeValueCount(app, kAXWindowsAttribute, &windowsInApp);
210 AXUIElementCopyAttributeValue(app, kAXWindowsAttribute, (CFTypeRef*)&array);
211 for (CFIndex j = 0; j < windowsInApp; j++) {
212 AXUIElementRef win = (AXUIElementRef) CFArrayGetValueAtIndex(array, j);
213 newWindow(win, winfo.d);
217 #warning Port me to Mac64
221 #ifdef EXPERIMENTAL_WINDOW_TRACKING
222 void KWindowSystemPrivate::tryRegisterProcess()
224 kDebug(240) <<
"Single-shot timer, trying to register processes";
225 while (!nonProcessedWindows.empty()) {
226 KWindowInfo winfo = nonProcessedWindows.takeLast();
227 pid_t pid = winfo.d->pid();
228 AXUIElementRef app = winfo.d->axElement();
229 ProcessSerialNumber psn = winfo.d->psn();
232 AXObserverRef observer;
234 observer = newWindowObservers[pid];
235 if ((err = AXObserverAddNotification(observer, app, kAXWindowCreatedNotification, winfo.d)) != noErr) {
236 kDebug(240) <<
"Error " << err <<
" adding notification to observer";
238 kDebug(240) <<
"Added notification and observer";
240 observer = windowClosedObservers[pid];
242 CFIndex windowsInApp;
243 AXUIElementGetAttributeValueCount(app, kAXWindowsAttribute, &windowsInApp);
245 AXUIElementCopyAttributeValue(app, kAXWindowsAttribute, (CFTypeRef*)&array);
246 for (CFIndex j = 0; j < windowsInApp; j++) {
247 AXUIElementRef win = (AXUIElementRef) CFArrayGetValueAtIndex(array, j);
248 newWindow(win, winfo.d);
254 void KWindowSystemPrivate::applicationTerminated(
const ProcessSerialNumber& psn)
256 kDebug(240) <<
"Terminated PSN: " << psn.lowLongOfPSN <<
":" << psn.highLongOfPSN;
257 WId
id = processes[psn];
258 if (windows.contains(
id)) {
260 foreach (KWindowInfo::Private* wi, winfo.d->children) {
261 winids.removeAll(wi->win);
264 winids.removeAll(
id);
269 #ifdef EXPERIMENTAL_WINDOW_TRACKING
270 void KWindowSystemPrivate::windowClosed(AXUIElementRef element,
void* refcon)
272 kDebug(240) <<
"Received window closed notification";
274 KWindowInfo::Private* wind = (KWindowInfo::Private*) refcon;
275 KWindowInfo::Private* parent = wind->parent;
276 parent->children.removeAll(wind);
277 winids.removeAll(wind->win);
281 void KWindowSystemPrivate::newWindow(AXUIElementRef win,
void* refcon)
283 kDebug(240) <<
"Received new window notification";
285 KWindowInfo::Private* winfod = (KWindowInfo::Private*) refcon;
286 pid_t pid = winfod->pid();
287 ProcessSerialNumber psn = winfod->psn();
288 AXObserverRef observer = windowClosedObservers[pid];
292 if (AXObserverAddNotification(observer, win, kAXUIElementDestroyedNotification, win2.d) != noErr) {
294 kDebug(240)
"error adding closed observer to window.";
298 windows[win2.win()] = win2;
299 winids.append(win2.win());
300 win2.d->setProcessSerialNumber(psn);
301 win2.d->setAxElement(win);
302 winfod->children.append(win2.d);
303 win2.d->parent = winfod;
310 return &(g_kwmInstanceContainer->kwm);
313 KWindowSystemPrivate* KWindowSystem::s_d_func()
315 return g_kwmInstanceContainer->d;
327 return d->windows.contains(
id);
333 if (d->windows.contains(win)) {
334 return d->windows[win];
336 return KWindowInfo( win, properties, properties2 );
344 kDebug(240) <<
"QList<WId> KWindowSystem::stackingOrder() isn't yet implemented!";
351 kDebug(240) <<
"WId KWindowSystem::activeWindow() isn't yet implemented!";
358 kDebug(240) <<
"KWindowSystem::activateWindow( WId win, long time )isn't yet implemented!";
360 if (d->windows.contains(win)) {
361 ProcessSerialNumber psn = d->windows[win].d->psn();
362 SetFrontProcess(&psn);
369 kDebug(240) <<
"KWindowSystem::forceActiveWindow( WId win, long time ) isn't yet implemented!";
376 kDebug(240) <<
"KWindowSystem::demandAttention( WId win, bool set ) isn't yet implemented!";
396 kDebug(240) <<
"KWindowSystem::setCurrentDesktop( int desktop ) isn't yet implemented!";
402 kDebug(240) <<
"KWindowSystem::setOnAllDesktops( WId win, bool b ) isn't yet implemented!";
409 kDebug(240) <<
"KWindowSystem::setOnDesktop( WId win, int desktop ) isn't yet implemented!";
414 kDebug(240) <<
"KWindowSystem::setMainWindow( QWidget*, WId ) isn't yet implemented!";
422 if (!info.d->loadedData) {
423 info.d->updateData();
428 OSErr err = GetIconRefFromFile(&info.d->iconSpec, &icon, &label);
430 OSStatus err = GetIconRefFromFileInfo(&info.d->iconSpec, 0, 0,
431 kIconServicesCatalogInfoMask, 0, kIconServicesNormalUsageFlag, &icon, &label);
434 kDebug(240) <<
"Error getting icon from application";
437 QPixmap ret(width, height);
438 ret.fill(
QColor(0, 0, 0, 0));
440 CGRect rect = CGRectMake(0, 0, width, height);
442 CGContextRef ctx = qt_mac_cg_context(&ret);
443 CGAffineTransform old_xform = CGContextGetCTM(ctx);
444 CGContextConcatCTM(ctx, CGAffineTransformInvert(old_xform));
445 CGContextConcatCTM(ctx, CGAffineTransformIdentity);
448 b.blue = b.green = b.red = 255*255;
449 PlotIconRefInContext(ctx, &rect, kAlignNone, kTransformNone, &b, kPlotIconRefNormalFlags, icon);
450 CGContextRelease(ctx);
452 ReleaseIconRef(icon);
456 kDebug(240) <<
"QPixmap KWindowSystem::icon( WId win, int width, int height, bool scale ) isn't yet implemented for local windows!";
463 return icon(win, width, height, scale);
470 kDebug(240) <<
"KWindowSystem::setIcons( WId win, const QPixmap& icon, const QPixmap& miniIcon ) isn't yet implemented!";
477 if (
hasWId(winid))
return;
479 static WindowGroupRef desktopGroup = 0;
480 static WindowGroupRef dockGroup = 0;
482 WindowRef win = HIViewGetWindow( (HIViewRef) winid );
485 kDebug(240) <<
"setType( WId win, NET::WindowType windowType ) isn't yet implemented for the type you requested!";
489 CreateWindowGroup(0, &desktopGroup);
490 SetWindowGroupLevel(desktopGroup, kCGDesktopIconWindowLevel);
492 SetWindowGroup(win, desktopGroup);
495 CreateWindowGroup(0, &dockGroup);
496 SetWindowGroupLevel(dockGroup, kCGDockWindowLevel);
498 SetWindowGroup(win, dockGroup);
499 ChangeWindowAttributes(win, kWindowNoTitleBarAttribute, kWindowNoAttributes);
502 #warning port me to Mac64
509 kDebug(240) <<
"KWindowSystem::setState( WId win, unsigned long state ) isn't yet implemented!";
515 kDebug(240) <<
"KWindowSystem::clearState( WId win, unsigned long state ) isn't yet implemented!";
521 kDebug(240) <<
"KWindowSystem::minimizeWindow( WId win, bool animation) isn't yet implemented!";
527 kDebug(240) <<
"KWindowSystem::unminimizeWindow( WId win, bool animation ) isn't yet implemented!";
533 kDebug(240) <<
"KWindowSystem::raiseWindow( WId win ) isn't yet implemented!";
539 kDebug(240) <<
"KWindowSystem::lowerWindow( WId win ) isn't yet implemented!";
550 kDebug(240) <<
"QRect KWindowSystem::workArea( int desktop ) isn't yet implemented!";
557 kDebug(240) <<
"QRect KWindowSystem::workArea( const QList<WId>& exclude, int desktop ) isn't yet implemented!";
563 return i18n(
"Desktop %1", desktop );
568 kDebug(240) <<
"KWindowSystem::setDesktopName( int desktop, const QString& name ) isn't yet implemented!";
579 kDebug(240) <<
"KWindowSystem::setUserTime( WId win, long time ) isn't yet implemented!";
584 int right_width,
int right_start,
int right_end,
int top_width,
int top_start,
int top_end,
585 int bottom_width,
int bottom_start,
int bottom_end )
587 kDebug(240) <<
"KWindowSystem::setExtendedStrut isn't yet implemented!";
593 kDebug(240) <<
"KWindowSystem::setStrut isn't yet implemented!";
605 kDebug(240) <<
"QString KWindowSystem::readNameProperty( WId window, unsigned long atom ) isn't yet implemented!";
612 kDebug(240) <<
"KWindowSystem::doNotManage( const QString& title ) isn't yet implemented!";
618 kDebug(240) <<
"connectNotify( const char* signal ) isn't yet implemented!";
630 kDebug() <<
"setBlockingCompositing( WId window, bool active ) isn't yet implemented!";
633 #include "moc_kwindowsystem.cpp"