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

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

trunk: Merged in qt 4.6.1 sources.

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