Warning: That file was not part of the compilation database. It may have many parsing errors.

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

Warning: That file was not part of the compilation database. It may have many parsing errors.