diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2011-05-07 00:02:01 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@nokia.com> | 2011-05-07 00:02:01 +0200 |
commit | f67b8df3ebdba2d398b9cce686b7c644adffff08 (patch) | |
tree | 062dd469f7cf8daa01a32d3e7b767b8fbdb7573a /src/gui/platforms/mac | |
parent | 32ce4fe9e6a94e77828e976776cf08da85254ff2 (diff) |
library split
Diffstat (limited to 'src/gui/platforms/mac')
61 files changed, 0 insertions, 32377 deletions
diff --git a/src/gui/platforms/mac/qapplication_mac.mm b/src/gui/platforms/mac/qapplication_mac.mm deleted file mode 100644 index f607a72e92..0000000000 --- a/src/gui/platforms/mac/qapplication_mac.mm +++ /dev/null @@ -1,3134 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -#include <Cocoa/Cocoa.h> - -#include "qapplication.h" -#include "qbitarray.h" -#include "qclipboard.h" -#include "qcursor.h" -#include "qdatastream.h" -#include "qdatetime.h" -#include "qdesktopwidget.h" -#include "qdockwidget.h" -#include "qevent.h" -#include "qhash.h" -#include "qlayout.h" -#include "qmenubar.h" -#include "qmessagebox.h" -#include "qmime.h" -#include "qpixmapcache.h" -#include "qpointer.h" -#include "qsessionmanager.h" -#include "qsettings.h" -#include "qsocketnotifier.h" -#include "qstyle.h" -#include "qstylefactory.h" -#include "qtextcodec.h" -#include "qtoolbar.h" -#include "qvariant.h" -#include "qwidget.h" -#include "qcolormap.h" -#include "qdir.h" -#include "qdebug.h" -#include "qtimer.h" -#include "qurl.h" -#include "private/qmacinputcontext_p.h" -#include "private/qpaintengine_mac_p.h" -#include "private/qcursor_p.h" -#include "private/qapplication_p.h" -#include "private/qcolor_p.h" -#include "private/qwidget_p.h" -#include "private/qkeymapper_p.h" -#include "private/qeventdispatcher_mac_p.h" -#include "private/qeventdispatcher_unix_p.h" -#include <private/qcocoamenuloader_mac_p.h> -#include <private/qcocoaapplication_mac_p.h> -#include <private/qcocoaapplicationdelegate_mac_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#include <private/qcocoawindow_mac_p.h> -#include <private/qpixmap_mac_p.h> -#include <private/qdesktopwidget_mac_p.h> -#include <private/qeventdispatcher_mac_p.h> -#include <qvarlengtharray.h> - -#ifndef QT_NO_ACCESSIBILITY -# include "qaccessible.h" -#endif - -#ifndef QT_NO_THREAD -# include "qmutex.h" -#endif - -#include <unistd.h> -#include <string.h> -#include <sys/time.h> -#include <sys/select.h> - -/***************************************************************************** - QApplication debug facilities - *****************************************************************************/ -//#define DEBUG_EVENTS //like EventDebug but more specific to Qt -//#define DEBUG_DROPPED_EVENTS -//#define DEBUG_MOUSE_MAPS -//#define DEBUG_MODAL_EVENTS -//#define DEBUG_PLATFORM_SETTINGS - -#define QMAC_SPEAK_TO_ME -#ifdef QMAC_SPEAK_TO_ME -#include "qregexp.h" -#endif - -#ifndef kThemeBrushAlternatePrimaryHighlightColor -#define kThemeBrushAlternatePrimaryHighlightColor -5 -#endif - -#define kCMDeviceUnregisteredNotification CFSTR("CMDeviceUnregisteredNotification") -#define kCMDefaultDeviceNotification CFSTR("CMDefaultDeviceNotification") -#define kCMDeviceProfilesNotification CFSTR("CMDeviceProfilesNotification") -#define kCMDefaultDeviceProfileNotification CFSTR("CMDefaultDeviceProfileNotification") - -QT_BEGIN_NAMESPACE - -//for qt_mac.h -QPaintDevice *qt_mac_safe_pdev = 0; -QList<QMacWindowChangeEvent*> *QMacWindowChangeEvent::change_events = 0; -QPointer<QWidget> topLevelAt_cache = 0; - -/***************************************************************************** - Internal variables and functions - *****************************************************************************/ -static struct { - bool use_qt_time_limit; - QPointer<QWidget> last_widget; - int last_x, last_y; - int last_modifiers, last_button; - EventTime last_time; -} qt_mac_dblclick = { false, 0, -1, -1, 0, 0, -2 }; - -static bool app_do_modal = false; // modal mode -extern QWidgetList *qt_modal_stack; // stack of modal widgets -extern bool qt_tab_all_widgets; // from qapplication.cpp -bool qt_mac_app_fullscreen = false; -bool qt_scrollbar_jump_to_pos = false; -static bool qt_mac_collapse_on_dblclick = true; -extern int qt_antialiasing_threshold; // from qapplication.cpp -QWidget * qt_button_down; // widget got last button-down -QPointer<QWidget> qt_last_mouse_receiver; -#ifndef QT_MAC_USE_COCOA -static bool qt_button_down_in_content; // whether the button_down was in the content area. -static bool qt_mac_previous_press_in_popup_mode = false; -static bool qt_mac_no_click_through_mode = false; -static int tablet_button_state = 0; -#endif -#if defined(QT_DEBUG) -static bool appNoGrab = false; // mouse/keyboard grabbing -#endif -#ifndef QT_MAC_USE_COCOA -static EventHandlerRef app_proc_handler = 0; -static EventHandlerUPP app_proc_handlerUPP = 0; -#endif -static AEEventHandlerUPP app_proc_ae_handlerUPP = NULL; -static EventHandlerRef tablet_proximity_handler = 0; -static EventHandlerUPP tablet_proximity_UPP = 0; -bool QApplicationPrivate::native_modal_dialog_active; - -Q_GUI_EXPORT bool qt_applefontsmoothing_enabled; - -/***************************************************************************** - External functions - *****************************************************************************/ -extern void qt_mac_beep(); //qsound_mac.mm -extern Qt::KeyboardModifiers qt_mac_get_modifiers(int keys); //qkeymapper_mac.cpp -extern bool qt_mac_can_clickThrough(const QWidget *); //qwidget_mac.cpp -extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp -extern OSWindowRef qt_mac_window_for(const QWidget*); //qwidget_mac.cpp -extern QWidget *qt_mac_find_window(OSWindowRef); //qwidget_mac.cpp -extern void qt_mac_set_cursor(const QCursor *); //qcursor_mac.cpp -extern bool qt_mac_is_macsheet(const QWidget *); //qwidget_mac.cpp -extern QString qt_mac_from_pascal_string(const Str255); //qglobal.cpp -extern void qt_mac_command_set_enabled(MenuRef, UInt32, bool); //qmenu_mac.cpp -extern bool qt_sendSpontaneousEvent(QObject *obj, QEvent *event); // qapplication.cpp -extern void qt_mac_update_cursor(); // qcursor_mac.mm - -// Forward Decls -void onApplicationWindowChangedActivation( QWidget*widget, bool activated ); -void onApplicationChangedActivation( bool activated ); - -static void qt_mac_read_fontsmoothing_settings() -{ - qt_applefontsmoothing_enabled = true; - int w = 10, h = 10; - QImage image(w, h, QImage::Format_RGB32); - image.fill(0xffffffff); - QPainter p(&image); - p.drawText(0, h, "X\\"); - p.end(); - - const int *bits = (const int *) ((const QImage &) image).bits(); - int bpl = image.bytesPerLine() / 4; - for (int y=0; y<w; ++y) { - for (int x=0; x<h; ++x) { - int r = qRed(bits[x]); - int g = qGreen(bits[x]); - int b = qBlue(bits[x]); - if (r != g || r != b) { - qt_applefontsmoothing_enabled = true; - return; - } - } - bits += bpl; - } - qt_applefontsmoothing_enabled = false; -} - -Q_GUI_EXPORT bool qt_mac_execute_apple_script(const char *script, long script_len, AEDesc *ret) { - OSStatus err; - AEDesc scriptTextDesc; - ComponentInstance theComponent = 0; - OSAID scriptID = kOSANullScript, resultID = kOSANullScript; - - // set up locals to a known state - AECreateDesc(typeNull, 0, 0, &scriptTextDesc); - scriptID = kOSANullScript; - resultID = kOSANullScript; - - // open the scripting component - theComponent = OpenDefaultComponent(kOSAComponentType, typeAppleScript); - if (!theComponent) { - err = paramErr; - goto bail; - } - - // put the script text into an aedesc - err = AECreateDesc(typeUTF8Text, script, script_len, &scriptTextDesc); - if (err != noErr) - goto bail; - - // compile the script - err = OSACompile(theComponent, &scriptTextDesc, kOSAModeNull, &scriptID); - if (err != noErr) - goto bail; - - // run the script - err = OSAExecute(theComponent, scriptID, kOSANullScript, kOSAModeNull, &resultID); - - // collect the results - if any - if (ret) { - AECreateDesc(typeNull, 0, 0, ret); - if (err == errOSAScriptError) - OSAScriptError(theComponent, kOSAErrorMessage, typeChar, ret); - else if (err == noErr && resultID != kOSANullScript) - OSADisplay(theComponent, resultID, typeChar, kOSAModeNull, ret); - } -bail: - AEDisposeDesc(&scriptTextDesc); - if (scriptID != kOSANullScript) - OSADispose(theComponent, scriptID); - if (resultID != kOSANullScript) - OSADispose(theComponent, resultID); - if (theComponent) - CloseComponent(theComponent); - return err == noErr; -} - -Q_GUI_EXPORT bool qt_mac_execute_apple_script(const char *script, AEDesc *ret) -{ - return qt_mac_execute_apple_script(script, qstrlen(script), ret); -} - -Q_GUI_EXPORT bool qt_mac_execute_apple_script(const QString &script, AEDesc *ret) -{ - const QByteArray l = script.toUtf8(); return qt_mac_execute_apple_script(l.constData(), l.size(), ret); -} - -/* Resolution change magic */ -void qt_mac_display_change_callbk(CGDirectDisplayID, CGDisplayChangeSummaryFlags flags, void *) -{ -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - const bool resized = flags & kCGDisplayDesktopShapeChangedFlag; -#else - Q_UNUSED(flags); - const bool resized = true; -#endif - if (resized && qApp) { - if (QDesktopWidget *dw = qApp->desktop()) { - QResizeEvent *re = new QResizeEvent(dw->size(), dw->size()); - QApplication::postEvent(dw, re); - QCoreGraphicsPaintEngine::cleanUpMacColorSpaces(); - } - } -} - -#ifdef DEBUG_PLATFORM_SETTINGS -static void qt_mac_debug_palette(const QPalette &pal, const QPalette &pal2, const QString &where) -{ - const char *const groups[] = {"Active", "Disabled", "Inactive" }; - const char *const roles[] = { "WindowText", "Button", "Light", "Midlight", "Dark", "Mid", - "Text", "BrightText", "ButtonText", "Base", "Window", "Shadow", - "Highlight", "HighlightedText", "Link", "LinkVisited" }; - if (!where.isNull()) - qDebug("qt-internal: %s", where.toLatin1().constData()); - for(int grp = 0; grp < QPalette::NColorGroups; grp++) { - for(int role = 0; role < QPalette::NColorRoles; role++) { - QBrush b = pal.brush((QPalette::ColorGroup)grp, (QPalette::ColorRole)role); - QPixmap pm = b.texture(); - qDebug(" %s::%s %d::%d::%d [%p]%s", groups[grp], roles[role], b.color().red(), - b.color().green(), b.color().blue(), pm.isNull() ? 0 : &pm, - pal2.brush((QPalette::ColorGroup)grp, (QPalette::ColorRole)role) != b ? " (*)" : ""); - } - } - -} -#else -#define qt_mac_debug_palette(x, y, z) -#endif - -//raise a notification -#ifndef QT_MAC_USE_COCOA -static NMRec qt_mac_notification = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -#endif -void qt_mac_send_notification() -{ -#ifndef QT_MAC_USE_COCOA - //send it - qt_mac_notification.nmMark = 1; //non-zero magic number - qt_mac_notification.qType = nmType; - NMInstall(&qt_mac_notification); -#else - QMacCocoaAutoReleasePool pool; - [[NSApplication sharedApplication] requestUserAttention:NSInformationalRequest]; -#endif -} - -void qt_mac_cancel_notification() -{ -#ifndef QT_MAC_USE_COCOA - NMRemove(&qt_mac_notification); -#else - QMacCocoaAutoReleasePool pool; - [[NSApplication sharedApplication] cancelUserAttentionRequest:NSInformationalRequest]; -#endif -} - -#ifndef QT_MAC_USE_COCOA -//find widget (and part) at a given point -static short qt_mac_window_at(int x, int y, QWidget **w=0) -{ - Point p; - p.h = x; - p.v = y; - OSWindowRef wp; - WindowPartCode wpc; - OSStatus err = FindWindowOfClass(&p, kAllWindowClasses, &wp, &wpc); - if(err != noErr) { - if(w) - (*w) = 0; - return wpc; - } - if(w) { - if(wp) { - *w = qt_mac_find_window(wp); -#if 0 - if(!*w) - qWarning("QApplication: qt_mac_window_at: Couldn't find %d",(int)wp); -#endif - } else { - *w = 0; - } - } - return wpc; -} - -#endif - -void qt_mac_set_app_icon(const QPixmap &pixmap) -{ -#ifndef QT_MAC_USE_COCOA - if(pixmap.isNull()) { - RestoreApplicationDockTileImage(); - } else { - CGImageRef img = (CGImageRef)pixmap.macCGHandle(); - SetApplicationDockTileImage(img); - CGImageRelease(img); - } -#else - QMacCocoaAutoReleasePool pool; - NSImage *image = NULL; - if (pixmap.isNull()) { - // Get Application icon from bundle - image = [[NSImage imageNamed:@"NSApplicationIcon"] retain]; // released below - } else { - image = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap)); - } - - [NSApp setApplicationIconImage:image]; - [image release]; -#endif -} - -Q_GUI_EXPORT void qt_mac_set_press_and_hold_context(bool b) -{ - Q_UNUSED(b); - qWarning("qt_mac_set_press_and_hold_context: This functionality is no longer available"); -} - -bool qt_nograb() // application no-grab option -{ -#if defined(QT_DEBUG) - return appNoGrab; -#else - return false; -#endif -} - -void qt_mac_update_os_settings() -{ - if (!qApp) - return; - if (!QApplication::startingUp()) { - static bool needToPolish = true; - if (needToPolish) { - QApplication::style()->polish(qApp); - needToPolish = false; - } - } - //focus mode - /* First worked as of 10.2.3 */ - QSettings appleSettings(QLatin1String("apple.com")); - QVariant appleValue = appleSettings.value(QLatin1String("AppleKeyboardUIMode"), 0); - qt_tab_all_widgets = (appleValue.toInt() & 0x2); - //paging mode - /* First worked as of 10.2.3 */ - appleValue = appleSettings.value(QLatin1String("AppleScrollerPagingBehavior"), false); - qt_scrollbar_jump_to_pos = appleValue.toBool(); - //collapse - /* First worked as of 10.3.3 */ - appleValue = appleSettings.value(QLatin1String("AppleMiniaturizeOnDoubleClick"), true); - qt_mac_collapse_on_dblclick = appleValue.toBool(); - - // Anti-aliasing threshold - appleValue = appleSettings.value(QLatin1String("AppleAntiAliasingThreshold")); - if (appleValue.isValid()) - qt_antialiasing_threshold = appleValue.toInt(); - -#ifdef DEBUG_PLATFORM_SETTINGS - qDebug("qt_mac_update_os_settings *********************************************************************"); -#endif - { // setup the global palette - QColor qc; - (void) QApplication::style(); // trigger creation of application style and system palettes - QPalette pal = *QApplicationPrivate::sys_pal; - - pal.setBrush( QPalette::Active, QPalette::Highlight, qcolorForTheme(kThemeBrushPrimaryHighlightColor) ); - pal.setBrush( QPalette::Inactive, QPalette::Highlight, qcolorForTheme(kThemeBrushSecondaryHighlightColor) ); - - pal.setBrush( QPalette::Disabled, QPalette::Highlight, qcolorForTheme(kThemeBrushSecondaryHighlightColor) ); - pal.setBrush( QPalette::Active, QPalette::Shadow, qcolorForTheme(kThemeBrushButtonActiveDarkShadow) ); - - pal.setBrush( QPalette::Inactive, QPalette::Shadow, qcolorForTheme(kThemeBrushButtonInactiveDarkShadow) ); - pal.setBrush( QPalette::Disabled, QPalette::Shadow, qcolorForTheme(kThemeBrushButtonInactiveDarkShadow) ); - - qc = qcolorForThemeTextColor(kThemeTextColorDialogActive); - pal.setColor(QPalette::Active, QPalette::Text, qc); - pal.setColor(QPalette::Active, QPalette::WindowText, qc); - pal.setColor(QPalette::Active, QPalette::HighlightedText, qc); - - qc = qcolorForThemeTextColor(kThemeTextColorDialogInactive); - pal.setColor(QPalette::Inactive, QPalette::Text, qc); - pal.setColor(QPalette::Inactive, QPalette::WindowText, qc); - pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc); - pal.setColor(QPalette::Disabled, QPalette::Text, qc); - pal.setColor(QPalette::Disabled, QPalette::WindowText, qc); - pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc); - pal.setBrush(QPalette::ToolTipBase, QColor(255, 255, 199)); - - if (!QApplicationPrivate::sys_pal || *QApplicationPrivate::sys_pal != pal) { - QApplicationPrivate::setSystemPalette(pal); - QApplication::setPalette(pal); - } -#ifdef DEBUG_PLATFORM_SETTINGS - qt_mac_debug_palette(pal, QApplication::palette(), "Global Palette"); -#endif - } - - QFont fnt = qfontForThemeFont(kThemeApplicationFont); -#ifdef DEBUG_PLATFORM_SETTINGS - qDebug("qt-internal: Font for Application [%s::%d::%d::%d]", - fnt.family().toLatin1().constData(), fnt.pointSize(), fnt.bold(), fnt.italic()); -#endif - if (!QApplicationPrivate::sys_font || *QApplicationPrivate::sys_font != fnt) - QApplicationPrivate::setSystemFont(fnt); - - { //setup the fonts - struct FontMap { - FontMap(const char *qc, short fk) : qt_class(qc), font_key(fk) { } - const char *const qt_class; - short font_key; - } mac_widget_fonts[] = { - FontMap("QPushButton", kThemePushButtonFont), - FontMap("QListView", kThemeViewsFont), - FontMap("QListBox", kThemeViewsFont), - FontMap("QTitleBar", kThemeWindowTitleFont), - FontMap("QMenuBar", kThemeMenuTitleFont), - FontMap("QMenu", kThemeMenuItemFont), - FontMap("QComboMenuItem", kThemeSystemFont), - FontMap("QHeaderView", kThemeSmallSystemFont), - FontMap("Q3Header", kThemeSmallSystemFont), - FontMap("QTipLabel", kThemeSmallSystemFont), - FontMap("QLabel", kThemeSystemFont), - FontMap("QToolButton", kThemeSmallSystemFont), - FontMap("QMenuItem", kThemeMenuItemFont), // It doesn't exist, but its unique. - FontMap("QComboLineEdit", kThemeViewsFont), // It doesn't exist, but its unique. - FontMap("QSmallFont", kThemeSmallSystemFont), // It doesn't exist, but its unique. - FontMap("QMiniFont", kThemeMiniSystemFont), // It doesn't exist, but its unique. - FontMap(0, 0) }; - for(int i = 0; mac_widget_fonts[i].qt_class; i++) { - QFont fnt = qfontForThemeFont(mac_widget_fonts[i].font_key); - bool set_font = true; - FontHash *hash = qt_app_fonts_hash(); - if (!hash->isEmpty()) { - FontHash::const_iterator it - = hash->constFind(mac_widget_fonts[i].qt_class); - if (it != hash->constEnd()) - set_font = (fnt != *it); - } - if (set_font) { - QApplication::setFont(fnt, mac_widget_fonts[i].qt_class); -#ifdef DEBUG_PLATFORM_SETTINGS - qDebug("qt-internal: Font for %s [%s::%d::%d::%d]", mac_widget_fonts[i].qt_class, - fnt.family().toLatin1().constData(), fnt.pointSize(), fnt.bold(), fnt.italic()); -#endif - } - } - } - QApplicationPrivate::initializeWidgetPaletteHash(); -#ifdef DEBUG_PLATFORM_SETTINGS - qDebug("qt_mac_update_os_settings END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); -#endif -} - -void QApplicationPrivate::initializeWidgetPaletteHash() -{ - { //setup the palette - struct PaletteMap { - inline PaletteMap(const char *qc, ThemeBrush a, ThemeBrush i) : - qt_class(qc), active(a), inactive(i) { } - const char *const qt_class; - ThemeBrush active, inactive; - } mac_widget_colors[] = { - PaletteMap("QToolButton", kThemeTextColorBevelButtonActive, kThemeTextColorBevelButtonInactive), - PaletteMap("QAbstractButton", kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive), - PaletteMap("QHeaderView", kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive), - PaletteMap("Q3Header", kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive), - PaletteMap("QComboBox", kThemeTextColorPopupButtonActive, kThemeTextColorPopupButtonInactive), - PaletteMap("QAbstractItemView", kThemeTextColorListView, kThemeTextColorDialogInactive), - PaletteMap("QMessageBoxLabel", kThemeTextColorAlertActive, kThemeTextColorAlertInactive), - PaletteMap("QTabBar", kThemeTextColorTabFrontActive, kThemeTextColorTabFrontInactive), - PaletteMap("QLabel", kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive), - PaletteMap("QGroupBox", kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive), - PaletteMap("QMenu", kThemeTextColorPopupLabelActive, kThemeTextColorPopupLabelInactive), - PaletteMap("QTextEdit", 0, 0), - PaletteMap("QTextControl", 0, 0), - PaletteMap("QLineEdit", 0, 0), - PaletteMap(0, 0, 0) }; - QColor qc; - for(int i = 0; mac_widget_colors[i].qt_class; i++) { - QPalette pal; - if (mac_widget_colors[i].active != 0) { - qc = qcolorForThemeTextColor(mac_widget_colors[i].active); - pal.setColor(QPalette::Active, QPalette::Text, qc); - pal.setColor(QPalette::Active, QPalette::WindowText, qc); - pal.setColor(QPalette::Active, QPalette::HighlightedText, qc); - qc = qcolorForThemeTextColor(mac_widget_colors[i].inactive); - pal.setColor(QPalette::Inactive, QPalette::Text, qc); - pal.setColor(QPalette::Disabled, QPalette::Text, qc); - pal.setColor(QPalette::Inactive, QPalette::WindowText, qc); - pal.setColor(QPalette::Disabled, QPalette::WindowText, qc); - pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc); - pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc); - } - if (!strcmp(mac_widget_colors[i].qt_class, "QMenu")) { - qc = qcolorForThemeTextColor(kThemeTextColorMenuItemActive); - pal.setBrush(QPalette::ButtonText, qc); - qc = qcolorForThemeTextColor(kThemeTextColorMenuItemSelected); - pal.setBrush(QPalette::HighlightedText, qc); - qc = qcolorForThemeTextColor(kThemeTextColorMenuItemDisabled); - pal.setBrush(QPalette::Disabled, QPalette::Text, qc); - } else if (!strcmp(mac_widget_colors[i].qt_class, "QAbstractButton") - || !strcmp(mac_widget_colors[i].qt_class, "QHeaderView") - || !strcmp(mac_widget_colors[i].qt_class, "Q3Header")) { //special - pal.setColor(QPalette::Disabled, QPalette::ButtonText, - pal.color(QPalette::Disabled, QPalette::Text)); - pal.setColor(QPalette::Inactive, QPalette::ButtonText, - pal.color(QPalette::Inactive, QPalette::Text)); - pal.setColor(QPalette::Active, QPalette::ButtonText, - pal.color(QPalette::Active, QPalette::Text)); - } else if (!strcmp(mac_widget_colors[i].qt_class, "QAbstractItemView")) { - pal.setBrush(QPalette::Active, QPalette::Highlight, - qcolorForTheme(kThemeBrushAlternatePrimaryHighlightColor)); - qc = qcolorForThemeTextColor(kThemeTextColorMenuItemSelected); - pal.setBrush(QPalette::Active, QPalette::HighlightedText, qc); -#if 1 - pal.setBrush(QPalette::Inactive, QPalette::Text, - pal.brush(QPalette::Active, QPalette::Text)); - pal.setBrush(QPalette::Inactive, QPalette::HighlightedText, - pal.brush(QPalette::Active, QPalette::Text)); -#endif - } else if (!strcmp(mac_widget_colors[i].qt_class, "QTextEdit") - || !strcmp(mac_widget_colors[i].qt_class, "QTextControl")) { - pal.setBrush(QPalette::Inactive, QPalette::Text, - pal.brush(QPalette::Active, QPalette::Text)); - pal.setBrush(QPalette::Inactive, QPalette::HighlightedText, - pal.brush(QPalette::Active, QPalette::Text)); - } else if (!strcmp(mac_widget_colors[i].qt_class, "QLineEdit")) { - pal.setBrush(QPalette::Disabled, QPalette::Base, - pal.brush(QPalette::Active, QPalette::Base)); - } - - bool set_palette = true; - PaletteHash *phash = qt_app_palettes_hash(); - if (!phash->isEmpty()) { - PaletteHash::const_iterator it - = phash->constFind(mac_widget_colors[i].qt_class); - if (it != phash->constEnd()) - set_palette = (pal != *it); - } - if (set_palette) { - QApplication::setPalette(pal, mac_widget_colors[i].qt_class); -#ifdef DEBUG_PLATFORM_SETTINGS - qt_mac_debug_palette(pal, QApplication::palette(), QLatin1String("Palette for ") + QString::fromLatin1(mac_widget_colors[i].qt_class)); -#endif - } - } - } -} - -static void qt_mac_event_release(EventRef &event) -{ - ReleaseEvent(event); - event = 0; -} -#ifndef QT_MAC_USE_COCOA -static void qt_mac_event_release(QWidget *w, EventRef &event) -{ - if (event) { - QWidget *widget = 0; - if (GetEventParameter(event, kEventParamQWidget, typeQWidget, 0, sizeof(widget), 0, &widget) == noErr - && w == widget) { - if (IsEventInQueue(GetMainEventQueue(), event)) - RemoveEventFromQueue(GetMainEventQueue(), event); - qt_mac_event_release(event); - } - } -} - -static bool qt_mac_event_remove(EventRef &event) -{ - if (event) { - if (IsEventInQueue(GetMainEventQueue(), event)) - RemoveEventFromQueue(GetMainEventQueue(), event); - qt_mac_event_release(event); - return true; - } - return false; -} -#endif - -/* sheets */ -#ifndef QT_MAC_USE_COCOA -static EventRef request_showsheet_pending = 0; -#endif -void qt_event_request_showsheet(QWidget *w) -{ - Q_ASSERT(qt_mac_is_macsheet(w)); -#ifdef QT_MAC_USE_COCOA - [NSApp beginSheet:qt_mac_window_for(w) modalForWindow:qt_mac_window_for(w->parentWidget()) - modalDelegate:nil didEndSelector:nil contextInfo:0]; -#else - qt_mac_event_remove(request_showsheet_pending); - CreateEvent(0, kEventClassQt, kEventQtRequestShowSheet, GetCurrentEventTime(), - kEventAttributeUserEvent, &request_showsheet_pending); - SetEventParameter(request_showsheet_pending, kEventParamQWidget, typeQWidget, sizeof(w), &w); - PostEventToQueue(GetMainEventQueue(), request_showsheet_pending, kEventPriorityStandard); -#endif -} - -static void qt_post_window_change_event(QWidget *widget) -{ - qt_widget_private(widget)->needWindowChange = true; - QEvent *glWindowChangeEvent = new QEvent(QEvent::MacGLWindowChange); - QApplication::postEvent(widget, glWindowChangeEvent); -} - -/* - Posts updates to all child and grandchild OpenGL widgets for the given widget. -*/ -static void qt_mac_update_child_gl_widgets(QWidget *widget) -{ - // Update all OpenGL child widgets for the given widget. - QList<QWidgetPrivate::GlWidgetInfo> &glWidgets = qt_widget_private(widget)->glWidgets; - QList<QWidgetPrivate::GlWidgetInfo>::iterator end = glWidgets.end(); - QList<QWidgetPrivate::GlWidgetInfo>::iterator it = glWidgets.begin(); - - for (;it != end; ++it) { - qt_post_window_change_event(it->widget); - } -} - -/* - Sends updates to all child and grandchild gl widgets that have updates pending. -*/ -void qt_mac_send_posted_gl_updates(QWidget *widget) -{ - QList<QWidgetPrivate::GlWidgetInfo> &glWidgets = qt_widget_private(widget)->glWidgets; - QList<QWidgetPrivate::GlWidgetInfo>::iterator end = glWidgets.end(); - QList<QWidgetPrivate::GlWidgetInfo>::iterator it = glWidgets.begin(); - - for (;it != end; ++it) { - QWidget *glWidget = it->widget; - if (qt_widget_private(glWidget)->needWindowChange) { - QEvent glChangeEvent(QEvent::MacGLWindowChange); - QApplication::sendEvent(glWidget, &glChangeEvent); - } - } -} - -/* - Posts updates to all OpenGL widgets within the window that the given widget intersects. -*/ -static void qt_mac_update_intersected_gl_widgets(QWidget *widget) -{ -#ifndef QT_MAC_USE_COCOA - QList<QWidgetPrivate::GlWidgetInfo> &glWidgets = qt_widget_private(widget->window())->glWidgets; - if (glWidgets.isEmpty()) - return; - - // Exit if the window has not been created yet (mapToGlobal/size will force create it) - if (widget->testAttribute(Qt::WA_WState_Created) == false || HIViewGetWindow(qt_mac_nativeview_for(widget)) == 0) - return; - - const QRect globalWidgetRect = QRect(widget->mapToGlobal(QPoint(0, 0)), widget->size()); - - QList<QWidgetPrivate::GlWidgetInfo>::iterator end = glWidgets.end(); - QList<QWidgetPrivate::GlWidgetInfo>::iterator it = glWidgets.begin(); - - for (;it != end; ++it){ - QWidget *glWidget = it->widget; - const QRect globalGlWidgetRect = QRect(glWidget->mapToGlobal(QPoint(0, 0)), glWidget->size()); - if (globalWidgetRect.intersects(globalGlWidgetRect)) { - qt_post_window_change_event(glWidget); - it->lastUpdateWidget = widget; - } else if (it->lastUpdateWidget == widget) { - // Update the gl wigets that the widget intersected the last time around, - // and that we are not intersecting now. This prevents paint errors when the - // intersecting widget leaves a gl widget. - qt_post_window_change_event(glWidget); - it->lastUpdateWidget = 0; - } - } -#else - Q_UNUSED(widget); -#endif -} - -/* - Posts a kEventQtRequestWindowChange event to the main Carbon event queue. -*/ -static EventRef request_window_change_pending = 0; -Q_GUI_EXPORT void qt_event_request_window_change() -{ - if(request_window_change_pending) - return; - - CreateEvent(0, kEventClassQt, kEventQtRequestWindowChange, GetCurrentEventTime(), - kEventAttributeUserEvent, &request_window_change_pending); - PostEventToQueue(GetMainEventQueue(), request_window_change_pending, kEventPriorityHigh); -} - -/* window changing. This is a hack around Apple's missing functionality, pending the toolbox - team fix. --Sam */ -Q_GUI_EXPORT void qt_event_request_window_change(QWidget *widget) -{ - if (!widget) - return; - - // Post a kEventQtRequestWindowChange event. This event is semi-public, - // don't remove this line! - qt_event_request_window_change(); - - // Post update request on gl widgets unconditionally. - if (qt_widget_private(widget)->isGLWidget == true) { - qt_post_window_change_event(widget); - return; - } - - qt_mac_update_child_gl_widgets(widget); - qt_mac_update_intersected_gl_widgets(widget); -} - -/* activation */ -static struct { - QPointer<QWidget> widget; - EventRef event; - EventLoopTimerRef timer; - EventLoopTimerUPP timerUPP; -} request_activate_pending = { 0, 0, 0, 0 }; -bool qt_event_remove_activate() -{ - if (request_activate_pending.timer) { - RemoveEventLoopTimer(request_activate_pending.timer); - request_activate_pending.timer = 0; - } - if (request_activate_pending.event) - qt_mac_event_release(request_activate_pending.event); - return true; -} - -void qt_event_activate_timer_callbk(EventLoopTimerRef r, void *) -{ - EventLoopTimerRef otc = request_activate_pending.timer; - qt_event_remove_activate(); - if (r == otc && !request_activate_pending.widget.isNull()) { - const QWidget *tlw = request_activate_pending.widget->window(); - Qt::WindowType wt = tlw->windowType(); - if (tlw->isVisible() - && ((wt != Qt::Desktop && wt != Qt::Popup && wt != Qt::Tool) || tlw->isModal())) { - CreateEvent(0, kEventClassQt, kEventQtRequestActivate, GetCurrentEventTime(), - kEventAttributeUserEvent, &request_activate_pending.event); - PostEventToQueue(GetMainEventQueue(), request_activate_pending.event, kEventPriorityHigh); - } - } -} - -void qt_event_request_activate(QWidget *w) -{ - if (w == request_activate_pending.widget) - return; - - /* We put these into a timer because due to order of events being sent we need to be sure this - comes from inside of the event loop */ - qt_event_remove_activate(); - if (!request_activate_pending.timerUPP) - request_activate_pending.timerUPP = NewEventLoopTimerUPP(qt_event_activate_timer_callbk); - request_activate_pending.widget = w; - InstallEventLoopTimer(GetMainEventLoop(), 0, 0, request_activate_pending.timerUPP, 0, &request_activate_pending.timer); -} - - -/* menubars */ -#ifndef QT_MAC_USE_COCOA -static EventRef request_menubarupdate_pending = 0; -#endif -void qt_event_request_menubarupdate() -{ -#ifndef QT_MAC_USE_COCOA - if (request_menubarupdate_pending) { - if (IsEventInQueue(GetMainEventQueue(), request_menubarupdate_pending)) - return; -#ifdef DEBUG_DROPPED_EVENTS - qDebug("%s:%d Whoa, we dropped an event on the floor!", __FILE__, __LINE__); -#endif - } - - CreateEvent(0, kEventClassQt, kEventQtRequestMenubarUpdate, GetCurrentEventTime(), - kEventAttributeUserEvent, &request_menubarupdate_pending); - PostEventToQueue(GetMainEventQueue(), request_menubarupdate_pending, kEventPriorityHigh); -#else - // Just call this. The request has the benefit that we don't call this multiple times, but - // we can optimize this. - QMenuBar::macUpdateMenuBar(); -#endif -} - -#ifndef QT_MAC_USE_COCOA -//context menu -static EventRef request_context_pending = 0; -static void qt_event_request_context(QWidget *w=0, EventRef *where=0) -{ - if (!where) - where = &request_context_pending; - if (*where) - return; - CreateEvent(0, kEventClassQt, kEventQtRequestContext, GetCurrentEventTime(), - kEventAttributeUserEvent, where); - if (w) - SetEventParameter(*where, kEventParamQWidget, typeQWidget, sizeof(w), &w); - PostEventToQueue(GetMainEventQueue(), *where, kEventPriorityStandard); -} -#endif - -void QApplicationPrivate::createEventDispatcher() -{ - Q_Q(QApplication); - if (q->type() != QApplication::Tty) - eventDispatcher = new QEventDispatcherMac(q); - else - eventDispatcher = new QEventDispatcherUNIX(q); -} - -/* clipboard */ -void qt_event_send_clipboard_changed() -{ -#ifndef QT_MAC_USE_COCOA - AppleEvent ae; - if (AECreateAppleEvent(kEventClassQt, typeAEClipboardChanged, 0, kAutoGenerateReturnID, kAnyTransactionID, &ae) != noErr) - qDebug("Can't happen!!"); - AppleEvent reply; - AESend(&ae, &reply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, 0, 0); -#endif -} - -/* app menu */ -static QMenu *qt_mac_dock_menu = 0; -Q_GUI_EXPORT void qt_mac_set_dock_menu(QMenu *menu) -{ - qt_mac_dock_menu = menu; -#ifdef QT_MAC_USE_COCOA - [NSApp setDockMenu:menu->macMenu()]; -#else - SetApplicationDockTileMenu(menu->macMenu()); -#endif -} - -/* events that hold pointers to widgets, must be cleaned up like this */ -void qt_mac_event_release(QWidget *w) -{ - if (w) { -#ifndef QT_MAC_USE_COCOA - qt_mac_event_release(w, request_showsheet_pending); - qt_mac_event_release(w, request_context_pending); -#endif - if (w == qt_mac_dock_menu) { - qt_mac_dock_menu = 0; -#ifndef QT_MAC_USE_COCOA - SetApplicationDockTileMenu(0); -#else - [NSApp setDockMenu:0]; -#endif - } - } -} - -struct QMacAppleEventTypeSpec { - AEEventClass mac_class; - AEEventID mac_id; -} app_apple_events[] = { - { kCoreEventClass, kAEQuitApplication }, - { kCoreEventClass, kAEOpenDocuments }, - { kInternetEventClass, kAEGetURL }, -}; - -#ifndef QT_MAC_USE_COCOA - -#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) -enum -{ - kEventMouseScroll = 11, - kEventParamMouseWheelSmoothVerticalDelta = 'saxy', - kEventParamMouseWheelSmoothHorizontalDelta = 'saxx', -}; -#endif - -/* watched events */ -static EventTypeSpec app_events[] = { - { kEventClassQt, kEventQtRequestWindowChange }, - { kEventClassQt, kEventQtRequestShowSheet }, - { kEventClassQt, kEventQtRequestContext }, - { kEventClassQt, kEventQtRequestActivate }, - { kEventClassQt, kEventQtRequestMenubarUpdate }, - - { kEventClassWindow, kEventWindowActivated }, - { kEventClassWindow, kEventWindowDeactivated }, - - { kEventClassMouse, kEventMouseScroll }, - { kEventClassMouse, kEventMouseWheelMoved }, - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseDragged }, - { kEventClassMouse, kEventMouseMoved }, - - { kEventClassTablet, kEventTabletProximity }, - - { kEventClassApplication, kEventAppActivated }, - { kEventClassApplication, kEventAppDeactivated }, - { kEventClassApplication, kEventAppAvailableWindowBoundsChanged }, - - // { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged }, - { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassKeyboard, kEventRawKeyUp }, - { kEventClassKeyboard, kEventRawKeyDown }, - - { kEventClassCommand, kEventCommandProcess }, - - { kEventClassAppleEvent, kEventAppleEvent }, - - { kAppearanceEventClass, kAEAppearanceChanged } -}; - -void qt_init_app_proc_handler() -{ - InstallEventHandler(GetApplicationEventTarget(), app_proc_handlerUPP, - GetEventTypeCount(app_events), app_events, (void *)qApp, - &app_proc_handler); -} -#endif // QT_MAC_USE_COCOA - -static void qt_init_tablet_proximity_handler() -{ - EventTypeSpec tabletProximityEvent = { kEventClassTablet, kEventTabletProximity }; - InstallEventHandler(GetEventMonitorTarget(), tablet_proximity_UPP, - 1, &tabletProximityEvent, qApp, &tablet_proximity_handler); -} - -static void qt_release_tablet_proximity_handler() -{ - RemoveEventHandler(tablet_proximity_handler); -} - -QString QApplicationPrivate::appName() const -{ - static QString applName; - if (applName.isEmpty()) { - applName = QCoreApplicationPrivate::macMenuBarName(); - ProcessSerialNumber psn; - if (applName.isEmpty() && qt_is_gui_used && GetCurrentProcess(&psn) == noErr) { - QCFString cfstr; - CopyProcessName(&psn, &cfstr); - applName = cfstr; - } - } - return applName; -} - -void qt_release_app_proc_handler() -{ -#ifndef QT_MAC_USE_COCOA - if (app_proc_handler) { - RemoveEventHandler(app_proc_handler); - app_proc_handler = 0; - } -#endif -} - -void qt_color_profile_changed(CFNotificationCenterRef, void *, CFStringRef, const void *, - CFDictionaryRef) -{ - QCoreGraphicsPaintEngine::cleanUpMacColorSpaces(); -} -/* platform specific implementations */ -void qt_init(QApplicationPrivate *priv, int) -{ - if (qt_is_gui_used) { - CGDisplayRegisterReconfigurationCallback(qt_mac_display_change_callbk, 0); - CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter(); - CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed, - kCMDeviceUnregisteredNotification, 0, - CFNotificationSuspensionBehaviorDeliverImmediately); - CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed, - kCMDefaultDeviceNotification, 0, - CFNotificationSuspensionBehaviorDeliverImmediately); - CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed, - kCMDeviceProfilesNotification, 0, - CFNotificationSuspensionBehaviorDeliverImmediately); - CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed, - kCMDefaultDeviceProfileNotification, 0, - CFNotificationSuspensionBehaviorDeliverImmediately); - ProcessSerialNumber psn; - if (GetCurrentProcess(&psn) == noErr) { - // Jambi needs to transform itself since most people aren't "used" - // to putting things in bundles, but other people may actually not - // want to tranform the process (running as a helper or something) - // so don't do that for them. This means checking both LSUIElement - // and LSBackgroundOnly. If you set them both... well, you - // shouldn't do that. - - bool forceTransform = true; - CFTypeRef value = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), - CFSTR("LSUIElement")); - if (value) { - CFTypeID valueType = CFGetTypeID(value); - // Officially it's supposed to be a string, a boolean makes sense, so we'll check. - // A number less so, but OK. - if (valueType == CFStringGetTypeID()) - forceTransform = !(QCFString::toQString(static_cast<CFStringRef>(value)).toInt()); - else if (valueType == CFBooleanGetTypeID()) - forceTransform = !CFBooleanGetValue(static_cast<CFBooleanRef>(value)); - else if (valueType == CFNumberGetTypeID()) { - int valueAsInt; - CFNumberGetValue(static_cast<CFNumberRef>(value), kCFNumberIntType, &valueAsInt); - forceTransform = !valueAsInt; - } - } - - if (forceTransform) { - value = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), - CFSTR("LSBackgroundOnly")); - if (value) { - CFTypeID valueType = CFGetTypeID(value); - if (valueType == CFBooleanGetTypeID()) - forceTransform = !CFBooleanGetValue(static_cast<CFBooleanRef>(value)); - else if (valueType == CFStringGetTypeID()) - forceTransform = !(QCFString::toQString(static_cast<CFStringRef>(value)).toInt()); - else if (valueType == CFNumberGetTypeID()) { - int valueAsInt; - CFNumberGetValue(static_cast<CFNumberRef>(value), kCFNumberIntType, &valueAsInt); - forceTransform = !valueAsInt; - } - } - } - - - if (forceTransform) { - TransformProcessType(&psn, kProcessTransformToForegroundApplication); - } - } - } - - char **argv = priv->argv; - - // Get command line params - if (int argc = priv->argc) { - int i, j = 1; - QString passed_psn; - for(i=1; i < argc; i++) { - if (argv[i] && *argv[i] != '-') { - argv[j++] = argv[i]; - continue; - } - QByteArray arg(argv[i]); -#if defined(QT_DEBUG) - if (arg == "-nograb") - appNoGrab = !appNoGrab; - else -#endif // QT_DEBUG - if (arg.left(5) == "-psn_") { - passed_psn = QString::fromLatin1(arg.mid(6)); - } else { - argv[j++] = argv[i]; - } - } - if (j < priv->argc) { - priv->argv[j] = 0; - priv->argc = j; - } - - //special hack to change working directory (for an app bundle) when running from finder - if (!passed_psn.isNull() && QDir::currentPath() == QLatin1String("/")) { - QCFType<CFURLRef> bundleURL(CFBundleCopyBundleURL(CFBundleGetMainBundle())); - QString qbundlePath = QCFString(CFURLCopyFileSystemPath(bundleURL, - kCFURLPOSIXPathStyle)); - if (qbundlePath.endsWith(QLatin1String(".app"))) - QDir::setCurrent(qbundlePath.section(QLatin1Char('/'), 0, -2)); - } - } - - QMacPasteboardMime::initialize(); - - qApp->setObjectName(priv->appName()); - if (qt_is_gui_used) { - QColormap::initialize(); - QFont::initialize(); - QCursorData::initialize(); - QCoreGraphicsPaintEngine::initialize(); -#ifndef QT_NO_ACCESSIBILITY - QAccessible::initialize(); -#endif - QMacInputContext::initialize(); - QApplicationPrivate::inputContext = new QMacInputContext; - - if (QApplication::desktopSettingsAware()) - qt_mac_update_os_settings(); -#ifndef QT_MAC_USE_COCOA - if (!app_proc_handler) { - app_proc_handlerUPP = NewEventHandlerUPP(QApplicationPrivate::globalEventProcessor); - qt_init_app_proc_handler(); - } - -#endif - if (!app_proc_ae_handlerUPP && !QApplication::testAttribute(Qt::AA_MacPluginApplication)) { - app_proc_ae_handlerUPP = AEEventHandlerUPP(QApplicationPrivate::globalAppleEventProcessor); - for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i) { - // Install apple event handler, but avoid overwriting an already - // existing handler (it means a 3rd party application has installed one): - SRefCon refCon = 0; - AEEventHandlerUPP current_handler = NULL; - AEGetEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, ¤t_handler, &refCon, false); - if (!current_handler) - AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, - app_proc_ae_handlerUPP, SRefCon(qApp), false); - } - } - - if (QApplicationPrivate::app_style) { - QEvent ev(QEvent::Style); - qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev); - } - } - if (QApplication::desktopSettingsAware()) - QApplicationPrivate::qt_mac_apply_settings(); - - // Cocoa application delegate -#ifdef QT_MAC_USE_COCOA - NSApplication *cocoaApp = [QNSApplication sharedApplication]; - qt_redirectNSApplicationSendEvent(); - - QMacCocoaAutoReleasePool pool; - id oldDelegate = [cocoaApp delegate]; - QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate]; - Q_ASSERT(newDelegate); - [newDelegate setQtPrivate:priv]; - // Only do things that make sense to do once, otherwise we crash. - if (oldDelegate != newDelegate && !QApplication::testAttribute(Qt::AA_MacPluginApplication)) { - [newDelegate setReflectionDelegate:oldDelegate]; - [cocoaApp setDelegate:newDelegate]; - - QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader = [[QT_MANGLE_NAMESPACE(QCocoaMenuLoader) alloc] init]; - if ([NSBundle loadNibNamed:@"qt_menu" owner:qtMenuLoader] == false) { - qFatal("Qt internal error: qt_menu.nib could not be loaded. The .nib file" - " should be placed in QtGui.framework/Versions/Current/Resources/ " - " or in the resources directory of your application bundle."); - } - - [cocoaApp setMenu:[qtMenuLoader menu]]; - [newDelegate setMenuLoader:qtMenuLoader]; - [qtMenuLoader release]; - } -#endif - // Register for Carbon tablet proximity events on the event monitor target. - // This means that we should receive proximity events even when we aren't the active application. - if (!tablet_proximity_handler) { - tablet_proximity_UPP = NewEventHandlerUPP(QApplicationPrivate::tabletProximityCallback); - qt_init_tablet_proximity_handler(); - } - priv->native_modal_dialog_active = false; - - qt_mac_read_fontsmoothing_settings(); -} - -void qt_release_apple_event_handler() -{ - if(app_proc_ae_handlerUPP) { - for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i) - AERemoveEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, - app_proc_ae_handlerUPP, true); - DisposeAEEventHandlerUPP(app_proc_ae_handlerUPP); - app_proc_ae_handlerUPP = 0; - } -} - -/***************************************************************************** - qt_cleanup() - cleans up when the application is finished - *****************************************************************************/ - -void qt_cleanup() -{ - CGDisplayRemoveReconfigurationCallback(qt_mac_display_change_callbk, 0); - CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter(); - CFNotificationCenterRemoveObserver(center, qApp, kCMDeviceUnregisteredNotification, 0); - CFNotificationCenterRemoveObserver(center, qApp, kCMDefaultDeviceNotification, 0); - CFNotificationCenterRemoveObserver(center, qApp, kCMDeviceProfilesNotification, 0); - CFNotificationCenterRemoveObserver(center, qApp, kCMDefaultDeviceProfileNotification, 0); - -#ifndef QT_MAC_USE_COCOA - qt_release_app_proc_handler(); - if (app_proc_handlerUPP) { - DisposeEventHandlerUPP(app_proc_handlerUPP); - app_proc_handlerUPP = 0; - } -#endif - qt_release_apple_event_handler(); - qt_release_tablet_proximity_handler(); - if (tablet_proximity_UPP) - DisposeEventHandlerUPP(tablet_proximity_UPP); - - QPixmapCache::clear(); - if (qt_is_gui_used) { -#ifndef QT_NO_ACCESSIBILITY - QAccessible::cleanup(); -#endif - QMacInputContext::cleanup(); - QCursorData::cleanup(); - QFont::cleanup(); - QColormap::cleanup(); - if (qt_mac_safe_pdev) { - delete qt_mac_safe_pdev; - qt_mac_safe_pdev = 0; - } - extern void qt_mac_unregister_widget(); // qapplication_mac.cpp - qt_mac_unregister_widget(); - } -} - -/***************************************************************************** - Platform specific global and internal functions - *****************************************************************************/ -void qt_updated_rootinfo() -{ -} - -bool qt_wstate_iconified(WId) -{ - return false; -} - -/***************************************************************************** - Platform specific QApplication members - *****************************************************************************/ -extern QWidget * mac_mouse_grabber; -extern QWidget * mac_keyboard_grabber; - -#ifdef QT3_SUPPORT -void QApplication::setMainWidget(QWidget *mainWidget) -{ - QApplicationPrivate::main_widget = mainWidget; - if (QApplicationPrivate::main_widget && windowIcon().isNull() - && QApplicationPrivate::main_widget->testAttribute(Qt::WA_SetWindowIcon)) - setWindowIcon(QApplicationPrivate::main_widget->windowIcon()); -} -#endif -#ifndef QT_NO_CURSOR - -/***************************************************************************** - QApplication cursor stack - *****************************************************************************/ - -void QApplication::setOverrideCursor(const QCursor &cursor) -{ - qApp->d_func()->cursor_list.prepend(cursor); - -#ifdef QT_MAC_USE_COCOA - qt_mac_update_cursor(); -#else - if (qApp && qApp->activeWindow()) - qt_mac_set_cursor(&qApp->d_func()->cursor_list.first()); -#endif -} - -void QApplication::restoreOverrideCursor() -{ - if (qApp->d_func()->cursor_list.isEmpty()) - return; - qApp->d_func()->cursor_list.removeFirst(); - -#ifdef QT_MAC_USE_COCOA - qt_mac_update_cursor(); -#else - if (qApp && qApp->activeWindow()) { - const QCursor def(Qt::ArrowCursor); - qt_mac_set_cursor(qApp->d_func()->cursor_list.isEmpty() ? &def : &qApp->d_func()->cursor_list.first()); - } -#endif -} -#endif // QT_NO_CURSOR - -QWidget *QApplication::topLevelAt(const QPoint &p) -{ -#ifndef QT_MAC_USE_COCOA - QWidget *widget; - qt_mac_window_at(p.x(), p.y(), &widget); - return widget; -#else - // Use a cache to avoid iterate through the whole list of windows for all - // calls to to topLevelAt. We e.g. do this for each and every mouse - // move since we need to find the widget under mouse: - if (topLevelAt_cache && topLevelAt_cache->frameGeometry().contains(p)) - return topLevelAt_cache; - - // INVARIANT: Cache miss. Go through the list if windows instead: - QMacCocoaAutoReleasePool pool; - NSPoint cocoaPoint = flipPoint(p); - NSInteger windowCount; - NSCountWindows(&windowCount); - if (windowCount <= 0) - return 0; // There's no window to find! - - QVarLengthArray<NSInteger> windowList(windowCount); - NSWindowList(windowCount, windowList.data()); - int firstQtWindowFound = -1; - for (int i = 0; i < windowCount; ++i) { - NSWindow *window = [NSApp windowWithWindowNumber:windowList[i]]; - if (window) { - QWidget *candidateWindow = [window QT_MANGLE_NAMESPACE(qt_qwidget)]; - if (candidateWindow && firstQtWindowFound == -1) - firstQtWindowFound = i; - - if (NSPointInRect(cocoaPoint, [window frame])) { - // Check to see if there's a hole in the window where the mask is. - // If there is, we should just continue to see if there is a window below. - if (candidateWindow && !candidateWindow->mask().isEmpty()) { - QPoint localPoint = candidateWindow->mapFromGlobal(p); - if (!candidateWindow->mask().contains(localPoint)) - continue; - else - return candidateWindow; - } else { - if (i == firstQtWindowFound) { - // The cache will only work when the window under mouse is - // top most (that is, not partially obscured by other windows. - // And we only set it if no mask is present to optimize for the common case: - topLevelAt_cache = candidateWindow; - } - return candidateWindow; - } - } - } - } - - topLevelAt_cache = 0; - return 0; -#endif -} - -/***************************************************************************** - Main event loop - *****************************************************************************/ - -bool QApplicationPrivate::modalState() -{ - return app_do_modal; -} - -#ifdef QT_MAC_USE_COCOA -#endif - -void QApplicationPrivate::enterModal_sys(QWidget *widget) -{ -#ifdef DEBUG_MODAL_EVENTS - Q_ASSERT(widget); - qDebug("Entering modal state with %s::%s::%p (%d)", widget->metaObject()->className(), widget->objectName().toLocal8Bit().constData(), - widget, qt_modal_stack ? (int)qt_modal_stack->count() : -1); -#endif - if (!qt_modal_stack) - qt_modal_stack = new QWidgetList; - - dispatchEnterLeave(0, qt_last_mouse_receiver); - qt_last_mouse_receiver = 0; - - qt_modal_stack->insert(0, widget); - if (!app_do_modal) - qt_event_request_menubarupdate(); - app_do_modal = true; - qt_button_down = 0; - -#ifdef QT_MAC_USE_COCOA - if (!qt_mac_is_macsheet(widget)) - QEventDispatcherMacPrivate::beginModalSession(widget); -#endif -} - -void QApplicationPrivate::leaveModal_sys(QWidget *widget) -{ - if (qt_modal_stack && qt_modal_stack->removeAll(widget)) { -#ifdef DEBUG_MODAL_EVENTS - qDebug("Leaving modal state with %s::%s::%p (%d)", widget->metaObject()->className(), widget->objectName().toLocal8Bit().constData(), - widget, qt_modal_stack->count()); -#endif - if (qt_modal_stack->isEmpty()) { - delete qt_modal_stack; - qt_modal_stack = 0; - QPoint p(QCursor::pos()); - app_do_modal = false; - QWidget* w = 0; - if (QWidget *grabber = QWidget::mouseGrabber()) - w = grabber; - else - w = QApplication::widgetAt(p.x(), p.y()); - dispatchEnterLeave(w, qt_last_mouse_receiver); // send synthetic enter event - qt_last_mouse_receiver = w; - } -#ifdef QT_MAC_USE_COCOA - if (!qt_mac_is_macsheet(widget)) - QEventDispatcherMacPrivate::endModalSession(widget); -#endif - } -#ifdef DEBUG_MODAL_EVENTS - else qDebug("Failure to remove %s::%s::%p -- %p", widget->metaObject()->className(), widget->objectName().toLocal8Bit().constData(), widget, qt_modal_stack); -#endif - app_do_modal = (qt_modal_stack != 0); - if (!app_do_modal) - qt_event_request_menubarupdate(); -} - -QWidget *QApplicationPrivate::tryModalHelper_sys(QWidget *top) -{ -#ifndef QT_MAC_USE_COCOA - if(top && qt_mac_is_macsheet(top) && !IsWindowVisible(qt_mac_window_for(top))) { - if(OSWindowRef wp = GetFrontWindowOfClass(kSheetWindowClass, true)) { - if(QWidget *sheet = qt_mac_find_window(wp)) - top = sheet; - } - } -#endif - return top; -} - -#ifndef QT_MAC_USE_COCOA -static bool qt_try_modal(QWidget *widget, EventRef event) -{ - QWidget * top = 0; - - if (QApplicationPrivate::tryModalHelper(widget, &top)) - return true; - - // INVARIANT: widget is modally shaddowed within its - // window, and should therefore not handle the event. - // However, if the window is not active, the event - // might suggest that we should bring it to front: - - bool block_event = false; - - if (event) { - switch (GetEventClass(event)) { - case kEventClassMouse: - case kEventClassKeyboard: - block_event = true; - break; - } - } - - QWidget *activeWidget = QApplication::activeWindow(); - if ((!activeWidget || QApplicationPrivate::isBlockedByModal(activeWidget)) && - top->isWindow() && block_event && !QApplicationPrivate::native_modal_dialog_active) - top->raise(); - -#ifdef DEBUG_MODAL_EVENTS - qDebug("%s:%d -- final decision! (%s)", __FILE__, __LINE__, block_event ? "false" : "true"); -#endif - return !block_event; -} -#endif - -OSStatus QApplicationPrivate::tabletProximityCallback(EventHandlerCallRef, EventRef carbonEvent, - void *) -{ - OSType eventClass = GetEventClass(carbonEvent); - UInt32 eventKind = GetEventKind(carbonEvent); - if (eventClass != kEventClassTablet || eventKind != kEventTabletProximity) - return eventNotHandledErr; - - // Get the current point of the device and its unique ID. - ::TabletProximityRec proxRec; - GetEventParameter(carbonEvent, kEventParamTabletProximityRec, typeTabletProximityRec, 0, - sizeof(proxRec), 0, &proxRec); - qt_dispatchTabletProximityEvent(proxRec); - return noErr; -} - -OSStatus -QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event, void *data) -{ -#ifndef QT_MAC_USE_COCOA - QApplication *app = (QApplication *)data; - QScopedLoopLevelCounter loopLevelCounter(app->d_func()->threadData); - long result; - if (app->filterEvent(&event, &result)) - return result; - if(app->macEventFilter(er, event)) //someone else ate it - return noErr; - QPointer<QWidget> widget; - - /*We assume all events are handled and in - the code below we set it to false when we know we didn't handle it, this - will let rogue events through (shouldn't really happen, but better safe - than sorry) */ - bool handled_event=true; - UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event); - switch(eclass) - { - case kEventClassQt: - if(ekind == kEventQtRequestShowSheet) { - request_showsheet_pending = 0; - QWidget *widget = 0; - GetEventParameter(event, kEventParamQWidget, typeQWidget, 0, - sizeof(widget), 0, &widget); - if(widget) { - if (widget->macEvent(er, event)) - return noErr; - WindowPtr window = qt_mac_window_for(widget); - bool just_show = !qt_mac_is_macsheet(widget); - if(!just_show) { - OSStatus err = ShowSheetWindow(window, qt_mac_window_for(widget->parentWidget())); - if(err != noErr) - qWarning("Qt: QWidget: Unable to show as sheet %s::%s [%ld]", widget->metaObject()->className(), - widget->objectName().toLocal8Bit().constData(), long(err)); - just_show = true; - } - if(just_show) //at least the window will be visible, but the sheet flag doesn't work sadly (probalby too many sheets) - ShowHide(window, true); - } - } else if(ekind == kEventQtRequestWindowChange) { - qt_mac_event_release(request_window_change_pending); - } else if(ekind == kEventQtRequestMenubarUpdate) { - qt_mac_event_release(request_menubarupdate_pending); - QMenuBar::macUpdateMenuBar(); - } else if(ekind == kEventQtRequestActivate) { - qt_mac_event_release(request_activate_pending.event); - if(request_activate_pending.widget) { - QWidget *tlw = request_activate_pending.widget->window(); - if (tlw->macEvent(er, event)) - return noErr; - request_activate_pending.widget = 0; - tlw->activateWindow(); - SelectWindow(qt_mac_window_for(tlw)); - } - } else if(ekind == kEventQtRequestContext) { - bool send = false; - if ((send = (event == request_context_pending))) - qt_mac_event_release(request_context_pending); - if(send) { - //figure out which widget to send it to - QPoint where = QCursor::pos(); - QWidget *widget = 0; - GetEventParameter(event, kEventParamQWidget, typeQWidget, 0, - sizeof(widget), 0, &widget); - if(!widget) { - if(qt_button_down) - widget = qt_button_down; - else - widget = QApplication::widgetAt(where.x(), where.y()); - } - if(widget && !isBlockedByModal(widget)) { - if (widget->macEvent(er, event)) - return noErr; - QPoint plocal(widget->mapFromGlobal(where)); - const Qt::KeyboardModifiers keyboardModifiers = qt_mac_get_modifiers(GetCurrentEventKeyModifiers()); - QContextMenuEvent qme(QContextMenuEvent::Mouse, plocal, where, keyboardModifiers); - QApplication::sendEvent(widget, &qme); - if(qme.isAccepted()) { //once this happens the events before are pitched - qt_button_down = 0; - qt_mac_dblclick.last_widget = 0; - } - } else { - handled_event = false; - } - } - } else { - handled_event = false; - } - break; - case kEventClassTablet: - switch (ekind) { - case kEventTabletProximity: - // Get the current point of the device and its unique ID. - ::TabletProximityRec proxRec; - GetEventParameter(event, kEventParamTabletProximityRec, typeTabletProximityRec, 0, - sizeof(proxRec), 0, &proxRec); - qt_dispatchTabletProximityEvent(proxRec); - } - break; - case kEventClassMouse: - { - static const int kEventParamQAppSeenMouseEvent = 'QASM'; - // Check if we've seen the event, if we have we shouldn't process - // it again as it may lead to spurious "double events" - bool seenEvent; - if (GetEventParameter(event, kEventParamQAppSeenMouseEvent, - typeBoolean, 0, sizeof(bool), 0, &seenEvent) == noErr) { - if (seenEvent) - return eventNotHandledErr; - } - seenEvent = true; - SetEventParameter(event, kEventParamQAppSeenMouseEvent, typeBoolean, - sizeof(bool), &seenEvent); - - Point where; - bool inNonClientArea = false; - GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0, - sizeof(where), 0, &where); -#if defined(DEBUG_MOUSE_MAPS) - const char *edesc = 0; - switch(ekind) { - case kEventMouseDown: edesc = "MouseButtonPress"; break; - case kEventMouseUp: edesc = "MouseButtonRelease"; break; - case kEventMouseDragged: case kEventMouseMoved: edesc = "MouseMove"; break; - case kEventMouseScroll: edesc = "MouseWheelScroll"; break; - case kEventMouseWheelMoved: edesc = "MouseWheelMove"; break; - } - if(ekind == kEventMouseDown || ekind == kEventMouseUp) - qDebug("Handling mouse: %s", edesc); -#endif - QEvent::Type etype = QEvent::None; - Qt::KeyboardModifiers modifiers; - { - UInt32 mac_modifiers = 0; - GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 0, - sizeof(mac_modifiers), 0, &mac_modifiers); - modifiers = qt_mac_get_modifiers(mac_modifiers); - } - Qt::MouseButtons buttons; - { - UInt32 mac_buttons = 0; - GetEventParameter(event, kEventParamMouseChord, typeUInt32, 0, - sizeof(mac_buttons), 0, &mac_buttons); - if (ekind != kEventMouseWheelMoved) - buttons = qt_mac_get_buttons(mac_buttons); - else - buttons = QApplication::mouseButtons(); - } - - int wheel_deltaX = 0; - int wheel_deltaY = 0; - static EventRef compatibilityEvent = 0; - - if (ekind == kEventMouseScroll) { - // kEventMouseScroll is the new way of dealing with mouse wheel - // events (kEventMouseWheelMoved was the old). kEventMouseScroll results - // in much smoother scrolling when using Mighty Mouse or TrackPad. For - // compatibility with older applications, carbon will also send us - // kEventMouseWheelMoved events if we dont eat this event - // (actually two events; one for horizontal and one for vertical). - // As a results of this, and to make sure we dont't receive duplicate events, - // we try to detect when this happend by checking the 'compatibilityEvent'. - // Since delta is delivered as pixels rather than degrees, we need to - // convert from pixels to degrees in a sensible manner. - // It looks like 1/4 degrees per pixel behaves most native. - // (NB: Qt expects the unit for delta to be 8 per degree): - const int pixelsToDegrees = 2; - SInt32 mdelt = 0; - GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0, - sizeof(mdelt), 0, &mdelt); - wheel_deltaX = mdelt * pixelsToDegrees; - mdelt = 0; - GetEventParameter(event, kEventParamMouseWheelSmoothVerticalDelta, typeSInt32, 0, - sizeof(mdelt), 0, &mdelt); - wheel_deltaY = mdelt * pixelsToDegrees; - GetEventParameter(event, kEventParamEventRef, typeEventRef, 0, - sizeof(compatibilityEvent), 0, &compatibilityEvent); - } else if (ekind == kEventMouseWheelMoved) { - if (event != compatibilityEvent) { - compatibilityEvent = 0; - int mdelt = 0; - GetEventParameter(event, kEventParamMouseWheelDelta, typeSInt32, 0, - sizeof(mdelt), 0, &mdelt); - EventMouseWheelAxis axis; - GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, 0, - sizeof(axis), 0, &axis); - - // Remove acceleration, and use either -120 or 120 as delta: - if (axis == kEventMouseWheelAxisX) - wheel_deltaX = qBound(-120, int(mdelt * 10000), 120); - else - wheel_deltaY = qBound(-120, int(mdelt * 10000), 120); - } - } - - Qt::MouseButton button = Qt::NoButton; - if(ekind == kEventMouseDown || ekind == kEventMouseUp) { - EventMouseButton mac_button = 0; - GetEventParameter(event, kEventParamMouseButton, typeMouseButton, 0, - sizeof(mac_button), 0, &mac_button); - button = qt_mac_get_button(mac_button); - } - - switch(ekind) { - case kEventMouseDown: - etype = QEvent::MouseButtonPress; - break; - case kEventMouseUp: - etype = QEvent::MouseButtonRelease; - break; - case kEventMouseDragged: - case kEventMouseMoved: - etype = QEvent::MouseMove; - break; - } - - const bool inPopupMode = app->d_func()->inPopupMode(); - - // A click outside a popup closes the popup. Make sure - // that no events are generated for the release part of that click. - // (The press goes to the popup and closes it.) - if (etype == QEvent::MouseButtonPress) { - qt_mac_previous_press_in_popup_mode = inPopupMode; - } else if (qt_mac_previous_press_in_popup_mode && !inPopupMode && etype == QEvent::MouseButtonRelease) { - qt_mac_previous_press_in_popup_mode = false; - handled_event = true; -#if defined(DEBUG_MOUSE_MAPS) - qDebug("Bail out early due to qt_mac_previous_press_in_popup_mode"); -#endif - break; // break from case kEventClassMouse - } - - //figure out which widget to send it to - if(inPopupMode) { - QWidget *popup = qApp->activePopupWidget(); - if (qt_button_down && qt_button_down->window() == popup) { - widget = qt_button_down; - } else { - QPoint pos = popup->mapFromGlobal(QPoint(where.h, where.v)); - widget = popup->childAt(pos); - } - if(!widget) - widget = popup; - } else { - if(mac_mouse_grabber) { - widget = mac_mouse_grabber; - } else if (qt_button_down) { - widget = qt_button_down; - } else { - { - WindowPtr window = 0; - if(GetEventParameter(event, kEventParamWindowRef, typeWindowRef, 0, - sizeof(window), 0, &window) != noErr) - FindWindowOfClass(&where, kAllWindowClasses, &window, 0); - if(window) { - HIViewRef hiview; - if(HIViewGetViewForMouseEvent(HIViewGetRoot(window), event, &hiview) == noErr) { - widget = QWidget::find((WId)hiview); - if (widget) { - // Make sure we didn't pass over a widget with a "fake hole" in it. - QWidget *otherWidget = QApplication::widgetAt(where.h, where.v); - if (otherWidget && otherWidget->testAttribute(Qt::WA_MouseNoMask)) - widget = otherWidget; - } - } - } - } - if(!widget) //fallback - widget = QApplication::widgetAt(where.h, where.v); - if(ekind == kEventMouseUp && widget) { - short part = qt_mac_window_at(where.h, where.v); - if(part == inDrag) { - UInt32 count = 0; - GetEventParameter(event, kEventParamClickCount, typeUInt32, NULL, - sizeof(count), NULL, &count); - if(count == 2 && qt_mac_collapse_on_dblclick) { - if (widget->macEvent(er, event)) - return noErr; - widget->setWindowState(widget->windowState() | Qt::WindowMinimized); - //we send a hide to be like X11/Windows - QEvent e(QEvent::Hide); - QApplication::sendSpontaneousEvent(widget, &e); - break; - } - } - } - } - } - if (widget && widget->macEvent(er, event)) - return noErr; - WindowPartCode wpc = qt_mac_window_at(where.h, where.v, 0); - if (wpc == inProxyIcon && modifiers == Qt::ControlModifier && buttons != Qt::NoButton) { - QIconDragEvent e; - QApplication::sendSpontaneousEvent(widget, &e); - if (e.isAccepted()) { - return noErr; // IconDrag ate it. - } - } - if (inPopupMode == false - && (qt_button_down == 0 || qt_button_down_in_content == false) - && (wpc != inContent && wpc != inStructure)) { - inNonClientArea = true; - switch (etype) { - case QEvent::MouseButtonPress: { - UInt32 count = 0; - GetEventParameter(event, kEventParamClickCount, typeUInt32, 0, - sizeof(count), 0, &count); - if(count % 2 || count == 0) { - etype = QEvent::NonClientAreaMouseButtonPress; - } else { - etype = QEvent::NonClientAreaMouseButtonDblClick; - }} break; - case QEvent::MouseButtonRelease: - etype = QEvent::NonClientAreaMouseButtonRelease; - break; - case QEvent::MouseMove: - if (widget == 0 || widget->hasMouseTracking()) - etype = QEvent::NonClientAreaMouseMove; - break; - default: - break; - } - } - - if(qt_mac_find_window((FrontWindow()))) { //set the cursor up - QCursor cursor(Qt::ArrowCursor); - QWidget *cursor_widget = widget; - if(cursor_widget && cursor_widget == qt_button_down && ekind == kEventMouseUp) - cursor_widget = QApplication::widgetAt(where.h, where.v); - if(cursor_widget) { //only over the app, do we set a cursor.. - if(!qApp->d_func()->cursor_list.isEmpty()) { - cursor = qApp->d_func()->cursor_list.first(); - } else { - for(; cursor_widget; cursor_widget = cursor_widget->parentWidget()) { - QWExtra *extra = cursor_widget->d_func()->extraData(); - if(extra && extra->curs && cursor_widget->isEnabled()) { - cursor = *extra->curs; - break; - } - } - } - } - qt_mac_set_cursor(&cursor); - } - - //This mouse button state stuff looks like this on purpose - //although it looks hacky it is VERY intentional.. - if(widget && app_do_modal && !qt_try_modal(widget, event)) { - if(ekind == kEventMouseDown && qt_mac_is_macsheet(QApplication::activeModalWidget())) - QApplication::activeModalWidget()->parentWidget()->activateWindow(); //sheets have a parent - handled_event = false; -#if defined(DEBUG_MOUSE_MAPS) - qDebug("Bail out early due to qt_try_modal"); -#endif - break; - } - - UInt32 tabletEventType = 0; - GetEventParameter(event, kEventParamTabletEventType, typeUInt32, 0, - sizeof(tabletEventType), 0, &tabletEventType); - if (tabletEventType == kEventTabletPoint) { - TabletPointRec tabletPointRec; - GetEventParameter(event, kEventParamTabletPointRec, typeTabletPointRec, 0, - sizeof(tabletPointRec), 0, &tabletPointRec); - QEvent::Type t = QEvent::TabletMove; //default - int new_tablet_button_state = tabletPointRec.buttons ? 1 : 0; - if (new_tablet_button_state != tablet_button_state) - if (new_tablet_button_state) - t = QEvent::TabletPress; - else - t = QEvent::TabletRelease; - tablet_button_state = new_tablet_button_state; - - QMacTabletHash *tabletHash = qt_mac_tablet_hash(); - if (!tabletHash->contains(tabletPointRec.deviceID) && t != QEvent::TabletRelease) { - // Never discard TabletRelease events as they may be delivered *after* TabletLeaveProximity events - qWarning("handleTabletEvent: This tablet device is unknown" - " (received no proximity event for it). Discarding event."); - return false; - } - QTabletDeviceData &deviceData = tabletHash->operator[](tabletPointRec.deviceID); - if (t == QEvent::TabletPress) { - deviceData.widgetToGetPress = widget; - } else if (t == QEvent::TabletRelease && deviceData.widgetToGetPress) { - widget = deviceData.widgetToGetPress; - deviceData.widgetToGetPress = 0; - } - - if (widget) { - int tiltX = ((int)tabletPointRec.tiltX)/(32767/64); // 32K -> 60 - int tiltY = ((int)tabletPointRec.tiltY)/(-32767/64); // 32K -> 60 - HIPoint hiPoint; - GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, 0, sizeof(HIPoint), 0, &hiPoint); - QPointF hiRes(hiPoint.x, hiPoint.y); - QPoint global(where.h, where.v); - - - - QPoint local(widget->mapFromGlobal(global)); - int z = 0; - qreal rotation = 0.0; - qreal tp = 0.0; - // Again from the Wacom.h header - - if (deviceData.capabilityMask & 0x0200) // Z-axis - z = tabletPointRec.absZ; - - if (deviceData.capabilityMask & 0x0800) // Tangential pressure - tp = tabletPointRec.tangentialPressure / 32767.0; - - if (deviceData.capabilityMask & 0x2000) // Rotation - rotation = qreal(tabletPointRec.rotation) / 64.0; - - QTabletEvent e(t, local, global, hiRes, deviceData.tabletDeviceType, - deviceData.tabletPointerType, - qreal(tabletPointRec.pressure / qreal(0xffff)), tiltX, tiltY, - tp, rotation, z, modifiers, deviceData.tabletUniqueID); - QApplication::sendSpontaneousEvent(widget, &e); - if (e.isAccepted()) { - if (t == QEvent::TabletPress) { - qt_button_down = widget; - } else if (t == QEvent::TabletRelease) { - qt_button_down = 0; - } -#if defined(DEBUG_MOUSE_MAPS) - qDebug("Bail out early due to tablet acceptance"); -#endif - break; - } - } - } - - if(ekind == kEventMouseDown) { - qt_mac_no_click_through_mode = false; - const short windowPart = qt_mac_window_at(where.h, where.v, 0); - // Menubar almost always wins. - if (!inPopupMode && windowPart == inMenuBar) { - MenuSelect(where); //allow menu tracking - return noErr; - } - - if (widget && !(GetCurrentKeyModifiers() & cmdKey)) { - extern bool qt_isGenuineQWidget(const QWidget *); // qwidget_mac.cpp - QWidget *window = widget->window(); - bool genuineQtWidget = qt_isGenuineQWidget(widget); // the widget, not the window. - window->raise(); - - bool needActivate = (window->windowType() != Qt::Desktop) - && (window->windowType() != Qt::Popup) - && !qt_mac_is_macsheet(window); - if (needActivate && (!window->isModal() && qobject_cast<QDockWidget *>(window))) - needActivate = false; - - if (genuineQtWidget && needActivate) - needActivate = !window->isActiveWindow() - || !IsWindowActive(qt_mac_window_for(window)); - - if (needActivate) { - window->activateWindow(); - if (!qt_mac_can_clickThrough(widget)) { - qt_mac_no_click_through_mode = true; - handled_event = false; -#if defined(DEBUG_MOUSE_MAPS) - qDebug("Bail out early due to qt_mac_canClickThrough %s::%s", widget->metaObject()->className(), - widget->objectName().toLocal8Bit().constData()); -#endif - break; - } - } - } - - if(qt_mac_dblclick.last_widget && - qt_mac_dblclick.last_x != -1 && qt_mac_dblclick.last_y != -1 && - QRect(qt_mac_dblclick.last_x-2, qt_mac_dblclick.last_y-2, 4, 4).contains(QPoint(where.h, where.v))) { - if(qt_mac_dblclick.use_qt_time_limit) { - EventTime now = GetEventTime(event); - if(qt_mac_dblclick.last_time != -2 && qt_mac_dblclick.last_widget == widget && - now - qt_mac_dblclick.last_time <= ((double)QApplicationPrivate::mouse_double_click_time)/1000 && - qt_mac_dblclick.last_button == button) - etype = QEvent::MouseButtonDblClick; - } else { - UInt32 count = 0; - GetEventParameter(event, kEventParamClickCount, typeUInt32, 0, - sizeof(count), 0, &count); - if(!(count % 2) && qt_mac_dblclick.last_modifiers == modifiers && - qt_mac_dblclick.last_widget == widget && qt_mac_dblclick.last_button == button) - etype = QEvent::MouseButtonDblClick; - } - if(etype == QEvent::MouseButtonDblClick) - qt_mac_dblclick.last_widget = 0; - } - if(etype != QEvent::MouseButtonDblClick) { - qt_mac_dblclick.last_x = where.h; - qt_mac_dblclick.last_y = where.v; - } else { - qt_mac_dblclick.last_x = qt_mac_dblclick.last_y = -1; - } - } else if(qt_mac_no_click_through_mode) { - if(ekind == kEventMouseUp) - qt_mac_no_click_through_mode = false; - handled_event = false; -#if defined(DEBUG_MOUSE_MAPS) - qDebug("Bail out early due to qt_mac_no_click_through_mode"); -#endif - break; - } - - QPointer<QWidget> leaveAfterRelease = 0; - switch(ekind) { - case kEventMouseUp: - if (!buttons) { - if (!inPopupMode && !QWidget::mouseGrabber()) - leaveAfterRelease = qt_button_down; - qt_button_down = 0; - } - break; - case kEventMouseDown: { - if (!qt_button_down) - qt_button_down = widget; - WindowPartCode wpc = qt_mac_window_at(where.h, where.v, 0); - qt_button_down_in_content = (wpc == inContent || wpc == inStructure); - break; } - } - - // Check if we should send enter/leave events: - switch(ekind) { - case kEventMouseDragged: - case kEventMouseMoved: - case kEventMouseUp: - case kEventMouseDown: { - // If we are in popup mode, widget will point to the current popup no matter - // where the mouse cursor is. In that case find out if the mouse cursor is - // really over the popup in order to send correct enter / leave envents. - QWidget * const enterLeaveWidget = (inPopupMode || ekind == kEventMouseUp) ? - QApplication::widgetAt(where.h, where.v) : static_cast<QWidget*>(widget); - - if ((QWidget *) qt_last_mouse_receiver != enterLeaveWidget || inNonClientArea) { -#ifdef DEBUG_MOUSE_MAPS - qDebug("Entering: %p - %s (%s), Leaving %s (%s)", (QWidget*)enterLeaveWidget, - enterLeaveWidget ? enterLeaveWidget->metaObject()->className() : "none", - enterLeaveWidget ? enterLeaveWidget->objectName().toLocal8Bit().constData() : "", - qt_last_mouse_receiver ? qt_last_mouse_receiver->metaObject()->className() : "none", - qt_last_mouse_receiver ? qt_last_mouse_receiver->objectName().toLocal8Bit().constData() : ""); -#endif - - QWidget * const mouseGrabber = QWidget::mouseGrabber(); - - if (inPopupMode) { - QWidget *enter = enterLeaveWidget; - QWidget *leave = qt_last_mouse_receiver; - if (mouseGrabber) { - QWidget * const popupWidget = qApp->activePopupWidget(); - if (leave == popupWidget) - enter = mouseGrabber; - if (enter == popupWidget) - leave = mouseGrabber; - if ((enter == mouseGrabber && leave == popupWidget) - || (leave == mouseGrabber && enter == popupWidget)) { - QApplicationPrivate::dispatchEnterLeave(enter, leave); - qt_last_mouse_receiver = enter; - } - } else { - QApplicationPrivate::dispatchEnterLeave(enter, leave); - qt_last_mouse_receiver = enter; - } - } else if ((!qt_button_down || !qt_last_mouse_receiver) && !mouseGrabber && !leaveAfterRelease) { - QApplicationPrivate::dispatchEnterLeave(enterLeaveWidget, qt_last_mouse_receiver); - qt_last_mouse_receiver = enterLeaveWidget; - } - } - break; } - } - - if(widget) { - QPoint p(where.h, where.v); - QPoint plocal(widget->mapFromGlobal(p)); - if(etype == QEvent::MouseButtonPress) { - qt_mac_dblclick.last_widget = widget; - qt_mac_dblclick.last_modifiers = modifiers; - qt_mac_dblclick.last_button = button; - qt_mac_dblclick.last_time = GetEventTime(event); - } - - if (wheel_deltaX || wheel_deltaY) { -#ifndef QT_NO_WHEELEVENT - if (wheel_deltaX) { - QWheelEvent qwe(plocal, p, wheel_deltaX, buttons, modifiers, Qt::Horizontal); - QApplication::sendSpontaneousEvent(widget, &qwe); - if (!qwe.isAccepted() && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != widget) { - QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(p), p, - wheel_deltaX, buttons, modifiers, Qt::Horizontal); - QApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2); - if (!qwe2.isAccepted()) - handled_event = false; - } - } - if (wheel_deltaY) { - QWheelEvent qwe(plocal, p, wheel_deltaY, buttons, modifiers, Qt::Vertical); - QApplication::sendSpontaneousEvent(widget, &qwe); - if (!qwe.isAccepted() && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != widget) { - QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(p), p, - wheel_deltaY, buttons, modifiers, Qt::Vertical); - QApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2); - if (!qwe2.isAccepted()) - handled_event = false; - } - } -#endif // QT_NO_WHEELEVENT - } else { -#ifdef QMAC_SPEAK_TO_ME - const int speak_keys = Qt::AltModifier | Qt::ShiftModifier; - if(etype == QMouseEvent::MouseButtonDblClick && ((modifiers & speak_keys) == speak_keys)) { - QVariant v = widget->property("displayText"); - if(!v.isValid()) v = widget->property("text"); - if(!v.isValid()) v = widget->property("windowTitle"); - if(v.isValid()) { - QString s = v.toString(); - s.replace(QRegExp(QString::fromLatin1("(\\&|\\<[^\\>]*\\>)")), QLatin1String("")); - SpeechChannel ch; - NewSpeechChannel(0, &ch); - SpeakText(ch, s.toLatin1().constData(), s.length()); - DisposeSpeechChannel(ch); - } - } -#endif - Qt::MouseButton buttonToSend = button; - static bool lastButtonTranslated = false; - if(ekind == kEventMouseDown && - button == Qt::LeftButton && (modifiers & Qt::MetaModifier)) { - buttonToSend = Qt::RightButton; - lastButtonTranslated = true; - } else if(ekind == kEventMouseUp && lastButtonTranslated) { - buttonToSend = Qt::RightButton; - lastButtonTranslated = false; - } - QMouseEvent qme(etype, plocal, p, buttonToSend, buttons, modifiers); - QApplication::sendSpontaneousEvent(widget, &qme); - if(!qme.isAccepted() || inNonClientArea) - handled_event = false; - } - - if (leaveAfterRelease) { - QWidget *enter = QApplication::widgetAt(where.h, where.v); - QApplicationPrivate::dispatchEnterLeave(enter, leaveAfterRelease); - qt_last_mouse_receiver = enter; - leaveAfterRelease = 0; - } - - if(ekind == kEventMouseDown && - ((button == Qt::RightButton) || - (button == Qt::LeftButton && (modifiers & Qt::MetaModifier)))) - qt_event_request_context(); - -#ifdef DEBUG_MOUSE_MAPS - const char *event_desc = edesc; - if(etype == QEvent::MouseButtonDblClick) - event_desc = "Double Click"; - else if(etype == QEvent::NonClientAreaMouseButtonPress) - event_desc = "NonClientMousePress"; - else if(etype == QEvent::NonClientAreaMouseButtonRelease) - event_desc = "NonClientMouseRelease"; - else if(etype == QEvent::NonClientAreaMouseMove) - event_desc = "NonClientMouseMove"; - else if(etype == QEvent::NonClientAreaMouseButtonDblClick) - event_desc = "NonClientMouseDblClick"; - qDebug("%d %d (%d %d) - Would send (%s) event to %p %s %s (%d 0x%08x 0x%08x %d)", p.x(), p.y(), - plocal.x(), plocal.y(), event_desc, (QWidget*)widget, - widget ? widget->objectName().toLocal8Bit().constData() : "*Unknown*", - widget ? widget->metaObject()->className() : "*Unknown*", - button, (int)buttons, (int)modifiers, wheel_deltaX); -#endif - } else { - handled_event = false; - } - break; - } - case kEventClassTextInput: - case kEventClassKeyboard: { - EventRef key_event = event; - if(eclass == kEventClassTextInput) { - Q_ASSERT(ekind == kEventTextInputUnicodeForKeyEvent); - OSStatus err = GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, 0, - sizeof(key_event), 0, &key_event); - Q_ASSERT(err == noErr); - Q_UNUSED(err); - } - const UInt32 key_ekind = GetEventKind(key_event); - Q_ASSERT(GetEventClass(key_event) == kEventClassKeyboard); - - if(key_ekind == kEventRawKeyDown) - qt_keymapper_private()->updateKeyMap(er, key_event, data); - if(mac_keyboard_grabber) - widget = mac_keyboard_grabber; - else if (app->activePopupWidget()) - widget = (app->activePopupWidget()->focusWidget() ? - app->activePopupWidget()->focusWidget() : app->activePopupWidget()); - else if(QApplication::focusWidget()) - widget = QApplication::focusWidget(); - else - widget = app->activeWindow(); - - if (widget) { - if (widget->macEvent(er, event)) - return noErr; - } else { - // Darn, I need to update tho modifier state, even though - // Qt itself isn't getting them, otherwise the keyboard state get inconsistent. - if (key_ekind == kEventRawKeyModifiersChanged) { - UInt32 modifiers = 0; - GetEventParameter(key_event, kEventParamKeyModifiers, typeUInt32, 0, - sizeof(modifiers), 0, &modifiers); - extern void qt_mac_send_modifiers_changed(quint32 modifiers, QObject *object); // qkeymapper_mac.cpp - // Just send it to the qApp for the time being. - qt_mac_send_modifiers_changed(modifiers, qApp); - } - handled_event = false; - break; - } - - if(app_do_modal && !qt_try_modal(widget, key_event)) - break; - if (eclass == kEventClassTextInput) { - handled_event = false; - } else { - handled_event = qt_keymapper_private()->translateKeyEvent(widget, er, key_event, data, - widget == mac_keyboard_grabber); - } - break; } - case kEventClassWindow: { - WindowRef wid = 0; - GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0, - sizeof(WindowRef), 0, &wid); - widget = qt_mac_find_window(wid); - if (widget && widget->macEvent(er, event)) - return noErr; - if(ekind == kEventWindowActivated) { - if(QApplicationPrivate::app_style) { - QEvent ev(QEvent::Style); - QApplication::sendSpontaneousEvent(QApplicationPrivate::app_style, &ev); - } - - if(widget && app_do_modal && !qt_try_modal(widget, event)) - break; - - if(widget && widget->window()->isVisible()) { - QWidget *tlw = widget->window(); - if(tlw->isWindow() && !(tlw->windowType() == Qt::Popup) - && !qt_mac_is_macdrawer(tlw) - && (!tlw->parentWidget() || tlw->isModal() - || !(tlw->windowType() == Qt::Tool))) { - bool just_send_event = false; - { - WindowActivationScope scope; - if(GetWindowActivationScope((WindowRef)wid, &scope) == noErr && - scope == kWindowActivationScopeIndependent) { - if(GetFrontWindowOfClass(kAllWindowClasses, true) != wid) - just_send_event = true; - } - } - if(just_send_event) { - QEvent e(QEvent::WindowActivate); - QApplication::sendSpontaneousEvent(widget, &e); - } else { - app->setActiveWindow(tlw); - } - } - QMenuBar::macUpdateMenuBar(); - } - } else if(ekind == kEventWindowDeactivated) { - if(widget && QApplicationPrivate::active_window == widget) - app->setActiveWindow(0); - } else { - handled_event = false; - } - break; } - case kEventClassApplication: - if(ekind == kEventAppActivated) { - if(QApplication::desktopSettingsAware()) - qt_mac_update_os_settings(); - if(qt_clipboard) { //manufacture an event so the clipboard can see if it has changed - QEvent ev(QEvent::Clipboard); - QApplication::sendSpontaneousEvent(qt_clipboard, &ev); - } - if(app) { - QEvent ev(QEvent::ApplicationActivate); - QApplication::sendSpontaneousEvent(app, &ev); - } - if(!app->activeWindow()) { - WindowPtr wp = ActiveNonFloatingWindow(); - if(QWidget *tmp_w = qt_mac_find_window(wp)) - app->setActiveWindow(tmp_w); - } - QMenuBar::macUpdateMenuBar(); - } else if(ekind == kEventAppDeactivated) { - //qt_mac_no_click_through_mode = false; - while(app->d_func()->inPopupMode()) - app->activePopupWidget()->close(); - if(app) { - QEvent ev(QEvent::ApplicationDeactivate); - QApplication::sendSpontaneousEvent(app, &ev); - } - app->setActiveWindow(0); - } else if(ekind == kEventAppAvailableWindowBoundsChanged) { - QDesktopWidgetImplementation::instance()->onResize(); - } else { - handled_event = false; - } - break; - case kAppearanceEventClass: - if(ekind == kAEAppearanceChanged) { - if(QApplication::desktopSettingsAware()) - qt_mac_update_os_settings(); - if(QApplicationPrivate::app_style) { - QEvent ev(QEvent::Style); - QApplication::sendSpontaneousEvent(QApplicationPrivate::app_style, &ev); - } - } else { - handled_event = false; - } - break; - case kEventClassAppleEvent: - if(ekind == kEventAppleEvent) { - EventRecord erec; - if(!ConvertEventRefToEventRecord(event, &erec)) - qDebug("Qt: internal: WH0A, unexpected condition reached. %s:%d", __FILE__, __LINE__); - else if(AEProcessAppleEvent(&erec) != noErr) - handled_event = false; - } else { - handled_event = false; - } - break; - case kEventClassCommand: - if(ekind == kEventCommandProcess) { - HICommand cmd; - GetEventParameter(event, kEventParamDirectObject, typeHICommand, - 0, sizeof(cmd), 0, &cmd); - handled_event = false; - if(!cmd.menu.menuRef && GetApplicationDockTileMenu()) { - EventRef copy = CopyEvent(event); - HICommand copy_cmd; - GetEventParameter(event, kEventParamDirectObject, typeHICommand, - 0, sizeof(copy_cmd), 0, ©_cmd); - copy_cmd.menu.menuRef = GetApplicationDockTileMenu(); - SetEventParameter(copy, kEventParamDirectObject, typeHICommand, sizeof(copy_cmd), ©_cmd); - if(SendEventToMenu(copy, copy_cmd.menu.menuRef) == noErr) - handled_event = true; - } - if(!handled_event) { - if(cmd.commandID == kHICommandQuit) { - // Quitting the application is not Qt's responsibility if - // used in a plugin or just embedded into a native application. - // In that case, let the event pass down to the native apps event handler. - if (!QApplication::testAttribute(Qt::AA_MacPluginApplication)) { - handled_event = true; - HiliteMenu(0); - bool handle_quit = true; - if(QApplicationPrivate::modalState()) { - int visible = 0; - const QWidgetList tlws = QApplication::topLevelWidgets(); - for(int i = 0; i < tlws.size(); ++i) { - if(tlws.at(i)->isVisible()) - ++visible; - } - handle_quit = (visible <= 1); - } - if(handle_quit) { - QCloseEvent ev; - QApplication::sendSpontaneousEvent(app, &ev); - if(ev.isAccepted()) - app->quit(); - } else { - QApplication::beep(); - } - } - } else if(cmd.commandID == kHICommandSelectWindow) { - if((GetCurrentKeyModifiers() & cmdKey)) - handled_event = true; - } else if(cmd.commandID == kHICommandAbout) { - QMessageBox::aboutQt(0); - HiliteMenu(0); - handled_event = true; - } - } - } - break; - } - -#ifdef DEBUG_EVENTS - qDebug("%shandled event %c%c%c%c %d", handled_event ? "(*) " : "", - char(eclass >> 24), char((eclass >> 16) & 255), char((eclass >> 8) & 255), - char(eclass & 255), (int)ekind); -#endif - if(!handled_event) //let the event go through - return eventNotHandledErr; - return noErr; //we eat the event -#else - Q_UNUSED(er); - Q_UNUSED(event); - Q_UNUSED(data); - return eventNotHandledErr; -#endif -} - -#ifdef QT_MAC_USE_COCOA -void QApplicationPrivate::qt_initAfterNSAppStarted() -{ - setupAppleEvents(); - qt_mac_update_cursor(); -} - -void QApplicationPrivate::setupAppleEvents() -{ - // This function is called from the event dispatcher when NSApplication has - // finished initialization, which appears to be just after [NSApplication run] has - // started to execute. By setting up our apple events handlers this late, we override - // the ones set up by NSApplication. - - // If Qt is used as a plugin, we let the 3rd party application handle events - // like quit and open file events. Otherwise, if we install our own handlers, we - // easily end up breaking functionallity the 3rd party application depend on: - if (QApplication::testAttribute(Qt::AA_MacPluginApplication)) - return; - - QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate]; - NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager]; - [eventManager setEventHandler:newDelegate andSelector:@selector(appleEventQuit:withReplyEvent:) - forEventClass:kCoreEventClass andEventID:kAEQuitApplication]; - [eventManager setEventHandler:newDelegate andSelector:@selector(getUrl:withReplyEvent:) - forEventClass:kInternetEventClass andEventID:kAEGetURL]; -} -#endif - -// In Carbon this is your one stop for apple events. -// In Cocoa, it ISN'T. This is the catch-all Apple Event handler that exists -// for the time between instantiating the NSApplication, but before the -// NSApplication has installed it's OWN Apple Event handler. When Cocoa has -// that set up, we remove this. So, if you are debugging problems, you likely -// want to check out QCocoaApplicationDelegate instead. -OSStatus QApplicationPrivate::globalAppleEventProcessor(const AppleEvent *ae, AppleEvent *, long handlerRefcon) -{ - QApplication *app = (QApplication *)handlerRefcon; - bool handled_event=false; - OSType aeID=typeWildCard, aeClass=typeWildCard; - AEGetAttributePtr(ae, keyEventClassAttr, typeType, 0, &aeClass, sizeof(aeClass), 0); - AEGetAttributePtr(ae, keyEventIDAttr, typeType, 0, &aeID, sizeof(aeID), 0); - if(aeClass == kCoreEventClass) { - switch(aeID) { - case kAEQuitApplication: { - extern bool qt_mac_quit_menu_item_enabled; // qmenu_mac.cpp - if (qt_mac_quit_menu_item_enabled) { - QCloseEvent ev; - QApplication::sendSpontaneousEvent(app, &ev); - if(ev.isAccepted()) { - handled_event = true; - app->quit(); - } - } else { - QApplication::beep(); // Sorry, you can't quit right now. - } - break; } - case kAEOpenDocuments: { - AEDescList docs; - if(AEGetParamDesc(ae, keyDirectObject, typeAEList, &docs) == noErr) { - long cnt = 0; - AECountItems(&docs, &cnt); - UInt8 *str_buffer = NULL; - for(int i = 0; i < cnt; i++) { - FSRef ref; - if(AEGetNthPtr(&docs, i+1, typeFSRef, 0, 0, &ref, sizeof(ref), 0) != noErr) - continue; - if(!str_buffer) - str_buffer = (UInt8 *)malloc(1024); - FSRefMakePath(&ref, str_buffer, 1024); - QFileOpenEvent ev(QString::fromUtf8((const char *)str_buffer)); - QApplication::sendSpontaneousEvent(app, &ev); - } - if(str_buffer) - free(str_buffer); - } - break; } - default: - break; - } - } else if (aeClass == kInternetEventClass) { - switch (aeID) { - case kAEGetURL: { - char urlData[1024]; - Size actualSize; - if (AEGetParamPtr(ae, keyDirectObject, typeChar, 0, urlData, - sizeof(urlData) - 1, &actualSize) == noErr) { - urlData[actualSize] = 0; - QFileOpenEvent ev(QUrl(QString::fromUtf8(urlData))); - QApplication::sendSpontaneousEvent(app, &ev); - } - break; - } - default: - break; - } - } -#ifdef DEBUG_EVENTS - qDebug("Qt: internal: %shandled Apple event! %c%c%c%c %c%c%c%c", handled_event ? "(*)" : "", - char(aeID >> 24), char((aeID >> 16) & 255), char((aeID >> 8) & 255),char(aeID & 255), - char(aeClass >> 24), char((aeClass >> 16) & 255), char((aeClass >> 8) & 255),char(aeClass & 255)); -#else - if(!handled_event) //let the event go through - return eventNotHandledErr; - return noErr; //we eat the event -#endif -} - -/*! - \fn bool QApplication::macEventFilter(EventHandlerCallRef caller, EventRef event) - - \warning This virtual function is only used under Mac OS X, and behaves different - depending on if Qt is based on Carbon or Cocoa. - - For the Carbon port, If you create an application that inherits QApplication and reimplement - this function, you get direct access to all Carbon Events that Qt registers - for from Mac OS X with this function being called with the \a caller and - the \a event. - - For the Cocoa port, If you create an application that inherits QApplication and reimplement - this function, you get direct access to all Cocoa Events that Qt receives - from Mac OS X with this function being called with the \a caller being 0 and - the \a event being an NSEvent pointer: - - NSEvent *e = reinterpret_cast<NSEvent *>(event); - - Return true if you want to stop the event from being processed. - Return false for normal event dispatching. The default - implementation returns false. - - \sa macEventFilter(void *nsevent) -*/ -bool QApplication::macEventFilter(EventHandlerCallRef, EventRef) -{ - return false; -} - -/*! - \internal -*/ -void QApplicationPrivate::openPopup(QWidget *popup) -{ - if (!QApplicationPrivate::popupWidgets) // create list - QApplicationPrivate::popupWidgets = new QWidgetList; - QApplicationPrivate::popupWidgets->append(popup); // add to end of list - - // popups are not focus-handled by the window system (the first - // popup grabbed the keyboard), so we have to do that manually: A - // new popup gets the focus - if (popup->focusWidget()) { - popup->focusWidget()->setFocus(Qt::PopupFocusReason); - } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup - popup->setFocus(Qt::PopupFocusReason); - } -} - -/*! - \internal -*/ -void QApplicationPrivate::closePopup(QWidget *popup) -{ - Q_Q(QApplication); - if (!QApplicationPrivate::popupWidgets) - return; - - QApplicationPrivate::popupWidgets->removeAll(popup); - if (popup == qt_button_down) - qt_button_down = 0; - if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup - delete QApplicationPrivate::popupWidgets; - QApplicationPrivate::popupWidgets = 0; - - // Special case for Tool windows: since they are activated and deactived together - // with a normal window they never become the QApplicationPrivate::active_window. - QWidget *appFocusWidget = QApplication::focusWidget(); - if (appFocusWidget && appFocusWidget->window()->windowType() == Qt::Tool) { - appFocusWidget->setFocus(Qt::PopupFocusReason); - } else if (QApplicationPrivate::active_window) { - if (QWidget *fw = QApplicationPrivate::active_window->focusWidget()) { - if (fw != QApplication::focusWidget()) { - fw->setFocus(Qt::PopupFocusReason); - } else { - QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason); - q->sendEvent(fw, &e); - } - } - } - } else { - // popups are not focus-handled by the window system (the - // first popup grabbed the keyboard), so we have to do that - // manually: A popup was closed, so the previous popup gets - // the focus. - QWidget* aw = QApplicationPrivate::popupWidgets->last(); - if (QWidget *fw = aw->focusWidget()) - fw->setFocus(Qt::PopupFocusReason); - } -} - -void QApplication::beep() -{ - qt_mac_beep(); -} - -void QApplication::alert(QWidget *widget, int duration) -{ - if (!QApplicationPrivate::checkInstance("alert")) - return; - - QWidgetList windowsToMark; - if (!widget) - windowsToMark += topLevelWidgets(); - else - windowsToMark.append(widget->window()); - - bool needNotification = false; - for (int i = 0; i < windowsToMark.size(); ++i) { - QWidget *window = windowsToMark.at(i); - if (!window->isActiveWindow() && window->isVisible()) { - needNotification = true; // yeah, we may set it multiple times, but that's OK. - if (duration != 0) { - QTimer *timer = new QTimer(qApp); - timer->setSingleShot(true); - connect(timer, SIGNAL(timeout()), qApp, SLOT(_q_alertTimeOut())); - if (QTimer *oldTimer = qApp->d_func()->alertTimerHash.value(widget)) { - qApp->d_func()->alertTimerHash.remove(widget); - delete oldTimer; - } - qApp->d_func()->alertTimerHash.insert(widget, timer); - timer->start(duration); - } - } - } - if (needNotification) - qt_mac_send_notification(); -} - -void QApplicationPrivate::_q_alertTimeOut() -{ - if (QTimer *timer = qobject_cast<QTimer *>(q_func()->sender())) { - QHash<QWidget *, QTimer *>::iterator it = alertTimerHash.begin(); - while (it != alertTimerHash.end()) { - if (it.value() == timer) { - alertTimerHash.erase(it); - timer->deleteLater(); - break; - } - ++it; - } - if (alertTimerHash.isEmpty()) { - qt_mac_cancel_notification(); - } - } -} - -void QApplication::setCursorFlashTime(int msecs) -{ - QApplicationPrivate::cursor_flash_time = msecs; -} - -int QApplication::cursorFlashTime() -{ - return QApplicationPrivate::cursor_flash_time; -} - -void QApplication::setDoubleClickInterval(int ms) -{ - qt_mac_dblclick.use_qt_time_limit = true; - QApplicationPrivate::mouse_double_click_time = ms; -} - -int QApplication::doubleClickInterval() -{ - if (!qt_mac_dblclick.use_qt_time_limit) { //get it from the system - QSettings appleSettings(QLatin1String("apple.com")); - /* First worked as of 10.3.3 */ - double dci = appleSettings.value(QLatin1String("com/apple/mouse/doubleClickThreshold"), 0.5).toDouble(); - return int(dci * 1000); - } - return QApplicationPrivate::mouse_double_click_time; -} - -void QApplication::setKeyboardInputInterval(int ms) -{ - QApplicationPrivate::keyboard_input_time = ms; -} - -int QApplication::keyboardInputInterval() -{ - // FIXME: get from the system - return QApplicationPrivate::keyboard_input_time; -} - -#ifndef QT_NO_WHEELEVENT -void QApplication::setWheelScrollLines(int n) -{ - QApplicationPrivate::wheel_scroll_lines = n; -} - -int QApplication::wheelScrollLines() -{ - return QApplicationPrivate::wheel_scroll_lines; -} -#endif - -void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable) -{ - switch (effect) { - case Qt::UI_FadeMenu: - QApplicationPrivate::fade_menu = enable; - break; - case Qt::UI_AnimateMenu: - QApplicationPrivate::animate_menu = enable; - break; - case Qt::UI_FadeTooltip: - QApplicationPrivate::fade_tooltip = enable; - break; - case Qt::UI_AnimateTooltip: - QApplicationPrivate::animate_tooltip = enable; - break; - case Qt::UI_AnimateCombo: - QApplicationPrivate::animate_combo = enable; - break; - case Qt::UI_AnimateToolBox: - QApplicationPrivate::animate_toolbox = enable; - break; - case Qt::UI_General: - QApplicationPrivate::fade_tooltip = true; - break; - default: - QApplicationPrivate::animate_ui = enable; - break; - } - - if (enable) - QApplicationPrivate::animate_ui = true; -} - -bool QApplication::isEffectEnabled(Qt::UIEffect effect) -{ - if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui) - return false; - - switch(effect) { - case Qt::UI_AnimateMenu: - return QApplicationPrivate::animate_menu; - case Qt::UI_FadeMenu: - return QApplicationPrivate::fade_menu; - case Qt::UI_AnimateCombo: - return QApplicationPrivate::animate_combo; - case Qt::UI_AnimateTooltip: - return QApplicationPrivate::animate_tooltip; - case Qt::UI_FadeTooltip: - return QApplicationPrivate::fade_tooltip; - case Qt::UI_AnimateToolBox: - return QApplicationPrivate::animate_toolbox; - default: - break; - } - return QApplicationPrivate::animate_ui; -} - -/*! - \internal -*/ -bool QApplicationPrivate::qt_mac_apply_settings() -{ - QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); - settings.beginGroup(QLatin1String("Qt")); - - /* - Qt settings. This is how they are written into the datastream. - Palette/ * - QPalette - font - QFont - libraryPath - QStringList - style - QString - doubleClickInterval - int - cursorFlashTime - int - wheelScrollLines - int - colorSpec - QString - defaultCodec - QString - globalStrut/width - int - globalStrut/height - int - GUIEffects - QStringList - Font Substitutions/ * - QStringList - Font Substitutions/... - QStringList - */ - - // read library (ie. plugin) path list - QString libpathkey = - QString::fromLatin1("%1.%2/libraryPath") - .arg(QT_VERSION >> 16) - .arg((QT_VERSION & 0xff00) >> 8); - QStringList pathlist = settings.value(libpathkey).toString().split(QLatin1Char(':')); - if (!pathlist.isEmpty()) { - QStringList::ConstIterator it = pathlist.begin(); - while(it != pathlist.end()) - QApplication::addLibraryPath(*it++); - } - - QString defaultcodec = settings.value(QLatin1String("defaultCodec"), QVariant(QLatin1String("none"))).toString(); - if (defaultcodec != QLatin1String("none")) { - QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1().constData()); - if (codec) - QTextCodec::setCodecForTr(codec); - } - - if (qt_is_gui_used) { - QString str; - QStringList strlist; - int num; - - // read new palette - int i; - QPalette pal(QApplication::palette()); - strlist = settings.value(QLatin1String("Palette/active")).toStringList(); - if (strlist.count() == QPalette::NColorRoles) { - for (i = 0; i < QPalette::NColorRoles; i++) - pal.setColor(QPalette::Active, (QPalette::ColorRole) i, - QColor(strlist[i])); - } - strlist = settings.value(QLatin1String("Palette/inactive")).toStringList(); - if (strlist.count() == QPalette::NColorRoles) { - for (i = 0; i < QPalette::NColorRoles; i++) - pal.setColor(QPalette::Inactive, (QPalette::ColorRole) i, - QColor(strlist[i])); - } - strlist = settings.value(QLatin1String("Palette/disabled")).toStringList(); - if (strlist.count() == QPalette::NColorRoles) { - for (i = 0; i < QPalette::NColorRoles; i++) - pal.setColor(QPalette::Disabled, (QPalette::ColorRole) i, - QColor(strlist[i])); - } - - if (pal != QApplication::palette()) - QApplication::setPalette(pal); - - // read new font - QFont font(QApplication::font()); - str = settings.value(QLatin1String("font")).toString(); - if (!str.isEmpty()) { - font.fromString(str); - if (font != QApplication::font()) - QApplication::setFont(font); - } - - // read new QStyle - QString stylename = settings.value(QLatin1String("style")).toString(); - if (! stylename.isNull() && ! stylename.isEmpty()) { - QStyle *style = QStyleFactory::create(stylename); - if (style) - QApplication::setStyle(style); - else - stylename = QLatin1String("default"); - } else { - stylename = QLatin1String("default"); - } - - num = settings.value(QLatin1String("doubleClickInterval"), - QApplication::doubleClickInterval()).toInt(); - QApplication::setDoubleClickInterval(num); - - num = settings.value(QLatin1String("cursorFlashTime"), - QApplication::cursorFlashTime()).toInt(); - QApplication::setCursorFlashTime(num); - -#ifndef QT_NO_WHEELEVENT - num = settings.value(QLatin1String("wheelScrollLines"), - QApplication::wheelScrollLines()).toInt(); - QApplication::setWheelScrollLines(num); -#endif - - QString colorspec = settings.value(QLatin1String("colorSpec"), - QVariant(QLatin1String("default"))).toString(); - if (colorspec == QLatin1String("normal")) - QApplication::setColorSpec(QApplication::NormalColor); - else if (colorspec == QLatin1String("custom")) - QApplication::setColorSpec(QApplication::CustomColor); - else if (colorspec == QLatin1String("many")) - QApplication::setColorSpec(QApplication::ManyColor); - else if (colorspec != QLatin1String("default")) - colorspec = QLatin1String("default"); - - int w = settings.value(QLatin1String("globalStrut/width")).toInt(); - int h = settings.value(QLatin1String("globalStrut/height")).toInt(); - QSize strut(w, h); - if (strut.isValid()) - QApplication::setGlobalStrut(strut); - - QStringList effects = settings.value(QLatin1String("GUIEffects")).toStringList(); - if (!effects.isEmpty()) { - if (effects.contains(QLatin1String("none"))) - QApplication::setEffectEnabled(Qt::UI_General, false); - if (effects.contains(QLatin1String("general"))) - QApplication::setEffectEnabled(Qt::UI_General, true); - if (effects.contains(QLatin1String("animatemenu"))) - QApplication::setEffectEnabled(Qt::UI_AnimateMenu, true); - if (effects.contains(QLatin1String("fademenu"))) - QApplication::setEffectEnabled(Qt::UI_FadeMenu, true); - if (effects.contains(QLatin1String("animatecombo"))) - QApplication::setEffectEnabled(Qt::UI_AnimateCombo, true); - if (effects.contains(QLatin1String("animatetooltip"))) - QApplication::setEffectEnabled(Qt::UI_AnimateTooltip, true); - if (effects.contains(QLatin1String("fadetooltip"))) - QApplication::setEffectEnabled(Qt::UI_FadeTooltip, true); - if (effects.contains(QLatin1String("animatetoolbox"))) - QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, true); - } else { - QApplication::setEffectEnabled(Qt::UI_General, true); - } - - settings.beginGroup(QLatin1String("Font Substitutions")); - QStringList fontsubs = settings.childKeys(); - if (!fontsubs.isEmpty()) { - QStringList::Iterator it = fontsubs.begin(); - for (; it != fontsubs.end(); ++it) { - QString fam = QString::fromLatin1((*it).toLatin1().constData()); - QStringList subs = settings.value(fam).toStringList(); - QFont::insertSubstitutions(fam, subs); - } - } - settings.endGroup(); - } - - settings.endGroup(); - return true; -} - -// DRSWAT - -bool QApplicationPrivate::canQuit() -{ -#ifndef QT_MAC_USE_COCOA - return true; -#else - Q_Q(QApplication); -#ifdef QT_MAC_USE_COCOA - [[NSApp mainMenu] cancelTracking]; -#else - HiliteMenu(0); -#endif - - bool handle_quit = true; - if (QApplicationPrivate::modalState() && [[[[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] - menuLoader] quitMenuItem] isEnabled]) { - int visible = 0; - const QWidgetList tlws = QApplication::topLevelWidgets(); - for(int i = 0; i < tlws.size(); ++i) { - if (tlws.at(i)->isVisible()) - ++visible; - } - handle_quit = (visible <= 1); - } - if (handle_quit) { - QCloseEvent ev; - QApplication::sendSpontaneousEvent(q, &ev); - if (ev.isAccepted()) { - return true; - } - } - return false; -#endif -} - -void onApplicationWindowChangedActivation(QWidget *widget, bool activated) -{ -#if QT_MAC_USE_COCOA - if (!widget) - return; - - if (activated) { - if (QApplicationPrivate::app_style) { - QEvent ev(QEvent::Style); - qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev); - } - qApp->setActiveWindow(widget); - } else { // deactivated - if (QApplicationPrivate::active_window == widget) - qApp->setActiveWindow(0); - } - - QMenuBar::macUpdateMenuBar(); - qt_mac_update_cursor(); -#else - Q_UNUSED(widget); - Q_UNUSED(activated); -#endif -} - - -void onApplicationChangedActivation( bool activated ) -{ -#if QT_MAC_USE_COCOA - QApplication *app = qApp; - -//NSLog(@"App Changed Activation\n"); - - if ( activated ) { - if (QApplication::desktopSettingsAware()) - qt_mac_update_os_settings(); - - if (qt_clipboard) { //manufacture an event so the clipboard can see if it has changed - QEvent ev(QEvent::Clipboard); - qt_sendSpontaneousEvent(qt_clipboard, &ev); - } - - if (app) { - QEvent ev(QEvent::ApplicationActivate); - qt_sendSpontaneousEvent(app, &ev); - } - - if (!app->activeWindow()) { - OSWindowRef wp = [NSApp keyWindow]; - if (QWidget *tmp_w = qt_mac_find_window(wp)) - app->setActiveWindow(tmp_w); - } - QMenuBar::macUpdateMenuBar(); - qt_mac_update_cursor(); - } else { // de-activated - QApplicationPrivate *priv = [[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] qAppPrivate]; - while (priv->inPopupMode()) - app->activePopupWidget()->close(); - if (app) { - QEvent ev(QEvent::ApplicationDeactivate); - qt_sendSpontaneousEvent(app, &ev); - } - app->setActiveWindow(0); - } -#else - Q_UNUSED(activated); -#endif -} - -void QApplicationPrivate::initializeMultitouch_sys() -{ } -void QApplicationPrivate::cleanupMultitouch_sys() -{ } - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qclipboard_mac.cpp b/src/gui/platforms/mac/qclipboard_mac.cpp deleted file mode 100644 index 4a8bc56e41..0000000000 --- a/src/gui/platforms/mac/qclipboard_mac.cpp +++ /dev/null @@ -1,634 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qclipboard.h" -#include "qapplication.h" -#include "qbitmap.h" -#include "qdatetime.h" -#include "qdebug.h" -#include "qapplication_p.h" -#include <private/qt_mac_p.h> -#include "qevent.h" -#include "qurl.h" -#include <stdlib.h> -#include <string.h> -#include "qt_cocoa_helpers_mac_p.h" - -QT_BEGIN_NAMESPACE - -QT_USE_NAMESPACE - -/***************************************************************************** - QClipboard debug facilities - *****************************************************************************/ -//#define DEBUG_PASTEBOARD - -#ifndef QT_NO_CLIPBOARD - -/***************************************************************************** - QClipboard member functions for mac. - *****************************************************************************/ - -static QMacPasteboard *qt_mac_pasteboards[2] = {0, 0}; - -static inline QMacPasteboard *qt_mac_pasteboard(QClipboard::Mode mode) -{ - Q_ASSERT(mode == QClipboard::Clipboard || mode == QClipboard::FindBuffer); - if (mode == QClipboard::Clipboard) - return qt_mac_pasteboards[0]; - else - return qt_mac_pasteboards[1]; -} - -static void qt_mac_cleanupPasteboard() { - delete qt_mac_pasteboards[0]; - delete qt_mac_pasteboards[1]; - qt_mac_pasteboards[0] = 0; - qt_mac_pasteboards[1] = 0; -} - -static bool qt_mac_updateScrap(QClipboard::Mode mode) -{ - if(!qt_mac_pasteboards[0]) { - qt_mac_pasteboards[0] = new QMacPasteboard(kPasteboardClipboard, QMacPasteboardMime::MIME_CLIP); - qt_mac_pasteboards[1] = new QMacPasteboard(kPasteboardFind, QMacPasteboardMime::MIME_CLIP); - qAddPostRoutine(qt_mac_cleanupPasteboard); - return true; - } - return qt_mac_pasteboard(mode)->sync(); -} - -void QClipboard::clear(Mode mode) -{ - if (!supportsMode(mode)) - return; - qt_mac_updateScrap(mode); - qt_mac_pasteboard(mode)->clear(); - setMimeData(0, mode); -} - -void QClipboard::ownerDestroyed() -{ -} - - -void QClipboard::connectNotify(const char *signal) -{ - Q_UNUSED(signal); -} - -bool QClipboard::event(QEvent *e) -{ - if(e->type() != QEvent::Clipboard) - return QObject::event(e); - - if (qt_mac_updateScrap(QClipboard::Clipboard)) { - emitChanged(QClipboard::Clipboard); - } - - if (qt_mac_updateScrap(QClipboard::FindBuffer)) { - emitChanged(QClipboard::FindBuffer); - } - - return QObject::event(e); -} - -const QMimeData *QClipboard::mimeData(Mode mode) const -{ - if (!supportsMode(mode)) - return 0; - qt_mac_updateScrap(mode); - return qt_mac_pasteboard(mode)->mimeData(); -} - -void QClipboard::setMimeData(QMimeData *src, Mode mode) -{ - if (!supportsMode(mode)) - return; - qt_mac_updateScrap(mode); - qt_mac_pasteboard(mode)->setMimeData(src); - emitChanged(mode); -} - -bool QClipboard::supportsMode(Mode mode) const -{ - return (mode == Clipboard || mode == FindBuffer); -} - -bool QClipboard::ownsMode(Mode mode) const -{ - Q_UNUSED(mode); - return false; -} - -#endif // QT_NO_CLIPBOARD - -/***************************************************************************** - QMacPasteboard code -*****************************************************************************/ - -QMacPasteboard::QMacPasteboard(PasteboardRef p, uchar mt) -{ - mac_mime_source = false; - mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL); - paste = p; - CFRetain(paste); -} - -QMacPasteboard::QMacPasteboard(uchar mt) -{ - mac_mime_source = false; - mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL); - paste = 0; - OSStatus err = PasteboardCreate(0, &paste); - if(err == noErr) { - PasteboardSetPromiseKeeper(paste, promiseKeeper, this); - } else { - qDebug("PasteBoard: Error creating pasteboard: [%d]", (int)err); - } -} - -QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt) -{ - mac_mime_source = false; - mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL); - paste = 0; - OSStatus err = PasteboardCreate(name, &paste); - if(err == noErr) { - PasteboardSetPromiseKeeper(paste, promiseKeeper, this); - } else { - qDebug("PasteBoard: Error creating pasteboard: %s [%d]", QCFString::toQString(name).toLatin1().constData(), (int)err); - } -} - -QMacPasteboard::~QMacPasteboard() -{ - // commit all promises for paste after exit close - for (int i = 0; i < promises.count(); ++i) { - const Promise &promise = promises.at(i); - QCFString flavor = QCFString(promise.convertor->flavorFor(promise.mime)); - promiseKeeper(paste, (PasteboardItemID)promise.itemId, flavor, this); - } - - if(paste) - CFRelease(paste); -} - -PasteboardRef -QMacPasteboard::pasteBoard() const -{ - return paste; -} - -OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id, CFStringRef flavor, void *_qpaste) -{ - QMacPasteboard *qpaste = (QMacPasteboard*)_qpaste; - const long promise_id = (long)id; - - // Find the kept promise - const QString flavorAsQString = QCFString::toQString(flavor); - QMacPasteboard::Promise promise; - for (int i = 0; i < qpaste->promises.size(); i++){ - QMacPasteboard::Promise tmp = qpaste->promises[i]; - if (tmp.itemId == promise_id && tmp.convertor->canConvert(tmp.mime, flavorAsQString)){ - promise = tmp; - break; - } - } - - if (!promise.itemId && flavorAsQString == QLatin1String("com.trolltech.qt.MimeTypeName")) { - // we have promised this data, but wont be able to convert, so return null data. - // This helps in making the application/x-qt-mime-type-name hidden from normal use. - QByteArray ba; - QCFType<CFDataRef> data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size()); - PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags); - return noErr; - } - - if (!promise.itemId) { - // There was no promise that could deliver data for the - // given id and flavor. This should not happend. - qDebug("Pasteboard: %d: Request for %ld, %s, but no promise found!", __LINE__, promise_id, qPrintable(flavorAsQString)); - return cantGetFlavorErr; - } - -#ifdef DEBUG_PASTEBOARD - qDebug("PasteBoard: Calling in promise for %s[%ld] [%s] (%s) [%d]", qPrintable(promise.mime), promise_id, - qPrintable(flavorAsQString), qPrintable(promise.convertor->convertorName()), promise.offset); -#endif - - QList<QByteArray> md = promise.convertor->convertFromMime(promise.mime, promise.data, flavorAsQString); - if (md.size() <= promise.offset) - return cantGetFlavorErr; - const QByteArray &ba = md[promise.offset]; - QCFType<CFDataRef> data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size()); - PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags); - return noErr; -} - -bool -QMacPasteboard::hasOSType(int c_flavor) const -{ - if (!paste) - return false; - - sync(); - - ItemCount cnt = 0; - if(PasteboardGetItemCount(paste, &cnt) || !cnt) - return false; - -#ifdef DEBUG_PASTEBOARD - qDebug("PasteBoard: hasOSType [%c%c%c%c]", (c_flavor>>24)&0xFF, (c_flavor>>16)&0xFF, - (c_flavor>>8)&0xFF, (c_flavor>>0)&0xFF); -#endif - for(uint index = 1; index <= cnt; ++index) { - - PasteboardItemID id; - if(PasteboardGetItemIdentifier(paste, index, &id) != noErr) - return false; - - QCFType<CFArrayRef> types; - if(PasteboardCopyItemFlavors(paste, id, &types ) != noErr) - return false; - - const int type_count = CFArrayGetCount(types); - for(int i = 0; i < type_count; ++i) { - CFStringRef flavor = (CFStringRef)CFArrayGetValueAtIndex(types, i); - const int os_flavor = UTGetOSTypeFromString(UTTypeCopyPreferredTagWithClass(flavor, kUTTagClassOSType)); - if(os_flavor == c_flavor) { -#ifdef DEBUG_PASTEBOARD - qDebug(" - Found!"); -#endif - return true; - } - } - } -#ifdef DEBUG_PASTEBOARD - qDebug(" - NotFound!"); -#endif - return false; -} - -bool -QMacPasteboard::hasFlavor(QString c_flavor) const -{ - if (!paste) - return false; - - sync(); - - ItemCount cnt = 0; - if(PasteboardGetItemCount(paste, &cnt) || !cnt) - return false; - -#ifdef DEBUG_PASTEBOARD - qDebug("PasteBoard: hasFlavor [%s]", qPrintable(c_flavor)); -#endif - for(uint index = 1; index <= cnt; ++index) { - - PasteboardItemID id; - if(PasteboardGetItemIdentifier(paste, index, &id) != noErr) - return false; - - PasteboardFlavorFlags flags; - if(PasteboardGetItemFlavorFlags(paste, id, QCFString(c_flavor), &flags) == noErr) { -#ifdef DEBUG_PASTEBOARD - qDebug(" - Found!"); -#endif - return true; - } - } -#ifdef DEBUG_PASTEBOARD - qDebug(" - NotFound!"); -#endif - return false; -} - -class QMacPasteboardMimeSource : public QMimeData { - const QMacPasteboard *paste; -public: - QMacPasteboardMimeSource(const QMacPasteboard *p) : QMimeData(), paste(p) { } - ~QMacPasteboardMimeSource() { } - virtual QStringList formats() const { return paste->formats(); } - virtual QVariant retrieveData(const QString &format, QVariant::Type type) const { return paste->retrieveData(format, type); } -}; - -QMimeData -*QMacPasteboard::mimeData() const -{ - if(!mime) { - mac_mime_source = true; - mime = new QMacPasteboardMimeSource(this); - - } - return mime; -} - -class QMacMimeData : public QMimeData -{ -public: - QVariant variantData(const QString &mime) { return retrieveData(mime, QVariant::Invalid); } -private: - QMacMimeData(); -}; - -void -QMacPasteboard::setMimeData(QMimeData *mime_src) -{ - if (!paste) - return; - - if (mime == mime_src || (!mime_src && mime && mac_mime_source)) - return; - mac_mime_source = false; - delete mime; - mime = mime_src; - - QList<QMacPasteboardMime*> availableConverters = QMacPasteboardMime::all(mime_type); - if (mime != 0) { - clear_helper(); - QStringList formats = mime_src->formats(); - -#ifdef QT_MAC_USE_COCOA - // QMimeData sub classes reimplementing the formats() might not expose the - // temporary "application/x-qt-mime-type-name" mimetype. So check the existence - // of this mime type while doing drag and drop. - QString dummyMimeType(QLatin1String("application/x-qt-mime-type-name")); - if (!formats.contains(dummyMimeType)) { - QByteArray dummyType = mime_src->data(dummyMimeType); - if (!dummyType.isEmpty()) { - formats.append(dummyMimeType); - } - } -#endif - for(int f = 0; f < formats.size(); ++f) { - QString mimeType = formats.at(f); - for (QList<QMacPasteboardMime *>::Iterator it = availableConverters.begin(); it != availableConverters.end(); ++it) { - QMacPasteboardMime *c = (*it); - QString flavor(c->flavorFor(mimeType)); - if(!flavor.isEmpty()) { - QVariant mimeData = static_cast<QMacMimeData*>(mime_src)->variantData(mimeType); -#if 0 - //### Grrr, why didn't I put in a virtual int QMacPasteboardMime::count()? --Sam - const int numItems = c->convertFromMime(mimeType, mimeData, flavor).size(); -#else - int numItems = 1; //this is a hack but it is much faster than allowing conversion above - if(c->convertorName() == QLatin1String("FileURL")) - numItems = mime_src->urls().count(); -#endif - for(int item = 0; item < numItems; ++item) { - const int itemID = item+1; //id starts at 1 - promises.append(QMacPasteboard::Promise(itemID, c, mimeType, mimeData, item)); - PasteboardPutItemFlavor(paste, (PasteboardItemID)itemID, QCFString(flavor), 0, kPasteboardFlavorNoFlags); -#ifdef DEBUG_PASTEBOARD - qDebug(" - adding %d %s [%s] <%s> [%d]", - itemID, qPrintable(mimeType), qPrintable(flavor), qPrintable(c->convertorName()), item); -#endif - } - } - } - } - } -} - -QStringList -QMacPasteboard::formats() const -{ - if (!paste) - return QStringList(); - - sync(); - - QStringList ret; - ItemCount cnt = 0; - if(PasteboardGetItemCount(paste, &cnt) || !cnt) - return ret; - -#ifdef DEBUG_PASTEBOARD - qDebug("PasteBoard: Formats [%d]", (int)cnt); -#endif - for(uint index = 1; index <= cnt; ++index) { - - PasteboardItemID id; - if(PasteboardGetItemIdentifier(paste, index, &id) != noErr) - continue; - - QCFType<CFArrayRef> types; - if(PasteboardCopyItemFlavors(paste, id, &types ) != noErr) - continue; - - const int type_count = CFArrayGetCount(types); - for(int i = 0; i < type_count; ++i) { - const QString flavor = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(types, i)); -#ifdef DEBUG_PASTEBOARD - qDebug(" -%s", qPrintable(QString(flavor))); -#endif - QString mimeType = QMacPasteboardMime::flavorToMime(mime_type, flavor); - if(!mimeType.isEmpty() && !ret.contains(mimeType)) { -#ifdef DEBUG_PASTEBOARD - qDebug(" -<%d> %s [%s]", ret.size(), qPrintable(mimeType), qPrintable(QString(flavor))); -#endif - ret << mimeType; - } - } - } - return ret; -} - -bool -QMacPasteboard::hasFormat(const QString &format) const -{ - if (!paste) - return false; - - sync(); - - ItemCount cnt = 0; - if(PasteboardGetItemCount(paste, &cnt) || !cnt) - return false; - -#ifdef DEBUG_PASTEBOARD - qDebug("PasteBoard: hasFormat [%s]", qPrintable(format)); -#endif - for(uint index = 1; index <= cnt; ++index) { - - PasteboardItemID id; - if(PasteboardGetItemIdentifier(paste, index, &id) != noErr) - continue; - - QCFType<CFArrayRef> types; - if(PasteboardCopyItemFlavors(paste, id, &types ) != noErr) - continue; - - const int type_count = CFArrayGetCount(types); - for(int i = 0; i < type_count; ++i) { - const QString flavor = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(types, i)); -#ifdef DEBUG_PASTEBOARD - qDebug(" -%s [0x%x]", qPrintable(QString(flavor)), mime_type); -#endif - QString mimeType = QMacPasteboardMime::flavorToMime(mime_type, flavor); -#ifdef DEBUG_PASTEBOARD - if(!mimeType.isEmpty()) - qDebug(" - %s", qPrintable(mimeType)); -#endif - if(mimeType == format) - return true; - } - } - return false; -} - -QVariant -QMacPasteboard::retrieveData(const QString &format, QVariant::Type) const -{ - if (!paste) - return QVariant(); - - sync(); - - ItemCount cnt = 0; - if(PasteboardGetItemCount(paste, &cnt) || !cnt) - return QByteArray(); - -#ifdef DEBUG_PASTEBOARD - qDebug("Pasteboard: retrieveData [%s]", qPrintable(format)); -#endif - const QList<QMacPasteboardMime *> mimes = QMacPasteboardMime::all(mime_type); - for(int mime = 0; mime < mimes.size(); ++mime) { - QMacPasteboardMime *c = mimes.at(mime); - QString c_flavor = c->flavorFor(format); - if(!c_flavor.isEmpty()) { - // Handle text/plain a little differently. Try handling Unicode first. - bool checkForUtf16 = (c_flavor == QLatin1String("com.apple.traditional-mac-plain-text") - || c_flavor == QLatin1String("public.utf8-plain-text")); - if (checkForUtf16 || c_flavor == QLatin1String("public.utf16-plain-text")) { - // Try to get the NSStringPboardType from NSPasteboard, newlines are mapped - // correctly (as '\n') in this data. The 'public.utf16-plain-text' type - // usually maps newlines to '\r' instead. - QString str = qt_mac_get_pasteboardString(paste); - if (!str.isEmpty()) - return str; - } - if (checkForUtf16 && hasFlavor(QLatin1String("public.utf16-plain-text"))) - c_flavor = QLatin1String("public.utf16-plain-text"); - - QVariant ret; - QList<QByteArray> retList; - for(uint index = 1; index <= cnt; ++index) { - PasteboardItemID id; - if(PasteboardGetItemIdentifier(paste, index, &id) != noErr) - continue; - - QCFType<CFArrayRef> types; - if(PasteboardCopyItemFlavors(paste, id, &types ) != noErr) - continue; - - const int type_count = CFArrayGetCount(types); - for(int i = 0; i < type_count; ++i) { - CFStringRef flavor = static_cast<CFStringRef>(CFArrayGetValueAtIndex(types, i)); - if(c_flavor == QCFString::toQString(flavor)) { - QCFType<CFDataRef> macBuffer; - if(PasteboardCopyItemFlavorData(paste, id, flavor, &macBuffer) == noErr) { - QByteArray buffer((const char *)CFDataGetBytePtr(macBuffer), CFDataGetLength(macBuffer)); - if(!buffer.isEmpty()) { -#ifdef DEBUG_PASTEBOARD - qDebug(" - %s [%s] (%s)", qPrintable(format), qPrintable(QCFString::toQString(flavor)), qPrintable(c->convertorName())); -#endif - buffer.detach(); //detach since we release the macBuffer - retList.append(buffer); - break; //skip to next element - } - } - } else { -#ifdef DEBUG_PASTEBOARD - qDebug(" - NoMatch %s [%s] (%s)", qPrintable(c_flavor), qPrintable(QCFString::toQString(flavor)), qPrintable(c->convertorName())); -#endif - } - } - } - - if (!retList.isEmpty()) { - ret = c->convertToMime(format, retList, c_flavor); - return ret; - } - } - } - return QVariant(); -} - -void QMacPasteboard::clear_helper() -{ - if (paste) - PasteboardClear(paste); - promises.clear(); -} - -void -QMacPasteboard::clear() -{ -#ifdef DEBUG_PASTEBOARD - qDebug("PasteBoard: clear!"); -#endif - clear_helper(); -} - -bool -QMacPasteboard::sync() const -{ - if (!paste) - return false; - const bool fromGlobal = PasteboardSynchronize(paste) & kPasteboardModified; - - if (fromGlobal) - const_cast<QMacPasteboard *>(this)->setMimeData(0); - -#ifdef DEBUG_PASTEBOARD - if(fromGlobal) - qDebug("Pasteboard: Synchronize!"); -#endif - return fromGlobal; -} - - - - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qcocoaapplication_mac.mm b/src/gui/platforms/mac/qcocoaapplication_mac.mm deleted file mode 100644 index 872f31dec7..0000000000 --- a/src/gui/platforms/mac/qcocoaapplication_mac.mm +++ /dev/null @@ -1,222 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -#include <qglobal.h> -#ifdef QT_MAC_USE_COCOA -#include <private/qcocoaapplication_mac_p.h> -#include <private/qcocoaapplicationdelegate_mac_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#include <private/qcocoaintrospection_p.h> - -QT_USE_NAMESPACE - -@implementation NSApplication (QT_MANGLE_NAMESPACE(QApplicationIntegration)) - -- (void)QT_MANGLE_NAMESPACE(qt_setDockMenu):(NSMenu *)newMenu -{ - [[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] setDockMenu:newMenu]; -} - -- (QApplicationPrivate *)QT_MANGLE_NAMESPACE(qt_qappPrivate) -{ - return [[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] qAppPrivate]; -} - -- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader) -{ - return [[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] menuLoader]; -} - -- (int)QT_MANGLE_NAMESPACE(qt_validModesForFontPanel):(NSFontPanel *)fontPanel -{ - Q_UNUSED(fontPanel); - // only display those things that QFont can handle - return NSFontPanelFaceModeMask - | NSFontPanelSizeModeMask - | NSFontPanelCollectionModeMask - | NSFontPanelUnderlineEffectModeMask - | NSFontPanelStrikethroughEffectModeMask; -} - -- (void)qt_sendPostedMessage:(NSEvent *)event -{ - // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5! - // That is why we need to split the address in two parts: - quint64 lower = [event data1]; - quint64 upper = [event data2]; - QCocoaPostMessageArgs *args = reinterpret_cast<QCocoaPostMessageArgs *>(lower | (upper << 32)); - // Special case for convenience: if the argument is an NSNumber, we unbox it directly. - // Use NSValue instead if this behaviour is unwanted. - id a1 = ([args->arg1 isKindOfClass:[NSNumber class]]) ? (id)[args->arg1 intValue] : args->arg1; - id a2 = ([args->arg2 isKindOfClass:[NSNumber class]]) ? (id)[args->arg2 intValue] : args->arg2; - switch (args->argCount) { - case 0: - [args->target performSelector:args->selector]; - break; - case 1: - [args->target performSelector:args->selector withObject:a1]; - break; - case 3: - [args->target performSelector:args->selector withObject:a1 withObject:a2]; - break; - } - - delete args; -} - -- (BOOL)qt_filterEvent:(NSEvent *)event -{ - if (qApp->macEventFilter(0, reinterpret_cast<EventRef>(event))) - return true; - - if ([event type] == NSApplicationDefined) { - switch ([event subtype]) { - case QtCocoaEventSubTypePostMessage: - [NSApp qt_sendPostedMessage:event]; - return true; - default: - break; - } - } - return false; -} - -@end - -@implementation QNSApplication - -- (void)qt_sendEvent_original:(NSEvent *)event -{ - Q_UNUSED(event); - // This method will only be used as a signature - // template for the method we add into NSApplication - // containing the original [NSApplication sendEvent:] implementation -} - -- (void)qt_sendEvent_replacement:(NSEvent *)event -{ - // This method (or its implementation to be precise) will - // be called instead of sendEvent if redirection occurs. - // 'self' will then be an instance of NSApplication - // (and not QNSApplication) - if (![NSApp qt_filterEvent:event]) - [self qt_sendEvent_original:event]; -} - -- (void)sendEvent:(NSEvent *)event -{ - // This method will be called if - // no redirection occurs - if (![NSApp qt_filterEvent:event]) - [super sendEvent:event]; -} - -- (void)qtDispatcherToQAction:(id)sender -{ - // Forward actions sendt from the menu bar (e.g. quit) to the menu loader. - // Having this method here means that we are the last stop in the responder - // chain, and that we are able to handle menu actions even when no window is - // visible on screen. Note: If Qt is used as a plugin, Qt will not use a - // native menu bar. Hence, we will also not need to do any redirection etc. as - // we do with sendEvent. - [[NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)] qtDispatcherToQAction:sender]; -} - -@end - -QT_BEGIN_NAMESPACE - -void qt_redirectNSApplicationSendEvent() -{ - if ([NSApp isMemberOfClass:[QNSApplication class]]) { - // No need to change implementation since Qt - // already controls a subclass of NSApplication - return; - } - - // Change the implementation of [NSApplication sendEvent] to the - // implementation of qt_sendEvent_replacement found in QNSApplication. - // And keep the old implementation that gets overwritten inside a new - // method 'qt_sendEvent_original' that we add to NSApplication - qt_cocoa_change_implementation( - [NSApplication class], - @selector(sendEvent:), - [QNSApplication class], - @selector(qt_sendEvent_replacement:), - @selector(qt_sendEvent_original:)); - } - -QT_END_NAMESPACE -#endif diff --git a/src/gui/platforms/mac/qcocoaapplication_mac_p.h b/src/gui/platforms/mac/qcocoaapplication_mac_p.h deleted file mode 100644 index 0c3f5e442d..0000000000 --- a/src/gui/platforms/mac/qcocoaapplication_mac_p.h +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp -// and many other. This header file may change from version to version -// without notice, or even be removed. -// -// We mean it. -// - -/* - Cocoa Application Categories -*/ -#include "qmacdefines_mac.h" -#ifdef QT_MAC_USE_COCOA -#import <AppKit/AppKit.h> -QT_FORWARD_DECLARE_CLASS(QApplicationPrivate) -@class QT_MANGLE_NAMESPACE(QCocoaMenuLoader); - -@interface NSApplication (QT_MANGLE_NAMESPACE(QApplicationIntegration)) -- (void)QT_MANGLE_NAMESPACE(qt_setDockMenu):(NSMenu *)newMenu; -- (QApplicationPrivate *)QT_MANGLE_NAMESPACE(qt_qappPrivate); -- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader); -- (int)QT_MANGLE_NAMESPACE(qt_validModesForFontPanel):(NSFontPanel *)fontPanel; - -- (void)qt_sendPostedMessage:(NSEvent *)event; -- (BOOL)qt_filterEvent:(NSEvent *)event; -@end - -@interface QNSApplication : NSApplication { -} -@end - -QT_BEGIN_NAMESPACE - -void qt_redirectNSApplicationSendEvent(); - -QT_END_NAMESPACE - -#endif diff --git a/src/gui/platforms/mac/qcocoaapplicationdelegate_mac.mm b/src/gui/platforms/mac/qcocoaapplicationdelegate_mac.mm deleted file mode 100644 index 77cd8902c3..0000000000 --- a/src/gui/platforms/mac/qcocoaapplicationdelegate_mac.mm +++ /dev/null @@ -1,354 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** - ** - ** Copyright (c) 2007-2008, Apple, Inc. - ** - ** All rights reserved. - ** - ** Redistribution and use in source and binary forms, with or without - ** modification, are permitted provided that the following conditions are met: - ** - ** * Redistributions of source code must retain the above copyright notice, - ** this list of conditions and the following disclaimer. - ** - ** * Redistributions in binary form must reproduce the above copyright notice, - ** this list of conditions and the following disclaimer in the documentation - ** and/or other materials provided with the distribution. - ** - ** * Neither the name of Apple, Inc. nor the names of its contributors - ** may be used to endorse or promote products derived from this software - ** without specific prior written permission. - ** - ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - ** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ** - ****************************************************************************/ - -#include "qmacdefines_mac.h" -#ifdef QT_MAC_USE_COCOA - -#import <private/qcocoaapplicationdelegate_mac_p.h> -#import <private/qcocoamenuloader_mac_p.h> -#import <private/qcocoaapplication_mac_p.h> -#include <private/qapplication_p.h> -#include <private/qt_mac_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#include <private/qdesktopwidget_mac_p.h> -#include <qevent.h> -#include <qurl.h> -#include <qapplication.h> - -QT_BEGIN_NAMESPACE -extern void onApplicationChangedActivation(bool); // qapplication_mac.mm -extern void qt_release_apple_event_handler(); //qapplication_mac.mm -extern QPointer<QWidget> qt_last_mouse_receiver; // qapplication_mac.cpp -extern QPointer<QWidget> qt_last_native_mouse_receiver; // qt_cocoa_helpers_mac.mm -extern QPointer<QWidget> qt_button_down; // qapplication_mac.cpp - -QT_END_NAMESPACE - -QT_FORWARD_DECLARE_CLASS(QDesktopWidgetImplementation) -QT_USE_NAMESPACE - -static QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *sharedCocoaApplicationDelegate = nil; - -static void cleanupCocoaApplicationDelegate() -{ - [sharedCocoaApplicationDelegate release]; -} - -@implementation QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) - -- (id)init -{ - self = [super init]; - if (self) - inLaunch = true; - return self; -} - -- (void)dealloc -{ - sharedCocoaApplicationDelegate = nil; - [dockMenu release]; - [qtMenuLoader release]; - if (reflectionDelegate) { - [NSApp setDelegate:reflectionDelegate]; - [reflectionDelegate release]; - } - [super dealloc]; -} - -+ (id)allocWithZone:(NSZone *)zone -{ - @synchronized(self) { - if (sharedCocoaApplicationDelegate == nil) { - sharedCocoaApplicationDelegate = [super allocWithZone:zone]; - return sharedCocoaApplicationDelegate; - qAddPostRoutine(cleanupCocoaApplicationDelegate); - } - } - return nil; -} - -+ (QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate)*)sharedDelegate -{ - @synchronized(self) { - if (sharedCocoaApplicationDelegate == nil) - [[self alloc] init]; - } - return [[sharedCocoaApplicationDelegate retain] autorelease]; -} - -- (void)setDockMenu:(NSMenu*)newMenu -{ - [newMenu retain]; - [dockMenu release]; - dockMenu = newMenu; -} - -- (NSMenu *)applicationDockMenu -{ - return [[dockMenu retain] autorelease]; -} - -- (QApplicationPrivate *)qAppPrivate -{ - return qtPrivate; -} - -- (void)setQtPrivate:(QApplicationPrivate *)value -{ - qtPrivate = value; -} - -- (void)setMenuLoader:(QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader -{ - [menuLoader retain]; - [qtMenuLoader release]; - qtMenuLoader = menuLoader; -} - -- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader -{ - return [[qtMenuLoader retain] autorelease]; -} - -// This function will only be called when NSApp is actually running. Before -// that, the kAEQuitApplication Apple event will be sent to -// QApplicationPrivate::globalAppleEventProcessor in qapplication_mac.mm -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender -{ - Q_UNUSED(sender); - // The reflection delegate gets precedence - if (reflectionDelegate - && [reflectionDelegate respondsToSelector:@selector(applicationShouldTerminate:)]) { - return [reflectionDelegate applicationShouldTerminate:sender]; - } - - if (qtPrivate->canQuit()) { - if (!startedQuit) { - startedQuit = true; - qAppInstance()->quit(); - startedQuit = false; - } - } - - if (qtPrivate->threadData->eventLoops.size() == 0) { - // INVARIANT: No event loop is executing. This probably - // means that Qt is used as a plugin, or as a part of a native - // Cocoa application. In any case it should be fine to - // terminate now: - return NSTerminateNow; - } - - return NSTerminateCancel; -} - -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification -{ - Q_UNUSED(aNotification); - inLaunch = false; - qt_release_apple_event_handler(); -} - -- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames -{ - for (NSString *fileName in filenames) { - QString qtFileName = qt_mac_NSStringToQString(fileName); - if (inLaunch) { - // We need to be careful because Cocoa will be nice enough to take - // command line arguments and send them to us as events. Given the history - // of Qt Applications, this will result in behavior people don't want, as - // they might be doing the opening themselves with the command line parsing. - if (qApp->arguments().contains(qtFileName)) - continue; - } - QFileOpenEvent foe(qtFileName); - qt_sendSpontaneousEvent(qAppInstance(), &foe); - } - - if (reflectionDelegate && - [reflectionDelegate respondsToSelector:@selector(application:openFiles:)]) - [reflectionDelegate application:sender openFiles:filenames]; -} - -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender -{ - // If we have a reflection delegate, that will get to call the shots. - if (reflectionDelegate - && [reflectionDelegate respondsToSelector: - @selector(applicationShouldTerminateAfterLastWindowClosed:)]) - return [reflectionDelegate applicationShouldTerminateAfterLastWindowClosed:sender]; - return NO; // Someday qApp->quitOnLastWindowClosed(); when QApp and NSApp work closer together. -} - - -- (void)applicationDidBecomeActive:(NSNotification *)notification -{ - if (reflectionDelegate - && [reflectionDelegate respondsToSelector:@selector(applicationDidBecomeActive:)]) - [reflectionDelegate applicationDidBecomeActive:notification]; - - onApplicationChangedActivation(true); - - if (!QWidget::mouseGrabber()){ - // Update enter/leave immidiatly, don't wait for a move event. But only - // if no grab exists (even if the grab points to this widget, it seems, ref X11) - QPoint qlocal, qglobal; - QWidget *widgetUnderMouse = 0; - qt_mac_getTargetForMouseEvent(0, QEvent::Enter, qlocal, qglobal, 0, &widgetUnderMouse); - QApplicationPrivate::dispatchEnterLeave(widgetUnderMouse, 0); - qt_last_mouse_receiver = widgetUnderMouse; - qt_last_native_mouse_receiver = widgetUnderMouse ? - (widgetUnderMouse->internalWinId() ? widgetUnderMouse : widgetUnderMouse->nativeParentWidget()) : 0; - } -} - -- (void)applicationDidResignActive:(NSNotification *)notification -{ - if (reflectionDelegate - && [reflectionDelegate respondsToSelector:@selector(applicationDidResignActive:)]) - [reflectionDelegate applicationDidResignActive:notification]; - - onApplicationChangedActivation(false); - - if (!QWidget::mouseGrabber()) - QApplicationPrivate::dispatchEnterLeave(0, qt_last_mouse_receiver); - qt_last_mouse_receiver = 0; - qt_last_native_mouse_receiver = 0; - qt_button_down = 0; -} - -- (void)applicationDidChangeScreenParameters:(NSNotification *)notification -{ - Q_UNUSED(notification); - QDesktopWidgetImplementation::instance()->onResize(); -} - -- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate -{ - [oldDelegate retain]; - [reflectionDelegate release]; - reflectionDelegate = oldDelegate; -} - -- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector -{ - NSMethodSignature *result = [super methodSignatureForSelector:aSelector]; - if (!result && reflectionDelegate) { - result = [reflectionDelegate methodSignatureForSelector:aSelector]; - } - return result; -} - -- (BOOL)respondsToSelector:(SEL)aSelector -{ - BOOL result = [super respondsToSelector:aSelector]; - if (!result && reflectionDelegate) - result = [reflectionDelegate respondsToSelector:aSelector]; - return result; -} - -- (void)forwardInvocation:(NSInvocation *)invocation -{ - SEL invocationSelector = [invocation selector]; - if (reflectionDelegate && [reflectionDelegate respondsToSelector:invocationSelector]) - [invocation invokeWithTarget:reflectionDelegate]; - else - [self doesNotRecognizeSelector:invocationSelector]; -} - -- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent -{ - Q_UNUSED(replyEvent); - - NSString *urlString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue]; - QUrl url(qt_mac_NSStringToQString(urlString)); - QFileOpenEvent qtEvent(url); - qt_sendSpontaneousEvent(qAppInstance(), &qtEvent); -} - -- (void)appleEventQuit:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent -{ - Q_UNUSED(event); - Q_UNUSED(replyEvent); - [NSApp terminate:self]; -} - -- (void)qtDispatcherToQAction:(id)sender -{ - [[NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)] qtDispatcherToQAction:sender]; -} - -@end -#endif diff --git a/src/gui/platforms/mac/qcocoaapplicationdelegate_mac_p.h b/src/gui/platforms/mac/qcocoaapplicationdelegate_mac_p.h deleted file mode 100644 index 714c046f48..0000000000 --- a/src/gui/platforms/mac/qcocoaapplicationdelegate_mac_p.h +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -/**************************************************************************** - ** - ** Copyright (c) 2007-2008, Apple, Inc. - ** - ** All rights reserved. - ** - ** Redistribution and use in source and binary forms, with or without - ** modification, are permitted provided that the following conditions are met: - ** - ** * Redistributions of source code must retain the above copyright notice, - ** this list of conditions and the following disclaimer. - ** - ** * Redistributions in binary form must reproduce the above copyright notice, - ** this list of conditions and the following disclaimer in the documentation - ** and/or other materials provided with the distribution. - ** - ** * Neither the name of Apple, Inc. nor the names of its contributors - ** may be used to endorse or promote products derived from this software - ** without specific prior written permission. - ** - ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - ** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ** - ****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp -// and many other. This header file may change from version to version -// without notice, or even be removed. -// -// We mean it. -// - - -#include "qmacdefines_mac.h" -#ifdef QT_MAC_USE_COCOA -#import <Cocoa/Cocoa.h> - -QT_FORWARD_DECLARE_CLASS(QApplicationPrivate); - -@class QT_MANGLE_NAMESPACE(QCocoaMenuLoader); - -#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 - -@protocol NSApplicationDelegate <NSObject> -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification; -- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames; -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender; -- (void)applicationDidBecomeActive:(NSNotification *)notification; -- (void)applicationDidResignActive:(NSNotification *)notification; -@end - -#endif - -@interface QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) : NSObject <NSApplicationDelegate> { - bool startedQuit; - QApplicationPrivate *qtPrivate; - NSMenu *dockMenu; - QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader; - NSObject <NSApplicationDelegate> *reflectionDelegate; - bool inLaunch; -} -+ (QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate)*)sharedDelegate; -- (void)setDockMenu:(NSMenu *)newMenu; -- (void)setQtPrivate:(QApplicationPrivate *)value; -- (QApplicationPrivate *)qAppPrivate; -- (void)setMenuLoader:(QT_MANGLE_NAMESPACE(QCocoaMenuLoader)*)menuLoader; -- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader; -- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate; -- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent; -@end -#endif diff --git a/src/gui/platforms/mac/qcocoaintrospection_mac.mm b/src/gui/platforms/mac/qcocoaintrospection_mac.mm deleted file mode 100644 index 70c893aeec..0000000000 --- a/src/gui/platforms/mac/qcocoaintrospection_mac.mm +++ /dev/null @@ -1,125 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -#include <private/qcocoaintrospection_p.h> - -QT_BEGIN_NAMESPACE - -void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel, SEL backupSel) -{ -#ifndef QT_MAC_USE_COCOA - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) -#endif - { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - // The following code replaces the _implementation_ for the selector we want to hack - // (originalSel) with the implementation found in proxyClass. Then it creates - // a new 'backup' method inside baseClass containing the old, original, - // implementation (fakeSel). You can let the proxy implementation of originalSel - // call fakeSel if needed (similar approach to calling a super class implementation). - // fakeSel must also be implemented in proxyClass, as the signature is used - // as template for the method one we add into baseClass. - // NB: You will typically never create any instances of proxyClass; we use it - // only for stealing its contents and put it into baseClass. - if (!replacementSel) - replacementSel = originalSel; - - Method originalMethod = class_getInstanceMethod(baseClass, originalSel); - Method replacementMethod = class_getInstanceMethod(proxyClass, replacementSel); - IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(replacementMethod)); - - if (backupSel) { - Method backupMethod = class_getInstanceMethod(proxyClass, backupSel); - class_addMethod(baseClass, backupSel, originalImp, method_getTypeEncoding(backupMethod)); - } -#endif - } -} - -void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel) -{ -#ifndef QT_MAC_USE_COCOA - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) -#endif - { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - Method originalMethod = class_getInstanceMethod(baseClass, originalSel); - Method backupMethodInBaseClass = class_getInstanceMethod(baseClass, backupSel); - method_setImplementation(originalMethod, method_getImplementation(backupMethodInBaseClass)); -#endif - } -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qcocoaintrospection_p.h b/src/gui/platforms/mac/qcocoaintrospection_p.h deleted file mode 100644 index 1c7d6ac13c..0000000000 --- a/src/gui/platforms/mac/qcocoaintrospection_p.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -#include <qglobal.h> -#import <objc/objc-class.h> - -QT_BEGIN_NAMESPACE - -void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel = 0, SEL backupSel = 0); -void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel); - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qcocoamenuloader_mac.mm b/src/gui/platforms/mac/qcocoamenuloader_mac.mm deleted file mode 100644 index 71ff011069..0000000000 --- a/src/gui/platforms/mac/qcocoamenuloader_mac.mm +++ /dev/null @@ -1,264 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmacdefines_mac.h" -#ifdef QT_MAC_USE_COCOA -#include <qaction.h> -#include <qcoreapplication.h> -#include <private/qcocoamenuloader_mac_p.h> -#include <private/qapplication_p.h> -#include <private/qt_mac_p.h> -#include <private/qmenubar_p.h> -#include <qmenubar.h> -#include <private/qt_cocoa_helpers_mac_p.h> - -QT_FORWARD_DECLARE_CLASS(QCFString) -QT_FORWARD_DECLARE_CLASS(QString) - -#ifndef QT_NO_TRANSLATION - QT_BEGIN_NAMESPACE - extern QString qt_mac_applicationmenu_string(int type); - QT_END_NAMESPACE -#endif - -QT_USE_NAMESPACE - -@implementation QT_MANGLE_NAMESPACE(QCocoaMenuLoader) - -- (void)awakeFromNib -{ - servicesItem = [[appMenu itemWithTitle:@"Services"] retain]; - hideAllOthersItem = [[appMenu itemWithTitle:@"Hide Others"] retain]; - showAllItem = [[appMenu itemWithTitle:@"Show All"] retain]; - - // Get the names in the nib to match the app name set by Qt. - const NSString *appName = reinterpret_cast<const NSString*>(QCFString::toCFStringRef(qAppName())); - [quitItem setTitle:[[quitItem title] stringByReplacingOccurrencesOfString:@"NewApplication" - withString:const_cast<NSString *>(appName)]]; - [hideItem setTitle:[[hideItem title] stringByReplacingOccurrencesOfString:@"NewApplication" - withString:const_cast<NSString *>(appName)]]; - [aboutItem setTitle:[[aboutItem title] stringByReplacingOccurrencesOfString:@"NewApplication" - withString:const_cast<NSString *>(appName)]]; - [appName release]; - // Disable the items that don't do anything. If someone associates a QAction with them - // They should get synced back in. - [preferencesItem setEnabled:NO]; - [preferencesItem setHidden:YES]; - [aboutItem setEnabled:NO]; - [aboutItem setHidden:YES]; -} - -- (void)ensureAppMenuInMenu:(NSMenu *)menu -{ - // The application menu is the menu in the menu bar that contains the - // 'Quit' item. When changing menu bar (e.g when switching between - // windows with different menu bars), we never recreate this menu, but - // instead pull it out the current menu bar and place into the new one: - NSMenu *mainMenu = [NSApp mainMenu]; - if ([NSApp mainMenu] == menu) - return; // nothing to do (menu is the current menu bar)! - -#ifndef QT_NAMESPACE - Q_ASSERT(mainMenu); -#endif - // Grab the app menu out of the current menu. - int numItems = [mainMenu numberOfItems]; - NSMenuItem *oldAppMenuItem = 0; - for (int i = 0; i < numItems; ++i) { - NSMenuItem *item = [mainMenu itemAtIndex:i]; - if ([item submenu] == appMenu) { - oldAppMenuItem = item; - [oldAppMenuItem retain]; - [mainMenu removeItemAtIndex:i]; - break; - } - } - - if (oldAppMenuItem) { - [oldAppMenuItem setSubmenu:nil]; - [oldAppMenuItem release]; - NSMenuItem *appMenuItem = [[NSMenuItem alloc] initWithTitle:@"Apple" - action:nil keyEquivalent:@""]; - [appMenuItem setSubmenu:appMenu]; - [menu insertItem:appMenuItem atIndex:0]; - } -} - -- (void)removeActionsFromAppMenu -{ - for (NSMenuItem *item in [appMenu itemArray]) - [item setTag:nil]; -} - -- (void)dealloc -{ - [servicesItem release]; - [hideAllOthersItem release]; - [showAllItem release]; - - [lastAppSpecificItem release]; - [theMenu release]; - [appMenu release]; - [super dealloc]; -} - -- (NSMenu *)menu -{ - return [[theMenu retain] autorelease]; -} - -- (NSMenu *)applicationMenu -{ - return [[appMenu retain] autorelease]; -} - -- (NSMenuItem *)quitMenuItem -{ - return [[quitItem retain] autorelease]; -} - -- (NSMenuItem *)preferencesMenuItem -{ - return [[preferencesItem retain] autorelease]; -} - -- (NSMenuItem *)aboutMenuItem -{ - return [[aboutItem retain] autorelease]; -} - -- (NSMenuItem *)aboutQtMenuItem -{ - return [[aboutQtItem retain] autorelease]; -} - -- (NSMenuItem *)hideMenuItem -{ - return [[hideItem retain] autorelease]; -} - -- (NSMenuItem *)appSpecificMenuItem -{ - // Create an App-Specific menu item, insert it into the menu and return - // it as an autorelease item. - NSMenuItem *item = [[NSMenuItem alloc] init]; - - NSInteger location; - if (lastAppSpecificItem == nil) { - location = [appMenu indexOfItem:aboutQtItem]; - } else { - location = [appMenu indexOfItem:lastAppSpecificItem]; - [lastAppSpecificItem release]; - } - lastAppSpecificItem = item; // Keep track of this for later (i.e., don't release it) - [appMenu insertItem:item atIndex:location + 1]; - - return [[item retain] autorelease]; -} - -- (BOOL) acceptsFirstResponder -{ - return YES; -} - -- (void)terminate:(id)sender -{ - [NSApp terminate:sender]; -} - -- (void)orderFrontStandardAboutPanel:(id)sender -{ - [NSApp orderFrontStandardAboutPanel:sender]; -} - -- (void)hideOtherApplications:(id)sender -{ - [NSApp hideOtherApplications:sender]; -} - -- (void)unhideAllApplications:(id)sender -{ - [NSApp unhideAllApplications:sender]; -} - -- (void)hide:(id)sender -{ - [NSApp hide:sender]; -} - -- (void)qtUpdateMenubar -{ - QMenuBarPrivate::macUpdateMenuBarImmediatly(); -} - -- (void)qtTranslateApplicationMenu -{ -#ifndef QT_NO_TRANSLATION - [servicesItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(0))]; - [hideItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(1).arg(qAppName()))]; - [hideAllOthersItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(2))]; - [showAllItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(3))]; - [preferencesItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(4))]; - [quitItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(5).arg(qAppName()))]; - [aboutItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(6).arg(qAppName()))]; -#endif -} - -- (IBAction)qtDispatcherToQAction:(id)sender -{ - QScopedLoopLevelCounter loopLevelCounter(QApplicationPrivate::instance()->threadData); - NSMenuItem *item = static_cast<NSMenuItem *>(sender); - if (QAction *action = reinterpret_cast<QAction *>([item tag])) { - action->trigger(); - } else if (item == quitItem) { - // We got here because someone was once the quitItem, but it has been - // abandoned (e.g., the menubar was deleted). In the meantime, just do - // normal QApplication::quit(). - qApp->quit(); - } -} - - - (void)orderFrontCharacterPalette:(id)sender - { - [NSApp orderFrontCharacterPalette:sender]; - } -@end -#endif // QT_MAC_USE_COCOA diff --git a/src/gui/platforms/mac/qcocoamenuloader_mac_p.h b/src/gui/platforms/mac/qcocoamenuloader_mac_p.h deleted file mode 100644 index cfcc7e00c6..0000000000 --- a/src/gui/platforms/mac/qcocoamenuloader_mac_p.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QCOCOAMENULOADER_P_H -#define QCOCOAMENULOADER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -#include "qmacdefines_mac.h" -#ifdef QT_MAC_USE_COCOA -#import <Cocoa/Cocoa.h> - -@interface QT_MANGLE_NAMESPACE(QCocoaMenuLoader) : NSResponder -{ - IBOutlet NSMenu *theMenu; - IBOutlet NSMenu *appMenu; - IBOutlet NSMenuItem *quitItem; - IBOutlet NSMenuItem *preferencesItem; - IBOutlet NSMenuItem *aboutItem; - IBOutlet NSMenuItem *aboutQtItem; - IBOutlet NSMenuItem *hideItem; - NSMenuItem *lastAppSpecificItem; - NSMenuItem *servicesItem; - NSMenuItem *hideAllOthersItem; - NSMenuItem *showAllItem; -} -- (void)ensureAppMenuInMenu:(NSMenu *)menu; -- (void)removeActionsFromAppMenu; -- (NSMenu *)applicationMenu; -- (NSMenu *)menu; -- (NSMenuItem *)quitMenuItem; -- (NSMenuItem *)preferencesMenuItem; -- (NSMenuItem *)aboutMenuItem; -- (NSMenuItem *)aboutQtMenuItem; -- (NSMenuItem *)hideMenuItem; -- (NSMenuItem *)appSpecificMenuItem; -- (IBAction)terminate:(id)sender; -- (IBAction)orderFrontStandardAboutPanel:(id)sender; -- (IBAction)hideOtherApplications:(id)sender; -- (IBAction)unhideAllApplications:(id)sender; -- (IBAction)hide:(id)sender; -- (IBAction)qtDispatcherToQAction:(id)sender; -- (void)qtUpdateMenubar; -- (void)orderFrontCharacterPalette:(id)sender; -@end - -#endif // QT_MAC_USE_COCOA -#endif // QCOCOAMENULOADER_P_H diff --git a/src/gui/platforms/mac/qcocoapanel_mac.mm b/src/gui/platforms/mac/qcocoapanel_mac.mm deleted file mode 100644 index 67a12e25f8..0000000000 --- a/src/gui/platforms/mac/qcocoapanel_mac.mm +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#import <private/qcocoapanel_mac_p.h> -#ifdef QT_MAC_USE_COCOA -#import <private/qt_cocoa_helpers_mac_p.h> -#import <private/qcocoawindow_mac_p.h> -#import <private/qcocoawindowdelegate_mac_p.h> -#import <private/qcocoaview_mac_p.h> -#import <private/qcocoawindowcustomthemeframe_mac_p.h> -#import <private/qcocoaapplication_mac_p.h> -#import <private/qmultitouch_mac_p.h> -#import <private/qapplication_p.h> -#import <private/qbackingstore_p.h> -#import <private/qdnd_p.h> - -#include <QtGui/QWidget> - -QT_FORWARD_DECLARE_CLASS(QWidget); -QT_USE_NAMESPACE - -@implementation QT_MANGLE_NAMESPACE(QCocoaPanel) - -/*********************************************************************** - Copy and Paste between QCocoaWindow and QCocoaPanel - This is a bit unfortunate, but thanks to the dynamic dispatch we - have to duplicate this code or resort to really silly forwarding methods -**************************************************************************/ -#include "qcocoasharedwindowmethods_mac_p.h" - -@end -#endif diff --git a/src/gui/platforms/mac/qcocoapanel_mac_p.h b/src/gui/platforms/mac/qcocoapanel_mac_p.h deleted file mode 100644 index 542615903e..0000000000 --- a/src/gui/platforms/mac/qcocoapanel_mac_p.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QCOCOAPANEL_MAC_P -#define QCOCOAPANEL_MAC_P - -#include "qmacdefines_mac.h" -#ifdef QT_MAC_USE_COCOA -#import <Cocoa/Cocoa.h> - -QT_FORWARD_DECLARE_CLASS(QStringList); -QT_FORWARD_DECLARE_CLASS(QCocoaDropData); - -@interface NSPanel (QtIntegration) -- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender; -- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender; -- (void)draggingExited:(id <NSDraggingInfo>)sender; -- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender; -@end - -@interface QT_MANGLE_NAMESPACE(QCocoaPanel) : NSPanel { - QStringList *currentCustomDragTypes; - QCocoaDropData *dropData; - NSInteger dragEnterSequence; -} - -+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; -- (void)registerDragTypes; -- (void)drawRectOriginal:(NSRect)rect; - -@end -#endif - -#endif diff --git a/src/gui/platforms/mac/qcocoasharedwindowmethods_mac_p.h b/src/gui/platforms/mac/qcocoasharedwindowmethods_mac_p.h deleted file mode 100644 index ee1115bd4e..0000000000 --- a/src/gui/platforms/mac/qcocoasharedwindowmethods_mac_p.h +++ /dev/null @@ -1,610 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** - NB: This is not a header file, dispite the file name suffix. This file is - included directly into the source code of qcocoawindow_mac.mm and - qcocoapanel_mac.mm to avoid manually doing copy and paste of the exact - same code needed at both places. This solution makes it more difficult - to e.g fix a bug in qcocoawindow_mac.mm, but forget to do the same in - qcocoapanel_mac.mm. - The reason we need to do copy and paste in the first place, rather than - resolve to method overriding, is that QCocoaPanel needs to inherit from - NSPanel, while QCocoaWindow needs to inherit NSWindow rather than NSPanel). -****************************************************************************/ - -// WARNING: Don't include any header files from within this file. Put them -// directly into qcocoawindow_mac_p.h and qcocoapanel_mac_p.h - -QT_BEGIN_NAMESPACE -extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm -extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp -extern const QStringList& qEnabledDraggedTypes(); // qmime_mac.cpp -extern void qt_event_request_window_change(QWidget *); // qapplication_mac.mm -extern void qt_mac_send_posted_gl_updates(QWidget *widget); // qapplication_mac.mm - -Q_GLOBAL_STATIC(QPointer<QWidget>, currentDragTarget); -QT_END_NAMESPACE - -- (id)initWithContentRect:(NSRect)contentRect - styleMask:(NSUInteger)windowStyle - backing:(NSBackingStoreType)bufferingType - defer:(BOOL)deferCreation -{ - self = [super initWithContentRect:contentRect styleMask:windowStyle - backing:bufferingType defer:deferCreation]; - if (self) { - currentCustomDragTypes = 0; - } - return self; -} - -- (void)dealloc -{ - delete currentCustomDragTypes; - [super dealloc]; -} - -- (BOOL)canBecomeKeyWindow -{ - QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)]; - if (!widget) - return NO; // This should happen only for qt_root_win - if (QApplicationPrivate::isBlockedByModal(widget)) - return NO; - - bool isToolTip = (widget->windowType() == Qt::ToolTip); - bool isPopup = (widget->windowType() == Qt::Popup); - return !(isPopup || isToolTip); -} - -- (BOOL)canBecomeMainWindow -{ - QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)]; - if (!widget) - return NO; // This should happen only for qt_root_win - if ([self isSheet]) - return NO; - - bool isToolTip = (widget->windowType() == Qt::ToolTip); - bool isPopup = (widget->windowType() == Qt::Popup); - bool isTool = (widget->windowType() == Qt::Tool); - return !(isPopup || isToolTip || isTool); -} - -- (void)becomeMainWindow -{ - [super becomeMainWindow]; - // Cocoa sometimes tell a hidden window to become the - // main window (and as such, show it). This can e.g - // happend when the application gets activated. If - // this is the case, we tell it to hide again: - if (![self isVisible]) - [self orderOut:self]; -} - -- (void)toggleToolbarShown:(id)sender -{ - macSendToolbarChangeEvent([self QT_MANGLE_NAMESPACE(qt_qwidget)]); - [super toggleToolbarShown:sender]; -} - -- (void)flagsChanged:(NSEvent *)theEvent -{ - qt_dispatchModifiersChanged(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); - [super flagsChanged:theEvent]; -} - - -- (void)tabletProximity:(NSEvent *)tabletEvent -{ - qt_dispatchTabletProximityEvent(tabletEvent); -} - -- (void)terminate:(id)sender -{ - // This function is called from the quit item in the menubar when this window - // is in the first responder chain (see also qtDispatcherToQAction above) - [NSApp terminate:sender]; -} - -- (void)setLevel:(NSInteger)windowLevel -{ - // Cocoa will upon activating/deactivating applications level modal - // windows up and down, regardsless of any explicit set window level. - // To ensure that modal stays-on-top dialogs actually stays on top after - // the application is activated (and therefore stacks in front of - // other stays-on-top windows), we need to add this little special-case override: - QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; - if (widget && widget->isModal() && (widget->windowFlags() & Qt::WindowStaysOnTopHint)) - [super setLevel:NSPopUpMenuWindowLevel]; - else - [super setLevel:windowLevel]; -} - -- (void)sendEvent:(NSEvent *)event -{ - [self retain]; - - bool handled = false; - switch([event type]) { - case NSMouseMoved: - // Cocoa sends move events to a parent and all its children under the mouse, much - // like Qt handles hover events. But we only want to handle the move event once, so - // to optimize a bit (since we subscribe for move event for all views), we handle it - // here before this logic happends. Note: it might be tempting to do this shortcut for - // all mouse events. The problem is that Cocoa does more than just find the correct view - // when sending the event, like raising windows etc. So avoid it as much as possible: - handled = qt_mac_handleMouseEvent(event, QEvent::MouseMove, Qt::NoButton, 0); - break; - default: - break; - } - - if (!handled) { - [super sendEvent:event]; - qt_mac_handleNonClientAreaMouseEvent(self, event); - } - [self release]; -} - -- (void)setInitialFirstResponder:(NSView *)view -{ - // This method is called the first time the window is placed on screen and - // is the earliest point in time we can connect OpenGL contexts to NSViews. - QWidget *qwidget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; - if (qwidget) { - qt_event_request_window_change(qwidget); - qt_mac_send_posted_gl_updates(qwidget); - } - - [super setInitialFirstResponder:view]; -} - -- (BOOL)makeFirstResponder:(NSResponder *)responder -{ - // For some reason Cocoa wants to flip the first responder - // when Qt doesn't want to, sorry, but "No" :-) - if (responder == nil && qApp->focusWidget()) - return NO; - return [super makeFirstResponder:responder]; -} - -+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask -{ - if (styleMask & QtMacCustomizeWindow) - return [QT_MANGLE_NAMESPACE(QCocoaWindowCustomThemeFrame) class]; - return [super frameViewClassForStyleMask:styleMask]; -} - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 -- (void)touchesBeganWithEvent:(NSEvent *)event; -{ - QPoint qlocal, qglobal; - QWidget *widgetToGetTouch = 0; - qt_mac_getTargetForMouseEvent(event, QEvent::Gesture, qlocal, qglobal, 0, &widgetToGetTouch); - if (!widgetToGetTouch) - return; - - bool all = widgetToGetTouch->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents); - qt_translateRawTouchEvent(widgetToGetTouch, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all)); -} - -- (void)touchesMovedWithEvent:(NSEvent *)event; -{ - QPoint qlocal, qglobal; - QWidget *widgetToGetTouch = 0; - qt_mac_getTargetForMouseEvent(event, QEvent::Gesture, qlocal, qglobal, 0, &widgetToGetTouch); - if (!widgetToGetTouch) - return; - - bool all = widgetToGetTouch->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents); - qt_translateRawTouchEvent(widgetToGetTouch, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all)); -} - -- (void)touchesEndedWithEvent:(NSEvent *)event; -{ - QPoint qlocal, qglobal; - QWidget *widgetToGetTouch = 0; - qt_mac_getTargetForMouseEvent(event, QEvent::Gesture, qlocal, qglobal, 0, &widgetToGetTouch); - if (!widgetToGetTouch) - return; - - bool all = widgetToGetTouch->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents); - qt_translateRawTouchEvent(widgetToGetTouch, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all)); -} - -- (void)touchesCancelledWithEvent:(NSEvent *)event; -{ - QPoint qlocal, qglobal; - QWidget *widgetToGetTouch = 0; - qt_mac_getTargetForMouseEvent(event, QEvent::Gesture, qlocal, qglobal, 0, &widgetToGetTouch); - if (!widgetToGetTouch) - return; - - bool all = widgetToGetTouch->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents); - qt_translateRawTouchEvent(widgetToGetTouch, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all)); -} -#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - --(void)registerDragTypes -{ - // Calling registerForDraggedTypes below is slow, so only do - // it once for each window, or when the custom types change. - QMacCocoaAutoReleasePool pool; - const QStringList& customTypes = qEnabledDraggedTypes(); - if (currentCustomDragTypes == 0 || *currentCustomDragTypes != customTypes) { - if (currentCustomDragTypes == 0) - currentCustomDragTypes = new QStringList(); - *currentCustomDragTypes = customTypes; - const NSString* mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName"; - NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType, - NSFilenamesPboardType, NSStringPboardType, - NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType, - NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType, - NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType, - NSRTFDPboardType, NSHTMLPboardType, NSPICTPboardType, - NSURLPboardType, NSPDFPboardType, NSVCardPboardType, - NSFilesPromisePboardType, NSInkTextPboardType, - NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil]; - // Add custom types supported by the application. - for (int i = 0; i < customTypes.size(); i++) { - [supportedTypes addObject:qt_mac_QStringToNSString(customTypes[i])]; - } - [self registerForDraggedTypes:supportedTypes]; - } -} - -- (void)removeDropData -{ - if (dropData) { - delete dropData; - dropData = 0; - } -} - -- (void)addDropData:(id <NSDraggingInfo>)sender -{ - [self removeDropData]; - CFStringRef dropPasteboard = (CFStringRef) [[sender draggingPasteboard] name]; - dropData = new QCocoaDropData(dropPasteboard); -} - -- (void)changeDraggingCursor:(NSDragOperation)newOperation -{ - static SEL action = nil; - static bool operationSupported = false; - if (action == nil) { - action = NSSelectorFromString(@"operationNotAllowedCursor"); - if ([NSCursor respondsToSelector:action]) { - operationSupported = true; - } - } - if (operationSupported) { - NSCursor *notAllowedCursor = [NSCursor performSelector:action]; - bool isNotAllowedCursor = ([NSCursor currentCursor] == notAllowedCursor); - if (newOperation == NSDragOperationNone && !isNotAllowedCursor) { - [notAllowedCursor push]; - } else if (newOperation != NSDragOperationNone && isNotAllowedCursor) { - [notAllowedCursor pop]; - } - - } -} - -- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender -{ - // The user dragged something into the window. Send a draggingEntered message - // to the QWidget under the mouse. As the drag moves over the window, and over - // different widgets, we will handle enter and leave events from within - // draggingUpdated below. The reason why we handle this ourselves rather than - // subscribing for drag events directly in QCocoaView is that calling - // registerForDraggedTypes on the views will severly degrade initialization time - // for an application that uses a lot of drag subscribing widgets. - - NSPoint nswindowPoint = [sender draggingLocation]; - NSPoint nsglobalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:nswindowPoint]; - QPoint globalPoint = flipPoint(nsglobalPoint).toPoint(); - - QWidget *qwidget = QApplication::widgetAt(globalPoint); - *currentDragTarget() = qwidget; - if (!qwidget) - return [super draggingEntered:sender]; - if (qwidget->testAttribute(Qt::WA_DropSiteRegistered) == false) - return NSDragOperationNone; - - [self addDropData:sender]; - - QMimeData *mimeData = dropData; - if (QDragManager::self()->source()) - mimeData = QDragManager::self()->dragPrivate()->data; - - NSDragOperation nsActions = [sender draggingSourceOperationMask]; - Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations(nsActions); - QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) = nsActions; - Qt::KeyboardModifiers modifiers = Qt::NoModifier; - - if ([sender draggingSource] != nil) { - // modifier flags might have changed, update it here since we don't send any input events. - QApplicationPrivate::modifier_buttons = qt_cocoaModifiers2QtModifiers([[NSApp currentEvent] modifierFlags]); - modifiers = QApplication::keyboardModifiers(); - } else { - // when the source is from another application the above technique will not work. - modifiers = qt_cocoaDragOperation2QtModifiers(nsActions); - } - - // send the drag enter event to the widget. - QPoint localPoint(qwidget->mapFromGlobal(globalPoint)); - QDragEnterEvent qDEEvent(localPoint, qtAllowed, mimeData, QApplication::mouseButtons(), modifiers); - QApplication::sendEvent(qwidget, &qDEEvent); - - if (!qDEEvent.isAccepted()) { - // The enter event was not accepted. We mark this by removing - // the drop data so we don't send subsequent drag move events: - [self removeDropData]; - [self changeDraggingCursor:NSDragOperationNone]; - return NSDragOperationNone; - } else { - // Send a drag move event immediately after a drag enter event (as per documentation). - QDragMoveEvent qDMEvent(localPoint, qtAllowed, mimeData, QApplication::mouseButtons(), modifiers); - qDMEvent.setDropAction(qDEEvent.dropAction()); - qDMEvent.accept(); // accept by default, since enter event was accepted. - QApplication::sendEvent(qwidget, &qDMEvent); - - if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction) { - // Since we accepted the drag enter event, the widget expects - // future drage move events. - nsActions = NSDragOperationNone; - // Save as ignored in the answer rect. - qDMEvent.setDropAction(Qt::IgnoreAction); - } else { - nsActions = QT_PREPEND_NAMESPACE(qt_mac_mapDropAction)(qDMEvent.dropAction()); - } - - QT_PREPEND_NAMESPACE(qt_mac_copy_answer_rect)(qDMEvent); - [self changeDraggingCursor:nsActions]; - return nsActions; - } - } - -- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender -{ - NSPoint nswindowPoint = [sender draggingLocation]; - NSPoint nsglobalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:nswindowPoint]; - QPoint globalPoint = flipPoint(nsglobalPoint).toPoint(); - - QWidget *qwidget = QApplication::widgetAt(globalPoint); - if (!qwidget) - return [super draggingEntered:sender]; - - // First, check if the widget under the mouse has changed since the - // last drag move events. If so, we need to change target, and dispatch - // syntetic drag enter/leave events: - if (qwidget != *currentDragTarget()) { - if (*currentDragTarget() && dropData) { - QDragLeaveEvent de; - QApplication::sendEvent(*currentDragTarget(), &de); - [self removeDropData]; - } - return [self draggingEntered:sender]; - } - - if (qwidget->testAttribute(Qt::WA_DropSiteRegistered) == false) - return NSDragOperationNone; - - // If we have no drop data (which will be assigned inside draggingEntered), it means - // that the current drag target did not accept the enter event. If so, we ignore - // subsequent move events as well: - if (dropData == 0) { - [self changeDraggingCursor:NSDragOperationNone]; - return NSDragOperationNone; - } - - // If the mouse is still within the accepted rect (provided by - // the application on a previous event), we follow the optimization - // and just return the answer given at that point: - NSDragOperation nsActions = [sender draggingSourceOperationMask]; - QPoint localPoint(qwidget->mapFromGlobal(globalPoint)); - if (qt_mac_mouse_inside_answer_rect(localPoint) - && QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) == nsActions) { - NSDragOperation operation = QT_PREPEND_NAMESPACE(qt_mac_mapDropActions)(QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastAction)); - [self changeDraggingCursor:operation]; - return operation; - } - - QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) = nsActions; - Qt::DropActions qtAllowed = QT_PREPEND_NAMESPACE(qt_mac_mapNSDragOperations)(nsActions); - Qt::KeyboardModifiers modifiers = Qt::NoModifier; - - // Update modifiers: - if ([sender draggingSource] != nil) { - QApplicationPrivate::modifier_buttons = qt_cocoaModifiers2QtModifiers([[NSApp currentEvent] modifierFlags]); - modifiers = QApplication::keyboardModifiers(); - } else { - modifiers = qt_cocoaDragOperation2QtModifiers(nsActions); - } - - QMimeData *mimeData = dropData; - if (QDragManager::self()->source()) - mimeData = QDragManager::self()->dragPrivate()->data; - - // Insert the same drop action on the event according to - // what the application told us it should be on the previous event: - QDragMoveEvent qDMEvent(localPoint, qtAllowed, mimeData, QApplication::mouseButtons(), modifiers); - if (QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec).lastAction != Qt::IgnoreAction - && QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec).buttons == qDMEvent.mouseButtons() - && QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec).modifiers == qDMEvent.keyboardModifiers()) - qDMEvent.setDropAction(QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec).lastAction); - - // Now, end the drag move event to the widget: - qDMEvent.accept(); - QApplication::sendEvent(qwidget, &qDMEvent); - - NSDragOperation operation = qt_mac_mapDropAction(qDMEvent.dropAction()); - if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction) { - // Ignore this event (we will still receive further - // notifications), save as ignored in the answer rect: - operation = NSDragOperationNone; - qDMEvent.setDropAction(Qt::IgnoreAction); - } - - qt_mac_copy_answer_rect(qDMEvent); - [self changeDraggingCursor:operation]; - - return operation; -} - -- (void)draggingExited:(id <NSDraggingInfo>)sender -{ - NSPoint nswindowPoint = [sender draggingLocation]; - NSPoint nsglobalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:nswindowPoint]; - QPoint globalPoint = flipPoint(nsglobalPoint).toPoint(); - - QWidget *qwidget = *currentDragTarget(); - if (!qwidget) - return [super draggingExited:sender]; - - if (dropData) { - QDragLeaveEvent de; - QApplication::sendEvent(qwidget, &de); - [self removeDropData]; - } - - // Clean-up: - [self removeDropData]; - *currentDragTarget() = 0; - [self changeDraggingCursor:NSDragOperationEvery]; -} - -- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender -{ - QWidget *qwidget = *currentDragTarget(); - if (!qwidget) - return NO; - - *currentDragTarget() = 0; - NSPoint nswindowPoint = [sender draggingLocation]; - NSPoint nsglobalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:nswindowPoint]; - QPoint globalPoint = flipPoint(nsglobalPoint).toPoint(); - - [self addDropData:sender]; - - NSDragOperation nsActions = [sender draggingSourceOperationMask]; - Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations(nsActions); - QMimeData *mimeData = dropData; - - if (QDragManager::self()->source()) - mimeData = QDragManager::self()->dragPrivate()->data; - if (QDragManager::self()->object) - QDragManager::self()->dragPrivate()->target = qwidget; - - QPoint localPoint(qwidget->mapFromGlobal(globalPoint)); - QDropEvent de(localPoint, qtAllowed, mimeData, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); - QApplication::sendEvent(qwidget, &de); - - if (QDragManager::self()->object) - QDragManager::self()->dragPrivate()->executed_action = de.dropAction(); - - return de.isAccepted(); -} - -// This is a hack and it should be removed once we find the real cause for -// the painting problems. -// We have a static variable that signals if we have been called before or not. -static bool firstDrawingInvocation = true; - -// The method below exists only as a workaround to draw/not draw the baseline -// in the title bar. This is to support unifiedToolbar look. - -// This method is very special. To begin with, it is a -// method that will get called only if we enable documentMode. -// Furthermore, it won't get called as a normal method, we swap -// this method with the normal implementation of drawRect in -// _NSThemeFrame. When this method is active, its mission is to -// first call the original drawRect implementation so the widget -// gets proper painting. After that, it needs to detect if there -// is a toolbar or not, in order to decide how to handle the unified -// look. The distinction is important since the presence and -// visibility of a toolbar change the way we enter into unified mode. -// When there is a toolbar and that toolbar is visible, the problem -// is as simple as to tell the toolbar not to draw its baseline. -// However when there is not toolbar or the toolbar is not visible, -// we need to draw a line on top of the baseline, because the baseline -// in that case will belong to the title. For this case we need to draw -// a line on top of the baseline. -// As usual, there is a special case. When we first are called, we might -// need to repaint ourselves one more time. We only need that if we -// didn't get the activation, i.e. when we are launched via the command -// line. And this only if the toolbar is visible from the beginning, -// so we have a special flag that signals if we need to repaint or not. -- (void)drawRectSpecial:(NSRect)rect -{ - // Call the original drawing method. - [id(self) drawRectOriginal:rect]; - NSWindow *window = [id(self) window]; - NSToolbar *toolbar = [window toolbar]; - if(!toolbar) { - // There is no toolbar, we have to draw a line on top of the line drawn by Cocoa. - macDrawRectOnTop((void *)window); - } else { - if([toolbar isVisible]) { - // We tell Cocoa to avoid drawing the line at the end. - if(firstDrawingInvocation) { - firstDrawingInvocation = false; - macSyncDrawingOnFirstInvocation((void *)window); - } else - [toolbar setShowsBaselineSeparator:NO]; - } else { - // There is a toolbar but it is not visible so - // we have to draw a line on top of the line drawn by Cocoa. - macDrawRectOnTop((void *)window); - } - } -} - -- (void)drawRectOriginal:(NSRect)rect -{ - Q_UNUSED(rect) - // This method implementation is here to silenct the compiler. - // See drawRectSpecial for information. -} - diff --git a/src/gui/platforms/mac/qcocoaview_mac.mm b/src/gui/platforms/mac/qcocoaview_mac.mm deleted file mode 100644 index e885d1552c..0000000000 --- a/src/gui/platforms/mac/qcocoaview_mac.mm +++ /dev/null @@ -1,1388 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#import <private/qcocoaview_mac_p.h> -#ifdef QT_MAC_USE_COCOA - -#include <private/qwidget_p.h> -#include <private/qt_mac_p.h> -#include <private/qapplication_p.h> -#include <private/qabstractscrollarea_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#include <private/qdnd_p.h> -#include <private/qmacinputcontext_p.h> -#include <private/qevent_p.h> -#include <private/qbackingstore_p.h> -#include <private/qwindowsurface_raster_p.h> -#include <private/qunifiedtoolbarsurface_mac_p.h> - -#include <qscrollarea.h> -#include <qhash.h> -#include <qtextformat.h> -#include <qpaintengine.h> -#include <QUrl> -#include <QAccessible> -#include <QFileInfo> -#include <QFile> - -#include <qdebug.h> - -@interface NSEvent (Qt_Compile_Leopard_DeviceDelta) - - (CGFloat)deviceDeltaX; - - (CGFloat)deviceDeltaY; - - (CGFloat)deviceDeltaZ; -@end - -@interface NSEvent (Qt_Compile_Leopard_Gestures) - - (CGFloat)magnification; -@end - -QT_BEGIN_NAMESPACE - -extern void qt_mac_update_cursor(); // qcursor_mac.mm -extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); // qapplication.cpp -extern QPointer<QWidget> qt_last_mouse_receiver; // qapplication_mac.cpp -extern QPointer<QWidget> qt_last_native_mouse_receiver; // qt_cocoa_helpers_mac.mm -extern OSViewRef qt_mac_nativeview_for(const QWidget *w); // qwidget_mac.mm -extern OSViewRef qt_mac_effectiveview_for(const QWidget *w); // qwidget_mac.mm -extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp -extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); -extern QWidget *mac_mouse_grabber; -extern bool qt_mac_clearDirtyOnWidgetInsideDrawWidget; // qwidget.cpp - -static QColor colorFrom(NSColor *color) -{ - QColor qtColor; - NSString *colorSpace = [color colorSpaceName]; - if (colorSpace == NSDeviceCMYKColorSpace) { - CGFloat cyan, magenta, yellow, black, alpha; - [color getCyan:&cyan magenta:&magenta yellow:&yellow black:&black alpha:&alpha]; - qtColor.setCmykF(cyan, magenta, yellow, black, alpha); - } else { - NSColor *tmpColor; - tmpColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace]; - CGFloat red, green, blue, alpha; - [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha]; - qtColor.setRgbF(red, green, blue, alpha); - } - return qtColor; -} - -QT_END_NAMESPACE - -QT_FORWARD_DECLARE_CLASS(QMacCocoaAutoReleasePool) -QT_FORWARD_DECLARE_CLASS(QCFString) -QT_FORWARD_DECLARE_CLASS(QDragManager) -QT_FORWARD_DECLARE_CLASS(QMimeData) -QT_FORWARD_DECLARE_CLASS(QPoint) -QT_FORWARD_DECLARE_CLASS(QApplication) -QT_FORWARD_DECLARE_CLASS(QApplicationPrivate) -QT_FORWARD_DECLARE_CLASS(QDragEnterEvent) -QT_FORWARD_DECLARE_CLASS(QDragMoveEvent) -QT_FORWARD_DECLARE_CLASS(QStringList) -QT_FORWARD_DECLARE_CLASS(QString) -QT_FORWARD_DECLARE_CLASS(QRect) -QT_FORWARD_DECLARE_CLASS(QRegion) -QT_FORWARD_DECLARE_CLASS(QAbstractScrollArea) -QT_FORWARD_DECLARE_CLASS(QAbstractScrollAreaPrivate) -QT_FORWARD_DECLARE_CLASS(QPaintEvent) -QT_FORWARD_DECLARE_CLASS(QPainter) -QT_FORWARD_DECLARE_CLASS(QHoverEvent) -QT_FORWARD_DECLARE_CLASS(QCursor) -QT_USE_NAMESPACE -extern "C" { - extern NSString *NSTextInputReplacementRangeAttributeName; -} - -//#define ALIEN_DEBUG 1 -#ifdef ALIEN_DEBUG -static int qCocoaViewCount = 0; -#endif - -@implementation QT_MANGLE_NAMESPACE(QCocoaView) - -- (id)initWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate -{ - self = [super init]; - if (self) { - [self finishInitWithQWidget:widget widgetPrivate:widgetprivate]; - } - [self setFocusRingType:NSFocusRingTypeNone]; - composingText = new QString(); - -#ifdef ALIEN_DEBUG - ++qCocoaViewCount; - qDebug() << "Alien: create native view for" << widget << ". qCocoaViewCount is:" << qCocoaViewCount; -#endif - - composing = false; - sendKeyEvents = true; - fromKeyDownEvent = false; - alienTouchCount = 0; - - [self setHidden:YES]; - return self; -} - -- (void) finishInitWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate -{ - qwidget = widget; - qwidgetprivate = widgetprivate; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(frameDidChange:) - name:@"NSViewFrameDidChangeNotification" - object:self]; -} - -- (void)dealloc -{ - QMacCocoaAutoReleasePool pool; - delete composingText; - [[NSNotificationCenter defaultCenter] removeObserver:self]; - -#ifdef ALIEN_DEBUG - --qCocoaViewCount; - qDebug() << "Alien: widget deallocated. qCocoaViewCount is:" << qCocoaViewCount; -#endif - - [super dealloc]; -} - -- (BOOL)isOpaque -{ - if (!qwidgetprivate) - return [super isOpaque]; - return qwidgetprivate->isOpaque; -} - -- (BOOL)isFlipped -{ - return YES; -} - -// We preserve the content of the view if WA_StaticContents is defined. -// -// More info in the Cocoa documentation: -// http://developer.apple.com/mac/library/documentation/cocoa/conceptual/CocoaViewsGuide/Optimizing/Optimizing.html -- (BOOL) preservesContentDuringLiveResize -{ - return qwidget->testAttribute(Qt::WA_StaticContents); -} - -- (void) setFrameSize:(NSSize)newSize -{ - [super setFrameSize:newSize]; - - // A change in size has required the view to be invalidated. - if ([self inLiveResize]) { - NSRect rects[4]; - NSInteger count; - [self getRectsExposedDuringLiveResize:rects count:&count]; - while (count-- > 0) - { - [self setNeedsDisplayInRect:rects[count]]; - } - } else { - [self setNeedsDisplay:YES]; - } - - // Make sure the opengl context is updated on resize. - if (qwidgetprivate && qwidgetprivate->isGLWidget && [self window]) { - qwidgetprivate->needWindowChange = true; - QEvent event(QEvent::MacGLWindowChange); - qApp->sendEvent(qwidget, &event); - } -} - -// We catch the 'setNeedsDisplay:' message in order to avoid a useless full repaint. -// During the resize, the top of the widget is repainted, probably because of the -// change of coordinate space (Quartz vs Qt). This is then followed by this message: -// -[NSView _setNeedsDisplayIfTopLeftChanged] -// which force a full repaint by sending the message 'setNeedsDisplay:'. -// That is what we are preventing here. -- (void)setNeedsDisplay:(BOOL)flag { - if (![self inLiveResize] || !(qwidget->testAttribute(Qt::WA_StaticContents))) { - [super setNeedsDisplay:flag]; - } -} - -- (void)drawRect:(NSRect)aRect -{ - if (!qwidget) - return; - - // Getting context. - CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - qt_mac_retain_graphics_context(context); - - // We use a different graphics system. - // - // Widgets that are set to paint on screen, specifically QGLWidget, - // requires the native engine to execute in order to be drawn. - if (QApplicationPrivate::graphicsSystem() != 0 && !qwidget->testAttribute(Qt::WA_PaintOnScreen)) { - - // Raster engine. - if (QApplicationPrivate::graphics_system_name == QLatin1String("raster")) { - - if (!qwidgetprivate->isInUnifiedToolbar) { - - // Qt handles the painting occuring inside the window. - // Cocoa also keeps track of all widgets as NSView and therefore might - // ask for a repainting of a widget even if Qt is already taking care of it. - // - // The only valid reason for Cocoa to call drawRect: is for window manipulation - // (ie. resize, ...). - // - // Qt will then forward the update to the children. - if (!qwidget->isWindow()) { - qt_mac_release_graphics_context(context); - return; - } - - QRasterWindowSurface *winSurface = dynamic_cast<QRasterWindowSurface *>(qwidget->windowSurface()); - if (!winSurface || !winSurface->needsFlush) { - qt_mac_release_graphics_context(context); - return; - } - - // Clip to region. - const QVector<QRect> &rects = winSurface->regionToFlush.rects(); - for (int i = 0; i < rects.size(); ++i) { - const QRect &rect = rects.at(i); - CGContextAddRect(context, CGRectMake(rect.x(), rect.y(), rect.width(), rect.height())); - } - CGContextClip(context); - - QRect r = winSurface->regionToFlush.boundingRect(); - const CGRect area = CGRectMake(r.x(), r.y(), r.width(), r.height()); - - qt_mac_draw_image(context, winSurface->imageContext(), area, area); - - winSurface->needsFlush = false; - winSurface->regionToFlush = QRegion(); - - } else { - - QUnifiedToolbarSurface *unifiedSurface = qwidgetprivate->unifiedSurface; - if (!unifiedSurface) { - qt_mac_release_graphics_context(context); - return; - } - - int areaX = qwidgetprivate->toolbar_offset.x(); - int areaY = qwidgetprivate->toolbar_offset.y(); - int areaWidth = qwidget->geometry().width(); - int areaHeight = qwidget->geometry().height(); - const CGRect area = CGRectMake(areaX, areaY, areaWidth, areaHeight); - const CGRect drawingArea = CGRectMake(0, 0, areaWidth, areaHeight); - - qt_mac_draw_image(context, unifiedSurface->imageContext(), area, drawingArea); - - qwidgetprivate->flushRequested = false; - - } - - CGContextFlush(context); - qt_mac_release_graphics_context(context); - return; - } - - // Qt handles the painting occuring inside the window. - // Cocoa also keeps track of all widgets as NSView and therefore might - // ask for a repainting of a widget even if Qt is already taking care of it. - // - // The only valid reason for Cocoa to call drawRect: is for window manipulation - // (ie. resize, ...). - // - // Qt will then forward the update to the children. - if (qwidget->isWindow()) { - qwidgetprivate->syncBackingStore(qwidget->rect()); - } - } - - // Native engine. - qwidgetprivate->hd = context; - - if (qwidget->isVisible() && qwidget->updatesEnabled()) { //process the actual paint event. - if (qwidget->testAttribute(Qt::WA_WState_InPaintEvent)) - qWarning("QWidget::repaint: Recursive repaint detected"); - - const QRect qrect = QRect(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height); - QRegion qrgn; - - const NSRect *rects; - NSInteger count; - [self getRectsBeingDrawn:&rects count:&count]; - for (int i = 0; i < count; ++i) { - QRect tmpRect = QRect(rects[i].origin.x, rects[i].origin.y, rects[i].size.width, rects[i].size.height); - qrgn += tmpRect; - } - - if (!qwidget->isWindow() && !qobject_cast<QAbstractScrollArea *>(qwidget->parent())) { - const QRegion &parentMask = qwidget->window()->mask(); - if (!parentMask.isEmpty()) { - const QPoint mappedPoint = qwidget->mapTo(qwidget->window(), qrect.topLeft()); - qrgn.translate(mappedPoint); - qrgn &= parentMask; - qrgn.translate(-mappedPoint.x(), -mappedPoint.y()); - } - } - - QPoint redirectionOffset(0, 0); - //setup the context - qwidget->setAttribute(Qt::WA_WState_InPaintEvent); - QPaintEngine *engine = qwidget->paintEngine(); - if (engine) - engine->setSystemClip(qrgn); - if (qwidgetprivate->extra && qwidgetprivate->extra->hasMask) { - CGRect widgetRect = CGRectMake(0, 0, qwidget->width(), qwidget->height()); - CGContextTranslateCTM (context, 0, widgetRect.size.height); - CGContextScaleCTM(context, 1, -1); - if (qwidget->isWindow()) - CGContextClearRect(context, widgetRect); - CGContextClipToMask(context, widgetRect, qwidgetprivate->extra->imageMask); - CGContextScaleCTM(context, 1, -1); - CGContextTranslateCTM (context, 0, -widgetRect.size.height); - } - - if (qwidget->isWindow() && !qwidgetprivate->isOpaque - && !qwidget->testAttribute(Qt::WA_MacBrushedMetal)) { - CGContextClearRect(context, NSRectToCGRect(aRect)); - } - - qwidget->setAttribute(Qt::WA_WState_InPaintEvent, false); - QWidgetPrivate *qwidgetPrivate = qt_widget_private(qwidget); - - // We specify that we want to draw the widget itself, and - // all its children recursive. But we skip native children, because - // they will receive drawRect calls by themselves as needed: - int flags = QWidgetPrivate::DrawPaintOnScreen - | QWidgetPrivate::DrawRecursive - | QWidgetPrivate::DontDrawNativeChildren; - - if (qwidget->isWindow()) - flags |= QWidgetPrivate::DrawAsRoot; - - // Start to draw: - qt_mac_clearDirtyOnWidgetInsideDrawWidget = true; - qwidgetPrivate->drawWidget(qwidget, qrgn, QPoint(), flags, 0); - qt_mac_clearDirtyOnWidgetInsideDrawWidget = false; - - if (!redirectionOffset.isNull()) - QPainter::restoreRedirected(qwidget); - if (engine) - engine->setSystemClip(QRegion()); - qwidget->setAttribute(Qt::WA_WState_InPaintEvent, false); - if(!qwidget->testAttribute(Qt::WA_PaintOutsidePaintEvent) && qwidget->paintingActive()) - qWarning("QWidget: It is dangerous to leave painters active on a" - " widget outside of the PaintEvent"); - } - qwidgetprivate->hd = 0; - qt_mac_release_graphics_context(context); -} - -- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent -{ - // Find the widget that should receive the event: - QPoint qlocal, qglobal; - QWidget *widgetToGetMouse = qt_mac_getTargetForMouseEvent(theEvent, QEvent::MouseButtonPress, qlocal, qglobal, qwidget, 0); - if (!widgetToGetMouse) - return NO; - - return !widgetToGetMouse->testAttribute(Qt::WA_MacNoClickThrough); -} - -- (NSView *)hitTest:(NSPoint)aPoint -{ - if (!qwidget) - return [super hitTest:aPoint]; - - if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) - return nil; // You cannot hit a transparent for mouse event widget. - return [super hitTest:aPoint]; -} - -- (void)updateTrackingAreas -{ - if (!qwidget) - return; - - // [NSView addTrackingArea] is slow, so bail out early if we can: - if (NSIsEmptyRect([self visibleRect])) - return; - - QMacCocoaAutoReleasePool pool; - if (NSArray *trackingArray = [self trackingAreas]) { - NSUInteger size = [trackingArray count]; - for (NSUInteger i = 0; i < size; ++i) { - NSTrackingArea *t = [trackingArray objectAtIndex:i]; - [self removeTrackingArea:t]; - } - } - - // Ideally, we shouldn't have NSTrackingMouseMoved events included below, it should - // only be turned on if mouseTracking, hover is on or a tool tip is set. - // Unfortunately, Qt will send "tooltip" events on mouse moves, so we need to - // turn it on in ALL case. That means EVERY QCocoaView gets to pay the cost of - // mouse moves delivered to it (Apple recommends keeping it OFF because there - // is a performance hit). So it goes. - NSUInteger trackingOptions = NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp - | NSTrackingInVisibleRect | NSTrackingMouseMoved; - NSTrackingArea *ta = [[NSTrackingArea alloc] initWithRect:NSMakeRect(0, 0, - qwidget->width(), - qwidget->height()) - options:trackingOptions - owner:self - userInfo:nil]; - [self addTrackingArea:ta]; - [ta release]; -} - -- (void)mouseEntered:(NSEvent *)event -{ - // Cocoa will not send a move event on mouseEnter. But since - // Qt expect this, we fake one now. See also mouseExited below - // for info about enter/leave event handling - NSEvent *nsmoveEvent = [NSEvent - mouseEventWithType:NSMouseMoved - location:[[self window] mouseLocationOutsideOfEventStream] - modifierFlags: [event modifierFlags] - timestamp: [event timestamp] - windowNumber: [event windowNumber] - context: [event context] - eventNumber: [event eventNumber] - clickCount: 0 - pressure: 0]; - - // Important: Cocoa sends us mouseEnter on all views under the mouse - // and not just the one on top. Therefore, to we cannot use qwidget - // as native widget for this case. Instead, we let qt_mac_handleMouseEvent - // resolve it (last argument set to 0): - qt_mac_handleMouseEvent(nsmoveEvent, QEvent::MouseMove, Qt::NoButton, 0); -} - -- (void)mouseExited:(NSEvent *)event -{ - // Note: normal enter/leave handling is done from within mouseMove. This handler - // catches the case when the mouse moves out of the window (which mouseMove do not). - // Updating the mouse cursor follows the same logic as enter/leave. And we update - // neither if a grab exists (even if the grab points to this widget, it seems, ref X11) - Q_UNUSED(event); - if (self == [[self window] contentView] && !qt_button_down && !QWidget::mouseGrabber()) { - qt_mac_update_cursor(); - // If the mouse exits the content view, but qt_mac_getTargetForMouseEvent still - // reports a target, it means that either there is a grab involved, or the mouse - // hovered over another window in the application. In both cases, move events will - // cause qt_mac_handleMouseEvent to be called, which will handle enter/leave. - QPoint qlocal, qglobal; - QWidget *widgetUnderMouse = 0; - qt_mac_getTargetForMouseEvent(event, QEvent::Leave, qlocal, qglobal, qwidget, &widgetUnderMouse); - - if (widgetUnderMouse == 0) { - QApplicationPrivate::dispatchEnterLeave(0, qt_last_mouse_receiver); - qt_last_mouse_receiver = 0; - qt_last_native_mouse_receiver = 0; - } - } -} - -- (void)flagsChanged:(NSEvent *)theEvent -{ - QWidget *widgetToGetKey = qt_mac_getTargetForKeyEvent(qwidget); - if (!widgetToGetKey) - return; - - qt_dispatchModifiersChanged(theEvent, widgetToGetKey); - [super flagsChanged:theEvent]; -} - -- (void)mouseMoved:(NSEvent *)theEvent -{ - // Important: this method will only be called when the view's window is _not_ inside - // QCocoaWindow/QCocoaPanel. Otherwise, [QCocoaWindow sendEvent] will handle the event - // before it ends up here. So, this method is added for supporting QMacNativeWidget. - // TODO: Cocoa send move events to all views under the mouse. So make sure we only - // handle the event for the widget on top when using QMacNativeWidget. - qt_mac_handleMouseEvent(theEvent, QEvent::MouseMove, Qt::NoButton, qwidget); -} - -- (void)mouseDown:(NSEvent *)theEvent -{ - qt_mac_handleMouseEvent(theEvent, QEvent::MouseButtonPress, Qt::LeftButton, qwidget); - // Don't call super here. This prevents us from getting the mouseUp event, - // which we need to send even if the mouseDown event was not accepted. - // (this is standard Qt behavior.) -} - -- (void)mouseUp:(NSEvent *)theEvent -{ - qt_mac_handleMouseEvent(theEvent, QEvent::MouseButtonRelease, Qt::LeftButton, qwidget); -} - -- (void)rightMouseDown:(NSEvent *)theEvent -{ - qt_mac_handleMouseEvent(theEvent, QEvent::MouseButtonPress, Qt::RightButton, qwidget); -} - -- (void)rightMouseUp:(NSEvent *)theEvent -{ - qt_mac_handleMouseEvent(theEvent, QEvent::MouseButtonRelease, Qt::RightButton, qwidget); -} - -- (void)otherMouseDown:(NSEvent *)theEvent -{ - Qt::MouseButton mouseButton = cocoaButton2QtButton([theEvent buttonNumber]); - qt_mac_handleMouseEvent(theEvent, QEvent::MouseButtonPress, mouseButton, qwidget); -} - -- (void)otherMouseUp:(NSEvent *)theEvent -{ - Qt::MouseButton mouseButton = cocoaButton2QtButton([theEvent buttonNumber]); - qt_mac_handleMouseEvent(theEvent, QEvent::MouseButtonRelease, mouseButton, qwidget); -} - -- (void)mouseDragged:(NSEvent *)theEvent -{ - qt_mac_handleMouseEvent(theEvent, QEvent::MouseMove, Qt::NoButton, qwidget); -} - -- (void)rightMouseDragged:(NSEvent *)theEvent -{ - qt_mac_handleMouseEvent(theEvent, QEvent::MouseMove, Qt::NoButton, qwidget); -} - -- (void)otherMouseDragged:(NSEvent *)theEvent -{ - qt_mac_handleMouseEvent(theEvent, QEvent::MouseMove, Qt::NoButton, qwidget); -} - -- (void)scrollWheel:(NSEvent *)theEvent -{ - // Give the Input Manager a chance to process the wheel event. - NSInputManager *currentIManager = [NSInputManager currentInputManager]; - if (currentIManager && [currentIManager wantsToHandleMouseEvents]) { - [currentIManager handleMouseEvent:theEvent]; - } - - Qt::MouseButtons buttons = QApplication::mouseButtons(); - Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([theEvent modifierFlags]); - - // Find the widget that should receive the event: - QPoint qlocal, qglobal; - QWidget *widgetToGetMouse = qt_mac_getTargetForMouseEvent(theEvent, QEvent::Wheel, qlocal, qglobal, qwidget, 0); - if (!widgetToGetMouse) - return; - - int deltaX = 0; - int deltaY = 0; - int deltaZ = 0; - - const EventRef carbonEvent = (EventRef)[theEvent eventRef]; - const UInt32 carbonEventKind = carbonEvent ? ::GetEventKind(carbonEvent) : 0; - const bool scrollEvent = carbonEventKind == kEventMouseScroll; - - if (scrollEvent) { - // The mouse device containts pixel scroll wheel support (Mighty Mouse, Trackpad). - // Since deviceDelta is delivered as pixels rather than degrees, we need to - // convert from pixels to degrees in a sensible manner. - // It looks like 1/4 degrees per pixel behaves most native. - // (NB: Qt expects the unit for delta to be 8 per degree): - const int pixelsToDegrees = 2; // 8 * 1/4 - deltaX = [theEvent deviceDeltaX] * pixelsToDegrees; - deltaY = [theEvent deviceDeltaY] * pixelsToDegrees; - deltaZ = [theEvent deviceDeltaZ] * pixelsToDegrees; - } else { - // carbonEventKind == kEventMouseWheelMoved - // Remove acceleration, and use either -120 or 120 as delta: - deltaX = qBound(-120, int([theEvent deltaX] * 10000), 120); - deltaY = qBound(-120, int([theEvent deltaY] * 10000), 120); - deltaZ = qBound(-120, int([theEvent deltaZ] * 10000), 120); - } - -#ifndef QT_NO_WHEELEVENT - // ### Qt 5: Send one QWheelEvent with dx, dy and dz - - if (deltaX != 0 && deltaY != 0) - QMacScrollOptimization::initDelayedScroll(); - - if (deltaX != 0) { - QWheelEvent qwe(qlocal, qglobal, deltaX, buttons, keyMods, Qt::Horizontal); - qt_sendSpontaneousEvent(widgetToGetMouse, &qwe); - } - - if (deltaY != 0) { - QWheelEvent qwe(qlocal, qglobal, deltaY, buttons, keyMods, Qt::Vertical); - qt_sendSpontaneousEvent(widgetToGetMouse, &qwe); - } - - if (deltaZ != 0) { - // Qt doesn't explicitly support wheels with a Z component. In a misguided attempt to - // try to be ahead of the pack, I'm adding this extra value. - QWheelEvent qwe(qlocal, qglobal, deltaZ, buttons, keyMods, (Qt::Orientation)3); - qt_sendSpontaneousEvent(widgetToGetMouse, &qwe); - } - - if (deltaX != 0 && deltaY != 0) - QMacScrollOptimization::performDelayedScroll(); -#endif //QT_NO_WHEELEVENT -} - -- (void)tabletProximity:(NSEvent *)tabletEvent -{ - qt_dispatchTabletProximityEvent(tabletEvent); -} - -- (void)tabletPoint:(NSEvent *)tabletEvent -{ - if (!qt_mac_handleTabletEvent(self, tabletEvent)) - [super tabletPoint:tabletEvent]; -} - -- (void)magnifyWithEvent:(NSEvent *)event -{ - QPoint qlocal, qglobal; - QWidget *widgetToGetGesture = 0; - qt_mac_getTargetForMouseEvent(event, QEvent::Gesture, qlocal, qglobal, qwidget, &widgetToGetGesture); - if (!widgetToGetGesture) - return; - if (!QApplicationPrivate::tryModalHelper(widgetToGetGesture, 0)) - return; - -#ifndef QT_NO_GESTURES - QNativeGestureEvent qNGEvent; - qNGEvent.gestureType = QNativeGestureEvent::Zoom; - NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]]; - qNGEvent.position = flipPoint(p).toPoint(); - qNGEvent.percentage = [event magnification]; - qt_sendSpontaneousEvent(widgetToGetGesture, &qNGEvent); -#endif // QT_NO_GESTURES -} - -- (void)rotateWithEvent:(NSEvent *)event -{ - QPoint qlocal, qglobal; - QWidget *widgetToGetGesture = 0; - qt_mac_getTargetForMouseEvent(event, QEvent::Gesture, qlocal, qglobal, qwidget, &widgetToGetGesture); - if (!widgetToGetGesture) - return; - if (!QApplicationPrivate::tryModalHelper(widgetToGetGesture, 0)) - return; - -#ifndef QT_NO_GESTURES - QNativeGestureEvent qNGEvent; - qNGEvent.gestureType = QNativeGestureEvent::Rotate; - NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]]; - qNGEvent.position = flipPoint(p).toPoint(); - qNGEvent.percentage = -[event rotation]; - qt_sendSpontaneousEvent(widgetToGetGesture, &qNGEvent); -#endif // QT_NO_GESTURES -} - -- (void)swipeWithEvent:(NSEvent *)event -{ - QPoint qlocal, qglobal; - QWidget *widgetToGetGesture = 0; - qt_mac_getTargetForMouseEvent(event, QEvent::Gesture, qlocal, qglobal, qwidget, &widgetToGetGesture); - if (!widgetToGetGesture) - return; - if (!QApplicationPrivate::tryModalHelper(widgetToGetGesture, 0)) - return; - -#ifndef QT_NO_GESTURES - QNativeGestureEvent qNGEvent; - qNGEvent.gestureType = QNativeGestureEvent::Swipe; - NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]]; - qNGEvent.position = flipPoint(p).toPoint(); - if ([event deltaX] == 1) - qNGEvent.angle = 180.0f; - else if ([event deltaX] == -1) - qNGEvent.angle = 0.0f; - else if ([event deltaY] == 1) - qNGEvent.angle = 90.0f; - else if ([event deltaY] == -1) - qNGEvent.angle = 270.0f; - qt_sendSpontaneousEvent(widgetToGetGesture, &qNGEvent); -#endif // QT_NO_GESTURES -} - -- (void)beginGestureWithEvent:(NSEvent *)event -{ - QPoint qlocal, qglobal; - QWidget *widgetToGetGesture = 0; - qt_mac_getTargetForMouseEvent(event, QEvent::Gesture, qlocal, qglobal, qwidget, &widgetToGetGesture); - if (!widgetToGetGesture) - return; - if (!QApplicationPrivate::tryModalHelper(widgetToGetGesture, 0)) - return; - -#ifndef QT_NO_GESTURES - QNativeGestureEvent qNGEvent; - qNGEvent.gestureType = QNativeGestureEvent::GestureBegin; - NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]]; - qNGEvent.position = flipPoint(p).toPoint(); - qt_sendSpontaneousEvent(widgetToGetGesture, &qNGEvent); -#endif // QT_NO_GESTURES -} - -- (void)endGestureWithEvent:(NSEvent *)event -{ - QPoint qlocal, qglobal; - QWidget *widgetToGetGesture = 0; - qt_mac_getTargetForMouseEvent(event, QEvent::Gesture, qlocal, qglobal, qwidget, &widgetToGetGesture); - if (!widgetToGetGesture) - return; - if (!QApplicationPrivate::tryModalHelper(widgetToGetGesture, 0)) - return; - -#ifndef QT_NO_GESTURES - QNativeGestureEvent qNGEvent; - qNGEvent.gestureType = QNativeGestureEvent::GestureEnd; - NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]]; - qNGEvent.position = flipPoint(p).toPoint(); - qt_sendSpontaneousEvent(widgetToGetGesture, &qNGEvent); -} -#endif // QT_NO_GESTURES - -- (void)frameDidChange:(NSNotification *)note -{ - Q_UNUSED(note); - if (!qwidget) - return; - if (qwidget->isWindow()) - return; - NSRect newFrame = [self frame]; - QRect newGeo(newFrame.origin.x, newFrame.origin.y, newFrame.size.width, newFrame.size.height); - bool moved = qwidget->testAttribute(Qt::WA_Moved); - bool resized = qwidget->testAttribute(Qt::WA_Resized); - qwidget->setGeometry(newGeo); - qwidget->setAttribute(Qt::WA_Moved, moved); - qwidget->setAttribute(Qt::WA_Resized, resized); - qwidgetprivate->syncCocoaMask(); -} - -- (BOOL)isEnabled -{ - if (!qwidget) - return [super isEnabled]; - return [super isEnabled] && qwidget->isEnabled(); -} - -- (void)setEnabled:(BOOL)flag -{ - QMacCocoaAutoReleasePool pool; - [super setEnabled:flag]; - if (qwidget && qwidget->isEnabled() != flag) - qwidget->setEnabled(flag); -} - -+ (Class)cellClass -{ - return [NSActionCell class]; -} - -- (BOOL)acceptsFirstResponder -{ - if (!qwidget) - return NO; - - // Disabled widget shouldn't get focus even if it's a window. - // hence disabled windows will not get any key or mouse events. - if (!qwidget->isEnabled()) - return NO; - - if (qwidget->isWindow() && !qt_widget_private(qwidget)->topData()->embedded) { - QWidget *focusWidget = qApp->focusWidget(); - if (!focusWidget) { - // There is no focus widget, but we still want to receive key events - // for shortcut handling etc. So we accept first responer for the - // content view as a last resort: - return YES; - } - if (!focusWidget->internalWinId() && focusWidget->nativeParentWidget() == qwidget) { - // The current focus widget is alien, and hence, cannot get acceptsFirstResponder - // calls. Since the focus widget is a child of qwidget, we let this view say YES: - return YES; - } - if (focusWidget->window() != qwidget) { - // The current focus widget is in another window. Since cocoa - // suggest that this window should be key now, we accept: - return YES; - } - } - - return qwidget->focusPolicy() != Qt::NoFocus; -} - -- (BOOL)resignFirstResponder -{ - if (!qwidget) - return YES; - - // Seems like the following test only triggers if this - // view is inside a QMacNativeWidget: -// if (QWidget *fw = QApplication::focusWidget()) { -// if (qwidget == fw || qwidget == fw->nativeParentWidget()) -// fw->clearFocus(); -// } - return YES; -} - -- (BOOL)becomeFirstResponder -{ - // see the comment in the acceptsFirstResponder - if the window "stole" focus - // let it become the responder, but don't tell Qt - if (qwidget && qt_widget_private(qwidget->window())->topData()->embedded - && !QApplication::focusWidget() && qwidget->focusPolicy() != Qt::NoFocus) - qwidget->setFocus(Qt::OtherFocusReason); - return YES; -} - -- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal -{ - Q_UNUSED(isLocal); - return supportedActions; -} - -- (void)setSupportedActions:(NSDragOperation)actions -{ - supportedActions = actions; -} - -- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation -{ - Q_UNUSED(anImage); - Q_UNUSED(aPoint); - macCurrentDnDParameters()->performedAction = operation; - if (QDragManager::self()->object - && QDragManager::self()->dragPrivate()->executed_action != Qt::ActionMask) { - macCurrentDnDParameters()->performedAction = - qt_mac_mapDropAction(QDragManager::self()->dragPrivate()->executed_action); - } -} - -- (QWidget *)qt_qwidget -{ - return qwidget; -} - -- (void) qt_clearQWidget -{ - qwidget = 0; - qwidgetprivate = 0; -} - -- (void)keyDown:(NSEvent *)theEvent -{ - if (!qwidget) - return; - QWidget *widgetToGetKey = qt_mac_getTargetForKeyEvent(qwidget); - if (!widgetToGetKey) - return; - - sendKeyEvents = true; - - if (widgetToGetKey->testAttribute(Qt::WA_InputMethodEnabled) - && !(widgetToGetKey->inputMethodHints() & Qt::ImhDigitsOnly - || widgetToGetKey->inputMethodHints() & Qt::ImhFormattedNumbersOnly - || widgetToGetKey->inputMethodHints() & Qt::ImhHiddenText)) { - fromKeyDownEvent = true; - [qt_mac_nativeview_for(qwidget) interpretKeyEvents:[NSArray arrayWithObject: theEvent]]; - fromKeyDownEvent = false; - } - - if (sendKeyEvents && !composing) { - bool keyEventEaten = qt_dispatchKeyEvent(theEvent, widgetToGetKey); - if (!keyEventEaten && qwidget) { - // The event is not yet eaten, and if Qt is embedded inside a native - // cocoa application, send it to first responder not owned by Qt. - // The exception is if widgetToGetKey was redirected to a popup. - QWidget *toplevel = qwidget->window(); - if (toplevel == widgetToGetKey->window()) { - if (qt_widget_private(toplevel)->topData()->embedded) { - if (NSResponder *w = [qt_mac_nativeview_for(toplevel) superview]) - [w keyDown:theEvent]; - } - } - } - } -} - - -- (void)keyUp:(NSEvent *)theEvent -{ - if (sendKeyEvents) { - QWidget *widgetToGetKey = qt_mac_getTargetForKeyEvent(qwidget); - if (!widgetToGetKey) - return; - - bool keyEventEaten = qt_dispatchKeyEvent(theEvent, widgetToGetKey); - if (!keyEventEaten && qwidget) { - // The event is not yet eaten, and if Qt is embedded inside a native - // cocoa application, send it to first responder not owned by Qt. - // The exception is if widgetToGetKey was redirected to a popup. - QWidget *toplevel = qwidget->window(); - if (toplevel == widgetToGetKey->window()) { - if (qt_widget_private(toplevel)->topData()->embedded) { - if (NSResponder *w = [qt_mac_nativeview_for(toplevel) superview]) - [w keyUp:theEvent]; - } - } - } - } -} - -- (void)viewWillMoveToWindow:(NSWindow *)window -{ - if (qwidget == 0) - return; - - if (qwidget->windowFlags() & Qt::MSWindowsOwnDC - && (window != [self window])) { // OpenGL Widget - QEvent event(QEvent::MacGLClearDrawable); - qApp->sendEvent(qwidget, &event); - } -} - -- (void)viewDidMoveToWindow -{ - if (qwidget == 0) - return; - - if (qwidget->windowFlags() & Qt::MSWindowsOwnDC && [self window]) { - // call update paint event - qwidgetprivate->needWindowChange = true; - QEvent event(QEvent::MacGLWindowChange); - qApp->sendEvent(qwidget, &event); - } -} - - -// NSTextInput Protocol implementation - -- (void) insertText:(id)aString -{ - QString commitText; - if ([aString length]) { - if ([aString isKindOfClass:[NSAttributedString class]]) { - commitText = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string])); - } else { - commitText = QCFString::toQString(reinterpret_cast<CFStringRef>(aString)); - }; - } - - // When entering characters through Character Viewer or Keyboard Viewer, the text is passed - // through this insertText method. Since we dont receive a keyDown Event in such cases, the - // composing flag will be false. - if (([aString length] && composing) || !fromKeyDownEvent) { - // Send the commit string to the widget. - composing = false; - sendKeyEvents = false; - QInputMethodEvent e; - e.setCommitString(commitText); - if (QWidget *widgetToGetKey = qt_mac_getTargetForKeyEvent(qwidget)) - qt_sendSpontaneousEvent(widgetToGetKey, &e); - } else { - // The key sequence "`q" on a French Keyboard will generate two calls to insertText before - // it returns from interpretKeyEvents. The first call will turn off 'composing' and accept - // the "`" key. The last keyDown event needs to be processed by the widget to get the - // character "q". The string parameter is ignored for the second call. - sendKeyEvents = true; - } - - composingText->clear(); -} - -- (void) setMarkedText:(id)aString selectedRange:(NSRange)selRange -{ - // Generate the QInputMethodEvent with preedit string and the attributes - // for rendering it. The attributes handled here are 'underline', - // 'underline color' and 'cursor position'. - sendKeyEvents = false; - composing = true; - QString qtText; - // Cursor position is retrived from the range. - QList<QInputMethodEvent::Attribute> attrs; - attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, selRange.location + selRange.length, 1, QVariant()); - if ([aString isKindOfClass:[NSAttributedString class]]) { - qtText = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string])); - composingLength = qtText.length(); - int index = 0; - // Create attributes for individual sections of preedit text - while (index < composingLength) { - NSRange effectiveRange; - NSRange range = NSMakeRange(index, composingLength-index); - NSDictionary *attributes = [aString attributesAtIndex:index - longestEffectiveRange:&effectiveRange - inRange:range]; - NSNumber *underlineStyle = [attributes objectForKey:NSUnderlineStyleAttributeName]; - if (underlineStyle) { - QColor clr (Qt::black); - NSColor *color = [attributes objectForKey:NSUnderlineColorAttributeName]; - if (color) { - clr = colorFrom(color); - } - QTextCharFormat format; - format.setFontUnderline(true); - format.setUnderlineColor(clr); - attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, - effectiveRange.location, - effectiveRange.length, - format); - } - index = effectiveRange.location + effectiveRange.length; - } - } else { - // No attributes specified, take only the preedit text. - qtText = QCFString::toQString(reinterpret_cast<CFStringRef>(aString)); - composingLength = qtText.length(); - } - // Make sure that we have at least one text format. - if (attrs.size() <= 1) { - QTextCharFormat format; - format.setFontUnderline(true); - attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, - 0, composingLength, format); - } - *composingText = qtText; - - QInputMethodEvent e(qtText, attrs); - if (QWidget *widgetToGetKey = qt_mac_getTargetForKeyEvent(qwidget)) - qt_sendSpontaneousEvent(widgetToGetKey, &e); - - if (!composingLength) - composing = false; -} - -- (void) unmarkText -{ - if (composing) { - QInputMethodEvent e; - e.setCommitString(*composingText); - if (QWidget *widgetToGetKey = qt_mac_getTargetForKeyEvent(qwidget)) - qt_sendSpontaneousEvent(widgetToGetKey, &e); - } - composingText->clear(); - composing = false; -} - -- (BOOL) hasMarkedText -{ - return (composing ? YES: NO); -} - -- (void) doCommandBySelector:(SEL)aSelector -{ - Q_UNUSED(aSelector); -} - -- (BOOL)isComposing -{ - return composing; -} - -- (NSInteger) conversationIdentifier -{ - // Return a unique identifier fot this ime conversation - return (NSInteger)self; -} - -- (NSAttributedString *) attributedSubstringFromRange:(NSRange)theRange -{ - QString selectedText(qwidget->inputMethodQuery(Qt::ImCurrentSelection).toString()); - if (!selectedText.isEmpty()) { - QCFString string(selectedText.mid(theRange.location, theRange.length)); - const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string); - return [[[NSAttributedString alloc] initWithString:const_cast<NSString *>(tmpString)] autorelease]; - } else { - return nil; - } -} - -- (NSRange) markedRange -{ - NSRange range; - if (composing) { - range.location = 0; - range.length = composingLength; - } else { - range.location = NSNotFound; - range.length = 0; - } - return range; -} - -- (NSRange) selectedRange -{ - NSRange selRange; - QString selectedText(qwidget->inputMethodQuery(Qt::ImCurrentSelection).toString()); - if (!selectedText.isEmpty()) { - // Consider only the selected text. - selRange.location = 0; - selRange.length = selectedText.length(); - } else { - // No selected text. - selRange.location = NSNotFound; - selRange.length = 0; - } - return selRange; - -} - -- (NSRect) firstRectForCharacterRange:(NSRange)theRange -{ - Q_UNUSED(theRange); - // The returned rect is always based on the internal cursor. - QWidget *widgetToGetKey = qt_mac_getTargetForKeyEvent(qwidget); - if (!widgetToGetKey) - return NSZeroRect; - - QRect mr(widgetToGetKey->inputMethodQuery(Qt::ImMicroFocus).toRect()); - QPoint mp(widgetToGetKey->mapToGlobal(QPoint(mr.bottomLeft()))); - NSRect rect ; - rect.origin.x = mp.x(); - rect.origin.y = flipYCoordinate(mp.y()); - rect.size.width = mr.width(); - rect.size.height = mr.height(); - return rect; -} - -- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint -{ - // We dont support cursor movements using mouse while composing. - Q_UNUSED(thePoint); - return NSNotFound; -} - -- (NSArray*) validAttributesForMarkedText -{ - QWidget *widgetToGetKey = qt_mac_getTargetForKeyEvent(qwidget); - if (!widgetToGetKey) - return nil; - - if (!widgetToGetKey->testAttribute(Qt::WA_InputMethodEnabled)) - return nil; // Not sure if that's correct, but it's saves a malloc. - - // Support only underline color/style. - return [NSArray arrayWithObjects:NSUnderlineColorAttributeName, - NSUnderlineStyleAttributeName, nil]; -} -@end - -QT_BEGIN_NAMESPACE -void QMacInputContext::reset() -{ - QWidget *w = QInputContext::focusWidget(); - if (w) { - NSView *view = qt_mac_effectiveview_for(w); - if ([view isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) { - QMacCocoaAutoReleasePool pool; - QT_MANGLE_NAMESPACE(QCocoaView) *qc = static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view); - NSInputManager *currentIManager = [NSInputManager currentInputManager]; - if (currentIManager) { - [currentIManager markedTextAbandoned:view]; - [qc unmarkText]; - } - } - } -} - -bool QMacInputContext::isComposing() const -{ - QWidget *w = QInputContext::focusWidget(); - if (w) { - NSView *view = qt_mac_effectiveview_for(w); - if ([view isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) { - return [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view) isComposing]; - } - } - return false; -} - -extern bool qt_mac_in_drag; -void * /*NSImage */qt_mac_create_nsimage(const QPixmap &pm); -static const int default_pm_hotx = -2; -static const int default_pm_hoty = -16; -static const char* default_pm[] = { - "13 9 3 1", - ". c None", - " c #000000", - "X c #FFFFFF", - "X X X X X X X", - " X X X X X X ", - "X ......... X", - " X.........X ", - "X ......... X", - " X.........X ", - "X ......... X", - " X X X X X X ", - "X X X X X X X", -}; - -Qt::DropAction QDragManager::drag(QDrag *o) -{ - if(qt_mac_in_drag) { //just make sure.. - qWarning("Qt: Internal error: WH0A, unexpected condition reached"); - return Qt::IgnoreAction; - } - if(object == o) - return Qt::IgnoreAction; - /* At the moment it seems clear that Mac OS X does not want to drag with a non-left button - so we just bail early to prevent it */ - if(!(GetCurrentEventButtonState() & kEventMouseButtonPrimary)) - return Qt::IgnoreAction; - - if(object) { - dragPrivate()->source->removeEventFilter(this); - cancel(); - beingCancelled = false; - } - - object = o; - dragPrivate()->target = 0; - -#ifndef QT_NO_ACCESSIBILITY - QAccessible::updateAccessibility(this, 0, QAccessible::DragDropStart); -#endif - - // setup the data - QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacPasteboardMime::MIME_DND); - dragPrivate()->data->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy")); - dragBoard.setMimeData(dragPrivate()->data); - - // create the image - QPoint hotspot; - QPixmap pix = dragPrivate()->pixmap; - if(pix.isNull()) { - if(dragPrivate()->data->hasText() || dragPrivate()->data->hasUrls()) { - // get the string - QString s = dragPrivate()->data->hasText() ? dragPrivate()->data->text() - : dragPrivate()->data->urls().first().toString(); - if(s.length() > 26) - s = s.left(23) + QChar(0x2026); - if(!s.isEmpty()) { - // draw it - QFont f(qApp->font()); - f.setPointSize(12); - QFontMetrics fm(f); - QPixmap tmp(fm.width(s), fm.height()); - if(!tmp.isNull()) { - QPainter p(&tmp); - p.fillRect(0, 0, tmp.width(), tmp.height(), Qt::color0); - p.setPen(Qt::color1); - p.setFont(f); - p.drawText(0, fm.ascent(), s); - // save it - pix = tmp; - hotspot = QPoint(tmp.width() / 2, tmp.height() / 2); - } - } - } else { - pix = QPixmap(default_pm); - hotspot = QPoint(default_pm_hotx, default_pm_hoty); - } - } else { - hotspot = dragPrivate()->hotspot; - } - - // Convert the image to NSImage: - NSImage *image = (NSImage *)qt_mac_create_nsimage(pix); - [image retain]; - - DnDParams *dndParams = macCurrentDnDParameters(); - QT_MANGLE_NAMESPACE(QCocoaView) *theView = static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(dndParams->view); - - // Save supported actions: - [theView setSupportedActions: qt_mac_mapDropActions(dragPrivate()->possible_actions)]; - QPoint pointInView = [theView qt_qwidget]->mapFromGlobal(dndParams->globalPoint); - NSPoint imageLoc = {pointInView.x() - hotspot.x(), pointInView.y() + pix.height() - hotspot.y()}; - NSSize mouseOffset = {0.0, 0.0}; - NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; - dragPrivate()->executed_action = Qt::ActionMask; - - // Execute the drag: - [theView retain]; - [theView dragImage:image - at:imageLoc - offset:mouseOffset - event:dndParams->theEvent - pasteboard:pboard - source:theView - slideBack:YES]; - - // Reset the implicit grab widget when drag ends because we will not - // receive the mouse release event when DND is active: - qt_button_down = 0; - [theView release]; - [image release]; - if (dragPrivate()) - dragPrivate()->executed_action = Qt::IgnoreAction; - object = 0; - Qt::DropAction performedAction(qt_mac_mapNSDragOperation(dndParams->performedAction)); - - // Do post drag processing, if required. - if (performedAction != Qt::IgnoreAction) { - // Check if the receiver points us to a file location. - // if so, we need to do the file copy/move ourselves. - QCFType<CFURLRef> pasteLocation = 0; - PasteboardCopyPasteLocation(dragBoard.pasteBoard(), &pasteLocation); - if (pasteLocation) { - QList<QUrl> urls = o->mimeData()->urls(); - for (int i = 0; i < urls.size(); ++i) { - QUrl fromUrl = urls.at(i); - QString filename = QFileInfo(fromUrl.path()).fileName(); - QUrl toUrl(QCFString::toQString(CFURLGetString(pasteLocation)) + filename); - if (performedAction == Qt::MoveAction) - QFile::rename(fromUrl.path(), toUrl.path()); - else if (performedAction == Qt::CopyAction) - QFile::copy(fromUrl.path(), toUrl.path()); - } - } - } - - // Clean-up: - o->setMimeData(0); - o->deleteLater(); - return performedAction; -} - -QT_END_NAMESPACE - -#endif // QT_MAC_USE_COCOA diff --git a/src/gui/platforms/mac/qcocoaview_mac_p.h b/src/gui/platforms/mac/qcocoaview_mac_p.h deleted file mode 100644 index cc79b6705b..0000000000 --- a/src/gui/platforms/mac/qcocoaview_mac_p.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <qevent.h> -#ifdef QT_MAC_USE_COCOA -#import <Cocoa/Cocoa.h> - -@class QT_MANGLE_NAMESPACE(QCocoaView); -QT_FORWARD_DECLARE_CLASS(QWidgetPrivate); -QT_FORWARD_DECLARE_CLASS(QWidget); -QT_FORWARD_DECLARE_CLASS(QEvent); -QT_FORWARD_DECLARE_CLASS(QString); -QT_FORWARD_DECLARE_CLASS(QStringList); - -Q_GUI_EXPORT -@interface QT_MANGLE_NAMESPACE(QCocoaView) : NSControl <NSTextInput> { - QWidget *qwidget; - QWidgetPrivate *qwidgetprivate; - NSDragOperation supportedActions; - bool composing; - int composingLength; - bool sendKeyEvents; - bool fromKeyDownEvent; - QString *composingText; - @public int alienTouchCount; -} -- (id)initWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate; -- (void) finishInitWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate; -- (void)frameDidChange:(NSNotification *)note; -- (void)setSupportedActions:(NSDragOperation)actions; -- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal; -- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation; -- (BOOL)isComposing; -- (QWidget *)qt_qwidget; -- (void) qt_clearQWidget; - -@end -#endif diff --git a/src/gui/platforms/mac/qcocoawindow_mac.mm b/src/gui/platforms/mac/qcocoawindow_mac.mm deleted file mode 100644 index 6e5023aaca..0000000000 --- a/src/gui/platforms/mac/qcocoawindow_mac.mm +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmacdefines_mac.h" -#ifdef QT_MAC_USE_COCOA -#import <private/qcocoawindow_mac_p.h> -#import <private/qcocoawindowdelegate_mac_p.h> -#import <private/qcocoaview_mac_p.h> -#import <private/qt_cocoa_helpers_mac_p.h> -#import <private/qcocoawindowcustomthemeframe_mac_p.h> -#import <private/qcocoaapplication_mac_p.h> -#import <private/qdnd_p.h> -#import <private/qmultitouch_mac_p.h> - -#include <QtGui/QWidget> - -QT_FORWARD_DECLARE_CLASS(QWidget); -QT_USE_NAMESPACE - -@implementation NSWindow (QT_MANGLE_NAMESPACE(QWidgetIntegration)) - -- (id)QT_MANGLE_NAMESPACE(qt_initWithQWidget):(QWidget*)widget contentRect:(NSRect)rect styleMask:(NSUInteger)mask -{ - self = [self initWithContentRect:rect styleMask:mask backing:NSBackingStoreBuffered defer:YES]; - if (self) { - [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] becomeDelegteForWindow:self widget:widget]; - [self setReleasedWhenClosed:NO]; - } - return self; -} - -- (QWidget *)QT_MANGLE_NAMESPACE(qt_qwidget) -{ - QWidget *widget = 0; - if ([self delegate] == [QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate]) - widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; - return widget; -} - -@end - -@implementation QT_MANGLE_NAMESPACE(QCocoaWindow) - -/*********************************************************************** - Copy and Paste between QCocoaWindow and QCocoaPanel - This is a bit unfortunate, but thanks to the dynamic dispatch we - have to duplicate this code or resort to really silly forwarding methods -**************************************************************************/ -#include "qcocoasharedwindowmethods_mac_p.h" - -@end -#endif diff --git a/src/gui/platforms/mac/qcocoawindow_mac_p.h b/src/gui/platforms/mac/qcocoawindow_mac_p.h deleted file mode 100644 index d567cab244..0000000000 --- a/src/gui/platforms/mac/qcocoawindow_mac_p.h +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QCOCOAWINDOW_MAC_P -#define QCOCOAWINDOW_MAC_P - -#ifdef QT_MAC_USE_COCOA -#include "qmacdefines_mac.h" -#import <Cocoa/Cocoa.h> -#include <private/qapplication_p.h> -#include <private/qbackingstore_p.h> - -enum { QtMacCustomizeWindow = 1 << 21 }; // This will one day be run over by - -QT_FORWARD_DECLARE_CLASS(QWidget); -QT_FORWARD_DECLARE_CLASS(QStringList); -QT_FORWARD_DECLARE_CLASS(QCocoaDropData); - -@interface NSWindow (QtCoverForHackWithCategory) -+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; -@end - -@interface NSWindow (QT_MANGLE_NAMESPACE(QWidgetIntegration)) -- (id)QT_MANGLE_NAMESPACE(qt_initWithQWidget):(QWidget *)widget contentRect:(NSRect)rect styleMask:(NSUInteger)mask; -- (QWidget *)QT_MANGLE_NAMESPACE(qt_qwidget); -@end - -@interface NSWindow (QtIntegration) -- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender; -- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender; -- (void)draggingExited:(id <NSDraggingInfo>)sender; -- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender; -@end - -@interface QT_MANGLE_NAMESPACE(QCocoaWindow) : NSWindow { - QStringList *currentCustomDragTypes; - QCocoaDropData *dropData; - NSInteger dragEnterSequence; -} - -+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; -- (void)registerDragTypes; -- (void)drawRectOriginal:(NSRect)rect; - -@end -#endif - -#endif diff --git a/src/gui/platforms/mac/qcocoawindowcustomthemeframe_mac.mm b/src/gui/platforms/mac/qcocoawindowcustomthemeframe_mac.mm deleted file mode 100644 index b761934c01..0000000000 --- a/src/gui/platforms/mac/qcocoawindowcustomthemeframe_mac.mm +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmacdefines_mac.h" - -#ifdef QT_MAC_USE_COCOA - -#import "private/qcocoawindowcustomthemeframe_mac_p.h" -#import "private/qcocoawindow_mac_p.h" -#include "private/qt_cocoa_helpers_mac_p.h" -#include "qwidget.h" - -@implementation QT_MANGLE_NAMESPACE(QCocoaWindowCustomThemeFrame) - -- (void)_updateButtons -{ - [super _updateButtons]; - NSWindow *window = [self window]; - qt_syncCocoaTitleBarButtons(window, [window QT_MANGLE_NAMESPACE(qt_qwidget)]); -} - -@end - -#endif diff --git a/src/gui/platforms/mac/qcocoawindowcustomthemeframe_mac_p.h b/src/gui/platforms/mac/qcocoawindowcustomthemeframe_mac_p.h deleted file mode 100644 index 09b40875f6..0000000000 --- a/src/gui/platforms/mac/qcocoawindowcustomthemeframe_mac_p.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp -// and many other. This header file may change from version to version -// without notice, or even be removed. -// -// We mean it. -// -#import <Cocoa/Cocoa.h> -#include "qmacdefines_mac.h" -#import "qnsthemeframe_mac_p.h" - -@interface QT_MANGLE_NAMESPACE(QCocoaWindowCustomThemeFrame) : NSThemeFrame -{ -} - -@end diff --git a/src/gui/platforms/mac/qcocoawindowdelegate_mac.mm b/src/gui/platforms/mac/qcocoawindowdelegate_mac.mm deleted file mode 100644 index 1faf068a12..0000000000 --- a/src/gui/platforms/mac/qcocoawindowdelegate_mac.mm +++ /dev/null @@ -1,439 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#import "private/qcocoawindowdelegate_mac_p.h" -#ifdef QT_MAC_USE_COCOA -#include <private/qwidget_p.h> -#include <private/qapplication_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#include <qevent.h> -#include <qlayout.h> -#include <qcoreapplication.h> -#include <qmenubar.h> -#include <QMainWindow> -#include <QToolBar> -#include <private/qmainwindowlayout_p.h> - -QT_BEGIN_NAMESPACE -extern QWidgetData *qt_qwidget_data(QWidget *); // qwidget.cpp -extern void onApplicationWindowChangedActivation(QWidget *, bool); //qapplication_mac.mm -extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); // qapplication.cpp -QT_END_NAMESPACE - -QT_USE_NAMESPACE - -static QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) *sharedCocoaWindowDelegate = nil; - -// This is a singleton, but unlike most Cocoa singletons, it lives in a library and could be -// pontentially loaded and unloaded. This means we should at least attempt to do the -// memory management correctly. - -static void cleanupCocoaWindowDelegate() -{ - [sharedCocoaWindowDelegate release]; -} - -@implementation QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) - -- (id)init -{ - self = [super init]; - if (self != nil) { - m_windowHash = new QHash<NSWindow *, QWidget *>(); - m_drawerHash = new QHash<NSDrawer *, QWidget *>(); - } - return self; -} - -- (void)dealloc -{ - sharedCocoaWindowDelegate = nil; - QHash<NSWindow *, QWidget *>::const_iterator windowIt = m_windowHash->constBegin(); - while (windowIt != m_windowHash->constEnd()) { - [windowIt.key() setDelegate:nil]; - ++windowIt; - } - delete m_windowHash; - QHash<NSDrawer *, QWidget *>::const_iterator drawerIt = m_drawerHash->constBegin(); - while (drawerIt != m_drawerHash->constEnd()) { - [drawerIt.key() setDelegate:nil]; - ++drawerIt; - } - delete m_drawerHash; - [super dealloc]; -} - -+ (id)allocWithZone:(NSZone *)zone -{ - @synchronized(self) { - if (sharedCocoaWindowDelegate == nil) { - sharedCocoaWindowDelegate = [super allocWithZone:zone]; - return sharedCocoaWindowDelegate; - qAddPostRoutine(cleanupCocoaWindowDelegate); - } - } - return nil; -} - -+ (QT_MANGLE_NAMESPACE(QCocoaWindowDelegate)*)sharedDelegate -{ - @synchronized(self) { - if (sharedCocoaWindowDelegate == nil) - [[self alloc] init]; - } - return [[sharedCocoaWindowDelegate retain] autorelease]; -} - --(void)syncSizeForWidget:(QWidget *)qwidget toSize:(const QSize &)newSize fromSize:(const QSize &)oldSize -{ - qt_qwidget_data(qwidget)->crect.setSize(newSize); - // ### static contents optimization needs to go here - const OSViewRef view = qt_mac_nativeview_for(qwidget); - [view setFrameSize:NSMakeSize(newSize.width(), newSize.height())]; - if (!qwidget->isVisible()) { - qwidget->setAttribute(Qt::WA_PendingResizeEvent, true); - } else { - QResizeEvent qre(newSize, oldSize); - if (qwidget->testAttribute(Qt::WA_PendingResizeEvent)) { - qwidget->setAttribute(Qt::WA_PendingResizeEvent, false); - QApplication::sendEvent(qwidget, &qre); - } else { - qt_sendSpontaneousEvent(qwidget, &qre); - } - } -} - -- (void)dumpMaximizedStateforWidget:(QWidget*)qwidget window:(NSWindow *)window -{ - if (!window) - return; // Nothing to do. - QWidgetData *widgetData = qt_qwidget_data(qwidget); - if ((widgetData->window_state & Qt::WindowMaximized) && ![window isZoomed]) { - widgetData->window_state &= ~Qt::WindowMaximized; - QWindowStateChangeEvent e(Qt::WindowState(widgetData->window_state | Qt::WindowMaximized)); - qt_sendSpontaneousEvent(qwidget, &e); - } -} - -- (NSSize)closestAcceptableSizeForWidget:(QWidget *)qwidget window:(NSWindow *)window - withNewSize:(NSSize)proposedSize -{ - [self dumpMaximizedStateforWidget:qwidget window:window]; - QSize newSize = QLayout::closestAcceptableSize(qwidget, - QSize(proposedSize.width, proposedSize.height)); - return [NSWindow frameRectForContentRect: - NSMakeRect(0., 0., newSize.width(), newSize.height()) - styleMask:[window styleMask]].size; -} - -- (NSSize)windowWillResize:(NSWindow *)windowToResize toSize:(NSSize)proposedFrameSize -{ - QWidget *qwidget = m_windowHash->value(windowToResize); - return [self closestAcceptableSizeForWidget:qwidget window:windowToResize - withNewSize:[NSWindow contentRectForFrameRect: - NSMakeRect(0, 0, - proposedFrameSize.width, - proposedFrameSize.height) - styleMask:[windowToResize styleMask]].size]; -} - -- (NSSize)drawerWillResizeContents:(NSDrawer *)sender toSize:(NSSize)contentSize -{ - QWidget *qwidget = m_drawerHash->value(sender); - return [self closestAcceptableSizeForWidget:qwidget window:nil withNewSize:contentSize]; -} - --(void)windowDidMiniaturize:(NSNotification*)notification -{ - QWidget *qwidget = m_windowHash->value([notification object]); - if (!qwidget->isMinimized()) { - QWidgetData *widgetData = qt_qwidget_data(qwidget); - widgetData->window_state = widgetData->window_state | Qt::WindowMinimized; - QWindowStateChangeEvent e(Qt::WindowStates(widgetData->window_state & ~Qt::WindowMinimized)); - qt_sendSpontaneousEvent(qwidget, &e); - } - // Send hide to match Qt on X11 and Windows - QEvent e(QEvent::Hide); - qt_sendSpontaneousEvent(qwidget, &e); -} - -- (void)windowDidResize:(NSNotification *)notification -{ - NSWindow *window = [notification object]; - QWidget *qwidget = m_windowHash->value(window); - QWidgetData *widgetData = qt_qwidget_data(qwidget); - if (!(qwidget->windowState() & (Qt::WindowMaximized | Qt::WindowFullScreen)) && [window isZoomed]) { - widgetData->window_state = widgetData->window_state | Qt::WindowMaximized; - QWindowStateChangeEvent e(Qt::WindowStates(widgetData->window_state - & ~Qt::WindowMaximized)); - qt_sendSpontaneousEvent(qwidget, &e); - } else { - widgetData->window_state = widgetData->window_state & ~Qt::WindowMaximized; - QWindowStateChangeEvent e(Qt::WindowStates(widgetData->window_state - | Qt::WindowMaximized)); - qt_sendSpontaneousEvent(qwidget, &e); - } - NSRect rect = [[window contentView] frame]; - const QSize newSize(rect.size.width, rect.size.height); - const QSize &oldSize = widgetData->crect.size(); - if (newSize != oldSize) { - QWidgetPrivate::qt_mac_update_sizer(qwidget); - [self syncSizeForWidget:qwidget toSize:newSize fromSize:oldSize]; - } - - // We force the repaint to be synchronized with the resize of the window. - // Otherwise, the resize looks sluggish because we paint one event loop later. - if ([[window contentView] inLiveResize]) { - qwidget->repaint(); - - // We need to repaint the toolbar as well. - QMainWindow* mWindow = qobject_cast<QMainWindow*>(qwidget->window()); - if (mWindow) { - QMainWindowLayout *mLayout = qobject_cast<QMainWindowLayout*>(mWindow->layout()); - QList<QToolBar *> toolbarList = mLayout->qtoolbarsInUnifiedToolbarList; - - for (int i = 0; i < toolbarList.size(); ++i) { - QToolBar* toolbar = toolbarList.at(i); - toolbar->repaint(); - } - } - } -} - -- (void)windowDidMove:(NSNotification *)notification -{ - // The code underneath needs to translate the window location - // from bottom left (which is the origin used by Cocoa) to - // upper left (which is the origin used by Qt): - NSWindow *window = [notification object]; - NSRect newRect = [window frame]; - QWidget *qwidget = m_windowHash->value(window); - QPoint qtPoint = flipPoint(NSMakePoint(newRect.origin.x, - newRect.origin.y + newRect.size.height)).toPoint(); - const QRect &oldRect = qwidget->frameGeometry(); - - if (qtPoint.x() != oldRect.x() || qtPoint.y() != oldRect.y()) { - QWidgetData *widgetData = qt_qwidget_data(qwidget); - QRect oldCRect = widgetData->crect; - QWidgetPrivate *widgetPrivate = qt_widget_private(qwidget); - const QRect &fStrut = widgetPrivate->frameStrut(); - widgetData->crect.moveTo(qtPoint.x() + fStrut.left(), qtPoint.y() + fStrut.top()); - if (!qwidget->isVisible()) { - qwidget->setAttribute(Qt::WA_PendingMoveEvent, true); - } else { - QMoveEvent qme(qtPoint, oldRect.topLeft()); - qt_sendSpontaneousEvent(qwidget, &qme); - } - } -} - --(BOOL)windowShouldClose:(id)windowThatWantsToClose -{ - QWidget *qwidget = m_windowHash->value(windowThatWantsToClose); - QScopedLoopLevelCounter counter(qt_widget_private(qwidget)->threadData); - return qt_widget_private(qwidget)->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); -} - --(void)windowDidDeminiaturize:(NSNotification *)notification -{ - QWidget *qwidget = m_windowHash->value([notification object]); - QWidgetData *widgetData = qt_qwidget_data(qwidget); - Qt::WindowStates currState = Qt::WindowStates(widgetData->window_state); - Qt::WindowStates newState = currState; - if (currState & Qt::WindowMinimized) - newState &= ~Qt::WindowMinimized; - if (!(currState & Qt::WindowActive)) - newState |= Qt::WindowActive; - if (newState != currState) { - widgetData->window_state = newState; - QWindowStateChangeEvent e(currState); - qt_sendSpontaneousEvent(qwidget, &e); - } - QShowEvent qse; - qt_sendSpontaneousEvent(qwidget, &qse); -} - --(void)windowDidBecomeMain:(NSNotification*)notification -{ - QWidget *qwidget = m_windowHash->value([notification object]); - Q_ASSERT(qwidget); - onApplicationWindowChangedActivation(qwidget, true); -} - --(void)windowDidResignMain:(NSNotification*)notification -{ - QWidget *qwidget = m_windowHash->value([notification object]); - Q_ASSERT(qwidget); - onApplicationWindowChangedActivation(qwidget, false); -} - -// These are the same as main, but they are probably better to keep separate since there is a -// tiny difference between main and key windows. --(void)windowDidBecomeKey:(NSNotification*)notification -{ - QWidget *qwidget = m_windowHash->value([notification object]); - Q_ASSERT(qwidget); - onApplicationWindowChangedActivation(qwidget, true); -} - --(void)windowDidResignKey:(NSNotification*)notification -{ - QWidget *qwidget = m_windowHash->value([notification object]); - Q_ASSERT(qwidget); - onApplicationWindowChangedActivation(qwidget, false); -} - --(QWidget *)qt_qwidgetForWindow:(NSWindow *)window -{ - return m_windowHash->value(window); -} - -- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame -{ - Q_UNUSED(newFrame); - // saving the current window geometry before the window is maximized - QWidget *qwidget = m_windowHash->value(window); - QWidgetPrivate *widgetPrivate = qt_widget_private(qwidget); - if (qwidget->isWindow()) { - if(qwidget->windowState() & Qt::WindowMaximized) { - // Restoring - widgetPrivate->topData()->wasMaximized = false; - } else { - // Maximizing - widgetPrivate->topData()->normalGeometry = qwidget->geometry(); - // If the window was maximized we need to update the coordinates since now it will start at 0,0. - // We do this in a special field that is only used when not restoring but manually resizing the window. - // Since the coordinates are fixed we just set a boolean flag. - widgetPrivate->topData()->wasMaximized = true; - } - } - return YES; -} - -- (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)defaultFrame -{ - NSRect frameToReturn = defaultFrame; - QWidget *qwidget = m_windowHash->value(window); - QSizeF size = qwidget->maximumSize(); - NSRect windowFrameRect = [window frame]; - NSRect viewFrameRect = [[window contentView] frame]; - // consider additional size required for titlebar & frame - frameToReturn.size.width = qMin<CGFloat>(frameToReturn.size.width, - size.width()+(windowFrameRect.size.width - viewFrameRect.size.width)); - frameToReturn.size.height = qMin<CGFloat>(frameToReturn.size.height, - size.height()+(windowFrameRect.size.height - viewFrameRect.size.height)); - return frameToReturn; -} - -- (void)becomeDelegteForWindow:(NSWindow *)window widget:(QWidget *)widget -{ - m_windowHash->insert(window, widget); - [window setDelegate:self]; -} - -- (void)resignDelegateForWindow:(NSWindow *)window -{ - [window setDelegate:nil]; - m_windowHash->remove(window); -} - -- (void)becomeDelegateForDrawer:(NSDrawer *)drawer widget:(QWidget *)widget -{ - m_drawerHash->insert(drawer, widget); - [drawer setDelegate:self]; - NSWindow *window = [[drawer contentView] window]; - [self becomeDelegteForWindow:window widget:widget]; -} - -- (void)resignDelegateForDrawer:(NSDrawer *)drawer -{ - QWidget *widget = m_drawerHash->value(drawer); - [drawer setDelegate:nil]; - if (widget) - [self resignDelegateForWindow:[[drawer contentView] window]]; - m_drawerHash->remove(drawer); -} - -- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu -{ - Q_UNUSED(menu); - QWidget *qwidget = m_windowHash->value(window); - if (qwidget && !qwidget->windowFilePath().isEmpty()) { - return YES; - } - return NO; -} - -- (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event - from:(NSPoint)dragImageLocation - withPasteboard:(NSPasteboard *)pasteboard -{ - Q_UNUSED(event); - Q_UNUSED(dragImageLocation); - Q_UNUSED(pasteboard); - QWidget *qwidget = m_windowHash->value(window); - if (qwidget && !qwidget->windowFilePath().isEmpty()) { - return YES; - } - return NO; -} - -- (void)syncContentViewFrame: (NSNotification *)notification -{ - NSView *cView = [notification object]; - if (cView) { - NSWindow *window = [cView window]; - QWidget *qwidget = m_windowHash->value(window); - if (qwidget) { - QWidgetData *widgetData = qt_qwidget_data(qwidget); - NSRect rect = [cView frame]; - const QSize newSize(rect.size.width, rect.size.height); - const QSize &oldSize = widgetData->crect.size(); - if (newSize != oldSize) { - [self syncSizeForWidget:qwidget toSize:newSize fromSize:oldSize]; - } - } - - } -} - -@end -#endif// QT_MAC_USE_COCOA diff --git a/src/gui/platforms/mac/qcocoawindowdelegate_mac_p.h b/src/gui/platforms/mac/qcocoawindowdelegate_mac_p.h deleted file mode 100644 index 638ce2df9a..0000000000 --- a/src/gui/platforms/mac/qcocoawindowdelegate_mac_p.h +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qmacdefines_mac.h" - -#ifdef QT_MAC_USE_COCOA -#import <Cocoa/Cocoa.h> - -QT_BEGIN_NAMESPACE -template <class Key, class T> class QHash; -QT_END_NAMESPACE -using QT_PREPEND_NAMESPACE(QHash); -QT_FORWARD_DECLARE_CLASS(QWidget) -QT_FORWARD_DECLARE_CLASS(QSize) -QT_FORWARD_DECLARE_CLASS(QWidgetData) - -#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 -@protocol NSWindowDelegate <NSObject> -- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize; -- (void)windowDidMiniaturize:(NSNotification*)notification; -- (void)windowDidResize:(NSNotification *)notification; -- (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)defaultFrame; -- (void)windowDidMove:(NSNotification *)notification; -- (BOOL)windowShouldClose:(id)window; -- (void)windowDidDeminiaturize:(NSNotification *)notification; -- (void)windowDidBecomeMain:(NSNotification*)notification; -- (void)windowDidResignMain:(NSNotification*)notification; -- (void)windowDidBecomeKey:(NSNotification*)notification; -- (void)windowDidResignKey:(NSNotification*)notification; -- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu; -- (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard; -- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame; -@end - -@protocol NSDrawerDelegate <NSObject> -- (NSSize)drawerWillResizeContents:(NSDrawer *)sender toSize:(NSSize)contentSize; -@end - -#endif - - - -@interface QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) : NSObject<NSWindowDelegate, NSDrawerDelegate> { - QHash<NSWindow *, QWidget *> *m_windowHash; - QHash<NSDrawer *, QWidget *> *m_drawerHash; -} -+ (QT_MANGLE_NAMESPACE(QCocoaWindowDelegate)*)sharedDelegate; -- (void)becomeDelegteForWindow:(NSWindow *)window widget:(QWidget *)widget; -- (void)resignDelegateForWindow:(NSWindow *)window; -- (void)becomeDelegateForDrawer:(NSDrawer *)drawer widget:(QWidget *)widget; -- (void)resignDelegateForDrawer:(NSDrawer *)drawer; -- (void)dumpMaximizedStateforWidget:(QWidget*)qwidget window:(NSWindow *)window; -- (void)syncSizeForWidget:(QWidget *)qwidget - toSize:(const QSize &)newSize - fromSize:(const QSize &)oldSize; -- (NSSize)closestAcceptableSizeForWidget:(QWidget *)qwidget - window:(NSWindow *)window withNewSize:(NSSize)proposedSize; -- (QWidget *)qt_qwidgetForWindow:(NSWindow *)window; -- (void)syncContentViewFrame: (NSNotification *)notification; -@end -#endif diff --git a/src/gui/platforms/mac/qcolormap_mac.cpp b/src/gui/platforms/mac/qcolormap_mac.cpp deleted file mode 100644 index 28589f41b8..0000000000 --- a/src/gui/platforms/mac/qcolormap_mac.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qcolormap.h" -#include "qcolor.h" - -QT_BEGIN_NAMESPACE - -class QColormapPrivate -{ -public: - inline QColormapPrivate() - : ref(1) - { } - - QAtomicInt ref; -}; -static QColormap *qt_mac_global_map = 0; - -void QColormap::initialize() -{ - qt_mac_global_map = new QColormap; -} - -void QColormap::cleanup() -{ - delete qt_mac_global_map; - qt_mac_global_map = 0; -} - -QColormap QColormap::instance(int) -{ - return *qt_mac_global_map; -} - -QColormap::QColormap() : d(new QColormapPrivate) -{} - -QColormap::QColormap(const QColormap &colormap) :d (colormap.d) -{ d->ref.ref(); } - -QColormap::~QColormap() -{ - if (!d->ref.deref()) - delete d; -} - -QColormap::Mode QColormap::mode() const -{ return QColormap::Direct; } - -int QColormap::depth() const -{ - return 32; -} - -int QColormap::size() const -{ - return -1; -} - -uint QColormap::pixel(const QColor &color) const -{ return color.rgba(); } - -const QColor QColormap::colorAt(uint pixel) const -{ return QColor(pixel); } - -const QVector<QColor> QColormap::colormap() const -{ return QVector<QColor>(); } - -QColormap &QColormap::operator=(const QColormap &colormap) -{ qAtomicAssign(d, colormap.d); return *this; } - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qcursor_mac.mm b/src/gui/platforms/mac/qcursor_mac.mm deleted file mode 100644 index 0afa3ee4f0..0000000000 --- a/src/gui/platforms/mac/qcursor_mac.mm +++ /dev/null @@ -1,689 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qcursor_p.h> -#include <private/qpixmap_mac_p.h> -#include <qapplication.h> -#include <qbitmap.h> -#include <qcursor.h> -#include <qevent.h> -#include <string.h> -#include <unistd.h> -#include <AppKit/NSCursor.h> -#include <qpainter.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#include <private/qapplication_p.h> - -QT_BEGIN_NAMESPACE - -/***************************************************************************** - Externals - *****************************************************************************/ -extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; -extern OSWindowRef qt_mac_window_for(const QWidget *); //qwidget_mac.cpp -extern GrafPtr qt_mac_qd_context(const QPaintDevice *); //qpaintdevice_mac.cpp -extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); //qapplication_mac.cpp -extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp - -/***************************************************************************** - Internal QCursorData class - *****************************************************************************/ - -class QMacAnimateCursor : public QObject -{ - int timerId, step; - ThemeCursor curs; -public: - QMacAnimateCursor() : QObject(), timerId(-1) { } - void start(ThemeCursor c) { - step = 1; - if(timerId != -1) - killTimer(timerId); - timerId = startTimer(300); - curs = c; - } - void stop() { - if(timerId != -1) { - killTimer(timerId); - timerId = -1; - } - } -protected: - void timerEvent(QTimerEvent *e) { - if(e->timerId() == timerId) { - /* - if(SetAnimatedThemeCursor(curs, step++) == themeBadCursorIndexErr) - stop(); - */ - } - } -}; - -inline void *qt_mac_nsCursorForQCursor(const QCursor &c) -{ - c.d->update(); - return [[static_cast<NSCursor *>(c.d->curs.cp.nscursor) retain] autorelease]; -} - -static QCursorData *currentCursor = 0; //current cursor - -void qt_mac_set_cursor(const QCursor *c) -{ -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(*c)) set]; -#else - if (!c) { - currentCursor = 0; - return; - } - c->handle(); //force the cursor to get loaded, if it's not - - if(currentCursor && currentCursor->type == QCursorData::TYPE_ThemeCursor - && currentCursor->curs.tc.anim) - currentCursor->curs.tc.anim->stop(); - if(c->d->type == QCursorData::TYPE_ImageCursor) { - [static_cast<NSCursor *>(c->d->curs.cp.nscursor) set]; - } else if(c->d->type == QCursorData::TYPE_ThemeCursor) { - if(SetAnimatedThemeCursor(c->d->curs.tc.curs, 0) == themeBadCursorIndexErr) { - SetThemeCursor(c->d->curs.tc.curs); - } else { - if(!c->d->curs.tc.anim) - c->d->curs.tc.anim = new QMacAnimateCursor; - c->d->curs.tc.anim->start(c->d->curs.tc.curs); - } - } - - currentCursor = c->d; -#endif -} - -static QPointer<QWidget> lastWidgetUnderMouse = 0; -static QPointer<QWidget> lastMouseCursorWidget = 0; -static bool qt_button_down_on_prev_call = false; -static QCursor *grabCursor = 0; - -void qt_mac_updateCursorWithWidgetUnderMouse(QWidget *widgetUnderMouse) -{ - QCursor cursor(Qt::ArrowCursor); - if (qt_button_down) { - // The widget that is currently pressed - // grabs the mouse cursor: - widgetUnderMouse = qt_button_down; - qt_button_down_on_prev_call = true; - } else if (qt_button_down_on_prev_call) { - // Grab has been released, so do - // a full check: - qt_button_down_on_prev_call = false; - lastWidgetUnderMouse = 0; - lastMouseCursorWidget = 0; - } - - if (QApplication::overrideCursor()) { - cursor = *QApplication::overrideCursor(); - } else if (grabCursor) { - cursor = *grabCursor; - } else if (widgetUnderMouse) { - if (widgetUnderMouse == lastWidgetUnderMouse) { - // Optimization that should hit when the widget under - // the mouse does not change as the mouse moves: - if (lastMouseCursorWidget) - cursor = lastMouseCursorWidget->cursor(); - } else { - QWidget *w = widgetUnderMouse; - for (; w; w = w->parentWidget()) { - if (w->testAttribute(Qt::WA_SetCursor)) { - cursor = w->cursor(); - break; - } - if (w->isWindow()) - break; - } - // One final check in case we ran out of parents in the loop: - if (w && !w->testAttribute(Qt::WA_SetCursor)) - w = 0; - - lastWidgetUnderMouse = widgetUnderMouse; - lastMouseCursorWidget = w; - } - } - -#ifdef QT_MAC_USE_COCOA - cursor.d->update(); - NSCursor *nsCursor = static_cast<NSCursor *>(cursor.d->curs.cp.nscursor); - if ([NSCursor currentCursor] != nsCursor) { - QMacCocoaAutoReleasePool pool; - [nsCursor set]; - } -#else - qt_mac_set_cursor(&cursor); -#endif -} - -void qt_mac_update_cursor() -{ - // This function is similar to qt_mac_updateCursorWithWidgetUnderMouse - // except that is clears the optimization cache, and finds the widget - // under mouse itself. Clearing the cache is useful in cases where the - // application has been deactivated/activated etc. - // NB: since we dont have any true native widget, the call to - // qt_mac_getTargetForMouseEvent will fail when the mouse is over QMacNativeWidgets. -#ifdef QT_MAC_USE_COCOA - lastWidgetUnderMouse = 0; - lastMouseCursorWidget = 0; - QWidget *widgetUnderMouse = 0; - - if (qt_button_down) { - widgetUnderMouse = qt_button_down; - } else { - QPoint localPoint; - QPoint globalPoint; - qt_mac_getTargetForMouseEvent(0, QEvent::None, localPoint, globalPoint, 0, &widgetUnderMouse); - } - qt_mac_updateCursorWithWidgetUnderMouse(widgetUnderMouse); -#else - qt_mac_updateCursorWithWidgetUnderMouse(QApplication::widgetAt(QCursor::pos())); -#endif -} - -void qt_mac_setMouseGrabCursor(bool set, QCursor *const cursor = 0) -{ - if (grabCursor) { - delete grabCursor; - grabCursor = 0; - } - if (set) { - if (cursor) - grabCursor = new QCursor(*cursor); - else if (lastMouseCursorWidget) - grabCursor = new QCursor(lastMouseCursorWidget->cursor()); - else - grabCursor = new QCursor(Qt::ArrowCursor); - } - qt_mac_update_cursor(); -} - -#ifndef QT_MAC_USE_COCOA -void qt_mac_update_cursor_at_global_pos(const QPoint &globalPos) -{ - qt_mac_updateCursorWithWidgetUnderMouse(QApplication::widgetAt(globalPos)); -} -#endif - -static int nextCursorId = Qt::BitmapCursor; - -QCursorData::QCursorData(Qt::CursorShape s) - : cshape(s), bm(0), bmm(0), hx(-1), hy(-1), mId(s), type(TYPE_None) -{ - ref = 1; - memset(&curs, '\0', sizeof(curs)); -} - -QCursorData::~QCursorData() -{ - if (type == TYPE_ImageCursor) { - if (curs.cp.my_cursor) { - QMacCocoaAutoReleasePool pool; - [static_cast<NSCursor *>(curs.cp.nscursor) release]; - } - } else if(type == TYPE_ThemeCursor) { - delete curs.tc.anim; - } - type = TYPE_None; - - delete bm; - delete bmm; - if(currentCursor == this) - currentCursor = 0; -} - -QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY) -{ - if (!QCursorData::initialized) - QCursorData::initialize(); - if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) { - qWarning("Qt: QCursor: Cannot create bitmap cursor; invalid bitmap(s)"); - QCursorData *c = qt_cursorTable[0]; - c->ref.ref(); - return c; - } - // This is silly, but this is apparently called outside the constructor, so we have - // to be ready for that case. - QCursorData *x = new QCursorData; - x->ref = 1; - x->mId = ++nextCursorId; - x->bm = new QBitmap(bitmap); - x->bmm = new QBitmap(mask); - x->cshape = Qt::BitmapCursor; - x->hx = hotX >= 0 ? hotX : bitmap.width() / 2; - x->hy = hotY >= 0 ? hotY : bitmap.height() / 2; - return x; -} - -Qt::HANDLE QCursor::handle() const -{ - if(!QCursorData::initialized) - QCursorData::initialize(); - if(d->type == QCursorData::TYPE_None) - d->update(); - return (Qt::HANDLE)d->mId; -} - -QPoint QCursor::pos() -{ - return flipPoint([NSEvent mouseLocation]).toPoint(); -} - -void QCursor::setPos(int x, int y) -{ -#ifdef QT_MAC_USE_COCOA - CGPoint pos; - pos.x = x; - pos.y = y; - - CGEventRef e = CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, 0); - CGEventPost(kCGHIDEventTap, e); - CFRelease(e); -#else - CGWarpMouseCursorPosition(CGPointMake(x, y)); - - /* I'm not too keen on doing this, but this makes it a lot easier, so I just - send the event back through the event system and let it get propagated correctly - ideally this would not really need to be faked --Sam - */ - QWidget *widget = 0; - if(QWidget *grb = QWidget::mouseGrabber()) - widget = grb; - else - widget = QApplication::widgetAt(QPoint(x, y)); - if(widget) { - QMouseEvent me(QMouseEvent::MouseMove, widget->mapFromGlobal(QPoint(x, y)), Qt::NoButton, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); - qt_sendSpontaneousEvent(widget, &me); - } -#endif -} - -void QCursorData::initCursorFromBitmap() -{ - NSImage *nsimage; - QImage finalCursor(bm->size(), QImage::Format_ARGB32); - QImage bmi = bm->toImage().convertToFormat(QImage::Format_RGB32); - QImage bmmi = bmm->toImage().convertToFormat(QImage::Format_RGB32); - for (int row = 0; row < finalCursor.height(); ++row) { - QRgb *bmData = reinterpret_cast<QRgb *>(bmi.scanLine(row)); - QRgb *bmmData = reinterpret_cast<QRgb *>(bmmi.scanLine(row)); - QRgb *finalData = reinterpret_cast<QRgb *>(finalCursor.scanLine(row)); - for (int col = 0; col < finalCursor.width(); ++col) { - if (bmmData[col] == 0xff000000 && bmData[col] == 0xffffffff) { - finalData[col] = 0xffffffff; - } else if (bmmData[col] == 0xff000000 && bmData[col] == 0xffffffff) { - finalData[col] = 0x7f000000; - } else if (bmmData[col] == 0xffffffff && bmData[col] == 0xffffffff) { - finalData[col] = 0x00000000; - } else { - finalData[col] = 0xff000000; - } - } - } - type = QCursorData::TYPE_ImageCursor; - curs.cp.my_cursor = true; - QPixmap bmCopy = QPixmap::fromImage(finalCursor); - NSPoint hotSpot = { hx, hy }; - nsimage = static_cast<NSImage*>(qt_mac_create_nsimage(bmCopy)); - curs.cp.nscursor = [[NSCursor alloc] initWithImage:nsimage hotSpot: hotSpot]; - [nsimage release]; -} - -void QCursorData::initCursorFromPixmap() -{ - type = QCursorData::TYPE_ImageCursor; - curs.cp.my_cursor = true; - NSPoint hotSpot = { hx, hy }; - NSImage *nsimage; - nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap)); - curs.cp.nscursor = [[NSCursor alloc] initWithImage:nsimage hotSpot: hotSpot]; - [nsimage release]; -} - -void QCursorData::update() -{ - if(!QCursorData::initialized) - QCursorData::initialize(); - if(type != QCursorData::TYPE_None) - return; - - /* Note to self... *** - * mask x data - * 0xFF x 0x00 == fully opaque white - * 0x00 x 0xFF == xor'd black - * 0xFF x 0xFF == fully opaque black - * 0x00 x 0x00 == fully transparent - */ - - if (hx < 0) - hx = 0; - if (hy < 0) - hy = 0; - -#define QT_USE_APPROXIMATE_CURSORS -#ifdef QT_USE_APPROXIMATE_CURSORS - static const uchar cur_ver_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0, - 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x0f, 0xf0, - 0x07, 0xe0, 0x03, 0xc0, 0x01, 0x80, 0x00, 0x00 }; - static const uchar mcur_ver_bits[] = { - 0x00, 0x00, 0x03, 0x80, 0x07, 0xc0, 0x0f, 0xe0, 0x1f, 0xf0, 0x3f, 0xf8, - 0x7f, 0xfc, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x7f, 0xfc, 0x3f, 0xf8, - 0x1f, 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80 }; - - static const uchar cur_hor_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x18, 0x30, - 0x38, 0x38, 0x7f, 0xfc, 0x7f, 0xfc, 0x38, 0x38, 0x18, 0x30, 0x08, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static const uchar mcur_hor_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x0c, 0x60, 0x1c, 0x70, 0x3c, 0x78, - 0x7f, 0xfc, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xfc, 0x3c, 0x78, - 0x1c, 0x70, 0x0c, 0x60, 0x04, 0x40, 0x00, 0x00 }; - - static const uchar cur_fdiag_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0xf8, 0x00, 0x78, - 0x00, 0xf8, 0x01, 0xd8, 0x23, 0x88, 0x37, 0x00, 0x3e, 0x00, 0x3c, 0x00, - 0x3e, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static const uchar mcur_fdiag_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0xfc, - 0x41, 0xfc, 0x63, 0xfc, 0x77, 0xdc, 0x7f, 0x8c, 0x7f, 0x04, 0x7e, 0x00, - 0x7f, 0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x00, 0x00 }; - - static const uchar cur_bdiag_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x3e, 0x00, - 0x37, 0x00, 0x23, 0x88, 0x01, 0xd8, 0x00, 0xf8, 0x00, 0x78, 0x00, 0xf8, - 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static const uchar mcur_bdiag_bits[] = { - 0x00, 0x00, 0x7f, 0xc0, 0x7f, 0x80, 0x7f, 0x00, 0x7e, 0x00, 0x7f, 0x04, - 0x7f, 0x8c, 0x77, 0xdc, 0x63, 0xfc, 0x41, 0xfc, 0x00, 0xfc, 0x01, 0xfc, - 0x03, 0xfc, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00 }; - - static const unsigned char cur_up_arrow_bits[] = { - 0x00, 0x80, 0x01, 0x40, 0x01, 0x40, 0x02, 0x20, 0x02, 0x20, 0x04, 0x10, - 0x04, 0x10, 0x08, 0x08, 0x0f, 0x78, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, - 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0xc0 }; - static const unsigned char mcur_up_arrow_bits[] = { - 0x00, 0x80, 0x01, 0xc0, 0x01, 0xc0, 0x03, 0xe0, 0x03, 0xe0, 0x07, 0xf0, - 0x07, 0xf0, 0x0f, 0xf8, 0x0f, 0xf8, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, - 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0 }; -#endif - const uchar *cursorData = 0; - const uchar *cursorMaskData = 0; -#ifdef QT_MAC_USE_COCOA - switch (cshape) { // map Q cursor to MAC cursor - case Qt::BitmapCursor: { - if (pixmap.isNull()) - initCursorFromBitmap(); - else - initCursorFromPixmap(); - break; } - case Qt::BlankCursor: { - pixmap = QPixmap(16, 16); - pixmap.fill(Qt::transparent); - initCursorFromPixmap(); - break; } - case Qt::ArrowCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.cp.nscursor = [NSCursor arrowCursor]; - break; } - case Qt::CrossCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.cp.nscursor = [NSCursor crosshairCursor]; - break; } - case Qt::WaitCursor: { - pixmap = QPixmap(QLatin1String(":/trolltech/mac/cursors/images/spincursor.png")); - initCursorFromPixmap(); - break; } - case Qt::IBeamCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.cp.nscursor = [NSCursor IBeamCursor]; - break; } - case Qt::SizeAllCursor: { - pixmap = QPixmap(QLatin1String(":/trolltech/mac/cursors/images/pluscursor.png")); - initCursorFromPixmap(); - break; } - case Qt::WhatsThisCursor: { //for now just use the pointing hand - case Qt::PointingHandCursor: - type = QCursorData::TYPE_ThemeCursor; - curs.cp.nscursor = [NSCursor pointingHandCursor]; - break; } - case Qt::BusyCursor: { - pixmap = QPixmap(QLatin1String(":/trolltech/mac/cursors/images/waitcursor.png")); - initCursorFromPixmap(); - break; } - case Qt::SplitVCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.cp.nscursor = [NSCursor resizeUpDownCursor]; - break; } - case Qt::SplitHCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.cp.nscursor = [NSCursor resizeLeftRightCursor]; - break; } - case Qt::ForbiddenCursor: { - pixmap = QPixmap(QLatin1String(":/trolltech/mac/cursors/images/forbiddencursor.png")); - initCursorFromPixmap(); - break; } - case Qt::OpenHandCursor: - type = QCursorData::TYPE_ThemeCursor; - curs.cp.nscursor = [NSCursor openHandCursor]; - break; - case Qt::ClosedHandCursor: - type = QCursorData::TYPE_ThemeCursor; - curs.cp.nscursor = [NSCursor closedHandCursor]; - break; - case Qt::DragCopyCursor: - type = QCursorData::TYPE_ThemeCursor; - if ([NSCursor respondsToSelector:@selector(dragCopyCursor)]) - curs.cp.nscursor = [NSCursor performSelector:@selector(dragCopyCursor)]; - break; - case Qt::DragMoveCursor: - type = QCursorData::TYPE_ThemeCursor; - curs.cp.nscursor = [NSCursor arrowCursor]; - break; - case Qt::DragLinkCursor: - type = QCursorData::TYPE_ThemeCursor; - if ([NSCursor respondsToSelector:@selector(dragLinkCursor)]) - curs.cp.nscursor = [NSCursor performSelector:@selector(dragLinkCursor)]; - break; -#define QT_USE_APPROXIMATE_CURSORS -#ifdef QT_USE_APPROXIMATE_CURSORS - case Qt::SizeVerCursor: - cursorData = cur_ver_bits; - cursorMaskData = mcur_ver_bits; - hx = hy = 8; - break; - case Qt::SizeHorCursor: - cursorData = cur_hor_bits; - cursorMaskData = mcur_hor_bits; - hx = hy = 8; - break; - case Qt::SizeBDiagCursor: - cursorData = cur_fdiag_bits; - cursorMaskData = mcur_fdiag_bits; - hx = hy = 8; - break; - case Qt::SizeFDiagCursor: - cursorData = cur_bdiag_bits; - cursorMaskData = mcur_bdiag_bits; - hx = hy = 8; - break; - case Qt::UpArrowCursor: - cursorData = cur_up_arrow_bits; - cursorMaskData = mcur_up_arrow_bits; - hx = 8; - break; -#endif - default: - qWarning("Qt: QCursor::update: Invalid cursor shape %d", cshape); - return; - } -#else - // Carbon - switch (cshape) { // map Q cursor to MAC cursor - case Qt::BitmapCursor: { - if (pixmap.isNull()) - initCursorFromBitmap(); - else - initCursorFromPixmap(); - break; } - case Qt::BlankCursor: { - pixmap = QPixmap(16, 16); - pixmap.fill(Qt::transparent); - initCursorFromPixmap(); - break; } - case Qt::ArrowCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemeArrowCursor; - break; } - case Qt::CrossCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemeCrossCursor; - break; } - case Qt::WaitCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemeWatchCursor; - break; } - case Qt::IBeamCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemeIBeamCursor; - break; } - case Qt::SizeAllCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemePlusCursor; - break; } - case Qt::WhatsThisCursor: { //for now just use the pointing hand - case Qt::PointingHandCursor: - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemePointingHandCursor; - break; } - case Qt::BusyCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemeSpinningCursor; - break; } - case Qt::SplitVCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemeResizeUpDownCursor; - break; } - case Qt::SplitHCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemeResizeLeftRightCursor; - break; } - case Qt::ForbiddenCursor: { - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemeNotAllowedCursor; - break; } - case Qt::OpenHandCursor: - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemeOpenHandCursor; - break; - case Qt::ClosedHandCursor: - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemeClosedHandCursor; - break; - case Qt::DragMoveCursor: - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemeArrowCursor; - break; - case Qt::DragCopyCursor: - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemeCopyArrowCursor; - break; - case Qt::DragLinkCursor: - type = QCursorData::TYPE_ThemeCursor; - curs.tc.curs = kThemeAliasArrowCursor; - break; -#define QT_USE_APPROXIMATE_CURSORS -#ifdef QT_USE_APPROXIMATE_CURSORS - case Qt::SizeVerCursor: - cursorData = cur_ver_bits; - cursorMaskData = mcur_ver_bits; - hx = hy = 8; - break; - case Qt::SizeHorCursor: - cursorData = cur_hor_bits; - cursorMaskData = mcur_hor_bits; - hx = hy = 8; - break; - case Qt::SizeBDiagCursor: - cursorData = cur_fdiag_bits; - cursorMaskData = mcur_fdiag_bits; - hx = hy = 8; - break; - case Qt::SizeFDiagCursor: - cursorData = cur_bdiag_bits; - cursorMaskData = mcur_bdiag_bits; - hx = hy = 8; - break; - case Qt::UpArrowCursor: - cursorData = cur_up_arrow_bits; - cursorMaskData = mcur_up_arrow_bits; - hx = 8; - break; -#endif - default: - qWarning("Qt: QCursor::update: Invalid cursor shape %d", cshape); - return; - } -#endif - - if (cursorData) { - bm = new QBitmap(QBitmap::fromData(QSize(16, 16), cursorData, - QImage::Format_Mono)); - bmm = new QBitmap(QBitmap::fromData(QSize(16, 16), cursorMaskData, - QImage::Format_Mono)); - initCursorFromBitmap(); - } - -#if 0 - if(type == QCursorData::TYPE_CursPtr && curs.cp.hcurs && curs.cp.my_cursor) { - curs.cp.hcurs->hotSpot.h = hx >= 0 ? hx : 8; - curs.cp.hcurs->hotSpot.v = hy >= 0 ? hy : 8; - } -#endif -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qdesktopwidget_mac.mm b/src/gui/platforms/mac/qdesktopwidget_mac.mm deleted file mode 100644 index 0b529c9843..0000000000 --- a/src/gui/platforms/mac/qdesktopwidget_mac.mm +++ /dev/null @@ -1,257 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -#import <Cocoa/Cocoa.h> - -#include "qapplication.h" -#include "qdesktopwidget.h" -#include <private/qt_mac_p.h> -#include "qwidget_p.h" -#include <private/qt_cocoa_helpers_mac_p.h> -#include <private/qdesktopwidget_mac_p.h> - -QT_BEGIN_NAMESPACE - -QT_USE_NAMESPACE - -/***************************************************************************** - Externals - *****************************************************************************/ - -/***************************************************************************** - QDesktopWidget member functions - *****************************************************************************/ - -Q_GLOBAL_STATIC(QDesktopWidgetImplementation, qdesktopWidgetImplementation) - -QDesktopWidgetImplementation::QDesktopWidgetImplementation() - : appScreen(0) -{ - onResize(); -} - -QDesktopWidgetImplementation::~QDesktopWidgetImplementation() -{ -} - -QDesktopWidgetImplementation *QDesktopWidgetImplementation::instance() -{ - return qdesktopWidgetImplementation(); -} - -QRect QDesktopWidgetImplementation::availableRect(int screenIndex) const -{ - if (screenIndex < 0 || screenIndex >= screenCount) - screenIndex = appScreen; - - return availableRects[screenIndex].toRect(); -} - -QRect QDesktopWidgetImplementation::screenRect(int screenIndex) const -{ - if (screenIndex < 0 || screenIndex >= screenCount) - screenIndex = appScreen; - - return screenRects[screenIndex].toRect(); -} - -void QDesktopWidgetImplementation::onResize() -{ - QMacCocoaAutoReleasePool pool; - NSArray *displays = [NSScreen screens]; - screenCount = [displays count]; - - screenRects.clear(); - availableRects.clear(); - NSRect primaryRect = [[displays objectAtIndex:0] frame]; - for (int i = 0; i<screenCount; i++) { - NSRect r = [[displays objectAtIndex:i] frame]; - int flippedY = - r.origin.y + // account for position offset and - primaryRect.size.height - r.size.height; // height difference. - screenRects.append(QRectF(r.origin.x, flippedY, - r.size.width, r.size.height)); - - r = [[displays objectAtIndex:i] visibleFrame]; - flippedY = - r.origin.y + // account for position offset and - primaryRect.size.height - r.size.height; // height difference. - availableRects.append(QRectF(r.origin.x, flippedY, - r.size.width, r.size.height)); - } -} - - - -QDesktopWidget::QDesktopWidget() - : QWidget(0, Qt::Desktop) -{ - setObjectName(QLatin1String("desktop")); - setAttribute(Qt::WA_WState_Visible); -} - -QDesktopWidget::~QDesktopWidget() -{ -} - -bool QDesktopWidget::isVirtualDesktop() const -{ - return true; -} - -int QDesktopWidget::primaryScreen() const -{ - return qdesktopWidgetImplementation()->appScreen; -} - -int QDesktopWidget::numScreens() const -{ - return qdesktopWidgetImplementation()->screenCount; -} - -QWidget *QDesktopWidget::screen(int) -{ - return this; -} - -const QRect QDesktopWidget::availableGeometry(int screen) const -{ - return qdesktopWidgetImplementation()->availableRect(screen); -} - -const QRect QDesktopWidget::screenGeometry(int screen) const -{ - return qdesktopWidgetImplementation()->screenRect(screen); -} - -int QDesktopWidget::screenNumber(const QWidget *widget) const -{ - QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); - if (!widget) - return d->appScreen; - QRect frame = widget->frameGeometry(); - if (!widget->isWindow()) - frame.moveTopLeft(widget->mapToGlobal(QPoint(0,0))); - int maxSize = -1, maxScreen = -1; - for (int i = 0; i < d->screenCount; ++i) { - QRect rr = d->screenRect(i); - QRect sect = rr.intersected(frame); - int size = sect.width() * sect.height(); - if (size > maxSize && sect.width() > 0 && sect.height() > 0) { - maxSize = size; - maxScreen = i; - } - } - return maxScreen; -} - -int QDesktopWidget::screenNumber(const QPoint &point) const -{ - QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); - int closestScreen = -1; - int shortestDistance = INT_MAX; - for (int i = 0; i < d->screenCount; ++i) { - QRect rr = d->screenRect(i); - int thisDistance = QWidgetPrivate::pointToRect(point, rr); - if (thisDistance < shortestDistance) { - shortestDistance = thisDistance; - closestScreen = i; - } - } - return closestScreen; -} - -void QDesktopWidget::resizeEvent(QResizeEvent *) -{ - QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); - - const int oldScreenCount = d->screenCount; - const QVector<QRectF> oldRects(d->screenRects); - const QVector<QRectF> oldWorks(d->availableRects); - - d->onResize(); - - for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) { - if (oldRects.at(i) != d->screenRects.at(i)) - emit resized(i); - } - for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) { - if (oldWorks.at(i) != d->availableRects.at(i)) - emit workAreaResized(i); - } - - if (oldScreenCount != d->screenCount) - emit screenCountChanged(d->screenCount); -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qdesktopwidget_mac_p.h b/src/gui/platforms/mac/qdesktopwidget_mac_p.h deleted file mode 100644 index ac638ea7d8..0000000000 --- a/src/gui/platforms/mac/qdesktopwidget_mac_p.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <qrect.h> - -QT_BEGIN_NAMESPACE - -class QDesktopWidgetImplementation -{ -public: - QDesktopWidgetImplementation(); - ~QDesktopWidgetImplementation(); - static QDesktopWidgetImplementation *instance(); - - int appScreen; - int screenCount; - - QVector<QRectF> availableRects; - QVector<QRectF> screenRects; - - QRect availableRect(int screenIndex) const; - QRect screenRect(int screenIndex) const; - void onResize(); -}; - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qdnd_mac.mm b/src/gui/platforms/mac/qdnd_mac.mm deleted file mode 100644 index 3af2ba007c..0000000000 --- a/src/gui/platforms/mac/qdnd_mac.mm +++ /dev/null @@ -1,753 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qapplication.h" -#ifndef QT_NO_DRAGANDDROP -#include "qbitmap.h" -#include "qcursor.h" -#include "qevent.h" -#include "qpainter.h" -#include "qurl.h" -#include "qwidget.h" -#include "qfile.h" -#include "qfileinfo.h" -#include <stdlib.h> -#include <string.h> -#ifndef QT_NO_ACCESSIBILITY -# include "qaccessible.h" -#endif - -#include <private/qapplication_p.h> -#include <private/qwidget_p.h> -#include <private/qdnd_p.h> -#include <private/qt_mac_p.h> - -QT_BEGIN_NAMESPACE - -QT_USE_NAMESPACE - -QMacDndAnswerRecord qt_mac_dnd_answer_rec; - -/***************************************************************************** - QDnD debug facilities - *****************************************************************************/ -//#define DEBUG_DRAG_EVENTS -//#define DEBUG_DRAG_PROMISES - -/***************************************************************************** - QDnD globals - *****************************************************************************/ -bool qt_mac_in_drag = false; -#ifndef QT_MAC_USE_COCOA -static DragReference qt_mac_current_dragRef = 0; -#endif - -/***************************************************************************** - Externals - *****************************************************************************/ -extern void qt_mac_send_modifiers_changed(quint32, QObject *); //qapplication_mac.cpp -extern uint qGlobalPostedEventsCount(); //qapplication.cpp -extern RgnHandle qt_mac_get_rgn(); // qregion_mac.cpp -extern void qt_mac_dispose_rgn(RgnHandle); // qregion_mac.cpp -/***************************************************************************** - QDnD utility functions - *****************************************************************************/ - -//default pixmap -static const int default_pm_hotx = -2; -static const int default_pm_hoty = -16; -#ifndef QT_MAC_USE_COCOA -static const char * const default_pm[] = { - "13 9 3 1", - ". c None", - " c #000000", - "X c #FFFFFF", - "X X X X X X X", - " X X X X X X ", - "X ......... X", - " X.........X ", - "X ......... X", - " X.........X ", - "X ......... X", - " X X X X X X ", - "X X X X X X X", -}; -#endif - -//action management -#ifdef DEBUG_DRAG_EVENTS -# define MAP_MAC_ENUM(x) x, #x -#else -# define MAP_MAC_ENUM(x) x -#endif -struct mac_enum_mapper -{ - int mac_code; - int qt_code; -#ifdef DEBUG_DRAG_EVENTS - char *qt_desc; -#endif -}; -#ifndef QT_MAC_USE_COCOA -static mac_enum_mapper dnd_action_symbols[] = { - { kDragActionAlias, MAP_MAC_ENUM(Qt::LinkAction) }, - { kDragActionMove, MAP_MAC_ENUM(Qt::MoveAction) }, - { kDragActionGeneric, MAP_MAC_ENUM(Qt::CopyAction) }, - { kDragActionCopy, MAP_MAC_ENUM(Qt::CopyAction) }, - { 0, MAP_MAC_ENUM(0) } -}; -static DragActions qt_mac_dnd_map_qt_actions(Qt::DropActions qActions) -{ - DragActions ret = kDragActionNothing; - for(int i = 0; dnd_action_symbols[i].qt_code; ++i) { - if(qActions & dnd_action_symbols[i].qt_code) - ret |= dnd_action_symbols[i].mac_code; - } - return ret; -} -static Qt::DropActions qt_mac_dnd_map_mac_actions(DragActions macActions) -{ -#ifdef DEBUG_DRAG_EVENTS - qDebug("Converting DND ActionList: 0x%lx", macActions); -#endif - Qt::DropActions ret = Qt::IgnoreAction; - for(int i = 0; dnd_action_symbols[i].qt_code; ++i) { -#ifdef DEBUG_DRAG_EVENTS - qDebug(" %d) [%s] : %s", i, dnd_action_symbols[i].qt_desc, - (macActions & dnd_action_symbols[i].mac_code) ? "true" : "false"); -#endif - if(macActions & dnd_action_symbols[i].mac_code) - ret |= Qt::DropAction(dnd_action_symbols[i].qt_code); - } - return ret; -} -static Qt::DropAction qt_mac_dnd_map_mac_default_action(DragActions macActions) -{ - static Qt::DropAction preferred_actions[] = { Qt::CopyAction, Qt::LinkAction, //in order - Qt::MoveAction, Qt::IgnoreAction }; - Qt::DropAction ret = Qt::IgnoreAction; - const Qt::DropActions qtActions = qt_mac_dnd_map_mac_actions(macActions); - for(int i = 0; preferred_actions[i] != Qt::IgnoreAction; ++i) { - if(qtActions & preferred_actions[i]) { - ret = preferred_actions[i]; - break; - } - } -#ifdef DEBUG_DRAG_EVENTS - for(int i = 0; dnd_action_symbols[i].qt_code; ++i) { - if(dnd_action_symbols[i].qt_code == ret) { - qDebug("Got default action: %s [0x%lx]", dnd_action_symbols[i].qt_desc, macActions); - break; - } - } -#endif - return ret; -} -static void qt_mac_dnd_update_action(DragReference dragRef) { - SInt16 modifiers; - GetDragModifiers(dragRef, &modifiers, 0, 0); - qt_mac_send_modifiers_changed(modifiers, qApp); - - Qt::DropAction qtAction = Qt::IgnoreAction; - { - DragActions macAllowed = kDragActionNothing; - GetDragDropAction(dragRef, &macAllowed); - Qt::DropActions qtAllowed = qt_mac_dnd_map_mac_actions(macAllowed); - qtAction = QDragManager::self()->defaultAction(qtAllowed, QApplication::keyboardModifiers()); -#if 1 - if(!(qtAllowed & qtAction)) - qtAction = qt_mac_dnd_map_mac_default_action(macAllowed); -#endif - } - DragActions macAction = qt_mac_dnd_map_qt_actions(qtAction); - - DragActions currentActions; - GetDragDropAction(dragRef, ¤tActions); - if(currentActions != macAction) { - SetDragDropAction(dragRef, macAction); - QDragManager::self()->emitActionChanged(qtAction); - } -} -#endif // !QT_MAC_USE_COCOA - -/***************************************************************************** - DnD functions - *****************************************************************************/ -bool QDropData::hasFormat_sys(const QString &mime) const -{ -#ifndef QT_MAC_USE_COCOA - OSPasteboardRef board; - if(GetDragPasteboard(qt_mac_current_dragRef, &board) != noErr) { - qDebug("DnD: Cannot get PasteBoard!"); - return false; - } - return QMacPasteboard(board, QMacPasteboardMime::MIME_DND).hasFormat(mime); -#else - Q_UNUSED(mime); - return false; -#endif // !QT_MAC_USE_COCOA -} - -QVariant QDropData::retrieveData_sys(const QString &mime, QVariant::Type type) const -{ -#ifndef QT_MAC_USE_COCOA - OSPasteboardRef board; - if(GetDragPasteboard(qt_mac_current_dragRef, &board) != noErr) { - qDebug("DnD: Cannot get PasteBoard!"); - return QVariant(); - } - return QMacPasteboard(board, QMacPasteboardMime::MIME_DND).retrieveData(mime, type); -#else - Q_UNUSED(mime); - Q_UNUSED(type); - return QVariant(); -#endif // !QT_MAC_USE_COCOA -} - -QStringList QDropData::formats_sys() const -{ -#ifndef QT_MAC_USE_COCOA - OSPasteboardRef board; - if(GetDragPasteboard(qt_mac_current_dragRef, &board) != noErr) { - qDebug("DnD: Cannot get PasteBoard!"); - return QStringList(); - } - return QMacPasteboard(board, QMacPasteboardMime::MIME_DND).formats(); -#else - return QStringList(); -#endif -} - -void QDragManager::timerEvent(QTimerEvent*) -{ -} - -bool QDragManager::eventFilter(QObject *, QEvent *) -{ - return false; -} - -void QDragManager::updateCursor() -{ -} - -void QDragManager::cancel(bool) -{ - if(object) { - beingCancelled = true; - object = 0; - } -#ifndef QT_NO_ACCESSIBILITY - QAccessible::updateAccessibility(this, 0, QAccessible::DragDropEnd); -#endif -} - -void QDragManager::move(const QPoint &) -{ -} - -void QDragManager::drop() -{ -} - -/** - If a drop action is already set on the carbon event - (from e.g. an earlier enter event), we insert the same - action on the new Qt event that has yet to be sendt. -*/ -static inline bool qt_mac_set_existing_drop_action(const DragRef &dragRef, QDropEvent &event) -{ -#ifndef QT_MAC_USE_COCOA - DragActions currentAction = kDragActionNothing; - OSStatus err = GetDragDropAction(dragRef, ¤tAction); - if (err == noErr && currentAction != kDragActionNothing) { - // This looks a bit evil, but we only ever set one action, so it's OK. - event.setDropAction(Qt::DropAction(int(qt_mac_dnd_map_mac_actions(currentAction)))); - return true; - } -#else - Q_UNUSED(dragRef); - Q_UNUSED(event); -#endif - return false; -} - -/** - If an answer rect has been set on the event (after being sent - to the global event processor), we store that rect so we can - check if the mouse is in the same area upon next drag move event. -*/ -void qt_mac_copy_answer_rect(const QDragMoveEvent &event) -{ - if (!event.answerRect().isEmpty()) { - qt_mac_dnd_answer_rec.rect = event.answerRect(); - qt_mac_dnd_answer_rec.buttons = event.mouseButtons(); - qt_mac_dnd_answer_rec.modifiers = event.keyboardModifiers(); - qt_mac_dnd_answer_rec.lastAction = event.dropAction(); - } -} - -bool qt_mac_mouse_inside_answer_rect(QPoint mouse) -{ - if (!qt_mac_dnd_answer_rec.rect.isEmpty() - && qt_mac_dnd_answer_rec.rect.contains(mouse) - && QApplication::mouseButtons() == qt_mac_dnd_answer_rec.buttons - && QApplication::keyboardModifiers() == qt_mac_dnd_answer_rec.modifiers) - return true; - else - return false; -} - -bool QWidgetPrivate::qt_mac_dnd_event(uint kind, DragRef dragRef) -{ -#ifndef QT_MAC_USE_COCOA - Q_Q(QWidget); - qt_mac_current_dragRef = dragRef; - if (kind != kEventControlDragLeave) - qt_mac_dnd_update_action(dragRef); - - Point mouse; - GetDragMouse(dragRef, &mouse, 0L); - if(!mouse.h && !mouse.v) - GetGlobalMouse(&mouse); - - if(QApplicationPrivate::modalState()) { - for(QWidget *modal = q; modal; modal = modal->parentWidget()) { - if(modal->isWindow()) { - if(modal != QApplication::activeModalWidget()) - return noErr; - break; - } - } - } - - //lookup the possible actions - DragActions allowed = kDragActionNothing; - GetDragAllowableActions(dragRef, &allowed); - Qt::DropActions qtAllowed = qt_mac_dnd_map_mac_actions(allowed); - - //lookup the source dragAccepted - QMimeData *dropdata = QDragManager::self()->dropData; - if(QDragManager::self()->source()) - dropdata = QDragManager::self()->dragPrivate()->data; - - // 'interrestedInDrag' should end up being 'true' if a later drop - // will be accepted by the widget for the current mouse position - bool interrestedInDrag = true; - - //Dispatch events - if (kind == kEventControlDragWithin) { - if (qt_mac_mouse_inside_answer_rect(q->mapFromGlobal(QPoint(mouse.h, mouse.v)))) - return qt_mac_dnd_answer_rec.lastAction == Qt::IgnoreAction; - else - qt_mac_dnd_answer_rec.clear(); - - QDragMoveEvent qDMEvent(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); - - // Accept the event by default if a - // drag action exists on the carbon event - if (qt_mac_set_existing_drop_action(dragRef, qDMEvent)) - qDMEvent.accept(); - - QApplication::sendEvent(q, &qDMEvent); - if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction) - interrestedInDrag = false; - - qt_mac_copy_answer_rect(qDMEvent); - SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDMEvent.dropAction())); - - } else if (kind == kEventControlDragEnter) { - qt_mac_dnd_answer_rec.clear(); - - QDragEnterEvent qDEEvent(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); - qt_mac_set_existing_drop_action(dragRef, qDEEvent); - QApplication::sendEvent(q, &qDEEvent); - SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDEEvent.dropAction())); - - if (!qDEEvent.isAccepted()) - // The widget is simply not interested in this - // drag. So tell carbon this by returning 'false'. We will then - // not receive any further move, drop or leave events for this widget. - return false; - else { - // Documentation states that a drag move event is sent immediately after - // a drag enter event. So we do that. This will honor widgets overriding - // 'dragMoveEvent' only, and not 'dragEnterEvent' - QDragMoveEvent qDMEvent(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); - qDMEvent.accept(); // accept by default, since enter event was accepted. - qDMEvent.setDropAction(qDEEvent.dropAction()); - QApplication::sendEvent(q, &qDMEvent); - if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction) - interrestedInDrag = false; - - qt_mac_copy_answer_rect(qDMEvent); - SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDMEvent.dropAction())); - } - - } else if(kind == kEventControlDragLeave) { - QDragLeaveEvent de; - QApplication::sendEvent(q, &de); - } else if(kind == kEventControlDragReceive) { - QDropEvent de(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); - if(QDragManager::self()->object) - QDragManager::self()->dragPrivate()->target = q; - QApplication::sendEvent(q, &de); - if(!de.isAccepted()) { - interrestedInDrag = false; - SetDragDropAction(dragRef, kDragActionNothing); - } else { - if(QDragManager::self()->object) - QDragManager::self()->dragPrivate()->executed_action = de.dropAction(); - SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(de.dropAction())); - } - } - -#ifdef DEBUG_DRAG_EVENTS - { - const char *desc = 0; - switch(kind) { - case kEventControlDragWithin: desc = "DragMove"; break; - case kEventControlDragEnter: desc = "DragEnter"; break; - case kEventControlDragLeave: desc = "DragLeave"; break; - case kEventControlDragReceive: desc = "DragDrop"; break; - } - if(desc) { - QPoint pos(q->mapFromGlobal(QPoint(mouse.h, mouse.v))); - qDebug("Sending <%s>(%d, %d) event to %p(%s::%s) [%d] (%p)", - desc, pos.x(), pos.y(), q, q->metaObject()->className(), - q->objectName().toLocal8Bit().constData(), ret, dragRef); - } - } -#endif - - //set the cursor - bool found_cursor = false; - if(kind == kEventControlDragWithin || kind == kEventControlDragEnter) { - ThemeCursor cursor = kThemeNotAllowedCursor; - found_cursor = true; - if (interrestedInDrag) { - DragActions action = kDragActionNothing; - GetDragDropAction(dragRef, &action); - switch(qt_mac_dnd_map_mac_default_action(action)) { - case Qt::IgnoreAction: - cursor = kThemeNotAllowedCursor; - break; - case Qt::MoveAction: - cursor = kThemeArrowCursor; - break; - case Qt::CopyAction: - cursor = kThemeCopyArrowCursor; - break; - case Qt::LinkAction: - cursor = kThemeAliasArrowCursor; - break; - default: - cursor = kThemeNotAllowedCursor; - break; - } - } - SetThemeCursor(cursor); - } - if(found_cursor) { - qt_mac_set_cursor(0); //just use our's - } else { - QCursor cursor(Qt::ArrowCursor); - if(qApp && qApp->overrideCursor()) { - cursor = *qApp->overrideCursor(); - } else if(q) { - for(QWidget *p = q; p; p = p->parentWidget()) { - if(p->isEnabled() && p->testAttribute(Qt::WA_SetCursor)) { - cursor = p->cursor(); - break; - } - } - } - qt_mac_set_cursor(&cursor); - } - - //idle things - if(qGlobalPostedEventsCount()) { - QApplication::sendPostedEvents(); - QApplication::flush(); - } - - // If this was not a drop, tell carbon that we will be interresed in receiving more - // events for the current drag. We do that by returning true. - if (kind == kEventControlDragReceive) - return interrestedInDrag; - else - return true; -#else - Q_UNUSED(kind); - Q_UNUSED(dragRef); - return false; -#endif // !QT_MAC_USE_COCOA -} - -#ifndef QT_MAC_USE_COCOA -Qt::DropAction QDragManager::drag(QDrag *o) -{ - - if(qt_mac_in_drag) { //just make sure.. - qWarning("Qt: Internal error: WH0A, unexpected condition reached"); - return Qt::IgnoreAction; - } - if(object == o) - return Qt::IgnoreAction; - /* At the moment it seems clear that Mac OS X does not want to drag with a non-left button - so we just bail early to prevent it */ - if(!(GetCurrentEventButtonState() & kEventMouseButtonPrimary)) - return Qt::IgnoreAction; - - if(object) { - dragPrivate()->source->removeEventFilter(this); - cancel(); - beingCancelled = false; - } - - object = o; - dragPrivate()->target = 0; - -#ifndef QT_NO_ACCESSIBILITY - QAccessible::updateAccessibility(this, 0, QAccessible::DragDropStart); -#endif - - //setup the data - QMacPasteboard dragBoard(QMacPasteboardMime::MIME_DND); - dragBoard.setMimeData(dragPrivate()->data); - - //create the drag - OSErr result; - DragRef dragRef; - if((result = NewDragWithPasteboard(dragBoard.pasteBoard(), &dragRef))) - return Qt::IgnoreAction; - //setup the actions - DragActions possibleActions = qt_mac_dnd_map_qt_actions(dragPrivate()->possible_actions); - SetDragAllowableActions(dragRef, //local - possibleActions, - true); - SetDragAllowableActions(dragRef, //remote (same as local) - possibleActions, - false); - - - QPoint hotspot; - QPixmap pix = dragPrivate()->pixmap; - if(pix.isNull()) { - if(dragPrivate()->data->hasText() || dragPrivate()->data->hasUrls()) { - //get the string - QString s = dragPrivate()->data->hasText() ? dragPrivate()->data->text() - : dragPrivate()->data->urls().first().toString(); - if(s.length() > 26) - s = s.left(23) + QChar(0x2026); - if(!s.isEmpty()) { - //draw it - QFont f(qApp->font()); - f.setPointSize(12); - QFontMetrics fm(f); - const int width = fm.width(s); - const int height = fm.height(); - if(width > 0 && height > 0) { - QPixmap tmp(width, height); - QPainter p(&tmp); - p.fillRect(0, 0, tmp.width(), tmp.height(), Qt::color0); - p.setPen(Qt::color1); - p.setFont(f); - p.drawText(0, fm.ascent(), s); - p.end(); - //save it - pix = tmp; - hotspot = QPoint(tmp.width() / 2, tmp.height() / 2); - } - } - } else { - pix = QPixmap(default_pm); - hotspot = QPoint(default_pm_hotx, default_pm_hoty); - } - } else { - hotspot = dragPrivate()->hotspot; - } - - //so we must fake an event - EventRecord fakeEvent; - GetGlobalMouse(&(fakeEvent.where)); - fakeEvent.message = 0; - fakeEvent.what = mouseDown; - fakeEvent.when = EventTimeToTicks(GetCurrentEventTime()); - fakeEvent.modifiers = GetCurrentKeyModifiers(); - if(GetCurrentEventButtonState() & 2) - fakeEvent.modifiers |= controlKey; - - //find the hotspot in relation to the pixmap - Point boundsPoint; - boundsPoint.h = fakeEvent.where.h - hotspot.x(); - boundsPoint.v = fakeEvent.where.v - hotspot.y(); - Rect boundsRect; - SetRect(&boundsRect, boundsPoint.h, boundsPoint.v, boundsPoint.h + pix.width(), boundsPoint.v + pix.height()); - - //set the drag image - QRegion dragRegion(boundsPoint.h, boundsPoint.v, pix.width(), pix.height()), pixRegion; - if(!pix.isNull()) { - HIPoint hipoint = { -hotspot.x(), -hotspot.y() }; - CGImageRef img = (CGImageRef)pix.macCGHandle(); - SetDragImageWithCGImage(dragRef, img, &hipoint, 0); - CGImageRelease(img); - } - - SetDragItemBounds(dragRef, (ItemReference)1 , &boundsRect); - { //do the drag - qt_mac_in_drag = true; - qt_mac_dnd_update_action(dragRef); - result = TrackDrag(dragRef, &fakeEvent, QMacSmartQuickDrawRegion(dragRegion.toQDRgn())); - qt_mac_in_drag = false; - } - object = 0; - if(result == noErr) { - // Check if the receiver points us to - // a file location. If so, we need to do - // the file copy/move ourselves: - QCFType<CFURLRef> pasteLocation = 0; - PasteboardCopyPasteLocation(dragBoard.pasteBoard(), &pasteLocation); - if (pasteLocation){ - Qt::DropAction action = o->d_func()->defaultDropAction; - if (action == Qt::IgnoreAction){ - if (o->d_func()->possible_actions & Qt::MoveAction) - action = Qt::MoveAction; - else if (o->d_func()->possible_actions & Qt::CopyAction) - action = Qt::CopyAction; - - } - bool atleastOne = false; - QList<QUrl> urls = o->mimeData()->urls(); - for (int i = 0; i < urls.size(); ++i){ - QUrl fromUrl = urls.at(i); - QString filename = QFileInfo(fromUrl.path()).fileName(); - QUrl toUrl(QCFString::toQString(CFURLGetString(pasteLocation)) + filename); - if (action == Qt::MoveAction){ - if (QFile::rename(fromUrl.path(), toUrl.path())) - atleastOne = true; - } else if (action == Qt::CopyAction){ - if (QFile::copy(fromUrl.path(), toUrl.path())) - atleastOne = true; - } - } - if (atleastOne){ - DisposeDrag(dragRef); - o->setMimeData(0); - o->deleteLater(); - return action; - } - } - - DragActions ret = kDragActionNothing; - GetDragDropAction(dragRef, &ret); - DisposeDrag(dragRef); //cleanup - o->setMimeData(0); - o->deleteLater(); - return qt_mac_dnd_map_mac_default_action(ret); - } - DisposeDrag(dragRef); //cleanup - return Qt::IgnoreAction; -} -#endif - -void QDragManager::updatePixmap() -{ -} - -QCocoaDropData::QCocoaDropData(CFStringRef pasteboard) - : QInternalMimeData() -{ - NSString* pasteboardName = (NSString*)pasteboard; - [pasteboardName retain]; - dropPasteboard = pasteboard; -} - -QCocoaDropData::~QCocoaDropData() -{ - NSString* pasteboardName = (NSString*)dropPasteboard; - [pasteboardName release]; -} - -QStringList QCocoaDropData::formats_sys() const -{ - QStringList formats; - OSPasteboardRef board; - if (PasteboardCreate(dropPasteboard, &board) != noErr) { - qDebug("DnD: Cannot get PasteBoard!"); - return formats; - } - formats = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).formats(); - return formats; -} - -QVariant QCocoaDropData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const -{ - QVariant data; - OSPasteboardRef board; - if (PasteboardCreate(dropPasteboard, &board) != noErr) { - qDebug("DnD: Cannot get PasteBoard!"); - return data; - } - data = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).retrieveData(mimeType, type); - CFRelease(board); - return data; -} - -bool QCocoaDropData::hasFormat_sys(const QString &mimeType) const -{ - bool has = false; - OSPasteboardRef board; - if (PasteboardCreate(dropPasteboard, &board) != noErr) { - qDebug("DnD: Cannot get PasteBoard!"); - return has; - } - has = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).hasFormat(mimeType); - CFRelease(board); - return has; -} - -#endif // QT_NO_DRAGANDDROP -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qeventdispatcher_mac.mm b/src/gui/platforms/mac/qeventdispatcher_mac.mm deleted file mode 100644 index 677a7368b4..0000000000 --- a/src/gui/platforms/mac/qeventdispatcher_mac.mm +++ /dev/null @@ -1,1200 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -#include "qplatformdefs.h" -#include "private/qt_mac_p.h" -#include "qeventdispatcher_mac_p.h" -#include "qapplication.h" -#include "qevent.h" -#include "qdialog.h" -#include "qhash.h" -#include "qsocketnotifier.h" -#include "private/qwidget_p.h" -#include "private/qthread_p.h" -#include "private/qapplication_p.h" - -#include <private/qcocoaapplication_mac_p.h> -#include "private/qt_cocoa_helpers_mac_p.h" - -#ifndef QT_NO_THREAD -# include "qmutex.h" -#endif - -QT_BEGIN_NAMESPACE - -QT_USE_NAMESPACE - -/***************************************************************************** - Externals - *****************************************************************************/ -extern void qt_event_request_timer(MacTimerInfo *); //qapplication_mac.cpp -extern MacTimerInfo *qt_event_get_timer(EventRef); //qapplication_mac.cpp -extern void qt_event_request_select(QEventDispatcherMac *); //qapplication_mac.cpp -extern void qt_event_request_updates(); //qapplication_mac.cpp -extern OSWindowRef qt_mac_window_for(const QWidget *); //qwidget_mac.cpp -extern bool qt_is_gui_used; //qapplication.cpp -extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp -extern bool qt_mac_is_macsheet(const QWidget *); //qwidget_mac.cpp - -static inline CFRunLoopRef mainRunLoop() -{ -#ifndef QT_MAC_USE_COCOA - return reinterpret_cast<CFRunLoopRef>(const_cast<void *>(GetCFRunLoopFromEventLoop(GetMainEventLoop()))); -#else - return CFRunLoopGetMain(); -#endif -} - -/***************************************************************************** - Timers stuff - *****************************************************************************/ - -/* timer call back */ -void QEventDispatcherMacPrivate::activateTimer(CFRunLoopTimerRef, void *info) -{ - int timerID = -#ifdef Q_OS_MAC64 - qint64(info); -#else - int(info); -#endif - - MacTimerInfo *tmr; - tmr = macTimerHash.value(timerID); - if (tmr == 0 || tmr->pending == true) - return; // Can't send another timer event if it's pending. - - - if (blockSendPostedEvents) { - QCoreApplication::postEvent(tmr->obj, new QTimerEvent(tmr->id)); - } else { - tmr->pending = true; - QTimerEvent e(tmr->id); - qt_sendSpontaneousEvent(tmr->obj, &e); - // Get the value again in case the timer gets unregistered during the sendEvent. - tmr = macTimerHash.value(timerID); - if (tmr != 0) - tmr->pending = false; - } - -} - -void QEventDispatcherMac::registerTimer(int timerId, int interval, QObject *obj) -{ -#ifndef QT_NO_DEBUG - if (timerId < 1 || interval < 0 || !obj) { - qWarning("QEventDispatcherMac::registerTimer: invalid arguments"); - return; - } else if (obj->thread() != thread() || thread() != QThread::currentThread()) { - qWarning("QObject::startTimer: timers cannot be started from another thread"); - return; - } -#endif - - MacTimerInfo *t = new MacTimerInfo(); - t->id = timerId; - t->interval = interval; - t->obj = obj; - t->runLoopTimer = 0; - t->pending = false; - - CFAbsoluteTime fireDate = CFAbsoluteTimeGetCurrent(); - CFTimeInterval cfinterval = qMax(CFTimeInterval(interval) / 1000, 0.0000001); - fireDate += cfinterval; - QEventDispatcherMacPrivate::macTimerHash.insert(timerId, t); - CFRunLoopTimerContext info = { 0, (void *)timerId, 0, 0, 0 }; - t->runLoopTimer = CFRunLoopTimerCreate(0, fireDate, cfinterval, 0, 0, - QEventDispatcherMacPrivate::activateTimer, &info); - if (t->runLoopTimer == 0) { - qFatal("QEventDispatcherMac::registerTimer: Cannot create timer"); - } - CFRunLoopAddTimer(mainRunLoop(), t->runLoopTimer, kCFRunLoopCommonModes); -} - -bool QEventDispatcherMac::unregisterTimer(int identifier) -{ -#ifndef QT_NO_DEBUG - if (identifier < 1) { - qWarning("QEventDispatcherMac::unregisterTimer: invalid argument"); - return false; - } else if (thread() != QThread::currentThread()) { - qWarning("QObject::killTimer: timers cannot be stopped from another thread"); - return false; - } -#endif - if (identifier <= 0) - return false; // not init'd or invalid timer - - MacTimerInfo *timerInfo = QEventDispatcherMacPrivate::macTimerHash.take(identifier); - if (timerInfo == 0) - return false; - - if (!QObjectPrivate::get(timerInfo->obj)->inThreadChangeEvent) - QAbstractEventDispatcherPrivate::releaseTimerId(identifier); - CFRunLoopTimerInvalidate(timerInfo->runLoopTimer); - CFRelease(timerInfo->runLoopTimer); - delete timerInfo; - - return true; -} - -bool QEventDispatcherMac::unregisterTimers(QObject *obj) -{ -#ifndef QT_NO_DEBUG - if (!obj) { - qWarning("QEventDispatcherMac::unregisterTimers: invalid argument"); - return false; - } else if (obj->thread() != thread() || thread() != QThread::currentThread()) { - qWarning("QObject::killTimers: timers cannot be stopped from another thread"); - return false; - } -#endif - - MacTimerHash::iterator it = QEventDispatcherMacPrivate::macTimerHash.begin(); - while (it != QEventDispatcherMacPrivate::macTimerHash.end()) { - MacTimerInfo *timerInfo = it.value(); - if (timerInfo->obj != obj) { - ++it; - } else { - if (!QObjectPrivate::get(timerInfo->obj)->inThreadChangeEvent) - QAbstractEventDispatcherPrivate::releaseTimerId(timerInfo->id); - CFRunLoopTimerInvalidate(timerInfo->runLoopTimer); - CFRelease(timerInfo->runLoopTimer); - delete timerInfo; - it = QEventDispatcherMacPrivate::macTimerHash.erase(it); - } - } - return true; -} - -QList<QEventDispatcherMac::TimerInfo> -QEventDispatcherMac::registeredTimers(QObject *object) const -{ - if (!object) { - qWarning("QEventDispatcherMac:registeredTimers: invalid argument"); - return QList<TimerInfo>(); - } - - QList<TimerInfo> list; - - MacTimerHash::const_iterator it = QEventDispatcherMacPrivate::macTimerHash.constBegin(); - while (it != QEventDispatcherMacPrivate::macTimerHash.constEnd()) { - MacTimerInfo *t = it.value(); - if (t->obj == object) - list << TimerInfo(t->id, t->interval); - ++it; - } - return list; -} - -/************************************************************************** - Socket Notifiers - *************************************************************************/ -void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef, - const void *, void *info) { - QEventDispatcherMacPrivate *const eventDispatcher - = static_cast<QEventDispatcherMacPrivate *>(info); - int nativeSocket = CFSocketGetNative(s); - MacSocketInfo *socketInfo = eventDispatcher->macSockets.value(nativeSocket); - QEvent notifierEvent(QEvent::SockAct); - - // There is a race condition that happen where we disable the notifier and - // the kernel still has a notification to pass on. We then get this - // notification after we've successfully disabled the CFSocket, but our Qt - // notifier is now gone. The upshot is we have to check the notifier - // everytime. - if (callbackType == kCFSocketReadCallBack) { - if (socketInfo->readNotifier) - QApplication::sendEvent(socketInfo->readNotifier, ¬ifierEvent); - } else if (callbackType == kCFSocketWriteCallBack) { - if (socketInfo->writeNotifier) - QApplication::sendEvent(socketInfo->writeNotifier, ¬ifierEvent); - } -} - -/* - Adds a loop source for the given socket to the current run loop. -*/ -CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket) -{ - CFRunLoopSourceRef loopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0); - if (!loopSource) - return 0; - - CFRunLoopAddSource(mainRunLoop(), loopSource, kCFRunLoopCommonModes); - return loopSource; -} - -/* - Removes the loop source for the given socket from the current run loop. -*/ -void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop) -{ - Q_ASSERT(runloop); - CFRunLoopRemoveSource(mainRunLoop(), runloop, kCFRunLoopCommonModes); - CFSocketDisableCallBacks(socket, kCFSocketReadCallBack); - CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack); - CFRunLoopSourceInvalidate(runloop); -} - -/* - Register a QSocketNotifier with the mac event system by creating a CFSocket with - with a read/write callback. - - Qt has separate socket notifiers for reading and writing, but on the mac there is - a limitation of one CFSocket object for each native socket. -*/ -void QEventDispatcherMac::registerSocketNotifier(QSocketNotifier *notifier) -{ - Q_ASSERT(notifier); - int nativeSocket = notifier->socket(); - int type = notifier->type(); -#ifndef QT_NO_DEBUG - if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) { - qWarning("QSocketNotifier: Internal error"); - return; - } else if (notifier->thread() != thread() - || thread() != QThread::currentThread()) { - qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread"); - return; - } -#endif - - Q_D(QEventDispatcherMac); - - if (type == QSocketNotifier::Exception) { - qWarning("QSocketNotifier::Exception is not supported on Mac OS X"); - return; - } - - // Check if we have a CFSocket for the native socket, create one if not. - MacSocketInfo *socketInfo = d->macSockets.value(nativeSocket); - if (!socketInfo) { - socketInfo = new MacSocketInfo(); - - // Create CFSocket, specify that we want both read and write callbacks (the callbacks - // are enabled/disabled later on). - const int callbackTypes = kCFSocketReadCallBack | kCFSocketWriteCallBack; - CFSocketContext context = {0, d, 0, 0, 0}; - socketInfo->socket = CFSocketCreateWithNative(kCFAllocatorDefault, nativeSocket, callbackTypes, qt_mac_socket_callback, &context); - if (CFSocketIsValid(socketInfo->socket) == false) { - qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to create CFSocket"); - return; - } - - CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket); - flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write - flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation - CFSocketSetSocketFlags(socketInfo->socket, flags); - - // Add CFSocket to runloop. - if(!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) { - qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop"); - CFSocketInvalidate(socketInfo->socket); - CFRelease(socketInfo->socket); - return; - } - - // Disable both callback types by default. This must be done after - // we add the CFSocket to the runloop, or else these calls will have - // no effect. - CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); - CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); - - d->macSockets.insert(nativeSocket, socketInfo); - } - - // Increment read/write counters and select enable callbacks if necessary. - if (type == QSocketNotifier::Read) { - Q_ASSERT(socketInfo->readNotifier == 0); - socketInfo->readNotifier = notifier; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); - } else if (type == QSocketNotifier::Write) { - Q_ASSERT(socketInfo->writeNotifier == 0); - socketInfo->writeNotifier = notifier; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); - } -} - -/* - Unregister QSocketNotifer. The CFSocket correspoding to this notifier is - removed from the runloop of this is the last notifier that users - that CFSocket. -*/ -void QEventDispatcherMac::unregisterSocketNotifier(QSocketNotifier *notifier) -{ - Q_ASSERT(notifier); - int nativeSocket = notifier->socket(); - int type = notifier->type(); -#ifndef QT_NO_DEBUG - if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) { - qWarning("QSocketNotifier: Internal error"); - return; - } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) { - qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread"); - return; - } -#endif - - Q_D(QEventDispatcherMac); - - if (type == QSocketNotifier::Exception) { - qWarning("QSocketNotifier::Exception is not supported on Mac OS X"); - return; - } - MacSocketInfo *socketInfo = d->macSockets.value(nativeSocket); - if (!socketInfo) { - qWarning("QEventDispatcherMac::unregisterSocketNotifier: Tried to unregister a not registered notifier"); - return; - } - - // Decrement read/write counters and disable callbacks if necessary. - if (type == QSocketNotifier::Read) { - Q_ASSERT(notifier == socketInfo->readNotifier); - socketInfo->readNotifier = 0; - CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); - } else if (type == QSocketNotifier::Write) { - Q_ASSERT(notifier == socketInfo->writeNotifier); - socketInfo->writeNotifier = 0; - CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); - } - - // Remove CFSocket from runloop if this was the last QSocketNotifier. - if (socketInfo->readNotifier == 0 && socketInfo->writeNotifier == 0) { - if (CFSocketIsValid(socketInfo->socket)) - qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop); - CFRunLoopSourceInvalidate(socketInfo->runloop); - CFRelease(socketInfo->runloop); - CFSocketInvalidate(socketInfo->socket); - CFRelease(socketInfo->socket); - delete socketInfo; - d->macSockets.remove(nativeSocket); - } -} - -bool QEventDispatcherMac::hasPendingEvents() -{ - extern uint qGlobalPostedEventsCount(); - return qGlobalPostedEventsCount() || (qt_is_gui_used && GetNumEventsInQueue(GetMainEventQueue())); -} - - -static bool qt_mac_send_event(QEventLoop::ProcessEventsFlags, OSEventRef event, OSWindowRef pt) -{ -#ifndef QT_MAC_USE_COCOA - if(pt && SendEventToWindow(event, pt) != eventNotHandledErr) - return true; - return !SendEventToEventTarget(event, GetEventDispatcherTarget()); -#else // QT_MAC_USE_COCOA - if (pt) - [pt sendEvent:event]; - else - [NSApp sendEvent:event]; - return true; -#endif -} - -#ifdef QT_MAC_USE_COCOA -static bool IsMouseOrKeyEvent( NSEvent* event ) -{ - bool result = false; - - switch( [event type] ) - { - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSRightMouseDown: - case NSRightMouseUp: - case NSMouseMoved: // ?? - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSMouseEntered: - case NSMouseExited: - case NSKeyDown: - case NSKeyUp: - case NSFlagsChanged: // key modifiers changed? - case NSCursorUpdate: // ?? - case NSScrollWheel: - case NSTabletPoint: - case NSTabletProximity: - case NSOtherMouseDown: - case NSOtherMouseUp: - case NSOtherMouseDragged: -#ifndef QT_NO_GESTURES -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - case NSEventTypeGesture: // touch events - case NSEventTypeMagnify: - case NSEventTypeSwipe: - case NSEventTypeRotate: - case NSEventTypeBeginGesture: - case NSEventTypeEndGesture: -#endif -#endif // QT_NO_GESTURES - result = true; - break; - - default: - break; - } - return result; -} -#endif - -static inline void qt_mac_waitForMoreEvents() -{ -#ifndef QT_MAC_USE_COCOA - while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e20, true) == kCFRunLoopRunTimedOut) ; -#else - // If no event exist in the cocoa event que, wait - // (and free up cpu time) until at least one event occur. - // This implementation is a bit on the edge, but seems to - // work fine: - NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantFuture] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - if (event) - [NSApp postEvent:event atStart:YES]; -#endif -} - -#ifdef QT_MAC_USE_COCOA -static inline void qt_mac_waitForMoreModalSessionEvents() -{ - // If no event exist in the cocoa event que, wait - // (and free up cpu time) until at least one event occur. - // This implementation is a bit on the edge, but seems to - // work fine: - NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantFuture] - inMode:NSModalPanelRunLoopMode - dequeue:YES]; - if (event) - [NSApp postEvent:event atStart:YES]; -} -#endif - -bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags) -{ - Q_D(QEventDispatcherMac); - d->interrupt = false; - -#ifdef QT_MAC_USE_COCOA - bool interruptLater = false; - QtMacInterruptDispatcherHelp::cancelInterruptLater(); -#endif - - // In case we end up recursing while we now process events, make sure - // that we send remaining posted Qt events before this call returns: - wakeUp(); - emit awake(); - - bool excludeUserEvents = flags & QEventLoop::ExcludeUserInputEvents; - bool retVal = false; - forever { - if (d->interrupt) - break; - -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - NSEvent* event = 0; - - // First, send all previously excluded input events, if any: - if (!excludeUserEvents) { - while (!d->queuedUserInputEvents.isEmpty()) { - event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst()); - if (!filterEvent(event)) { - qt_mac_send_event(flags, event, 0); - retVal = true; - } - [event release]; - } - } - - // If Qt is used as a plugin, or as an extension in a native cocoa - // application, we should not run or stop NSApplication; This will be - // done from the application itself. And if processEvents is called - // manually (rather than from a QEventLoop), we cannot enter a tight - // loop and block this call, but instead we need to return after one flush. - // Finally, if we are to exclude user input events, we cannot call [NSApp run] - // as we then loose control over which events gets dispatched: - const bool canExec_3rdParty = d->nsAppRunCalledByQt || ![NSApp isRunning]; - const bool canExec_Qt = !excludeUserEvents && - (flags & QEventLoop::DialogExec || flags & QEventLoop::EventLoopExec) ; - - if (canExec_Qt && canExec_3rdParty) { - // We can use exec-mode, meaning that we can stay in a tight loop until - // interrupted. This is mostly an optimization, but it allow us to use - // [NSApp run], which is the normal code path for cocoa applications. - if (NSModalSession session = d->currentModalSession()) { - QBoolBlocker execGuard(d->currentExecIsNSAppRun, false); - while ([NSApp runModalSession:session] == NSRunContinuesResponse && !d->interrupt) - qt_mac_waitForMoreModalSessionEvents(); - - if (!d->interrupt && session == d->currentModalSessionCached) { - // Someone called [NSApp stopModal:] from outside the event - // dispatcher (e.g to stop a native dialog). But that call wrongly stopped - // 'session' as well. As a result, we need to restart all internal sessions: - d->temporarilyStopAllModalSessions(); - } - } else { - d->nsAppRunCalledByQt = true; - QBoolBlocker execGuard(d->currentExecIsNSAppRun, true); - [NSApp run]; - } - retVal = true; - } else { - // We cannot block the thread (and run in a tight loop). - // Instead we will process all current pending events and return. - d->ensureNSAppInitialized(); - if (NSModalSession session = d->currentModalSession()) { - // INVARIANT: a modal window is executing. - if (!excludeUserEvents) { - // Since we can dispatch all kinds of events, we choose - // to use cocoa's native way of running modal sessions: - if (flags & QEventLoop::WaitForMoreEvents) - qt_mac_waitForMoreModalSessionEvents(); - NSInteger status = [NSApp runModalSession:session]; - if (status != NSRunContinuesResponse && session == d->currentModalSessionCached) { - // INVARIANT: Someone called [NSApp stopModal:] from outside the event - // dispatcher (e.g to stop a native dialog). But that call wrongly stopped - // 'session' as well. As a result, we need to restart all internal sessions: - d->temporarilyStopAllModalSessions(); - } - retVal = true; - } else do { - // Dispatch all non-user events (but que non-user events up for later). In - // this case, we need more control over which events gets dispatched, and - // cannot use [NSApp runModalSession:session]: - event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:nil - inMode:NSModalPanelRunLoopMode - dequeue: YES]; - - if (event) { - if (IsMouseOrKeyEvent(event)) { - [event retain]; - d->queuedUserInputEvents.append(event); - continue; - } - if (!filterEvent(event) && qt_mac_send_event(flags, event, 0)) - retVal = true; - } - } while (!d->interrupt && event != nil); - } else do { - // INVARIANT: No modal window is executing. - event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:nil - inMode:NSDefaultRunLoopMode - dequeue: YES]; - - if (event) { - if (flags & QEventLoop::ExcludeUserInputEvents) { - if (IsMouseOrKeyEvent(event)) { - [event retain]; - d->queuedUserInputEvents.append(event); - continue; - } - } - if (!filterEvent(event) && qt_mac_send_event(flags, event, 0)) - retVal = true; - } - } while (!d->interrupt && event != nil); - - // Be sure to flush the Qt posted events when not using exec mode - // (exec mode will always do this call from the event loop source): - if (!d->interrupt) - QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData); - - // Since the window that holds modality might have changed while processing - // events, we we need to interrupt when we return back the previous process - // event recursion to ensure that we spin the correct modal session. - // We do the interruptLater at the end of the function to ensure that we don't - // disturb the 'wait for more events' below (as deleteLater will post an event): - interruptLater = true; - } -#else - do { - EventRef event; - if (!(flags & QEventLoop::ExcludeUserInputEvents) - && !d->queuedUserInputEvents.isEmpty()) { - // process a pending user input event - event = static_cast<EventRef>(d->queuedUserInputEvents.takeFirst()); - } else { - OSStatus err = ReceiveNextEvent(0,0, kEventDurationNoWait, true, &event); - if(err != noErr) - continue; - // else - if (flags & QEventLoop::ExcludeUserInputEvents) { - UInt32 ekind = GetEventKind(event), - eclass = GetEventClass(event); - switch(eclass) { - case kEventClassQt: - if(ekind != kEventQtRequestContext) - break; - // fall through - case kEventClassMouse: - case kEventClassKeyboard: - d->queuedUserInputEvents.append(event); - continue; - } - } - } - - if (!filterEvent(&event) && qt_mac_send_event(flags, event, 0)) - retVal = true; - ReleaseEvent(event); - } while(!d->interrupt && GetNumEventsInQueue(GetMainEventQueue()) > 0); - -#endif - - bool canWait = (d->threadData->canWait - && !retVal - && !d->interrupt - && (flags & QEventLoop::WaitForMoreEvents)); - if (canWait) { - // INVARIANT: We haven't processed any events yet. And we're told - // to stay inside this function until at least one event is processed. - qt_mac_waitForMoreEvents(); - flags &= ~QEventLoop::WaitForMoreEvents; - } else { - // Done with event processing for now. - // Leave the function: - break; - } - } - - // If we're interrupted, we need to interrupt the _current_ - // recursion as well to check if it is still supposed to be - // executing. This way we wind down the stack until we land - // on a recursion that again calls processEvents (typically - // from QEventLoop), and set interrupt to false: - if (d->interrupt) - interrupt(); - -#ifdef QT_MAC_USE_COCOA - if (interruptLater) - QtMacInterruptDispatcherHelp::interruptLater(); -#endif - - return retVal; -} - -void QEventDispatcherMac::wakeUp() -{ - Q_D(QEventDispatcherMac); - d->serialNumber.ref(); - CFRunLoopSourceSignal(d->postedEventsSource); - CFRunLoopWakeUp(mainRunLoop()); -} - -void QEventDispatcherMac::flush() -{ - if(qApp) { - QWidgetList tlws = QApplication::topLevelWidgets(); - for(int i = 0; i < tlws.size(); i++) { - QWidget *tlw = tlws.at(i); - if(tlw->isVisible()) - macWindowFlush(qt_mac_window_for(tlw)); - } - } -} - -/***************************************************************************** - QEventDispatcherMac Implementation - *****************************************************************************/ -MacTimerHash QEventDispatcherMacPrivate::macTimerHash; -bool QEventDispatcherMacPrivate::blockSendPostedEvents = false; -bool QEventDispatcherMacPrivate::interrupt = false; - -#ifdef QT_MAC_USE_COCOA -QStack<QCocoaModalSessionInfo> QEventDispatcherMacPrivate::cocoaModalSessionStack; -bool QEventDispatcherMacPrivate::currentExecIsNSAppRun = false; -bool QEventDispatcherMacPrivate::nsAppRunCalledByQt = false; -bool QEventDispatcherMacPrivate::cleanupModalSessionsNeeded = false; -NSModalSession QEventDispatcherMacPrivate::currentModalSessionCached = 0; - -void QEventDispatcherMacPrivate::ensureNSAppInitialized() -{ - // Some elements in Cocoa require NSApplication to be running before - // they get fully initialized, in particular the menu bar. This - // function is intended for cases where a dialog is told to execute before - // QApplication::exec is called, or the application spins the events loop - // manually rather than calling QApplication:exec. - // The function makes sure that NSApplication starts running, but stops - // it again as soon as the send posted events callback is called. That way - // we let Cocoa finish the initialization it seems to need. We'll only - // apply this trick at most once for any application, and we avoid doing it - // for the common case where main just starts QApplication::exec. - if (nsAppRunCalledByQt || [NSApp isRunning]) - return; - nsAppRunCalledByQt = true; - QBoolBlocker block1(interrupt, true); - QBoolBlocker block2(currentExecIsNSAppRun, true); - [NSApp run]; -} - -void QEventDispatcherMacPrivate::temporarilyStopAllModalSessions() -{ - // Flush, and Stop, all created modal session, and as - // such, make them pending again. The next call to - // currentModalSession will recreate them again. The - // reason to stop all session like this is that otherwise - // a call [NSApp stop] would not stop NSApp, but rather - // the current modal session. So if we need to stop NSApp - // we need to stop all the modal session first. To avoid changing - // the stacking order of the windows while doing so, we put - // up a block that is used in QCocoaWindow and QCocoaPanel: - int stackSize = cocoaModalSessionStack.size(); - for (int i=0; i<stackSize; ++i) { - QCocoaModalSessionInfo &info = cocoaModalSessionStack[i]; - if (info.session) { - [NSApp endModalSession:info.session]; - info.session = 0; - } - } - currentModalSessionCached = 0; -} - -NSModalSession QEventDispatcherMacPrivate::currentModalSession() -{ - // If we have one or more modal windows, this function will create - // a session for each of those, and return the one for the top. - if (currentModalSessionCached) - return currentModalSessionCached; - - if (cocoaModalSessionStack.isEmpty()) - return 0; - - int sessionCount = cocoaModalSessionStack.size(); - for (int i=0; i<sessionCount; ++i) { - QCocoaModalSessionInfo &info = cocoaModalSessionStack[i]; - if (!info.widget) - continue; - if (info.widget->testAttribute(Qt::WA_DontShowOnScreen)) - continue; - if (!info.session) { - QMacCocoaAutoReleasePool pool; - NSWindow *window = qt_mac_window_for(info.widget); - if (!window) - continue; - - ensureNSAppInitialized(); - QBoolBlocker block1(blockSendPostedEvents, true); - info.nswindow = window; - [(NSWindow*) info.nswindow retain]; - int levelBeforeEnterModal = [window level]; - info.session = [NSApp beginModalSessionForWindow:window]; - // Make sure we don't stack the window lower that it was before - // entering modal, in case it e.g. had the stays-on-top flag set: - if (levelBeforeEnterModal > [window level]) - [window setLevel:levelBeforeEnterModal]; - } - currentModalSessionCached = info.session; - cleanupModalSessionsNeeded = false; - } - return currentModalSessionCached; -} - -static void setChildrenWorksWhenModal(QWidget *widget, bool worksWhenModal) -{ - // For NSPanels (but not NSWindows, sadly), we can set the flag - // worksWhenModal, so that they are active even when they are not modal. - QList<QDialog *> dialogs = widget->findChildren<QDialog *>(); - for (int i=0; i<dialogs.size(); ++i){ - NSWindow *window = qt_mac_window_for(dialogs[i]); - if (window && [window isKindOfClass:[NSPanel class]]) { - [static_cast<NSPanel *>(window) setWorksWhenModal:worksWhenModal]; - if (worksWhenModal && [window isVisible]){ - [window orderFront:window]; - } - } - } -} - -void QEventDispatcherMacPrivate::updateChildrenWorksWhenModal() -{ - // Make the dialog children of the widget - // active. And make the dialog children of - // the previous modal dialog unactive again: - QMacCocoaAutoReleasePool pool; - int size = cocoaModalSessionStack.size(); - if (size > 0){ - if (QWidget *prevModal = cocoaModalSessionStack[size-1].widget) - setChildrenWorksWhenModal(prevModal, true); - if (size > 1){ - if (QWidget *prevModal = cocoaModalSessionStack[size-2].widget) - setChildrenWorksWhenModal(prevModal, false); - } - } -} - -void QEventDispatcherMacPrivate::cleanupModalSessions() -{ - // Go through the list of modal sessions, and end those - // that no longer has a widget assosiated; no widget means - // the the session has logically ended. The reason we wait like - // this to actually end the sessions for real (rather than at the - // point they were marked as stopped), is that ending a session - // when no other session runs below it on the stack will make cocoa - // drop some events on the floor. - QMacCocoaAutoReleasePool pool; - int stackSize = cocoaModalSessionStack.size(); - - for (int i=stackSize-1; i>=0; --i) { - QCocoaModalSessionInfo &info = cocoaModalSessionStack[i]; - if (info.widget) { - // This session has a widget, and is therefore not marked - // as stopped. So just make it current. There might still be other - // stopped sessions on the stack, but those will be stopped on - // a later "cleanup" call. - currentModalSessionCached = info.session; - break; - } - cocoaModalSessionStack.remove(i); - currentModalSessionCached = 0; - if (info.session) { - [NSApp endModalSession:info.session]; - [(NSWindow *)info.nswindow release]; - } - } - - updateChildrenWorksWhenModal(); - cleanupModalSessionsNeeded = false; -} - -void QEventDispatcherMacPrivate::beginModalSession(QWidget *widget) -{ - // Add a new, empty (null), NSModalSession to the stack. - // It will become active the next time QEventDispatcher::processEvents is called. - // A QCocoaModalSessionInfo is considered pending to become active if the widget pointer - // is non-zero, and the session pointer is zero (it will become active upon a call to - // currentModalSession). A QCocoaModalSessionInfo is considered pending to be stopped if - // the widget pointer is zero, and the session pointer is non-zero (it will be fully - // stopped in cleanupModalSessions()). - QCocoaModalSessionInfo info = {widget, 0, 0}; - cocoaModalSessionStack.push(info); - updateChildrenWorksWhenModal(); - currentModalSessionCached = 0; -} - -void QEventDispatcherMacPrivate::endModalSession(QWidget *widget) -{ - // Mark all sessions attached to widget as pending to be stopped. We do this - // by setting the widget pointer to zero, but leave the session pointer. - // We don't tell cocoa to stop any sessions just yet, because cocoa only understands - // when we stop the _current_ modal session (which is the session on top of - // the stack, and might not belong to 'widget'). - int stackSize = cocoaModalSessionStack.size(); - for (int i=stackSize-1; i>=0; --i) { - QCocoaModalSessionInfo &info = cocoaModalSessionStack[i]; - if (info.widget == widget) { - info.widget = 0; - if (i == stackSize-1) { - // The top sessions ended. Interrupt the event dispatcher - // to start spinning the correct session immidiatly: - currentModalSessionCached = 0; - cleanupModalSessionsNeeded = true; - QEventDispatcherMac::instance()->interrupt(); - } - } - } -} - -#endif - -QEventDispatcherMacPrivate::QEventDispatcherMacPrivate() -{ -} - -QEventDispatcherMac::QEventDispatcherMac(QObject *parent) - : QAbstractEventDispatcher(*new QEventDispatcherMacPrivate, parent) -{ - Q_D(QEventDispatcherMac); - CFRunLoopSourceContext context; - bzero(&context, sizeof(CFRunLoopSourceContext)); - context.info = d; - context.equal = QEventDispatcherMacPrivate::postedEventSourceEqualCallback; - context.perform = QEventDispatcherMacPrivate::postedEventsSourcePerformCallback; - d->postedEventsSource = CFRunLoopSourceCreate(0, 0, &context); - Q_ASSERT(d->postedEventsSource); - CFRunLoopAddSource(mainRunLoop(), d->postedEventsSource, kCFRunLoopCommonModes); - - CFRunLoopObserverContext observerContext; - bzero(&observerContext, sizeof(CFRunLoopObserverContext)); - observerContext.info = this; - d->waitingObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, - kCFRunLoopBeforeWaiting | kCFRunLoopAfterWaiting, - true, 0, - QEventDispatcherMacPrivate::waitingObserverCallback, - &observerContext); - CFRunLoopAddObserver(mainRunLoop(), d->waitingObserver, kCFRunLoopCommonModes); - - /* The first cycle in the loop adds the source and the events of the source - are not processed. - We use an observer to process the posted events for the first - execution of the loop. */ - CFRunLoopObserverContext firstTimeObserverContext; - bzero(&firstTimeObserverContext, sizeof(CFRunLoopObserverContext)); - firstTimeObserverContext.info = d; - d->firstTimeObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, - kCFRunLoopEntry, - /* repeats = */ false, - 0, - QEventDispatcherMacPrivate::firstLoopEntry, - &firstTimeObserverContext); - CFRunLoopAddObserver(mainRunLoop(), d->firstTimeObserver, kCFRunLoopCommonModes); -} - -void QEventDispatcherMacPrivate::waitingObserverCallback(CFRunLoopObserverRef, - CFRunLoopActivity activity, void *info) -{ - if (activity == kCFRunLoopBeforeWaiting) - emit static_cast<QEventDispatcherMac*>(info)->aboutToBlock(); - else - emit static_cast<QEventDispatcherMac*>(info)->awake(); -} - -Boolean QEventDispatcherMacPrivate::postedEventSourceEqualCallback(const void *info1, const void *info2) -{ - return info1 == info2; -} - -inline static void processPostedEvents(QEventDispatcherMacPrivate *const d, const bool blockSendPostedEvents) -{ - if (blockSendPostedEvents) { - // We're told to not send posted events (because the event dispatcher - // is currently working on setting up the correct session to run). But - // we still need to make sure that we don't fall asleep until pending events - // are sendt, so we just signal this need, and return: - CFRunLoopSourceSignal(d->postedEventsSource); - return; - } - -#ifdef QT_MAC_USE_COCOA - if (d->cleanupModalSessionsNeeded) - d->cleanupModalSessions(); -#endif - - if (d->interrupt) { -#ifdef QT_MAC_USE_COCOA - if (d->currentExecIsNSAppRun) { - // The event dispatcher has been interrupted. But since - // [NSApplication run] is running the event loop, we - // delayed stopping it until now (to let cocoa process - // pending cocoa events first). - if (d->currentModalSessionCached) - d->temporarilyStopAllModalSessions(); - [NSApp stop:NSApp]; - d->cancelWaitForMoreEvents(); - } -#endif - return; - } - - if (!d->threadData->canWait || (d->serialNumber != d->lastSerial)) { - d->lastSerial = d->serialNumber; - QApplicationPrivate::sendPostedEvents(0, 0, d->threadData); - } -} - -void QEventDispatcherMacPrivate::firstLoopEntry(CFRunLoopObserverRef ref, - CFRunLoopActivity activity, - void *info) -{ - Q_UNUSED(ref); - Q_UNUSED(activity); -#ifdef QT_MAC_USE_COCOA - QApplicationPrivate::qt_initAfterNSAppStarted(); -#endif - processPostedEvents(static_cast<QEventDispatcherMacPrivate *>(info), blockSendPostedEvents); -} - -void QEventDispatcherMacPrivate::postedEventsSourcePerformCallback(void *info) -{ - processPostedEvents(static_cast<QEventDispatcherMacPrivate *>(info), blockSendPostedEvents); -} - -#ifdef QT_MAC_USE_COCOA -void QEventDispatcherMacPrivate::cancelWaitForMoreEvents() -{ - // In case the event dispatcher is waiting for more - // events somewhere, we post a dummy event to wake it up: - QMacCocoaAutoReleasePool pool; - [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint - modifierFlags:0 timestamp:0. windowNumber:0 context:0 - subtype:QtCocoaEventSubTypeWakeup data1:0 data2:0] atStart:NO]; -} -#endif - -void QEventDispatcherMac::interrupt() -{ - Q_D(QEventDispatcherMac); - d->interrupt = true; - wakeUp(); - -#ifndef QT_MAC_USE_COCOA - CFRunLoopStop(mainRunLoop()); -#else - // We do nothing more here than setting d->interrupt = true, and - // poke the event loop if it is sleeping. Actually stopping - // NSApp, or the current modal session, is done inside the send - // posted events callback. We do this to ensure that all current pending - // cocoa events gets delivered before we stop. Otherwise, if we now stop - // the last event loop recursion, cocoa will just drop pending posted - // events on the floor before we get a chance to reestablish a new session. - d->cancelWaitForMoreEvents(); -#endif -} - -QEventDispatcherMac::~QEventDispatcherMac() -{ - Q_D(QEventDispatcherMac); - //timer cleanup - MacTimerHash::iterator it = QEventDispatcherMacPrivate::macTimerHash.begin(); - while (it != QEventDispatcherMacPrivate::macTimerHash.end()) { - MacTimerInfo *t = it.value(); - if (t->runLoopTimer) { - CFRunLoopTimerInvalidate(t->runLoopTimer); - CFRelease(t->runLoopTimer); - } - delete t; - ++it; - } - QEventDispatcherMacPrivate::macTimerHash.clear(); - - // Remove CFSockets from the runloop. - for (MacSocketHash::ConstIterator it = d->macSockets.constBegin(); it != d->macSockets.constEnd(); ++it) { - MacSocketInfo *socketInfo = (*it); - if (CFSocketIsValid(socketInfo->socket)) { - qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop); - CFRunLoopSourceInvalidate(socketInfo->runloop); - CFRelease(socketInfo->runloop); - CFSocketInvalidate(socketInfo->socket); - CFRelease(socketInfo->socket); - } - } - CFRunLoopRemoveSource(mainRunLoop(), d->postedEventsSource, kCFRunLoopCommonModes); - CFRelease(d->postedEventsSource); - - CFRunLoopObserverInvalidate(d->waitingObserver); - CFRelease(d->waitingObserver); - - CFRunLoopObserverInvalidate(d->firstTimeObserver); - CFRelease(d->firstTimeObserver); -} - -#ifdef QT_MAC_USE_COCOA - -QtMacInterruptDispatcherHelp* QtMacInterruptDispatcherHelp::instance = 0; - -QtMacInterruptDispatcherHelp::QtMacInterruptDispatcherHelp() : cancelled(false) -{ - // The whole point of this class is that we enable a way to interrupt - // the event dispatcher when returning back to a lower recursion level - // than where interruptLater was called. This is needed to detect if - // [NSApp run] should still be running at the recursion level it is at. - // Since the interrupt is canceled if processEvents is called before - // this object gets deleted, we also avoid interrupting unnecessary. - deleteLater(); -} - -QtMacInterruptDispatcherHelp::~QtMacInterruptDispatcherHelp() -{ - if (cancelled) - return; - instance = 0; - QEventDispatcherMac::instance()->interrupt(); -} - -void QtMacInterruptDispatcherHelp::cancelInterruptLater() -{ - if (!instance) - return; - instance->cancelled = true; - delete instance; - instance = 0; -} - -void QtMacInterruptDispatcherHelp::interruptLater() -{ - cancelInterruptLater(); - instance = new QtMacInterruptDispatcherHelp; -} - -#endif - -QT_END_NAMESPACE - diff --git a/src/gui/platforms/mac/qeventdispatcher_mac_p.h b/src/gui/platforms/mac/qeventdispatcher_mac_p.h deleted file mode 100644 index 12fcafbb01..0000000000 --- a/src/gui/platforms/mac/qeventdispatcher_mac_p.h +++ /dev/null @@ -1,224 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -#ifndef QEVENTDISPATCHER_MAC_P_H -#define QEVENTDISPATCHER_MAC_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtGui/qwindowdefs.h> -#include <QtCore/qhash.h> -#include <QtCore/qstack.h> -#include "private/qabstracteventdispatcher_p.h" -#include "private/qt_mac_p.h" - -QT_BEGIN_NAMESPACE - -#ifdef QT_MAC_USE_COCOA -typedef struct _NSModalSession *NSModalSession; -typedef struct _QCocoaModalSessionInfo { - QPointer<QWidget> widget; - NSModalSession session; - void *nswindow; -} QCocoaModalSessionInfo; -#endif - -class QEventDispatcherMacPrivate; - -class QEventDispatcherMac : public QAbstractEventDispatcher -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QEventDispatcherMac) - -public: - explicit QEventDispatcherMac(QObject *parent = 0); - ~QEventDispatcherMac(); - - bool processEvents(QEventLoop::ProcessEventsFlags flags); - bool hasPendingEvents(); - - void registerSocketNotifier(QSocketNotifier *notifier); - void unregisterSocketNotifier(QSocketNotifier *notifier); - - void registerTimer(int timerId, int interval, QObject *object); - bool unregisterTimer(int timerId); - bool unregisterTimers(QObject *object); - QList<TimerInfo> registeredTimers(QObject *object) const; - - void wakeUp(); - void flush(); - void interrupt(); - -private: - friend void qt_mac_select_timer_callbk(__EventLoopTimer*, void*); - friend class QApplicationPrivate; -}; - -struct MacTimerInfo { - int id; - int interval; - QObject *obj; - bool pending; - CFRunLoopTimerRef runLoopTimer; - bool operator==(const MacTimerInfo &other) - { - return (id == other.id); - } -}; -typedef QHash<int, MacTimerInfo *> MacTimerHash; - -struct MacSocketInfo { - MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0) {} - CFSocketRef socket; - CFRunLoopSourceRef runloop; - QObject *readNotifier; - QObject *writeNotifier; -}; -typedef QHash<int, MacSocketInfo *> MacSocketHash; - -class QEventDispatcherMacPrivate : public QAbstractEventDispatcherPrivate -{ - Q_DECLARE_PUBLIC(QEventDispatcherMac) - -public: - QEventDispatcherMacPrivate(); - - static MacTimerHash macTimerHash; - // Set 'blockSendPostedEvents' to true if you _really_ need - // to make sure that qt events are not posted while calling - // low-level cocoa functions (like beginModalForWindow). And - // use a QBoolBlocker to be safe: - static bool blockSendPostedEvents; -#ifdef QT_MAC_USE_COCOA - // The following variables help organizing modal sessions: - static QStack<QCocoaModalSessionInfo> cocoaModalSessionStack; - static bool currentExecIsNSAppRun; - static bool nsAppRunCalledByQt; - static bool cleanupModalSessionsNeeded; - static NSModalSession currentModalSessionCached; - static NSModalSession currentModalSession(); - static void updateChildrenWorksWhenModal(); - static void temporarilyStopAllModalSessions(); - static void beginModalSession(QWidget *widget); - static void endModalSession(QWidget *widget); - static void cancelWaitForMoreEvents(); - static void cleanupModalSessions(); - static void ensureNSAppInitialized(); -#endif - - MacSocketHash macSockets; - QList<void *> queuedUserInputEvents; // List of EventRef in Carbon, and NSEvent * in Cocoa - CFRunLoopSourceRef postedEventsSource; - CFRunLoopObserverRef waitingObserver; - CFRunLoopObserverRef firstTimeObserver; - QAtomicInt serialNumber; - int lastSerial; - static bool interrupt; -private: - static Boolean postedEventSourceEqualCallback(const void *info1, const void *info2); - static void postedEventsSourcePerformCallback(void *info); - static void activateTimer(CFRunLoopTimerRef, void *info); - static void waitingObserverCallback(CFRunLoopObserverRef observer, - CFRunLoopActivity activity, void *info); - static void firstLoopEntry(CFRunLoopObserverRef ref, CFRunLoopActivity activity, void *info); -}; - -#ifdef QT_MAC_USE_COCOA -class QtMacInterruptDispatcherHelp : public QObject -{ - static QtMacInterruptDispatcherHelp *instance; - bool cancelled; - - QtMacInterruptDispatcherHelp(); - ~QtMacInterruptDispatcherHelp(); - - public: - static void interruptLater(); - static void cancelInterruptLater(); -}; -#endif - -QT_END_NAMESPACE - -#endif // QEVENTDISPATCHER_MAC_P_H diff --git a/src/gui/platforms/mac/qfont_mac.cpp b/src/gui/platforms/mac/qfont_mac.cpp deleted file mode 100644 index daf68c03ea..0000000000 --- a/src/gui/platforms/mac/qfont_mac.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfont.h" -#include "qfont_p.h" -#include "qfontengine_p.h" -#include "qfontengine_mac_p.h" -#include "qfontinfo.h" -#include "qfontmetrics.h" -#include "qpaintdevice.h" -#include "qstring.h" -#include <private/qt_mac_p.h> -#include <private/qtextengine_p.h> -#include <private/qunicodetables_p.h> -#include <qapplication.h> -#include "qfontdatabase.h" -#include <qpainter.h> -#include "qtextengine_p.h" -#include <stdlib.h> - -QT_BEGIN_NAMESPACE - -extern float qt_mac_defaultDpi_x(); //qpaintdevice_mac.cpp - -int qt_mac_pixelsize(const QFontDef &def, int dpi) -{ - float ret; - if(def.pixelSize == -1) - ret = def.pointSize * dpi / qt_mac_defaultDpi_x(); - else - ret = def.pixelSize; - return qRound(ret); -} -int qt_mac_pointsize(const QFontDef &def, int dpi) -{ - float ret; - if(def.pointSize < 0) - ret = def.pixelSize * qt_mac_defaultDpi_x() / float(dpi); - else - ret = def.pointSize; - return qRound(ret); -} - -QString QFont::rawName() const -{ - return family(); -} - -void QFont::setRawName(const QString &name) -{ - setFamily(name); -} - -void QFont::cleanup() -{ - QFontCache::cleanup(); -} - -/*! - Returns an ATSUFontID -*/ -quint32 QFont::macFontID() const // ### need 64-bit version -{ -#ifdef QT_MAC_USE_COCOA - return 0; -#elif 1 - QFontEngine *fe = d->engineForScript(QUnicodeTables::Common); - if (fe && fe->type() == QFontEngine::Multi) - return static_cast<QFontEngineMacMulti*>(fe)->macFontID(); -#else - Str255 name; - if(FMGetFontFamilyName((FMFontFamily)((UInt32)handle()), name) == noErr) { - short fnum; - GetFNum(name, &fnum); - return fnum; - } -#endif - return 0; -} - -// Returns an ATSUFonFamilyRef -Qt::HANDLE QFont::handle() const -{ -#if 0 - QFontEngine *fe = d->engineForScript(QUnicodeTables::Common); - if (fe && fe->type() == QFontEngine::Mac) - return (Qt::HANDLE)static_cast<QFontEngineMacMulti*>(fe)->fontFamilyRef(); -#endif - return 0; -} - -void QFont::initialize() -{ } - -QString QFont::defaultFamily() const -{ - switch(d->request.styleHint) { - case QFont::Times: - return QString::fromLatin1("Times New Roman"); - case QFont::Courier: - return QString::fromLatin1("Courier New"); - case QFont::Monospace: - return QString::fromLatin1("Courier"); - case QFont::Decorative: - return QString::fromLatin1("Bookman Old Style"); - case QFont::Cursive: - return QString::fromLatin1("Apple Chancery"); - case QFont::Fantasy: - return QString::fromLatin1("Papyrus"); - case QFont::Helvetica: - case QFont::System: - default: - return QString::fromLatin1("Helvetica"); - } -} - -QString QFont::lastResortFamily() const -{ - return QString::fromLatin1("Helvetica"); -} - -QString QFont::lastResortFont() const -{ - return QString::fromLatin1("Geneva"); -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qfontdatabase_mac.cpp b/src/gui/platforms/mac/qfontdatabase_mac.cpp deleted file mode 100644 index 5ba236b5f7..0000000000 --- a/src/gui/platforms/mac/qfontdatabase_mac.cpp +++ /dev/null @@ -1,466 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qt_mac_p.h> -#include "qfontengine_p.h" -#include <qfile.h> -#include <qabstractfileengine.h> -#include <stdlib.h> -#include <qendian.h> -#include <private/qfontengine_coretext_p.h> -#include <private/qfontengine_mac_p.h> - -QT_BEGIN_NAMESPACE - -int qt_mac_pixelsize(const QFontDef &def, int dpi); //qfont_mac.cpp -int qt_mac_pointsize(const QFontDef &def, int dpi); //qfont_mac.cpp - -#ifndef QT_MAC_USE_COCOA -static void initWritingSystems(QtFontFamily *family, ATSFontRef atsFont) -{ - ByteCount length = 0; - if (ATSFontGetTable(atsFont, MAKE_TAG('O', 'S', '/', '2'), 0, 0, 0, &length) != noErr) - return; - QVarLengthArray<uchar> os2Table(length); - if (length < 86 - || ATSFontGetTable(atsFont, MAKE_TAG('O', 'S', '/', '2'), 0, length, os2Table.data(), &length) != noErr) - return; - - // See also qfontdatabase_win.cpp, offsets taken from OS/2 table in the TrueType spec - quint32 unicodeRange[4] = { - qFromBigEndian<quint32>(os2Table.data() + 42), - qFromBigEndian<quint32>(os2Table.data() + 46), - qFromBigEndian<quint32>(os2Table.data() + 50), - qFromBigEndian<quint32>(os2Table.data() + 54) - }; - quint32 codePageRange[2] = { qFromBigEndian<quint32>(os2Table.data() + 78), qFromBigEndian<quint32>(os2Table.data() + 82) }; - QList<QFontDatabase::WritingSystem> systems = qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange); -#if 0 - QCFString name; - ATSFontGetName(atsFont, kATSOptionFlagsDefault, &name); - qDebug() << systems.count() << "writing systems for" << QString(name); -qDebug() << "first char" << hex << unicodeRange[0]; - for (int i = 0; i < systems.count(); ++i) - qDebug() << QFontDatabase::writingSystemName(systems.at(i)); -#endif - for (int i = 0; i < systems.count(); ++i) - family->writingSystems[systems.at(i)] = QtFontFamily::Supported; -} -#endif - -static void initializeDb() -{ - QFontDatabasePrivate *db = privateDb(); - if(!db || db->count) - return; - -#if defined(QT_MAC_USE_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 -if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - QCFType<CTFontCollectionRef> collection = CTFontCollectionCreateFromAvailableFonts(0); - if(!collection) - return; - QCFType<CFArrayRef> fonts = CTFontCollectionCreateMatchingFontDescriptors(collection); - if(!fonts) - return; - QString foundry_name = "CoreText"; - const int numFonts = CFArrayGetCount(fonts); - for(int i = 0; i < numFonts; ++i) { - CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i); - - QCFString family_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute); - QtFontFamily *family = db->family(family_name, true); - for(int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) - family->writingSystems[ws] = QtFontFamily::Supported; - QtFontFoundry *foundry = family->foundry(foundry_name, true); - - QtFontStyle::Key styleKey; - if(QCFType<CFDictionaryRef> styles = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)) { - if(CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontWeightTrait)) { - Q_ASSERT(CFNumberIsFloatType(weight)); - double d; - if(CFNumberGetValue(weight, kCFNumberDoubleType, &d)) { - //qDebug() << "BOLD" << (QString)family_name << d; - styleKey.weight = (d > 0.0) ? QFont::Bold : QFont::Normal; - } - } - if(CFNumberRef italic = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontSlantTrait)) { - Q_ASSERT(CFNumberIsFloatType(italic)); - double d; - if(CFNumberGetValue(italic, kCFNumberDoubleType, &d)) { - //qDebug() << "ITALIC" << (QString)family_name << d; - if (d > 0.0) - styleKey.style = QFont::StyleItalic; - } - } - } - - QtFontStyle *style = foundry->style(styleKey, true); - style->smoothScalable = true; - if(QCFType<CFNumberRef> size = (CFNumberRef)CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) { - //qDebug() << "WHEE"; - int pixel_size=0; - if(CFNumberIsFloatType(size)) { - double d; - CFNumberGetValue(size, kCFNumberDoubleType, &d); - pixel_size = d; - } else { - CFNumberGetValue(size, kCFNumberIntType, &pixel_size); - } - //qDebug() << "SIZE" << (QString)family_name << pixel_size; - if(pixel_size) - style->pixelSize(pixel_size, true); - } else { - //qDebug() << "WTF?"; - } - } -} else -#endif - { -#ifndef QT_MAC_USE_COCOA - FMFontIterator it; - if (!FMCreateFontIterator(0, 0, kFMUseGlobalScopeOption, &it)) { - while (true) { - FMFont fmFont; - if (FMGetNextFont(&it, &fmFont) != noErr) - break; - - FMFontFamily fmFamily; - FMFontStyle fmStyle; - QString familyName; - - QtFontStyle::Key styleKey; - - ATSFontRef atsFont = FMGetATSFontRefFromFont(fmFont); - - if (!FMGetFontFamilyInstanceFromFont(fmFont, &fmFamily, &fmStyle)) { - { //sanity check the font, and see if we can use it at all! --Sam - ATSUFontID fontID; - if(ATSUFONDtoFontID(fmFamily, 0, &fontID) != noErr) - continue; - } - - if (fmStyle & ::italic) - styleKey.style = QFont::StyleItalic; - if (fmStyle & ::bold) - styleKey.weight = QFont::Bold; - - ATSFontFamilyRef familyRef = FMGetATSFontFamilyRefFromFontFamily(fmFamily); - QCFString cfFamilyName;; - ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &cfFamilyName); - familyName = cfFamilyName; - } else { - QCFString cfFontName; - ATSFontGetName(atsFont, kATSOptionFlagsDefault, &cfFontName); - familyName = cfFontName; - quint16 macStyle = 0; - { - uchar data[4]; - ByteCount len = 4; - if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'e', 'a', 'd'), 44, 4, &data, &len) == noErr) - macStyle = qFromBigEndian<quint16>(data); - } - if (macStyle & 1) - styleKey.weight = QFont::Bold; - if (macStyle & 2) - styleKey.style = QFont::StyleItalic; - } - - QtFontFamily *family = db->family(familyName, true); - QtFontFoundry *foundry = family->foundry(QString(), true); - QtFontStyle *style = foundry->style(styleKey, true); - style->pixelSize(0, true); - style->smoothScalable = true; - - initWritingSystems(family, atsFont); - } - FMDisposeFontIterator(&it); - } -#endif - } - -} - -static inline void load(const QString & = QString(), int = -1) -{ - initializeDb(); -} - -static const char *styleHint(const QFontDef &request) -{ - const char *stylehint = 0; - switch (request.styleHint) { - case QFont::SansSerif: - stylehint = "Arial"; - break; - case QFont::Serif: - stylehint = "Times New Roman"; - break; - case QFont::TypeWriter: - stylehint = "Courier New"; - break; - default: - if (request.fixedPitch) - stylehint = "Courier New"; - break; - } - return stylehint; -} - -static inline float weightToFloat(unsigned int weight) -{ - return (weight - 50) / 100.0; -} - -void QFontDatabase::load(const QFontPrivate *d, int script) -{ - // sanity checks - if(!qApp) - qWarning("QFont: Must construct a QApplication before a QFont"); - - Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount); - Q_UNUSED(script); - - QFontDef req = d->request; - req.pixelSize = qt_mac_pixelsize(req, d->dpi); - - // set the point size to 0 to get better caching - req.pointSize = 0; - QFontCache::Key key = QFontCache::Key(req, QUnicodeTables::Common, d->screen); - - if(!(d->engineData = QFontCache::instance()->findEngineData(key))) { - d->engineData = new QFontEngineData; - QFontCache::instance()->insertEngineData(key, d->engineData); - } else { - d->engineData->ref.ref(); - } - if(d->engineData->engine) // already loaded - return; - - // set it to the actual pointsize, so QFontInfo will do the right thing - req.pointSize = qRound(qt_mac_pointsize(d->request, d->dpi)); - - QFontEngine *e = QFontCache::instance()->findEngine(key); - if(!e && qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) { - e = new QTestFontEngine(req.pixelSize); - e->fontDef = req; - } - - if(e) { - e->ref.ref(); - d->engineData->engine = e; - return; // the font info and fontdef should already be filled - } - - //find the font - QStringList family_list = familyList(req); - - const char *stylehint = styleHint(req); - if (stylehint) - family_list << QLatin1String(stylehint); - - // add QFont::defaultFamily() to the list, for compatibility with - // previous versions - family_list << QApplication::font().defaultFamily(); - -#if defined(QT_MAC_USE_COCOA) - QCFString fontName = NULL, familyName = NULL; -#else - ATSFontFamilyRef familyRef = 0; - ATSFontRef fontRef = 0; -#endif - - QMutexLocker locker(fontDatabaseMutex()); - QFontDatabasePrivate *db = privateDb(); - if (!db->count) - initializeDb(); - for(int i = 0; i < family_list.size(); ++i) { - for (int k = 0; k < db->count; ++k) { - if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) { - QByteArray family_name = db->families[k]->name.toUtf8(); -#if defined(QT_MAC_USE_COCOA) - QCFType<CTFontRef> ctFont = CTFontCreateWithName(QCFString(db->families[k]->name), 12, NULL); - if (ctFont) { - fontName = CTFontCopyFullName(ctFont); - familyName = CTFontCopyFamilyName(ctFont); - goto FamilyFound; - } -#else - familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); - if (familyRef) { - fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); - goto FamilyFound; - } -#endif - } - } - } -FamilyFound: - //fill in the engine's font definition - QFontDef fontDef = d->request; //copy.. - if(fontDef.pointSize < 0) - fontDef.pointSize = qt_mac_pointsize(fontDef, d->dpi); - else - fontDef.pixelSize = qt_mac_pixelsize(fontDef, d->dpi); - -#ifdef QT_MAC_USE_COCOA - fontDef.family = familyName; - QFontEngine *engine = new QCoreTextFontEngineMulti(fontName, fontDef, d->kerning); -#else - QCFString actualName; - if (ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr) - fontDef.family = actualName; - QFontEngine *engine = new QFontEngineMacMulti(familyRef, fontRef, fontDef, d->kerning); -#endif - d->engineData->engine = engine; - engine->ref.ref(); //a ref for the engineData->engine - QFontCache::instance()->insertEngine(key, engine); -} - -static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) -{ - ATSFontContainerRef handle; - OSStatus e = noErr; - - if(fnt->data.isEmpty()) { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - extern OSErr qt_mac_create_fsref(const QString &, FSRef *); // qglobal.cpp - FSRef ref; - if(qt_mac_create_fsref(fnt->fileName, &ref) != noErr) - return; - - ATSFontActivateFromFileReference(&ref, kATSFontContextLocal, kATSFontFormatUnspecified, 0, kATSOptionFlagsDefault, &handle); - } else -#endif - { -#ifndef Q_WS_MAC64 - extern Q_CORE_EXPORT OSErr qt_mac_create_fsspec(const QString &, FSSpec *); // global.cpp - FSSpec spec; - if(qt_mac_create_fsspec(fnt->fileName, &spec) != noErr) - return; - - e = ATSFontActivateFromFileSpecification(&spec, kATSFontContextLocal, kATSFontFormatUnspecified, - 0, kATSOptionFlagsDefault, &handle); -#endif - } - } else { - e = ATSFontActivateFromMemory((void *)fnt->data.constData(), fnt->data.size(), kATSFontContextLocal, - kATSFontFormatUnspecified, 0, kATSOptionFlagsDefault, &handle); - - fnt->data = QByteArray(); - } - - if(e != noErr) - return; - - ItemCount fontCount = 0; - e = ATSFontFindFromContainer(handle, kATSOptionFlagsDefault, 0, 0, &fontCount); - if(e != noErr) - return; - - QVarLengthArray<ATSFontRef> containedFonts(fontCount); - e = ATSFontFindFromContainer(handle, kATSOptionFlagsDefault, fontCount, containedFonts.data(), &fontCount); - if(e != noErr) - return; - - fnt->families.clear(); -#if defined(QT_MAC_USE_COCOA) - // Make sure that the family name set on the font matches what - // kCTFontFamilyNameAttribute returns in initializeDb(). - // So far the best solution seems find the installed font - // using CoreText and get the family name from it. - // (ATSFontFamilyGetName appears to be the correct API, but also - // returns the font display name.) - for(int i = 0; i < containedFonts.size(); ++i) { - QCFString fontPostScriptName; - ATSFontGetPostScriptName(containedFonts[i], kATSOptionFlagsDefault, &fontPostScriptName); - QCFType<CTFontDescriptorRef> font = CTFontDescriptorCreateWithNameAndSize(fontPostScriptName, 14); - QCFString familyName = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute); - fnt->families.append(familyName); - } -#else - for(int i = 0; i < containedFonts.size(); ++i) { - QCFString family; - ATSFontGetName(containedFonts[i], kATSOptionFlagsDefault, &family); - fnt->families.append(family); - } -#endif - - fnt->handle = handle; -} - -bool QFontDatabase::removeApplicationFont(int handle) -{ - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - if(handle < 0 || handle >= db->applicationFonts.count()) - return false; - - OSStatus e = ATSFontDeactivate(db->applicationFonts.at(handle).handle, - /*iRefCon=*/0, kATSOptionFlagsDefault); - if(e != noErr) - return false; - - db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont(); - - db->invalidate(); - return true; -} - -bool QFontDatabase::removeAllApplicationFonts() -{ - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - for(int i = 0; i < db->applicationFonts.count(); ++i) { - if(!removeApplicationFont(i)) - return false; - } - return true; -} - -bool QFontDatabase::supportsThreadedFontRendering() -{ - return true; -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qfontengine_coretext.mm b/src/gui/platforms/mac/qfontengine_coretext.mm deleted file mode 100644 index d4df2183ed..0000000000 --- a/src/gui/platforms/mac/qfontengine_coretext.mm +++ /dev/null @@ -1,880 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfontengine_coretext_p.h" - -#include <QtCore/qendian.h> -#include <QtCore/qsettings.h> - -#include <private/qimage_p.h> - -#if !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - -QT_BEGIN_NAMESPACE - -static float SYNTHETIC_ITALIC_SKEW = tanf(14 * acosf(0) / 90); - -static void loadAdvancesForGlyphs(CTFontRef ctfont, - QVarLengthArray<CGGlyph> &cgGlyphs, - QGlyphLayout *glyphs, int len, - QTextEngine::ShaperFlags flags, - const QFontDef &fontDef) -{ - Q_UNUSED(flags); - QVarLengthArray<CGSize> advances(len); - CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), len); - - for (int i = 0; i < len; ++i) { - if (glyphs->glyphs[i] & 0xff000000) - continue; - glyphs->advances_x[i] = QFixed::fromReal(advances[i].width); - glyphs->advances_y[i] = QFixed::fromReal(advances[i].height); - } - - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - for (int i = 0; i < len; ++i) { - glyphs->advances_x[i] = glyphs->advances_x[i].round(); - glyphs->advances_y[i] = glyphs->advances_y[i].round(); - } - } -} - -QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning) - : QFontEngineMulti(0) -{ - this->fontDef = fontDef; - CTFontSymbolicTraits symbolicTraits = 0; - if (fontDef.weight >= QFont::Bold) - symbolicTraits |= kCTFontBoldTrait; - switch (fontDef.style) { - case QFont::StyleNormal: - break; - case QFont::StyleItalic: - case QFont::StyleOblique: - symbolicTraits |= kCTFontItalicTrait; - break; - } - - transform = CGAffineTransformIdentity; - if (fontDef.stretch != 100) { - transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); - } - - QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithNameAndSize(name, fontDef.pixelSize); - QCFType<CTFontRef> baseFont = CTFontCreateWithFontDescriptor(descriptor, fontDef.pixelSize, &transform); - ctfont = CTFontCreateCopyWithSymbolicTraits(baseFont, fontDef.pixelSize, &transform, symbolicTraits, symbolicTraits); - - // CTFontCreateCopyWithSymbolicTraits returns NULL if we ask for a trait that does - // not exist for the given font. (for example italic) - if (ctfont == 0) { - ctfont = baseFont; - CFRetain(ctfont); - } - init(kerning); -} - -QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(CGFontRef cgFontRef, const QFontDef &fontDef, bool kerning) - : QFontEngineMulti(0) -{ - this->fontDef = fontDef; - - transform = CGAffineTransformIdentity; - if (fontDef.stretch != 100) { - transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); - } - - ctfont = CTFontCreateWithGraphicsFont(cgFontRef, fontDef.pixelSize, &transform, NULL); - init(kerning); -} - -QCoreTextFontEngineMulti::~QCoreTextFontEngineMulti() -{ - CFRelease(ctfont); -} - -void QCoreTextFontEngineMulti::init(bool kerning) -{ - Q_ASSERT(ctfont != NULL); - attributeDict = CFDictionaryCreateMutable(0, 2, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - CFDictionaryAddValue(attributeDict, NSFontAttributeName, ctfont); - if (!kerning) { - float zero = 0.0; - QCFType<CFNumberRef> noKern = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &zero); - CFDictionaryAddValue(attributeDict, kCTKernAttributeName, noKern); - } - - QCoreTextFontEngine *fe = new QCoreTextFontEngine(ctfont, fontDef); - fe->ref.ref(); - engines.append(fe); -} - -uint QCoreTextFontEngineMulti::fontIndexForFont(CTFontRef font) const -{ - for (int i = 0; i < engines.count(); ++i) { - if (CFEqual(engineAt(i)->ctfont, font)) - return i; - } - - QCoreTextFontEngineMulti *that = const_cast<QCoreTextFontEngineMulti *>(this); - QCoreTextFontEngine *fe = new QCoreTextFontEngine(font, fontDef); - fe->ref.ref(); - that->engines.append(fe); - return engines.count() - 1; -} - -bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, - int *nglyphs, QTextEngine::ShaperFlags flags, - unsigned short *logClusters, const HB_CharAttributes *, - QScriptItem *si) const -{ - QCFType<CFStringRef> cfstring = CFStringCreateWithCharactersNoCopy(0, - reinterpret_cast<const UniChar *>(str), - len, kCFAllocatorNull); - QCFType<CFAttributedStringRef> attributedString = CFAttributedStringCreate(0, cfstring, attributeDict); - QCFType<CTTypesetterRef> typeSetter; - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - if (flags & QTextEngine::RightToLeft) { - const void *optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel }; - const short rtlForcedEmbeddingLevelValue = 1; - const void *rtlOptionValues[] = { CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &rtlForcedEmbeddingLevelValue) }; - QCFType<CFDictionaryRef> options = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, 1, - &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - typeSetter = CTTypesetterCreateWithAttributedStringAndOptions(attributedString, options); - } else -#else - Q_UNUSED(flags); -#endif - typeSetter = CTTypesetterCreateWithAttributedString(attributedString); - - CFRange range = {0, 0}; - QCFType<CTLineRef> line = CTTypesetterCreateLine(typeSetter, range); - CFArrayRef array = CTLineGetGlyphRuns(line); - uint arraySize = CFArrayGetCount(array); - glyph_t *outGlyphs = glyphs->glyphs; - HB_GlyphAttributes *outAttributes = glyphs->attributes; - QFixed *outAdvances_x = glyphs->advances_x; - QFixed *outAdvances_y = glyphs->advances_y; - glyph_t *initialGlyph = outGlyphs; - - if (arraySize == 0) { - // CoreText failed to shape the text we gave it, so we assume one glyph - // per character and build a list of invalid glyphs with zero advance - *nglyphs = len; - for (int i = 0; i < len; ++i) { - outGlyphs[i] = 0; - if (logClusters) - logClusters[i] = i; - outAdvances_x[i] = QFixed(); - outAdvances_y[i] = QFixed(); - outAttributes[i].clusterStart = true; - } - return true; - } - - const bool rtl = (CTRunGetStatus(static_cast<CTRunRef>(CFArrayGetValueAtIndex(array, 0))) & kCTRunStatusRightToLeft); - - bool outOBounds = false; - for (uint i = 0; i < arraySize; ++i) { - CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex(array, rtl ? (arraySize - 1 - i) : i)); - CFIndex glyphCount = CTRunGetGlyphCount(run); - if (glyphCount == 0) - continue; - - Q_ASSERT((CTRunGetStatus(run) & kCTRunStatusRightToLeft) == rtl); - CFRange stringRange = CTRunGetStringRange(run); - int prepend = 0; -#if MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5 - UniChar beginGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location); - QChar dir = QChar::direction(beginGlyph); - bool beginWithOverride = dir == QChar::DirLRO || dir == QChar::DirRLO || dir == QChar::DirLRE || dir == QChar::DirRLE; - if (beginWithOverride) { - logClusters[stringRange.location] = 0; - outGlyphs[0] = 0xFFFF; - outAdvances_x[0] = 0; - outAdvances_y[0] = 0; - outAttributes[0].clusterStart = true; - outAttributes[0].dontPrint = true; - outGlyphs++; - outAdvances_x++; - outAdvances_y++; - outAttributes++; - prepend = 1; - } -#endif - UniChar endGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location + stringRange.length - 1); - bool endWithPDF = QChar::direction(endGlyph) == QChar::DirPDF; - if (endWithPDF) - glyphCount++; - - if (!outOBounds && outGlyphs + glyphCount - initialGlyph > *nglyphs) { - outOBounds = true; - } - if (!outOBounds) { - CFDictionaryRef runAttribs = CTRunGetAttributes(run); - //NSLog(@"Dictionary %@", runAttribs); - if (!runAttribs) - runAttribs = attributeDict; - CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(runAttribs, NSFontAttributeName)); - uint fontIndex = fontIndexForFont(runFont); - const QFontEngine *engine = engineAt(fontIndex); - fontIndex <<= 24; - si->ascent = qMax(engine->ascent(), si->ascent); - si->descent = qMax(engine->descent(), si->descent); - si->leading = qMax(engine->leading(), si->leading); - //NSLog(@"Run Font Name = %@", CTFontCopyFamilyName(runFont)); - if (endWithPDF) - glyphCount--; - - QVarLengthArray<CGGlyph, 512> cgglyphs(0); - const CGGlyph *tmpGlyphs = CTRunGetGlyphsPtr(run); - if (!tmpGlyphs) { - cgglyphs.resize(glyphCount); - CTRunGetGlyphs(run, range, cgglyphs.data()); - tmpGlyphs = cgglyphs.constData(); - } - QVarLengthArray<CGPoint, 512> cgpoints(0); - const CGPoint *tmpPoints = CTRunGetPositionsPtr(run); - if (!tmpPoints) { - cgpoints.resize(glyphCount); - CTRunGetPositions(run, range, cgpoints.data()); - tmpPoints = cgpoints.constData(); - } - - const int rtlOffset = rtl ? (glyphCount - 1) : 0; - const int rtlSign = rtl ? -1 : 1; - - if (logClusters) { - CFRange stringRange = CTRunGetStringRange(run); - QVarLengthArray<CFIndex, 512> stringIndices(0); - const CFIndex *tmpIndices = CTRunGetStringIndicesPtr(run); - if (!tmpIndices) { - stringIndices.resize(glyphCount); - CTRunGetStringIndices(run, range, stringIndices.data()); - tmpIndices = stringIndices.constData(); - } - - const int firstGlyphIndex = outGlyphs - initialGlyph; - outAttributes[0].clusterStart = true; - - CFIndex k = 0; - CFIndex i = 0; - for (i = stringRange.location + prepend; - (i < stringRange.location + stringRange.length) && (k < glyphCount); ++i) { - if (tmpIndices[k * rtlSign + rtlOffset] == i || i == stringRange.location + prepend) { - logClusters[i] = k + firstGlyphIndex; - outAttributes[k].clusterStart = true; - ++k; - } else { - logClusters[i] = k + firstGlyphIndex - 1; - } - } - // in case of a ligature at the end, fill the remaining logcluster entries - for (;i < stringRange.location + stringRange.length; i++) { - logClusters[i] = k + firstGlyphIndex - 1; - } - } - for (CFIndex i = 0; i < glyphCount - 1; ++i) { - int idx = rtlOffset + rtlSign * i; - outGlyphs[idx] = tmpGlyphs[i] | fontIndex; - outAdvances_x[idx] = QFixed::fromReal(tmpPoints[i + 1].x - tmpPoints[i].x); - // Use negative y advance for flipped coordinate system - outAdvances_y[idx] = QFixed::fromReal(tmpPoints[i].y - tmpPoints[i + 1].y); - - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - outAdvances_x[idx] = outAdvances_x[idx].round(); - outAdvances_y[idx] = outAdvances_y[idx].round(); - } - } - CGSize lastGlyphAdvance; - CTFontGetAdvancesForGlyphs(runFont, kCTFontHorizontalOrientation, tmpGlyphs + glyphCount - 1, &lastGlyphAdvance, 1); - - outGlyphs[rtl ? 0 : (glyphCount - 1)] = tmpGlyphs[glyphCount - 1] | fontIndex; - outAdvances_x[rtl ? 0 : (glyphCount - 1)] = - (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? QFixed::fromReal(lastGlyphAdvance.width).round() - : QFixed::fromReal(lastGlyphAdvance.width); - - if (endWithPDF) { - logClusters[stringRange.location + stringRange.length - 1] = glyphCount + prepend; - outGlyphs[glyphCount] = 0xFFFF; - outAdvances_x[glyphCount] = 0; - outAdvances_y[glyphCount] = 0; - outAttributes[glyphCount].clusterStart = true; - outAttributes[glyphCount].dontPrint = true; - glyphCount++; - } - } - outGlyphs += glyphCount; - outAttributes += glyphCount; - outAdvances_x += glyphCount; - outAdvances_y += glyphCount; - } - *nglyphs = (outGlyphs - initialGlyph); - return !outOBounds; -} - -bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, - int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - *nglyphs = len; - QCFType<CFStringRef> cfstring; - - QVarLengthArray<CGGlyph> cgGlyphs(len); - CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len); - - for (int i = 0; i < len; ++i) { - if (cgGlyphs[i]) { - glyphs->glyphs[i] = cgGlyphs[i]; - } else { - if (!cfstring) - cfstring = CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar *>(str), len, kCFAllocatorNull); - QCFType<CTFontRef> substituteFont = CTFontCreateForString(ctfont, cfstring, CFRangeMake(i, 1)); - CGGlyph substituteGlyph = 0; - CTFontGetGlyphsForCharacters(substituteFont, (const UniChar*)str + i, &substituteGlyph, 1); - if (substituteGlyph) { - const uint fontIndex = (fontIndexForFont(substituteFont) << 24); - glyphs->glyphs[i] = substituteGlyph | fontIndex; - if (!(flags & QTextEngine::GlyphIndicesOnly)) { - CGSize advance; - CTFontGetAdvancesForGlyphs(substituteFont, kCTFontHorizontalOrientation, &substituteGlyph, &advance, 1); - glyphs->advances_x[i] = QFixed::fromReal(advance.width); - glyphs->advances_y[i] = QFixed::fromReal(advance.height); - } - } - } - } - - if (flags & QTextEngine::GlyphIndicesOnly) - return true; - - loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, len, flags, fontDef); - return true; -} - -void QCoreTextFontEngineMulti::loadEngine(int) -{ - // Do nothing - Q_ASSERT(false); -} - -extern int qt_antialiasing_threshold; // from qapplication.cpp - -static inline CGAffineTransform transformFromFontDef(const QFontDef &fontDef) -{ - CGAffineTransform transform = CGAffineTransformIdentity; - if (fontDef.stretch != 100) - transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); - return transform; -} - -QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def) -{ - fontDef = def; - transform = transformFromFontDef(fontDef); - ctfont = font; - CFRetain(ctfont); - cgFont = CTFontCopyGraphicsFont(font, NULL); - init(); -} - -QCoreTextFontEngine::QCoreTextFontEngine(CGFontRef font, const QFontDef &def) -{ - fontDef = def; - transform = transformFromFontDef(fontDef); - cgFont = font; - // Keep reference count balanced - CFRetain(cgFont); - ctfont = CTFontCreateWithGraphicsFont(font, fontDef.pixelSize, &transform, NULL); - init(); -} - -QCoreTextFontEngine::~QCoreTextFontEngine() -{ - CFRelease(cgFont); - CFRelease(ctfont); -} - -extern QFont::Weight weightFromInteger(int weight); // qfontdatabase.cpp - -int getTraitValue(CFDictionaryRef allTraits, CFStringRef trait) -{ - if (CFDictionaryContainsKey(allTraits, trait)) { - CFNumberRef traitNum = (CFNumberRef) CFDictionaryGetValue(allTraits, trait); - float v = 0; - CFNumberGetValue(traitNum, kCFNumberFloatType, &v); - // the value we get from CFNumberRef is from -1.0 to 1.0 - int value = v * 500 + 500; - return value; - } - - return 0; -} - -void QCoreTextFontEngine::init() -{ - Q_ASSERT(ctfont != NULL); - Q_ASSERT(cgFont != NULL); - - QCFString family = CTFontCopyFamilyName(ctfont); - fontDef.family = family; - - synthesisFlags = 0; - CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctfont); - if (traits & kCTFontItalicTrait) - fontDef.style = QFont::StyleItalic; - - CFDictionaryRef allTraits = CTFontCopyTraits(ctfont); - fontDef.weight = weightFromInteger(getTraitValue(allTraits, kCTFontWeightTrait)); - int slant = getTraitValue(allTraits, kCTFontSlantTrait); - if (slant > 500 && !(traits & kCTFontItalicTrait)) - fontDef.style = QFont::StyleOblique; - CFRelease(allTraits); - - if (fontDef.weight >= QFont::Bold && !(traits & kCTFontBoldTrait)) - synthesisFlags |= SynthesizedBold; - // XXX: we probably don't need to synthesis italic for oblique font - if (fontDef.style != QFont::StyleNormal && !(traits & kCTFontItalicTrait)) - synthesisFlags |= SynthesizedItalic; - - avgCharWidth = 0; - QByteArray os2Table = getSfntTable(MAKE_TAG('O', 'S', '/', '2')); - unsigned emSize = CTFontGetUnitsPerEm(ctfont); - if (os2Table.size() >= 10) { - fsType = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(os2Table.constData() + 8)); - // qAbs is a workaround for weird fonts like Lucida Grande - qint16 width = qAbs(qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(os2Table.constData() + 2))); - avgCharWidth = QFixed::fromReal(width * fontDef.pixelSize / emSize); - } else - avgCharWidth = QFontEngine::averageCharWidth(); - - ctMaxCharWidth = ctMinLeftBearing = ctMinRightBearing = 0; - QByteArray hheaTable = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a')); - if (hheaTable.size() >= 16) { - quint16 width = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 10)); - ctMaxCharWidth = width * fontDef.pixelSize / emSize; - qint16 bearing = qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 12)); - ctMinLeftBearing = bearing * fontDef.pixelSize / emSize; - bearing = qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 14)); - ctMinRightBearing = bearing * fontDef.pixelSize / emSize; - } -} - -bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, - int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - *nglyphs = len; - QCFType<CFStringRef> cfstring; - - QVarLengthArray<CGGlyph> cgGlyphs(len); - CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len); - - for (int i = 0; i < len; ++i) - if (cgGlyphs[i]) - glyphs->glyphs[i] = cgGlyphs[i]; - - if (flags & QTextEngine::GlyphIndicesOnly) - return true; - - loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, len, flags, fontDef); - return true; -} - -glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs) -{ - QFixed w; - bool round = fontDef.styleStrategy & QFont::ForceIntegerMetrics; - - for (int i = 0; i < glyphs.numGlyphs; ++i) { - w += round ? glyphs.effectiveAdvance(i).round() - : glyphs.effectiveAdvance(i); - } - return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs, round), ascent()+descent(), w, 0); -} - -glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph) -{ - glyph_metrics_t ret; - CGGlyph g = glyph; - CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, 0, 1); - if (synthesisFlags & QFontEngine::SynthesizedItalic) { - rect.size.width += rect.size.height * SYNTHETIC_ITALIC_SKEW; - } - ret.width = QFixed::fromReal(rect.size.width); - ret.height = QFixed::fromReal(rect.size.height); - ret.x = QFixed::fromReal(rect.origin.x); - ret.y = -QFixed::fromReal(rect.origin.y) - ret.height; - CGSize advances[1]; - CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, advances, 1); - ret.xoff = QFixed::fromReal(advances[0].width); - ret.yoff = QFixed::fromReal(advances[0].height); - - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - ret.xoff = ret.xoff.round(); - ret.yoff = ret.yoff.round(); - } - - return ret; -} - -QFixed QCoreTextFontEngine::ascent() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? QFixed::fromReal(CTFontGetAscent(ctfont)).round() - : QFixed::fromReal(CTFontGetAscent(ctfont)); -} -QFixed QCoreTextFontEngine::descent() const -{ - QFixed d = QFixed::fromReal(CTFontGetDescent(ctfont)); - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - d = d.round(); - - // subtract a pixel to even out the historical +1 in QFontMetrics::height(). - // Fix in Qt 5. - return d - 1; -} -QFixed QCoreTextFontEngine::leading() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? QFixed::fromReal(CTFontGetLeading(ctfont)).round() - : QFixed::fromReal(CTFontGetLeading(ctfont)); -} -QFixed QCoreTextFontEngine::xHeight() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? QFixed::fromReal(CTFontGetXHeight(ctfont)).round() - : QFixed::fromReal(CTFontGetXHeight(ctfont)); -} - -QFixed QCoreTextFontEngine::averageCharWidth() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? avgCharWidth.round() : avgCharWidth; -} - -qreal QCoreTextFontEngine::maxCharWidth() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(ctMaxCharWidth) : ctMaxCharWidth; -} - -qreal QCoreTextFontEngine::minLeftBearing() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(ctMinLeftBearing) : ctMinLeftBearing; -} - -qreal QCoreTextFontEngine::minRightBearing() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(ctMinRightBearing) : ctMinLeftBearing; -} - -void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight) -{ - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> glyphs; - QTransform matrix; - matrix.translate(x, y); - getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - if (glyphs.size() == 0) - return; - - CGContextSetFontSize(ctx, fontDef.pixelSize); - - CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx); - - CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight); - - CGAffineTransformConcat(cgMatrix, oldTextMatrix); - - if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); - - cgMatrix = CGAffineTransformConcat(cgMatrix, transform); - - CGContextSetTextMatrix(ctx, cgMatrix); - - CGContextSetTextDrawingMode(ctx, kCGTextFill); - - - QVarLengthArray<CGSize> advances(glyphs.size()); - QVarLengthArray<CGGlyph> cgGlyphs(glyphs.size()); - - for (int i = 0; i < glyphs.size() - 1; ++i) { - advances[i].width = (positions[i + 1].x - positions[i].x).toReal(); - advances[i].height = (positions[i + 1].y - positions[i].y).toReal(); - cgGlyphs[i] = glyphs[i]; - } - advances[glyphs.size() - 1].width = 0; - advances[glyphs.size() - 1].height = 0; - cgGlyphs[glyphs.size() - 1] = glyphs[glyphs.size() - 1]; - - CGContextSetFont(ctx, cgFont); - //NSLog(@"Font inDraw %@ ctfont %@", CGFontCopyFullName(cgFont), CTFontCopyFamilyName(ctfont)); - - CGContextSetTextPosition(ctx, positions[0].x.toReal(), positions[0].y.toReal()); - - CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size()); - - if (synthesisFlags & QFontEngine::SynthesizedBold) { - CGContextSetTextPosition(ctx, positions[0].x.toReal() + 0.5 * lineThickness().toReal(), - positions[0].y.toReal()); - - CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size()); - } - - CGContextSetTextMatrix(ctx, oldTextMatrix); -} - -struct ConvertPathInfo -{ - ConvertPathInfo(QPainterPath *newPath, const QPointF &newPos) : path(newPath), pos(newPos) {} - QPainterPath *path; - QPointF pos; -}; - -static void convertCGPathToQPainterPath(void *info, const CGPathElement *element) -{ - ConvertPathInfo *myInfo = static_cast<ConvertPathInfo *>(info); - switch(element->type) { - case kCGPathElementMoveToPoint: - myInfo->path->moveTo(element->points[0].x + myInfo->pos.x(), - element->points[0].y + myInfo->pos.y()); - break; - case kCGPathElementAddLineToPoint: - myInfo->path->lineTo(element->points[0].x + myInfo->pos.x(), - element->points[0].y + myInfo->pos.y()); - break; - case kCGPathElementAddQuadCurveToPoint: - myInfo->path->quadTo(element->points[0].x + myInfo->pos.x(), - element->points[0].y + myInfo->pos.y(), - element->points[1].x + myInfo->pos.x(), - element->points[1].y + myInfo->pos.y()); - break; - case kCGPathElementAddCurveToPoint: - myInfo->path->cubicTo(element->points[0].x + myInfo->pos.x(), - element->points[0].y + myInfo->pos.y(), - element->points[1].x + myInfo->pos.x(), - element->points[1].y + myInfo->pos.y(), - element->points[2].x + myInfo->pos.x(), - element->points[2].y + myInfo->pos.y()); - break; - case kCGPathElementCloseSubpath: - myInfo->path->closeSubpath(); - break; - default: - qDebug() << "Unhandled path transform type: " << element->type; - } - -} - -void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nGlyphs, - QPainterPath *path, QTextItem::RenderFlags) -{ - CGAffineTransform cgMatrix = CGAffineTransformIdentity; - cgMatrix = CGAffineTransformScale(cgMatrix, 1, -1); - - if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); - - for (int i = 0; i < nGlyphs; ++i) { - QCFType<CGPathRef> cgpath = CTFontCreatePathForGlyph(ctfont, glyphs[i], &cgMatrix); - ConvertPathInfo info(path, positions[i].toPointF()); - CGPathApply(cgpath, &info, convertCGPathToQPainterPath); - } -} - -QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int /*margin*/, bool aa) -{ - const glyph_metrics_t br = boundingBox(glyph); - QImage im(qRound(br.width)+2, qRound(br.height)+2, QImage::Format_RGB32); - im.fill(0); - - CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - uint cgflags = kCGImageAlphaNoneSkipFirst; -#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - cgflags |= kCGBitmapByteOrder32Host; -#endif - CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(), - 8, im.bytesPerLine(), colorspace, - cgflags); - CGContextSetFontSize(ctx, fontDef.pixelSize); - CGContextSetShouldAntialias(ctx, aa || - (fontDef.pointSize > qt_antialiasing_threshold - && !(fontDef.styleStrategy & QFont::NoAntialias))); - CGContextSetShouldSmoothFonts(ctx, aa); - CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx); - CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, 1, 0, 0); - - CGAffineTransformConcat(cgMatrix, oldTextMatrix); - - if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); - - cgMatrix = CGAffineTransformConcat(cgMatrix, transform); - - CGContextSetTextMatrix(ctx, cgMatrix); - CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); - CGContextSetTextDrawingMode(ctx, kCGTextFill); - - CGContextSetFont(ctx, cgFont); - - qreal pos_x = -br.x.toReal() + subPixelPosition.toReal(); - qreal pos_y = im.height() + br.y.toReal() - 1; - CGContextSetTextPosition(ctx, pos_x, pos_y); - - CGSize advance; - advance.width = 0; - advance.height = 0; - CGGlyph cgGlyph = glyph; - CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); - - if (synthesisFlags & QFontEngine::SynthesizedBold) { - CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y); - CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); - } - - CGContextRelease(ctx); - - return im; -} - -QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) -{ - QImage im = imageForGlyph(glyph, subPixelPosition, 0, false); - - QImage indexed(im.width(), im.height(), QImage::Format_Indexed8); - QVector<QRgb> colors(256); - for (int i=0; i<256; ++i) - colors[i] = qRgba(0, 0, 0, i); - indexed.setColorTable(colors); - - for (int y=0; y<im.height(); ++y) { - uint *src = (uint*) im.scanLine(y); - uchar *dst = indexed.scanLine(y); - for (int x=0; x<im.width(); ++x) { - *dst = qGray(*src); - ++dst; - ++src; - } - } - - return indexed; -} - -QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, const QTransform &x) -{ - if (x.type() >= QTransform::TxScale) - return QFontEngine::alphaRGBMapForGlyph(glyph, subPixelPosition, margin, x); - - QImage im = imageForGlyph(glyph, subPixelPosition, margin, true); - qGamma_correct_back_to_linear_cs(&im); - return im; -} - -void QCoreTextFontEngine::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const -{ - int i, numGlyphs = glyphs->numGlyphs; - QVarLengthArray<CGGlyph> cgGlyphs(numGlyphs); - - for (i = 0; i < numGlyphs; ++i) { - if (glyphs->glyphs[i] & 0xff000000) - cgGlyphs[i] = 0; - else - cgGlyphs[i] = glyphs->glyphs[i]; - } - - loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, numGlyphs, flags, fontDef); -} - -QFontEngine::FaceId QCoreTextFontEngine::faceId() const -{ - return QFontEngine::FaceId(); -} - -bool QCoreTextFontEngine::canRender(const QChar *string, int len) -{ - QVarLengthArray<CGGlyph> cgGlyphs(len); - return CTFontGetGlyphsForCharacters(ctfont, (const UniChar *) string, cgGlyphs.data(), len); -} - -bool QCoreTextFontEngine::getSfntTableData(uint tag, uchar *buffer, uint *length) const -{ - QCFType<CFDataRef> table = CTFontCopyTable(ctfont, tag, 0); - if (!table || !length) - return false; - CFIndex tableLength = CFDataGetLength(table); - int availableLength = *length; - *length = tableLength; - if (buffer) { - if (tableLength > availableLength) - return false; - CFDataGetBytes(table, CFRangeMake(0, tableLength), buffer); - } - return true; -} - -void QCoreTextFontEngine::getUnscaledGlyph(glyph_t, QPainterPath *, glyph_metrics_t *) -{ - // ### -} - -QFixed QCoreTextFontEngine::emSquareSize() const -{ - return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont))); -} - -QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const -{ - QFontDef newFontDef = fontDef; - newFontDef.pixelSize = pixelSize; - newFontDef.pointSize = pixelSize * 72.0 / qt_defaultDpi(); - - return new QCoreTextFontEngine(cgFont, fontDef); -} - -QT_END_NAMESPACE - -#endif// !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - diff --git a/src/gui/platforms/mac/qfontengine_coretext_p.h b/src/gui/platforms/mac/qfontengine_coretext_p.h deleted file mode 100644 index bb80a9b2f3..0000000000 --- a/src/gui/platforms/mac/qfontengine_coretext_p.h +++ /dev/null @@ -1,144 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QFONTENGINE_CORETEXT_P_H -#define QFONTENGINE_CORETEXT_P_H - -#include <private/qfontengine_p.h> - -#if !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - -class QRawFontPrivate; -class QCoreTextFontEngineMulti; -class QCoreTextFontEngine : public QFontEngine -{ -public: - QCoreTextFontEngine(CTFontRef font, const QFontDef &def); - QCoreTextFontEngine(CGFontRef font, const QFontDef &def); - ~QCoreTextFontEngine(); - - virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; - virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; - - virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); - virtual glyph_metrics_t boundingBox(glyph_t glyph); - - virtual QFixed ascent() const; - virtual QFixed descent() const; - virtual QFixed leading() const; - virtual QFixed xHeight() const; - virtual qreal maxCharWidth() const; - virtual QFixed averageCharWidth() const; - - virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, - QPainterPath *path, QTextItem::RenderFlags); - - virtual const char *name() const { return "QCoreTextFontEngine"; } - - virtual bool canRender(const QChar *string, int len); - - virtual int synthesized() const { return synthesisFlags; } - virtual bool supportsSubPixelPositions() const { return true; } - - virtual Type type() const { return QFontEngine::Mac; } - - void draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight); - - virtual FaceId faceId() const; - virtual bool getSfntTableData(uint /*tag*/, uchar * /*buffer*/, uint * /*length*/) const; - virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); - virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition); - virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); - virtual qreal minRightBearing() const; - virtual qreal minLeftBearing() const; - virtual QFixed emSquareSize() const; - - virtual QFontEngine *cloneWithSize(qreal pixelSize) const; - -private: - friend class QRawFontPrivate; - - void init(); - QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, bool colorful); - CTFontRef ctfont; - CGFontRef cgFont; - int synthesisFlags; - CGAffineTransform transform; - QFixed avgCharWidth; - qreal ctMaxCharWidth; - qreal ctMinLeftBearing; - qreal ctMinRightBearing; - friend class QCoreTextFontEngineMulti; -}; - -class QCoreTextFontEngineMulti : public QFontEngineMulti -{ -public: - QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning); - QCoreTextFontEngineMulti(CGFontRef cgFontRef, const QFontDef &fontDef, bool kerning); - ~QCoreTextFontEngineMulti(); - - virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, - QTextEngine::ShaperFlags flags) const; - bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, - QTextEngine::ShaperFlags flags, - unsigned short *logClusters, const HB_CharAttributes *charAttributes, - QScriptItem *si) const; - - virtual const char *name() const { return "CoreText"; } -protected: - virtual void loadEngine(int at); - -private: - void init(bool kerning); - inline const QCoreTextFontEngine *engineAt(int i) const - { return static_cast<const QCoreTextFontEngine *>(engines.at(i)); } - - uint fontIndexForFont(CTFontRef font) const; - CTFontRef ctfont; - mutable QCFType<CFMutableDictionaryRef> attributeDict; - CGAffineTransform transform; - friend class QFontDialogPrivate; -}; - -#endif// !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - -#endif // QFONTENGINE_CORETEXT_P_H diff --git a/src/gui/platforms/mac/qfontengine_mac.mm b/src/gui/platforms/mac/qfontengine_mac.mm deleted file mode 100644 index 9f094ad7d1..0000000000 --- a/src/gui/platforms/mac/qfontengine_mac.mm +++ /dev/null @@ -1,1236 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfontengine_mac_p.h" - -#include <private/qapplication_p.h> -#include <private/qfontengine_p.h> -#include <private/qpainter_p.h> -#include <private/qtextengine_p.h> -#include <qbitmap.h> -#include <private/qpaintengine_mac_p.h> -#include <private/qprintengine_mac_p.h> -#include <qglobal.h> -#include <qpixmap.h> -#include <qpixmapcache.h> -#include <qvarlengtharray.h> -#include <qdebug.h> -#include <qendian.h> -#include <qmath.h> -#include <private/qimage_p.h> - -#include <ApplicationServices/ApplicationServices.h> -#include <AppKit/AppKit.h> - -QT_BEGIN_NAMESPACE - -/***************************************************************************** - QFontEngine debug facilities - *****************************************************************************/ -//#define DEBUG_ADVANCES - -extern int qt_antialiasing_threshold; // QApplication.cpp - -#ifndef FixedToQFixed -#define FixedToQFixed(a) QFixed::fromFixed((a) >> 10) -#define QFixedToFixed(x) ((x).value() << 10) -#endif - -class QMacFontPath -{ - float x, y; - QPainterPath *path; -public: - inline QMacFontPath(float _x, float _y, QPainterPath *_path) : x(_x), y(_y), path(_path) { } - inline void setPosition(float _x, float _y) { x = _x; y = _y; } - inline void advance(float _x) { x += _x; } - static OSStatus lineTo(const Float32Point *, void *); - static OSStatus cubicTo(const Float32Point *, const Float32Point *, - const Float32Point *, void *); - static OSStatus moveTo(const Float32Point *, void *); - static OSStatus closePath(void *); -}; - -OSStatus QMacFontPath::lineTo(const Float32Point *pt, void *data) - -{ - QMacFontPath *p = static_cast<QMacFontPath*>(data); - p->path->lineTo(p->x + pt->x, p->y + pt->y); - return noErr; -} - -OSStatus QMacFontPath::cubicTo(const Float32Point *cp1, const Float32Point *cp2, - const Float32Point *ep, void *data) - -{ - QMacFontPath *p = static_cast<QMacFontPath*>(data); - p->path->cubicTo(p->x + cp1->x, p->y + cp1->y, - p->x + cp2->x, p->y + cp2->y, - p->x + ep->x, p->y + ep->y); - return noErr; -} - -OSStatus QMacFontPath::moveTo(const Float32Point *pt, void *data) -{ - QMacFontPath *p = static_cast<QMacFontPath*>(data); - p->path->moveTo(p->x + pt->x, p->y + pt->y); - return noErr; -} - -OSStatus QMacFontPath::closePath(void *data) -{ - static_cast<QMacFontPath*>(data)->path->closeSubpath(); - return noErr; -} - - -#ifndef QT_MAC_USE_COCOA -QFontEngineMacMulti::QFontEngineMacMulti(const ATSFontFamilyRef &atsFamily, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning) - : QFontEngineMulti(0) -{ - this->fontDef = fontDef; - this->kerning = kerning; - - // hopefully (CTFontCreateWithName or CTFontCreateWithFontDescriptor) + CTFontCreateCopyWithSymbolicTraits - // (or CTFontCreateWithQuickdrawInstance) - FMFontFamily fmFamily; - FMFontStyle fntStyle = 0; - fmFamily = FMGetFontFamilyFromATSFontFamilyRef(atsFamily); - if (fmFamily == kInvalidFontFamily) { - // Use the ATSFont then... - fontID = FMGetFontFromATSFontRef(atsFontRef); - } else { - if (fontDef.weight >= QFont::Bold) - fntStyle |= ::bold; - if (fontDef.style != QFont::StyleNormal) - fntStyle |= ::italic; - - FMFontStyle intrinsicStyle; - FMFont fnt = 0; - if (FMGetFontFromFontFamilyInstance(fmFamily, fntStyle, &fnt, &intrinsicStyle) == noErr) - fontID = FMGetATSFontRefFromFont(fnt); - } - - // CFDictionaryRef, <CTStringAttributes.h> - OSStatus status; - - status = ATSUCreateTextLayout(&textLayout); - Q_ASSERT(status == noErr); - - const int maxAttributeCount = 5; - ATSUAttributeTag tags[maxAttributeCount + 1]; - ByteCount sizes[maxAttributeCount + 1]; - ATSUAttributeValuePtr values[maxAttributeCount + 1]; - int attributeCount = 0; - - Fixed size = FixRatio(fontDef.pixelSize, 1); - tags[attributeCount] = kATSUSizeTag; - sizes[attributeCount] = sizeof(size); - values[attributeCount] = &size; - ++attributeCount; - - tags[attributeCount] = kATSUFontTag; - sizes[attributeCount] = sizeof(fontID); - values[attributeCount] = &this->fontID; - ++attributeCount; - - transform = CGAffineTransformIdentity; - if (fontDef.stretch != 100) { - transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); - tags[attributeCount] = kATSUFontMatrixTag; - sizes[attributeCount] = sizeof(transform); - values[attributeCount] = &transform; - ++attributeCount; - } - - status = ATSUCreateStyle(&style); - Q_ASSERT(status == noErr); - - Q_ASSERT(attributeCount < maxAttributeCount + 1); - status = ATSUSetAttributes(style, attributeCount, tags, sizes, values); - Q_ASSERT(status == noErr); - - QFontEngineMac *fe = new QFontEngineMac(style, fontID, fontDef, this); - fe->ref.ref(); - engines.append(fe); -} - -QFontEngineMacMulti::~QFontEngineMacMulti() -{ - ATSUDisposeTextLayout(textLayout); - ATSUDisposeStyle(style); - - for (int i = 0; i < engines.count(); ++i) { - QFontEngineMac *fe = const_cast<QFontEngineMac *>(static_cast<const QFontEngineMac *>(engines.at(i))); - fe->multiEngine = 0; - if (!fe->ref.deref()) - delete fe; - } - engines.clear(); -} - -struct QGlyphLayoutInfo -{ - QGlyphLayout *glyphs; - int *numGlyphs; - bool callbackCalled; - int *mappedFonts; - QTextEngine::ShaperFlags flags; - QFontEngineMacMulti::ShaperItem *shaperItem; - unsigned int styleStrategy; -}; - -static OSStatus atsuPostLayoutCallback(ATSULayoutOperationSelector selector, ATSULineRef lineRef, URefCon refCon, - void *operationExtraParameter, ATSULayoutOperationCallbackStatus *callbackStatus) -{ - Q_UNUSED(selector); - Q_UNUSED(operationExtraParameter); - - QGlyphLayoutInfo *nfo = reinterpret_cast<QGlyphLayoutInfo *>(refCon); - nfo->callbackCalled = true; - - ATSLayoutRecord *layoutData = 0; - ItemCount itemCount = 0; - - OSStatus e = noErr; - e = ATSUDirectGetLayoutDataArrayPtrFromLineRef(lineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, - /*iCreate =*/ false, - (void **) &layoutData, - &itemCount); - if (e != noErr) - return e; - - *nfo->numGlyphs = itemCount - 1; - - Fixed *baselineDeltas = 0; - - e = ATSUDirectGetLayoutDataArrayPtrFromLineRef(lineRef, kATSUDirectDataBaselineDeltaFixedArray, - /*iCreate =*/ true, - (void **) &baselineDeltas, - &itemCount); - if (e != noErr) - return e; - - int nextCharStop = -1; - int currentClusterGlyph = -1; // first glyph in log cluster - QFontEngineMacMulti::ShaperItem *item = nfo->shaperItem; - if (item->charAttributes) { - item = nfo->shaperItem; -#if !defined(QT_NO_DEBUG) - int surrogates = 0; - const QChar *str = item->string; - for (int i = item->from; i < item->from + item->length - 1; ++i) { - surrogates += (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00 - && str[i+1].unicode() >= 0xdc00 && str[i+1].unicode() < 0xe000); - } -#endif - for (nextCharStop = item->from; nextCharStop < item->from + item->length; ++nextCharStop) - if (item->charAttributes[nextCharStop].charStop) - break; - nextCharStop -= item->from; - } - - nfo->glyphs->attributes[0].clusterStart = true; - int glyphIdx = 0; - int glyphIncrement = 1; - if (nfo->flags & QTextEngine::RightToLeft) { - glyphIdx = itemCount - 2; - glyphIncrement = -1; - } - for (int i = 0; i < *nfo->numGlyphs; ++i, glyphIdx += glyphIncrement) { - - int charOffset = layoutData[glyphIdx].originalOffset / sizeof(UniChar); - const int fontIdx = nfo->mappedFonts[charOffset]; - - ATSGlyphRef glyphId = layoutData[glyphIdx].glyphID; - - QFixed yAdvance = FixedToQFixed(baselineDeltas[glyphIdx]); - QFixed xAdvance = FixedToQFixed(layoutData[glyphIdx + 1].realPos - layoutData[glyphIdx].realPos); - - if (nfo->styleStrategy & QFont::ForceIntegerMetrics) { - yAdvance = yAdvance.round(); - xAdvance = xAdvance.round(); - } - - if (glyphId != 0xffff || i == 0) { - if (i < nfo->glyphs->numGlyphs) - { - nfo->glyphs->glyphs[i] = (glyphId & 0x00ffffff) | (fontIdx << 24); - - nfo->glyphs->advances_y[i] = yAdvance; - nfo->glyphs->advances_x[i] = xAdvance; - } - } else { - // ATSUI gives us 0xffff as glyph id at the index in the glyph array for - // a character position that maps to a ligtature. Such a glyph id does not - // result in any visual glyph, but it may have an advance, which is why we - // sum up the glyph advances. - --i; - nfo->glyphs->advances_y[i] += yAdvance; - nfo->glyphs->advances_x[i] += xAdvance; - *nfo->numGlyphs -= 1; - } - - if (item->log_clusters) { - if (charOffset >= nextCharStop) { - nfo->glyphs->attributes[i].clusterStart = true; - currentClusterGlyph = i; - - ++nextCharStop; - for (; nextCharStop < item->length; ++nextCharStop) - if (item->charAttributes[item->from + nextCharStop].charStop) - break; - } else { - if (currentClusterGlyph == -1) - currentClusterGlyph = i; - } - item->log_clusters[charOffset] = currentClusterGlyph; - - // surrogate handling - if (charOffset < item->length - 1) { - QChar current = item->string[item->from + charOffset]; - QChar next = item->string[item->from + charOffset + 1]; - if (current.unicode() >= 0xd800 && current.unicode() < 0xdc00 - && next.unicode() >= 0xdc00 && next.unicode() < 0xe000) { - item->log_clusters[charOffset + 1] = currentClusterGlyph; - } - } - } - } - - /* - if (item) { - qDebug() << "resulting logclusters:"; - for (int i = 0; i < item->length; ++i) - qDebug() << "logClusters[" << i << "] =" << item->log_clusters[i]; - qDebug() << "clusterstarts:"; - for (int i = 0; i < *nfo->numGlyphs; ++i) - qDebug() << "clusterStart[" << i << "] =" << nfo->glyphs[i].attributes.clusterStart; - } - */ - - ATSUDirectReleaseLayoutDataArrayPtr(lineRef, kATSUDirectDataBaselineDeltaFixedArray, - (void **) &baselineDeltas); - - ATSUDirectReleaseLayoutDataArrayPtr(lineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, - (void **) &layoutData); - - *callbackStatus = kATSULayoutOperationCallbackStatusHandled; - return noErr; -} - -int QFontEngineMacMulti::fontIndexForFontID(ATSUFontID id) const -{ - for (int i = 0; i < engines.count(); ++i) { - if (engineAt(i)->fontID == id) - return i; - } - - QFontEngineMacMulti *that = const_cast<QFontEngineMacMulti *>(this); - QFontEngineMac *fe = new QFontEngineMac(style, id, fontDef, that); - fe->ref.ref(); - that->engines.append(fe); - return engines.count() - 1; -} - -bool QFontEngineMacMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - return stringToCMap(str, len, glyphs, nglyphs, flags, /*logClusters=*/0, /*charAttributes=*/0); -} - -bool QFontEngineMacMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags, - unsigned short *logClusters, const HB_CharAttributes *charAttributes, QScriptItem *) const -{ - if (*nglyphs < len) { - *nglyphs = len; - return false; - } - - ShaperItem shaperItem; - shaperItem.string = str; - shaperItem.from = 0; - shaperItem.length = len; - shaperItem.glyphs = *glyphs; - shaperItem.glyphs.numGlyphs = *nglyphs; - shaperItem.flags = flags; - shaperItem.log_clusters = logClusters; - shaperItem.charAttributes = charAttributes; - - const int maxChars = qMax(1, - int(SHRT_MAX / maxCharWidth()) - - 10 // subtract a few to be on the safe side - ); - if (len < maxChars || !charAttributes) - return stringToCMapInternal(str, len, glyphs, nglyphs, flags, &shaperItem); - - int charIdx = 0; - int glyphIdx = 0; - ShaperItem tmpItem = shaperItem; - - do { - tmpItem.from = shaperItem.from + charIdx; - - int charCount = qMin(maxChars, len - charIdx); - - int lastWhitespace = tmpItem.from + charCount - 1; - int lastSoftBreak = lastWhitespace; - int lastCharStop = lastSoftBreak; - for (int i = lastCharStop; i >= tmpItem.from; --i) { - if (tmpItem.charAttributes[i].whiteSpace) { - lastWhitespace = i; - break; - } if (tmpItem.charAttributes[i].lineBreakType != HB_NoBreak) { - lastSoftBreak = i; - } if (tmpItem.charAttributes[i].charStop) { - lastCharStop = i; - } - } - charCount = qMin(lastWhitespace, qMin(lastSoftBreak, lastCharStop)) - tmpItem.from + 1; - - int glyphCount = shaperItem.glyphs.numGlyphs - glyphIdx; - if (glyphCount <= 0) - return false; - tmpItem.length = charCount; - tmpItem.glyphs = shaperItem.glyphs.mid(glyphIdx, glyphCount); - tmpItem.log_clusters = shaperItem.log_clusters + charIdx; - if (!stringToCMapInternal(tmpItem.string + tmpItem.from, tmpItem.length, - &tmpItem.glyphs, &glyphCount, flags, - &tmpItem)) { - *nglyphs = glyphIdx + glyphCount; - return false; - } - for (int i = 0; i < charCount; ++i) - tmpItem.log_clusters[i] += glyphIdx; - glyphIdx += glyphCount; - charIdx += charCount; - } while (charIdx < len); - *nglyphs = glyphIdx; - glyphs->numGlyphs = glyphIdx; - - return true; -} - -bool QFontEngineMacMulti::stringToCMapInternal(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags,ShaperItem *shaperItem) const -{ - //qDebug() << "stringToCMap" << QString(str, len); - - OSStatus e = noErr; - - e = ATSUSetTextPointerLocation(textLayout, (UniChar *)(str), 0, len, len); - if (e != noErr) { - qWarning("Qt: internal: %ld: Error ATSUSetTextPointerLocation %s: %d", long(e), __FILE__, __LINE__); - return false; - } - - QGlyphLayoutInfo nfo; - nfo.glyphs = glyphs; - nfo.numGlyphs = nglyphs; - nfo.callbackCalled = false; - nfo.flags = flags; - nfo.shaperItem = shaperItem; - nfo.styleStrategy = fontDef.styleStrategy; - - int prevNumGlyphs = *nglyphs; - - QVarLengthArray<int> mappedFonts(len); - for (int i = 0; i < len; ++i) - mappedFonts[i] = 0; - nfo.mappedFonts = mappedFonts.data(); - - Q_ASSERT(sizeof(void *) <= sizeof(URefCon)); - e = ATSUSetTextLayoutRefCon(textLayout, (URefCon)&nfo); - if (e != noErr) { - qWarning("Qt: internal: %ld: Error ATSUSetTextLayoutRefCon %s: %d", long(e), __FILE__, __LINE__); - return false; - } - - { - const int maxAttributeCount = 3; - ATSUAttributeTag tags[maxAttributeCount + 1]; - ByteCount sizes[maxAttributeCount + 1]; - ATSUAttributeValuePtr values[maxAttributeCount + 1]; - int attributeCount = 0; - - tags[attributeCount] = kATSULineLayoutOptionsTag; - ATSLineLayoutOptions layopts = kATSLineHasNoOpticalAlignment - | kATSLineIgnoreFontLeading - | kATSLineNoSpecialJustification // we do kashidas ourselves - | kATSLineDisableAllJustification - ; - - if (fontDef.styleStrategy & QFont::NoAntialias) - layopts |= kATSLineNoAntiAliasing; - - if (!kerning) - layopts |= kATSLineDisableAllKerningAdjustments; - - values[attributeCount] = &layopts; - sizes[attributeCount] = sizeof(layopts); - ++attributeCount; - - tags[attributeCount] = kATSULayoutOperationOverrideTag; - ATSULayoutOperationOverrideSpecifier spec; - spec.operationSelector = kATSULayoutOperationPostLayoutAdjustment; - spec.overrideUPP = atsuPostLayoutCallback; - values[attributeCount] = &spec; - sizes[attributeCount] = sizeof(spec); - ++attributeCount; - - // CTWritingDirection - Boolean direction; - if (flags & QTextEngine::RightToLeft) - direction = kATSURightToLeftBaseDirection; - else - direction = kATSULeftToRightBaseDirection; - tags[attributeCount] = kATSULineDirectionTag; - values[attributeCount] = &direction; - sizes[attributeCount] = sizeof(direction); - ++attributeCount; - - Q_ASSERT(attributeCount < maxAttributeCount + 1); - e = ATSUSetLayoutControls(textLayout, attributeCount, tags, sizes, values); - if (e != noErr) { - qWarning("Qt: internal: %ld: Error ATSUSetLayoutControls %s: %d", long(e), __FILE__, __LINE__); - return false; - } - - } - - e = ATSUSetRunStyle(textLayout, style, 0, len); - if (e != noErr) { - qWarning("Qt: internal: %ld: Error ATSUSetRunStyle %s: %d", long(e), __FILE__, __LINE__); - return false; - } - - if (!(fontDef.styleStrategy & QFont::NoFontMerging)) { - int pos = 0; - do { - ATSUFontID substFont = 0; - UniCharArrayOffset changedOffset = 0; - UniCharCount changeCount = 0; - - e = ATSUMatchFontsToText(textLayout, pos, len - pos, - &substFont, &changedOffset, - &changeCount); - if (e == kATSUFontsMatched) { - int fontIdx = fontIndexForFontID(substFont); - for (uint i = 0; i < changeCount; ++i) - mappedFonts[changedOffset + i] = fontIdx; - pos = changedOffset + changeCount; - ATSUSetRunStyle(textLayout, engineAt(fontIdx)->style, changedOffset, changeCount); - } else if (e == kATSUFontsNotMatched) { - pos = changedOffset + changeCount; - } - } while (pos < len && e != noErr); - } - { // trigger the a layout - // CFAttributedStringCreate, CTFramesetterCreateWithAttributedString (or perhaps Typesetter) - Rect rect; - e = ATSUMeasureTextImage(textLayout, kATSUFromTextBeginning, kATSUToTextEnd, - /*iLocationX =*/ 0, /*iLocationY =*/ 0, - &rect); - if (e != noErr) { - qWarning("Qt: internal: %ld: Error ATSUMeasureTextImage %s: %d", long(e), __FILE__, __LINE__); - return false; - } - } - - if (!nfo.callbackCalled) { - qWarning("Qt: internal: %ld: Error ATSUMeasureTextImage did not trigger callback %s: %d", long(e), __FILE__, __LINE__); - return false; - } - - ATSUClearLayoutCache(textLayout, kATSUFromTextBeginning); - if (prevNumGlyphs < *nfo.numGlyphs) - return false; - return true; -} - -void QFontEngineMacMulti::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const -{ - Q_ASSERT(false); - Q_UNUSED(glyphs); - Q_UNUSED(flags); -} - -void QFontEngineMacMulti::doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const -{ - //Q_ASSERT(false); -} - -void QFontEngineMacMulti::loadEngine(int /*at*/) -{ - // should never be called! - Q_ASSERT(false); -} - -bool QFontEngineMacMulti::canRender(const QChar *string, int len) -{ - ATSUSetTextPointerLocation(textLayout, reinterpret_cast<const UniChar *>(string), 0, len, len); - ATSUSetRunStyle(textLayout, style, 0, len); - - OSStatus e = noErr; - int pos = 0; - do { - FMFont substFont = 0; - UniCharArrayOffset changedOffset = 0; - UniCharCount changeCount = 0; - - // CTFontCreateForString - e = ATSUMatchFontsToText(textLayout, pos, len - pos, - &substFont, &changedOffset, - &changeCount); - if (e == kATSUFontsMatched) { - pos = changedOffset + changeCount; - } else if (e == kATSUFontsNotMatched) { - break; - } - } while (pos < len && e != noErr); - - return e == noErr || e == kATSUFontsMatched; -} - -QFontEngineMac::QFontEngineMac(ATSUStyle baseStyle, ATSUFontID fontID, const QFontDef &def, QFontEngineMacMulti *multiEngine) - : fontID(fontID), multiEngine(multiEngine), cmap(0), symbolCMap(false) -{ - fontDef = def; - ATSUCreateAndCopyStyle(baseStyle, &style); - ATSFontRef atsFont = FMGetATSFontRefFromFont(fontID); - cgFont = CGFontCreateWithPlatformFont(&atsFont); - - const int maxAttributeCount = 4; - ATSUAttributeTag tags[maxAttributeCount + 1]; - ByteCount sizes[maxAttributeCount + 1]; - ATSUAttributeValuePtr values[maxAttributeCount + 1]; - int attributeCount = 0; - - synthesisFlags = 0; - - // synthesizing using CG is not recommended - quint16 macStyle = 0; - { - uchar data[4]; - ByteCount len = 4; - if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'e', 'a', 'd'), 44, 4, &data, &len) == noErr) - macStyle = qFromBigEndian<quint16>(data); - } - - Boolean atsuBold = false; - Boolean atsuItalic = false; - if (fontDef.weight >= QFont::Bold) { - if (!(macStyle & 1)) { - synthesisFlags |= SynthesizedBold; - atsuBold = true; - tags[attributeCount] = kATSUQDBoldfaceTag; - sizes[attributeCount] = sizeof(atsuBold); - values[attributeCount] = &atsuBold; - ++attributeCount; - } - } - if (fontDef.style != QFont::StyleNormal) { - if (!(macStyle & 2)) { - synthesisFlags |= SynthesizedItalic; - atsuItalic = true; - tags[attributeCount] = kATSUQDItalicTag; - sizes[attributeCount] = sizeof(atsuItalic); - values[attributeCount] = &atsuItalic; - ++attributeCount; - } - } - - tags[attributeCount] = kATSUFontTag; - values[attributeCount] = &fontID; - sizes[attributeCount] = sizeof(fontID); - ++attributeCount; - - Q_ASSERT(attributeCount < maxAttributeCount + 1); - OSStatus err = ATSUSetAttributes(style, attributeCount, tags, sizes, values); - Q_ASSERT(err == noErr); - Q_UNUSED(err); - - // CTFontCopyTable - quint16 tmpFsType; - if (ATSFontGetTable(atsFont, MAKE_TAG('O', 'S', '/', '2'), 8, 2, &tmpFsType, 0) == noErr) - fsType = qFromBigEndian<quint16>(tmpFsType); - else - fsType = 0; - - if (multiEngine) - transform = multiEngine->transform; - else - transform = CGAffineTransformIdentity; - - ATSUTextMeasurement metric; - - ATSUGetAttribute(style, kATSUAscentTag, sizeof(metric), &metric, 0); - m_ascent = FixRound(metric); - - ATSUGetAttribute(style, kATSUDescentTag, sizeof(metric), &metric, 0); - m_descent = FixRound(metric); - - ATSUGetAttribute(style, kATSULeadingTag, sizeof(metric), &metric, 0); - m_leading = FixRound(metric); - - ATSFontMetrics metrics; - - ATSFontGetHorizontalMetrics(FMGetATSFontRefFromFont(fontID), kATSOptionFlagsDefault, &metrics); - m_maxCharWidth = metrics.maxAdvanceWidth * fontDef.pointSize; - - ATSFontGetHorizontalMetrics(FMGetATSFontRefFromFont(fontID), kATSOptionFlagsDefault, &metrics); - m_xHeight = QFixed::fromReal(metrics.xHeight * fontDef.pointSize); - - ATSFontGetHorizontalMetrics(FMGetATSFontRefFromFont(fontID), kATSOptionFlagsDefault, &metrics); - m_averageCharWidth = QFixed::fromReal(metrics.avgAdvanceWidth * fontDef.pointSize); - - // Use width of 'X' if ATSFontGetHorizontalMetrics returns 0 for avgAdvanceWidth. - if (m_averageCharWidth == QFixed(0)) { - QChar c('X'); - QGlyphLayoutArray<1> glyphs; - int nglyphs = 1; - stringToCMap(&c, 1, &glyphs, &nglyphs, 0); - glyph_metrics_t metrics = boundingBox(glyphs); - m_averageCharWidth = metrics.width; - } -} - -QFontEngineMac::~QFontEngineMac() -{ - ATSUDisposeStyle(style); -} - -static inline unsigned int getChar(const QChar *str, int &i, const int len) -{ - unsigned int uc = str[i].unicode(); - if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { - uint low = str[i+1].unicode(); - if (low >= 0xdc00 && low < 0xe000) { - uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; - ++i; - } - } - return uc; -} - -// Not used directly for shaping, only used to calculate m_averageCharWidth -bool QFontEngineMac::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - if (!cmap) { - cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); - int size = 0; - cmap = getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()), cmapTable.size(), &symbolCMap, &size); - if (!cmap) - return false; - } - if (symbolCMap) { - for (int i = 0; i < len; ++i) { - unsigned int uc = getChar(str, i, len); - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc); - if(!glyphs->glyphs[i] && uc < 0x100) - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); - } - } else { - for (int i = 0; i < len; ++i) { - unsigned int uc = getChar(str, i, len); - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc); - } - } - - *nglyphs = len; - glyphs->numGlyphs = *nglyphs; - - if (!(flags & QTextEngine::GlyphIndicesOnly)) - recalcAdvances(glyphs, flags); - - return true; -} - -void QFontEngineMac::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const -{ - Q_UNUSED(flags) - - QVarLengthArray<GlyphID> atsuGlyphs(glyphs->numGlyphs); - for (int i = 0; i < glyphs->numGlyphs; ++i) - atsuGlyphs[i] = glyphs->glyphs[i]; - - QVarLengthArray<ATSGlyphScreenMetrics> metrics(glyphs->numGlyphs); - - ATSUGlyphGetScreenMetrics(style, glyphs->numGlyphs, atsuGlyphs.data(), sizeof(GlyphID), - /* iForcingAntiAlias =*/ false, - /* iAntiAliasSwitch =*/true, - metrics.data()); - - for (int i = 0; i < glyphs->numGlyphs; ++i) { - glyphs->advances_x[i] = QFixed::fromReal(metrics[i].deviceAdvance.x); - glyphs->advances_y[i] = QFixed::fromReal(metrics[i].deviceAdvance.y); - - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - glyphs->advances_x[i] = glyphs->advances_x[i].round(); - glyphs->advances_y[i] = glyphs->advances_y[i].round(); - } - } -} - -glyph_metrics_t QFontEngineMac::boundingBox(const QGlyphLayout &glyphs) -{ - QFixed w; - bool round = fontDef.styleStrategy & QFont::ForceIntegerMetrics; - for (int i = 0; i < glyphs.numGlyphs; ++i) { - w += round ? glyphs.effectiveAdvance(i).round() - : glyphs.effectiveAdvance(i); - } - return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs, round), ascent()+descent(), w, 0); -} - -glyph_metrics_t QFontEngineMac::boundingBox(glyph_t glyph) -{ - GlyphID atsuGlyph = glyph; - - ATSGlyphScreenMetrics metrics; - - ATSUGlyphGetScreenMetrics(style, 1, &atsuGlyph, 0, - /* iForcingAntiAlias =*/ false, - /* iAntiAliasSwitch =*/true, - &metrics); - - // ### check again - - glyph_metrics_t gm; - gm.width = int(metrics.width); - gm.height = int(metrics.height); - gm.x = QFixed::fromReal(metrics.topLeft.x); - gm.y = -QFixed::fromReal(metrics.topLeft.y); - gm.xoff = QFixed::fromReal(metrics.deviceAdvance.x); - gm.yoff = QFixed::fromReal(metrics.deviceAdvance.y); - - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - gm.x = gm.x.floor(); - gm.y = gm.y.floor(); - gm.xoff = gm.xoff.round(); - gm.yoff = gm.yoff.round(); - } - - return gm; -} - -QFixed QFontEngineMac::ascent() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_ascent.round() - : m_ascent; -} - -QFixed QFontEngineMac::descent() const -{ - // subtract a pixel to even out the historical +1 in QFontMetrics::height(). - // Fix in Qt 5. - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_descent.round() - 1 - : m_descent; -} - -QFixed QFontEngineMac::leading() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_leading.round() - : m_leading; -} - -qreal QFontEngineMac::maxCharWidth() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(m_maxCharWidth) - : m_maxCharWidth; -} - -QFixed QFontEngineMac::xHeight() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_xHeight.round() - : m_xHeight; -} - -QFixed QFontEngineMac::averageCharWidth() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_averageCharWidth.round() - : m_averageCharWidth; -} - -static void addGlyphsToPathHelper(ATSUStyle style, glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path) -{ - if (!numGlyphs) - return; - - OSStatus e; - - QMacFontPath fontpath(0, 0, path); - ATSCubicMoveToUPP moveTo = NewATSCubicMoveToUPP(QMacFontPath::moveTo); - ATSCubicLineToUPP lineTo = NewATSCubicLineToUPP(QMacFontPath::lineTo); - ATSCubicCurveToUPP cubicTo = NewATSCubicCurveToUPP(QMacFontPath::cubicTo); - ATSCubicClosePathUPP closePath = NewATSCubicClosePathUPP(QMacFontPath::closePath); - - // CTFontCreatePathForGlyph - for (int i = 0; i < numGlyphs; ++i) { - GlyphID glyph = glyphs[i]; - - fontpath.setPosition(positions[i].x.toReal(), positions[i].y.toReal()); - ATSUGlyphGetCubicPaths(style, glyph, moveTo, lineTo, - cubicTo, closePath, &fontpath, &e); - } - - DisposeATSCubicMoveToUPP(moveTo); - DisposeATSCubicLineToUPP(lineTo); - DisposeATSCubicCurveToUPP(cubicTo); - DisposeATSCubicClosePathUPP(closePath); -} - -void QFontEngineMac::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, - QTextItem::RenderFlags) -{ - addGlyphsToPathHelper(style, glyphs, positions, numGlyphs, path); -} - - -/*! - Helper function for alphaMapForGlyph and alphaRGBMapForGlyph. The two are identical, except for - the subpixel antialiasing... -*/ -QImage QFontEngineMac::imageForGlyph(glyph_t glyph, int margin, bool colorful) -{ - const glyph_metrics_t br = boundingBox(glyph); - QImage im(qRound(br.width)+2, qRound(br.height)+4, QImage::Format_RGB32); - im.fill(0xff000000); - - CGColorSpaceRef colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace(); - uint cgflags = kCGImageAlphaNoneSkipFirst; -#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - cgflags |= kCGBitmapByteOrder32Host; -#endif - CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(), - 8, im.bytesPerLine(), colorspace, - cgflags); - CGContextSetFontSize(ctx, fontDef.pixelSize); - CGContextSetShouldAntialias(ctx, fontDef.pointSize > qt_antialiasing_threshold && !(fontDef.styleStrategy & QFont::NoAntialias)); - // turn off sub-pixel hinting - no support for that in OpenGL - CGContextSetShouldSmoothFonts(ctx, colorful); - CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx); - CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, 1, 0, 0); - CGAffineTransformConcat(cgMatrix, oldTextMatrix); - - if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, tanf(14 * acosf(0) / 90), 1, 0, 0)); - - cgMatrix = CGAffineTransformConcat(cgMatrix, transform); - - CGContextSetTextMatrix(ctx, cgMatrix); - CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); - CGContextSetTextDrawingMode(ctx, kCGTextFill); - CGContextSetFont(ctx, cgFont); - - qreal pos_x = -br.x.toReal() + 1; - qreal pos_y = im.height() + br.y.toReal() - 2; - CGContextSetTextPosition(ctx, pos_x, pos_y); - - CGSize advance; - advance.width = 0; - advance.height = 0; - CGGlyph cgGlyph = glyph; - CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); - - if (synthesisFlags & QFontEngine::SynthesizedBold) { - CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y); - CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); - } - - CGContextRelease(ctx); - - return im; -} - -QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph) -{ - QImage im = imageForGlyph(glyph, 2, false); - - QImage indexed(im.width(), im.height(), QImage::Format_Indexed8); - QVector<QRgb> colors(256); - for (int i=0; i<256; ++i) - colors[i] = qRgba(0, 0, 0, i); - indexed.setColorTable(colors); - - for (int y=0; y<im.height(); ++y) { - uint *src = (uint*) im.scanLine(y); - uchar *dst = indexed.scanLine(y); - for (int x=0; x<im.width(); ++x) { - *dst = qGray(*src); - ++dst; - ++src; - } - } - - return indexed; -} - -QImage QFontEngineMac::alphaRGBMapForGlyph(glyph_t glyph, QFixed, int margin, const QTransform &t) -{ - QImage im = imageForGlyph(glyph, margin, true); - - if (t.type() >= QTransform::TxScale) { - im = im.transformed(t); - } - - qGamma_correct_back_to_linear_cs(&im); - - return im; -} - - -bool QFontEngineMac::canRender(const QChar *string, int len) -{ - Q_ASSERT(false); - Q_UNUSED(string); - Q_UNUSED(len); - return false; -} - -void QFontEngineMac::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight) -{ - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> glyphs; - QTransform matrix; - matrix.translate(x, y); - getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - if (glyphs.size() == 0) - return; - - CGContextSetFontSize(ctx, fontDef.pixelSize); - - CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx); - - CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight); - - CGAffineTransformConcat(cgMatrix, oldTextMatrix); - - if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0)); - - cgMatrix = CGAffineTransformConcat(cgMatrix, transform); - - CGContextSetTextMatrix(ctx, cgMatrix); - - CGContextSetTextDrawingMode(ctx, kCGTextFill); - - - QVarLengthArray<CGSize> advances(glyphs.size()); - QVarLengthArray<CGGlyph> cgGlyphs(glyphs.size()); - - for (int i = 0; i < glyphs.size() - 1; ++i) { - advances[i].width = (positions[i + 1].x - positions[i].x).toReal(); - advances[i].height = (positions[i + 1].y - positions[i].y).toReal(); - cgGlyphs[i] = glyphs[i]; - } - advances[glyphs.size() - 1].width = 0; - advances[glyphs.size() - 1].height = 0; - cgGlyphs[glyphs.size() - 1] = glyphs[glyphs.size() - 1]; - - CGContextSetFont(ctx, cgFont); - - CGContextSetTextPosition(ctx, positions[0].x.toReal(), positions[0].y.toReal()); - - CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size()); - - if (synthesisFlags & QFontEngine::SynthesizedBold) { - CGContextSetTextPosition(ctx, positions[0].x.toReal() + 0.5 * lineThickness().toReal(), - positions[0].y.toReal()); - - CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size()); - } - - CGContextSetTextMatrix(ctx, oldTextMatrix); -} - -QFontEngine::FaceId QFontEngineMac::faceId() const -{ - FaceId ret; -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) -if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - // CTFontGetPlatformFont - FSRef ref; - if (ATSFontGetFileReference(FMGetATSFontRefFromFont(fontID), &ref) != noErr) - return ret; - ret.filename = QByteArray(128, 0); - ret.index = fontID; - FSRefMakePath(&ref, (UInt8 *)ret.filename.data(), ret.filename.size()); -}else -#endif -{ - FSSpec spec; - if (ATSFontGetFileSpecification(FMGetATSFontRefFromFont(fontID), &spec) != noErr) - return ret; - - FSRef ref; - FSpMakeFSRef(&spec, &ref); - ret.filename = QByteArray(128, 0); - ret.index = fontID; - FSRefMakePath(&ref, (UInt8 *)ret.filename.data(), ret.filename.size()); -} - return ret; -} - -QByteArray QFontEngineMac::getSfntTable(uint tag) const -{ - ATSFontRef atsFont = FMGetATSFontRefFromFont(fontID); - - ByteCount length; - OSStatus status = ATSFontGetTable(atsFont, tag, 0, 0, 0, &length); - if (status != noErr) - return QByteArray(); - QByteArray table(length, 0); - // CTFontCopyTable - status = ATSFontGetTable(atsFont, tag, 0, table.length(), table.data(), &length); - if (status != noErr) - return QByteArray(); - return table; -} - -QFontEngine::Properties QFontEngineMac::properties() const -{ - QFontEngine::Properties props; - ATSFontRef atsFont = FMGetATSFontRefFromFont(fontID); - quint16 tmp; - // CTFontGetUnitsPerEm - if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'e', 'a', 'd'), 18, 2, &tmp, 0) == noErr) - props.emSquare = qFromBigEndian<quint16>(tmp); - struct { - qint16 xMin; - qint16 yMin; - qint16 xMax; - qint16 yMax; - } bbox; - bbox.xMin = bbox.xMax = bbox.yMin = bbox.yMax = 0; - // CTFontGetBoundingBox - if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'e', 'a', 'd'), 36, 8, &bbox, 0) == noErr) { - bbox.xMin = qFromBigEndian<quint16>(bbox.xMin); - bbox.yMin = qFromBigEndian<quint16>(bbox.yMin); - bbox.xMax = qFromBigEndian<quint16>(bbox.xMax); - bbox.yMax = qFromBigEndian<quint16>(bbox.yMax); - } - struct { - qint16 ascender; - qint16 descender; - qint16 linegap; - } metrics; - metrics.ascender = metrics.descender = metrics.linegap = 0; - // CTFontGetAscent, etc. - if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'h', 'e', 'a'), 4, 6, &metrics, 0) == noErr) { - metrics.ascender = qFromBigEndian<quint16>(metrics.ascender); - metrics.descender = qFromBigEndian<quint16>(metrics.descender); - metrics.linegap = qFromBigEndian<quint16>(metrics.linegap); - } - props.ascent = metrics.ascender; - props.descent = -metrics.descender; - props.leading = metrics.linegap; - props.boundingBox = QRectF(bbox.xMin, -bbox.yMax, - bbox.xMax - bbox.xMin, - bbox.yMax - bbox.yMin); - props.italicAngle = 0; - props.capHeight = props.ascent; - - qint16 lw = 0; - // fonts lie - if (ATSFontGetTable(atsFont, MAKE_TAG('p', 'o', 's', 't'), 10, 2, &lw, 0) == noErr) - lw = qFromBigEndian<quint16>(lw); - props.lineWidth = lw; - - // CTFontCopyPostScriptName - QCFString psName; - if (ATSFontGetPostScriptName(FMGetATSFontRefFromFont(fontID), kATSOptionFlagsDefault, &psName) == noErr) - props.postscriptName = QString(psName).toUtf8(); - props.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(props.postscriptName); - return props; -} - -void QFontEngineMac::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) -{ - ATSUStyle unscaledStyle; - ATSUCreateAndCopyStyle(style, &unscaledStyle); - - int emSquare = properties().emSquare.toInt(); - - const int maxAttributeCount = 4; - ATSUAttributeTag tags[maxAttributeCount + 1]; - ByteCount sizes[maxAttributeCount + 1]; - ATSUAttributeValuePtr values[maxAttributeCount + 1]; - int attributeCount = 0; - - Fixed size = FixRatio(emSquare, 1); - tags[attributeCount] = kATSUSizeTag; - sizes[attributeCount] = sizeof(size); - values[attributeCount] = &size; - ++attributeCount; - - Q_ASSERT(attributeCount < maxAttributeCount + 1); - OSStatus err = ATSUSetAttributes(unscaledStyle, attributeCount, tags, sizes, values); - Q_ASSERT(err == noErr); - Q_UNUSED(err); - - // various CTFont metrics functions: CTFontGetBoundingRectsForGlyphs, CTFontGetAdvancesForGlyphs - GlyphID atsuGlyph = glyph; - ATSGlyphScreenMetrics atsuMetrics; - ATSUGlyphGetScreenMetrics(unscaledStyle, 1, &atsuGlyph, 0, - /* iForcingAntiAlias =*/ false, - /* iAntiAliasSwitch =*/true, - &atsuMetrics); - - metrics->width = int(atsuMetrics.width); - metrics->height = int(atsuMetrics.height); - metrics->x = QFixed::fromReal(atsuMetrics.topLeft.x); - metrics->y = -QFixed::fromReal(atsuMetrics.topLeft.y); - metrics->xoff = QFixed::fromReal(atsuMetrics.deviceAdvance.x); - metrics->yoff = QFixed::fromReal(atsuMetrics.deviceAdvance.y); - - QFixedPoint p; - addGlyphsToPathHelper(unscaledStyle, &glyph, &p, 1, path); - - ATSUDisposeStyle(unscaledStyle); -} -#endif // !QT_MAC_USE_COCOA - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qfontengine_mac_p.h b/src/gui/platforms/mac/qfontengine_mac_p.h deleted file mode 100644 index 292ea98d9a..0000000000 --- a/src/gui/platforms/mac/qfontengine_mac_p.h +++ /dev/null @@ -1,165 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QFONTENGINE_MAC_P_H -#define QFONTENGINE_MAC_P_H - -#include <private/qfontengine_p.h> - -#ifndef QT_MAC_USE_COCOA -class QFontEngineMacMulti; -class QFontEngineMac : public QFontEngine -{ - friend class QFontEngineMacMulti; -public: - QFontEngineMac(ATSUStyle baseStyle, ATSUFontID fontID, const QFontDef &def, QFontEngineMacMulti *multiEngine = 0); - virtual ~QFontEngineMac(); - - virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *numGlyphs, QTextEngine::ShaperFlags flags) const; - virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; - - virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); - virtual glyph_metrics_t boundingBox(glyph_t glyph); - - virtual QFixed ascent() const; - virtual QFixed descent() const; - virtual QFixed leading() const; - virtual QFixed xHeight() const; - virtual qreal maxCharWidth() const; - virtual QFixed averageCharWidth() const; - - virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, - QPainterPath *path, QTextItem::RenderFlags); - - virtual const char *name() const { return "QFontEngineMac"; } - - virtual bool canRender(const QChar *string, int len); - - virtual int synthesized() const { return synthesisFlags; } - - virtual Type type() const { return QFontEngine::Mac; } - - void draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight); - - virtual FaceId faceId() const; - virtual QByteArray getSfntTable(uint tag) const; - virtual Properties properties() const; - virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); - virtual QImage alphaMapForGlyph(glyph_t); - virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); - -private: - QImage imageForGlyph(glyph_t glyph, int margin, bool colorful); - - ATSUFontID fontID; - QCFType<CGFontRef> cgFont; - ATSUStyle style; - int synthesisFlags; - mutable QGlyphLayout kashidaGlyph; - QFontEngineMacMulti *multiEngine; - mutable const unsigned char *cmap; - mutable bool symbolCMap; - mutable QByteArray cmapTable; - CGAffineTransform transform; - QFixed m_ascent; - QFixed m_descent; - QFixed m_leading; - qreal m_maxCharWidth; - QFixed m_xHeight; - QFixed m_averageCharWidth; -}; - -class QFontEngineMacMulti : public QFontEngineMulti -{ - friend class QFontEngineMac; -public: - // internal - struct ShaperItem - { - inline ShaperItem() : string(0), from(0), length(0), - log_clusters(0), charAttributes(0) {} - - const QChar *string; - int from; - int length; - QGlyphLayout glyphs; - unsigned short *log_clusters; - const HB_CharAttributes *charAttributes; - QTextEngine::ShaperFlags flags; - }; - - QFontEngineMacMulti(const ATSFontFamilyRef &atsFamily, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning); - virtual ~QFontEngineMacMulti(); - - virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; - bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags, - unsigned short *logClusters, const HB_CharAttributes *charAttributes, QScriptItem *) const; - - virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; - virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const; - - virtual const char *name() const { return "ATSUI"; } - - virtual bool canRender(const QChar *string, int len); - - inline ATSUFontID macFontID() const { return fontID; } - -protected: - virtual void loadEngine(int at); - -private: - inline const QFontEngineMac *engineAt(int i) const - { return static_cast<const QFontEngineMac *>(engines.at(i)); } - - bool stringToCMapInternal(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags, ShaperItem *item) const; - - int fontIndexForFontID(ATSUFontID id) const; - - ATSUFontID fontID; - uint kerning : 1; - - mutable ATSUTextLayout textLayout; - mutable ATSUStyle style; - CGAffineTransform transform; -}; -#endif //!QT_MAC_USE_COCOA - -#endif // QFONTENGINE_MAC_P_H diff --git a/src/gui/platforms/mac/qkeymapper_mac.cpp b/src/gui/platforms/mac/qkeymapper_mac.cpp deleted file mode 100644 index d3bbf89711..0000000000 --- a/src/gui/platforms/mac/qkeymapper_mac.cpp +++ /dev/null @@ -1,1023 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qt_mac_p.h> -#include <qdebug.h> -#include <qevent.h> -#include <private/qevent_p.h> -#include <qtextcodec.h> -#include <qapplication.h> -#include <qinputcontext.h> -#include <private/qkeymapper_p.h> -#include <private/qapplication_p.h> -#include <private/qmacinputcontext_p.h> - -QT_BEGIN_NAMESPACE - -QT_USE_NAMESPACE - -/***************************************************************************** - QKeyMapper debug facilities - *****************************************************************************/ -//#define DEBUG_KEY_BINDINGS -//#define DEBUG_KEY_BINDINGS_MODIFIERS -//#define DEBUG_KEY_MAPS - -/***************************************************************************** - Internal variables and functions - *****************************************************************************/ -bool qt_mac_eat_unicode_key = false; -extern bool qt_sendSpontaneousEvent(QObject *obj, QEvent *event); //qapplication_mac.cpp - -Q_GUI_EXPORT void qt_mac_secure_keyboard(bool b) -{ - static bool secure = false; - if (b != secure){ - b ? EnableSecureEventInput() : DisableSecureEventInput(); - secure = b; - } -} - -/* - \internal - A Mac KeyboardLayoutItem has 8 possible states: - 1. Unmodified - 2. Shift - 3. Control - 4. Control + Shift - 5. Alt - 6. Alt + Shift - 7. Alt + Control - 8. Alt + Control + Shift - 9. Meta - 10. Meta + Shift - 11. Meta + Control - 12. Meta + Control + Shift - 13. Meta + Alt - 14. Meta + Alt + Shift - 15. Meta + Alt + Control - 16. Meta + Alt + Control + Shift -*/ -struct KeyboardLayoutItem { - bool dirty; - quint32 qtKey[16]; // Can by any Qt::Key_<foo>, or unicode character -}; - -// Possible modifier states. -// NOTE: The order of these states match the order in QKeyMapperPrivate::updatePossibleKeyCodes()! -static const Qt::KeyboardModifiers ModsTbl[] = { - Qt::NoModifier, // 0 - Qt::ShiftModifier, // 1 - Qt::ControlModifier, // 2 - Qt::ControlModifier | Qt::ShiftModifier, // 3 - Qt::AltModifier, // 4 - Qt::AltModifier | Qt::ShiftModifier, // 5 - Qt::AltModifier | Qt::ControlModifier, // 6 - Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7 - Qt::MetaModifier, // 8 - Qt::MetaModifier | Qt::ShiftModifier, // 9 - Qt::MetaModifier | Qt::ControlModifier, // 10 - Qt::MetaModifier | Qt::ControlModifier | Qt::ShiftModifier,// 11 - Qt::MetaModifier | Qt::AltModifier, // 12 - Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier, // 13 - Qt::MetaModifier | Qt::AltModifier | Qt::ControlModifier, // 14 - Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 15 -}; - -/* key maps */ -struct qt_mac_enum_mapper -{ - int mac_code; - int qt_code; -#if defined(DEBUG_KEY_BINDINGS) -# define QT_MAC_MAP_ENUM(x) x, #x - const char *desc; -#else -# define QT_MAC_MAP_ENUM(x) x -#endif -}; - -//modifiers -static qt_mac_enum_mapper qt_mac_modifier_symbols[] = { - { shiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) }, - { rightShiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) }, - { controlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) }, - { rightControlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) }, - { cmdKey, QT_MAC_MAP_ENUM(Qt::ControlModifier) }, - { optionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) }, - { rightOptionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) }, - { kEventKeyModifierNumLockMask, QT_MAC_MAP_ENUM(Qt::KeypadModifier) }, - { 0, QT_MAC_MAP_ENUM(0) } -}; -Qt::KeyboardModifiers qt_mac_get_modifiers(int keys) -{ -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", keys, keys); -#endif - Qt::KeyboardModifiers ret = Qt::NoModifier; - for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) { - if (keys & qt_mac_modifier_symbols[i].mac_code) { -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc); -#endif - ret |= Qt::KeyboardModifier(qt_mac_modifier_symbols[i].qt_code); - } - } - if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { - Qt::KeyboardModifiers oldModifiers = ret; - ret &= ~(Qt::MetaModifier | Qt::ControlModifier); - if (oldModifiers & Qt::ControlModifier) - ret |= Qt::MetaModifier; - if (oldModifiers & Qt::MetaModifier) - ret |= Qt::ControlModifier; - } - return ret; -} -static int qt_mac_get_mac_modifiers(Qt::KeyboardModifiers keys) -{ -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", (int)keys, (int)keys); -#endif - int ret = 0; - for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) { - if (keys & qt_mac_modifier_symbols[i].qt_code) { -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc); -#endif - ret |= qt_mac_modifier_symbols[i].mac_code; - } - } - - if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { - int oldModifiers = ret; - ret &= ~(controlKeyBit | cmdKeyBit); - if (oldModifiers & controlKeyBit) - ret |= cmdKeyBit; - if (oldModifiers & cmdKeyBit) - ret |= controlKeyBit; - } - return ret; -} -void qt_mac_send_modifiers_changed(quint32 modifiers, QObject *object) -{ - static quint32 cachedModifiers = 0; - quint32 lastModifiers = cachedModifiers, - changedModifiers = lastModifiers ^ modifiers; - cachedModifiers = modifiers; - - //check the bits - static qt_mac_enum_mapper modifier_key_symbols[] = { - { shiftKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Shift) }, - { rightShiftKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Shift) }, //??? - { controlKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Meta) }, - { rightControlKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Meta) }, //??? - { cmdKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Control) }, - { optionKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Alt) }, - { rightOptionKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Alt) }, //??? - { alphaLockBit, QT_MAC_MAP_ENUM(Qt::Key_CapsLock) }, - { kEventKeyModifierNumLockBit, QT_MAC_MAP_ENUM(Qt::Key_NumLock) }, - { 0, QT_MAC_MAP_ENUM(0) } }; - for (int i = 0; i <= 32; i++) { //just check each bit - if (!(changedModifiers & (1 << i))) - continue; - QEvent::Type etype = QEvent::KeyPress; - if (lastModifiers & (1 << i)) - etype = QEvent::KeyRelease; - int key = 0; - for (uint x = 0; modifier_key_symbols[x].mac_code; x++) { - if (modifier_key_symbols[x].mac_code == i) { -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("got modifier changed: %s", modifier_key_symbols[x].desc); -#endif - key = modifier_key_symbols[x].qt_code; - break; - } - } - if (!key) { -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("could not get modifier changed: %d", i); -#endif - continue; - } -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("KeyEvent (modif): Sending %s to %s::%s: %d - 0x%08x", - etype == QEvent::KeyRelease ? "KeyRelease" : "KeyPress", - object ? object->metaObject()->className() : "none", - object ? object->objectName().toLatin1().constData() : "", - key, (int)modifiers); -#endif - QKeyEvent ke(etype, key, qt_mac_get_modifiers(modifiers ^ (1 << i)), QLatin1String("")); - qt_sendSpontaneousEvent(object, &ke); - } -} - -//keyboard keys (non-modifiers) -static qt_mac_enum_mapper qt_mac_keyboard_symbols[] = { - { kHomeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Home) }, - { kEnterCharCode, QT_MAC_MAP_ENUM(Qt::Key_Enter) }, - { kEndCharCode, QT_MAC_MAP_ENUM(Qt::Key_End) }, - { kBackspaceCharCode, QT_MAC_MAP_ENUM(Qt::Key_Backspace) }, - { kTabCharCode, QT_MAC_MAP_ENUM(Qt::Key_Tab) }, - { kPageUpCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageUp) }, - { kPageDownCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageDown) }, - { kReturnCharCode, QT_MAC_MAP_ENUM(Qt::Key_Return) }, - { kEscapeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Escape) }, - { kLeftArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Left) }, - { kRightArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Right) }, - { kUpArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Up) }, - { kDownArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Down) }, - { kHelpCharCode, QT_MAC_MAP_ENUM(Qt::Key_Help) }, - { kDeleteCharCode, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, -//ascii maps, for debug - { ':', QT_MAC_MAP_ENUM(Qt::Key_Colon) }, - { ';', QT_MAC_MAP_ENUM(Qt::Key_Semicolon) }, - { '<', QT_MAC_MAP_ENUM(Qt::Key_Less) }, - { '=', QT_MAC_MAP_ENUM(Qt::Key_Equal) }, - { '>', QT_MAC_MAP_ENUM(Qt::Key_Greater) }, - { '?', QT_MAC_MAP_ENUM(Qt::Key_Question) }, - { '@', QT_MAC_MAP_ENUM(Qt::Key_At) }, - { ' ', QT_MAC_MAP_ENUM(Qt::Key_Space) }, - { '!', QT_MAC_MAP_ENUM(Qt::Key_Exclam) }, - { '"', QT_MAC_MAP_ENUM(Qt::Key_QuoteDbl) }, - { '#', QT_MAC_MAP_ENUM(Qt::Key_NumberSign) }, - { '$', QT_MAC_MAP_ENUM(Qt::Key_Dollar) }, - { '%', QT_MAC_MAP_ENUM(Qt::Key_Percent) }, - { '&', QT_MAC_MAP_ENUM(Qt::Key_Ampersand) }, - { '\'', QT_MAC_MAP_ENUM(Qt::Key_Apostrophe) }, - { '(', QT_MAC_MAP_ENUM(Qt::Key_ParenLeft) }, - { ')', QT_MAC_MAP_ENUM(Qt::Key_ParenRight) }, - { '*', QT_MAC_MAP_ENUM(Qt::Key_Asterisk) }, - { '+', QT_MAC_MAP_ENUM(Qt::Key_Plus) }, - { ',', QT_MAC_MAP_ENUM(Qt::Key_Comma) }, - { '-', QT_MAC_MAP_ENUM(Qt::Key_Minus) }, - { '.', QT_MAC_MAP_ENUM(Qt::Key_Period) }, - { '/', QT_MAC_MAP_ENUM(Qt::Key_Slash) }, - { '[', QT_MAC_MAP_ENUM(Qt::Key_BracketLeft) }, - { ']', QT_MAC_MAP_ENUM(Qt::Key_BracketRight) }, - { '\\', QT_MAC_MAP_ENUM(Qt::Key_Backslash) }, - { '_', QT_MAC_MAP_ENUM(Qt::Key_Underscore) }, - { '`', QT_MAC_MAP_ENUM(Qt::Key_QuoteLeft) }, - { '{', QT_MAC_MAP_ENUM(Qt::Key_BraceLeft) }, - { '}', QT_MAC_MAP_ENUM(Qt::Key_BraceRight) }, - { '|', QT_MAC_MAP_ENUM(Qt::Key_Bar) }, - { '~', QT_MAC_MAP_ENUM(Qt::Key_AsciiTilde) }, - { '^', QT_MAC_MAP_ENUM(Qt::Key_AsciiCircum) }, - { 0, QT_MAC_MAP_ENUM(0) } -}; - -static qt_mac_enum_mapper qt_mac_keyvkey_symbols[] = { //real scan codes - { 122, QT_MAC_MAP_ENUM(Qt::Key_F1) }, - { 120, QT_MAC_MAP_ENUM(Qt::Key_F2) }, - { 99, QT_MAC_MAP_ENUM(Qt::Key_F3) }, - { 118, QT_MAC_MAP_ENUM(Qt::Key_F4) }, - { 96, QT_MAC_MAP_ENUM(Qt::Key_F5) }, - { 97, QT_MAC_MAP_ENUM(Qt::Key_F6) }, - { 98, QT_MAC_MAP_ENUM(Qt::Key_F7) }, - { 100, QT_MAC_MAP_ENUM(Qt::Key_F8) }, - { 101, QT_MAC_MAP_ENUM(Qt::Key_F9) }, - { 109, QT_MAC_MAP_ENUM(Qt::Key_F10) }, - { 103, QT_MAC_MAP_ENUM(Qt::Key_F11) }, - { 111, QT_MAC_MAP_ENUM(Qt::Key_F12) }, - { 105, QT_MAC_MAP_ENUM(Qt::Key_F13) }, - { 107, QT_MAC_MAP_ENUM(Qt::Key_F14) }, - { 113, QT_MAC_MAP_ENUM(Qt::Key_F15) }, - { 106, QT_MAC_MAP_ENUM(Qt::Key_F16) }, - { 0, QT_MAC_MAP_ENUM(0) } -}; - -static qt_mac_enum_mapper qt_mac_private_unicode[] = { - { 0xF700, QT_MAC_MAP_ENUM(Qt::Key_Up) }, //NSUpArrowFunctionKey - { 0xF701, QT_MAC_MAP_ENUM(Qt::Key_Down) }, //NSDownArrowFunctionKey - { 0xF702, QT_MAC_MAP_ENUM(Qt::Key_Left) }, //NSLeftArrowFunctionKey - { 0xF703, QT_MAC_MAP_ENUM(Qt::Key_Right) }, //NSRightArrowFunctionKey - { 0xF727, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertFunctionKey - { 0xF728, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteFunctionKey - { 0xF729, QT_MAC_MAP_ENUM(Qt::Key_Home) }, //NSHomeFunctionKey - { 0xF72B, QT_MAC_MAP_ENUM(Qt::Key_End) }, //NSEndFunctionKey - { 0xF72C, QT_MAC_MAP_ENUM(Qt::Key_PageUp) }, //NSPageUpFunctionKey - { 0xF72D, QT_MAC_MAP_ENUM(Qt::Key_PageDown) }, //NSPageDownFunctionKey - { 0xF72F, QT_MAC_MAP_ENUM(Qt::Key_ScrollLock) }, //NSScrollLockFunctionKey - { 0xF730, QT_MAC_MAP_ENUM(Qt::Key_Pause) }, //NSPauseFunctionKey - { 0xF731, QT_MAC_MAP_ENUM(Qt::Key_SysReq) }, //NSSysReqFunctionKey - { 0xF735, QT_MAC_MAP_ENUM(Qt::Key_Menu) }, //NSMenuFunctionKey - { 0xF738, QT_MAC_MAP_ENUM(Qt::Key_Print) }, //NSPrintFunctionKey - { 0xF73A, QT_MAC_MAP_ENUM(Qt::Key_Clear) }, //NSClearDisplayFunctionKey - { 0xF73D, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertCharFunctionKey - { 0xF73E, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteCharFunctionKey - { 0xF741, QT_MAC_MAP_ENUM(Qt::Key_Select) }, //NSSelectFunctionKey - { 0xF742, QT_MAC_MAP_ENUM(Qt::Key_Execute) }, //NSExecuteFunctionKey - { 0xF746, QT_MAC_MAP_ENUM(Qt::Key_Help) }, //NSHelpFunctionKey - { 0xF747, QT_MAC_MAP_ENUM(Qt::Key_Mode_switch) }, //NSModeSwitchFunctionKey - { 0, QT_MAC_MAP_ENUM(0) } -}; - -static int qt_mac_get_key(int modif, const QChar &key, int virtualKey) -{ -#ifdef DEBUG_KEY_BINDINGS - qDebug("**Mapping key: %d (0x%04x) - %d (0x%04x)", key.unicode(), key.unicode(), virtualKey, virtualKey); -#endif - - if (key == kClearCharCode && virtualKey == 0x47) - return Qt::Key_Clear; - - if (key.isDigit()) { -#ifdef DEBUG_KEY_BINDINGS - qDebug("%d: got key: %d", __LINE__, key.digitValue()); -#endif - return key.digitValue() + Qt::Key_0; - } - - if (key.isLetter()) { -#ifdef DEBUG_KEY_BINDINGS - qDebug("%d: got key: %d", __LINE__, (key.toUpper().unicode() - 'A')); -#endif - return (key.toUpper().unicode() - 'A') + Qt::Key_A; - } - if (key.isSymbol()) { -#ifdef DEBUG_KEY_BINDINGS - qDebug("%d: got key: %d", __LINE__, (key.unicode())); -#endif - return key.unicode(); - } - - for (int i = 0; qt_mac_keyboard_symbols[i].qt_code; i++) { - if (qt_mac_keyboard_symbols[i].mac_code == key) { - /* To work like Qt for X11 we issue Backtab when Shift + Tab are pressed */ - if (qt_mac_keyboard_symbols[i].qt_code == Qt::Key_Tab && (modif & Qt::ShiftModifier)) { -#ifdef DEBUG_KEY_BINDINGS - qDebug("%d: got key: Qt::Key_Backtab", __LINE__); -#endif - return Qt::Key_Backtab; - } - -#ifdef DEBUG_KEY_BINDINGS - qDebug("%d: got key: %s", __LINE__, qt_mac_keyboard_symbols[i].desc); -#endif - return qt_mac_keyboard_symbols[i].qt_code; - } - } - - //last ditch try to match the scan code - for (int i = 0; qt_mac_keyvkey_symbols[i].qt_code; i++) { - if (qt_mac_keyvkey_symbols[i].mac_code == virtualKey) { -#ifdef DEBUG_KEY_BINDINGS - qDebug("%d: got key: %s", __LINE__, qt_mac_keyvkey_symbols[i].desc); -#endif - return qt_mac_keyvkey_symbols[i].qt_code; - } - } - - // check if they belong to key codes in private unicode range - if (key >= 0xf700 && key <= 0xf747) { - if (key >= 0xf704 && key <= 0xf726) { - return Qt::Key_F1 + (key.unicode() - 0xf704) ; - } - for (int i = 0; qt_mac_private_unicode[i].qt_code; i++) { - if (qt_mac_private_unicode[i].mac_code == key) { - return qt_mac_private_unicode[i].qt_code; - } - } - - } - - //oh well -#ifdef DEBUG_KEY_BINDINGS - qDebug("Unknown case.. %s:%d %d[%d] %d", __FILE__, __LINE__, key.unicode(), key.toLatin1(), virtualKey); -#endif - return Qt::Key_unknown; -} - -static Boolean qt_KeyEventComparatorProc(EventRef inEvent, void *data) -{ - UInt32 ekind = GetEventKind(inEvent), - eclass = GetEventClass(inEvent); - return (eclass == kEventClassKeyboard && (void *)ekind == data); -} - -static bool translateKeyEventInternal(EventHandlerCallRef er, EventRef keyEvent, int *qtKey, - QChar *outChar, Qt::KeyboardModifiers *outModifiers, bool *outHandled) -{ -#if !defined(QT_MAC_USE_COCOA) || defined(Q_OS_MAC64) - Q_UNUSED(er); - Q_UNUSED(outHandled); -#endif - const UInt32 ekind = GetEventKind(keyEvent); - { - UInt32 mac_modifiers = 0; - GetEventParameter(keyEvent, kEventParamKeyModifiers, typeUInt32, 0, - sizeof(mac_modifiers), 0, &mac_modifiers); -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("************ Mapping modifiers and key ***********"); -#endif - *outModifiers = qt_mac_get_modifiers(mac_modifiers); -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("------------ Mapping modifiers and key -----------"); -#endif - } - - //get keycode - UInt32 keyCode = 0; - GetEventParameter(keyEvent, kEventParamKeyCode, typeUInt32, 0, sizeof(keyCode), 0, &keyCode); - - //get mac mapping - static UInt32 tmp_unused_state = 0L; - const UCKeyboardLayout *uchrData = 0; -#if defined(Q_OS_MAC32) - KeyboardLayoutRef keyLayoutRef = 0; - KLGetCurrentKeyboardLayout(&keyLayoutRef); - OSStatus err; - if (keyLayoutRef != 0) { - err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLuchrData, - (reinterpret_cast<const void **>(&uchrData))); - if (err != noErr) { - qWarning("Qt::internal::unable to get keyboardlayout %ld %s:%d", - long(err), __FILE__, __LINE__); - } - } -#else - QCFType<TISInputSourceRef> inputSource = TISCopyCurrentKeyboardInputSource(); - Q_ASSERT(inputSource != 0); - CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(inputSource, - kTISPropertyUnicodeKeyLayoutData)); - uchrData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0; -#endif - *qtKey = Qt::Key_unknown; - if (uchrData) { - // The easy stuff; use the unicode stuff! - UniChar string[4]; - UniCharCount actualLength; - UInt32 currentModifiers = GetCurrentEventKeyModifiers(); - UInt32 currentModifiersWOAltOrControl = currentModifiers & ~(controlKey | optionKey); - int keyAction; - switch (ekind) { - default: - case kEventRawKeyDown: - keyAction = kUCKeyActionDown; - break; - case kEventRawKeyUp: - keyAction = kUCKeyActionUp; - break; - case kEventRawKeyRepeat: - keyAction = kUCKeyActionAutoKey; - break; - } - OSStatus err = UCKeyTranslate(uchrData, keyCode, keyAction, - ((currentModifiersWOAltOrControl >> 8) & 0xff), LMGetKbdType(), - kUCKeyTranslateNoDeadKeysMask, &tmp_unused_state, 4, &actualLength, - string); - if (err == noErr) { - *outChar = QChar(string[0]); - *qtKey = qt_mac_get_key(*outModifiers, *outChar, keyCode); - if (currentModifiersWOAltOrControl != currentModifiers) { - // Now get the real char. - err = UCKeyTranslate(uchrData, keyCode, keyAction, - ((currentModifiers >> 8) & 0xff), LMGetKbdType(), - kUCKeyTranslateNoDeadKeysMask, &tmp_unused_state, 4, &actualLength, - string); - if (err == noErr) - *outChar = QChar(string[0]); - } - } else { - qWarning("Qt::internal::UCKeyTranslate is returnining %ld %s:%d", - long(err), __FILE__, __LINE__); - } - } -#ifdef Q_OS_MAC32 - else { - // The road less travelled; use KeyTranslate - const void *keyboard_layout; - KeyboardLayoutRef keyLayoutRef = 0; - KLGetCurrentKeyboardLayout(&keyLayoutRef); - err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLKCHRData, - reinterpret_cast<const void **>(&keyboard_layout)); - - int translatedChar = KeyTranslate(keyboard_layout, (GetCurrentEventKeyModifiers() & - (kEventKeyModifierNumLockMask|shiftKey|cmdKey| - rightShiftKey|alphaLock)) | keyCode, - &tmp_unused_state); - if (!translatedChar) { -#ifdef QT_MAC_USE_COCOA - if (outHandled) { - qt_mac_eat_unicode_key = false; - if (er) - CallNextEventHandler(er, keyEvent); - *outHandled = qt_mac_eat_unicode_key; - } -#endif - return false; - } - - //map it into qt keys - *qtKey = qt_mac_get_key(*outModifiers, QChar(translatedChar), keyCode); - if (*outModifiers & (Qt::AltModifier | Qt::ControlModifier)) { - if (translatedChar & (1 << 7)) //high ascii - translatedChar = 0; - } else { //now get the real ascii value - UInt32 tmp_mod = 0L; - static UInt32 tmp_state = 0L; - if (*outModifiers & Qt::ShiftModifier) - tmp_mod |= shiftKey; - if (*outModifiers & Qt::MetaModifier) - tmp_mod |= controlKey; - if (*outModifiers & Qt::ControlModifier) - tmp_mod |= cmdKey; - if (GetCurrentEventKeyModifiers() & alphaLock) //no Qt mapper - tmp_mod |= alphaLock; - if (*outModifiers & Qt::AltModifier) - tmp_mod |= optionKey; - if (*outModifiers & Qt::KeypadModifier) - tmp_mod |= kEventKeyModifierNumLockMask; - translatedChar = KeyTranslate(keyboard_layout, tmp_mod | keyCode, &tmp_state); - } - { - ByteCount unilen = 0; - if (GetEventParameter(keyEvent, kEventParamKeyUnicodes, typeUnicodeText, 0, 0, &unilen, 0) - == noErr && unilen == 2) { - GetEventParameter(keyEvent, kEventParamKeyUnicodes, typeUnicodeText, 0, unilen, 0, outChar); - } else if (translatedChar) { - static QTextCodec *c = 0; - if (!c) - c = QTextCodec::codecForName("Apple Roman"); - char tmpChar = (char)translatedChar; // **sigh** - *outChar = c->toUnicode(&tmpChar, 1).at(0); - } else { - *qtKey = qt_mac_get_key(*outModifiers, QChar(translatedChar), keyCode); - } - } - } -#endif - if (*qtKey == Qt::Key_unknown) - *qtKey = qt_mac_get_key(*outModifiers, *outChar, keyCode); - return true; -} - -QKeyMapperPrivate::QKeyMapperPrivate() -{ - memset(keyLayout, 0, sizeof(keyLayout)); - keyboard_layout_format.unicode = 0; -#ifdef Q_OS_MAC32 - keyboard_mode = NullMode; -#else - currentInputSource = 0; -#endif -} - -QKeyMapperPrivate::~QKeyMapperPrivate() -{ - deleteLayouts(); -} - -bool -QKeyMapperPrivate::updateKeyboard() -{ - const UCKeyboardLayout *uchrData = 0; -#ifdef Q_OS_MAC32 - KeyboardLayoutRef keyLayoutRef = 0; - KLGetCurrentKeyboardLayout(&keyLayoutRef); - - if (keyboard_mode != NullMode && currentKeyboardLayout == keyLayoutRef) - return false; - - OSStatus err; - if (keyLayoutRef != 0) { - err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLuchrData, - const_cast<const void **>(reinterpret_cast<const void **>(&uchrData))); - if (err != noErr) { - qWarning("Qt::internal::unable to get unicode keyboardlayout %ld %s:%d", - long(err), __FILE__, __LINE__); - } - } -#else - QCFType<TISInputSourceRef> source = TISCopyCurrentKeyboardInputSource(); - if (keyboard_mode != NullMode && source == currentInputSource) { - return false; - } - Q_ASSERT(source != 0); - CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(source, - kTISPropertyUnicodeKeyLayoutData)); - uchrData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0; -#endif - - keyboard_kind = LMGetKbdType(); - if (uchrData) { - keyboard_layout_format.unicode = uchrData; - keyboard_mode = UnicodeMode; - } -#ifdef Q_OS_MAC32 - else { - void *happy; - err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLKCHRData, - const_cast<const void **>(reinterpret_cast<void **>(&happy))); - if (err != noErr) { - qFatal("Qt::internal::unable to get non-unicode layout, cannot procede %ld %s:%d", - long(err), __FILE__, __LINE__); - } - keyboard_layout_format.other = happy; - keyboard_mode = OtherMode; - } - - currentKeyboardLayout = keyLayoutRef; -#else - currentInputSource = source; -#endif - keyboard_dead = 0; - CFStringRef iso639Code; -#ifdef Q_OS_MAC32 -# ifndef kKLLanguageCode -# define kKLLanguageCode 9 -# endif - KLGetKeyboardLayoutProperty(currentKeyboardLayout, kKLLanguageCode, - reinterpret_cast<const void **>(&iso639Code)); -#else - CFArrayRef array = static_cast<CFArrayRef>(TISGetInputSourceProperty(currentInputSource, kTISPropertyInputSourceLanguages)); - iso639Code = static_cast<CFStringRef>(CFArrayGetValueAtIndex(array, 0)); // Actually a RFC3066bis, but it's close enough -#endif - if (iso639Code) { - keyboardInputLocale = QLocale(QCFString::toQString(iso639Code)); - keyboardInputDirection = keyboardInputLocale.textDirection(); - } else { - keyboardInputLocale = QLocale::c(); - keyboardInputDirection = Qt::LeftToRight; - } - return true; -} - -void -QKeyMapperPrivate::deleteLayouts() -{ - keyboard_mode = NullMode; - for (int i = 0; i < 255; ++i) { - if (keyLayout[i]) { - delete keyLayout[i]; - keyLayout[i] = 0; - } - } -} - -void -QKeyMapperPrivate::clearMappings() -{ - deleteLayouts(); - updateKeyboard(); -} - -QList<int> -QKeyMapperPrivate::possibleKeys(QKeyEvent *e) -{ - QList<int> ret; - - KeyboardLayoutItem *kbItem = keyLayout[e->nativeVirtualKey()]; - if (!kbItem) // Key is not in any keyboard layout (e.g. eisu-key on Japanese keyboard) - return ret; - - int baseKey = kbItem->qtKey[0]; - Qt::KeyboardModifiers keyMods = e->modifiers(); - ret << int(baseKey + keyMods); // The base key is _always_ valid, of course - - for (int i = 1; i < 8; ++i) { - Qt::KeyboardModifiers neededMods = ModsTbl[i]; - int key = kbItem->qtKey[i]; - if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) - ret << int(key + (keyMods & ~neededMods)); - } - - return ret; -} - -bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef er, EventRef event, - void *info, bool grab) -{ - Q_ASSERT(GetEventClass(event) == kEventClassKeyboard); - bool handled_event=true; - UInt32 ekind = GetEventKind(event); - - // unfortunately modifiers changed event looks quite different, so I have a separate - // code path - if (ekind == kEventRawKeyModifiersChanged) { - //figure out changed modifiers, wish Apple would just send a delta - UInt32 modifiers = 0; - GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 0, - sizeof(modifiers), 0, &modifiers); - qt_mac_send_modifiers_changed(modifiers, widget); - return true; - } - - QInputContext *currentContext = qApp->inputContext(); - if (currentContext && currentContext->isComposing()) { - if (ekind == kEventRawKeyDown) { - QMacInputContext *context = qobject_cast<QMacInputContext*>(currentContext); - if (context) - context->setLastKeydownEvent(event); - } - return false; - } - // Once we process the key down , we don't need to send the saved event again from - // kEventTextInputUnicodeForKeyEvent, so clear it. - if (currentContext && ekind == kEventRawKeyDown) { - QMacInputContext *context = qobject_cast<QMacInputContext*>(currentContext); - if (context) - context->setLastKeydownEvent(0); - } - - //get modifiers - Qt::KeyboardModifiers modifiers; - int qtKey; - QChar ourChar; - if (translateKeyEventInternal(er, event, &qtKey, &ourChar, &modifiers, - &handled_event) == false) - return handled_event; - QString text(ourChar); - /* This is actually wrong - but unfortunately it is the best that can be - done for now because of the Control/Meta mapping problems */ - if (modifiers & (Qt::ControlModifier | Qt::MetaModifier) - && !qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { - text = QString(); - } - - - if (widget) { -#ifndef QT_MAC_USE_COCOA - Q_UNUSED(info); - // Try not to call "other" event handlers if we have a popup, - // However, if the key has text - // then we should pass it along because otherwise then people - // can use input method stuff. - if (!qApp->activePopupWidget() - || (qApp->activePopupWidget() && !text.isEmpty())) { - //Find out if someone else wants the event, namely - //is it of use to text services? If so we won't bother - //with a QKeyEvent. - qt_mac_eat_unicode_key = false; - if (er) - CallNextEventHandler(er, event); - extern bool qt_mac_menubar_is_open(); - if (qt_mac_eat_unicode_key || qt_mac_menubar_is_open()) { - return true; - } - } -#endif - // Try to compress key events. - if (!text.isEmpty() && widget->testAttribute(Qt::WA_KeyCompression)) { - EventTime lastTime = GetEventTime(event); - for (;;) { - EventRef releaseEvent = FindSpecificEventInQueue(GetMainEventQueue(), - qt_KeyEventComparatorProc, - (void*)kEventRawKeyUp); - if (!releaseEvent) - break; - const EventTime releaseTime = GetEventTime(releaseEvent); - if (releaseTime < lastTime) - break; - lastTime = releaseTime; - - EventRef pressEvent = FindSpecificEventInQueue(GetMainEventQueue(), - qt_KeyEventComparatorProc, - (void*)kEventRawKeyDown); - if (!pressEvent) - break; - const EventTime pressTime = GetEventTime(pressEvent); - if (pressTime < lastTime) - break; - lastTime = pressTime; - - Qt::KeyboardModifiers compressMod; - int compressQtKey = 0; - QChar compressChar; - if (translateKeyEventInternal(er, pressEvent, - &compressQtKey, &compressChar, &compressMod, 0) - == false) { - break; - } - // Copied from qapplication_x11.cpp (change both). - - bool stopCompression = - // 1) misc keys - (compressQtKey >= Qt::Key_Escape && compressQtKey <= Qt::Key_SysReq) - // 2) cursor movement - || (compressQtKey >= Qt::Key_Home && compressQtKey <= Qt::Key_PageDown) - // 3) extra keys - || (compressQtKey >= Qt::Key_Super_L && compressQtKey <= Qt::Key_Direction_R) - // 4) something that a) doesn't translate to text or b) translates - // to newline text - || (compressQtKey == 0) - || (compressChar == QLatin1Char('\n')) - || (compressQtKey == Qt::Key_unknown); - - if (compressMod == modifiers && !compressChar.isNull() && !stopCompression) { -#ifdef DEBUG_KEY_BINDINGS - qDebug("compressing away %c", compressChar.toLatin1()); -#endif - text += compressChar; - // Clean up - RemoveEventFromQueue(GetMainEventQueue(), releaseEvent); - RemoveEventFromQueue(GetMainEventQueue(), pressEvent); - } else { -#ifdef DEBUG_KEY_BINDINGS - qDebug("stoping compression.."); -#endif - break; - } - } - } - - // There is no way to get the scan code from carbon. But we cannot use the value 0, since - // it indicates that the event originates from somewhere else than the keyboard - UInt32 macScanCode = 1; - UInt32 macVirtualKey = 0; - GetEventParameter(event, kEventParamKeyCode, typeUInt32, 0, sizeof(macVirtualKey), 0, &macVirtualKey); - UInt32 macModifiers = 0; - GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 0, - sizeof(macModifiers), 0, &macModifiers); -#ifdef QT_MAC_USE_COCOA - // The unicode characters in the range 0xF700-0xF747 are reserved - // by Mac OS X for transient use as keyboard function keys. We - // wont send 'text' for such key events. This is done to match - // behavior on other platforms. - unsigned int *unicodeKey = (unsigned int*)info; - if (*unicodeKey >= 0xf700 && *unicodeKey <= 0xf747) - text = QString(); - bool isAccepted; -#endif - handled_event = QKeyMapper::sendKeyEvent(widget, grab, - (ekind == kEventRawKeyUp) ? QEvent::KeyRelease : QEvent::KeyPress, - qtKey, modifiers, text, ekind == kEventRawKeyRepeat, 0, - macScanCode, macVirtualKey, macModifiers -#ifdef QT_MAC_USE_COCOA - ,&isAccepted -#endif - ); -#ifdef QT_MAC_USE_COCOA - *unicodeKey = (unsigned int)isAccepted; -#endif - } - return handled_event; -} - -void -QKeyMapperPrivate::updateKeyMap(EventHandlerCallRef, EventRef event, void * -#if defined(QT_MAC_USE_COCOA) - unicodeKey // unicode character from NSEvent (modifiers applied) -#endif - ) -{ - UInt32 macVirtualKey = 0; - GetEventParameter(event, kEventParamKeyCode, typeUInt32, 0, sizeof(macVirtualKey), 0, &macVirtualKey); - if (updateKeyboard()) - QKeyMapper::changeKeyboard(); - else if (keyLayout[macVirtualKey]) - return; - - UniCharCount buffer_size = 10; - UniChar buffer[buffer_size]; - keyLayout[macVirtualKey] = new KeyboardLayoutItem; - for (int i = 0; i < 16; ++i) { - UniCharCount out_buffer_size = 0; - keyLayout[macVirtualKey]->qtKey[i] = 0; -#ifdef Q_WS_MAC32 - if (keyboard_mode == UnicodeMode) { -#endif - const UInt32 keyModifier = ((qt_mac_get_mac_modifiers(ModsTbl[i]) >> 8) & 0xFF); - OSStatus err = UCKeyTranslate(keyboard_layout_format.unicode, macVirtualKey, kUCKeyActionDown, keyModifier, - keyboard_kind, 0, &keyboard_dead, buffer_size, &out_buffer_size, buffer); - if (err == noErr && out_buffer_size) { - const QChar unicode(buffer[0]); - int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey); - if (qtkey == Qt::Key_unknown) - qtkey = unicode.unicode(); - keyLayout[macVirtualKey]->qtKey[i] = qtkey; - } -#ifndef Q_WS_MAC32 - else { - const QChar unicode(*((UniChar *)unicodeKey)); - int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey); - if (qtkey == Qt::Key_unknown) - qtkey = unicode.unicode(); - keyLayout[macVirtualKey]->qtKey[i] = qtkey; - } -#endif -#ifdef Q_WS_MAC32 - } else { - const UInt32 keyModifier = (qt_mac_get_mac_modifiers(ModsTbl[i])); - - uchar translatedChar = KeyTranslate(keyboard_layout_format.other, keyModifier | macVirtualKey, &keyboard_dead); - if (translatedChar) { - static QTextCodec *c = 0; - if (!c) - c = QTextCodec::codecForName("Apple Roman"); - const QChar unicode(c->toUnicode((const char *)&translatedChar, 1).at(0)); - int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey); - if (qtkey == Qt::Key_unknown) - qtkey = unicode.unicode(); - keyLayout[macVirtualKey]->qtKey[i] = qtkey; - } - } -#endif - } -#ifdef DEBUG_KEY_MAPS - qDebug("updateKeyMap for virtual key = 0x%02x!", (uint)macVirtualKey); - for (int i = 0; i < 16; ++i) { - qDebug(" [%d] (%d,0x%02x,'%c')", i, - keyLayout[macVirtualKey]->qtKey[i], - keyLayout[macVirtualKey]->qtKey[i], - keyLayout[macVirtualKey]->qtKey[i]); - } -#endif -} - -bool -QKeyMapper::sendKeyEvent(QWidget *widget, bool grab, - QEvent::Type type, int code, Qt::KeyboardModifiers modifiers, - const QString &text, bool autorepeat, int count, - quint32 nativeScanCode, quint32 nativeVirtualKey, - quint32 nativeModifiers, bool *isAccepted) -{ - Q_UNUSED(count); - if (widget && widget->isEnabled()) { - bool key_event = true; -#if defined(QT3_SUPPORT) && !defined(QT_NO_SHORTCUT) - if (type == QEvent::KeyPress && !grab - && QApplicationPrivate::instance()->use_compat()) { - QKeyEventEx accel_ev(type, code, modifiers, - text, autorepeat, qMax(1, int(text.length())), - nativeScanCode, nativeVirtualKey, nativeModifiers); - if (QApplicationPrivate::instance()->qt_tryAccelEvent(widget, &accel_ev)) { -#if defined(DEBUG_KEY_BINDINGS) || defined(DEBUG_KEY_BINDINGS_MODIFIERS) - qDebug("KeyEvent: %s::%s consumed Accel: %s", - widget ? widget->metaObject()->className() : "none", - widget ? widget->objectName().toLatin1().constData() : "", - text.toLatin1().constData()); -#endif - key_event = false; - } else { - if (accel_ev.isAccepted()) { -#if defined(DEBUG_KEY_BINDINGS) || defined(DEBUG_KEY_BINDINGS_MODIFIERS) - qDebug("KeyEvent: %s::%s overrode Accel: %s", - widget ? widget->metaObject()->className() : "none", - widget ? widget->objectName().toLatin1().constData() : "", - text.toLatin1().constData()); -#endif - } - } - } -#else -Q_UNUSED(grab); -#endif // QT3_SUPPORT && !QT_NO_SHORTCUT - if (key_event) { -#if defined(DEBUG_KEY_BINDINGS) || defined(DEBUG_KEY_BINDINGS_MODIFIERS) - qDebug("KeyEvent: Sending %s to %s::%s: %s 0x%08x%s", - type == QEvent::KeyRelease ? "KeyRelease" : "KeyPress", - widget ? widget->metaObject()->className() : "none", - widget ? widget->objectName().toLatin1().constData() : "", - text.toLatin1().constData(), int(modifiers), - autorepeat ? " Repeat" : ""); -#endif - QKeyEventEx ke(type, code, modifiers, text, autorepeat, qMax(1, text.length()), - nativeScanCode, nativeVirtualKey, nativeModifiers); - bool retMe = qt_sendSpontaneousEvent(widget,&ke); - if (isAccepted) - *isAccepted = ke.isAccepted(); - return retMe; - } - } - return false; -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qmacdefines_mac.h b/src/gui/platforms/mac/qmacdefines_mac.h deleted file mode 100644 index d6ccb93593..0000000000 --- a/src/gui/platforms/mac/qmacdefines_mac.h +++ /dev/null @@ -1,180 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -/* - * qmacdefines_mac_p.h - * All the defines you'll ever need for Qt/Mac :-) - */ - -/* This is just many defines. Therefore it doesn't need things like: -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -QT_END_NAMESPACE - -QT_END_HEADER - -Yes, it is an informative comment ;-) -*/ - -#include <QtCore/qglobal.h> - -#ifdef qDebug -# define old_qDebug qDebug -# undef qDebug -#endif - -#ifdef __LP64__ -typedef signed int OSStatus; -#else -typedef signed long OSStatus; -#endif - -#ifdef __OBJC__ -# ifdef slots -# define old_slots slots -# undef slots -# endif -#include <Cocoa/Cocoa.h> -# ifdef old_slots -# undef slots -# define slots -# undef old_slots -# endif -#endif -#ifdef QT_MAC_USE_COCOA - typedef struct OpaqueEventHandlerCallRef * EventHandlerCallRef; - typedef struct OpaqueEventRef * EventRef; - typedef struct OpaqueMenuRef * MenuRef; - typedef struct OpaquePasteboardRef* PasteboardRef; - typedef struct OpaqueRgnHandle * RgnHandle; - typedef const struct __HIShape *HIShapeRef; - typedef struct __HIShape *HIMutableShapeRef; - typedef struct CGRect CGRect; - typedef struct CGImage *CGImageRef; - typedef struct CGContext *CGContextRef; - typedef struct GDevice * GDPtr; - typedef GDPtr * GDHandle; - typedef struct OpaqueIconRef * IconRef; -# ifdef __OBJC__ - typedef NSWindow* OSWindowRef; - typedef NSView *OSViewRef; - typedef NSMenu *OSMenuRef; - typedef NSEvent *OSEventRef; -# else - typedef void *OSWindowRef; - typedef void *OSViewRef; - typedef void *OSMenuRef; - typedef void *OSEventRef; -# endif -#else // Carbon - typedef struct OpaqueEventHandlerCallRef * EventHandlerCallRef; - typedef struct OpaqueEventRef * EventRef; - typedef struct OpaqueMenuRef * MenuRef; - typedef struct OpaquePasteboardRef* PasteboardRef; - typedef struct OpaqueRgnHandle * RgnHandle; - typedef const struct __HIShape *HIShapeRef; - typedef struct __HIShape *HIMutableShapeRef; - typedef struct CGRect CGRect; - typedef struct CGImage *CGImageRef; - typedef struct CGContext *CGContextRef; - typedef struct GDevice * GDPtr; - typedef GDPtr * GDHandle; - typedef struct OpaqueIconRef * IconRef; - typedef struct OpaqueWindowPtr * WindowRef; - typedef struct OpaqueControlRef * HIViewRef; - typedef WindowRef OSWindowRef; - typedef HIViewRef OSViewRef; - typedef MenuRef OSMenuRef; - typedef EventRef OSEventRef; -#endif // QT_MAC_USE_COCOA - -typedef PasteboardRef OSPasteboardRef; -typedef struct AEDesc AEDescList; -typedef AEDescList AERecord; -typedef AERecord AppleEvent; - -#ifdef check -#undef check -#endif - -#ifdef old_qDebug -# undef qDebug -# define qDebug QT_NO_QDEBUG_MACRO -# undef old_qDebug -#endif diff --git a/src/gui/platforms/mac/qmacgesturerecognizer_mac.mm b/src/gui/platforms/mac/qmacgesturerecognizer_mac.mm deleted file mode 100644 index 6a4f0bb445..0000000000 --- a/src/gui/platforms/mac/qmacgesturerecognizer_mac.mm +++ /dev/null @@ -1,272 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmacgesturerecognizer_mac_p.h" -#include "qgesture.h" -#include "qgesture_p.h" -#include "qevent.h" -#include "qevent_p.h" -#include "qwidget.h" -#include "qdebug.h" - -#ifndef QT_NO_GESTURES - -QT_BEGIN_NAMESPACE - -QMacSwipeGestureRecognizer::QMacSwipeGestureRecognizer() -{ -} - -QGesture *QMacSwipeGestureRecognizer::create(QObject * /*target*/) -{ - return new QSwipeGesture; -} - -QGestureRecognizer::Result -QMacSwipeGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *event) -{ - if (event->type() == QEvent::NativeGesture && obj->isWidgetType()) { - QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event); - switch (ev->gestureType) { - case QNativeGestureEvent::Swipe: { - QSwipeGesture *g = static_cast<QSwipeGesture *>(gesture); - g->setSwipeAngle(ev->angle); - g->setHotSpot(ev->position); - return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; - break; } - default: - break; - } - } - - return QGestureRecognizer::Ignore; -} - -void QMacSwipeGestureRecognizer::reset(QGesture *gesture) -{ - QSwipeGesture *g = static_cast<QSwipeGesture *>(gesture); - g->setSwipeAngle(0); - QGestureRecognizer::reset(gesture); -} - -//////////////////////////////////////////////////////////////////////// - -QMacPinchGestureRecognizer::QMacPinchGestureRecognizer() -{ -} - -QGesture *QMacPinchGestureRecognizer::create(QObject * /*target*/) -{ - return new QPinchGesture; -} - -QGestureRecognizer::Result -QMacPinchGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *event) -{ - if (event->type() == QEvent::NativeGesture && obj->isWidgetType()) { - QPinchGesture *g = static_cast<QPinchGesture *>(gesture); - QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event); - switch(ev->gestureType) { - case QNativeGestureEvent::GestureBegin: - reset(gesture); - g->setStartCenterPoint(static_cast<QWidget*>(obj)->mapFromGlobal(ev->position)); - g->setCenterPoint(g->startCenterPoint()); - g->setChangeFlags(QPinchGesture::CenterPointChanged); - g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags()); - g->setHotSpot(ev->position); - return QGestureRecognizer::MayBeGesture | QGestureRecognizer::ConsumeEventHint; - case QNativeGestureEvent::Rotate: { - g->setLastScaleFactor(g->scaleFactor()); - g->setLastRotationAngle(g->rotationAngle()); - g->setRotationAngle(g->rotationAngle() + ev->percentage); - g->setChangeFlags(QPinchGesture::RotationAngleChanged); - g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags()); - g->setHotSpot(ev->position); - return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; - } - case QNativeGestureEvent::Zoom: - g->setLastScaleFactor(g->scaleFactor()); - g->setLastRotationAngle(g->rotationAngle()); - g->setScaleFactor(g->scaleFactor() * (1 + ev->percentage)); - g->setChangeFlags(QPinchGesture::ScaleFactorChanged); - g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags()); - g->setHotSpot(ev->position); - return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; - case QNativeGestureEvent::GestureEnd: - return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; - default: - break; - } - } - - return QGestureRecognizer::Ignore; -} - -void QMacPinchGestureRecognizer::reset(QGesture *gesture) -{ - QPinchGesture *g = static_cast<QPinchGesture *>(gesture); - g->setChangeFlags(0); - g->setTotalChangeFlags(0); - g->setScaleFactor(1.0f); - g->setTotalScaleFactor(1.0f); - g->setLastScaleFactor(1.0f); - g->setRotationAngle(0.0f); - g->setTotalRotationAngle(0.0f); - g->setLastRotationAngle(0.0f); - g->setCenterPoint(QPointF()); - g->setStartCenterPoint(QPointF()); - g->setLastCenterPoint(QPointF()); - QGestureRecognizer::reset(gesture); -} - -//////////////////////////////////////////////////////////////////////// - -#if defined(QT_MAC_USE_COCOA) - -QMacPanGestureRecognizer::QMacPanGestureRecognizer() : _panCanceled(true) -{ -} - -QGesture *QMacPanGestureRecognizer::create(QObject *target) -{ - if (!target) - return new QPanGesture; - - if (QWidget *w = qobject_cast<QWidget *>(target)) { - w->setAttribute(Qt::WA_AcceptTouchEvents); - w->setAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents); - return new QPanGesture; - } - return 0; -} - -QGestureRecognizer::Result -QMacPanGestureRecognizer::recognize(QGesture *gesture, QObject *target, QEvent *event) -{ - const int panBeginDelay = 300; - const int panBeginRadius = 3; - - QPanGesture *g = static_cast<QPanGesture *>(gesture); - - switch (event->type()) { - case QEvent::TouchBegin: { - const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); - if (ev->touchPoints().size() == 1) { - reset(gesture); - _startPos = QCursor::pos(); - _panTimer.start(panBeginDelay, target); - _panCanceled = false; - return QGestureRecognizer::MayBeGesture; - } - break;} - case QEvent::TouchEnd: { - if (_panCanceled) - break; - - const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); - if (ev->touchPoints().size() == 1) - return QGestureRecognizer::FinishGesture; - break;} - case QEvent::TouchUpdate: { - if (_panCanceled) - break; - - const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); - if (ev->touchPoints().size() == 1) { - if (_panTimer.isActive()) { - // INVARIANT: Still in maybeGesture. Check if the user - // moved his finger so much that it makes sense to cancel the pan: - const QPointF p = QCursor::pos(); - if ((p - _startPos).manhattanLength() > panBeginRadius) { - _panCanceled = true; - _panTimer.stop(); - return QGestureRecognizer::CancelGesture; - } - } else { - const QPointF p = QCursor::pos(); - const QPointF posOffset = p - _startPos; - g->setLastOffset(g->offset()); - g->setOffset(QPointF(posOffset.x(), posOffset.y())); - g->setHotSpot(_startPos); - return QGestureRecognizer::TriggerGesture; - } - } else if (_panTimer.isActive()) { - // I only want to cancel the pan if the user is pressing - // more than one finger, and the pan hasn't started yet: - _panCanceled = true; - _panTimer.stop(); - return QGestureRecognizer::CancelGesture; - } - break;} - case QEvent::Timer: { - QTimerEvent *ev = static_cast<QTimerEvent *>(event); - if (ev->timerId() == _panTimer.timerId()) { - _panTimer.stop(); - if (_panCanceled) - break; - // Begin new pan session! - _startPos = QCursor::pos(); - g->setHotSpot(_startPos); - return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; - } - break; } - default: - break; - } - - return QGestureRecognizer::Ignore; -} - -void QMacPanGestureRecognizer::reset(QGesture *gesture) -{ - QPanGesture *g = static_cast<QPanGesture *>(gesture); - _startPos = QPointF(); - _panCanceled = true; - g->setOffset(QPointF(0, 0)); - g->setLastOffset(QPointF(0, 0)); - g->setAcceleration(qreal(1)); - QGestureRecognizer::reset(gesture); -} -#endif // QT_MAC_USE_COCOA - -QT_END_NAMESPACE - -#endif // QT_NO_GESTURES diff --git a/src/gui/platforms/mac/qmacgesturerecognizer_mac_p.h b/src/gui/platforms/mac/qmacgesturerecognizer_mac_p.h deleted file mode 100644 index 465f6a2ac8..0000000000 --- a/src/gui/platforms/mac/qmacgesturerecognizer_mac_p.h +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMACSWIPEGESTURERECOGNIZER_MAC_P_H -#define QMACSWIPEGESTURERECOGNIZER_MAC_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qtimer.h" -#include "qpoint.h" -#include "qgesturerecognizer.h" - -#ifndef QT_NO_GESTURES - -QT_BEGIN_NAMESPACE - -class QMacSwipeGestureRecognizer : public QGestureRecognizer -{ -public: - QMacSwipeGestureRecognizer(); - - QGesture *create(QObject *target); - QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event); - void reset(QGesture *gesture); -}; - -class QMacPinchGestureRecognizer : public QGestureRecognizer -{ -public: - QMacPinchGestureRecognizer(); - - QGesture *create(QObject *target); - QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event); - void reset(QGesture *gesture); -}; - -#if defined(QT_MAC_USE_COCOA) - -class QMacPanGestureRecognizer : public QObject, public QGestureRecognizer -{ -public: - QMacPanGestureRecognizer(); - - QGesture *create(QObject *target); - QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event); - void reset(QGesture *gesture); -private: - QPointF _startPos; - QBasicTimer _panTimer; - bool _panCanceled; -}; - -#endif - -QT_END_NAMESPACE - -#endif // QT_NO_GESTURES - -#endif // QMACSWIPEGESTURERECOGNIZER_MAC_P_H diff --git a/src/gui/platforms/mac/qmime_mac.cpp b/src/gui/platforms/mac/qmime_mac.cpp deleted file mode 100644 index d6f6222c23..0000000000 --- a/src/gui/platforms/mac/qmime_mac.cpp +++ /dev/null @@ -1,1310 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmime.h" - -//#define USE_INTERNET_CONFIG - -#ifndef USE_INTERNET_CONFIG -# include "qfile.h" -# include "qfileinfo.h" -# include "qtextstream.h" -# include "qdir.h" -# include <unistd.h> -# include <sys/types.h> -# include <sys/stat.h> -# include <sys/fcntl.h> -#endif - -#include "qdebug.h" -#include "qpixmap.h" -#include "qimagewriter.h" -#include "qimagereader.h" -#include "qdatastream.h" -#include "qbuffer.h" -#include "qdatetime.h" -#include "qapplication_p.h" -#include "qtextcodec.h" -#include "qregexp.h" -#include "qurl.h" -#include "qmap.h" -#include <private/qt_mac_p.h> - - -#ifdef Q_WS_MAC32 -#include <QuickTime/QuickTime.h> -#include <qlibrary.h> -#endif - -QT_BEGIN_NAMESPACE - -extern CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0); // qpaintengine_mac.cpp - -typedef QList<QMacPasteboardMime*> MimeList; -Q_GLOBAL_STATIC(MimeList, globalMimeList) - -static void cleanup_mimes() -{ - MimeList *mimes = globalMimeList(); - while (!mimes->isEmpty()) - delete mimes->takeFirst(); -} - -Q_GLOBAL_STATIC(QStringList, globalDraggedTypesList) - -/*! - \fn void qRegisterDraggedTypes(const QStringList &types) - \relates QMacPasteboardMime - - Registers the given \a types as custom pasteboard types. - - This function should be called to enable the Drag and Drop events - for custom pasteboard types on Cocoa implementations. This is required - in addition to a QMacPasteboardMime subclass implementation. By default - drag and drop is enabled for all standard pasteboard types. - - \sa QMacPasteboardMime -*/ -Q_GUI_EXPORT void qRegisterDraggedTypes(const QStringList &types) -{ - (*globalDraggedTypesList()) += types; -} - -const QStringList& qEnabledDraggedTypes() -{ - return (*globalDraggedTypesList()); -} - - -/***************************************************************************** - QDnD debug facilities - *****************************************************************************/ -//#define DEBUG_MIME_MAPS - -//functions -extern QString qt_mac_from_pascal_string(const Str255); //qglobal.cpp -extern void qt_mac_from_pascal_string(QString, Str255, TextEncoding encoding=0, int len=-1); //qglobal.cpp - -ScrapFlavorType qt_mac_mime_type = 'CUTE'; -CFStringRef qt_mac_mime_typeUTI = CFSTR("com.pasteboard.trolltech.marker"); - -/*! - \class QMacPasteboardMime - \brief The QMacPasteboardMime class converts between a MIME type and a - \l{http://developer.apple.com/macosx/uniformtypeidentifiers.html}{Uniform - Type Identifier (UTI)} format. - \since 4.2 - - \ingroup draganddrop - - Qt's drag and drop and clipboard facilities use the MIME - standard. On X11, this maps trivially to the Xdnd protocol. On - Mac, although some applications use MIME to describe clipboard - contents, it is more common to use Apple's UTI format. - - QMacPasteboardMime's role is to bridge the gap between MIME and UTI; - By subclasses this class, one can extend Qt's drag and drop - and clipboard handling to convert to and from unsupported, or proprietary, UTI formats. - - A subclass of QMacPasteboardMime will automatically be registered, and active, upon instantiation. - - Qt has predefined support for the following UTIs: - \list - \i public.utf8-plain-text - converts to "text/plain" - \i public.utf16-plain-text - converts to "text/plain" - \i public.html - converts to "text/html" - \i public.url - converts to "text/uri-list" - \i public.file-url - converts to "text/uri-list" - \i public.tiff - converts to "application/x-qt-image" - \i public.vcard - converts to "text/plain" - \i com.apple.traditional-mac-plain-text - converts to "text/plain" - \i com.apple.pict - converts to "application/x-qt-image" - \endlist - - When working with MIME data, Qt will interate through all instances of QMacPasteboardMime to - find an instance that can convert to, or from, a specific MIME type. It will do this by calling - canConvert() on each instance, starting with (and choosing) the last created instance first. - The actual conversions will be done by using convertToMime() and convertFromMime(). - - \note The API uses the term "flavor" in some cases. This is for backwards - compatibility reasons, and should now be understood as UTIs. -*/ - -/*! \enum QMacPasteboardMime::QMacPasteboardMimeType - \internal -*/ - -/*! - Constructs a new conversion object of type \a t, adding it to the - globally accessed list of available convertors. -*/ -QMacPasteboardMime::QMacPasteboardMime(char t) : type(t) -{ - globalMimeList()->append(this); -} - -/*! - Destroys a conversion object, removing it from the global - list of available convertors. -*/ -QMacPasteboardMime::~QMacPasteboardMime() -{ - if(!QApplication::closingDown()) - globalMimeList()->removeAll(this); -} - -class QMacPasteboardMimeAny : public QMacPasteboardMime { -private: - -public: - QMacPasteboardMimeAny() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) { - } - ~QMacPasteboardMimeAny() { - } - QString convertorName(); - - QString flavorFor(const QString &mime); - QString mimeFor(QString flav); - bool canConvert(const QString &mime, QString flav); - QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav); - QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav); -}; - -QString QMacPasteboardMimeAny::convertorName() -{ - return QLatin1String("Any-Mime"); -} - -QString QMacPasteboardMimeAny::flavorFor(const QString &mime) -{ - // do not handle the mime type name in the drag pasteboard - if(mime == QLatin1String("application/x-qt-mime-type-name")) - return QString(); - QString ret = QLatin1String("com.trolltech.anymime.") + mime; - return ret.replace(QLatin1Char('/'), QLatin1String("--")); -} - -QString QMacPasteboardMimeAny::mimeFor(QString flav) -{ - const QString any_prefix = QLatin1String("com.trolltech.anymime."); - if(flav.size() > any_prefix.length() && flav.startsWith(any_prefix)) - return flav.mid(any_prefix.length()).replace(QLatin1String("--"), QLatin1String("/")); - return QString(); -} - -bool QMacPasteboardMimeAny::canConvert(const QString &mime, QString flav) -{ - return mimeFor(flav) == mime; -} - -QVariant QMacPasteboardMimeAny::convertToMime(const QString &mime, QList<QByteArray> data, QString) -{ - if(data.count() > 1) - qWarning("QMacPasteboardMimeAny: Cannot handle multiple member data"); - QVariant ret; - if (mime == QLatin1String("text/plain")) - ret = QString::fromUtf8(data.first()); - else - ret = data.first(); - return ret; -} - -QList<QByteArray> QMacPasteboardMimeAny::convertFromMime(const QString &mime, QVariant data, QString) -{ - QList<QByteArray> ret; - if (mime == QLatin1String("text/plain")) - ret.append(data.toString().toUtf8()); - else - ret.append(data.toByteArray()); - return ret; -} - -class QMacPasteboardMimeTypeName : public QMacPasteboardMime { -private: - -public: - QMacPasteboardMimeTypeName() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) { - } - ~QMacPasteboardMimeTypeName() { - } - QString convertorName(); - - QString flavorFor(const QString &mime); - QString mimeFor(QString flav); - bool canConvert(const QString &mime, QString flav); - QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav); - QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav); -}; - -QString QMacPasteboardMimeTypeName::convertorName() -{ - return QLatin1String("Qt-Mime-Type"); -} - -QString QMacPasteboardMimeTypeName::flavorFor(const QString &mime) -{ - if(mime == QLatin1String("application/x-qt-mime-type-name")) - return QLatin1String("com.trolltech.qt.MimeTypeName"); - return QString(); -} - -QString QMacPasteboardMimeTypeName::mimeFor(QString) -{ - return QString(); -} - -bool QMacPasteboardMimeTypeName::canConvert(const QString &, QString) -{ - return false; -} - -QVariant QMacPasteboardMimeTypeName::convertToMime(const QString &, QList<QByteArray>, QString) -{ - QVariant ret; - return ret; -} - -QList<QByteArray> QMacPasteboardMimeTypeName::convertFromMime(const QString &, QVariant, QString) -{ - QList<QByteArray> ret; - ret.append(QString("x-qt-mime-type-name").toUtf8()); - return ret; -} - -class QMacPasteboardMimePlainText : public QMacPasteboardMime { -public: - QMacPasteboardMimePlainText() : QMacPasteboardMime(MIME_ALL) { } - QString convertorName(); - - QString flavorFor(const QString &mime); - QString mimeFor(QString flav); - bool canConvert(const QString &mime, QString flav); - QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav); - QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav); -}; - -QString QMacPasteboardMimePlainText::convertorName() -{ - return QLatin1String("PlainText"); -} - -QString QMacPasteboardMimePlainText::flavorFor(const QString &mime) -{ - if (mime == QLatin1String("text/plain")) - return QLatin1String("com.apple.traditional-mac-plain-text"); - return QString(); -} - -QString QMacPasteboardMimePlainText::mimeFor(QString flav) -{ - if (flav == QLatin1String("com.apple.traditional-mac-plain-text")) - return QLatin1String("text/plain"); - return QString(); -} - -bool QMacPasteboardMimePlainText::canConvert(const QString &mime, QString flav) -{ - return flavorFor(mime) == flav; -} - -QVariant QMacPasteboardMimePlainText::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor) -{ - if(data.count() > 1) - qWarning("QMacPasteboardMimePlainText: Cannot handle multiple member data"); - const QByteArray &firstData = data.first(); - QVariant ret; - if(flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text"))) { - QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault, - reinterpret_cast<const UInt8 *>(firstData.constData()), - firstData.size(), CFStringGetSystemEncoding(), false)); - ret = QString(str); - } else { - qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype)); - } - return ret; -} - -QList<QByteArray> QMacPasteboardMimePlainText::convertFromMime(const QString &, QVariant data, QString flavor) -{ - QList<QByteArray> ret; - QString string = data.toString(); - if(flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text"))) - ret.append(string.toLatin1()); - return ret; -} - -class QMacPasteboardMimeUnicodeText : public QMacPasteboardMime { -public: - QMacPasteboardMimeUnicodeText() : QMacPasteboardMime(MIME_ALL) { } - QString convertorName(); - - QString flavorFor(const QString &mime); - QString mimeFor(QString flav); - bool canConvert(const QString &mime, QString flav); - QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav); - QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav); -}; - -QString QMacPasteboardMimeUnicodeText::convertorName() -{ - return QLatin1String("UnicodeText"); -} - -QString QMacPasteboardMimeUnicodeText::flavorFor(const QString &mime) -{ - if (mime == QLatin1String("text/plain")) - return QLatin1String("public.utf16-plain-text"); - int i = mime.indexOf(QLatin1String("charset=")); - if (i >= 0) { - QString cs(mime.mid(i+8).toLower()); - i = cs.indexOf(QLatin1Char(';')); - if (i>=0) - cs = cs.left(i); - if (cs == QLatin1String("system")) - return QLatin1String("public.utf8-plain-text"); - else if (cs == QLatin1String("iso-10646-ucs-2") - || cs == QLatin1String("utf16")) - return QLatin1String("public.utf16-plain-text"); - } - return QString(); -} - -QString QMacPasteboardMimeUnicodeText::mimeFor(QString flav) -{ - if (flav == QLatin1String("public.utf16-plain-text") || flav == QLatin1String("public.utf8-plain-text")) - return QLatin1String("text/plain"); - return QString(); -} - -bool QMacPasteboardMimeUnicodeText::canConvert(const QString &mime, QString flav) -{ - return flavorFor(mime) == flav; -} - -QVariant QMacPasteboardMimeUnicodeText::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor) -{ - if(data.count() > 1) - qWarning("QMacPasteboardMimeUnicodeText: Cannot handle multiple member data"); - const QByteArray &firstData = data.first(); - // I can only handle two types (system and unicode) so deal with them that way - QVariant ret; - if(flavor == QLatin1String("public.utf8-plain-text")) { - QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault, - reinterpret_cast<const UInt8 *>(firstData.constData()), - firstData.size(), CFStringGetSystemEncoding(), false)); - ret = QString(str); - } else if (flavor == QLatin1String("public.utf16-plain-text")) { - ret = QString(reinterpret_cast<const QChar *>(firstData.constData()), - firstData.size() / sizeof(QChar)); - } else { - qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype)); - } - return ret; -} - -QList<QByteArray> QMacPasteboardMimeUnicodeText::convertFromMime(const QString &, QVariant data, QString flavor) -{ - QList<QByteArray> ret; - QString string = data.toString(); - if(flavor == QLatin1String("public.utf8-plain-text")) - ret.append(string.toUtf8()); - else if (flavor == QLatin1String("public.utf16-plain-text")) - ret.append(QByteArray((char*)string.utf16(), string.length()*2)); - return ret; -} - -class QMacPasteboardMimeHTMLText : public QMacPasteboardMime { -public: - QMacPasteboardMimeHTMLText() : QMacPasteboardMime(MIME_ALL) { } - QString convertorName(); - - QString flavorFor(const QString &mime); - QString mimeFor(QString flav); - bool canConvert(const QString &mime, QString flav); - QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav); - QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav); -}; - -QString QMacPasteboardMimeHTMLText::convertorName() -{ - return QLatin1String("HTML"); -} - -QString QMacPasteboardMimeHTMLText::flavorFor(const QString &mime) -{ - if (mime == QLatin1String("text/html")) - return QLatin1String("public.html"); - return QString(); -} - -QString QMacPasteboardMimeHTMLText::mimeFor(QString flav) -{ - if (flav == QLatin1String("public.html")) - return QLatin1String("text/html"); - return QString(); -} - -bool QMacPasteboardMimeHTMLText::canConvert(const QString &mime, QString flav) -{ - return flavorFor(mime) == flav; -} - -QVariant QMacPasteboardMimeHTMLText::convertToMime(const QString &mimeType, QList<QByteArray> data, QString flavor) -{ - if (!canConvert(mimeType, flavor)) - return QVariant(); - if (data.count() > 1) - qWarning("QMacPasteboardMimeHTMLText: Cannot handle multiple member data"); - return data.first(); -} - -QList<QByteArray> QMacPasteboardMimeHTMLText::convertFromMime(const QString &mime, QVariant data, QString flavor) -{ - QList<QByteArray> ret; - if (!canConvert(mime, flavor)) - return ret; - ret.append(data.toByteArray()); - return ret; -} - - -#ifdef Q_WS_MAC32 - -// This can be removed once 10.6 is the minimum (or we have to require 64-bit) whichever comes first. - -typedef ComponentResult (*PtrGraphicsImportSetDataHandle)(GraphicsImportComponent, Handle); -typedef ComponentResult (*PtrGraphicsImportCreateCGImage)(GraphicsImportComponent, CGImageRef*, UInt32); -typedef ComponentResult (*PtrGraphicsExportSetInputCGImage)(GraphicsExportComponent, CGImageRef); -typedef ComponentResult (*PtrGraphicsExportSetOutputHandle)(GraphicsExportComponent, Handle); -typedef ComponentResult (*PtrGraphicsExportDoExport)(GraphicsExportComponent, unsigned long *); - -static PtrGraphicsImportSetDataHandle ptrGraphicsImportSetDataHandle = 0; -static PtrGraphicsImportCreateCGImage ptrGraphicsImportCreateCGImage = 0; -static PtrGraphicsExportSetInputCGImage ptrGraphicsExportSetInputCGImage = 0; -static PtrGraphicsExportSetOutputHandle ptrGraphicsExportSetOutputHandle = 0; -static PtrGraphicsExportDoExport ptrGraphicsExportDoExport = 0; - -static bool resolveMimeQuickTimeSymbols() -{ - if (ptrGraphicsImportSetDataHandle == 0) { - QLibrary library(QLatin1String("/System/Library/Frameworks/QuickTime.framework/QuickTime")); - ptrGraphicsImportSetDataHandle = reinterpret_cast<PtrGraphicsImportSetDataHandle>(library.resolve("GraphicsImportSetDataHandle")); - ptrGraphicsImportCreateCGImage = reinterpret_cast<PtrGraphicsImportCreateCGImage>(library.resolve("GraphicsImportCreateCGImage")); - ptrGraphicsExportSetInputCGImage = reinterpret_cast<PtrGraphicsExportSetInputCGImage>(library.resolve("GraphicsExportSetInputCGImage")); - ptrGraphicsExportSetOutputHandle = reinterpret_cast<PtrGraphicsExportSetOutputHandle>(library.resolve("GraphicsExportSetOutputHandle")); - ptrGraphicsExportDoExport = reinterpret_cast<PtrGraphicsExportDoExport>(library.resolve("GraphicsExportDoExport")); - } - - return ptrGraphicsImportSetDataHandle != 0 - && ptrGraphicsImportCreateCGImage != 0 && ptrGraphicsExportSetInputCGImage != 0 - && ptrGraphicsExportSetOutputHandle != 0 && ptrGraphicsExportDoExport != 0; -} - -class QMacPasteboardMimePict : public QMacPasteboardMime { -public: - QMacPasteboardMimePict() : QMacPasteboardMime(MIME_ALL) { } - QString convertorName(); - - QString flavorFor(const QString &mime); - QString mimeFor(QString flav); - bool canConvert(const QString &mime, QString flav); - QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav); - QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav); -}; - -QString QMacPasteboardMimePict::convertorName() -{ - return QLatin1String("Pict"); -} - -QString QMacPasteboardMimePict::flavorFor(const QString &mime) -{ - if(mime.startsWith(QLatin1String("application/x-qt-image"))) - return QLatin1String("com.apple.pict"); - return QString(); -} - -QString QMacPasteboardMimePict::mimeFor(QString flav) -{ - if(flav == QLatin1String("com.apple.pict")) - return QLatin1String("application/x-qt-image"); - return QString(); -} - -bool QMacPasteboardMimePict::canConvert(const QString &mime, QString flav) -{ - return flav == QLatin1String("com.apple.pict") - && mime == QLatin1String("application/x-qt-image"); -} - - -QVariant QMacPasteboardMimePict::convertToMime(const QString &mime, QList<QByteArray> data, QString flav) -{ - if(data.count() > 1) - qWarning("QMacPasteboardMimePict: Cannot handle multiple member data"); - QVariant ret; - if (!resolveMimeQuickTimeSymbols()) - return ret; - - if(!canConvert(mime, flav)) - return ret; - const QByteArray &a = data.first(); - - // This function expects the 512 header (just to skip it, so create the extra space for it). - Handle pic = NewHandle(a.size() + 512); - memcpy(*pic + 512, a.constData(), a.size()); - - GraphicsImportComponent graphicsImporter; - ComponentResult result = OpenADefaultComponent(GraphicsImporterComponentType, - kQTFileTypePicture, &graphicsImporter); - QCFType<CGImageRef> cgImage; - if (!result) - result = ptrGraphicsImportSetDataHandle(graphicsImporter, pic); - if (!result) - result = ptrGraphicsImportCreateCGImage(graphicsImporter, &cgImage, - kGraphicsImportCreateCGImageUsingCurrentSettings); - if (!result) - ret = QVariant(QPixmap::fromMacCGImageRef(cgImage).toImage()); - CloseComponent(graphicsImporter); - DisposeHandle(pic); - return ret; -} - -QList<QByteArray> QMacPasteboardMimePict::convertFromMime(const QString &mime, QVariant variant, - QString flav) -{ - QList<QByteArray> ret; - if (!resolveMimeQuickTimeSymbols()) - return ret; - - if (!canConvert(mime, flav)) - return ret; - QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(qvariant_cast<QImage>(variant)); - Handle pic = NewHandle(0); - GraphicsExportComponent graphicsExporter; - ComponentResult result = OpenADefaultComponent(GraphicsExporterComponentType, - kQTFileTypePicture, &graphicsExporter); - if (!result) { - unsigned long sizeWritten; - result = ptrGraphicsExportSetInputCGImage(graphicsExporter, cgimage); - if (!result) - result = ptrGraphicsExportSetOutputHandle(graphicsExporter, pic); - if (!result) - result = ptrGraphicsExportDoExport(graphicsExporter, &sizeWritten); - - CloseComponent(graphicsExporter); - } - - int size = GetHandleSize((Handle)pic); - // Skip the Picture File header (512 bytes) and feed the raw data - QByteArray ar(reinterpret_cast<char *>(*pic + 512), size - 512); - ret.append(ar); - DisposeHandle(pic); - return ret; -} - - -#endif //Q_WS_MAC32 - -class QMacPasteboardMimeTiff : public QMacPasteboardMime { -public: - QMacPasteboardMimeTiff() : QMacPasteboardMime(MIME_ALL) { } - QString convertorName(); - - QString flavorFor(const QString &mime); - QString mimeFor(QString flav); - bool canConvert(const QString &mime, QString flav); - QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav); - QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav); -}; - -QString QMacPasteboardMimeTiff::convertorName() -{ - return QLatin1String("Tiff"); -} - -QString QMacPasteboardMimeTiff::flavorFor(const QString &mime) -{ - if(mime.startsWith(QLatin1String("application/x-qt-image"))) - return QLatin1String("public.tiff"); - return QString(); -} - -QString QMacPasteboardMimeTiff::mimeFor(QString flav) -{ - if(flav == QLatin1String("public.tiff")) - return QLatin1String("application/x-qt-image"); - return QString(); -} - -bool QMacPasteboardMimeTiff::canConvert(const QString &mime, QString flav) -{ - return flav == QLatin1String("public.tiff") && mime == QLatin1String("application/x-qt-image"); -} - -QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteArray> data, QString flav) -{ - if(data.count() > 1) - qWarning("QMacPasteboardMimeTiff: Cannot handle multiple member data"); - QVariant ret; - if (!canConvert(mime, flav)) - return ret; - const QByteArray &a = data.first(); - QCFType<CGImageRef> image; - QCFType<CFDataRef> tiffData = CFDataCreateWithBytesNoCopy(0, - reinterpret_cast<const UInt8 *>(a.constData()), - a.size(), kCFAllocatorNull); - QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0); - image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0); - - if (image != 0) - ret = QVariant(QPixmap::fromMacCGImageRef(image).toImage()); - return ret; -} - -QList<QByteArray> QMacPasteboardMimeTiff::convertFromMime(const QString &mime, QVariant variant, QString flav) -{ - QList<QByteArray> ret; - if (!canConvert(mime, flav)) - return ret; - - QImage img = qvariant_cast<QImage>(variant); - QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(img); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0); - QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data, kUTTypeTIFF, 1, 0); - if (imageDestination != 0) { - CFTypeRef keys[2]; - QCFType<CFTypeRef> values[2]; - QCFType<CFDictionaryRef> options; - keys[0] = kCGImagePropertyPixelWidth; - keys[1] = kCGImagePropertyPixelHeight; - int width = img.width(); - int height = img.height(); - values[0] = CFNumberCreate(0, kCFNumberIntType, &width); - values[1] = CFNumberCreate(0, kCFNumberIntType, &height); - options = CFDictionaryCreate(0, reinterpret_cast<const void **>(keys), - reinterpret_cast<const void **>(values), 2, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - CGImageDestinationAddImage(imageDestination, cgimage, options); - CGImageDestinationFinalize(imageDestination); - } - QByteArray ar(CFDataGetLength(data), 0); - CFDataGetBytes(data, - CFRangeMake(0, ar.size()), - reinterpret_cast<UInt8 *>(ar.data())); - ret.append(ar); - } else -#endif - { -#ifdef Q_WS_MAC32 - Handle tiff = NewHandle(0); - if (resolveMimeQuickTimeSymbols()) { - GraphicsExportComponent graphicsExporter; - ComponentResult result = OpenADefaultComponent(GraphicsExporterComponentType, - kQTFileTypeTIFF, &graphicsExporter); - if (!result) { - unsigned long sizeWritten; - result = ptrGraphicsExportSetInputCGImage(graphicsExporter, cgimage); - if (!result) - result = ptrGraphicsExportSetOutputHandle(graphicsExporter, tiff); - if (!result) - result = ptrGraphicsExportDoExport(graphicsExporter, &sizeWritten); - - CloseComponent(graphicsExporter); - } - } - int size = GetHandleSize((Handle)tiff); - QByteArray ar(reinterpret_cast<char *>(*tiff), size); - ret.append(ar); - DisposeHandle(tiff); -#endif - } - return ret; -} - - -class QMacPasteboardMimeFileUri : public QMacPasteboardMime { -public: - QMacPasteboardMimeFileUri() : QMacPasteboardMime(MIME_ALL) { } - QString convertorName(); - - QString flavorFor(const QString &mime); - QString mimeFor(QString flav); - bool canConvert(const QString &mime, QString flav); - QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav); - QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav); -}; - -QString QMacPasteboardMimeFileUri::convertorName() -{ - return QLatin1String("FileURL"); -} - -QString QMacPasteboardMimeFileUri::flavorFor(const QString &mime) -{ - if (mime == QLatin1String("text/uri-list")) - return QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0)); - return QString(); -} - -QString QMacPasteboardMimeFileUri::mimeFor(QString flav) -{ - if (flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0))) - return QLatin1String("text/uri-list"); - return QString(); -} - -bool QMacPasteboardMimeFileUri::canConvert(const QString &mime, QString flav) -{ - return mime == QLatin1String("text/uri-list") - && flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0)); -} - -QVariant QMacPasteboardMimeFileUri::convertToMime(const QString &mime, QList<QByteArray> data, QString flav) -{ - if(!canConvert(mime, flav)) - return QVariant(); - QList<QVariant> ret; - for(int i = 0; i < data.size(); ++i) { - QUrl url = QUrl::fromEncoded(data.at(i)); - if (url.host().toLower() == QLatin1String("localhost")) - url.setHost(QString()); - url.setPath(url.path().normalized(QString::NormalizationForm_C)); - ret.append(url); - } - return QVariant(ret); -} - -QList<QByteArray> QMacPasteboardMimeFileUri::convertFromMime(const QString &mime, QVariant data, QString flav) -{ - QList<QByteArray> ret; - if (!canConvert(mime, flav)) - return ret; - QList<QVariant> urls = data.toList(); - for(int i = 0; i < urls.size(); ++i) { - QUrl url = urls.at(i).toUrl(); - if (url.scheme().isEmpty()) - url.setScheme(QLatin1String("file")); - if (url.scheme().toLower() == QLatin1String("file")) { - if (url.host().isEmpty()) - url.setHost(QLatin1String("localhost")); - url.setPath(url.path().normalized(QString::NormalizationForm_D)); - } - ret.append(url.toEncoded()); - } - return ret; -} - -class QMacPasteboardMimeUrl : public QMacPasteboardMime { -public: - QMacPasteboardMimeUrl() : QMacPasteboardMime(MIME_ALL) { } - QString convertorName(); - - QString flavorFor(const QString &mime); - QString mimeFor(QString flav); - bool canConvert(const QString &mime, QString flav); - QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav); - QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav); -}; - -QString QMacPasteboardMimeUrl::convertorName() -{ - return QLatin1String("URL"); -} - -QString QMacPasteboardMimeUrl::flavorFor(const QString &mime) -{ - if(mime.startsWith(QLatin1String("text/uri-list"))) - return QLatin1String("public.url"); - return QString(); -} - -QString QMacPasteboardMimeUrl::mimeFor(QString flav) -{ - if(flav == QLatin1String("public.url")) - return QLatin1String("text/uri-list"); - return QString(); -} - -bool QMacPasteboardMimeUrl::canConvert(const QString &mime, QString flav) -{ - return flav == QLatin1String("public.url") - && mime == QLatin1String("text/uri-list"); -} - -QVariant QMacPasteboardMimeUrl::convertToMime(const QString &mime, QList<QByteArray> data, QString flav) -{ - if(!canConvert(mime, flav)) - return QVariant(); - - QList<QVariant> ret; - for (int i=0; i<data.size(); ++i) { - QUrl url = QUrl::fromEncoded(data.at(i)); - if (url.host().toLower() == QLatin1String("localhost")) - url.setHost(QString()); - url.setPath(url.path().normalized(QString::NormalizationForm_C)); - ret.append(url); - } - return QVariant(ret); -} - -QList<QByteArray> QMacPasteboardMimeUrl::convertFromMime(const QString &mime, QVariant data, QString flav) -{ - QList<QByteArray> ret; - if (!canConvert(mime, flav)) - return ret; - - QList<QVariant> urls = data.toList(); - for(int i=0; i<urls.size(); ++i) { - QUrl url = urls.at(i).toUrl(); - if (url.scheme().isEmpty()) - url.setScheme(QLatin1String("file")); - if (url.scheme().toLower() == QLatin1String("file")) { - if (url.host().isEmpty()) - url.setHost(QLatin1String("localhost")); - url.setPath(url.path().normalized(QString::NormalizationForm_D)); - } - ret.append(url.toEncoded()); - } - return ret; -} - -class QMacPasteboardMimeVCard : public QMacPasteboardMime -{ -public: - QMacPasteboardMimeVCard() : QMacPasteboardMime(MIME_ALL){ } - QString convertorName(); - - QString flavorFor(const QString &mime); - QString mimeFor(QString flav); - bool canConvert(const QString &mime, QString flav); - QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav); - QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav); -}; - -QString QMacPasteboardMimeVCard::convertorName() -{ - return QString("VCard"); -} - -bool QMacPasteboardMimeVCard::canConvert(const QString &mime, QString flav) -{ - return mimeFor(flav) == mime; -} - -QString QMacPasteboardMimeVCard::flavorFor(const QString &mime) -{ - if(mime.startsWith(QLatin1String("text/plain"))) - return QLatin1String("public.vcard"); - return QString(); -} - -QString QMacPasteboardMimeVCard::mimeFor(QString flav) -{ - if (flav == QLatin1String("public.vcard")) - return QLatin1String("text/plain"); - return QString(); -} - -QVariant QMacPasteboardMimeVCard::convertToMime(const QString &mime, QList<QByteArray> data, QString) -{ - QByteArray cards; - if (mime == QLatin1String("text/plain")) { - for (int i=0; i<data.size(); ++i) - cards += data[i]; - } - return QVariant(cards); -} - -QList<QByteArray> QMacPasteboardMimeVCard::convertFromMime(const QString &mime, QVariant data, QString) -{ - QList<QByteArray> ret; - if (mime == QLatin1String("text/plain")) - ret.append(data.toString().toUtf8()); - return ret; -} - -#ifdef QT3_SUPPORT -class QMacPasteboardMimeQt3Any : public QMacPasteboardMime { -private: - int current_max; - QFile library_file; - QDateTime mime_registry_loaded; - QMap<QString, int> mime_registry; - int registerMimeType(const QString &mime); - bool loadMimeRegistry(); - -public: - QMacPasteboardMimeQt3Any() : QMacPasteboardMime(MIME_QT3_CONVERTOR) { - current_max = 'QT00'; - } - ~QMacPasteboardMimeQt3Any() { - } - QString convertorName(); - - QString flavorFor(const QString &mime); - QString mimeFor(QString flav); - bool canConvert(const QString &mime, QString flav); - QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav); - QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav); -}; - -static bool qt_mac_openMimeRegistry(bool global, QIODevice::OpenMode mode, QFile &file) -{ - QString dir = QLatin1String("/Library/Qt"); - if(!global) - dir.prepend(QDir::homePath()); - file.setFileName(dir + QLatin1String("/.mime_types")); - if(mode != QIODevice::ReadOnly) { - if(!QFile::exists(dir)) { - // Do it with a system call as I don't see much worth in - // doing it with QDir since we have to chmod anyway. - bool success = ::mkdir(dir.toLocal8Bit().constData(), S_IRUSR | S_IWUSR | S_IXUSR) == 0; - if (success) - success = ::chmod(dir.toLocal8Bit().constData(), S_IRUSR | S_IWUSR | S_IXUSR - | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH) == 0; - if (!success) - return false; - } - if (!file.exists()) { - // Create the file and chmod it so that everyone can write to it. - int fd = ::open(file.fileName().toLocal8Bit().constData(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); - bool success = fd != -1; - if (success) - success = ::fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) == 0; - if (fd != -1) - ::close(fd); - if(!success) - return false; - } - } - return file.open(mode); -} - -static void qt_mac_loadMimeRegistry(QFile &file, QMap<QString, int> ®istry, int &max) -{ - file.reset(); - QTextStream stream(&file); - while(!stream.atEnd()) { - QString mime = stream.readLine(); - int mactype = stream.readLine().toInt(); - if(mactype > max) - max = mactype; - registry.insert(mime, mactype); - } -} - -bool QMacPasteboardMimeQt3Any::loadMimeRegistry() -{ - if(!library_file.isOpen()) { - if(!qt_mac_openMimeRegistry(true, QIODevice::ReadWrite, library_file)) { - QFile global; - if(qt_mac_openMimeRegistry(true, QIODevice::ReadOnly, global)) { - qt_mac_loadMimeRegistry(global, mime_registry, current_max); - global.close(); - } - if(!qt_mac_openMimeRegistry(false, QIODevice::ReadWrite, library_file)) { - qWarning("QMacPasteboardMimeAnyQt3Mime: Failure to open mime resources %s -- %s", library_file.fileName().toLatin1().constData(), - library_file.errorString().toLatin1().constData()); - return false; - } - } - } - - QFileInfo fi(library_file); - if(!mime_registry_loaded.isNull() && mime_registry_loaded == fi.lastModified()) - return true; - mime_registry_loaded = fi.lastModified(); - qt_mac_loadMimeRegistry(library_file, mime_registry, current_max); - return true; -} - -int QMacPasteboardMimeQt3Any::registerMimeType(const QString &mime) -{ - if(!mime_registry.contains(mime)) { - if(!loadMimeRegistry()) { - qWarning("QMacPasteboardMimeAnyQt3Mime: Internal error"); - return 0; - } - if(!mime_registry.contains(mime)) { - if(!library_file.isOpen()) { - if(!library_file.open(QIODevice::WriteOnly)) { - qWarning("QMacPasteboardMimeAnyQt3Mime: Failure to open %s -- %s", library_file.fileName().toLatin1().constData(), - library_file.errorString().toLatin1().constData()); - return false; - } - } - int ret = ++current_max; - mime_registry_loaded = QFileInfo(library_file).lastModified(); - QTextStream stream(&library_file); - stream << mime << endl; - stream << ret << endl; - mime_registry.insert(mime, ret); - library_file.flush(); //flush and set mtime - return ret; - } - } - return mime_registry[mime]; -} - -QString QMacPasteboardMimeQt3Any::convertorName() -{ - return QLatin1String("Qt3-Any-Mime"); -} - -QString QMacPasteboardMimeQt3Any::flavorFor(const QString &mime) -{ - const int os_flav = registerMimeType(mime); - QCFType<CFArrayRef> ids = UTTypeCreateAllIdentifiersForTag(0, kUTTagClassOSType, - QCFString(UTCreateStringForOSType(os_flav))); - if(ids) { - const int type_count = CFArrayGetCount(ids); - if(type_count) { - if(type_count > 1) - qDebug("Can't happen!"); - return QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(ids, 0)); - } - } - return QString(); -} - -QString QMacPasteboardMimeQt3Any::mimeFor(QString flav) -{ - loadMimeRegistry(); - const int os_flav = UTGetOSTypeFromString(UTTypeCopyPreferredTagWithClass(QCFString(flav), kUTTagClassOSType)); - for(QMap<QString, int>::const_iterator it = mime_registry.constBegin(); - it != mime_registry.constEnd(); ++it) { - if(it.value() == os_flav) - return QString::fromLatin1(it.key().toLatin1()); - } - return QString(); -} - -bool QMacPasteboardMimeQt3Any::canConvert(const QString &mime, QString flav) -{ - loadMimeRegistry(); - const int os_flav = UTGetOSTypeFromString(UTTypeCopyPreferredTagWithClass(QCFString(flav), kUTTagClassOSType)); - if(mime_registry.contains(mime) && mime_registry[mime] == os_flav) - return true; - return false; -} - -QVariant QMacPasteboardMimeQt3Any::convertToMime(const QString &, QList<QByteArray>, QString) -{ - qWarning("QMacPasteboardMimeAnyQt3Mime: Cannot write anything!"); - return QVariant(); -} - -QList<QByteArray> QMacPasteboardMimeQt3Any::convertFromMime(const QString &mime, QVariant data, QString) -{ - QList<QByteArray> ret; - if (mime == QLatin1String("text/plain")) { - ret.append(data.toString().toUtf8()); - } else { - ret.append(data.toByteArray()); - } - return ret; -} -#endif - -/*! - \internal - - This is an internal function. -*/ -void QMacPasteboardMime::initialize() -{ - if(globalMimeList()->isEmpty()) { - qAddPostRoutine(cleanup_mimes); - - //standard types that we wrap - new QMacPasteboardMimeTiff; -#ifdef Q_WS_MAC32 - // 10.6 does automatic synthesis to and from PICT to standard image types (like TIFF), - // so don't bother doing it ourselves, especially since it's not available in 64-bit. - if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_6) - new QMacPasteboardMimePict; -#endif - new QMacPasteboardMimeUnicodeText; - new QMacPasteboardMimePlainText; - new QMacPasteboardMimeHTMLText; - new QMacPasteboardMimeFileUri; - new QMacPasteboardMimeUrl; - new QMacPasteboardMimeTypeName; - new QMacPasteboardMimeVCard; - //make sure our "non-standard" types are always last! --Sam - new QMacPasteboardMimeAny; -#ifdef QT3_SUPPORT - new QMacPasteboardMimeQt3Any; -#endif - } -} - -/*! - Returns the most-recently created QMacPasteboardMime of type \a t that can convert - between the \a mime and \a flav formats. Returns 0 if no such convertor - exists. -*/ -QMacPasteboardMime* -QMacPasteboardMime::convertor(uchar t, const QString &mime, QString flav) -{ - MimeList *mimes = globalMimeList(); - for(MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) { -#ifdef DEBUG_MIME_MAPS - qDebug("QMacPasteboardMime::convertor: seeing if %s (%d) can convert %s to %d[%c%c%c%c] [%d]", - (*it)->convertorName().toLatin1().constData(), - (*it)->type & t, mime.toLatin1().constData(), - flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF, - (*it)->canConvert(mime,flav)); - for(int i = 0; i < (*it)->countFlavors(); ++i) { - int f = (*it)->flavor(i); - qDebug(" %d) %d[%c%c%c%c] [%s]", i, f, - (f >> 24) & 0xFF, (f >> 16) & 0xFF, (f >> 8) & 0xFF, (f) & 0xFF, - (*it)->convertorName().toLatin1().constData()); - } -#endif - if(((*it)->type & t) && (*it)->canConvert(mime, flav)) - return (*it); - } - return 0; -} -/*! - Returns a MIME type of type \a t for \a flav, or 0 if none exists. -*/ -QString QMacPasteboardMime::flavorToMime(uchar t, QString flav) -{ - MimeList *mimes = globalMimeList(); - for(MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) { -#ifdef DEBUG_MIME_MAPS - qDebug("QMacMIme::flavorToMime: attempting %s (%d) for flavor %d[%c%c%c%c] [%s]", - (*it)->convertorName().toLatin1().constData(), - (*it)->type & t, flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF, - (*it)->mimeFor(flav).toLatin1().constData()); - -#endif - if((*it)->type & t) { - QString mimeType = (*it)->mimeFor(flav); - if(!mimeType.isNull()) - return mimeType; - } - } - return QString(); -} - -/*! - Returns a list of all currently defined QMacPasteboardMime objects of type \a t. -*/ -QList<QMacPasteboardMime*> QMacPasteboardMime::all(uchar t) -{ - MimeList ret; - MimeList *mimes = globalMimeList(); - for(MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) { - if((*it)->type & t) - ret.append((*it)); - } - return ret; -} - - -/*! - \fn QString QMacPasteboardMime::convertorName() - - Returns a name for the convertor. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! - \fn bool QMacPasteboardMime::canConvert(const QString &mime, QString flav) - - Returns true if the convertor can convert (both ways) between - \a mime and \a flav; otherwise returns false. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! - \fn QString QMacPasteboardMime::mimeFor(QString flav) - - Returns the MIME UTI used for Mac flavor \a flav, or 0 if this - convertor does not support \a flav. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! - \fn QString QMacPasteboardMime::flavorFor(const QString &mime) - - Returns the Mac UTI used for MIME type \a mime, or 0 if this - convertor does not support \a mime. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! - \fn QVariant QMacPasteboardMime::convertToMime(const QString &mime, QList<QByteArray> data, QString flav) - - Returns \a data converted from Mac UTI \a flav to MIME type \a - mime. - - Note that Mac flavors must all be self-terminating. The input \a - data may contain trailing data. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! - \fn QList<QByteArray> QMacPasteboardMime::convertFromMime(const QString &mime, QVariant data, QString flav) - - Returns \a data converted from MIME type \a mime - to Mac UTI \a flav. - - Note that Mac flavors must all be self-terminating. The return - value may contain trailing data. - - All subclasses must reimplement this pure virtual function. -*/ - - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qmultitouch_mac.mm b/src/gui/platforms/mac/qmultitouch_mac.mm deleted file mode 100644 index d9e845a01c..0000000000 --- a/src/gui/platforms/mac/qmultitouch_mac.mm +++ /dev/null @@ -1,218 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qmultitouch_mac_p.h> -#include <qcursor.h> - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - -QT_BEGIN_NAMESPACE - -#ifdef QT_MAC_USE_COCOA - -QHash<qint64, QCocoaTouch*> QCocoaTouch::_currentTouches; -QPointF QCocoaTouch::_screenReferencePos; -QPointF QCocoaTouch::_trackpadReferencePos; -int QCocoaTouch::_idAssignmentCount = 0; -int QCocoaTouch::_touchCount = 0; -bool QCocoaTouch::_updateInternalStateOnly = true; - -QCocoaTouch::QCocoaTouch(NSTouch *nstouch) -{ - if (_currentTouches.size() == 0) - _idAssignmentCount = 0; - - _touchPoint.setId(_idAssignmentCount++); - _touchPoint.setPressure(1.0); - _identity = qint64([nstouch identity]); - _currentTouches.insert(_identity, this); - updateTouchData(nstouch, NSTouchPhaseBegan); -} - -QCocoaTouch::~QCocoaTouch() -{ - _currentTouches.remove(_identity); -} - -void QCocoaTouch::updateTouchData(NSTouch *nstouch, NSTouchPhase phase) -{ - if (_touchCount == 1) - _touchPoint.setState(toTouchPointState(phase) | Qt::TouchPointPrimary); - else - _touchPoint.setState(toTouchPointState(phase)); - - // From the normalized position on the trackpad, calculate - // where on screen the touchpoint should be according to the - // reference position: - NSPoint npos = [nstouch normalizedPosition]; - QPointF qnpos = QPointF(npos.x, 1 - npos.y); - _touchPoint.setNormalizedPos(qnpos); - - if (_touchPoint.id() == 0 && phase == NSTouchPhaseBegan) { - _trackpadReferencePos = qnpos; - _screenReferencePos = QCursor::pos(); - } - - NSSize dsize = [nstouch deviceSize]; - float ppiX = (qnpos.x() - _trackpadReferencePos.x()) * dsize.width; - float ppiY = (qnpos.y() - _trackpadReferencePos.y()) * dsize.height; - QPointF relativePos = _trackpadReferencePos - QPointF(ppiX, ppiY); - _touchPoint.setScreenPos(_screenReferencePos - relativePos); -} - -QCocoaTouch *QCocoaTouch::findQCocoaTouch(NSTouch *nstouch) -{ - qint64 identity = qint64([nstouch identity]); - if (_currentTouches.contains(identity)) - return _currentTouches.value(identity); - return 0; -} - -Qt::TouchPointState QCocoaTouch::toTouchPointState(NSTouchPhase nsState) -{ - Qt::TouchPointState qtState = Qt::TouchPointReleased; - switch (nsState) { - case NSTouchPhaseBegan: - qtState = Qt::TouchPointPressed; - break; - case NSTouchPhaseMoved: - qtState = Qt::TouchPointMoved; - break; - case NSTouchPhaseStationary: - qtState = Qt::TouchPointStationary; - break; - case NSTouchPhaseEnded: - case NSTouchPhaseCancelled: - qtState = Qt::TouchPointReleased; - break; - default: - break; - } - return qtState; -} - -QList<QTouchEvent::TouchPoint> -QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch) -{ - QMap<int, QTouchEvent::TouchPoint> touchPoints; - NSSet *ended = [event touchesMatchingPhase:NSTouchPhaseEnded | NSTouchPhaseCancelled inView:nil]; - NSSet *active = [event - touchesMatchingPhase:NSTouchPhaseBegan | NSTouchPhaseMoved | NSTouchPhaseStationary - inView:nil]; - _touchCount = [active count]; - - // First: remove touches that were ended by the user. If we are - // currently not accepting single touches, a corresponding 'begin' - // has never been send to the app for these events. - // So should therefore not send the following removes either. - - for (int i=0; i<int([ended count]); ++i) { - NSTouch *touch = [[ended allObjects] objectAtIndex:i]; - QCocoaTouch *qcocoaTouch = findQCocoaTouch(touch); - if (qcocoaTouch) { - qcocoaTouch->updateTouchData(touch, [touch phase]); - if (!_updateInternalStateOnly) - touchPoints.insert(qcocoaTouch->_touchPoint.id(), qcocoaTouch->_touchPoint); - delete qcocoaTouch; - } - } - - bool wasUpdateInternalStateOnly = _updateInternalStateOnly; - _updateInternalStateOnly = !acceptSingleTouch && _touchCount < 2; - - // Next: update, or create, existing touches. - // We always keep track of all touch points, even - // when not accepting single touches. - - for (int i=0; i<int([active count]); ++i) { - NSTouch *touch = [[active allObjects] objectAtIndex:i]; - QCocoaTouch *qcocoaTouch = findQCocoaTouch(touch); - if (!qcocoaTouch) - qcocoaTouch = new QCocoaTouch(touch); - else - qcocoaTouch->updateTouchData(touch, wasUpdateInternalStateOnly ? NSTouchPhaseBegan : [touch phase]); - if (!_updateInternalStateOnly) - touchPoints.insert(qcocoaTouch->_touchPoint.id(), qcocoaTouch->_touchPoint); - } - - // Next: sadly, we need to check that our touch hash is in - // sync with cocoa. This is typically not the case after a system - // gesture happend (like a four-finger-swipe to show expose). - - if (_touchCount != _currentTouches.size()) { - // Remove all instances, and basically start from scratch: - touchPoints.clear(); - foreach (QCocoaTouch *qcocoaTouch, _currentTouches.values()) { - if (!_updateInternalStateOnly) { - qcocoaTouch->_touchPoint.setState(Qt::TouchPointReleased); - touchPoints.insert(qcocoaTouch->_touchPoint.id(), qcocoaTouch->_touchPoint); - } - delete qcocoaTouch; - } - _currentTouches.clear(); - _updateInternalStateOnly = !acceptSingleTouch; - return touchPoints.values(); - } - - // Finally: If this call _started_ to reject single - // touches, we need to fake a relase for the remaining - // touch now (and refake a begin for it later, if needed). - - if (_updateInternalStateOnly && !wasUpdateInternalStateOnly && !_currentTouches.isEmpty()) { - QCocoaTouch *qcocoaTouch = _currentTouches.values().first(); - qcocoaTouch->_touchPoint.setState(Qt::TouchPointReleased); - touchPoints.insert(qcocoaTouch->_touchPoint.id(), qcocoaTouch->_touchPoint); - // Since this last touch also will end up beeing the first - // touch (if the user adds a second finger without lifting - // the first), we promote it to be the primary touch: - qcocoaTouch->_touchPoint.setId(0); - _idAssignmentCount = 1; - } - - return touchPoints.values(); -} - -#endif - -QT_END_NAMESPACE - -#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - diff --git a/src/gui/platforms/mac/qmultitouch_mac_p.h b/src/gui/platforms/mac/qmultitouch_mac_p.h deleted file mode 100644 index 16be930d0a..0000000000 --- a/src/gui/platforms/mac/qmultitouch_mac_p.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QMULTITOUCH_MAC_P_H -#define QMULTITOUCH_MAC_P_H - -#ifdef QT_MAC_USE_COCOA -#import <Cocoa/Cocoa.h> -#endif - -#include <qevent.h> -#include <qhash.h> -#include <QtCore> - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - -QT_BEGIN_NAMESPACE - -#ifdef QT_MAC_USE_COCOA - -class QCocoaTouch -{ - public: - static QList<QTouchEvent::TouchPoint> getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch); - static void setMouseInDraggingState(bool inDraggingState); - - private: - static QHash<qint64, QCocoaTouch*> _currentTouches; - static QPointF _screenReferencePos; - static QPointF _trackpadReferencePos; - static int _idAssignmentCount; - static int _touchCount; - static bool _updateInternalStateOnly; - - QTouchEvent::TouchPoint _touchPoint; - qint64 _identity; - - QCocoaTouch(NSTouch *nstouch); - ~QCocoaTouch(); - - void updateTouchData(NSTouch *nstouch, NSTouchPhase phase); - static QCocoaTouch *findQCocoaTouch(NSTouch *nstouch); - static Qt::TouchPointState toTouchPointState(NSTouchPhase nsState); -}; - -#endif // QT_MAC_USE_COCOA - -QT_END_NAMESPACE - -#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - -#endif // QMULTITOUCH_MAC_P_H - diff --git a/src/gui/platforms/mac/qnsframeview_mac_p.h b/src/gui/platforms/mac/qnsframeview_mac_p.h deleted file mode 100644 index 6ec3f64efa..0000000000 --- a/src/gui/platforms/mac/qnsframeview_mac_p.h +++ /dev/null @@ -1,154 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp -// and many other. This header file may change from version to version -// without notice, or even be removed. -// -// We mean it. -// - -// Private AppKit class (dumped from classdump). - -#import <Cocoa/Cocoa.h> - -@interface NSFrameView : NSView -{ - unsigned int styleMask; - NSString *_title; - NSCell *titleCell; - NSButton *closeButton; - NSButton *zoomButton; - NSButton *minimizeButton; - char resizeByIncrement; - char frameNeedsDisplay; - unsigned char tabViewCount; - NSSize resizeParameter; - int shadowState; -} - -+ (void)initialize; -+ (void)initTitleCell:fp8 styleMask:(unsigned int)fp12; -+ (struct _NSRect)frameRectForContentRect:(struct _NSRect)fp8 styleMask:(unsigned int)fp24; -+ (struct _NSRect)contentRectForFrameRect:(struct _NSRect)fp8 styleMask:(unsigned int)fp24; -+ (struct _NSSize)minFrameSizeForMinContentSize:(struct _NSSize)fp8 styleMask:(unsigned int)fp16; -+ (struct _NSSize)minContentSizeForMinFrameSize:(struct _NSSize)fp8 styleMask:(unsigned int)fp16; -+ (float)minFrameWidthWithTitle:fp8 styleMask:(unsigned int)fp12; -+ (unsigned int)_validateStyleMask:(unsigned int)fp8; -- initWithFrame:(struct _NSRect)fp8 styleMask:(unsigned int)fp24 owner:fp28; -- initWithFrame:(struct _NSRect)fp8; -- (void)dealloc; -- (void)shapeWindow; -- (void)tileAndSetWindowShape:(char)fp8; -- (void)tile; -- (void)drawRect:(struct _NSRect)fp8; -- (void)_drawFrameRects:(struct _NSRect)fp8; -- (void)drawFrame:(struct _NSRect)fp8; -- (void)drawThemeContentFill:(struct _NSRect)fp8 inView:fp24; -- (void)drawWindowBackgroundRect:(struct _NSRect)fp8; -- (void)drawWindowBackgroundRegion:(void *)fp8; -- (float)contentAlpha; -- (void)_windowChangedKeyState; -- (void)_updateButtonState; -- (char)_isSheet; -- (char)_isUtility; -- (void)setShadowState:(int)fp8; -- (int)shadowState; -- (char)_canHaveToolbar; -- (char)_toolbarIsInTransition; -- (char)_toolbarIsShown; -- (char)_toolbarIsHidden; -- (void)_showToolbarWithAnimation:(char)fp8; -- (void)_hideToolbarWithAnimation:(char)fp8; -- (float)_distanceFromToolbarBaseToTitlebar; -- (int)_shadowType; -- (unsigned int)_shadowFlags; -- (void)_setShadowParameters; -- (void)_drawFrameShadowAndFlushContext:fp8; -- (void)setUpGState; -- (void)adjustHalftonePhase; -- (void)systemColorsDidChange:fp8; -- frameColor; -- contentFill; -- (void)tabViewAdded; -- (void)tabViewRemoved; -- title; -- (void)setTitle:fp8; -- titleCell; -- (void)initTitleCell:fp8; -- (void)setResizeIncrements:(struct _NSSize)fp8; -- (struct _NSSize)resizeIncrements; -- (void)setAspectRatio:(struct _NSSize)fp8; -- (struct _NSSize)aspectRatio; -- (unsigned int)styleMask; -- representedFilename; -- (void)setRepresentedFilename:fp8; -- (void)setDocumentEdited:(char)fp8; -- (void)_setFrameNeedsDisplay:(char)fp8; -- (char)frameNeedsDisplay; -- titleFont; -- (struct _NSRect)_maxTitlebarTitleRect; -- (struct _NSRect)titlebarRect; -- (void)_setUtilityWindow:(char)fp8; -- (void)_setNonactivatingPanel:(char)fp8; -- (void)setIsClosable:(char)fp8; -- (void)setIsResizable:(char)fp8; -- closeButton; -- minimizeButton; -- zoomButton; -- (struct _NSSize)miniaturizedSize; -- (void)_clearDragMargins; -- (void)_resetDragMargins; -- (void)setTitle:fp8 andDefeatWrap:(char)fp12; -- (struct _NSRect)frameRectForContentRect:(struct _NSRect)fp8 styleMask:(unsigned int)fp24; -- (struct _NSRect)contentRectForFrameRect:(struct _NSRect)fp8 styleMask:(unsigned int)fp24; -- (struct _NSSize)minFrameSizeForMinContentSize:(struct _NSSize)fp8 styleMask:(unsigned int)fp16; -- (struct _NSRect)dragRectForFrameRect:(struct _NSRect)fp8; -- (struct _NSRect)contentRect; -- (struct _NSSize)minFrameSize; -- (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(struct _NSRect)fp8 isVisibleRect:(char)fp24 rectIsVisibleRectForView:fp28 topView:(char)fp32; - -@end diff --git a/src/gui/platforms/mac/qnsthemeframe_mac_p.h b/src/gui/platforms/mac/qnsthemeframe_mac_p.h deleted file mode 100644 index 2cb4916c06..0000000000 --- a/src/gui/platforms/mac/qnsthemeframe_mac_p.h +++ /dev/null @@ -1,246 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp -// and many other. This header file may change from version to version -// without notice, or even be removed. -// -// We mean it. -// - -// Private AppKit class (dumped from classdump). - -#import <Cocoa/Cocoa.h> -#import "qnstitledframe_mac_p.h" - -@interface NSThemeFrame : NSTitledFrame -{ - NSButton *toolbarButton; - int toolbarVisibleStatus; - NSImage *showToolbarTransitionImage; - NSSize showToolbarPreWindowSize; - NSButton *modeButton; - int leftGroupTrackingTagNum; - int rightGroupTrackingTagNum; - char mouseInsideLeftGroup; - char mouseInsideRightGroup; - int widgetState; - NSString *displayName; -} - -+ (void)initialize; -+ (float)_windowBorderThickness:(unsigned int)fp8; -+ (float)_minXWindowBorderWidth:(unsigned int)fp8; -+ (float)_maxXWindowBorderWidth:(unsigned int)fp8; -+ (float)_minYWindowBorderHeight:(unsigned int)fp8; -+ (float)_windowTitlebarButtonSpacingWidth:(unsigned int)fp8; -+ (float)_windowFileButtonSpacingWidth:(unsigned int)fp8; -+ (float)_minXTitlebarWidgetInset:(unsigned int)fp8; -+ (float)_maxXTitlebarWidgetInset:(unsigned int)fp8; -+ (float)minFrameWidthWithTitle:fp8 styleMask:(unsigned int)fp12; -+ (float)_windowSideTitlebarTitleMinWidth:(unsigned int)fp8; -+ (float)_windowTitlebarTitleMinHeight:(unsigned int)fp8; -+ (float)_sideTitlebarWidth:(unsigned int)fp8; -+ (float)_titlebarHeight:(unsigned int)fp8; -+ (float)_resizeHeight:(unsigned int)fp8; -+ (char)_resizeFromEdge; -+ (struct _NSSize)sizeOfTitlebarButtons:(unsigned int)fp8; -+ (float)_contentToFrameMinXWidth:(unsigned int)fp8; -+ (float)_contentToFrameMaxXWidth:(unsigned int)fp8; -+ (float)_contentToFrameMinYHeight:(unsigned int)fp8; -+ (float)_contentToFrameMaxYHeight:(unsigned int)fp8; -+ (unsigned int)_validateStyleMask:(unsigned int)fp8; -- (struct _NSSize)_topCornerSize; -- (struct _NSSize)_bottomCornerSize; -- (void *)_createWindowOpaqueShape; -- (void)shapeWindow; -- (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)fp8 isVisibleRect:(char)fp24 rectIsVisibleRectForView:fp28 topView:(char)fp32; -- (void *)_regionForOpaqueDescendants:(NSRect)fp8 forMove:(char)fp24; -- (void)_drawFrameInterior:(NSRect *)fp8 clip:(NSRect)fp12; -- (void)_setTextShadow:(char)fp8; -- (void)_drawTitleBar:(NSRect)fp8; -- (void)_drawResizeIndicators:(NSRect)fp8; -- (void)_drawFrameRects:(NSRect)fp8; -- (void)drawFrame:(NSRect)fp8; -- contentFill; -- (void)viewDidEndLiveResize; -- (float)contentAlpha; -- (void)setThemeFrameWidgetState:(int)fp8; -- (char)constrainResizeEdge:(int *)fp8 withDelta:(struct _NSSize)fp12 elapsedTime:(float)fp20; -- (void)addFileButton:fp8; -- (void)_updateButtons; -- (void)_updateButtonState; -- newCloseButton; -- newZoomButton; -- newMiniaturizeButton; -- newToolbarButton; -- newFileButton; -- (void)_resetTitleBarButtons; -- (void)setDocumentEdited:(char)fp8; -- toolbarButton; -- modeButton; -- initWithFrame:(NSRect)fp8 styleMask:(unsigned int)fp24 owner:fp28; -- (void)dealloc; -- (void)setFrameSize:(struct _NSSize)fp8; -- (char)_canHaveToolbar; -- (char)_toolbarIsInTransition; -- (char)_toolbarIsShown; -- (char)_toolbarIsHidden; -- _toolbarView; -- _toolbar; -- (float)_distanceFromToolbarBaseToTitlebar; -- (unsigned int)_shadowFlags; -- (NSRect)frameRectForContentRect:(NSRect)fp8 styleMask:(unsigned int)fp24; -- (NSRect)contentRectForFrameRect:(NSRect)fp8 styleMask:(unsigned int)fp24; -- (struct _NSSize)minFrameSizeForMinContentSize:(struct _NSSize)fp8 styleMask:(unsigned int)fp16; -- (NSRect)contentRect; -- (NSRect)_contentRectExcludingToolbar; -- (NSRect)_contentRectIncludingToolbarAtHome; -- (void)_setToolbarShowHideResizeWeightingOptimizationOn:(char)fp8; -- (char)_usingToolbarShowHideWeightingOptimization; -- (void)handleSetFrameCommonRedisplay; -- (void)_startLiveResizeAsTopLevel; -- (void)_endLiveResizeAsTopLevel; -- (void)_growContentReshapeContentAndToolbarView:(int)fp8 animate:(char)fp12; -- (char)_growWindowReshapeContentAndToolbarView:(int)fp8 animate:(char)fp12; -- (void)_reshapeContentAndToolbarView:(int)fp8 resizeWindow:(char)fp12 animate:(char)fp16; -- (void)_toolbarFrameSizeChanged:fp8 oldSize:(struct _NSSize)fp12; -- (void)_syncToolbarPosition; -- (void)_showHideToolbar:(int)fp8 resizeWindow:(char)fp12 animate:(char)fp16; -- (void)_showToolbarWithAnimation:(char)fp8; -- (void)_hideToolbarWithAnimation:(char)fp8; -- (void)_drawToolbarTransitionIfNecessary; -- (void)drawRect:(NSRect)fp8; -- (void)resetCursorRects; -- (char)shouldBeTreatedAsInkEvent:fp8; -- (char)_shouldBeTreatedAsInkEventInInactiveWindow:fp8; -//- hitTest:(struct _NSPoint)fp8; // collides with hittest in qcocoasharedwindowmethods_mac_p.h -- (NSRect)_leftGroupRect; -- (NSRect)_rightGroupRect; -- (void)_updateWidgets; -- (void)_updateMouseTracking; -- (void)mouseEntered:fp8; -- (void)mouseExited:fp8; -- (void)_setMouseEnteredGroup:(char)fp8 entered:(char)fp12; -- (char)_mouseInGroup:fp8; -- (struct _NSSize)miniaturizedSize; -- (float)_minXTitlebarDecorationMinWidth; -- (float)_maxXTitlebarDecorationMinWidth; -- (struct _NSSize)minFrameSize; -- (float)_windowBorderThickness; -- (float)_windowTitlebarXResizeBorderThickness; -- (float)_windowTitlebarYResizeBorderThickness; -- (float)_windowResizeBorderThickness; -- (float)_minXWindowBorderWidth; -- (float)_maxXWindowBorderWidth; -- (float)_minYWindowBorderHeight; -- (float)_maxYWindowBorderHeight; -- (float)_minYTitlebarButtonsOffset; -- (float)_minYTitlebarTitleOffset; -- (float)_sideTitlebarWidth; -- (float)_titlebarHeight; -- (NSRect)_titlebarTitleRect; -- (NSRect)titlebarRect; -- (float)_windowTitlebarTitleMinHeight; -- (struct _NSSize)_sizeOfTitlebarFileButton; -- (struct _NSSize)sizeOfTitlebarToolbarButton; -- (float)_windowTitlebarButtonSpacingWidth; -- (float)_windowFileButtonSpacingWidth; -- (float)_minXTitlebarWidgetInset; -- (float)_maxXTitlebarWidgetInset; -- (float)_minXTitlebarButtonsWidth; -- (float)_maxXTitlebarButtonsWidth; -- (struct _NSPoint)_closeButtonOrigin; -- (struct _NSPoint)_zoomButtonOrigin; -- (struct _NSPoint)_collapseButtonOrigin; -- (struct _NSPoint)_toolbarButtonOrigin; -- (struct _NSPoint)_fileButtonOrigin; -- (void)_tileTitlebar; -- (NSRect)_commandPopupRect; -- (void)_resetDragMargins; -- (float)_maxYTitlebarDragHeight; -- (float)_minXTitlebarDragWidth; -- (float)_maxXTitlebarDragWidth; -- (float)_contentToFrameMinXWidth; -- (float)_contentToFrameMaxXWidth; -- (float)_contentToFrameMinYHeight; -- (float)_contentToFrameMaxYHeight; -- (float)_windowResizeCornerThickness; -- (NSRect)_minYResizeRect; -- (NSRect)_minYminXResizeRect; -- (NSRect)_minYmaxXResizeRect; -- (NSRect)_minXResizeRect; -- (NSRect)_minXminYResizeRect; -- (NSRect)_minXmaxYResizeRect; -- (NSRect)_maxYResizeRect; -- (NSRect)_maxYminXResizeRect; -- (NSRect)_maxYmaxXResizeRect; -- (NSRect)_maxXResizeRect; -- (NSRect)_maxXminYResizeRect; -- (NSRect)_maxXmaxYResizeRect; -- (NSRect)_minXTitlebarResizeRect; -- (NSRect)_maxXTitlebarResizeRect; -- (NSRect)_minXBorderRect; -- (NSRect)_maxXBorderRect; -- (NSRect)_maxYBorderRect; -- (NSRect)_minYBorderRect; -- (void)_setUtilityWindow:(char)fp8; -- (char)_isUtility; -- (float)_sheetHeightAdjustment; -- (void)_setSheet:(char)fp8; -- (char)_isSheet; -- (char)_isResizable; -- (char)_isClosable; -- (char)_isMiniaturizable; -- (char)_hasToolbar; -- (NSRect)_growBoxRect; -- (void)_drawGrowBoxWithClip:(NSRect)fp8; -- (char)_inactiveButtonsNeedMask; -- (void)mouseDown:fp8; -- _displayName; -- (void)_setDisplayName:fp8; - -@end diff --git a/src/gui/platforms/mac/qnstitledframe_mac_p.h b/src/gui/platforms/mac/qnstitledframe_mac_p.h deleted file mode 100644 index 4eb5332194..0000000000 --- a/src/gui/platforms/mac/qnstitledframe_mac_p.h +++ /dev/null @@ -1,205 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp -// and many other. This header file may change from version to version -// without notice, or even be removed. -// -// We mean it. -// - -// Private AppKit class (dumped from classdump). - -#import <Cocoa/Cocoa.h> -#import "qnsframeview_mac_p.h" - - -@interface NSTitledFrame : NSFrameView -{ - int resizeFlags; - id fileButton; /* NSDocumentDragButton* */ - NSSize titleCellSize; -} - -+ (float)_windowBorderThickness:(unsigned int)fp8; -+ (float)_minXWindowBorderWidth:(unsigned int)fp8; -+ (float)_maxXWindowBorderWidth:(unsigned int)fp8; -+ (float)_minYWindowBorderHeight:(unsigned int)fp8; -+ (char)_resizeFromEdge; -+ (NSRect)frameRectForContentRect:(NSRect)fp8 styleMask:(unsigned int)fp24; -+ (NSRect)contentRectForFrameRect:(NSRect)fp8 styleMask:(unsigned int)fp24; -+ (struct _NSSize)minFrameSizeForMinContentSize:(struct _NSSize)fp8 styleMask:(unsigned int)fp16; -+ (struct _NSSize)minContentSizeForMinFrameSize:(struct _NSSize)fp8 styleMask:(unsigned int)fp16; -+ (float)minFrameWidthWithTitle:fp8 styleMask:(unsigned int)fp12; -+ (struct _NSSize)_titleCellSizeForTitle:fp8 styleMask:(unsigned int)fp12; -+ (float)_titleCellHeight:(unsigned int)fp8; -+ (float)_windowTitlebarTitleMinHeight:(unsigned int)fp8; -+ (float)_titlebarHeight:(unsigned int)fp8; -+ (struct _NSSize)sizeOfTitlebarButtons:(unsigned int)fp8; -+ (float)windowTitlebarLinesSpacingWidth:(unsigned int)fp8; -+ (float)windowTitlebarTitleLinesSpacingWidth:(unsigned int)fp8; -+ (float)_contentToFrameMinXWidth:(unsigned int)fp8; -+ (float)_contentToFrameMaxXWidth:(unsigned int)fp8; -+ (float)_contentToFrameMinYHeight:(unsigned int)fp8; -+ (float)_contentToFrameMaxYHeight:(unsigned int)fp8; -- initWithFrame:(NSRect)fp8 styleMask:(unsigned int)fp24 owner:fp28; -- (void)dealloc; -- (void)setIsClosable:(char)fp8; -- (void)setIsResizable:(char)fp8; -- (void)_resetTitleFont; -- (void)_setUtilityWindow:(char)fp8; -- (char)isOpaque; -- (char)worksWhenModal; -- (void)propagateFrameDirtyRects:(NSRect)fp8; -- (void)_showDrawRect:(NSRect)fp8; -- (void)_drawFrameInterior:(NSRect *)fp8 clip:(NSRect)fp12; -- (void)drawFrame:(NSRect)fp8; -- (void)_drawFrameRects:(NSRect)fp8; -- (void)_drawTitlebar:(NSRect)fp8; -- (void)_drawTitlebarPattern:(int)fp8 inRect:(NSRect)fp12 clippedByRect:(NSRect)fp28 forKey:(char)fp44 alignment:(int)fp48; -- (void)_drawTitlebarLines:(int)fp8 inRect:(NSRect)fp12 clippedByRect:(NSRect)fp28; -- frameHighlightColor; -- frameShadowColor; -- (void)setFrameSize:(struct _NSSize)fp8; -- (void)setFrameOrigin:(struct _NSPoint)fp8; -- (void)tileAndSetWindowShape:(char)fp8; -- (void)tile; -- (void)_tileTitlebar; -- (void)setTitle:fp8; -- (char)_shouldRepresentFilename; -- (void)setRepresentedFilename:fp8; -- (void)_drawTitleStringIn:(NSRect)fp8 withColor:fp24; -- titleFont; -- (void)_drawResizeIndicators:(NSRect)fp8; -- titleButtonOfClass:(Class)fp8; -- initTitleButton:fp8; -- newCloseButton; -- newZoomButton; -- newMiniaturizeButton; -- newFileButton; -- fileButton; -- (void)_removeButtons; -- (void)_updateButtons; -- (char)_eventInTitlebar:fp8; -- (char)acceptsFirstMouse:fp8; -- (void)mouseDown:fp8; -- (void)mouseUp:fp8; -- (void)rightMouseDown:fp8; -- (void)rightMouseUp:fp8; -- (int)resizeEdgeForEvent:fp8; -- (struct _NSSize)_resizeDeltaFromPoint:(struct _NSPoint)fp8 toEvent:fp16; -- (NSRect)_validFrameForResizeFrame:(NSRect)fp8 fromResizeEdge:(int)fp24; -- (NSRect)frame:(NSRect)fp8 resizedFromEdge:(int)fp24 withDelta:(struct _NSSize)fp28; -- (char)constrainResizeEdge:(int *)fp8 withDelta:(struct _NSSize)fp12 elapsedTime:(float)fp20; -- (void)resizeWithEvent:fp8; -- (int)resizeFlags; -- (void)resetCursorRects; -- (void)setDocumentEdited:(char)fp8; -- (struct _NSSize)miniaturizedSize; -- (struct _NSSize)minFrameSize; -- (float)_windowBorderThickness; -- (float)_windowTitlebarXResizeBorderThickness; -- (float)_windowTitlebarYResizeBorderThickness; -- (float)_windowResizeBorderThickness; -- (float)_minXWindowBorderWidth; -- (float)_maxXWindowBorderWidth; -- (float)_minYWindowBorderHeight; -- (void)_invalidateTitleCellSize; -- (void)_invalidateTitleCellWidth; -- (float)_titleCellHeight; -- (struct _NSSize)_titleCellSize; -- (float)_titlebarHeight; -- (NSRect)titlebarRect; -- (NSRect)_maxTitlebarTitleRect; -- (NSRect)_titlebarTitleRect; -- (float)_windowTitlebarTitleMinHeight; -- (NSRect)dragRectForFrameRect:(NSRect)fp8; -- (struct _NSSize)sizeOfTitlebarButtons; -- (struct _NSSize)_sizeOfTitlebarFileButton; -- (float)_windowTitlebarButtonSpacingWidth; -- (float)_minXTitlebarButtonsWidth; -- (float)_maxXTitlebarButtonsWidth; -- (int)_numberOfTitlebarLines; -- (float)windowTitlebarLinesSpacingWidth; -- (float)windowTitlebarTitleLinesSpacingWidth; -- (float)_minLinesWidthWithSpace; -- (NSRect)_minXTitlebarLinesRectWithTitleCellRect:(NSRect)fp8; -- (NSRect)_maxXTitlebarLinesRectWithTitleCellRect:(NSRect)fp8; -- (float)_minXTitlebarDecorationMinWidth; -- (float)_maxXTitlebarDecorationMinWidth; -- (struct _NSPoint)_closeButtonOrigin; -- (struct _NSPoint)_zoomButtonOrigin; -- (struct _NSPoint)_collapseButtonOrigin; -- (struct _NSPoint)_fileButtonOrigin; -- (float)_maxYTitlebarDragHeight; -- (float)_minXTitlebarDragWidth; -- (float)_maxXTitlebarDragWidth; -- (float)_contentToFrameMinXWidth; -- (float)_contentToFrameMaxXWidth; -- (float)_contentToFrameMinYHeight; -- (float)_contentToFrameMaxYHeight; -- (NSRect)contentRect; -- (float)_windowResizeCornerThickness; -- (NSRect)_minYResizeRect; -- (NSRect)_minYminXResizeRect; -- (NSRect)_minYmaxXResizeRect; -- (NSRect)_minXResizeRect; -- (NSRect)_minXminYResizeRect; -- (NSRect)_minXmaxYResizeRect; -- (NSRect)_maxYResizeRect; -- (NSRect)_maxYminXResizeRect; -- (NSRect)_maxYmaxXResizeRect; -- (NSRect)_maxXResizeRect; -- (NSRect)_maxXminYResizeRect; -- (NSRect)_maxXmaxYResizeRect; -- (NSRect)_minXTitlebarResizeRect; -- (NSRect)_maxXTitlebarResizeRect; -- (NSRect)_minXBorderRect; -- (NSRect)_maxXBorderRect; -- (NSRect)_maxYBorderRect; -- (NSRect)_minYBorderRect; - -@end diff --git a/src/gui/platforms/mac/qpaintdevice_mac.cpp b/src/gui/platforms/mac/qpaintdevice_mac.cpp deleted file mode 100644 index 245408a0b0..0000000000 --- a/src/gui/platforms/mac/qpaintdevice_mac.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qpaintdevice.h" -#include "qpainter.h" -#include "qwidget.h" -#include "qbitmap.h" -#include "qapplication.h" -#include "qprinter.h" -#include <qdebug.h> -#include <private/qt_mac_p.h> -#include <private/qprintengine_mac_p.h> -#include <private/qpixmap_mac_p.h> -#include <private/qpixmap_raster_p.h> - -QT_BEGIN_NAMESPACE - -/***************************************************************************** - Internal variables and functions - *****************************************************************************/ - -/*! \internal */ -float qt_mac_defaultDpi_x() -{ - // Mac OS X currently assumes things to be 72 dpi. - // (see http://developer.apple.com/releasenotes/GraphicsImaging/RN-ResolutionIndependentUI/) - // This may need to be re-worked as we go further in the resolution-independence stuff. - return 72; -} - -/*! \internal */ -float qt_mac_defaultDpi_y() -{ - // Mac OS X currently assumes things to be 72 dpi. - // (see http://developer.apple.com/releasenotes/GraphicsImaging/RN-ResolutionIndependentUI/) - // This may need to be re-worked as we go further in the resolution-independence stuff. - return 72; -} - - -/*! \internal - - Returns the QuickDraw CGrafPtr of the paint device. 0 is returned - if it can't be obtained. Do not hold the pointer around for long - as it can be relocated. - - \warning This function is only available on Mac OS X. -*/ - -Q_GUI_EXPORT GrafPtr qt_mac_qd_context(const QPaintDevice *device) -{ - if (device->devType() == QInternal::Pixmap) { - return static_cast<GrafPtr>(static_cast<const QPixmap *>(device)->macQDHandle()); - } else if(device->devType() == QInternal::Widget) { - return static_cast<GrafPtr>(static_cast<const QWidget *>(device)->macQDHandle()); - } else if(device->devType() == QInternal::Printer) { - QPaintEngine *engine = static_cast<const QPrinter *>(device)->paintEngine(); - return static_cast<GrafPtr>(static_cast<const QMacPrintEngine *>(engine)->handle()); - } - return 0; -} - -extern CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *pdev); - -/*! \internal - - Returns the CoreGraphics CGContextRef of the paint device. 0 is - returned if it can't be obtained. It is the caller's responsiblity to - CGContextRelease the context when finished using it. - - \warning This function is only available on Mac OS X. -*/ - -Q_GUI_EXPORT CGContextRef qt_mac_cg_context(const QPaintDevice *pdev) -{ - if (pdev->devType() == QInternal::Pixmap) { - const QPixmap *pm = static_cast<const QPixmap*>(pdev); - CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); - uint flags = kCGImageAlphaPremultipliedFirst; -#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - flags |= kCGBitmapByteOrder32Host; -#endif - CGContextRef ret = 0; - - // It would make sense to put this into a mac #ifdef'ed - // virtual function in the QPixmapData at some point - if (pm->data->classId() == QPixmapData::MacClass) { - const QMacPixmapData *pmData = static_cast<const QMacPixmapData*>(pm->data.data()); - ret = CGBitmapContextCreate(pmData->pixels, pmData->w, pmData->h, - 8, pmData->bytesPerRow, colorspace, - flags); - if(!ret) - qWarning("QPaintDevice: Unable to create context for pixmap (%d/%d/%d)", - pmData->w, pmData->h, (pmData->bytesPerRow * pmData->h)); - } else if (pm->data->classId() == QPixmapData::RasterClass) { - QImage *image = pm->data->buffer(); - ret = CGBitmapContextCreate(image->bits(), image->width(), image->height(), - 8, image->bytesPerLine(), colorspace, flags); - } - - CGContextTranslateCTM(ret, 0, pm->height()); - CGContextScaleCTM(ret, 1, -1); - return ret; - } else if (pdev->devType() == QInternal::Widget) { - CGContextRef ret = static_cast<CGContextRef>(static_cast<const QWidget *>(pdev)->macCGHandle()); - CGContextRetain(ret); - return ret; - } else if (pdev->devType() == QInternal::MacQuartz) { - return static_cast<const QMacQuartzPaintDevice *>(pdev)->cgContext(); - } - return 0; -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qpaintengine_mac.cpp b/src/gui/platforms/mac/qpaintengine_mac.cpp deleted file mode 100644 index c6d061dea8..0000000000 --- a/src/gui/platforms/mac/qpaintengine_mac.cpp +++ /dev/null @@ -1,1751 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qbitmap.h> -#include <qpaintdevice.h> -#include <private/qpaintengine_mac_p.h> -#include <qpainterpath.h> -#include <qpixmapcache.h> -#include <private/qpaintengine_raster_p.h> -#include <private/qprintengine_mac_p.h> -#include <qprinter.h> -#include <qstack.h> -#include <qtextcodec.h> -#include <qwidget.h> -#include <qvarlengtharray.h> -#include <qdebug.h> -#include <qcoreapplication.h> -#include <qmath.h> - -#include <private/qfont_p.h> -#include <private/qfontengine_p.h> -#include <private/qfontengine_coretext_p.h> -#include <private/qfontengine_mac_p.h> -#include <private/qnumeric_p.h> -#include <private/qpainter_p.h> -#include <private/qpainterpath_p.h> -#include <private/qpixmap_mac_p.h> -#include <private/qt_mac_p.h> -#include <private/qtextengine_p.h> -#include <private/qwidget_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> - -#include <string.h> - -QT_BEGIN_NAMESPACE - -extern int qt_antialiasing_threshold; // QApplication.cpp - -/***************************************************************************** - External functions - *****************************************************************************/ -extern CGImageRef qt_mac_create_imagemask(const QPixmap &px, const QRectF &sr); //qpixmap_mac.cpp -extern QPoint qt_mac_posInWindow(const QWidget *w); //qwidget_mac.cpp -extern OSWindowRef qt_mac_window_for(const QWidget *); //qwidget_mac.cpp -extern CGContextRef qt_mac_cg_context(const QPaintDevice *); //qpaintdevice_mac.cpp -extern void qt_mac_dispose_rgn(RgnHandle r); //qregion_mac.cpp -extern QPixmap qt_pixmapForBrush(int, bool); //qbrush.cpp - -void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform); - - -//Implemented for qt_mac_p.h -QMacCGContext::QMacCGContext(QPainter *p) -{ - QPaintEngine *pe = p->paintEngine(); - if (pe->type() == QPaintEngine::MacPrinter) - pe = static_cast<QMacPrintEngine*>(pe)->paintEngine(); - pe->syncState(); - context = 0; - if(pe->type() == QPaintEngine::CoreGraphics) - context = static_cast<QCoreGraphicsPaintEngine*>(pe)->handle(); - - int devType = p->device()->devType(); - if (pe->type() == QPaintEngine::Raster - && (devType == QInternal::Widget || - devType == QInternal::Pixmap || - devType == QInternal::Image)) { - - extern CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice); - CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pe->paintDevice()); - uint flags = kCGImageAlphaPremultipliedFirst; -#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - flags |= kCGBitmapByteOrder32Host; -#endif - const QImage *image = (const QImage *) pe->paintDevice(); - - context = CGBitmapContextCreate((void *) image->bits(), image->width(), image->height(), - 8, image->bytesPerLine(), colorspace, flags); - - CGContextTranslateCTM(context, 0, image->height()); - CGContextScaleCTM(context, 1, -1); - - if (devType == QInternal::Widget) { - QRegion clip = p->paintEngine()->systemClip(); - QTransform native = p->deviceTransform(); - QTransform logical = p->combinedTransform(); - - if (p->hasClipping()) { - QRegion r = p->clipRegion(); - r.translate(native.dx(), native.dy()); - if (clip.isEmpty()) - clip = r; - else - clip &= r; - } - qt_mac_clip_cg(context, clip, 0); - - CGContextTranslateCTM(context, native.dx(), native.dy()); - } - } else { - CGContextRetain(context); - } -} - - -/***************************************************************************** - QCoreGraphicsPaintEngine utility functions - *****************************************************************************/ - -//conversion -inline static float qt_mac_convert_color_to_cg(int c) { return ((float)c * 1000 / 255) / 1000; } -inline static int qt_mac_convert_color_from_cg(float c) { return qRound(c * 255); } -CGAffineTransform qt_mac_convert_transform_to_cg(const QTransform &t) { - return CGAffineTransformMake(t.m11(), t.m12(), t.m21(), t.m22(), t.dx(), t.dy()); -} - -CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice) -{ - bool isWidget = (paintDevice->devType() == QInternal::Widget); - return QCoreGraphicsPaintEngine::macDisplayColorSpace(isWidget ? static_cast<const QWidget *>(paintDevice) - : 0); -} - -inline static QCFType<CGColorRef> cgColorForQColor(const QColor &col, QPaintDevice *pdev) -{ - CGFloat components[] = { - qt_mac_convert_color_to_cg(col.red()), - qt_mac_convert_color_to_cg(col.green()), - qt_mac_convert_color_to_cg(col.blue()), - qt_mac_convert_color_to_cg(col.alpha()) - }; - return CGColorCreate(qt_mac_colorSpaceForDeviceType(pdev), components); -} - -// There's architectural problems with using native gradients -// on the Mac at the moment, so disable them. -// #define QT_MAC_USE_NATIVE_GRADIENTS - -#ifdef QT_MAC_USE_NATIVE_GRADIENTS -static bool drawGradientNatively(const QGradient *gradient) -{ - return gradient->spread() == QGradient::PadSpread; -} - -// gradiant callback -static void qt_mac_color_gradient_function(void *info, const CGFloat *in, CGFloat *out) -{ - QBrush *brush = static_cast<QBrush *>(info); - Q_ASSERT(brush && brush->gradient()); - - const QGradientStops stops = brush->gradient()->stops(); - const int n = stops.count(); - Q_ASSERT(n >= 1); - const QGradientStop *begin = stops.constBegin(); - const QGradientStop *end = begin + n; - - qreal p = in[0]; - const QGradientStop *i = begin; - while (i != end && i->first < p) - ++i; - - QRgb c; - if (i == begin) { - c = begin->second.rgba(); - } else if (i == end) { - c = (end - 1)->second.rgba(); - } else { - const QGradientStop &s1 = *(i - 1); - const QGradientStop &s2 = *i; - qreal p1 = s1.first; - qreal p2 = s2.first; - QRgb c1 = s1.second.rgba(); - QRgb c2 = s2.second.rgba(); - int idist = 256 * (p - p1) / (p2 - p1); - int dist = 256 - idist; - c = qRgba(INTERPOLATE_PIXEL_256(qRed(c1), dist, qRed(c2), idist), - INTERPOLATE_PIXEL_256(qGreen(c1), dist, qGreen(c2), idist), - INTERPOLATE_PIXEL_256(qBlue(c1), dist, qBlue(c2), idist), - INTERPOLATE_PIXEL_256(qAlpha(c1), dist, qAlpha(c2), idist)); - } - - out[0] = qt_mac_convert_color_to_cg(qRed(c)); - out[1] = qt_mac_convert_color_to_cg(qGreen(c)); - out[2] = qt_mac_convert_color_to_cg(qBlue(c)); - out[3] = qt_mac_convert_color_to_cg(qAlpha(c)); -} -#endif - -//clipping handling -void QCoreGraphicsPaintEnginePrivate::resetClip() -{ - static bool inReset = false; - if (inReset) - return; - inReset = true; - - CGAffineTransform old_xform = CGContextGetCTM(hd); - - //setup xforms - CGContextConcatCTM(hd, CGAffineTransformInvert(old_xform)); - while (stackCount > 0) { - restoreGraphicsState(); - } - saveGraphicsState(); - inReset = false; - //reset xforms - CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd))); - CGContextConcatCTM(hd, old_xform); -} - -static CGRect qt_mac_compose_rect(const QRectF &r, float off=0) -{ - return CGRectMake(r.x()+off, r.y()+off, r.width(), r.height()); -} - -static CGMutablePathRef qt_mac_compose_path(const QPainterPath &p, float off=0) -{ - CGMutablePathRef ret = CGPathCreateMutable(); - QPointF startPt; - for (int i=0; i<p.elementCount(); ++i) { - const QPainterPath::Element &elm = p.elementAt(i); - switch (elm.type) { - case QPainterPath::MoveToElement: - if(i > 0 - && p.elementAt(i - 1).x == startPt.x() - && p.elementAt(i - 1).y == startPt.y()) - CGPathCloseSubpath(ret); - startPt = QPointF(elm.x, elm.y); - CGPathMoveToPoint(ret, 0, elm.x+off, elm.y+off); - break; - case QPainterPath::LineToElement: - CGPathAddLineToPoint(ret, 0, elm.x+off, elm.y+off); - break; - case QPainterPath::CurveToElement: - Q_ASSERT(p.elementAt(i+1).type == QPainterPath::CurveToDataElement); - Q_ASSERT(p.elementAt(i+2).type == QPainterPath::CurveToDataElement); - CGPathAddCurveToPoint(ret, 0, - elm.x+off, elm.y+off, - p.elementAt(i+1).x+off, p.elementAt(i+1).y+off, - p.elementAt(i+2).x+off, p.elementAt(i+2).y+off); - i+=2; - break; - default: - qFatal("QCoreGraphicsPaintEngine::drawPath(), unhandled type: %d", elm.type); - break; - } - } - if(!p.isEmpty() - && p.elementAt(p.elementCount() - 1).x == startPt.x() - && p.elementAt(p.elementCount() - 1).y == startPt.y()) - CGPathCloseSubpath(ret); - return ret; -} - -CGColorSpaceRef QCoreGraphicsPaintEngine::m_genericColorSpace = 0; -QHash<CGDirectDisplayID, CGColorSpaceRef> QCoreGraphicsPaintEngine::m_displayColorSpaceHash; -bool QCoreGraphicsPaintEngine::m_postRoutineRegistered = false; - -CGColorSpaceRef QCoreGraphicsPaintEngine::macGenericColorSpace() -{ -#if 0 - if (!m_genericColorSpace) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - } else -#endif - { - m_genericColorSpace = CGColorSpaceCreateDeviceRGB(); - } - if (!m_postRoutineRegistered) { - m_postRoutineRegistered = true; - qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces); - } - } - return m_genericColorSpace; -#else - // Just return the main display colorspace for the moment. - return macDisplayColorSpace(); -#endif -} - -/* - Ideally, we should pass the widget in here, and use CGGetDisplaysWithRect() etc. - to support multiple displays correctly. -*/ -CGColorSpaceRef QCoreGraphicsPaintEngine::macDisplayColorSpace(const QWidget *widget) -{ - CGColorSpaceRef colorSpace; - - CGDirectDisplayID displayID; - CMProfileRef displayProfile = 0; - if (widget == 0) { - displayID = CGMainDisplayID(); - } else { - const QRect &qrect = widget->window()->geometry(); - CGRect rect = CGRectMake(qrect.x(), qrect.y(), qrect.width(), qrect.height()); - CGDisplayCount throwAway; - CGDisplayErr dErr = CGGetDisplaysWithRect(rect, 1, &displayID, &throwAway); - if (dErr != kCGErrorSuccess) - return macDisplayColorSpace(0); // fall back on main display - } - if ((colorSpace = m_displayColorSpaceHash.value(displayID))) - return colorSpace; - - CMError err = CMGetProfileByAVID((CMDisplayIDType)displayID, &displayProfile); - if (err == noErr) { - colorSpace = CGColorSpaceCreateWithPlatformColorSpace(displayProfile); - } else if (widget) { - return macDisplayColorSpace(0); // fall back on main display - } - - if (colorSpace == 0) - colorSpace = CGColorSpaceCreateDeviceRGB(); - - m_displayColorSpaceHash.insert(displayID, colorSpace); - CMCloseProfile(displayProfile); - if (!m_postRoutineRegistered) { - m_postRoutineRegistered = true; - qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces); - } - return colorSpace; -} - -void QCoreGraphicsPaintEngine::cleanUpMacColorSpaces() -{ - if (m_genericColorSpace) { - CFRelease(m_genericColorSpace); - m_genericColorSpace = 0; - } - QHash<CGDirectDisplayID, CGColorSpaceRef>::const_iterator it = m_displayColorSpaceHash.constBegin(); - while (it != m_displayColorSpaceHash.constEnd()) { - if (it.value()) - CFRelease(it.value()); - ++it; - } - m_displayColorSpaceHash.clear(); -} - -void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform) -{ - CGAffineTransform old_xform = CGAffineTransformIdentity; - if(orig_xform) { //setup xforms - old_xform = CGContextGetCTM(hd); - CGContextConcatCTM(hd, CGAffineTransformInvert(old_xform)); - CGContextConcatCTM(hd, *orig_xform); - } - - //do the clipping - CGContextBeginPath(hd); - if(rgn.isEmpty()) { - CGContextAddRect(hd, CGRectMake(0, 0, 0, 0)); - } else { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - QCFType<HIMutableShapeRef> shape = rgn.toHIMutableShape(); - Q_ASSERT(!HIShapeIsEmpty(shape)); - HIShapeReplacePathInCGContext(shape, hd); - } else -#endif - { - QVector<QRect> rects = rgn.rects(); - const int count = rects.size(); - for(int i = 0; i < count; i++) { - const QRect &r = rects[i]; - CGRect mac_r = CGRectMake(r.x(), r.y(), r.width(), r.height()); - CGContextAddRect(hd, mac_r); - } - } - - } - CGContextClip(hd); - - if(orig_xform) {//reset xforms - CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd))); - CGContextConcatCTM(hd, old_xform); - } -} - - -//pattern handling (tiling) -#if 1 -# define QMACPATTERN_MASK_MULTIPLIER 32 -#else -# define QMACPATTERN_MASK_MULTIPLIER 1 -#endif -class QMacPattern -{ -public: - QMacPattern() : as_mask(false), pdev(0), image(0) { data.bytes = 0; } - ~QMacPattern() { CGImageRelease(image); } - int width() { - if(image) - return CGImageGetWidth(image); - if(data.bytes) - return 8*QMACPATTERN_MASK_MULTIPLIER; - return data.pixmap.width(); - } - int height() { - if(image) - return CGImageGetHeight(image); - if(data.bytes) - return 8*QMACPATTERN_MASK_MULTIPLIER; - return data.pixmap.height(); - } - - //input - QColor foreground; - bool as_mask; - struct { - QPixmap pixmap; - const uchar *bytes; - } data; - QPaintDevice *pdev; - //output - CGImageRef image; -}; -static void qt_mac_draw_pattern(void *info, CGContextRef c) -{ - QMacPattern *pat = (QMacPattern*)info; - int w = 0, h = 0; - bool isBitmap = (pat->data.pixmap.depth() == 1); - if(!pat->image) { //lazy cache - if(pat->as_mask) { - Q_ASSERT(pat->data.bytes); - w = h = 8; -#if (QMACPATTERN_MASK_MULTIPLIER == 1) - CGDataProviderRef provider = CGDataProviderCreateWithData(0, pat->data.bytes, w*h, 0); - pat->image = CGImageMaskCreate(w, h, 1, 1, 1, provider, 0, false); - CGDataProviderRelease(provider); -#else - const int numBytes = (w*h)/sizeof(uchar); - uchar xor_bytes[numBytes]; - for(int i = 0; i < numBytes; ++i) - xor_bytes[i] = pat->data.bytes[i] ^ 0xFF; - CGDataProviderRef provider = CGDataProviderCreateWithData(0, xor_bytes, w*h, 0); - CGImageRef swatch = CGImageMaskCreate(w, h, 1, 1, 1, provider, 0, false); - CGDataProviderRelease(provider); - - const QColor c0(0, 0, 0, 0), c1(255, 255, 255, 255); - QPixmap pm(w*QMACPATTERN_MASK_MULTIPLIER, h*QMACPATTERN_MASK_MULTIPLIER); - pm.fill(c0); - CGContextRef pm_ctx = qt_mac_cg_context(&pm); - CGContextSetFillColorWithColor(c, cgColorForQColor(c1, pat->pdev)); - CGRect rect = CGRectMake(0, 0, w, h); - for(int x = 0; x < QMACPATTERN_MASK_MULTIPLIER; ++x) { - rect.origin.x = x * w; - for(int y = 0; y < QMACPATTERN_MASK_MULTIPLIER; ++y) { - rect.origin.y = y * h; - qt_mac_drawCGImage(pm_ctx, &rect, swatch); - } - } - pat->image = qt_mac_create_imagemask(pm, pm.rect()); - CGImageRelease(swatch); - CGContextRelease(pm_ctx); - w *= QMACPATTERN_MASK_MULTIPLIER; - h *= QMACPATTERN_MASK_MULTIPLIER; -#endif - } else { - w = pat->data.pixmap.width(); - h = pat->data.pixmap.height(); - if (isBitmap) - pat->image = qt_mac_create_imagemask(pat->data.pixmap, pat->data.pixmap.rect()); - else - pat->image = (CGImageRef)pat->data.pixmap.macCGHandle(); - } - } else { - w = CGImageGetWidth(pat->image); - h = CGImageGetHeight(pat->image); - } - - //draw - bool needRestore = false; - if (CGImageIsMask(pat->image)) { - CGContextSaveGState(c); - CGContextSetFillColorWithColor(c, cgColorForQColor(pat->foreground, pat->pdev)); - } - CGRect rect = CGRectMake(0, 0, w, h); - qt_mac_drawCGImage(c, &rect, pat->image); - if(needRestore) - CGContextRestoreGState(c); -} -static void qt_mac_dispose_pattern(void *info) -{ - QMacPattern *pat = (QMacPattern*)info; - delete pat; -} - -/***************************************************************************** - QCoreGraphicsPaintEngine member functions - *****************************************************************************/ - -inline static QPaintEngine::PaintEngineFeatures qt_mac_cg_features() -{ - return QPaintEngine::PaintEngineFeatures(QPaintEngine::AllFeatures & ~QPaintEngine::PaintOutsidePaintEvent - & ~QPaintEngine::PerspectiveTransform - & ~QPaintEngine::ConicalGradientFill - & ~QPaintEngine::LinearGradientFill - & ~QPaintEngine::RadialGradientFill - & ~QPaintEngine::BrushStroke); -} - -QCoreGraphicsPaintEngine::QCoreGraphicsPaintEngine() -: QPaintEngine(*(new QCoreGraphicsPaintEnginePrivate), qt_mac_cg_features()) -{ -} - -QCoreGraphicsPaintEngine::QCoreGraphicsPaintEngine(QPaintEnginePrivate &dptr) -: QPaintEngine(dptr, qt_mac_cg_features()) -{ -} - -QCoreGraphicsPaintEngine::~QCoreGraphicsPaintEngine() -{ -} - -bool -QCoreGraphicsPaintEngine::begin(QPaintDevice *pdev) -{ - Q_D(QCoreGraphicsPaintEngine); - if(isActive()) { // already active painting - qWarning("QCoreGraphicsPaintEngine::begin: Painter already active"); - return false; - } - - //initialization - d->pdev = pdev; - d->complexXForm = false; - d->cosmeticPen = QCoreGraphicsPaintEnginePrivate::CosmeticSetPenWidth; - d->cosmeticPenSize = 1; - d->current.clipEnabled = false; - d->pixelSize = QPoint(1,1); - d->hd = qt_mac_cg_context(pdev); - if(d->hd) { - d->saveGraphicsState(); - d->orig_xform = CGContextGetCTM(d->hd); - if (d->shading) { - CGShadingRelease(d->shading); - d->shading = 0; - } - d->setClip(0); //clear the context's clipping - } - - setActive(true); - - if(d->pdev->devType() == QInternal::Widget) { // device is a widget - QWidget *w = (QWidget*)d->pdev; - bool unclipped = w->testAttribute(Qt::WA_PaintUnclipped); - - if((w->windowType() == Qt::Desktop)) { - if(!unclipped) - qWarning("QCoreGraphicsPaintEngine::begin: Does not support clipped desktop on Mac OS X"); - // ## need to do [qt_mac_window_for(w) makeKeyAndOrderFront]; (need to rename the file) - } else if(unclipped) { - qWarning("QCoreGraphicsPaintEngine::begin: Does not support unclipped painting"); - } - } else if(d->pdev->devType() == QInternal::Pixmap) { // device is a pixmap - QPixmap *pm = (QPixmap*)d->pdev; - if(pm->isNull()) { - qWarning("QCoreGraphicsPaintEngine::begin: Cannot paint null pixmap"); - end(); - return false; - } - } - - setDirty(QPaintEngine::DirtyPen); - setDirty(QPaintEngine::DirtyBrush); - setDirty(QPaintEngine::DirtyBackground); - setDirty(QPaintEngine::DirtyHints); - return true; -} - -bool -QCoreGraphicsPaintEngine::end() -{ - Q_D(QCoreGraphicsPaintEngine); - setActive(false); - if(d->pdev->devType() == QInternal::Widget && static_cast<QWidget*>(d->pdev)->windowType() == Qt::Desktop) { -#ifndef QT_MAC_USE_COCOA - HideWindow(qt_mac_window_for(static_cast<QWidget*>(d->pdev))); -#else -// // ### need to do [qt_mac_window_for(static_cast<QWidget *>(d->pdev)) orderOut]; (need to rename) -#endif - - } - if(d->shading) { - CGShadingRelease(d->shading); - d->shading = 0; - } - d->pdev = 0; - if(d->hd) { - d->restoreGraphicsState(); - CGContextSynchronize(d->hd); - CGContextRelease(d->hd); - d->hd = 0; - } - return true; -} - -void -QCoreGraphicsPaintEngine::updateState(const QPaintEngineState &state) -{ - Q_D(QCoreGraphicsPaintEngine); - QPaintEngine::DirtyFlags flags = state.state(); - - if (flags & DirtyTransform) - updateMatrix(state.transform()); - - if (flags & DirtyClipEnabled) { - if (state.isClipEnabled()) - updateClipPath(painter()->clipPath(), Qt::ReplaceClip); - else - updateClipPath(QPainterPath(), Qt::NoClip); - } - - if (flags & DirtyClipPath) { - updateClipPath(state.clipPath(), state.clipOperation()); - } else if (flags & DirtyClipRegion) { - updateClipRegion(state.clipRegion(), state.clipOperation()); - } - - // If the clip has changed we need to update all other states - // too, since they are included in the system context on OSX, - // and changing the clip resets that context back to scratch. - if (flags & (DirtyClipPath | DirtyClipRegion | DirtyClipEnabled)) - flags |= AllDirty; - - if (flags & DirtyPen) - updatePen(state.pen()); - if (flags & (DirtyBrush|DirtyBrushOrigin)) - updateBrush(state.brush(), state.brushOrigin()); - if (flags & DirtyFont) - updateFont(state.font()); - if (flags & DirtyOpacity) - updateOpacity(state.opacity()); - if (flags & DirtyHints) - updateRenderHints(state.renderHints()); - if (flags & DirtyCompositionMode) - updateCompositionMode(state.compositionMode()); - - if (flags & (DirtyPen | DirtyTransform)) { - if (!d->current.pen.isCosmetic()) { - d->cosmeticPen = QCoreGraphicsPaintEnginePrivate::CosmeticNone; - } else if (d->current.transform.m11() < d->current.transform.m22()-1.0 || - d->current.transform.m11() > d->current.transform.m22()+1.0) { - d->cosmeticPen = QCoreGraphicsPaintEnginePrivate::CosmeticTransformPath; - d->cosmeticPenSize = d->adjustPenWidth(d->current.pen.widthF()); - if (!d->cosmeticPenSize) - d->cosmeticPenSize = 1.0; - } else { - d->cosmeticPen = QCoreGraphicsPaintEnginePrivate::CosmeticSetPenWidth; - static const float sqrt2 = sqrt(2); - qreal width = d->current.pen.widthF(); - if (!width) - width = 1; - d->cosmeticPenSize = sqrt(pow(d->pixelSize.y(), 2) + pow(d->pixelSize.x(), 2)) / sqrt2 * width; - } - } -} - -void -QCoreGraphicsPaintEngine::updatePen(const QPen &pen) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - d->current.pen = pen; - d->setStrokePen(pen); -} - -void -QCoreGraphicsPaintEngine::updateBrush(const QBrush &brush, const QPointF &brushOrigin) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - d->current.brush = brush; - -#ifdef QT_MAC_USE_NATIVE_GRADIENTS - // Quartz supports only pad spread - if (const QGradient *gradient = brush.gradient()) { - if (drawGradientNatively(gradient)) { - gccaps |= QPaintEngine::LinearGradientFill | QPaintEngine::RadialGradientFill; - } else { - gccaps &= ~(QPaintEngine::LinearGradientFill | QPaintEngine::RadialGradientFill); - } - } -#endif - - if (d->shading) { - CGShadingRelease(d->shading); - d->shading = 0; - } - d->setFillBrush(brushOrigin); -} - -void -QCoreGraphicsPaintEngine::updateOpacity(qreal opacity) -{ - Q_D(QCoreGraphicsPaintEngine); - CGContextSetAlpha(d->hd, opacity); -} - -void -QCoreGraphicsPaintEngine::updateFont(const QFont &) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - updatePen(d->current.pen); -} - -void -QCoreGraphicsPaintEngine::updateMatrix(const QTransform &transform) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (qt_is_nan(transform.m11()) || qt_is_nan(transform.m12()) || qt_is_nan(transform.m13()) - || qt_is_nan(transform.m21()) || qt_is_nan(transform.m22()) || qt_is_nan(transform.m23()) - || qt_is_nan(transform.m31()) || qt_is_nan(transform.m32()) || qt_is_nan(transform.m33())) - return; - - d->current.transform = transform; - d->setTransform(transform.isIdentity() ? 0 : &transform); - d->complexXForm = (transform.m11() != 1 || transform.m22() != 1 - || transform.m12() != 0 || transform.m21() != 0); - d->pixelSize = d->devicePixelSize(d->hd); -} - -void -QCoreGraphicsPaintEngine::updateClipPath(const QPainterPath &p, Qt::ClipOperation op) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - if(op == Qt::NoClip) { - if(d->current.clipEnabled) { - d->current.clipEnabled = false; - d->current.clip = QRegion(); - d->setClip(0); - } - } else { - if(!d->current.clipEnabled) - op = Qt::ReplaceClip; - d->current.clipEnabled = true; - QRegion clipRegion(p.toFillPolygon().toPolygon(), p.fillRule()); - if(op == Qt::ReplaceClip) { - d->current.clip = clipRegion; - d->setClip(0); - if(p.isEmpty()) { - CGRect rect = CGRectMake(0, 0, 0, 0); - CGContextClipToRect(d->hd, rect); - } else { - CGMutablePathRef path = qt_mac_compose_path(p); - CGContextBeginPath(d->hd); - CGContextAddPath(d->hd, path); - if(p.fillRule() == Qt::WindingFill) - CGContextClip(d->hd); - else - CGContextEOClip(d->hd); - CGPathRelease(path); - } - } else if(op == Qt::IntersectClip) { - d->current.clip = d->current.clip.intersected(clipRegion); - d->setClip(&d->current.clip); - } else if(op == Qt::UniteClip) { - d->current.clip = d->current.clip.united(clipRegion); - d->setClip(&d->current.clip); - } - } -} - -void -QCoreGraphicsPaintEngine::updateClipRegion(const QRegion &clipRegion, Qt::ClipOperation op) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - if(op == Qt::NoClip) { - d->current.clipEnabled = false; - d->current.clip = QRegion(); - d->setClip(0); - } else { - if(!d->current.clipEnabled) - op = Qt::ReplaceClip; - d->current.clipEnabled = true; - if(op == Qt::IntersectClip) - d->current.clip = d->current.clip.intersected(clipRegion); - else if(op == Qt::ReplaceClip) - d->current.clip = clipRegion; - else if(op == Qt::UniteClip) - d->current.clip = d->current.clip.united(clipRegion); - d->setClip(&d->current.clip); - } -} - -void -QCoreGraphicsPaintEngine::drawPath(const QPainterPath &p) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - CGMutablePathRef path = qt_mac_compose_path(p); - uchar ops = QCoreGraphicsPaintEnginePrivate::CGStroke; - if(p.fillRule() == Qt::WindingFill) - ops |= QCoreGraphicsPaintEnginePrivate::CGFill; - else - ops |= QCoreGraphicsPaintEnginePrivate::CGEOFill; - CGContextBeginPath(d->hd); - d->drawPath(ops, path); - CGPathRelease(path); -} - -void -QCoreGraphicsPaintEngine::drawRects(const QRectF *rects, int rectCount) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - for (int i=0; i<rectCount; ++i) { - QRectF r = rects[i]; - - CGMutablePathRef path = CGPathCreateMutable(); - CGPathAddRect(path, 0, qt_mac_compose_rect(r)); - d->drawPath(QCoreGraphicsPaintEnginePrivate::CGFill|QCoreGraphicsPaintEnginePrivate::CGStroke, - path); - CGPathRelease(path); - } -} - -void -QCoreGraphicsPaintEngine::drawPoints(const QPointF *points, int pointCount) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - if (d->current.pen.capStyle() == Qt::FlatCap) - CGContextSetLineCap(d->hd, kCGLineCapSquare); - - CGMutablePathRef path = CGPathCreateMutable(); - for(int i=0; i < pointCount; i++) { - float x = points[i].x(), y = points[i].y(); - CGPathMoveToPoint(path, 0, x, y); - CGPathAddLineToPoint(path, 0, x+0.001, y); - } - - bool doRestore = false; - if(d->cosmeticPen == QCoreGraphicsPaintEnginePrivate::CosmeticNone && !(state->renderHints() & QPainter::Antialiasing)) { - //we don't want adjusted pens for point rendering - doRestore = true; - d->saveGraphicsState(); - CGContextSetLineWidth(d->hd, d->current.pen.widthF()); - } - d->drawPath(QCoreGraphicsPaintEnginePrivate::CGStroke, path); - if (doRestore) - d->restoreGraphicsState(); - CGPathRelease(path); - if (d->current.pen.capStyle() == Qt::FlatCap) - CGContextSetLineCap(d->hd, kCGLineCapButt); -} - -void -QCoreGraphicsPaintEngine::drawEllipse(const QRectF &r) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - CGMutablePathRef path = CGPathCreateMutable(); - CGAffineTransform transform = CGAffineTransformMakeScale(r.width() / r.height(), 1); - CGPathAddArc(path, &transform,(r.x() + (r.width() / 2)) / (r.width() / r.height()), - r.y() + (r.height() / 2), r.height() / 2, 0, (2 * M_PI), false); - d->drawPath(QCoreGraphicsPaintEnginePrivate::CGFill | QCoreGraphicsPaintEnginePrivate::CGStroke, - path); - CGPathRelease(path); -} - -void -QCoreGraphicsPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - CGMutablePathRef path = CGPathCreateMutable(); - CGPathMoveToPoint(path, 0, points[0].x(), points[0].y()); - for(int x = 1; x < pointCount; ++x) - CGPathAddLineToPoint(path, 0, points[x].x(), points[x].y()); - if(mode != PolylineMode && points[0] != points[pointCount-1]) - CGPathAddLineToPoint(path, 0, points[0].x(), points[0].y()); - uint op = QCoreGraphicsPaintEnginePrivate::CGStroke; - if (mode != PolylineMode) - op |= mode == OddEvenMode ? QCoreGraphicsPaintEnginePrivate::CGEOFill - : QCoreGraphicsPaintEnginePrivate::CGFill; - d->drawPath(op, path); - CGPathRelease(path); -} - -void -QCoreGraphicsPaintEngine::drawLines(const QLineF *lines, int lineCount) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - CGMutablePathRef path = CGPathCreateMutable(); - for(int i = 0; i < lineCount; i++) { - const QPointF start = lines[i].p1(), end = lines[i].p2(); - CGPathMoveToPoint(path, 0, start.x(), start.y()); - CGPathAddLineToPoint(path, 0, end.x(), end.y()); - } - d->drawPath(QCoreGraphicsPaintEnginePrivate::CGStroke, path); - CGPathRelease(path); -} - -void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - if(pm.isNull()) - return; - - bool differentSize = (QRectF(0, 0, pm.width(), pm.height()) != sr), doRestore = false; - CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); - QCFType<CGImageRef> image; - bool isBitmap = (pm.depth() == 1); - if (isBitmap) { - doRestore = true; - d->saveGraphicsState(); - - const QColor &col = d->current.pen.color(); - CGContextSetFillColorWithColor(d->hd, cgColorForQColor(col, d->pdev)); - image = qt_mac_create_imagemask(pm, sr); - } else if (differentSize) { - QCFType<CGImageRef> img = pm.toMacCGImageRef(); - image = CGImageCreateWithImageInRect(img, CGRectMake(qRound(sr.x()), qRound(sr.y()), qRound(sr.width()), qRound(sr.height()))); - } else { - image = (CGImageRef)pm.macCGHandle(); - } - qt_mac_drawCGImage(d->hd, &rect, image); - if (doRestore) - d->restoreGraphicsState(); -} - -static void drawImageReleaseData (void *info, const void *, size_t) -{ - delete static_cast<QImage *>(info); -} - -CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0) -{ - QImage *image; - if (img.depth() != 32) - image = new QImage(img.convertToFormat(QImage::Format_ARGB32_Premultiplied)); - else - image = new QImage(img); - - uint cgflags = kCGImageAlphaNone; - switch (image->format()) { - case QImage::Format_ARGB32_Premultiplied: - cgflags = kCGImageAlphaPremultipliedFirst; - break; - case QImage::Format_ARGB32: - cgflags = kCGImageAlphaFirst; - break; - case QImage::Format_RGB32: - cgflags = kCGImageAlphaNoneSkipFirst; - default: - break; - } -#if defined(kCGBitmapByteOrder32Host) //only needed because CGImage.h added symbols in the minor version - cgflags |= kCGBitmapByteOrder32Host; -#endif - QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(image, - static_cast<const QImage *>(image)->bits(), - image->byteCount(), - drawImageReleaseData); - if (imagePtr) - *imagePtr = image; - return CGImageCreate(image->width(), image->height(), 8, 32, - image->bytesPerLine(), - QCoreGraphicsPaintEngine::macGenericColorSpace(), - cgflags, dataProvider, 0, false, kCGRenderingIntentDefault); - -} - -void QCoreGraphicsPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRectF &sr, - Qt::ImageConversionFlags flags) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_UNUSED(flags); - Q_ASSERT(isActive()); - - if (img.isNull() || state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - const QImage *image; - QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(img, &image); - CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); - if (QRectF(0, 0, img.width(), img.height()) != sr) - cgimage = CGImageCreateWithImageInRect(cgimage, CGRectMake(sr.x(), sr.y(), - sr.width(), sr.height())); - qt_mac_drawCGImage(d->hd, &rect, cgimage); -} - -void QCoreGraphicsPaintEngine::initialize() -{ -} - -void QCoreGraphicsPaintEngine::cleanup() -{ -} - -CGContextRef -QCoreGraphicsPaintEngine::handle() const -{ - return d_func()->hd; -} - -void -QCoreGraphicsPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, - const QPointF &p) -{ - Q_D(QCoreGraphicsPaintEngine); - Q_ASSERT(isActive()); - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - //save the old state - d->saveGraphicsState(); - - //setup the pattern - QMacPattern *qpattern = new QMacPattern; - qpattern->data.pixmap = pixmap; - qpattern->foreground = d->current.pen.color(); - qpattern->pdev = d->pdev; - CGPatternCallbacks callbks; - callbks.version = 0; - callbks.drawPattern = qt_mac_draw_pattern; - callbks.releaseInfo = qt_mac_dispose_pattern; - const int width = qpattern->width(), height = qpattern->height(); - CGAffineTransform trans = CGContextGetCTM(d->hd); - CGPatternRef pat = CGPatternCreate(qpattern, CGRectMake(0, 0, width, height), - trans, width, height, - kCGPatternTilingNoDistortion, true, &callbks); - CGColorSpaceRef cs = CGColorSpaceCreatePattern(0); - CGContextSetFillColorSpace(d->hd, cs); - CGFloat component = 1.0; //just one - CGContextSetFillPattern(d->hd, pat, &component); - CGSize phase = CGSizeApplyAffineTransform(CGSizeMake(-(p.x()-r.x()), -(p.y()-r.y())), trans); - CGContextSetPatternPhase(d->hd, phase); - - //fill the rectangle - CGRect mac_rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); - CGContextFillRect(d->hd, mac_rect); - - //restore the state - d->restoreGraphicsState(); - //cleanup - CGColorSpaceRelease(cs); - CGPatternRelease(pat); -} - -void QCoreGraphicsPaintEngine::drawTextItem(const QPointF &pos, const QTextItem &item) -{ - Q_D(QCoreGraphicsPaintEngine); - if (d->current.transform.type() == QTransform::TxProject -#ifndef QMAC_NATIVE_GRADIENTS - || painter()->pen().brush().gradient() //Just let the base engine "emulate" the gradient -#endif - ) { - QPaintEngine::drawTextItem(pos, item); - return; - } - - if (state->compositionMode() == QPainter::CompositionMode_Destination) - return; - - const QTextItemInt &ti = static_cast<const QTextItemInt &>(item); - - QPen oldPen = painter()->pen(); - QBrush oldBrush = painter()->brush(); - QPointF oldBrushOrigin = painter()->brushOrigin(); - updatePen(Qt::NoPen); - updateBrush(oldPen.brush(), QPointF(0, 0)); - - Q_ASSERT(type() == QPaintEngine::CoreGraphics); - - QFontEngine *fe = ti.fontEngine; - - const bool textAA = state->renderHints() & QPainter::TextAntialiasing && fe->fontDef.pointSize > qt_antialiasing_threshold && !(fe->fontDef.styleStrategy & QFont::NoAntialias); - const bool lineAA = state->renderHints() & QPainter::Antialiasing; - if(textAA != lineAA) - CGContextSetShouldAntialias(d->hd, textAA); - - if (ti.glyphs.numGlyphs) { - switch (fe->type()) { - case QFontEngine::Mac: -#ifdef QT_MAC_USE_COCOA - static_cast<QCoreTextFontEngine *>(fe)->draw(d->hd, pos.x(), pos.y(), ti, paintDevice()->height()); -#else - static_cast<QFontEngineMac *>(fe)->draw(d->hd, pos.x(), pos.y(), ti, paintDevice()->height()); -#endif - break; - case QFontEngine::Box: - d->drawBoxTextItem(pos, ti); - break; - default: - break; - } - } - - if(textAA != lineAA) - CGContextSetShouldAntialias(d->hd, !textAA); - - updatePen(oldPen); - updateBrush(oldBrush, oldBrushOrigin); -} - -QPainter::RenderHints -QCoreGraphicsPaintEngine::supportedRenderHints() const -{ - return QPainter::RenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); -} -enum CGCompositeMode { - kCGCompositeModeClear = 0, - kCGCompositeModeCopy = 1, - kCGCompositeModeSourceOver = 2, - kCGCompositeModeSourceIn = 3, - kCGCompositeModeSourceOut = 4, - kCGCompositeModeSourceAtop = 5, - kCGCompositeModeDestinationOver = 6, - kCGCompositeModeDestinationIn = 7, - kCGCompositeModeDestinationOut = 8, - kCGCompositeModeDestinationAtop = 9, - kCGCompositeModeXOR = 10, - kCGCompositeModePlusDarker = 11, // (max (0, (1-d) + (1-s))) - kCGCompositeModePlusLighter = 12, // (min (1, s + d)) - }; -extern "C" { - extern void CGContextSetCompositeOperation(CGContextRef, int); -} // private function, but is in all versions of OS X. -void -QCoreGraphicsPaintEngine::updateCompositionMode(QPainter::CompositionMode mode) -{ -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - int cg_mode = kCGBlendModeNormal; - switch(mode) { - case QPainter::CompositionMode_Multiply: - cg_mode = kCGBlendModeMultiply; - break; - case QPainter::CompositionMode_Screen: - cg_mode = kCGBlendModeScreen; - break; - case QPainter::CompositionMode_Overlay: - cg_mode = kCGBlendModeOverlay; - break; - case QPainter::CompositionMode_Darken: - cg_mode = kCGBlendModeDarken; - break; - case QPainter::CompositionMode_Lighten: - cg_mode = kCGBlendModeLighten; - break; - case QPainter::CompositionMode_ColorDodge: - cg_mode = kCGBlendModeColorDodge; - break; - case QPainter::CompositionMode_ColorBurn: - cg_mode = kCGBlendModeColorBurn; - break; - case QPainter::CompositionMode_HardLight: - cg_mode = kCGBlendModeHardLight; - break; - case QPainter::CompositionMode_SoftLight: - cg_mode = kCGBlendModeSoftLight; - break; - case QPainter::CompositionMode_Difference: - cg_mode = kCGBlendModeDifference; - break; - case QPainter::CompositionMode_Exclusion: - cg_mode = kCGBlendModeExclusion; - break; - case QPainter::CompositionMode_Plus: - cg_mode = kCGBlendModePlusLighter; - break; - case QPainter::CompositionMode_SourceOver: - cg_mode = kCGBlendModeNormal; - break; - case QPainter::CompositionMode_DestinationOver: - cg_mode = kCGBlendModeDestinationOver; - break; - case QPainter::CompositionMode_Clear: - cg_mode = kCGBlendModeClear; - break; - case QPainter::CompositionMode_Source: - cg_mode = kCGBlendModeCopy; - break; - case QPainter::CompositionMode_Destination: - cg_mode = -1; - break; - case QPainter::CompositionMode_SourceIn: - cg_mode = kCGBlendModeSourceIn; - break; - case QPainter::CompositionMode_DestinationIn: - cg_mode = kCGCompositeModeDestinationIn; - break; - case QPainter::CompositionMode_SourceOut: - cg_mode = kCGBlendModeSourceOut; - break; - case QPainter::CompositionMode_DestinationOut: - cg_mode = kCGBlendModeDestinationOver; - break; - case QPainter::CompositionMode_SourceAtop: - cg_mode = kCGBlendModeSourceAtop; - break; - case QPainter::CompositionMode_DestinationAtop: - cg_mode = kCGBlendModeDestinationAtop; - break; - case QPainter::CompositionMode_Xor: - cg_mode = kCGBlendModeXOR; - break; - default: - break; - } - if (cg_mode > -1) { - CGContextSetBlendMode(d_func()->hd, CGBlendMode(cg_mode)); - } - } else -#endif - // The standard porter duff ops. - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_3 - && mode <= QPainter::CompositionMode_Xor) { - int cg_mode = kCGCompositeModeCopy; - switch (mode) { - case QPainter::CompositionMode_SourceOver: - cg_mode = kCGCompositeModeSourceOver; - break; - case QPainter::CompositionMode_DestinationOver: - cg_mode = kCGCompositeModeDestinationOver; - break; - case QPainter::CompositionMode_Clear: - cg_mode = kCGCompositeModeClear; - break; - default: - qWarning("QCoreGraphicsPaintEngine: Unhandled composition mode %d", (int)mode); - break; - case QPainter::CompositionMode_Source: - cg_mode = kCGCompositeModeCopy; - break; - case QPainter::CompositionMode_Destination: - cg_mode = CGCompositeMode(-1); - break; - case QPainter::CompositionMode_SourceIn: - cg_mode = kCGCompositeModeSourceIn; - break; - case QPainter::CompositionMode_DestinationIn: - cg_mode = kCGCompositeModeDestinationIn; - break; - case QPainter::CompositionMode_SourceOut: - cg_mode = kCGCompositeModeSourceOut; - break; - case QPainter::CompositionMode_DestinationOut: - cg_mode = kCGCompositeModeDestinationOut; - break; - case QPainter::CompositionMode_SourceAtop: - cg_mode = kCGCompositeModeSourceAtop; - break; - case QPainter::CompositionMode_DestinationAtop: - cg_mode = kCGCompositeModeDestinationAtop; - break; - case QPainter::CompositionMode_Xor: - cg_mode = kCGCompositeModeXOR; - break; - } - if (cg_mode > -1) - CGContextSetCompositeOperation(d_func()->hd, CGCompositeMode(cg_mode)); - } else { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - bool needPrivateAPI = false; - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - int cg_mode = kCGBlendModeNormal; - switch (mode) { - case QPainter::CompositionMode_Multiply: - cg_mode = kCGBlendModeMultiply; - break; - case QPainter::CompositionMode_Screen: - cg_mode = kCGBlendModeScreen; - break; - case QPainter::CompositionMode_Overlay: - cg_mode = kCGBlendModeOverlay; - break; - case QPainter::CompositionMode_Darken: - cg_mode = kCGBlendModeDarken; - break; - case QPainter::CompositionMode_Lighten: - cg_mode = kCGBlendModeLighten; - break; - case QPainter::CompositionMode_ColorDodge: - cg_mode = kCGBlendModeColorDodge; - break; - case QPainter::CompositionMode_ColorBurn: - cg_mode = kCGBlendModeColorBurn; - break; - case QPainter::CompositionMode_HardLight: - cg_mode = kCGBlendModeHardLight; - break; - case QPainter::CompositionMode_SoftLight: - cg_mode = kCGBlendModeSoftLight; - break; - case QPainter::CompositionMode_Difference: - cg_mode = kCGBlendModeDifference; - break; - case QPainter::CompositionMode_Exclusion: - cg_mode = kCGBlendModeExclusion; - break; - case QPainter::CompositionMode_Plus: - needPrivateAPI = true; - cg_mode = kCGCompositeModePlusLighter; - break; - default: - break; - } - if (!needPrivateAPI) - CGContextSetBlendMode(d_func()->hd, CGBlendMode(cg_mode)); - else - CGContextSetCompositeOperation(d_func()->hd, CGCompositeMode(cg_mode)); - } -#endif - } -} - -void -QCoreGraphicsPaintEngine::updateRenderHints(QPainter::RenderHints hints) -{ - Q_D(QCoreGraphicsPaintEngine); - CGContextSetShouldAntialias(d->hd, hints & QPainter::Antialiasing); - static const CGFloat ScaleFactor = qt_mac_get_scalefactor(); - if (ScaleFactor > 1.) { - CGContextSetInterpolationQuality(d->hd, kCGInterpolationHigh); - } else { - CGContextSetInterpolationQuality(d->hd, (hints & QPainter::SmoothPixmapTransform) ? - kCGInterpolationHigh : kCGInterpolationNone); - } - bool textAntialiasing = (hints & QPainter::TextAntialiasing) == QPainter::TextAntialiasing; - if (!textAntialiasing || d->disabledSmoothFonts) { - d->disabledSmoothFonts = !textAntialiasing; - CGContextSetShouldSmoothFonts(d->hd, textAntialiasing); - } -} - -/* - Returns the size of one device pixel in user-space coordinates. -*/ -QPointF QCoreGraphicsPaintEnginePrivate::devicePixelSize(CGContextRef) -{ - QPointF p1 = current.transform.inverted().map(QPointF(0, 0)); - QPointF p2 = current.transform.inverted().map(QPointF(1, 1)); - return QPointF(qAbs(p2.x() - p1.x()), qAbs(p2.y() - p1.y())); -} - -/* - Adjusts the pen width so we get correct line widths in the - non-transformed, aliased case. -*/ -float QCoreGraphicsPaintEnginePrivate::adjustPenWidth(float penWidth) -{ - Q_Q(QCoreGraphicsPaintEngine); - float ret = penWidth; - if (!complexXForm && !(q->state->renderHints() & QPainter::Antialiasing)) { - if (penWidth < 2) - ret = 1; - else if (penWidth < 3) - ret = 1.5; - else - ret = penWidth -1; - } - return ret; -} - -void -QCoreGraphicsPaintEnginePrivate::setStrokePen(const QPen &pen) -{ - //pencap - CGLineCap cglinecap = kCGLineCapButt; - if(pen.capStyle() == Qt::SquareCap) - cglinecap = kCGLineCapSquare; - else if(pen.capStyle() == Qt::RoundCap) - cglinecap = kCGLineCapRound; - CGContextSetLineCap(hd, cglinecap); - CGContextSetLineWidth(hd, adjustPenWidth(pen.widthF())); - - //join - CGLineJoin cglinejoin = kCGLineJoinMiter; - if(pen.joinStyle() == Qt::BevelJoin) - cglinejoin = kCGLineJoinBevel; - else if(pen.joinStyle() == Qt::RoundJoin) - cglinejoin = kCGLineJoinRound; - CGContextSetLineJoin(hd, cglinejoin); -// CGContextSetMiterLimit(hd, pen.miterLimit()); - - //pen style - QVector<CGFloat> linedashes; - if(pen.style() == Qt::CustomDashLine) { - QVector<qreal> customs = pen.dashPattern(); - for(int i = 0; i < customs.size(); ++i) - linedashes.append(customs.at(i)); - } else if(pen.style() == Qt::DashLine) { - linedashes.append(4); - linedashes.append(2); - } else if(pen.style() == Qt::DotLine) { - linedashes.append(1); - linedashes.append(2); - } else if(pen.style() == Qt::DashDotLine) { - linedashes.append(4); - linedashes.append(2); - linedashes.append(1); - linedashes.append(2); - } else if(pen.style() == Qt::DashDotDotLine) { - linedashes.append(4); - linedashes.append(2); - linedashes.append(1); - linedashes.append(2); - linedashes.append(1); - linedashes.append(2); - } - const CGFloat cglinewidth = pen.widthF() <= 0.0f ? 1.0f : float(pen.widthF()); - for(int i = 0; i < linedashes.size(); ++i) { - linedashes[i] *= cglinewidth; - if(cglinewidth < 3 && (cglinecap == kCGLineCapSquare || cglinecap == kCGLineCapRound)) { - if((i%2)) - linedashes[i] += cglinewidth/2; - else - linedashes[i] -= cglinewidth/2; - } - } - CGContextSetLineDash(hd, pen.dashOffset() * cglinewidth, linedashes.data(), linedashes.size()); - - // color - CGContextSetStrokeColorWithColor(hd, cgColorForQColor(pen.color(), pdev)); -} - -// Add our own patterns here to deal with the fact that the coordinate system -// is flipped vertically with Quartz2D. -static const uchar *qt_mac_patternForBrush(int brushStyle) -{ - Q_ASSERT(brushStyle > Qt::SolidPattern && brushStyle < Qt::LinearGradientPattern); - static const uchar dense1_pat[] = { 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00 }; - static const uchar dense2_pat[] = { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 }; - static const uchar dense3_pat[] = { 0x11, 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa }; - static const uchar dense4_pat[] = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }; - static const uchar dense5_pat[] = { 0xee, 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55 }; - static const uchar dense6_pat[] = { 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff, 0x77 }; - static const uchar dense7_pat[] = { 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff }; - static const uchar hor_pat[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff }; - static const uchar ver_pat[] = { 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef }; - static const uchar cross_pat[] = { 0xef, 0xef, 0xef, 0xef, 0x00, 0xef, 0xef, 0xef }; - static const uchar fdiag_pat[] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe }; - static const uchar bdiag_pat[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f }; - static const uchar dcross_pat[] = { 0x7e, 0xbd, 0xdb, 0xe7, 0xe7, 0xdb, 0xbd, 0x7e }; - static const uchar *const pat_tbl[] = { - dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat, - dense6_pat, dense7_pat, - hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat }; - return pat_tbl[brushStyle - Qt::Dense1Pattern]; -} - -void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset) -{ - // pattern - Qt::BrushStyle bs = current.brush.style(); -#ifdef QT_MAC_USE_NATIVE_GRADIENTS - if (bs == Qt::LinearGradientPattern || bs == Qt::RadialGradientPattern) { - const QGradient *grad = static_cast<const QGradient*>(current.brush.gradient()); - if (drawGradientNatively(grad)) { - Q_ASSERT(grad->spread() == QGradient::PadSpread); - - static const CGFloat domain[] = { 0.0f, +1.0f }; - static const CGFunctionCallbacks callbacks = { 0, qt_mac_color_gradient_function, 0 }; - CGFunctionRef fill_func = CGFunctionCreate(reinterpret_cast<void *>(¤t.brush), - 1, domain, 4, 0, &callbacks); - - CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); - if (bs == Qt::LinearGradientPattern) { - const QLinearGradient *linearGrad = static_cast<const QLinearGradient *>(grad); - const QPointF start(linearGrad->start()); - const QPointF stop(linearGrad->finalStop()); - shading = CGShadingCreateAxial(colorspace, CGPointMake(start.x(), start.y()), - CGPointMake(stop.x(), stop.y()), fill_func, true, true); - } else { - Q_ASSERT(bs == Qt::RadialGradientPattern); - const QRadialGradient *radialGrad = static_cast<const QRadialGradient *>(grad); - QPointF center(radialGrad->center()); - QPointF focal(radialGrad->focalPoint()); - qreal radius = radialGrad->radius(); - shading = CGShadingCreateRadial(colorspace, CGPointMake(focal.x(), focal.y()), - 0.0, CGPointMake(center.x(), center.y()), radius, fill_func, false, true); - } - - CGFunctionRelease(fill_func); - } - } else -#endif - if(bs != Qt::SolidPattern && bs != Qt::NoBrush -#ifndef QT_MAC_USE_NATIVE_GRADIENTS - && (bs < Qt::LinearGradientPattern || bs > Qt::ConicalGradientPattern) -#endif - ) - { - QMacPattern *qpattern = new QMacPattern; - qpattern->pdev = pdev; - CGFloat components[4] = { 1.0, 1.0, 1.0, 1.0 }; - CGColorSpaceRef base_colorspace = 0; - if(bs == Qt::TexturePattern) { - qpattern->data.pixmap = current.brush.texture(); - if(qpattern->data.pixmap.isQBitmap()) { - const QColor &col = current.brush.color(); - components[0] = qt_mac_convert_color_to_cg(col.red()); - components[1] = qt_mac_convert_color_to_cg(col.green()); - components[2] = qt_mac_convert_color_to_cg(col.blue()); - base_colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace(); - } - } else { - qpattern->as_mask = true; - - qpattern->data.bytes = qt_mac_patternForBrush(bs); - const QColor &col = current.brush.color(); - components[0] = qt_mac_convert_color_to_cg(col.red()); - components[1] = qt_mac_convert_color_to_cg(col.green()); - components[2] = qt_mac_convert_color_to_cg(col.blue()); - base_colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace(); - } - int width = qpattern->width(), height = qpattern->height(); - qpattern->foreground = current.brush.color(); - - CGColorSpaceRef fill_colorspace = CGColorSpaceCreatePattern(base_colorspace); - CGContextSetFillColorSpace(hd, fill_colorspace); - - CGAffineTransform xform = CGContextGetCTM(hd); - xform = CGAffineTransformConcat(qt_mac_convert_transform_to_cg(current.brush.transform()), xform); - xform = CGAffineTransformTranslate(xform, offset.x(), offset.y()); - - CGPatternCallbacks callbks; - callbks.version = 0; - callbks.drawPattern = qt_mac_draw_pattern; - callbks.releaseInfo = qt_mac_dispose_pattern; - CGPatternRef fill_pattern = CGPatternCreate(qpattern, CGRectMake(0, 0, width, height), - xform, width, height, kCGPatternTilingNoDistortion, - !base_colorspace, &callbks); - CGContextSetFillPattern(hd, fill_pattern, components); - - CGPatternRelease(fill_pattern); - CGColorSpaceRelease(fill_colorspace); - } else if(bs != Qt::NoBrush) { - CGContextSetFillColorWithColor(hd, cgColorForQColor(current.brush.color(), pdev)); - } -} - -void -QCoreGraphicsPaintEnginePrivate::setClip(const QRegion *rgn) -{ - Q_Q(QCoreGraphicsPaintEngine); - if(hd) { - resetClip(); - QRegion sysClip = q->systemClip(); - if(!sysClip.isEmpty()) - qt_mac_clip_cg(hd, sysClip, &orig_xform); - if(rgn) - qt_mac_clip_cg(hd, *rgn, 0); - } -} - -struct qt_mac_cg_transform_path { - CGMutablePathRef path; - CGAffineTransform transform; -}; - -void qt_mac_cg_transform_path_apply(void *info, const CGPathElement *element) -{ - Q_ASSERT(info && element); - qt_mac_cg_transform_path *t = (qt_mac_cg_transform_path*)info; - switch(element->type) { - case kCGPathElementMoveToPoint: - CGPathMoveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y); - break; - case kCGPathElementAddLineToPoint: - CGPathAddLineToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y); - break; - case kCGPathElementAddQuadCurveToPoint: - CGPathAddQuadCurveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y, - element->points[1].x, element->points[1].y); - break; - case kCGPathElementAddCurveToPoint: - CGPathAddCurveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y, - element->points[1].x, element->points[1].y, - element->points[2].x, element->points[2].y); - break; - case kCGPathElementCloseSubpath: - CGPathCloseSubpath(t->path); - break; - default: - qDebug() << "Unhandled path transform type: " << element->type; - } -} - -void QCoreGraphicsPaintEnginePrivate::drawPath(uchar ops, CGMutablePathRef path) -{ - Q_Q(QCoreGraphicsPaintEngine); - Q_ASSERT((ops & (CGFill | CGEOFill)) != (CGFill | CGEOFill)); //can't really happen - if((ops & (CGFill | CGEOFill))) { - if (shading) { - Q_ASSERT(path); - CGContextBeginPath(hd); - CGContextAddPath(hd, path); - saveGraphicsState(); - if (ops & CGFill) - CGContextClip(hd); - else if (ops & CGEOFill) - CGContextEOClip(hd); - if (current.brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode) { - CGRect boundingBox = CGPathGetBoundingBox(path); - CGContextConcatCTM(hd, - CGAffineTransformMake(boundingBox.size.width, 0, - 0, boundingBox.size.height, - boundingBox.origin.x, boundingBox.origin.y)); - } - CGContextDrawShading(hd, shading); - restoreGraphicsState(); - ops &= ~CGFill; - ops &= ~CGEOFill; - } else if (current.brush.style() == Qt::NoBrush) { - ops &= ~CGFill; - ops &= ~CGEOFill; - } - } - if((ops & CGStroke) && current.pen.style() == Qt::NoPen) - ops &= ~CGStroke; - - if(ops & (CGEOFill | CGFill)) { - CGContextBeginPath(hd); - CGContextAddPath(hd, path); - if (ops & CGEOFill) { - CGContextEOFillPath(hd); - } else { - CGContextFillPath(hd); - } - } - - // Avoid saving and restoring the context if we can. - const bool needContextSave = (cosmeticPen != QCoreGraphicsPaintEnginePrivate::CosmeticNone || - !(q->state->renderHints() & QPainter::Antialiasing)); - if(ops & CGStroke) { - if (needContextSave) - saveGraphicsState(); - CGContextBeginPath(hd); - - // Translate a fraction of a pixel size in the y direction - // to make sure that primitives painted at pixel borders - // fills the right pixel. This is needed since the y xais - // in the Quartz coordinate system is inverted compared to Qt. - if (!(q->state->renderHints() & QPainter::Antialiasing)) { - if (current.pen.style() == Qt::SolidLine || current.pen.width() >= 3) - CGContextTranslateCTM(hd, double(pixelSize.x()) * 0.25, double(pixelSize.y()) * 0.25); - else if (current.pen.style() == Qt::DotLine && QSysInfo::MacintoshVersion == QSysInfo::MV_10_3) - ; // Do nothing. - else - CGContextTranslateCTM(hd, 0, double(pixelSize.y()) * 0.1); - } - - if (cosmeticPen != QCoreGraphicsPaintEnginePrivate::CosmeticNone) { - // If antialiazing is enabled, use the cosmetic pen size directly. - if (q->state->renderHints() & QPainter::Antialiasing) - CGContextSetLineWidth(hd, cosmeticPenSize); - else if (current.pen.widthF() <= 1) - CGContextSetLineWidth(hd, cosmeticPenSize * 0.9f); - else - CGContextSetLineWidth(hd, cosmeticPenSize); - } - if(cosmeticPen == QCoreGraphicsPaintEnginePrivate::CosmeticTransformPath) { - qt_mac_cg_transform_path t; - t.transform = qt_mac_convert_transform_to_cg(current.transform); - t.path = CGPathCreateMutable(); - CGPathApply(path, &t, qt_mac_cg_transform_path_apply); //transform the path - setTransform(0); //unset the context transform - CGContextSetLineWidth(hd, cosmeticPenSize); - CGContextAddPath(hd, t.path); - CGPathRelease(t.path); - } else { - CGContextAddPath(hd, path); - } - - CGContextStrokePath(hd); - if (needContextSave) - restoreGraphicsState(); - } -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qpaintengine_mac_p.h b/src/gui/platforms/mac/qpaintengine_mac_p.h deleted file mode 100644 index 3e71d6ca6b..0000000000 --- a/src/gui/platforms/mac/qpaintengine_mac_p.h +++ /dev/null @@ -1,254 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPAINTENGINE_MAC_P_H -#define QPAINTENGINE_MAC_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "QtGui/qpaintengine.h" -#include "private/qt_mac_p.h" -#include "private/qpaintengine_p.h" -#include "private/qpolygonclipper_p.h" -#include "private/qfont_p.h" -#include "QtCore/qhash.h" - -typedef struct CGColorSpace *CGColorSpaceRef; -QT_BEGIN_NAMESPACE - -class QCoreGraphicsPaintEnginePrivate; -class QCoreGraphicsPaintEngine : public QPaintEngine -{ - Q_DECLARE_PRIVATE(QCoreGraphicsPaintEngine) - -public: - QCoreGraphicsPaintEngine(); - ~QCoreGraphicsPaintEngine(); - - bool begin(QPaintDevice *pdev); - bool end(); - static CGColorSpaceRef macGenericColorSpace(); - static CGColorSpaceRef macDisplayColorSpace(const QWidget *widget = 0); - - void updateState(const QPaintEngineState &state); - - void updatePen(const QPen &pen); - void updateBrush(const QBrush &brush, const QPointF &pt); - void updateFont(const QFont &font); - void updateOpacity(qreal opacity); - void updateMatrix(const QTransform &matrix); - void updateTransform(const QTransform &matrix); - void updateClipRegion(const QRegion ®ion, Qt::ClipOperation op); - void updateClipPath(const QPainterPath &path, Qt::ClipOperation op); - void updateCompositionMode(QPainter::CompositionMode mode); - void updateRenderHints(QPainter::RenderHints hints); - - void drawLines(const QLineF *lines, int lineCount); - void drawRects(const QRectF *rects, int rectCount); - void drawPoints(const QPointF *p, int pointCount); - void drawEllipse(const QRectF &r); - void drawPath(const QPainterPath &path); - - void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); - void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); - - void drawTextItem(const QPointF &pos, const QTextItem &item); - void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, - Qt::ImageConversionFlags flags = Qt::AutoColor); - - Type type() const { return QPaintEngine::CoreGraphics; } - - CGContextRef handle() const; - - static void initialize(); - static void cleanup(); - - QPainter::RenderHints supportedRenderHints() const; - - //avoid partial shadowed overload warnings... - void drawLines(const QLine *lines, int lineCount) { QPaintEngine::drawLines(lines, lineCount); } - void drawRects(const QRect *rects, int rectCount) { QPaintEngine::drawRects(rects, rectCount); } - void drawPoints(const QPoint *p, int pointCount) { QPaintEngine::drawPoints(p, pointCount); } - void drawEllipse(const QRect &r) { QPaintEngine::drawEllipse(r); } - void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) - { QPaintEngine::drawPolygon(points, pointCount, mode); } - -protected: - friend class QMacPrintEngine; - friend class QMacPrintEnginePrivate; - friend void qt_mac_display_change_callbk(CGDirectDisplayID, CGDisplayChangeSummaryFlags, void *); - friend void qt_color_profile_changed(CFNotificationCenterRef center, void *, - CFStringRef , const void *, CFDictionaryRef); - QCoreGraphicsPaintEngine(QPaintEnginePrivate &dptr); - -private: - static bool m_postRoutineRegistered; - static CGColorSpaceRef m_genericColorSpace; - static QHash<CGDirectDisplayID, CGColorSpaceRef> m_displayColorSpaceHash; - static void cleanUpMacColorSpaces(); - Q_DISABLE_COPY(QCoreGraphicsPaintEngine) -}; - -/***************************************************************************** - Private data - *****************************************************************************/ -class QCoreGraphicsPaintEnginePrivate : public QPaintEnginePrivate -{ - Q_DECLARE_PUBLIC(QCoreGraphicsPaintEngine) -public: - QCoreGraphicsPaintEnginePrivate() - : hd(0), shading(0), stackCount(0), complexXForm(false), disabledSmoothFonts(false) - { - } - - struct { - QPen pen; - QBrush brush; - uint clipEnabled : 1; - QRegion clip; - QTransform transform; - } current; - - //state info (shared with QD) - CGAffineTransform orig_xform; - - //cg structures - CGContextRef hd; - CGShadingRef shading; - int stackCount; - bool complexXForm; - bool disabledSmoothFonts; - enum { CosmeticNone, CosmeticTransformPath, CosmeticSetPenWidth } cosmeticPen; - - // pixel and cosmetic pen size in user coordinates. - QPointF pixelSize; - float cosmeticPenSize; - - //internal functions - enum { CGStroke=0x01, CGEOFill=0x02, CGFill=0x04 }; - void drawPath(uchar ops, CGMutablePathRef path = 0); - void setClip(const QRegion *rgn=0); - void resetClip(); - void setFillBrush(const QPointF &origin=QPoint()); - void setStrokePen(const QPen &pen); - inline void saveGraphicsState(); - inline void restoreGraphicsState(); - float penOffset(); - QPointF devicePixelSize(CGContextRef context); - float adjustPenWidth(float penWidth); - inline void setTransform(const QTransform *matrix=0) - { - CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd))); - CGAffineTransform xform = orig_xform; - if(matrix) { - extern CGAffineTransform qt_mac_convert_transform_to_cg(const QTransform &); - xform = CGAffineTransformConcat(qt_mac_convert_transform_to_cg(*matrix), xform); - } - CGContextConcatCTM(hd, xform); - CGContextSetTextMatrix(hd, xform); - } -}; - -inline void QCoreGraphicsPaintEnginePrivate::saveGraphicsState() -{ - ++stackCount; - CGContextSaveGState(hd); -} - -inline void QCoreGraphicsPaintEnginePrivate::restoreGraphicsState() -{ - --stackCount; - Q_ASSERT(stackCount >= 0); - CGContextRestoreGState(hd); -} - -class QMacQuartzPaintDevice : public QPaintDevice -{ -public: - QMacQuartzPaintDevice(CGContextRef cg, int width, int height, int bytesPerLine) - : mCG(cg), mWidth(width), mHeight(height), mBytesPerLine(bytesPerLine) - { } - int devType() const { return QInternal::MacQuartz; } - CGContextRef cgContext() const { return mCG; } - int metric(PaintDeviceMetric metric) const { - switch (metric) { - case PdmWidth: - return mWidth; - case PdmHeight: - return mHeight; - case PdmWidthMM: - return (qt_defaultDpiX() * mWidth) / 2.54; - case PdmHeightMM: - return (qt_defaultDpiY() * mHeight) / 2.54; - case PdmNumColors: - return 0; - case PdmDepth: - return 32; - case PdmDpiX: - case PdmPhysicalDpiX: - return qt_defaultDpiX(); - case PdmDpiY: - case PdmPhysicalDpiY: - return qt_defaultDpiY(); - } - return 0; - } - QPaintEngine *paintEngine() const { qWarning("This function should never be called."); return 0; } -private: - CGContextRef mCG; - int mWidth; - int mHeight; - int mBytesPerLine; -}; - -QT_END_NAMESPACE - -#endif // QPAINTENGINE_MAC_P_H diff --git a/src/gui/platforms/mac/qpixmap_mac.cpp b/src/gui/platforms/mac/qpixmap_mac.cpp deleted file mode 100644 index 72e2aa6e04..0000000000 --- a/src/gui/platforms/mac/qpixmap_mac.cpp +++ /dev/null @@ -1,1195 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qpixmap.h" -#include "qimage.h" -#include "qapplication.h" -#include "qbitmap.h" -#include "qmatrix.h" -#include "qtransform.h" -#include "qlibrary.h" -#include "qvarlengtharray.h" -#include "qdebug.h" -#include <private/qdrawhelper_p.h> -#include <private/qpixmap_mac_p.h> -#include <private/qpixmap_raster_p.h> -#include <private/qpaintengine_mac_p.h> -#include <private/qt_mac_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> - -#include <limits.h> -#include <string.h> - -QT_BEGIN_NAMESPACE - -/***************************************************************************** - Externals - *****************************************************************************/ -extern const uchar *qt_get_bitflip_array(); //qimage.cpp -extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); //qpaintdevice_mac.cpp -extern RgnHandle qt_mac_get_rgn(); //qregion_mac.cpp -extern void qt_mac_dispose_rgn(RgnHandle r); //qregion_mac.cpp -extern QRegion qt_mac_convert_mac_region(RgnHandle rgn); //qregion_mac.cpp - -static int qt_pixmap_serial = 0; - -Q_GUI_EXPORT quint32 *qt_mac_pixmap_get_base(const QPixmap *pix) -{ - return static_cast<QMacPixmapData*>(pix->data.data())->pixels; -} - -Q_GUI_EXPORT int qt_mac_pixmap_get_bytes_per_line(const QPixmap *pix) -{ - return static_cast<QMacPixmapData*>(pix->data.data())->bytesPerRow; -} - -void qt_mac_cgimage_data_free(void *info, const void *memoryToFree, size_t) -{ - QMacPixmapData *pmdata = static_cast<QMacPixmapData *>(info); - if (!pmdata) { - free(const_cast<void *>(memoryToFree)); - } else { - if (QMacPixmapData::validDataPointers.contains(pmdata) == false) { - free(const_cast<void *>(memoryToFree)); - return; - } - if (pmdata->pixels == pmdata->pixelsToFree) { - // something we aren't expecting, just free it. - Q_ASSERT(memoryToFree != pmdata->pixelsToFree); - free(const_cast<void *>(memoryToFree)); - } else { - free(pmdata->pixelsToFree); - pmdata->pixelsToFree = static_cast<quint32 *>(const_cast<void *>(memoryToFree)); - } - pmdata->cg_dataBeingReleased = 0; - } -} - -CGImageRef qt_mac_image_to_cgimage(const QImage &image) -{ - int bitsPerColor = 8; - int bitsPerPixel = 32; - if (image.depth() == 1) { - bitsPerColor = 1; - bitsPerPixel = 1; - } - QCFType<CGDataProviderRef> provider = - CGDataProviderCreateWithData(0, image.bits(), image.bytesPerLine() * image.height(), - 0); - - uint cgflags = kCGImageAlphaPremultipliedFirst; -#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - cgflags |= kCGBitmapByteOrder32Host; -#endif - - CGImageRef cgImage = CGImageCreate(image.width(), image.height(), bitsPerColor, bitsPerPixel, - image.bytesPerLine(), - QCoreGraphicsPaintEngine::macGenericColorSpace(), - cgflags, provider, - 0, - 0, - kCGRenderingIntentDefault); - - return cgImage; -} - -/***************************************************************************** - QPixmap member functions - *****************************************************************************/ - -static inline QRgb qt_conv16ToRgb(ushort c) { - static const int qt_rbits = (565/100); - static const int qt_gbits = (565/10%10); - static const int qt_bbits = (565%10); - static const int qt_red_shift = qt_bbits+qt_gbits-(8-qt_rbits); - static const int qt_green_shift = qt_bbits-(8-qt_gbits); - static const int qt_neg_blue_shift = 8-qt_bbits; - static const int qt_blue_mask = (1<<qt_bbits)-1; - static const int qt_green_mask = (1<<(qt_gbits+qt_bbits))-((1<<qt_bbits)-1); - static const int qt_red_mask = (1<<(qt_rbits+qt_gbits+qt_bbits))-(1<<(qt_gbits+qt_bbits)); - - const int r=(c & qt_red_mask); - const int g=(c & qt_green_mask); - const int b=(c & qt_blue_mask); - const int tr = r >> qt_red_shift; - const int tg = g >> qt_green_shift; - const int tb = b << qt_neg_blue_shift; - - return qRgb(tr,tg,tb); -} - -QSet<QMacPixmapData*> QMacPixmapData::validDataPointers; - -QMacPixmapData::QMacPixmapData(PixelType type) - : QPixmapData(type, MacClass), has_alpha(0), has_mask(0), - uninit(true), pixels(0), pixelsSize(0), pixelsToFree(0), - bytesPerRow(0), cg_data(0), cg_dataBeingReleased(0), cg_mask(0), - pengine(0) -{ -} - -QPixmapData *QMacPixmapData::createCompatiblePixmapData() const -{ - return new QMacPixmapData(pixelType()); -} - -#define BEST_BYTE_ALIGNMENT 16 -#define COMPTUE_BEST_BYTES_PER_ROW(bpr) \ - (((bpr) + (BEST_BYTE_ALIGNMENT - 1)) & ~(BEST_BYTE_ALIGNMENT - 1)) - -void QMacPixmapData::resize(int width, int height) -{ - setSerialNumber(++qt_pixmap_serial); - - w = width; - h = height; - is_null = (w <= 0 || h <= 0); - d = (pixelType() == BitmapType ? 1 : 32); - bool make_null = w <= 0 || h <= 0; // create null pixmap - if (make_null || d == 0) { - w = 0; - h = 0; - is_null = true; - d = 0; - if (!make_null) - qWarning("Qt: QPixmap: Invalid pixmap parameters"); - return; - } - - if (w < 1 || h < 1) - return; - - //create the pixels - bytesPerRow = w * sizeof(quint32); // Minimum bytes per row. - - // Quartz2D likes things as a multple of 16 (for now). - bytesPerRow = COMPTUE_BEST_BYTES_PER_ROW(bytesPerRow); - macCreatePixels(); -} - -#undef COMPUTE_BEST_BYTES_PER_ROW - -void QMacPixmapData::fromImage(const QImage &img, - Qt::ImageConversionFlags flags) -{ - setSerialNumber(++qt_pixmap_serial); - - // the conversion code only handles format >= - // Format_ARGB32_Premultiplied at the moment.. - if (img.format() > QImage::Format_ARGB32_Premultiplied) { - QImage image; - if (img.hasAlphaChannel()) - image = img.convertToFormat(QImage::Format_ARGB32_Premultiplied); - else - image = img.convertToFormat(QImage::Format_RGB32); - fromImage(image, flags); - return; - } - - w = img.width(); - h = img.height(); - is_null = (w <= 0 || h <= 0); - d = (pixelType() == BitmapType ? 1 : img.depth()); - - QImage image = img; - int dd = QPixmap::defaultDepth(); - bool force_mono = (dd == 1 || - (flags & Qt::ColorMode_Mask)==Qt::MonoOnly); - if (force_mono) { // must be monochrome - if (d != 1) { - image = image.convertToFormat(QImage::Format_MonoLSB, flags); // dither - d = 1; - } - } else { // can be both - bool conv8 = false; - if(d > 8 && dd <= 8) { // convert to 8 bit - if ((flags & Qt::DitherMode_Mask) == Qt::AutoDither) - flags = (flags & ~Qt::DitherMode_Mask) - | Qt::PreferDither; - conv8 = true; - } else if ((flags & Qt::ColorMode_Mask) == Qt::ColorOnly) { - conv8 = d == 1; // native depth wanted - } else if (d == 1) { - if (image.colorCount() == 2) { - QRgb c0 = image.color(0); // Auto: convert to best - QRgb c1 = image.color(1); - conv8 = qMin(c0,c1) != qRgb(0,0,0) || qMax(c0,c1) != qRgb(255,255,255); - } else { - // eg. 1-color monochrome images (they do exist). - conv8 = true; - } - } - if (conv8) { - image = image.convertToFormat(QImage::Format_Indexed8, flags); - d = 8; - } - } - - if (image.depth()==1) { - image.setColor(0, QColor(Qt::color0).rgba()); - image.setColor(1, QColor(Qt::color1).rgba()); - } - - if (d == 16 || d == 24) { - image = image.convertToFormat(QImage::Format_RGB32, flags); - fromImage(image, flags); - return; - } - - // different size or depth, make a new pixmap - resize(w, h); - - quint32 *dptr = pixels, *drow; - const uint dbpr = bytesPerRow; - - const QImage::Format sfmt = image.format(); - const unsigned short sbpr = image.bytesPerLine(); - - // use const_cast to prevent a detach - const uchar *sptr = const_cast<const QImage &>(image).bits(), *srow; - - for (int y = 0; y < h; ++y) { - drow = dptr + (y * (dbpr / 4)); - srow = sptr + (y * sbpr); - switch(sfmt) { - case QImage::Format_MonoLSB: - case QImage::Format_Mono:{ - for (int x = 0; x < w; ++x) { - char one_bit = *(srow + (x / 8)); - if (sfmt == QImage::Format_Mono) - one_bit = one_bit >> (7 - (x % 8)); - else - one_bit = one_bit >> (x % 8); - if ((one_bit & 0x01)) - *(drow+x) = 0xFF000000; - else - *(drow+x) = 0xFFFFFFFF; - } - break; - } - case QImage::Format_Indexed8: { - int numColors = image.numColors(); - if (numColors > 0) { - for (int x = 0; x < w; ++x) { - int index = *(srow + x); - *(drow+x) = PREMUL(image.color(qMin(index, numColors))); - } - } - } break; - case QImage::Format_RGB32: - for (int x = 0; x < w; ++x) - *(drow+x) = *(((quint32*)srow) + x) | 0xFF000000; - break; - case QImage::Format_ARGB32: - case QImage::Format_ARGB32_Premultiplied: - for (int x = 0; x < w; ++x) { - if(sfmt == QImage::Format_RGB32) - *(drow+x) = 0xFF000000 | (*(((quint32*)srow) + x) & 0x00FFFFFF); - else if(sfmt == QImage::Format_ARGB32_Premultiplied) - *(drow+x) = *(((quint32*)srow) + x); - else - *(drow+x) = PREMUL(*(((quint32*)srow) + x)); - } - break; - default: - qWarning("Qt: internal: Oops: Forgot a format [%d] %s:%d", sfmt, - __FILE__, __LINE__); - break; - } - } - if (sfmt != QImage::Format_RGB32) { //setup the alpha - bool alphamap = image.depth() == 32; - if (sfmt == QImage::Format_Indexed8) { - const QVector<QRgb> rgb = image.colorTable(); - for (int i = 0, count = image.colorCount(); i < count; ++i) { - const int alpha = qAlpha(rgb[i]); - if (alpha != 0xff) { - alphamap = true; - break; - } - } - } - macSetHasAlpha(alphamap); - } - uninit = false; -} - -int get_index(QImage * qi,QRgb mycol) -{ - int loopc; - for(loopc=0;loopc<qi->colorCount();loopc++) { - if(qi->color(loopc)==mycol) - return loopc; - } - qi->setColorCount(qi->colorCount()+1); - qi->setColor(qi->colorCount(),mycol); - return qi->colorCount(); -} - -QImage QMacPixmapData::toImage() const -{ - QImage::Format format = QImage::Format_MonoLSB; - if (d != 1) //Doesn't support index color modes - format = (has_alpha ? QImage::Format_ARGB32_Premultiplied : - QImage::Format_RGB32); - - QImage image(w, h, format); - quint32 *sptr = pixels, *srow; - const uint sbpr = bytesPerRow; - if (format == QImage::Format_MonoLSB) { - image.fill(0); - image.setColorCount(2); - image.setColor(0, QColor(Qt::color0).rgba()); - image.setColor(1, QColor(Qt::color1).rgba()); - for (int y = 0; y < h; ++y) { - uchar *scanLine = image.scanLine(y); - srow = sptr + (y * (sbpr/4)); - for (int x = 0; x < w; ++x) { - if (!(*(srow + x) & RGB_MASK)) - scanLine[x >> 3] |= (1 << (x & 7)); - } - } - } else { - for (int y = 0; y < h; ++y) { - srow = sptr + (y * (sbpr / 4)); - memcpy(image.scanLine(y), srow, w * 4); - } - - } - - return image; -} - -void QMacPixmapData::fill(const QColor &fillColor) - -{ - { //we don't know what backend to use so we cannot paint here - quint32 *dptr = pixels; - Q_ASSERT_X(dptr, "QPixmap::fill", "No dptr"); - const quint32 colr = PREMUL(fillColor.rgba()); - const int nbytes = bytesPerRow * h; - if (!colr) { - memset(dptr, 0, nbytes); - } else { - for (uint i = 0; i < nbytes / sizeof(quint32); ++i) - *(dptr + i) = colr; - } - } - - // If we had an alpha channel from before, don't - // switch it off. Only go from no alpha to alpha: - if (fillColor.alpha() != 255) - macSetHasAlpha(true); -} - -QPixmap QMacPixmapData::alphaChannel() const -{ - if (!has_alpha) - return QPixmap(); - - QMacPixmapData *alpha = new QMacPixmapData(PixmapType); - alpha->resize(w, h); - macGetAlphaChannel(alpha, false); - return QPixmap(alpha); -} - -void QMacPixmapData::setAlphaChannel(const QPixmap &alpha) -{ - has_mask = true; - QMacPixmapData *alphaData = static_cast<QMacPixmapData*>(alpha.data.data()); - macSetAlphaChannel(alphaData, false); -} - -QBitmap QMacPixmapData::mask() const -{ - if (!has_mask && !has_alpha) - return QBitmap(); - - QMacPixmapData *mask = new QMacPixmapData(BitmapType); - mask->resize(w, h); - macGetAlphaChannel(mask, true); - return QPixmap(mask); -} - -void QMacPixmapData::setMask(const QBitmap &mask) -{ - if (mask.isNull()) { - QMacPixmapData opaque(PixmapType); - opaque.resize(w, h); - opaque.fill(QColor(255, 255, 255, 255)); - macSetAlphaChannel(&opaque, true); - has_alpha = has_mask = false; - return; - } - - has_alpha = false; - has_mask = true; - QMacPixmapData *maskData = static_cast<QMacPixmapData*>(mask.data.data()); - macSetAlphaChannel(maskData, true); -} - -int QMacPixmapData::metric(QPaintDevice::PaintDeviceMetric theMetric) const -{ - switch (theMetric) { - case QPaintDevice::PdmWidth: - return w; - case QPaintDevice::PdmHeight: - return h; - case QPaintDevice::PdmWidthMM: - return qRound(metric(QPaintDevice::PdmWidth) * 25.4 / qreal(metric(QPaintDevice::PdmDpiX))); - case QPaintDevice::PdmHeightMM: - return qRound(metric(QPaintDevice::PdmHeight) * 25.4 / qreal(metric(QPaintDevice::PdmDpiY))); - case QPaintDevice::PdmNumColors: - return 1 << d; - case QPaintDevice::PdmDpiX: - case QPaintDevice::PdmPhysicalDpiX: { - extern float qt_mac_defaultDpi_x(); //qpaintdevice_mac.cpp - return int(qt_mac_defaultDpi_x()); - } - case QPaintDevice::PdmDpiY: - case QPaintDevice::PdmPhysicalDpiY: { - extern float qt_mac_defaultDpi_y(); //qpaintdevice_mac.cpp - return int(qt_mac_defaultDpi_y()); - } - case QPaintDevice::PdmDepth: - return d; - default: - qWarning("QPixmap::metric: Invalid metric command"); - } - return 0; -} - -QMacPixmapData::~QMacPixmapData() -{ - validDataPointers.remove(this); - if (cg_mask) { - CGImageRelease(cg_mask); - cg_mask = 0; - } - - delete pengine; // Make sure we aren't drawing on the context anymore. - if (cg_data) { - CGImageRelease(cg_data); - } else if (!cg_dataBeingReleased && pixels != pixelsToFree) { - free(pixels); - } - free(pixelsToFree); -} - -void QMacPixmapData::macSetAlphaChannel(const QMacPixmapData *pix, bool asMask) -{ - if (!pixels || !h || !w || pix->w != w || pix->h != h) - return; - - quint32 *dptr = pixels, *drow; - const uint dbpr = bytesPerRow; - const unsigned short sbpr = pix->bytesPerRow; - quint32 *sptr = pix->pixels, *srow; - for (int y=0; y < h; ++y) { - drow = dptr + (y * (dbpr/4)); - srow = sptr + (y * (sbpr/4)); - if(d == 1) { - for (int x=0; x < w; ++x) { - if((*(srow+x) & RGB_MASK)) - *(drow+x) = 0xFFFFFFFF; - } - } else if(d == 8) { - for (int x=0; x < w; ++x) - *(drow+x) = (*(drow+x) & RGB_MASK) | (*(srow+x) << 24); - } else if(asMask) { - for (int x=0; x < w; ++x) { - if(*(srow+x) & RGB_MASK) - *(drow+x) = (*(drow+x) & RGB_MASK); - else - *(drow+x) = (*(drow+x) & RGB_MASK) | 0xFF000000; - *(drow+x) = PREMUL(*(drow+x)); - } - } else { - for (int x=0; x < w; ++x) { - const uchar alpha = qGray(qRed(*(srow+x)), qGreen(*(srow+x)), qBlue(*(srow+x))); - const uchar destAlpha = qt_div_255(alpha * qAlpha(*(drow+x))); -#if 1 - *(drow+x) = (*(drow+x) & RGB_MASK) | (destAlpha << 24); -#else - *(drow+x) = qRgba(qt_div_255(qRed(*(drow+x) * alpha)), - qt_div_255(qGreen(*(drow+x) * alpha)), - qt_div_255(qBlue(*(drow+x) * alpha)), destAlpha); -#endif - *(drow+x) = PREMUL(*(drow+x)); - } - } - } - macSetHasAlpha(true); -} - -void QMacPixmapData::macGetAlphaChannel(QMacPixmapData *pix, bool asMask) const -{ - quint32 *dptr = pix->pixels, *drow; - const uint dbpr = pix->bytesPerRow; - const unsigned short sbpr = bytesPerRow; - quint32 *sptr = pixels, *srow; - for(int y=0; y < h; ++y) { - drow = dptr + (y * (dbpr/4)); - srow = sptr + (y * (sbpr/4)); - if(asMask) { - for (int x = 0; x < w; ++x) { - if (*(srow + x) & qRgba(0, 0, 0, 255)) - *(drow + x) = 0x00000000; - else - *(drow + x) = 0xFFFFFFFF; - } - } else { - for (int x = 0; x < w; ++x) { - const int alpha = qAlpha(*(srow + x)); - *(drow + x) = qRgb(alpha, alpha, alpha); - } - } - } -} - -void QMacPixmapData::macSetHasAlpha(bool b) -{ - has_alpha = b; - macReleaseCGImageRef(); -} - -void QMacPixmapData::macCreateCGImageRef() -{ - Q_ASSERT(cg_data == 0); - //create the cg data - CGColorSpaceRef colorspace = QCoreGraphicsPaintEngine::macDisplayColorSpace(); - QCFType<CGDataProviderRef> provider = CGDataProviderCreateWithData(this, - pixels, bytesPerRow * h, - qt_mac_cgimage_data_free); - validDataPointers.insert(this); - uint cgflags = kCGImageAlphaPremultipliedFirst; -#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - cgflags |= kCGBitmapByteOrder32Host; -#endif - cg_data = CGImageCreate(w, h, 8, 32, bytesPerRow, colorspace, - cgflags, provider, 0, 0, kCGRenderingIntentDefault); -} - -void QMacPixmapData::macReleaseCGImageRef() -{ - if (!cg_data) - return; // There's nothing we need to do - - cg_dataBeingReleased = cg_data; - CGImageRelease(cg_data); - cg_data = 0; - - if (pixels != pixelsToFree) { - macCreatePixels(); - } else { - pixelsToFree = 0; - } -} - - -// We create our space in memory to paint on here. If we already have existing pixels -// copy them over. This is to preserve the fact that CGImageRef's are immutable. -void QMacPixmapData::macCreatePixels() -{ - const int numBytes = bytesPerRow * h; - quint32 *base_pixels; - if (pixelsToFree && pixelsToFree != pixels) { - // Reuse unused block of memory lying around from a previous callback. - base_pixels = pixelsToFree; - pixelsToFree = 0; - } else { - // We need a block of memory to do stuff with. - base_pixels = static_cast<quint32 *>(malloc(numBytes)); - } - - if (pixels) - memcpy(base_pixels, pixels, pixelsSize); - pixels = base_pixels; - pixelsSize = numBytes; -} - -#if 0 -QPixmap QMacPixmapData::transformed(const QTransform &transform, - Qt::TransformationMode mode) const -{ - int w, h; // size of target pixmap - const int ws = width(); - const int hs = height(); - - QTransform mat(transform.m11(), transform.m12(), - transform.m21(), transform.m22(), 0., 0.); - if (transform.m12() == 0.0F && transform.m21() == 0.0F && - transform.m11() >= 0.0F && transform.m22() >= 0.0F) - { - h = int(qAbs(mat.m22()) * hs + 0.9999); - w = int(qAbs(mat.m11()) * ws + 0.9999); - h = qAbs(h); - w = qAbs(w); - } else { // rotation or shearing - QPolygonF a(QRectF(0,0,ws+1,hs+1)); - a = mat.map(a); - QRectF r = a.boundingRect().normalized(); - w = int(r.width() + 0.9999); - h = int(r.height() + 0.9999); - } - mat = QPixmap::trueMatrix(mat, ws, hs); - if (!h || !w) - return QPixmap(); - - // create destination - QMacPixmapData *pm = new QMacPixmapData(pixelType(), w, h); - const quint32 *sptr = pixels; - quint32 *dptr = pm->pixels; - memset(dptr, 0, (pm->bytesPerRow * pm->h)); - - // do the transform - if (mode == Qt::SmoothTransformation) { -#warning QMacPixmapData::transformed not properly implemented - qWarning("QMacPixmapData::transformed not properly implemented"); -#if 0 - QPainter p(&pm); - p.setRenderHint(QPainter::Antialiasing); - p.setRenderHint(QPainter::SmoothPixmapTransform); - p.setTransform(mat); - p.drawPixmap(0, 0, *this); -#endif - } else { - bool invertible; - mat = mat.inverted(&invertible); - if (!invertible) - return QPixmap(); - - const int bpp = 32; - const int xbpl = (w * bpp) / 8; - if (!qt_xForm_helper(mat, 0, QT_XFORM_TYPE_MSBFIRST, bpp, - (uchar*)dptr, xbpl, (pm->bytesPerRow) - xbpl, - h, (uchar*)sptr, (bytesPerRow), ws, hs)) { - qWarning("QMacPixmapData::transform(): failure"); - return QPixmap(); - } - } - - // update the alpha - pm->macSetHasAlpha(true); - return QPixmap(pm); -} -#endif - -QT_BEGIN_INCLUDE_NAMESPACE -#include <OpenGL/OpenGL.h> -#include <OpenGL/gl.h> -QT_END_INCLUDE_NAMESPACE - -// Load and resolve the symbols we need from OpenGL manually so QtGui doesn't have to link against the OpenGL framework. -typedef CGLError (*PtrCGLChoosePixelFormat)(const CGLPixelFormatAttribute *, CGLPixelFormatObj *, long *); -typedef CGLError (*PtrCGLClearDrawable)(CGLContextObj); -typedef CGLError (*PtrCGLCreateContext)(CGLPixelFormatObj, CGLContextObj, CGLContextObj *); -typedef CGLError (*PtrCGLDestroyContext)(CGLContextObj); -typedef CGLError (*PtrCGLDestroyPixelFormat)(CGLPixelFormatObj); -typedef CGLError (*PtrCGLSetCurrentContext)(CGLContextObj); -typedef CGLError (*PtrCGLSetFullScreen)(CGLContextObj); -typedef void (*PtrglFinish)(); -typedef void (*PtrglPixelStorei)(GLenum, GLint); -typedef void (*PtrglReadBuffer)(GLenum); -typedef void (*PtrglReadPixels)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *); - -static PtrCGLChoosePixelFormat ptrCGLChoosePixelFormat = 0; -static PtrCGLClearDrawable ptrCGLClearDrawable = 0; -static PtrCGLCreateContext ptrCGLCreateContext = 0; -static PtrCGLDestroyContext ptrCGLDestroyContext = 0; -static PtrCGLDestroyPixelFormat ptrCGLDestroyPixelFormat = 0; -static PtrCGLSetCurrentContext ptrCGLSetCurrentContext = 0; -static PtrCGLSetFullScreen ptrCGLSetFullScreen = 0; -static PtrglFinish ptrglFinish = 0; -static PtrglPixelStorei ptrglPixelStorei = 0; -static PtrglReadBuffer ptrglReadBuffer = 0; -static PtrglReadPixels ptrglReadPixels = 0; - -static bool resolveOpenGLSymbols() -{ - if (ptrCGLChoosePixelFormat == 0) { - QLibrary library(QLatin1String("/System/Library/Frameworks/OpenGL.framework/OpenGL")); - ptrCGLChoosePixelFormat = (PtrCGLChoosePixelFormat)(library.resolve("CGLChoosePixelFormat")); - ptrCGLClearDrawable = (PtrCGLClearDrawable)(library.resolve("CGLClearDrawable")); - ptrCGLCreateContext = (PtrCGLCreateContext)(library.resolve("CGLCreateContext")); - ptrCGLDestroyContext = (PtrCGLDestroyContext)(library.resolve("CGLDestroyContext")); - ptrCGLDestroyPixelFormat = (PtrCGLDestroyPixelFormat)(library.resolve("CGLDestroyPixelFormat")); - ptrCGLSetCurrentContext = (PtrCGLSetCurrentContext)(library.resolve("CGLSetCurrentContext")); - ptrCGLSetFullScreen = (PtrCGLSetFullScreen)(library.resolve("CGLSetFullScreen")); - ptrglFinish = (PtrglFinish)(library.resolve("glFinish")); - ptrglPixelStorei = (PtrglPixelStorei)(library.resolve("glPixelStorei")); - ptrglReadBuffer = (PtrglReadBuffer)(library.resolve("glReadBuffer")); - ptrglReadPixels = (PtrglReadPixels)(library.resolve("glReadPixels")); - } - return ptrCGLChoosePixelFormat && ptrCGLClearDrawable && ptrCGLCreateContext - && ptrCGLDestroyContext && ptrCGLDestroyPixelFormat && ptrCGLSetCurrentContext - && ptrCGLSetFullScreen && ptrglFinish && ptrglPixelStorei - && ptrglReadBuffer && ptrglReadPixels; -} - -// Inverts the given pixmap in the y direction. -static void qt_mac_flipPixmap(void *data, int rowBytes, int height) -{ - int bottom = height - 1; - void *base = data; - void *buffer = malloc(rowBytes); - - int top = 0; - while ( top < bottom ) - { - void *topP = (void *)((top * rowBytes) + (intptr_t)base); - void *bottomP = (void *)((bottom * rowBytes) + (intptr_t)base); - - bcopy( topP, buffer, rowBytes ); - bcopy( bottomP, topP, rowBytes ); - bcopy( buffer, bottomP, rowBytes ); - - ++top; - --bottom; - } - free(buffer); -} - -// Grabs displayRect from display and places it into buffer. -static void qt_mac_grabDisplayRect(CGDirectDisplayID display, const QRect &displayRect, void *buffer) -{ - if (display == kCGNullDirectDisplay) - return; - - CGLPixelFormatAttribute attribs[] = { - kCGLPFAFullScreen, - kCGLPFADisplayMask, - (CGLPixelFormatAttribute)0, /* Display mask bit goes here */ - (CGLPixelFormatAttribute)0 - }; - - attribs[2] = (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(display); - - // Build a full-screen GL context - CGLPixelFormatObj pixelFormatObj; - long numPixelFormats; - - ptrCGLChoosePixelFormat( attribs, &pixelFormatObj, &numPixelFormats ); - - if (!pixelFormatObj) // No full screen context support - return; - - CGLContextObj glContextObj; - ptrCGLCreateContext(pixelFormatObj, 0, &glContextObj); - ptrCGLDestroyPixelFormat(pixelFormatObj) ; - if (!glContextObj) - return; - - ptrCGLSetCurrentContext(glContextObj); - ptrCGLSetFullScreen(glContextObj) ; - - ptrglReadBuffer(GL_FRONT); - - ptrglFinish(); // Finish all OpenGL commands - ptrglPixelStorei(GL_PACK_ALIGNMENT, 4); // Force 4-byte alignment - ptrglPixelStorei(GL_PACK_ROW_LENGTH, 0); - ptrglPixelStorei(GL_PACK_SKIP_ROWS, 0); - ptrglPixelStorei(GL_PACK_SKIP_PIXELS, 0); - - // Fetch the data in XRGB format, matching the bitmap context. - ptrglReadPixels(GLint(displayRect.x()), GLint(displayRect.y()), - GLint(displayRect.width()), GLint(displayRect.height()), -#ifdef __BIG_ENDIAN__ - GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer -#else - GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, buffer -#endif - ); - - ptrCGLSetCurrentContext(0); - ptrCGLClearDrawable(glContextObj); // disassociate from full screen - ptrCGLDestroyContext(glContextObj); // and destroy the context -} - -// Returns a pixmap containing the screen contents at rect. -static QPixmap qt_mac_grabScreenRect(const QRect &rect) -{ - if (!resolveOpenGLSymbols()) - return QPixmap(); - - const int maxDisplays = 128; // 128 displays should be enough for everyone. - CGDirectDisplayID displays[maxDisplays]; - CGDisplayCount displayCount; - const CGRect cgRect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); - const CGDisplayErr err = CGGetDisplaysWithRect(cgRect, maxDisplays, displays, &displayCount); - - if (err && displayCount == 0) - return QPixmap(); - - long bytewidth = rect.width() * 4; // Assume 4 bytes/pixel for now - bytewidth = (bytewidth + 3) & ~3; // Align to 4 bytes - QVarLengthArray<char> buffer(rect.height() * bytewidth); - - for (uint i = 0; i < displayCount; ++i) { - const CGRect bounds = CGDisplayBounds(displays[i]); - // Translate to display-local coordinates - QRect displayRect = rect.translated(qRound(-bounds.origin.x), qRound(-bounds.origin.y)); - // Adjust for inverted y axis. - displayRect.moveTop(qRound(bounds.size.height) - displayRect.y() - rect.height()); - qt_mac_grabDisplayRect(displays[i], displayRect, buffer.data()); - } - - qt_mac_flipPixmap(buffer.data(), bytewidth, rect.height()); - QCFType<CGContextRef> bitmap = CGBitmapContextCreate(buffer.data(), rect.width(), - rect.height(), 8, bytewidth, - QCoreGraphicsPaintEngine::macGenericColorSpace(), - kCGImageAlphaNoneSkipFirst); - QCFType<CGImageRef> image = CGBitmapContextCreateImage(bitmap); - return QPixmap::fromMacCGImageRef(image); -} - -#ifndef QT_MAC_USE_COCOA // no QuickDraw in 64-bit mode -static QPixmap qt_mac_grabScreenRect_10_3(int x, int y, int w, int h, QWidget *widget) -{ - QPixmap pm = QPixmap(w, h); - extern WindowPtr qt_mac_window_for(const QWidget *); // qwidget_mac.cpp - const BitMap *windowPort = 0; - if((widget->windowType() == Qt::Desktop)) { - GDHandle gdh; - if(!(gdh=GetMainDevice())) - qDebug("Qt: internal: Unexpected condition reached: %s:%d", __FILE__, __LINE__); - windowPort = (BitMap*)(*(*gdh)->gdPMap); - } else { - windowPort = GetPortBitMapForCopyBits(GetWindowPort(qt_mac_window_for(widget))); - } - const BitMap *pixmapPort = GetPortBitMapForCopyBits(static_cast<GWorldPtr>(pm.macQDHandle())); - Rect macSrcRect, macDstRect; - SetRect(&macSrcRect, x, y, x + w, y + h); - SetRect(&macDstRect, 0, 0, w, h); - CopyBits(windowPort, pixmapPort, &macSrcRect, &macDstRect, srcCopy, 0); - return pm; -} -#endif - -QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h) -{ - QWidget *widget = QWidget::find(window); - if (widget == 0) - return QPixmap(); - - if(w == -1) - w = widget->width() - x; - if(h == -1) - h = widget->height() - y; - - QPoint globalCoord(0, 0); - globalCoord = widget->mapToGlobal(globalCoord); - QRect rect(globalCoord.x() + x, globalCoord.y() + y, w, h); - -#ifdef QT_MAC_USE_COCOA - return qt_mac_grabScreenRect(rect); -#else -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - return qt_mac_grabScreenRect(rect); - } else -#endif - { - return qt_mac_grabScreenRect_10_3(x, y, w, h, widget); - } -#endif // ifdef Q_WS_MAC64 -} - -/*! \internal - - Returns the QuickDraw CGrafPtr of the pixmap. 0 is returned if it can't - be obtained. Do not hold the pointer around for long as it can be - relocated. - - \warning This function is only available on Mac OS X. - \warning As of Qt 4.6, this function \e{always} returns zero. -*/ - -Qt::HANDLE QPixmap::macQDHandle() const -{ - return 0; -} - -/*! \internal - - Returns the QuickDraw CGrafPtr of the pixmap's alpha channel. 0 is - returned if it can't be obtained. Do not hold the pointer around for - long as it can be relocated. - - \warning This function is only available on Mac OS X. - \warning As of Qt 4.6, this function \e{always} returns zero. -*/ - -Qt::HANDLE QPixmap::macQDAlphaHandle() const -{ - return 0; -} - -/*! \internal - - Returns the CoreGraphics CGContextRef of the pixmap. 0 is returned if - it can't be obtained. It is the caller's responsiblity to - CGContextRelease the context when finished using it. - - \warning This function is only available on Mac OS X. -*/ - -Qt::HANDLE QPixmap::macCGHandle() const -{ - if (isNull()) - return 0; - - if (data->classId() == QPixmapData::MacClass) { - QMacPixmapData *d = static_cast<QMacPixmapData *>(data.data()); - if (!d->cg_data) - d->macCreateCGImageRef(); - CGImageRef ret = d->cg_data; - CGImageRetain(ret); - return ret; - } else if (data->classId() == QPixmapData::RasterClass) { - return qt_mac_image_to_cgimage(static_cast<QRasterPixmapData *>(data.data())->image); - } - return 0; -} - -bool QMacPixmapData::hasAlphaChannel() const -{ - return has_alpha; -} - -CGImageRef qt_mac_create_imagemask(const QPixmap &pixmap, const QRectF &sr) -{ - QMacPixmapData *px = static_cast<QMacPixmapData*>(pixmap.data.data()); - if (px->cg_mask) { - if (px->cg_mask_rect == sr) { - CGImageRetain(px->cg_mask); //reference for the caller - return px->cg_mask; - } - CGImageRelease(px->cg_mask); - px->cg_mask = 0; - } - - const int sx = qRound(sr.x()), sy = qRound(sr.y()), sw = qRound(sr.width()), sh = qRound(sr.height()); - const int sbpr = px->bytesPerRow; - const uint nbytes = sw * sh; - // alpha is always 255 for bitmaps, ignore it in this case. - const quint32 mask = px->depth() == 1 ? 0x00ffffff : 0xffffffff; - quint8 *dptr = static_cast<quint8 *>(malloc(nbytes)); - quint32 *sptr = px->pixels, *srow; - for(int y = sy, offset=0; y < sh; ++y) { - srow = sptr + (y * (sbpr / 4)); - for(int x = sx; x < sw; ++x) - *(dptr+(offset++)) = (*(srow+x) & mask) ? 255 : 0; - } - QCFType<CGDataProviderRef> provider = CGDataProviderCreateWithData(0, dptr, nbytes, qt_mac_cgimage_data_free); - px->cg_mask = CGImageMaskCreate(sw, sh, 8, 8, nbytes / sh, provider, 0, 0); - px->cg_mask_rect = sr; - CGImageRetain(px->cg_mask); //reference for the caller - return px->cg_mask; -} - -#ifndef QT_MAC_USE_COCOA -IconRef qt_mac_create_iconref(const QPixmap &px) -{ - if (px.isNull()) - return 0; - - //create icon - IconFamilyHandle iconFamily = reinterpret_cast<IconFamilyHandle>(NewHandle(0)); - //create data - { - struct { - OSType mac_type; - int width, height, depth; - bool mask; - } images[] = { - { kThumbnail32BitData, 128, 128, 32, false }, - { kThumbnail8BitMask, 128, 128, 8, true }, - { 0, 0, 0, 0, false } //end marker - }; - for(int i = 0; images[i].mac_type; i++) { - //get QPixmap data - QImage scaled_px = px.toImage().scaled(images[i].width, images[i].height); - - quint32 *sptr = (quint32 *) scaled_px.bits(); - quint32 *srow; - uint sbpr = scaled_px.bytesPerLine(); - - //get Handle data - const int dbpr = images[i].width * (images[i].depth/8); - Handle hdl = NewHandle(dbpr*images[i].height); - if(!sptr) { //handle null pixmap - memset((*hdl), '\0', dbpr*images[i].height); - } else if(images[i].mask) { - if(images[i].mac_type == kThumbnail8BitMask) { - for(int y = 0, hindex = 0; y < images[i].height; ++y) { - srow = sptr + (y * (sbpr/4)); - for(int x = 0; x < images[i].width; ++x) - *((*hdl)+(hindex++)) = qAlpha(*(srow+x)); - } - } - } else { - char *dest = (*hdl); -#if defined(__i386__) - if(images[i].depth == 32) { - for(int y = 0; y < images[i].height; ++y) { - uint *source = (uint*)((const uchar*)sptr+(sbpr*y)); - for(int x = 0; x < images[i].width; ++x, dest += 4) - *((uint*)dest) = CFSwapInt32(*(source + x)); - } - } else -#endif - { - for(int y = 0; y < images[i].height; ++y) - memcpy(dest+(y*dbpr), ((const uchar*)sptr+(sbpr*y)), dbpr); - } - } - - //set the family data to the Handle - OSStatus set = SetIconFamilyData(iconFamily, images[i].mac_type, hdl); - if(set != noErr) - qWarning("%s: %d -- Unable to create icon data[%d]!! %ld", - __FILE__, __LINE__, i, long(set)); - DisposeHandle(hdl); - } - } - - //acquire and cleanup - IconRef ret; - static int counter = 0; - const OSType kQtCreator = 'CUTE'; - RegisterIconRefFromIconFamily(kQtCreator, (OSType)counter, iconFamily, &ret); - AcquireIconRef(ret); - UnregisterIconRef(kQtCreator, (OSType)counter); - DisposeHandle(reinterpret_cast<Handle>(iconFamily)); - counter++; - return ret; - -} -#endif - -/*! \internal */ -QPaintEngine* QMacPixmapData::paintEngine() const -{ - if (!pengine) { - QMacPixmapData *that = const_cast<QMacPixmapData*>(this); - that->pengine = new QCoreGraphicsPaintEngine(); - } - return pengine; -} - -void QMacPixmapData::copy(const QPixmapData *data, const QRect &rect) -{ - if (data->pixelType() == BitmapType) { - QBitmap::fromImage(toImage().copy(rect)); - return; - } - - const QMacPixmapData *macData = static_cast<const QMacPixmapData*>(data); - - resize(rect.width(), rect.height()); - - has_alpha = macData->has_alpha; - has_mask = macData->has_mask; - uninit = false; - - const int x = rect.x(); - const int y = rect.y(); - char *dest = reinterpret_cast<char*>(pixels); - const char *src = reinterpret_cast<const char*>(macData->pixels + x) + y * macData->bytesPerRow; - for (int i = 0; i < h; ++i) { - memcpy(dest, src, w * 4); - dest += bytesPerRow; - src += macData->bytesPerRow; - } - - has_alpha = macData->has_alpha; - has_mask = macData->has_mask; -} - -bool QMacPixmapData::scroll(int dx, int dy, const QRect &rect) -{ - Q_UNUSED(dx); - Q_UNUSED(dy); - Q_UNUSED(rect); - return false; -} - -/*! - \since 4.2 - - Creates a \c CGImageRef equivalent to the QPixmap. Returns the \c CGImageRef handle. - - It is the caller's responsibility to release the \c CGImageRef data - after use. - - \warning This function is only available on Mac OS X. - - \sa fromMacCGImageRef() -*/ -CGImageRef QPixmap::toMacCGImageRef() const -{ - return (CGImageRef)macCGHandle(); -} - -/*! - \since 4.2 - - Returns a QPixmap that is equivalent to the given \a image. - - \warning This function is only available on Mac OS X. - - \sa toMacCGImageRef(), {QPixmap#Pixmap Conversion}{Pixmap Conversion} -*/ -QPixmap QPixmap::fromMacCGImageRef(CGImageRef image) -{ - const size_t w = CGImageGetWidth(image), - h = CGImageGetHeight(image); - QPixmap ret(w, h); - ret.fill(Qt::transparent); - CGRect rect = CGRectMake(0, 0, w, h); - CGContextRef ctx = qt_mac_cg_context(&ret); - qt_mac_drawCGImage(ctx, &rect, image); - CGContextRelease(ctx); - return ret; -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qpixmap_mac_p.h b/src/gui/platforms/mac/qpixmap_mac_p.h deleted file mode 100644 index 307e38aceb..0000000000 --- a/src/gui/platforms/mac/qpixmap_mac_p.h +++ /dev/null @@ -1,134 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPIXMAP_MAC_P_H -#define QPIXMAP_MAC_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtGui/private/qpixmapdata_p.h> -#include <QtGui/private/qpixmapdatafactory_p.h> -#include <QtGui/private/qt_mac_p.h> - -QT_BEGIN_NAMESPACE - -class QMacPixmapData : public QPixmapData -{ -public: - QMacPixmapData(PixelType type); - ~QMacPixmapData(); - - QPixmapData *createCompatiblePixmapData() const; - - void resize(int width, int height); - void fromImage(const QImage &image, Qt::ImageConversionFlags flags); - void copy(const QPixmapData *data, const QRect &rect); - bool scroll(int dx, int dy, const QRect &rect); - - int metric(QPaintDevice::PaintDeviceMetric metric) const; - void fill(const QColor &color); - QBitmap mask() const; - void setMask(const QBitmap &mask); - bool hasAlphaChannel() const; -// QPixmap transformed(const QTransform &matrix, -// Qt::TransformationMode mode) const; - void setAlphaChannel(const QPixmap &alphaChannel); - QPixmap alphaChannel() const; - QImage toImage() const; - QPaintEngine* paintEngine() const; - -private: - - uint has_alpha : 1, has_mask : 1, uninit : 1; - - void macSetHasAlpha(bool b); - void macGetAlphaChannel(QMacPixmapData *, bool asMask) const; - void macSetAlphaChannel(const QMacPixmapData *, bool asMask); - void macCreateCGImageRef(); - void macCreatePixels(); - void macReleaseCGImageRef(); - /* - pixels stores the pixmap data. pixelsToFree is either 0 or some memory - block that was bound to a CGImageRef and released, and for which the - release callback has been called. There are two uses to pixelsToFree: - - 1. If pixels == pixelsToFree, then we know that the CGImageRef is done\ - with the data and we can modify pixels without breaking CGImageRef's - mutability invariant. - - 2. If pixels != pixelsToFree and pixelsToFree != 0, then we can reuse - pixelsToFree later on instead of malloc'ing memory. - */ - quint32 *pixels; - uint pixelsSize; - quint32 *pixelsToFree; - uint bytesPerRow; - QRectF cg_mask_rect; - CGImageRef cg_data, cg_dataBeingReleased, cg_mask; - static QSet<QMacPixmapData*> validDataPointers; - - QPaintEngine *pengine; - - friend class QPixmap; - friend class QRasterBuffer; - friend class QRasterPaintEngine; - friend class QCoreGraphicsPaintEngine; - friend CGImageRef qt_mac_create_imagemask(const QPixmap&, const QRectF&); - friend quint32 *qt_mac_pixmap_get_base(const QPixmap*); - friend int qt_mac_pixmap_get_bytes_per_line(const QPixmap*); - friend void qt_mac_cgimage_data_free(void *, const void*, size_t); - friend IconRef qt_mac_create_iconref(const QPixmap&); - friend CGContextRef qt_mac_cg_context(const QPaintDevice*); - friend QColor qcolorForThemeTextColor(ThemeTextColor themeColor); -}; - -QT_END_NAMESPACE - -#endif // QPIXMAP_MAC_P_H diff --git a/src/gui/platforms/mac/qprintengine_mac.mm b/src/gui/platforms/mac/qprintengine_mac.mm deleted file mode 100644 index 1dce30301f..0000000000 --- a/src/gui/platforms/mac/qprintengine_mac.mm +++ /dev/null @@ -1,911 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qprintengine_mac_p.h> -#include <qdebug.h> -#include <qthread.h> -#include <QtCore/qcoreapplication.h> - -#ifndef QT_NO_PRINTER - -QT_BEGIN_NAMESPACE - -extern QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size); - -QMacPrintEngine::QMacPrintEngine(QPrinter::PrinterMode mode) : QPaintEngine(*(new QMacPrintEnginePrivate)) -{ - Q_D(QMacPrintEngine); - d->mode = mode; - d->initialize(); -} - -bool QMacPrintEngine::begin(QPaintDevice *dev) -{ - Q_D(QMacPrintEngine); - - Q_ASSERT(dev && dev->devType() == QInternal::Printer); - if (!static_cast<QPrinter *>(dev)->isValid()) - return false; - - if (d->state == QPrinter::Idle && !d->isPrintSessionInitialized()) // Need to reinitialize - d->initialize(); - - d->paintEngine->state = state; - d->paintEngine->begin(dev); - Q_ASSERT_X(d->state == QPrinter::Idle, "QMacPrintEngine", "printer already active"); - - if (PMSessionValidatePrintSettings(d->session, d->settings, kPMDontWantBoolean) != noErr - || PMSessionValidatePageFormat(d->session, d->format, kPMDontWantBoolean) != noErr) { - d->state = QPrinter::Error; - return false; - } - - if (!d->outputFilename.isEmpty()) { - QCFType<CFURLRef> outFile = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, - QCFString(d->outputFilename), - kCFURLPOSIXPathStyle, - false); - if (PMSessionSetDestination(d->session, d->settings, kPMDestinationFile, - kPMDocumentFormatPDF, outFile) != noErr) { - qWarning("QMacPrintEngine::begin: Problem setting file [%s]", d->outputFilename.toUtf8().constData()); - return false; - } - } - OSStatus status = noErr; -#ifndef QT_MAC_USE_COCOA - status = d->shouldSuppressStatus() ? PMSessionBeginCGDocumentNoDialog(d->session, d->settings, d->format) - : PMSessionBeginCGDocument(d->session, d->settings, d->format); -#else - status = PMSessionBeginCGDocumentNoDialog(d->session, d->settings, d->format); -#endif - - if (status != noErr) { - d->state = QPrinter::Error; - return false; - } - - d->state = QPrinter::Active; - setActive(true); - d->newPage_helper(); - return true; -} - -bool QMacPrintEngine::end() -{ - Q_D(QMacPrintEngine); - if (d->state == QPrinter::Aborted) - return true; // I was just here a function call ago :) - if(d->paintEngine->type() == QPaintEngine::CoreGraphics) { - // We dont need the paint engine to call restoreGraphicsState() - static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->stackCount = 0; - static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->hd = 0; - } - d->paintEngine->end(); - if (d->state != QPrinter::Idle) - d->releaseSession(); - d->state = QPrinter::Idle; - return true; -} - -QPaintEngine * -QMacPrintEngine::paintEngine() const -{ - return d_func()->paintEngine; -} - -Qt::HANDLE QMacPrintEngine::handle() const -{ - QCoreGraphicsPaintEngine *cgEngine = static_cast<QCoreGraphicsPaintEngine*>(paintEngine()); - return cgEngine->d_func()->hd; -} - -QMacPrintEnginePrivate::~QMacPrintEnginePrivate() -{ -#ifdef QT_MAC_USE_COCOA - [printInfo release]; -#endif - delete paintEngine; -} - -void QMacPrintEnginePrivate::setPaperSize(QPrinter::PaperSize ps) -{ - Q_Q(QMacPrintEngine); - QSizeF newSize = qt_paperSizeToQSizeF(ps); - QCFType<CFArrayRef> formats; - PMPrinter printer; - - if (PMSessionGetCurrentPrinter(session, &printer) == noErr - && PMSessionCreatePageFormatList(session, printer, &formats) == noErr) { - CFIndex total = CFArrayGetCount(formats); - PMPageFormat tmp; - PMRect paper; - for (CFIndex idx = 0; idx < total; ++idx) { - tmp = static_cast<PMPageFormat>( - const_cast<void *>(CFArrayGetValueAtIndex(formats, idx))); - PMGetUnadjustedPaperRect(tmp, &paper); - int wMM = int((paper.right - paper.left) / 72 * 25.4 + 0.5); - int hMM = int((paper.bottom - paper.top) / 72 * 25.4 + 0.5); - if (newSize.width() == wMM && newSize.height() == hMM) { - PMCopyPageFormat(tmp, format); - // reset the orientation and resolution as they are lost in the copy. - q->setProperty(QPrintEngine::PPK_Orientation, orient); - if (PMSessionValidatePageFormat(session, format, kPMDontWantBoolean) != noErr) { - // Don't know, warn for the moment. - qWarning("QMacPrintEngine, problem setting format and resolution for this page size"); - } - break; - } - } - } -} - -QPrinter::PaperSize QMacPrintEnginePrivate::paperSize() const -{ - PMRect paper; - PMGetUnadjustedPaperRect(format, &paper); - int wMM = int((paper.right - paper.left) / 72 * 25.4 + 0.5); - int hMM = int((paper.bottom - paper.top) / 72 * 25.4 + 0.5); - for (int i = QPrinter::A4; i < QPrinter::NPaperSize; ++i) { - QSizeF s = qt_paperSizeToQSizeF(QPrinter::PaperSize(i)); - if (s.width() == wMM && s.height() == hMM) - return (QPrinter::PaperSize)i; - } - return QPrinter::Custom; -} - -QList<QVariant> QMacPrintEnginePrivate::supportedResolutions() const -{ - Q_ASSERT_X(session, "QMacPrinterEngine::supportedResolutions", - "must have a valid printer session"); - UInt32 resCount; - QList<QVariant> resolutions; - PMPrinter printer; - if (PMSessionGetCurrentPrinter(session, &printer) == noErr) { - PMResolution res; - OSStatus status = PMPrinterGetPrinterResolutionCount(printer, &resCount); - if (status == kPMNotImplemented) { -#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) - // *Sigh* we have to use the non-indexed version. - if (PMPrinterGetPrinterResolution(printer, kPMMinSquareResolution, &res) == noErr) - resolutions.append(int(res.hRes)); - if (PMPrinterGetPrinterResolution(printer, kPMMaxSquareResolution, &res) == noErr) { - QVariant var(int(res.hRes)); - if (!resolutions.contains(var)) - resolutions.append(var); - } - if (PMPrinterGetPrinterResolution(printer, kPMDefaultResolution, &res) == noErr) { - QVariant var(int(res.hRes)); - if (!resolutions.contains(var)) - resolutions.append(var); - } -#endif - } else if (status == noErr) { - // According to the docs, index start at 1. - for (UInt32 i = 1; i <= resCount; ++i) { - if (PMPrinterGetIndexedPrinterResolution(printer, i, &res) == noErr) - resolutions.append(QVariant(int(res.hRes))); - } - } else { - qWarning("QMacPrintEngine::supportedResolutions: Unexpected error: %ld", long(status)); - } - } - return resolutions; -} - -bool QMacPrintEnginePrivate::shouldSuppressStatus() const -{ - if (suppressStatus == true) - return true; - - // Supress displaying the automatic progress dialog if we are printing - // from a non-gui thread. - return (qApp->thread() != QThread::currentThread()); -} - -QPrinter::PrinterState QMacPrintEngine::printerState() const -{ - return d_func()->state; -} - -bool QMacPrintEngine::newPage() -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - OSStatus err = -#ifndef QT_MAC_USE_COCOA - d->shouldSuppressStatus() ? PMSessionEndPageNoDialog(d->session) - : PMSessionEndPage(d->session); -#else - PMSessionEndPageNoDialog(d->session); -#endif - if (err != noErr) { - if (err == kPMCancel) { - // User canceled, we need to abort! - abort(); - } else { - // Not sure what the problem is... - qWarning("QMacPrintEngine::newPage: Cannot end current page. %ld", long(err)); - d->state = QPrinter::Error; - } - return false; - } - return d->newPage_helper(); -} - -bool QMacPrintEngine::abort() -{ - Q_D(QMacPrintEngine); - if (d->state != QPrinter::Active) - return false; - bool ret = end(); - d->state = QPrinter::Aborted; - return ret; -} - -static inline int qt_get_PDMWidth(PMPageFormat pformat, bool fullPage, - const PMResolution &resolution) -{ - int val = 0; - PMRect r; - qreal hRatio = resolution.hRes / 72; - if (fullPage) { - if (PMGetAdjustedPaperRect(pformat, &r) == noErr) - val = qRound((r.right - r.left) * hRatio); - } else { - if (PMGetAdjustedPageRect(pformat, &r) == noErr) - val = qRound((r.right - r.left) * hRatio); - } - return val; -} - -static inline int qt_get_PDMHeight(PMPageFormat pformat, bool fullPage, - const PMResolution &resolution) -{ - int val = 0; - PMRect r; - qreal vRatio = resolution.vRes / 72; - if (fullPage) { - if (PMGetAdjustedPaperRect(pformat, &r) == noErr) - val = qRound((r.bottom - r.top) * vRatio); - } else { - if (PMGetAdjustedPageRect(pformat, &r) == noErr) - val = qRound((r.bottom - r.top) * vRatio); - } - return val; -} - - -int QMacPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const -{ - Q_D(const QMacPrintEngine); - int val = 1; - switch (m) { - case QPaintDevice::PdmWidth: - if (d->hasCustomPaperSize) { - val = qRound(d->customSize.width()); - if (d->hasCustomPageMargins) { - val -= qRound(d->leftMargin + d->rightMargin); - } else { - QList<QVariant> margins = property(QPrintEngine::PPK_PageMargins).toList(); - val -= qRound(margins.at(0).toDouble() + margins.at(2).toDouble()); - } - } else { - val = qt_get_PDMWidth(d->format, property(PPK_FullPage).toBool(), d->resolution); - } - break; - case QPaintDevice::PdmHeight: - if (d->hasCustomPaperSize) { - val = qRound(d->customSize.height()); - if (d->hasCustomPageMargins) { - val -= qRound(d->topMargin + d->bottomMargin); - } else { - QList<QVariant> margins = property(QPrintEngine::PPK_PageMargins).toList(); - val -= qRound(margins.at(1).toDouble() + margins.at(3).toDouble()); - } - } else { - val = qt_get_PDMHeight(d->format, property(PPK_FullPage).toBool(), d->resolution); - } - break; - case QPaintDevice::PdmWidthMM: - val = metric(QPaintDevice::PdmWidth); - val = int((val * 254 + 5 * d->resolution.hRes) / (10 * d->resolution.hRes)); - break; - case QPaintDevice::PdmHeightMM: - val = metric(QPaintDevice::PdmHeight); - val = int((val * 254 + 5 * d->resolution.vRes) / (10 * d->resolution.vRes)); - break; - case QPaintDevice::PdmPhysicalDpiX: - case QPaintDevice::PdmPhysicalDpiY: { - PMPrinter printer; - if(PMSessionGetCurrentPrinter(d->session, &printer) == noErr) { - PMResolution resolution; -#ifndef QT_MAC_USE_COCOA -# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - PMPrinterGetOutputResolution(printer, d->settings, &resolution); - } else -# endif - { - PMPrinterGetPrinterResolution(printer, kPMCurrentValue, &resolution); - } -#else - PMPrinterGetOutputResolution(printer, d->settings, &resolution); -#endif - val = (int)resolution.vRes; - break; - } - //otherwise fall through - } - case QPaintDevice::PdmDpiY: - val = (int)d->resolution.vRes; - break; - case QPaintDevice::PdmDpiX: - val = (int)d->resolution.hRes; - break; - case QPaintDevice::PdmNumColors: - val = (1 << metric(QPaintDevice::PdmDepth)); - break; - case QPaintDevice::PdmDepth: - val = 24; - break; - default: - val = 0; - qWarning("QPrinter::metric: Invalid metric command"); - } - return val; -} - -void QMacPrintEnginePrivate::initialize() -{ - Q_Q(QMacPrintEngine); - -#ifndef QT_MAC_USE_COCOA - Q_ASSERT(!session); -#else - Q_ASSERT(!printInfo); -#endif - - if (!paintEngine) - paintEngine = new QCoreGraphicsPaintEngine(); - - q->gccaps = paintEngine->gccaps; - - fullPage = false; - -#ifndef QT_MAC_USE_COCOA - if (PMCreateSession(&session) != 0) - session = 0; -#else - QMacCocoaAutoReleasePool pool; - printInfo = [[NSPrintInfo alloc] initWithDictionary:[NSDictionary dictionary]]; - session = static_cast<PMPrintSession>([printInfo PMPrintSession]); -#endif - - PMPrinter printer; - if (session && PMSessionGetCurrentPrinter(session, &printer) == noErr) { - QList<QVariant> resolutions = supportedResolutions(); - if (!resolutions.isEmpty() && mode != QPrinter::ScreenResolution) { - if (resolutions.count() > 1 && mode == QPrinter::HighResolution) { - int max = 0; - for (int i = 0; i < resolutions.count(); ++i) { - int value = resolutions.at(i).toInt(); - if (value > max) - max = value; - } - resolution.hRes = resolution.vRes = max; - } else { - resolution.hRes = resolution.vRes = resolutions.at(0).toInt(); - } - if(resolution.hRes == 0) - resolution.hRes = resolution.vRes = 600; - } else { - resolution.hRes = resolution.vRes = qt_defaultDpi(); - } - } - -#ifndef QT_MAC_USE_COCOA - bool settingsInitialized = (settings != 0); - bool settingsOK = !settingsInitialized ? PMCreatePrintSettings(&settings) == noErr : true; - if (settingsOK && !settingsInitialized) - settingsOK = PMSessionDefaultPrintSettings(session, settings) == noErr; - - - bool formatInitialized = (format != 0); - bool formatOK = !formatInitialized ? PMCreatePageFormat(&format) == noErr : true; - if (formatOK) { - if (!formatInitialized) { - formatOK = PMSessionDefaultPageFormat(session, format) == noErr; - } - formatOK = PMSessionValidatePageFormat(session, format, kPMDontWantBoolean) == noErr; - } -#else - settings = static_cast<PMPrintSettings>([printInfo PMPrintSettings]); - format = static_cast<PMPageFormat>([printInfo PMPageFormat]); -#endif - -#ifndef QT_MAC_USE_COCOA - if (!settingsOK || !formatOK) { - qWarning("QMacPrintEngine::initialize: Unable to initialize QPainter"); - state = QPrinter::Error; - } -#endif - - QHash<QMacPrintEngine::PrintEnginePropertyKey, QVariant>::const_iterator propC; - for (propC = valueCache.constBegin(); propC != valueCache.constEnd(); propC++) { - q->setProperty(propC.key(), propC.value()); - } -} - -void QMacPrintEnginePrivate::releaseSession() -{ -#ifndef QT_MAC_USE_COCOA - if (shouldSuppressStatus()) { - PMSessionEndPageNoDialog(session); - PMSessionEndDocumentNoDialog(session); - } else { - PMSessionEndPage(session); - PMSessionEndDocument(session); - } - PMRelease(session); -#else - PMSessionEndPageNoDialog(session); - PMSessionEndDocumentNoDialog(session); - [printInfo release]; -#endif - printInfo = 0; - session = 0; -} - -bool QMacPrintEnginePrivate::newPage_helper() -{ - Q_Q(QMacPrintEngine); - Q_ASSERT(state == QPrinter::Active); - - if (PMSessionError(session) != noErr) { - q->abort(); - return false; - } - - // pop the stack of saved graphic states, in case we get the same - // context back - either way, the stack count should be 0 when we - // get the new one - QCoreGraphicsPaintEngine *cgEngine = static_cast<QCoreGraphicsPaintEngine*>(paintEngine); - while (cgEngine->d_func()->stackCount > 0) - cgEngine->d_func()->restoreGraphicsState(); - - OSStatus status = -#ifndef QT_MAC_USE_COCOA - shouldSuppressStatus() ? PMSessionBeginPageNoDialog(session, format, 0) - : PMSessionBeginPage(session, format, 0); -#else - PMSessionBeginPageNoDialog(session, format, 0); -#endif - if(status != noErr) { - state = QPrinter::Error; - return false; - } - - QRect page = q->property(QPrintEngine::PPK_PageRect).toRect(); - QRect paper = q->property(QPrintEngine::PPK_PaperRect).toRect(); - - CGContextRef cgContext; - OSStatus err = noErr; - err = PMSessionGetCGGraphicsContext(session, &cgContext); - if(err != noErr) { - qWarning("QMacPrintEngine::newPage: Cannot retrieve CoreGraphics context: %ld", long(err)); - state = QPrinter::Error; - return false; - } - cgEngine->d_func()->hd = cgContext; - - // Set the resolution as a scaling ration of 72 (the default). - CGContextScaleCTM(cgContext, 72 / resolution.hRes, 72 / resolution.vRes); - - CGContextScaleCTM(cgContext, 1, -1); - CGContextTranslateCTM(cgContext, 0, -paper.height()); - if (!fullPage) - CGContextTranslateCTM(cgContext, page.x() - paper.x(), page.y() - paper.y()); - cgEngine->d_func()->orig_xform = CGContextGetCTM(cgContext); - cgEngine->d_func()->setClip(0); - cgEngine->state->dirtyFlags = QPaintEngine::DirtyFlag(QPaintEngine::AllDirty - & ~(QPaintEngine::DirtyClipEnabled - | QPaintEngine::DirtyClipRegion - | QPaintEngine::DirtyClipPath)); - if (cgEngine->painter()->hasClipping()) - cgEngine->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled; - cgEngine->syncState(); - return true; -} - - -void QMacPrintEngine::updateState(const QPaintEngineState &state) -{ - d_func()->paintEngine->updateState(state); -} - -void QMacPrintEngine::drawRects(const QRectF *r, int num) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawRects(r, num); -} - -void QMacPrintEngine::drawPoints(const QPointF *points, int pointCount) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawPoints(points, pointCount); -} - -void QMacPrintEngine::drawEllipse(const QRectF &r) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawEllipse(r); -} - -void QMacPrintEngine::drawLines(const QLineF *lines, int lineCount) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawLines(lines, lineCount); -} - -void QMacPrintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawPolygon(points, pointCount, mode); -} - -void QMacPrintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawPixmap(r, pm, sr); -} - -void QMacPrintEngine::drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawImage(r, pm, sr, flags); -} - -void QMacPrintEngine::drawTextItem(const QPointF &p, const QTextItem &ti) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawTextItem(p, ti); -} - -void QMacPrintEngine::drawTiledPixmap(const QRectF &dr, const QPixmap &pixmap, const QPointF &sr) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawTiledPixmap(dr, pixmap, sr); -} - -void QMacPrintEngine::drawPath(const QPainterPath &path) -{ - Q_D(QMacPrintEngine); - Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawPath(path); -} - - -void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value) -{ - Q_D(QMacPrintEngine); - - d->valueCache.insert(key, value); - if (!d->session) - return; - - switch (key) { - case PPK_CollateCopies: - break; - case PPK_ColorMode: - break; - case PPK_Creator: - break; - case PPK_DocumentName: - break; - case PPK_PageOrder: - break; - case PPK_PaperSource: - break; - case PPK_SelectionOption: - break; - case PPK_Resolution: { - PMPrinter printer; - UInt32 count; - if (PMSessionGetCurrentPrinter(d->session, &printer) != noErr) - break; - if (PMPrinterGetPrinterResolutionCount(printer, &count) != noErr) - break; - PMResolution resolution = { 0.0, 0.0 }; - PMResolution bestResolution = { 0.0, 0.0 }; - int dpi = value.toInt(); - int bestDistance = INT_MAX; - for (UInt32 i = 1; i <= count; ++i) { // Yes, it starts at 1 - if (PMPrinterGetIndexedPrinterResolution(printer, i, &resolution) == noErr) { - if (dpi == int(resolution.hRes)) { - bestResolution = resolution; - break; - } else { - int distance = qAbs(dpi - int(resolution.hRes)); - if (distance < bestDistance) { - bestDistance = distance; - bestResolution = resolution; - } - } - } - } - PMSessionValidatePageFormat(d->session, d->format, kPMDontWantBoolean); - break; - } - - case PPK_FullPage: - d->fullPage = value.toBool(); - break; - case PPK_CopyCount: // fallthrough - case PPK_NumberOfCopies: - PMSetCopies(d->settings, value.toInt(), false); - break; - case PPK_Orientation: { - if (d->state == QPrinter::Active) { - qWarning("QMacPrintEngine::setOrientation: Orientation cannot be changed during a print job, ignoring change"); - } else { - QPrinter::Orientation newOrientation = QPrinter::Orientation(value.toInt()); - if (d->hasCustomPaperSize && (d->orient != newOrientation)) - d->customSize = QSizeF(d->customSize.height(), d->customSize.width()); - d->orient = newOrientation; - PMOrientation o = d->orient == QPrinter::Portrait ? kPMPortrait : kPMLandscape; - PMSetOrientation(d->format, o, false); - PMSessionValidatePageFormat(d->session, d->format, kPMDontWantBoolean); - } - break; } - case PPK_OutputFileName: - d->outputFilename = value.toString(); - break; - case PPK_PaperSize: - d->setPaperSize(QPrinter::PaperSize(value.toInt())); - break; - case PPK_PrinterName: { - bool printerNameSet = false; - OSStatus status = noErr; - QCFType<CFArrayRef> printerList; - status = PMServerCreatePrinterList(kPMServerLocal, &printerList); - if (status == noErr) { - CFIndex count = CFArrayGetCount(printerList); - for (CFIndex i=0; i<count; ++i) { - PMPrinter printer = static_cast<PMPrinter>(const_cast<void *>(CFArrayGetValueAtIndex(printerList, i))); - QString name = QCFString::toQString(PMPrinterGetName(printer)); - if (name == value.toString()) { - status = PMSessionSetCurrentPMPrinter(d->session, printer); - printerNameSet = true; - break; - } - } - } - if (status != noErr) - qWarning("QMacPrintEngine::setPrinterName: Error setting printer: %ld", long(status)); - if (!printerNameSet) { - qWarning("QMacPrintEngine::setPrinterName: Failed to set printer named '%s'.", qPrintable(value.toString())); - d->releaseSession(); - d->state = QPrinter::Idle; - } - break; } - case PPK_SuppressSystemPrintStatus: - d->suppressStatus = value.toBool(); - break; - case PPK_CustomPaperSize: - { - PMOrientation orientation; - PMGetOrientation(d->format, &orientation); - d->hasCustomPaperSize = true; - d->customSize = value.toSizeF(); - if (orientation != kPMPortrait) - d->customSize = QSizeF(d->customSize.height(), d->customSize.width()); - break; - } - case PPK_PageMargins: - { - QList<QVariant> margins(value.toList()); - Q_ASSERT(margins.size() == 4); - d->leftMargin = margins.at(0).toDouble(); - d->topMargin = margins.at(1).toDouble(); - d->rightMargin = margins.at(2).toDouble(); - d->bottomMargin = margins.at(3).toDouble(); - d->hasCustomPageMargins = true; - break; - } - - default: - break; - } -} - -QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const -{ - Q_D(const QMacPrintEngine); - QVariant ret; - - if (!d->session && d->valueCache.contains(key)) - return *d->valueCache.find(key); - - switch (key) { - case PPK_CollateCopies: - ret = false; - break; - case PPK_ColorMode: - ret = QPrinter::Color; - break; - case PPK_Creator: - break; - case PPK_DocumentName: - break; - case PPK_FullPage: - ret = d->fullPage; - break; - case PPK_NumberOfCopies: - ret = 1; - break; - case PPK_CopyCount: { - UInt32 copies = 1; - PMGetCopies(d->settings, &copies); - ret = (uint) copies; - break; - } - case PPK_SupportsMultipleCopies: - ret = true; - break; - case PPK_Orientation: - PMOrientation orientation; - PMGetOrientation(d->format, &orientation); - ret = orientation == kPMPortrait ? QPrinter::Portrait : QPrinter::Landscape; - break; - case PPK_OutputFileName: - ret = d->outputFilename; - break; - case PPK_PageOrder: - break; - case PPK_PaperSource: - break; - case PPK_PageRect: { - // PageRect is returned in device pixels - QRect r; - PMRect macrect, macpaper; - qreal hRatio = d->resolution.hRes / 72; - qreal vRatio = d->resolution.vRes / 72; - if (d->hasCustomPaperSize) { - r = QRect(0, 0, qRound(d->customSize.width() * hRatio), qRound(d->customSize.height() * vRatio)); - if (d->hasCustomPageMargins) { - r.adjust(qRound(d->leftMargin * hRatio), qRound(d->topMargin * vRatio), - -qRound(d->rightMargin * hRatio), -qRound(d->bottomMargin * vRatio)); - } else { - QList<QVariant> margins = property(QPrintEngine::PPK_PageMargins).toList(); - r.adjust(qRound(margins.at(0).toDouble() * hRatio), - qRound(margins.at(1).toDouble() * vRatio), - -qRound(margins.at(2).toDouble() * hRatio), - -qRound(margins.at(3).toDouble()) * vRatio); - } - } else if (PMGetAdjustedPageRect(d->format, ¯ect) == noErr - && PMGetAdjustedPaperRect(d->format, &macpaper) == noErr) - { - if (d->fullPage || d->hasCustomPageMargins) { - r.setCoords(int(macpaper.left * hRatio), int(macpaper.top * vRatio), - int(macpaper.right * hRatio), int(macpaper.bottom * vRatio)); - r.translate(-r.x(), -r.y()); - if (d->hasCustomPageMargins) { - r.adjust(qRound(d->leftMargin * hRatio), qRound(d->topMargin * vRatio), - -qRound(d->rightMargin * hRatio), -qRound(d->bottomMargin * vRatio)); - } - } else { - r.setCoords(int(macrect.left * hRatio), int(macrect.top * vRatio), - int(macrect.right * hRatio), int(macrect.bottom * vRatio)); - r.translate(int(-macpaper.left * hRatio), int(-macpaper.top * vRatio)); - } - } - ret = r; - break; } - case PPK_PaperSize: - ret = d->paperSize(); - break; - case PPK_PaperRect: { - QRect r; - PMRect macrect; - if (d->hasCustomPaperSize) { - r = QRect(0, 0, qRound(d->customSize.width()), qRound(d->customSize.height())); - } else if (PMGetAdjustedPaperRect(d->format, ¯ect) == noErr) { - qreal hRatio = d->resolution.hRes / 72; - qreal vRatio = d->resolution.vRes / 72; - r.setCoords(int(macrect.left * hRatio), int(macrect.top * vRatio), - int(macrect.right * hRatio), int(macrect.bottom * vRatio)); - r.translate(-r.x(), -r.y()); - } - ret = r; - break; } - case PPK_PrinterName: { - PMPrinter printer; - OSStatus status = PMSessionGetCurrentPrinter(d->session, &printer); - if (status != noErr) - qWarning("QMacPrintEngine::printerName: Failed getting current PMPrinter: %ld", long(status)); - if (printer) - ret = QCFString::toQString(PMPrinterGetName(printer)); - break; } - case PPK_Resolution: { - ret = d->resolution.hRes; - break; - } - case PPK_SupportedResolutions: - ret = d->supportedResolutions(); - break; - case PPK_CustomPaperSize: - ret = d->customSize; - break; - case PPK_PageMargins: - { - QList<QVariant> margins; - if (d->hasCustomPageMargins) { - margins << d->leftMargin << d->topMargin - << d->rightMargin << d->bottomMargin; - } else { - PMPaperMargins paperMargins; - PMPaper paper; - PMGetPageFormatPaper(d->format, &paper); - PMPaperGetMargins(paper, &paperMargins); - margins << paperMargins.left << paperMargins.top - << paperMargins.right << paperMargins.bottom; - } - ret = margins; - break; - } - default: - break; - } - return ret; -} - -QT_END_NAMESPACE - -#endif // QT_NO_PRINTER diff --git a/src/gui/platforms/mac/qprintengine_mac_p.h b/src/gui/platforms/mac/qprintengine_mac_p.h deleted file mode 100644 index 511705d26f..0000000000 --- a/src/gui/platforms/mac/qprintengine_mac_p.h +++ /dev/null @@ -1,166 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPRINTENGINE_MAC_P_H -#define QPRINTENGINE_MAC_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QT_NO_PRINTER - -#include "QtGui/qprinter.h" -#include "QtGui/qprintengine.h" -#include "private/qpaintengine_mac_p.h" -#include "private/qpainter_p.h" - -#ifdef __OBJC__ -@class NSPrintInfo; -#else -typedef void NSPrintInfo; -#endif - -QT_BEGIN_NAMESPACE - -class QPrinterPrivate; -class QMacPrintEnginePrivate; -class QMacPrintEngine : public QPaintEngine, public QPrintEngine -{ - Q_DECLARE_PRIVATE(QMacPrintEngine) -public: - QMacPrintEngine(QPrinter::PrinterMode mode); - - Qt::HANDLE handle() const; - - bool begin(QPaintDevice *dev); - bool end(); - virtual QPaintEngine::Type type() const { return QPaintEngine::MacPrinter; } - - QPaintEngine *paintEngine() const; - - void setProperty(PrintEnginePropertyKey key, const QVariant &value); - QVariant property(PrintEnginePropertyKey key) const; - - QPrinter::PrinterState printerState() const; - - bool newPage(); - bool abort(); - int metric(QPaintDevice::PaintDeviceMetric) const; - - //forwarded functions - - void updateState(const QPaintEngineState &state); - - virtual void drawLines(const QLineF *lines, int lineCount); - virtual void drawRects(const QRectF *r, int num); - virtual void drawPoints(const QPointF *p, int pointCount); - virtual void drawEllipse(const QRectF &r); - virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); - virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags); - virtual void drawTextItem(const QPointF &p, const QTextItem &ti); - virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); - virtual void drawPath(const QPainterPath &); - -private: - friend class QPrintDialog; - friend class QPageSetupDialog; -}; - -class QMacPrintEnginePrivate : public QPaintEnginePrivate -{ - Q_DECLARE_PUBLIC(QMacPrintEngine) -public: - QPrinter::PrinterMode mode; - QPrinter::PrinterState state; - QPrinter::Orientation orient; - NSPrintInfo *printInfo; - PMPageFormat format; - PMPrintSettings settings; - PMPrintSession session; - PMResolution resolution; - QString outputFilename; - bool fullPage; - QPaintEngine *paintEngine; - bool suppressStatus; - bool hasCustomPaperSize; - QSizeF customSize; - bool hasCustomPageMargins; - qreal leftMargin; - qreal topMargin; - qreal rightMargin; - qreal bottomMargin; - QHash<QMacPrintEngine::PrintEnginePropertyKey, QVariant> valueCache; - QMacPrintEnginePrivate() : mode(QPrinter::ScreenResolution), state(QPrinter::Idle), - orient(QPrinter::Portrait), printInfo(0), format(0), settings(0), - session(0), paintEngine(0), suppressStatus(false), - hasCustomPaperSize(false), hasCustomPageMargins(false) {} - ~QMacPrintEnginePrivate(); - void initialize(); - void releaseSession(); - bool newPage_helper(); - void setPaperSize(QPrinter::PaperSize ps); - QPrinter::PaperSize paperSize() const; - QList<QVariant> supportedResolutions() const; - inline bool isPrintSessionInitialized() const - { -#ifndef QT_MAC_USE_COCOA - return session != 0; -#else - return printInfo != 0; -#endif - } - bool shouldSuppressStatus() const; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_PRINTER - -#endif // QPRINTENGINE_WIN_P_H diff --git a/src/gui/platforms/mac/qprinterinfo_mac.cpp b/src/gui/platforms/mac/qprinterinfo_mac.cpp deleted file mode 100644 index b24ab70267..0000000000 --- a/src/gui/platforms/mac/qprinterinfo_mac.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qprinterinfo.h" -#include "qprinterinfo_p.h" - -#include "private/qt_mac_p.h" - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_PRINTER - -extern QPrinter::PaperSize qSizeFTopaperSize(const QSizeF &size); - -QList<QPrinterInfo> QPrinterInfo::availablePrinters() -{ - QList<QPrinterInfo> printers; - - QCFType<CFArrayRef> array; - if (PMServerCreatePrinterList(kPMServerLocal, &array) == noErr) { - CFIndex count = CFArrayGetCount(array); - for (int i = 0; i < count; ++i) { - PMPrinter printer = static_cast<PMPrinter>(const_cast<void *>(CFArrayGetValueAtIndex(array, i))); - QString printerName = QCFString::toQString(PMPrinterGetName(printer)); - - QPrinterInfo printerInfo(printerName); - if (PMPrinterIsDefault(printer)) - printerInfo.d_ptr->isDefault = true; - printers.append(printerInfo); - } - } - - return printers; -} - -QPrinterInfo QPrinterInfo::defaultPrinter() -{ - QList<QPrinterInfo> printers = availablePrinters(); - foreach (const QPrinterInfo &printerInfo, printers) { - if (printerInfo.isDefault()) - return printerInfo; - } - - return printers.value(0); -} - -QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const -{ - const Q_D(QPrinterInfo); - - QList<QPrinter::PaperSize> paperSizes; - if (isNull()) - return paperSizes; - - PMPrinter cfPrn = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(d->name)); - if (!cfPrn) - return paperSizes; - - CFArrayRef array; - if (PMPrinterGetPaperList(cfPrn, &array) != noErr) { - PMRelease(cfPrn); - return paperSizes; - } - - int count = CFArrayGetCount(array); - for (int i = 0; i < count; ++i) { - PMPaper paper = static_cast<PMPaper>(const_cast<void *>(CFArrayGetValueAtIndex(array, i))); - double width, height; - if (PMPaperGetWidth(paper, &width) == noErr && PMPaperGetHeight(paper, &height) == noErr) { - QSizeF size(width * 0.3527, height * 0.3527); - paperSizes.append(qSizeFTopaperSize(size)); - } - } - - PMRelease(cfPrn); - - return paperSizes; -} - -#endif // QT_NO_PRINTER - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qrawfont_mac.cpp b/src/gui/platforms/mac/qrawfont_mac.cpp deleted file mode 100644 index 1ed4185a5d..0000000000 --- a/src/gui/platforms/mac/qrawfont_mac.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/qglobal.h> - -#if !defined(QT_NO_RAWFONT) - -#include "qrawfont_p.h" -#include "qfontengine_coretext_p.h" - -QT_BEGIN_NAMESPACE - -void QRawFontPrivate::platformCleanUp() -{ -} - -extern int qt_defaultDpi(); - -void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, - int pixelSize, - QFont::HintingPreference hintingPreference) -{ - // Mac OS X ignores it - Q_UNUSED(hintingPreference); - - QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(NULL, - fontData.constData(), fontData.size(), NULL); - - CGFontRef cgFont = CGFontCreateWithDataProvider(dataProvider); - - if (cgFont == NULL) { - qWarning("QRawFont::platformLoadFromData: CGFontCreateWithDataProvider failed"); - } else { - QFontDef def; - def.pixelSize = pixelSize; - def.pointSize = pixelSize * 72.0 / qt_defaultDpi(); - fontEngine = new QCoreTextFontEngine(cgFont, def); - CFRelease(cgFont); - fontEngine->ref.ref(); - } -} - -QT_END_NAMESPACE - -#endif // QT_NO_RAWFONT diff --git a/src/gui/platforms/mac/qregion_mac.cpp b/src/gui/platforms/mac/qregion_mac.cpp deleted file mode 100644 index 50fd783df4..0000000000 --- a/src/gui/platforms/mac/qregion_mac.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qt_mac_p.h> -#include "qcoreapplication.h" -#include <qlibrary.h> - -QT_BEGIN_NAMESPACE - -QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0 }; - -#if defined(Q_WS_MAC32) && !defined(QT_MAC_USE_COCOA) -#define RGN_CACHE_SIZE 200 -#ifdef RGN_CACHE_SIZE -static bool rgncache_init = false; -static int rgncache_used; -static RgnHandle rgncache[RGN_CACHE_SIZE]; -static void qt_mac_cleanup_rgncache() -{ - rgncache_init = false; - for(int i = 0; i < RGN_CACHE_SIZE; ++i) { - if(rgncache[i]) { - --rgncache_used; - DisposeRgn(rgncache[i]); - rgncache[i] = 0; - } - } -} -#endif - -Q_GUI_EXPORT RgnHandle qt_mac_get_rgn() -{ -#ifdef RGN_CACHE_SIZE - if(!rgncache_init) { - rgncache_used = 0; - rgncache_init = true; - for(int i = 0; i < RGN_CACHE_SIZE; ++i) - rgncache[i] = 0; - qAddPostRoutine(qt_mac_cleanup_rgncache); - } else if(rgncache_used) { - for(int i = 0; i < RGN_CACHE_SIZE; ++i) { - if(rgncache[i]) { - RgnHandle ret = rgncache[i]; - SetEmptyRgn(ret); - rgncache[i] = 0; - --rgncache_used; - return ret; - } - } - } -#endif - return NewRgn(); -} - -Q_GUI_EXPORT void qt_mac_dispose_rgn(RgnHandle r) -{ -#ifdef RGN_CACHE_SIZE - if(rgncache_init && rgncache_used < RGN_CACHE_SIZE) { - for(int i = 0; i < RGN_CACHE_SIZE; ++i) { - if(!rgncache[i]) { - ++rgncache_used; - rgncache[i] = r; - return; - } - } - } -#endif - DisposeRgn(r); -} - -static OSStatus qt_mac_get_rgn_rect(UInt16 msg, RgnHandle, const Rect *rect, void *reg) -{ - if(msg == kQDRegionToRectsMsgParse) { - QRect rct(rect->left, rect->top, (rect->right - rect->left), (rect->bottom - rect->top)); - if(!rct.isEmpty()) - *((QRegion *)reg) += rct; - } - return noErr; -} - -Q_GUI_EXPORT QRegion qt_mac_convert_mac_region(RgnHandle rgn) -{ - return QRegion::fromQDRgn(rgn); -} - -QRegion QRegion::fromQDRgn(RgnHandle rgn) -{ - QRegion ret; - ret.detach(); - OSStatus oss = QDRegionToRects(rgn, kQDParseRegionFromTopLeft, qt_mac_get_rgn_rect, (void *)&ret); - if(oss != noErr) - return QRegion(); - return ret; -} - -/*! - \internal - Create's a RegionHandle, it's the caller's responsibility to release. -*/ -RgnHandle QRegion::toQDRgn() const -{ - RgnHandle rgnHandle = qt_mac_get_rgn(); - if(d->qt_rgn && d->qt_rgn->numRects) { - RgnHandle tmp_rgn = qt_mac_get_rgn(); - int n = d->qt_rgn->numRects; - const QRect *qt_r = (n == 1) ? &d->qt_rgn->extents : d->qt_rgn->rects.constData(); - while (n--) { - SetRectRgn(tmp_rgn, - qMax(SHRT_MIN, qt_r->x()), - qMax(SHRT_MIN, qt_r->y()), - qMin(SHRT_MAX, qt_r->right() + 1), - qMin(SHRT_MAX, qt_r->bottom() + 1)); - UnionRgn(rgnHandle, tmp_rgn, rgnHandle); - ++qt_r; - } - qt_mac_dispose_rgn(tmp_rgn); - } - return rgnHandle; -} - -/*! - \internal - Create's a RegionHandle, it's the caller's responsibility to release. - Returns 0 if the QRegion overflows. -*/ -RgnHandle QRegion::toQDRgnForUpdate_sys() const -{ - RgnHandle rgnHandle = qt_mac_get_rgn(); - if(d->qt_rgn && d->qt_rgn->numRects) { - RgnHandle tmp_rgn = qt_mac_get_rgn(); - int n = d->qt_rgn->numRects; - const QRect *qt_r = (n == 1) ? &d->qt_rgn->extents : d->qt_rgn->rects.constData(); - while (n--) { - - // detect overflow. Tested for use with HIViewSetNeedsDisplayInRegion - // in QWidgetPrivate::update_sys(). - enum { HIViewSetNeedsDisplayInRegionOverflow = 10000 }; // empirically determined conservative value - if (qt_r->right() > HIViewSetNeedsDisplayInRegionOverflow || qt_r->bottom() > HIViewSetNeedsDisplayInRegionOverflow) { - qt_mac_dispose_rgn(tmp_rgn); - qt_mac_dispose_rgn(rgnHandle); - return 0; - } - - SetRectRgn(tmp_rgn, - qMax(SHRT_MIN, qt_r->x()), - qMax(SHRT_MIN, qt_r->y()), - qMin(SHRT_MAX, qt_r->right() + 1), - qMin(SHRT_MAX, qt_r->bottom() + 1)); - UnionRgn(rgnHandle, tmp_rgn, rgnHandle); - ++qt_r; - } - qt_mac_dispose_rgn(tmp_rgn); - } - return rgnHandle; -} - -#endif - -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) -OSStatus QRegion::shape2QRegionHelper(int inMessage, HIShapeRef, - const CGRect *inRect, void *inRefcon) -{ - QRegion *region = static_cast<QRegion *>(inRefcon); - if (!region) - return paramErr; - - switch (inMessage) { - case kHIShapeEnumerateRect: - *region += QRect(inRect->origin.x, inRect->origin.y, - inRect->size.width, inRect->size.height); - break; - case kHIShapeEnumerateInit: - // Assume the region is already setup correctly - case kHIShapeEnumerateTerminate: - default: - break; - } - return noErr; -} -#endif - -/*! - \internal - Create's a mutable shape, it's the caller's responsibility to release. - WARNING: this function clamps the coordinates to SHRT_MIN/MAX on 10.4 and below. -*/ -HIMutableShapeRef QRegion::toHIMutableShape() const -{ - HIMutableShapeRef shape = HIShapeCreateMutable(); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - if (d->qt_rgn && d->qt_rgn->numRects) { - int n = d->qt_rgn->numRects; - const QRect *qt_r = (n == 1) ? &d->qt_rgn->extents : d->qt_rgn->rects.constData(); - while (n--) { - CGRect cgRect = CGRectMake(qt_r->x(), qt_r->y(), qt_r->width(), qt_r->height()); - HIShapeUnionWithRect(shape, &cgRect); - ++qt_r; - } - } - } else -#endif - { -#ifndef QT_MAC_USE_COCOA - QCFType<HIShapeRef> qdShape = HIShapeCreateWithQDRgn(QMacSmartQuickDrawRegion(toQDRgn())); - HIShapeUnion(qdShape, shape, shape); -#endif - } - return shape; -} - -#if !defined(Q_WS_MAC64) && !defined(QT_MAC_USE_COCOA) -typedef OSStatus (*PtrHIShapeGetAsQDRgn)(HIShapeRef, RgnHandle); -static PtrHIShapeGetAsQDRgn ptrHIShapeGetAsQDRgn = 0; -#endif - - -QRegion QRegion::fromHIShapeRef(HIShapeRef shape) -{ - QRegion returnRegion; - returnRegion.detach(); - // Begin gratuitous #if-defery -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) -# ifndef Q_WS_MAC64 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { -# endif - HIShapeEnumerate(shape, kHIShapeParseFromTopLeft, shape2QRegionHelper, &returnRegion); -# ifndef Q_WS_MAC64 - } else -# endif -#endif - { -#if !defined(Q_WS_MAC64) && !defined(QT_MAC_USE_COCOA) - if (ptrHIShapeGetAsQDRgn == 0) { - QLibrary library(QLatin1String("/System/Library/Frameworks/Carbon.framework/Carbon")); - library.setLoadHints(QLibrary::ExportExternalSymbolsHint); - ptrHIShapeGetAsQDRgn = reinterpret_cast<PtrHIShapeGetAsQDRgn>(library.resolve("HIShapeGetAsQDRgn")); - } - RgnHandle rgn = qt_mac_get_rgn(); - ptrHIShapeGetAsQDRgn(shape, rgn); - returnRegion = QRegion::fromQDRgn(rgn); - qt_mac_dispose_rgn(rgn); -#endif - } - return returnRegion; -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qsound_mac.mm b/src/gui/platforms/mac/qsound_mac.mm deleted file mode 100644 index 5a9af135b0..0000000000 --- a/src/gui/platforms/mac/qsound_mac.mm +++ /dev/null @@ -1,190 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include <qapplication.h> -#include "qsound.h" -#include "qsound_p.h" -#include <private/qt_mac_p.h> -#include <qhash.h> -#include <qdebug.h> -#import <AppKit/AppKit.h> - -#include <AppKit/NSSound.h> - -QT_BEGIN_NAMESPACE - -void qt_mac_beep() -{ - NSBeep(); -} - -QT_END_NAMESPACE - -#ifndef QT_NO_SOUND - -QT_BEGIN_NAMESPACE - -typedef QHash<QSound *, NSSound const *> Sounds; -static Sounds sounds; - -class QAuServerMac : public QAuServer -{ - Q_OBJECT -public: - QAuServerMac(QObject* parent) : QAuServer(parent) { } - void play(const QString& filename); - void play(QSound *s); - void stop(QSound*); - bool okay() { return true; } - using QAuServer::decLoop; // promote to public. -protected: - NSSound *createNSSound(const QString &filename, QSound *qSound); -}; - -QT_END_NAMESPACE - -#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 -@protocol NSSoundDelegate <NSObject> --(void)sound:(NSSound *)sound didFinishPlaying:(BOOL)aBool; -@end -#endif - -QT_USE_NAMESPACE - -@interface QT_MANGLE_NAMESPACE(QMacSoundDelegate) : NSObject<NSSoundDelegate> { - QSound *qSound; // may be null. - QAuServerMac* server; -} --(id)initWithQSound:(QSound*)sound:(QAuServerMac*)server; -@end - -@implementation QT_MANGLE_NAMESPACE(QMacSoundDelegate) --(id)initWithQSound:(QSound*)s:(QAuServerMac*)serv { - self = [super init]; - if(self) { - qSound = s; - server = serv; - } - return self; -} - -// Delegate function that gets called each time a sound finishes. --(void)sound:(NSSound *)sound didFinishPlaying:(BOOL)finishedOk -{ - // qSound is null if this sound was started by play(QString), - // in which case there is no corresponding QSound object. - if (qSound == 0) { - [sound release]; - [self release]; - return; - } - - // finishedOk is false if the sound cold not be played or - // if it was interrupted by stop(). - if (finishedOk == false) { - sounds.remove(qSound); - [sound release]; - [self release]; - return; - } - - // Check if the sound should loop "forever" (until stop). - if (qSound->loops() == -1) { - [sound play]; - return; - } - - const int remainingIterations = server->decLoop(qSound); - if (remainingIterations > 0) { - [sound play]; - } else { - sounds.remove(qSound); - [sound release]; - [self release]; - } -} -@end - -QT_BEGIN_NAMESPACE - -void QAuServerMac::play(const QString &fileName) -{ - QMacCocoaAutoReleasePool pool; - NSSound * const nsSound = createNSSound(fileName, 0); - [nsSound play]; -} - -void QAuServerMac::play(QSound *qSound) -{ - QMacCocoaAutoReleasePool pool; - NSSound * const nsSound = createNSSound(qSound->fileName(), qSound); - [nsSound play]; - // Keep track of the nsSound object so we can find it again in stop(). - sounds[qSound] = nsSound; -} - -void QAuServerMac::stop(QSound *qSound) -{ - Sounds::const_iterator it = sounds.constFind(qSound); - if (it != sounds.constEnd()) - [*it stop]; -} - -// Creates an NSSound object and installs a "sound finished" callack delegate on it. -NSSound *QAuServerMac::createNSSound(const QString &fileName, QSound *qSound) -{ - NSString *nsFileName = const_cast<NSString *>(reinterpret_cast<const NSString *>(QCFString::toCFStringRef(fileName))); - NSSound * const nsSound = [[NSSound alloc] initWithContentsOfFile: nsFileName byReference:YES]; - QT_MANGLE_NAMESPACE(QMacSoundDelegate) * const delegate = [[QT_MANGLE_NAMESPACE(QMacSoundDelegate) alloc] initWithQSound:qSound:this]; - [nsSound setDelegate:delegate]; - [nsFileName release]; - return nsSound; -} - -QAuServer* qt_new_audio_server() -{ - return new QAuServerMac(qApp); -} - -QT_END_NAMESPACE - -#include "qsound_mac.moc" - -#endif // QT_NO_SOUND diff --git a/src/gui/platforms/mac/qt_cocoa_helpers_mac.mm b/src/gui/platforms/mac/qt_cocoa_helpers_mac.mm deleted file mode 100644 index 32123ee682..0000000000 --- a/src/gui/platforms/mac/qt_cocoa_helpers_mac.mm +++ /dev/null @@ -1,1824 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -#include <private/qcore_mac_p.h> -#include <qaction.h> -#include <qwidget.h> -#include <qdesktopwidget.h> -#include <qevent.h> -#include <qpixmapcache.h> -#include <qvarlengtharray.h> -#include <private/qevent_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#include <private/qt_mac_p.h> -#include <private/qapplication_p.h> -#include <private/qcocoaapplication_mac_p.h> -#include <private/qcocoawindow_mac_p.h> -#include <private/qcocoaview_mac_p.h> -#include <private/qkeymapper_p.h> -#include <private/qwidget_p.h> -#include <private/qcocoawindow_mac_p.h> - -QT_BEGIN_NAMESPACE - -#ifdef QT_MAC_USE_COCOA -// Cmd + left mousebutton should produce a right button -// press (mainly for mac users with one-button mice): -static bool qt_leftButtonIsRightButton = false; -#endif - -Q_GLOBAL_STATIC(QMacWindowFader, macwindowFader); - -QMacWindowFader::QMacWindowFader() - : m_duration(0.250) -{ -} - -QMacWindowFader *QMacWindowFader::currentFader() -{ - return macwindowFader(); -} - -void QMacWindowFader::registerWindowToFade(QWidget *window) -{ - m_windowsToFade.append(window); -} - -void QMacWindowFader::performFade() -{ - const QWidgetList myWidgetsToFade = m_windowsToFade; - const int widgetCount = myWidgetsToFade.count(); -#if QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - [NSAnimationContext beginGrouping]; - [[NSAnimationContext currentContext] setDuration:NSTimeInterval(m_duration)]; -#endif - - for (int i = 0; i < widgetCount; ++i) { - QWidget *widget = m_windowsToFade.at(i); - OSWindowRef window = qt_mac_window_for(widget); -#if QT_MAC_USE_COCOA - [[window animator] setAlphaValue:0.0]; - QTimer::singleShot(qRound(m_duration * 1000), widget, SLOT(hide())); -#else - TransitionWindowOptions options = {0, m_duration, 0, 0}; - TransitionWindowWithOptions(window, kWindowFadeTransitionEffect, kWindowHideTransitionAction, - 0, 1, &options); -#endif - } -#if QT_MAC_USE_COCOA - [NSAnimationContext endGrouping]; -#endif - m_duration = 0.250; - m_windowsToFade.clear(); -} - -extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); // qapplication.cpp; -extern QWidget * mac_mouse_grabber; -extern QWidget *qt_button_down; //qapplication_mac.cpp -extern QPointer<QWidget> qt_last_mouse_receiver; -extern OSViewRef qt_mac_effectiveview_for(const QWidget *w); -extern void qt_mac_updateCursorWithWidgetUnderMouse(QWidget *widgetUnderMouse); // qcursor_mac.mm - -void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds) -{ -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; -#endif - OSWindowRef wnd = static_cast<OSWindowRef>(window); - if (wnd) { - QWidget *widget; -#if QT_MAC_USE_COCOA - widget = [wnd QT_MANGLE_NAMESPACE(qt_qwidget)]; -#else - const UInt32 kWidgetCreatorQt = kEventClassQt; - enum { - kWidgetPropertyQWidget = 'QWId' //QWidget * - }; - if (GetWindowProperty(static_cast<WindowRef>(window), kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(widget), 0, &widget) != noErr) - widget = 0; -#endif - if (widget) { - QMacWindowFader::currentFader()->setFadeDuration(durationSeconds); - QMacWindowFader::currentFader()->registerWindowToFade(widget); - QMacWindowFader::currentFader()->performFade(); - } - } -} -struct dndenum_mapper -{ - NSDragOperation mac_code; - Qt::DropAction qt_code; - bool Qt2Mac; -}; - -#if defined(QT_MAC_USE_COCOA) && defined(__OBJC__) - -static dndenum_mapper dnd_enums[] = { - { NSDragOperationLink, Qt::LinkAction, true }, - { NSDragOperationMove, Qt::MoveAction, true }, - { NSDragOperationCopy, Qt::CopyAction, true }, - { NSDragOperationGeneric, Qt::CopyAction, false }, - { NSDragOperationEvery, Qt::ActionMask, false }, - { NSDragOperationNone, Qt::IgnoreAction, false } -}; - -NSDragOperation qt_mac_mapDropAction(Qt::DropAction action) -{ - for (int i=0; dnd_enums[i].qt_code; i++) { - if (dnd_enums[i].Qt2Mac && (action & dnd_enums[i].qt_code)) { - return dnd_enums[i].mac_code; - } - } - return NSDragOperationNone; -} - -NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions) -{ - NSDragOperation nsActions = NSDragOperationNone; - for (int i=0; dnd_enums[i].qt_code; i++) { - if (dnd_enums[i].Qt2Mac && (actions & dnd_enums[i].qt_code)) - nsActions |= dnd_enums[i].mac_code; - } - return nsActions; -} - -Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions) -{ - Qt::DropAction action = Qt::IgnoreAction; - for (int i=0; dnd_enums[i].mac_code; i++) { - if (nsActions & dnd_enums[i].mac_code) - return dnd_enums[i].qt_code; - } - return action; -} - -Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions) -{ - Qt::DropActions actions = Qt::IgnoreAction; - for (int i=0; dnd_enums[i].mac_code; i++) { - if (nsActions & dnd_enums[i].mac_code) - actions |= dnd_enums[i].qt_code; - } - return actions; -} - -Q_GLOBAL_STATIC(DnDParams, currentDnDParameters); -DnDParams *macCurrentDnDParameters() -{ - return currentDnDParameters(); -} -#endif - -bool macWindowIsTextured( void * /*OSWindowRef*/ window ) -{ - OSWindowRef wnd = static_cast<OSWindowRef>(window); -#if QT_MAC_USE_COCOA - return ( [wnd styleMask] & NSTexturedBackgroundWindowMask ) ? true : false; -#else - WindowAttributes currentAttributes; - GetWindowAttributes(wnd, ¤tAttributes); - return (currentAttributes & kWindowMetalAttribute) ? true : false; -#endif -} - -void macWindowToolbarShow(const QWidget *widget, bool show ) -{ - OSWindowRef wnd = qt_mac_window_for(widget); -#if QT_MAC_USE_COCOA - if (NSToolbar *toolbar = [wnd toolbar]) { - QMacCocoaAutoReleasePool pool; - if (show != [toolbar isVisible]) { - [toolbar setVisible:show]; - } else { - // The toolbar may be in sync, but we are not, update our framestrut. - qt_widget_private(const_cast<QWidget *>(widget))->updateFrameStrut(); - } - } -#else - qt_widget_private(const_cast<QWidget *>(widget))->updateFrameStrut(); - ShowHideWindowToolbar(wnd, show, false); -#endif -} - - -void macWindowToolbarSet( void * /*OSWindowRef*/ window, void *toolbarRef ) -{ - OSWindowRef wnd = static_cast<OSWindowRef>(window); -#if QT_MAC_USE_COCOA - [wnd setToolbar:static_cast<NSToolbar *>(toolbarRef)]; -#else - SetWindowToolbar(wnd, static_cast<HIToolbarRef>(toolbarRef)); -#endif -} - -bool macWindowToolbarIsVisible( void * /*OSWindowRef*/ window ) -{ - OSWindowRef wnd = static_cast<OSWindowRef>(window); -#if QT_MAC_USE_COCOA - if (NSToolbar *toolbar = [wnd toolbar]) - return [toolbar isVisible]; - return false; -#else - return IsWindowToolbarVisible(wnd); -#endif -} - -void macWindowSetHasShadow( void * /*OSWindowRef*/ window, bool hasShadow ) -{ - OSWindowRef wnd = static_cast<OSWindowRef>(window); -#if QT_MAC_USE_COCOA - [wnd setHasShadow:BOOL(hasShadow)]; -#else - if (hasShadow) - ChangeWindowAttributes(wnd, 0, kWindowNoShadowAttribute); - else - ChangeWindowAttributes(wnd, kWindowNoShadowAttribute, 0); -#endif -} - -void macWindowFlush(void * /*OSWindowRef*/ window) -{ - OSWindowRef wnd = static_cast<OSWindowRef>(window); -#if QT_MAC_USE_COCOA - [wnd flushWindowIfNeeded]; -#else - HIWindowFlush(wnd); -#endif -} - -void * /*NSImage */qt_mac_create_nsimage(const QPixmap &pm) -{ - QMacCocoaAutoReleasePool pool; - if(QCFType<CGImageRef> image = pm.toMacCGImageRef()) { - NSImage *newImage = 0; - NSRect imageRect = NSMakeRect(0.0, 0.0, CGImageGetWidth(image), CGImageGetHeight(image)); - newImage = [[NSImage alloc] initWithSize:imageRect.size]; - [newImage lockFocus]; - { - CGContextRef imageContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - CGContextDrawImage(imageContext, *(CGRect*)&imageRect, image); - } - [newImage unlockFocus]; - return newImage; - } - return 0; -} - -void qt_mac_update_mouseTracking(QWidget *widget) -{ -#ifdef QT_MAC_USE_COCOA - [qt_mac_nativeview_for(widget) updateTrackingAreas]; -#else - Q_UNUSED(widget); -#endif -} - -OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage) -{ - // Verbatim copy if HIViewDrawCGImage (as shown on Carbon-Dev) - OSStatus err = noErr; - - require_action(inContext != NULL, InvalidContext, err = paramErr); - require_action(inBounds != NULL, InvalidBounds, err = paramErr); - require_action(inImage != NULL, InvalidImage, err = paramErr); - - CGContextSaveGState( inContext ); - CGContextTranslateCTM (inContext, 0, inBounds->origin.y + CGRectGetMaxY(*inBounds)); - CGContextScaleCTM(inContext, 1, -1); - - CGContextDrawImage(inContext, *inBounds, inImage); - - CGContextRestoreGState(inContext); -InvalidImage: -InvalidBounds: -InvalidContext: - return err; -} - -bool qt_mac_checkForNativeSizeGrip(const QWidget *widget) -{ -#ifndef QT_MAC_USE_COCOA - OSViewRef nativeSizeGrip = 0; - HIViewFindByID(HIViewGetRoot(HIViewGetWindow(HIViewRef(widget->winId()))), kHIViewWindowGrowBoxID, &nativeSizeGrip); - return (nativeSizeGrip != 0); -#else - return [[reinterpret_cast<NSView *>(widget->effectiveWinId()) window] showsResizeIndicator]; -#endif -} -struct qt_mac_enum_mapper -{ - int mac_code; - int qt_code; -#if defined(DEBUG_MOUSE_MAPS) -# define QT_MAC_MAP_ENUM(x) x, #x - const char *desc; -#else -# define QT_MAC_MAP_ENUM(x) x -#endif -}; - -//mouse buttons -static qt_mac_enum_mapper qt_mac_mouse_symbols[] = { -{ kEventMouseButtonPrimary, QT_MAC_MAP_ENUM(Qt::LeftButton) }, -{ kEventMouseButtonSecondary, QT_MAC_MAP_ENUM(Qt::RightButton) }, -{ kEventMouseButtonTertiary, QT_MAC_MAP_ENUM(Qt::MidButton) }, -{ 4, QT_MAC_MAP_ENUM(Qt::XButton1) }, -{ 5, QT_MAC_MAP_ENUM(Qt::XButton2) }, -{ 0, QT_MAC_MAP_ENUM(0) } -}; -Qt::MouseButtons qt_mac_get_buttons(int buttons) -{ -#ifdef DEBUG_MOUSE_MAPS - qDebug("Qt: internal: **Mapping buttons: %d (0x%04x)", buttons, buttons); -#endif - Qt::MouseButtons ret = Qt::NoButton; - for(int i = 0; qt_mac_mouse_symbols[i].qt_code; i++) { - if (buttons & (0x01<<(qt_mac_mouse_symbols[i].mac_code-1))) { -#ifdef DEBUG_MOUSE_MAPS - qDebug("Qt: internal: got button: %s", qt_mac_mouse_symbols[i].desc); -#endif - ret |= Qt::MouseButtons(qt_mac_mouse_symbols[i].qt_code); - } - } - return ret; -} -Qt::MouseButton qt_mac_get_button(EventMouseButton button) -{ -#ifdef DEBUG_MOUSE_MAPS - qDebug("Qt: internal: **Mapping button: %d (0x%04x)", button, button); -#endif - Qt::MouseButtons ret = 0; - for(int i = 0; qt_mac_mouse_symbols[i].qt_code; i++) { - if (button == qt_mac_mouse_symbols[i].mac_code) { -#ifdef DEBUG_MOUSE_MAPS - qDebug("Qt: internal: got button: %s", qt_mac_mouse_symbols[i].desc); -#endif - return Qt::MouseButton(qt_mac_mouse_symbols[i].qt_code); - } - } - return Qt::NoButton; -} - -void macSendToolbarChangeEvent(QWidget *widget) -{ - QToolBarChangeEvent ev(!(GetCurrentKeyModifiers() & cmdKey)); - qt_sendSpontaneousEvent(widget, &ev); -} - -Q_GLOBAL_STATIC(QMacTabletHash, tablet_hash) -QMacTabletHash *qt_mac_tablet_hash() -{ - return tablet_hash(); -} - -#ifdef QT_MAC_USE_COCOA - -// Clears the QWidget pointer that each QCocoaView holds. -void qt_mac_clearCocoaViewQWidgetPointers(QWidget *widget) -{ - QT_MANGLE_NAMESPACE(QCocoaView) *cocoaView = reinterpret_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(qt_mac_nativeview_for(widget)); - if (cocoaView && [cocoaView respondsToSelector:@selector(qt_qwidget)]) { - [cocoaView qt_clearQWidget]; - } -} - -void qt_dispatchTabletProximityEvent(void * /*NSEvent * */ tabletEvent) -{ - NSEvent *proximityEvent = static_cast<NSEvent *>(tabletEvent); - // simply construct a Carbon proximity record and handle it all in one spot. - TabletProximityRec carbonProximityRec = { [proximityEvent vendorID], - [proximityEvent tabletID], - [proximityEvent pointingDeviceID], - [proximityEvent deviceID], - [proximityEvent systemTabletID], - [proximityEvent vendorPointingDeviceType], - [proximityEvent pointingDeviceSerialNumber], - [proximityEvent uniqueID], - [proximityEvent capabilityMask], - [proximityEvent pointingDeviceType], - [proximityEvent isEnteringProximity] }; - qt_dispatchTabletProximityEvent(carbonProximityRec); -} -#endif // QT_MAC_USE_COCOA - -void qt_dispatchTabletProximityEvent(const ::TabletProximityRec &proxRec) -{ - QTabletDeviceData proximityDevice; - proximityDevice.tabletUniqueID = proxRec.uniqueID; - proximityDevice.capabilityMask = proxRec.capabilityMask; - - switch (proxRec.pointerType) { - case NSUnknownPointingDevice: - default: - proximityDevice.tabletPointerType = QTabletEvent::UnknownPointer; - break; - case NSPenPointingDevice: - proximityDevice.tabletPointerType = QTabletEvent::Pen; - break; - case NSCursorPointingDevice: - proximityDevice.tabletPointerType = QTabletEvent::Cursor; - break; - case NSEraserPointingDevice: - proximityDevice.tabletPointerType = QTabletEvent::Eraser; - break; - } - uint bits = proxRec.vendorPointerType; - if (bits == 0 && proximityDevice.tabletUniqueID != 0) { - // Fallback. It seems that the driver doesn't always include all the information. - // High-End Wacom devices store their "type" in the uper bits of the Unique ID. - // I'm not sure how to handle it for consumer devices, but I'll test that in a bit. - bits = proximityDevice.tabletUniqueID >> 32; - } - // Defined in the "EN0056-NxtGenImpGuideX" - // on Wacom's Developer Website (www.wacomeng.com) - if (((bits & 0x0006) == 0x0002) && ((bits & 0x0F06) != 0x0902)) { - proximityDevice.tabletDeviceType = QTabletEvent::Stylus; - } else { - switch (bits & 0x0F06) { - case 0x0802: - proximityDevice.tabletDeviceType = QTabletEvent::Stylus; - break; - case 0x0902: - proximityDevice.tabletDeviceType = QTabletEvent::Airbrush; - break; - case 0x0004: - proximityDevice.tabletDeviceType = QTabletEvent::FourDMouse; - break; - case 0x0006: - proximityDevice.tabletDeviceType = QTabletEvent::Puck; - break; - case 0x0804: - proximityDevice.tabletDeviceType = QTabletEvent::RotationStylus; - break; - default: - proximityDevice.tabletDeviceType = QTabletEvent::NoDevice; - } - } - // The deviceID is "unique" while in the proximity, it's a key that we can use for - // linking up TabletDeviceData to an event (especially if there are two devices in action). - bool entering = proxRec.enterProximity; - if (entering) { - qt_mac_tablet_hash()->insert(proxRec.deviceID, proximityDevice); - } else { - qt_mac_tablet_hash()->remove(proxRec.deviceID); - } - - QTabletEvent qtabletProximity(entering ? QEvent::TabletEnterProximity - : QEvent::TabletLeaveProximity, - QPoint(), QPoint(), QPointF(), proximityDevice.tabletDeviceType, - proximityDevice.tabletPointerType, 0., 0, 0, 0., 0., 0, 0, - proximityDevice.tabletUniqueID); - - qt_sendSpontaneousEvent(qApp, &qtabletProximity); -} - -// Use this method to keep all the information in the TextSegment. As long as it is ordered -// we are in OK shape, and we can influence that ourselves. -struct KeyPair -{ - QChar cocoaKey; - Qt::Key qtKey; -}; - -bool operator==(const KeyPair &entry, QChar qchar) -{ - return entry.cocoaKey == qchar; -} - -bool operator<(const KeyPair &entry, QChar qchar) -{ - return entry.cocoaKey < qchar; -} - -bool operator<(QChar qchar, const KeyPair &entry) -{ - return qchar < entry.cocoaKey; -} - -bool operator<(const Qt::Key &key, const KeyPair &entry) -{ - return key < entry.qtKey; -} - -bool operator<(const KeyPair &entry, const Qt::Key &key) -{ - return entry.qtKey < key; -} - -static bool qtKey2CocoaKeySortLessThan(const KeyPair &entry1, const KeyPair &entry2) -{ - return entry1.qtKey < entry2.qtKey; -} - -static const int NumEntries = 59; -static const KeyPair entries[NumEntries] = { - { NSEnterCharacter, Qt::Key_Enter }, - { NSBackspaceCharacter, Qt::Key_Backspace }, - { NSTabCharacter, Qt::Key_Tab }, - { NSNewlineCharacter, Qt::Key_Return }, - { NSCarriageReturnCharacter, Qt::Key_Return }, - { NSBackTabCharacter, Qt::Key_Backtab }, - { kEscapeCharCode, Qt::Key_Escape }, - // Cocoa sends us delete when pressing backspace! - // (NB when we reverse this list in qtKey2CocoaKey, there - // will be two indices of Qt::Key_Backspace. But is seems to work - // ok for menu shortcuts (which uses that function): - { NSDeleteCharacter, Qt::Key_Backspace }, - { NSUpArrowFunctionKey, Qt::Key_Up }, - { NSDownArrowFunctionKey, Qt::Key_Down }, - { NSLeftArrowFunctionKey, Qt::Key_Left }, - { NSRightArrowFunctionKey, Qt::Key_Right }, - { NSF1FunctionKey, Qt::Key_F1 }, - { NSF2FunctionKey, Qt::Key_F2 }, - { NSF3FunctionKey, Qt::Key_F3 }, - { NSF4FunctionKey, Qt::Key_F4 }, - { NSF5FunctionKey, Qt::Key_F5 }, - { NSF6FunctionKey, Qt::Key_F6 }, - { NSF7FunctionKey, Qt::Key_F7 }, - { NSF8FunctionKey, Qt::Key_F8 }, - { NSF9FunctionKey, Qt::Key_F8 }, - { NSF10FunctionKey, Qt::Key_F10 }, - { NSF11FunctionKey, Qt::Key_F11 }, - { NSF12FunctionKey, Qt::Key_F12 }, - { NSF13FunctionKey, Qt::Key_F13 }, - { NSF14FunctionKey, Qt::Key_F14 }, - { NSF15FunctionKey, Qt::Key_F15 }, - { NSF16FunctionKey, Qt::Key_F16 }, - { NSF17FunctionKey, Qt::Key_F17 }, - { NSF18FunctionKey, Qt::Key_F18 }, - { NSF19FunctionKey, Qt::Key_F19 }, - { NSF20FunctionKey, Qt::Key_F20 }, - { NSF21FunctionKey, Qt::Key_F21 }, - { NSF22FunctionKey, Qt::Key_F22 }, - { NSF23FunctionKey, Qt::Key_F23 }, - { NSF24FunctionKey, Qt::Key_F24 }, - { NSF25FunctionKey, Qt::Key_F25 }, - { NSF26FunctionKey, Qt::Key_F26 }, - { NSF27FunctionKey, Qt::Key_F27 }, - { NSF28FunctionKey, Qt::Key_F28 }, - { NSF29FunctionKey, Qt::Key_F29 }, - { NSF30FunctionKey, Qt::Key_F30 }, - { NSF31FunctionKey, Qt::Key_F31 }, - { NSF32FunctionKey, Qt::Key_F32 }, - { NSF33FunctionKey, Qt::Key_F33 }, - { NSF34FunctionKey, Qt::Key_F34 }, - { NSF35FunctionKey, Qt::Key_F35 }, - { NSInsertFunctionKey, Qt::Key_Insert }, - { NSDeleteFunctionKey, Qt::Key_Delete }, - { NSHomeFunctionKey, Qt::Key_Home }, - { NSEndFunctionKey, Qt::Key_End }, - { NSPageUpFunctionKey, Qt::Key_PageUp }, - { NSPageDownFunctionKey, Qt::Key_PageDown }, - { NSPrintScreenFunctionKey, Qt::Key_Print }, - { NSScrollLockFunctionKey, Qt::Key_ScrollLock }, - { NSPauseFunctionKey, Qt::Key_Pause }, - { NSSysReqFunctionKey, Qt::Key_SysReq }, - { NSMenuFunctionKey, Qt::Key_Menu }, - { NSHelpFunctionKey, Qt::Key_Help }, -}; -static const KeyPair * const end = entries + NumEntries; - -QChar qtKey2CocoaKey(Qt::Key key) -{ - // The first time this function is called, create a reverse - // looup table sorted on Qt Key rather than Cocoa key: - static QVector<KeyPair> rev_entries(NumEntries); - static bool mustInit = true; - if (mustInit){ - mustInit = false; - for (int i=0; i<NumEntries; ++i) - rev_entries[i] = entries[i]; - qSort(rev_entries.begin(), rev_entries.end(), qtKey2CocoaKeySortLessThan); - } - const QVector<KeyPair>::iterator i - = qBinaryFind(rev_entries.begin(), rev_entries.end(), key); - if (i == rev_entries.end()) - return QChar(); - return i->cocoaKey; -} - -#ifdef QT_MAC_USE_COCOA -static Qt::Key cocoaKey2QtKey(QChar keyCode) -{ - const KeyPair *i = qBinaryFind(entries, end, keyCode); - if (i == end) - return Qt::Key(keyCode.unicode()); - return i->qtKey; -} - -Qt::KeyboardModifiers qt_cocoaModifiers2QtModifiers(ulong modifierFlags) -{ - Qt::KeyboardModifiers qtMods =Qt::NoModifier; - if (modifierFlags & NSShiftKeyMask) - qtMods |= Qt::ShiftModifier; - if (modifierFlags & NSControlKeyMask) - qtMods |= Qt::MetaModifier; - if (modifierFlags & NSAlternateKeyMask) - qtMods |= Qt::AltModifier; - if (modifierFlags & NSCommandKeyMask) - qtMods |= Qt::ControlModifier; - if (modifierFlags & NSNumericPadKeyMask) - qtMods |= Qt::KeypadModifier; - return qtMods; -} - -NSString *qt_mac_removePrivateUnicode(NSString* string) -{ - int len = [string length]; - if (len) { - QVarLengthArray <unichar, 10> characters(len); - bool changed = false; - for (int i = 0; i<len; i++) { - characters[i] = [string characterAtIndex:i]; - // check if they belong to key codes in private unicode range - // currently we need to handle only the NSDeleteFunctionKey - if (characters[i] == NSDeleteFunctionKey) { - characters[i] = NSDeleteCharacter; - changed = true; - } - } - if (changed) - return [NSString stringWithCharacters:characters.data() length:len]; - } - return string; -} - -Qt::KeyboardModifiers qt_cocoaDragOperation2QtModifiers(uint dragOperations) -{ - Qt::KeyboardModifiers qtMods =Qt::NoModifier; - if (dragOperations & NSDragOperationLink) - qtMods |= Qt::MetaModifier; - if (dragOperations & NSDragOperationGeneric) - qtMods |= Qt::ControlModifier; - if (dragOperations & NSDragOperationCopy) - qtMods |= Qt::AltModifier; - return qtMods; -} - -static inline QEvent::Type cocoaEvent2QtEvent(NSUInteger eventType) -{ - // Handle the trivial cases that can be determined from the type. - switch (eventType) { - case NSKeyDown: - return QEvent::KeyPress; - case NSKeyUp: - return QEvent::KeyRelease; - case NSLeftMouseDown: - case NSRightMouseDown: - case NSOtherMouseDown: - return QEvent::MouseButtonPress; - case NSLeftMouseUp: - case NSRightMouseUp: - case NSOtherMouseUp: - return QEvent::MouseButtonRelease; - case NSMouseMoved: - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - return QEvent::MouseMove; - case NSScrollWheel: - return QEvent::Wheel; - } - return QEvent::None; -} - -static bool mustUseCocoaKeyEvent() -{ - QCFType<TISInputSourceRef> source = TISCopyCurrentKeyboardInputSource(); - return TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData) == 0; -} - -bool qt_dispatchKeyEventWithCocoa(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent) -{ - NSEvent *event = static_cast<NSEvent *>(keyEvent); - NSString *keyChars = [event charactersIgnoringModifiers]; - int keyLength = [keyChars length]; - if (keyLength == 0) - return false; // Dead Key, nothing to do! - bool ignoreText = false; - Qt::Key qtKey = Qt::Key_unknown; - if (keyLength == 1) { - QChar ch([keyChars characterAtIndex:0]); - if (ch.isLower()) - ch = ch.toUpper(); - qtKey = cocoaKey2QtKey(ch); - // Do not set the text for Function-Key Unicodes characters (0xF700–0xF8FF). - ignoreText = (ch.unicode() >= 0xF700 && ch.unicode() <= 0xF8FF); - } - Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([event modifierFlags]); - QString text; - - // To quote from the Carbon port: This is actually wrong--but it is the best that - // can be done for now because of the Control/Meta mapping issues - // (we always get text on the Mac) - if (!ignoreText && !(keyMods & (Qt::ControlModifier | Qt::MetaModifier))) - text = QCFString::toQString(reinterpret_cast<CFStringRef>(keyChars)); - - UInt32 macScanCode = 1; - QKeyEventEx ke(cocoaEvent2QtEvent([event type]), qtKey, keyMods, text, [event isARepeat], qMax(1, keyLength), - macScanCode, [event keyCode], [event modifierFlags]); - return qt_sendSpontaneousEvent(widgetToGetEvent, &ke) && ke.isAccepted(); -} -#endif - -Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum) -{ - if (buttonNum == 0) - return Qt::LeftButton; - if (buttonNum == 1) - return Qt::RightButton; - if (buttonNum == 2) - return Qt::MidButton; - if (buttonNum == 3) - return Qt::XButton1; - if (buttonNum == 4) - return Qt::XButton2; - return Qt::NoButton; -} - -bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent) -{ -#ifndef QT_MAC_USE_COCOA - Q_UNUSED(keyEvent); - Q_UNUSED(widgetToGetEvent); - return false; -#else - NSEvent *event = static_cast<NSEvent *>(keyEvent); - EventRef key_event = static_cast<EventRef>(const_cast<void *>([event eventRef])); - Q_ASSERT(key_event); - unsigned int info = 0; - - if ([event type] == NSKeyDown) { - NSString *characters = [event characters]; - if ([characters length]) { - unichar value = [characters characterAtIndex:0]; - qt_keymapper_private()->updateKeyMap(0, key_event, (void *)&value); - info = value; - } - } - - if (qt_mac_sendMacEventToWidget(widgetToGetEvent, key_event)) - return true; - - if (mustUseCocoaKeyEvent()) - return qt_dispatchKeyEventWithCocoa(keyEvent, widgetToGetEvent); - - bool consumed = qt_keymapper_private()->translateKeyEvent(widgetToGetEvent, 0, key_event, &info, true); - return consumed && (info != 0); -#endif -} - -void qt_dispatchModifiersChanged(void * /*NSEvent * */flagsChangedEvent, QWidget *widgetToGetEvent) -{ -#ifndef QT_MAC_USE_COCOA - Q_UNUSED(flagsChangedEvent); - Q_UNUSED(widgetToGetEvent); -#else - UInt32 modifiers = 0; - // Sync modifiers with Qt - NSEvent *event = static_cast<NSEvent *>(flagsChangedEvent); - EventRef key_event = static_cast<EventRef>(const_cast<void *>([event eventRef])); - Q_ASSERT(key_event); - GetEventParameter(key_event, kEventParamKeyModifiers, typeUInt32, 0, - sizeof(modifiers), 0, &modifiers); - extern void qt_mac_send_modifiers_changed(quint32 modifiers, QObject *object); - qt_mac_send_modifiers_changed(modifiers, widgetToGetEvent); -#endif -} - -QPointF flipPoint(const NSPoint &p) -{ - return QPointF(p.x, flipYCoordinate(p.y)); -} - -NSPoint flipPoint(const QPoint &p) -{ - return NSMakePoint(p.x(), flipYCoordinate(p.y())); -} - -NSPoint flipPoint(const QPointF &p) -{ - return NSMakePoint(p.x(), flipYCoordinate(p.y())); -} - -#if QT_MAC_USE_COCOA && __OBJC__ - -void qt_mac_handleNonClientAreaMouseEvent(NSWindow *window, NSEvent *event) -{ - QWidget *widgetToGetEvent = [window QT_MANGLE_NAMESPACE(qt_qwidget)]; - if (widgetToGetEvent == 0) - return; - - NSEventType evtType = [event type]; - QPoint qlocalPoint; - QPoint qglobalPoint; - bool processThisEvent = false; - bool fakeNCEvents = false; - bool fakeMouseEvents = false; - - // Check if this is a mouse event. - if (evtType == NSLeftMouseDown || evtType == NSLeftMouseUp - || evtType == NSRightMouseDown || evtType == NSRightMouseUp - || evtType == NSOtherMouseDown || evtType == NSOtherMouseUp - || evtType == NSMouseMoved || evtType == NSLeftMouseDragged - || evtType == NSRightMouseDragged || evtType == NSOtherMouseDragged) { - // Check if we want to pass this message to another window - if (mac_mouse_grabber && mac_mouse_grabber != widgetToGetEvent) { - NSWindow *grabWindow = static_cast<NSWindow *>(qt_mac_window_for(mac_mouse_grabber)); - if (window != grabWindow) { - window = grabWindow; - widgetToGetEvent = mac_mouse_grabber; - fakeNCEvents = true; - } - } - // Dont generate normal NC mouse events for Left Button dragged - if(evtType != NSLeftMouseDragged || fakeNCEvents) { - NSPoint windowPoint = [event locationInWindow]; - NSPoint globalPoint = [[event window] convertBaseToScreen:windowPoint]; - NSRect frameRect = [window frame]; - if (fakeNCEvents || NSMouseInRect(globalPoint, frameRect, NO)) { - NSRect contentRect = [window contentRectForFrameRect:frameRect]; - qglobalPoint = QPoint(flipPoint(globalPoint).toPoint()); - QWidget *w = widgetToGetEvent->childAt(widgetToGetEvent->mapFromGlobal(qglobalPoint)); - // check that the mouse pointer is on the non-client area and - // there are not widgets in it. - if (fakeNCEvents || (!NSMouseInRect(globalPoint, contentRect, NO) && !w)) { - qglobalPoint = QPoint(flipPoint(globalPoint).toPoint()); - qlocalPoint = widgetToGetEvent->mapFromGlobal(qglobalPoint); - processThisEvent = true; - } - } - } - } - // This is not an NC area mouse message. - if (!processThisEvent) - return; - - // If the window is frame less, generate fake mouse events instead. (floating QToolBar) - // or if someone already got an explicit or implicit grab - if (mac_mouse_grabber || qt_button_down || - (fakeNCEvents && (widgetToGetEvent->window()->windowFlags() & Qt::FramelessWindowHint))) - fakeMouseEvents = true; - - Qt::MouseButton button; - QEvent::Type eventType; - // Convert to Qt::Event type - switch (evtType) { - case NSLeftMouseDown: - button = Qt::LeftButton; - eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonPress - : QEvent::MouseButtonPress; - break; - case NSLeftMouseUp: - button = Qt::LeftButton; - eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonRelease - : QEvent::MouseButtonRelease; - break; - case NSRightMouseDown: - button = Qt::RightButton; - eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonPress - : QEvent::MouseButtonPress; - break; - case NSRightMouseUp: - button = Qt::RightButton; - eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonRelease - : QEvent::MouseButtonRelease; - break; - case NSOtherMouseDown: - button = cocoaButton2QtButton([event buttonNumber]); - eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonPress - : QEvent::MouseButtonPress; - break; - case NSOtherMouseUp: - button = cocoaButton2QtButton([event buttonNumber]); - eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonRelease - : QEvent::MouseButtonRelease; - break; - case NSMouseMoved: - button = Qt::NoButton; - eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseMove - : QEvent::MouseMove; - break; - case NSLeftMouseDragged: - button = Qt::LeftButton; - eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseMove - : QEvent::MouseMove; - break; - case NSRightMouseDragged: - button = Qt::RightButton; - eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseMove - : QEvent::MouseMove; - break; - case NSOtherMouseDragged: - button = cocoaButton2QtButton([event buttonNumber]); - eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseMove - : QEvent::MouseMove; - break; - default: - qWarning("not handled! Non client area mouse message"); - return; - } - - Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([event modifierFlags]); - if (eventType == QEvent::NonClientAreaMouseButtonPress || eventType == QEvent::MouseButtonPress) { - NSInteger clickCount = [event clickCount]; - if (clickCount % 2 == 0) - eventType = (!fakeMouseEvents) ? QEvent::NonClientAreaMouseButtonDblClick - : QEvent::MouseButtonDblClick; - if (button == Qt::LeftButton && (keyMods & Qt::MetaModifier)) { - button = Qt::RightButton; - qt_leftButtonIsRightButton = true; - } - } else if (eventType == QEvent::NonClientAreaMouseButtonRelease || eventType == QEvent::MouseButtonRelease) { - if (button == Qt::LeftButton && qt_leftButtonIsRightButton) { - button = Qt::RightButton; - qt_leftButtonIsRightButton = false; - } - } - - Qt::MouseButtons buttons = 0; - { - UInt32 mac_buttons; - if (GetEventParameter((EventRef)[event eventRef], kEventParamMouseChord, typeUInt32, 0, - sizeof(mac_buttons), 0, &mac_buttons) == noErr) - buttons = qt_mac_get_buttons(mac_buttons); - } - - QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, buttons, keyMods); - qt_sendSpontaneousEvent(widgetToGetEvent, &qme); - - // We don't need to set the implicit grab widget here because we won't - // reach this point if then event type is Press over a Qt widget. - // However we might need to unset it if the event is Release. - if (eventType == QEvent::MouseButtonRelease) - qt_button_down = 0; -} - -QWidget *qt_mac_getTargetForKeyEvent(QWidget *widgetThatReceivedEvent) -{ - if (QWidget *popup = QApplication::activePopupWidget()) { - QWidget *focusInPopup = popup->focusWidget(); - return focusInPopup ? focusInPopup : popup; - } - - QWidget *widgetToGetKey = qApp->focusWidget(); - if (!widgetToGetKey) - widgetToGetKey = widgetThatReceivedEvent; - - return widgetToGetKey; -} - -// This function will find the widget that should receive the -// mouse event. Because of explicit/implicit mouse grabs, popups, -// etc, this might not end up being the same as the widget under -// the mouse (which is more interresting when handling enter/leave -// events -QWidget *qt_mac_getTargetForMouseEvent( - // You can call this function without providing an event. - NSEvent *event, - QEvent::Type eventType, - QPoint &returnLocalPoint, - QPoint &returnGlobalPoint, - QWidget *nativeWidget, - QWidget **returnWidgetUnderMouse) -{ - Q_UNUSED(event); - NSPoint nsglobalpoint = event ? [[event window] convertBaseToScreen:[event locationInWindow]] : [NSEvent mouseLocation]; - returnGlobalPoint = flipPoint(nsglobalpoint).toPoint(); - QWidget *mouseGrabber = QWidget::mouseGrabber(); - bool buttonDownNotBlockedByModal = qt_button_down && !QApplicationPrivate::isBlockedByModal(qt_button_down); - QWidget *popup = QApplication::activePopupWidget(); - - // Resolve the widget under the mouse: - QWidget *widgetUnderMouse = 0; - if (popup || qt_button_down || !nativeWidget || !nativeWidget->isVisible()) { - // Using QApplication::widgetAt for finding the widget under the mouse - // is most safe, since it ignores cocoas own mouse down redirections (which - // we need to be prepared for when using nativeWidget as starting point). - // (the only exception is for QMacNativeWidget, where QApplication::widgetAt fails). - // But it is also slower (I guess), so we try to avoid it and use nativeWidget if we can: - widgetUnderMouse = QApplication::widgetAt(returnGlobalPoint); - } - - if (!widgetUnderMouse && nativeWidget) { - // Entering here should be the common case. We - // also handle the QMacNativeWidget fallback case. - QPoint p = nativeWidget->mapFromGlobal(returnGlobalPoint); - widgetUnderMouse = nativeWidget->childAt(p); - if (!widgetUnderMouse && nativeWidget->rect().contains(p)) - widgetUnderMouse = nativeWidget; - } - - if (widgetUnderMouse) { - // Check if widgetUnderMouse is blocked by a modal - // window, or the mouse if over the frame strut: - if (widgetUnderMouse == qt_button_down) { - // Small optimization to avoid an extra call to isBlockedByModal: - if (buttonDownNotBlockedByModal == false) - widgetUnderMouse = 0; - } else if (QApplicationPrivate::isBlockedByModal(widgetUnderMouse)) { - widgetUnderMouse = 0; - } - - if (widgetUnderMouse && widgetUnderMouse->isWindow()) { - // Exclude the titlebar (and frame strut) when finding widget under mouse: - QPoint p = widgetUnderMouse->mapFromGlobal(returnGlobalPoint); - if (!widgetUnderMouse->rect().contains(p)) - widgetUnderMouse = 0; - } - } - if (returnWidgetUnderMouse) - *returnWidgetUnderMouse = widgetUnderMouse; - - // Resolve the target for the mouse event. Default will be - // widgetUnderMouse, except if there is a grab (popup/mouse/button-down): - if (popup && !mouseGrabber) { - // We special case handling of popups, since they have an implicitt mouse grab. - QWidget *candidate = buttonDownNotBlockedByModal ? qt_button_down : widgetUnderMouse; - if (!popup->isAncestorOf(candidate)) { - // INVARIANT: we have a popup, but the candidate is not - // in it. But the popup will grab the mouse anyway, - // except if the user scrolls: - if (eventType == QEvent::Wheel) - return 0; - returnLocalPoint = popup->mapFromGlobal(returnGlobalPoint); - return popup; - } else if (popup == candidate) { - // INVARIANT: The candidate is the popup itself, and not a child: - returnLocalPoint = popup->mapFromGlobal(returnGlobalPoint); - return popup; - } else { - // INVARIANT: The candidate is a child inside the popup: - returnLocalPoint = candidate->mapFromGlobal(returnGlobalPoint); - return candidate; - } - } - - QWidget *target = mouseGrabber; - if (!target && buttonDownNotBlockedByModal) - target = qt_button_down; - if (!target) - target = widgetUnderMouse; - if (!target) - return 0; - - returnLocalPoint = target->mapFromGlobal(returnGlobalPoint); - return target; -} - -QPointer<QWidget> qt_last_native_mouse_receiver = 0; - -static inline void qt_mac_checkEnterLeaveForNativeWidgets(QWidget *maybeEnterWidget) -{ - // Dispatch enter/leave for the cases where QApplicationPrivate::sendMouseEvent do - // not. This will in general be the cases when alien widgets are not involved: - // 1. from a native widget to another native widget or - // 2. from a native widget to no widget - // 3. from no widget to a native or alien widget - - if (qt_button_down || QWidget::mouseGrabber()) - return; - - if ((maybeEnterWidget == qt_last_native_mouse_receiver) && qt_last_native_mouse_receiver) - return; - if (maybeEnterWidget) { - if (!qt_last_native_mouse_receiver) { - // case 3 - QApplicationPrivate::dispatchEnterLeave(maybeEnterWidget, 0); - qt_last_native_mouse_receiver = maybeEnterWidget->internalWinId() ? maybeEnterWidget : maybeEnterWidget->nativeParentWidget(); - } else if (maybeEnterWidget->internalWinId()) { - // case 1 - QApplicationPrivate::dispatchEnterLeave(maybeEnterWidget, qt_last_native_mouse_receiver); - qt_last_native_mouse_receiver = maybeEnterWidget->internalWinId() ? maybeEnterWidget : maybeEnterWidget->nativeParentWidget(); - } // else at lest one of the widgets are alien, so enter/leave will be handled in QApplicationPrivate - } else { - if (qt_last_native_mouse_receiver) { - // case 2 - QApplicationPrivate::dispatchEnterLeave(0, qt_last_native_mouse_receiver); - qt_last_mouse_receiver = 0; - qt_last_native_mouse_receiver = 0; - } - } -} - -bool qt_mac_handleMouseEvent(NSEvent *event, QEvent::Type eventType, Qt::MouseButton button, QWidget *nativeWidget) -{ - // Give the Input Manager a chance to process the mouse events. - NSInputManager *currentIManager = [NSInputManager currentInputManager]; - if (currentIManager && [currentIManager wantsToHandleMouseEvents]) { - [currentIManager handleMouseEvent:event]; - } - - // Find the widget that should receive the event, and the widget under the mouse. Those - // can differ if an implicit or explicit mouse grab is active: - QWidget *widgetUnderMouse = 0; - QPoint localPoint, globalPoint; - QWidget *widgetToGetMouse = qt_mac_getTargetForMouseEvent(event, eventType, localPoint, globalPoint, nativeWidget, &widgetUnderMouse); - if (!widgetToGetMouse) - return false; - - // From here on, we let nativeWidget actually be the native widget under widgetUnderMouse. The reason - // for this, is that qt_mac_getTargetForMouseEvent will set cocoa's mouse event redirection aside when - // determining which widget is under the mouse (in other words, it will usually ignore nativeWidget). - // nativeWidget will be used in QApplicationPrivate::sendMouseEvent to correctly dispatch enter/leave events. - if (widgetUnderMouse) - nativeWidget = widgetUnderMouse->internalWinId() ? widgetUnderMouse : widgetUnderMouse->nativeParentWidget(); - if (!nativeWidget) - return false; - NSView *view = qt_mac_effectiveview_for(nativeWidget); - - // Handle tablet events (if any) first. - if (qt_mac_handleTabletEvent(view, event)) { - // Tablet event was handled. In Qt we aren't supposed to send the mouse event. - return true; - } - - EventRef carbonEvent = static_cast<EventRef>(const_cast<void *>([event eventRef])); - if (qt_mac_sendMacEventToWidget(widgetToGetMouse, carbonEvent)) - return true; - - // Keep previousButton to make sure we don't send double click - // events when the user double clicks using two different buttons: - static Qt::MouseButton previousButton = Qt::NoButton; - - Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([event modifierFlags]); - NSInteger clickCount = [event clickCount]; - Qt::MouseButtons buttons = 0; - { - UInt32 mac_buttons; - if (GetEventParameter(carbonEvent, kEventParamMouseChord, typeUInt32, 0, - sizeof(mac_buttons), 0, &mac_buttons) == noErr) - buttons = qt_mac_get_buttons(mac_buttons); - } - - // Send enter/leave events for the cases when QApplicationPrivate::sendMouseEvent do not: - qt_mac_checkEnterLeaveForNativeWidgets(widgetUnderMouse); - - switch (eventType) { - default: - qWarning("not handled! %d", eventType); - break; - case QEvent::MouseMove: - if (button == Qt::LeftButton && qt_leftButtonIsRightButton) - button = Qt::RightButton; - break; - case QEvent::MouseButtonPress: - qt_button_down = widgetUnderMouse; - if (clickCount % 2 == 0 && (previousButton == Qt::NoButton || previousButton == button)) - eventType = QEvent::MouseButtonDblClick; - if (button == Qt::LeftButton && (keyMods & Qt::MetaModifier)) { - button = Qt::RightButton; - qt_leftButtonIsRightButton = true; - } - break; - case QEvent::MouseButtonRelease: - if (button == Qt::LeftButton && qt_leftButtonIsRightButton) { - button = Qt::RightButton; - qt_leftButtonIsRightButton = false; - } - qt_button_down = 0; - break; - } - - qt_mac_updateCursorWithWidgetUnderMouse(widgetUnderMouse); - - DnDParams *dndParams = currentDnDParameters(); - dndParams->view = view; - dndParams->theEvent = event; - dndParams->globalPoint = globalPoint; - - // Send the mouse event: - QMouseEvent qme(eventType, localPoint, globalPoint, button, buttons, keyMods); - QApplicationPrivate::sendMouseEvent( - widgetToGetMouse, &qme, widgetUnderMouse, nativeWidget, - &qt_button_down, qt_last_mouse_receiver, true); - - if (eventType == QEvent::MouseButtonPress && button == Qt::RightButton) { - QContextMenuEvent qcme(QContextMenuEvent::Mouse, localPoint, globalPoint, keyMods); - qt_sendSpontaneousEvent(widgetToGetMouse, &qcme); - } - - if (eventType == QEvent::MouseButtonRelease) { - // A mouse button was released, which means that the implicit grab was - // released. We therefore need to re-check if should send (delayed) enter leave events: - // qt_button_down has now become NULL since the call at the top of the function. Also, since - // the relase might have closed a window, we dont give the nativeWidget hint - qt_mac_getTargetForMouseEvent(0, QEvent::None, localPoint, globalPoint, nativeWidget, &widgetUnderMouse); - qt_mac_checkEnterLeaveForNativeWidgets(widgetUnderMouse); - } - - previousButton = button; - return true; -} -#endif - -bool qt_mac_handleTabletEvent(void * /*QCocoaView * */view, void * /*NSEvent * */tabletEvent) -{ -#ifndef QT_MAC_USE_COCOA - Q_UNUSED(view); - Q_UNUSED(tabletEvent); - return false; -#else - QT_MANGLE_NAMESPACE(QCocoaView) *theView = static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view); - NSView *theNSView = static_cast<NSView *>(view); - NSEvent *theTabletEvent = static_cast<NSEvent *>(tabletEvent); - - NSEventType eventType = [theTabletEvent type]; - if (eventType != NSTabletPoint && [theTabletEvent subtype] != NSTabletPointEventSubtype) - return false; // Not a tablet event. - - NSPoint windowPoint = [theTabletEvent locationInWindow]; - NSPoint globalPoint = [[theTabletEvent window] convertBaseToScreen:windowPoint]; - - QWidget *qwidget = [theView qt_qwidget]; - QWidget *widgetToGetMouse = qwidget; - QWidget *popup = qAppInstance()->activePopupWidget(); - if (popup && popup != qwidget->window()) - widgetToGetMouse = popup; - - if (qt_mac_sendMacEventToWidget(widgetToGetMouse, - static_cast<EventRef>(const_cast<void *>([theTabletEvent eventRef])))) - return true; - if (widgetToGetMouse != qwidget) { - theNSView = qt_mac_nativeview_for(widgetToGetMouse); - windowPoint = [[theNSView window] convertScreenToBase:globalPoint]; - } - NSPoint localPoint = [theNSView convertPoint:windowPoint fromView:nil]; - // Tablet events do not handle WA_TransparentForMouseEvents ATM - // In theory, people who set the WA_TransparentForMouseEvents attribute won't handle - // tablet events either in which case they will fall into the mouse event case and get - // them passed on. This will NOT handle the raw events, but that might not be a big problem. - - const QMacTabletHash *tabletHash = qt_mac_tablet_hash(); - if (!tabletHash->contains([theTabletEvent deviceID])) { - qWarning("QCocoaView handleTabletEvent: This tablet device is unknown" - " (received no proximity event for it). Discarding event."); - return false; - } - const QTabletDeviceData &deviceData = tabletHash->value([theTabletEvent deviceID]); - - - QEvent::Type qType; - switch (eventType) { - case NSLeftMouseDown: - case NSRightMouseDown: - qType = QEvent::TabletPress; - break; - case NSLeftMouseUp: - case NSRightMouseUp: - qType = QEvent::TabletRelease; - break; - case NSMouseMoved: - case NSTabletPoint: - case NSLeftMouseDragged: - case NSRightMouseDragged: - default: - qType = QEvent::TabletMove; - break; - } - - qreal pressure; - if (eventType != NSMouseMoved) { - pressure = [theTabletEvent pressure]; - } else { - pressure = 0.0; - } - - NSPoint tilt = [theTabletEvent tilt]; - int xTilt = qRound(tilt.x * 60.0); - int yTilt = qRound(tilt.y * -60.0); - qreal tangentialPressure = 0; - qreal rotation = 0; - int z = 0; - if (deviceData.capabilityMask & 0x0200) - z = [theTabletEvent absoluteZ]; - - if (deviceData.capabilityMask & 0x0800) - tangentialPressure = [theTabletEvent tangentialPressure]; - - rotation = [theTabletEvent rotation]; - QPointF hiRes = flipPoint(globalPoint); - QTabletEvent qtabletEvent(qType, QPoint(localPoint.x, localPoint.y), - hiRes.toPoint(), hiRes, - deviceData.tabletDeviceType, deviceData.tabletPointerType, - pressure, xTilt, yTilt, tangentialPressure, rotation, z, - qt_cocoaModifiers2QtModifiers([theTabletEvent modifierFlags]), - deviceData.tabletUniqueID); - - qt_sendSpontaneousEvent(widgetToGetMouse, &qtabletEvent); - return qtabletEvent.isAccepted(); -#endif -} - -void qt_mac_updateContentBorderMetricts(void * /*OSWindowRef */window, const ::HIContentBorderMetrics &metrics) -{ - OSWindowRef theWindow = static_cast<OSWindowRef>(window); -#if !defined(QT_MAC_USE_COCOA) -# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - ::HIWindowSetContentBorderThickness(theWindow, &metrics); - } -# else - Q_UNUSED(window); - Q_UNUSED(metrics); -# endif -#else - if ([theWindow styleMask] & NSTexturedBackgroundWindowMask) - [theWindow setContentBorderThickness:metrics.top forEdge:NSMaxYEdge]; - [theWindow setContentBorderThickness:metrics.bottom forEdge:NSMinYEdge]; -#endif -} - -#if QT_MAC_USE_COCOA -void qt_mac_replaceDrawRect(void * /*OSWindowRef */window, QWidgetPrivate *widget) -{ - QMacCocoaAutoReleasePool pool; - OSWindowRef theWindow = static_cast<OSWindowRef>(window); - if(!theWindow) - return; - id theClass = [[[theWindow contentView] superview] class]; - // What we do here is basically to add a new selector to NSThemeFrame called - // "drawRectOriginal:" which will contain the original implementation of - // "drawRect:". After that we get the new implementation from QCocoaWindow - // and exchange them. The new implementation is called drawRectSpecial. - // We cannot just add the method because it might have been added before and since - // we cannot remove a method once it has been added we need to ask QCocoaWindow if - // we did the swap or not. - if(!widget->drawRectOriginalAdded) { - Method m2 = class_getInstanceMethod(theClass, @selector(drawRect:)); - if(!m2) { - // This case is pretty extreme, no drawRect means no drawing! - return; - } - class_addMethod(theClass, @selector(drawRectOriginal:), method_getImplementation(m2), method_getTypeEncoding(m2)); - widget->drawRectOriginalAdded = true; - } - if(widget->originalDrawMethod) { - Method m0 = class_getInstanceMethod([theWindow class], @selector(drawRectSpecial:)); - if(!m0) { - // Ok, this means the methods were never swapped. Just ignore - return; - } - Method m1 = class_getInstanceMethod(theClass, @selector(drawRect:)); - if(!m1) { - // Ok, this means the methods were never swapped. Just ignore - return; - } - // We have the original method here. Proceed and swap the methods. - method_exchangeImplementations(m1, m0); - widget->originalDrawMethod = false; - [theWindow display]; - } -} - -void qt_mac_replaceDrawRectOriginal(void * /*OSWindowRef */window, QWidgetPrivate *widget) -{ - QMacCocoaAutoReleasePool pool; - OSWindowRef theWindow = static_cast<OSWindowRef>(window); - id theClass = [[[theWindow contentView] superview] class]; - // Now we need to revert the methods to their original state. - // We cannot remove the method, so we just keep track of it in QCocoaWindow. - Method m0 = class_getInstanceMethod([theWindow class], @selector(drawRectSpecial:)); - if(!m0) { - // Ok, this means the methods were never swapped. Just ignore - return; - } - Method m1 = class_getInstanceMethod(theClass, @selector(drawRect:)); - if(!m1) { - // Ok, this means the methods were never swapped. Just ignore - return; - } - method_exchangeImplementations(m1, m0); - widget->originalDrawMethod = true; - [theWindow display]; -} -#endif // QT_MAC_USE_COCOA - -#if QT_MAC_USE_COCOA -void qt_mac_showBaseLineSeparator(void * /*OSWindowRef */window, bool show) -{ - if(!window) - return; - QMacCocoaAutoReleasePool pool; - OSWindowRef theWindow = static_cast<OSWindowRef>(window); - NSToolbar *macToolbar = [theWindow toolbar]; - [macToolbar setShowsBaselineSeparator:show]; -} -#endif // QT_MAC_USE_COCOA - -QStringList qt_mac_NSArrayToQStringList(void *nsarray) -{ - QStringList result; - NSArray *array = static_cast<NSArray *>(nsarray); - for (NSUInteger i=0; i<[array count]; ++i) - result << qt_mac_NSStringToQString([array objectAtIndex:i]); - return result; -} - -void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list) -{ - NSMutableArray *result = [NSMutableArray arrayWithCapacity:list.size()]; - for (int i=0; i<list.size(); ++i){ - [result addObject:reinterpret_cast<const NSString *>(QCFString::toCFStringRef(list[i]))]; - } - return result; -} - -#if QT_MAC_USE_COCOA -void qt_syncCocoaTitleBarButtons(OSWindowRef window, QWidget *widgetForWindow) -{ - if (!widgetForWindow) - return; - - Qt::WindowFlags flags = widgetForWindow->windowFlags(); - bool customize = flags & Qt::CustomizeWindowHint; - - NSButton *btn = [window standardWindowButton:NSWindowZoomButton]; - // BOOL is not an int, so the bitwise AND doesn't work. - bool go = uint(customize && !(flags & Qt::WindowMaximizeButtonHint)) == 0; - [btn setEnabled:go]; - - btn = [window standardWindowButton:NSWindowMiniaturizeButton]; - go = uint(customize && !(flags & Qt::WindowMinimizeButtonHint)) == 0; - [btn setEnabled:go]; - - btn = [window standardWindowButton:NSWindowCloseButton]; - go = uint(customize && !(flags & Qt::WindowSystemMenuHint - || flags & Qt::WindowCloseButtonHint)) == 0; - [btn setEnabled:go]; - - [window setShowsToolbarButton:uint(flags & Qt::MacWindowToolBarButtonHint) != 0]; -} -#endif // QT_MAC_USE_COCOA - -// Carbon: Make sure you call QDEndContext on the context when done with it. -CGContextRef qt_mac_graphicsContextFor(QWidget *widget) -{ - if (!widget) - return 0; - -#ifndef QT_MAC_USE_COCOA - CGContextRef context; - CGrafPtr port = GetWindowPort(qt_mac_window_for(widget)); - QDBeginCGContext(port, &context); -#else - CGContextRef context = (CGContextRef)[[NSGraphicsContext graphicsContextWithWindow:qt_mac_window_for(widget)] graphicsPort]; -#endif - return context; -} - -void qt_mac_dispatchPendingUpdateRequests(QWidget *widget) -{ - if (!widget) - return; -#ifndef QT_MAC_USE_COCOA - HIViewRender(qt_mac_nativeview_for(widget)); -#else - [qt_mac_nativeview_for(widget) displayIfNeeded]; -#endif -} - -CGFloat qt_mac_get_scalefactor() -{ -#ifndef QT_MAC_USE_COCOA - return HIGetScaleFactor(); -#else - return [[NSScreen mainScreen] userSpaceScaleFactor]; -#endif -} - -QString qt_mac_get_pasteboardString(OSPasteboardRef paste) -{ - QMacCocoaAutoReleasePool pool; - NSPasteboard *pb = nil; - CFStringRef pbname; - if (PasteboardCopyName(paste, &pbname) == noErr) { - pb = [NSPasteboard pasteboardWithName:const_cast<NSString *>(reinterpret_cast<const NSString *>(pbname))]; - CFRelease(pbname); - } else { - pb = [NSPasteboard generalPasteboard]; - } - if (pb) { - NSString *text = [pb stringForType:NSStringPboardType]; - if (text) - return qt_mac_NSStringToQString(text); - } - return QString(); -} - -QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height) -{ - QPixmap ret(width, height); - ret.fill(QColor(0, 0, 0, 0)); - - CGRect rect = CGRectMake(0, 0, width, height); - - CGContextRef ctx = qt_mac_cg_context(&ret); - CGAffineTransform old_xform = CGContextGetCTM(ctx); - CGContextConcatCTM(ctx, CGAffineTransformInvert(old_xform)); - CGContextConcatCTM(ctx, CGAffineTransformIdentity); - - ::RGBColor b; - b.blue = b.green = b.red = 255*255; - PlotIconRefInContext(ctx, &rect, kAlignNone, kTransformNone, &b, kPlotIconRefNormalFlags, icon); - CGContextRelease(ctx); - return ret; -} - -void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayIcon, QIcon *retIcon, QStyle::StandardPixmap standardIcon) -{ - int size = 16; - while (size <= 128) { - - const QString cacheKey = QLatin1String("qt_mac_constructQIconFromIconRef") + QString::number(standardIcon) + QString::number(size); - QPixmap mainIcon; - if (standardIcon >= QStyle::SP_CustomBase) { - mainIcon = qt_mac_convert_iconref(icon, size, size); - } else if (QPixmapCache::find(cacheKey, mainIcon) == false) { - mainIcon = qt_mac_convert_iconref(icon, size, size); - QPixmapCache::insert(cacheKey, mainIcon); - } - - if (overlayIcon) { - int littleSize = size / 2; - QPixmap overlayPix = qt_mac_convert_iconref(overlayIcon, littleSize, littleSize); - QPainter painter(&mainIcon); - painter.drawPixmap(size - littleSize, size - littleSize, overlayPix); - } - - retIcon->addPixmap(mainIcon); - size += size; // 16 -> 32 -> 64 -> 128 - } -} - -#ifdef QT_MAC_USE_COCOA -void qt_mac_menu_collapseSeparators(void */*NSMenu **/ theMenu, bool collapse) -{ - QMacCocoaAutoReleasePool pool; - OSMenuRef menu = static_cast<OSMenuRef>(theMenu); - if (collapse) { - bool previousIsSeparator = true; // setting to true kills all the separators placed at the top. - NSMenuItem *previousItem = nil; - - NSArray *itemArray = [menu itemArray]; - for (unsigned int i = 0; i < [itemArray count]; ++i) { - NSMenuItem *item = reinterpret_cast<NSMenuItem *>([itemArray objectAtIndex:i]); - if ([item isSeparatorItem]) { - [item setHidden:previousIsSeparator]; - } - - if (![item isHidden]) { - previousItem = item; - previousIsSeparator = ([previousItem isSeparatorItem]); - } - } - - // We now need to check the final item since we don't want any separators at the end of the list. - if (previousItem && previousIsSeparator) - [previousItem setHidden:YES]; - } else { - NSArray *itemArray = [menu itemArray]; - for (unsigned int i = 0; i < [itemArray count]; ++i) { - NSMenuItem *item = reinterpret_cast<NSMenuItem *>([itemArray objectAtIndex:i]); - if (QAction *action = reinterpret_cast<QAction *>([item tag])) - [item setHidden:!action->isVisible()]; - } - } -} - -class CocoaPostMessageAfterEventLoopExitHelp : public QObject -{ - id target; - SEL selector; - int argCount; - id arg1; - id arg2; -public: - CocoaPostMessageAfterEventLoopExitHelp(id target, SEL selector, int argCount, id arg1, id arg2) - : target(target), selector(selector), argCount(argCount), arg1(arg1), arg2(arg2){ - deleteLater(); - } - - ~CocoaPostMessageAfterEventLoopExitHelp() - { - qt_cocoaPostMessage(target, selector, argCount, arg1, arg2); - } -}; - -void qt_cocoaPostMessage(id target, SEL selector, int argCount, id arg1, id arg2) -{ - // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5! - // That is why we need to split the address in two parts: - QCocoaPostMessageArgs *args = new QCocoaPostMessageArgs(target, selector, argCount, arg1, arg2); - quint32 lower = quintptr(args); - quint32 upper = quintptr(args) >> 32; - NSEvent *e = [NSEvent otherEventWithType:NSApplicationDefined - location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:0 - context:nil subtype:QtCocoaEventSubTypePostMessage data1:lower data2:upper]; - [NSApp postEvent:e atStart:NO]; -} - -void qt_cocoaPostMessageAfterEventLoopExit(id target, SEL selector, int argCount, id arg1, id arg2) -{ - if (QApplicationPrivate::instance()->threadData->eventLoops.size() <= 1) - qt_cocoaPostMessage(target, selector, argCount, arg1, arg2); - else - new CocoaPostMessageAfterEventLoopExitHelp(target, selector, argCount, arg1, arg2); -} - -#endif - -QMacCocoaAutoReleasePool::QMacCocoaAutoReleasePool() -{ -#ifndef QT_MAC_USE_COCOA - NSApplicationLoad(); -#endif - pool = (void*)[[NSAutoreleasePool alloc] init]; -} - -QMacCocoaAutoReleasePool::~QMacCocoaAutoReleasePool() -{ - [(NSAutoreleasePool*)pool release]; -} - -void qt_mac_post_retranslateAppMenu() -{ -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - qt_cocoaPostMessage([NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)], @selector(qtTranslateApplicationMenu)); -#endif -} - -QWidgetPrivate *QMacScrollOptimization::_target = 0; -bool QMacScrollOptimization::_inWheelEvent = false; -int QMacScrollOptimization::_dx = 0; -int QMacScrollOptimization::_dy = 0; -QRect QMacScrollOptimization::_scrollRect = QRect(0, 0, -1, -1); - -#ifdef QT_MAC_USE_COCOA -// This method implements the magic for the drawRectSpecial method. -// We draw a line at the upper edge of the content view in order to -// override the title baseline. -void macDrawRectOnTop(void * /*OSWindowRef */window) -{ - OSWindowRef theWindow = static_cast<OSWindowRef>(window); - NSView *contentView = [theWindow contentView]; - if(!contentView) - return; - // Get coordinates of the content view - NSRect contentRect = [contentView frame]; - // Draw a line on top of the already drawn line. - // We need to check if we are active or not to use the proper color. - if([theWindow isKeyWindow] || [theWindow isMainWindow]) { - [[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set]; - } else { - [[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set]; - } - NSPoint origin = NSMakePoint(0, contentRect.size.height); - NSPoint end = NSMakePoint(contentRect.size.width, contentRect.size.height); - [NSBezierPath strokeLineFromPoint:origin toPoint:end]; -} - -// This method will (or at least should) get called only once. -// Its mission is to find out if we are active or not. If we are active -// we assume that we were launched via finder, otherwise we assume -// we were called from the command line. The distinction is important, -// since in the first case we don't need to trigger a paintEvent, while -// in the second case we do. -void macSyncDrawingOnFirstInvocation(void * /*OSWindowRef */window) -{ - OSWindowRef theWindow = static_cast<OSWindowRef>(window); - NSApplication *application = [NSApplication sharedApplication]; - NSToolbar *toolbar = [theWindow toolbar]; - if([application isActive]) { - // Launched from finder - [toolbar setShowsBaselineSeparator:NO]; - } else { - // Launched from commandline - [toolbar setVisible:false]; - [toolbar setShowsBaselineSeparator:NO]; - [toolbar setVisible:true]; - [theWindow display]; - } -} - -void qt_cocoaStackChildWindowOnTopOfOtherChildren(QWidget *childWidget) -{ - if (!childWidget) - return; - - QWidget *parent = childWidget->parentWidget(); - if (childWidget->isWindow() && parent) { - if ([[qt_mac_window_for(parent) childWindows] containsObject:qt_mac_window_for(childWidget)]) { - QWidgetPrivate *d = qt_widget_private(childWidget); - d->setSubWindowStacking(false); - d->setSubWindowStacking(true); - } - } -} - -void qt_mac_display(QWidget *widget) -{ - NSView *theNSView = qt_mac_nativeview_for(widget); - [theNSView display]; -} - -void qt_mac_setNeedsDisplay(QWidget *widget) -{ - NSView *theNSView = qt_mac_nativeview_for(widget); - [theNSView setNeedsDisplay:YES]; -} - -void qt_mac_setNeedsDisplayInRect(QWidget *widget, QRegion region) -{ - NSView *theNSView = qt_mac_nativeview_for(widget); - if (region.isEmpty()) { - [theNSView setNeedsDisplay:YES]; - return; - } - - QVector<QRect> rects = region.rects(); - for (int i = 0; i < rects.count(); ++i) { - const QRect &rect = rects.at(i); - NSRect nsrect = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); - [theNSView setNeedsDisplayInRect:nsrect]; - } - -} - -#endif // QT_MAC_USE_COCOA - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qt_cocoa_helpers_mac_p.h b/src/gui/platforms/mac/qt_cocoa_helpers_mac_p.h deleted file mode 100644 index a49753ae2f..0000000000 --- a/src/gui/platforms/mac/qt_cocoa_helpers_mac_p.h +++ /dev/null @@ -1,340 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -#ifndef QT_COCOA_HELPERS_MAC_P_H -#define QT_COCOA_HELPERS_MAC_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp -// and many other. This header file may change from version to version -// without notice, or even be removed. -// -// We mean it. -// - -#include <private/qt_mac_p.h> - -#include <qapplication.h> -#include <qdesktopwidget.h> -#include <qwidget.h> -#include <qevent.h> -#include <qhash.h> -#include <qlabel.h> -#include <qpointer.h> -#include <qstyle.h> -#include <qstyleoption.h> -#include <qstylepainter.h> -#include <qtimer.h> -#include <qtooltip.h> -#include <private/qeffects_p.h> -#include <private/qwidget_p.h> -#include <qtextdocument.h> -#include <qdebug.h> -#include <qpoint.h> -#include "private/qt_mac_p.h" - -struct HIContentBorderMetrics; - -#ifdef Q_WS_MAC32 -typedef struct _NSPoint NSPoint; // Just redefine here so I don't have to pull in all of Cocoa. -#else -typedef struct CGPoint NSPoint; -#endif - -QT_BEGIN_NAMESPACE - -enum { - QtCocoaEventSubTypeWakeup = SHRT_MAX, - QtCocoaEventSubTypePostMessage = SHRT_MAX-1 -}; - -Qt::MouseButtons qt_mac_get_buttons(int buttons); -Qt::MouseButton qt_mac_get_button(EventMouseButton button); -void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds = 0.15); -bool macWindowIsTextured(void * /*OSWindowRef*/ window); -void macWindowToolbarShow(const QWidget *widget, bool show ); -void macWindowToolbarSet( void * /*OSWindowRef*/ window, void* toolbarRef ); -bool macWindowToolbarIsVisible( void * /*OSWindowRef*/ window ); -void macWindowSetHasShadow( void * /*OSWindowRef*/ window, bool hasShadow ); -void macWindowFlush(void * /*OSWindowRef*/ window); -void macSendToolbarChangeEvent(QWidget *widget); -void qt_mac_updateContentBorderMetricts(void * /*OSWindowRef */window, const ::HIContentBorderMetrics &metrics); -void qt_mac_replaceDrawRect(void * /*OSWindowRef */window, QWidgetPrivate *widget); -void qt_mac_replaceDrawRectOriginal(void * /*OSWindowRef */window, QWidgetPrivate *widget); -void qt_mac_showBaseLineSeparator(void * /*OSWindowRef */window, bool show); -void * /*NSImage */qt_mac_create_nsimage(const QPixmap &pm); -void qt_mac_update_mouseTracking(QWidget *widget); -OSStatus qt_mac_drawCGImage(CGContextRef cg, const CGRect *inbounds, CGImageRef); -bool qt_mac_checkForNativeSizeGrip(const QWidget *widget); -void qt_dispatchTabletProximityEvent(void * /*NSEvent * */ tabletEvent); -#ifdef QT_MAC_USE_COCOA -bool qt_dispatchKeyEventWithCocoa(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent); -// These methods exists only for supporting unified mode. -void macDrawRectOnTop(void * /*OSWindowRef */ window); -void macSyncDrawingOnFirstInvocation(void * /*OSWindowRef */window); -void qt_cocoaStackChildWindowOnTopOfOtherChildren(QWidget *widget); -void qt_mac_menu_collapseSeparators(void * /*NSMenu */ menu, bool collapse); -#endif -bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent); -void qt_dispatchModifiersChanged(void * /*NSEvent * */flagsChangedEvent, QWidget *widgetToGetEvent); -bool qt_mac_handleTabletEvent(void * /*QCocoaView * */view, void * /*NSEvent * */event); -inline QApplication *qAppInstance() { return static_cast<QApplication *>(QCoreApplication::instance()); } -struct ::TabletProximityRec; -void qt_dispatchTabletProximityEvent(const ::TabletProximityRec &proxRec); -Qt::KeyboardModifiers qt_cocoaModifiers2QtModifiers(ulong modifierFlags); -Qt::KeyboardModifiers qt_cocoaDragOperation2QtModifiers(uint dragOperations); -QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height); -void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayIcon, QIcon *retIcon, - QStyle::StandardPixmap standardIcon = QStyle::SP_CustomBase); - -#if QT_MAC_USE_COCOA && __OBJC__ -struct DnDParams -{ - NSView *view; - NSEvent *theEvent; - QPoint globalPoint; - NSDragOperation performedAction; -}; - -DnDParams *macCurrentDnDParameters(); -NSDragOperation qt_mac_mapDropAction(Qt::DropAction action); -NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions); -Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions); -Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions); - -QWidget *qt_mac_getTargetForKeyEvent(QWidget *widgetThatReceivedEvent); -QWidget *qt_mac_getTargetForMouseEvent(NSEvent *event, QEvent::Type eventType, - QPoint &returnLocalPoint, QPoint &returnGlobalPoint, QWidget *nativeWidget, QWidget **returnWidgetUnderMouse); -bool qt_mac_handleMouseEvent(NSEvent *event, QEvent::Type eventType, Qt::MouseButton button, QWidget *nativeWidget); -void qt_mac_handleNonClientAreaMouseEvent(NSWindow *window, NSEvent *event); -#endif - -inline int flipYCoordinate(int y) -{ - return QApplication::desktop()->screenGeometry(0).height() - y; -} - -inline qreal flipYCoordinate(qreal y) -{ - return QApplication::desktop()->screenGeometry(0).height() - y; -} - -QPointF flipPoint(const NSPoint &p); -NSPoint flipPoint(const QPoint &p); -NSPoint flipPoint(const QPointF &p); - -QStringList qt_mac_NSArrayToQStringList(void *nsarray); -void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list); - -void qt_syncCocoaTitleBarButtons(OSWindowRef window, QWidget *widgetForWindow); - -CGFloat qt_mac_get_scalefactor(); -QString qt_mac_get_pasteboardString(OSPasteboardRef paste); - -#ifdef __OBJC__ -inline NSMutableArray *qt_mac_QStringListToNSMutableArray(const QStringList &qstrlist) -{ return reinterpret_cast<NSMutableArray *>(qt_mac_QStringListToNSMutableArrayVoid(qstrlist)); } - -inline QString qt_mac_NSStringToQString(const NSString *nsstr) -{ return QCFString::toQString(reinterpret_cast<const CFStringRef>(nsstr)); } - -inline NSString *qt_mac_QStringToNSString(const QString &qstr) -{ return [reinterpret_cast<const NSString *>(QCFString::toCFStringRef(qstr)) autorelease]; } - -#ifdef QT_MAC_USE_COCOA -class QCocoaPostMessageArgs { -public: - id target; - SEL selector; - int argCount; - id arg1; - id arg2; - QCocoaPostMessageArgs(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0) - : target(target), selector(selector), argCount(argCount), arg1(arg1), arg2(arg2) - { - [target retain]; - [arg1 retain]; - [arg2 retain]; - } - - ~QCocoaPostMessageArgs() - { - [arg2 release]; - [arg1 release]; - [target release]; - } -}; -void qt_cocoaPostMessage(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0); -void qt_cocoaPostMessageAfterEventLoopExit(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0); -#endif - -#endif - -class QMacScrollOptimization { - // This class is made to optimize for the case when the user - // scrolls both horizontally and vertically at the same - // time. This will result in two QWheelEvents (one for each - // direction), which will typically result in two calls to - // QWidget::_scroll_sys. Rather than copying pixels twize on - // screen because of this, we add this helper class to try to - // get away with only one blit. - static QWidgetPrivate *_target; - static bool _inWheelEvent; - static int _dx; - static int _dy; - static QRect _scrollRect; - -public: - static void initDelayedScroll() - { - _inWheelEvent = true; - } - - static bool delayScroll(QWidgetPrivate *target, int dx, int dy, const QRect &scrollRect) - { - if (!_inWheelEvent) - return false; - if (_target && _target != target) - return false; - if (_scrollRect.width() != -1 && _scrollRect != scrollRect) - return false; - - _target = target; - _dx += dx; - _dy += dy; - _scrollRect = scrollRect; - return true; - } - - static void performDelayedScroll() - { - if (!_inWheelEvent) - return; - _inWheelEvent = false; - if (!_target) - return; - - _target->scroll_sys(_dx, _dy, _scrollRect); - - _target = 0; - _dx = 0; - _dy = 0; - _scrollRect = QRect(0, 0, -1, -1); - } -}; - -void qt_mac_post_retranslateAppMenu(); - -#ifdef QT_MAC_USE_COCOA -void qt_mac_display(QWidget *widget); -void qt_mac_setNeedsDisplay(QWidget *widget); -void qt_mac_setNeedsDisplayInRect(QWidget *widget, QRegion region); -#endif // QT_MAC_USE_COCOA - - -// Utility functions to ease the use of Core Graphics contexts. - -inline void qt_mac_retain_graphics_context(CGContextRef context) -{ - CGContextRetain(context); - CGContextSaveGState(context); -} - -inline void qt_mac_release_graphics_context(CGContextRef context) -{ - CGContextRestoreGState(context); - CGContextRelease(context); -} - -inline void qt_mac_draw_image(CGContextRef context, CGContextRef imageContext, CGRect area, CGRect drawingArea) -{ - CGImageRef image = CGBitmapContextCreateImage(imageContext); - CGImageRef subImage = CGImageCreateWithImageInRect(image, area); - - CGContextTranslateCTM (context, 0, drawingArea.origin.y + CGRectGetMaxY(drawingArea)); - CGContextScaleCTM(context, 1, -1); - CGContextDrawImage(context, drawingArea, subImage); - - CGImageRelease(subImage); - CGImageRelease(image); -} - -QT_END_NAMESPACE - -#endif // QT_COCOA_HELPERS_MAC_P_H diff --git a/src/gui/platforms/mac/qt_mac.cpp b/src/gui/platforms/mac/qt_mac.cpp deleted file mode 100644 index 046bcf6a54..0000000000 --- a/src/gui/platforms/mac/qt_mac.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qt_mac_p.h> -#include <private/qpixmap_mac_p.h> -#include <private/qnativeimage_p.h> -#include <qdebug.h> - -QT_BEGIN_NAMESPACE -#ifdef QT_MAC_USE_COCOA -static CTFontRef CopyCTThemeFont(ThemeFontID themeID) -{ - CTFontUIFontType ctID = HIThemeGetUIFontType(themeID); - return CTFontCreateUIFontForLanguage(ctID, 0, 0); -} -#endif - -QFont qfontForThemeFont(ThemeFontID themeID) -{ -#ifndef QT_MAC_USE_COCOA - static const ScriptCode Script = smRoman; - Str255 f_name; - SInt16 f_size; - Style f_style; - GetThemeFont(themeID, Script, f_name, &f_size, &f_style); - extern QString qt_mac_from_pascal_string(const Str255); //qglobal.cpp - return QFont(qt_mac_from_pascal_string(f_name), f_size, - (f_style & ::bold) ? QFont::Bold : QFont::Normal, - (bool)(f_style & ::italic)); -#else - QCFType<CTFontRef> ctfont = CopyCTThemeFont(themeID); - QString familyName = QCFString(CTFontCopyFamilyName(ctfont)); - QCFType<CFDictionaryRef> dict = CTFontCopyTraits(ctfont); - CFNumberRef num = static_cast<CFNumberRef>(CFDictionaryGetValue(dict, kCTFontWeightTrait)); - float fW; - CFNumberGetValue(num, kCFNumberFloat32Type, &fW); - QFont::Weight wght = fW > 0. ? QFont::Bold : QFont::Normal; - num = static_cast<CFNumberRef>(CFDictionaryGetValue(dict, kCTFontSlantTrait)); - CFNumberGetValue(num, kCFNumberFloatType, &fW); - bool italic = (fW != 0.0); - return QFont(familyName, CTFontGetSize(ctfont), wght, italic); -#endif -} - -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) -static QColor qcolorFromCGColor(CGColorRef cgcolor) -{ - QColor pc; - CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(cgcolor)); - const CGFloat *components = CGColorGetComponents(cgcolor); - if (model == kCGColorSpaceModelRGB) { - pc.setRgbF(components[0], components[1], components[2], components[3]); - } else if (model == kCGColorSpaceModelCMYK) { - pc.setCmykF(components[0], components[1], components[2], components[3]); - } else if (model == kCGColorSpaceModelMonochrome) { - pc.setRgbF(components[0], components[0], components[0], components[1]); - } else { - // Colorspace we can't deal with. - qWarning("Qt: qcolorFromCGColor: cannot convert from colorspace model: %d", model); - Q_ASSERT(false); - } - return pc; -} - -static inline QColor leopardBrush(ThemeBrush brush) -{ - QCFType<CGColorRef> cgClr = 0; - HIThemeBrushCreateCGColor(brush, &cgClr); - return qcolorFromCGColor(cgClr); -} -#endif - -QColor qcolorForTheme(ThemeBrush brush) -{ -#ifndef QT_MAC_USE_COCOA -# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - return leopardBrush(brush); - } else -# endif - { - RGBColor rgbcolor; - GetThemeBrushAsColor(brush, 32, true, &rgbcolor); - return QColor(rgbcolor.red / 256, rgbcolor.green / 256, rgbcolor.blue / 256); - } -#else - return leopardBrush(brush); -#endif -} - -QColor qcolorForThemeTextColor(ThemeTextColor themeColor) -{ -#ifdef Q_OS_MAC32 - RGBColor c; - GetThemeTextColor(themeColor, 32, true, &c); - QColor color = QColor(c.red / 256, c.green / 256, c.blue / 256); - return color; -#else - // There is no equivalent to GetThemeTextColor in 64-bit and it was rather bad that - // I didn't file a request to implement this for Snow Leopard. So, in the meantime - // I've encoded the values from the GetThemeTextColor. This is not exactly ideal - // as if someone really wants to mess with themeing, these colors will be wrong. - // It also means that we need to make sure the values for differences between - // OS releases (and it will be likely that we are a step behind.) - switch (themeColor) { - case kThemeTextColorAlertActive: - case kThemeTextColorTabFrontActive: - case kThemeTextColorBevelButtonActive: - case kThemeTextColorListView: - case kThemeTextColorPlacardActive: - case kThemeTextColorPopupButtonActive: - case kThemeTextColorPopupLabelActive: - case kThemeTextColorPushButtonActive: - return Qt::black; - case kThemeTextColorAlertInactive: - case kThemeTextColorDialogInactive: - case kThemeTextColorPlacardInactive: - return QColor(69, 69, 69, 255); - case kThemeTextColorPopupButtonInactive: - case kThemeTextColorPopupLabelInactive: - case kThemeTextColorPushButtonInactive: - case kThemeTextColorTabFrontInactive: - case kThemeTextColorBevelButtonInactive: - return QColor(127, 127, 127, 255); - default: { - QNativeImage nativeImage(16,16, QNativeImage::systemFormat()); - CGRect cgrect = CGRectMake(0, 0, 16, 16); - HIThemeSetTextFill(themeColor, 0, nativeImage.cg, kHIThemeOrientationNormal); - CGContextFillRect(nativeImage.cg, cgrect); - QColor color = nativeImage.image.pixel(0,0); - return QColor(nativeImage.image.pixel(0 , 0)); - } - } -#endif -} -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qt_mac_p.h b/src/gui/platforms/mac/qt_mac_p.h deleted file mode 100644 index b2bb804ff0..0000000000 --- a/src/gui/platforms/mac/qt_mac_p.h +++ /dev/null @@ -1,286 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT_MAC_P_H -#define QT_MAC_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qmacdefines_mac.h" - -#ifdef __OBJC__ -#include <Cocoa/Cocoa.h> -#ifdef QT_MAC_USE_COCOA -#include <objc/runtime.h> -#endif // QT_MAC_USE_COCOA -#endif - -#include <CoreServices/CoreServices.h> - -#include "QtCore/qglobal.h" -#include "QtCore/qvariant.h" -#include "QtCore/qmimedata.h" -#include "QtCore/qpointer.h" -#include "private/qcore_mac_p.h" - - -#include "QtGui/qpainter.h" - -#include <Carbon/Carbon.h> - -QT_BEGIN_NAMESPACE -class QWidget; -class QDragMoveEvent; - -/* Event masks */ -// internal Qt types - - // Event class for our own Carbon events. -#if defined(QT_NAMESPACE) && defined(QT_NAMESPACE_MAC_CRC) -// Take the CRC we generated at configure time. This *may* result in a -// collision with another value If that is the case, please change the value -// here to something other than 'Cute'. -const UInt32 kEventClassQt = QT_NAMESPACE_MAC_CRC; -#else -const UInt32 kEventClassQt = 'Cute'; -#endif - -enum { - //AE types - typeAEClipboardChanged = 1, - //types - typeQWidget = 1, /* QWidget * */ - //params - kEventParamQWidget = 'qwid', /* typeQWidget */ - //events - kEventQtRequestContext = 13, - kEventQtRequestMenubarUpdate = 14, - kEventQtRequestShowSheet = 17, - kEventQtRequestActivate = 18, - kEventQtRequestWindowChange = 20 -}; - -// Simple class to manage short-lived regions -class QMacSmartQuickDrawRegion -{ - RgnHandle qdRgn; - Q_DISABLE_COPY(QMacSmartQuickDrawRegion) -public: - explicit QMacSmartQuickDrawRegion(RgnHandle rgn) : qdRgn(rgn) {} - ~QMacSmartQuickDrawRegion() { - extern void qt_mac_dispose_rgn(RgnHandle); // qregion_mac.cpp - qt_mac_dispose_rgn(qdRgn); - } - operator RgnHandle() { - return qdRgn; - } -}; - -// Class for chaining to gether a bunch of fades. It pretty much is only used for qmenu fading. -class QMacWindowFader -{ - QWidgetList m_windowsToFade; - float m_duration; - Q_DISABLE_COPY(QMacWindowFader) -public: - QMacWindowFader(); // PLEASE DON'T CALL THIS. - static QMacWindowFader *currentFader(); - void registerWindowToFade(QWidget *window); - void setFadeDuration(float durationInSecs) { m_duration = durationInSecs; } - float fadeDuration() const { return m_duration; } - void performFade(); -}; - -class Q_GUI_EXPORT QMacCocoaAutoReleasePool -{ -private: - void *pool; -public: - QMacCocoaAutoReleasePool(); - ~QMacCocoaAutoReleasePool(); - - inline void *handle() const { return pool; } -}; - -QString qt_mac_removeMnemonics(const QString &original); //implemented in qmacstyle_mac.cpp - -class Q_GUI_EXPORT QMacWindowChangeEvent -{ -private: - static QList<QMacWindowChangeEvent*> *change_events; -public: - QMacWindowChangeEvent() { - } - virtual ~QMacWindowChangeEvent() { - } - static inline void exec(bool ) { - } -protected: - virtual void windowChanged() = 0; - virtual void flushWindowChanged() = 0; -}; - -class QMacCGContext -{ - CGContextRef context; -public: - QMacCGContext(QPainter *p); //qpaintengine_mac.cpp - inline QMacCGContext() { context = 0; } - inline QMacCGContext(const QPaintDevice *pdev) { - extern CGContextRef qt_mac_cg_context(const QPaintDevice *); - context = qt_mac_cg_context(pdev); - } - inline QMacCGContext(CGContextRef cg, bool takeOwnership=false) { - context = cg; - if(!takeOwnership) - CGContextRetain(context); - } - inline QMacCGContext(const QMacCGContext ©) : context(0) { *this = copy; } - inline ~QMacCGContext() { - if(context) - CGContextRelease(context); - } - inline bool isNull() const { return context; } - inline operator CGContextRef() { return context; } - inline QMacCGContext &operator=(const QMacCGContext ©) { - if(context) - CGContextRelease(context); - context = copy.context; - CGContextRetain(context); - return *this; - } - inline QMacCGContext &operator=(CGContextRef cg) { - if(context) - CGContextRelease(context); - context = cg; - CGContextRetain(context); //we do not take ownership - return *this; - } -}; - -class QMacPasteboardMime; -class QMimeData; - -class QMacPasteboard -{ - struct Promise { - Promise() : itemId(0), convertor(0) { } - Promise(int itemId, QMacPasteboardMime *c, QString m, QVariant d, int o=0) : itemId(itemId), offset(o), convertor(c), mime(m), data(d) { } - int itemId, offset; - QMacPasteboardMime *convertor; - QString mime; - QVariant data; - }; - QList<Promise> promises; - - OSPasteboardRef paste; - uchar mime_type; - mutable QPointer<QMimeData> mime; - mutable bool mac_mime_source; - static OSStatus promiseKeeper(OSPasteboardRef, PasteboardItemID, CFStringRef, void *); - void clear_helper(); -public: - QMacPasteboard(OSPasteboardRef p, uchar mime_type=0); - QMacPasteboard(uchar mime_type); - QMacPasteboard(CFStringRef name=0, uchar mime_type=0); - ~QMacPasteboard(); - - bool hasFlavor(QString flavor) const; - bool hasOSType(int c_flavor) const; - - OSPasteboardRef pasteBoard() const; - QMimeData *mimeData() const; - void setMimeData(QMimeData *mime); - - QStringList formats() const; - bool hasFormat(const QString &format) const; - QVariant retrieveData(const QString &format, QVariant::Type) const; - - void clear(); - bool sync() const; -}; - -extern QPaintDevice *qt_mac_safe_pdev; //qapplication_mac.cpp - -extern OSWindowRef qt_mac_window_for(const QWidget*); //qwidget_mac.mm -extern OSViewRef qt_mac_nativeview_for(const QWidget *); //qwidget_mac.mm -extern QPoint qt_mac_nativeMapFromParent(const QWidget *child, const QPoint &pt); //qwidget_mac.mm - -#ifdef check -# undef check -#endif - -QFont qfontForThemeFont(ThemeFontID themeID); - -QColor qcolorForTheme(ThemeBrush brush); - -QColor qcolorForThemeTextColor(ThemeTextColor themeColor); - -struct QMacDndAnswerRecord { - QRect rect; - Qt::KeyboardModifiers modifiers; - Qt::MouseButtons buttons; - Qt::DropAction lastAction; - unsigned int lastOperation; - void clear() { - rect = QRect(); - modifiers = Qt::NoModifier; - buttons = Qt::NoButton; - lastAction = Qt::IgnoreAction; - lastOperation = 0; - } -}; -extern QMacDndAnswerRecord qt_mac_dnd_answer_rec; -void qt_mac_copy_answer_rect(const QDragMoveEvent &event); -bool qt_mac_mouse_inside_answer_rect(QPoint mouse); - -QT_END_NAMESPACE - -#endif // QT_MAC_P_H diff --git a/src/gui/platforms/mac/qtextengine_mac.cpp b/src/gui/platforms/mac/qtextengine_mac.cpp deleted file mode 100644 index 2c6e579b45..0000000000 --- a/src/gui/platforms/mac/qtextengine_mac.cpp +++ /dev/null @@ -1,656 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qtextengine_p.h" - -#include <private/qfontengine_coretext_p.h> -#include <private/qfontengine_mac_p.h> - -QT_BEGIN_NAMESPACE - -// set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs -// and no reordering. -// also computes logClusters heuristically -static void heuristicSetGlyphAttributes(const QChar *uc, int length, QGlyphLayout *glyphs, unsigned short *logClusters, int num_glyphs) -{ - // ### zeroWidth and justification are missing here!!!!! - - Q_UNUSED(num_glyphs); - -// qDebug("QScriptEngine::heuristicSetGlyphAttributes, num_glyphs=%d", item->num_glyphs); - - const bool symbolFont = false; // #### - glyphs->attributes[0].mark = false; - glyphs->attributes[0].clusterStart = true; - glyphs->attributes[0].dontPrint = (!symbolFont && uc[0].unicode() == 0x00ad) || qIsControlChar(uc[0].unicode()); - - int pos = 0; - int lastCat = QChar::category(uc[0].unicode()); - for (int i = 1; i < length; ++i) { - if (logClusters[i] == pos) - // same glyph - continue; - ++pos; - while (pos < logClusters[i]) { - ++pos; - } - // hide soft-hyphens by default - if ((!symbolFont && uc[i].unicode() == 0x00ad) || qIsControlChar(uc[i].unicode())) - glyphs->attributes[pos].dontPrint = true; - const QUnicodeTables::Properties *prop = QUnicodeTables::properties(uc[i].unicode()); - int cat = prop->category; - - // one gets an inter character justification point if the current char is not a non spacing mark. - // as then the current char belongs to the last one and one gets a space justification point - // after the space char. - if (lastCat == QChar::Separator_Space) - glyphs->attributes[pos-1].justification = HB_Space; - else if (cat != QChar::Mark_NonSpacing) - glyphs->attributes[pos-1].justification = HB_Character; - else - glyphs->attributes[pos-1].justification = HB_NoJustification; - - lastCat = cat; - } - pos = logClusters[length-1]; - if (lastCat == QChar::Separator_Space) - glyphs->attributes[pos].justification = HB_Space; - else - glyphs->attributes[pos].justification = HB_Character; -} - -struct QArabicProperties { - unsigned char shape; - unsigned char justification; -}; -Q_DECLARE_TYPEINFO(QArabicProperties, Q_PRIMITIVE_TYPE); - -enum QArabicShape { - XIsolated, - XFinal, - XInitial, - XMedial, - // intermediate state - XCausing -}; - - -// these groups correspond to the groups defined in the Unicode standard. -// Some of these groups are equal with regards to both joining and line breaking behaviour, -// and thus have the same enum value -// -// I'm not sure the mapping of syriac to arabic enums is correct with regards to justification, but as -// I couldn't find any better document I'll hope for the best. -enum ArabicGroup { - // NonJoining - ArabicNone, - ArabicSpace, - // Transparent - Transparent, - // Causing - Center, - Kashida, - - // Arabic - // Dual - Beh, - Noon, - Meem = Noon, - Heh = Noon, - KnottedHeh = Noon, - HehGoal = Noon, - SwashKaf = Noon, - Yeh, - Hah, - Seen, - Sad = Seen, - Tah, - Kaf = Tah, - Gaf = Tah, - Lam = Tah, - Ain, - Feh = Ain, - Qaf = Ain, - // Right - Alef, - Waw, - Dal, - TehMarbuta = Dal, - Reh, - HamzaOnHehGoal, - YehWithTail = HamzaOnHehGoal, - YehBarre = HamzaOnHehGoal, - - // Syriac - // Dual - Beth = Beh, - Gamal = Ain, - Heth = Noon, - Teth = Hah, - Yudh = Noon, - Kaph = Noon, - Lamadh = Lam, - Mim = Noon, - Nun = Noon, - Semakh = Noon, - FinalSemakh = Noon, - SyriacE = Ain, - Pe = Ain, - ReversedPe = Hah, - Qaph = Noon, - Shin = Noon, - Fe = Ain, - - // Right - Alaph = Alef, - Dalath = Dal, - He = Dal, - SyriacWaw = Waw, - Zain = Alef, - YudhHe = Waw, - Sadhe = HamzaOnHehGoal, - Taw = Dal, - - // Compiler bug? Otherwise ArabicGroupsEnd would be equal to Dal + 1. - Dummy = HamzaOnHehGoal, - ArabicGroupsEnd -}; - -static const unsigned char arabic_group[0x150] = { - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - ArabicNone, ArabicNone, Alef, Alef, - Waw, Alef, Yeh, Alef, - Beh, TehMarbuta, Beh, Beh, - Hah, Hah, Hah, Dal, - - Dal, Reh, Reh, Seen, - Seen, Sad, Sad, Tah, - Tah, Ain, Ain, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - // 0x640 - Kashida, Feh, Qaf, Kaf, - Lam, Meem, Noon, Heh, - Waw, Yeh, Yeh, Transparent, - Transparent, Transparent, Transparent, Transparent, - - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, Beh, Qaf, - - Transparent, Alef, Alef, Alef, - ArabicNone, Alef, Waw, Waw, - Yeh, Beh, Beh, Beh, - Beh, Beh, Beh, Beh, - - // 0x680 - Beh, Hah, Hah, Hah, - Hah, Hah, Hah, Hah, - Dal, Dal, Dal, Dal, - Dal, Dal, Dal, Dal, - - Dal, Reh, Reh, Reh, - Reh, Reh, Reh, Reh, - Reh, Reh, Seen, Seen, - Seen, Sad, Sad, Tah, - - Ain, Feh, Feh, Feh, - Feh, Feh, Feh, Qaf, - Qaf, Gaf, SwashKaf, Gaf, - Kaf, Kaf, Kaf, Gaf, - - Gaf, Gaf, Gaf, Gaf, - Gaf, Lam, Lam, Lam, - Lam, Noon, Noon, Noon, - Noon, Noon, KnottedHeh, Hah, - - // 0x6c0 - TehMarbuta, HehGoal, HamzaOnHehGoal, HamzaOnHehGoal, - Waw, Waw, Waw, Waw, - Waw, Waw, Waw, Waw, - Yeh, YehWithTail, Yeh, Waw, - - Yeh, Yeh, YehBarre, YehBarre, - ArabicNone, TehMarbuta, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, ArabicNone, ArabicNone, Transparent, - - Transparent, Transparent, Transparent, Transparent, - Transparent, ArabicNone, ArabicNone, Transparent, - Transparent, ArabicNone, Transparent, Transparent, - Transparent, Transparent, Dal, Reh, - - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, Seen, Sad, - Ain, ArabicNone, ArabicNone, KnottedHeh, - - // 0x700 - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - Alaph, Transparent, Beth, Gamal, - Gamal, Dalath, Dalath, He, - SyriacWaw, Zain, Heth, Teth, - Teth, Yudh, YudhHe, Kaph, - - Lamadh, Mim, Nun, Semakh, - FinalSemakh, SyriacE, Pe, ReversedPe, - Sadhe, Qaph, Dalath, Shin, - Taw, Beth, Gamal, Dalath, - - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, ArabicNone, - ArabicNone, Zain, Kaph, Fe, -}; - -static inline ArabicGroup arabicGroup(unsigned short uc) -{ - if (uc >= 0x0600 && uc < 0x750) - return (ArabicGroup) arabic_group[uc-0x600]; - else if (uc == 0x200d) - return Center; - else if (QChar::category(uc) == QChar::Separator_Space) - return ArabicSpace; - else - return ArabicNone; -} - - -/* - Arabic shaping obeys a number of rules according to the joining classes (see Unicode book, section on - arabic). - - Each unicode char has a joining class (right, dual (left&right), center (joincausing) or transparent). - transparent joining is not encoded in QChar::joining(), but applies to all combining marks and format marks. - - Right join-causing: dual + center - Left join-causing: dual + right + center - - Rules are as follows (for a string already in visual order, as we have it here): - - R1 Transparent characters do not affect joining behaviour. - R2 A right joining character, that has a right join-causing char on the right will get form XRight - (R3 A left joining character, that has a left join-causing char on the left will get form XLeft) - Note: the above rule is meaningless, as there are no pure left joining characters defined in Unicode - R4 A dual joining character, that has a left join-causing char on the left and a right join-causing char on - the right will get form XMedial - R5 A dual joining character, that has a right join causing char on the right, and no left join causing char on the left - will get form XRight - R6 A dual joining character, that has a left join causing char on the left, and no right join causing char on the right - will get form XLeft - R7 Otherwise the character will get form XIsolated - - Additionally we have to do the minimal ligature support for lam-alef ligatures: - - L1 Transparent characters do not affect ligature behaviour. - L2 Any sequence of Alef(XRight) + Lam(XMedial) will form the ligature Alef.Lam(XLeft) - L3 Any sequence of Alef(XRight) + Lam(XLeft) will form the ligature Alef.Lam(XIsolated) - - The state table below handles rules R1-R7. -*/ - -enum Joining { - JNone, - JCausing, - JDual, - JRight, - JTransparent -}; - -static const Joining joining_for_group[ArabicGroupsEnd] = { - // NonJoining - JNone, // ArabicNone - JNone, // ArabicSpace - // Transparent - JTransparent, // Transparent - // Causing - JCausing, // Center - JCausing, // Kashida - // Dual - JDual, // Beh - JDual, // Noon - JDual, // Yeh - JDual, // Hah - JDual, // Seen - JDual, // Tah - JDual, // Ain - // Right - JRight, // Alef - JRight, // Waw - JRight, // Dal - JRight, // Reh - JRight // HamzaOnHehGoal -}; - - -struct JoiningPair { - QArabicShape form1; - QArabicShape form2; -}; - -static const JoiningPair joining_table[5][4] = -// None, Causing, Dual, Right -{ - { { XIsolated, XIsolated }, { XIsolated, XCausing }, { XIsolated, XInitial }, { XIsolated, XIsolated } }, // XIsolated - { { XFinal, XIsolated }, { XFinal, XCausing }, { XFinal, XInitial }, { XFinal, XIsolated } }, // XFinal - { { XIsolated, XIsolated }, { XInitial, XCausing }, { XInitial, XMedial }, { XInitial, XFinal } }, // XInitial - { { XFinal, XIsolated }, { XMedial, XCausing }, { XMedial, XMedial }, { XMedial, XFinal } }, // XMedial - { { XIsolated, XIsolated }, { XIsolated, XCausing }, { XIsolated, XMedial }, { XIsolated, XFinal } }, // XCausing -}; - - -/* -According to http://www.microsoft.com/middleeast/Arabicdev/IE6/KBase.asp - -1. Find the priority of the connecting opportunities in each word -2. Add expansion at the highest priority connection opportunity -3. If more than one connection opportunity have the same highest value, - use the opportunity closest to the end of the word. - -Following is a chart that provides the priority for connection -opportunities and where expansion occurs. The character group names -are those in table 6.6 of the UNICODE 2.0 book. - - -PrioritY Glyph Condition Kashida Location - -Arabic_Kashida User inserted Kashida The user entered a Kashida in a position. After the user - (Shift+j or Shift+[E with hat]) Thus, it is the highest priority to insert an inserted kashida - automatic kashida. - -Arabic_Seen Seen, Sad Connecting to the next character. After the character. - (Initial or medial form). - -Arabic_HaaDal Teh Marbutah, Haa, Dal Connecting to previous character. Before the final form - of these characters. - -Arabic_Alef Alef, Tah, Lam, Connecting to previous character. Before the final form - Kaf and Gaf of these characters. - -Arabic_BaRa Reh, Yeh Connected to medial Beh Before preceding medial Baa - -Arabic_Waw Waw, Ain, Qaf, Feh Connecting to previous character. Before the final form of - these characters. - -Arabic_Normal Other connecting Connecting to previous character. Before the final form - characters of these characters. - - - -This seems to imply that we have at most one kashida point per arabic word. - -*/ - -void qt_getArabicProperties(const unsigned short *chars, int len, QArabicProperties *properties) -{ -// qDebug("arabicSyriacOpenTypeShape: properties:"); - int lastPos = 0; - int lastGroup = ArabicNone; - - ArabicGroup group = arabicGroup(chars[0]); - Joining j = joining_for_group[group]; - QArabicShape shape = joining_table[XIsolated][j].form2; - properties[0].justification = HB_NoJustification; - - for (int i = 1; i < len; ++i) { - // #### fix handling for spaces and punktuation - properties[i].justification = HB_NoJustification; - - group = arabicGroup(chars[i]); - j = joining_for_group[group]; - - if (j == JTransparent) { - properties[i].shape = XIsolated; - continue; - } - - properties[lastPos].shape = joining_table[shape][j].form1; - shape = joining_table[shape][j].form2; - - switch(lastGroup) { - case Seen: - if (properties[lastPos].shape == XInitial || properties[lastPos].shape == XMedial) - properties[i-1].justification = HB_Arabic_Seen; - break; - case Hah: - if (properties[lastPos].shape == XFinal) - properties[lastPos-1].justification = HB_Arabic_HaaDal; - break; - case Alef: - if (properties[lastPos].shape == XFinal) - properties[lastPos-1].justification = HB_Arabic_Alef; - break; - case Ain: - if (properties[lastPos].shape == XFinal) - properties[lastPos-1].justification = HB_Arabic_Waw; - break; - case Noon: - if (properties[lastPos].shape == XFinal) - properties[lastPos-1].justification = HB_Arabic_Normal; - break; - case ArabicNone: - break; - - default: - Q_ASSERT(false); - } - - lastGroup = ArabicNone; - - switch(group) { - case ArabicNone: - case Transparent: - // ### Center should probably be treated as transparent when it comes to justification. - case Center: - break; - case ArabicSpace: - properties[i].justification = HB_Arabic_Space; - break; - case Kashida: - properties[i].justification = HB_Arabic_Kashida; - break; - case Seen: - lastGroup = Seen; - break; - - case Hah: - case Dal: - lastGroup = Hah; - break; - - case Alef: - case Tah: - lastGroup = Alef; - break; - - case Yeh: - case Reh: - if (properties[lastPos].shape == XMedial && arabicGroup(chars[lastPos]) == Beh) - properties[lastPos-1].justification = HB_Arabic_BaRa; - break; - - case Ain: - case Waw: - lastGroup = Ain; - break; - - case Noon: - case Beh: - case HamzaOnHehGoal: - lastGroup = Noon; - break; - case ArabicGroupsEnd: - Q_ASSERT(false); - } - - lastPos = i; - } - properties[lastPos].shape = joining_table[shape][JNone].form1; - - -// for (int i = 0; i < len; ++i) -// qDebug("arabic properties(%d): uc=%x shape=%d, justification=%d", i, chars[i], properties[i].shape, properties[i].justification); -} - -void QTextEngine::shapeTextMac(int item) const -{ - QScriptItem &si = layoutData->items[item]; - - si.glyph_data_offset = layoutData->used; - - QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading); - if (font->type() != QFontEngine::Multi) { - shapeTextWithHarfbuzz(item); - return; - } - -#ifndef QT_MAC_USE_COCOA - QFontEngineMacMulti *fe = static_cast<QFontEngineMacMulti *>(font); -#else - QCoreTextFontEngineMulti *fe = static_cast<QCoreTextFontEngineMulti *>(font); -#endif - QTextEngine::ShaperFlags flags; - if (si.analysis.bidiLevel % 2) - flags |= RightToLeft; - if (option.useDesignMetrics()) - flags |= DesignMetrics; - - attributes(); // pre-initialize char attributes - - const int len = length(item); - int num_glyphs = length(item); - const QChar *str = layoutData->string.unicode() + si.position; - ushort upperCased[256]; - if (si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase - || si.analysis.flags == QScriptAnalysis::Lowercase) { - ushort *uc = upperCased; - if (len > 256) - uc = new ushort[len]; - for (int i = 0; i < len; ++i) { - if(si.analysis.flags == QScriptAnalysis::Lowercase) - uc[i] = str[i].toLower().unicode(); - else - uc[i] = str[i].toUpper().unicode(); - } - str = reinterpret_cast<const QChar *>(uc); - } - - ensureSpace(num_glyphs); - num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used; - - QGlyphLayout g = availableGlyphs(&si); - g.numGlyphs = num_glyphs; - unsigned short *log_clusters = logClusters(&si); - - bool stringToCMapFailed = false; - if (!fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, attributes(), &si)) { - ensureSpace(num_glyphs); - g = availableGlyphs(&si); - stringToCMapFailed = !fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, - attributes(), &si); - } - - if (!stringToCMapFailed) { - heuristicSetGlyphAttributes(str, len, &g, log_clusters, num_glyphs); - - si.num_glyphs = num_glyphs; - - layoutData->used += si.num_glyphs; - - QGlyphLayout g = shapedGlyphs(&si); - - if (si.analysis.script == QUnicodeTables::Arabic) { - QVarLengthArray<QArabicProperties> props(len + 2); - QArabicProperties *properties = props.data(); - int f = si.position; - int l = len; - if (f > 0) { - --f; - ++l; - ++properties; - } - if (f + l < layoutData->string.length()) { - ++l; - } - qt_getArabicProperties((const unsigned short *)(layoutData->string.unicode()+f), l, props.data()); - - unsigned short *log_clusters = logClusters(&si); - - for (int i = 0; i < len; ++i) { - int gpos = log_clusters[i]; - g.attributes[gpos].justification = properties[i].justification; - } - } - } - - const ushort *uc = reinterpret_cast<const ushort *>(str); - - if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase - || si.analysis.flags == QScriptAnalysis::Lowercase) - && uc != upperCased) - delete [] uc; -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/mac/qwidget_mac.mm b/src/gui/platforms/mac/qwidget_mac.mm deleted file mode 100644 index 354f05ba10..0000000000 --- a/src/gui/platforms/mac/qwidget_mac.mm +++ /dev/null @@ -1,5420 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -#include <private/qt_mac_p.h> -#include <private/qeventdispatcher_mac_p.h> - -#include "qapplication.h" -#include "qapplication_p.h" -#include "qbitmap.h" -#include "qcursor.h" -#include "qdesktopwidget.h" -#include "qevent.h" -#include "qfileinfo.h" -#include "qimage.h" -#include "qlayout.h" -#include "qmenubar.h" -#include <private/qbackingstore_p.h> -#include <private/qwindowsurface_mac_p.h> -#include <private/qpaintengine_mac_p.h> -#include "qpainter.h" -#include "qstyle.h" -#include "qtimer.h" -#include "qfocusframe.h" -#include "qdebug.h" -#include <private/qmainwindowlayout_p.h> - -#include <private/qabstractscrollarea_p.h> -#include <qabstractscrollarea.h> -#include <ApplicationServices/ApplicationServices.h> -#include <limits.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#include <private/qcocoaview_mac_p.h> -#include <private/qcocoawindow_mac_p.h> -#include <private/qcocoawindowdelegate_mac_p.h> -#include <private/qcocoapanel_mac_p.h> - -#include "qwidget_p.h" -#include "qevent_p.h" -#include "qdnd_p.h" -#include <QtGui/qgraphicsproxywidget.h> -#include "qmainwindow.h" - -QT_BEGIN_NAMESPACE - -// qmainwindow.cpp -extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window); - -#define XCOORD_MAX 16383 -#define WRECT_MAX 8191 - -#ifndef QT_MAC_USE_COCOA - -extern "C" { - extern OSStatus _HIViewScrollRectWithOptions(HIViewRef, const HIRect *, CGFloat, CGFloat, - OptionBits) __attribute__ ((weak)); -} -#define kHIViewScrollRectAdjustInvalid 1 -#define kHIViewScrollRectDontInvalidateRevealedArea 2 -#endif - - -/***************************************************************************** - QWidget debug facilities - *****************************************************************************/ -//#define DEBUG_WINDOW_RGNS -//#define DEBUG_WINDOW_CREATE -//#define DEBUG_WINDOW_STATE -//#define DEBUG_WIDGET_PAINT - -/***************************************************************************** - QWidget globals - *****************************************************************************/ -#ifndef QT_MAC_USE_COCOA -typedef QHash<Qt::WindowFlags, WindowGroupRef> WindowGroupHash; -Q_GLOBAL_STATIC(WindowGroupHash, qt_mac_window_groups) -const UInt32 kWidgetCreatorQt = kEventClassQt; -enum { - kWidgetPropertyQWidget = 'QWId' //QWidget * -}; -#endif - -static bool qt_mac_raise_process = true; -static OSWindowRef qt_root_win = 0; -QWidget *mac_mouse_grabber = 0; -QWidget *mac_keyboard_grabber = 0; - -#ifndef QT_MAC_USE_COCOA -#ifdef QT_NAMESPACE - -// produce the string "com.trolltech.qt-namespace.widget", where "namespace" is the contents of QT_NAMESPACE. -#define SS(x) #x -#define S0(x) SS(x) -#define S "com.trolltech.qt-" S0(QT_NAMESPACE) ".widget" - -static CFStringRef kObjectQWidget = CFSTR(S); - -#undef SS -#undef S0 -#undef S - -#else -static CFStringRef kObjectQWidget = CFSTR("com.trolltech.qt.widget"); -#endif // QT_NAMESPACE -#endif // QT_MAC_USE_COCOA - -/***************************************************************************** - Externals - *****************************************************************************/ -extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp -extern QWidget *qt_mac_modal_blocked(QWidget *); //qapplication_mac.mm -extern void qt_event_request_activate(QWidget *); //qapplication_mac.mm -extern bool qt_event_remove_activate(); //qapplication_mac.mm -extern void qt_mac_event_release(QWidget *w); //qapplication_mac.mm -extern void qt_event_request_showsheet(QWidget *); //qapplication_mac.mm -extern void qt_event_request_window_change(QWidget *); //qapplication_mac.mm -extern QPointer<QWidget> qt_last_mouse_receiver; //qapplication_mac.mm -extern QPointer<QWidget> qt_last_native_mouse_receiver; //qt_cocoa_helpers_mac.mm -extern IconRef qt_mac_create_iconref(const QPixmap &); //qpixmap_mac.cpp -extern void qt_mac_set_cursor(const QCursor *, const QPoint &); //qcursor_mac.mm -extern void qt_mac_update_cursor(); //qcursor_mac.mm -extern bool qt_nograb(); -extern CGImageRef qt_mac_create_cgimage(const QPixmap &, bool); //qpixmap_mac.cpp -extern RgnHandle qt_mac_get_rgn(); //qregion_mac.cpp -extern QRegion qt_mac_convert_mac_region(RgnHandle rgn); //qregion_mac.cpp -extern void qt_mac_setMouseGrabCursor(bool set, QCursor *cursor = 0); // qcursor_mac.mm -extern QPointer<QWidget> topLevelAt_cache; // qapplication_mac.mm -/***************************************************************************** - QWidget utility functions - *****************************************************************************/ -void Q_GUI_EXPORT qt_mac_set_raise_process(bool b) { qt_mac_raise_process = b; } -static QSize qt_mac_desktopSize() -{ - int w = 0, h = 0; - CGDisplayCount cg_count; - CGGetActiveDisplayList(0, 0, &cg_count); - QVector<CGDirectDisplayID> displays(cg_count); - CGGetActiveDisplayList(cg_count, displays.data(), &cg_count); - Q_ASSERT(cg_count == (CGDisplayCount)displays.size()); - for(int i = 0; i < (int)cg_count; ++i) { - CGRect r = CGDisplayBounds(displays.at(i)); - w = qMax<int>(w, qRound(r.origin.x + r.size.width)); - h = qMax<int>(h, qRound(r.origin.y + r.size.height)); - } - return QSize(w, h); -} - -#ifdef QT_MAC_USE_COCOA -static NSDrawer *qt_mac_drawer_for(const QWidget *widget) -{ - NSView *widgetView = reinterpret_cast<NSView *>(widget->window()->effectiveWinId()); - NSArray *windows = [NSApp windows]; - for (NSWindow *window in windows) { - NSArray *drawers = [window drawers]; - for (NSDrawer *drawer in drawers) { - if ([drawer contentView] == widgetView) - return drawer; - } - } - return 0; -} -#endif - -static void qt_mac_destructView(OSViewRef view) -{ -#ifdef QT_MAC_USE_COCOA - NSWindow *window = [view window]; - if ([window contentView] == view) - [window setContentView:[[NSView alloc] initWithFrame:[view bounds]]]; - [view removeFromSuperview]; - [view release]; -#else - HIViewRemoveFromSuperview(view); - CFRelease(view); -#endif -} - -static void qt_mac_destructWindow(OSWindowRef window) -{ -#ifdef QT_MAC_USE_COCOA - if ([window isVisible] && [window isSheet]){ - [NSApp endSheet:window]; - [window orderOut:window]; - } - - [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] resignDelegateForWindow:window]; - [window release]; -#else - // Remove property to clean up memory: - RemoveWindowProperty(window, kWidgetCreatorQt, kWidgetPropertyQWidget); - CFRelease(window); -#endif -} - -static void qt_mac_destructDrawer(NSDrawer *drawer) -{ -#ifdef QT_MAC_USE_COCOA - [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] resignDelegateForDrawer:drawer]; - [drawer release]; -#else - Q_UNUSED(drawer); -#endif -} - -bool qt_mac_can_clickThrough(const QWidget *w) -{ - static int qt_mac_carbon_clickthrough = -1; - if (qt_mac_carbon_clickthrough < 0) - qt_mac_carbon_clickthrough = !qgetenv("QT_MAC_NO_COCOA_CLICKTHROUGH").isEmpty(); - bool ret = !qt_mac_carbon_clickthrough; - for ( ; w; w = w->parentWidget()) { - if (w->testAttribute(Qt::WA_MacNoClickThrough)) { - ret = false; - break; - } - } - return ret; -} - -bool qt_mac_is_macsheet(const QWidget *w) -{ - if (!w) - return false; - - Qt::WindowModality modality = w->windowModality(); - if (modality == Qt::ApplicationModal) - return false; - return w->parentWidget() && (modality == Qt::WindowModal || w->windowType() == Qt::Sheet); -} - -bool qt_mac_is_macdrawer(const QWidget *w) -{ - return (w && w->parentWidget() && w->windowType() == Qt::Drawer); -} - -bool qt_mac_insideKeyWindow(const QWidget *w) -{ -#ifdef QT_MAC_USE_COCOA - return [[reinterpret_cast<NSView *>(w->effectiveWinId()) window] isKeyWindow]; -#else - Q_UNUSED(w); -#endif - return false; -} - -bool qt_mac_set_drawer_preferred_edge(QWidget *w, Qt::DockWidgetArea where) //users of Qt for Mac OS X can use this.. -{ - if(!qt_mac_is_macdrawer(w)) - return false; - -#if QT_MAC_USE_COCOA - NSDrawer *drawer = qt_mac_drawer_for(w); - if (!drawer) - return false; - NSRectEdge edge; - if (where & Qt::LeftDockWidgetArea) - edge = NSMinXEdge; - else if (where & Qt::RightDockWidgetArea) - edge = NSMaxXEdge; - else if (where & Qt::TopDockWidgetArea) - edge = NSMaxYEdge; - else if (where & Qt::BottomDockWidgetArea) - edge = NSMinYEdge; - else - return false; - - if (edge == [drawer preferredEdge]) //no-op - return false; - - if (w->isVisible()) { - [drawer close]; - [drawer openOnEdge:edge]; - } - [drawer setPreferredEdge:edge]; -#else - OSWindowRef window = qt_mac_window_for(w); - OptionBits edge; - if(where & Qt::LeftDockWidgetArea) - edge = kWindowEdgeLeft; - else if(where & Qt::RightDockWidgetArea) - edge = kWindowEdgeRight; - else if(where & Qt::TopDockWidgetArea) - edge = kWindowEdgeTop; - else if(where & Qt::BottomDockWidgetArea) - edge = kWindowEdgeBottom; - else - return false; - - if(edge == GetDrawerPreferredEdge(window)) //no-op - return false; - - //do it - SetDrawerPreferredEdge(window, edge); - if(w->isVisible()) { - CloseDrawer(window, false); - OpenDrawer(window, edge, true); - } -#endif - return true; -} - -#ifndef QT_MAC_USE_COCOA -Q_GUI_EXPORT -#endif -QPoint qt_mac_posInWindow(const QWidget *w) -{ - QPoint ret = w->data->wrect.topLeft(); - while(w && !w->isWindow()) { - ret += w->pos(); - w = w->parentWidget(); - } - return ret; -} - -//find a QWidget from a OSWindowRef -QWidget *qt_mac_find_window(OSWindowRef window) -{ -#ifdef QT_MAC_USE_COCOA - return [window QT_MANGLE_NAMESPACE(qt_qwidget)]; -#else - if(!window) - return 0; - - QWidget *ret; - if(GetWindowProperty(window, kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(ret), 0, &ret) == noErr) - return ret; - return 0; -#endif -} - -inline static void qt_mac_set_fullscreen_mode(bool b) -{ - extern bool qt_mac_app_fullscreen; //qapplication_mac.mm - if(qt_mac_app_fullscreen == b) - return; - qt_mac_app_fullscreen = b; - if (b) { - SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar); - } else { - SetSystemUIMode(kUIModeNormal, 0); - } -} - -Q_GUI_EXPORT OSViewRef qt_mac_nativeview_for(const QWidget *w) -{ - return reinterpret_cast<OSViewRef>(w->internalWinId()); -} - -Q_GUI_EXPORT OSViewRef qt_mac_effectiveview_for(const QWidget *w) -{ - // Get the first non-alien (parent) widget for - // w, and return its NSView (if it has one): - return reinterpret_cast<OSViewRef>(w->effectiveWinId()); -} - -Q_GUI_EXPORT OSViewRef qt_mac_get_contentview_for(OSWindowRef w) -{ -#ifdef QT_MAC_USE_COCOA - return [w contentView]; -#else - HIViewRef contentView = 0; - OSStatus err = GetRootControl(w, &contentView); // Returns the window's content view (Apple QA1214) - if (err == errUnknownControl) { - contentView = HIViewGetRoot(w); - } else if (err != noErr) { - qWarning("Qt:Could not get content or root view of window! %s:%d [%ld]", - __FILE__, __LINE__, err); - } - return contentView; -#endif -} - -bool qt_mac_sendMacEventToWidget(QWidget *widget, EventRef ref) -{ - return widget->macEvent(0, ref); -} - -Q_GUI_EXPORT OSWindowRef qt_mac_window_for(OSViewRef view) -{ -#ifdef QT_MAC_USE_COCOA - if (view) - return [view window]; - return 0; -#else - return HIViewGetWindow(view); -#endif -} - -static bool qt_isGenuineQWidget(OSViewRef ref) -{ -#ifdef QT_MAC_USE_COCOA - return [ref isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]; -#else - return HIObjectIsOfClass(HIObjectRef(ref), kObjectQWidget); -#endif -} - -bool qt_isGenuineQWidget(const QWidget *window) -{ - if (!window) - return false; - - if (!window->internalWinId()) - return true; //alien - - return qt_isGenuineQWidget(OSViewRef(window->internalWinId())); -} - -Q_GUI_EXPORT OSWindowRef qt_mac_window_for(const QWidget *w) -{ - if (OSViewRef hiview = qt_mac_effectiveview_for(w)) { - OSWindowRef window = qt_mac_window_for(hiview); - if (window) - return window; - - if (qt_isGenuineQWidget(hiview)) { - // This is a workaround for NSToolbar. When a widget is hidden - // by clicking the toolbar button, Cocoa reparents the widgets - // to another window (but Qt doesn't know about it). - // When we start showing them, it reparents back, - // but at this point it's window is nil, but the window it's being brought - // into (the Qt one) is for sure created. - // This stops the hierarchy moving under our feet. - QWidget *toplevel = w->window(); - if (toplevel != w) { - hiview = qt_mac_nativeview_for(toplevel); - if (OSWindowRef w = qt_mac_window_for(hiview)) - return w; - } - - toplevel->d_func()->createWindow_sys(); - // Reget the hiview since "create window" could potentially move the view (I guess). - hiview = qt_mac_nativeview_for(toplevel); - return qt_mac_window_for(hiview); - } - } - return 0; -} - -#ifndef QT_MAC_USE_COCOA -/* Checks if the current group is a 'stay on top' group. If so, the - group gets removed from the hash table */ -static void qt_mac_release_stays_on_top_group(WindowGroupRef group) -{ - for (WindowGroupHash::iterator it = qt_mac_window_groups()->begin(); it != qt_mac_window_groups()->end(); ++it) { - if (it.value() == group) { - qt_mac_window_groups()->remove(it.key()); - return; - } - } -} - -/* Use this function instead of ReleaseWindowGroup, this will be sure to release the - stays on top window group (created with qt_mac_get_stays_on_top_group below) */ -static void qt_mac_release_window_group(WindowGroupRef group) -{ - ReleaseWindowGroup(group); - if (GetWindowGroupRetainCount(group) == 0) - qt_mac_release_stays_on_top_group(group); -} -#define ReleaseWindowGroup(x) Are you sure you wanted to do that? (you wanted qt_mac_release_window_group) - -SInt32 qt_mac_get_group_level(WindowClass wclass) -{ - SInt32 group_level; - CGWindowLevel tmpLevel; - GetWindowGroupLevelOfType(GetWindowGroupOfClass(wclass), kWindowGroupLevelActive, &tmpLevel); - group_level = tmpLevel; - return group_level; -} -#endif - -#ifndef QT_MAC_USE_COCOA -static void qt_mac_set_window_group(OSWindowRef window, Qt::WindowFlags flags, int level) -{ - WindowGroupRef group = 0; - if (qt_mac_window_groups()->contains(flags)) { - group = qt_mac_window_groups()->value(flags); - RetainWindowGroup(group); - } else { - CreateWindowGroup(kWindowActivationScopeNone, &group); - SetWindowGroupLevel(group, level); - SetWindowGroupParent(group, GetWindowGroupOfClass(kAllWindowClasses)); - qt_mac_window_groups()->insert(flags, group); - } - SetWindowGroup(window, group); -} - -inline static void qt_mac_set_window_group_to_stays_on_top(OSWindowRef window, Qt::WindowType type) -{ - // We create one static stays on top window group so that - // all stays on top (aka popups) will fall into the same - // group and be able to be raise()'d with releation to one another (from - // within the same window group). - qt_mac_set_window_group(window, type|Qt::WindowStaysOnTopHint, qt_mac_get_group_level(kOverlayWindowClass)); -} - -inline static void qt_mac_set_window_group_to_tooltip(OSWindowRef window) -{ - // Since new groups are created for 'stays on top' windows, the - // same must be done for tooltips. Otherwise, tooltips would be drawn - // below 'stays on top' widgets even tough they are on the same level. - // Also, add 'two' to the group level to make sure they also get on top of popups. - qt_mac_set_window_group(window, Qt::ToolTip, qt_mac_get_group_level(kHelpWindowClass)+2); -} - -inline static void qt_mac_set_window_group_to_popup(OSWindowRef window) -{ - // In Qt, a popup is seen as a 'stay on top' window. - // Since new groups are created for 'stays on top' windows, the - // same must be done for popups. Otherwise, popups would be drawn - // below 'stays on top' windows. Add 1 to get above pure stay-on-top windows. - qt_mac_set_window_group(window, Qt::Popup, qt_mac_get_group_level(kOverlayWindowClass)+1); -} -#endif - -inline static bool updateRedirectedToGraphicsProxyWidget(QWidget *widget, const QRect &rect) -{ - if (!widget) - return false; - -#ifndef QT_NO_GRAPHICSVIEW - QWidget *tlw = widget->window(); - QWExtra *extra = qt_widget_private(tlw)->extra; - if (extra && extra->proxyWidget) { - extra->proxyWidget->update(rect.translated(widget->mapTo(tlw, QPoint()))); - return true; - } -#endif - - return false; -} - -inline static bool updateRedirectedToGraphicsProxyWidget(QWidget *widget, const QRegion &rgn) -{ - if (!widget) - return false; - -#ifndef QT_NO_GRAPHICSVIEW - QWidget *tlw = widget->window(); - QWExtra *extra = qt_widget_private(tlw)->extra; - if (extra && extra->proxyWidget) { - const QPoint offset(widget->mapTo(tlw, QPoint())); - const QVector<QRect> rects = rgn.rects(); - for (int i = 0; i < rects.size(); ++i) - extra->proxyWidget->update(rects.at(i).translated(offset)); - return true; - } -#endif - - return false; -} - -void QWidgetPrivate::macSetNeedsDisplay(QRegion region) -{ - Q_Q(QWidget); -#ifndef QT_MAC_USE_COCOA - if (region.isEmpty()) - HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true); - else if (RgnHandle rgnHandle = region.toQDRgnForUpdate_sys()) - HIViewSetNeedsDisplayInRegion(qt_mac_nativeview_for(q), QMacSmartQuickDrawRegion(rgnHandle), true); - else - HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true); // do a complete repaint on overflow. -#else - if (NSView *nativeView = qt_mac_nativeview_for(q)) { - // INVARIANT: q is _not_ alien. So we can optimize a little: - if (region.isEmpty()) { - [nativeView setNeedsDisplay:YES]; - } else { - QVector<QRect> rects = region.rects(); - for (int i = 0; i<rects.count(); ++i) { - const QRect &rect = rects.at(i); - NSRect nsrect = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); - [nativeView setNeedsDisplayInRect:nsrect]; - } - } - } else if (QWidget *effectiveWidget = q->nativeParentWidget()) { - // INVARIANT: q is alien, and effectiveWidget is native. - if (NSView *effectiveView = qt_mac_nativeview_for(effectiveWidget)) { - if (region.isEmpty()) { - const QRect &rect = q->rect(); - QPoint p = q->mapTo(effectiveWidget, rect.topLeft()); - NSRect nsrect = NSMakeRect(p.x(), p.y(), rect.width(), rect.height()); - [effectiveView setNeedsDisplayInRect:nsrect]; - } else { - QVector<QRect> rects = region.rects(); - for (int i = 0; i<rects.count(); ++i) { - const QRect &rect = rects.at(i); - QPoint p = q->mapTo(effectiveWidget, rect.topLeft()); - NSRect nsrect = NSMakeRect(p.x(), p.y(), rect.width(), rect.height()); - [effectiveView setNeedsDisplayInRect:nsrect]; - } - } - } - } -#endif -} - -void QWidgetPrivate::macUpdateIsOpaque() -{ - Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created)) - return; -#ifndef QT_MAC_USE_COCOA - HIViewFeatures bits; - HIViewRef hiview = qt_mac_nativeview_for(q); - HIViewGetFeatures(hiview, &bits); - if ((bits & kHIViewIsOpaque) == isOpaque) - return; - if (isOpaque) { - HIViewChangeFeatures(hiview, kHIViewIsOpaque, 0); - } else { - HIViewChangeFeatures(hiview, 0, kHIViewIsOpaque); - } - if (q->isVisible()) - HIViewReshapeStructure(qt_mac_nativeview_for(q)); -#else - if (isRealWindow() && !q->testAttribute(Qt::WA_MacBrushedMetal)) { - bool opaque = isOpaque; - if (extra && extra->imageMask) - opaque = false; // we are never opaque when we have a mask. - [qt_mac_window_for(q) setOpaque:opaque]; - } -#endif -} -#ifdef QT_MAC_USE_COCOA -static OSWindowRef qt_mac_create_window(QWidget *widget, WindowClass wclass, - NSUInteger wattr, const QRect &crect) -{ - // Determine if we need to add in our "custom window" attribute. Cocoa is rather clever - // in deciding if we need the maximize button or not (i.e., it's resizeable, so you - // must need a maximize button). So, the only buttons we have control over are the - // close and minimize buttons. If someone wants to customize and NOT have the maximize - // button, then we have to do our hack. We only do it for these cases because otherwise - // the window looks different when activated. This "QtMacCustomizeWindow" attribute is - // intruding on a public space and WILL BREAK in the future. - // One can hope that there is a more public API available by that time. - Qt::WindowFlags flags = widget ? widget->windowFlags() : Qt::WindowFlags(0); - if ((flags & Qt::CustomizeWindowHint)) { - if ((flags & (Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint - | Qt::WindowMinimizeButtonHint | Qt::WindowTitleHint)) - && !(flags & Qt::WindowMaximizeButtonHint)) - wattr |= QtMacCustomizeWindow; - } - - // If we haven't created the desktop widget, you have to pass the rectangle - // in "cocoa coordinates" (i.e., top points to the lower left coordinate). - // Otherwise, we do the conversion for you. Since we are the only ones that - // create the desktop widget, this is OK (but confusing). - NSRect geo = NSMakeRect(crect.left(), - (qt_root_win != 0) ? flipYCoordinate(crect.bottom() + 1) : crect.top(), - crect.width(), crect.height()); - QMacCocoaAutoReleasePool pool; - OSWindowRef window; - switch (wclass) { - case kMovableModalWindowClass: - case kModalWindowClass: - case kSheetWindowClass: - case kFloatingWindowClass: - case kOverlayWindowClass: - case kHelpWindowClass: { - NSPanel *panel; - BOOL needFloating = NO; - BOOL worksWhenModal = widget && (widget->windowType() == Qt::Popup); - // Add in the extra flags if necessary. - switch (wclass) { - case kSheetWindowClass: - wattr |= NSDocModalWindowMask; - break; - case kFloatingWindowClass: - case kHelpWindowClass: - needFloating = YES; - wattr |= NSUtilityWindowMask; - break; - default: - break; - } - panel = [[QT_MANGLE_NAMESPACE(QCocoaPanel) alloc] QT_MANGLE_NAMESPACE(qt_initWithQWidget):widget contentRect:geo styleMask:wattr]; - [panel setFloatingPanel:needFloating]; - [panel setWorksWhenModal:worksWhenModal]; - window = panel; - break; - } - case kDrawerWindowClass: { - NSDrawer *drawer = [[NSDrawer alloc] initWithContentSize:geo.size preferredEdge:NSMinXEdge]; - [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] becomeDelegateForDrawer:drawer widget:widget]; - QWidget *parentWidget = widget->parentWidget(); - if (parentWidget) - [drawer setParentWindow:qt_mac_window_for(parentWidget)]; - [drawer setLeadingOffset:0.0]; - [drawer setTrailingOffset:25.0]; - window = [[drawer contentView] window]; // Just to make sure we actually return a window - break; - } - default: - window = [[QT_MANGLE_NAMESPACE(QCocoaWindow) alloc] QT_MANGLE_NAMESPACE(qt_initWithQWidget):widget contentRect:geo styleMask:wattr]; - break; - } - qt_syncCocoaTitleBarButtons(window, widget); - return window; -} -#else -static OSWindowRef qt_mac_create_window(QWidget *, WindowClass wclass, WindowAttributes wattr, - const QRect &crect) -{ - OSWindowRef window; - Rect geo; - SetRect(&geo, crect.left(), crect.top(), crect.right() + 1, crect.bottom() + 1); - OSStatus err; - if(geo.right <= geo.left) geo.right = geo.left + 1; - if(geo.bottom <= geo.top) geo.bottom = geo.top + 1; - Rect null_rect; - SetRect(&null_rect, 0, 0, 1, 1); - err = CreateNewWindow(wclass, wattr, &null_rect, &window); - if(err == noErr) { - err = SetWindowBounds(window, kWindowContentRgn, &geo); - if(err != noErr) - qWarning("QWidget: Internal error (%s:%d)", __FILE__, __LINE__); - } - return window; -} - -#ifndef QT_NO_GESTURES -#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 -/* We build the release package against the 10.4 SDK. - So, to enable gestures for applications running on - 10.6+, we define the missing constants here: */ -enum { - kEventClassGesture = 'gest', - kEventGestureStarted = 1, - kEventGestureEnded = 2, - kEventGestureMagnify = 4, - kEventGestureSwipe = 5, - kEventGestureRotate = 6, - kEventParamRotationAmount = 'rota', - kEventParamSwipeDirection = 'swip', - kEventParamMagnificationAmount = 'magn' -}; -#endif -#endif // QT_NO_GESTURES - -// window events -static EventTypeSpec window_events[] = { - { kEventClassWindow, kEventWindowClose }, - { kEventClassWindow, kEventWindowExpanded }, - { kEventClassWindow, kEventWindowHidden }, - { kEventClassWindow, kEventWindowZoom }, - { kEventClassWindow, kEventWindowZoomed }, - { kEventClassWindow, kEventWindowCollapsed }, - { kEventClassWindow, kEventWindowToolbarSwitchMode }, - { kEventClassWindow, kEventWindowProxyBeginDrag }, - { kEventClassWindow, kEventWindowProxyEndDrag }, - { kEventClassWindow, kEventWindowResizeCompleted }, - { kEventClassWindow, kEventWindowBoundsChanging }, - { kEventClassWindow, kEventWindowGetRegion }, - { kEventClassWindow, kEventWindowGetClickModality }, - { kEventClassWindow, kEventWindowTransitionCompleted }, - { kEventClassGesture, kEventGestureStarted }, - { kEventClassGesture, kEventGestureEnded }, - { kEventClassGesture, kEventGestureMagnify }, - { kEventClassGesture, kEventGestureSwipe }, - { kEventClassGesture, kEventGestureRotate }, - { kEventClassMouse, kEventMouseDown } -}; -static EventHandlerUPP mac_win_eventUPP = 0; -static void cleanup_win_eventUPP() -{ - DisposeEventHandlerUPP(mac_win_eventUPP); - mac_win_eventUPP = 0; -} -static const EventHandlerUPP make_win_eventUPP() -{ - if(mac_win_eventUPP) - return mac_win_eventUPP; - qAddPostRoutine(cleanup_win_eventUPP); - return mac_win_eventUPP = NewEventHandlerUPP(QWidgetPrivate::qt_window_event); -} -OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, void *) -{ - QScopedLoopLevelCounter loopLevelCounter(qApp->d_func()->threadData); - bool handled_event = true; - UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event); - switch(eclass) { - case kEventClassWindow: { - WindowRef wid = 0; - GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0, - sizeof(WindowRef), 0, &wid); - QWidget *widget = qt_mac_find_window(wid); - if(!widget) { - handled_event = false; - } else if(ekind == kEventWindowGetClickModality) { - // Carbon will send us kEventWindowGetClickModality before every - // mouse press / release event. By returning 'true', we tell Carbon - // that we would like the event target to receive the mouse event even - // if the target is modally shaddowed. In Qt, this makes sense when we - // e.g. have a popup showing, as the popup will grab the event - // and perhaps use it to close itself. - // By also setting the current modal window back into the event, we - // help Carbon determining which window is supposed to be raised. - handled_event = qApp->activePopupWidget() ? true : false; - } else if(ekind == kEventWindowClose) { - widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); - QMenuBar::macUpdateMenuBar(); - } else if (ekind == kEventWindowTransitionCompleted) { - WindowTransitionAction transitionAction; - GetEventParameter(event, kEventParamWindowTransitionAction, typeWindowTransitionAction, - 0, sizeof(transitionAction), 0, &transitionAction); - if (transitionAction == kWindowHideTransitionAction) - widget->hide(); - } else if(ekind == kEventWindowExpanded) { - Qt::WindowStates currState = Qt::WindowStates(widget->data->window_state); - Qt::WindowStates newState = currState; - if (currState & Qt::WindowMinimized) - newState &= ~Qt::WindowMinimized; - if (!(currState & Qt::WindowActive)) - newState |= Qt::WindowActive; - if (newState != currState) { - // newState will differ from currState if the window - // was expanded after clicking on the jewels (as opposed - // to calling QWidget::setWindowState) - widget->data->window_state = newState; - QWindowStateChangeEvent e(currState); - QApplication::sendSpontaneousEvent(widget, &e); - } - - QShowEvent qse; - QApplication::sendSpontaneousEvent(widget, &qse); - } else if(ekind == kEventWindowZoom) { - widget->d_func()->topData()->normalGeometry = widget->geometry(); - handled_event = false; - } else if(ekind == kEventWindowZoomed) { - WindowPartCode windowPart; - GetEventParameter(event, kEventParamWindowPartCode, - typeWindowPartCode, 0, sizeof(windowPart), 0, &windowPart); - if(windowPart == inZoomIn && widget->isMaximized()) { - - widget->data->window_state = widget->data->window_state & ~Qt::WindowMaximized; - QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state | Qt::WindowMaximized)); - QApplication::sendSpontaneousEvent(widget, &e); - } else if(windowPart == inZoomOut && !widget->isMaximized()) { - widget->data->window_state = widget->data->window_state | Qt::WindowMaximized; - QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state - & ~Qt::WindowMaximized)); - QApplication::sendSpontaneousEvent(widget, &e); - } - qt_button_down = 0; - } else if(ekind == kEventWindowCollapsed) { - if (!widget->isMinimized()) { - widget->data->window_state = widget->data->window_state | Qt::WindowMinimized; - QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state & ~Qt::WindowMinimized)); - QApplication::sendSpontaneousEvent(widget, &e); - } - - // Deactivate this window: - if (widget->isActiveWindow() && !(widget->windowType() == Qt::Popup)) { - QWidget *w = 0; - if (widget->parentWidget()) - w = widget->parentWidget()->window(); - if (!w || (!w->isVisible() && !w->isMinimized())) { - for (WindowPtr wp = GetFrontWindowOfClass(kDocumentWindowClass, true); - wp; wp = GetNextWindowOfClass(wp, kDocumentWindowClass, true)) { - if ((w = qt_mac_find_window(wp))) - break; - } - } - if(!(w && w->isVisible() && !w->isMinimized())) - qApp->setActiveWindow(0); - } - - //we send a hide to be like X11/Windows - QEvent e(QEvent::Hide); - QApplication::sendSpontaneousEvent(widget, &e); - qt_button_down = 0; - } else if(ekind == kEventWindowToolbarSwitchMode) { - macSendToolbarChangeEvent(widget); - HIToolbarRef toolbar; - if (GetWindowToolbar(wid, &toolbar) == noErr) { - if (toolbar) { - // Let HIToolbar do its thang, but things like the OpenGL context - // needs to know about it. - CallNextEventHandler(er, event); - qt_event_request_window_change(widget); - widget->data->fstrut_dirty = true; - } - } - } else if(ekind == kEventWindowGetRegion) { - WindowRef window; - GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0, - sizeof(window), 0, &window); - WindowRegionCode wcode; - GetEventParameter(event, kEventParamWindowRegionCode, typeWindowRegionCode, 0, - sizeof(wcode), 0, &wcode); - if (wcode != kWindowOpaqueRgn){ - // If the region is kWindowOpaqueRgn, don't call next - // event handler cause this will make the shadow of - // masked windows become offset. Unfortunately, we're not sure why. - CallNextEventHandler(er, event); - } - RgnHandle rgn; - GetEventParameter(event, kEventParamRgnHandle, typeQDRgnHandle, 0, - sizeof(rgn), 0, &rgn); - - if(QWidgetPrivate::qt_widget_rgn(qt_mac_find_window(window), wcode, rgn, false)) - SetEventParameter(event, kEventParamRgnHandle, typeQDRgnHandle, sizeof(rgn), &rgn); - } else if(ekind == kEventWindowProxyBeginDrag) { - QIconDragEvent e; - QApplication::sendSpontaneousEvent(widget, &e); - } else if(ekind == kEventWindowResizeCompleted) { - // Create a mouse up event, since such an event is not send by carbon to the - // application event handler (while a mouse down <b>is</b> on kEventWindowResizeStarted) - EventRef mouseUpEvent; - CreateEvent(0, kEventClassMouse, kEventMouseUp, 0, kEventAttributeUserEvent, &mouseUpEvent); - UInt16 mbutton = kEventMouseButtonPrimary; - SetEventParameter(mouseUpEvent, kEventParamMouseButton, typeMouseButton, sizeof(mbutton), &mbutton); - WindowRef window; - GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0, sizeof(window), 0, &window); - Rect dragRect; - GetWindowBounds(window, kWindowGrowRgn, &dragRect); - Point pos = {dragRect.bottom, dragRect.right}; - SetEventParameter(mouseUpEvent, kEventParamMouseLocation, typeQDPoint, sizeof(pos), &pos); - SendEventToApplication(mouseUpEvent); - ReleaseEvent(mouseUpEvent); - } else if(ekind == kEventWindowBoundsChanging) { - UInt32 flags = 0; - GetEventParameter(event, kEventParamAttributes, typeUInt32, 0, - sizeof(flags), 0, &flags); - Rect nr; - GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, 0, - sizeof(nr), 0, &nr); - - QRect newRect(nr.left, nr.top, nr.right - nr.left, nr.bottom - nr.top); - - QTLWExtra * const tlwExtra = widget->d_func()->maybeTopData(); - if (tlwExtra && tlwExtra->isSetGeometry == 1) { - widget->d_func()->setGeometry_sys_helper(newRect.left(), newRect.top(), newRect.width(), newRect.height(), tlwExtra->isMove); - } else { - //implicitly removes the maximized bit - if((widget->data->window_state & Qt::WindowMaximized) && - IsWindowInStandardState(wid, 0, 0)) { - widget->data->window_state &= ~Qt::WindowMaximized; - QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state - | Qt::WindowMaximized)); - QApplication::sendSpontaneousEvent(widget, &e); - - } - - handled_event = false; - const QRect oldRect = widget->data->crect; - if((flags & kWindowBoundsChangeOriginChanged)) { - if(nr.left != oldRect.x() || nr.top != oldRect.y()) { - widget->data->crect.moveTo(nr.left, nr.top); - QMoveEvent qme(widget->data->crect.topLeft(), oldRect.topLeft()); - QApplication::sendSpontaneousEvent(widget, &qme); - } - } - if((flags & kWindowBoundsChangeSizeChanged)) { - if (widget->isWindow()) { - QSize newSize = QLayout::closestAcceptableSize(widget, newRect.size()); - int dh = newSize.height() - newRect.height(); - int dw = newSize.width() - newRect.width(); - if (dw != 0 || dh != 0) { - handled_event = true; // We want to change the bounds, so we handle the event - - // set the rect, so we can also do the resize down below (yes, we need to resize). - newRect.setBottom(newRect.bottom() + dh); - newRect.setRight(newRect.right() + dw); - - nr.left = newRect.x(); - nr.top = newRect.y(); - nr.right = nr.left + newRect.width(); - nr.bottom = nr.top + newRect.height(); - SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), &nr); - } - } - - if (oldRect.width() != newRect.width() || oldRect.height() != newRect.height()) { - widget->data->crect.setSize(newRect.size()); - HIRect bounds = CGRectMake(0, 0, newRect.width(), newRect.height()); - - // If the WA_StaticContents attribute is set we can optimize the resize - // by only repainting the newly exposed area. We do this by disabling - // painting when setting the size of the view. The OS will invalidate - // the newly exposed area for us. - const bool staticContents = widget->testAttribute(Qt::WA_StaticContents); - const HIViewRef view = qt_mac_nativeview_for(widget); - if (staticContents) - HIViewSetDrawingEnabled(view, false); - HIViewSetFrame(view, &bounds); - if (staticContents) - HIViewSetDrawingEnabled(view, true); - - QResizeEvent qre(newRect.size(), oldRect.size()); - QApplication::sendSpontaneousEvent(widget, &qre); - qt_event_request_window_change(widget); - } - } - } - } else if (ekind == kEventWindowHidden) { - // Make sure that we also hide any visible sheets on our window. - // Cocoa does the right thing for us. - const QObjectList children = widget->children(); - const int childCount = children.count(); - for (int i = 0; i < childCount; ++i) { - QObject *obj = children.at(i); - if (obj->isWidgetType()) { - QWidget *widget = static_cast<QWidget *>(obj); - if (qt_mac_is_macsheet(widget) && widget->isVisible()) - widget->hide(); - } - } - } else { - handled_event = false; - } - break; } - case kEventClassMouse: { -#if 0 - return SendEventToApplication(event); -#endif - - bool send_to_app = false; - { - WindowPartCode wpc; - if (GetEventParameter(event, kEventParamWindowPartCode, typeWindowPartCode, 0, - sizeof(wpc), 0, &wpc) == noErr && wpc != inContent) - send_to_app = true; - } - if(!send_to_app) { - WindowRef window; - if(GetEventParameter(event, kEventParamWindowRef, typeWindowRef, 0, - sizeof(window), 0, &window) == noErr) { - HIViewRef hiview; - if(HIViewGetViewForMouseEvent(HIViewGetRoot(window), event, &hiview) == noErr) { - if(QWidget *w = QWidget::find((WId)hiview)) { -#if 0 - send_to_app = !w->isActiveWindow(); -#else - Q_UNUSED(w); - send_to_app = true; -#endif - } - } - } - } - if(send_to_app) - return SendEventToApplication(event); - handled_event = false; - break; } - -#ifndef QT_NO_GESTURES - case kEventClassGesture: { - // First, find the widget that was under - // the mouse when the gesture happened: - HIPoint screenLocation; - if (GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, 0, - sizeof(screenLocation), 0, &screenLocation) != noErr) { - handled_event = false; - break; - } - QWidget *widget = QApplication::widgetAt(screenLocation.x, screenLocation.y); - if (!widget) { - handled_event = false; - break; - } - - QNativeGestureEvent qNGEvent; - qNGEvent.position = QPoint(screenLocation.x, screenLocation.y); - - switch (ekind) { - case kEventGestureStarted: - qNGEvent.gestureType = QNativeGestureEvent::GestureBegin; - break; - case kEventGestureEnded: - qNGEvent.gestureType = QNativeGestureEvent::GestureEnd; - break; - case kEventGestureRotate: { - CGFloat amount; - if (GetEventParameter(event, kEventParamRotationAmount, 'cgfl', 0, - sizeof(amount), 0, &amount) != noErr) { - handled_event = false; - break; - } - qNGEvent.gestureType = QNativeGestureEvent::Rotate; - qNGEvent.percentage = float(-amount); - break; } - case kEventGestureSwipe: { - HIPoint swipeDirection; - if (GetEventParameter(event, kEventParamSwipeDirection, typeHIPoint, 0, - sizeof(swipeDirection), 0, &swipeDirection) != noErr) { - handled_event = false; - break; - } - qNGEvent.gestureType = QNativeGestureEvent::Swipe; - if (swipeDirection.x == 1) - qNGEvent.angle = 180.0f; - else if (swipeDirection.x == -1) - qNGEvent.angle = 0.0f; - else if (swipeDirection.y == 1) - qNGEvent.angle = 90.0f; - else if (swipeDirection.y == -1) - qNGEvent.angle = 270.0f; - break; } - case kEventGestureMagnify: { - CGFloat amount; - if (GetEventParameter(event, kEventParamMagnificationAmount, 'cgfl', 0, - sizeof(amount), 0, &amount) != noErr) { - handled_event = false; - break; - } - qNGEvent.gestureType = QNativeGestureEvent::Zoom; - qNGEvent.percentage = float(amount); - break; } - } - - QApplication::sendSpontaneousEvent(widget, &qNGEvent); - break; } -#endif // QT_NO_GESTURES - - default: - handled_event = false; - } - if(!handled_event) //let the event go through - return eventNotHandledErr; - return noErr; //we eat the event -} - -// widget events -static HIObjectClassRef widget_class = 0; -static EventTypeSpec widget_events[] = { - { kEventClassHIObject, kEventHIObjectConstruct }, - { kEventClassHIObject, kEventHIObjectDestruct }, - - { kEventClassControl, kEventControlDraw }, - { kEventClassControl, kEventControlInitialize }, - { kEventClassControl, kEventControlGetPartRegion }, - { kEventClassControl, kEventControlGetClickActivation }, - { kEventClassControl, kEventControlSetFocusPart }, - { kEventClassControl, kEventControlDragEnter }, - { kEventClassControl, kEventControlDragWithin }, - { kEventClassControl, kEventControlDragLeave }, - { kEventClassControl, kEventControlDragReceive }, - { kEventClassControl, kEventControlOwningWindowChanged }, - { kEventClassControl, kEventControlBoundsChanged }, - { kEventClassControl, kEventControlGetSizeConstraints }, - { kEventClassControl, kEventControlVisibilityChanged }, - - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseMoved }, - { kEventClassMouse, kEventMouseDragged } -}; -static EventHandlerUPP mac_widget_eventUPP = 0; -static void cleanup_widget_eventUPP() -{ - DisposeEventHandlerUPP(mac_widget_eventUPP); - mac_widget_eventUPP = 0; -} -static const EventHandlerUPP make_widget_eventUPP() -{ - if(mac_widget_eventUPP) - return mac_widget_eventUPP; - qAddPostRoutine(cleanup_widget_eventUPP); - return mac_widget_eventUPP = NewEventHandlerUPP(QWidgetPrivate::qt_widget_event); -} -OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, void *) -{ - QScopedLoopLevelCounter loopLevelCounter(QApplicationPrivate::instance()->threadData); - - bool handled_event = true; - UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event); - switch(eclass) { - case kEventClassHIObject: { - HIViewRef view = 0; - GetEventParameter(event, kEventParamHIObjectInstance, typeHIObjectRef, - 0, sizeof(view), 0, &view); - if(ekind == kEventHIObjectConstruct) { - if(view) { - HIViewChangeFeatures(view, kHIViewAllowsSubviews, 0); - SetEventParameter(event, kEventParamHIObjectInstance, - typeVoidPtr, sizeof(view), &view); - } - } else if(ekind == kEventHIObjectDestruct) { - //nothing to really do.. or is there? - } else { - handled_event = false; - } - break; } - case kEventClassControl: { - QWidget *widget = 0; - HIViewRef hiview = 0; - if(GetEventParameter(event, kEventParamDirectObject, typeControlRef, - 0, sizeof(hiview), 0, &hiview) == noErr) - widget = QWidget::find((WId)hiview); - if (widget && widget->macEvent(er, event)) - return noErr; - if(ekind == kEventControlDraw) { - if(widget && qt_isGenuineQWidget(hiview)) { - - // if there is a window change event pending for any gl child wigets, - // send it immediately. (required for flicker-free resizing) - extern void qt_mac_send_posted_gl_updates(QWidget *widget); - qt_mac_send_posted_gl_updates(widget); - - if (QApplicationPrivate::graphicsSystem() && !widget->d_func()->paintOnScreen()) { - widget->d_func()->syncBackingStore(); - widget->d_func()->dirtyOnWidget = QRegion(); - return noErr; - } - - //requested rgn - RgnHandle rgn; - GetEventParameter(event, kEventParamRgnHandle, typeQDRgnHandle, 0, sizeof(rgn), 0, &rgn); - QRegion qrgn(qt_mac_convert_mac_region(rgn)); - - //update handles - GrafPtr qd = 0; - CGContextRef cg = 0; - if(GetEventParameter(event, kEventParamCGContextRef, typeCGContextRef, 0, sizeof(cg), 0, &cg) != noErr) { - Q_ASSERT(false); - } - widget->d_func()->hd = cg; - widget->d_func()->qd_hd = qd; - CGContextSaveGState(cg); - -#ifdef DEBUG_WIDGET_PAINT - const bool doDebug = true; - if(doDebug) { - qDebug("asked to draw %p[%p] [%s::%s] %p[%p] [%d] [%dx%d]", widget, hiview, widget->metaObject()->className(), - widget->objectName().local8Bit().data(), widget->parentWidget(), - (HIViewRef)(widget->parentWidget() ? qt_mac_nativeview_for(widget->parentWidget()) : (HIViewRef)0), - HIViewIsCompositingEnabled(hiview), qt_mac_posInWindow(widget).x(), qt_mac_posInWindow(widget).y()); -#if 0 - QVector<QRect> region_rects = qrgn.rects(); - qDebug("Region! %d", region_rects.count()); - for(int i = 0; i < region_rects.count(); i++) - qDebug("%d %d %d %d", region_rects[i].x(), region_rects[i].y(), - region_rects[i].width(), region_rects[i].height()); - region_rects = widget->d_func()->clp.rects(); - qDebug("Widget Region! %d", region_rects.count()); - for(int i = 0; i < region_rects.count(); i++) - qDebug("%d %d %d %d", region_rects[i].x(), region_rects[i].y(), - region_rects[i].width(), region_rects[i].height()); -#endif - } -#endif - if (widget->isVisible() && widget->updatesEnabled()) { //process the actual paint event. - if(widget->testAttribute(Qt::WA_WState_InPaintEvent)) - qWarning("QWidget::repaint: Recursive repaint detected"); - if (widget->isWindow() && !widget->d_func()->isOpaque - && !widget->testAttribute(Qt::WA_MacBrushedMetal)) { - QRect qrgnRect = qrgn.boundingRect(); - CGContextClearRect(cg, CGRectMake(qrgnRect.x(), qrgnRect.y(), qrgnRect.width(), qrgnRect.height())); - } - - QPoint redirectionOffset(0, 0); - QWidget *tl = widget->window(); - if (tl) { - Qt::WindowFlags flags = tl->windowFlags(); - if (flags & Qt::FramelessWindowHint - || (flags & Qt::CustomizeWindowHint && !(flags & Qt::WindowTitleHint))) { - if(tl->d_func()->extra && !tl->d_func()->extra->mask.isEmpty()) - redirectionOffset += tl->d_func()->extra->mask.boundingRect().topLeft(); - } - } - - //setup the context - widget->setAttribute(Qt::WA_WState_InPaintEvent); - QPaintEngine *engine = widget->paintEngine(); - if (engine) - engine->setSystemClip(qrgn); - - //handle the erase - if (engine && (!widget->testAttribute(Qt::WA_NoSystemBackground) - && (widget->isWindow() || widget->autoFillBackground()) - || widget->testAttribute(Qt::WA_TintedBackground) - || widget->testAttribute(Qt::WA_StyledBackground))) { -#ifdef DEBUG_WIDGET_PAINT - if(doDebug) - qDebug(" Handling erase for [%s::%s]", widget->metaObject()->className(), - widget->objectName().local8Bit().data()); -#endif - if (!redirectionOffset.isNull()) - widget->d_func()->setRedirected(widget, redirectionOffset); - - bool was_unclipped = widget->testAttribute(Qt::WA_PaintUnclipped); - widget->setAttribute(Qt::WA_PaintUnclipped, false); - QPainter p(widget); - p.setClipping(false); - if(was_unclipped) - widget->setAttribute(Qt::WA_PaintUnclipped); - widget->d_func()->paintBackground(&p, qrgn, widget->isWindow() ? DrawAsRoot : 0); - if (widget->testAttribute(Qt::WA_TintedBackground)) { - QColor tint = widget->palette().window().color(); - tint.setAlphaF(.6); - const QVector<QRect> &rects = qrgn.rects(); - for (int i = 0; i < rects.size(); ++i) - p.fillRect(rects.at(i), tint); - } - p.end(); - if (!redirectionOffset.isNull()) - widget->d_func()->restoreRedirected(); - } - - if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) - CallNextEventHandler(er, event); - - //send the paint - redirectionOffset += widget->data->wrect.topLeft(); // Map from system to qt coordinates - if (!redirectionOffset.isNull()) - widget->d_func()->setRedirected(widget, redirectionOffset); - qrgn.translate(redirectionOffset); - QPaintEvent e(qrgn); - widget->d_func()->dirtyOnWidget = QRegion(); -#ifdef QT3_SUPPORT - e.setErased(true); -#endif - QApplication::sendSpontaneousEvent(widget, &e); - if (!redirectionOffset.isNull()) - widget->d_func()->restoreRedirected(); - - //cleanup - if (engine) - engine->setSystemClip(QRegion()); - - widget->setAttribute(Qt::WA_WState_InPaintEvent, false); - if(!widget->testAttribute(Qt::WA_PaintOutsidePaintEvent) && widget->paintingActive()) - qWarning("QWidget: It is dangerous to leave painters active on a widget outside of the PaintEvent"); - } - - widget->d_func()->hd = 0; - widget->d_func()->qd_hd = 0; - CGContextRestoreGState(cg); - } else if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) { - CallNextEventHandler(er, event); - } - } else if(ekind == kEventControlInitialize) { - if(HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) { - UInt32 features = kControlSupportsDragAndDrop | kControlSupportsClickActivation | kControlSupportsFocus; - SetEventParameter(event, kEventParamControlFeatures, typeUInt32, sizeof(features), &features); - } else { - handled_event = false; - } - } else if(ekind == kEventControlSetFocusPart) { - if(widget) { - ControlPartCode part; - GetEventParameter(event, kEventParamControlPart, typeControlPartCode, 0, - sizeof(part), 0, &part); - if(part == kControlFocusNoPart){ - if (widget->hasFocus()) - QApplicationPrivate::setFocusWidget(0, Qt::OtherFocusReason); - } else - widget->setFocus(); - } - if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) - CallNextEventHandler(er, event); - } else if(ekind == kEventControlGetClickActivation) { - ClickActivationResult clickT = kActivateAndIgnoreClick; - SetEventParameter(event, kEventParamClickActivation, typeClickActivationResult, - sizeof(clickT), &clickT); - } else if(ekind == kEventControlGetPartRegion) { - handled_event = false; - if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget) && CallNextEventHandler(er, event) == noErr) { - handled_event = true; - break; - } - if(widget && !widget->isWindow()) { - ControlPartCode part; - GetEventParameter(event, kEventParamControlPart, typeControlPartCode, 0, - sizeof(part), 0, &part); - if(part == kControlClickableMetaPart && widget->testAttribute(Qt::WA_TransparentForMouseEvents)) { - RgnHandle rgn; - GetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, 0, - sizeof(rgn), 0, &rgn); - SetEmptyRgn(rgn); - handled_event = true; - } else if(part == kControlStructureMetaPart || part == kControlClickableMetaPart) { - RgnHandle rgn; - GetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, 0, - sizeof(rgn), 0, &rgn); - SetRectRgn(rgn, 0, 0, widget->width(), widget->height()); - if(QWidgetPrivate::qt_widget_rgn(widget, kWindowStructureRgn, rgn, false)) - handled_event = true; - } else if(part == kControlOpaqueMetaPart) { - if(widget->d_func()->isOpaque) { - RgnHandle rgn; - GetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, 0, - sizeof(RgnHandle), 0, &rgn); - SetRectRgn(rgn, 0, 0, widget->width(), widget->height()); - QWidgetPrivate::qt_widget_rgn(widget, kWindowStructureRgn, rgn, false); - SetEventParameter(event, kEventParamControlRegion, typeQDRgnHandle, - sizeof(RgnHandle), &rgn); - handled_event = true; - } - } - } - } else if(ekind == kEventControlOwningWindowChanged) { - if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) - CallNextEventHandler(er, event); - if(widget && qt_mac_window_for(hiview)) { - WindowRef foo = 0; - GetEventParameter(event, kEventParamControlCurrentOwningWindow, typeWindowRef, 0, - sizeof(foo), 0, &foo); - widget->d_func()->initWindowPtr(); - } - if (widget) - qt_event_request_window_change(widget); - } else if(ekind == kEventControlDragEnter || ekind == kEventControlDragWithin || - ekind == kEventControlDragLeave || ekind == kEventControlDragReceive) { - // dnd are really handled in qdnd_mac.cpp, - // just modularize the code a little... - DragRef drag; - GetEventParameter(event, kEventParamDragRef, typeDragRef, 0, sizeof(drag), 0, &drag); - handled_event = false; - bool drag_allowed = false; - - QWidget *dropWidget = widget; - if (qobject_cast<QFocusFrame *>(widget)){ - // We might shadow widgets underneath the focus - // frame, so stay interrested, and let the dnd through - drag_allowed = true; - handled_event = true; - Point where; - GetDragMouse(drag, &where, 0); - dropWidget = QApplication::widgetAt(QPoint(where.h, where.v)); - - if (dropWidget != QDragManager::self()->currentTarget()) { - // We have to 'fake' enter and leave events for the shaddowed widgets: - if (ekind == kEventControlDragEnter) { - if (QDragManager::self()->currentTarget()) - QDragManager::self()->currentTarget()->d_func()->qt_mac_dnd_event(kEventControlDragLeave, drag); - if (dropWidget) { - dropWidget->d_func()->qt_mac_dnd_event(kEventControlDragEnter, drag); - } - // Set dropWidget to zero, so qt_mac_dnd_event - // doesn't get called a second time below: - dropWidget = 0; - } else if (ekind == kEventControlDragLeave) { - dropWidget = QDragManager::self()->currentTarget(); - if (dropWidget) { - dropWidget->d_func()->qt_mac_dnd_event(kEventControlDragLeave, drag); - } - // Set dropWidget to zero, so qt_mac_dnd_event - // doesn't get called a second time below: - dropWidget = 0; - } - } - } - - // Send the dnd event to the widget: - if (dropWidget && dropWidget->d_func()->qt_mac_dnd_event(ekind, drag)) { - drag_allowed = true; - handled_event = true; - } - - if (ekind == kEventControlDragEnter) { - // If we don't accept the enter event, we will - // receive no more drag events for this widget - const Boolean wouldAccept = drag_allowed ? true : false; - SetEventParameter(event, kEventParamControlWouldAcceptDrop, typeBoolean, - sizeof(wouldAccept), &wouldAccept); - } - } else if (ekind == kEventControlBoundsChanged) { - if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_Moved) || widget->testAttribute(Qt::WA_Resized)) { - handled_event = false; - } else { - // Sync our view in case some other (non-Qt) view is controlling us. - handled_event = true; - Rect newBounds; - GetEventParameter(event, kEventParamCurrentBounds, - typeQDRectangle, 0, sizeof(Rect), 0, &newBounds); - QRect rect(newBounds.left, newBounds.top, - newBounds.right - newBounds.left, newBounds.bottom - newBounds.top); - - bool moved = widget->testAttribute(Qt::WA_Moved); - bool resized = widget->testAttribute(Qt::WA_Resized); - widget->setGeometry(rect); - widget->setAttribute(Qt::WA_Moved, moved); - widget->setAttribute(Qt::WA_Resized, resized); - qt_event_request_window_change(widget); - } - } else if (ekind == kEventControlGetSizeConstraints) { - if (!widget || !qt_isGenuineQWidget(widget)) { - handled_event = false; - } else { - handled_event = true; - QWidgetItem item(widget); - QSize size = item.minimumSize(); - HISize hisize = { size.width(), size.height() }; - SetEventParameter(event, kEventParamMinimumSize, typeHISize, sizeof(HISize), &hisize); - size = item.maximumSize(); - hisize.width = size.width() + 2; // ### shouldn't have to add 2 (but it works). - hisize.height = size.height(); - SetEventParameter(event, kEventParamMaximumSize, typeHISize, sizeof(HISize), &hisize); - } - } else if (ekind == kEventControlVisibilityChanged) { - handled_event = false; - if (widget) { - qt_event_request_window_change(widget); - if (!HIViewIsVisible(HIViewRef(widget->winId()))) { - if (widget == qt_button_down) - qt_button_down = 0; - } - } - } - break; } - case kEventClassMouse: { - bool send_to_app = false; - if(qt_button_down) - send_to_app = true; - if(send_to_app) { - OSStatus err = SendEventToApplication(event); - if(err != noErr) - handled_event = false; - } else { - CallNextEventHandler(er, event); - } - break; } - default: - handled_event = false; - break; - } - if(!handled_event) //let the event go through - return eventNotHandledErr; - return noErr; //we eat the event -} -#endif - -OSViewRef qt_mac_create_widget(QWidget *widget, QWidgetPrivate *widgetPrivate, OSViewRef parent) -{ -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - QT_MANGLE_NAMESPACE(QCocoaView) *view = [[QT_MANGLE_NAMESPACE(QCocoaView) alloc] initWithQWidget:widget widgetPrivate:widgetPrivate]; - -#ifdef ALIEN_DEBUG - qDebug() << "Creating NSView for" << widget; -#endif - - if (view && parent) - [parent addSubview:view]; - return view; -#else - Q_UNUSED(widget); - Q_UNUSED(widgetPrivate); - if(!widget_class) { - OSStatus err = HIObjectRegisterSubclass(kObjectQWidget, kHIViewClassID, 0, make_widget_eventUPP(), - GetEventTypeCount(widget_events), widget_events, - 0, &widget_class); - if (err && err != hiObjectClassExistsErr) - qWarning("QWidget: Internal error (%d)", __LINE__); - } - HIViewRef ret = 0; - if(HIObjectCreate(kObjectQWidget, 0, (HIObjectRef*)&ret) != noErr) - qWarning("QWidget: Internal error (%d)", __LINE__); - if(ret && parent) - HIViewAddSubview(parent, ret); - return ret; -#endif -} - -void qt_mac_unregister_widget() -{ -#ifndef QT_MAC_USE_COCOA - HIObjectUnregisterClass(widget_class); - widget_class = 0; -#endif -} - -void QWidgetPrivate::toggleDrawers(bool visible) -{ - for (int i = 0; i < children.size(); ++i) { - register QObject *object = children.at(i); - if (!object->isWidgetType()) - continue; - QWidget *widget = static_cast<QWidget*>(object); - if(qt_mac_is_macdrawer(widget)) { - bool oldState = widget->testAttribute(Qt::WA_WState_ExplicitShowHide); - if(visible) { - if (!widget->testAttribute(Qt::WA_WState_ExplicitShowHide)) - widget->show(); - } else { - widget->hide(); - if(!oldState) - widget->setAttribute(Qt::WA_WState_ExplicitShowHide, false); - } - } - } -} - -/***************************************************************************** - QWidgetPrivate member functions - *****************************************************************************/ -bool QWidgetPrivate::qt_mac_update_sizer(QWidget *w, int up) -{ - // I'm not sure what "up" is - if(!w || !w->isWindow()) - return false; - - QTLWExtra *topData = w->d_func()->topData(); - QWExtra *extraData = w->d_func()->extraData(); - // topData->resizer is only 4 bits, so subtracting -1 from zero causes bad stuff - // to happen, prevent that here (you really want the thing hidden). - if (up >= 0 || topData->resizer != 0) - topData->resizer += up; - OSWindowRef windowRef = qt_mac_window_for(OSViewRef(w->effectiveWinId())); - { -#ifndef QT_MAC_USE_COCOA - WindowClass wclass; - GetWindowClass(windowRef, &wclass); - if(!(GetAvailableWindowAttributes(wclass) & kWindowResizableAttribute)) - return true; -#endif - } - bool remove_grip = (topData->resizer || (w->windowFlags() & Qt::FramelessWindowHint) - || (extraData->maxw && extraData->maxh && - extraData->maxw == extraData->minw && extraData->maxh == extraData->minh)); -#ifndef QT_MAC_USE_COCOA - WindowAttributes attr; - GetWindowAttributes(windowRef, &attr); - if(remove_grip) { - if(attr & kWindowResizableAttribute) { - ChangeWindowAttributes(qt_mac_window_for(w), kWindowNoAttributes, - kWindowResizableAttribute); - ReshapeCustomWindow(qt_mac_window_for(w)); - } - } else if(!(attr & kWindowResizableAttribute)) { - ChangeWindowAttributes(windowRef, kWindowResizableAttribute, - kWindowNoAttributes); - ReshapeCustomWindow(windowRef); - } -#else - [windowRef setShowsResizeIndicator:!remove_grip]; -#endif - return true; -} - -void QWidgetPrivate::qt_clean_root_win() -{ -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - [qt_root_win release]; -#else - if(!qt_root_win) - return; - CFRelease(qt_root_win); -#endif - qt_root_win = 0; -} - -bool QWidgetPrivate::qt_create_root_win() -{ - if(qt_root_win) - return false; - const QSize desktopSize = qt_mac_desktopSize(); - QRect desktopRect(QPoint(0, 0), desktopSize); -#ifdef QT_MAC_USE_COCOA - qt_root_win = qt_mac_create_window(0, kOverlayWindowClass, NSBorderlessWindowMask, desktopRect); -#else - WindowAttributes wattr = (kWindowCompositingAttribute | kWindowStandardHandlerAttribute); - qt_root_win = qt_mac_create_window(0, kOverlayWindowClass, wattr, desktopRect); -#endif - if(!qt_root_win) - return false; - qAddPostRoutine(qt_clean_root_win); - return true; -} - -bool QWidgetPrivate::qt_widget_rgn(QWidget *widget, short wcode, RgnHandle rgn, bool force = false) -{ - bool ret = false; -#ifndef QT_MAC_USE_COCOA - switch(wcode) { - case kWindowStructureRgn: { - if(widget) { - if(widget->d_func()->extra && !widget->d_func()->extra->mask.isEmpty()) { - QRegion rin = qt_mac_convert_mac_region(rgn); - if(!rin.isEmpty()) { - QPoint rin_tl = rin.boundingRect().topLeft(); //in offset - rin.translate(-rin_tl.x(), -rin_tl.y()); //bring into same space as below - QRegion mask = widget->d_func()->extra->mask; - Qt::WindowFlags flags = widget->windowFlags(); - if(widget->isWindow() - && !(flags & Qt::FramelessWindowHint - || (flags & Qt::CustomizeWindowHint && !(flags & Qt::WindowTitleHint)))) { - QRegion title; - { - QMacSmartQuickDrawRegion rgn(qt_mac_get_rgn()); - GetWindowRegion(qt_mac_window_for(widget), kWindowTitleBarRgn, rgn); - title = qt_mac_convert_mac_region(rgn); - } - QRect br = title.boundingRect(); - mask.translate(0, br.height()); //put the mask 'under' the title bar.. - title.translate(-br.x(), -br.y()); - mask += title; - } - - QRegion cr = rin & mask; - cr.translate(rin_tl.x(), rin_tl.y()); //translate back to incoming space - CopyRgn(QMacSmartQuickDrawRegion(cr.toQDRgn()), rgn); - } - ret = true; - } else if(force) { - QRegion cr(widget->geometry()); - CopyRgn(QMacSmartQuickDrawRegion(cr.toQDRgn()), rgn); - ret = true; - } - } - break; } - default: break; - } - //qDebug() << widget << ret << wcode << qt_mac_convert_mac_region(rgn); -#else - Q_UNUSED(widget); - Q_UNUSED(wcode); - Q_UNUSED(rgn); - Q_UNUSED(force); -#endif - return ret; -} - -/***************************************************************************** - QWidget member functions - *****************************************************************************/ -void QWidgetPrivate::determineWindowClass() -{ - Q_Q(QWidget); -#if !defined(QT_NO_MAINWINDOW) && !defined(QT_NO_TOOLBAR) - // Make sure that QMainWindow has the MacWindowToolBarButtonHint when the - // unifiedTitleAndToolBarOnMac property is ON. This is to avoid reentry of - // setParent() triggered by the QToolBar::event(QEvent::ParentChange). - QMainWindow *mainWindow = qobject_cast<QMainWindow *>(q); - if (mainWindow && mainWindow->unifiedTitleAndToolBarOnMac()) { - data.window_flags |= Qt::MacWindowToolBarButtonHint; - } -#endif -#ifndef QT_MAC_USE_COCOA -// ### COCOA:Interleave these better! - - const Qt::WindowType type = q->windowType(); - Qt::WindowFlags &flags = data.window_flags; - const bool popup = (type == Qt::Popup); - if (type == Qt::ToolTip || type == Qt::SplashScreen || popup) - flags |= Qt::FramelessWindowHint; - - WindowClass wclass = kSheetWindowClass; - if(qt_mac_is_macdrawer(q)) - wclass = kDrawerWindowClass; - else if (q->testAttribute(Qt::WA_ShowModal) && flags & Qt::CustomizeWindowHint) - wclass = kDocumentWindowClass; - else if(popup || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && type == Qt::SplashScreen)) - wclass = kModalWindowClass; - else if(q->testAttribute(Qt::WA_ShowModal)) - wclass = kMovableModalWindowClass; - else if(type == Qt::ToolTip) - wclass = kHelpWindowClass; - else if(type == Qt::Tool || (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5 - && type == Qt::SplashScreen)) - wclass = kFloatingWindowClass; - else - wclass = kDocumentWindowClass; - - WindowGroupRef grp = 0; - WindowAttributes wattr = (kWindowCompositingAttribute | kWindowStandardHandlerAttribute); - if (q->testAttribute(Qt::WA_MacFrameworkScaled)) - wattr |= kWindowFrameworkScaledAttribute; - if(qt_mac_is_macsheet(q)) { - //grp = GetWindowGroupOfClass(kMovableModalWindowClass); - wclass = kSheetWindowClass; - } else { - grp = GetWindowGroupOfClass(wclass); - // Shift things around a bit to get the correct window class based on the presence - // (or lack) of the border. - bool customize = flags & Qt::CustomizeWindowHint; - bool framelessWindow = (flags & Qt::FramelessWindowHint || (customize && !(flags & Qt::WindowTitleHint))); - if (framelessWindow) { - if(wclass == kDocumentWindowClass) { - wattr |= kWindowNoTitleBarAttribute; - } else if(wclass == kFloatingWindowClass) { - wattr |= kWindowNoTitleBarAttribute; - } else if (wclass == kMovableModalWindowClass) { - wclass = kModalWindowClass; - } - } else { - if(wclass != kModalWindowClass) - wattr |= kWindowResizableAttribute; - } - // Only add extra decorations (well, buttons) for widgets that can have them - // and have an actual border we can put them on. - if(wclass != kModalWindowClass && wclass != kMovableModalWindowClass - && wclass != kSheetWindowClass && wclass != kPlainWindowClass - && !framelessWindow && wclass != kDrawerWindowClass - && wclass != kHelpWindowClass) { - if (flags & Qt::WindowMaximizeButtonHint) - wattr |= kWindowFullZoomAttribute; - if (flags & Qt::WindowMinimizeButtonHint) - wattr |= kWindowCollapseBoxAttribute; - if (flags & Qt::WindowSystemMenuHint || flags & Qt::WindowCloseButtonHint) - wattr |= kWindowCloseBoxAttribute; - if (flags & Qt::MacWindowToolBarButtonHint) - wattr |= kWindowToolbarButtonAttribute; - } else { - // Clear these hints so that we aren't call them on invalid windows - flags &= ~(Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint - | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint); - } - } - if((popup || type == Qt::Tool) && !q->isModal()) - wattr |= kWindowHideOnSuspendAttribute; - wattr |= kWindowLiveResizeAttribute; - -#ifdef DEBUG_WINDOW_CREATE -#define ADD_DEBUG_WINDOW_NAME(x) { x, #x } - struct { - UInt32 tag; - const char *name; - } known_attribs[] = { - ADD_DEBUG_WINDOW_NAME(kWindowCompositingAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowMetalAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowCollapseBoxAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowHorizontalZoomAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowVerticalZoomAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowResizableAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowNoActivatesAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowNoUpdatesAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowOpaqueForEventsAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowLiveResizeAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowCloseBoxAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute), - { 0, 0 } - }, known_classes[] = { - ADD_DEBUG_WINDOW_NAME(kHelpWindowClass), - ADD_DEBUG_WINDOW_NAME(kPlainWindowClass), - ADD_DEBUG_WINDOW_NAME(kDrawerWindowClass), - ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass), - ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass), - ADD_DEBUG_WINDOW_NAME(kSheetWindowClass), - ADD_DEBUG_WINDOW_NAME(kFloatingWindowClass), - ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass), - ADD_DEBUG_WINDOW_NAME(kDocumentWindowClass), - ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass), - ADD_DEBUG_WINDOW_NAME(kMovableModalWindowClass), - ADD_DEBUG_WINDOW_NAME(kModalWindowClass), - { 0, 0 } - }; - qDebug("Qt: internal: ************* Creating new window %p (%s::%s)", q, q->metaObject()->className(), - q->objectName().toLocal8Bit().constData()); - bool found_class = false; - for(int i = 0; known_classes[i].name; i++) { - if(wclass == known_classes[i].tag) { - found_class = true; - qDebug("Qt: internal: ** Class: %s", known_classes[i].name); - break; - } - } - if(!found_class) - qDebug("Qt: internal: !! Class: Unknown! (%d)", (int)wclass); - if(wattr) { - WindowAttributes tmp_wattr = wattr; - qDebug("Qt: internal: ** Attributes:"); - for(int i = 0; tmp_wattr && known_attribs[i].name; i++) { - if((tmp_wattr & known_attribs[i].tag) == known_attribs[i].tag) { - tmp_wattr ^= known_attribs[i].tag; - qDebug("Qt: internal: * %s %s", known_attribs[i].name, - (GetAvailableWindowAttributes(wclass) & known_attribs[i].tag) ? "" : "(*)"); - } - } - if(tmp_wattr) - qDebug("Qt: internal: !! Attributes: Unknown (%d)", (int)tmp_wattr); - } -#endif - - /* Just to be extra careful we will change to the kUtilityWindowClass if the - requested attributes cannot be used */ - if((GetAvailableWindowAttributes(wclass) & wattr) != wattr) { - WindowClass tmp_class = wclass; - if(wclass == kToolbarWindowClass || wclass == kUtilityWindowClass) - wclass = kFloatingWindowClass; - if(tmp_class != wclass) { - if(!grp) - grp = GetWindowGroupOfClass(wclass); - wclass = tmp_class; - } - } - topData()->wclass = wclass; - topData()->wattr = wattr; -#else - const Qt::WindowType type = q->windowType(); - Qt::WindowFlags &flags = data.window_flags; - const bool popup = (type == Qt::Popup); - if (type == Qt::ToolTip || type == Qt::SplashScreen || popup) - flags |= Qt::FramelessWindowHint; - - WindowClass wclass = kSheetWindowClass; - if(qt_mac_is_macdrawer(q)) - wclass = kDrawerWindowClass; - else if (q->testAttribute(Qt::WA_ShowModal) && flags & Qt::CustomizeWindowHint) - wclass = kDocumentWindowClass; - else if(popup || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && type == Qt::SplashScreen)) - wclass = kModalWindowClass; - else if(type == Qt::Dialog) - wclass = kMovableModalWindowClass; - else if(type == Qt::ToolTip) - wclass = kHelpWindowClass; - else if(type == Qt::Tool || (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5 - && type == Qt::SplashScreen)) - wclass = kFloatingWindowClass; - else if(q->testAttribute(Qt::WA_ShowModal)) - wclass = kMovableModalWindowClass; - else - wclass = kDocumentWindowClass; - - WindowAttributes wattr = NSBorderlessWindowMask; - if(qt_mac_is_macsheet(q)) { - //grp = GetWindowGroupOfClass(kMovableModalWindowClass); - wclass = kSheetWindowClass; - wattr = NSTitledWindowMask | NSResizableWindowMask; - } else { -#ifndef QT_MAC_USE_COCOA - grp = GetWindowGroupOfClass(wclass); -#endif - // Shift things around a bit to get the correct window class based on the presence - // (or lack) of the border. - bool customize = flags & Qt::CustomizeWindowHint; - bool framelessWindow = (flags & Qt::FramelessWindowHint || (customize && !(flags & Qt::WindowTitleHint))); - if (framelessWindow) { - if (wclass == kDocumentWindowClass) { - wclass = kSimpleWindowClass; - } else if (wclass == kFloatingWindowClass) { - wclass = kToolbarWindowClass; - } else if (wclass == kMovableModalWindowClass) { - wclass = kModalWindowClass; - } - } else { - wattr |= NSTitledWindowMask; - if (wclass != kModalWindowClass) - wattr |= NSResizableWindowMask; - } - // Only add extra decorations (well, buttons) for widgets that can have them - // and have an actual border we can put them on. - if (wclass != kModalWindowClass - && wclass != kSheetWindowClass && wclass != kPlainWindowClass - && !framelessWindow && wclass != kDrawerWindowClass - && wclass != kHelpWindowClass) { - if (flags & Qt::WindowMinimizeButtonHint) - wattr |= NSMiniaturizableWindowMask; - if (flags & Qt::WindowSystemMenuHint || flags & Qt::WindowCloseButtonHint) - wattr |= NSClosableWindowMask; - } else { - // Clear these hints so that we aren't call them on invalid windows - flags &= ~(Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint - | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint); - } - } - if (q->testAttribute(Qt::WA_MacBrushedMetal)) - wattr |= NSTexturedBackgroundWindowMask; - -#ifdef DEBUG_WINDOW_CREATE -#define ADD_DEBUG_WINDOW_NAME(x) { x, #x } - struct { - UInt32 tag; - const char *name; - } known_attribs[] = { - ADD_DEBUG_WINDOW_NAME(kWindowCompositingAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowMetalAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowStandardHandlerAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowCollapseBoxAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowHorizontalZoomAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowVerticalZoomAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowResizableAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowNoActivatesAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowNoUpdatesAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowOpaqueForEventsAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowLiveResizeAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowCloseBoxAttribute), - ADD_DEBUG_WINDOW_NAME(kWindowHideOnSuspendAttribute), - { 0, 0 } - }, known_classes[] = { - ADD_DEBUG_WINDOW_NAME(kHelpWindowClass), - ADD_DEBUG_WINDOW_NAME(kPlainWindowClass), - ADD_DEBUG_WINDOW_NAME(kDrawerWindowClass), - ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass), - ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass), - ADD_DEBUG_WINDOW_NAME(kSheetWindowClass), - ADD_DEBUG_WINDOW_NAME(kFloatingWindowClass), - ADD_DEBUG_WINDOW_NAME(kUtilityWindowClass), - ADD_DEBUG_WINDOW_NAME(kDocumentWindowClass), - ADD_DEBUG_WINDOW_NAME(kToolbarWindowClass), - ADD_DEBUG_WINDOW_NAME(kMovableModalWindowClass), - ADD_DEBUG_WINDOW_NAME(kModalWindowClass), - { 0, 0 } - }; - qDebug("Qt: internal: ************* Creating new window %p (%s::%s)", q, q->metaObject()->className(), - q->objectName().toLocal8Bit().constData()); - bool found_class = false; - for(int i = 0; known_classes[i].name; i++) { - if(wclass == known_classes[i].tag) { - found_class = true; - qDebug("Qt: internal: ** Class: %s", known_classes[i].name); - break; - } - } - if(!found_class) - qDebug("Qt: internal: !! Class: Unknown! (%d)", (int)wclass); - if(wattr) { - WindowAttributes tmp_wattr = wattr; - qDebug("Qt: internal: ** Attributes:"); - for(int i = 0; tmp_wattr && known_attribs[i].name; i++) { - if((tmp_wattr & known_attribs[i].tag) == known_attribs[i].tag) { - tmp_wattr ^= known_attribs[i].tag; - } - } - if(tmp_wattr) - qDebug("Qt: internal: !! Attributes: Unknown (%d)", (int)tmp_wattr); - } -#endif - -#ifndef QT_MAC_USE_COCOA - /* Just to be extra careful we will change to the kUtilityWindowClass if the - requested attributes cannot be used */ - if((GetAvailableWindowAttributes(wclass) & wattr) != wattr) { - WindowClass tmp_class = wclass; - if(wclass == kToolbarWindowClass || wclass == kUtilityWindowClass) - wclass = kFloatingWindowClass; - if(tmp_class != wclass) { - if(!grp) - grp = GetWindowGroupOfClass(wclass); - wclass = tmp_class; - } - } -#endif -#endif - topData()->wclass = wclass; - topData()->wattr = wattr; -} - -#ifndef QT_MAC_USE_COCOA // This is handled in Cocoa via our category. -void QWidgetPrivate::initWindowPtr() -{ - Q_Q(QWidget); - OSWindowRef windowRef = qt_mac_window_for(qt_mac_nativeview_for(q)); //do not create! - if(!windowRef) - return; - QWidget *window = q->window(), *oldWindow = 0; - if(GetWindowProperty(windowRef, kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(oldWindow), 0, &oldWindow) == noErr) { - Q_ASSERT(window == oldWindow); - return; - } - - if(SetWindowProperty(windowRef, kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(window), &window) != noErr) - qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__); //no real way to recover - if(!q->windowType() != Qt::Desktop) { //setup an event callback handler on the window - InstallWindowEventHandler(windowRef, make_win_eventUPP(), GetEventTypeCount(window_events), - window_events, static_cast<void *>(qApp), &window_event); - } -} - -void QWidgetPrivate::finishCreateWindow_sys_Carbon(OSWindowRef windowRef) -{ - Q_Q(QWidget); - const Qt::WindowType type = q->windowType(); - Qt::WindowFlags &flags = data.window_flags; - QWidget *parentWidget = q->parentWidget(); - - const bool desktop = (type == Qt::Desktop); - const bool dialog = (type == Qt::Dialog - || type == Qt::Sheet - || type == Qt::Drawer - || (flags & Qt::MSWindowsFixedSizeDialogHint)); - QTLWExtra *topExtra = topData(); - quint32 wattr = topExtra->wattr; - if (!desktop) - SetAutomaticControlDragTrackingEnabledForWindow(windowRef, true); - HIWindowChangeFeatures(windowRef, kWindowCanCollapse, 0); - if (wattr & kWindowHideOnSuspendAttribute) - HIWindowChangeAvailability(windowRef, kHIWindowExposeHidden, 0); - else - HIWindowChangeAvailability(windowRef, 0, kHIWindowExposeHidden); - if ((flags & Qt::WindowStaysOnTopHint)) - ChangeWindowAttributes(windowRef, kWindowNoAttributes, kWindowHideOnSuspendAttribute); - if (qt_mac_is_macdrawer(q) && parentWidget) - SetDrawerParent(windowRef, qt_mac_window_for (parentWidget)); - if (topExtra->group) { - qt_mac_release_window_group(topExtra->group); - topExtra->group = 0; - } - if (type == Qt::ToolTip) - qt_mac_set_window_group_to_tooltip(windowRef); - else if (type == Qt::Popup && (flags & Qt::WindowStaysOnTopHint)) - qt_mac_set_window_group_to_popup(windowRef); - else if (flags & Qt::WindowStaysOnTopHint) - qt_mac_set_window_group_to_stays_on_top(windowRef, type); - else if (dialog) - SetWindowGroup(windowRef, GetWindowGroupOfClass(kMovableModalWindowClass)); - -#ifdef DEBUG_WINDOW_CREATE - if (WindowGroupRef grpf = GetWindowGroup(windowRef)) { - QCFString cfname; - CopyWindowGroupName(grpf, &cfname); - SInt32 lvl; - GetWindowGroupLevel(grpf, &lvl); - const char *from = "Default"; - if (topExtra && grpf == topData()->group) - from = "Created"; - else if (grpf == grp) - from = "Copied"; - qDebug("Qt: internal: With window group '%s' [%p] @ %d: %s", - static_cast<QString>(cfname).toLatin1().constData(), grpf, (int)lvl, from); - } else { - qDebug("Qt: internal: No window group!!!"); - } - HIWindowAvailability hi_avail = 0; - if (HIWindowGetAvailability(windowRef, &hi_avail) == noErr) { - struct { - UInt32 tag; - const char *name; - } known_avail[] = { - ADD_DEBUG_WINDOW_NAME(kHIWindowExposeHidden), - { 0, 0 } - }; - qDebug("Qt: internal: ** HIWindowAvailibility:"); - for (int i = 0; hi_avail && known_avail[i].name; i++) { - if ((hi_avail & known_avail[i].tag) == known_avail[i].tag) { - hi_avail ^= known_avail[i].tag; - qDebug("Qt: internal: * %s", known_avail[i].name); - } - } - if (hi_avail) - qDebug("Qt: internal: !! Attributes: Unknown (%d)", (int)hi_avail); - } -#undef ADD_DEBUG_WINDOW_NAME -#endif - if (extra && !extra->mask.isEmpty()) - ReshapeCustomWindow(windowRef); - SetWindowModality(windowRef, kWindowModalityNone, 0); - if (qt_mac_is_macdrawer(q)) - SetDrawerOffsets(windowRef, 0.0, 25.0); - data.fstrut_dirty = true; // when we create a toplevel widget, the frame strut should be dirty - HIViewRef hiview = (HIViewRef)data.winid; - HIViewRef window_hiview = qt_mac_get_contentview_for(windowRef); - if(!hiview) { - hiview = qt_mac_create_widget(q, this, window_hiview); - setWinId((WId)hiview); - } else { - HIViewAddSubview(window_hiview, hiview); - } - if (hiview) { - Rect win_rect; - GetWindowBounds(qt_mac_window_for (window_hiview), kWindowContentRgn, &win_rect); - HIRect bounds = CGRectMake(0, 0, win_rect.right-win_rect.left, win_rect.bottom-win_rect.top); - HIViewSetFrame(hiview, &bounds); - HIViewSetVisible(hiview, true); - if (q->testAttribute(Qt::WA_DropSiteRegistered)) - registerDropSite(true); - transferChildren(); - } - initWindowPtr(); - - if (topExtra->posFromMove) { - updateFrameStrut(); - const QRect &fStrut = frameStrut(); - Rect r; - SetRect(&r, data.crect.left(), data.crect.top(), data.crect.right() + 1, data.crect.bottom() + 1); - SetRect(&r, r.left + fStrut.left(), r.top + fStrut.top(), - (r.left + fStrut.left() + data.crect.width()) - fStrut.right(), - (r.top + fStrut.top() + data.crect.height()) - fStrut.bottom()); - SetWindowBounds(windowRef, kWindowContentRgn, &r); - topExtra->posFromMove = false; - } - - if (q->testAttribute(Qt::WA_WState_WindowOpacitySet)){ - q->setWindowOpacity(topExtra->opacity / 255.0f); - } else if (qt_mac_is_macsheet(q)){ - SetThemeWindowBackground(qt_mac_window_for(q), kThemeBrushSheetBackgroundTransparent, true); - CGFloat alpha = 0; - GetWindowAlpha(qt_mac_window_for(q), &alpha); - if (alpha == 1){ - // For some reason the 'SetThemeWindowBackground' does not seem - // to work. So we do this little hack until it hopefully starts to - // work in newer versions of mac OS. - q->setWindowOpacity(0.95f); - q->setAttribute(Qt::WA_WState_WindowOpacitySet, false); - } - } else{ - // If the window has been recreated after beeing e.g. a sheet, - // make sure that we don't report a faulty opacity: - q->setWindowOpacity(1.0f); - q->setAttribute(Qt::WA_WState_WindowOpacitySet, false); - } - - // Since we only now have a window, sync our state. - macUpdateHideOnSuspend(); - macUpdateOpaqueSizeGrip(); - macUpdateMetalAttribute(); - macUpdateIgnoreMouseEvents(); - setWindowTitle_helper(extra->topextra->caption); - setWindowIconText_helper(extra->topextra->iconText); - setWindowFilePath_helper(extra->topextra->filePath); - setWindowModified_sys(q->isWindowModified()); - updateFrameStrut(); - qt_mac_update_sizer(q); - applyMaxAndMinSizeOnWindow(); -} -#else // QT_MAC_USE_COCOA - -void QWidgetPrivate::setWindowLevel() -{ - Q_Q(QWidget); - const QWidget * const windowParent = q->window()->parentWidget(); - const QWidget * const primaryWindow = windowParent ? windowParent->window() : 0; - NSInteger winLevel = -1; - - if (q->windowType() == Qt::Popup) { - winLevel = NSPopUpMenuWindowLevel; - // Popup should be in at least the same level as its parent. - if (primaryWindow) { - OSWindowRef parentRef = qt_mac_window_for(primaryWindow); - winLevel = qMax([parentRef level], winLevel); - } - } else if (q->windowType() == Qt::Tool) { - winLevel = NSFloatingWindowLevel; - } else if (q->windowType() == Qt::Dialog) { - // Correct modality level (NSModalPanelWindowLevel) will be - // set by cocoa when creating a modal session later. - winLevel = NSNormalWindowLevel; - } - - // StayOnTop window should appear above Tool windows. - if (data.window_flags & Qt::WindowStaysOnTopHint) - winLevel = NSPopUpMenuWindowLevel; - // Tooltips should appear above StayOnTop windows. - if (q->windowType() == Qt::ToolTip) - winLevel = NSScreenSaverWindowLevel; - // All other types are Normal level. - if (winLevel == -1) - winLevel = NSNormalWindowLevel; - [qt_mac_window_for(q) setLevel:winLevel]; -} - -void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWindowRef) -{ - Q_Q(QWidget); - QMacCocoaAutoReleasePool pool; - NSWindow *windowRef = static_cast<NSWindow *>(voidWindowRef); - const Qt::WindowType type = q->windowType(); - Qt::WindowFlags &flags = data.window_flags; - QWidget *parentWidget = q->parentWidget(); - - const bool popup = (type == Qt::Popup); - const bool dialog = (type == Qt::Dialog - || type == Qt::Sheet - || type == Qt::Drawer - || (flags & Qt::MSWindowsFixedSizeDialogHint)); - QTLWExtra *topExtra = topData(); - - if ((popup || type == Qt::Tool || type == Qt::ToolTip) && !q->isModal()) { - [windowRef setHidesOnDeactivate:YES]; - } else { - [windowRef setHidesOnDeactivate:NO]; - } - if (q->testAttribute(Qt::WA_MacNoShadow)) - [windowRef setHasShadow:NO]; - else - [windowRef setHasShadow:YES]; - Q_UNUSED(parentWidget); - Q_UNUSED(dialog); - - data.fstrut_dirty = true; // when we create a toplevel widget, the frame strut should be dirty - - OSViewRef nsview = (OSViewRef)data.winid; - if (!nsview) { - nsview = qt_mac_create_widget(q, this, 0); - setWinId(WId(nsview)); - } - [windowRef setContentView:nsview]; - [nsview setHidden:NO]; - transferChildren(); - - // Tell Cocoa explicit that we wan't the view to receive key events - // (regardless of focus policy) because this is how it works on other - // platforms (and in the carbon port): - [windowRef makeFirstResponder:nsview]; - - if (topExtra->posFromMove) { - updateFrameStrut(); - - const QRect &fStrut = frameStrut(); - const QRect &crect = data.crect; - const QRect frameRect(QPoint(crect.left(), crect.top()), - QSize(fStrut.left() + fStrut.right() + crect.width(), - fStrut.top() + fStrut.bottom() + crect.height())); - NSRect cocoaFrameRect = NSMakeRect(frameRect.x(), flipYCoordinate(frameRect.bottom() + 1), - frameRect.width(), frameRect.height()); - [windowRef setFrame:cocoaFrameRect display:NO]; - topExtra->posFromMove = false; - } - - if (q->testAttribute(Qt::WA_WState_WindowOpacitySet)){ - q->setWindowOpacity(topExtra->opacity / 255.0f); - } else if (qt_mac_is_macsheet(q)){ - CGFloat alpha = [qt_mac_window_for(q) alphaValue]; - if (alpha >= 1.0) { - q->setWindowOpacity(0.95f); - q->setAttribute(Qt::WA_WState_WindowOpacitySet, false); - } - } else{ - // If the window has been recreated after beeing e.g. a sheet, - // make sure that we don't report a faulty opacity: - q->setWindowOpacity(1.0f); - q->setAttribute(Qt::WA_WState_WindowOpacitySet, false); - } - - // Its more performant to handle the mouse cursor - // ourselves, expecially when using alien widgets: - [windowRef disableCursorRects]; - - setWindowLevel(); - macUpdateHideOnSuspend(); - macUpdateOpaqueSizeGrip(); - macUpdateIgnoreMouseEvents(); - setWindowTitle_helper(extra->topextra->caption); - setWindowIconText_helper(extra->topextra->iconText); - setWindowModified_sys(q->isWindowModified()); - updateFrameStrut(); - syncCocoaMask(); - macUpdateIsOpaque(); - qt_mac_update_sizer(q); - applyMaxAndMinSizeOnWindow(); -} - -#endif // QT_MAC_USE_COCOA - -/* - Recreates widget window. Useful if immutable - properties for it has changed. - */ -void QWidgetPrivate::recreateMacWindow() -{ - Q_Q(QWidget); - OSViewRef myView = qt_mac_nativeview_for(q); - OSWindowRef oldWindow = qt_mac_window_for(myView); -#ifndef QT_MAC_USE_COCOA - HIViewRemoveFromSuperview(myView); - determineWindowClass(); - createWindow_sys(); - - if (QMainWindowLayout *mwl = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q))) { - mwl->updateHIToolBarStatus(); - } - - if (IsWindowVisible(oldWindow)) - show_sys(); -#else - QMacCocoaAutoReleasePool pool; - [myView removeFromSuperview]; - determineWindowClass(); - createWindow_sys(); - if (NSToolbar *toolbar = [oldWindow toolbar]) { - OSWindowRef newWindow = qt_mac_window_for(myView); - [newWindow setToolbar:toolbar]; - [toolbar setVisible:[toolbar isVisible]]; - } - if ([oldWindow isVisible]){ - if ([oldWindow isSheet]) - [NSApp endSheet:oldWindow]; - [oldWindow orderOut:oldWindow]; - show_sys(); - } -#endif // QT_MAC_USE_COCOA - - // Release the window after creating the new window, because releasing it early - // may cause the app to quit ("close on last window closed attribute") - qt_mac_destructWindow(oldWindow); -} - -void QWidgetPrivate::createWindow_sys() -{ - Q_Q(QWidget); - Qt::WindowFlags &flags = data.window_flags; - QWidget *parentWidget = q->parentWidget(); - - QTLWExtra *topExtra = topData(); - if (topExtra->embedded) - return; // Simply return because this view "is" the top window. - quint32 wattr = topExtra->wattr; - - if(parentWidget && (parentWidget->window()->windowFlags() & Qt::WindowStaysOnTopHint)) // If our parent has Qt::WStyle_StaysOnTop, so must we - flags |= Qt::WindowStaysOnTopHint; - - data.fstrut_dirty = true; - - OSWindowRef windowRef = qt_mac_create_window(q, topExtra->wclass, wattr, data.crect); - if (windowRef == 0) - qWarning("QWidget: Internal error: %s:%d: If you reach this error please contact Qt Support and include the\n" - " WidgetFlags used in creating the widget.", __FILE__, __LINE__); -#ifndef QT_MAC_USE_COCOA - finishCreateWindow_sys_Carbon(windowRef); -#else - finishCreateWindow_sys_Cocoa(windowRef); -#endif -} - -void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow) -{ - Q_Q(QWidget); - QMacCocoaAutoReleasePool pool; - - OSViewRef destroyid = 0; -#ifndef QT_MAC_USE_COCOA - window_event = 0; -#endif - - Qt::WindowType type = q->windowType(); - Qt::WindowFlags flags = data.window_flags; - QWidget *parentWidget = q->parentWidget(); - - bool topLevel = (flags & Qt::Window); - bool popup = (type == Qt::Popup); - bool dialog = (type == Qt::Dialog - || type == Qt::Sheet - || type == Qt::Drawer - || (flags & Qt::MSWindowsFixedSizeDialogHint)); - bool desktop = (type == Qt::Desktop); - - // Determine this early for top-levels so, we can use it later. - if (topLevel) - determineWindowClass(); - - if (desktop) { - QSize desktopSize = qt_mac_desktopSize(); - q->setAttribute(Qt::WA_WState_Visible); - data.crect.setRect(0, 0, desktopSize.width(), desktopSize.height()); - dialog = popup = false; // force these flags off - } else { - if (topLevel && (type != Qt::Drawer)) { - if (QDesktopWidget *dsk = QApplication::desktop()) { // calc pos/size from screen - const bool wasResized = q->testAttribute(Qt::WA_Resized); - const bool wasMoved = q->testAttribute(Qt::WA_Moved); - int deskn = dsk->primaryScreen(); - if (parentWidget && parentWidget->windowType() != Qt::Desktop) - deskn = dsk->screenNumber(parentWidget); - QRect screenGeo = dsk->screenGeometry(deskn); - if (!wasResized) { -#ifndef QT_MAC_USE_COCOA - data.crect.setSize(QSize(screenGeo.width()/2, 4*screenGeo.height()/10)); -#else - NSRect newRect = [NSWindow frameRectForContentRect:NSMakeRect(0, 0, - screenGeo.width() / 2., - 4 * screenGeo.height() / 10.) - styleMask:topData()->wattr]; - data.crect.setSize(QSize(newRect.size.width, newRect.size.height)); -#endif - // Constrain to minimums and maximums we've set - if (extra->minw > 0) - data.crect.setWidth(qMax(extra->minw, data.crect.width())); - if (extra->minh > 0) - data.crect.setHeight(qMax(extra->minh, data.crect.height())); - if (extra->maxw > 0) - data.crect.setWidth(qMin(extra->maxw, data.crect.width())); - if (extra->maxh > 0) - data.crect.setHeight(qMin(extra->maxh, data.crect.height())); - } - if (!wasMoved && !q->testAttribute(Qt::WA_DontShowOnScreen)) - data.crect.moveTopLeft(QPoint(screenGeo.width()/4, - 3 * screenGeo.height() / 10)); - } - } - } - - - if(!window) // always initialize - initializeWindow=true; - - hd = 0; - if(window) { // override the old window (with a new NSView) - OSViewRef nativeView = OSViewRef(window); - OSViewRef parent = 0; -#ifndef QT_MAC_USE_COCOA - CFRetain(nativeView); -#else - [nativeView retain]; -#endif - if (destroyOldWindow) - destroyid = qt_mac_nativeview_for(q); - bool transfer = false; - setWinId((WId)nativeView); -#ifndef QT_MAC_USE_COCOA -#ifndef HIViewInstallEventHandler - // Macro taken from the CarbonEvents Header on Tiger -#define HIViewInstallEventHandler( target, handler, numTypes, list, userData, outHandlerRef ) \ - InstallEventHandler( HIObjectGetEventTarget( (HIObjectRef) (target) ), (handler), (numTypes), (list), (userData), (outHandlerRef) ) -#endif - HIViewInstallEventHandler(nativeView, make_widget_eventUPP(), GetEventTypeCount(widget_events), widget_events, 0, 0); -#endif - if(topLevel) { - for(int i = 0; i < 2; ++i) { - if(i == 1) { - if(!initializeWindow) - break; - createWindow_sys(); - } - if(OSWindowRef windowref = qt_mac_window_for(nativeView)) { -#ifndef QT_MAC_USE_COCOA - CFRetain(windowref); -#else - [windowref retain]; -#endif - if (initializeWindow) { - parent = qt_mac_get_contentview_for(windowref); - } else { -#ifndef QT_MAC_USE_COCOA - parent = HIViewGetSuperview(nativeView); -#else - parent = [nativeView superview]; -#endif - } - break; - } - } - if(!parent) - transfer = true; - } else if (parentWidget) { - // I need to be added to my parent, therefore my parent needs an NSView - // Alien note: a 'window' was supplied as argument, meaning this widget - // is not alien. So therefore the parent cannot be alien either. - parentWidget->createWinId(); - parent = qt_mac_nativeview_for(parentWidget); - } - if(parent != nativeView && parent) { -#ifndef QT_MAC_USE_COCOA - HIViewAddSubview(parent, nativeView); -#else - [parent addSubview:nativeView]; -#endif - } - if(transfer) - transferChildren(); - data.fstrut_dirty = true; // we'll re calculate this later - q->setAttribute(Qt::WA_WState_Visible, -#ifndef QT_MAC_USE_COCOA - HIViewIsVisible(nativeView) -#else - ![nativeView isHidden] -#endif - ); - if(initializeWindow) { -#ifndef QT_MAC_USE_COCOA - HIRect bounds = CGRectMake(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height()); - HIViewSetFrame(nativeView, &bounds); - q->setAttribute(Qt::WA_WState_Visible, HIViewIsVisible(nativeView)); -#else - NSRect bounds = NSMakeRect(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height()); - [nativeView setFrame:bounds]; - q->setAttribute(Qt::WA_WState_Visible, [nativeView isHidden]); -#endif - } -#ifndef QT_MAC_USE_COCOA - initWindowPtr(); -#endif - } else if (desktop) { // desktop widget - if (!qt_root_win) - QWidgetPrivate::qt_create_root_win(); - Q_ASSERT(qt_root_win); - WId rootWinID = 0; -#ifndef QT_MAC_USE_COCOA - CFRetain(qt_root_win); - if(HIViewRef rootContentView = HIViewGetRoot(qt_root_win)) { - rootWinID = (WId)rootContentView; - CFRetain(rootContentView); - } -#else - [qt_root_win retain]; - if (OSViewRef rootContentView = [qt_root_win contentView]) { - rootWinID = (WId)rootContentView; - [rootContentView retain]; - } -#endif - setWinId(rootWinID); - } else if (topLevel) { - determineWindowClass(); - if(OSViewRef osview = qt_mac_create_widget(q, this, 0)) { -#ifndef QT_MAC_USE_COCOA - HIRect bounds = CGRectMake(data.crect.x(), data.crect.y(), - data.crect.width(), data.crect.height()); - HIViewSetFrame(osview, &bounds); -#else - NSRect bounds = NSMakeRect(data.crect.x(), flipYCoordinate(data.crect.y()), - data.crect.width(), data.crect.height()); - [osview setFrame:bounds]; -#endif - setWinId((WId)osview); - } - } else { - data.fstrut_dirty = false; // non-toplevel widgets don't have a frame, so no need to update the strut - -#ifdef QT_MAC_USE_COCOA - if (q->testAttribute(Qt::WA_NativeWindow) == false || q->internalWinId() != 0) { - // INVARIANT: q is Alien, and we should not create an NSView to back it up. - } else -#endif - if (OSViewRef osview = qt_mac_create_widget(q, this, qt_mac_nativeview_for(parentWidget))) { -#ifndef QT_MAC_USE_COCOA - HIRect bounds = CGRectMake(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height()); - HIViewSetFrame(osview, &bounds); - setWinId((WId)osview); -#else - NSRect bounds = NSMakeRect(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height()); - [osview setFrame:bounds]; - setWinId((WId)osview); - if (q->isVisible()) { - // If q were Alien before, but now became native (e.g. if a call to - // winId was done from somewhere), we need to show the view immidiatly: - QMacCocoaAutoReleasePool pool; - [osview setHidden:NO]; - } -#endif - } - } - - updateIsOpaque(); - - if (q->testAttribute(Qt::WA_DropSiteRegistered)) - registerDropSite(true); - if (q->hasFocus()) - setFocus_sys(); - if (!topLevel && initializeWindow) - setWSGeometry(); - if (destroyid) - qt_mac_destructView(destroyid); -} - -/*! - Returns the QuickDraw handle of the widget. Use of this function is not - portable. This function will return 0 if QuickDraw is not supported, or - if the handle could not be created. - - \warning This function is only available on Mac OS X. -*/ - -Qt::HANDLE -QWidget::macQDHandle() const -{ -#ifndef QT_MAC_USE_COCOA - return d_func()->qd_hd; -#else - return 0; -#endif -} - -/*! - Returns the CoreGraphics handle of the widget. Use of this function is - not portable. This function will return 0 if no painter context can be - established, or if the handle could not be created. - - \warning This function is only available on Mac OS X. -*/ -Qt::HANDLE -QWidget::macCGHandle() const -{ - return handle(); -} - -void qt_mac_repaintParentUnderAlienWidget(QWidget *alienWidget) -{ - QWidget *nativeParent = alienWidget->nativeParentWidget(); - if (!nativeParent) - return; - - QPoint globalPos = alienWidget->mapToGlobal(QPoint(0, 0)); - QRect dirtyRect = QRect(nativeParent->mapFromGlobal(globalPos), alienWidget->size()); - nativeParent->repaint(dirtyRect); -} - -void QWidget::destroy(bool destroyWindow, bool destroySubWindows) -{ - Q_D(QWidget); - QMacCocoaAutoReleasePool pool; - d->aboutToDestroy(); - if (!isWindow() && parentWidget()) - parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); - if (!internalWinId()) - qt_mac_repaintParentUnderAlienWidget(this); - d->deactivateWidgetCleanup(); - qt_mac_event_release(this); - if(testAttribute(Qt::WA_WState_Created)) { - setAttribute(Qt::WA_WState_Created, false); - QObjectList chldrn = children(); - for(int i = 0; i < chldrn.size(); i++) { // destroy all widget children - QObject *obj = chldrn.at(i); - if(obj->isWidgetType()) - static_cast<QWidget*>(obj)->destroy(destroySubWindows, destroySubWindows); - } - if(mac_mouse_grabber == this) - releaseMouse(); - if(mac_keyboard_grabber == this) - releaseKeyboard(); - - if(testAttribute(Qt::WA_ShowModal)) // just be sure we leave modal - QApplicationPrivate::leaveModal(this); - else if((windowType() == Qt::Popup)) - qApp->d_func()->closePopup(this); - if (destroyWindow) { - if(OSViewRef hiview = qt_mac_nativeview_for(this)) { - OSWindowRef window = 0; - NSDrawer *drawer = nil; -#ifdef QT_MAC_USE_COCOA - if (qt_mac_is_macdrawer(this)) { - drawer = qt_mac_drawer_for(this); - } else -#endif - if (isWindow()) - window = qt_mac_window_for(hiview); - - // Because of how "destruct" works, we have to do just a normal release for the root_win. - if (window && window == qt_root_win) { -#ifndef QT_MAC_USE_COCOA - CFRelease(hiview); -#else - [hiview release]; -#endif - } else { - qt_mac_destructView(hiview); - } - if (drawer) - qt_mac_destructDrawer(drawer); - if (window) - qt_mac_destructWindow(window); - } - } - QT_TRY { - d->setWinId(0); - } QT_CATCH (const std::bad_alloc &) { - // swallow - destructors must not throw - } - } -} - -void QWidgetPrivate::transferChildren() -{ - Q_Q(QWidget); - if (!q->internalWinId()) - return; // Can't add any views anyway - - QObjectList chlist = q->children(); - for (int i = 0; i < chlist.size(); ++i) { - QObject *obj = chlist.at(i); - if (obj->isWidgetType()) { - QWidget *w = (QWidget *)obj; - if (!w->isWindow()) { - // This seems weird, no need to call it in a loop right? - if (!topData()->caption.isEmpty()) - setWindowTitle_helper(extra->topextra->caption); - if (w->internalWinId()) { -#ifndef QT_MAC_USE_COCOA - HIViewAddSubview(qt_mac_nativeview_for(q), qt_mac_nativeview_for(w)); -#else - // New NSWindows get an extra reference when drops are - // registered (at least in 10.5) which means that we may - // access the window later and get a crash (becasue our - // widget is dead). Work around this be having the drop - // site disabled until it is part of the new hierarchy. - bool oldRegistered = w->testAttribute(Qt::WA_DropSiteRegistered); - w->setAttribute(Qt::WA_DropSiteRegistered, false); - [qt_mac_nativeview_for(w) retain]; - [qt_mac_nativeview_for(w) removeFromSuperview]; - [qt_mac_nativeview_for(q) addSubview:qt_mac_nativeview_for(w)]; - [qt_mac_nativeview_for(w) release]; - w->setAttribute(Qt::WA_DropSiteRegistered, oldRegistered); -#endif - } - } - } - } -} - -#ifdef QT_MAC_USE_COCOA -void QWidgetPrivate::setSubWindowStacking(bool set) -{ - // After hitting too many unforeseen bugs trying to put Qt on top of the cocoa child - // window API, we have decided to revert this behaviour as much as we can. We - // therefore now only allow child windows to exist for children of modal dialogs. - static bool use_behaviour_qt473 = !qgetenv("QT_MAC_USE_CHILDWINDOWS").isEmpty(); - - // This will set/remove a visual relationship between parent and child on screen. - // The reason for doing this is to ensure that a child always stacks infront of - // its parent. Unfortunatly is turns out that [NSWindow addChildWindow] has - // several unwanted side-effects, one of them being the moving of a child when - // moving the parent, which we choose to accept. A way tougher side-effect is - // that Cocoa will hide the parent if you hide the child. And in the case of - // a tool window, since it will normally hide when you deactivate the - // application, Cocoa will hide the parent upon deactivate as well. The result often - // being no more visible windows on screen. So, to make a long story short, we only - // allow parent-child relationships between windows that both are either a plain window - // or a dialog. - - Q_Q(QWidget); - if (!q->isWindow()) - return; - NSWindow *qwin = [qt_mac_nativeview_for(q) window]; - if (!qwin) - return; - Qt::WindowType qtype = q->windowType(); - if (set && !(qtype == Qt::Window || qtype == Qt::Dialog)) - return; - if (set && ![qwin isVisible]) - return; - - if (QWidget *parent = q->parentWidget()) { - if (NSWindow *pwin = [qt_mac_nativeview_for(parent) window]) { - if (set) { - Qt::WindowType ptype = parent->window()->windowType(); - if ([pwin isVisible] - && (ptype == Qt::Window || ptype == Qt::Dialog) - && ![qwin parentWindow] - && (use_behaviour_qt473 || parent->windowModality() == Qt::ApplicationModal)) { - NSInteger level = [qwin level]; - [pwin addChildWindow:qwin ordered:NSWindowAbove]; - if ([qwin level] < level) - [qwin setLevel:level]; - } - } else { - [pwin removeChildWindow:qwin]; - } - } - } - - // Only set-up child windows for q if q is modal: - if (set && !use_behaviour_qt473 && q->windowModality() != Qt::ApplicationModal) - return; - - QObjectList widgets = q->children(); - for (int i=0; i<widgets.size(); ++i) { - QWidget *child = qobject_cast<QWidget *>(widgets.at(i)); - if (child && child->isWindow()) { - if (NSWindow *cwin = [qt_mac_nativeview_for(child) window]) { - if (set) { - Qt::WindowType ctype = child->window()->windowType(); - if ([cwin isVisible] && (ctype == Qt::Window || ctype == Qt::Dialog) && ![cwin parentWindow]) { - NSInteger level = [cwin level]; - [qwin addChildWindow:cwin ordered:NSWindowAbove]; - if ([cwin level] < level) - [cwin setLevel:level]; - } - } else { - [qwin removeChildWindow:qt_mac_window_for(child)]; - } - } - } - } -} -#endif - -void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) -{ - Q_Q(QWidget); - QMacCocoaAutoReleasePool pool; - QTLWExtra *topData = maybeTopData(); - bool wasCreated = q->testAttribute(Qt::WA_WState_Created); -#ifdef QT_MAC_USE_COCOA - bool wasWindow = q->isWindow(); -#endif - OSViewRef old_id = 0; - - if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) - q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); - - // Maintain the glWidgets list on parent change: remove "our" gl widgets - // from the list on the old parent and grandparents. - if (glWidgets.isEmpty() == false) { - QWidget *current = q->parentWidget(); - while (current) { - for (QList<QWidgetPrivate::GlWidgetInfo>::const_iterator it = glWidgets.constBegin(); - it != glWidgets.constEnd(); ++it) - current->d_func()->glWidgets.removeAll(*it); - - if (current->isWindow()) - break; - current = current->parentWidget(); - } - } - -#ifndef QT_MAC_USE_COCOA - EventHandlerRef old_window_event = 0; -#else - bool oldToolbarVisible = false; - NSDrawer *oldDrawer = nil; - NSToolbar *oldToolbar = 0; -#endif - if (wasCreated && !(q->windowType() == Qt::Desktop)) { - old_id = qt_mac_nativeview_for(q); -#ifndef QT_MAC_USE_COCOA - old_window_event = window_event; -#else - if (qt_mac_is_macdrawer(q)) { - oldDrawer = qt_mac_drawer_for(q); - } - if (wasWindow) { - OSWindowRef oldWindow = qt_mac_window_for(old_id); - oldToolbar = [oldWindow toolbar]; - if (oldToolbar) { - [oldToolbar retain]; - oldToolbarVisible = [oldToolbar isVisible]; - [oldWindow setToolbar:nil]; - } - } -#endif - } - QWidget* oldtlw = q->window(); - - if (q->testAttribute(Qt::WA_DropSiteRegistered)) - q->setAttribute(Qt::WA_DropSiteRegistered, false); - - //recreate and setup flags - QObjectPrivate::setParent_helper(parent); - bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide); - if (wasCreated && !qt_isGenuineQWidget(q)) - return; - - if (!q->testAttribute(Qt::WA_WState_WindowOpacitySet)) { - q->setWindowOpacity(1.0f); - q->setAttribute(Qt::WA_WState_WindowOpacitySet, false); - } - - setWinId(0); //do after the above because they may want the id - - data.window_flags = f; - q->setAttribute(Qt::WA_WState_Created, false); - q->setAttribute(Qt::WA_WState_Visible, false); - q->setAttribute(Qt::WA_WState_Hidden, false); - adjustFlags(data.window_flags, q); - // keep compatibility with previous versions, we need to preserve the created state. - // (but we recreate the winId for the widget being reparented, again for compatibility, - // unless this is an alien widget. ) - const bool nonWindowWithCreatedParent = !q->isWindow() && parent->testAttribute(Qt::WA_WState_Created); - const bool nativeWidget = q->internalWinId() != 0; - if (wasCreated || (nativeWidget && nonWindowWithCreatedParent)) { - createWinId(); - if (q->isWindow()) { -#ifndef QT_MAC_USE_COCOA - // We do this down below for wasCreated, so avoid doing this twice - // (only for performance, it gets called a lot anyway). - if (!wasCreated) { - if (QMainWindowLayout *mwl = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q))) { - mwl->updateHIToolBarStatus(); - } - } -#else - // Simply transfer our toolbar over. Everything should stay put, unlike in Carbon. - if (oldToolbar && !(f & Qt::FramelessWindowHint)) { - OSWindowRef newWindow = qt_mac_window_for(q); - [newWindow setToolbar:oldToolbar]; - [oldToolbar release]; - [oldToolbar setVisible:oldToolbarVisible]; - } -#endif - } - } - if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden) - q->setAttribute(Qt::WA_WState_Hidden); - q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden); - - if (wasCreated) { - transferChildren(); -#ifndef QT_MAC_USE_COCOA - // If we were a unified window, We just transfered our toolbars out of the unified toolbar. - // So redo the status one more time. It apparently is not an issue with Cocoa. - if (q->isWindow()) { - if (QMainWindowLayout *mwl = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q))) { - mwl->updateHIToolBarStatus(); - } - } -#endif - - if (topData && - (!topData->caption.isEmpty() || !topData->filePath.isEmpty())) - setWindowTitle_helper(q->windowTitle()); - } - - if (q->testAttribute(Qt::WA_AcceptDrops) - || (!q->isWindow() && q->parentWidget() - && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) - q->setAttribute(Qt::WA_DropSiteRegistered, true); - - //cleanup -#ifndef QT_MAC_USE_COCOA - if (old_window_event) - RemoveEventHandler(old_window_event); -#endif - if (old_id) { //don't need old window anymore - OSWindowRef window = (oldtlw == q) ? qt_mac_window_for(old_id) : 0; - qt_mac_destructView(old_id); - -#ifdef QT_MAC_USE_COCOA - if (oldDrawer) { - qt_mac_destructDrawer(oldDrawer); - } else -#endif - if (window) - qt_mac_destructWindow(window); - } - - // Maintain the glWidgets list on parent change: add "our" gl widgets - // to the list on the new parent and grandparents. - if (glWidgets.isEmpty() == false) { - QWidget *current = q->parentWidget(); - while (current) { - current->d_func()->glWidgets += glWidgets; - if (current->isWindow()) - break; - current = current->parentWidget(); - } - } - invalidateBuffer(q->rect()); - qt_event_request_window_change(q); -} - -QPoint QWidget::mapToGlobal(const QPoint &pos) const -{ - Q_D(const QWidget); - if (!internalWinId()) { - QPoint p = pos + data->crect.topLeft(); - return isWindow() ? p : parentWidget()->mapToGlobal(p); - } -#ifndef QT_MAC_USE_COCOA - QPoint tmp = d->mapToWS(pos); - HIPoint hi_pos = CGPointMake(tmp.x(), tmp.y()); - HIViewConvertPoint(&hi_pos, qt_mac_nativeview_for(this), 0); - Rect win_rect; - GetWindowBounds(qt_mac_window_for(this), kWindowStructureRgn, &win_rect); - return QPoint((int)hi_pos.x+win_rect.left, (int)hi_pos.y+win_rect.top); -#else - QPoint tmp = d->mapToWS(pos); - NSPoint hi_pos = NSMakePoint(tmp.x(), tmp.y()); - hi_pos = [qt_mac_nativeview_for(this) convertPoint:hi_pos toView:nil]; - NSRect win_rect = [qt_mac_window_for(this) frame]; - hi_pos.x += win_rect.origin.x; - hi_pos.y += win_rect.origin.y; - // If we aren't the desktop we need to flip, if you flip the desktop on itself, you get the other problem. - return ((window()->windowFlags() & Qt::Desktop) == Qt::Desktop) ? QPointF(hi_pos.x, hi_pos.y).toPoint() - : flipPoint(hi_pos).toPoint(); -#endif -} - -QPoint QWidget::mapFromGlobal(const QPoint &pos) const -{ - Q_D(const QWidget); - if (!internalWinId()) { - QPoint p = isWindow() ? pos : parentWidget()->mapFromGlobal(pos); - return p - data->crect.topLeft(); - } -#ifndef QT_MAC_USE_COCOA - Rect win_rect; - GetWindowBounds(qt_mac_window_for(this), kWindowStructureRgn, &win_rect); - HIPoint hi_pos = CGPointMake(pos.x()-win_rect.left, pos.y()-win_rect.top); - HIViewConvertPoint(&hi_pos, 0, qt_mac_nativeview_for(this)); - return d->mapFromWS(QPoint((int)hi_pos.x, (int)hi_pos.y)); -#else - NSRect win_rect = [qt_mac_window_for(this) frame]; - // The Window point is in "Cocoa coordinates," but the view is in "Qt coordinates" - // so make sure to keep them in sync. - NSPoint hi_pos = NSMakePoint(pos.x()-win_rect.origin.x, - flipYCoordinate(pos.y())-win_rect.origin.y); - hi_pos = [qt_mac_nativeview_for(this) convertPoint:hi_pos fromView:0]; - return d->mapFromWS(QPoint(qRound(hi_pos.x), qRound(hi_pos.y))); -#endif -} - -void QWidgetPrivate::updateSystemBackground() -{ -} - -void QWidgetPrivate::setCursor_sys(const QCursor &) -{ - qt_mac_update_cursor(); -} - -void QWidgetPrivate::unsetCursor_sys() -{ - qt_mac_update_cursor(); -} - -void QWidgetPrivate::setWindowTitle_sys(const QString &caption) -{ - Q_Q(QWidget); - if (q->isWindow()) { -#ifndef QT_MAC_USE_COCOA - SetWindowTitleWithCFString(qt_mac_window_for(q), QCFString(caption)); -#else - QMacCocoaAutoReleasePool pool; - [qt_mac_window_for(q) setTitle:qt_mac_QStringToNSString(caption)]; -#endif - } -} - -void QWidgetPrivate::setWindowModified_sys(bool mod) -{ - Q_Q(QWidget); - if (q->isWindow() && q->testAttribute(Qt::WA_WState_Created)) { -#ifndef QT_MAC_USE_COCOA - SetWindowModified(qt_mac_window_for(q), mod); -#else - [qt_mac_window_for(q) setDocumentEdited:mod]; -#endif - } -} - -void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath) -{ - Q_Q(QWidget); -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - QFileInfo fi(filePath); - [qt_mac_window_for(q) setRepresentedFilename:fi.exists() ? qt_mac_QStringToNSString(filePath) : @""]; -#else - bool validRef = false; - FSRef ref; - bzero(&ref, sizeof(ref)); - OSStatus status; - - if (!filePath.isEmpty()) { - status = FSPathMakeRef(reinterpret_cast<const UInt8 *>(filePath.toUtf8().constData()), &ref, 0); - validRef = (status == noErr); - } - // Set the proxy regardless, since this is our way of clearing it as well, but ignore the - // return value as well. - if (validRef) { - status = HIWindowSetProxyFSRef(qt_mac_window_for(q), &ref); - } else { - status = RemoveWindowProxy(qt_mac_window_for(q)); - } - if (status != noErr) - qWarning("QWidget::setWindowFilePath: Error setting proxyicon for path (%s):%ld", - qPrintable(filePath), status); -#endif -} - -void QWidgetPrivate::setWindowIcon_sys(bool forceReset) -{ - Q_Q(QWidget); - - if (!q->testAttribute(Qt::WA_WState_Created)) - return; - - QTLWExtra *topData = this->topData(); - if (topData->iconPixmap && !forceReset) // already set - return; - - QIcon icon = q->windowIcon(); - QPixmap *pm = 0; - if (!icon.isNull()) { - // now create the extra - if (!topData->iconPixmap) { - pm = new QPixmap(icon.pixmap(QSize(22, 22))); - topData->iconPixmap = pm; - } else { - pm = topData->iconPixmap; - } - } - if (q->isWindow()) { -#ifndef QT_MAC_USE_COCOA - IconRef previousIcon = 0; - if (icon.isNull()) { - RemoveWindowProxy(qt_mac_window_for(q)); - previousIcon = topData->windowIcon; - topData->windowIcon = 0; - } else { - WindowClass wclass; - GetWindowClass(qt_mac_window_for(q), &wclass); - - if (wclass == kDocumentWindowClass) { - IconRef newIcon = qt_mac_create_iconref(*pm); - previousIcon = topData->windowIcon; - topData->windowIcon = newIcon; - SetWindowProxyIcon(qt_mac_window_for(q), newIcon); - } - } - - // Release the previous icon if it was set by this function. - if (previousIcon != 0) - ReleaseIconRef(previousIcon); -#else - QMacCocoaAutoReleasePool pool; - if (icon.isNull()) - return; - NSButton *iconButton = [qt_mac_window_for(q) standardWindowButton:NSWindowDocumentIconButton]; - if (iconButton == nil) { - QCFString string(q->windowTitle()); - const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string); - [qt_mac_window_for(q) setRepresentedURL:[NSURL fileURLWithPath:const_cast<NSString *>(tmpString)]]; - iconButton = [qt_mac_window_for(q) standardWindowButton:NSWindowDocumentIconButton]; - } - if (icon.isNull()) { - [iconButton setImage:nil]; - } else { - QPixmap scaled = pm->scaled(QSize(16,16), Qt::KeepAspectRatio, Qt::SmoothTransformation); - NSImage *image = static_cast<NSImage *>(qt_mac_create_nsimage(scaled)); - [iconButton setImage:image]; - [image release]; - } -#endif - } -} - -void QWidgetPrivate::setWindowIconText_sys(const QString &iconText) -{ - Q_Q(QWidget); - if(q->isWindow() && !iconText.isEmpty()) { -#ifndef QT_MAC_USE_COCOA - SetWindowAlternateTitle(qt_mac_window_for(q), QCFString(iconText)); -#else - QMacCocoaAutoReleasePool pool; - [qt_mac_window_for(q) setMiniwindowTitle:qt_mac_QStringToNSString(iconText)]; -#endif - } -} - -void QWidget::grabMouse() -{ - if(isVisible() && !qt_nograb()) { - if(mac_mouse_grabber) - mac_mouse_grabber->releaseMouse(); - mac_mouse_grabber=this; - qt_mac_setMouseGrabCursor(true); - } -} - -#ifndef QT_NO_CURSOR -void QWidget::grabMouse(const QCursor &cursor) -{ - if(isVisible() && !qt_nograb()) { - if(mac_mouse_grabber) - mac_mouse_grabber->releaseMouse(); - mac_mouse_grabber=this; - qt_mac_setMouseGrabCursor(true, const_cast<QCursor *>(&cursor)); - } -} -#endif - -void QWidget::releaseMouse() -{ - if(!qt_nograb() && mac_mouse_grabber == this) { - mac_mouse_grabber = 0; - qt_mac_setMouseGrabCursor(false); - } -} - -void QWidget::grabKeyboard() -{ - if(!qt_nograb()) { - if(mac_keyboard_grabber) - mac_keyboard_grabber->releaseKeyboard(); - mac_keyboard_grabber = this; - } -} - -void QWidget::releaseKeyboard() -{ - if(!qt_nograb() && mac_keyboard_grabber == this) - mac_keyboard_grabber = 0; -} - -QWidget *QWidget::mouseGrabber() -{ - return mac_mouse_grabber; -} - -QWidget *QWidget::keyboardGrabber() -{ - return mac_keyboard_grabber; -} - -void QWidget::activateWindow() -{ - QWidget *tlw = window(); - if(!tlw->isVisible() || !tlw->isWindow() || (tlw->windowType() == Qt::Desktop)) - return; - qt_event_remove_activate(); - - QWidget *fullScreenWidget = tlw; - QWidget *parentW = tlw; - // Find the oldest parent or the parent with fullscreen, whichever comes first. - while (parentW) { - fullScreenWidget = parentW->window(); - if (fullScreenWidget->windowState() & Qt::WindowFullScreen) - break; - parentW = fullScreenWidget->parentWidget(); - } - - if (fullScreenWidget->windowType() != Qt::ToolTip) { - qt_mac_set_fullscreen_mode((fullScreenWidget->windowState() & Qt::WindowFullScreen) && - qApp->desktop()->screenNumber(this) == 0); - } - - bool windowActive; - OSWindowRef win = qt_mac_window_for(tlw); -#ifndef QT_MAC_USE_COCOA - windowActive = IsWindowActive(win); -#else - QMacCocoaAutoReleasePool pool; - windowActive = [win isKeyWindow]; -#endif - if ((tlw->windowType() == Qt::Popup) - || (tlw->windowType() == Qt::Tool) - || qt_mac_is_macdrawer(tlw) - || windowActive) { -#ifndef QT_MAC_USE_COCOA - ActivateWindow(win, true); - qApp->setActiveWindow(tlw); -#else - [win makeKeyWindow]; -#endif - } else if(!isMinimized()) { -#ifndef QT_MAC_USE_COCOA - SelectWindow(win); -#else - [win makeKeyAndOrderFront:win]; -#endif - } -} - -QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys() -{ - return new QMacWindowSurface(q_func()); -} - -void QWidgetPrivate::update_sys(const QRect &r) -{ - Q_Q(QWidget); - if (updateRedirectedToGraphicsProxyWidget(q, r)) - return; - dirtyOnWidget += r; - macSetNeedsDisplay(r != q->rect() ? r : QRegion()); -} - -void QWidgetPrivate::update_sys(const QRegion &rgn) -{ - Q_Q(QWidget); - if (updateRedirectedToGraphicsProxyWidget(q, rgn)) - return; - dirtyOnWidget += rgn; - macSetNeedsDisplay(rgn); -} - -bool QWidgetPrivate::isRealWindow() const -{ - return q_func()->isWindow() && !topData()->embedded; -} - -void QWidgetPrivate::show_sys() -{ - Q_Q(QWidget); - if ((q->windowType() == Qt::Desktop)) //desktop is always visible - return; - - invalidateBuffer(q->rect()); - if (q->testAttribute(Qt::WA_OutsideWSRange)) - return; - QMacCocoaAutoReleasePool pool; - q->setAttribute(Qt::WA_Mapped); - if (q->testAttribute(Qt::WA_DontShowOnScreen)) - return; - - bool realWindow = isRealWindow(); -#ifndef QT_MAC_USE_COCOA - if (realWindow && !q->testAttribute(Qt::WA_Moved)) { - if (qt_mac_is_macsheet(q)) - recreateMacWindow(); - q->createWinId(); - if (QWidget *p = q->parentWidget()) { - p->createWinId(); - RepositionWindow(qt_mac_window_for(q), qt_mac_window_for(p), kWindowCenterOnParentWindow); - } else { - RepositionWindow(qt_mac_window_for(q), 0, kWindowCenterOnMainScreen); - } - } -#endif - - data.fstrut_dirty = true; - if (realWindow) { - bool isCurrentlyMinimized = (q->windowState() & Qt::WindowMinimized); - setModal_sys(); - OSWindowRef window = qt_mac_window_for(q); -#ifndef QT_MAC_USE_COCOA - SizeWindow(window, q->width(), q->height(), true); -#endif - -#ifdef QT_MAC_USE_COCOA - // Make sure that we end up sending a repaint event to - // the widget if the window has been visible one before: - [qt_mac_get_contentview_for(window) setNeedsDisplay:YES]; -#endif - if(qt_mac_is_macsheet(q)) { - qt_event_request_showsheet(q); - } else if(qt_mac_is_macdrawer(q)) { -#ifndef QT_MAC_USE_COCOA - OpenDrawer(window, kWindowEdgeDefault, false); -#else - NSDrawer *drawer = qt_mac_drawer_for(q); - [drawer openOnEdge:[drawer preferredEdge]]; -#endif - } else { -#ifndef QT_MAC_USE_COCOA - ShowHide(window, true); -#else - // sync the opacity value back (in case of a fade). - [window setAlphaValue:q->windowOpacity()]; - - QWidget *top = 0; - if (QApplicationPrivate::tryModalHelper(q, &top)) { - [window makeKeyAndOrderFront:window]; - // If this window is app modal, we need to start spinning - // a modal session for it. Interrupting - // the event dispatcher will make this happend: - if (data.window_modality == Qt::ApplicationModal) - QEventDispatcherMac::instance()->interrupt(); - } else { - // The window is modally shaddowed, so we need to make - // sure that we don't pop in front of the modal window: - [window orderFront:window]; - if (!top->testAttribute(Qt::WA_DontShowOnScreen)) { - if (NSWindow *modalWin = qt_mac_window_for(top)) - [modalWin orderFront:window]; - } - } - setSubWindowStacking(true); - qt_mac_update_cursor(); -#endif - if (q->windowType() == Qt::Popup) { - qt_button_down = 0; - if (q->focusWidget()) - q->focusWidget()->d_func()->setFocus_sys(); - else - setFocus_sys(); - } - toggleDrawers(true); - } - if (isCurrentlyMinimized) { //show in collapsed state -#ifndef QT_MAC_USE_COCOA - CollapseWindow(window, true); -#else - [window miniaturize:window]; -#endif - } else if (!q->testAttribute(Qt::WA_ShowWithoutActivating)) { -#ifndef QT_MAC_USE_COCOA - qt_event_request_activate(q); -#endif - } - } else if(topData()->embedded || !q->parentWidget() || q->parentWidget()->isVisible()) { -#ifndef QT_MAC_USE_COCOA - HIViewSetVisible(qt_mac_nativeview_for(q), true); -#else - if (NSView *view = qt_mac_nativeview_for(q)) { - // INVARIANT: q is native. Just show the view: - [view setHidden:NO]; - } else { - // INVARIANT: q is alien. Repaint q instead: - q->repaint(); - } -#endif - } - -#ifdef QT_MAC_USE_COCOA - if ([NSApp isActive] && !qt_button_down && !QWidget::mouseGrabber()){ - // Update enter/leave immidiatly, don't wait for a move event. But only - // if no grab exists (even if the grab points to this widget, it seems, ref X11) - QPoint qlocal, qglobal; - QWidget *widgetUnderMouse = 0; - qt_mac_getTargetForMouseEvent(0, QEvent::Enter, qlocal, qglobal, 0, &widgetUnderMouse); - QApplicationPrivate::dispatchEnterLeave(widgetUnderMouse, qt_last_mouse_receiver); - qt_last_mouse_receiver = widgetUnderMouse; - qt_last_native_mouse_receiver = widgetUnderMouse ? - (widgetUnderMouse->internalWinId() ? widgetUnderMouse : widgetUnderMouse->nativeParentWidget()) : 0; - } -#endif - - topLevelAt_cache = 0; - qt_event_request_window_change(q); -} - -QPoint qt_mac_nativeMapFromParent(const QWidget *child, const QPoint &pt) -{ -#ifndef QT_MAC_USE_COCOA - CGPoint nativePoint = CGPointMake(pt.x(), pt.y()); - HIViewConvertPoint(&nativePoint, qt_mac_nativeview_for(child->parentWidget()), - qt_mac_nativeview_for(child)); -#else - NSPoint nativePoint = [qt_mac_nativeview_for(child) convertPoint:NSMakePoint(pt.x(), pt.y()) fromView:qt_mac_nativeview_for(child->parentWidget())]; -#endif - return QPoint(nativePoint.x, nativePoint.y); -} - - -void QWidgetPrivate::hide_sys() -{ - Q_Q(QWidget); - if((q->windowType() == Qt::Desktop)) //you can't hide the desktop! - return; - QMacCocoaAutoReleasePool pool; - if(q->isWindow()) { -#ifdef QT_MAC_USE_COCOA - setSubWindowStacking(false); -#endif - OSWindowRef window = qt_mac_window_for(q); - if(qt_mac_is_macsheet(q)) { -#ifndef QT_MAC_USE_COCOA - WindowRef parent = 0; - if(GetSheetWindowParent(window, &parent) != noErr || !parent) - ShowHide(window, false); - else - HideSheetWindow(window); -#else - [NSApp endSheet:window]; - [window orderOut:window]; -#endif - } else if(qt_mac_is_macdrawer(q)) { -#ifndef QT_MAC_USE_COCOA - CloseDrawer(window, false); -#else - [qt_mac_drawer_for(q) close]; -#endif - } else { -#ifndef QT_MAC_USE_COCOA - ShowHide(window, false); -#else - [window orderOut:window]; - // Unfortunately it is not as easy as just hiding the window, we need - // to find out if we were in full screen mode. If we were and this is - // the last window in full screen mode then we need to unset the full screen - // mode. If this is not the last visible window in full screen mode then we - // don't change the full screen mode. - if(q->isFullScreen()) - { - bool keepFullScreen = false; - QWidgetList windowList = qApp->topLevelWidgets(); - int windowCount = windowList.count(); - for(int i = 0; i < windowCount; i++) - { - QWidget *w = windowList[i]; - // If it is the same window, we don't need to check :-) - if(q == w) - continue; - // If they are not visible or if they are minimized then - // we just ignore them. - if(!w->isVisible() || w->isMinimized()) - continue; - // Is it full screen? - // Notice that if there is one window in full screen mode then we - // cannot switch the full screen mode off, therefore we just abort. - if(w->isFullScreen()) { - keepFullScreen = true; - break; - } - } - // No windows in full screen mode, so let just unset that flag. - if(!keepFullScreen) - qt_mac_set_fullscreen_mode(false); - } -#endif - toggleDrawers(false); - qt_mac_update_cursor(); -#ifndef QT_MAC_USE_COCOA - // Clear modality (because it seems something that we've always done). - if (data.window_modality != Qt::NonModal) { - SetWindowModality(window, kWindowModalityNone, - q->parentWidget() ? qt_mac_window_for(q->parentWidget()->window()) : 0); - } -#endif - } -#ifndef QT_MAC_USE_COCOA - // If the window we now hide was the active window, we need - // to find, and activate another window on screen. NB: Cocoa takes care of this - // logic for us (and distinquishes between main windows and key windows) - if (q->isActiveWindow() && !(q->windowType() == Qt::Popup)) { - QWidget *w = 0; - if(q->parentWidget()) - w = q->parentWidget()->window(); - if(!w || (!w->isVisible() && !w->isMinimized())) { - for (WindowPtr wp = GetFrontWindowOfClass(kMovableModalWindowClass, true); - wp; wp = GetNextWindowOfClass(wp, kMovableModalWindowClass, true)) { - if((w = qt_mac_find_window(wp))) - break; - } - if (!w){ - for (WindowPtr wp = GetFrontWindowOfClass(kDocumentWindowClass, true); - wp; wp = GetNextWindowOfClass(wp, kDocumentWindowClass, true)) { - if((w = qt_mac_find_window(wp))) - break; - } - } - if (!w){ - for(WindowPtr wp = GetFrontWindowOfClass(kSimpleWindowClass, true); - wp; wp = GetNextWindowOfClass(wp, kSimpleWindowClass, true)) { - if((w = qt_mac_find_window(wp))) - break; - } - } - } - if(w && w->isVisible() && !w->isMinimized()) { - qt_event_request_activate(w); - } - } -#endif - } else { - invalidateBuffer(q->rect()); -#ifndef QT_MAC_USE_COCOA - HIViewSetVisible(qt_mac_nativeview_for(q), false); -#else - if (NSView *view = qt_mac_nativeview_for(q)) { - // INVARIANT: q is native. Just hide the view: - [view setHidden:YES]; - } else { - // INVARIANT: q is alien. Repaint where q is placed instead: - qt_mac_repaintParentUnderAlienWidget(q); - } -#endif - } - -#ifdef QT_MAC_USE_COCOA - if ([NSApp isActive] && !qt_button_down && !QWidget::mouseGrabber()){ - // Update enter/leave immidiatly, don't wait for a move event. But only - // if no grab exists (even if the grab points to this widget, it seems, ref X11) - QPoint qlocal, qglobal; - QWidget *widgetUnderMouse = 0; - qt_mac_getTargetForMouseEvent(0, QEvent::Leave, qlocal, qglobal, 0, &widgetUnderMouse); - QApplicationPrivate::dispatchEnterLeave(widgetUnderMouse, qt_last_native_mouse_receiver); - qt_last_mouse_receiver = widgetUnderMouse; - qt_last_native_mouse_receiver = widgetUnderMouse ? - (widgetUnderMouse->internalWinId() ? widgetUnderMouse : widgetUnderMouse->nativeParentWidget()) : 0; - } -#endif - - topLevelAt_cache = 0; - qt_event_request_window_change(q); - deactivateWidgetCleanup(); - qt_mac_event_release(q); -} - -void QWidget::setWindowState(Qt::WindowStates newstate) -{ - Q_D(QWidget); - bool needShow = false; - Qt::WindowStates oldstate = windowState(); - if (oldstate == newstate) - return; - -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; -#endif - bool needSendStateChange = true; - if(isWindow()) { - if((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) { - if(newstate & Qt::WindowFullScreen) { - if(QTLWExtra *tlextra = d->topData()) { - if(tlextra->normalGeometry.width() < 0) { - if(!testAttribute(Qt::WA_Resized)) - adjustSize(); - tlextra->normalGeometry = geometry(); - } - tlextra->savedFlags = windowFlags(); - } - needShow = isVisible(); - const QRect fullscreen(qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(this))); - setParent(parentWidget(), Qt::Window | Qt::FramelessWindowHint | (windowFlags() & 0xffff0000)); //save - setGeometry(fullscreen); - if(!qApp->desktop()->screenNumber(this)) - qt_mac_set_fullscreen_mode(true); - } else { - needShow = isVisible(); - if(!qApp->desktop()->screenNumber(this)) - qt_mac_set_fullscreen_mode(false); - setParent(parentWidget(), d->topData()->savedFlags); - setGeometry(d->topData()->normalGeometry); - d->topData()->normalGeometry.setRect(0, 0, -1, -1); - } - } - - d->createWinId(); - - OSWindowRef window = qt_mac_window_for(this); - if((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) { - if (newstate & Qt::WindowMinimized) { -#ifndef QT_MAC_USE_COCOA - CollapseWindow(window, true); -#else - [window miniaturize:window]; -#endif - } else { -#ifndef QT_MAC_USE_COCOA - CollapseWindow(window, false); -#else - [window deminiaturize:window]; -#endif - } - needSendStateChange = oldstate == windowState(); // Collapse didn't change our flags. - } - - if((newstate & Qt::WindowMaximized) && !((newstate & Qt::WindowFullScreen))) { - if(QTLWExtra *tlextra = d->topData()) { - if(tlextra->normalGeometry.width() < 0) { - if(!testAttribute(Qt::WA_Resized)) - adjustSize(); - tlextra->normalGeometry = geometry(); - } - } - } else if(!(newstate & Qt::WindowFullScreen)) { -// d->topData()->normalGeometry = QRect(0, 0, -1, -1); - } - -#ifdef DEBUG_WINDOW_STATE -#define WSTATE(x) qDebug("%s -- %s --> %s", #x, (oldstate & x) ? "true" : "false", (newstate & x) ? "true" : "false") - WSTATE(Qt::WindowMinimized); - WSTATE(Qt::WindowMaximized); - WSTATE(Qt::WindowFullScreen); -#undef WSTATE -#endif - if(!(newstate & (Qt::WindowMinimized|Qt::WindowFullScreen)) && - ((oldstate & Qt::WindowFullScreen) || (oldstate & Qt::WindowMinimized) || - (oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized))) { - if(newstate & Qt::WindowMaximized) { - data->fstrut_dirty = true; -#ifndef QT_MAC_USE_COCOA - HIToolbarRef toolbarRef; - if (GetWindowToolbar(window, &toolbarRef) == noErr && toolbarRef - && !isVisible() && !IsWindowToolbarVisible(window)) { - // HIToolbar, needs to be shown so that it's in the structure window - // Typically this is part of a main window and will get shown - // during the show, but it's will make the maximize all wrong. - ShowHideWindowToolbar(window, true, false); - d->updateFrameStrut(); // In theory the dirty would work, but it's optimized out if the window is not visible :( - } - Rect bounds; - QDesktopWidget *dsk = QApplication::desktop(); - QRect avail = dsk->availableGeometry(dsk->screenNumber(this)); - SetRect(&bounds, avail.x(), avail.y(), avail.x() + avail.width(), avail.y() + avail.height()); - if(QWExtra *extra = d->extraData()) { - if(bounds.right - bounds.left > extra->maxw) - bounds.right = bounds.left + extra->maxw; - if(bounds.bottom - bounds.top > extra->maxh) - bounds.bottom = bounds.top + extra->maxh; - } - if(d->topData()) { - QRect fs = d->frameStrut(); - bounds.left += fs.left(); - if(bounds.right < avail.x()+avail.width()) - bounds.right = qMin<short>((uint)avail.x()+avail.width(), bounds.right+fs.left()); - if(bounds.bottom < avail.y()+avail.height()) - bounds.bottom = qMin<short>((uint)avail.y()+avail.height(), bounds.bottom+fs.top()); - bounds.top += fs.top(); - bounds.right -= fs.right(); - bounds.bottom -= fs.bottom(); - } - QRect orect(geometry().x(), geometry().y(), width(), height()), - nrect(bounds.left, bounds.top, bounds.right - bounds.left, - bounds.bottom - bounds.top); - if(orect != nrect) { // the new rect differ from the old - Point idealSize = { nrect.height(), nrect.width() }; - ZoomWindowIdeal(window, inZoomOut, &idealSize); - } -#else - NSToolbar *toolbarRef = [window toolbar]; - if (toolbarRef && !isVisible() && ![toolbarRef isVisible]) { - // HIToolbar, needs to be shown so that it's in the structure window - // Typically this is part of a main window and will get shown - // during the show, but it's will make the maximize all wrong. - // ### Not sure this is right for NSToolbar... - [toolbarRef setVisible:true]; -// ShowHideWindowToolbar(window, true, false); - d->updateFrameStrut(); // In theory the dirty would work, but it's optimized out if the window is not visible :( - } - // Everything should be handled by Cocoa. - [window zoom:window]; -#endif - needSendStateChange = oldstate == windowState(); // Zoom didn't change flags. - } else if(oldstate & Qt::WindowMaximized && !(oldstate & Qt::WindowFullScreen)) { -#ifndef QT_MAC_USE_COCOA - Point idealSize; - ZoomWindowIdeal(window, inZoomIn, &idealSize); -#else - [window zoom:window]; -#endif - if(QTLWExtra *tlextra = d->topData()) { - setGeometry(tlextra->normalGeometry); - tlextra->normalGeometry.setRect(0, 0, -1, -1); - } - } - } - } - - data->window_state = newstate; - - if(needShow) - show(); - - if(newstate & Qt::WindowActive) - activateWindow(); - - qt_event_request_window_change(this); - if (needSendStateChange) { - QWindowStateChangeEvent e(oldstate); - QApplication::sendEvent(this, &e); - } -} - -void QWidgetPrivate::setFocus_sys() -{ - Q_Q(QWidget); - if (q->testAttribute(Qt::WA_WState_Created)) { -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - NSView *view = qt_mac_nativeview_for(q); - [[view window] makeFirstResponder:view]; -#else - SetKeyboardFocus(qt_mac_window_for(q), qt_mac_nativeview_for(q), 1); -#endif - } -} - -NSComparisonResult compareViews2Raise(id view1, id view2, void *context) -{ - id topView = reinterpret_cast<id>(context); - if (view1 == topView) - return NSOrderedDescending; - if (view2 == topView) - return NSOrderedAscending; - return NSOrderedSame; -} - -void QWidgetPrivate::raise_sys() -{ - Q_Q(QWidget); - if((q->windowType() == Qt::Desktop)) - return; - -#if QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - if (isRealWindow()) { - // With the introduction of spaces it is not as simple as just raising the window. - // First we need to check if we are in the right space. If we are, then we just continue - // as usual. The problem comes when we are not in the active space. There are two main cases: - // 1. Our parent was moved to a new space. In this case we want the window to be raised - // in the same space as its parent. - // 2. We don't have a parent. For this case we will just raise the window and let Cocoa - // switch to the corresponding space. - // NOTICE: There are a lot of corner cases here. We are keeping this simple for now, if - // required we will introduce special handling for some of them. - if (!q->testAttribute(Qt::WA_DontShowOnScreen) && q->isVisible()) { - OSWindowRef window = qt_mac_window_for(q); - // isOnActiveSpace is available only from 10.6 onwards, so we need to check if it is - // available before calling it. - if([window respondsToSelector:@selector(isOnActiveSpace)]) { - if(![window performSelector:@selector(isOnActiveSpace)]) { - QWidget *parentWidget = q->parentWidget(); - if(parentWidget) { - OSWindowRef parentWindow = qt_mac_window_for(parentWidget); - if(parentWindow && [parentWindow respondsToSelector:@selector(isOnActiveSpace)]) { - if ([parentWindow performSelector:@selector(isOnActiveSpace)]) { - // The window was created in a different space. Therefore if we want - // to show it in the current space we need to recreate it in the new - // space. - recreateMacWindow(); - window = qt_mac_window_for(q); - } - } - } - } - } - [window orderFront:window]; - } - if (qt_mac_raise_process) { //we get to be the active process now - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly); - } - } else { - NSView *view = qt_mac_nativeview_for(q); - NSView *parentView = [view superview]; - [parentView sortSubviewsUsingFunction:compareViews2Raise context:reinterpret_cast<void *>(view)]; - } - topLevelAt_cache = 0; -#else - if(q->isWindow()) { - //raise this window - BringToFront(qt_mac_window_for(q)); - if(qt_mac_raise_process) { //we get to be the active process now - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly); - } - } else if(q->parentWidget()) { - HIViewSetZOrder(qt_mac_nativeview_for(q), kHIViewZOrderAbove, 0); - qt_event_request_window_change(q); - } -#endif -} - -NSComparisonResult compareViews2Lower(id view1, id view2, void *context) -{ - id topView = reinterpret_cast<id>(context); - if (view1 == topView) - return NSOrderedAscending; - if (view2 == topView) - return NSOrderedDescending; - return NSOrderedSame; -} - -void QWidgetPrivate::lower_sys() -{ - Q_Q(QWidget); - if((q->windowType() == Qt::Desktop)) - return; -#ifdef QT_MAC_USE_COCOA - if (isRealWindow()) { - OSWindowRef window = qt_mac_window_for(q); - [window orderBack:window]; - } else { - NSView *view = qt_mac_nativeview_for(q); - NSView *parentView = [view superview]; - [parentView sortSubviewsUsingFunction:compareViews2Lower context:reinterpret_cast<void *>(view)]; - } - topLevelAt_cache = 0; -#else - if(q->isWindow()) { - SendBehind(qt_mac_window_for(q), 0); - } else if(q->parentWidget()) { - invalidateBuffer(q->rect()); - HIViewSetZOrder(qt_mac_nativeview_for(q), kHIViewZOrderBelow, 0); - qt_event_request_window_change(q); - } -#endif -} - -NSComparisonResult compareViews2StackUnder(id view1, id view2, void *context) -{ - const QHash<NSView *, int> &viewOrder = *reinterpret_cast<QHash<NSView *, int> *>(context); - if (viewOrder[view1] < viewOrder[view2]) - return NSOrderedAscending; - if (viewOrder[view1] > viewOrder[view2]) - return NSOrderedDescending; - return NSOrderedSame; -} - -void QWidgetPrivate::stackUnder_sys(QWidget *w) -{ - // stackUnder - Q_Q(QWidget); - if(!w || q->isWindow() || (q->windowType() == Qt::Desktop)) - return; -#ifdef QT_MAC_USE_COCOA - // Do the same trick as lower_sys() and put this widget before the widget passed in. - NSView *myView = qt_mac_nativeview_for(q); - NSView *wView = qt_mac_nativeview_for(w); - - QHash<NSView *, int> viewOrder; - NSView *parentView = [myView superview]; - NSArray *subviews = [parentView subviews]; - NSUInteger index = 1; - // make a hash of view->zorderindex and make sure z-value is always odd, - // so that when we modify the order we create a new (even) z-value which - // will not interfere with others. - for (NSView *subview in subviews) { - viewOrder.insert(subview, index * 2); - ++index; - } - viewOrder[myView] = viewOrder[wView] - 1; - - [parentView sortSubviewsUsingFunction:compareViews2StackUnder context:reinterpret_cast<void *>(&viewOrder)]; -#else - QWidget *p = q->parentWidget(); - if(!p || p != w->parentWidget()) - return; - invalidateBuffer(q->rect()); - HIViewSetZOrder(qt_mac_nativeview_for(q), kHIViewZOrderBelow, qt_mac_nativeview_for(w)); - qt_event_request_window_change(q); -#endif -} - -#ifndef QT_MAC_USE_COCOA -/* - Modifies the bounds for a widgets backing HIView during moves and resizes. Also updates the - widget, either by scrolling its contents or repainting, depending on the WA_StaticContents - flag -*/ -static void qt_mac_update_widget_position(QWidget *q, QRect oldRect, QRect newRect) -{ - HIRect bounds = CGRectMake(newRect.x(), newRect.y(), - newRect.width(), newRect.height()); - - const HIViewRef view = qt_mac_nativeview_for(q); - const bool isMove = (oldRect.topLeft() != newRect.topLeft()); - const bool isResize = (oldRect.size() != newRect.size()); - -// qDebug() << oldRect << newRect << isMove << isResize << q->testAttribute(Qt::WA_OpaquePaintEvent) << q->testAttribute(Qt::WA_StaticContents); - QWidgetPrivate *qd = qt_widget_private(q); - - // Perform a normal (complete repaint) update in some cases: - if ( - // always repaint on move. - (isMove) || - - // limited update on resize requires WA_StaticContents. - (isResize && q->testAttribute(Qt::WA_StaticContents) == false) || - - // one of the rects are invalid - (oldRect.isValid() == false || newRect.isValid() == false) || - - // the position update is a part of a drag-and-drop operation - QDragManager::self()->object || - - // we are on Panther (no HIViewSetNeedsDisplayInRect) - QSysInfo::MacintoshVersion < QSysInfo::MV_10_4 - ){ - HIViewSetFrame(view, &bounds); - return; - } - - const int dx = newRect.x() - oldRect.x(); - const int dy = newRect.y() - oldRect.y(); - - if (isMove) { - // HIViewScrollRect silently fails if we try to scroll anything under the grow box. - // Check if there's one present within the widget rect, and if there is fall back - // to repainting the entire widget. - QWidget const * const parentWidget = q->parentWidget(); - const HIViewRef parentView = qt_mac_nativeview_for(parentWidget); - HIViewRef nativeSizeGrip = 0; - if (q->testAttribute(Qt::WA_WState_Created)) - HIViewFindByID(HIViewGetRoot(HIViewGetWindow(HIViewRef(q->winId()))), kHIViewWindowGrowBoxID, &nativeSizeGrip); - if (nativeSizeGrip) { - QWidget * const window = q->window(); - - const int sizeGripSize = 20; - const QRect oldWidgetRect = QRect(q->mapTo(window, QPoint(0, 0)), QSize(oldRect.width(), oldRect.height())); - const QRect newWidgetRect = QRect(q->mapTo(window, QPoint(0, 0)), QSize(newRect.width(), newRect.height())); - const QRect sizeGripRect = QRect(window->rect().bottomRight() - QPoint(sizeGripSize, sizeGripSize), - window->rect().bottomRight()); - - if (sizeGripRect.intersects(oldWidgetRect) || sizeGripRect.intersects(newWidgetRect)) { - HIViewSetFrame(view, &bounds); - return; - } - } - - // Don't scroll anything outside the parent widget rect. - const QRect scrollRect = (oldRect | newRect) & parentWidget->rect(); - const HIRect scrollBounds = - CGRectMake(scrollRect.x(), scrollRect.y(), scrollRect.width(), scrollRect.height()); - - // We cannot scroll when the widget has a mask as that would - // scroll the masked out areas too - if (qd->extra && qd->extra->hasMask) { - HIViewMoveBy(view, dx, dy); - return; - } - - OSStatus err = HIViewScrollRect(parentView, &scrollBounds, dx, dy); - if (err != noErr) { - HIViewSetNeedsDisplay(view, true); - qWarning("QWidget: Internal error (%s:%d)", __FILE__, __LINE__); - } - } - // Set the view bounds with drawing disabled to prevent repaints. - HIViewSetDrawingEnabled(view, false); - HIViewSetFrame(view, &bounds); - HIViewSetDrawingEnabled(view, true); - - // Update any newly exposed areas due to resizing. - const int startx = oldRect.width(); - const int stopx = newRect.width(); - const int starty = oldRect.height(); - const int stopy = newRect.height(); - - const HIRect verticalSlice = CGRectMake(startx, 0, stopx , stopy); - HIViewSetNeedsDisplayInRect(view, &verticalSlice, true); - const HIRect horizontalSlice = CGRectMake(0, starty, startx, stopy); - HIViewSetNeedsDisplayInRect(view, &horizontalSlice, true); -} -#endif - -/* - Helper function for non-toplevel widgets. Helps to map Qt's 32bit - coordinate system to OS X's 16bit coordinate system. - - Sets the geometry of the widget to data.crect, but clipped to sizes - that OS X can handle. Unmaps widgets that are completely outside the - valid range. - - Maintains data.wrect, which is the geometry of the OS X widget, - measured in this widget's coordinate system. - - if the parent is not clipped, parentWRect is empty, otherwise - parentWRect is the geometry of the parent's OS X rect, measured in - parent's coord sys -*/ -void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect) -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - - if (!q->internalWinId() && QApplicationPrivate::graphicsSystem() != 0) { - // We have no view to move, and no paint engine that - // we can update dirty regions on. So just return: - return; - } - - QMacCocoaAutoReleasePool pool; - - /* - There are up to four different coordinate systems here: - Qt coordinate system for this widget. - X coordinate system for this widget (relative to wrect). - Qt coordinate system for parent - X coordinate system for parent (relative to parent's wrect). - */ - - // wrect is the same as crect, except that it is - // clipped to fit inside parent (and screen): - QRect wrect; - - // wrectInParentCoordSys will be the same as wrect, except that it is - // originated in q's parent rather than q itself. It starts out in - // parent's Qt coord system, and ends up in parent's coordinate system: - QRect wrectInParentCoordSys = data.crect; - - // If q's parent has been clipped, parentWRect will - // be filled with the parents clipped crect: - QRect parentWRect; - - // Embedded have different meaning on each platform, and on - // Mac, it means that q is a QMacNativeWidget. - bool isEmbeddedWindow = (q->isWindow() && topData()->embedded); -#ifdef QT_MAC_USE_COCOA - NSView *nsview = qt_mac_nativeview_for(q); -#endif - if (!isEmbeddedWindow) { - parentWRect = q->parentWidget()->data->wrect; - } else { - // INVARIANT: q's parent view is not owned by Qt. So we need to - // do some extra calls to get the clipped rect of the parent view: -#ifndef QT_MAC_USE_COCOA - HIViewRef parentView = HIViewGetSuperview(qt_mac_nativeview_for(q)); -#else - NSView *parentView = [qt_mac_nativeview_for(q) superview]; -#endif - if (parentView) { -#ifndef QT_MAC_USE_COCOA - HIRect tmpRect; - HIViewGetFrame(parentView, &tmpRect); -#else - NSRect tmpRect = [parentView frame]; -#endif - parentWRect = QRect(tmpRect.origin.x, tmpRect.origin.y, - tmpRect.size.width, tmpRect.size.height); - } else { - const QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX); - parentWRect = wrectRange; - } - } - - if (parentWRect.isValid()) { - // INVARIANT: q's parent has been clipped. - // So we fit our own wrects inside it: - if (!parentWRect.contains(wrectInParentCoordSys) && !isEmbeddedWindow) { - wrectInParentCoordSys &= parentWRect; - wrect = wrectInParentCoordSys; - // Make sure wrect is originated in q's coordinate system: - wrect.translate(-data.crect.topLeft()); - } - // // Make sure wrectInParentCoordSys originated in q's parent coordinate system: - wrectInParentCoordSys.translate(-parentWRect.topLeft()); - } else { - // INVARIANT: we dont know yet the clipping rect of q's parent. - // So we may or may not have to adjust our wrects: - - if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) { - // This is where the main optimization is: we have an old wrect from an earlier - // setGeometry call, and the new crect is smaller than it. If the final wrect is - // also inside the old wrect, we can just move q and its children to the new - // location without any clipping: - - // vrect will be the part of q that's will be visible inside - // q's parent. If it inside the old wrect, then we can just move: - QRect vrect = wrectInParentCoordSys & q->parentWidget()->rect(); - vrect.translate(-data.crect.topLeft()); - - if (data.wrect.contains(vrect)) { - wrectInParentCoordSys = data.wrect; - wrectInParentCoordSys.translate(data.crect.topLeft()); -#ifndef QT_MAC_USE_COCOA - HIRect bounds = CGRectMake(wrectInParentCoordSys.x(), wrectInParentCoordSys.y(), - wrectInParentCoordSys.width(), wrectInParentCoordSys.height()); - HIViewSetFrame(qt_mac_nativeview_for(q), &bounds); -#else - if (nsview) { - // INVARIANT: q is native. Set view frame: - NSRect bounds = NSMakeRect(wrectInParentCoordSys.x(), wrectInParentCoordSys.y(), - wrectInParentCoordSys.width(), wrectInParentCoordSys.height()); - [nsview setFrame:bounds]; - } else { - // INVARIANT: q is alien. Repaint wrect instead (includes old and new wrect): - QWidget *parent = q->parentWidget(); - QPoint globalPosWRect = parent->mapToGlobal(data.wrect.topLeft()); - - QWidget *nativeParent = q->nativeParentWidget(); - QRect dirtyWRect = QRect(nativeParent->mapFromGlobal(globalPosWRect), data.wrect.size()); - - nativeParent->update(dirtyWRect); - } -#endif - if (q->testAttribute(Qt::WA_OutsideWSRange)) { - q->setAttribute(Qt::WA_OutsideWSRange, false); - if (!dontShow) { - q->setAttribute(Qt::WA_Mapped); -#ifndef QT_MAC_USE_COCOA - HIViewSetVisible(qt_mac_nativeview_for(q), true); -#else - // If q is Alien, the following call does nothing: - [nsview setHidden:NO]; -#endif - } - } - return; - } - } - -#ifndef QT_MAC_USE_COCOA - const QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX); - if (!validRange.contains(wrectInParentCoordSys)) { - // We're too big, and must clip: - QPoint screenOffset(0, 0); // offset of the part being on screen - const QWidget *parentWidget = q->parentWidget(); - while (parentWidget && !parentWidget->isWindow()) { - screenOffset -= parentWidget->data->crect.topLeft(); - parentWidget = parentWidget->parentWidget(); - } - QRect cropRect(screenOffset.x() - WRECT_MAX, - screenOffset.y() - WRECT_MAX, - 2*WRECT_MAX, - 2*WRECT_MAX); - - wrectInParentCoordSys &=cropRect; - wrect = wrectInParentCoordSys; - wrect.translate(-data.crect.topLeft()); - } -#endif //QT_MAC_USE_COCOA - } - - // unmap if we are outside the valid window system coord system - bool outsideRange = !wrectInParentCoordSys.isValid(); - bool mapWindow = false; - if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) { - q->setAttribute(Qt::WA_OutsideWSRange, outsideRange); - if (outsideRange) { -#ifndef QT_MAC_USE_COCOA - HIViewSetVisible(qt_mac_nativeview_for(q), false); -#else - // If q is Alien, the following call does nothing: - [nsview setHidden:YES]; -#endif - q->setAttribute(Qt::WA_Mapped, false); - } else if (!q->isHidden()) { - mapWindow = true; - } - } - - if (outsideRange) - return; - - // Store the new clipped rect: - bool jump = (data.wrect != wrect); - data.wrect = wrect; - - // and now recursively for all children... - // ### can be optimized - for (int i = 0; i < children.size(); ++i) { - QObject *object = children.at(i); - if (object->isWidgetType()) { - QWidget *w = static_cast<QWidget *>(object); - if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created)) - w->d_func()->setWSGeometry(); - } - } - -#ifndef QT_MAC_USE_COCOA - // Move the actual HIView: - qt_mac_update_widget_position(q, oldRect, wrectInParentCoordSys); - if (jump) - q->update(); -#else - if (nsview) { - // INVARIANT: q is native. Move the actual NSView: - NSRect bounds = NSMakeRect( - wrectInParentCoordSys.x(), wrectInParentCoordSys.y(), - wrectInParentCoordSys.width(), wrectInParentCoordSys.height()); - [nsview setFrame:bounds]; - if (jump) - q->update(); - } else if (QApplicationPrivate::graphicsSystem() == 0){ - // INVARIANT: q is alien and we use native paint engine. - // Schedule updates where q is moved from and to: - const QWidget *parent = q->parentWidget(); - const QPoint globalPosOldWRect = parent->mapToGlobal(oldRect.topLeft()); - const QPoint globalPosNewWRect = parent->mapToGlobal(wrectInParentCoordSys.topLeft()); - - QWidget *nativeParent = q->nativeParentWidget(); - const QRegion dirtyOldWRect = QRect(nativeParent->mapFromGlobal(globalPosOldWRect), oldRect.size()); - const QRegion dirtyNewWRect = QRect(nativeParent->mapFromGlobal(globalPosNewWRect), wrectInParentCoordSys.size()); - - const bool sizeUnchanged = oldRect.size() == wrectInParentCoordSys.size(); - const bool posUnchanged = oldRect.topLeft() == wrectInParentCoordSys.topLeft(); - - // Resolve/minimize the region that needs to update: - if (sizeUnchanged && q->testAttribute(Qt::WA_OpaquePaintEvent)) { - // INVARIANT: q is opaque, and is only moved (not resized). So in theory we only - // need to blit pixels, and skip a repaint. But we can only make this work if we - // had access to the backbuffer, so we need to update all: - nativeParent->update(dirtyOldWRect | dirtyNewWRect); - } else if (posUnchanged && q->testAttribute(Qt::WA_StaticContents)) { - // We only need to redraw exposed areas: - nativeParent->update(dirtyNewWRect - dirtyOldWRect); - } else { - nativeParent->update(dirtyOldWRect | dirtyNewWRect); - } - } -#endif - - if (mapWindow && !dontShow) { - q->setAttribute(Qt::WA_Mapped); -#ifndef QT_MAC_USE_COCOA - HIViewSetVisible(qt_mac_nativeview_for(q), true); -#else - // If q is Alien, the following call does nothing: - [nsview setHidden:NO]; -#endif - } -} - -void QWidgetPrivate::adjustWithinMaxAndMinSize(int &w, int &h) -{ - if (QWExtra *extra = extraData()) { - w = qMin(w, extra->maxw); - h = qMin(h, extra->maxh); - w = qMax(w, extra->minw); - h = qMax(h, extra->minh); - - // Deal with size increment - if (QTLWExtra *top = topData()) { - if(top->incw) { - w = w/top->incw; - w *= top->incw; - } - if(top->inch) { - h = h/top->inch; - h *= top->inch; - } - } - } - - if (isRealWindow()) { - w = qMax(0, w); - h = qMax(0, h); - } -} - -void QWidgetPrivate::applyMaxAndMinSizeOnWindow() -{ - Q_Q(QWidget); - QMacCocoaAutoReleasePool pool; - - const float max_f(20000); -#ifndef QT_MAC_USE_COCOA -#define SF(x) ((x > max_f) ? max_f : x) - HISize max = CGSizeMake(SF(extra->maxw), SF(extra->maxh)); - HISize min = CGSizeMake(SF(extra->minw), SF(extra->minh)); -#undef SF - SetWindowResizeLimits(qt_mac_window_for(q), &min, &max); -#else -#define SF(x) ((x > max_f) ? max_f : x) - NSSize max = NSMakeSize(SF(extra->maxw), SF(extra->maxh)); - NSSize min = NSMakeSize(SF(extra->minw), SF(extra->minh)); -#undef SF - [qt_mac_window_for(q) setContentMinSize:min]; - [qt_mac_window_for(q) setContentMaxSize:max]; -#endif -} - -void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - - if(q->windowType() == Qt::Desktop) - return; - - QMacCocoaAutoReleasePool pool; - bool realWindow = isRealWindow(); - - if (realWindow && !q->testAttribute(Qt::WA_DontShowOnScreen)){ - adjustWithinMaxAndMinSize(w, h); -#ifndef QT_MAC_USE_COCOA - if (w != 0 && h != 0) { - topData()->isSetGeometry = 1; - topData()->isMove = isMove; - Rect r; SetRect(&r, x, y, x + w, y + h); - SetWindowBounds(qt_mac_window_for(q), kWindowContentRgn, &r); - topData()->isSetGeometry = 0; - } else { - setGeometry_sys_helper(x, y, w, h, isMove); - } -#else - if (!isMove && !q->testAttribute(Qt::WA_Moved) && !q->isVisible()) { - // INVARIANT: The location of the window has not yet been set. The default will - // instead be to center it on the desktop, or over the parent, if any. Since we now - // resize the window, we need to adjust the top left position to keep the window - // centeralized. And we need to to this now (and before show) in case the positioning - // of other windows (e.g. sub-windows) depend on this position: - if (QWidget *p = q->parentWidget()) { - x = p->geometry().center().x() - (w / 2); - y = p->geometry().center().y() - (h / 2); - } else { - QRect availGeo = QApplication::desktop()->availableGeometry(q); - x = availGeo.center().x() - (w / 2); - y = availGeo.center().y() - (h / 2); - } - } - - QSize olds = q->size(); - const bool isResize = (olds != QSize(w, h)); - NSWindow *window = qt_mac_window_for(q); - const QRect &fStrut = frameStrut(); - const QRect frameRect(QPoint(x - fStrut.left(), y - fStrut.top()), - QSize(fStrut.left() + fStrut.right() + w, - fStrut.top() + fStrut.bottom() + h)); - NSRect cocoaFrameRect = NSMakeRect(frameRect.x(), flipYCoordinate(frameRect.bottom() + 1), - frameRect.width(), frameRect.height()); - // The setFrame call will trigger a 'windowDidResize' notification for the corresponding - // NSWindow. The pending flag is set, so that the resize event can be send as non-spontaneous. - if (isResize) - q->setAttribute(Qt::WA_PendingResizeEvent); - QPoint currTopLeft = data.crect.topLeft(); - if (currTopLeft.x() == x && currTopLeft.y() == y - && cocoaFrameRect.size.width != 0 - && cocoaFrameRect.size.height != 0) { - [window setFrame:cocoaFrameRect display:realWindow]; - } else { - // The window is moved and resized (or resized to zero). - // Since Cocoa usually only sends us a resize callback after - // setting a window frame, we issue an explicit move as - // well. To stop Cocoa from optimize away the move (since the move - // would have the same origin as the setFrame call) we shift the - // window back and forth inbetween. - cocoaFrameRect.origin.y += 1; - [window setFrame:cocoaFrameRect display:realWindow]; - cocoaFrameRect.origin.y -= 1; - [window setFrameOrigin:cocoaFrameRect.origin]; - } -#endif - } else { - setGeometry_sys_helper(x, y, w, h, isMove); - } - - topLevelAt_cache = 0; -} - -void QWidgetPrivate::setGeometry_sys_helper(int x, int y, int w, int h, bool isMove) -{ - Q_Q(QWidget); - bool realWindow = isRealWindow(); - - QPoint oldp = q->pos(); - QSize olds = q->size(); - const bool isResize = (olds != QSize(w, h)); - - if (!realWindow && !isResize && QPoint(x, y) == oldp) - return; - - if (isResize) - data.window_state = data.window_state & ~Qt::WindowMaximized; - - const bool visible = q->isVisible(); - // Apply size restrictions, applicable for Windows & Widgets. - if (QWExtra *extra = extraData()) { - w = qMin(w, extra->maxw); - h = qMin(h, extra->maxh); - w = qMax(w, extra->minw); - h = qMax(h, extra->minh); - } - data.crect = QRect(x, y, w, h); - - if (realWindow) { - adjustWithinMaxAndMinSize(w, h); - qt_mac_update_sizer(q); - -#ifndef QT_MAC_USE_COCOA - if (q->windowFlags() & Qt::WindowMaximizeButtonHint) { - OSWindowRef window = qt_mac_window_for(q); - if (extra->maxw && extra->maxh && extra->maxw == extra->minw - && extra->maxh == extra->minh) { - ChangeWindowAttributes(window, kWindowNoAttributes, kWindowFullZoomAttribute); - } else { - ChangeWindowAttributes(window, kWindowFullZoomAttribute, kWindowNoAttributes); - } - } - HIRect bounds = CGRectMake(0, 0, w, h); - HIViewSetFrame(qt_mac_nativeview_for(q), &bounds); -#else - [qt_mac_nativeview_for(q) setFrame:NSMakeRect(0, 0, w, h)]; -#endif - } else { - const QRect oldRect(oldp, olds); - if (!isResize && QApplicationPrivate::graphicsSystem()) - moveRect(oldRect, x - oldp.x(), y - oldp.y()); - - setWSGeometry(false, oldRect); - - if (isResize && QApplicationPrivate::graphicsSystem()) - invalidateBuffer_resizeHelper(oldp, olds); - } - - if(isMove || isResize) { - if(!visible) { - if(isMove && q->pos() != oldp) - q->setAttribute(Qt::WA_PendingMoveEvent, true); - if(isResize) - q->setAttribute(Qt::WA_PendingResizeEvent, true); - } else { - if(isResize) { //send the resize event.. - QResizeEvent e(q->size(), olds); - QApplication::sendEvent(q, &e); - } - if(isMove && q->pos() != oldp) { //send the move event.. - QMoveEvent e(q->pos(), oldp); - QApplication::sendEvent(q, &e); - } - } - } - qt_event_request_window_change(q); -} - -void QWidgetPrivate::setConstraints_sys() -{ - updateMaximizeButton_sys(); - applyMaxAndMinSizeOnWindow(); -} - -void QWidgetPrivate::updateMaximizeButton_sys() -{ - Q_Q(QWidget); - if (q->data->window_flags & Qt::CustomizeWindowHint) - return; - - OSWindowRef window = qt_mac_window_for(q); - QTLWExtra * tlwExtra = topData(); -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - NSButton *maximizeButton = [window standardWindowButton:NSWindowZoomButton]; -#endif - if (extra->maxw && extra->maxh - && extra->maxw == extra->minw - && extra->maxh == extra->minh) { - // The window has a fixed size, so gray out the maximize button: - if (!tlwExtra->savedWindowAttributesFromMaximized) { -#ifndef QT_MAC_USE_COCOA - GetWindowAttributes(window, - (WindowAttributes*)&extra->topextra->savedWindowAttributesFromMaximized); - -#else - tlwExtra->savedWindowAttributesFromMaximized = (![maximizeButton isHidden] && [maximizeButton isEnabled]); -#endif - } -#ifndef QT_MAC_USE_COCOA - ChangeWindowAttributes(window, kWindowNoAttributes, kWindowFullZoomAttribute); -#else - [maximizeButton setEnabled:NO]; -#endif - - - } else { - if (tlwExtra->savedWindowAttributesFromMaximized) { -#ifndef QT_MAC_USE_COCOA - ChangeWindowAttributes(window, - extra->topextra->savedWindowAttributesFromMaximized, - kWindowNoAttributes); -#else - [maximizeButton setEnabled:YES]; -#endif - tlwExtra->savedWindowAttributesFromMaximized = 0; - } - } - - -} - -void QWidgetPrivate::scroll_sys(int dx, int dy) -{ - if (QApplicationPrivate::graphicsSystem() && !paintOnScreen()) { - // INVARIANT: Alien paint engine - scrollChildren(dx, dy); - scrollRect(q_func()->rect(), dx, dy); - } else { - scroll_sys(dx, dy, QRect()); - } -} - -void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &qscrollRect) -{ - if (QMacScrollOptimization::delayScroll(this, dx, dy, qscrollRect)) - return; - - Q_Q(QWidget); - if (QApplicationPrivate::graphicsSystem() && !paintOnScreen()) { - // INVARIANT: Alien paint engine - scrollRect(qscrollRect, dx, dy); - return; - } - - static int accelEnv = -1; - if (accelEnv == -1) { - accelEnv = qgetenv("QT_NO_FAST_SCROLL").toInt() == 0; - } - - // Scroll the whole widget if qscrollRect is not valid: - QRect validScrollRect = qscrollRect.isValid() ? qscrollRect : q->rect(); - validScrollRect &= clipRect(); - - // If q is overlapped by other widgets, we cannot just blit pixels since - // this will move overlapping widgets as well. In case we just update: - const bool overlapped = isOverlapped(validScrollRect.translated(data.crect.topLeft())); - const bool accelerateScroll = accelEnv && isOpaque && !overlapped; - const bool isAlien = (q->internalWinId() == 0); - const QPoint scrollDelta(dx, dy); - - // If qscrollRect is valid, we are _not_ supposed to scroll q's children (as documented). - // But we do scroll children (and the whole of q) if qscrollRect is invalid. This case is - // documented as undefined, but we exploit it to help factor our code into one function. - const bool scrollChildren = !qscrollRect.isValid(); - - if (!q->updatesEnabled()) { - // We are told not to update anything on q at this point. So unless - // we are supposed to scroll children, we bail out early: - if (!scrollChildren || q->children().isEmpty()) - return; - } - - if (!accelerateScroll) { - if (overlapped) { - QRegion region(validScrollRect); - subtractOpaqueSiblings(region); - update_sys(region); - }else { - update_sys(qscrollRect); - } - return; - } - -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; -#else - Q_UNUSED(isAlien); - // We're not sure what the following call is supposed to achive - // but until we see what it breaks, we don't bring it into the - // Cocoa port: - qt_event_request_window_change(q); -#endif - - // First move all native children. Alien children will indirectly be - // moved when the parent is scrolled. All directly or indirectly moved - // children will receive a move event before the function call returns. - QWidgetList movedChildren; - if (scrollChildren) { - QObjectList children = q->children(); - - for (int i=0; i<children.size(); i++) { - QObject *obj = children.at(i); - if (QWidget *w = qobject_cast<QWidget*>(obj)) { - if (!w->isWindow()) { - w->data->crect = QRect(w->pos() + scrollDelta, w->size()); -#ifndef QT_MAC_USE_COCOA - if (w->testAttribute(Qt::WA_WState_Created)) { - HIRect bounds = CGRectMake(w->data->crect.x(), w->data->crect.y(), - w->data->crect.width(), w->data->crect.height()); - HIViewRef hiview = qt_mac_nativeview_for(w); - const bool opaque = q->testAttribute(Qt::WA_OpaquePaintEvent); - - if (opaque) - HIViewSetDrawingEnabled(hiview, false); - HIViewSetFrame(hiview, &bounds); - if (opaque) - HIViewSetDrawingEnabled(hiview, true); - } -#else - if (NSView *view = qt_mac_nativeview_for(w)) { - // INVARIANT: w is not alien - [view setFrame:NSMakeRect( - w->data->crect.x(), w->data->crect.y(), - w->data->crect.width(), w->data->crect.height())]; - } -#endif - movedChildren.append(w); - } - } - } - } - - if (q->testAttribute(Qt::WA_WState_Created) && q->isVisible()) { - // Scroll q itself according to the qscrollRect, and - // call update on any exposed areas so that they get redrawn: - -#ifndef QT_MAC_USE_COCOA - OSViewRef view = qt_mac_nativeview_for(q); - HIRect scrollrect = CGRectMake(qscrollRect.x(), qscrollRect.y(), qscrollRect.width(), qscrollRect.height()); - OSStatus err = _HIViewScrollRectWithOptions(view, qscrollRect.isValid() ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid); - if (err) { - // The only parameter that can go wrong, is the rect. - qWarning("QWidget::scroll: Your rectangle was too big for the widget, clipping rect"); - scrollrect = CGRectMake(qMax(qscrollRect.x(), 0), qMax(qscrollRect.y(), 0), - qMin(qscrollRect.width(), q->width()), qMin(qscrollRect.height(), q->height())); - _HIViewScrollRectWithOptions(view, qscrollRect.isValid() ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid); - } -#else - - QWidget *nativeWidget = isAlien ? q->nativeParentWidget() : q; - if (!nativeWidget) - return; - OSViewRef view = qt_mac_nativeview_for(nativeWidget); - if (!view) - return; - - // Calculate the rectangles that needs to be redrawn - // after the scroll. This will be source rect minus destination rect: - QRect deltaXRect; - if (dx != 0) { - deltaXRect.setY(validScrollRect.y()); - deltaXRect.setHeight(validScrollRect.height()); - if (dx > 0) { - deltaXRect.setX(validScrollRect.x()); - deltaXRect.setWidth(dx); - } else { - deltaXRect.setX(validScrollRect.x() + validScrollRect.width() + dx); - deltaXRect.setWidth(-dx); - } - } - - QRect deltaYRect; - if (dy != 0) { - deltaYRect.setX(validScrollRect.x()); - deltaYRect.setWidth(validScrollRect.width()); - if (dy > 0) { - deltaYRect.setY(validScrollRect.y()); - deltaYRect.setHeight(dy); - } else { - deltaYRect.setY(validScrollRect.y() + validScrollRect.height() + dy); - deltaYRect.setHeight(-dy); - } - } - - if (isAlien) { - // Adjust the scroll rect to the location as seen from the native parent: - QPoint scrollTopLeftInsideNative = nativeWidget->mapFromGlobal(q->mapToGlobal(validScrollRect.topLeft())); - validScrollRect.moveTo(scrollTopLeftInsideNative); - } - - // Make the pixel copy rect within the validScrollRect bounds: - NSRect nsscrollRect = NSMakeRect( - validScrollRect.x() + (dx < 0 ? -dx : 0), - validScrollRect.y() + (dy < 0 ? -dy : 0), - validScrollRect.width() + (dx > 0 ? -dx : 0), - validScrollRect.height() + (dy > 0 ? -dy : 0)); - - NSSize deltaSize = NSMakeSize(dx, dy); - [view scrollRect:nsscrollRect by:deltaSize]; - - // Some areas inside the scroll rect might have been marked as dirty from before, which - // means that they are scheduled to be redrawn. But as we now scroll, those dirty rects - // should also move along to ensure that q receives repaints on the correct places. - // Since some of the dirty rects might lay outside, or only intersect with, the scroll - // rect, the old calls to setNeedsDisplay still makes sense. - // NB: Using [view translateRectsNeedingDisplayInRect:nsscrollRect by:deltaSize] have - // so far not been proven fruitful to solve this problem. - const QVector<QRect> &dirtyRectsToScroll = dirtyOnWidget.rects(); - for (int i=0; i<dirtyRectsToScroll.size(); ++i) { - QRect qdirtyRect = dirtyRectsToScroll[i]; - qdirtyRect.translate(dx, dy); - update_sys(qdirtyRect); - } - - // Update newly exposed areas. This will generate new dirty areas on - // q, and therefore, we do it after updating the old dirty rects above: - if (dx != 0) - update_sys(deltaXRect); - if (dy != 0) - update_sys(deltaYRect); - -#endif // QT_MAC_USE_COCOA - } - - for (int i=0; i<movedChildren.size(); i++) { - QWidget *w = movedChildren.at(i); - QMoveEvent e(w->pos(), w->pos() - scrollDelta); - QApplication::sendEvent(w, &e); - } -} - -int QWidget::metric(PaintDeviceMetric m) const -{ - switch(m) { - case PdmHeightMM: - return qRound(metric(PdmHeight) * 25.4 / qreal(metric(PdmDpiY))); - case PdmWidthMM: - return qRound(metric(PdmWidth) * 25.4 / qreal(metric(PdmDpiX))); - case PdmHeight: - case PdmWidth: -#ifndef QT_MAC_USE_COCOA - { HIRect rect; - HIViewGetFrame(qt_mac_nativeview_for(this), &rect); - if(m == PdmWidth) - return (int)rect.size.width; - return (int)rect.size.height; } -#else - if (m == PdmWidth) - return data->crect.width(); - else - return data->crect.height(); -#endif - case PdmDepth: - return 32; - case PdmNumColors: - return INT_MAX; - case PdmDpiX: - case PdmPhysicalDpiX: { - Q_D(const QWidget); - if (d->extra && d->extra->customDpiX) - return d->extra->customDpiX; - else if (d->parent) - return static_cast<QWidget *>(d->parent)->metric(m); - extern float qt_mac_defaultDpi_x(); //qpaintdevice_mac.cpp - return int(qt_mac_defaultDpi_x()); } - case PdmDpiY: - case PdmPhysicalDpiY: { - Q_D(const QWidget); - if (d->extra && d->extra->customDpiY) - return d->extra->customDpiY; - else if (d->parent) - return static_cast<QWidget *>(d->parent)->metric(m); - extern float qt_mac_defaultDpi_y(); //qpaintdevice_mac.cpp - return int(qt_mac_defaultDpi_y()); } - default: //leave this so the compiler complains when new ones are added - qWarning("QWidget::metric: Unhandled parameter %d", m); - return QPaintDevice::metric(m); - } - return 0; -} - -void QWidgetPrivate::createSysExtra() -{ -#ifdef QT_MAC_USE_COCOA - extra->imageMask = 0; -#endif -} - -void QWidgetPrivate::deleteSysExtra() -{ -#ifdef QT_MAC_USE_COCOA - if (extra->imageMask) - CFRelease(extra->imageMask); -#endif -} - -void QWidgetPrivate::createTLSysExtra() -{ - extra->topextra->resizer = 0; - extra->topextra->isSetGeometry = 0; - extra->topextra->isMove = 0; - extra->topextra->wattr = 0; - extra->topextra->wclass = 0; - extra->topextra->group = 0; - extra->topextra->windowIcon = 0; - extra->topextra->savedWindowAttributesFromMaximized = 0; -} - -void QWidgetPrivate::deleteTLSysExtra() -{ -#ifndef QT_MAC_USE_COCOA - if (extra->topextra->group) { - qt_mac_release_window_group(extra->topextra->group); - extra->topextra->group = 0; - } - if (extra->topextra->windowIcon) { - ReleaseIconRef(extra->topextra->windowIcon); - extra->topextra->windowIcon = 0; - } -#endif -} - -void QWidgetPrivate::updateFrameStrut() -{ - Q_Q(QWidget); - - QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this); - - that->data.fstrut_dirty = false; - QTLWExtra *top = that->topData(); - -#if QT_MAC_USE_COCOA - // 1 Get the window frame - OSWindowRef oswnd = qt_mac_window_for(q); - NSRect frameW = [oswnd frame]; - // 2 Get the content frame - so now - NSRect frameC = [oswnd contentRectForFrameRect:frameW]; - top->frameStrut.setCoords(frameC.origin.x - frameW.origin.x, - (frameW.origin.y + frameW.size.height) - (frameC.origin.y + frameC.size.height), - (frameW.origin.x + frameW.size.width) - (frameC.origin.x + frameC.size.width), - frameC.origin.y - frameW.origin.y); -#else - Rect window_r; - GetWindowStructureWidths(qt_mac_window_for(q), &window_r); - top->frameStrut.setCoords(window_r.left, window_r.top, window_r.right, window_r.bottom); -#endif -} - -void QWidgetPrivate::registerDropSite(bool on) -{ - Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created)) - return; -#ifndef QT_MAC_USE_COCOA - SetControlDragTrackingEnabled(qt_mac_nativeview_for(q), on); -#else - NSWindow *win = qt_mac_window_for(q); - if (on) { - if ([win isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaWindow) class]]) - [static_cast<QT_MANGLE_NAMESPACE(QCocoaWindow) *>(win) registerDragTypes]; - else if ([win isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaPanel) class]]) - [static_cast<QT_MANGLE_NAMESPACE(QCocoaPanel) *>(win) registerDragTypes]; - } -#endif -} - -void QWidgetPrivate::registerTouchWindow(bool enable) -{ - Q_UNUSED(enable); -#ifdef QT_MAC_USE_COCOA -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_6) - return; - - Q_Q(QWidget); - if (enable == touchEventsEnabled) - return; - - QCocoaView *view = static_cast<QCocoaView *>(qt_mac_effectiveview_for(q)); - if (!view) - return; - - if (enable) { - ++view->alienTouchCount; - if (view->alienTouchCount == 1) { - touchEventsEnabled = true; - [view setAcceptsTouchEvents:YES]; - } - } else { - --view->alienTouchCount; - if (view->alienTouchCount == 0) { - touchEventsEnabled = false; - [view setAcceptsTouchEvents:NO]; - } - } -#endif -#endif -} - -void QWidgetPrivate::setMask_sys(const QRegion ®ion) -{ - Q_UNUSED(region); - Q_Q(QWidget); - -#ifndef QT_MAC_USE_COCOA - if (q->isWindow()) - ReshapeCustomWindow(qt_mac_window_for(q)); - else - HIViewReshapeStructure(qt_mac_nativeview_for(q)); -#else - if (!q->internalWinId()) - return; - - if (extra->mask.isEmpty()) { - extra->maskBits = QImage(); - finishCocoaMaskSetup(); - } else { - syncCocoaMask(); - } - - topLevelAt_cache = 0; -#endif -} - -void QWidgetPrivate::setWindowOpacity_sys(qreal level) -{ - Q_Q(QWidget); - - if (!q->isWindow()) - return; - - level = qBound(0.0, level, 1.0); - topData()->opacity = (uchar)(level * 255); - if (!q->testAttribute(Qt::WA_WState_Created)) - return; - - OSWindowRef oswindow = qt_mac_window_for(q); -#if QT_MAC_USE_COCOA - [oswindow setAlphaValue:level]; -#else - SetWindowAlpha(oswindow, level); -#endif -} - -#ifdef QT_MAC_USE_COCOA -void QWidgetPrivate::syncCocoaMask() -{ - Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created) || !extra) - return; - - if (extra->hasMask) { - if(extra->maskBits.size() != q->size()) { - extra->maskBits = QImage(q->size(), QImage::Format_Mono); - } - extra->maskBits.fill(QColor(Qt::color1).rgba()); - extra->maskBits.setNumColors(2); - extra->maskBits.setColor(0, QColor(Qt::color0).rgba()); - extra->maskBits.setColor(1, QColor(Qt::color1).rgba()); - QPainter painter(&extra->maskBits); - painter.setBrush(Qt::color1); - painter.setPen(Qt::NoPen); - painter.drawRects(extra->mask.rects()); - painter.end(); - finishCocoaMaskSetup(); - } -} - -void QWidgetPrivate::finishCocoaMaskSetup() -{ - Q_Q(QWidget); - - if (!q->testAttribute(Qt::WA_WState_Created) || !extra) - return; - - // Technically this is too late to release, because the data behind the image - // has already been released. But it's more tidy to do it here. - // If you are seeing a crash, consider doing a CFRelease before changing extra->maskBits. - if (extra->imageMask) { - CFRelease(extra->imageMask); - extra->imageMask = 0; - } - - if (!extra->maskBits.isNull()) { - QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(0, - extra->maskBits.bits(), - extra->maskBits.numBytes(), - 0); // shouldn't need to release. - CGFloat decode[2] = {1, 0}; - extra->imageMask = CGImageMaskCreate(extra->maskBits.width(), extra->maskBits.height(), - 1, 1, extra->maskBits.bytesPerLine(), dataProvider, - decode, false); - } - if (q->isWindow()) { - NSWindow *window = qt_mac_window_for(q); - [window setOpaque:(extra->imageMask == 0)]; - [window invalidateShadow]; - } - macSetNeedsDisplay(QRegion()); -} -#endif - -struct QPaintEngineCleanupHandler -{ - inline QPaintEngineCleanupHandler() : engine(0) {} - inline ~QPaintEngineCleanupHandler() { delete engine; } - QPaintEngine *engine; -}; - -Q_GLOBAL_STATIC(QPaintEngineCleanupHandler, engineHandler) - -QPaintEngine *QWidget::paintEngine() const -{ - QPaintEngine *&pe = engineHandler()->engine; - if (!pe) - pe = new QCoreGraphicsPaintEngine(); - if (pe->isActive()) { - QPaintEngine *engine = new QCoreGraphicsPaintEngine(); - engine->setAutoDestruct(true); - return engine; - } - return pe; -} - -void QWidgetPrivate::setModal_sys() -{ - Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow()) - return; - const QWidget * const windowParent = q->window()->parentWidget(); - const QWidget * const primaryWindow = windowParent ? windowParent->window() : 0; - OSWindowRef windowRef = qt_mac_window_for(q); - -#ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - bool alreadySheet = [windowRef styleMask] & NSDocModalWindowMask; - - if (windowParent && q->windowModality() == Qt::WindowModal){ - // INVARIANT: Window should be window-modal (which implies a sheet). - if (!alreadySheet) { - // NB: the following call will call setModal_sys recursivly: - recreateMacWindow(); - windowRef = qt_mac_window_for(q); - } - if ([windowRef isKindOfClass:[NSPanel class]]){ - // If the primary window of the sheet parent is a child of a modal dialog, - // the sheet parent should not be modally shaddowed. - // This goes for the sheet as well: - OSWindowRef ref = primaryWindow ? qt_mac_window_for(primaryWindow) : 0; - bool isDialog = ref ? [ref isKindOfClass:[NSPanel class]] : false; - bool worksWhenModal = isDialog ? [static_cast<NSPanel *>(ref) worksWhenModal] : false; - if (worksWhenModal) - [static_cast<NSPanel *>(windowRef) setWorksWhenModal:YES]; - } - } else { - // INVARIANT: Window shold _not_ be window-modal (and as such, not a sheet). - if (alreadySheet){ - // NB: the following call will call setModal_sys recursivly: - recreateMacWindow(); - windowRef = qt_mac_window_for(q); - } - if (q->windowModality() == Qt::NonModal - && primaryWindow && primaryWindow->windowModality() == Qt::ApplicationModal) { - // INVARIANT: Our window has a parent that is application modal. - // This means that q is supposed to be on top of this window and - // not be modally shaddowed: - if ([windowRef isKindOfClass:[NSPanel class]]) - [static_cast<NSPanel *>(windowRef) setWorksWhenModal:YES]; - } - } - -#else - const bool primaryWindowModal = primaryWindow ? primaryWindow->testAttribute(Qt::WA_ShowModal) : false; - const bool modal = q->testAttribute(Qt::WA_ShowModal); - - WindowClass old_wclass; - GetWindowClass(windowRef, &old_wclass); - - if (modal || primaryWindowModal) { - if (q->windowModality() == Qt::WindowModal - || (primaryWindow && primaryWindow->windowModality() == Qt::WindowModal)){ - // Window should be window-modal (which implies a sheet). - if (old_wclass != kSheetWindowClass){ - // We cannot convert a created window to a sheet. - // So we recreate the window: - recreateMacWindow(); - return; - } - } else { - // Window should be application-modal (which implies NOT using a sheet). - if (old_wclass == kSheetWindowClass){ - // We cannot convert a sheet to a window. - // So we recreate the window: - recreateMacWindow(); - return; - } else if (!(q->data->window_flags & Qt::CustomizeWindowHint)) { - if (old_wclass == kDocumentWindowClass || old_wclass == kFloatingWindowClass || old_wclass == kUtilityWindowClass){ - // Only change the class to kMovableModalWindowClass if the no explicit jewels - // are set (kMovableModalWindowClass can't contain them), and the current window class - // can be converted to modal (according to carbon doc). Mind the order of - // HIWindowChangeClass and ChangeWindowAttributes. - WindowGroupRef group = GetWindowGroup(windowRef); - HIWindowChangeClass(windowRef, kMovableModalWindowClass); - quint32 tmpWattr = kWindowCloseBoxAttribute | kWindowHorizontalZoomAttribute; - ChangeWindowAttributes(windowRef, tmpWattr, kWindowNoAttributes); - ChangeWindowAttributes(windowRef, kWindowNoAttributes, tmpWattr); - // If the window belongs to a qt-created group, set that group once more: - if (data.window_flags & Qt::WindowStaysOnTopHint - || q->windowType() == Qt::Popup - || q->windowType() == Qt::ToolTip) - SetWindowGroup(windowRef, group); - } - // Popups are usually handled "special" and are never modal. - Qt::WindowType winType = q->windowType(); - if (winType != Qt::Popup && winType != Qt::ToolTip) - SetWindowModality(windowRef, kWindowModalityAppModal, 0); - } - } - } else if (windowRef) { - if (old_wclass == kSheetWindowClass){ - // Converting a sheet to a window is complex. It's easier to recreate: - recreateMacWindow(); - return; - } - - SetWindowModality(windowRef, kWindowModalityNone, 0); - if (!(q->data->window_flags & Qt::CustomizeWindowHint)) { - if (q->window()->d_func()->topData()->wattr |= kWindowCloseBoxAttribute) - ChangeWindowAttributes(windowRef, kWindowCloseBoxAttribute, kWindowNoAttributes); - if (q->window()->d_func()->topData()->wattr |= kWindowHorizontalZoomAttribute) - ChangeWindowAttributes(windowRef, kWindowHorizontalZoomAttribute, kWindowNoAttributes); - if (q->window()->d_func()->topData()->wattr |= kWindowCollapseBoxAttribute) - ChangeWindowAttributes(windowRef, kWindowCollapseBoxAttribute, kWindowNoAttributes); - } - - WindowClass newClass = q->window()->d_func()->topData()->wclass; - if (old_wclass != newClass && newClass != 0){ - WindowGroupRef group = GetWindowGroup(windowRef); - HIWindowChangeClass(windowRef, newClass); - // If the window belongs to a qt-created group, set that group once more: - if (data.window_flags & Qt::WindowStaysOnTopHint - || q->windowType() == Qt::Popup - || q->windowType() == Qt::ToolTip) - SetWindowGroup(windowRef, group); - } - } - - // Make sure that HIWindowChangeClass didn't remove drag support - // or reset the opaque size grip setting: - SetAutomaticControlDragTrackingEnabledForWindow(windowRef, true); - macUpdateOpaqueSizeGrip(); -#endif -} - -void QWidgetPrivate::macUpdateHideOnSuspend() -{ - Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow() || q->windowType() != Qt::Tool) - return; -#ifndef QT_MAC_USE_COCOA - if(q->testAttribute(Qt::WA_MacAlwaysShowToolWindow)) - ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowHideOnSuspendAttribute); - else - ChangeWindowAttributes(qt_mac_window_for(q), kWindowHideOnSuspendAttribute, 0); -#else - if(q->testAttribute(Qt::WA_MacAlwaysShowToolWindow)) - [qt_mac_window_for(q) setHidesOnDeactivate:NO]; - else - [qt_mac_window_for(q) setHidesOnDeactivate:YES]; -#endif -} - -void QWidgetPrivate::macUpdateOpaqueSizeGrip() -{ - Q_Q(QWidget); - - if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow()) - return; - -#ifndef QT_MAC_USE_COCOA // Growbox is always transparent on Cocoa. Can emulate with setting a QSizeGrip - HIViewRef growBox; - HIViewFindByID(HIViewGetRoot(qt_mac_window_for(q)), kHIViewWindowGrowBoxID, &growBox); - if (!growBox) - return; - HIGrowBoxViewSetTransparent(growBox, !q->testAttribute(Qt::WA_MacOpaqueSizeGrip)); -#endif -} - -void QWidgetPrivate::macUpdateSizeAttribute() -{ - Q_Q(QWidget); - QEvent event(QEvent::MacSizeChange); - QApplication::sendEvent(q, &event); - for (int i = 0; i < children.size(); ++i) { - QWidget *w = qobject_cast<QWidget *>(children.at(i)); - if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation)) - && !q->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent - && !w->testAttribute(Qt::WA_MacSmallSize) - && !w->testAttribute(Qt::WA_MacNormalSize)) - w->d_func()->macUpdateSizeAttribute(); - } - resolveFont(); -} - -void QWidgetPrivate::macUpdateIgnoreMouseEvents() -{ -#ifndef QT_MAC_USE_COCOA // This is handled inside the mouse handler on Cocoa. - Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created)) - return; - - if(q->isWindow()) - { - if(q->testAttribute(Qt::WA_TransparentForMouseEvents)) - ChangeWindowAttributes(qt_mac_window_for(q), kWindowIgnoreClicksAttribute, 0); - else - ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowIgnoreClicksAttribute); - ReshapeCustomWindow(qt_mac_window_for(q)); - } else { -#ifndef kHIViewFeatureIgnoresClicks -#define kHIViewFeatureIgnoresClicks kHIViewIgnoresClicks -#endif - if(q->testAttribute(Qt::WA_TransparentForMouseEvents)) - HIViewChangeFeatures(qt_mac_nativeview_for(q), kHIViewFeatureIgnoresClicks, 0); - else - HIViewChangeFeatures(qt_mac_nativeview_for(q), 0, kHIViewFeatureIgnoresClicks); - HIViewReshapeStructure(qt_mac_nativeview_for(q)); - } -#endif -} - -void QWidgetPrivate::macUpdateMetalAttribute() -{ - Q_Q(QWidget); - bool realWindow = isRealWindow(); - if (!q->testAttribute(Qt::WA_WState_Created) || !realWindow) - return; - - if (realWindow) { -#if QT_MAC_USE_COCOA - // Cocoa doesn't let us change the style mask once it's been changed - // So, that means we need to recreate the window. - OSWindowRef cocoaWindow = qt_mac_window_for(q); - if ([cocoaWindow styleMask] & NSTexturedBackgroundWindowMask) - return; - recreateMacWindow(); -#else - QMainWindowLayout *layout = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q)); - if (q->testAttribute(Qt::WA_MacBrushedMetal)) { - if (layout) - layout->updateHIToolBarStatus(); - ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalAttribute, 0); - ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalNoContentSeparatorAttribute, 0); - } else { - ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalNoContentSeparatorAttribute); - ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalAttribute); - if (layout) - layout->updateHIToolBarStatus(); - } -#endif - } -} - -void QWidgetPrivate::setEnabled_helper_sys(bool enable) -{ -#ifdef QT_MAC_USE_COCOA - Q_Q(QWidget); - NSView *view = qt_mac_nativeview_for(q); - if ([view isKindOfClass:[NSControl class]]) - [static_cast<NSControl *>(view) setEnabled:enable]; -#else - Q_UNUSED(enable); -#endif -} - -QT_END_NAMESPACE |