1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** As a special exception, The Qt Company gives you certain additional
27** rights. These rights are described in The Qt Company LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** GNU General Public License Usage
31** Alternatively, this file may be used under the terms of the GNU
32** General Public License version 3.0 as published by the Free Software
33** Foundation and appearing in the file LICENSE.GPL included in the
34** packaging of this file.  Please review the following information to
35** ensure the GNU General Public License version 3.0 requirements will be
36** met: http://www.gnu.org/copyleft/gpl.html.
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/****************************************************************************
43**
44** Copyright (c) 2007-2008, Apple, Inc.
45**
46** All rights reserved.
47**
48** Redistribution and use in source and binary forms, with or without
49** modification, are permitted provided that the following conditions are met:
50**
51**   * Redistributions of source code must retain the above copyright notice,
52**     this list of conditions and the following disclaimer.
53**
54**   * Redistributions in binary form must reproduce the above copyright notice,
55**     this list of conditions and the following disclaimer in the documentation
56**     and/or other materials provided with the distribution.
57**
58**   * Neither the name of Apple, Inc. nor the names of its contributors
59**     may be used to endorse or promote products derived from this software
60**     without specific prior written permission.
61**
62** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
63** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
64** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
65** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
66** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
67** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
68** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
69** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
70** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
71** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
72** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73**
74****************************************************************************/
75
76#include <Cocoa/Cocoa.h>
77
78#include "qapplication.h"
79#include "qbitarray.h"
80#include "qclipboard.h"
81#include "qcursor.h"
82#include "qdatastream.h"
83#include "qdatetime.h"
84#include "qdesktopwidget.h"
85#include "qdockwidget.h"
86#include "qevent.h"
87#include "qhash.h"
88#include "qlayout.h"
89#include "qmenubar.h"
90#include "qmessagebox.h"
91#include "qmime.h"
92#include "qpixmapcache.h"
93#include "qpointer.h"
94#include "qsessionmanager.h"
95#include "qsettings.h"
96#include "qsocketnotifier.h"
97#include "qstyle.h"
98#include "qstylefactory.h"
99#include "qtextcodec.h"
100#include "qtoolbar.h"
101#include "qvariant.h"
102#include "qwidget.h"
103#include "qcolormap.h"
104#include "qdir.h"
105#include "qdebug.h"
106#include "qtimer.h"
107#include "qurl.h"
108#include "private/qmacinputcontext_p.h"
109#include "private/qpaintengine_mac_p.h"
110#include "private/qcursor_p.h"
111#include "private/qapplication_p.h"
112#include "private/qcolor_p.h"
113#include "private/qwidget_p.h"
114#include "private/qkeymapper_p.h"
115#include "private/qeventdispatcher_mac_p.h"
116#include "private/qeventdispatcher_unix_p.h"
117#include <private/qcocoamenuloader_mac_p.h>
118#include <private/qcocoaapplication_mac_p.h>
119#include <private/qcocoaapplicationdelegate_mac_p.h>
120#include <private/qt_cocoa_helpers_mac_p.h>
121#include <private/qcocoawindow_mac_p.h>
122#include <private/qpixmap_mac_p.h>
123#include <private/qdesktopwidget_mac_p.h>
124#include <private/qeventdispatcher_mac_p.h>
125#include <qvarlengtharray.h>
126
127#ifndef QT_NO_ACCESSIBILITY
128#  include "qaccessible.h"
129#endif
130
131#ifndef QT_NO_THREAD
132#  include "qmutex.h"
133#endif
134
135#include <unistd.h>
136#include <string.h>
137#include <sys/time.h>
138#include <sys/select.h>
139
140/*****************************************************************************
141  QApplication debug facilities
142 *****************************************************************************/
143//#define DEBUG_EVENTS //like EventDebug but more specific to Qt
144//#define DEBUG_DROPPED_EVENTS
145//#define DEBUG_MOUSE_MAPS
146//#define DEBUG_MODAL_EVENTS
147//#define DEBUG_PLATFORM_SETTINGS
148
149#define QMAC_SPEAK_TO_ME
150#ifdef QMAC_SPEAK_TO_ME
151#include "qregexp.h"
152#endif
153
154#ifndef kThemeBrushAlternatePrimaryHighlightColor
155#define kThemeBrushAlternatePrimaryHighlightColor -5
156#endif
157
158#define kCMDeviceUnregisteredNotification CFSTR("CMDeviceUnregisteredNotification")
159#define kCMDefaultDeviceNotification CFSTR("CMDefaultDeviceNotification")
160#define kCMDeviceProfilesNotification CFSTR("CMDeviceProfilesNotification")
161#define kCMDefaultDeviceProfileNotification CFSTR("CMDefaultDeviceProfileNotification")
162
163QT_BEGIN_NAMESPACE
164
165//for qt_mac.h
166QPaintDevice *qt_mac_safe_pdev = 0;
167QList<QMacWindowChangeEvent*> *QMacWindowChangeEvent::change_events = 0;
168QPointer<QWidget> topLevelAt_cache = 0;
169
170/*****************************************************************************
171  Internal variables and functions
172 *****************************************************************************/
173static struct {
174    bool use_qt_time_limit;
175    QPointer<QWidget> last_widget;
176    int last_x, last_y;
177    int last_modifiers, last_button;
178    EventTime last_time;
179} qt_mac_dblclick = { false, 0, -1, -1, 0, 0, -2 };
180
181static bool app_do_modal = false;       // modal mode
182extern QWidgetList *qt_modal_stack;     // stack of modal widgets
183extern bool qt_tab_all_widgets;         // from qapplication.cpp
184bool qt_mac_app_fullscreen = false;
185bool qt_scrollbar_jump_to_pos = false;
186static bool qt_mac_collapse_on_dblclick = true;
187extern int qt_antialiasing_threshold; // from qapplication.cpp
188QWidget * qt_button_down;                // widget got last button-down
189QPointer<QWidget> qt_last_mouse_receiver;
190#ifndef QT_MAC_USE_COCOA
191static bool qt_button_down_in_content; // whether the button_down was in the content area.
192static bool qt_mac_previous_press_in_popup_mode = false;
193static bool qt_mac_no_click_through_mode = false;
194static int tablet_button_state = 0;
195#endif
196#if defined(QT_DEBUG)
197static bool        appNoGrab        = false;        // mouse/keyboard grabbing
198#endif
199#ifndef QT_MAC_USE_COCOA
200static EventHandlerRef app_proc_handler = 0;
201static EventHandlerUPP app_proc_handlerUPP = 0;
202#endif
203static AEEventHandlerUPP app_proc_ae_handlerUPP = NULL;
204static EventHandlerRef tablet_proximity_handler = 0;
205static EventHandlerUPP tablet_proximity_UPP = 0;
206bool QApplicationPrivate::native_modal_dialog_active;
207
208Q_GUI_EXPORT bool qt_applefontsmoothing_enabled;
209
210/*****************************************************************************
211  External functions
212 *****************************************************************************/
213extern void qt_mac_beep(); //qsound_mac.mm
214extern Qt::KeyboardModifiers qt_mac_get_modifiers(int keys); //qkeymapper_mac.cpp
215extern bool qt_mac_can_clickThrough(const QWidget *); //qwidget_mac.cpp
216extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
217extern OSWindowRef qt_mac_window_for(const QWidget*); //qwidget_mac.cpp
218extern QWidget *qt_mac_find_window(OSWindowRef); //qwidget_mac.cpp
219extern void qt_mac_set_cursor(const QCursor *); //qcursor_mac.cpp
220extern bool qt_mac_is_macsheet(const QWidget *); //qwidget_mac.cpp
221extern void qt_mac_command_set_enabled(MenuRef, UInt32, bool); //qmenu_mac.cpp
222extern bool qt_sendSpontaneousEvent(QObject *obj, QEvent *event); // qapplication.cpp
223extern void qt_mac_update_cursor(); // qcursor_mac.mm
224
225// Forward Decls
226void onApplicationWindowChangedActivation( QWidget*widget, bool activated );
227void onApplicationChangedActivation( bool activated );
228
229#ifdef QT_MAC_USE_COCOA
230void qt_mac_loadMenuNib(QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader)
231{
232    // Create qt_menu.nib dir in temp.
233    QDir temp = QDir::temp();
234    temp.mkdir("qt_menu.nib");
235    QString nibDir = temp.canonicalPath() + QLatin1String("/") + QLatin1String("qt_menu.nib/");
236    if (!QDir(nibDir).exists()) {
237        qWarning("qt_mac_loadMenuNib: could not create nib directory in temp");
238        return;
239    }
240
241    // Copy nib files from resources to temp.
242    QDir nibResource(":/trolltech/mac/qt_menu.nib/");
243    if (!nibResource.exists()) {
244        qWarning("qt_mac_loadMenuNib: could not load nib from resources");
245        return;
246    }
247    foreach (const QFileInfo &file, nibResource.entryInfoList())
248        QFile::copy(file.absoluteFilePath(), nibDir + QLatin1String("/") + file.fileName());
249
250    // Load and instantiate nib file from temp
251    NSURL *nibUrl = [NSURL fileURLWithPath : const_cast<NSString *>(reinterpret_cast<const NSString *>(QCFString::toCFStringRef(nibDir)))];
252    NSNib *nib = [[NSNib alloc] initWithContentsOfURL : nibUrl];
253    [nib autorelease];
254    if (!nib) {
255        qWarning("qt_mac_loadMenuNib: could not load nib from temp");
256        return;
257    }
258    bool ok = [nib instantiateNibWithOwner : qtMenuLoader topLevelObjects : nil];
259    if (!ok)
260        qWarning("qt_mac_loadMenuNib: could not instantiate nib");
261}
262#endif
263
264static void qt_mac_read_fontsmoothing_settings()
265{
266    qt_applefontsmoothing_enabled = true;
267    int w = 10, h = 10;
268    QImage image(w, h, QImage::Format_RGB32);
269    image.fill(0xffffffff);
270    QPainter p(&image);
271    p.drawText(0, h, "X\\");
272    p.end();
273
274    const int *bits = (const int *) ((const QImage &) image).bits();
275    int bpl = image.bytesPerLine() / 4;
276    for (int y=0; y<w; ++y) {
277        for (int x=0; x<h; ++x) {
278            int r = qRed(bits[x]);
279            int g = qGreen(bits[x]);
280            int b = qBlue(bits[x]);
281            if (r != g || r != b) {
282                qt_applefontsmoothing_enabled = true;
283                return;
284            }
285        }
286        bits += bpl;
287    }
288    qt_applefontsmoothing_enabled = false;
289}
290
291Q_GUI_EXPORT bool qt_mac_execute_apple_script(const char *script, long script_len, AEDesc *ret) {
292    OSStatus err;
293    AEDesc scriptTextDesc;
294    ComponentInstance theComponent = 0;
295    OSAID scriptID = kOSANullScript, resultID = kOSANullScript;
296
297    // set up locals to a known state
298    AECreateDesc(typeNull, 0, 0, &scriptTextDesc);
299    scriptID = kOSANullScript;
300    resultID = kOSANullScript;
301
302    // open the scripting component
303    theComponent = OpenDefaultComponent(kOSAComponentType, typeAppleScript);
304    if (!theComponent) {
305        err = paramErr;
306        goto bail;
307    }
308
309    // put the script text into an aedesc
310    err = AECreateDesc(typeUTF8Text, script, script_len, &scriptTextDesc);
311    if (err != noErr)
312        goto bail;
313
314    // compile the script
315    err = OSACompile(theComponent, &scriptTextDesc, kOSAModeNull, &scriptID);
316    if (err != noErr)
317        goto bail;
318
319    // run the script
320    err = OSAExecute(theComponent, scriptID, kOSANullScript, kOSAModeNull, &resultID);
321
322    // collect the results - if any
323    if (ret) {
324        AECreateDesc(typeNull, 0, 0, ret);
325        if (err == errOSAScriptError)
326            OSAScriptError(theComponent, kOSAErrorMessage, typeChar, ret);
327        else if (err == noErr && resultID != kOSANullScript)
328            OSADisplay(theComponent, resultID, typeChar, kOSAModeNull, ret);
329    }
330bail:
331    AEDisposeDesc(&scriptTextDesc);
332    if (scriptID != kOSANullScript)
333        OSADispose(theComponent, scriptID);
334    if (resultID != kOSANullScript)
335        OSADispose(theComponent, resultID);
336    if (theComponent)
337        CloseComponent(theComponent);
338    return err == noErr;
339}
340
341Q_GUI_EXPORT bool qt_mac_execute_apple_script(const char *script, AEDesc *ret)
342{
343    return qt_mac_execute_apple_script(script, qstrlen(script), ret);
344}
345
346Q_GUI_EXPORT bool qt_mac_execute_apple_script(const QString &script, AEDesc *ret)
347{
348    const QByteArray l = script.toUtf8(); return qt_mac_execute_apple_script(l.constData(), l.size(), ret);
349}
350
351/* Resolution change magic */
352void qt_mac_display_change_callbk(CGDirectDisplayID, CGDisplayChangeSummaryFlags flags, void *)
353{
354#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
355    const bool resized = flags & kCGDisplayDesktopShapeChangedFlag;
356#else
357    Q_UNUSED(flags);
358    const bool resized = true;
359#endif
360    if (resized && qApp) {
361        if (QDesktopWidget *dw = qApp->desktop()) {
362            QResizeEvent *re = new QResizeEvent(dw->size(), dw->size());
363            QApplication::postEvent(dw, re);
364            QCoreGraphicsPaintEngine::cleanUpMacColorSpaces();
365        }
366    }
367}
368
369#ifdef DEBUG_PLATFORM_SETTINGS
370static void qt_mac_debug_palette(const QPalette &pal, const QPalette &pal2, const QString &where)
371{
372    const char *const groups[] = {"Active", "Disabled", "Inactive" };
373    const char *const roles[] = { "WindowText", "Button", "Light", "Midlight", "Dark", "Mid",
374                            "Text", "BrightText", "ButtonText", "Base", "Window", "Shadow",
375                            "Highlight", "HighlightedText", "Link", "LinkVisited" };
376    if (!where.isNull())
377        qDebug("qt-internal: %s", where.toLatin1().constData());
378    for(int grp = 0; grp < QPalette::NColorGroups; grp++) {
379        for(int role = 0; role < QPalette::NColorRoles; role++) {
380            QBrush b = pal.brush((QPalette::ColorGroup)grp, (QPalette::ColorRole)role);
381            QPixmap pm = b.texture();
382            qDebug("  %s::%s %d::%d::%d [%p]%s", groups[grp], roles[role], b.color().red(),
383                   b.color().green(), b.color().blue(), pm.isNull() ? 0 : &pm,
384                   pal2.brush((QPalette::ColorGroup)grp, (QPalette::ColorRole)role) != b ? " (*)" : "");
385        }
386    }
387
388}
389#else
390#define qt_mac_debug_palette(x, y, z)
391#endif
392
393//raise a notification
394#ifndef QT_MAC_USE_COCOA
395static NMRec qt_mac_notification = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
396#endif
397void qt_mac_send_notification()
398{
399#ifndef QT_MAC_USE_COCOA
400    //send it
401    qt_mac_notification.nmMark = 1; //non-zero magic number
402    qt_mac_notification.qType = nmType;
403    NMInstall(&qt_mac_notification);
404#else
405    QMacCocoaAutoReleasePool pool;
406    [[NSApplication sharedApplication] requestUserAttention:NSInformationalRequest];
407#endif
408}
409
410void qt_mac_cancel_notification()
411{
412#ifndef QT_MAC_USE_COCOA
413    NMRemove(&qt_mac_notification);
414#else
415    QMacCocoaAutoReleasePool pool;
416    [[NSApplication sharedApplication] cancelUserAttentionRequest:NSInformationalRequest];
417#endif
418}
419
420#ifndef QT_MAC_USE_COCOA
421//find widget (and part) at a given point
422static short qt_mac_window_at(int x, int y, QWidget **w=0)
423{
424    Point p;
425    p.h = x;
426    p.v = y;
427    OSWindowRef wp;
428    WindowPartCode wpc;
429    OSStatus err = FindWindowOfClass(&p, kAllWindowClasses, &wp, &wpc);
430    if(err != noErr) {
431        if(w)
432            (*w) = 0;
433        return wpc;
434    }
435    if(w) {
436        if(wp) {
437            *w = qt_mac_find_window(wp);
438#if 0
439            if(!*w)
440                qWarning("QApplication: qt_mac_window_at: Couldn't find %d",(int)wp);
441#endif
442        } else {
443            *w = 0;
444        }
445    }
446    return wpc;
447}
448
449#endif
450
451void qt_mac_set_app_icon(const QPixmap &pixmap)
452{
453#ifndef QT_MAC_USE_COCOA
454    if(pixmap.isNull()) {
455        RestoreApplicationDockTileImage();
456    } else {
457        CGImageRef img = (CGImageRef)pixmap.macCGHandle();
458        SetApplicationDockTileImage(img);
459        CGImageRelease(img);
460    }
461#else
462    QMacCocoaAutoReleasePool pool;
463    NSImage *image = NULL;
464    if (pixmap.isNull()) {
465        // Get Application icon from bundle
466        image = [[NSImage imageNamed:@"NSApplicationIcon"] retain]; // released below
467    } else {
468        image = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap));
469    }
470
471    [[NSApplication sharedApplication] setApplicationIconImage:image];
472    [image release];
473#endif
474}
475
476Q_GUI_EXPORT void qt_mac_set_press_and_hold_context(bool b)
477{
478    Q_UNUSED(b);
479    qWarning("qt_mac_set_press_and_hold_context: This functionality is no longer available");
480}
481
482bool qt_nograb()                                // application no-grab option
483{
484#if defined(QT_DEBUG)
485    return appNoGrab;
486#else
487    return false;
488#endif
489}
490
491void qt_mac_update_os_settings()
492{
493    if (!qApp)
494        return;
495    if (!QApplication::startingUp()) {
496        static bool needToPolish = true;
497        if (needToPolish) {
498            QApplication::style()->polish(qApp);
499            needToPolish = false;
500        }
501    }
502    //focus mode
503    /* First worked as of 10.2.3 */
504    QSettings appleSettings(QLatin1String("apple.com"));
505    QVariant appleValue = appleSettings.value(QLatin1String("AppleKeyboardUIMode"), 0);
506    qt_tab_all_widgets = (appleValue.toInt() & 0x2);
507    //paging mode
508    /* First worked as of 10.2.3 */
509    appleValue = appleSettings.value(QLatin1String("AppleScrollerPagingBehavior"), false);
510    qt_scrollbar_jump_to_pos = appleValue.toBool();
511    //collapse
512    /* First worked as of 10.3.3 */
513    appleValue = appleSettings.value(QLatin1String("AppleMiniaturizeOnDoubleClick"), true);
514    qt_mac_collapse_on_dblclick = appleValue.toBool();
515
516    // Anti-aliasing threshold
517    appleValue = appleSettings.value(QLatin1String("AppleAntiAliasingThreshold"));
518    if (appleValue.isValid())
519        qt_antialiasing_threshold = appleValue.toInt();
520
521#ifdef DEBUG_PLATFORM_SETTINGS
522    qDebug("qt_mac_update_os_settings *********************************************************************");
523#endif
524    { // setup the global palette
525        QColor qc;
526        (void) QApplication::style();  // trigger creation of application style and system palettes
527        QPalette pal = *QApplicationPrivate::sys_pal;
528
529        pal.setBrush( QPalette::Active, QPalette::Highlight, qcolorForTheme(kThemeBrushPrimaryHighlightColor) );
530        pal.setBrush( QPalette::Inactive, QPalette::Highlight, qcolorForTheme(kThemeBrushSecondaryHighlightColor) );
531
532        pal.setBrush( QPalette::Disabled, QPalette::Highlight, qcolorForTheme(kThemeBrushSecondaryHighlightColor) );
533        pal.setBrush( QPalette::Active, QPalette::Shadow, qcolorForTheme(kThemeBrushButtonActiveDarkShadow) );
534
535        pal.setBrush( QPalette::Inactive, QPalette::Shadow, qcolorForTheme(kThemeBrushButtonInactiveDarkShadow) );
536        pal.setBrush( QPalette::Disabled, QPalette::Shadow, qcolorForTheme(kThemeBrushButtonInactiveDarkShadow) );
537
538        qc = qcolorForThemeTextColor(kThemeTextColorDialogActive);
539        pal.setColor(QPalette::Active, QPalette::Text, qc);
540        pal.setColor(QPalette::Active, QPalette::WindowText, qc);
541        pal.setColor(QPalette::Active, QPalette::HighlightedText, qc);
542
543        qc = qcolorForThemeTextColor(kThemeTextColorDialogInactive);
544        pal.setColor(QPalette::Inactive, QPalette::Text, qc);
545        pal.setColor(QPalette::Inactive, QPalette::WindowText, qc);
546        pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
547        pal.setColor(QPalette::Disabled, QPalette::Text, qc);
548        pal.setColor(QPalette::Disabled, QPalette::WindowText, qc);
549        pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
550        pal.setBrush(QPalette::ToolTipBase, QColor(255, 255, 199));
551
552        if (!QApplicationPrivate::sys_pal || *QApplicationPrivate::sys_pal != pal) {
553            QApplicationPrivate::setSystemPalette(pal);
554            QApplication::setPalette(pal);
555        }
556#ifdef DEBUG_PLATFORM_SETTINGS
557        qt_mac_debug_palette(pal, QApplication::palette(), "Global Palette");
558#endif
559    }
560
561    QFont fnt = qfontForThemeFont(kThemeApplicationFont);
562#ifdef DEBUG_PLATFORM_SETTINGS
563    qDebug("qt-internal: Font for Application [%s::%d::%d::%d]",
564           fnt.family().toLatin1().constData(), fnt.pointSize(), fnt.bold(), fnt.italic());
565#endif
566    if (!QApplicationPrivate::sys_font || *QApplicationPrivate::sys_font != fnt)
567        QApplicationPrivate::setSystemFont(fnt);
568
569    { //setup the fonts
570        struct FontMap {
571            FontMap(const char *qc, short fk) : qt_class(qc), font_key(fk) { }
572            const char *const qt_class;
573            short font_key;
574        } mac_widget_fonts[] = {
575            FontMap("QPushButton", kThemePushButtonFont),
576            FontMap("QListView", kThemeViewsFont),
577            FontMap("QListBox", kThemeViewsFont),
578            FontMap("QTitleBar", kThemeWindowTitleFont),
579            FontMap("QMenuBar", kThemeMenuTitleFont),
580            FontMap("QMenu", kThemeMenuItemFont),
581            FontMap("QComboMenuItem", kThemeSystemFont),
582            FontMap("QHeaderView", kThemeSmallSystemFont),
583            FontMap("Q3Header", kThemeSmallSystemFont),
584            FontMap("QTipLabel", kThemeSmallSystemFont),
585            FontMap("QLabel", kThemeSystemFont),
586            FontMap("QToolButton", kThemeSmallSystemFont),
587            FontMap("QMenuItem", kThemeMenuItemFont),  // It doesn't exist, but its unique.
588            FontMap("QComboLineEdit", kThemeViewsFont),  // It doesn't exist, but its unique.
589            FontMap("QSmallFont", kThemeSmallSystemFont),  // It doesn't exist, but its unique.
590            FontMap("QMiniFont", kThemeMiniSystemFont),  // It doesn't exist, but its unique.
591            FontMap(0, 0) };
592        for(int i = 0; mac_widget_fonts[i].qt_class; i++) {
593            QFont fnt = qfontForThemeFont(mac_widget_fonts[i].font_key);
594            bool set_font = true;
595            FontHash *hash = qt_app_fonts_hash();
596            if (!hash->isEmpty()) {
597                FontHash::const_iterator it
598                                        = hash->constFind(mac_widget_fonts[i].qt_class);
599                if (it != hash->constEnd())
600                    set_font = (fnt != *it);
601            }
602            if (set_font) {
603                QApplication::setFont(fnt, mac_widget_fonts[i].qt_class);
604#ifdef DEBUG_PLATFORM_SETTINGS
605                qDebug("qt-internal: Font for %s [%s::%d::%d::%d]", mac_widget_fonts[i].qt_class,
606                       fnt.family().toLatin1().constData(), fnt.pointSize(), fnt.bold(), fnt.italic());
607#endif
608            }
609        }
610    }
611    QApplicationPrivate::initializeWidgetPaletteHash();
612#ifdef DEBUG_PLATFORM_SETTINGS
613    qDebug("qt_mac_update_os_settings END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
614#endif
615}
616
617void QApplicationPrivate::initializeWidgetPaletteHash()
618{
619    { //setup the palette
620        struct PaletteMap {
621            inline PaletteMap(const char *qc, ThemeBrush a, ThemeBrush i) :
622                qt_class(qc), active(a), inactive(i) { }
623            const char *const qt_class;
624            ThemeBrush active, inactive;
625        } mac_widget_colors[] = {
626            PaletteMap("QToolButton", kThemeTextColorBevelButtonActive, kThemeTextColorBevelButtonInactive),
627            PaletteMap("QAbstractButton", kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
628            PaletteMap("QHeaderView", kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
629            PaletteMap("Q3Header", kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
630            PaletteMap("QComboBox", kThemeTextColorPopupButtonActive, kThemeTextColorPopupButtonInactive),
631            PaletteMap("QAbstractItemView", kThemeTextColorListView, kThemeTextColorDialogInactive),
632            PaletteMap("QMessageBoxLabel", kThemeTextColorAlertActive, kThemeTextColorAlertInactive),
633            PaletteMap("QTabBar", kThemeTextColorTabFrontActive, kThemeTextColorTabFrontInactive),
634            PaletteMap("QLabel", kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
635            PaletteMap("QGroupBox", kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
636            PaletteMap("QMenu", kThemeTextColorPopupLabelActive, kThemeTextColorPopupLabelInactive),
637            PaletteMap("QTextEdit", 0, 0),
638            PaletteMap("QTextControl", 0, 0),
639            PaletteMap("QLineEdit", 0, 0),
640            PaletteMap(0, 0, 0) };
641        QColor qc;
642        for(int i = 0; mac_widget_colors[i].qt_class; i++) {
643            QPalette pal;
644            if (mac_widget_colors[i].active != 0) {
645                qc = qcolorForThemeTextColor(mac_widget_colors[i].active);
646                pal.setColor(QPalette::Active, QPalette::Text, qc);
647                pal.setColor(QPalette::Active, QPalette::WindowText, qc);
648                pal.setColor(QPalette::Active, QPalette::HighlightedText, qc);
649                qc = qcolorForThemeTextColor(mac_widget_colors[i].inactive);
650                pal.setColor(QPalette::Inactive, QPalette::Text, qc);
651                pal.setColor(QPalette::Disabled, QPalette::Text, qc);
652                pal.setColor(QPalette::Inactive, QPalette::WindowText, qc);
653                pal.setColor(QPalette::Disabled, QPalette::WindowText, qc);
654                pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
655                pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
656            }
657            if (!strcmp(mac_widget_colors[i].qt_class, "QMenu")) {
658                qc = qcolorForThemeTextColor(kThemeTextColorMenuItemActive);
659                pal.setBrush(QPalette::ButtonText, qc);
660                qc = qcolorForThemeTextColor(kThemeTextColorMenuItemSelected);
661                pal.setBrush(QPalette::HighlightedText, qc);
662                qc = qcolorForThemeTextColor(kThemeTextColorMenuItemDisabled);
663                pal.setBrush(QPalette::Disabled, QPalette::Text, qc);
664            } else if (!strcmp(mac_widget_colors[i].qt_class, "QAbstractButton")
665                      || !strcmp(mac_widget_colors[i].qt_class, "QHeaderView")
666                      || !strcmp(mac_widget_colors[i].qt_class, "Q3Header")) { //special
667                pal.setColor(QPalette::Disabled, QPalette::ButtonText,
668                             pal.color(QPalette::Disabled, QPalette::Text));
669                pal.setColor(QPalette::Inactive, QPalette::ButtonText,
670                             pal.color(QPalette::Inactive, QPalette::Text));
671                pal.setColor(QPalette::Active, QPalette::ButtonText,
672                             pal.color(QPalette::Active, QPalette::Text));
673            } else if (!strcmp(mac_widget_colors[i].qt_class, "QAbstractItemView")) {
674                pal.setBrush(QPalette::Active, QPalette::Highlight,
675                             qcolorForTheme(kThemeBrushAlternatePrimaryHighlightColor));
676                qc = qcolorForThemeTextColor(kThemeTextColorMenuItemSelected);
677                pal.setBrush(QPalette::Active, QPalette::HighlightedText, qc);
678#if 1
679                pal.setBrush(QPalette::Inactive, QPalette::Text,
680                              pal.brush(QPalette::Active, QPalette::Text));
681                pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
682                              pal.brush(QPalette::Active, QPalette::Text));
683#endif
684            } else if (!strcmp(mac_widget_colors[i].qt_class, "QTextEdit")
685                       || !strcmp(mac_widget_colors[i].qt_class, "QTextControl")) {
686                pal.setBrush(QPalette::Inactive, QPalette::Text,
687                              pal.brush(QPalette::Active, QPalette::Text));
688                pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
689                              pal.brush(QPalette::Active, QPalette::Text));
690            } else if (!strcmp(mac_widget_colors[i].qt_class, "QLineEdit")) {
691                pal.setBrush(QPalette::Disabled, QPalette::Base,
692                             pal.brush(QPalette::Active, QPalette::Base));
693            }
694
695            bool set_palette = true;
696            PaletteHash *phash = qt_app_palettes_hash();
697            if (!phash->isEmpty()) {
698                PaletteHash::const_iterator it
699                                    = phash->constFind(mac_widget_colors[i].qt_class);
700                if (it != phash->constEnd())
701                    set_palette = (pal != *it);
702            }
703            if (set_palette) {
704                QApplication::setPalette(pal, mac_widget_colors[i].qt_class);
705#ifdef DEBUG_PLATFORM_SETTINGS
706                qt_mac_debug_palette(pal, QApplication::palette(), QLatin1String("Palette for ") + QString::fromLatin1(mac_widget_colors[i].qt_class));
707#endif
708            }
709        }
710    }
711}
712
713static void qt_mac_event_release(EventRef &event)
714{
715    ReleaseEvent(event);
716    event = 0;
717}
718#ifndef QT_MAC_USE_COCOA
719static void qt_mac_event_release(QWidget *w, EventRef &event)
720{
721    if (event) {
722        QWidget *widget = 0;
723        if (GetEventParameter(event, kEventParamQWidget, typeQWidget, 0, sizeof(widget), 0, &widget) == noErr
724           && w == widget) {
725            if (IsEventInQueue(GetMainEventQueue(), event))
726                RemoveEventFromQueue(GetMainEventQueue(), event);
727            qt_mac_event_release(event);
728        }
729    }
730}
731
732static bool qt_mac_event_remove(EventRef &event)
733{
734    if (event) {
735        if (IsEventInQueue(GetMainEventQueue(), event))
736            RemoveEventFromQueue(GetMainEventQueue(), event);
737        qt_mac_event_release(event);
738        return true;
739    }
740    return false;
741}
742#endif
743
744/* sheets */
745#ifndef QT_MAC_USE_COCOA
746static EventRef request_showsheet_pending = 0;
747#endif
748void qt_event_request_showsheet(QWidget *w)
749{
750    Q_ASSERT(qt_mac_is_macsheet(w));
751#ifdef QT_MAC_USE_COCOA
752    w->repaint();
753    [[NSApplication sharedApplication] beginSheet:qt_mac_window_for(w) modalForWindow:qt_mac_window_for(w->parentWidget())
754        modalDelegate:nil didEndSelector:nil contextInfo:0];
755#else
756    qt_mac_event_remove(request_showsheet_pending);
757    CreateEvent(0, kEventClassQt, kEventQtRequestShowSheet, GetCurrentEventTime(),
758                kEventAttributeUserEvent, &request_showsheet_pending);
759    SetEventParameter(request_showsheet_pending, kEventParamQWidget, typeQWidget, sizeof(w), &w);
760    PostEventToQueue(GetMainEventQueue(), request_showsheet_pending, kEventPriorityStandard);
761#endif
762}
763
764static void qt_post_window_change_event(QWidget *widget)
765{
766    qt_widget_private(widget)->needWindowChange = true;
767    QEvent *glWindowChangeEvent = new QEvent(QEvent::MacGLWindowChange);
768    QApplication::postEvent(widget, glWindowChangeEvent);
769}
770
771/*
772    Posts updates to all child and grandchild OpenGL widgets for the given widget.
773*/
774static void qt_mac_update_child_gl_widgets(QWidget *widget)
775{
776    // Update all OpenGL child widgets for the given widget.
777    QList<QWidgetPrivate::GlWidgetInfo> &glWidgets = qt_widget_private(widget)->glWidgets;
778    QList<QWidgetPrivate::GlWidgetInfo>::iterator end = glWidgets.end();
779    QList<QWidgetPrivate::GlWidgetInfo>::iterator it = glWidgets.begin();
780
781    for (;it != end; ++it) {
782        qt_post_window_change_event(it->widget);
783    }
784}
785
786/*
787    Sends updates to all child and grandchild gl widgets that have updates pending.
788*/
789void qt_mac_send_posted_gl_updates(QWidget *widget)
790{
791    QList<QWidgetPrivate::GlWidgetInfo> &glWidgets = qt_widget_private(widget)->glWidgets;
792    QList<QWidgetPrivate::GlWidgetInfo>::iterator end = glWidgets.end();
793    QList<QWidgetPrivate::GlWidgetInfo>::iterator it = glWidgets.begin();
794
795    for (;it != end; ++it) {
796        QWidget *glWidget = it->widget;
797        if (qt_widget_private(glWidget)->needWindowChange) {
798            QEvent glChangeEvent(QEvent::MacGLWindowChange);
799            QApplication::sendEvent(glWidget, &glChangeEvent);
800        }
801    }
802}
803
804/*
805    Posts updates to all OpenGL widgets within the window that the given widget intersects.
806*/
807static void qt_mac_update_intersected_gl_widgets(QWidget *widget)
808{
809#ifndef QT_MAC_USE_COCOA
810    QList<QWidgetPrivate::GlWidgetInfo> &glWidgets = qt_widget_private(widget->window())->glWidgets;
811    if (glWidgets.isEmpty())
812        return;
813
814    // Exit if the window has not been created yet (mapToGlobal/size will force create it)
815    if (widget->testAttribute(Qt::WA_WState_Created) == false || HIViewGetWindow(qt_mac_nativeview_for(widget)) == 0)
816        return;
817
818    const QRect globalWidgetRect = QRect(widget->mapToGlobal(QPoint(0, 0)), widget->size());
819
820    QList<QWidgetPrivate::GlWidgetInfo>::iterator end = glWidgets.end();
821    QList<QWidgetPrivate::GlWidgetInfo>::iterator it = glWidgets.begin();
822
823    for (;it != end; ++it){
824        QWidget *glWidget = it->widget;
825        const QRect globalGlWidgetRect = QRect(glWidget->mapToGlobal(QPoint(0, 0)), glWidget->size());
826        if (globalWidgetRect.intersects(globalGlWidgetRect)) {
827            qt_post_window_change_event(glWidget);
828            it->lastUpdateWidget = widget;
829        } else if (it->lastUpdateWidget == widget) {
830            // Update the gl wigets that the widget intersected the last time around,
831            // and that we are not intersecting now. This prevents paint errors when the
832            // intersecting widget leaves a gl widget.
833            qt_post_window_change_event(glWidget);
834            it->lastUpdateWidget = 0;
835        }
836    }
837#else
838    Q_UNUSED(widget);
839#endif
840}
841
842/*
843    Posts a kEventQtRequestWindowChange event to the main Carbon event queue.
844*/
845static EventRef request_window_change_pending = 0;
846Q_GUI_EXPORT void qt_event_request_window_change()
847{
848    if(request_window_change_pending)
849        return;
850
851    CreateEvent(0, kEventClassQt, kEventQtRequestWindowChange, GetCurrentEventTime(),
852                kEventAttributeUserEvent, &request_window_change_pending);
853    PostEventToQueue(GetMainEventQueue(), request_window_change_pending, kEventPriorityHigh);
854}
855
856/* window changing. This is a hack around Apple's missing functionality, pending the toolbox
857   team fix. --Sam */
858Q_GUI_EXPORT void qt_event_request_window_change(QWidget *widget)
859{
860    if (!widget)
861        return;
862
863    // Post a kEventQtRequestWindowChange event. This event is semi-public,
864    // don't remove this line!
865    qt_event_request_window_change();
866
867    // Post update request on gl widgets unconditionally.
868    if (qt_widget_private(widget)->isGLWidget == true) {
869        qt_post_window_change_event(widget);
870        return;
871    }
872
873    qt_mac_update_child_gl_widgets(widget);
874    qt_mac_update_intersected_gl_widgets(widget);
875}
876
877/* activation */
878static struct {
879    QPointer<QWidget> widget;
880    EventRef event;
881    EventLoopTimerRef timer;
882    EventLoopTimerUPP timerUPP;
883} request_activate_pending = { 0, 0, 0, 0 };
884bool qt_event_remove_activate()
885{
886    if (request_activate_pending.timer) {
887        RemoveEventLoopTimer(request_activate_pending.timer);
888        request_activate_pending.timer = 0;
889    }
890    if (request_activate_pending.event)
891        qt_mac_event_release(request_activate_pending.event);
892    return true;
893}
894
895void qt_event_activate_timer_callbk(EventLoopTimerRef r, void *)
896{
897    EventLoopTimerRef otc = request_activate_pending.timer;
898    qt_event_remove_activate();
899    if (r == otc && !request_activate_pending.widget.isNull()) {
900        const QWidget *tlw = request_activate_pending.widget->window();
901        Qt::WindowType wt = tlw->windowType();
902        if (tlw->isVisible()
903               && ((wt != Qt::Desktop && wt != Qt::Popup && wt != Qt::Tool) || tlw->isModal())) {
904            CreateEvent(0, kEventClassQt, kEventQtRequestActivate, GetCurrentEventTime(),
905                        kEventAttributeUserEvent, &request_activate_pending.event);
906            PostEventToQueue(GetMainEventQueue(), request_activate_pending.event, kEventPriorityHigh);
907        }
908    }
909}
910
911void qt_event_request_activate(QWidget *w)
912{
913    if (w == request_activate_pending.widget)
914        return;
915
916    /* We put these into a timer because due to order of events being sent we need to be sure this
917       comes from inside of the event loop */
918    qt_event_remove_activate();
919    if (!request_activate_pending.timerUPP)
920        request_activate_pending.timerUPP = NewEventLoopTimerUPP(qt_event_activate_timer_callbk);
921    request_activate_pending.widget = w;
922    InstallEventLoopTimer(GetMainEventLoop(), 0, 0, request_activate_pending.timerUPP, 0, &request_activate_pending.timer);
923}
924
925
926/* menubars */
927#ifndef QT_MAC_USE_COCOA
928static EventRef request_menubarupdate_pending = 0;
929#endif
930void qt_event_request_menubarupdate()
931{
932#ifndef QT_MAC_USE_COCOA
933    if (request_menubarupdate_pending) {
934        if (IsEventInQueue(GetMainEventQueue(), request_menubarupdate_pending))
935            return;
936#ifdef DEBUG_DROPPED_EVENTS
937        qDebug("%s:%d Whoa, we dropped an event on the floor!", __FILE__, __LINE__);
938#endif
939    }
940
941    CreateEvent(0, kEventClassQt, kEventQtRequestMenubarUpdate, GetCurrentEventTime(),
942                kEventAttributeUserEvent, &request_menubarupdate_pending);
943    PostEventToQueue(GetMainEventQueue(), request_menubarupdate_pending, kEventPriorityHigh);
944#else
945    // Just call this. The request has the benefit that we don't call this multiple times, but
946    // we can optimize this.
947    QMenuBar::macUpdateMenuBar();
948#endif
949}
950
951#ifndef QT_MAC_USE_COCOA
952//context menu
953static EventRef request_context_pending = 0;
954static void qt_event_request_context(QWidget *w=0, EventRef *where=0)
955{
956    if (!where)
957        where = &request_context_pending;
958    if (*where)
959        return;
960    CreateEvent(0, kEventClassQt, kEventQtRequestContext, GetCurrentEventTime(),
961                kEventAttributeUserEvent, where);
962    if (w)
963        SetEventParameter(*where, kEventParamQWidget, typeQWidget, sizeof(w), &w);
964    PostEventToQueue(GetMainEventQueue(), *where, kEventPriorityStandard);
965}
966#endif
967
968void QApplicationPrivate::createEventDispatcher()
969{
970    Q_Q(QApplication);
971    if (q->type() != QApplication::Tty)
972        eventDispatcher = new QEventDispatcherMac(q);
973    else
974        eventDispatcher = new QEventDispatcherUNIX(q);
975}
976
977/* clipboard */
978void qt_event_send_clipboard_changed()
979{
980#ifndef QT_MAC_USE_COCOA
981    AppleEvent ae;
982    if (AECreateAppleEvent(kEventClassQt, typeAEClipboardChanged, 0, kAutoGenerateReturnID, kAnyTransactionID, &ae) != noErr)
983        qDebug("Can't happen!!");
984    AppleEvent reply;
985    AESend(&ae, &reply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, 0, 0);
986#endif
987}
988
989/* app menu */
990static QMenu *qt_mac_dock_menu = 0;
991Q_GUI_EXPORT void qt_mac_set_dock_menu(QMenu *menu)
992{
993    qt_mac_dock_menu = menu;
994#ifdef QT_MAC_USE_COCOA
995    [[NSApplication sharedApplication] setDockMenu:menu->macMenu()];
996#else
997    SetApplicationDockTileMenu(menu->macMenu());
998#endif
999}
1000
1001/* events that hold pointers to widgets, must be cleaned up like this */
1002void qt_mac_event_release(QWidget *w)
1003{
1004    if (w) {
1005#ifndef QT_MAC_USE_COCOA
1006        qt_mac_event_release(w, request_showsheet_pending);
1007        qt_mac_event_release(w, request_context_pending);
1008#endif
1009        if (w == qt_mac_dock_menu) {
1010            qt_mac_dock_menu = 0;
1011#ifndef QT_MAC_USE_COCOA
1012            SetApplicationDockTileMenu(0);
1013#else
1014            [[NSApplication sharedApplication] setDockMenu:0];
1015#endif
1016        }
1017    }
1018}
1019
1020struct QMacAppleEventTypeSpec {
1021    AEEventClass mac_class;
1022    AEEventID mac_id;
1023} app_apple_events[] = {
1024    { kCoreEventClass, kAEQuitApplication },
1025    { kCoreEventClass, kAEOpenDocuments },
1026    { kInternetEventClass, kAEGetURL },
1027};
1028
1029#ifndef QT_MAC_USE_COCOA
1030
1031#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
1032enum
1033{
1034    kEventMouseScroll                          = 11,
1035    kEventParamMouseWheelSmoothVerticalDelta   = 'saxy',
1036    kEventParamMouseWheelSmoothHorizontalDelta = 'saxx',
1037};
1038#endif
1039
1040/* watched events */
1041static EventTypeSpec app_events[] = {
1042    { kEventClassQt, kEventQtRequestWindowChange },
1043    { kEventClassQt, kEventQtRequestShowSheet },
1044    { kEventClassQt, kEventQtRequestContext },
1045    { kEventClassQt, kEventQtRequestActivate },
1046    { kEventClassQt, kEventQtRequestMenubarUpdate },
1047
1048    { kEventClassWindow, kEventWindowActivated },
1049    { kEventClassWindow, kEventWindowDeactivated },
1050
1051    { kEventClassMouse, kEventMouseScroll },
1052    { kEventClassMouse, kEventMouseWheelMoved },
1053    { kEventClassMouse, kEventMouseDown },
1054    { kEventClassMouse, kEventMouseUp },
1055    { kEventClassMouse, kEventMouseDragged },
1056    { kEventClassMouse, kEventMouseMoved },
1057
1058    { kEventClassTablet, kEventTabletProximity },
1059
1060    { kEventClassApplication, kEventAppActivated },
1061    { kEventClassApplication, kEventAppDeactivated },
1062    { kEventClassApplication, kEventAppAvailableWindowBoundsChanged },
1063
1064    //    { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
1065    { kEventClassKeyboard, kEventRawKeyModifiersChanged },
1066    { kEventClassKeyboard, kEventRawKeyRepeat },
1067    { kEventClassKeyboard, kEventRawKeyUp },
1068    { kEventClassKeyboard, kEventRawKeyDown },
1069
1070    { kEventClassCommand, kEventCommandProcess },
1071
1072    { kEventClassAppleEvent, kEventAppleEvent },
1073
1074    { kAppearanceEventClass, kAEAppearanceChanged }
1075};
1076
1077void qt_init_app_proc_handler()
1078{
1079    InstallEventHandler(GetApplicationEventTarget(), app_proc_handlerUPP,
1080                        GetEventTypeCount(app_events), app_events, (void *)qApp,
1081                        &app_proc_handler);
1082}
1083#endif // QT_MAC_USE_COCOA
1084
1085static void qt_init_tablet_proximity_handler()
1086{
1087    EventTypeSpec	tabletProximityEvent = { kEventClassTablet, kEventTabletProximity };
1088    InstallEventHandler(GetEventMonitorTarget(), tablet_proximity_UPP,
1089                        1, &tabletProximityEvent, qApp, &tablet_proximity_handler);
1090}
1091
1092static void qt_release_tablet_proximity_handler()
1093{
1094    RemoveEventHandler(tablet_proximity_handler);
1095}
1096
1097QString QApplicationPrivate::appName() const
1098{
1099    static QString applName;
1100    if (applName.isEmpty()) {
1101        applName = QCoreApplicationPrivate::macMenuBarName();
1102        ProcessSerialNumber psn;
1103        if (applName.isEmpty() && qt_is_gui_used && GetCurrentProcess(&psn) == noErr) {
1104            QCFString cfstr;
1105            CopyProcessName(&psn, &cfstr);
1106            applName = cfstr;
1107        }
1108    }
1109    return applName;
1110}
1111
1112void qt_release_app_proc_handler()
1113{
1114#ifndef QT_MAC_USE_COCOA
1115    if (app_proc_handler) {
1116        RemoveEventHandler(app_proc_handler);
1117        app_proc_handler = 0;
1118    }
1119#endif
1120}
1121
1122void qt_color_profile_changed(CFNotificationCenterRef, void *, CFStringRef, const void *,
1123                              CFDictionaryRef)
1124{
1125    QCoreGraphicsPaintEngine::cleanUpMacColorSpaces();
1126}
1127/* platform specific implementations */
1128void qt_init(QApplicationPrivate *priv, int)
1129{
1130    if (qt_is_gui_used) {
1131        CGDisplayRegisterReconfigurationCallback(qt_mac_display_change_callbk, 0);
1132        CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter();
1133        CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
1134                                        kCMDeviceUnregisteredNotification, 0,
1135                                        CFNotificationSuspensionBehaviorDeliverImmediately);
1136        CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
1137                                        kCMDefaultDeviceNotification, 0,
1138                                        CFNotificationSuspensionBehaviorDeliverImmediately);
1139        CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
1140                                        kCMDeviceProfilesNotification, 0,
1141                                        CFNotificationSuspensionBehaviorDeliverImmediately);
1142        CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
1143                                        kCMDefaultDeviceProfileNotification, 0,
1144                                        CFNotificationSuspensionBehaviorDeliverImmediately);
1145        ProcessSerialNumber psn;
1146        if (GetCurrentProcess(&psn) == noErr) {
1147            // Jambi needs to transform itself since most people aren't "used"
1148            // to putting things in bundles, but other people may actually not
1149            // want to tranform the process (running as a helper or something)
1150            // so don't do that for them. This means checking both LSUIElement
1151            // and LSBackgroundOnly. If you set them both... well, you
1152            // shouldn't do that.
1153
1154            bool forceTransform = true;
1155            CFTypeRef value = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(),
1156                                                                   CFSTR("LSUIElement"));
1157            if (value) {
1158                CFTypeID valueType = CFGetTypeID(value);
1159                // Officially it's supposed to be a string, a boolean makes sense, so we'll check.
1160                // A number less so, but OK.
1161                if (valueType == CFStringGetTypeID())
1162                    forceTransform = !(QCFString::toQString(static_cast<CFStringRef>(value)).toInt());
1163                else if (valueType == CFBooleanGetTypeID())
1164                    forceTransform = !CFBooleanGetValue(static_cast<CFBooleanRef>(value));
1165                else if (valueType == CFNumberGetTypeID()) {
1166                    int valueAsInt;
1167                    CFNumberGetValue(static_cast<CFNumberRef>(value), kCFNumberIntType, &valueAsInt);
1168                    forceTransform = !valueAsInt;
1169                }
1170            }
1171
1172            if (forceTransform) {
1173                value = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(),
1174                                                             CFSTR("LSBackgroundOnly"));
1175                if (value) {
1176                    CFTypeID valueType = CFGetTypeID(value);
1177                    if (valueType == CFBooleanGetTypeID())
1178                        forceTransform = !CFBooleanGetValue(static_cast<CFBooleanRef>(value));
1179                    else if (valueType == CFStringGetTypeID())
1180                        forceTransform = !(QCFString::toQString(static_cast<CFStringRef>(value)).toInt());
1181                    else if (valueType == CFNumberGetTypeID()) {
1182                        int valueAsInt;
1183                        CFNumberGetValue(static_cast<CFNumberRef>(value), kCFNumberIntType, &valueAsInt);
1184                        forceTransform = !valueAsInt;
1185                    }
1186                }
1187            }
1188
1189
1190            if (forceTransform) {
1191                TransformProcessType(&psn, kProcessTransformToForegroundApplication);
1192            }
1193        }
1194    }
1195
1196    char **argv = priv->argv;
1197
1198    // Get command line params
1199    if (int argc = priv->argc) {
1200        int i, j = 1;
1201        QString passed_psn;
1202        for(i=1; i < argc; i++) {
1203            if (argv[i] && *argv[i] != '-') {
1204                argv[j++] = argv[i];
1205                continue;
1206            }
1207            QByteArray arg(argv[i]);
1208#if defined(QT_DEBUG)
1209            if (arg == "-nograb")
1210                appNoGrab = !appNoGrab;
1211            else
1212#endif // QT_DEBUG
1213                if (arg.left(5) == "-psn_") {
1214                    passed_psn = QString::fromLatin1(arg.mid(6));
1215                } else {
1216                    argv[j++] = argv[i];
1217                }
1218        }
1219        if (j < priv->argc) {
1220            priv->argv[j] = 0;
1221            priv->argc = j;
1222        }
1223
1224        //special hack to change working directory (for an app bundle) when running from finder
1225        if (!passed_psn.isNull() && QDir::currentPath() == QLatin1String("/")) {
1226            QCFType<CFURLRef> bundleURL(CFBundleCopyBundleURL(CFBundleGetMainBundle()));
1227            QString qbundlePath = QCFString(CFURLCopyFileSystemPath(bundleURL,
1228                                            kCFURLPOSIXPathStyle));
1229            if (qbundlePath.endsWith(QLatin1String(".app")))
1230                QDir::setCurrent(qbundlePath.section(QLatin1Char('/'), 0, -2));
1231        }
1232   }
1233
1234    QMacPasteboardMime::initialize();
1235
1236    qApp->setObjectName(priv->appName());
1237    if (qt_is_gui_used) {
1238        QColormap::initialize();
1239        QFont::initialize();
1240        QCursorData::initialize();
1241        QCoreGraphicsPaintEngine::initialize();
1242#ifndef QT_NO_ACCESSIBILITY
1243        QAccessible::initialize();
1244#endif
1245#ifndef QT_NO_IM
1246        QMacInputContext::initialize();
1247        QApplicationPrivate::inputContext = new QMacInputContext;
1248#endif
1249        if (QApplication::desktopSettingsAware())
1250            qt_mac_update_os_settings();
1251#ifndef QT_MAC_USE_COCOA
1252        if (!app_proc_handler) {
1253            app_proc_handlerUPP = NewEventHandlerUPP(QApplicationPrivate::globalEventProcessor);
1254            qt_init_app_proc_handler();
1255        }
1256
1257#endif
1258        if (!app_proc_ae_handlerUPP && !QApplication::testAttribute(Qt::AA_MacPluginApplication)) {
1259            app_proc_ae_handlerUPP = AEEventHandlerUPP(QApplicationPrivate::globalAppleEventProcessor);
1260            for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i) {
1261                // Install apple event handler, but avoid overwriting an already
1262                // existing handler (it means a 3rd party application has installed one):
1263                SRefCon refCon = 0;
1264                AEEventHandlerUPP current_handler = NULL;
1265                AEGetEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, &current_handler, &refCon, false);
1266                if (!current_handler)
1267                    AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id,
1268                            app_proc_ae_handlerUPP, SRefCon(qApp), false);
1269            }
1270        }
1271
1272        if (QApplicationPrivate::app_style) {
1273            QEvent ev(QEvent::Style);
1274            qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
1275        }
1276    }
1277    if (QApplication::desktopSettingsAware())
1278        QApplicationPrivate::qt_mac_apply_settings();
1279
1280    // Cocoa application delegate
1281#ifdef QT_MAC_USE_COCOA
1282    NSApplication *cocoaApp = [QT_MANGLE_NAMESPACE(QNSApplication) sharedApplication];
1283    qt_redirectNSApplicationSendEvent();
1284
1285    QMacCocoaAutoReleasePool pool;
1286    id oldDelegate = [cocoaApp delegate];
1287    QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
1288    Q_ASSERT(newDelegate);
1289    [newDelegate setQtPrivate:priv];
1290    // Only do things that make sense to do once, otherwise we crash.
1291    if (oldDelegate != newDelegate && !QApplication::testAttribute(Qt::AA_MacPluginApplication)) {
1292        [newDelegate setReflectionDelegate:oldDelegate];
1293        [cocoaApp setDelegate:newDelegate];
1294
1295        QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader = [[QT_MANGLE_NAMESPACE(QCocoaMenuLoader) alloc] init];
1296        qt_mac_loadMenuNib(qtMenuLoader);
1297
1298        [cocoaApp setMenu:[qtMenuLoader menu]];
1299        [newDelegate setMenuLoader:qtMenuLoader];
1300    }
1301#endif
1302    // Register for Carbon tablet proximity events on the event monitor target.
1303    // This means that we should receive proximity events even when we aren't the active application.
1304    if (!tablet_proximity_handler) {
1305        tablet_proximity_UPP = NewEventHandlerUPP(QApplicationPrivate::tabletProximityCallback);
1306        qt_init_tablet_proximity_handler();
1307    }
1308   priv->native_modal_dialog_active = false;
1309
1310   qt_mac_read_fontsmoothing_settings();
1311}
1312
1313void qt_release_apple_event_handler()
1314{
1315    if(app_proc_ae_handlerUPP) {
1316        for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i)
1317            AERemoveEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id,
1318                    app_proc_ae_handlerUPP, true);
1319        DisposeAEEventHandlerUPP(app_proc_ae_handlerUPP);
1320        app_proc_ae_handlerUPP = 0;
1321    }
1322}
1323
1324/*****************************************************************************
1325  qt_cleanup() - cleans up when the application is finished
1326 *****************************************************************************/
1327
1328void qt_cleanup()
1329{
1330    CGDisplayRemoveReconfigurationCallback(qt_mac_display_change_callbk, 0);
1331    CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter();
1332    CFNotificationCenterRemoveObserver(center, qApp, kCMDeviceUnregisteredNotification, 0);
1333    CFNotificationCenterRemoveObserver(center, qApp, kCMDefaultDeviceNotification, 0);
1334    CFNotificationCenterRemoveObserver(center, qApp, kCMDeviceProfilesNotification, 0);
1335    CFNotificationCenterRemoveObserver(center, qApp, kCMDefaultDeviceProfileNotification, 0);
1336
1337#ifndef QT_MAC_USE_COCOA
1338    qt_release_app_proc_handler();
1339    if (app_proc_handlerUPP) {
1340        DisposeEventHandlerUPP(app_proc_handlerUPP);
1341        app_proc_handlerUPP = 0;
1342    }
1343#endif
1344    qt_release_apple_event_handler();
1345
1346#ifdef QT_MAC_USE_COCOA
1347    qt_resetNSApplicationSendEvent();
1348#endif
1349
1350    qt_release_tablet_proximity_handler();
1351    if (tablet_proximity_UPP)
1352        DisposeEventHandlerUPP(tablet_proximity_UPP);
1353
1354    QPixmapCache::clear();
1355    if (qt_is_gui_used) {
1356#ifndef QT_NO_ACCESSIBILITY
1357        QAccessible::cleanup();
1358#endif
1359#ifndef QT_NO_IM
1360        QMacInputContext::cleanup();
1361#endif
1362        QCursorData::cleanup();
1363        QFont::cleanup();
1364        QColormap::cleanup();
1365        if (qt_mac_safe_pdev) {
1366            delete qt_mac_safe_pdev;
1367            qt_mac_safe_pdev = 0;
1368        }
1369        extern void qt_mac_unregister_widget(); // qapplication_mac.cpp
1370        qt_mac_unregister_widget();
1371    }
1372}
1373
1374/*****************************************************************************
1375  Platform specific global and internal functions
1376 *****************************************************************************/
1377void qt_updated_rootinfo()
1378{
1379}
1380
1381bool qt_wstate_iconified(WId)
1382{
1383    return false;
1384}
1385
1386/*****************************************************************************
1387  Platform specific QApplication members
1388 *****************************************************************************/
1389extern QWidget * mac_mouse_grabber;
1390extern QWidget * mac_keyboard_grabber;
1391
1392#ifdef QT3_SUPPORT
1393void QApplication::setMainWidget(QWidget *mainWidget)
1394{
1395    QApplicationPrivate::main_widget = mainWidget;
1396    if (QApplicationPrivate::main_widget && windowIcon().isNull()
1397        && QApplicationPrivate::main_widget->testAttribute(Qt::WA_SetWindowIcon))
1398        setWindowIcon(QApplicationPrivate::main_widget->windowIcon());
1399}
1400#endif
1401#ifndef QT_NO_CURSOR
1402
1403/*****************************************************************************
1404  QApplication cursor stack
1405 *****************************************************************************/
1406
1407void QApplication::setOverrideCursor(const QCursor &cursor)
1408{
1409    qApp->d_func()->cursor_list.prepend(cursor);
1410
1411#ifdef QT_MAC_USE_COCOA
1412    qt_mac_update_cursor();
1413#else
1414    if (qApp && qApp->activeWindow())
1415        qt_mac_set_cursor(&qApp->d_func()->cursor_list.first());
1416#endif
1417}
1418
1419void QApplication::restoreOverrideCursor()
1420{
1421    if (qApp->d_func()->cursor_list.isEmpty())
1422        return;
1423    qApp->d_func()->cursor_list.removeFirst();
1424
1425#ifdef QT_MAC_USE_COCOA
1426    qt_mac_update_cursor();
1427#else
1428    if (qApp && qApp->activeWindow()) {
1429        const QCursor def(Qt::ArrowCursor);
1430        qt_mac_set_cursor(qApp->d_func()->cursor_list.isEmpty() ? &def : &qApp->d_func()->cursor_list.first());
1431    }
1432#endif
1433}
1434#endif // QT_NO_CURSOR
1435
1436Qt::KeyboardModifiers QApplication::queryKeyboardModifiers()
1437{
1438    return qt_mac_get_modifiers(GetCurrentEventKeyModifiers());
1439}
1440
1441QWidget *QApplication::topLevelAt(const QPoint &p)
1442{
1443#ifndef QT_MAC_USE_COCOA
1444    QWidget *widget;
1445    qt_mac_window_at(p.x(), p.y(), &widget);
1446    return widget;
1447#else
1448    // Use a cache to avoid iterate through the whole list of windows for all
1449    // calls to to topLevelAt. We e.g. do this for each and every mouse
1450    // move since we need to find the widget under mouse:
1451    if (topLevelAt_cache && topLevelAt_cache->frameGeometry().contains(p))
1452        return topLevelAt_cache;
1453
1454    // INVARIANT: Cache miss. Go through the list if windows instead:
1455    QMacCocoaAutoReleasePool pool;
1456    NSPoint cocoaPoint = flipPoint(p);
1457    NSInteger windowCount;
1458    NSCountWindows(&windowCount);
1459    if (windowCount <= 0)
1460        return 0;  // There's no window to find!
1461
1462    QVarLengthArray<NSInteger> windowList(windowCount);
1463    NSWindowList(windowCount, windowList.data());
1464    int firstQtWindowFound = -1;
1465    for (int i = 0; i < windowCount; ++i) {
1466        NSWindow *window = [[NSApplication sharedApplication] windowWithWindowNumber:windowList[i]];
1467        if (window) {
1468            QWidget *candidateWindow = [window QT_MANGLE_NAMESPACE(qt_qwidget)];
1469            if (candidateWindow && firstQtWindowFound == -1)
1470                firstQtWindowFound = i;
1471
1472            if (NSPointInRect(cocoaPoint, [window frame])) {
1473                // Check to see if there's a hole in the window where the mask is.
1474                // If there is, we should just continue to see if there is a window below.
1475                if (candidateWindow && !candidateWindow->mask().isEmpty()) {
1476                    QPoint localPoint = candidateWindow->mapFromGlobal(p);
1477                    if (!candidateWindow->mask().contains(localPoint))
1478                        continue;
1479                    else
1480                        return candidateWindow;
1481                } else {
1482                    if (i == firstQtWindowFound) {
1483                        // The cache will only work when the window under mouse is
1484                        // top most (that is, not partially obscured by other windows.
1485                        // And we only set it if no mask is present to optimize for the common case:
1486                        topLevelAt_cache = candidateWindow;
1487                    }
1488                    return candidateWindow;
1489                }
1490            }
1491        }
1492    }
1493
1494    topLevelAt_cache = 0;
1495    return 0;
1496#endif
1497}
1498
1499/*****************************************************************************
1500  Main event loop
1501 *****************************************************************************/
1502
1503bool QApplicationPrivate::modalState()
1504{
1505    return app_do_modal;
1506}
1507
1508#ifdef QT_MAC_USE_COCOA
1509#endif
1510
1511void QApplicationPrivate::enterModal_sys(QWidget *widget)
1512{
1513#ifdef DEBUG_MODAL_EVENTS
1514    Q_ASSERT(widget);
1515    qDebug("Entering modal state with %s::%s::%p (%d)", widget->metaObject()->className(), widget->objectName().toLocal8Bit().constData(),
1516            widget, qt_modal_stack ? (int)qt_modal_stack->count() : -1);
1517#endif
1518    if (!qt_modal_stack)
1519        qt_modal_stack = new QWidgetList;
1520
1521    dispatchEnterLeave(0, qt_last_mouse_receiver);
1522    qt_last_mouse_receiver = 0;
1523
1524    qt_modal_stack->insert(0, widget);
1525    if (!app_do_modal)
1526        qt_event_request_menubarupdate();
1527    app_do_modal = true;
1528    qt_button_down = 0;
1529
1530#ifdef QT_MAC_USE_COCOA
1531    if (!qt_mac_is_macsheet(widget))
1532        QEventDispatcherMacPrivate::beginModalSession(widget);
1533#endif
1534}
1535
1536void QApplicationPrivate::leaveModal_sys(QWidget *widget)
1537{
1538    if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
1539#ifdef DEBUG_MODAL_EVENTS
1540        qDebug("Leaving modal state with %s::%s::%p (%d)", widget->metaObject()->className(), widget->objectName().toLocal8Bit().constData(),
1541               widget, qt_modal_stack->count());
1542#endif
1543        if (qt_modal_stack->isEmpty()) {
1544            delete qt_modal_stack;
1545            qt_modal_stack = 0;
1546            QPoint p(QCursor::pos());
1547            app_do_modal = false;
1548            QWidget* w = 0;
1549            if (QWidget *grabber = QWidget::mouseGrabber())
1550                w = grabber;
1551            else
1552                w = QApplication::widgetAt(p.x(), p.y());
1553            dispatchEnterLeave(w, qt_last_mouse_receiver); // send synthetic enter event
1554            qt_last_mouse_receiver = w;
1555        }
1556#ifdef QT_MAC_USE_COCOA
1557        if (!qt_mac_is_macsheet(widget))
1558            QEventDispatcherMacPrivate::endModalSession(widget);
1559#endif
1560    }
1561#ifdef DEBUG_MODAL_EVENTS
1562    else qDebug("Failure to remove %s::%s::%p -- %p", widget->metaObject()->className(), widget->objectName().toLocal8Bit().constData(), widget, qt_modal_stack);
1563#endif
1564    app_do_modal = (qt_modal_stack != 0);
1565    if (!app_do_modal)
1566        qt_event_request_menubarupdate();
1567}
1568
1569QWidget *QApplicationPrivate::tryModalHelper_sys(QWidget *top)
1570{
1571#ifndef QT_MAC_USE_COCOA
1572    if(top && qt_mac_is_macsheet(top) && !IsWindowVisible(qt_mac_window_for(top))) {
1573        if(OSWindowRef wp = GetFrontWindowOfClass(kSheetWindowClass, true)) {
1574            if(QWidget *sheet = qt_mac_find_window(wp))
1575                top = sheet;
1576        }
1577    }
1578#endif
1579    return top;
1580}
1581
1582#ifndef QT_MAC_USE_COCOA
1583static bool qt_try_modal(QWidget *widget, EventRef event)
1584{
1585    QWidget * top = 0;
1586
1587    if (QApplicationPrivate::tryModalHelper(widget, &top))
1588        return true;
1589
1590    // INVARIANT: widget is modally shaddowed within its
1591    // window, and should therefore not handle the event.
1592    // However, if the window is not active, the event
1593    // might suggest that we should bring it to front:
1594
1595    bool block_event = false;
1596
1597    if (event) {
1598        switch (GetEventClass(event)) {
1599        case kEventClassMouse:
1600        case kEventClassKeyboard:
1601            block_event = true;
1602            break;
1603        }
1604    }
1605
1606    QWidget *activeWidget = QApplication::activeWindow();
1607    if ((!activeWidget || QApplicationPrivate::isBlockedByModal(activeWidget)) &&
1608       top->isWindow() && block_event && !QApplicationPrivate::native_modal_dialog_active)
1609        top->raise();
1610
1611#ifdef DEBUG_MODAL_EVENTS
1612    qDebug("%s:%d -- final decision! (%s)", __FILE__, __LINE__, block_event ? "false" : "true");
1613#endif
1614    return !block_event;
1615}
1616#endif
1617
1618OSStatus QApplicationPrivate::tabletProximityCallback(EventHandlerCallRef, EventRef carbonEvent,
1619                                                      void *)
1620{
1621    OSType eventClass = GetEventClass(carbonEvent);
1622    UInt32 eventKind = GetEventKind(carbonEvent);
1623    if (eventClass != kEventClassTablet || eventKind != kEventTabletProximity)
1624        return eventNotHandledErr;
1625
1626    // Get the current point of the device and its unique ID.
1627    ::TabletProximityRec proxRec;
1628    GetEventParameter(carbonEvent, kEventParamTabletProximityRec, typeTabletProximityRec, 0,
1629                      sizeof(proxRec), 0, &proxRec);
1630    qt_dispatchTabletProximityEvent(proxRec);
1631    return noErr;
1632}
1633
1634OSStatus
1635QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event, void *data)
1636{
1637#ifndef QT_MAC_USE_COCOA
1638    QApplication *app = (QApplication *)data;
1639    QScopedLoopLevelCounter loopLevelCounter(app->d_func()->threadData);
1640    long result;
1641    if (app->filterEvent(&event, &result))
1642        return result;
1643    if(app->macEventFilter(er, event)) //someone else ate it
1644        return noErr;
1645    QPointer<QWidget> widget;
1646
1647    /*We assume all events are handled and in
1648      the code below we set it to false when we know we didn't handle it, this
1649      will let rogue events through (shouldn't really happen, but better safe
1650      than sorry) */
1651    bool handled_event=true;
1652    UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event);
1653    switch(eclass)
1654    {
1655    case kEventClassQt:
1656        if(ekind == kEventQtRequestShowSheet) {
1657            request_showsheet_pending = 0;
1658            QWidget *widget = 0;
1659            GetEventParameter(event, kEventParamQWidget, typeQWidget, 0,
1660                              sizeof(widget), 0, &widget);
1661            if(widget) {
1662                if (widget->macEvent(er, event))
1663                    return noErr;
1664                WindowPtr window = qt_mac_window_for(widget);
1665                bool just_show = !qt_mac_is_macsheet(widget);
1666                if(!just_show) {
1667                    OSStatus err = ShowSheetWindow(window, qt_mac_window_for(widget->parentWidget()));
1668                    if(err != noErr)
1669                        qWarning("Qt: QWidget: Unable to show as sheet %s::%s [%ld]", widget->metaObject()->className(),
1670                                 widget->objectName().toLocal8Bit().constData(), long(err));
1671                    just_show = true;
1672                }
1673                if(just_show) //at least the window will be visible, but the sheet flag doesn't work sadly (probalby too many sheets)
1674                    ShowHide(window, true);
1675            }
1676        } else if(ekind == kEventQtRequestWindowChange) {
1677            qt_mac_event_release(request_window_change_pending);
1678        } else if(ekind == kEventQtRequestMenubarUpdate) {
1679            qt_mac_event_release(request_menubarupdate_pending);
1680            QMenuBar::macUpdateMenuBar();
1681        } else if(ekind == kEventQtRequestActivate) {
1682            qt_mac_event_release(request_activate_pending.event);
1683            if(request_activate_pending.widget) {
1684                QWidget *tlw = request_activate_pending.widget->window();
1685                if (tlw->macEvent(er, event))
1686                    return noErr;
1687                request_activate_pending.widget = 0;
1688                tlw->activateWindow();
1689                SelectWindow(qt_mac_window_for(tlw));
1690            }
1691        } else if(ekind == kEventQtRequestContext) {
1692            bool send = false;
1693            if ((send = (event == request_context_pending)))
1694                qt_mac_event_release(request_context_pending);
1695            if(send) {
1696                //figure out which widget to send it to
1697                QPoint where = QCursor::pos();
1698                QWidget *widget = 0;
1699                GetEventParameter(event, kEventParamQWidget, typeQWidget, 0,
1700                                  sizeof(widget), 0, &widget);
1701                if(!widget) {
1702                    if(qt_button_down)
1703                        widget = qt_button_down;
1704                    else
1705                        widget = QApplication::widgetAt(where.x(), where.y());
1706                }
1707                if(widget && !isBlockedByModal(widget)) {
1708                    if (widget->macEvent(er, event))
1709                        return noErr;
1710                    QPoint plocal(widget->mapFromGlobal(where));
1711                    const Qt::KeyboardModifiers keyboardModifiers = qt_mac_get_modifiers(GetCurrentEventKeyModifiers());
1712                    QContextMenuEvent qme(QContextMenuEvent::Mouse, plocal, where, keyboardModifiers);
1713                    QApplication::sendEvent(widget, &qme);
1714                    if(qme.isAccepted()) { //once this happens the events before are pitched
1715                        qt_button_down = 0;
1716                        qt_mac_dblclick.last_widget = 0;
1717                    }
1718                } else {
1719                    handled_event = false;
1720                }
1721            }
1722        } else {
1723            handled_event = false;
1724        }
1725        break;
1726    case kEventClassTablet:
1727        switch (ekind) {
1728        case kEventTabletProximity:
1729            // Get the current point of the device and its unique ID.
1730            ::TabletProximityRec proxRec;
1731            GetEventParameter(event, kEventParamTabletProximityRec, typeTabletProximityRec, 0,
1732                              sizeof(proxRec), 0, &proxRec);
1733            qt_dispatchTabletProximityEvent(proxRec);
1734        }
1735        break;
1736    case kEventClassMouse:
1737    {
1738        static const int kEventParamQAppSeenMouseEvent = 'QASM';
1739        // Check if we've seen the event, if we have we shouldn't process
1740        // it again as it may lead to spurious "double events"
1741        bool seenEvent;
1742        if (GetEventParameter(event, kEventParamQAppSeenMouseEvent,
1743                              typeBoolean, 0, sizeof(bool), 0, &seenEvent) == noErr) {
1744            if (seenEvent)
1745                return eventNotHandledErr;
1746        }
1747        seenEvent = true;
1748        SetEventParameter(event, kEventParamQAppSeenMouseEvent, typeBoolean,
1749                          sizeof(bool), &seenEvent);
1750
1751        Point where;
1752        bool inNonClientArea = false;
1753        GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0,
1754                          sizeof(where), 0, &where);
1755#if defined(DEBUG_MOUSE_MAPS)
1756        const char *edesc = 0;
1757        switch(ekind) {
1758        case kEventMouseDown: edesc = "MouseButtonPress"; break;
1759        case kEventMouseUp: edesc = "MouseButtonRelease"; break;
1760        case kEventMouseDragged: case kEventMouseMoved: edesc = "MouseMove"; break;
1761        case kEventMouseScroll: edesc = "MouseWheelScroll"; break;
1762        case kEventMouseWheelMoved: edesc = "MouseWheelMove"; break;
1763        }
1764        if(ekind == kEventMouseDown || ekind == kEventMouseUp)
1765            qDebug("Handling mouse: %s", edesc);
1766#endif
1767        QEvent::Type etype = QEvent::None;
1768        Qt::KeyboardModifiers modifiers;
1769        {
1770            UInt32 mac_modifiers = 0;
1771            GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 0,
1772                              sizeof(mac_modifiers), 0, &mac_modifiers);
1773            modifiers = qt_mac_get_modifiers(mac_modifiers);
1774        }
1775        Qt::MouseButtons buttons;
1776        {
1777            UInt32 mac_buttons = 0;
1778            GetEventParameter(event, kEventParamMouseChord, typeUInt32, 0,
1779                              sizeof(mac_buttons), 0, &mac_buttons);
1780            if (ekind != kEventMouseWheelMoved)
1781                buttons = qt_mac_get_buttons(mac_buttons);
1782            else
1783                buttons = QApplication::mouseButtons();
1784        }
1785
1786        int wheel_deltaX = 0;
1787        int wheel_deltaY = 0;
1788        static EventRef compatibilityEvent = 0;
1789
1790        if (ekind == kEventMouseScroll) {
1791            // kEventMouseScroll is the new way of dealing with mouse wheel
1792            // events (kEventMouseWheelMoved was the old). kEventMouseScroll results
1793            // in much smoother scrolling when using Mighty Mouse or TrackPad. For
1794            // compatibility with older applications, carbon will also send us
1795            // kEventMouseWheelMoved events if we dont eat this event
1796            // (actually two events; one for horizontal and one for vertical).
1797            // As a results of this, and to make sure we dont't receive duplicate events,
1798            // we try to detect when this happend by checking the 'compatibilityEvent'.
1799            // Since delta is delivered as pixels rather than degrees, we need to
1800            // convert from pixels to degrees in a sensible manner.
1801            // It looks like 1/4 degrees per pixel behaves most native.
1802            // (NB: Qt expects the unit for delta to be 8 per degree):
1803            const int pixelsToDegrees = 2;
1804            SInt32 mdelt = 0;
1805            GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0,
1806                              sizeof(mdelt), 0, &mdelt);
1807            wheel_deltaX = mdelt * pixelsToDegrees;
1808            mdelt = 0;
1809            GetEventParameter(event, kEventParamMouseWheelSmoothVerticalDelta, typeSInt32, 0,
1810                              sizeof(mdelt), 0, &mdelt);
1811            wheel_deltaY = mdelt * pixelsToDegrees;
1812            GetEventParameter(event, kEventParamEventRef, typeEventRef, 0,
1813                              sizeof(compatibilityEvent), 0, &compatibilityEvent);
1814        } else if (ekind == kEventMouseWheelMoved) {
1815            if (event != compatibilityEvent) {
1816                compatibilityEvent = 0;
1817                int mdelt = 0;
1818                GetEventParameter(event, kEventParamMouseWheelDelta, typeSInt32, 0,
1819                        sizeof(mdelt), 0, &mdelt);
1820                EventMouseWheelAxis axis;
1821                GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, 0,
1822                        sizeof(axis), 0, &axis);
1823
1824                // Remove acceleration, and use either -120 or 120 as delta:
1825                if (axis == kEventMouseWheelAxisX)
1826                    wheel_deltaX = qBound(-120, int(mdelt * 10000), 120);
1827                else
1828                    wheel_deltaY = qBound(-120, int(mdelt * 10000), 120);
1829            }
1830        }
1831
1832        Qt::MouseButton button = Qt::NoButton;
1833        if(ekind == kEventMouseDown || ekind == kEventMouseUp) {
1834            EventMouseButton mac_button = 0;
1835            GetEventParameter(event, kEventParamMouseButton, typeMouseButton, 0,
1836                              sizeof(mac_button), 0, &mac_button);
1837            button = qt_mac_get_button(mac_button);
1838        }
1839
1840        switch(ekind) {
1841        case kEventMouseDown:
1842            etype = QEvent::MouseButtonPress;
1843            break;
1844        case kEventMouseUp:
1845            etype = QEvent::MouseButtonRelease;
1846            break;
1847        case kEventMouseDragged:
1848        case kEventMouseMoved:
1849            etype = QEvent::MouseMove;
1850            break;
1851        }
1852
1853        const bool inPopupMode = app->d_func()->inPopupMode();
1854
1855        // A click outside a popup closes the popup. Make sure
1856        // that no events are generated for the release part of that click.
1857        // (The press goes to the popup and closes it.)
1858        if (etype == QEvent::MouseButtonPress) {
1859            qt_mac_previous_press_in_popup_mode = inPopupMode;
1860        } else if (qt_mac_previous_press_in_popup_mode && !inPopupMode && etype == QEvent::MouseButtonRelease) {
1861            qt_mac_previous_press_in_popup_mode = false;
1862            handled_event = true;
1863#if defined(DEBUG_MOUSE_MAPS)
1864            qDebug("Bail out early due to qt_mac_previous_press_in_popup_mode");
1865#endif
1866            break; // break from case kEventClassMouse
1867        }
1868
1869        //figure out which widget to send it to
1870        if(inPopupMode) {
1871            QWidget *popup = qApp->activePopupWidget();
1872            if (qt_button_down && qt_button_down->window() == popup) {
1873                widget = qt_button_down;
1874            } else {
1875                QPoint pos = popup->mapFromGlobal(QPoint(where.h, where.v));
1876                widget = popup->childAt(pos);
1877            }
1878            if(!widget)
1879                widget = popup;
1880        } else {
1881            if(mac_mouse_grabber) {
1882                widget = mac_mouse_grabber;
1883            } else if (qt_button_down) {
1884                widget = qt_button_down;
1885            } else {
1886                {
1887                    WindowPtr window = 0;
1888                    if(GetEventParameter(event, kEventParamWindowRef, typeWindowRef, 0,
1889                                         sizeof(window), 0, &window) != noErr)
1890                        FindWindowOfClass(&where, kAllWindowClasses, &window, 0);
1891                    if(window) {
1892                        HIViewRef hiview;
1893                        if(HIViewGetViewForMouseEvent(HIViewGetRoot(window), event, &hiview) == noErr) {
1894                            widget = QWidget::find((WId)hiview);
1895                            if (widget) {
1896                                // Make sure we didn't pass over a widget with a "fake hole" in it.
1897                                QWidget *otherWidget = QApplication::widgetAt(where.h, where.v);
1898                                if (otherWidget && otherWidget->testAttribute(Qt::WA_MouseNoMask))
1899                                    widget = otherWidget;
1900                            }
1901                        }
1902                    }
1903                }
1904                if(!widget) //fallback
1905                    widget = QApplication::widgetAt(where.h, where.v);
1906                if(ekind == kEventMouseUp && widget) {
1907                    short part = qt_mac_window_at(where.h, where.v);
1908                    if(part == inDrag) {
1909                        UInt32 count = 0;
1910                        GetEventParameter(event, kEventParamClickCount, typeUInt32, NULL,
1911                                          sizeof(count), NULL, &count);
1912                        if(count == 2 && qt_mac_collapse_on_dblclick) {
1913                            if (widget->macEvent(er, event))
1914                                return noErr;
1915                            widget->setWindowState(widget->windowState() | Qt::WindowMinimized);
1916                            //we send a hide to be like X11/Windows
1917                            QEvent e(QEvent::Hide);
1918                            QApplication::sendSpontaneousEvent(widget, &e);
1919                            break;
1920                        }
1921                    }
1922                }
1923            }
1924        }
1925        if (widget && widget->macEvent(er, event))
1926            return noErr;
1927        WindowPartCode wpc = qt_mac_window_at(where.h, where.v, 0);
1928        if (wpc == inProxyIcon && modifiers == Qt::ControlModifier && buttons != Qt::NoButton) {
1929            QIconDragEvent e;
1930            QApplication::sendSpontaneousEvent(widget, &e);
1931            if (e.isAccepted()) {
1932                return noErr; // IconDrag ate it.
1933            }
1934        }
1935        if (inPopupMode == false
1936                && (qt_button_down == 0 || qt_button_down_in_content == false)
1937                && (wpc != inContent && wpc != inStructure)) {
1938            inNonClientArea = true;
1939            switch (etype) {
1940            case QEvent::MouseButtonPress: {
1941                UInt32 count = 0;
1942                GetEventParameter(event, kEventParamClickCount, typeUInt32, 0,
1943                                      sizeof(count), 0, &count);
1944                if(count % 2 || count == 0) {
1945                    etype = QEvent::NonClientAreaMouseButtonPress;
1946                } else {
1947                    etype = QEvent::NonClientAreaMouseButtonDblClick;
1948                }} break;
1949            case QEvent::MouseButtonRelease:
1950                etype = QEvent::NonClientAreaMouseButtonRelease;
1951                break;
1952            case QEvent::MouseMove:
1953                if (widget == 0 || widget->hasMouseTracking())
1954                    etype = QEvent::NonClientAreaMouseMove;
1955                break;
1956            default:
1957                break;
1958            }
1959        }
1960
1961        if(qt_mac_find_window((FrontWindow()))) { //set the cursor up
1962            QCursor cursor(Qt::ArrowCursor);
1963            QWidget *cursor_widget = widget;
1964            if(cursor_widget && cursor_widget == qt_button_down && ekind == kEventMouseUp)
1965                cursor_widget = QApplication::widgetAt(where.h, where.v);
1966            if(cursor_widget) { //only over the app, do we set a cursor..
1967                if(!qApp->d_func()->cursor_list.isEmpty()) {
1968                    cursor = qApp->d_func()->cursor_list.first();
1969                } else {
1970                    for(; cursor_widget; cursor_widget = cursor_widget->parentWidget()) {
1971                        QWExtra *extra = cursor_widget->d_func()->extraData();
1972                        if(extra && extra->curs && cursor_widget->isEnabled()) {
1973                            cursor = *extra->curs;
1974                            break;
1975                        }
1976                    }
1977                }
1978            }
1979            qt_mac_set_cursor(&cursor);
1980        }
1981
1982        //This mouse button state stuff looks like this on purpose
1983        //although it looks hacky it is VERY intentional..
1984        if(widget && app_do_modal && !qt_try_modal(widget, event)) {
1985            if(ekind == kEventMouseDown && qt_mac_is_macsheet(QApplication::activeModalWidget()))
1986                QApplication::activeModalWidget()->parentWidget()->activateWindow(); //sheets have a parent
1987            handled_event = false;
1988#if defined(DEBUG_MOUSE_MAPS)
1989            qDebug("Bail out early due to qt_try_modal");
1990#endif
1991            break;
1992        }
1993
1994        UInt32 tabletEventType = 0;
1995        GetEventParameter(event, kEventParamTabletEventType, typeUInt32, 0,
1996                          sizeof(tabletEventType), 0, &tabletEventType);
1997        if (tabletEventType == kEventTabletPoint) {
1998            TabletPointRec tabletPointRec;
1999            GetEventParameter(event, kEventParamTabletPointRec, typeTabletPointRec, 0,
2000                              sizeof(tabletPointRec), 0, &tabletPointRec);
2001            QEvent::Type t = QEvent::TabletMove; //default
2002            int new_tablet_button_state = tabletPointRec.buttons ? 1 : 0;
2003            if (new_tablet_button_state != tablet_button_state)
2004                if (new_tablet_button_state)
2005                    t = QEvent::TabletPress;
2006                else
2007                    t = QEvent::TabletRelease;
2008            tablet_button_state = new_tablet_button_state;
2009
2010            QMacTabletHash *tabletHash = qt_mac_tablet_hash();
2011            if (!tabletHash->contains(tabletPointRec.deviceID) && t != QEvent::TabletRelease) {
2012                // Never discard TabletRelease events as they may be delivered *after* TabletLeaveProximity events
2013                qWarning("handleTabletEvent: This tablet device is unknown"
2014                         " (received no proximity event for it). Discarding event.");
2015                return false;
2016            }
2017            QTabletDeviceData &deviceData = tabletHash->operator[](tabletPointRec.deviceID);
2018            if (t == QEvent::TabletPress) {
2019                deviceData.widgetToGetPress = widget;
2020            } else if (t == QEvent::TabletRelease && deviceData.widgetToGetPress) {
2021                widget = deviceData.widgetToGetPress;
2022                deviceData.widgetToGetPress = 0;
2023            }
2024
2025            if (widget) {
2026                int tiltX = ((int)tabletPointRec.tiltX)/(32767/64); // 32K -> 60
2027                int tiltY = ((int)tabletPointRec.tiltY)/(-32767/64); // 32K -> 60
2028                HIPoint hiPoint;
2029                GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, 0, sizeof(HIPoint), 0, &hiPoint);
2030                QPointF hiRes(hiPoint.x, hiPoint.y);
2031                QPoint global(where.h, where.v);
2032
2033
2034
2035                QPoint local(widget->mapFromGlobal(global));
2036                int z = 0;
2037                qreal rotation = 0.0;
2038                qreal tp = 0.0;
2039                // Again from the Wacom.h header
2040
2041                if (deviceData.capabilityMask & 0x0200)     // Z-axis
2042                    z = tabletPointRec.absZ;
2043
2044                if (deviceData.capabilityMask & 0x0800)  // Tangential pressure
2045                    tp = tabletPointRec.tangentialPressure / 32767.0;
2046
2047                if (deviceData.capabilityMask & 0x2000) // Rotation
2048                    rotation = qreal(tabletPointRec.rotation) / 64.0;
2049
2050                QTabletEvent e(t, local, global, hiRes, deviceData.tabletDeviceType,
2051                               deviceData.tabletPointerType,
2052                               qreal(tabletPointRec.pressure / qreal(0xffff)), tiltX, tiltY,
2053                               tp, rotation, z, modifiers, deviceData.tabletUniqueID);
2054                QApplication::sendSpontaneousEvent(widget, &e);
2055                if (e.isAccepted()) {
2056                    if (t == QEvent::TabletPress) {
2057                        qt_button_down = widget;
2058                    } else if (t == QEvent::TabletRelease) {
2059                        qt_button_down = 0;
2060                    }
2061#if defined(DEBUG_MOUSE_MAPS)
2062                    qDebug("Bail out early due to tablet acceptance");
2063#endif
2064                    break;
2065                }
2066            }
2067        }
2068
2069        if(ekind == kEventMouseDown) {
2070            qt_mac_no_click_through_mode = false;
2071            const short windowPart = qt_mac_window_at(where.h, where.v, 0);
2072            // Menubar almost always wins.
2073            if (!inPopupMode && windowPart == inMenuBar) {
2074                MenuSelect(where); //allow menu tracking
2075                return noErr;
2076            }
2077
2078            if (widget && !(GetCurrentKeyModifiers() & cmdKey)) {
2079                extern bool qt_isGenuineQWidget(const QWidget *); // qwidget_mac.cpp
2080                QWidget *window = widget->window();
2081                bool genuineQtWidget = qt_isGenuineQWidget(widget);  // the widget, not the window.
2082                window->raise();
2083
2084                bool needActivate = (window->windowType() != Qt::Desktop)
2085                                     && (window->windowType() != Qt::Popup)
2086                                     && !qt_mac_is_macsheet(window);
2087                if (needActivate && (!window->isModal() && qobject_cast<QDockWidget *>(window)))
2088                    needActivate = false;
2089
2090                if (genuineQtWidget && needActivate)
2091                    needActivate = !window->isActiveWindow()
2092                                    || !IsWindowActive(qt_mac_window_for(window));
2093
2094                if (needActivate) {
2095                    window->activateWindow();
2096                    if (!qt_mac_can_clickThrough(widget)) {
2097                        qt_mac_no_click_through_mode = true;
2098                        handled_event = false;
2099#if defined(DEBUG_MOUSE_MAPS)
2100                        qDebug("Bail out early due to qt_mac_canClickThrough %s::%s", widget->metaObject()->className(),
2101                                widget->objectName().toLocal8Bit().constData());
2102#endif
2103                        break;
2104                    }
2105                }
2106            }
2107
2108            if(qt_mac_dblclick.last_widget &&
2109               qt_mac_dblclick.last_x != -1 && qt_mac_dblclick.last_y != -1 &&
2110               QRect(qt_mac_dblclick.last_x-2, qt_mac_dblclick.last_y-2, 4, 4).contains(QPoint(where.h, where.v))) {
2111                if(qt_mac_dblclick.use_qt_time_limit) {
2112                    EventTime now = GetEventTime(event);
2113                    if(qt_mac_dblclick.last_time != -2 && qt_mac_dblclick.last_widget == widget &&
2114                       now - qt_mac_dblclick.last_time <= ((double)QApplicationPrivate::mouse_double_click_time)/1000 &&
2115                       qt_mac_dblclick.last_button == button)
2116                        etype = QEvent::MouseButtonDblClick;
2117                } else {
2118                    UInt32 count = 0;
2119                    GetEventParameter(event, kEventParamClickCount, typeUInt32, 0,
2120                                      sizeof(count), 0, &count);
2121                    if(!(count % 2) && qt_mac_dblclick.last_modifiers == modifiers &&
2122                       qt_mac_dblclick.last_widget == widget && qt_mac_dblclick.last_button == button)
2123                        etype = QEvent::MouseButtonDblClick;
2124                }
2125                if(etype == QEvent::MouseButtonDblClick)
2126                    qt_mac_dblclick.last_widget = 0;
2127            }
2128            if(etype != QEvent::MouseButtonDblClick) {
2129                qt_mac_dblclick.last_x = where.h;
2130                qt_mac_dblclick.last_y = where.v;
2131            } else {
2132                qt_mac_dblclick.last_x = qt_mac_dblclick.last_y = -1;
2133            }
2134        } else if(qt_mac_no_click_through_mode) {
2135            if(ekind == kEventMouseUp)
2136                qt_mac_no_click_through_mode = false;
2137            handled_event = false;
2138#if defined(DEBUG_MOUSE_MAPS)
2139            qDebug("Bail out early due to qt_mac_no_click_through_mode");
2140#endif
2141            break;
2142        }
2143
2144        QPointer<QWidget> leaveAfterRelease = 0;
2145        switch(ekind) {
2146        case kEventMouseUp:
2147            if (!buttons) {
2148                if (!inPopupMode && !QWidget::mouseGrabber())
2149                    leaveAfterRelease = qt_button_down;
2150                qt_button_down = 0;
2151            }
2152            break;
2153        case kEventMouseDown: {
2154            if (!qt_button_down)
2155                qt_button_down = widget;
2156            WindowPartCode wpc = qt_mac_window_at(where.h, where.v, 0);
2157            qt_button_down_in_content = (wpc == inContent || wpc == inStructure);
2158            break;  }
2159        }
2160
2161        // Check if we should send enter/leave events:
2162        switch(ekind) {
2163        case kEventMouseDragged:
2164        case kEventMouseMoved:
2165        case kEventMouseUp:
2166        case kEventMouseDown: {
2167            // If we are in popup mode, widget will point to the current popup no matter
2168            // where the mouse cursor is. In that case find out if the mouse cursor is
2169            // really over the popup in order to send correct enter / leave envents.
2170            QWidget * const enterLeaveWidget = (inPopupMode || ekind == kEventMouseUp) ?
2171                    QApplication::widgetAt(where.h, where.v) :  static_cast<QWidget*>(widget);
2172
2173            if ((QWidget *) qt_last_mouse_receiver != enterLeaveWidget || inNonClientArea) {
2174#ifdef DEBUG_MOUSE_MAPS
2175                qDebug("Entering: %p - %s (%s), Leaving %s (%s)", (QWidget*)enterLeaveWidget,
2176                       enterLeaveWidget ? enterLeaveWidget->metaObject()->className() : "none",
2177                       enterLeaveWidget ? enterLeaveWidget->objectName().toLocal8Bit().constData() : "",
2178                       qt_last_mouse_receiver ? qt_last_mouse_receiver->metaObject()->className() : "none",
2179                       qt_last_mouse_receiver ? qt_last_mouse_receiver->objectName().toLocal8Bit().constData() : "");
2180#endif
2181
2182                QWidget * const mouseGrabber = QWidget::mouseGrabber();
2183
2184                if (inPopupMode) {
2185                    QWidget *enter = enterLeaveWidget;
2186                    QWidget *leave = qt_last_mouse_receiver;
2187                    if (mouseGrabber) {
2188                        QWidget * const popupWidget = qApp->activePopupWidget();
2189                        if (leave == popupWidget)
2190                            enter = mouseGrabber;
2191                        if (enter == popupWidget)
2192                            leave = mouseGrabber;
2193                        if ((enter == mouseGrabber && leave == popupWidget)
2194                            || (leave == mouseGrabber  && enter == popupWidget)) {
2195                            QApplicationPrivate::dispatchEnterLeave(enter, leave);
2196                            qt_last_mouse_receiver = enter;
2197                        }
2198                    } else {
2199                        QApplicationPrivate::dispatchEnterLeave(enter, leave);
2200                        qt_last_mouse_receiver = enter;
2201                    }
2202                } else if ((!qt_button_down || !qt_last_mouse_receiver) && !mouseGrabber && !leaveAfterRelease) {
2203                    QApplicationPrivate::dispatchEnterLeave(enterLeaveWidget, qt_last_mouse_receiver);
2204                    qt_last_mouse_receiver = enterLeaveWidget;
2205                }
2206            }
2207            break; }
2208        }
2209
2210        if(widget) {
2211            QPoint p(where.h, where.v);
2212            QPoint plocal(widget->mapFromGlobal(p));
2213            if(etype == QEvent::MouseButtonPress) {
2214                qt_mac_dblclick.last_widget = widget;
2215                qt_mac_dblclick.last_modifiers = modifiers;
2216                qt_mac_dblclick.last_button = button;
2217                qt_mac_dblclick.last_time = GetEventTime(event);
2218            }
2219
2220            if (wheel_deltaX || wheel_deltaY) {
2221#ifndef QT_NO_WHEELEVENT
2222                if (wheel_deltaX) {
2223                    QWheelEvent qwe(plocal, p, wheel_deltaX, buttons, modifiers, Qt::Horizontal);
2224                    QApplication::sendSpontaneousEvent(widget, &qwe);
2225                    if (!qwe.isAccepted() && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != widget) {
2226                        QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(p), p,
2227                                wheel_deltaX, buttons, modifiers, Qt::Horizontal);
2228                        QApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
2229                        if (!qwe2.isAccepted())
2230                            handled_event = false;
2231                    }
2232                }
2233                if (wheel_deltaY) {
2234                    QWheelEvent qwe(plocal, p, wheel_deltaY, buttons, modifiers, Qt::Vertical);
2235                    QApplication::sendSpontaneousEvent(widget, &qwe);
2236                    if (!qwe.isAccepted() && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != widget) {
2237                        QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(p), p,
2238                                wheel_deltaY, buttons, modifiers, Qt::Vertical);
2239                        QApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
2240                        if (!qwe2.isAccepted())
2241                            handled_event = false;
2242                    }
2243                }
2244#endif // QT_NO_WHEELEVENT
2245            } else {
2246#ifdef QMAC_SPEAK_TO_ME
2247                const int speak_keys = Qt::AltModifier | Qt::ShiftModifier;
2248		if(etype == QMouseEvent::MouseButtonDblClick && ((modifiers & speak_keys) == speak_keys)) {
2249                    QVariant v = widget->property("displayText");
2250                    if(!v.isValid()) v = widget->property("text");
2251                    if(!v.isValid()) v = widget->property("windowTitle");
2252                    if(v.isValid()) {
2253                        QString s = v.toString();
2254                        s.replace(QRegExp(QString::fromLatin1("(\\&|\\<[^\\>]*\\>)")), QLatin1String(""));
2255                        SpeechChannel ch;
2256                        NewSpeechChannel(0, &ch);
2257                        SpeakText(ch, s.toLatin1().constData(), s.length());
2258                        DisposeSpeechChannel(ch);
2259                    }
2260                }
2261#endif
2262                Qt::MouseButton buttonToSend = button;
2263                static bool lastButtonTranslated = false;
2264                if(ekind == kEventMouseDown &&
2265                   button == Qt::LeftButton && (modifiers & Qt::MetaModifier)) {
2266                    buttonToSend = Qt::RightButton;
2267                    lastButtonTranslated = true;
2268                } else if(ekind == kEventMouseUp && lastButtonTranslated) {
2269                    buttonToSend = Qt::RightButton;
2270                    lastButtonTranslated = false;
2271                }
2272                QMouseEvent qme(etype, plocal, p, buttonToSend, buttons, modifiers);
2273                QApplication::sendSpontaneousEvent(widget, &qme);
2274                if(!qme.isAccepted() || inNonClientArea)
2275                    handled_event = false;
2276            }
2277
2278            if (leaveAfterRelease) {
2279                QWidget *enter = QApplication::widgetAt(where.h, where.v);
2280                QApplicationPrivate::dispatchEnterLeave(enter, leaveAfterRelease);
2281                qt_last_mouse_receiver = enter;
2282                leaveAfterRelease = 0;
2283            }
2284
2285            if(ekind == kEventMouseDown &&
2286               ((button == Qt::RightButton) ||
2287                (button == Qt::LeftButton && (modifiers & Qt::MetaModifier))))
2288                qt_event_request_context();
2289
2290#ifdef DEBUG_MOUSE_MAPS
2291            const char *event_desc = edesc;
2292            if(etype == QEvent::MouseButtonDblClick)
2293                event_desc = "Double Click";
2294            else if(etype == QEvent::NonClientAreaMouseButtonPress)
2295                event_desc = "NonClientMousePress";
2296            else if(etype == QEvent::NonClientAreaMouseButtonRelease)
2297                event_desc = "NonClientMouseRelease";
2298            else if(etype == QEvent::NonClientAreaMouseMove)
2299                event_desc = "NonClientMouseMove";
2300            else if(etype == QEvent::NonClientAreaMouseButtonDblClick)
2301                event_desc = "NonClientMouseDblClick";
2302            qDebug("%d %d (%d %d) - Would send (%s) event to %p %s %s (%d 0x%08x 0x%08x %d)", p.x(), p.y(),
2303                   plocal.x(), plocal.y(), event_desc, (QWidget*)widget,
2304                   widget ? widget->objectName().toLocal8Bit().constData() : "*Unknown*",
2305                   widget ? widget->metaObject()->className() : "*Unknown*",
2306                   button, (int)buttons, (int)modifiers, wheel_deltaX);
2307#endif
2308        } else {
2309            handled_event = false;
2310        }
2311        break;
2312    }
2313    case kEventClassTextInput:
2314    case kEventClassKeyboard: {
2315        EventRef key_event = event;
2316        if(eclass == kEventClassTextInput) {
2317            Q_ASSERT(ekind == kEventTextInputUnicodeForKeyEvent);
2318            OSStatus err = GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, 0,
2319                                             sizeof(key_event), 0, &key_event);
2320            Q_ASSERT(err == noErr);
2321            Q_UNUSED(err);
2322        }
2323        const UInt32 key_ekind = GetEventKind(key_event);
2324        Q_ASSERT(GetEventClass(key_event) == kEventClassKeyboard);
2325
2326        if(key_ekind == kEventRawKeyDown)
2327            qt_keymapper_private()->updateKeyMap(er, key_event, data);
2328        if(mac_keyboard_grabber)
2329            widget = mac_keyboard_grabber;
2330        else if (app->activePopupWidget())
2331            widget = (app->activePopupWidget()->focusWidget() ?
2332                      app->activePopupWidget()->focusWidget() : app->activePopupWidget());
2333        else if(QApplication::focusWidget())
2334            widget = QApplication::focusWidget();
2335        else
2336            widget = app->activeWindow();
2337
2338        if (widget) {
2339            if (widget->macEvent(er, event))
2340                return noErr;
2341        } else {
2342            // Darn, I need to update tho modifier state, even though
2343            // Qt itself isn't getting them, otherwise the keyboard state get inconsistent.
2344            if (key_ekind == kEventRawKeyModifiersChanged) {
2345                UInt32 modifiers = 0;
2346                GetEventParameter(key_event, kEventParamKeyModifiers, typeUInt32, 0,
2347                                  sizeof(modifiers), 0, &modifiers);
2348                extern void qt_mac_send_modifiers_changed(quint32 modifiers, QObject *object); // qkeymapper_mac.cpp
2349                // Just send it to the qApp for the time being.
2350                qt_mac_send_modifiers_changed(modifiers, qApp);
2351            }
2352            handled_event = false;
2353            break;
2354        }
2355
2356        if(app_do_modal && !qt_try_modal(widget, key_event))
2357            break;
2358        if (eclass == kEventClassTextInput) {
2359            handled_event = false;
2360        } else {
2361            handled_event = qt_keymapper_private()->translateKeyEvent(widget, er, key_event, data,
2362                                                                      widget == mac_keyboard_grabber);
2363        }
2364        break; }
2365    case kEventClassWindow: {
2366        WindowRef wid = 0;
2367        GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0,
2368                          sizeof(WindowRef), 0, &wid);
2369        widget = qt_mac_find_window(wid);
2370        if (widget && widget->macEvent(er, event))
2371            return noErr;
2372        if(ekind == kEventWindowActivated) {
2373            if(QApplicationPrivate::app_style) {
2374                QEvent ev(QEvent::Style);
2375                QApplication::sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
2376            }
2377
2378            if(widget && app_do_modal && !qt_try_modal(widget, event))
2379                break;
2380
2381            if(widget && widget->window()->isVisible()) {
2382                QWidget *tlw = widget->window();
2383		if(tlw->isWindow() && !(tlw->windowType() == Qt::Popup)
2384                   && !qt_mac_is_macdrawer(tlw)
2385                   && (!tlw->parentWidget() || tlw->isModal()
2386                       || !(tlw->windowType() == Qt::Tool))) {
2387                    bool just_send_event = false;
2388                    {
2389                        WindowActivationScope scope;
2390                        if(GetWindowActivationScope((WindowRef)wid, &scope) == noErr &&
2391                           scope == kWindowActivationScopeIndependent) {
2392                            if(GetFrontWindowOfClass(kAllWindowClasses, true) != wid)
2393                                just_send_event = true;
2394                        }
2395                    }
2396                    if(just_send_event) {
2397                        QEvent e(QEvent::WindowActivate);
2398                        QApplication::sendSpontaneousEvent(widget, &e);
2399                    } else {
2400                        app->setActiveWindow(tlw);
2401                    }
2402                }
2403                QMenuBar::macUpdateMenuBar();
2404            }
2405        } else if(ekind == kEventWindowDeactivated) {
2406            if(widget && QApplicationPrivate::active_window == widget)
2407                app->setActiveWindow(0);
2408        } else {
2409            handled_event = false;
2410        }
2411        break; }
2412    case kEventClassApplication:
2413        if(ekind == kEventAppActivated) {
2414            if(QApplication::desktopSettingsAware())
2415                qt_mac_update_os_settings();
2416            if(qt_clipboard) { //manufacture an event so the clipboard can see if it has changed
2417                QEvent ev(QEvent::Clipboard);
2418                QApplication::sendSpontaneousEvent(qt_clipboard, &ev);
2419            }
2420            if(app) {
2421                QEvent ev(QEvent::ApplicationActivate);
2422                QApplication::sendSpontaneousEvent(app, &ev);
2423            }
2424            if(!app->activeWindow()) {
2425                WindowPtr wp = ActiveNonFloatingWindow();
2426                if(QWidget *tmp_w = qt_mac_find_window(wp))
2427                    app->setActiveWindow(tmp_w);
2428            }
2429            QMenuBar::macUpdateMenuBar();
2430        } else if(ekind == kEventAppDeactivated) {
2431            //qt_mac_no_click_through_mode = false;
2432            while(app->d_func()->inPopupMode())
2433                app->activePopupWidget()->close();
2434            if(app) {
2435                QEvent ev(QEvent::ApplicationDeactivate);
2436                QApplication::sendSpontaneousEvent(app, &ev);
2437            }
2438            app->setActiveWindow(0);
2439        } else if(ekind == kEventAppAvailableWindowBoundsChanged) {
2440            QDesktopWidgetImplementation::instance()->onResize();
2441        } else {
2442            handled_event = false;
2443        }
2444        break;
2445    case kAppearanceEventClass:
2446        if(ekind == kAEAppearanceChanged) {
2447            if(QApplication::desktopSettingsAware())
2448                qt_mac_update_os_settings();
2449            if(QApplicationPrivate::app_style) {
2450                QEvent ev(QEvent::Style);
2451                QApplication::sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
2452            }
2453        } else {
2454            handled_event = false;
2455        }
2456        break;
2457    case kEventClassAppleEvent:
2458        if(ekind == kEventAppleEvent) {
2459            EventRecord erec;
2460            if(!ConvertEventRefToEventRecord(event, &erec))
2461                qDebug("Qt: internal: WH0A, unexpected condition reached. %s:%d", __FILE__, __LINE__);
2462            else if(AEProcessAppleEvent(&erec) != noErr)
2463                handled_event = false;
2464        } else {
2465            handled_event = false;
2466        }
2467        break;
2468    case kEventClassCommand:
2469        if(ekind == kEventCommandProcess) {
2470            HICommand cmd;
2471            GetEventParameter(event, kEventParamDirectObject, typeHICommand,
2472                              0, sizeof(cmd), 0, &cmd);
2473            handled_event = false;
2474            if(!cmd.menu.menuRef && GetApplicationDockTileMenu()) {
2475                EventRef copy = CopyEvent(event);
2476                HICommand copy_cmd;
2477                GetEventParameter(event, kEventParamDirectObject, typeHICommand,
2478                                  0, sizeof(copy_cmd), 0, &copy_cmd);
2479                copy_cmd.menu.menuRef = GetApplicationDockTileMenu();
2480                SetEventParameter(copy, kEventParamDirectObject, typeHICommand, sizeof(copy_cmd), &copy_cmd);
2481                if(SendEventToMenu(copy, copy_cmd.menu.menuRef) == noErr)
2482                    handled_event = true;
2483            }
2484            if(!handled_event) {
2485                if(cmd.commandID == kHICommandQuit) {
2486                    // Quitting the application is not Qt's responsibility if
2487                    // used in a plugin or just embedded into a native application.
2488                    // In that case, let the event pass down to the native apps event handler.
2489                    if (!QApplication::testAttribute(Qt::AA_MacPluginApplication)) {
2490                        handled_event = true;
2491                        HiliteMenu(0);
2492                        bool handle_quit = true;
2493                        if(QApplicationPrivate::modalState()) {
2494                            int visible = 0;
2495                            const QWidgetList tlws = QApplication::topLevelWidgets();
2496                            for(int i = 0; i < tlws.size(); ++i) {
2497                                if(tlws.at(i)->isVisible())
2498                                    ++visible;
2499                            }
2500                            handle_quit = (visible <= 1);
2501                        }
2502                        if(handle_quit) {
2503                            QCloseEvent ev;
2504                            QApplication::sendSpontaneousEvent(app, &ev);
2505                            if(ev.isAccepted())
2506                                app->quit();
2507                        } else {
2508                            QApplication::beep();
2509                        }
2510                    }
2511                } else if(cmd.commandID == kHICommandSelectWindow) {
2512                    if((GetCurrentKeyModifiers() & cmdKey))
2513                        handled_event = true;
2514                } else if(cmd.commandID == kHICommandAbout) {
2515                    QMessageBox::aboutQt(0);
2516                    HiliteMenu(0);
2517                    handled_event = true;
2518                }
2519            }
2520        }
2521        break;
2522    }
2523
2524#ifdef DEBUG_EVENTS
2525    qDebug("%shandled event %c%c%c%c %d", handled_event ? "(*) " : "",
2526           char(eclass >> 24), char((eclass >> 16) & 255), char((eclass >> 8) & 255),
2527           char(eclass & 255), (int)ekind);
2528#endif
2529    if(!handled_event) //let the event go through
2530        return eventNotHandledErr;
2531    return noErr; //we eat the event
2532#else
2533    Q_UNUSED(er);
2534    Q_UNUSED(event);
2535    Q_UNUSED(data);
2536    return eventNotHandledErr;
2537#endif
2538}
2539
2540#ifdef QT_MAC_USE_COCOA
2541void QApplicationPrivate::qt_initAfterNSAppStarted()
2542{
2543    setupAppleEvents();
2544    qt_mac_update_cursor();
2545}
2546
2547void QApplicationPrivate::setupAppleEvents()
2548{
2549    // This function is called from the event dispatcher when NSApplication has
2550    // finished initialization, which appears to be just after [NSApplication run] has
2551    // started to execute. By setting up our apple events handlers this late, we override
2552    // the ones set up by NSApplication.
2553
2554    // If Qt is used as a plugin, we let the 3rd party application handle events
2555    // like quit and open file events. Otherwise, if we install our own handlers, we
2556    // easily end up breaking functionallity the 3rd party application depend on:
2557    if (QApplication::testAttribute(Qt::AA_MacPluginApplication))
2558        return;
2559
2560    QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
2561    NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
2562    [eventManager setEventHandler:newDelegate andSelector:@selector(appleEventQuit:withReplyEvent:)
2563     forEventClass:kCoreEventClass andEventID:kAEQuitApplication];
2564    [eventManager setEventHandler:newDelegate andSelector:@selector(getUrl:withReplyEvent:)
2565      forEventClass:kInternetEventClass andEventID:kAEGetURL];
2566}
2567#endif
2568
2569// In Carbon this is your one stop for apple events.
2570// In Cocoa, it ISN'T. This is the catch-all Apple Event handler that exists
2571// for the time between instantiating the NSApplication, but before the
2572// NSApplication has installed it's OWN Apple Event handler. When Cocoa has
2573// that set up, we remove this.  So, if you are debugging problems, you likely
2574// want to check out QCocoaApplicationDelegate instead.
2575OSStatus QApplicationPrivate::globalAppleEventProcessor(const AppleEvent *ae, AppleEvent *, long handlerRefcon)
2576{
2577    QApplication *app = (QApplication *)handlerRefcon;
2578    bool handled_event=false;
2579    OSType aeID=typeWildCard, aeClass=typeWildCard;
2580    AEGetAttributePtr(ae, keyEventClassAttr, typeType, 0, &aeClass, sizeof(aeClass), 0);
2581    AEGetAttributePtr(ae, keyEventIDAttr, typeType, 0, &aeID, sizeof(aeID), 0);
2582    if(aeClass == kCoreEventClass) {
2583        switch(aeID) {
2584        case kAEQuitApplication: {
2585            extern bool qt_mac_quit_menu_item_enabled; // qmenu_mac.cpp
2586            if (qt_mac_quit_menu_item_enabled) {
2587                QCloseEvent ev;
2588                QApplication::sendSpontaneousEvent(app, &ev);
2589                if(ev.isAccepted()) {
2590                    handled_event = true;
2591                    app->quit();
2592                }
2593            } else {
2594                QApplication::beep();  // Sorry, you can't quit right now.
2595            }
2596            break; }
2597        case kAEOpenDocuments: {
2598            AEDescList docs;
2599            if(AEGetParamDesc(ae, keyDirectObject, typeAEList, &docs) == noErr) {
2600                long cnt = 0;
2601                AECountItems(&docs, &cnt);
2602                UInt8 *str_buffer = NULL;
2603                for(int i = 0; i < cnt; i++) {
2604                    FSRef ref;
2605                    if(AEGetNthPtr(&docs, i+1, typeFSRef, 0, 0, &ref, sizeof(ref), 0) != noErr)
2606                        continue;
2607                    if(!str_buffer)
2608                        str_buffer = (UInt8 *)malloc(1024);
2609                    FSRefMakePath(&ref, str_buffer, 1024);
2610                    QFileOpenEvent ev(QString::fromUtf8((const char *)str_buffer));
2611                    QApplication::sendSpontaneousEvent(app, &ev);
2612                }
2613                if(str_buffer)
2614                    free(str_buffer);
2615            }
2616            break; }
2617        default:
2618            break;
2619        }
2620    } else if (aeClass == kInternetEventClass) {
2621        switch (aeID) {
2622        case kAEGetURL: {
2623            char urlData[1024];
2624            Size actualSize;
2625            if (AEGetParamPtr(ae, keyDirectObject, typeChar, 0, urlData,
2626                    sizeof(urlData) - 1, &actualSize) == noErr) {
2627                urlData[actualSize] = 0;
2628                QFileOpenEvent ev(QUrl(QString::fromUtf8(urlData)));
2629                QApplication::sendSpontaneousEvent(app, &ev);
2630            }
2631            break;
2632        }
2633        default:
2634            break;
2635        }
2636    }
2637#ifdef DEBUG_EVENTS
2638    qDebug("Qt: internal: %shandled Apple event! %c%c%c%c %c%c%c%c", handled_event ? "(*)" : "",
2639           char(aeID >> 24), char((aeID >> 16) & 255), char((aeID >> 8) & 255),char(aeID & 255),
2640           char(aeClass >> 24), char((aeClass >> 16) & 255), char((aeClass >> 8) & 255),char(aeClass & 255));
2641#else
2642    if(!handled_event) //let the event go through
2643        return eventNotHandledErr;
2644    return noErr; //we eat the event
2645#endif
2646}
2647
2648/*!
2649    \fn bool QApplication::macEventFilter(EventHandlerCallRef caller, EventRef event)
2650
2651    \warning This virtual function is only used under Mac OS X, and behaves different
2652    depending on if Qt is based on Carbon or Cocoa.
2653
2654    For the Carbon port, If you create an application that inherits QApplication and reimplement
2655    this function, you get direct access to all Carbon Events that Qt registers
2656    for from Mac OS X with this function being called with the \a caller and
2657    the \a event.
2658
2659    For the Cocoa port, If you create an application that inherits QApplication and reimplement
2660    this function, you get direct access to all Cocoa Events that Qt receives
2661    from Mac OS X with this function being called with the \a caller being 0 and
2662    the \a event being an NSEvent pointer:
2663
2664    NSEvent *e = reinterpret_cast<NSEvent *>(event);
2665
2666    Return true if you want to stop the event from being processed.
2667    Return false for normal event dispatching. The default
2668    implementation returns false.
2669*/
2670bool QApplication::macEventFilter(EventHandlerCallRef, EventRef)
2671{
2672    return false;
2673}
2674
2675/*!
2676    \internal
2677*/
2678void QApplicationPrivate::openPopup(QWidget *popup)
2679{
2680    if (!QApplicationPrivate::popupWidgets)                        // create list
2681        QApplicationPrivate::popupWidgets = new QWidgetList;
2682    QApplicationPrivate::popupWidgets->append(popup);                // add to end of list
2683
2684    // popups are not focus-handled by the window system (the first
2685    // popup grabbed the keyboard), so we have to do that manually: A
2686    // new popup gets the focus
2687    if (popup->focusWidget()) {
2688        popup->focusWidget()->setFocus(Qt::PopupFocusReason);
2689    } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
2690        popup->setFocus(Qt::PopupFocusReason);
2691    }
2692}
2693
2694/*!
2695    \internal
2696*/
2697void QApplicationPrivate::closePopup(QWidget *popup)
2698{
2699    Q_Q(QApplication);
2700    if (!QApplicationPrivate::popupWidgets)
2701        return;
2702
2703    QApplicationPrivate::popupWidgets->removeAll(popup);
2704    if (popup == qt_button_down)
2705        qt_button_down = 0;
2706    if (QApplicationPrivate::popupWidgets->isEmpty()) {  // this was the last popup
2707        delete QApplicationPrivate::popupWidgets;
2708        QApplicationPrivate::popupWidgets = 0;
2709
2710        // Special case for Tool windows: since they are activated and deactived together
2711        // with a normal window they never become the QApplicationPrivate::active_window.
2712        QWidget *appFocusWidget = QApplication::focusWidget();
2713        if (appFocusWidget && appFocusWidget->window()->windowType() == Qt::Tool) {
2714            appFocusWidget->setFocus(Qt::PopupFocusReason);
2715        } else if (QApplicationPrivate::active_window) {
2716            if (QWidget *fw = QApplicationPrivate::active_window->focusWidget()) {
2717                if (fw != QApplication::focusWidget()) {
2718                    fw->setFocus(Qt::PopupFocusReason);
2719                } else {
2720                    QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
2721                    q->sendEvent(fw, &e);
2722                }
2723            }
2724        }
2725    } else {
2726        // popups are not focus-handled by the window system (the
2727        // first popup grabbed the keyboard), so we have to do that
2728        // manually: A popup was closed, so the previous popup gets
2729        // the focus.
2730        QWidget* aw = QApplicationPrivate::popupWidgets->last();
2731        if (QWidget *fw = aw->focusWidget())
2732            fw->setFocus(Qt::PopupFocusReason);
2733    }
2734}
2735
2736void QApplication::beep()
2737{
2738    qt_mac_beep();
2739}
2740
2741void QApplication::alert(QWidget *widget, int duration)
2742{
2743    if (!QApplicationPrivate::checkInstance("alert"))
2744        return;
2745
2746    QWidgetList windowsToMark;
2747    if (!widget)
2748        windowsToMark += topLevelWidgets();
2749    else
2750        windowsToMark.append(widget->window());
2751
2752    bool needNotification = false;
2753    for (int i = 0; i < windowsToMark.size(); ++i) {
2754        QWidget *window = windowsToMark.at(i);
2755        if (!window->isActiveWindow() && window->isVisible()) {
2756            needNotification = true; // yeah, we may set it multiple times, but that's OK.
2757            if (duration != 0) {
2758               QTimer *timer = new QTimer(qApp);
2759               timer->setSingleShot(true);
2760               connect(timer, SIGNAL(timeout()), qApp, SLOT(_q_alertTimeOut()));
2761               if (QTimer *oldTimer = qApp->d_func()->alertTimerHash.value(widget)) {
2762                   qApp->d_func()->alertTimerHash.remove(widget);
2763                   delete oldTimer;
2764               }
2765               qApp->d_func()->alertTimerHash.insert(widget, timer);
2766               timer->start(duration);
2767            }
2768        }
2769    }
2770    if (needNotification)
2771        qt_mac_send_notification();
2772}
2773
2774void QApplicationPrivate::_q_alertTimeOut()
2775{
2776    if (QTimer *timer = qobject_cast<QTimer *>(q_func()->sender())) {
2777        QHash<QWidget *, QTimer *>::iterator it = alertTimerHash.begin();
2778        while (it != alertTimerHash.end()) {
2779            if (it.value() == timer) {
2780                alertTimerHash.erase(it);
2781                timer->deleteLater();
2782                break;
2783            }
2784            ++it;
2785        }
2786        if (alertTimerHash.isEmpty()) {
2787            qt_mac_cancel_notification();
2788        }
2789    }
2790}
2791
2792void  QApplication::setCursorFlashTime(int msecs)
2793{
2794    QApplicationPrivate::cursor_flash_time = msecs;
2795}
2796
2797int QApplication::cursorFlashTime()
2798{
2799    return QApplicationPrivate::cursor_flash_time;
2800}
2801
2802void QApplication::setDoubleClickInterval(int ms)
2803{
2804    qt_mac_dblclick.use_qt_time_limit = true;
2805    QApplicationPrivate::mouse_double_click_time = ms;
2806}
2807
2808int QApplication::doubleClickInterval()
2809{
2810    if (!qt_mac_dblclick.use_qt_time_limit) { //get it from the system
2811        QSettings appleSettings(QLatin1String("apple.com"));
2812        /* First worked as of 10.3.3 */
2813        double dci = appleSettings.value(QLatin1String("com/apple/mouse/doubleClickThreshold"), 0.5).toDouble();
2814        return int(dci * 1000);
2815    }
2816    return QApplicationPrivate::mouse_double_click_time;
2817}
2818
2819void QApplication::setKeyboardInputInterval(int ms)
2820{
2821    QApplicationPrivate::keyboard_input_time = ms;
2822}
2823
2824int QApplication::keyboardInputInterval()
2825{
2826    // FIXME: get from the system
2827    return QApplicationPrivate::keyboard_input_time;
2828}
2829
2830#ifndef QT_NO_WHEELEVENT
2831void QApplication::setWheelScrollLines(int n)
2832{
2833    QApplicationPrivate::wheel_scroll_lines = n;
2834}
2835
2836int QApplication::wheelScrollLines()
2837{
2838    return QApplicationPrivate::wheel_scroll_lines;
2839}
2840#endif
2841
2842void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
2843{
2844    switch (effect) {
2845    case Qt::UI_FadeMenu:
2846        QApplicationPrivate::fade_menu = enable;
2847        break;
2848    case Qt::UI_AnimateMenu:
2849        QApplicationPrivate::animate_menu = enable;
2850        break;
2851    case Qt::UI_FadeTooltip:
2852        QApplicationPrivate::fade_tooltip = enable;
2853        break;
2854    case Qt::UI_AnimateTooltip:
2855        QApplicationPrivate::animate_tooltip = enable;
2856        break;
2857    case Qt::UI_AnimateCombo:
2858        QApplicationPrivate::animate_combo = enable;
2859        break;
2860    case Qt::UI_AnimateToolBox:
2861        QApplicationPrivate::animate_toolbox = enable;
2862        break;
2863    case Qt::UI_General:
2864        QApplicationPrivate::fade_tooltip = true;
2865        break;
2866    default:
2867        QApplicationPrivate::animate_ui = enable;
2868        break;
2869    }
2870
2871    if (enable)
2872        QApplicationPrivate::animate_ui = true;
2873}
2874
2875bool QApplication::isEffectEnabled(Qt::UIEffect effect)
2876{
2877    if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui)
2878        return false;
2879
2880    switch(effect) {
2881    case Qt::UI_AnimateMenu:
2882        return QApplicationPrivate::animate_menu;
2883    case Qt::UI_FadeMenu:
2884        return QApplicationPrivate::fade_menu;
2885    case Qt::UI_AnimateCombo:
2886        return QApplicationPrivate::animate_combo;
2887    case Qt::UI_AnimateTooltip:
2888        return QApplicationPrivate::animate_tooltip;
2889    case Qt::UI_FadeTooltip:
2890        return QApplicationPrivate::fade_tooltip;
2891    case Qt::UI_AnimateToolBox:
2892        return QApplicationPrivate::animate_toolbox;
2893    default:
2894        break;
2895    }
2896    return QApplicationPrivate::animate_ui;
2897}
2898
2899/*!
2900    \internal
2901*/
2902bool QApplicationPrivate::qt_mac_apply_settings()
2903{
2904    QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
2905    settings.beginGroup(QLatin1String("Qt"));
2906
2907    /*
2908      Qt settings.  This is how they are written into the datastream.
2909      Palette/ *             - QPalette
2910      font                   - QFont
2911      libraryPath            - QStringList
2912      style                  - QString
2913      doubleClickInterval    - int
2914      cursorFlashTime        - int
2915      wheelScrollLines       - int
2916      colorSpec              - QString
2917      defaultCodec           - QString
2918      globalStrut/width      - int
2919      globalStrut/height     - int
2920      GUIEffects             - QStringList
2921      Font Substitutions/ *  - QStringList
2922      Font Substitutions/... - QStringList
2923    */
2924
2925    // read library (ie. plugin) path list
2926    QString libpathkey =
2927        QString::fromLatin1("%1.%2/libraryPath")
2928                    .arg(QT_VERSION >> 16)
2929                    .arg((QT_VERSION & 0xff00) >> 8);
2930    QStringList pathlist = settings.value(libpathkey).toString().split(QLatin1Char(':'));
2931    if (!pathlist.isEmpty()) {
2932        QStringList::ConstIterator it = pathlist.begin();
2933        while(it != pathlist.end())
2934            QApplication::addLibraryPath(*it++);
2935    }
2936
2937    QString defaultcodec = settings.value(QLatin1String("defaultCodec"), QVariant(QLatin1String("none"))).toString();
2938    if (defaultcodec != QLatin1String("none")) {
2939        QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1().constData());
2940        if (codec)
2941            QTextCodec::setCodecForTr(codec);
2942    }
2943
2944    if (qt_is_gui_used) {
2945        QString str;
2946        QStringList strlist;
2947        int num;
2948
2949        // read new palette
2950        int i;
2951        QPalette pal(QApplication::palette());
2952        strlist = settings.value(QLatin1String("Palette/active")).toStringList();
2953        if (strlist.count() == QPalette::NColorRoles) {
2954            for (i = 0; i < QPalette::NColorRoles; i++)
2955                pal.setColor(QPalette::Active, (QPalette::ColorRole) i,
2956                            QColor(strlist[i]));
2957        }
2958        strlist = settings.value(QLatin1String("Palette/inactive")).toStringList();
2959        if (strlist.count() == QPalette::NColorRoles) {
2960            for (i = 0; i < QPalette::NColorRoles; i++)
2961                pal.setColor(QPalette::Inactive, (QPalette::ColorRole) i,
2962                            QColor(strlist[i]));
2963        }
2964        strlist = settings.value(QLatin1String("Palette/disabled")).toStringList();
2965        if (strlist.count() == QPalette::NColorRoles) {
2966            for (i = 0; i < QPalette::NColorRoles; i++)
2967                pal.setColor(QPalette::Disabled, (QPalette::ColorRole) i,
2968                            QColor(strlist[i]));
2969        }
2970
2971        if (pal != QApplication::palette())
2972            QApplication::setPalette(pal);
2973
2974        // read new font
2975        QFont font(QApplication::font());
2976        str = settings.value(QLatin1String("font")).toString();
2977        if (!str.isEmpty()) {
2978            font.fromString(str);
2979            if (font != QApplication::font())
2980                QApplication::setFont(font);
2981        }
2982
2983        // read new QStyle
2984        QString stylename = settings.value(QLatin1String("style")).toString();
2985        if (! stylename.isNull() && ! stylename.isEmpty()) {
2986            QStyle *style = QStyleFactory::create(stylename);
2987            if (style)
2988                QApplication::setStyle(style);
2989            else
2990                stylename = QLatin1String("default");
2991        } else {
2992            stylename = QLatin1String("default");
2993        }
2994
2995        num = settings.value(QLatin1String("doubleClickInterval"),
2996                            QApplication::doubleClickInterval()).toInt();
2997        QApplication::setDoubleClickInterval(num);
2998
2999        num = settings.value(QLatin1String("cursorFlashTime"),
3000                            QApplication::cursorFlashTime()).toInt();
3001        QApplication::setCursorFlashTime(num);
3002
3003#ifndef QT_NO_WHEELEVENT
3004        num = settings.value(QLatin1String("wheelScrollLines"),
3005                            QApplication::wheelScrollLines()).toInt();
3006        QApplication::setWheelScrollLines(num);
3007#endif
3008
3009        QString colorspec = settings.value(QLatin1String("colorSpec"),
3010                                            QVariant(QLatin1String("default"))).toString();
3011        if (colorspec == QLatin1String("normal"))
3012            QApplication::setColorSpec(QApplication::NormalColor);
3013        else if (colorspec == QLatin1String("custom"))
3014            QApplication::setColorSpec(QApplication::CustomColor);
3015        else if (colorspec == QLatin1String("many"))
3016            QApplication::setColorSpec(QApplication::ManyColor);
3017        else if (colorspec != QLatin1String("default"))
3018            colorspec = QLatin1String("default");
3019
3020        int w = settings.value(QLatin1String("globalStrut/width")).toInt();
3021        int h = settings.value(QLatin1String("globalStrut/height")).toInt();
3022        QSize strut(w, h);
3023        if (strut.isValid())
3024            QApplication::setGlobalStrut(strut);
3025
3026        QStringList effects = settings.value(QLatin1String("GUIEffects")).toStringList();
3027        if (!effects.isEmpty()) {
3028            if (effects.contains(QLatin1String("none")))
3029                QApplication::setEffectEnabled(Qt::UI_General, false);
3030            if (effects.contains(QLatin1String("general")))
3031                QApplication::setEffectEnabled(Qt::UI_General, true);
3032            if (effects.contains(QLatin1String("animatemenu")))
3033                QApplication::setEffectEnabled(Qt::UI_AnimateMenu, true);
3034            if (effects.contains(QLatin1String("fademenu")))
3035                QApplication::setEffectEnabled(Qt::UI_FadeMenu, true);
3036            if (effects.contains(QLatin1String("animatecombo")))
3037                QApplication::setEffectEnabled(Qt::UI_AnimateCombo, true);
3038            if (effects.contains(QLatin1String("animatetooltip")))
3039                QApplication::setEffectEnabled(Qt::UI_AnimateTooltip, true);
3040            if (effects.contains(QLatin1String("fadetooltip")))
3041                QApplication::setEffectEnabled(Qt::UI_FadeTooltip, true);
3042            if (effects.contains(QLatin1String("animatetoolbox")))
3043                QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, true);
3044        } else {
3045            QApplication::setEffectEnabled(Qt::UI_General, true);
3046        }
3047
3048        settings.beginGroup(QLatin1String("Font Substitutions"));
3049        QStringList fontsubs = settings.childKeys();
3050        if (!fontsubs.isEmpty()) {
3051            QStringList::Iterator it = fontsubs.begin();
3052            for (; it != fontsubs.end(); ++it) {
3053                QString fam = QString::fromLatin1((*it).toLatin1().constData());
3054                QStringList subs = settings.value(fam).toStringList();
3055                QFont::insertSubstitutions(fam, subs);
3056            }
3057        }
3058        settings.endGroup();
3059    }
3060
3061    settings.endGroup();
3062    return true;
3063}
3064
3065// DRSWAT
3066
3067bool QApplicationPrivate::canQuit()
3068{
3069#ifndef QT_MAC_USE_COCOA
3070    return true;
3071#else
3072    Q_Q(QApplication);
3073#ifdef QT_MAC_USE_COCOA
3074    [[[NSApplication sharedApplication] mainMenu] cancelTracking];
3075#else
3076    HiliteMenu(0);
3077#endif
3078
3079    bool handle_quit = true;
3080    if (QApplicationPrivate::modalState() && [[[[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate]
3081                                                   menuLoader] quitMenuItem] isEnabled]) {
3082        int visible = 0;
3083        const QWidgetList tlws = QApplication::topLevelWidgets();
3084        for(int i = 0; i < tlws.size(); ++i) {
3085            if (tlws.at(i)->isVisible())
3086                ++visible;
3087        }
3088        handle_quit = (visible <= 1);
3089    }
3090    if (handle_quit) {
3091        QCloseEvent ev;
3092        QApplication::sendSpontaneousEvent(q, &ev);
3093        if (ev.isAccepted()) {
3094            return true;
3095        }
3096    }
3097    return false;
3098#endif
3099}
3100
3101void onApplicationWindowChangedActivation(QWidget *widget, bool activated)
3102{
3103#if QT_MAC_USE_COCOA
3104    if (!widget)
3105        return;
3106
3107    if (activated) {
3108        if (QApplicationPrivate::app_style) {
3109            QEvent ev(QEvent::Style);
3110            qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
3111        }
3112        qApp->setActiveWindow(widget);
3113    } else { // deactivated
3114        if (QApplicationPrivate::active_window == widget)
3115            qApp->setActiveWindow(0);
3116    }
3117
3118    QMenuBar::macUpdateMenuBar();
3119    qt_mac_update_cursor();
3120#else
3121    Q_UNUSED(widget);
3122    Q_UNUSED(activated);
3123#endif
3124}
3125
3126
3127void onApplicationChangedActivation( bool activated )
3128{
3129#if QT_MAC_USE_COCOA
3130    QApplication    *app    = qApp;
3131
3132//NSLog(@"App Changed Activation\n");
3133
3134    if ( activated ) {
3135        if (QApplication::desktopSettingsAware())
3136            qt_mac_update_os_settings();
3137
3138        if (qt_clipboard) { //manufacture an event so the clipboard can see if it has changed
3139            QEvent ev(QEvent::Clipboard);
3140            qt_sendSpontaneousEvent(qt_clipboard, &ev);
3141        }
3142
3143        if (app) {
3144            QEvent ev(QEvent::ApplicationActivate);
3145            qt_sendSpontaneousEvent(app, &ev);
3146        }
3147
3148        if (!app->activeWindow()) {
3149            OSWindowRef wp = [[NSApplication sharedApplication] keyWindow];
3150            if (QWidget *tmp_w = qt_mac_find_window(wp))
3151                app->setActiveWindow(tmp_w);
3152        }
3153        QMenuBar::macUpdateMenuBar();
3154        qt_mac_update_cursor();
3155    } else { // de-activated
3156        QApplicationPrivate *priv = [[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] qAppPrivate];
3157        if (priv->inPopupMode())
3158            app->activePopupWidget()->close();
3159        if (app) {
3160            QEvent ev(QEvent::ApplicationDeactivate);
3161            qt_sendSpontaneousEvent(app, &ev);
3162        }
3163        app->setActiveWindow(0);
3164    }
3165#else
3166    Q_UNUSED(activated);
3167#endif
3168}
3169
3170void QApplicationPrivate::initializeMultitouch_sys()
3171{ }
3172void QApplicationPrivate::cleanupMultitouch_sys()
3173{ }
3174
3175QT_END_NAMESPACE
3176