source: trunk/src/gui/kernel/qapplication_mac.mm

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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