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

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

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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