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

Last change on this file since 694 was 651, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.2 sources.

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