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

Last change on this file since 807 was 769, checked in by Dmitry A. Kuminov, 15 years ago

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

File size: 120.8 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#ifndef QT_NO_WHEELEVENT
2147 if (wheel_deltaX) {
2148 QWheelEvent qwe(plocal, p, wheel_deltaX, buttons, modifiers, Qt::Horizontal);
2149 QApplication::sendSpontaneousEvent(widget, &qwe);
2150 if (!qwe.isAccepted() && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != widget) {
2151 QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(p), p,
2152 wheel_deltaX, buttons, modifiers, Qt::Horizontal);
2153 QApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
2154 if (!qwe2.isAccepted())
2155 handled_event = false;
2156 }
2157 }
2158 if (wheel_deltaY) {
2159 QWheelEvent qwe(plocal, p, wheel_deltaY, buttons, modifiers, Qt::Vertical);
2160 QApplication::sendSpontaneousEvent(widget, &qwe);
2161 if (!qwe.isAccepted() && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != widget) {
2162 QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(p), p,
2163 wheel_deltaY, buttons, modifiers, Qt::Vertical);
2164 QApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
2165 if (!qwe2.isAccepted())
2166 handled_event = false;
2167 }
2168 }
2169#endif // QT_NO_WHEELEVENT
2170 } else {
2171#ifdef QMAC_SPEAK_TO_ME
2172 const int speak_keys = Qt::AltModifier | Qt::ShiftModifier;
2173 if(etype == QMouseEvent::MouseButtonDblClick && ((modifiers & speak_keys) == speak_keys)) {
2174 QVariant v = widget->property("displayText");
2175 if(!v.isValid()) v = widget->property("text");
2176 if(!v.isValid()) v = widget->property("windowTitle");
2177 if(v.isValid()) {
2178 QString s = v.toString();
2179 s.replace(QRegExp(QString::fromLatin1("(\\&|\\<[^\\>]*\\>)")), QLatin1String(""));
2180 SpeechChannel ch;
2181 NewSpeechChannel(0, &ch);
2182 SpeakText(ch, s.toLatin1().constData(), s.length());
2183 DisposeSpeechChannel(ch);
2184 }
2185 }
2186#endif
2187 Qt::MouseButton buttonToSend = button;
2188 static bool lastButtonTranslated = false;
2189 if(ekind == kEventMouseDown &&
2190 button == Qt::LeftButton && (modifiers & Qt::MetaModifier)) {
2191 buttonToSend = Qt::RightButton;
2192 lastButtonTranslated = true;
2193 } else if(ekind == kEventMouseUp && lastButtonTranslated) {
2194 buttonToSend = Qt::RightButton;
2195 lastButtonTranslated = false;
2196 }
2197 QMouseEvent qme(etype, plocal, p, buttonToSend, buttons, modifiers);
2198 QApplication::sendSpontaneousEvent(widget, &qme);
2199 if(!qme.isAccepted() || inNonClientArea)
2200 handled_event = false;
2201 }
2202
2203 if (leaveAfterRelease) {
2204 QWidget *enter = QApplication::widgetAt(where.h, where.v);
2205 QApplicationPrivate::dispatchEnterLeave(enter, leaveAfterRelease);
2206 qt_mouseover = enter;
2207 leaveAfterRelease = 0;
2208 }
2209
2210 if(ekind == kEventMouseDown &&
2211 ((button == Qt::RightButton) ||
2212 (button == Qt::LeftButton && (modifiers & Qt::MetaModifier))))
2213 qt_event_request_context();
2214
2215#ifdef DEBUG_MOUSE_MAPS
2216 const char *event_desc = edesc;
2217 if(etype == QEvent::MouseButtonDblClick)
2218 event_desc = "Double Click";
2219 else if(etype == QEvent::NonClientAreaMouseButtonPress)
2220 event_desc = "NonClientMousePress";
2221 else if(etype == QEvent::NonClientAreaMouseButtonRelease)
2222 event_desc = "NonClientMouseRelease";
2223 else if(etype == QEvent::NonClientAreaMouseMove)
2224 event_desc = "NonClientMouseMove";
2225 else if(etype == QEvent::NonClientAreaMouseButtonDblClick)
2226 event_desc = "NonClientMouseDblClick";
2227 qDebug("%d %d (%d %d) - Would send (%s) event to %p %s %s (%d 0x%08x 0x%08x %d)", p.x(), p.y(),
2228 plocal.x(), plocal.y(), event_desc, (QWidget*)widget,
2229 widget ? widget->objectName().toLocal8Bit().constData() : "*Unknown*",
2230 widget ? widget->metaObject()->className() : "*Unknown*",
2231 button, (int)buttons, (int)modifiers, wheel_deltaX);
2232#endif
2233 } else {
2234 handled_event = false;
2235 }
2236 break;
2237 }
2238 case kEventClassTextInput:
2239 case kEventClassKeyboard: {
2240 EventRef key_event = event;
2241 if(eclass == kEventClassTextInput) {
2242 Q_ASSERT(ekind == kEventTextInputUnicodeForKeyEvent);
2243 OSStatus err = GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, 0,
2244 sizeof(key_event), 0, &key_event);
2245 Q_ASSERT(err == noErr);
2246 Q_UNUSED(err);
2247 }
2248 const UInt32 key_ekind = GetEventKind(key_event);
2249 Q_ASSERT(GetEventClass(key_event) == kEventClassKeyboard);
2250
2251 if(key_ekind == kEventRawKeyDown)
2252 qt_keymapper_private()->updateKeyMap(er, key_event, data);
2253 if(mac_keyboard_grabber)
2254 widget = mac_keyboard_grabber;
2255 else if (app->activePopupWidget())
2256 widget = (app->activePopupWidget()->focusWidget() ?
2257 app->activePopupWidget()->focusWidget() : app->activePopupWidget());
2258 else if(QApplication::focusWidget())
2259 widget = QApplication::focusWidget();
2260 else
2261 widget = app->activeWindow();
2262
2263 if (widget) {
2264 if (widget->macEvent(er, event))
2265 return noErr;
2266 } else {
2267 // Darn, I need to update tho modifier state, even though
2268 // Qt itself isn't getting them, otherwise the keyboard state get inconsistent.
2269 if (key_ekind == kEventRawKeyModifiersChanged) {
2270 UInt32 modifiers = 0;
2271 GetEventParameter(key_event, kEventParamKeyModifiers, typeUInt32, 0,
2272 sizeof(modifiers), 0, &modifiers);
2273 extern void qt_mac_send_modifiers_changed(quint32 modifiers, QObject *object); // qkeymapper_mac.cpp
2274 // Just send it to the qApp for the time being.
2275 qt_mac_send_modifiers_changed(modifiers, qApp);
2276 }
2277 handled_event = false;
2278 break;
2279 }
2280
2281 if(app_do_modal && !qt_try_modal(widget, key_event))
2282 break;
2283 if (eclass == kEventClassTextInput) {
2284 handled_event = false;
2285 } else {
2286 handled_event = qt_keymapper_private()->translateKeyEvent(widget, er, key_event, data,
2287 widget == mac_keyboard_grabber);
2288 }
2289 break; }
2290 case kEventClassWindow: {
2291 WindowRef wid = 0;
2292 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0,
2293 sizeof(WindowRef), 0, &wid);
2294 widget = qt_mac_find_window(wid);
2295 if (widget && widget->macEvent(er, event))
2296 return noErr;
2297 if(ekind == kEventWindowActivated) {
2298 if(QApplicationPrivate::app_style) {
2299 QEvent ev(QEvent::Style);
2300 QApplication::sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
2301 }
2302
2303 if(widget && app_do_modal && !qt_try_modal(widget, event))
2304 break;
2305
2306 if(widget && widget->window()->isVisible()) {
2307 QWidget *tlw = widget->window();
2308 if(tlw->isWindow() && !(tlw->windowType() == Qt::Popup)
2309 && !qt_mac_is_macdrawer(tlw)
2310 && (!tlw->parentWidget() || tlw->isModal()
2311 || !(tlw->windowType() == Qt::Tool))) {
2312 bool just_send_event = false;
2313 {
2314 WindowActivationScope scope;
2315 if(GetWindowActivationScope((WindowRef)wid, &scope) == noErr &&
2316 scope == kWindowActivationScopeIndependent) {
2317 if(GetFrontWindowOfClass(kAllWindowClasses, true) != wid)
2318 just_send_event = true;
2319 }
2320 }
2321 if(just_send_event) {
2322 QEvent e(QEvent::WindowActivate);
2323 QApplication::sendSpontaneousEvent(widget, &e);
2324 } else {
2325 app->setActiveWindow(tlw);
2326 }
2327 }
2328 QMenuBar::macUpdateMenuBar();
2329 }
2330 } else if(ekind == kEventWindowDeactivated) {
2331 if(widget && QApplicationPrivate::active_window == widget)
2332 app->setActiveWindow(0);
2333 } else {
2334 handled_event = false;
2335 }
2336 break; }
2337 case kEventClassApplication:
2338 if(ekind == kEventAppActivated) {
2339 if(QApplication::desktopSettingsAware())
2340 qt_mac_update_os_settings();
2341 if(qt_clipboard) { //manufacture an event so the clipboard can see if it has changed
2342 QEvent ev(QEvent::Clipboard);
2343 QApplication::sendSpontaneousEvent(qt_clipboard, &ev);
2344 }
2345 if(app) {
2346 QEvent ev(QEvent::ApplicationActivate);
2347 QApplication::sendSpontaneousEvent(app, &ev);
2348 }
2349 if(!app->activeWindow()) {
2350 WindowPtr wp = ActiveNonFloatingWindow();
2351 if(QWidget *tmp_w = qt_mac_find_window(wp))
2352 app->setActiveWindow(tmp_w);
2353 }
2354 QMenuBar::macUpdateMenuBar();
2355 } else if(ekind == kEventAppDeactivated) {
2356 //qt_mac_no_click_through_mode = false;
2357 while(app->d_func()->inPopupMode())
2358 app->activePopupWidget()->close();
2359 if(app) {
2360 QEvent ev(QEvent::ApplicationDeactivate);
2361 QApplication::sendSpontaneousEvent(app, &ev);
2362 }
2363 app->setActiveWindow(0);
2364 } else if(ekind == kEventAppAvailableWindowBoundsChanged) {
2365 QDesktopWidgetImplementation::instance()->onResize();
2366 } else {
2367 handled_event = false;
2368 }
2369 break;
2370 case kAppearanceEventClass:
2371 if(ekind == kAEAppearanceChanged) {
2372 if(QApplication::desktopSettingsAware())
2373 qt_mac_update_os_settings();
2374 if(QApplicationPrivate::app_style) {
2375 QEvent ev(QEvent::Style);
2376 QApplication::sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
2377 }
2378 } else {
2379 handled_event = false;
2380 }
2381 break;
2382 case kEventClassAppleEvent:
2383 if(ekind == kEventAppleEvent) {
2384 EventRecord erec;
2385 if(!ConvertEventRefToEventRecord(event, &erec))
2386 qDebug("Qt: internal: WH0A, unexpected condition reached. %s:%d", __FILE__, __LINE__);
2387 else if(AEProcessAppleEvent(&erec) != noErr)
2388 handled_event = false;
2389 } else {
2390 handled_event = false;
2391 }
2392 break;
2393 case kEventClassCommand:
2394 if(ekind == kEventCommandProcess) {
2395 HICommand cmd;
2396 GetEventParameter(event, kEventParamDirectObject, typeHICommand,
2397 0, sizeof(cmd), 0, &cmd);
2398 handled_event = false;
2399 if(!cmd.menu.menuRef && GetApplicationDockTileMenu()) {
2400 EventRef copy = CopyEvent(event);
2401 HICommand copy_cmd;
2402 GetEventParameter(event, kEventParamDirectObject, typeHICommand,
2403 0, sizeof(copy_cmd), 0, &copy_cmd);
2404 copy_cmd.menu.menuRef = GetApplicationDockTileMenu();
2405 SetEventParameter(copy, kEventParamDirectObject, typeHICommand, sizeof(copy_cmd), &copy_cmd);
2406 if(SendEventToMenu(copy, copy_cmd.menu.menuRef) == noErr)
2407 handled_event = true;
2408 }
2409 if(!handled_event) {
2410 if(cmd.commandID == kHICommandQuit) {
2411 handled_event = true;
2412 HiliteMenu(0);
2413 bool handle_quit = true;
2414 if(QApplicationPrivate::modalState()) {
2415 int visible = 0;
2416 const QWidgetList tlws = QApplication::topLevelWidgets();
2417 for(int i = 0; i < tlws.size(); ++i) {
2418 if(tlws.at(i)->isVisible())
2419 ++visible;
2420 }
2421 handle_quit = (visible <= 1);
2422 }
2423 if(handle_quit) {
2424 QCloseEvent ev;
2425 QApplication::sendSpontaneousEvent(app, &ev);
2426 if(ev.isAccepted())
2427 app->quit();
2428 } else {
2429 QApplication::beep();
2430 }
2431 } else if(cmd.commandID == kHICommandSelectWindow) {
2432 if((GetCurrentKeyModifiers() & cmdKey))
2433 handled_event = true;
2434 } else if(cmd.commandID == kHICommandAbout) {
2435 QMessageBox::aboutQt(0);
2436 HiliteMenu(0);
2437 handled_event = true;
2438 }
2439 }
2440 }
2441 break;
2442 }
2443
2444#ifdef DEBUG_EVENTS
2445 qDebug("%shandled event %c%c%c%c %d", handled_event ? "(*) " : "",
2446 char(eclass >> 24), char((eclass >> 16) & 255), char((eclass >> 8) & 255),
2447 char(eclass & 255), (int)ekind);
2448#endif
2449 if(!handled_event) //let the event go through
2450 return eventNotHandledErr;
2451 return noErr; //we eat the event
2452#else
2453 Q_UNUSED(er);
2454 Q_UNUSED(event);
2455 Q_UNUSED(data);
2456 return eventNotHandledErr;
2457#endif
2458}
2459
2460// In Carbon this is your one stop for apple events.
2461// In Cocoa, it ISN'T. This is the catch-all Apple Event handler that exists
2462// for the time between instantiating the NSApplication, but before the
2463// NSApplication has installed it's OWN Apple Event handler. When Cocoa has
2464// that set up, we remove this. So, if you are debugging problems, you likely
2465// want to check out QCocoaApplicationDelegate instead.
2466OSStatus QApplicationPrivate::globalAppleEventProcessor(const AppleEvent *ae, AppleEvent *, long handlerRefcon)
2467{
2468 QApplication *app = (QApplication *)handlerRefcon;
2469 bool handled_event=false;
2470 OSType aeID=typeWildCard, aeClass=typeWildCard;
2471 AEGetAttributePtr(ae, keyEventClassAttr, typeType, 0, &aeClass, sizeof(aeClass), 0);
2472 AEGetAttributePtr(ae, keyEventIDAttr, typeType, 0, &aeID, sizeof(aeID), 0);
2473 if(aeClass == kCoreEventClass) {
2474 switch(aeID) {
2475 case kAEQuitApplication: {
2476 extern bool qt_mac_quit_menu_item_enabled; // qmenu_mac.cpp
2477 if (qt_mac_quit_menu_item_enabled) {
2478 QCloseEvent ev;
2479 QApplication::sendSpontaneousEvent(app, &ev);
2480 if(ev.isAccepted()) {
2481 handled_event = true;
2482 app->quit();
2483 }
2484 } else {
2485 QApplication::beep(); // Sorry, you can't quit right now.
2486 }
2487 break; }
2488 case kAEOpenDocuments: {
2489 AEDescList docs;
2490 if(AEGetParamDesc(ae, keyDirectObject, typeAEList, &docs) == noErr) {
2491 long cnt = 0;
2492 AECountItems(&docs, &cnt);
2493 UInt8 *str_buffer = NULL;
2494 for(int i = 0; i < cnt; i++) {
2495 FSRef ref;
2496 if(AEGetNthPtr(&docs, i+1, typeFSRef, 0, 0, &ref, sizeof(ref), 0) != noErr)
2497 continue;
2498 if(!str_buffer)
2499 str_buffer = (UInt8 *)malloc(1024);
2500 FSRefMakePath(&ref, str_buffer, 1024);
2501 QFileOpenEvent ev(QString::fromUtf8((const char *)str_buffer));
2502 QApplication::sendSpontaneousEvent(app, &ev);
2503 }
2504 if(str_buffer)
2505 free(str_buffer);
2506 }
2507 break; }
2508 default:
2509 break;
2510 }
2511 } else if (aeClass == kInternetEventClass) {
2512 switch (aeID) {
2513 case kAEGetURL: {
2514 char urlData[1024];
2515 Size actualSize;
2516 if (AEGetParamPtr(ae, keyDirectObject, typeChar, 0, urlData,
2517 sizeof(urlData) - 1, &actualSize) == noErr) {
2518 urlData[actualSize] = 0;
2519 QFileOpenEvent ev(QUrl(QString::fromUtf8(urlData)));
2520 QApplication::sendSpontaneousEvent(app, &ev);
2521 }
2522 break;
2523 }
2524 default:
2525 break;
2526 }
2527 }
2528#ifdef DEBUG_EVENTS
2529 qDebug("Qt: internal: %shandled Apple event! %c%c%c%c %c%c%c%c", handled_event ? "(*)" : "",
2530 char(aeID >> 24), char((aeID >> 16) & 255), char((aeID >> 8) & 255),char(aeID & 255),
2531 char(aeClass >> 24), char((aeClass >> 16) & 255), char((aeClass >> 8) & 255),char(aeClass & 255));
2532#else
2533 if(!handled_event) //let the event go through
2534 return eventNotHandledErr;
2535 return noErr; //we eat the event
2536#endif
2537}
2538
2539/*!
2540 \fn bool QApplication::macEventFilter(EventHandlerCallRef caller, EventRef event)
2541
2542 \warning This virtual function is only implemented under Mac OS X when against Carbon.
2543
2544 If you create an application that inherits QApplication and reimplement
2545 this function, you get direct access to all Carbon Events that Qt registers
2546 for from Mac OS X with this function being called with the \a caller and
2547 the \a event.
2548
2549 Return true if you want to stop the event from being processed.
2550 Return false for normal event dispatching. The default
2551 implementation returns false.
2552
2553 Cocoa uses a different event system which means this function is NOT CALLED
2554 when building Qt against Cocoa. If you want similar functionality subclass
2555 NSApplication and reimplement the sendEvent: message to handle all the
2556 NSEvents. You also will need to to instantiate your custom NSApplication
2557 before creating a QApplication. See \l
2558 {http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html}{Apple's
2559 NSApplication Reference} for more information.
2560
2561*/
2562bool QApplication::macEventFilter(EventHandlerCallRef, EventRef)
2563{
2564 return false;
2565}
2566
2567/*!
2568 \internal
2569*/
2570void QApplicationPrivate::openPopup(QWidget *popup)
2571{
2572 if (!QApplicationPrivate::popupWidgets) // create list
2573 QApplicationPrivate::popupWidgets = new QWidgetList;
2574 QApplicationPrivate::popupWidgets->append(popup); // add to end of list
2575
2576 // popups are not focus-handled by the window system (the first
2577 // popup grabbed the keyboard), so we have to do that manually: A
2578 // new popup gets the focus
2579 if (popup->focusWidget()) {
2580 popup->focusWidget()->setFocus(Qt::PopupFocusReason);
2581 } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
2582 popup->setFocus(Qt::PopupFocusReason);
2583 }
2584}
2585
2586/*!
2587 \internal
2588*/
2589void QApplicationPrivate::closePopup(QWidget *popup)
2590{
2591 Q_Q(QApplication);
2592 if (!QApplicationPrivate::popupWidgets)
2593 return;
2594
2595 QApplicationPrivate::popupWidgets->removeAll(popup);
2596 if (popup == qt_button_down)
2597 qt_button_down = 0;
2598 if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup
2599 delete QApplicationPrivate::popupWidgets;
2600 QApplicationPrivate::popupWidgets = 0;
2601
2602 // Special case for Tool windows: since they are activated and deactived together
2603 // with a normal window they never become the QApplicationPrivate::active_window.
2604 QWidget *appFocusWidget = QApplication::focusWidget();
2605 if (appFocusWidget && appFocusWidget->window()->windowType() == Qt::Tool) {
2606 appFocusWidget->setFocus(Qt::PopupFocusReason);
2607 } else if (QApplicationPrivate::active_window) {
2608 if (QWidget *fw = QApplicationPrivate::active_window->focusWidget()) {
2609 if (fw != QApplication::focusWidget()) {
2610 fw->setFocus(Qt::PopupFocusReason);
2611 } else {
2612 QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
2613 q->sendEvent(fw, &e);
2614 }
2615 }
2616 }
2617 } else {
2618 // popups are not focus-handled by the window system (the
2619 // first popup grabbed the keyboard), so we have to do that
2620 // manually: A popup was closed, so the previous popup gets
2621 // the focus.
2622 QWidget* aw = QApplicationPrivate::popupWidgets->last();
2623 if (QWidget *fw = aw->focusWidget())
2624 fw->setFocus(Qt::PopupFocusReason);
2625 }
2626}
2627
2628void QApplication::beep()
2629{
2630 qt_mac_beep();
2631}
2632
2633void QApplication::alert(QWidget *widget, int duration)
2634{
2635 if (!QApplicationPrivate::checkInstance("alert"))
2636 return;
2637
2638 QWidgetList windowsToMark;
2639 if (!widget)
2640 windowsToMark += topLevelWidgets();
2641 else
2642 windowsToMark.append(widget->window());
2643
2644 bool needNotification = false;
2645 for (int i = 0; i < windowsToMark.size(); ++i) {
2646 QWidget *window = windowsToMark.at(i);
2647 if (!window->isActiveWindow() && window->isVisible()) {
2648 needNotification = true; // yeah, we may set it multiple times, but that's OK.
2649 if (duration != 0) {
2650 QTimer *timer = new QTimer(qApp);
2651 timer->setSingleShot(true);
2652 connect(timer, SIGNAL(timeout()), qApp, SLOT(_q_alertTimeOut()));
2653 if (QTimer *oldTimer = qApp->d_func()->alertTimerHash.value(widget)) {
2654 qApp->d_func()->alertTimerHash.remove(widget);
2655 delete oldTimer;
2656 }
2657 qApp->d_func()->alertTimerHash.insert(widget, timer);
2658 timer->start(duration);
2659 }
2660 }
2661 }
2662 if (needNotification)
2663 qt_mac_send_notification();
2664}
2665
2666void QApplicationPrivate::_q_alertTimeOut()
2667{
2668 if (QTimer *timer = qobject_cast<QTimer *>(q_func()->sender())) {
2669 QHash<QWidget *, QTimer *>::iterator it = alertTimerHash.begin();
2670 while (it != alertTimerHash.end()) {
2671 if (it.value() == timer) {
2672 alertTimerHash.erase(it);
2673 timer->deleteLater();
2674 break;
2675 }
2676 ++it;
2677 }
2678 if (alertTimerHash.isEmpty()) {
2679 qt_mac_cancel_notification();
2680 }
2681 }
2682}
2683
2684void QApplication::setCursorFlashTime(int msecs)
2685{
2686 QApplicationPrivate::cursor_flash_time = msecs;
2687}
2688
2689int QApplication::cursorFlashTime()
2690{
2691 return QApplicationPrivate::cursor_flash_time;
2692}
2693
2694void QApplication::setDoubleClickInterval(int ms)
2695{
2696 qt_mac_dblclick.use_qt_time_limit = true;
2697 QApplicationPrivate::mouse_double_click_time = ms;
2698}
2699
2700int QApplication::doubleClickInterval()
2701{
2702 if (!qt_mac_dblclick.use_qt_time_limit) { //get it from the system
2703 QSettings appleSettings(QLatin1String("apple.com"));
2704 /* First worked as of 10.3.3 */
2705 double dci = appleSettings.value(QLatin1String("com/apple/mouse/doubleClickThreshold"), 0.5).toDouble();
2706 return int(dci * 1000);
2707 }
2708 return QApplicationPrivate::mouse_double_click_time;
2709}
2710
2711void QApplication::setKeyboardInputInterval(int ms)
2712{
2713 QApplicationPrivate::keyboard_input_time = ms;
2714}
2715
2716int QApplication::keyboardInputInterval()
2717{
2718 // FIXME: get from the system
2719 return QApplicationPrivate::keyboard_input_time;
2720}
2721
2722#ifndef QT_NO_WHEELEVENT
2723void QApplication::setWheelScrollLines(int n)
2724{
2725 QApplicationPrivate::wheel_scroll_lines = n;
2726}
2727
2728int QApplication::wheelScrollLines()
2729{
2730 return QApplicationPrivate::wheel_scroll_lines;
2731}
2732#endif
2733
2734void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
2735{
2736 switch (effect) {
2737 case Qt::UI_FadeMenu:
2738 QApplicationPrivate::fade_menu = enable;
2739 break;
2740 case Qt::UI_AnimateMenu:
2741 QApplicationPrivate::animate_menu = enable;
2742 break;
2743 case Qt::UI_FadeTooltip:
2744 QApplicationPrivate::fade_tooltip = enable;
2745 break;
2746 case Qt::UI_AnimateTooltip:
2747 QApplicationPrivate::animate_tooltip = enable;
2748 break;
2749 case Qt::UI_AnimateCombo:
2750 QApplicationPrivate::animate_combo = enable;
2751 break;
2752 case Qt::UI_AnimateToolBox:
2753 QApplicationPrivate::animate_toolbox = enable;
2754 break;
2755 case Qt::UI_General:
2756 QApplicationPrivate::fade_tooltip = true;
2757 break;
2758 default:
2759 QApplicationPrivate::animate_ui = enable;
2760 break;
2761 }
2762
2763 if (enable)
2764 QApplicationPrivate::animate_ui = true;
2765}
2766
2767bool QApplication::isEffectEnabled(Qt::UIEffect effect)
2768{
2769 if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui)
2770 return false;
2771
2772 switch(effect) {
2773 case Qt::UI_AnimateMenu:
2774 return QApplicationPrivate::animate_menu;
2775 case Qt::UI_FadeMenu:
2776 return QApplicationPrivate::fade_menu;
2777 case Qt::UI_AnimateCombo:
2778 return QApplicationPrivate::animate_combo;
2779 case Qt::UI_AnimateTooltip:
2780 return QApplicationPrivate::animate_tooltip;
2781 case Qt::UI_FadeTooltip:
2782 return QApplicationPrivate::fade_tooltip;
2783 case Qt::UI_AnimateToolBox:
2784 return QApplicationPrivate::animate_toolbox;
2785 default:
2786 break;
2787 }
2788 return QApplicationPrivate::animate_ui;
2789}
2790
2791/*!
2792 \internal
2793*/
2794bool QApplicationPrivate::qt_mac_apply_settings()
2795{
2796 QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
2797 settings.beginGroup(QLatin1String("Qt"));
2798
2799 /*
2800 Qt settings. This is how they are written into the datastream.
2801 Palette/ * - QPalette
2802 font - QFont
2803 libraryPath - QStringList
2804 style - QString
2805 doubleClickInterval - int
2806 cursorFlashTime - int
2807 wheelScrollLines - int
2808 colorSpec - QString
2809 defaultCodec - QString
2810 globalStrut/width - int
2811 globalStrut/height - int
2812 GUIEffects - QStringList
2813 Font Substitutions/ * - QStringList
2814 Font Substitutions/... - QStringList
2815 */
2816
2817 // read library (ie. plugin) path list
2818 QString libpathkey =
2819 QString::fromLatin1("%1.%2/libraryPath")
2820 .arg(QT_VERSION >> 16)
2821 .arg((QT_VERSION & 0xff00) >> 8);
2822 QStringList pathlist = settings.value(libpathkey).toString().split(QLatin1Char(':'));
2823 if (!pathlist.isEmpty()) {
2824 QStringList::ConstIterator it = pathlist.begin();
2825 while(it != pathlist.end())
2826 QApplication::addLibraryPath(*it++);
2827 }
2828
2829 QString defaultcodec = settings.value(QLatin1String("defaultCodec"), QVariant(QLatin1String("none"))).toString();
2830 if (defaultcodec != QLatin1String("none")) {
2831 QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1().constData());
2832 if (codec)
2833 QTextCodec::setCodecForTr(codec);
2834 }
2835
2836 if (qt_is_gui_used) {
2837 QString str;
2838 QStringList strlist;
2839 int num;
2840
2841 // read new palette
2842 int i;
2843 QPalette pal(QApplication::palette());
2844 strlist = settings.value(QLatin1String("Palette/active")).toStringList();
2845 if (strlist.count() == QPalette::NColorRoles) {
2846 for (i = 0; i < QPalette::NColorRoles; i++)
2847 pal.setColor(QPalette::Active, (QPalette::ColorRole) i,
2848 QColor(strlist[i]));
2849 }
2850 strlist = settings.value(QLatin1String("Palette/inactive")).toStringList();
2851 if (strlist.count() == QPalette::NColorRoles) {
2852 for (i = 0; i < QPalette::NColorRoles; i++)
2853 pal.setColor(QPalette::Inactive, (QPalette::ColorRole) i,
2854 QColor(strlist[i]));
2855 }
2856 strlist = settings.value(QLatin1String("Palette/disabled")).toStringList();
2857 if (strlist.count() == QPalette::NColorRoles) {
2858 for (i = 0; i < QPalette::NColorRoles; i++)
2859 pal.setColor(QPalette::Disabled, (QPalette::ColorRole) i,
2860 QColor(strlist[i]));
2861 }
2862
2863 if (pal != QApplication::palette())
2864 QApplication::setPalette(pal);
2865
2866 // read new font
2867 QFont font(QApplication::font());
2868 str = settings.value(QLatin1String("font")).toString();
2869 if (!str.isEmpty()) {
2870 font.fromString(str);
2871 if (font != QApplication::font())
2872 QApplication::setFont(font);
2873 }
2874
2875 // read new QStyle
2876 QString stylename = settings.value(QLatin1String("style")).toString();
2877 if (! stylename.isNull() && ! stylename.isEmpty()) {
2878 QStyle *style = QStyleFactory::create(stylename);
2879 if (style)
2880 QApplication::setStyle(style);
2881 else
2882 stylename = QLatin1String("default");
2883 } else {
2884 stylename = QLatin1String("default");
2885 }
2886
2887 num = settings.value(QLatin1String("doubleClickInterval"),
2888 QApplication::doubleClickInterval()).toInt();
2889 QApplication::setDoubleClickInterval(num);
2890
2891 num = settings.value(QLatin1String("cursorFlashTime"),
2892 QApplication::cursorFlashTime()).toInt();
2893 QApplication::setCursorFlashTime(num);
2894
2895#ifndef QT_NO_WHEELEVENT
2896 num = settings.value(QLatin1String("wheelScrollLines"),
2897 QApplication::wheelScrollLines()).toInt();
2898 QApplication::setWheelScrollLines(num);
2899#endif
2900
2901 QString colorspec = settings.value(QLatin1String("colorSpec"),
2902 QVariant(QLatin1String("default"))).toString();
2903 if (colorspec == QLatin1String("normal"))
2904 QApplication::setColorSpec(QApplication::NormalColor);
2905 else if (colorspec == QLatin1String("custom"))
2906 QApplication::setColorSpec(QApplication::CustomColor);
2907 else if (colorspec == QLatin1String("many"))
2908 QApplication::setColorSpec(QApplication::ManyColor);
2909 else if (colorspec != QLatin1String("default"))
2910 colorspec = QLatin1String("default");
2911
2912 int w = settings.value(QLatin1String("globalStrut/width")).toInt();
2913 int h = settings.value(QLatin1String("globalStrut/height")).toInt();
2914 QSize strut(w, h);
2915 if (strut.isValid())
2916 QApplication::setGlobalStrut(strut);
2917
2918 QStringList effects = settings.value(QLatin1String("GUIEffects")).toStringList();
2919 if (!effects.isEmpty()) {
2920 if (effects.contains(QLatin1String("none")))
2921 QApplication::setEffectEnabled(Qt::UI_General, false);
2922 if (effects.contains(QLatin1String("general")))
2923 QApplication::setEffectEnabled(Qt::UI_General, true);
2924 if (effects.contains(QLatin1String("animatemenu")))
2925 QApplication::setEffectEnabled(Qt::UI_AnimateMenu, true);
2926 if (effects.contains(QLatin1String("fademenu")))
2927 QApplication::setEffectEnabled(Qt::UI_FadeMenu, true);
2928 if (effects.contains(QLatin1String("animatecombo")))
2929 QApplication::setEffectEnabled(Qt::UI_AnimateCombo, true);
2930 if (effects.contains(QLatin1String("animatetooltip")))
2931 QApplication::setEffectEnabled(Qt::UI_AnimateTooltip, true);
2932 if (effects.contains(QLatin1String("fadetooltip")))
2933 QApplication::setEffectEnabled(Qt::UI_FadeTooltip, true);
2934 if (effects.contains(QLatin1String("animatetoolbox")))
2935 QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, true);
2936 } else {
2937 QApplication::setEffectEnabled(Qt::UI_General, true);
2938 }
2939
2940 settings.beginGroup(QLatin1String("Font Substitutions"));
2941 QStringList fontsubs = settings.childKeys();
2942 if (!fontsubs.isEmpty()) {
2943 QStringList::Iterator it = fontsubs.begin();
2944 for (; it != fontsubs.end(); ++it) {
2945 QString fam = QString::fromLatin1((*it).toLatin1().constData());
2946 QStringList subs = settings.value(fam).toStringList();
2947 QFont::insertSubstitutions(fam, subs);
2948 }
2949 }
2950 settings.endGroup();
2951 }
2952
2953 settings.endGroup();
2954 return true;
2955}
2956
2957// DRSWAT
2958
2959bool QApplicationPrivate::canQuit()
2960{
2961#ifndef QT_MAC_USE_COCOA
2962 return true;
2963#else
2964 Q_Q(QApplication);
2965#ifdef QT_MAC_USE_COCOA
2966 [[NSApp mainMenu] cancelTracking];
2967#else
2968 HiliteMenu(0);
2969#endif
2970
2971 bool handle_quit = true;
2972 if (QApplicationPrivate::modalState() && [[[[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate]
2973 menuLoader] quitMenuItem] isEnabled]) {
2974 int visible = 0;
2975 const QWidgetList tlws = QApplication::topLevelWidgets();
2976 for(int i = 0; i < tlws.size(); ++i) {
2977 if (tlws.at(i)->isVisible())
2978 ++visible;
2979 }
2980 handle_quit = (visible <= 1);
2981 }
2982 if (handle_quit) {
2983 QCloseEvent ev;
2984 QApplication::sendSpontaneousEvent(q, &ev);
2985 if (ev.isAccepted()) {
2986 return true;
2987 }
2988 }
2989 return false;
2990#endif
2991}
2992
2993void onApplicationWindowChangedActivation(QWidget *widget, bool activated)
2994{
2995#if QT_MAC_USE_COCOA
2996 if (!widget)
2997 return;
2998
2999 if (activated) {
3000 if (QApplicationPrivate::app_style) {
3001 QEvent ev(QEvent::Style);
3002 qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev);
3003 }
3004 qApp->setActiveWindow(widget);
3005 } else { // deactivated
3006 if (QApplicationPrivate::active_window == widget)
3007 qApp->setActiveWindow(0);
3008 }
3009
3010 QMenuBar::macUpdateMenuBar();
3011
3012#else
3013 Q_UNUSED(widget);
3014 Q_UNUSED(activated);
3015#endif
3016}
3017
3018
3019void onApplicationChangedActivation( bool activated )
3020{
3021#if QT_MAC_USE_COCOA
3022 QApplication *app = qApp;
3023
3024//NSLog(@"App Changed Activation\n");
3025
3026 if ( activated ) {
3027 if (QApplication::desktopSettingsAware())
3028 qt_mac_update_os_settings();
3029
3030 if (qt_clipboard) { //manufacture an event so the clipboard can see if it has changed
3031 QEvent ev(QEvent::Clipboard);
3032 qt_sendSpontaneousEvent(qt_clipboard, &ev);
3033 }
3034
3035 if (app) {
3036 QEvent ev(QEvent::ApplicationActivate);
3037 qt_sendSpontaneousEvent(app, &ev);
3038 }
3039
3040 if (!app->activeWindow()) {
3041#if QT_MAC_USE_COCOA
3042 OSWindowRef wp = [NSApp keyWindow];
3043#else
3044 OSWindowRef wp = ActiveNonFloatingWindow();
3045#endif
3046 if (QWidget *tmp_w = qt_mac_find_window(wp))
3047 app->setActiveWindow(tmp_w);
3048 }
3049 QMenuBar::macUpdateMenuBar();
3050 } else { // de-activated
3051 QApplicationPrivate *priv = [[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] qAppPrivate];
3052 while (priv->inPopupMode())
3053 app->activePopupWidget()->close();
3054 if (app) {
3055 QEvent ev(QEvent::ApplicationDeactivate);
3056 qt_sendSpontaneousEvent(app, &ev);
3057 }
3058 app->setActiveWindow(0);
3059 }
3060#else
3061 Q_UNUSED(activated);
3062#endif
3063}
3064
3065void QApplicationPrivate::initializeMultitouch_sys()
3066{ }
3067void QApplicationPrivate::cleanupMultitouch_sys()
3068{ }
3069
3070QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.