~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: VBoxUtils-darwin.cpp 35424 2011-01-07 13:05:41Z vboxsync $ */
 
2
/** @file
 
3
 * Qt GUI - Utility Classes and Functions specific to Darwin.
 
4
 */
 
5
 
 
6
/*
 
7
 * Copyright (C) 2006-2010 Oracle Corporation
 
8
 *
 
9
 * This file is part of VirtualBox Open Source Edition (OSE), as
 
10
 * available from http://www.virtualbox.org. This file is free software;
 
11
 * you can redistribute it and/or modify it under the terms of the GNU
 
12
 * General Public License (GPL) as published by the Free Software
 
13
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 
14
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 
15
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 
16
 */
 
17
 
 
18
#include "VBoxUtils-darwin.h"
 
19
#include "VBoxCocoaHelper.h"
 
20
#include "UICocoaApplication.h"
 
21
 
 
22
#include <iprt/mem.h>
 
23
 
 
24
#include <QMainWindow>
 
25
#include <QApplication>
 
26
#include <QWidget>
 
27
#include <QToolBar>
 
28
#include <QPainter>
 
29
#include <QPixmap>
 
30
#include <QContextMenuEvent>
 
31
 
 
32
#include <Carbon/Carbon.h>
 
33
 
 
34
#if QT_VERSION < 0x040400
 
35
extern void qt_mac_set_menubar_icons(bool b);
 
36
#endif /* QT_VERSION < 0x040400 */
 
37
 
 
38
NativeNSViewRef darwinToNativeView(QWidget *pWidget)
 
39
{
 
40
    if (pWidget)
 
41
        return reinterpret_cast<NativeNSViewRef>(pWidget->winId());
 
42
    return nil;
 
43
}
 
44
 
 
45
NativeNSWindowRef darwinToNativeWindow(QWidget *pWidget)
 
46
{
 
47
    if (pWidget)
 
48
        return ::darwinToNativeWindowImpl(::darwinToNativeView(pWidget));
 
49
    return nil;
 
50
}
 
51
 
 
52
NativeNSWindowRef darwinToNativeWindow(NativeNSViewRef aView)
 
53
{
 
54
    return ::darwinToNativeWindowImpl(aView);
 
55
}
 
56
 
 
57
NativeNSViewRef darwinToNativeView(NativeNSWindowRef aWindow)
 
58
{
 
59
    return ::darwinToNativeViewImpl(aWindow);
 
60
}
 
61
 
 
62
void darwinSetShowsToolbarButton(QToolBar *aToolBar, bool fEnabled)
 
63
{
 
64
    QWidget *parent = aToolBar->parentWidget();
 
65
    if (parent)
 
66
        ::darwinSetShowsToolbarButtonImpl(::darwinToNativeWindow(parent), fEnabled);
 
67
}
 
68
 
 
69
void darwinLabelWindow(QWidget *pWidget, QPixmap *pPixmap, bool fCenter)
 
70
{
 
71
    ::darwinLabelWindow(::darwinToNativeWindow(pWidget), ::darwinToNSImageRef(pPixmap), fCenter);
 
72
}
 
73
 
 
74
void darwinSetHidesAllTitleButtons(QWidget *pWidget)
 
75
{
 
76
#ifdef QT_MAC_USE_COCOA
 
77
    /* Currently only necessary in the Cocoa version */
 
78
    ::darwinSetHidesAllTitleButtonsImpl(::darwinToNativeWindow(pWidget));
 
79
#else /* QT_MAC_USE_COCOA */
 
80
    NOREF(pWidget);
 
81
#endif /* !QT_MAC_USE_COCOA */
 
82
}
 
83
 
 
84
void darwinSetShowsWindowTransparent(QWidget *pWidget, bool fEnabled)
 
85
{
 
86
    ::darwinSetShowsWindowTransparentImpl(::darwinToNativeWindow(pWidget), fEnabled);
 
87
}
 
88
 
 
89
void darwinWindowAnimateResize(QWidget *pWidget, const QRect &aTarget)
 
90
{
 
91
    ::darwinWindowAnimateResizeImpl(::darwinToNativeWindow(pWidget), aTarget.x(), aTarget.y(), aTarget.width(), aTarget.height());
 
92
}
 
93
 
 
94
void darwinWindowAnimateResizeNew(QWidget *pWidget, int h, bool fAnimate)
 
95
{
 
96
    ::darwinWindowAnimateResizeNewImpl(::darwinToNativeWindow(pWidget), h, fAnimate);
 
97
}
 
98
 
 
99
void darwinTest(QWidget *pWidget1, QWidget *pWidget2, int h)
 
100
{
 
101
    ::darwinTest(::darwinToNativeView(pWidget1), ::darwinToNativeView(pWidget2), h);
 
102
}
 
103
 
 
104
void darwinWindowInvalidateShape(QWidget *pWidget)
 
105
{
 
106
#ifdef QT_MAC_USE_COCOA
 
107
    /* Here a simple update is enough! */
 
108
    pWidget->update();
 
109
#else /* QT_MAC_USE_COCOA */
 
110
    ::darwinWindowInvalidateShapeImpl(::darwinToNativeWindow(pWidget));
 
111
#endif /* QT_MAC_USE_COCOA */
 
112
}
 
113
;
 
114
void darwinWindowInvalidateShadow(QWidget *pWidget)
 
115
{
 
116
#ifdef QT_MAC_USE_COCOA
 
117
    ::darwinWindowInvalidateShadowImpl(::darwinToNativeWindow(pWidget));
 
118
#else /* QT_MAC_USE_COCOA */
 
119
    NOREF(pWidget);
 
120
#endif /* QT_MAC_USE_COCOA */
 
121
}
 
122
 
 
123
void darwinSetShowsResizeIndicator(QWidget *pWidget, bool fEnabled)
 
124
{
 
125
    ::darwinSetShowsResizeIndicatorImpl(::darwinToNativeWindow(pWidget), fEnabled);
 
126
}
 
127
 
 
128
bool darwinIsWindowMaximized(QWidget *pWidget)
 
129
{
 
130
#ifdef QT_MAC_USE_COCOA
 
131
    /* Currently only necessary in the Cocoa version */
 
132
    return ::darwinIsWindowMaximized(::darwinToNativeWindow(pWidget));
 
133
#else /* QT_MAC_USE_COCOA */
 
134
    NOREF(pWidget);
 
135
    return false;
 
136
#endif /* !QT_MAC_USE_COCOA */
 
137
}
 
138
 
 
139
void darwinMinaturizeWindow(QWidget *pWidget)
 
140
{
 
141
    return ::darwinMinaturizeWindow(::darwinToNativeWindow(pWidget));
 
142
}
 
143
 
 
144
bool darwinOpenFile(const QString& strFile)
 
145
{
 
146
    return ::darwinOpenFile(darwinToNativeString(strFile.toUtf8().constData()));
 
147
}
 
148
 
 
149
QString darwinSystemLanguage(void)
 
150
{
 
151
    /* Get the locales supported by our bundle */
 
152
    CFArrayRef supportedLocales = ::CFBundleCopyBundleLocalizations(::CFBundleGetMainBundle());
 
153
    /* Check them against the languages currently selected by the user */
 
154
    CFArrayRef preferredLocales = ::CFBundleCopyPreferredLocalizationsFromArray(supportedLocales);
 
155
    /* Get the one which is on top */
 
156
    CFStringRef localeId = (CFStringRef)::CFArrayGetValueAtIndex(preferredLocales, 0);
 
157
    /* Convert them to a C-string */
 
158
    char localeName[20];
 
159
    ::CFStringGetCString(localeId, localeName, sizeof(localeName), kCFStringEncodingUTF8);
 
160
    /* Some cleanup */
 
161
    ::CFRelease(supportedLocales);
 
162
    ::CFRelease(preferredLocales);
 
163
    QString id(localeName);
 
164
    /* Check for some misbehavior */
 
165
    if (id.isEmpty() ||
 
166
        id.toLower() == "english")
 
167
        id = "en";
 
168
    return id;
 
169
}
 
170
 
 
171
void darwinDisableIconsInMenus(void)
 
172
{
 
173
    /* No icons in the menu of a mac application. */
 
174
#if QT_VERSION < 0x040400
 
175
    qt_mac_set_menubar_icons(false);
 
176
#else /* QT_VERSION < 0x040400 */
 
177
    /* Available since Qt 4.4 only */
 
178
    QApplication::instance()->setAttribute(Qt::AA_DontShowIconsInMenus, true);
 
179
#endif /* QT_VERSION >= 0x040400 */
 
180
}
 
181
 
 
182
int darwinWindowToolBarHeight(QWidget *pWidget)
 
183
{
 
184
#ifndef QT_MAC_USE_COCOA
 
185
    return ::darwinWindowToolBarHeight(::darwinToNativeWindow(pWidget));
 
186
#else /* QT_MAC_USE_COCOA */
 
187
    NOREF(pWidget);
 
188
    return 0;
 
189
#endif /* QT_MAC_USE_COCOA */
 
190
}
 
191
 
 
192
bool darwinIsToolbarVisible(QToolBar *pToolBar)
 
193
{
 
194
    bool fResult = false;
 
195
    QWidget *pParent = pToolBar->parentWidget();
 
196
    if (pParent)
 
197
        fResult = ::darwinIsToolbarVisible(::darwinToNativeWindow(pParent));
 
198
    return fResult;
 
199
}
 
200
 
 
201
 
 
202
bool darwinSetFrontMostProcess()
 
203
{
 
204
    ProcessSerialNumber psn = { 0, kCurrentProcess };
 
205
    return ::SetFrontProcess(&psn) == 0;
 
206
}
 
207
 
 
208
uint64_t darwinGetCurrentProcessId()
 
209
{
 
210
    uint64_t processId = 0;
 
211
    ProcessSerialNumber psn = { 0, kCurrentProcess };
 
212
    if (::GetCurrentProcess(&psn) == 0)
 
213
        processId = RT_MAKE_U64(psn.lowLongOfPSN, psn.highLongOfPSN);
 
214
    return processId;
 
215
}
 
216
 
 
217
CGContextRef darwinToCGContextRef(QWidget *pWidget)
 
218
{
 
219
    return static_cast<CGContext *>(pWidget->macCGHandle());
 
220
}
 
221
 
 
222
/* Proxy icon creation */
 
223
QPixmap darwinCreateDragPixmap(const QPixmap& aPixmap, const QString &aText)
 
224
{
 
225
    QFontMetrics fm(qApp->font());
 
226
    QRect tbRect = fm.boundingRect(aText);
 
227
    const int h = qMax(aPixmap.height(), fm.ascent() + 1);
 
228
    const int m = 2;
 
229
    QPixmap dragPixmap(aPixmap.width() + tbRect.width() + m, h);
 
230
    dragPixmap.fill(Qt::transparent);
 
231
    QPainter painter(&dragPixmap);
 
232
    painter.drawPixmap(0, qAbs(h - aPixmap.height()) / 2.0, aPixmap);
 
233
    painter.setPen(Qt::white);
 
234
    painter.drawText(QRect(aPixmap.width() + m, 1, tbRect.width(), h - 1), Qt::AlignLeft | Qt::AlignVCenter, aText);
 
235
    painter.setPen(Qt::black);
 
236
    painter.drawText(QRect(aPixmap.width() + m, 0, tbRect.width(), h - 1), Qt::AlignLeft | Qt::AlignVCenter, aText);
 
237
    painter.end();
 
238
    return dragPixmap;
 
239
}
 
240
 
 
241
/**
 
242
 * Callback for deleting the QImage object when CGImageCreate is done
 
243
 * with it (which is probably not until the returned CFGImageRef is released).
 
244
 *
 
245
 * @param   info        Pointer to the QImage.
 
246
 */
 
247
static void darwinDataProviderReleaseQImage(void *info, const void *, size_t)
 
248
{
 
249
    QImage *qimg = (QImage *)info;
 
250
    delete qimg;
 
251
}
 
252
 
 
253
/**
 
254
 * Converts a QPixmap to a CGImage.
 
255
 *
 
256
 * @returns CGImageRef for the new image. (Remember to release it when finished with it.)
 
257
 * @param   aPixmap     Pointer to the QPixmap instance to convert.
 
258
 */
 
259
CGImageRef darwinToCGImageRef(const QImage *pImage)
 
260
{
 
261
    QImage *imageCopy = new QImage(*pImage);
 
262
    /** @todo this code assumes 32-bit image input, the lazy bird convert image to 32-bit method is anything but optimal... */
 
263
    if (imageCopy->format() != QImage::Format_ARGB32)
 
264
        *imageCopy = imageCopy->convertToFormat(QImage::Format_ARGB32);
 
265
    Assert(!imageCopy->isNull());
 
266
 
 
267
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
 
268
    CGDataProviderRef dp = CGDataProviderCreateWithData(imageCopy, pImage->bits(), pImage->numBytes(), darwinDataProviderReleaseQImage);
 
269
 
 
270
    CGBitmapInfo bmpInfo = kCGImageAlphaFirst | kCGBitmapByteOrder32Host;
 
271
    CGImageRef ir = CGImageCreate(imageCopy->width(), imageCopy->height(), 8, 32, imageCopy->bytesPerLine(), cs,
 
272
                                   bmpInfo, dp, 0 /*decode */, 0 /* shouldInterpolate */,
 
273
                                   kCGRenderingIntentDefault);
 
274
    CGColorSpaceRelease(cs);
 
275
    CGDataProviderRelease(dp);
 
276
 
 
277
    Assert(ir);
 
278
    return ir;
 
279
}
 
280
 
 
281
/**
 
282
 * Converts a QPixmap to a CGImage.
 
283
 *
 
284
 * @returns CGImageRef for the new image. (Remember to release it when finished with it.)
 
285
 * @param   aPixmap     Pointer to the QPixmap instance to convert.
 
286
 */
 
287
CGImageRef darwinToCGImageRef(const QPixmap *pPixmap)
 
288
{
 
289
    /* It seems Qt releases the memory to an returned CGImageRef when the
 
290
     * associated QPixmap is destroyed. This shouldn't happen as long a
 
291
     * CGImageRef has a retrain count. As a workaround we make a real copy. */
 
292
    int bitmapBytesPerRow = pPixmap->width() * 4;
 
293
    int bitmapByteCount = (bitmapBytesPerRow * pPixmap->height());
 
294
    /* Create a memory block for the temporary image. It is initialized by zero
 
295
     * which means black & zero alpha. */
 
296
    void *pBitmapData = RTMemAllocZ(bitmapByteCount);
 
297
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
 
298
    /* Create a context to paint on */
 
299
    CGContextRef ctx = CGBitmapContextCreate(pBitmapData,
 
300
                                              pPixmap->width(),
 
301
                                              pPixmap->height(),
 
302
                                              8,
 
303
                                              bitmapBytesPerRow,
 
304
                                              cs,
 
305
                                              kCGImageAlphaPremultipliedFirst);
 
306
    /* Get the CGImageRef from Qt */
 
307
    CGImageRef qtPixmap = pPixmap->toMacCGImageRef();
 
308
    /* Draw the image from Qt & convert the context back to a new CGImageRef. */
 
309
    CGContextDrawImage(ctx, CGRectMake(0, 0, pPixmap->width(), pPixmap->height()), qtPixmap);
 
310
    CGImageRef newImage = CGBitmapContextCreateImage(ctx);
 
311
    /* Now release all used resources */
 
312
    CGImageRelease(qtPixmap);
 
313
    CGContextRelease(ctx);
 
314
    CGColorSpaceRelease(cs);
 
315
    RTMemFree(pBitmapData);
 
316
 
 
317
    /* Return the new CGImageRef */
 
318
    return newImage;
 
319
}
 
320
 
 
321
/**
 
322
 * Loads an image using Qt and converts it to a CGImage.
 
323
 *
 
324
 * @returns CGImageRef for the new image. (Remember to release it when finished with it.)
 
325
 * @param   aSource     The source name.
 
326
 */
 
327
CGImageRef darwinToCGImageRef(const char *pczSource)
 
328
{
 
329
    QPixmap qpm(QString(":/") + pczSource);
 
330
    Assert(!qpm.isNull());
 
331
    return ::darwinToCGImageRef(&qpm);
 
332
}
 
333
 
 
334
void darwinRegisterForUnifiedToolbarContextMenuEvents(QMainWindow *pWindow)
 
335
{
 
336
    UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(3) /* NSRightMouseDown */, ::darwinUnifiedToolbarEvents, pWindow);
 
337
}
 
338
 
 
339
void darwinUnregisterForUnifiedToolbarContextMenuEvents(QMainWindow *pWindow)
 
340
{
 
341
    UICocoaApplication::instance()->unregisterForNativeEvents(RT_BIT_32(3) /* NSRightMouseDown */, ::darwinUnifiedToolbarEvents, pWindow);
 
342
}
 
343
 
 
344
void darwinCreateContextMenuEvent(void *pvUser, int x, int y)
 
345
{
 
346
    QWidget *pWin = static_cast<QWidget*>(pvUser);
 
347
    QPoint global(x, y);
 
348
    QPoint local = pWin->mapFromGlobal(global);
 
349
    qApp->postEvent(pWin, new QContextMenuEvent(QContextMenuEvent::Mouse, local, global));
 
350
}
 
351
 
 
352
QString darwinResolveAlias(const QString &strFile)
 
353
{
 
354
    OSErr err = noErr;
 
355
    FSRef fileRef;
 
356
    QString strTarget;
 
357
    do
 
358
    {
 
359
        Boolean fDir;
 
360
        if ((err = FSPathMakeRef((const UInt8*)strFile.toUtf8().constData(), &fileRef, &fDir)) != noErr)
 
361
            break;
 
362
        Boolean fAlias = FALSE;
 
363
        if ((err = FSIsAliasFile(&fileRef, &fAlias, &fDir)) != noErr)
 
364
            break;
 
365
        if (fAlias == TRUE)
 
366
        {
 
367
            if ((err = FSResolveAliasFile(&fileRef, TRUE, &fAlias, &fDir)) != noErr)
 
368
                break;
 
369
            char pszPath[1024];
 
370
            if ((err = FSRefMakePath(&fileRef, (UInt8*)pszPath, 1024)) != noErr)
 
371
                break;
 
372
            strTarget = QString::fromUtf8(pszPath);
 
373
        }else
 
374
            strTarget = strFile;
 
375
    }while(0);
 
376
 
 
377
    return strTarget;
 
378
}
 
379
 
 
380
 
 
381
/********************************************************************************
 
382
 *
 
383
 * Old carbon stuff. Have to converted soon!
 
384
 *
 
385
 ********************************************************************************/
 
386
 
 
387
/* Event debugging stuff. Borrowed from Knuts Qt patch. */
 
388
#if defined (DEBUG)
 
389
 
 
390
# define MY_CASE(a) case a: return #a
 
391
const char * DarwinDebugEventName(UInt32 ekind)
 
392
{
 
393
    switch (ekind)
 
394
    {
 
395
# if !__LP64__
 
396
        MY_CASE(kEventWindowUpdate                );
 
397
        MY_CASE(kEventWindowDrawContent           );
 
398
# endif
 
399
        MY_CASE(kEventWindowActivated             );
 
400
        MY_CASE(kEventWindowDeactivated           );
 
401
        MY_CASE(kEventWindowHandleActivate        );
 
402
        MY_CASE(kEventWindowHandleDeactivate      );
 
403
        MY_CASE(kEventWindowGetClickActivation    );
 
404
        MY_CASE(kEventWindowGetClickModality      );
 
405
        MY_CASE(kEventWindowShowing               );
 
406
        MY_CASE(kEventWindowHiding                );
 
407
        MY_CASE(kEventWindowShown                 );
 
408
        MY_CASE(kEventWindowHidden                );
 
409
        MY_CASE(kEventWindowCollapsing            );
 
410
        MY_CASE(kEventWindowCollapsed             );
 
411
        MY_CASE(kEventWindowExpanding             );
 
412
        MY_CASE(kEventWindowExpanded              );
 
413
        MY_CASE(kEventWindowZoomed                );
 
414
        MY_CASE(kEventWindowBoundsChanging        );
 
415
        MY_CASE(kEventWindowBoundsChanged         );
 
416
        MY_CASE(kEventWindowResizeStarted         );
 
417
        MY_CASE(kEventWindowResizeCompleted       );
 
418
        MY_CASE(kEventWindowDragStarted           );
 
419
        MY_CASE(kEventWindowDragCompleted         );
 
420
        MY_CASE(kEventWindowClosed                );
 
421
        MY_CASE(kEventWindowTransitionStarted     );
 
422
        MY_CASE(kEventWindowTransitionCompleted   );
 
423
# if !__LP64__
 
424
        MY_CASE(kEventWindowClickDragRgn          );
 
425
        MY_CASE(kEventWindowClickResizeRgn        );
 
426
        MY_CASE(kEventWindowClickCollapseRgn      );
 
427
        MY_CASE(kEventWindowClickCloseRgn         );
 
428
        MY_CASE(kEventWindowClickZoomRgn          );
 
429
        MY_CASE(kEventWindowClickContentRgn       );
 
430
        MY_CASE(kEventWindowClickProxyIconRgn     );
 
431
        MY_CASE(kEventWindowClickToolbarButtonRgn );
 
432
        MY_CASE(kEventWindowClickStructureRgn     );
 
433
# endif
 
434
        MY_CASE(kEventWindowCursorChange          );
 
435
        MY_CASE(kEventWindowCollapse              );
 
436
        MY_CASE(kEventWindowCollapseAll           );
 
437
        MY_CASE(kEventWindowExpand                );
 
438
        MY_CASE(kEventWindowExpandAll             );
 
439
        MY_CASE(kEventWindowClose                 );
 
440
        MY_CASE(kEventWindowCloseAll              );
 
441
        MY_CASE(kEventWindowZoom                  );
 
442
        MY_CASE(kEventWindowZoomAll               );
 
443
        MY_CASE(kEventWindowContextualMenuSelect  );
 
444
        MY_CASE(kEventWindowPathSelect            );
 
445
        MY_CASE(kEventWindowGetIdealSize          );
 
446
        MY_CASE(kEventWindowGetMinimumSize        );
 
447
        MY_CASE(kEventWindowGetMaximumSize        );
 
448
        MY_CASE(kEventWindowConstrain             );
 
449
# if !__LP64__
 
450
        MY_CASE(kEventWindowHandleContentClick    );
 
451
# endif
 
452
        MY_CASE(kEventWindowGetDockTileMenu       );
 
453
        MY_CASE(kEventWindowProxyBeginDrag        );
 
454
        MY_CASE(kEventWindowProxyEndDrag          );
 
455
        MY_CASE(kEventWindowToolbarSwitchMode     );
 
456
        MY_CASE(kEventWindowFocusAcquired         );
 
457
        MY_CASE(kEventWindowFocusRelinquish       );
 
458
        MY_CASE(kEventWindowFocusContent          );
 
459
        MY_CASE(kEventWindowFocusToolbar          );
 
460
        MY_CASE(kEventWindowFocusDrawer           );
 
461
        MY_CASE(kEventWindowSheetOpening          );
 
462
        MY_CASE(kEventWindowSheetOpened           );
 
463
        MY_CASE(kEventWindowSheetClosing          );
 
464
        MY_CASE(kEventWindowSheetClosed           );
 
465
        MY_CASE(kEventWindowDrawerOpening         );
 
466
        MY_CASE(kEventWindowDrawerOpened          );
 
467
        MY_CASE(kEventWindowDrawerClosing         );
 
468
        MY_CASE(kEventWindowDrawerClosed          );
 
469
        MY_CASE(kEventWindowDrawFrame             );
 
470
        MY_CASE(kEventWindowDrawPart              );
 
471
        MY_CASE(kEventWindowGetRegion             );
 
472
        MY_CASE(kEventWindowHitTest               );
 
473
        MY_CASE(kEventWindowInit                  );
 
474
        MY_CASE(kEventWindowDispose               );
 
475
        MY_CASE(kEventWindowDragHilite            );
 
476
        MY_CASE(kEventWindowModified              );
 
477
        MY_CASE(kEventWindowSetupProxyDragImage   );
 
478
        MY_CASE(kEventWindowStateChanged          );
 
479
        MY_CASE(kEventWindowMeasureTitle          );
 
480
        MY_CASE(kEventWindowDrawGrowBox           );
 
481
        MY_CASE(kEventWindowGetGrowImageRegion    );
 
482
        MY_CASE(kEventWindowPaint                 );
 
483
    }
 
484
    static char s_sz[64];
 
485
    sprintf(s_sz, "kind=%u", (uint)ekind);
 
486
    return s_sz;
 
487
}
 
488
# undef MY_CASE
 
489
 
 
490
/* Convert a class into the 4 char code defined in
 
491
 * 'Developer/Headers/CFMCarbon/CarbonEvents.h' to
 
492
 * identify the event. */
 
493
const char * darwinDebugClassName(UInt32 eclass)
 
494
{
 
495
    char *pclass = (char*)&eclass;
 
496
    static char s_sz[11];
 
497
    sprintf(s_sz, "class=%c%c%c%c", pclass[3],
 
498
                                    pclass[2],
 
499
                                    pclass[1],
 
500
                                    pclass[0]);
 
501
    return s_sz;
 
502
}
 
503
 
 
504
void darwinDebugPrintEvent(const char *psz, EventRef evtRef)
 
505
{
 
506
  if (!evtRef)
 
507
      return;
 
508
  UInt32 ekind = GetEventKind(evtRef), eclass = GetEventClass(evtRef);
 
509
  if (eclass == kEventClassWindow)
 
510
  {
 
511
      switch (ekind)
 
512
      {
 
513
# if !__LP64__
 
514
          case kEventWindowDrawContent:
 
515
          case kEventWindowUpdate:
 
516
# endif
 
517
          case kEventWindowBoundsChanged:
 
518
              break;
 
519
          default:
 
520
          {
 
521
              WindowRef wid = NULL;
 
522
              GetEventParameter(evtRef, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &wid);
 
523
              QWidget *widget = QWidget::find((WId)wid);
 
524
              printf("%d %s: (%s) %#x win=%p wid=%p (%s)\n", (int)time(NULL), psz, darwinDebugClassName(eclass), (uint)ekind, wid, widget, DarwinDebugEventName(ekind));
 
525
              break;
 
526
          }
 
527
      }
 
528
  }
 
529
  else if (eclass == kEventClassCommand)
 
530
  {
 
531
      WindowRef wid = NULL;
 
532
      GetEventParameter(evtRef, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &wid);
 
533
      QWidget *widget = QWidget::find((WId)wid);
 
534
      const char *name = "Unknown";
 
535
      switch (ekind)
 
536
      {
 
537
          case kEventCommandProcess:
 
538
              name = "kEventCommandProcess";
 
539
              break;
 
540
          case kEventCommandUpdateStatus:
 
541
              name = "kEventCommandUpdateStatus";
 
542
              break;
 
543
      }
 
544
      printf("%d %s: (%s) %#x win=%p wid=%p (%s)\n", (int)time(NULL), psz, darwinDebugClassName(eclass), (uint)ekind, wid, widget, name);
 
545
  }
 
546
  else if (eclass == kEventClassKeyboard)
 
547
  {
 
548
      printf("%d %s: %#x(%s) %#x (kEventClassKeyboard)", (int)time(NULL), psz, (uint)eclass, darwinDebugClassName(eclass), (uint)ekind);
 
549
 
 
550
      UInt32 keyCode = 0;
 
551
      ::GetEventParameter(evtRef, kEventParamKeyCode, typeUInt32, NULL,
 
552
                           sizeof(keyCode), NULL, &keyCode);
 
553
      printf(" keyCode=%d (%#x) ", (int)keyCode, (unsigned)keyCode);
 
554
 
 
555
      char macCharCodes[8] = {0,0,0,0, 0,0,0,0};
 
556
      ::GetEventParameter(evtRef, kEventParamKeyCode, typeChar, NULL,
 
557
                           sizeof(macCharCodes), NULL, &macCharCodes[0]);
 
558
      printf(" macCharCodes={");
 
559
      for (unsigned i =0; i < 8 && macCharCodes[i]; i++)
 
560
          printf( i == 0 ? "%02x" : ",%02x", macCharCodes[i]);
 
561
      printf("}");
 
562
 
 
563
      UInt32 modifierMask = 0;
 
564
      ::GetEventParameter(evtRef, kEventParamKeyModifiers, typeUInt32, NULL,
 
565
                           sizeof(modifierMask), NULL, &modifierMask);
 
566
      printf(" modifierMask=%08x", (unsigned)modifierMask);
 
567
 
 
568
      UniChar keyUnicodes[8] = {0,0,0,0, 0,0,0,0};
 
569
      ::GetEventParameter(evtRef, kEventParamKeyUnicodes, typeUnicodeText, NULL,
 
570
                           sizeof(keyUnicodes), NULL, &keyUnicodes[0]);
 
571
      printf(" keyUnicodes={");
 
572
      for (unsigned i =0; i < 8 && keyUnicodes[i]; i++)
 
573
          printf( i == 0 ? "%02x" : ",%02x", keyUnicodes[i]);
 
574
      printf("}");
 
575
 
 
576
      UInt32 keyboardType = 0;
 
577
      ::GetEventParameter(evtRef, kEventParamKeyboardType, typeUInt32, NULL,
 
578
                           sizeof(keyboardType), NULL, &keyboardType);
 
579
      printf(" keyboardType=%08x", (unsigned)keyboardType);
 
580
 
 
581
      EventHotKeyID evtHotKeyId = {0,0};
 
582
      ::GetEventParameter(evtRef, typeEventHotKeyID, typeEventHotKeyID, NULL,
 
583
                           sizeof(evtHotKeyId), NULL, &evtHotKeyId);
 
584
      printf(" evtHotKeyId={signature=%08x, .id=%08x}", (unsigned)evtHotKeyId.signature, (unsigned)evtHotKeyId.id);
 
585
      printf("\n");
 
586
  }
 
587
  else
 
588
      printf("%d %s: %#x(%s) %#x\n", (int)time(NULL), psz, (uint)eclass, darwinDebugClassName(eclass), (uint)ekind);
 
589
}
 
590
 
 
591
#endif /* DEBUG */
 
592