1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 /****************************************************************************
44 ** Copyright (c) 2007-2008, Apple, Inc.
46 ** All rights reserved.
48 ** Redistribution and use in source and binary forms, with or without
49 ** modification, are permitted provided that the following conditions are met:
51 ** * Redistributions of source code must retain the above copyright notice,
52 ** this list of conditions and the following disclaimer.
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.
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.
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.
74 ****************************************************************************/
76 #include <Cocoa/Cocoa.h>
78 #include "qapplication.h"
79 #include "qbitarray.h"
80 #include "qclipboard.h"
82 #include "qdatastream.h"
83 #include "qdatetime.h"
84 #include "qdesktopwidget.h"
85 #include "qdockwidget.h"
90 #include "qmessagebox.h"
92 #include "qpixmapcache.h"
94 #include "qsessionmanager.h"
95 #include "qsettings.h"
96 #include "qsocketnotifier.h"
98 #include "qstylefactory.h"
99 #include "qtextcodec.h"
100 #include "qtoolbar.h"
101 #include "qvariant.h"
103 #include "qcolormap.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>
127 #ifndef QT_NO_ACCESSIBILITY
128 # include "qaccessible.h"
137 #include <sys/time.h>
138 #include <sys/select.h>
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
149 #define QMAC_SPEAK_TO_ME
150 #ifdef QMAC_SPEAK_TO_ME
154 #ifndef kThemeBrushAlternatePrimaryHighlightColor
155 #define kThemeBrushAlternatePrimaryHighlightColor -5
158 #define kCMDeviceUnregisteredNotification CFSTR("CMDeviceUnregisteredNotification")
159 #define kCMDefaultDeviceNotification CFSTR("CMDefaultDeviceNotification")
160 #define kCMDeviceProfilesNotification CFSTR("CMDeviceProfilesNotification")
161 #define kCMDefaultDeviceProfileNotification CFSTR("CMDefaultDeviceProfileNotification")
166 QPaintDevice *qt_mac_safe_pdev = 0;
167 QList<QMacWindowChangeEvent*> *QMacWindowChangeEvent::change_events = 0;
168 QPointer<QWidget> topLevelAt_cache = 0;
170 /*****************************************************************************
171 Internal variables and functions
172 *****************************************************************************/
174 bool use_qt_time_limit;
175 QPointer<QWidget> last_widget;
177 int last_modifiers, last_button;
179 } qt_mac_dblclick = { false, 0, -1, -1, 0, 0, -2 };
181 static bool app_do_modal = false; // modal mode
182 extern QWidgetList *qt_modal_stack; // stack of modal widgets
183 extern bool qt_tab_all_widgets; // from qapplication.cpp
184 bool qt_scrollbar_jump_to_pos = false;
185 static bool qt_mac_collapse_on_dblclick = true;
186 extern int qt_antialiasing_threshold; // from qapplication.cpp
187 QWidget * qt_button_down; // widget got last button-down
188 QPointer<QWidget> qt_last_mouse_receiver;
189 #if defined(QT_DEBUG)
190 static bool appNoGrab = false; // mouse/keyboard grabbing
192 static AEEventHandlerUPP app_proc_ae_handlerUPP = NULL;
193 static EventHandlerRef tablet_proximity_handler = 0;
194 static EventHandlerUPP tablet_proximity_UPP = 0;
195 bool QApplicationPrivate::native_modal_dialog_active;
197 Q_GUI_EXPORT bool qt_applefontsmoothing_enabled;
199 /*****************************************************************************
201 *****************************************************************************/
202 extern void qt_mac_beep(); //qsound_mac.mm
203 extern Qt::KeyboardModifiers qt_mac_get_modifiers(int keys); //qkeymapper_mac.cpp
204 extern bool qt_mac_can_clickThrough(const QWidget *); //qwidget_mac.cpp
205 extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
206 extern OSWindowRef qt_mac_window_for(const QWidget*); //qwidget_mac.cpp
207 extern QWidget *qt_mac_find_window(OSWindowRef); //qwidget_mac.cpp
208 extern void qt_mac_set_cursor(const QCursor *); //qcursor_mac.cpp
209 extern bool qt_mac_is_macsheet(const QWidget *); //qwidget_mac.cpp
210 extern QString qt_mac_from_pascal_string(const Str255); //qglobal.cpp
211 extern void qt_mac_command_set_enabled(MenuRef, UInt32, bool); //qmenu_mac.cpp
212 extern bool qt_sendSpontaneousEvent(QObject *obj, QEvent *event); // qapplication.cpp
213 extern void qt_mac_update_cursor(); // qcursor_mac.mm
216 void onApplicationWindowChangedActivation( QWidget*widget, bool activated );
217 void onApplicationChangedActivation( bool activated );
219 static void qt_mac_read_fontsmoothing_settings()
221 qt_applefontsmoothing_enabled = true;
223 QImage image(w, h, QImage::Format_RGB32);
224 image.fill(0xffffffff);
226 p.drawText(0, h, "X\\");
229 const int *bits = (const int *) ((const QImage &) image).bits();
230 int bpl = image.bytesPerLine() / 4;
231 for (int y=0; y<w; ++y) {
232 for (int x=0; x<h; ++x) {
233 int r = qRed(bits[x]);
234 int g = qGreen(bits[x]);
235 int b = qBlue(bits[x]);
236 if (r != g || r != b) {
237 qt_applefontsmoothing_enabled = true;
243 qt_applefontsmoothing_enabled = false;
246 Q_GUI_EXPORT bool qt_mac_execute_apple_script(const char *script, long script_len, AEDesc *ret) {
248 AEDesc scriptTextDesc;
249 ComponentInstance theComponent = 0;
250 OSAID scriptID = kOSANullScript, resultID = kOSANullScript;
252 // set up locals to a known state
253 AECreateDesc(typeNull, 0, 0, &scriptTextDesc);
254 scriptID = kOSANullScript;
255 resultID = kOSANullScript;
257 // open the scripting component
258 theComponent = OpenDefaultComponent(kOSAComponentType, typeAppleScript);
264 // put the script text into an aedesc
265 err = AECreateDesc(typeUTF8Text, script, script_len, &scriptTextDesc);
269 // compile the script
270 err = OSACompile(theComponent, &scriptTextDesc, kOSAModeNull, &scriptID);
275 err = OSAExecute(theComponent, scriptID, kOSANullScript, kOSAModeNull, &resultID);
277 // collect the results - if any
279 AECreateDesc(typeNull, 0, 0, ret);
280 if (err == errOSAScriptError)
281 OSAScriptError(theComponent, kOSAErrorMessage, typeChar, ret);
282 else if (err == noErr && resultID != kOSANullScript)
283 OSADisplay(theComponent, resultID, typeChar, kOSAModeNull, ret);
286 AEDisposeDesc(&scriptTextDesc);
287 if (scriptID != kOSANullScript)
288 OSADispose(theComponent, scriptID);
289 if (resultID != kOSANullScript)
290 OSADispose(theComponent, resultID);
292 CloseComponent(theComponent);
296 Q_GUI_EXPORT bool qt_mac_execute_apple_script(const char *script, AEDesc *ret)
298 return qt_mac_execute_apple_script(script, qstrlen(script), ret);
301 Q_GUI_EXPORT bool qt_mac_execute_apple_script(const QString &script, AEDesc *ret)
303 const QByteArray l = script.toUtf8(); return qt_mac_execute_apple_script(l.constData(), l.size(), ret);
306 /* Resolution change magic */
307 void qt_mac_display_change_callbk(CGDirectDisplayID, CGDisplayChangeSummaryFlags flags, void *)
309 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
310 const bool resized = flags & kCGDisplayDesktopShapeChangedFlag;
313 const bool resized = true;
315 if (resized && qApp) {
316 if (QDesktopWidget *dw = qApp->desktop()) {
317 QResizeEvent *re = new QResizeEvent(dw->size(), dw->size());
318 QApplication::postEvent(dw, re);
319 QCoreGraphicsPaintEngine::cleanUpMacColorSpaces();
324 #ifdef DEBUG_PLATFORM_SETTINGS
325 static void qt_mac_debug_palette(const QPalette &pal, const QPalette &pal2, const QString &where)
327 const char *const groups[] = {"Active", "Disabled", "Inactive" };
328 const char *const roles[] = { "WindowText", "Button", "Light", "Midlight", "Dark", "Mid",
329 "Text", "BrightText", "ButtonText", "Base", "Window", "Shadow",
330 "Highlight", "HighlightedText", "Link", "LinkVisited" };
332 qDebug("qt-internal: %s", where.toLatin1().constData());
333 for(int grp = 0; grp < QPalette::NColorGroups; grp++) {
334 for(int role = 0; role < QPalette::NColorRoles; role++) {
335 QBrush b = pal.brush((QPalette::ColorGroup)grp, (QPalette::ColorRole)role);
336 QPixmap pm = b.texture();
337 qDebug(" %s::%s %d::%d::%d [%p]%s", groups[grp], roles[role], b.color().red(),
338 b.color().green(), b.color().blue(), pm.isNull() ? 0 : &pm,
339 pal2.brush((QPalette::ColorGroup)grp, (QPalette::ColorRole)role) != b ? " (*)" : "");
345 #define qt_mac_debug_palette(x, y, z)
348 //raise a notification
349 void qt_mac_send_notification()
351 QMacCocoaAutoReleasePool pool;
352 [[NSApplication sharedApplication] requestUserAttention:NSInformationalRequest];
355 void qt_mac_cancel_notification()
357 QMacCocoaAutoReleasePool pool;
358 [[NSApplication sharedApplication] cancelUserAttentionRequest:NSInformationalRequest];
361 void qt_mac_set_app_icon(const QPixmap &pixmap)
363 QMacCocoaAutoReleasePool pool;
364 NSImage *image = NULL;
365 if (pixmap.isNull()) {
366 // Get Application icon from bundle
367 image = [[NSImage imageNamed:@"NSApplicationIcon"] retain]; // released below
369 image = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap));
372 [NSApp setApplicationIconImage:image];
376 Q_GUI_EXPORT void qt_mac_set_press_and_hold_context(bool b)
379 qWarning("qt_mac_set_press_and_hold_context: This functionality is no longer available");
382 bool qt_nograb() // application no-grab option
384 #if defined(QT_DEBUG)
391 void qt_mac_update_os_settings()
395 if (!QApplication::startingUp()) {
396 static bool needToPolish = true;
398 QApplication::style()->polish(qApp);
399 needToPolish = false;
403 /* First worked as of 10.2.3 */
404 QSettings appleSettings(QLatin1String("apple.com"));
405 QVariant appleValue = appleSettings.value(QLatin1String("AppleKeyboardUIMode"), 0);
406 qt_tab_all_widgets = (appleValue.toInt() & 0x2);
408 /* First worked as of 10.2.3 */
409 appleValue = appleSettings.value(QLatin1String("AppleScrollerPagingBehavior"), false);
410 qt_scrollbar_jump_to_pos = appleValue.toBool();
412 /* First worked as of 10.3.3 */
413 appleValue = appleSettings.value(QLatin1String("AppleMiniaturizeOnDoubleClick"), true);
414 qt_mac_collapse_on_dblclick = appleValue.toBool();
416 // Anti-aliasing threshold
417 appleValue = appleSettings.value(QLatin1String("AppleAntiAliasingThreshold"));
418 if (appleValue.isValid())
419 qt_antialiasing_threshold = appleValue.toInt();
421 #ifdef DEBUG_PLATFORM_SETTINGS
422 qDebug("qt_mac_update_os_settings *********************************************************************");
424 { // setup the global palette
426 (void) QApplication::style(); // trigger creation of application style and system palettes
427 QPalette pal = *QApplicationPrivate::sys_pal;
429 pal.setBrush( QPalette::Active, QPalette::Highlight, qcolorForTheme(kThemeBrushPrimaryHighlightColor) );
430 pal.setBrush( QPalette::Inactive, QPalette::Highlight, qcolorForTheme(kThemeBrushSecondaryHighlightColor) );
432 pal.setBrush( QPalette::Disabled, QPalette::Highlight, qcolorForTheme(kThemeBrushSecondaryHighlightColor) );
433 pal.setBrush( QPalette::Active, QPalette::Shadow, qcolorForTheme(kThemeBrushButtonActiveDarkShadow) );
435 pal.setBrush( QPalette::Inactive, QPalette::Shadow, qcolorForTheme(kThemeBrushButtonInactiveDarkShadow) );
436 pal.setBrush( QPalette::Disabled, QPalette::Shadow, qcolorForTheme(kThemeBrushButtonInactiveDarkShadow) );
438 qc = qcolorForThemeTextColor(kThemeTextColorDialogActive);
439 pal.setColor(QPalette::Active, QPalette::Text, qc);
440 pal.setColor(QPalette::Active, QPalette::WindowText, qc);
441 pal.setColor(QPalette::Active, QPalette::HighlightedText, qc);
443 qc = qcolorForThemeTextColor(kThemeTextColorDialogInactive);
444 pal.setColor(QPalette::Inactive, QPalette::Text, qc);
445 pal.setColor(QPalette::Inactive, QPalette::WindowText, qc);
446 pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
447 pal.setColor(QPalette::Disabled, QPalette::Text, qc);
448 pal.setColor(QPalette::Disabled, QPalette::WindowText, qc);
449 pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
450 pal.setBrush(QPalette::ToolTipBase, QColor(255, 255, 199));
452 if (!QApplicationPrivate::sys_pal || *QApplicationPrivate::sys_pal != pal) {
453 QApplicationPrivate::setSystemPalette(pal);
454 QApplication::setPalette(pal);
456 #ifdef DEBUG_PLATFORM_SETTINGS
457 qt_mac_debug_palette(pal, QApplication::palette(), "Global Palette");
461 QFont fnt = qfontForThemeFont(kThemeApplicationFont);
462 #ifdef DEBUG_PLATFORM_SETTINGS
463 qDebug("qt-internal: Font for Application [%s::%d::%d::%d]",
464 fnt.family().toLatin1().constData(), fnt.pointSize(), fnt.bold(), fnt.italic());
466 if (!QApplicationPrivate::sys_font || *QApplicationPrivate::sys_font != fnt)
467 QApplicationPrivate::setSystemFont(fnt);
471 FontMap(const char *qc, short fk) : qt_class(qc), font_key(fk) { }
472 const char *const qt_class;
474 } mac_widget_fonts[] = {
475 FontMap("QPushButton", kThemePushButtonFont),
476 FontMap("QListView", kThemeViewsFont),
477 FontMap("QListBox", kThemeViewsFont),
478 FontMap("QTitleBar", kThemeWindowTitleFont),
479 FontMap("QMenuBar", kThemeMenuTitleFont),
480 FontMap("QMenu", kThemeMenuItemFont),
481 FontMap("QComboMenuItem", kThemeSystemFont),
482 FontMap("QHeaderView", kThemeSmallSystemFont),
483 FontMap("Q3Header", kThemeSmallSystemFont),
484 FontMap("QTipLabel", kThemeSmallSystemFont),
485 FontMap("QLabel", kThemeSystemFont),
486 FontMap("QToolButton", kThemeSmallSystemFont),
487 FontMap("QMenuItem", kThemeMenuItemFont), // It doesn't exist, but its unique.
488 FontMap("QComboLineEdit", kThemeViewsFont), // It doesn't exist, but its unique.
489 FontMap("QSmallFont", kThemeSmallSystemFont), // It doesn't exist, but its unique.
490 FontMap("QMiniFont", kThemeMiniSystemFont), // It doesn't exist, but its unique.
492 for(int i = 0; mac_widget_fonts[i].qt_class; i++) {
493 QFont fnt = qfontForThemeFont(mac_widget_fonts[i].font_key);
494 bool set_font = true;
495 FontHash *hash = qt_app_fonts_hash();
496 if (!hash->isEmpty()) {
497 FontHash::const_iterator it
498 = hash->constFind(mac_widget_fonts[i].qt_class);
499 if (it != hash->constEnd())
500 set_font = (fnt != *it);
503 QApplication::setFont(fnt, mac_widget_fonts[i].qt_class);
504 #ifdef DEBUG_PLATFORM_SETTINGS
505 qDebug("qt-internal: Font for %s [%s::%d::%d::%d]", mac_widget_fonts[i].qt_class,
506 fnt.family().toLatin1().constData(), fnt.pointSize(), fnt.bold(), fnt.italic());
511 QApplicationPrivate::initializeWidgetPaletteHash();
512 #ifdef DEBUG_PLATFORM_SETTINGS
513 qDebug("qt_mac_update_os_settings END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
517 void QApplicationPrivate::initializeWidgetPaletteHash()
519 { //setup the palette
521 inline PaletteMap(const char *qc, ThemeBrush a, ThemeBrush i) :
522 qt_class(qc), active(a), inactive(i) { }
523 const char *const qt_class;
524 ThemeBrush active, inactive;
525 } mac_widget_colors[] = {
526 PaletteMap("QToolButton", kThemeTextColorBevelButtonActive, kThemeTextColorBevelButtonInactive),
527 PaletteMap("QAbstractButton", kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
528 PaletteMap("QHeaderView", kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
529 PaletteMap("Q3Header", kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
530 PaletteMap("QComboBox", kThemeTextColorPopupButtonActive, kThemeTextColorPopupButtonInactive),
531 PaletteMap("QAbstractItemView", kThemeTextColorListView, kThemeTextColorDialogInactive),
532 PaletteMap("QMessageBoxLabel", kThemeTextColorAlertActive, kThemeTextColorAlertInactive),
533 PaletteMap("QTabBar", kThemeTextColorTabFrontActive, kThemeTextColorTabFrontInactive),
534 PaletteMap("QLabel", kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
535 PaletteMap("QGroupBox", kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
536 PaletteMap("QMenu", kThemeTextColorPopupLabelActive, kThemeTextColorPopupLabelInactive),
537 PaletteMap("QTextEdit", 0, 0),
538 PaletteMap("QTextControl", 0, 0),
539 PaletteMap("QLineEdit", 0, 0),
540 PaletteMap(0, 0, 0) };
542 for(int i = 0; mac_widget_colors[i].qt_class; i++) {
544 if (mac_widget_colors[i].active != 0) {
545 qc = qcolorForThemeTextColor(mac_widget_colors[i].active);
546 pal.setColor(QPalette::Active, QPalette::Text, qc);
547 pal.setColor(QPalette::Active, QPalette::WindowText, qc);
548 pal.setColor(QPalette::Active, QPalette::HighlightedText, qc);
549 qc = qcolorForThemeTextColor(mac_widget_colors[i].inactive);
550 pal.setColor(QPalette::Inactive, QPalette::Text, qc);
551 pal.setColor(QPalette::Disabled, QPalette::Text, qc);
552 pal.setColor(QPalette::Inactive, QPalette::WindowText, qc);
553 pal.setColor(QPalette::Disabled, QPalette::WindowText, qc);
554 pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
555 pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
557 if (!strcmp(mac_widget_colors[i].qt_class, "QMenu")) {
558 qc = qcolorForThemeTextColor(kThemeTextColorMenuItemActive);
559 pal.setBrush(QPalette::ButtonText, qc);
560 qc = qcolorForThemeTextColor(kThemeTextColorMenuItemSelected);
561 pal.setBrush(QPalette::HighlightedText, qc);
562 qc = qcolorForThemeTextColor(kThemeTextColorMenuItemDisabled);
563 pal.setBrush(QPalette::Disabled, QPalette::Text, qc);
564 } else if (!strcmp(mac_widget_colors[i].qt_class, "QAbstractButton")
565 || !strcmp(mac_widget_colors[i].qt_class, "QHeaderView")
566 || !strcmp(mac_widget_colors[i].qt_class, "Q3Header")) { //special
567 pal.setColor(QPalette::Disabled, QPalette::ButtonText,
568 pal.color(QPalette::Disabled, QPalette::Text));
569 pal.setColor(QPalette::Inactive, QPalette::ButtonText,
570 pal.color(QPalette::Inactive, QPalette::Text));
571 pal.setColor(QPalette::Active, QPalette::ButtonText,
572 pal.color(QPalette::Active, QPalette::Text));
573 } else if (!strcmp(mac_widget_colors[i].qt_class, "QAbstractItemView")) {
574 pal.setBrush(QPalette::Active, QPalette::Highlight,
575 qcolorForTheme(kThemeBrushAlternatePrimaryHighlightColor));
576 qc = qcolorForThemeTextColor(kThemeTextColorMenuItemSelected);
577 pal.setBrush(QPalette::Active, QPalette::HighlightedText, qc);
579 pal.setBrush(QPalette::Inactive, QPalette::Text,
580 pal.brush(QPalette::Active, QPalette::Text));
581 pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
582 pal.brush(QPalette::Active, QPalette::Text));
584 } else if (!strcmp(mac_widget_colors[i].qt_class, "QTextEdit")
585 || !strcmp(mac_widget_colors[i].qt_class, "QTextControl")) {
586 pal.setBrush(QPalette::Inactive, QPalette::Text,
587 pal.brush(QPalette::Active, QPalette::Text));
588 pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
589 pal.brush(QPalette::Active, QPalette::Text));
590 } else if (!strcmp(mac_widget_colors[i].qt_class, "QLineEdit")) {
591 pal.setBrush(QPalette::Disabled, QPalette::Base,
592 pal.brush(QPalette::Active, QPalette::Base));
595 bool set_palette = true;
596 PaletteHash *phash = qt_app_palettes_hash();
597 if (!phash->isEmpty()) {
598 PaletteHash::const_iterator it
599 = phash->constFind(mac_widget_colors[i].qt_class);
600 if (it != phash->constEnd())
601 set_palette = (pal != *it);
604 QApplication::setPalette(pal, mac_widget_colors[i].qt_class);
605 #ifdef DEBUG_PLATFORM_SETTINGS
606 qt_mac_debug_palette(pal, QApplication::palette(), QLatin1String("Palette for ") + QString::fromLatin1(mac_widget_colors[i].qt_class));
613 static void qt_mac_event_release(EventRef &event)
620 void qt_event_request_showsheet(QWidget *w)
622 Q_ASSERT(qt_mac_is_macsheet(w));
623 [NSApp beginSheet:qt_mac_window_for(w) modalForWindow:qt_mac_window_for(w->parentWidget())
624 modalDelegate:nil didEndSelector:nil contextInfo:0];
627 static void qt_post_window_change_event(QWidget *widget)
629 qt_widget_private(widget)->needWindowChange = true;
630 QEvent *glWindowChangeEvent = new QEvent(QEvent::MacGLWindowChange);
631 QApplication::postEvent(widget, glWindowChangeEvent);
635 Posts updates to all child and grandchild OpenGL widgets for the given widget.
637 static void qt_mac_update_child_gl_widgets(QWidget *widget)
639 // Update all OpenGL child widgets for the given widget.
640 QList<QWidgetPrivate::GlWidgetInfo> &glWidgets = qt_widget_private(widget)->glWidgets;
641 QList<QWidgetPrivate::GlWidgetInfo>::iterator end = glWidgets.end();
642 QList<QWidgetPrivate::GlWidgetInfo>::iterator it = glWidgets.begin();
644 for (;it != end; ++it) {
645 qt_post_window_change_event(it->widget);
650 Sends updates to all child and grandchild gl widgets that have updates pending.
652 void qt_mac_send_posted_gl_updates(QWidget *widget)
654 QList<QWidgetPrivate::GlWidgetInfo> &glWidgets = qt_widget_private(widget)->glWidgets;
655 QList<QWidgetPrivate::GlWidgetInfo>::iterator end = glWidgets.end();
656 QList<QWidgetPrivate::GlWidgetInfo>::iterator it = glWidgets.begin();
658 for (;it != end; ++it) {
659 QWidget *glWidget = it->widget;
660 if (qt_widget_private(glWidget)->needWindowChange) {
661 QEvent glChangeEvent(QEvent::MacGLWindowChange);
662 QApplication::sendEvent(glWidget, &glChangeEvent);
668 Posts updates to all OpenGL widgets within the window that the given widget intersects.
670 static void qt_mac_update_intersected_gl_widgets(QWidget *widget)
676 Posts a kEventQtRequestWindowChange event to the main Carbon event queue.
678 static EventRef request_window_change_pending = 0;
679 Q_GUI_EXPORT void qt_event_request_window_change()
681 if(request_window_change_pending)
684 CreateEvent(0, kEventClassQt, kEventQtRequestWindowChange, GetCurrentEventTime(),
685 kEventAttributeUserEvent, &request_window_change_pending);
686 PostEventToQueue(GetMainEventQueue(), request_window_change_pending, kEventPriorityHigh);
689 /* window changing. This is a hack around Apple's missing functionality, pending the toolbox
691 Q_GUI_EXPORT void qt_event_request_window_change(QWidget *widget)
696 // Post a kEventQtRequestWindowChange event. This event is semi-public,
697 // don't remove this line!
698 qt_event_request_window_change();
700 // Post update request on gl widgets unconditionally.
701 if (qt_widget_private(widget)->isGLWidget == true) {
702 qt_post_window_change_event(widget);
706 qt_mac_update_child_gl_widgets(widget);
707 qt_mac_update_intersected_gl_widgets(widget);
712 QPointer<QWidget> widget;
714 EventLoopTimerRef timer;
715 EventLoopTimerUPP timerUPP;
716 } request_activate_pending = { 0, 0, 0, 0 };
717 bool qt_event_remove_activate()
719 if (request_activate_pending.timer) {
720 RemoveEventLoopTimer(request_activate_pending.timer);
721 request_activate_pending.timer = 0;
723 if (request_activate_pending.event)
724 qt_mac_event_release(request_activate_pending.event);
728 void qt_event_activate_timer_callbk(EventLoopTimerRef r, void *)
730 EventLoopTimerRef otc = request_activate_pending.timer;
731 qt_event_remove_activate();
732 if (r == otc && !request_activate_pending.widget.isNull()) {
733 const QWidget *tlw = request_activate_pending.widget->window();
734 Qt::WindowType wt = tlw->windowType();
736 && ((wt != Qt::Desktop && wt != Qt::Popup && wt != Qt::Tool) || tlw->isModal())) {
737 CreateEvent(0, kEventClassQt, kEventQtRequestActivate, GetCurrentEventTime(),
738 kEventAttributeUserEvent, &request_activate_pending.event);
739 PostEventToQueue(GetMainEventQueue(), request_activate_pending.event, kEventPriorityHigh);
744 void qt_event_request_activate(QWidget *w)
746 if (w == request_activate_pending.widget)
749 /* We put these into a timer because due to order of events being sent we need to be sure this
750 comes from inside of the event loop */
751 qt_event_remove_activate();
752 if (!request_activate_pending.timerUPP)
753 request_activate_pending.timerUPP = NewEventLoopTimerUPP(qt_event_activate_timer_callbk);
754 request_activate_pending.widget = w;
755 InstallEventLoopTimer(GetMainEventLoop(), 0, 0, request_activate_pending.timerUPP, 0, &request_activate_pending.timer);
760 void qt_event_request_menubarupdate()
762 // Just call this. The request has the benefit that we don't call this multiple times, but
763 // we can optimize this.
764 QMenuBar::macUpdateMenuBar();
768 void QApplicationPrivate::createEventDispatcher()
771 if (q->type() != QApplication::Tty)
772 eventDispatcher = new QEventDispatcherMac(q);
774 eventDispatcher = new QEventDispatcherUNIX(q);
778 void qt_event_send_clipboard_changed()
783 static QMenu *qt_mac_dock_menu = 0;
784 Q_GUI_EXPORT void qt_mac_set_dock_menu(QMenu *menu)
786 qt_mac_dock_menu = menu;
787 [NSApp setDockMenu:menu->macMenu()];
790 /* events that hold pointers to widgets, must be cleaned up like this */
791 void qt_mac_event_release(QWidget *w)
794 if (w == qt_mac_dock_menu) {
795 qt_mac_dock_menu = 0;
796 [NSApp setDockMenu:0];
801 struct QMacAppleEventTypeSpec {
802 AEEventClass mac_class;
804 } app_apple_events[] = {
805 { kCoreEventClass, kAEQuitApplication },
806 { kCoreEventClass, kAEOpenDocuments },
807 { kInternetEventClass, kAEGetURL },
810 static void qt_init_tablet_proximity_handler()
812 EventTypeSpec tabletProximityEvent = { kEventClassTablet, kEventTabletProximity };
813 InstallEventHandler(GetEventMonitorTarget(), tablet_proximity_UPP,
814 1, &tabletProximityEvent, qApp, &tablet_proximity_handler);
817 static void qt_release_tablet_proximity_handler()
819 RemoveEventHandler(tablet_proximity_handler);
822 QString QApplicationPrivate::appName() const
824 static QString applName;
825 if (applName.isEmpty()) {
826 applName = QCoreApplicationPrivate::macMenuBarName();
827 ProcessSerialNumber psn;
828 if (applName.isEmpty() && qt_is_gui_used && GetCurrentProcess(&psn) == noErr) {
830 CopyProcessName(&psn, &cfstr);
837 void qt_release_app_proc_handler()
841 void qt_color_profile_changed(CFNotificationCenterRef, void *, CFStringRef, const void *,
844 QCoreGraphicsPaintEngine::cleanUpMacColorSpaces();
846 /* platform specific implementations */
847 void qt_init(QApplicationPrivate *priv, int)
849 if (qt_is_gui_used) {
850 CGDisplayRegisterReconfigurationCallback(qt_mac_display_change_callbk, 0);
851 CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter();
852 CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
853 kCMDeviceUnregisteredNotification, 0,
854 CFNotificationSuspensionBehaviorDeliverImmediately);
855 CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
856 kCMDefaultDeviceNotification, 0,
857 CFNotificationSuspensionBehaviorDeliverImmediately);
858 CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
859 kCMDeviceProfilesNotification, 0,
860 CFNotificationSuspensionBehaviorDeliverImmediately);
861 CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
862 kCMDefaultDeviceProfileNotification, 0,
863 CFNotificationSuspensionBehaviorDeliverImmediately);
864 ProcessSerialNumber psn;
865 if (GetCurrentProcess(&psn) == noErr) {
866 // Jambi needs to transform itself since most people aren't "used"
867 // to putting things in bundles, but other people may actually not
868 // want to tranform the process (running as a helper or something)
869 // so don't do that for them. This means checking both LSUIElement
870 // and LSBackgroundOnly. If you set them both... well, you
871 // shouldn't do that.
873 bool forceTransform = true;
874 CFTypeRef value = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(),
875 CFSTR("LSUIElement"));
877 CFTypeID valueType = CFGetTypeID(value);
878 // Officially it's supposed to be a string, a boolean makes sense, so we'll check.
879 // A number less so, but OK.
880 if (valueType == CFStringGetTypeID())
881 forceTransform = !(QCFString::toQString(static_cast<CFStringRef>(value)).toInt());
882 else if (valueType == CFBooleanGetTypeID())
883 forceTransform = !CFBooleanGetValue(static_cast<CFBooleanRef>(value));
884 else if (valueType == CFNumberGetTypeID()) {
886 CFNumberGetValue(static_cast<CFNumberRef>(value), kCFNumberIntType, &valueAsInt);
887 forceTransform = !valueAsInt;
891 if (forceTransform) {
892 value = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(),
893 CFSTR("LSBackgroundOnly"));
895 CFTypeID valueType = CFGetTypeID(value);
896 if (valueType == CFBooleanGetTypeID())
897 forceTransform = !CFBooleanGetValue(static_cast<CFBooleanRef>(value));
898 else if (valueType == CFStringGetTypeID())
899 forceTransform = !(QCFString::toQString(static_cast<CFStringRef>(value)).toInt());
900 else if (valueType == CFNumberGetTypeID()) {
902 CFNumberGetValue(static_cast<CFNumberRef>(value), kCFNumberIntType, &valueAsInt);
903 forceTransform = !valueAsInt;
909 if (forceTransform) {
910 TransformProcessType(&psn, kProcessTransformToForegroundApplication);
915 char **argv = priv->argv;
917 // Get command line params
918 if (int argc = priv->argc) {
921 for(i=1; i < argc; i++) {
922 if (argv[i] && *argv[i] != '-') {
926 QByteArray arg(argv[i]);
927 #if defined(QT_DEBUG)
928 if (arg == "-nograb")
929 appNoGrab = !appNoGrab;
932 if (arg.left(5) == "-psn_") {
933 passed_psn = QString::fromLatin1(arg.mid(6));
938 if (j < priv->argc) {
943 //special hack to change working directory (for an app bundle) when running from finder
944 if (!passed_psn.isNull() && QDir::currentPath() == QLatin1String("/")) {
945 QCFType<CFURLRef> bundleURL(CFBundleCopyBundleURL(CFBundleGetMainBundle()));
946 QString qbundlePath = QCFString(CFURLCopyFileSystemPath(bundleURL,
947 kCFURLPOSIXPathStyle));
948 if (qbundlePath.endsWith(QLatin1String(".app")))
949 QDir::setCurrent(qbundlePath.section(QLatin1Char('/'), 0, -2));
953 QMacPasteboardMime::initialize();
955 qApp->setObjectName(priv->appName());
956 if (qt_is_gui_used) {
957 QColormap::initialize();
959 QCursorData::initialize();
960 QCoreGraphicsPaintEngine::initialize();
961 #ifndef QT_NO_ACCESSIBILITY
962 QAccessible::initialize();
964 QMacInputContext::initialize();
965 QApplicationPrivate::inputContext = new QMacInputContext;
967 if (QApplication::desktopSettingsAware())
968 qt_mac_update_os_settings();
969 if (!app_proc_ae_handlerUPP && !QApplication::testAttribute(Qt::AA_MacPluginApplication)) {
970 app_proc_ae_handlerUPP = AEEventHandlerUPP(QApplicationPrivate::globalAppleEventProcessor);
971 for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i) {
972 // Install apple event handler, but avoid overwriting an already
973 // existing handler (it means a 3rd party application has installed one):
975 AEEventHandlerUPP current_handler = NULL;
976 AEGetEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, ¤t_handler, &refCon, false);
977 if (!current_handler)
978 AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id,
979 app_proc_ae_handlerUPP, SRefCon(qApp), false);
983 if (QApplicationPrivate::app_style) {
984 QEvent ev(QEvent::Style);
985 qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
988 if (QApplication::desktopSettingsAware())
989 QApplicationPrivate::qt_mac_apply_settings();
991 // Cocoa application delegate
992 NSApplication *cocoaApp = [QNSApplication sharedApplication];
993 qt_redirectNSApplicationSendEvent();
995 QMacCocoaAutoReleasePool pool;
996 id oldDelegate = [cocoaApp delegate];
997 QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
998 Q_ASSERT(newDelegate);
999 [newDelegate setQtPrivate:priv];
1000 // Only do things that make sense to do once, otherwise we crash.
1001 if (oldDelegate != newDelegate && !QApplication::testAttribute(Qt::AA_MacPluginApplication)) {
1002 [newDelegate setReflectionDelegate:oldDelegate];
1003 [cocoaApp setDelegate:newDelegate];
1005 QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader = [[QT_MANGLE_NAMESPACE(QCocoaMenuLoader) alloc] init];
1006 if ([NSBundle loadNibNamed:@"qt_menu" owner:qtMenuLoader] == false) {
1007 qFatal("Qt internal error: qt_menu.nib could not be loaded. The .nib file"
1008 " should be placed in QtGui.framework/Versions/Current/Resources/ "
1009 " or in the resources directory of your application bundle.");
1012 [cocoaApp setMenu:[qtMenuLoader menu]];
1013 [newDelegate setMenuLoader:qtMenuLoader];
1014 [qtMenuLoader release];
1016 // Register for Carbon tablet proximity events on the event monitor target.
1017 // This means that we should receive proximity events even when we aren't the active application.
1018 if (!tablet_proximity_handler) {
1019 tablet_proximity_UPP = NewEventHandlerUPP(QApplicationPrivate::tabletProximityCallback);
1020 qt_init_tablet_proximity_handler();
1022 priv->native_modal_dialog_active = false;
1024 qt_mac_read_fontsmoothing_settings();
1027 void qt_release_apple_event_handler()
1029 if(app_proc_ae_handlerUPP) {
1030 for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i)
1031 AERemoveEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id,
1032 app_proc_ae_handlerUPP, true);
1033 DisposeAEEventHandlerUPP(app_proc_ae_handlerUPP);
1034 app_proc_ae_handlerUPP = 0;
1038 /*****************************************************************************
1039 qt_cleanup() - cleans up when the application is finished
1040 *****************************************************************************/
1044 CGDisplayRemoveReconfigurationCallback(qt_mac_display_change_callbk, 0);
1045 CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter();
1046 CFNotificationCenterRemoveObserver(center, qApp, kCMDeviceUnregisteredNotification, 0);
1047 CFNotificationCenterRemoveObserver(center, qApp, kCMDefaultDeviceNotification, 0);
1048 CFNotificationCenterRemoveObserver(center, qApp, kCMDeviceProfilesNotification, 0);
1049 CFNotificationCenterRemoveObserver(center, qApp, kCMDefaultDeviceProfileNotification, 0);
1051 qt_release_apple_event_handler();
1052 qt_release_tablet_proximity_handler();
1053 if (tablet_proximity_UPP)
1054 DisposeEventHandlerUPP(tablet_proximity_UPP);
1056 QPixmapCache::clear();
1057 if (qt_is_gui_used) {
1058 #ifndef QT_NO_ACCESSIBILITY
1059 QAccessible::cleanup();
1061 QMacInputContext::cleanup();
1062 QCursorData::cleanup();
1064 QColormap::cleanup();
1065 if (qt_mac_safe_pdev) {
1066 delete qt_mac_safe_pdev;
1067 qt_mac_safe_pdev = 0;
1069 extern void qt_mac_unregister_widget(); // qapplication_mac.cpp
1070 qt_mac_unregister_widget();
1074 /*****************************************************************************
1075 Platform specific global and internal functions
1076 *****************************************************************************/
1077 void qt_updated_rootinfo()
1081 bool qt_wstate_iconified(WId)
1086 /*****************************************************************************
1087 Platform specific QApplication members
1088 *****************************************************************************/
1089 extern QWidget * mac_mouse_grabber;
1090 extern QWidget * mac_keyboard_grabber;
1092 #ifndef QT_NO_CURSOR
1094 /*****************************************************************************
1095 QApplication cursor stack
1096 *****************************************************************************/
1098 void QApplication::setOverrideCursor(const QCursor &cursor)
1100 qApp->d_func()->cursor_list.prepend(cursor);
1102 qt_mac_update_cursor();
1105 void QApplication::restoreOverrideCursor()
1107 if (qApp->d_func()->cursor_list.isEmpty())
1109 qApp->d_func()->cursor_list.removeFirst();
1111 qt_mac_update_cursor();
1113 #endif // QT_NO_CURSOR
1115 QWidget *QApplication::topLevelAt(const QPoint &p)
1117 // Use a cache to avoid iterate through the whole list of windows for all
1118 // calls to to topLevelAt. We e.g. do this for each and every mouse
1119 // move since we need to find the widget under mouse:
1120 if (topLevelAt_cache && topLevelAt_cache->frameGeometry().contains(p))
1121 return topLevelAt_cache;
1123 // INVARIANT: Cache miss. Go through the list if windows instead:
1124 QMacCocoaAutoReleasePool pool;
1125 NSPoint cocoaPoint = flipPoint(p);
1126 NSInteger windowCount;
1127 NSCountWindows(&windowCount);
1128 if (windowCount <= 0)
1129 return 0; // There's no window to find!
1131 QVarLengthArray<NSInteger> windowList(windowCount);
1132 NSWindowList(windowCount, windowList.data());
1133 int firstQtWindowFound = -1;
1134 for (int i = 0; i < windowCount; ++i) {
1135 NSWindow *window = [NSApp windowWithWindowNumber:windowList[i]];
1137 QWidget *candidateWindow = [window QT_MANGLE_NAMESPACE(qt_qwidget)];
1138 if (candidateWindow && firstQtWindowFound == -1)
1139 firstQtWindowFound = i;
1141 if (NSPointInRect(cocoaPoint, [window frame])) {
1142 // Check to see if there's a hole in the window where the mask is.
1143 // If there is, we should just continue to see if there is a window below.
1144 if (candidateWindow && !candidateWindow->mask().isEmpty()) {
1145 QPoint localPoint = candidateWindow->mapFromGlobal(p);
1146 if (!candidateWindow->mask().contains(localPoint))
1149 return candidateWindow;
1151 if (i == firstQtWindowFound) {
1152 // The cache will only work when the window under mouse is
1153 // top most (that is, not partially obscured by other windows.
1154 // And we only set it if no mask is present to optimize for the common case:
1155 topLevelAt_cache = candidateWindow;
1157 return candidateWindow;
1163 topLevelAt_cache = 0;
1167 /*****************************************************************************
1169 *****************************************************************************/
1171 bool QApplicationPrivate::modalState()
1173 return app_do_modal;
1177 void QApplicationPrivate::enterModal_sys(QWidget *widget)
1179 #ifdef DEBUG_MODAL_EVENTS
1181 qDebug("Entering modal state with %s::%s::%p (%d)", widget->metaObject()->className(), widget->objectName().toLocal8Bit().constData(),
1182 widget, qt_modal_stack ? (int)qt_modal_stack->count() : -1);
1184 if (!qt_modal_stack)
1185 qt_modal_stack = new QWidgetList;
1187 dispatchEnterLeave(0, qt_last_mouse_receiver);
1188 qt_last_mouse_receiver = 0;
1190 qt_modal_stack->insert(0, widget);
1192 qt_event_request_menubarupdate();
1193 app_do_modal = true;
1196 if (!qt_mac_is_macsheet(widget))
1197 QEventDispatcherMacPrivate::beginModalSession(widget);
1200 void QApplicationPrivate::leaveModal_sys(QWidget *widget)
1202 if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
1203 #ifdef DEBUG_MODAL_EVENTS
1204 qDebug("Leaving modal state with %s::%s::%p (%d)", widget->metaObject()->className(), widget->objectName().toLocal8Bit().constData(),
1205 widget, qt_modal_stack->count());
1207 if (qt_modal_stack->isEmpty()) {
1208 delete qt_modal_stack;
1210 QPoint p(QCursor::pos());
1211 app_do_modal = false;
1213 if (QWidget *grabber = QWidget::mouseGrabber())
1216 w = QApplication::widgetAt(p.x(), p.y());
1217 dispatchEnterLeave(w, qt_last_mouse_receiver); // send synthetic enter event
1218 qt_last_mouse_receiver = w;
1220 if (!qt_mac_is_macsheet(widget))
1221 QEventDispatcherMacPrivate::endModalSession(widget);
1223 #ifdef DEBUG_MODAL_EVENTS
1224 else qDebug("Failure to remove %s::%s::%p -- %p", widget->metaObject()->className(), widget->objectName().toLocal8Bit().constData(), widget, qt_modal_stack);
1226 app_do_modal = (qt_modal_stack != 0);
1228 qt_event_request_menubarupdate();
1231 QWidget *QApplicationPrivate::tryModalHelper_sys(QWidget *top)
1237 OSStatus QApplicationPrivate::tabletProximityCallback(EventHandlerCallRef, EventRef carbonEvent,
1240 OSType eventClass = GetEventClass(carbonEvent);
1241 UInt32 eventKind = GetEventKind(carbonEvent);
1242 if (eventClass != kEventClassTablet || eventKind != kEventTabletProximity)
1243 return eventNotHandledErr;
1245 // Get the current point of the device and its unique ID.
1246 ::TabletProximityRec proxRec;
1247 GetEventParameter(carbonEvent, kEventParamTabletProximityRec, typeTabletProximityRec, 0,
1248 sizeof(proxRec), 0, &proxRec);
1249 qt_dispatchTabletProximityEvent(proxRec);
1254 QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event, void *data)
1259 return eventNotHandledErr;
1262 void QApplicationPrivate::qt_initAfterNSAppStarted()
1265 qt_mac_update_cursor();
1268 void QApplicationPrivate::setupAppleEvents()
1270 // This function is called from the event dispatcher when NSApplication has
1271 // finished initialization, which appears to be just after [NSApplication run] has
1272 // started to execute. By setting up our apple events handlers this late, we override
1273 // the ones set up by NSApplication.
1275 // If Qt is used as a plugin, we let the 3rd party application handle events
1276 // like quit and open file events. Otherwise, if we install our own handlers, we
1277 // easily end up breaking functionallity the 3rd party application depend on:
1278 if (QApplication::testAttribute(Qt::AA_MacPluginApplication))
1281 QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
1282 NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
1283 [eventManager setEventHandler:newDelegate andSelector:@selector(appleEventQuit:withReplyEvent:)
1284 forEventClass:kCoreEventClass andEventID:kAEQuitApplication];
1285 [eventManager setEventHandler:newDelegate andSelector:@selector(getUrl:withReplyEvent:)
1286 forEventClass:kInternetEventClass andEventID:kAEGetURL];
1289 // In Carbon this is your one stop for apple events.
1290 // In Cocoa, it ISN'T. This is the catch-all Apple Event handler that exists
1291 // for the time between instantiating the NSApplication, but before the
1292 // NSApplication has installed it's OWN Apple Event handler. When Cocoa has
1293 // that set up, we remove this. So, if you are debugging problems, you likely
1294 // want to check out QCocoaApplicationDelegate instead.
1295 OSStatus QApplicationPrivate::globalAppleEventProcessor(const AppleEvent *ae, AppleEvent *, long handlerRefcon)
1297 QApplication *app = (QApplication *)handlerRefcon;
1298 bool handled_event=false;
1299 OSType aeID=typeWildCard, aeClass=typeWildCard;
1300 AEGetAttributePtr(ae, keyEventClassAttr, typeType, 0, &aeClass, sizeof(aeClass), 0);
1301 AEGetAttributePtr(ae, keyEventIDAttr, typeType, 0, &aeID, sizeof(aeID), 0);
1302 if(aeClass == kCoreEventClass) {
1304 case kAEQuitApplication: {
1305 extern bool qt_mac_quit_menu_item_enabled; // qmenu_mac.cpp
1306 if (qt_mac_quit_menu_item_enabled) {
1308 QApplication::sendSpontaneousEvent(app, &ev);
1309 if(ev.isAccepted()) {
1310 handled_event = true;
1314 QApplication::beep(); // Sorry, you can't quit right now.
1317 case kAEOpenDocuments: {
1319 if(AEGetParamDesc(ae, keyDirectObject, typeAEList, &docs) == noErr) {
1321 AECountItems(&docs, &cnt);
1322 UInt8 *str_buffer = NULL;
1323 for(int i = 0; i < cnt; i++) {
1325 if(AEGetNthPtr(&docs, i+1, typeFSRef, 0, 0, &ref, sizeof(ref), 0) != noErr)
1328 str_buffer = (UInt8 *)malloc(1024);
1329 FSRefMakePath(&ref, str_buffer, 1024);
1330 QFileOpenEvent ev(QString::fromUtf8((const char *)str_buffer));
1331 QApplication::sendSpontaneousEvent(app, &ev);
1340 } else if (aeClass == kInternetEventClass) {
1345 if (AEGetParamPtr(ae, keyDirectObject, typeChar, 0, urlData,
1346 sizeof(urlData) - 1, &actualSize) == noErr) {
1347 urlData[actualSize] = 0;
1348 QFileOpenEvent ev(QUrl(QString::fromUtf8(urlData)));
1349 QApplication::sendSpontaneousEvent(app, &ev);
1358 qDebug("Qt: internal: %shandled Apple event! %c%c%c%c %c%c%c%c", handled_event ? "(*)" : "",
1359 char(aeID >> 24), char((aeID >> 16) & 255), char((aeID >> 8) & 255),char(aeID & 255),
1360 char(aeClass >> 24), char((aeClass >> 16) & 255), char((aeClass >> 8) & 255),char(aeClass & 255));
1362 if(!handled_event) //let the event go through
1363 return eventNotHandledErr;
1364 return noErr; //we eat the event
1369 \fn bool QApplication::macEventFilter(EventHandlerCallRef caller, EventRef event)
1371 \warning This virtual function is only used under Mac OS X, and behaves different
1372 depending on if Qt is based on Carbon or Cocoa.
1374 For the Carbon port, If you create an application that inherits QApplication and reimplement
1375 this function, you get direct access to all Carbon Events that Qt registers
1376 for from Mac OS X with this function being called with the \a caller and
1379 For the Cocoa port, If you create an application that inherits QApplication and reimplement
1380 this function, you get direct access to all Cocoa Events that Qt receives
1381 from Mac OS X with this function being called with the \a caller being 0 and
1382 the \a event being an NSEvent pointer:
1384 NSEvent *e = reinterpret_cast<NSEvent *>(event);
1386 Return true if you want to stop the event from being processed.
1387 Return false for normal event dispatching. The default
1388 implementation returns false.
1390 bool QApplication::macEventFilter(EventHandlerCallRef, EventRef)
1398 void QApplicationPrivate::openPopup(QWidget *popup)
1400 if (!QApplicationPrivate::popupWidgets) // create list
1401 QApplicationPrivate::popupWidgets = new QWidgetList;
1402 QApplicationPrivate::popupWidgets->append(popup); // add to end of list
1404 // popups are not focus-handled by the window system (the first
1405 // popup grabbed the keyboard), so we have to do that manually: A
1406 // new popup gets the focus
1407 if (popup->focusWidget()) {
1408 popup->focusWidget()->setFocus(Qt::PopupFocusReason);
1409 } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
1410 popup->setFocus(Qt::PopupFocusReason);
1417 void QApplicationPrivate::closePopup(QWidget *popup)
1420 if (!QApplicationPrivate::popupWidgets)
1423 QApplicationPrivate::popupWidgets->removeAll(popup);
1424 if (popup == qt_button_down)
1426 if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup
1427 delete QApplicationPrivate::popupWidgets;
1428 QApplicationPrivate::popupWidgets = 0;
1430 // Special case for Tool windows: since they are activated and deactived together
1431 // with a normal window they never become the QApplicationPrivate::active_window.
1432 QWidget *appFocusWidget = QApplication::focusWidget();
1433 if (appFocusWidget && appFocusWidget->window()->windowType() == Qt::Tool) {
1434 appFocusWidget->setFocus(Qt::PopupFocusReason);
1435 } else if (QApplicationPrivate::active_window) {
1436 if (QWidget *fw = QApplicationPrivate::active_window->focusWidget()) {
1437 if (fw != QApplication::focusWidget()) {
1438 fw->setFocus(Qt::PopupFocusReason);
1440 QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
1441 q->sendEvent(fw, &e);
1446 // popups are not focus-handled by the window system (the
1447 // first popup grabbed the keyboard), so we have to do that
1448 // manually: A popup was closed, so the previous popup gets
1450 QWidget* aw = QApplicationPrivate::popupWidgets->last();
1451 if (QWidget *fw = aw->focusWidget())
1452 fw->setFocus(Qt::PopupFocusReason);
1456 void QApplication::beep()
1461 void QApplication::alert(QWidget *widget, int duration)
1463 if (!QApplicationPrivate::checkInstance("alert"))
1466 QWidgetList windowsToMark;
1468 windowsToMark += topLevelWidgets();
1470 windowsToMark.append(widget->window());
1472 bool needNotification = false;
1473 for (int i = 0; i < windowsToMark.size(); ++i) {
1474 QWidget *window = windowsToMark.at(i);
1475 if (!window->isActiveWindow() && window->isVisible()) {
1476 needNotification = true; // yeah, we may set it multiple times, but that's OK.
1477 if (duration != 0) {
1478 QTimer *timer = new QTimer(qApp);
1479 timer->setSingleShot(true);
1480 connect(timer, SIGNAL(timeout()), qApp, SLOT(_q_alertTimeOut()));
1481 if (QTimer *oldTimer = qApp->d_func()->alertTimerHash.value(widget)) {
1482 qApp->d_func()->alertTimerHash.remove(widget);
1485 qApp->d_func()->alertTimerHash.insert(widget, timer);
1486 timer->start(duration);
1490 if (needNotification)
1491 qt_mac_send_notification();
1494 void QApplicationPrivate::_q_alertTimeOut()
1496 if (QTimer *timer = qobject_cast<QTimer *>(q_func()->sender())) {
1497 QHash<QWidget *, QTimer *>::iterator it = alertTimerHash.begin();
1498 while (it != alertTimerHash.end()) {
1499 if (it.value() == timer) {
1500 alertTimerHash.erase(it);
1501 timer->deleteLater();
1506 if (alertTimerHash.isEmpty()) {
1507 qt_mac_cancel_notification();
1512 void QApplication::setCursorFlashTime(int msecs)
1514 QApplicationPrivate::cursor_flash_time = msecs;
1517 int QApplication::cursorFlashTime()
1519 return QApplicationPrivate::cursor_flash_time;
1522 void QApplication::setDoubleClickInterval(int ms)
1524 qt_mac_dblclick.use_qt_time_limit = true;
1525 QApplicationPrivate::mouse_double_click_time = ms;
1528 int QApplication::doubleClickInterval()
1530 if (!qt_mac_dblclick.use_qt_time_limit) { //get it from the system
1531 QSettings appleSettings(QLatin1String("apple.com"));
1532 /* First worked as of 10.3.3 */
1533 double dci = appleSettings.value(QLatin1String("com/apple/mouse/doubleClickThreshold"), 0.5).toDouble();
1534 return int(dci * 1000);
1536 return QApplicationPrivate::mouse_double_click_time;
1539 void QApplication::setKeyboardInputInterval(int ms)
1541 QApplicationPrivate::keyboard_input_time = ms;
1544 int QApplication::keyboardInputInterval()
1546 // FIXME: get from the system
1547 return QApplicationPrivate::keyboard_input_time;
1550 #ifndef QT_NO_WHEELEVENT
1551 void QApplication::setWheelScrollLines(int n)
1553 QApplicationPrivate::wheel_scroll_lines = n;
1556 int QApplication::wheelScrollLines()
1558 return QApplicationPrivate::wheel_scroll_lines;
1562 void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
1565 case Qt::UI_FadeMenu:
1566 QApplicationPrivate::fade_menu = enable;
1568 case Qt::UI_AnimateMenu:
1569 QApplicationPrivate::animate_menu = enable;
1571 case Qt::UI_FadeTooltip:
1572 QApplicationPrivate::fade_tooltip = enable;
1574 case Qt::UI_AnimateTooltip:
1575 QApplicationPrivate::animate_tooltip = enable;
1577 case Qt::UI_AnimateCombo:
1578 QApplicationPrivate::animate_combo = enable;
1580 case Qt::UI_AnimateToolBox:
1581 QApplicationPrivate::animate_toolbox = enable;
1583 case Qt::UI_General:
1584 QApplicationPrivate::fade_tooltip = true;
1587 QApplicationPrivate::animate_ui = enable;
1592 QApplicationPrivate::animate_ui = true;
1595 bool QApplication::isEffectEnabled(Qt::UIEffect effect)
1597 if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui)
1601 case Qt::UI_AnimateMenu:
1602 return QApplicationPrivate::animate_menu;
1603 case Qt::UI_FadeMenu:
1604 return QApplicationPrivate::fade_menu;
1605 case Qt::UI_AnimateCombo:
1606 return QApplicationPrivate::animate_combo;
1607 case Qt::UI_AnimateTooltip:
1608 return QApplicationPrivate::animate_tooltip;
1609 case Qt::UI_FadeTooltip:
1610 return QApplicationPrivate::fade_tooltip;
1611 case Qt::UI_AnimateToolBox:
1612 return QApplicationPrivate::animate_toolbox;
1616 return QApplicationPrivate::animate_ui;
1622 bool QApplicationPrivate::qt_mac_apply_settings()
1624 QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
1625 settings.beginGroup(QLatin1String("Qt"));
1628 Qt settings. This is how they are written into the datastream.
1629 Palette/ * - QPalette
1631 libraryPath - QStringList
1633 doubleClickInterval - int
1634 cursorFlashTime - int
1635 wheelScrollLines - int
1637 defaultCodec - QString
1638 globalStrut/width - int
1639 globalStrut/height - int
1640 GUIEffects - QStringList
1641 Font Substitutions/ * - QStringList
1642 Font Substitutions/... - QStringList
1645 // read library (ie. plugin) path list
1646 QString libpathkey =
1647 QString::fromLatin1("%1.%2/libraryPath")
1648 .arg(QT_VERSION >> 16)
1649 .arg((QT_VERSION & 0xff00) >> 8);
1650 QStringList pathlist = settings.value(libpathkey).toString().split(QLatin1Char(':'));
1651 if (!pathlist.isEmpty()) {
1652 QStringList::ConstIterator it = pathlist.begin();
1653 while(it != pathlist.end())
1654 QApplication::addLibraryPath(*it++);
1657 QString defaultcodec = settings.value(QLatin1String("defaultCodec"), QVariant(QLatin1String("none"))).toString();
1658 if (defaultcodec != QLatin1String("none")) {
1659 QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1().constData());
1661 QTextCodec::setCodecForTr(codec);
1664 if (qt_is_gui_used) {
1666 QStringList strlist;
1671 QPalette pal(QApplication::palette());
1672 strlist = settings.value(QLatin1String("Palette/active")).toStringList();
1673 if (strlist.count() == QPalette::NColorRoles) {
1674 for (i = 0; i < QPalette::NColorRoles; i++)
1675 pal.setColor(QPalette::Active, (QPalette::ColorRole) i,
1676 QColor(strlist[i]));
1678 strlist = settings.value(QLatin1String("Palette/inactive")).toStringList();
1679 if (strlist.count() == QPalette::NColorRoles) {
1680 for (i = 0; i < QPalette::NColorRoles; i++)
1681 pal.setColor(QPalette::Inactive, (QPalette::ColorRole) i,
1682 QColor(strlist[i]));
1684 strlist = settings.value(QLatin1String("Palette/disabled")).toStringList();
1685 if (strlist.count() == QPalette::NColorRoles) {
1686 for (i = 0; i < QPalette::NColorRoles; i++)
1687 pal.setColor(QPalette::Disabled, (QPalette::ColorRole) i,
1688 QColor(strlist[i]));
1691 if (pal != QApplication::palette())
1692 QApplication::setPalette(pal);
1695 QFont font(QApplication::font());
1696 str = settings.value(QLatin1String("font")).toString();
1697 if (!str.isEmpty()) {
1698 font.fromString(str);
1699 if (font != QApplication::font())
1700 QApplication::setFont(font);
1704 QString stylename = settings.value(QLatin1String("style")).toString();
1705 if (! stylename.isNull() && ! stylename.isEmpty()) {
1706 QStyle *style = QStyleFactory::create(stylename);
1708 QApplication::setStyle(style);
1710 stylename = QLatin1String("default");
1712 stylename = QLatin1String("default");
1715 num = settings.value(QLatin1String("doubleClickInterval"),
1716 QApplication::doubleClickInterval()).toInt();
1717 QApplication::setDoubleClickInterval(num);
1719 num = settings.value(QLatin1String("cursorFlashTime"),
1720 QApplication::cursorFlashTime()).toInt();
1721 QApplication::setCursorFlashTime(num);
1723 #ifndef QT_NO_WHEELEVENT
1724 num = settings.value(QLatin1String("wheelScrollLines"),
1725 QApplication::wheelScrollLines()).toInt();
1726 QApplication::setWheelScrollLines(num);
1729 QString colorspec = settings.value(QLatin1String("colorSpec"),
1730 QVariant(QLatin1String("default"))).toString();
1731 if (colorspec == QLatin1String("normal"))
1732 QApplication::setColorSpec(QApplication::NormalColor);
1733 else if (colorspec == QLatin1String("custom"))
1734 QApplication::setColorSpec(QApplication::CustomColor);
1735 else if (colorspec == QLatin1String("many"))
1736 QApplication::setColorSpec(QApplication::ManyColor);
1737 else if (colorspec != QLatin1String("default"))
1738 colorspec = QLatin1String("default");
1740 int w = settings.value(QLatin1String("globalStrut/width")).toInt();
1741 int h = settings.value(QLatin1String("globalStrut/height")).toInt();
1743 if (strut.isValid())
1744 QApplication::setGlobalStrut(strut);
1746 QStringList effects = settings.value(QLatin1String("GUIEffects")).toStringList();
1747 if (!effects.isEmpty()) {
1748 if (effects.contains(QLatin1String("none")))
1749 QApplication::setEffectEnabled(Qt::UI_General, false);
1750 if (effects.contains(QLatin1String("general")))
1751 QApplication::setEffectEnabled(Qt::UI_General, true);
1752 if (effects.contains(QLatin1String("animatemenu")))
1753 QApplication::setEffectEnabled(Qt::UI_AnimateMenu, true);
1754 if (effects.contains(QLatin1String("fademenu")))
1755 QApplication::setEffectEnabled(Qt::UI_FadeMenu, true);
1756 if (effects.contains(QLatin1String("animatecombo")))
1757 QApplication::setEffectEnabled(Qt::UI_AnimateCombo, true);
1758 if (effects.contains(QLatin1String("animatetooltip")))
1759 QApplication::setEffectEnabled(Qt::UI_AnimateTooltip, true);
1760 if (effects.contains(QLatin1String("fadetooltip")))
1761 QApplication::setEffectEnabled(Qt::UI_FadeTooltip, true);
1762 if (effects.contains(QLatin1String("animatetoolbox")))
1763 QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, true);
1765 QApplication::setEffectEnabled(Qt::UI_General, true);
1768 settings.beginGroup(QLatin1String("Font Substitutions"));
1769 QStringList fontsubs = settings.childKeys();
1770 if (!fontsubs.isEmpty()) {
1771 QStringList::Iterator it = fontsubs.begin();
1772 for (; it != fontsubs.end(); ++it) {
1773 QString fam = QString::fromLatin1((*it).toLatin1().constData());
1774 QStringList subs = settings.value(fam).toStringList();
1775 QFont::insertSubstitutions(fam, subs);
1778 settings.endGroup();
1781 settings.endGroup();
1787 bool QApplicationPrivate::canQuit()
1790 [[NSApp mainMenu] cancelTracking];
1792 bool handle_quit = true;
1793 if (QApplicationPrivate::modalState() && [[[[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate]
1794 menuLoader] quitMenuItem] isEnabled]) {
1796 const QWidgetList tlws = QApplication::topLevelWidgets();
1797 for(int i = 0; i < tlws.size(); ++i) {
1798 if (tlws.at(i)->isVisible())
1801 handle_quit = (visible <= 1);
1805 QApplication::sendSpontaneousEvent(q, &ev);
1806 if (ev.isAccepted()) {
1813 void onApplicationWindowChangedActivation(QWidget *widget, bool activated)
1819 if (QApplicationPrivate::app_style) {
1820 QEvent ev(QEvent::Style);
1821 qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
1823 qApp->setActiveWindow(widget);
1824 } else { // deactivated
1825 if (QApplicationPrivate::active_window == widget)
1826 qApp->setActiveWindow(0);
1829 QMenuBar::macUpdateMenuBar();
1830 qt_mac_update_cursor();
1834 void onApplicationChangedActivation( bool activated )
1836 QApplication *app = qApp;
1838 //NSLog(@"App Changed Activation\n");
1841 if (QApplication::desktopSettingsAware())
1842 qt_mac_update_os_settings();
1844 if (qt_clipboard) { //manufacture an event so the clipboard can see if it has changed
1845 QEvent ev(QEvent::Clipboard);
1846 qt_sendSpontaneousEvent(qt_clipboard, &ev);
1850 QEvent ev(QEvent::ApplicationActivate);
1851 qt_sendSpontaneousEvent(app, &ev);
1854 if (!app->activeWindow()) {
1855 OSWindowRef wp = [NSApp keyWindow];
1856 if (QWidget *tmp_w = qt_mac_find_window(wp))
1857 app->setActiveWindow(tmp_w);
1859 QMenuBar::macUpdateMenuBar();
1860 qt_mac_update_cursor();
1861 } else { // de-activated
1862 QApplicationPrivate *priv = [[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] qAppPrivate];
1863 while (priv->inPopupMode())
1864 app->activePopupWidget()->close();
1866 QEvent ev(QEvent::ApplicationDeactivate);
1867 qt_sendSpontaneousEvent(app, &ev);
1869 app->setActiveWindow(0);
1873 void QApplicationPrivate::initializeMultitouch_sys()
1875 void QApplicationPrivate::cleanupMultitouch_sys()