diff options
Diffstat (limited to 'src/gui/kernel')
111 files changed, 13859 insertions, 3344 deletions
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index cb2b014..8489817 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -7,6 +7,7 @@ PRECOMPILED_HEADER = kernel/qt_gui_pch.h KERNEL_P= kernel HEADERS += \ kernel/qaction.h \ + kernel/qaction_p.h \ kernel/qactiongroup.h \ kernel/qapplication.h \ kernel/qapplication_p.h \ @@ -41,7 +42,11 @@ HEADERS += \ kernel/qwidgetaction.h \ kernel/qwidgetaction_p.h \ kernel/qwindowdefs.h \ - kernel/qkeymapper_p.h + kernel/qkeymapper_p.h \ + kernel/qgesture.h \ + kernel/qgesture_p.h \ + kernel/qstandardgestures.h \ + kernel/qstandardgestures_p.h SOURCES += \ kernel/qaction.cpp \ @@ -70,7 +75,9 @@ SOURCES += \ kernel/qwhatsthis.cpp \ kernel/qwidget.cpp \ kernel/qwidgetaction.cpp \ - kernel/qkeymapper.cpp + kernel/qkeymapper.cpp \ + kernel/qgesture.cpp \ + kernel/qstandardgestures.cpp win32 { DEFINES += QT_NO_DIRECTDRAW @@ -90,11 +97,33 @@ win32 { !contains(DEFINES, QT_NO_DIRECTDRAW):LIBS += ddraw.lib } +symbian { + SOURCES += \ + kernel/qapplication_s60.cpp \ + kernel/qeventdispatcher_s60.cpp \ + kernel/qwidget_s60.cpp \ + kernel/qcursor_s60.cpp \ + kernel/qdesktopwidget_s60.cpp \ + kernel/qkeymapper_s60.cpp\ + kernel/qclipboard_s60.cpp\ + kernel/qdnd_s60.cpp \ + kernel/qsound_s60.cpp + + HEADERS += \ + kernel/qt_s60_p.h \ + kernel/qeventdispatcher_s60_p.h + LIBS += -lbafl -lestor + + INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE +} + + unix:x11 { INCLUDEPATH += ../3rdparty/xorg HEADERS += \ kernel/qx11embed_x11.h \ - kernel/qx11info_x11.h + kernel/qx11info_x11.h \ + kernel/qkde_p.h SOURCES += \ kernel/qapplication_x11.cpp \ @@ -108,7 +137,8 @@ unix:x11 { kernel/qwidgetcreate_x11.cpp \ kernel/qx11embed_x11.cpp \ kernel/qx11info_x11.cpp \ - kernel/qkeymapper_x11.cpp + kernel/qkeymapper_x11.cpp \ + kernel/qkde.cpp contains(QT_CONFIG, glib) { SOURCES += \ @@ -116,7 +146,7 @@ unix:x11 { HEADERS += \ kernel/qguieventdispatcher_glib_p.h QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB - LIBS +=$$QT_LIBS_GLIB + LIBS_PRIVATE +=$$QT_LIBS_GLIB } SOURCES += \ kernel/qeventdispatcher_x11.cpp @@ -164,24 +194,26 @@ embedded { qcocoaview_mac_p.h \ qcocoaapplication_mac_p.h \ qcocoaapplicationdelegate_mac_p.h \ + qmultitouch_mac_p.h OBJECTIVE_SOURCES += \ kernel/qcursor_mac.mm \ kernel/qdnd_mac.mm \ kernel/qsound_mac.mm \ kernel/qapplication_mac.mm \ - kernel/qwidget_mac.mm \ - kernel/qcocoapanel_mac.mm \ - kernel/qcocoaview_mac.mm \ - kernel/qcocoawindow_mac.mm \ - kernel/qcocoawindowdelegate_mac.mm \ + kernel/qwidget_mac.mm \ + kernel/qcocoapanel_mac.mm \ + kernel/qcocoaview_mac.mm \ + kernel/qcocoawindow_mac.mm \ + kernel/qcocoawindowdelegate_mac.mm \ kernel/qcocoamenuloader_mac.mm \ kernel/qcocoaapplication_mac.mm \ kernel/qcocoaapplicationdelegate_mac.mm \ kernel/qt_cocoa_helpers_mac.mm \ - kernel/qdesktopwidget_mac.mm \ + kernel/qdesktopwidget_mac.mm \ kernel/qeventdispatcher_mac.mm \ - kernel/qcocoawindowcustomthemeframe_mac.mm + kernel/qcocoawindowcustomthemeframe_mac.mm \ + kernel/qmultitouch_mac.mm \ HEADERS += \ kernel/qt_cocoa_helpers_mac_p.h \ @@ -189,13 +221,13 @@ embedded { kernel/qcocoaapplicationdelegate_mac_p.h \ kernel/qeventdispatcher_mac_p.h - MENU_NIB.files = mac/qt_menu.nib - MENU_NIB.path = Resources + MENU_NIB.files = mac/qt_menu.nib + MENU_NIB.path = Resources MENU_NIB.version = Versions - QMAKE_BUNDLE_DATA += MENU_NIB - RESOURCES += mac/maccursors.qrc + QMAKE_BUNDLE_DATA += MENU_NIB + RESOURCES += mac/macresources.qrc - LIBS += -framework AppKit + LIBS_PRIVATE += -framework AppKit } wince*: { diff --git a/src/gui/kernel/mac.pri b/src/gui/kernel/mac.pri index 415fe0a..1538510 100644 --- a/src/gui/kernel/mac.pri +++ b/src/gui/kernel/mac.pri @@ -1,4 +1,4 @@ !x11:!embedded:mac { - LIBS += -framework Carbon -lz + LIBS_PRIVATE += -framework Carbon -lz *-mwerks:INCLUDEPATH += compat } diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp index 27d90c6..2a28c71 100644 --- a/src/gui/kernel/qaction.cpp +++ b/src/gui/kernel/qaction.cpp @@ -76,12 +76,13 @@ static QString qt_strippedText(QString s) s.remove(i-1,1); } return s.trimmed(); -}; +} QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0), visible(1), forceInvisible(0), checkable(0), checked(0), separator(0), fontSet(false), - menuRole(QAction::TextHeuristicRole), iconVisibleInMenu(-1) + menuRole(QAction::TextHeuristicRole), softKeyRole(QAction::OptionsSoftKey), + priority(QAction::NormalPriority), iconVisibleInMenu(-1) { #ifdef QT3_SUPPORT static int qt_static_action_id = -1; @@ -136,25 +137,31 @@ void QActionPrivate::redoGrab(QShortcutMap &map) void QActionPrivate::redoGrabAlternate(QShortcutMap &map) { Q_Q(QAction); - foreach (int id, alternateShortcutIds) - if (id) + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + if (const int id = alternateShortcutIds.at(i)) map.removeShortcut(id, q); + } alternateShortcutIds.clear(); if (alternateShortcuts.isEmpty()) return; - foreach (const QKeySequence& alternate, alternateShortcuts) { + for(int i = 0; i < alternateShortcuts.count(); ++i) { + const QKeySequence& alternate = alternateShortcuts.at(i); if (!alternate.isEmpty()) alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext)); else alternateShortcutIds.append(0); } if (!enabled) { - foreach (int id, alternateShortcutIds) + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + const int id = alternateShortcutIds.at(i); map.setShortcutEnabled(false, id, q); + } } if (!autorepeat) { - foreach (int id, alternateShortcutIds) + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + const int id = alternateShortcutIds.at(i); map.setShortcutAutoRepeat(false, id, q); + } } } @@ -163,9 +170,10 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map) Q_Q(QAction); if (shortcutId) map.setShortcutEnabled(enable, shortcutId, q); - foreach (int id, alternateShortcutIds) - if (id) + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + if (const int id = alternateShortcutIds.at(i)) map.setShortcutEnabled(enable, id, q); + } } #endif // QT_NO_SHORTCUT @@ -175,8 +183,8 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map) \brief The QAction class provides an abstract user interface action that can be inserted into widgets. - \ingroup application - \mainclass + \ingroup mainwindow-classes + \omit * parent and widget are different @@ -261,6 +269,26 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map) MenuRole for the actions in that submenu have no effect. They will never be moved. */ +/*! \enum QAction::SoftKeyRole + \value OptionsSoftKey + \value SelectSoftKey + \value BackSoftKey + \value NextSoftKey + \value PreviousSoftKey + \value OkSoftKey + \value CancelSoftKey + \value EditSoftKey + \value ViewSoftKey + \value BackSpaceSoftKey + \value EndEditSoftKey + \value RevertEditSoftKey + \value DeselectSoftKey + \value FinishSoftKey + \value MenuSoftKey + \value ContextMenuSoftKey + \value ExitSoftKey + */ + /*! Constructs an action with \a parent. If \a parent is an action group the action will be automatically inserted into the group. @@ -622,8 +650,10 @@ QAction::~QAction() #ifndef QT_NO_SHORTCUT if (d->shortcutId && qApp) { qApp->d_func()->shortcutMap.removeShortcut(d->shortcutId, this); - foreach (int id, d->alternateShortcutIds) + for(int i = 0; i < d->alternateShortcutIds.count(); ++i) { + const int id = d->alternateShortcutIds.at(i); qApp->d_func()->shortcutMap.removeShortcut(id, this); + } } #endif } @@ -905,6 +935,52 @@ QString QAction::whatsThis() const return d->whatsthis; } +/*! + \enum QAction::Priority + \since 4.6 + + This enum defines priorities for actions in user interface. + + \value LowPriority The action should not be prioritized in + the user interface. + + \value NormalPriority + + \value HighPriority The action should be prioritized in + the user interface. + + \sa priority +*/ + + +/*! + \property QAction::priority + \since 4.6 + + \brief the actions's priority in the user interface. + + This property can be set to indicate how the action should be prioritized + in the user interface. + + For instance, when toolbars have the Qt::ToolButtonTextBesideIcon + mode set, then actions with LowPriority will not show the text + labels. +*/ +void QAction::setPriority(Priority priority) +{ + Q_D(QAction); + if (d->priority == priority) + return; + + d->priority = priority; + d->sendDataChanged(); +} + +QAction::Priority QAction::priority() const +{ + Q_D(const QAction); + return d->priority; +} /*! \property QAction::checkable @@ -1158,6 +1234,8 @@ void QAction::activate(ActionEvent event) // the checked action of an exclusive group cannot be unchecked if (d->checked && (d->group && d->group->isExclusive() && d->group->checkedAction() == this)) { + if (guard) + emit triggered(true); QMetaObject::removeGuard(&guard); return; } @@ -1355,6 +1433,32 @@ QAction::MenuRole QAction::menuRole() const } /*! + \property QAction::softKeyRole + \brief the action's softkey role + \since 4.6 + + This indicates what softkey action this action is. Usually used on mobile + platforms to map QActions to hardware keys. + + The softkey role can be changed any time. +*/ +void QAction::setSoftKeyRole(SoftKeyRole softKeyRole) +{ + Q_D(QAction); + if (d->softKeyRole == softKeyRole) + return; + + d->softKeyRole = softKeyRole; + d->sendDataChanged(); +} + +QAction::SoftKeyRole QAction::softKeyRole() const +{ + Q_D(const QAction); + return d->softKeyRole; +} + +/*! \property QAction::iconVisibleInMenu \brief Whether or not an action should show an icon in a menu \since 4.4 @@ -1375,7 +1479,7 @@ QAction::MenuRole QAction::menuRole() const void QAction::setIconVisibleInMenu(bool visible) { Q_D(QAction); - if (visible != (bool)d->iconVisibleInMenu) { + if (d->iconVisibleInMenu == -1 || visible != bool(d->iconVisibleInMenu)) { int oldValue = d->iconVisibleInMenu; d->iconVisibleInMenu = visible; // Only send data changed if we really need to. diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h index d8d76a5..ef547ef 100644 --- a/src/gui/kernel/qaction.h +++ b/src/gui/kernel/qaction.h @@ -67,28 +67,39 @@ class Q_GUI_EXPORT QAction : public QObject Q_DECLARE_PRIVATE(QAction) Q_ENUMS(MenuRole) - Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable) + Q_ENUMS(SoftKeyRole) + Q_ENUMS(Priority) + Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY changed) Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled) - Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) - Q_PROPERTY(QIcon icon READ icon WRITE setIcon) - Q_PROPERTY(QString text READ text WRITE setText) - Q_PROPERTY(QString iconText READ iconText WRITE setIconText) - Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip) - Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip) - Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis) - Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY changed) + Q_PROPERTY(QIcon icon READ icon WRITE setIcon NOTIFY changed) + Q_PROPERTY(QString text READ text WRITE setText NOTIFY changed) + Q_PROPERTY(QString iconText READ iconText WRITE setIconText NOTIFY changed) + Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY changed) + Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip NOTIFY changed) + Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis NOTIFY changed) + Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed) #ifndef QT_NO_SHORTCUT - Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) - Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext) - Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat) + Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut NOTIFY changed) + Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext NOTIFY changed) + Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY changed) #endif - Q_PROPERTY(bool visible READ isVisible WRITE setVisible) - Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole) - Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu) + Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed) + Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed) + Q_PROPERTY(SoftKeyRole softKeyRole READ softKeyRole WRITE setSoftKeyRole NOTIFY changed) + Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed) + Q_PROPERTY(Priority priority READ priority WRITE setPriority) public: enum MenuRole { NoRole, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole, AboutRole, PreferencesRole, QuitRole }; + enum SoftKeyRole { OptionsSoftKey, SelectSoftKey, BackSoftKey, NextSoftKey, PreviousSoftKey, + OkSoftKey, CancelSoftKey, EditSoftKey, ViewSoftKey, BackSpaceSoftKey, + EndEditSoftKey, RevertEditSoftKey, DeselectSoftKey, FinishSoftKey, + MenuSoftKey, ContextMenuSoftKey, ExitSoftKey }; + enum Priority { LowPriority = 0, + NormalPriority = 128, + HighPriority = 256}; explicit QAction(QObject* parent); QAction(const QString &text, QObject* parent); QAction(const QIcon &icon, const QString &text, QObject* parent); @@ -123,6 +134,9 @@ public: void setWhatsThis(const QString &what); QString whatsThis() const; + void setPriority(Priority priority); + Priority priority() const; + #ifndef QT_NO_MENU QMenu *menu() const; void setMenu(QMenu *menu); @@ -168,6 +182,9 @@ public: void setMenuRole(MenuRole menuRole); MenuRole menuRole() const; + void setSoftKeyRole(SoftKeyRole softKeyRole); + SoftKeyRole softKeyRole() const; + void setIconVisibleInMenu(bool visible); bool isIconVisibleInMenu() const; diff --git a/src/gui/kernel/qaction_p.h b/src/gui/kernel/qaction_p.h index 5c6017c..34eccb2 100644 --- a/src/gui/kernel/qaction_p.h +++ b/src/gui/kernel/qaction_p.h @@ -102,6 +102,8 @@ public: uint separator : 1; uint fontSet : 1; QAction::MenuRole menuRole; + QAction::SoftKeyRole softKeyRole; + QAction::Priority priority; int iconVisibleInMenu : 3; // Only has values -1, 0, and 1 QList<QWidget *> widgets; #ifndef QT_NO_GRAPHICSVIEW diff --git a/src/gui/kernel/qactiongroup.cpp b/src/gui/kernel/qactiongroup.cpp index f1b7a50..daf3a2a 100644 --- a/src/gui/kernel/qactiongroup.cpp +++ b/src/gui/kernel/qactiongroup.cpp @@ -100,7 +100,7 @@ void QActionGroupPrivate::_q_actionHovered() \class QActionGroup \brief The QActionGroup class groups actions together. - \ingroup application + \ingroup mainwindow-classes In some situations it is useful to group actions together. For example, if you have a \gui{Left Align} action, a \gui{Right diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 327f5ce..511c797 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include "qplatformdefs.h" #include "qabstracteventdispatcher.h" #include "qaccessible.h" #include "qapplication.h" @@ -74,6 +75,9 @@ #ifdef Q_WS_X11 #include <private/qt_x11_p.h> +#endif + +#if defined(Q_WS_X11) || defined(Q_WS_S60) #include "qinputcontextfactory.h" #endif @@ -85,11 +89,12 @@ #include <stdlib.h> #include "qapplication_p.h" +#include "qevent_p.h" #include "qwidget_p.h" #include "qapplication.h" -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE #include "qdatetime.h" #include "qguifunctions_wince.h" extern bool qt_wince_is_smartphone(); //qguifunctions_wince.cpp @@ -97,19 +102,22 @@ extern bool qt_wince_is_mobile(); //qguifunctions_wince.cpp extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp #endif +#include "qdatetime.h" + +#ifdef QT_MAC_USE_COCOA +#include <private/qt_cocoa_helpers_mac_p.h> +#endif + //#define ALIEN_DEBUG static void initResources() { -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE Q_INIT_RESOURCE(qstyle_wince); #else Q_INIT_RESOURCE(qstyle); #endif -#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN) - Q_INIT_RESOURCE(qpaintengine_d3d); -#endif Q_INIT_RESOURCE(qmessagebox); #if !defined(QT_NO_PRINTDIALOG) Q_INIT_RESOURCE(qprintdialog); @@ -130,9 +138,11 @@ QInputContext *QApplicationPrivate::inputContext = 0; bool QApplicationPrivate::quitOnLastWindowClosed = true; -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE int QApplicationPrivate::autoMaximizeThreshold = -1; bool QApplicationPrivate::autoSipEnabled = false; +#else +bool QApplicationPrivate::autoSipEnabled = true; #endif QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type) @@ -173,16 +183,13 @@ QApplicationPrivate::~QApplicationPrivate() \brief The QApplication class manages the GUI application's control flow and main settings. - \ingroup application - \mainclass - QApplication contains the main event loop, where all events from the window system and other sources are processed and dispatched. It also handles the - application's initialization and finalization, and provides session - management. In addition, it handles most system-wide and application-wide - settings. + application's initialization, finalization, and provides session + management. In addition, QApplication handles most of the system-wide and + application-wide settings. - For any GUI application using Qt, there is precisely one QApplication + For any GUI application using Qt, there is precisely \bold one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any given time. For non-GUI Qt applications, use QCoreApplication instead, as it does not depend on the \l QtGui library. @@ -238,9 +245,9 @@ QApplicationPrivate::~QApplicationPrivate() saveState() for details. \endlist - The QApplication object does so much initialization. Hence, it \e{must} be + Since the QApplication object does so much initialization, it \e{must} be created before any other objects related to the user interface are created. - Since QApplication also deals with common command line arguments, it is + QApplication also deals with common command line arguments. Hence, it is usually a good idea to create it \e before any interpretation or modification of \c argv is done in the application itself. @@ -394,6 +401,7 @@ Qt::MouseButtons QApplicationPrivate::mouse_buttons = Qt::NoButton; Qt::KeyboardModifiers QApplicationPrivate::modifier_buttons = Qt::NoModifier; QStyle *QApplicationPrivate::app_style = 0; // default application style +QString QApplicationPrivate::styleOverride; // style override #ifndef QT_NO_STYLE_STYLESHEET QString QApplicationPrivate::styleSheet; // default application stylesheet @@ -408,7 +416,7 @@ QPalette *QApplicationPrivate::set_pal = 0; // default palette set by pro QGraphicsSystem *QApplicationPrivate::graphics_system = 0; // default graphics system QString QApplicationPrivate::graphics_system_name; // graphics system id - for delayed initialization -Q_GLOBAL_STATIC(QMutex, applicationFontMutex); +Q_GLOBAL_STATIC(QMutex, applicationFontMutex) QFont *QApplicationPrivate::app_font = 0; // default application font QFont *QApplicationPrivate::sys_font = 0; // default system font QFont *QApplicationPrivate::set_font = 0; // default font set by programmer @@ -430,7 +438,12 @@ bool Q_GUI_EXPORT qt_tab_all_widgets = true; bool qt_in_tab_key_event = false; int qt_antialiasing_threshold = -1; static int drag_time = 500; +#ifdef Q_OS_SYMBIAN +// The screens are a bit too small to for your thumb when using only 4 pixels drag distance. +static int drag_distance = 8; +#else static int drag_distance = 4; +#endif static Qt::LayoutDirection layout_direction = Qt::LeftToRight; QSize QApplicationPrivate::app_strut = QSize(0,0); // no default application strut bool QApplicationPrivate::animate_ui = true; @@ -441,12 +454,15 @@ bool QApplicationPrivate::animate_tooltip = false; bool QApplicationPrivate::fade_tooltip = false; bool QApplicationPrivate::animate_toolbox = false; bool QApplicationPrivate::widgetCount = false; -QString* QApplicationPrivate::styleOverride = 0; -#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) bool QApplicationPrivate::inSizeMove = false; #endif #ifdef QT_KEYPAD_NAVIGATION +# if defined(Q_OS_SYMBIAN) +bool QApplicationPrivate::keypadNavigation = true; +# else bool QApplicationPrivate::keypadNavigation = false; +# endif QWidget *QApplicationPrivate::oldEditFocus = 0; #endif @@ -466,15 +482,12 @@ static inline bool isAlien(QWidget *widget) // ######## move to QApplicationPrivate // Default application palettes and fonts (per widget type) - -typedef QHash<QByteArray, QPalette> PaletteHash; Q_GLOBAL_STATIC(PaletteHash, app_palettes) PaletteHash *qt_app_palettes_hash() { return app_palettes(); } -typedef QHash<QByteArray, QFont> FontHash; Q_GLOBAL_STATIC(FontHash, app_fonts) FontHash *qt_app_fonts_hash() { @@ -494,8 +507,6 @@ QWidgetList * qt_modal_stack=0; // stack of modal widgets */ void QApplicationPrivate::process_cmdline() { - Q_Q(QApplication); - Q_UNUSED(q);// only static members being used. // process platform-indep command line if (!qt_is_gui_used || !argc) return; @@ -540,7 +551,7 @@ void QApplicationPrivate::process_cmdline() #endif } else if (qstrcmp(arg, "-reverse") == 0) { force_reverse = true; - q->setLayoutDirection(Qt::RightToLeft); + QApplication::setLayoutDirection(Qt::RightToLeft); } else if (qstrcmp(arg, "-widgetcount") == 0) { widgetCount = true; } else if (arg == "-graphicssystem" && i < argc-1) { @@ -553,9 +564,7 @@ void QApplicationPrivate::process_cmdline() delete app_style; app_style = 0; } - if (!styleOverride) - styleOverride = new QString; - *styleOverride = s; + styleOverride = s; } } @@ -620,13 +629,6 @@ void QApplicationPrivate::process_cmdline() and QPixmaps. Available options are \c{raster} and \c{opengl}. \endlist - The Windows version of Qt supports an additional command line option, if - Direct3D support has been compiled into Qt: - \list - \o -direct3d will make the Direct3D paint engine the default widget - paint engine in Qt. \bold {This functionality is experimental.} - \endlist - The X11 version of Qt supports some traditional X11 command line options: \list \o -display \e display, sets the X display (default is $DISPLAY). @@ -686,9 +688,9 @@ QApplication::QApplication(int &argc, char **argv, int _internal) On X11, the window system is initialized if \a GUIenabled is true. If \a GUIenabled is false, the application does not connect to the X server. - On Windows and Macintosh, currently the window system is always - initialized, regardless of the value of GUIenabled. This may change in - future versions of Qt. + On Windows and Mac OS, currently the window system is always initialized, + regardless of the value of GUIenabled. This may change in future versions + of Qt. The following example shows how to create an application that uses a graphical interface when available. @@ -833,6 +835,12 @@ QApplication::QApplication(Display *dpy, int &argc, char **argv, #endif // Q_WS_X11 extern void qInitDrawhelperAsm(); +extern int qRegisterGuiVariant(); +extern int qUnregisterGuiVariant(); +#ifndef QT_NO_STATEMACHINE +extern int qRegisterGuiStateMachine(); +extern int qUnregisterGuiStateMachine(); +#endif /*! \fn void QApplicationPrivate::initialize() @@ -842,12 +850,15 @@ extern void qInitDrawhelperAsm(); void QApplicationPrivate::initialize() { QWidgetPrivate::mapper = new QWidgetMapper; - QWidgetPrivate::uncreatedWidgets = new QWidgetSet; + QWidgetPrivate::allWidgets = new QWidgetSet; if (qt_appType != QApplication::Tty) (void) QApplication::style(); // trigger creation of application style // trigger registering of QVariant's GUI types - extern int qRegisterGuiVariant(); qRegisterGuiVariant(); +#ifndef QT_NO_STATEMACHINE + // trigger registering of QStateMachine's GUI types + qRegisterGuiStateMachine(); +#endif is_app_running = true; // no longer starting up @@ -860,13 +871,7 @@ void QApplicationPrivate::initialize() if (qgetenv("QT_USE_NATIVE_WINDOWS").toInt() > 0) q->setAttribute(Qt::AA_NativeWindows); -#if defined(Q_WS_WIN) - // Alien is not currently working on Windows 98 - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) - q->setAttribute(Qt::AA_NativeWindows); -#endif - -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE #ifdef QT_AUTO_MAXIMIZE_THRESHOLD autoMaximizeThreshold = QT_AUTO_MAXIMIZE_THRESHOLD; #else @@ -875,7 +880,7 @@ void QApplicationPrivate::initialize() else autoMaximizeThreshold = -1; #endif //QT_AUTO_MAXIMIZE_THRESHOLD -#endif //Q_OS_WINCE +#endif //Q_WS_WINCE // Set up which span functions should be used in raster engine... qInitDrawhelperAsm(); @@ -893,6 +898,8 @@ void QApplicationPrivate::initialize() QApplicationPrivate::wheel_scroll_lines = 3; #endif #endif + + initializeMultitouch(); } /*! @@ -987,23 +994,14 @@ QApplication::~QApplication() qt_clipboard = 0; #endif - // delete widget mapper - if (QWidgetPrivate::mapper) { - QWidgetMapper * myMapper = QWidgetPrivate::mapper; - QWidgetPrivate::mapper = 0; - for (QWidgetMapper::Iterator it = myMapper->begin(); it != myMapper->end(); ++it) { - register QWidget *w = *it; - if (!w->parent()) // window - w->destroy(true, true); - } - delete myMapper; - } + delete QWidgetPrivate::mapper; + QWidgetPrivate::mapper = 0; - // delete uncreated widgets - if (QWidgetPrivate::uncreatedWidgets) { - QWidgetSet *mySet = QWidgetPrivate::uncreatedWidgets; - QWidgetPrivate::uncreatedWidgets = 0; - for (QWidgetSet::Iterator it = mySet->begin(); it != mySet->end(); ++it) { + // delete all widgets + if (QWidgetPrivate::allWidgets) { + QWidgetSet *mySet = QWidgetPrivate::allWidgets; + QWidgetPrivate::allWidgets = 0; + for (QWidgetSet::ConstIterator it = mySet->constBegin(); it != mySet->constEnd(); ++it) { register QWidget *w = *it; if (!w->parent()) // window w->destroy(true, true); @@ -1043,6 +1041,8 @@ QApplication::~QApplication() delete QDragManager::self(); #endif + d->cleanupMultitouch(); + qt_cleanup(); if (QApplicationPrivate::widgetCount) @@ -1069,8 +1069,11 @@ QApplication::~QApplication() QApplicationPrivate::fade_tooltip = false; QApplicationPrivate::widgetCount = false; +#ifndef QT_NO_STATEMACHINE + // trigger unregistering of QStateMachine's GUI types + qUnregisterGuiStateMachine(); +#endif // trigger unregistering of QVariant's GUI types - extern int qUnregisterGuiVariant(); qUnregisterGuiVariant(); } @@ -1197,21 +1200,22 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis \since 4.4 \brief defines a threshold for auto maximizing widgets - The auto maximize threshold is only available as part of Qt for Windows CE. + \bold{The auto maximize threshold is only available as part of Qt for + Windows CE.} This property defines a threshold for the size of a window as a percentage of the screen size. If the minimum size hint of a window exceeds the - threshold, calling show() will then cause the window to be maximized + threshold, calling show() will cause the window to be maximized automatically. - Setting the threshold to be 100 or greater means that it will cause it to - always be maximized. Setting it to be 50 means that the widget is maximized - if the vertical minimum size hint is at least 50% of the vertical screen - size. + Setting the threshold to 100 or greater means that the widget will always + be maximized. Alternatively, setting the threshold to 50 means that the + widget will be maximized only if the vertical minimum size hint is at least + 50% of the vertical screen size. - If -1 is specified then this will disable the feature. + Setting the threshold to -1 disables the feature. - On Windows CE the default is -1 (i.e. it is disabled). + On Windows CE the default is -1 (i.e., it is disabled). On Windows Mobile the default is 40. */ @@ -1220,14 +1224,18 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis \since 4.5 \brief toggles automatic SIP (software input panel) visibility - The auto SIP property is only available as part of Qt for Windows CE. - - Set this property to true to automatically display the SIP when entering + Set this property to \c true to automatically display the SIP when entering widgets that accept keyboard input. This property only affects widgets with - the WA_InputMethodEnabled attribute set. + the WA_InputMethodEnabled attribute set, and is typically used to launch + a virtual keyboard on devices which have very few or no keys. + + \bold{ The property only has an effect on platforms which use software input + panels, such as Windows CE and Symbian.} + + The default is platform dependent. */ -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE void QApplication::setAutoMaximizeThreshold(const int threshold) { QApplicationPrivate::autoMaximizeThreshold = threshold; @@ -1237,6 +1245,7 @@ int QApplication::autoMaximizeThreshold() const { return QApplicationPrivate::autoMaximizeThreshold; } +#endif void QApplication::setAutoSipEnabled(const bool enabled) { @@ -1247,7 +1256,6 @@ bool QApplication::autoSipEnabled() const { return QApplicationPrivate::autoSipEnabled; } -#endif #ifndef QT_NO_STYLE_STYLESHEET @@ -1289,44 +1297,14 @@ QStyle *QApplication::style() return 0; } -#if defined(Q_WS_X11) - if(!QApplicationPrivate::styleOverride) - QApplicationPrivate::x11_initialize_style(); // run-time search for default style -#endif if (!QApplicationPrivate::app_style) { // Compile-time search for default style // QString style; - if (QApplicationPrivate::styleOverride) { - style = *QApplicationPrivate::styleOverride; - delete QApplicationPrivate::styleOverride; - QApplicationPrivate::styleOverride = 0; - } else { -#if defined(Q_WS_WIN) && defined(Q_OS_WINCE) - if (qt_wince_is_smartphone() || qt_wince_is_pocket_pc()) - style = QLatin1String("WindowsMobile"); - else - style = QLatin1String("WindowsCE"); - -#elif defined(Q_WS_WIN) - if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA - && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) - style = QLatin1String("WindowsVista"); - else if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP - && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) - style = QLatin1String("WindowsXP"); - else - style = QLatin1String("Windows"); // default styles for Windows -#elif defined(Q_WS_X11) && defined(Q_OS_SOLARIS) - style = QLatin1String("CDE"); // default style for X11 on Solaris -#elif defined(Q_WS_X11) && defined(Q_OS_IRIX) - style = QLatin1String("SGI"); // default style for X11 on IRIX -#elif defined(Q_WS_X11) || defined(Q_WS_QWS) - style = QLatin1String("Plastique"); // default style for X11 and small devices -#elif defined(Q_WS_MAC) - style = QLatin1String("Macintosh"); // default style for all Mac's -#endif - } + if (!QApplicationPrivate::styleOverride.isEmpty()) + style = QApplicationPrivate::styleOverride; + else + style = QApplicationPrivate::desktopStyleKey(); QStyle *&app_style = QApplicationPrivate::app_style; app_style = QStyleFactory::create(style); @@ -1414,7 +1392,6 @@ void QApplication::setStyle(QStyle *style) } else #endif // QT_NO_STYLE_STYLESHEET QApplicationPrivate::app_style = style; - QApplicationPrivate::app_style->setParent(qApp); // take ownership // take care of possible palette requirements of certain gui @@ -1551,7 +1528,7 @@ int QApplication::colorSpec() strategy. Use this option if your application uses buttons, menus, texts and pixmaps with few colors. With this option, the application uses system global colors. This works fine for most - applications under X11, but on Windows machines it may cause + applications under X11, but on the Windows platform, it may cause dithering of non-standard colors. \o QApplication::CustomColor. Use this option if your application needs a small number of custom colors. On X11, this option is the @@ -1938,6 +1915,44 @@ void QApplicationPrivate::setSystemFont(const QFont &font) QApplication::setFont(*sys_font); } +/*! \internal +*/ +QString QApplicationPrivate::desktopStyleKey() +{ +QString desktopstyle; +#if defined(Q_WS_WIN) && defined(Q_WS_WINCE) + if (qt_wince_is_smartphone() || qt_wince_is_pocket_pc()) + desktopstyle = QLatin1String("WindowsMobile"); + else + desktopstyle = QLatin1String("WindowsCE"); + +#elif defined(Q_WS_WIN) + if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA + && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) + desktopstyle = QLatin1String("WindowsVista"); + else if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP + && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) + desktopstyle = QLatin1String("WindowsXP"); + else + desktopstyle = QLatin1String("Windows"); // default styles for Windows +#elif defined(Q_WS_X11) && defined(Q_OS_SOLARIS) + desktopstyle = QLatin1String("CDE"); // default style for X11 on Solaris +#elif defined(Q_WS_S60) + desktopstyle = QLatin1String("S60"); // default style for Symbian with S60 +#elif defined(Q_OS_SYMBIAN) + desktopstyle = QLatin1String("Windows"); // default style for Symbian without S60 +#elif defined(Q_WS_X11) && defined(Q_OS_IRIX) + desktopstyle = QLatin1String("SGI"); // default style for X11 on IRIX +#elif defined(Q_WS_QWS) + desktopstyle = QLatin1String("Plastique"); // default style for X11 and small devices +#elif defined(Q_WS_X11) + desktopstyle = QApplicationPrivate::x11_desktop_style(); // default runtime dependant style for X11 +#elif defined(Q_WS_MAC) + desktopstyle = QLatin1String("Macintosh"); // default style for all Mac's +#endif + return desktopstyle; +} + /*! \property QApplication::windowIcon \brief the default window icon @@ -2010,12 +2025,9 @@ QWidgetList QApplication::topLevelWidgets() QWidgetList QApplication::allWidgets() { - QWidgetList list; - if (QWidgetPrivate::mapper) - list += QWidgetPrivate::mapper->values(); - if (QWidgetPrivate::uncreatedWidgets) - list += QWidgetPrivate::uncreatedWidgets->toList(); - return list; + if (QWidgetPrivate::allWidgets) + return QWidgetPrivate::allWidgets->toList(); + return QWidgetList(); } /*! @@ -2080,6 +2092,16 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) prev->setEditFocus(false); } #endif +#ifndef QT_NO_IM + if (focus) { + QInputContext *prevIc; + prevIc = prev->inputContext(); + if (prevIc && prevIc != focus->inputContext()) { + QEvent closeSIPEvent(QEvent::CloseSoftwareInputPanel); + QApplication::sendEvent(prev, &closeSIPEvent); + } + } +#endif QFocusEvent out(QEvent::FocusOut, reason); QPointer<QWidget> that = prev; QApplication::sendEvent(prev, &out); @@ -2089,8 +2111,9 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) if(focus && QApplicationPrivate::focus_widget == focus) { if (focus->testAttribute(Qt::WA_InputMethodEnabled)) { QInputContext *qic = focus->inputContext(); - if (qic && focus_widget->testAttribute(Qt::WA_WState_Created)) - qic->setFocusWidget( focus_widget ); + if (qic && focus->testAttribute(Qt::WA_WState_Created) + && focus->isEnabled()) + qic->setFocusWidget(focus); } QFocusEvent in(QEvent::FocusIn, reason); QPointer<QWidget> that = focus; @@ -2309,10 +2332,6 @@ bool QApplication::event(QEvent *e) } else if (te->timerId() == d->toolTipFallAsleep.timerId()) { d->toolTipFallAsleep.stop(); } -#ifdef QT_MAC_USE_COCOA - } else if (e->type() == QEvent::CocoaRequestModal) { - d->_q_runAppModalWindow(); -#endif } return QCoreApplication::event(e); } @@ -2576,14 +2595,14 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) { QEvent leaveEvent(QEvent::Leave); for (int i = 0; i < leaveList.size(); ++i) { w = leaveList.at(i); - if (!qApp->activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) { + if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) { #if defined(Q_WS_WIN) || defined(Q_WS_X11) if (leaveAfterRelease == w) leaveAfterRelease = 0; #endif QApplication::sendEvent(w, &leaveEvent); if (w->testAttribute(Qt::WA_Hover) && - (!qApp->activePopupWidget() || qApp->activePopupWidget() == w->window())) { + (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) { Q_ASSERT(instance()); QHoverEvent he(QEvent::HoverLeave, QPoint(-1, -1), w->mapFromGlobal(QApplicationPrivate::instance()->hoverGlobalPos)); qApp->d_func()->notify_helper(w, &he); @@ -2594,10 +2613,10 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) { QEvent enterEvent(QEvent::Enter); for (int i = 0; i < enterList.size(); ++i) { w = enterList.at(i); - if (!qApp->activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) { + if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) { QApplication::sendEvent(w, &enterEvent); if (w->testAttribute(Qt::WA_Hover) && - (!qApp->activePopupWidget() || qApp->activePopupWidget() == w->window())) { + (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) { QHoverEvent he(QEvent::HoverEnter, w->mapFromGlobal(posEnter), QPoint(-1, -1)); qApp->d_func()->notify_helper(w, &he); } @@ -2671,7 +2690,7 @@ bool QApplicationPrivate::isBlockedByModal(QWidget *widget) widget = widget->window(); if (!modalState()) return false; - if (qApp->activePopupWidget() == widget) + if (QApplication::activePopupWidget() == widget) return false; for (int i = 0; i < qt_modal_stack->size(); ++i) { @@ -2760,7 +2779,7 @@ bool QApplicationPrivate::isBlockedByModal(QWidget *widget) void QApplicationPrivate::enterModal(QWidget *widget) { QSet<QWidget*> blocked; - QList<QWidget*> windows = qApp->topLevelWidgets(); + QList<QWidget*> windows = QApplication::topLevelWidgets(); for (int i = 0; i < windows.count(); ++i) { QWidget *window = windows.at(i); if (window->windowType() != Qt::Tool && isBlockedByModal(window)) @@ -2769,7 +2788,7 @@ void QApplicationPrivate::enterModal(QWidget *widget) enterModal_sys(widget); - windows = qApp->topLevelWidgets(); + windows = QApplication::topLevelWidgets(); QEvent e(QEvent::WindowBlocked); for (int i = 0; i < windows.count(); ++i) { QWidget *window = windows.at(i); @@ -2783,7 +2802,7 @@ void QApplicationPrivate::enterModal(QWidget *widget) void QApplicationPrivate::leaveModal(QWidget *widget) { QSet<QWidget*> blocked; - QList<QWidget*> windows = qApp->topLevelWidgets(); + QList<QWidget*> windows = QApplication::topLevelWidgets(); for (int i = 0; i < windows.count(); ++i) { QWidget *window = windows.at(i); if (window->windowType() != Qt::Tool && isBlockedByModal(window)) @@ -2792,7 +2811,7 @@ void QApplicationPrivate::leaveModal(QWidget *widget) leaveModal_sys(widget); - windows = qApp->topLevelWidgets(); + windows = QApplication::topLevelWidgets(); QEvent e(QEvent::WindowUnblocked); for (int i = 0; i < windows.count(); ++i) { QWidget *window = windows.at(i); @@ -2815,7 +2834,7 @@ bool QApplicationPrivate::tryModalHelper(QWidget *widget, QWidget **rettop) *rettop = top; // the active popup widget always gets the input event - if (qApp->activePopupWidget()) + if (QApplication::activePopupWidget()) return true; #if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA) @@ -2849,7 +2868,7 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint QWidget *receiver = candidate; if (!mouseGrabber) - mouseGrabber = buttonDown ? buttonDown : alienWidget; + mouseGrabber = (buttonDown && !isBlockedByModal(buttonDown)) ? buttonDown : alienWidget; if (mouseGrabber && mouseGrabber != candidate) { receiver = mouseGrabber; @@ -2868,7 +2887,8 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint */ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget, QWidget *nativeWidget, - QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver) + QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver, + bool spontaneous) { Q_ASSERT(receiver); Q_ASSERT(event); @@ -2881,7 +2901,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, QPointer<QWidget> receiverGuard = receiver; QPointer<QWidget> nativeGuard = nativeWidget; QPointer<QWidget> alienGuard = alienWidget; - QPointer<QWidget> activePopupWidget = qApp->activePopupWidget(); + QPointer<QWidget> activePopupWidget = QApplication::activePopupWidget(); const bool graphicsWidget = nativeWidget->testAttribute(Qt::WA_DontShowOnScreen); @@ -2921,7 +2941,11 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, // We need this quard in case someone opens a modal dialog / popup. If that's the case // leaveAfterRelease is set to null, but we shall not update lastMouseReceiver. const bool wasLeaveAfterRelease = leaveAfterRelease != 0; - bool result = QApplication::sendSpontaneousEvent(receiver, event); + bool result; + if (spontaneous) + result = QApplication::sendSpontaneousEvent(receiver, event); + else + result = QApplication::sendEvent(receiver, event); if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease && !event->buttons() && QWidget::mouseGrabber() != leaveAfterRelease) { @@ -3477,6 +3501,15 @@ void QApplication::changeOverrideCursor(const QCursor &cursor) if (qApp->d_func()->cursor_list.isEmpty()) return; qApp->d_func()->cursor_list.removeFirst(); +#ifdef QT_MAC_USE_COCOA + // We use native NSCursor stacks in Cocoa. The currentCursor is the + // top of this stack. So to avoid flickering of cursor, we have to + // change the cusor instead of pop-ing the existing OverrideCursor + // and pushing the new one. + qApp->d_func()->cursor_list.prepend(cursor); + qt_cocoaChangeOverrideCursor(cursor); + return; +#endif setOverrideCursor(cursor); } #endif @@ -3496,7 +3529,7 @@ void QApplication::changeOverrideCursor(const QCursor &cursor) It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets. - + Generally, no user interaction can take place before calling exec(). As a special case, modal widgets like QMessageBox can be used before calling exec(), because modal widgets call exec() to start a local event loop. @@ -3507,12 +3540,12 @@ void QApplication::changeOverrideCursor(const QCursor &cursor) We recommend that you connect clean-up code to the \l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in your - application's \c{main()} function because on some platforms the - QApplication::exec() call may not return. For example, on Windows when the - user logs off, the system terminates the process after Qt closes all - top-level windows. Hence, there is no guarantee that the application will - have time to exit its event loop and execute code at the end of the - \c{main()} function after the QApplication::exec() call. + application's \c{main()} function. This is because, on some platforms the + QApplication::exec() call may not return. For example, on the Windows + platform, when the user logs off, the system terminates the process after Qt + closes all top-level windows. Hence, there is \e{no guarantee} that the + application will have time to exit its event loop and execute code at the + end of the \c{main()} function, after the QApplication::exec() call. \sa quitOnLastWindowClosed, quit(), exit(), processEvents(), QCoreApplication::exec() @@ -3562,20 +3595,18 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QApplicationPrivate::mouse_buttons |= me->button(); else QApplicationPrivate::mouse_buttons &= ~me->button(); - } + } #if !defined(QT_NO_WHEELEVENT) || !defined(QT_NO_TABLETEVENT) - else if ( + else if (false # ifndef QT_NO_WHEELEVENT - e->type() == QEvent::Wheel -# else - false + || e->type() == QEvent::Wheel # endif # ifndef QT_NO_TABLETEVENT - || e->type() == QEvent::TabletMove - || e->type() == QEvent::TabletPress - || e->type() == QEvent::TabletRelease + || e->type() == QEvent::TabletMove + || e->type() == QEvent::TabletPress + || e->type() == QEvent::TabletRelease # endif - ) { + ) { QInputEvent *ie = static_cast<QInputEvent*>(e); QApplicationPrivate::modifier_buttons = ie->modifiers(); } @@ -3594,6 +3625,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: d->toolTipFallAsleep.stop(); + // fall-through case QEvent::Leave: d->toolTipWakeUp.stop(); default: @@ -3709,19 +3741,18 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QPoint relpos = mouse->pos(); if (e->spontaneous()) { +#ifndef QT_NO_IM + QInputContext *ic = w->inputContext(); + if (ic + && w->testAttribute(Qt::WA_InputMethodEnabled) + && ic->filterEvent(mouse)) + return true; +#endif if (e->type() == QEvent::MouseButtonPress) { - QWidget *fw = w; - while (fw) { - if (fw->isEnabled() - && QApplicationPrivate::shouldSetFocus(fw, Qt::ClickFocus)) { - fw->setFocus(Qt::MouseFocusReason); - break; - } - if (fw->isWindow()) - break; - fw = fw->parentWidget(); - } + QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, + Qt::ClickFocus, + Qt::MouseFocusReason); } // ### Qt 5 These dynamic tool tips should be an OPT-IN feature. Some platforms @@ -3787,7 +3818,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QPoint diff = relpos - w->mapFromGlobal(d->hoverGlobalPos); while (w) { if (w->testAttribute(Qt::WA_Hover) && - (!qApp->activePopupWidget() || qApp->activePopupWidget() == w->window())) { + (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) { QHoverEvent he(QEvent::HoverMove, relpos, relpos - diff); d->notify_helper(w, &he); } @@ -3810,17 +3841,9 @@ bool QApplication::notify(QObject *receiver, QEvent *e) bool eventAccepted = wheel->isAccepted(); if (e->spontaneous()) { - QWidget *fw = w; - while (fw) { - if (fw->isEnabled() - && QApplicationPrivate::shouldSetFocus(fw, Qt::WheelFocus)) { - fw->setFocus(Qt::MouseFocusReason); - break; - } - if (fw->isWindow()) - break; - fw = fw->parentWidget(); - } + QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, + Qt::WheelFocus, + Qt::MouseFocusReason); } while (w) { @@ -4025,7 +4048,72 @@ bool QApplication::notify(QObject *receiver, QEvent *e) } break; #endif + case QEvent::TouchBegin: + // Note: TouchUpdate and TouchEnd events are never propagated + { + QWidget *widget = static_cast<QWidget *>(receiver); + QTouchEvent *touchEvent = static_cast<QTouchEvent *>(e); + bool eventAccepted = touchEvent->isAccepted(); + if (widget->testAttribute(Qt::WA_AcceptTouchEvents) && e->spontaneous()) { + // give the widget focus if the focus policy allows it + QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget, + Qt::ClickFocus, + Qt::MouseFocusReason); + } + while (widget) { + // first, try to deliver the touch event + bool acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents); + touchEvent->setWidget(widget); + touchEvent->setAccepted(acceptTouchEvents); + res = acceptTouchEvents && d->notify_helper(widget, touchEvent); + eventAccepted = touchEvent->isAccepted(); + widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, res && eventAccepted); + touchEvent->spont = false; + if (res && eventAccepted) { + // the first widget to accept the TouchBegin gets an implicit grab. + for (int i = 0; i < touchEvent->touchPoints().count(); ++i) { + const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i); + d->widgetForTouchPointId[touchPoint.id()] = widget; + } + break; + } else if (widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) { + break; + } + widget = widget->parentWidget(); + d->updateTouchPointsForWidget(widget, touchEvent); + } + + touchEvent->setAccepted(eventAccepted); + break; + } + case QEvent::RequestSoftwareInputPanel: + case QEvent::CloseSoftwareInputPanel: +#ifndef QT_NO_IM + if (receiver->isWidgetType()) { + QWidget *w = static_cast<QWidget *>(receiver); + QInputContext *ic = w->inputContext(); + if (ic && ic->filterEvent(e)) { + break; + } + } +#endif + res = d->notify_helper(receiver, e); + break; + + case QEvent::NativeGesture: + { + // only propagate the first gesture event (after the GID_BEGIN) + QWidget *w = static_cast<QWidget *>(receiver); + while (w) { + e->ignore(); + res = d->notify_helper(w, e); + if ((res && e->isAccepted()) || w->isWindow()) + break; + w = w->parentWidget(); + } + break; + } default: res = d->notify_helper(receiver, e); break; @@ -4043,10 +4131,10 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e) if (receiver->isWidgetType()) { QWidget *widget = static_cast<QWidget *>(receiver); -#if !defined(Q_OS_WINCE) || (defined(GWES_ICONCURS) && !defined(QT_NO_CURSOR)) +#if !defined(Q_WS_WINCE) || (defined(GWES_ICONCURS) && !defined(QT_NO_CURSOR)) // toggle HasMouse widget state on enter and leave if ((e->type() == QEvent::Enter || e->type() == QEvent::DragEnter) && - (!qApp->activePopupWidget() || qApp->activePopupWidget() == widget->window())) + (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == widget->window())) widget->setAttribute(Qt::WA_UnderMouse, true); else if (e->type() == QEvent::Leave || e->type() == QEvent::DragLeave) widget->setAttribute(Qt::WA_UnderMouse, false); @@ -4072,9 +4160,6 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e) \class QSessionManager \brief The QSessionManager class provides access to the session manager. - \ingroup application - \ingroup environment - A session manager in a desktop environment (in which Qt GUI applications live) keeps track of a session, which is a group of running applications, each of which has a particular state. The state of an application contains @@ -4373,13 +4458,13 @@ HRESULT qt_CoCreateGuid(GUID* guid) { // We will use the following information to create the GUID // 1. absolute path to application - wchar_t tempFilename[512]; - if (!GetModuleFileNameW(0, tempFilename, 512)) + wchar_t tempFilename[MAX_PATH]; + if (!GetModuleFileName(0, tempFilename, MAX_PATH)) return S_FALSE; - unsigned int hash = qHash(QString::fromUtf16((const unsigned short *) tempFilename)); + unsigned int hash = qHash(QString::fromWCharArray(tempFilename)); guid->Data1 = hash; // 2. creation time of file - QFileInfo info(QString::fromUtf16((const unsigned short *) tempFilename)); + QFileInfo info(QString::fromWCharArray(tempFilename)); guid->Data2 = qHash(info.created().toTime_t()); // 3. current system time guid->Data3 = qHash(QDateTime::currentDateTime().toTime_t()); @@ -4413,10 +4498,10 @@ QSessionManager::QSessionManager(QApplication * app, QString &id, QString &key) GUID guid; CoCreateGuid(&guid); StringFromGUID2(guid, guidstr, 40); - id = QString::fromUtf16((ushort*)guidstr); + id = QString::fromWCharArray(guidstr); CoCreateGuid(&guid); StringFromGUID2(guid, guidstr, 40); - key = QString::fromUtf16((ushort*)guidstr); + key = QString::fromWCharArray(guidstr); #endif d->sessionId = id; d->sessionKey = key; @@ -4576,9 +4661,9 @@ void QSessionManager::requestPhase2() \oldcode app.setWinStyleHighlightColor(color); \newcode - QPalette palette(qApp->palette()); + QPalette palette(QApplication::palette()); palette.setColor(QPalette::Highlight, color); - qApp->setPalette(palette); + QApplication::setPalette(palette); \endcode */ @@ -4597,7 +4682,7 @@ void QSessionManager::requestPhase2() /*! \fn const QColor &QApplication::winStyleHighlightColor() - Use qApp->palette().color(QPalette::Active, QPalette::Highlight) instead. + Use QApplication::palette().color(QPalette::Active, QPalette::Highlight) instead. */ /*! @@ -4687,7 +4772,7 @@ void QApplicationPrivate::emitLastWindowClosed() If \a enable is true, Qt::Key_Up and Qt::Key_Down are used to change focus. - This feature is available in Qt for Embedded Linux only. + This feature is available in Qt for Embedded Linux and Symbian only. \sa keypadNavigationEnabled() */ @@ -4698,9 +4783,9 @@ void QApplication::setKeypadNavigationEnabled(bool enable) /*! Returns true if Qt is set to use keypad navigation; otherwise returns - false. The default is false. + false. The default value is true on Symbian, but false on other platforms. - This feature is available in Qt for Embedded Linux only. + This feature is available in Qt for Embedded Linux and Symbian only. \sa setKeypadNavigationEnabled() */ @@ -4724,7 +4809,7 @@ bool QApplication::keypadNavigationEnabled() On Mac OS X, this works more at the application level and will cause the application icon to bounce in the dock. - On Windows this causes the window's taskbar entry to flash for a time. If + On Windows, this causes the window's taskbar entry to flash for a time. If \a msec is zero, the flashing will stop and the taskbar entry will turn a different color (currently orange). @@ -4741,24 +4826,22 @@ bool QApplication::keypadNavigationEnabled() caret display. Usually the text cursor is displayed for half the cursor flash time, then hidden for the same amount of time, but this may vary. - The default value on X11 is 1000 milliseconds. On Windows, the control - panel value is used. Widgets should not cache this value since it may be - changed at any time by the user changing the global desktop settings. + The default value on X11 is 1000 milliseconds. On Windows, the + \gui{Control Panel} value is used and setting this property sets the cursor + flash time for all applications. - \note On Microsoft Windows, setting this property sets the cursor flash - time for all applications. + We recommend that widgets do not cache this value as it may change at any + time if the user changes the global desktop settings. */ /*! \property QApplication::doubleClickInterval - \brief the time limit in milliseconds that distinguishes a double click from two - consecutive mouse clicks - - The default value on X11 is 400 milliseconds. On Windows and Mac OS X, the - operating system's value is used. + \brief the time limit in milliseconds that distinguishes a double click + from two consecutive mouse clicks - On Microsoft Windows, calling this function sets the double click interval - for all applications. + The default value on X11 is 400 milliseconds. On Windows and Mac OS, the + operating system's value is used. However, on Windows and Symbian OS, + calling this function sets the double click interval for all applications. */ /*! @@ -4767,7 +4850,7 @@ bool QApplication::keypadNavigationEnabled() from two consecutive key presses \since 4.2 - The default value on X11 is 400 milliseconds. On Windows and Mac OS X, the + The default value on X11 is 400 milliseconds. On Windows and Mac OS, the operating system's value is used. */ @@ -4832,7 +4915,7 @@ bool QApplication::keypadNavigationEnabled() You need not have a main widget; connecting lastWindowClosed() to quit() is an alternative. - For X11, this function also resizes and moves the main widget according + On X11, this function also resizes and moves the main widget according to the \e -geometry command-line option, so you should set the default geometry (using \l QWidget::setGeometry()) before calling setMainWidget(). @@ -4861,9 +4944,10 @@ bool QApplication::keypadNavigationEnabled() Application cursors are stored on an internal stack. setOverrideCursor() pushes the cursor onto the stack, and restoreOverrideCursor() pops the active cursor off the stack. changeOverrideCursor() changes the curently - active application override cursor. Every setOverrideCursor() must - eventually be followed by a corresponding restoreOverrideCursor(), - otherwise the stack will never be emptied. + active application override cursor. + + Every setOverrideCursor() must eventually be followed by a corresponding + restoreOverrideCursor(), otherwise the stack will never be emptied. Example: \snippet doc/src/snippets/code/src_gui_kernel_qapplication_x11.cpp 0 @@ -4916,8 +5000,7 @@ void QApplication::setInputContext(QInputContext *inputContext) qWarning("QApplication::setInputContext: called with 0 input context"); return; } - if (d->inputContext) - delete d->inputContext; + delete d->inputContext; d->inputContext = inputContext; } @@ -4941,6 +5024,11 @@ QInputContext *QApplication::inputContext() const qic = QInputContextFactory::create(QLatin1String("xim"), that); that->d_func()->inputContext = qic; } +#elif defined(Q_WS_S60) + if (!d->inputContext) { + QApplication *that = const_cast<QApplication *>(this); + that->d_func()->inputContext = QInputContextFactory::create(QString::fromLatin1("coefep"), that); + } #endif return d->inputContext; } @@ -4958,6 +5046,8 @@ uint QApplicationPrivate::currentPlatform(){ platform |= KB_Gnome; if (X11->desktopEnvironment == DE_CDE) platform |= KB_CDE; +#elif defined(Q_OS_SYMBIAN) + platform = KB_S60; #endif return platform; } @@ -4992,6 +5082,23 @@ Qt::LayoutDirection QApplication::keyboardInputDirection() return qt_keymapper_private()->keyboardInputDirection; } +void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget, + Qt::FocusPolicy focusPolicy, + Qt::FocusReason focusReason) +{ + QWidget *focusWidget = widget; + while (focusWidget) { + if (focusWidget->isEnabled() + && QApplicationPrivate::shouldSetFocus(focusWidget, focusPolicy)) { + focusWidget->setFocus(focusReason); + break; + } + if (focusWidget->isWindow()) + break; + focusWidget = focusWidget->parentWidget(); + } +} + bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy) { QWidget *f = w; @@ -5027,19 +5134,19 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy) */ /*! \fn QDecoration* QApplication::qwsSetDecoration(const QString &decoration) - \overload + \overload - Requests a QDecoration object for \a decoration from the QDecorationFactory. + Requests a QDecoration object for \a decoration from the + QDecorationFactory. - The string must be one of the QDecorationFactory::keys(). Keys are - case insensitive. + The string must be one of the QDecorationFactory::keys(). Keys are case + insensitive. - A later call to the QApplication constructor will override the - requested style when a "-style" option is passed in as a commandline - parameter. + A later call to the QApplication constructor will override the requested + style when a "-style" option is passed in as a commandline parameter. - Returns 0 if an unknown \a decoration is passed, otherwise the QStyle object - returned is set as the application's GUI style. + Returns 0 if an unknown \a decoration is passed, otherwise the QStyle object + returned is set as the application's GUI style. */ /*! @@ -5136,6 +5243,211 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy) This normally takes some time. Does nothing on other platforms. */ +void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent) +{ + for (int i = 0; i < touchEvent->touchPoints().count(); ++i) { + QTouchEvent::TouchPoint &touchPoint = touchEvent->_touchPoints[i]; + + // preserve the sub-pixel resolution + QRectF rect = touchPoint.screenRect(); + const QPointF screenPos = rect.center(); + const QPointF delta = screenPos - screenPos.toPoint(); + + rect.moveCenter(widget->mapFromGlobal(screenPos.toPoint()) + delta); + touchPoint.setRect(rect); + touchPoint.setStartPos(widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta); + touchPoint.setLastPos(widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta); + } +} + +void QApplicationPrivate::initializeMultitouch() +{ + widgetForTouchPointId.clear(); + appCurrentTouchPoints.clear(); + + initializeMultitouch_sys(); +} + +void QApplicationPrivate::cleanupMultitouch() +{ + cleanupMultitouch_sys(); + + widgetForTouchPointId.clear(); + appCurrentTouchPoints.clear(); +} + +int QApplicationPrivate::findClosestTouchPointId(const QPointF &screenPos) +{ + int closestTouchPointId = -1; + qreal closestDistance = qreal(0.); + foreach (const QTouchEvent::TouchPoint &touchPoint, appCurrentTouchPoints) { + qreal distance = QLineF(screenPos, touchPoint.screenPos()).length(); + if (closestTouchPointId == -1 || distance < closestDistance) { + closestTouchPointId = touchPoint.id(); + closestDistance = distance; + } + } + return closestTouchPointId; +} + +void QApplicationPrivate::translateRawTouchEvent(QWidget *window, + QTouchEvent::DeviceType deviceType, + const QList<QTouchEvent::TouchPoint> &touchPoints) +{ + QApplicationPrivate *d = self; + typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints; + QHash<QWidget *, StatesAndTouchPoints> widgetsNeedingEvents; + + for (int i = 0; i < touchPoints.count(); ++i) { + QTouchEvent::TouchPoint touchPoint = touchPoints.at(i); + + // update state + QWidget *widget = 0; + switch (touchPoint.state()) { + case Qt::TouchPointPressed: + { + if (deviceType == QTouchEvent::TouchPad) { + // on touch-pads, send all touch points to the same widget + widget = d->widgetForTouchPointId.isEmpty() + ? 0 + : d->widgetForTouchPointId.constBegin().value(); + } + + if (!widget) { + // determine which widget this event will go to + if (!window) + window = QApplication::topLevelAt(touchPoint.screenPos().toPoint()); + if (!window) + continue; + widget = window->childAt(window->mapFromGlobal(touchPoint.screenPos().toPoint())); + if (!widget) + widget = window; + } + + if (deviceType == QTouchEvent::TouchScreen) { + int closestTouchPointId = d->findClosestTouchPointId(touchPoint.screenPos()); + QWidget *closestWidget = d->widgetForTouchPointId.value(closestTouchPointId); + if (closestWidget + && (widget->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget))) { + widget = closestWidget; + } + } + + d->widgetForTouchPointId[touchPoint.id()] = widget; + touchPoint.setStartScreenPos(touchPoint.screenPos()); + touchPoint.setLastScreenPos(touchPoint.screenPos()); + touchPoint.setStartNormalizedPos(touchPoint.normalizedPos()); + touchPoint.setLastNormalizedPos(touchPoint.normalizedPos()); + if (touchPoint.pressure() < qreal(0.)) + touchPoint.setPressure(qreal(1.)); + d->appCurrentTouchPoints.insert(touchPoint.id(), touchPoint); + break; + } + case Qt::TouchPointReleased: + { + widget = d->widgetForTouchPointId.take(touchPoint.id()); + if (!widget) + continue; + + QTouchEvent::TouchPoint previousTouchPoint = d->appCurrentTouchPoints.take(touchPoint.id()); + touchPoint.setStartScreenPos(previousTouchPoint.startScreenPos()); + touchPoint.setLastScreenPos(previousTouchPoint.screenPos()); + touchPoint.setStartNormalizedPos(previousTouchPoint.startNormalizedPos()); + touchPoint.setLastNormalizedPos(previousTouchPoint.normalizedPos()); + if (touchPoint.pressure() < qreal(0.)) + touchPoint.setPressure(qreal(0.)); + break; + } + default: + widget = d->widgetForTouchPointId.value(touchPoint.id()); + if (!widget) + continue; + + Q_ASSERT(d->appCurrentTouchPoints.contains(touchPoint.id())); + QTouchEvent::TouchPoint previousTouchPoint = d->appCurrentTouchPoints.value(touchPoint.id()); + touchPoint.setStartScreenPos(previousTouchPoint.startScreenPos()); + touchPoint.setLastScreenPos(previousTouchPoint.screenPos()); + touchPoint.setStartNormalizedPos(previousTouchPoint.startNormalizedPos()); + touchPoint.setLastNormalizedPos(previousTouchPoint.normalizedPos()); + if (touchPoint.pressure() < qreal(0.)) + touchPoint.setPressure(qreal(1.)); + d->appCurrentTouchPoints[touchPoint.id()] = touchPoint; + break; + } + Q_ASSERT(widget != 0); + + // make the *scene* functions return the same as the *screen* functions + touchPoint.setSceneRect(touchPoint.screenRect()); + touchPoint.setStartScenePos(touchPoint.startScreenPos()); + touchPoint.setLastScenePos(touchPoint.lastScreenPos()); + + StatesAndTouchPoints &maskAndPoints = widgetsNeedingEvents[widget]; + maskAndPoints.first |= touchPoint.state(); + if (touchPoint.isPrimary()) + maskAndPoints.first |= Qt::TouchPointPrimary; + maskAndPoints.second.append(touchPoint); + } + + if (widgetsNeedingEvents.isEmpty()) + return; + + QHash<QWidget *, StatesAndTouchPoints>::ConstIterator it = widgetsNeedingEvents.constBegin(); + const QHash<QWidget *, StatesAndTouchPoints>::ConstIterator end = widgetsNeedingEvents.constEnd(); + for (; it != end; ++it) { + QWidget *widget = it.key(); + if (!QApplicationPrivate::tryModalHelper(widget, 0)) + continue; + + QEvent::Type eventType; + switch (it.value().first & Qt::TouchPointStateMask) { + case Qt::TouchPointPressed: + eventType = QEvent::TouchBegin; + break; + case Qt::TouchPointReleased: + eventType = QEvent::TouchEnd; + break; + case Qt::TouchPointStationary: + // don't send the event if nothing changed + continue; + default: + eventType = QEvent::TouchUpdate; + break; + } + + QTouchEvent touchEvent(eventType, + deviceType, + QApplication::keyboardModifiers(), + it.value().first, + it.value().second); + updateTouchPointsForWidget(widget, &touchEvent); + + switch (touchEvent.type()) { + case QEvent::TouchBegin: + { + // if the TouchBegin handler recurses, we assume that means the event + // has been implicitly accepted and continue to send touch events + widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent); + (void ) QApplication::sendSpontaneousEvent(widget, &touchEvent); + break; + } + default: + if (widget->testAttribute(Qt::WA_WState_AcceptedTouchBeginEvent)) { + if (touchEvent.type() == QEvent::TouchEnd) + widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, false); + (void) QApplication::sendSpontaneousEvent(widget, &touchEvent); + } + break; + } + } +} + +Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window, + QTouchEvent::DeviceType deviceType, + const QList<QTouchEvent::TouchPoint> &touchPoints) +{ + QApplicationPrivate::translateRawTouchEvent(window, deviceType, touchPoints); +} + QT_END_NAMESPACE #include "moc_qapplication.cpp" diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h index 5060d22..92cf0f8 100644 --- a/src/gui/kernel/qapplication.h +++ b/src/gui/kernel/qapplication.h @@ -61,6 +61,10 @@ QT_BEGIN_HEADER +#if defined(Q_OS_SYMBIAN) +class TWsEvent; +#endif + QT_BEGIN_NAMESPACE QT_MODULE(Gui) @@ -84,6 +88,7 @@ class QApplicationPrivate; #endif #define qApp (static_cast<QApplication *>(QCoreApplication::instance())) + class Q_GUI_EXPORT QApplication : public QCoreApplication { Q_OBJECT @@ -102,10 +107,10 @@ class Q_GUI_EXPORT QApplication : public QCoreApplication #ifndef QT_NO_STYLE_STYLESHEET Q_PROPERTY(QString styleSheet READ styleSheet WRITE setStyleSheet) #endif -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE Q_PROPERTY(int autoMaximizeThreshold READ autoMaximizeThreshold WRITE setAutoMaximizeThreshold) - Q_PROPERTY(bool autoSipEnabled READ autoSipEnabled WRITE setAutoSipEnabled) #endif + Q_PROPERTY(bool autoSipEnabled READ autoSipEnabled WRITE setAutoSipEnabled) public: enum Type { Tty, GuiClient, GuiServer }; @@ -223,6 +228,12 @@ public: virtual int x11ClientMessage(QWidget*, XEvent*, bool passive_only); int x11ProcessEvent(XEvent*); #endif +#if defined(Q_OS_SYMBIAN) + int s60ProcessEvent(TWsEvent *event); + virtual bool s60EventFilter(TWsEvent *aEvent); + void symbianHandleCommand(int command); + void symbianResourceChange(int type); +#endif #if defined(Q_WS_QWS) virtual bool qwsEventFilter(QWSEvent *); int qwsProcessEvent(QWSEvent*); @@ -239,7 +250,6 @@ public: void winFocus(QWidget *, bool); static void winMouseButtonUp(); #endif - #ifndef QT_NO_SESSIONMANAGER // session management bool isSessionRestored() const; @@ -281,12 +291,12 @@ public Q_SLOTS: #ifndef QT_NO_STYLE_STYLESHEET void setStyleSheet(const QString& sheet); #endif -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE void setAutoMaximizeThreshold(const int threshold); int autoMaximizeThreshold() const; +#endif void setAutoSipEnabled(const bool enabled); bool autoSipEnabled() const; -#endif static void closeAllWindows(); static void aboutQt(); @@ -375,13 +385,12 @@ private: friend class QDirectPainterPrivate; #endif -#if defined(Q_WS_WIN) - friend QApplicationPrivate* getQApplicationPrivateInternal(); -#endif - #if defined(Q_WS_MAC) || defined(Q_WS_X11) Q_PRIVATE_SLOT(d_func(), void _q_alertTimeOut()) #endif +#if defined(QT_RX71_MULTITOUCH) + Q_PRIVATE_SLOT(d_func(), void _q_readRX71MultiTouchEvents()) +#endif }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index f440b00..ea5efb0 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -154,13 +154,16 @@ #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; -extern QHash<QByteArray, QFont> *qt_app_fonts_hash(); // qapplication.cpp /***************************************************************************** Internal variables and functions @@ -523,9 +526,9 @@ void qt_mac_update_os_settings() for(int i = 0; mac_widget_fonts[i].qt_class; i++) { QFont fnt = qfontForThemeFont(mac_widget_fonts[i].font_key); bool set_font = true; - QHash<QByteArray, QFont> *hash = qt_app_fonts_hash(); + FontHash *hash = qt_app_fonts_hash(); if (!hash->isEmpty()) { - QHash<QByteArray, QFont>::const_iterator it + FontHash::const_iterator it = hash->constFind(mac_widget_fonts[i].qt_class); if (it != hash->constEnd()) set_font = (fnt != *it); @@ -624,10 +627,9 @@ void QApplicationPrivate::initializeWidgetPaletteHash() } bool set_palette = true; - extern QHash<QByteArray, QPalette> *qt_app_palettes_hash(); //qapplication.cpp - QHash<QByteArray, QPalette> *phash = qt_app_palettes_hash(); + PaletteHash *phash = qt_app_palettes_hash(); if (!phash->isEmpty()) { - QHash<QByteArray, QPalette>::const_iterator it + PaletteHash::const_iterator it = phash->constFind(mac_widget_colors[i].qt_class); if (it != phash->constEnd()) set_palette = (pal != *it); @@ -1040,16 +1042,34 @@ void qt_release_app_proc_handler() #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 somethng) + // 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. @@ -1196,10 +1216,6 @@ void qt_init(QApplicationPrivate *priv, int) [qtMenuLoader release]; } #endif - if (QApplication::testAttribute(Qt::AA_MacPluginApplication)) { - extern void qt_mac_set_native_menubar(bool); - qt_mac_set_native_menubar(false); - } // 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) { @@ -1228,6 +1244,12 @@ void qt_release_apple_event_handler() 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) { @@ -1355,29 +1377,6 @@ QWidget *QApplication::topLevelAt(const QPoint &p) #endif } -static QWidget *qt_mac_recursive_widgetAt(QWidget *widget, int x, int y) -{ - if (!widget) - return 0; - const QObjectList kids = widget->children(); - for(int i = kids.size()-1; i >= 0; --i) { - if ( QWidget *kid = qobject_cast<QWidget*>(kids.at(i)) ) { - if (kid->isVisible() && !kid->isTopLevel() && - !kid->testAttribute(Qt::WA_TransparentForMouseEvents)) { - const int wx=kid->x(), wy=kid->y(), - wx2=wx+kid->width(), wy2=wy+kid->height(); - if (x >= wx && y >= wy && x < wx2 && y < wy2) { - const QRegion mask = kid->mask(); - if (!mask.isEmpty() && !mask.contains(QPoint(x-wx, y-wy))) - continue; - return qt_mac_recursive_widgetAt(kid, x-wx, y-wy); - } - } - } - } - return widget; -} - /***************************************************************************** Main event loop *****************************************************************************/ @@ -1410,13 +1409,8 @@ void QApplicationPrivate::enterModal_sys(QWidget *widget) qt_button_down = 0; #ifdef QT_MAC_USE_COCOA - if (!qt_mac_is_macsheet(widget)) { - // Add a new, empty (null), NSModalSession to the stack. - // The next time we spin the event dispatcher, it will - // check the stack, and recurse into a modal session for it: - QCocoaModalSessionInfo info = {widget, 0}; - QEventDispatcherMacPrivate::cocoaModalSessionStack.push(info); - } + if (!qt_mac_is_macsheet(widget)) + QEventDispatcherMacPrivate::beginModalSession(widget); #endif } @@ -1442,7 +1436,7 @@ void QApplicationPrivate::leaveModal_sys(QWidget *widget) } #ifdef QT_MAC_USE_COCOA if (!qt_mac_is_macsheet(widget)) - QEventDispatcherMacPrivate::rebuildModalSessionStack(true); + QEventDispatcherMacPrivate::endModalSession(widget); #endif } #ifdef DEBUG_MODAL_EVENTS @@ -1453,21 +1447,6 @@ void QApplicationPrivate::leaveModal_sys(QWidget *widget) qt_event_request_menubarupdate(); } -#if defined(QT_MAC_USE_COCOA) -void QApplicationPrivate::_q_runAppModalWindow() -{ - if (QEventDispatcherMacPrivate::blockCocoaRequestModal) { - // Just postpone the event until the event dispatcher tells - // us (by releasing the block) that it is OK to recurse into - // a new event loop for our non-execing modal window: - qApp->postEvent(qApp, new QEvent(QEvent::CocoaRequestModal)); - } else { - // Recurse into a new event loop for the current app modal window: - threadData->eventDispatcher->processEvents(QEventLoop::DialogExec); - } -} -#endif - QWidget *QApplicationPrivate::tryModalHelper_sys(QWidget *top) { #ifndef QT_MAC_USE_COCOA @@ -1654,15 +1633,6 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event bool inNonClientArea = false; GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0, sizeof(where), 0, &where); - if(ekind == kEventMouseMoved && qt_mac_app_fullscreen && - QApplication::desktop()->screenNumber(QPoint(where.h, where.v)) == - QApplication::desktop()->primaryScreen()) { - if(where.v <= 0) - ShowMenuBar(); - else if(qt_mac_window_at(where.h, where.v, 0) != inMenuBar) - HideMenuBar(); - } - #if defined(DEBUG_MOUSE_MAPS) const char *edesc = 0; switch(ekind) { @@ -1759,7 +1729,7 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event if(window) { HIViewRef hiview; if(HIViewGetViewForMouseEvent(HIViewGetRoot(window), event, &hiview) == noErr) { - widget = QWidget::find((WId)hiview);; + 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); @@ -1876,9 +1846,10 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event tablet_button_state = new_tablet_button_state; QMacTabletHash *tabletHash = qt_mac_tablet_hash(); - if (!tabletHash->contains(tabletPointRec.deviceID)) { - qWarning("QCocoaView handleTabletEvent: This tablet device is unknown" - " (received no proximity event for it). Discarding event."); + 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); @@ -1920,8 +1891,13 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event 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 table acceptance"); + qDebug("Bail out early due to tablet acceptance"); #endif break; } @@ -2968,4 +2944,9 @@ void onApplicationChangedActivation( bool activated ) #endif } +void QApplicationPrivate::initializeMultitouch_sys() +{ } +void QApplicationPrivate::cleanupMultitouch_sys() +{ } + QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 9090c35..3b6cd43 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -55,6 +55,7 @@ // #include "QtGui/qapplication.h" +#include "QtGui/qevent.h" #include "QtGui/qfont.h" #include "QtGui/qcursor.h" #include "QtGui/qregion.h" @@ -77,11 +78,10 @@ class QClipboard; class QGraphicsScene; class QGraphicsSystem; class QInputContext; -class QKeyEvent; -class QMouseEvent; class QObject; -class QWheelEvent; class QWidget; +class QGestureManager; +class QSocketNotifier; extern bool qt_is_gui_used; #ifndef QT_NO_CLIPBOARD @@ -100,6 +100,7 @@ extern QSysInfo::MacVersion qt_macver; #if defined(Q_WS_QWS) class QWSManager; class QDirectPainter; +struct QWSServerCleaner { ~QWSServerCleaner(); }; #endif #ifndef QT_NO_TABLET @@ -158,17 +159,19 @@ inline QPointF QTabletDeviceData::scaleCoord(int coordX, int coordY, int outOriginY, int outExtentY) const { QPointF ret; + if (sign(outExtentX) == sign(maxX)) - ret.setX(((coordX - minX) * qAbs(outExtentX) / qAbs(qreal(maxX))) + outOriginX); + ret.setX(((coordX - minX) * qAbs(outExtentX) / qAbs(qreal(maxX - minX))) + outOriginX); else - ret.setX(((qAbs(maxX) - (coordX - minX)) * qAbs(outExtentX) / qAbs(qreal(maxX))) + ret.setX(((qAbs(maxX) - (coordX - minX)) * qAbs(outExtentX) / qAbs(qreal(maxX - minX))) + outOriginX); if (sign(outExtentY) == sign(maxY)) - ret.setY(((coordY - minY) * qAbs(outExtentY) / qAbs(qreal(maxY))) + outOriginY); + ret.setY(((coordY - minY) * qAbs(outExtentY) / qAbs(qreal(maxY - minY))) + outOriginY); else - ret.setY(((qAbs(maxY) - (coordY - minY)) * qAbs(outExtentY) / qAbs(qreal(maxY))) + ret.setY(((qAbs(maxY) - (coordY - minY)) * qAbs(outExtentY) / qAbs(qreal(maxY - minY))) + outOriginY); + return ret; } #endif @@ -189,6 +192,90 @@ extern "C" { } #endif +#if defined(Q_WS_WIN) +typedef BOOL (WINAPI *PtrRegisterTouchWindow)(HWND, ULONG); +typedef BOOL (WINAPI *PtrGetTouchInputInfo)(HANDLE, UINT, PVOID, int); +typedef BOOL (WINAPI *PtrCloseTouchInputHandle)(HANDLE); + +typedef BOOL (WINAPI *PtrGetGestureInfo)(HANDLE, PVOID); +typedef BOOL (WINAPI *PtrGetGestureExtraArgs)(HANDLE, UINT, PBYTE); +typedef BOOL (WINAPI *PtrCloseGestureInfoHandle)(HANDLE); +typedef BOOL (WINAPI *PtrSetGestureConfig)(HWND, DWORD, UINT, PVOID, UINT); +typedef BOOL (WINAPI *PtrGetGestureConfig)(HWND, DWORD, DWORD, PUINT, PVOID, UINT); + +typedef BOOL (WINAPI *PtrBeginPanningFeedback)(HWND); +typedef BOOL (WINAPI *PtrUpdatePanningFeedback)(HWND, LONG, LONG, BOOL); +typedef BOOL (WINAPI *PtrEndPanningFeedback)(HWND, BOOL); + +#ifndef WM_GESTURE +# define WM_GESTURE 0x0119 + +# define GID_BEGIN 1 +# define GID_END 2 +# define GID_ZOOM 3 +# define GID_PAN 4 +# define GID_ROTATE 5 +# define GID_TWOFINGERTAP 6 +# define GID_ROLLOVER 7 + +typedef struct tagGESTUREINFO +{ + UINT cbSize; + DWORD dwFlags; + DWORD dwID; + HWND hwndTarget; + POINTS ptsLocation; + DWORD dwInstanceID; + DWORD dwSequenceID; + ULONGLONG ullArguments; + UINT cbExtraArgs; +} GESTUREINFO; + +# define GC_PAN 0x00000001 +# define GC_PAN_WITH_SINGLE_FINGER_VERTICALLY 0x00000002 +# define GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY 0x00000004 + +# define GC_ZOOM 0x00000001 +# define GC_ROTATE 0x00000001 + +typedef struct tagGESTURECONFIG +{ + DWORD dwID; + DWORD dwWant; + DWORD dwBlock; +} GESTURECONFIG; + +# define GID_ROTATE_ANGLE_FROM_ARGUMENT(arg) ((((double)(arg) / 65535.0) * 4.0 * 3.14159265) - 2.0*3.14159265) + +#endif // WM_GESTURE + +#if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES) +#undef GID_ZOOM +#define GID_ZOOM 0xf000 +#undef GID_ROTATE +#define GID_ROTATE 0xf001 +#undef GID_TWOFINGERTAP +#define GID_TWOFINGERTAP 0xf002 +#undef GID_ROLLOVER +#define GID_ROLLOVER 0xf003 +#endif + +#endif // Q_WS_WIN + +class QPanGesture; +class QPinchGesture; +class QSwipeGesture; + +struct QStandardGestures +{ + QPanGesture *pan; + QPinchGesture *pinch; + QSwipeGesture *swipe; + + QStandardGestures() : pan(0), pinch(0), swipe(0) { } +}; + + class QScopedLoopLevelCounter { QThreadData *threadData; @@ -200,6 +287,12 @@ public: { --threadData->loopLevel; } }; +typedef QHash<QByteArray, QFont> FontHash; +FontHash *qt_app_fonts_hash(); + +typedef QHash<QByteArray, QPalette> PaletteHash; +PaletteHash *qt_app_palettes_hash(); + class Q_GUI_EXPORT QApplicationPrivate : public QCoreApplicationPrivate { Q_DECLARE_PUBLIC(QApplication) @@ -209,7 +302,7 @@ public: #if defined(Q_WS_X11) #ifndef QT_NO_SETTINGS - static QString kdeHome(); + static QString x11_desktop_style(); static bool x11_apply_settings(); #endif static void reset_instance_pointer(); @@ -219,10 +312,11 @@ public: #endif static bool quitOnLastWindowClosed; static void emitLastWindowClosed(); -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE static int autoMaximizeThreshold; - static bool autoSipEnabled; #endif + static bool autoSipEnabled; + static QString desktopStyleKey(); static QGraphicsSystem *graphicsSystem() #if !defined(Q_WS_QWS) @@ -233,7 +327,6 @@ public: void createEventDispatcher(); QString appName() const; - static void dispatchEnterLeave(QWidget *enter, QWidget *leave); //modality @@ -270,6 +363,7 @@ public: KB_KDE = 8, KB_Gnome = 16, KB_CDE = 32, + KB_S60 = 64, KB_All = 0xffff }; @@ -358,7 +452,7 @@ public: #ifdef Q_WS_MAC static bool native_modal_dialog_active; #endif -#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) static bool inSizeMove; #endif @@ -382,6 +476,7 @@ public: #ifdef Q_WS_QWS QPointer<QWSManager> last_manager; + QWSServerCleaner qwsServerCleaner; # ifndef QT_NO_DIRECTPAINTER QMap<WId, QDirectPainter *> *directPainters; # endif @@ -392,7 +487,7 @@ public: static QApplicationPrivate *instance() { return self; } - static QString *styleOverride; + static QString styleOverride; static int app_compile_version; @@ -405,12 +500,6 @@ public: void _q_alertTimeOut(); QHash<QWidget *, QTimer *> alertTimerHash; #endif -#if defined(QT_MAC_USE_COCOA) - void _q_runAppModalWindow(); -#endif -#if defined(QT_MAC_USE_COCOA) - void _q_runModalWindow(); -#endif #ifndef QT_NO_STYLE_STYLESHEET static QString styleSheet; #endif @@ -419,20 +508,90 @@ public: QEvent::Type type, Qt::MouseButtons buttons, QWidget *buttonDown, QWidget *alienWidget); static bool sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget, - QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver); + QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver, + bool spontaneous = true); +#ifdef Q_OS_SYMBIAN + static TUint resolveS60ScanCode(TInt scanCode, TUint keysym); +#endif #if defined(Q_WS_WIN) || defined(Q_WS_X11) void sendSyntheticEnterLeave(QWidget *widget); #endif + QMap<int, QWidget *> widgetForTouchPointId; + QMap<int, QTouchEvent::TouchPoint> appCurrentTouchPoints; + static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); + void initializeMultitouch(); + void initializeMultitouch_sys(); + void cleanupMultitouch(); + void cleanupMultitouch_sys(); + int findClosestTouchPointId(const QPointF &screenPos); + void appendTouchPoint(const QTouchEvent::TouchPoint &touchPoint); + void removeTouchPoint(int touchPointId); + static void translateRawTouchEvent(QWidget *widget, + QTouchEvent::DeviceType deviceType, + const QList<QTouchEvent::TouchPoint> &touchPoints); + + typedef QMap<QWidget*, QStandardGestures> WidgetStandardGesturesMap; + WidgetStandardGesturesMap widgetGestures; + +#if defined(Q_WS_WIN) + static PtrRegisterTouchWindow RegisterTouchWindow; + static PtrGetTouchInputInfo GetTouchInputInfo; + static PtrCloseTouchInputHandle CloseTouchInputHandle; + + QHash<DWORD, int> touchInputIDToTouchPointID; + bool translateTouchEvent(const MSG &msg); + + PtrGetGestureInfo GetGestureInfo; + PtrGetGestureExtraArgs GetGestureExtraArgs; + PtrCloseGestureInfoHandle CloseGestureInfoHandle; + PtrSetGestureConfig SetGestureConfig; + PtrGetGestureConfig GetGestureConfig; + PtrBeginPanningFeedback BeginPanningFeedback; + PtrUpdatePanningFeedback UpdatePanningFeedback; + PtrEndPanningFeedback EndPanningFeedback; + QWidget *gestureWidget; +#endif + +#ifdef QT_RX71_MULTITOUCH + bool hasRX71MultiTouch; + + struct RX71TouchPointState { + QSocketNotifier *socketNotifier; + QTouchEvent::TouchPoint touchPoint; + + int minX, maxX, scaleX; + int minY, maxY, scaleY; + int minZ, maxZ; + }; + QList<RX71TouchPointState> allRX71TouchPoints; + + bool readRX71MultiTouchEvents(int deviceNumber); + void fakeMouseEventFromRX71TouchEvent(); + void _q_readRX71MultiTouchEvents(); +#endif + private: #ifdef Q_WS_QWS QMap<const QScreen*, QRect> maxWindowRects; #endif +#ifdef Q_OS_SYMBIAN + static QHash<TInt, TUint> scanCodeCache; +#endif + static QApplicationPrivate *self; + + static void giveFocusAccordingToFocusPolicy(QWidget *w, + Qt::FocusPolicy focusPolicy, + Qt::FocusReason focusReason); static bool shouldSetFocus(QWidget *w, Qt::FocusPolicy policy); }; +Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window, + QTouchEvent::DeviceType deviceType, + const QList<QTouchEvent::TouchPoint> &touchPoints); + QT_END_NAMESPACE #endif // QAPPLICATION_P_H diff --git a/src/gui/kernel/qapplication_qws.cpp b/src/gui/kernel/qapplication_qws.cpp index 1cdd1b4..e3bd786 100644 --- a/src/gui/kernel/qapplication_qws.cpp +++ b/src/gui/kernel/qapplication_qws.cpp @@ -72,6 +72,7 @@ //#include "qwsregionmanager_qws.h" #include "qwindowsystem_qws.h" #include "private/qwindowsystem_p.h" +#include "qdecorationfactory_qws.h" #include "qwsdisplay_qws.h" #include "private/qwsdisplay_qws_p.h" @@ -101,7 +102,11 @@ #include <locale.h> #include <errno.h> #include <fcntl.h> -#include <sys/time.h> +#ifdef Q_OS_VXWORKS +# include <sys/times.h> +#else +# include <sys/time.h> +#endif #include <sys/stat.h> #include <sys/types.h> @@ -118,6 +123,8 @@ #endif #endif +QT_BEGIN_NAMESPACE + #ifndef QT_NO_DIRECTPAINTER class QDirectPainter; extern void qt_directpainter_region(QDirectPainter *dp, const QRegion &alloc, int type); @@ -157,11 +164,9 @@ int qt_servershmid = -1; bool qws_overrideCursor = false; #ifndef QT_NO_QWS_MANAGER -#include "qdecorationfactory_qws.h" -QT_BEGIN_NAMESPACE +extern Q_GUI_EXPORT QWSServer *qwsServer; -QT_USE_NAMESPACE static QDecoration *qws_decoration = 0; #endif @@ -194,28 +199,35 @@ QString qws_dataDir() static QString result; if (!result.isEmpty()) return result; - QByteArray dataDir = QString(QLatin1String("/tmp/qtembedded-%1")).arg(qws_display_id).toLocal8Bit(); - if (mkdir(dataDir, 0700)) { + QByteArray dataDir; +#ifdef QT_QWS_TEMP_DIR + dataDir = QT_QWS_TEMP_DIR; +#else + dataDir = "/tmp"; +#endif + dataDir += "/qtembedded-"; + dataDir += QByteArray::number(qws_display_id); + if (QT_MKDIR(dataDir, 0700)) { if (errno != EEXIST) { qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData()); } } - struct stat buf; - if (lstat(dataDir, &buf)) + QT_STATBUF buf; + if (QT_LSTAT(dataDir, &buf)) qFatal("stat failed for Qt for Embedded Linux data directory: %s", dataDir.constData()); if (!S_ISDIR(buf.st_mode)) qFatal("%s is not a directory", dataDir.constData()); -#ifndef Q_OS_INTEGRITY +#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS) if (buf.st_uid != getuid()) qFatal("Qt for Embedded Linux data directory is not owned by user %d", getuid()); if ((buf.st_mode & 0677) != 0600) qFatal("Qt for Embedded Linux data directory has incorrect permissions: %s", dataDir.constData()); #endif - dataDir += "/"; + dataDir += '/'; result = QString::fromLocal8Bit(dataDir); return result; @@ -224,7 +236,7 @@ QString qws_dataDir() // Get the filename of the pipe Qt for Embedded Linux uses for server/client comms Q_GUI_EXPORT QString qws_qtePipeFilename() { - return (qws_dataDir() + QString(QLatin1String(QTE_PIPE)).arg(qws_display_id)); + return (qws_dataDir() + QString::fromLatin1(QTE_PIPE).arg(qws_display_id)); } static void setMaxWindowRect(const QRect &rect) @@ -485,8 +497,13 @@ QList<QWSCommand*> *qt_get_server_queue() void qt_server_enqueue(const QWSCommand *command) { QWSCommand *copy = QWSCommand::factory(command->type); - copy->copyFrom(command); - outgoing.append(copy); + QT_TRY { + copy->copyFrom(command); + outgoing.append(copy); + } QT_CATCH(...) { + delete copy; + QT_RETHROW; + } } QWSDisplay::Data::Data(QObject* parent, bool singleProcess) @@ -662,7 +679,7 @@ void QWSDisplay::Data::sendSynchronousCommand(QWSCommand & cmd) int QWSDisplay::Data::takeId() { int unusedIdCount = unused_identifiers.count(); - if (unusedIdCount == 10) + if (unusedIdCount <= 10) create(15); if (unusedIdCount == 0) { create(1); // Make sure we have an incoming id to wait for, just in case we're recursive @@ -2015,8 +2032,8 @@ bool QApplicationPrivate::qws_apply_settings() // read new QStyle QString stylename = settings.value(QLatin1String("style")).toString(); if (QCoreApplication::startingUp()) { - if (!stylename.isEmpty() && !QApplicationPrivate::styleOverride) - QApplicationPrivate::styleOverride = new QString(stylename); + if (!stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull()) + QApplicationPrivate::styleOverride = stylename; } else { QApplication::setStyle(stylename); } @@ -2284,7 +2301,8 @@ void qt_init(QApplicationPrivate *priv, int type) qt_appType = QApplication::Type(type); qws_single_process = true; QWSServer::startup(flags); - setenv("QWS_DISPLAY", qws_display_spec.constData(), 0); + if (!display) // if not already set + qputenv("QWS_DISPLAY", qws_display_spec); } if(qt_is_gui_used) { @@ -2299,7 +2317,7 @@ void qt_init(QApplicationPrivate *priv, int type) qws_decoration = QApplication::qwsSetDecoration(decoration); #endif // QT_NO_QWS_MANAGER #ifndef QT_NO_QWS_INPUTMETHODS - qApp->setInputContext(new QWSInputContext); + qApp->setInputContext(new QWSInputContext(qApp)); #endif } @@ -2352,7 +2370,7 @@ void qt_cleanup() QString QApplicationPrivate::appName() const // get application name { - return ::appName; + return QT_PREPEND_NAMESPACE(appName); } /***************************************************************************** @@ -3546,10 +3564,10 @@ bool QETWidget::translateKeyEvent(const QWSKeyEvent *event, bool grab) /* grab i #if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT) if (type == QEvent::KeyPress && !grab - && static_cast<QApplicationPrivate*>(qApp->d_ptr)->use_compat()) { + && static_cast<QApplicationPrivate*>(qApp->d_ptr.data())->use_compat()) { // send accel events if the keyboard is not grabbed QKeyEvent a(type, code, state, text, autor, int(text.length())); - if (static_cast<QApplicationPrivate*>(qApp->d_ptr)->qt_tryAccelEvent(this, &a)) + if (static_cast<QApplicationPrivate*>(qApp->d_ptr.data())->qt_tryAccelEvent(this, &a)) return true; } #else @@ -3749,4 +3767,19 @@ void QApplication::setArgs(int c, char **v) d->argv = v; } +void QApplicationPrivate::initializeMultitouch_sys() +{ } +void QApplicationPrivate::cleanupMultitouch_sys() +{ } + +/* \internal + This is used to clean up the qws server + in case the QApplication constructor threw an exception +*/ +QWSServerCleaner::~QWSServerCleaner() +{ + if (qwsServer && qws_single_process) + QWSServer::closedown(); +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp new file mode 100644 index 0000000..4260fd9 --- /dev/null +++ b/src/gui/kernel/qapplication_s60.cpp @@ -0,0 +1,1237 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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_p.h" +#include "qsessionmanager.h" +#include "qevent.h" +#include "qeventdispatcher_s60_p.h" +#include "qwidget.h" +#include "qdesktopwidget.h" +#include "private/qbackingstore_p.h" +#include "qt_s60_p.h" +#include "private/qevent_p.h" +#include "qstring.h" +#include "qdebug.h" +#include "qimage.h" +#include "private/qkeymapper_p.h" +#include "private/qfont_p.h" +#ifndef QT_NO_STYLE_S60 +#include "private/qs60style_p.h" +#endif +#include "private/qwindowsurface_s60_p.h" +#include "qpaintengine.h" +#include "private/qmenubar_p.h" + +#include "apgwgnam.h" // For CApaWindowGroupName +#include <MdaAudioTonePlayer.h> // For CMdaAudioToneUtility + +#if !defined(QT_NO_IM) && defined(Q_WS_S60) +#include "qinputcontext.h" +#include <private/qcoefepinputcontext_p.h> +#endif // !defined(QT_NO_IM) && defined(Q_WS_S60) + +#include "private/qstylesheetstyle_p.h" + +QT_BEGIN_NAMESPACE + +#if defined(QT_DEBUG) +static bool appNoGrab = false; // Grabbing enabled +#endif +static bool app_do_modal = false; // modal mode +Q_GLOBAL_STATIC(QS60Data, qt_s60Data); + +extern bool qt_sendSpontaneousEvent(QObject*,QEvent*); +extern QWidgetList *qt_modal_stack; // stack of modal widgets +extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp + +QWidget *qt_button_down = 0; // widget got last button-down + +QS60Data* qGlobalS60Data() +{ + return qt_s60Data(); +} + +bool qt_nograb() // application no-grab option +{ +#if defined(QT_DEBUG) + return appNoGrab; +#else + return false; +#endif +} + +// Modified from http://www3.symbian.com/faq.nsf/0/0F1464EE96E737E780256D5E00503DD1?OpenDocument +class QS60Beep : public CBase, public MMdaAudioToneObserver +{ +public: + static QS60Beep* NewL(TInt aFrequency, TTimeIntervalMicroSeconds iDuration); + void Play(); + ~QS60Beep(); +private: + void ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds iDuration); + void MatoPrepareComplete(TInt aError); + void MatoPlayComplete(TInt aError); +private: + typedef enum + { + EBeepNotPrepared, + EBeepPrepared, + EBeepPlaying + } TBeepState; +private: + CMdaAudioToneUtility* iToneUtil; + TBeepState iState; + TInt iFrequency; + TTimeIntervalMicroSeconds iDuration; +}; + +QS60Beep::~QS60Beep() +{ + delete iToneUtil; +} + +QS60Beep* QS60Beep::NewL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration) +{ + QS60Beep* self=new (ELeave) QS60Beep(); + CleanupStack::PushL(self); + self->ConstructL(aFrequency, aDuration); + CleanupStack::Pop(); + return self; +}; + +void QS60Beep::ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration) +{ + iToneUtil=CMdaAudioToneUtility::NewL(*this); + iState=EBeepNotPrepared; + iFrequency=aFrequency; + iDuration=aDuration; + iToneUtil->PrepareToPlayTone(iFrequency,iDuration); +} + +void QS60Beep::Play() +{ + if(iState!=EBeepNotPrepared){ + if(iState==EBeepPlaying) { + iToneUtil->CancelPlay(); + iState=EBeepPrepared; + } + } + + iToneUtil->Play(); + iState=EBeepPlaying; +} + +void QS60Beep::MatoPrepareComplete(TInt aError) +{ + if(aError==KErrNone) { + iState=EBeepPrepared; + } +} + +void QS60Beep::MatoPlayComplete(TInt aError) +{ + Q_UNUSED(aError); + iState=EBeepPrepared; +} + + +QHash<TInt, TUint> QApplicationPrivate::scanCodeCache; + +static Qt::KeyboardModifiers mapToQtModifiers(TUint s60Modifiers) +{ + Qt::KeyboardModifiers result = Qt::NoModifier; + + if (s60Modifiers & EModifierKeypad) + result |= Qt::KeypadModifier; + if (s60Modifiers & EModifierShift || s60Modifiers & EModifierLeftShift + || s60Modifiers & EModifierRightShift) + result |= Qt::ShiftModifier; + if (s60Modifiers & EModifierCtrl || s60Modifiers & EModifierLeftCtrl + || s60Modifiers & EModifierRightCtrl) + result |= Qt::ControlModifier; + if (s60Modifiers & EModifierAlt || s60Modifiers & EModifierLeftAlt + || s60Modifiers & EModifierRightAlt) + result |= Qt::AltModifier; + + return result; +} + +static void mapS60MouseEventTypeToQt(QEvent::Type *type, Qt::MouseButton *button, const TPointerEvent *pEvent) +{ + switch (pEvent->iType) { + case TPointerEvent::EButton1Down: + *type = QEvent::MouseButtonPress; + *button = Qt::LeftButton; + break; + case TPointerEvent::EButton1Up: + *type = QEvent::MouseButtonRelease; + *button = Qt::LeftButton; + break; + case TPointerEvent::EButton2Down: + *type = QEvent::MouseButtonPress; + *button = Qt::MidButton; + break; + case TPointerEvent::EButton2Up: + *type = QEvent::MouseButtonRelease; + *button = Qt::MidButton; + break; + case TPointerEvent::EButton3Down: + *type = QEvent::MouseButtonPress; + *button = Qt::RightButton; + break; + case TPointerEvent::EButton3Up: + *type = QEvent::MouseButtonRelease; + *button = Qt::RightButton; + break; + case TPointerEvent::EDrag: + *type = QEvent::MouseMove; + *button = Qt::NoButton; + break; + case TPointerEvent::EMove: + // Qt makes no distinction between move and drag + *type = QEvent::MouseMove; + *button = Qt::NoButton; + break; + default: + *type = QEvent::None; + *button = Qt::NoButton; + break; + } + if (pEvent->iModifiers & EModifierDoubleClick){ + *type = QEvent::MouseButtonDblClick; + } + + if (*type == QEvent::MouseButtonPress || *type == QEvent::MouseButtonDblClick) + QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | (*button); + else if (*type == QEvent::MouseButtonRelease) + QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons &(~(*button)); + + QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & Qt::MouseButtonMask; +} + +//### Can be replaced with CAknLongTapDetector if animation is required. +//NOTE: if CAknLongTapDetector is used make sure it gets variated out of 3.1 and 3.2,. +//also MLongTapObserver needs to be changed to MAknLongTapDetectorCallBack if CAknLongTapDetector is used. +class QLongTapTimer : public CTimer +{ +public: + static QLongTapTimer* NewL(QAbstractLongTapObserver *observer); + QLongTapTimer(QAbstractLongTapObserver *observer); + void ConstructL(); +public: + void PointerEventL(const TPointerEvent &event); + void RunL(); +protected: +private: + QAbstractLongTapObserver *m_observer; + TPointerEvent m_event; + QPoint m_pressedCoordinates; + int m_dragDistance; +}; + +QLongTapTimer* QLongTapTimer::NewL(QAbstractLongTapObserver *observer) +{ + QLongTapTimer* self = new QLongTapTimer(observer); + self->ConstructL(); + return self; +} +void QLongTapTimer::ConstructL() +{ + CTimer::ConstructL(); +} + +QLongTapTimer::QLongTapTimer(QAbstractLongTapObserver *observer):CTimer(CActive::EPriorityHigh) +{ + m_observer = observer; + m_dragDistance = qApp->startDragDistance(); + CActiveScheduler::Add(this); +} + +void QLongTapTimer::PointerEventL(const TPointerEvent& event) +{ + if ( event.iType == TPointerEvent::EDrag || event.iType == TPointerEvent::EButtonRepeat) + { + QPoint diff(QPoint(event.iPosition.iX,event.iPosition.iY) - m_pressedCoordinates); + if (diff.manhattanLength() < m_dragDistance) + return; + } + Cancel(); + m_event = event; + if (event.iType == TPointerEvent::EButton1Down) + { + m_pressedCoordinates = QPoint(event.iPosition.iX,event.iPosition.iY); + // must be same as KLongTapDelay in aknlongtapdetector.h + After(800000); + } +} +void QLongTapTimer::RunL() +{ + if (m_observer) + m_observer->HandleLongTapEventL(m_event.iPosition, m_event.iParentPosition); +} + +QSymbianControl::QSymbianControl(QWidget *w) + : CCoeControl(), qwidget(w), m_ignoreFocusChanged(false) +{ +} + +void QSymbianControl::ConstructL(bool topLevel, bool desktop) +{ + if (!desktop) + { + if (topLevel) + CreateWindowL(S60->windowGroup()); + + SetFocusing(true); + m_longTapDetector = QLongTapTimer::NewL(this); + } +} + +QSymbianControl::~QSymbianControl() +{ + S60->appUi()->RemoveFromStack(this); + delete m_longTapDetector; +} + +void QSymbianControl::setWidget(QWidget *w) +{ + qwidget = w; +} +void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation ) +{ + QWidget *alienWidget; + QPoint widgetPos = QPoint(aPenEventLocation.iX, aPenEventLocation.iY); + QPoint globalPos = QPoint(aPenEventScreenLocation.iX,aPenEventScreenLocation.iY); + alienWidget = qwidget->childAt(widgetPos); + if (!alienWidget) + alienWidget = qwidget; + QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons &(~Qt::LeftButton); + QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | Qt::RightButton; + QMouseEvent mEvent(QEvent::MouseButtonPress, alienWidget->mapFrom(qwidget, widgetPos), globalPos, + Qt::RightButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier); + + bool res = sendMouseEvent(alienWidget, &mEvent); + +#if !defined(QT_NO_CONTEXTMENU) + QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse, widgetPos, globalPos, mEvent.modifiers()); + qt_sendSpontaneousEvent(alienWidget, &contextMenuEvent); +#endif + + m_previousEventLongTap = true; +} + +void QSymbianControl::HandlePointerEventL(const TPointerEvent& pEvent) +{ + m_longTapDetector->PointerEventL(pEvent); + QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent)); +} + +void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent) +{ + //### refactor me, getting too complex + QMouseEvent::Type type; + Qt::MouseButton button; + mapS60MouseEventTypeToQt(&type, &button, &pEvent); + + if (m_previousEventLongTap) + if (type == QEvent::MouseButtonRelease){ + button = Qt::RightButton; + QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & ~Qt::RightButton; + m_previousEventLongTap = false; + } + if (type == QMouseEvent::None) + return; + + // store events for later sending/saving + QWidget *alienWidget; + typedef QPair<QWidget*,QMouseEvent> Event; + QList<Event > events; + + QPoint widgetPos = QPoint(pEvent.iPosition.iX, pEvent.iPosition.iY); + TPoint controlScreenPos = PositionRelativeToScreen(); + QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos; + + if (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick) + { + // get the button press target + alienWidget = qwidget->childAt(widgetPos); + if (!alienWidget) + alienWidget = qwidget; + S60->mousePressTarget = alienWidget; + } + alienWidget = S60->mousePressTarget; + + if (alienWidget != S60->lastPointerEventTarget) + if (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick || type == QEvent::MouseMove) + { + //moved to another widget, create enter and leave events + if (S60->lastPointerEventTarget) + { + QMouseEvent mEventLeave(QEvent::Leave, S60->lastPointerEventTarget->mapFromGlobal(S60->lastCursorPos), S60->lastCursorPos, + button, QApplicationPrivate::mouse_buttons, mapToQtModifiers(pEvent.iModifiers)); + events.append(Event(S60->lastPointerEventTarget,mEventLeave)); + } + QMouseEvent mEventEnter(QEvent::Enter, alienWidget->mapFromGlobal(globalPos), globalPos, + button, QApplicationPrivate::mouse_buttons, mapToQtModifiers(pEvent.iModifiers)); + + events.append(Event(alienWidget,mEventEnter)); + } + S60->lastCursorPos = globalPos; + S60->lastPointerEventPos = widgetPos; + S60->lastPointerEventTarget = alienWidget; + if (alienWidget) + { + QMouseEvent mEvent(type, alienWidget->mapFromGlobal(globalPos), globalPos, + button, QApplicationPrivate::mouse_buttons, mapToQtModifiers(pEvent.iModifiers)); + events.append(Event(alienWidget,mEvent)); + QEventDispatcherS60 *dispatcher; + // It is theoretically possible for someone to install a different event dispatcher. + if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(alienWidget->d_func()->threadData->eventDispatcher)) != 0) { + if (dispatcher->excludeUserInputEvents()) { + for (int i=0;i < events.count();++i) + { + Event next = events[i]; + dispatcher->saveInputEvent(this, next.first, new QMouseEvent(next.second)); + } + return; + } + } + } + for (int i=0;i < events.count();++i) + { + Event next = events[i]; + sendMouseEvent(next.first, &(next.second)); + } +} + +bool QSymbianControl::sendMouseEvent(QWidget *widget, QMouseEvent *mEvent) +{ + return qt_sendSpontaneousEvent(widget, mEvent); +} + +TKeyResponse QSymbianControl::OfferKeyEventL(const TKeyEvent& keyEvent, TEventCode type) +{ + TKeyResponse r = EKeyWasNotConsumed; + QT_TRYCATCH_LEAVING(r = OfferKeyEvent(keyEvent, type)); + return r; +} + +TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCode type) +{ + switch (type) { + //case EEventKeyDown: // <-- Intentionally left out. See below. + case EEventKeyUp: + case EEventKey: + { + // S60 has a confusing way of delivering key events. There are three types of + // events: EKeyEvent, EKeyEventDown and EKeyEventUp. When a key is pressed, the + // two first events are generated. When releasing the key, the last one is + // generated. + // Because S60 does not generate keysyms for EKeyEventDown and EKeyEventUp events, + // we need to do some special tricks to map it to the Qt way. First, we completely + // discard EKeyEventDown events, since they are redundant. Second, since + // EKeyEventUp does not give us a keysym, we need to cache the keysyms from + // the EKeyEvent events. This is what resolveS60ScanCode does. + + + // ### hackish way to send Qt application to background when pressing right softkey + /* + if( keyEvent.iScanCode == EStdKeyDevice1 ) { + S60->window_group->SetOrdinalPosition(-1); + qApp->setActiveWindow(0); + return EKeyWasNotConsumed; + } + */ + + TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode, + keyEvent.iCode); + int keyCode; + if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) { + // Normal characters keys. + keyCode = s60Keysym; + } else { + // Special S60 keys. + keyCode = qt_keymapper_private()->mapS60KeyToQt(s60Keysym); + } + Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers); + QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode, + mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods), + false, 1, keyEvent.iScanCode, s60Keysym, mods); +// WId wid = reinterpret_cast<RWindowGroup *>(keyEvent.Handle())->Child(); +// if (!wid) +// Could happen if window isn't shown yet. +// return EKeyWasNotConsumed; + QWidget *widget; + widget = QWidget::keyboardGrabber(); + if (!widget) { + if (QApplicationPrivate::popupWidgets != 0) { + widget = QApplication::activePopupWidget()->focusWidget(); + if (!widget) { + widget = QApplication::activePopupWidget(); + } + } else { + widget = QApplicationPrivate::focus_widget; + if (!widget) { + widget = qwidget; + } + } + } + + QEventDispatcherS60 *dispatcher; + // It is theoretically possible for someone to install a different event dispatcher. + if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widget->d_func()->threadData->eventDispatcher)) != 0) { + if (dispatcher->excludeUserInputEvents()) { + dispatcher->saveInputEvent(this, widget, new QKeyEventEx(qKeyEvent)); + return EKeyWasConsumed; + } + } + return sendKeyEvent(widget, &qKeyEvent); + } + } + return EKeyWasNotConsumed; +} + +void QSymbianControl::sendInputEvent(QWidget *widget, QInputEvent *inputEvent) +{ + switch (inputEvent->type()) { + case QEvent::KeyPress: + case QEvent::KeyRelease: + sendKeyEvent(widget, static_cast<QKeyEvent *>(inputEvent)); + break; + case QEvent::MouseButtonDblClick: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + sendMouseEvent(widget, static_cast<QMouseEvent *>(inputEvent)); + break; + default: + // Shouldn't get here. + Q_ASSERT_X(0 == 1, "QSymbianControl::sendInputEvent()", "inputEvent->type() is unknown"); + break; + } +} + +TKeyResponse QSymbianControl::sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent) +{ +#if !defined(QT_NO_IM) && defined(Q_WS_S60) + if (widget && widget->isEnabled() && widget->testAttribute(Qt::WA_InputMethodEnabled)) { + QInputContext *qic = widget->inputContext(); + if(qic && qic->filterEvent(keyEvent)) + return EKeyWasConsumed; + } +#endif // !defined(QT_NO_IM) && defined(Q_WS_S60) + + if (widget && qt_sendSpontaneousEvent(widget, keyEvent)) + if (keyEvent->isAccepted()) + return EKeyWasConsumed; + + return EKeyWasNotConsumed; +} + +#if !defined(QT_NO_IM) && defined(Q_WS_S60) +TCoeInputCapabilities QSymbianControl::InputCapabilities() const +{ + QWidget *w = 0; + + if(qwidget->hasFocus()) { + w = qwidget; + } else { + w = qwidget->focusWidget(); + } + + QCoeFepInputContext *ic; + if (w && w->isEnabled() && w->testAttribute(Qt::WA_InputMethodEnabled) + && (ic = qobject_cast<QCoeFepInputContext *>(w->inputContext()))) { + return ic->inputCapabilities(); + } else { + return TCoeInputCapabilities(TCoeInputCapabilities::ENone, 0, 0); + } +} +#endif + +void QSymbianControl::Draw(const TRect& r) const +{ + QWindowSurface *surface = qwidget->windowSurface(); + if (!surface) + return; + + QPaintEngine *engine = surface->paintDevice()->paintEngine(); + if (!engine) + return; + if (engine->type() == QPaintEngine::Raster) { + QS60WindowSurface *s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface()); + CFbsBitmap *bitmap = s60Surface->symbianBitmap(); + CWindowGc &gc = SystemGc(); + if (qwidget->d_func()->isOpaque) + gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); + gc.BitBlt(r.iTl, bitmap, r); + } else { + surface->flush(qwidget, QRegion(qt_TRect2QRect(r)), QPoint()); + } +} + +void QSymbianControl::SizeChanged() +{ + CCoeControl::SizeChanged(); + + QSize oldSize = qwidget->size(); + QSize newSize(Size().iWidth, Size().iHeight); + + if (oldSize != newSize) { + QRect cr = qwidget->geometry(); + cr.setSize(newSize); + qwidget->data->crect = cr; + if (qwidget->isVisible()) { + QTLWExtra *tlwExtra = qwidget->d_func()->maybeTopData(); + bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt(); + if (!slowResize && tlwExtra) + tlwExtra->inTopLevelResize = true; + QResizeEvent e(newSize, oldSize); + qt_sendSpontaneousEvent(qwidget, &e); + if (!qwidget->testAttribute(Qt::WA_StaticContents)) + qwidget->d_func()->syncBackingStore(); + if (!slowResize && tlwExtra) + tlwExtra->inTopLevelResize = false; + } + } +} + +void QSymbianControl::PositionChanged() +{ + CCoeControl::PositionChanged(); + + QPoint oldPos = qwidget->geometry().topLeft(); + QPoint newPos(Position().iX, Position().iY); + + if (oldPos != newPos) { + QRect cr = qwidget->geometry(); + cr.moveTopLeft(newPos); + qwidget->data->crect = cr; + QTLWExtra *top = qwidget->d_func()->maybeTopData(); + if (top) + top->normalGeometry = cr; + if (qwidget->isVisible()) { + QMoveEvent e(newPos, oldPos); + qt_sendSpontaneousEvent(qwidget, &e); + } else { + QMoveEvent * e = new QMoveEvent(newPos, oldPos); + QApplication::postEvent(qwidget, e); + } + } +} + +void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) +{ + if (m_ignoreFocusChanged) + return; + + // Popups never get focused, but still receive the FocusChanged when they are hidden. + if (QApplicationPrivate::popupWidgets != 0 + || (qwidget->windowType() & Qt::Popup) == Qt::Popup) + return; + + QEvent *deferredFocusEvent = new QEvent(QEvent::SymbianDeferredFocusChanged); + QApplication::postEvent(qwidget, deferredFocusEvent); +} + +void QSymbianControl::HandleResourceChange(int resourceType) +{ + switch (resourceType) { + case KInternalStatusPaneChange: + qwidget->d_func()->setWindowIcon_sys(true); + break; + case KUidValueCoeFontChangeEvent: + // font change event + break; +#ifdef Q_WS_S60 + case KEikDynamicLayoutVariantSwitch: + { + if (qwidget->isFullScreen()) { + SetExtentToWholeScreen(); + } else if (qwidget->isMaximized()) { + TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); + SetExtent(r.iTl, r.Size()); + } + break; + } +#endif + default: + break; + } + + CCoeControl::HandleResourceChange(resourceType); + +} +void QSymbianControl::CancelLongTapTimer() +{ + m_longTapDetector->Cancel(); +} + +TTypeUid::Ptr QSymbianControl::MopSupplyObject(TTypeUid id) +{ + if (id.iUid == ETypeId) + return id.MakePtr(this); + + return CCoeControl::MopSupplyObject(id); +} + +void qt_init(QApplicationPrivate * /* priv */, int) +{ +#ifdef QT_NO_DEBUG + if (!qgetenv("QT_S60_AUTO_FLUSH_WSERV").isEmpty()) +#endif + S60->wsSession().SetAutoFlush(ETrue); + + S60->updateScreenSize(); + + + TDisplayMode mode = S60->screenDevice()->DisplayMode(); + S60->screenDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel(mode); + + RProcess me; + TSecureId securId = me.SecureId(); + S60->uid = securId.operator TUid(); + +/* + ### Commented out for now as parameter handling not needed in SOS(yet). Code below will break testlib with -o flag + int argc = priv->argc; + char **argv = priv->argv; + + // Get command line params + int j = argc ? 1 : 0; + for (int i=1; i<argc; i++) { + if (argv[i] && *argv[i] != '-') { + argv[j++] = argv[i]; + continue; + } + +#if defined(QT_DEBUG) + if (qstrcmp(argv[i], "-nograb") == 0) + appNoGrab = !appNoGrab; + else +#endif // QT_DEBUG + ; + } +*/ +} + +/***************************************************************************** + qt_cleanup() - cleans up when the application is finished + *****************************************************************************/ +void qt_cleanup() +{ + QFontCache::cleanup(); // Has to happen now, since QFontEngineS60 has FBS handles +// S60 structure and window server session are freed in eventdispatcher destructor as they are needed there + + // It's important that this happens here, before the event dispatcher gets + // deleted, because the input context needs the event loop one last time before + // it dies. + delete QApplicationPrivate::inputContext; + QApplicationPrivate::inputContext = 0; +} + +void QApplicationPrivate::initializeWidgetPaletteHash() +{ + // TODO: Implement QApplicationPrivate::initializeWidgetPaletteHash() + // Possibly a task fot the S60Style guys +} + +void QApplicationPrivate::createEventDispatcher() +{ + Q_Q(QApplication); + eventDispatcher = new QEventDispatcherS60(q); +} + +QString QApplicationPrivate::appName() const +{ + return QCoreApplicationPrivate::appName(); +} + +bool QApplicationPrivate::modalState() +{ + return app_do_modal; +} + +void QApplicationPrivate::enterModal_sys(QWidget *widget) +{ + if (widget) { + widget->effectiveWinId()->DrawableWindow()->FadeBehind(ETrue); + // Modal partial screen dialogs (like queries) capture pointer events. + // ### FixMe: Add specialized behaviour for fullscreen modal dialogs + widget->effectiveWinId()->SetGloballyCapturing(ETrue); + widget->effectiveWinId()->SetPointerCapture(ETrue); + } + if (!qt_modal_stack) + qt_modal_stack = new QWidgetList; + qt_modal_stack->insert(0, widget); + app_do_modal = true; +} + +void QApplicationPrivate::leaveModal_sys(QWidget *widget) +{ + if (widget) { + widget->effectiveWinId()->DrawableWindow()->FadeBehind(EFalse); + // ### FixMe: Add specialized behaviour for fullscreen modal dialogs + widget->effectiveWinId()->SetGloballyCapturing(EFalse); + widget->effectiveWinId()->SetPointerCapture(EFalse); + } + if (qt_modal_stack && qt_modal_stack->removeAll(widget)) { + if (qt_modal_stack->isEmpty()) { + delete qt_modal_stack; + qt_modal_stack = 0; + } + } + app_do_modal = qt_modal_stack != 0; +} + +void QApplicationPrivate::openPopup(QWidget *popup) +{ + if (!QApplicationPrivate::popupWidgets) + QApplicationPrivate::popupWidgets = new QWidgetList; + QApplicationPrivate::popupWidgets->append(popup); + + + // Cancel focus widget pointer capture and long tap timer + if (QApplication::focusWidget()) { + static_cast<QSymbianControl*>(QApplication::focusWidget()->effectiveWinId())->CancelLongTapTimer(); + QApplication::focusWidget()->effectiveWinId()->SetPointerCapture(false); + } + + if (!qt_nograb()) { + // Cancel pointer capture and long tap timer for earlier popup + int popupCount = QApplicationPrivate::popupWidgets->count(); + if (popupCount > 1) { + QWidget* prevPopup = QApplicationPrivate::popupWidgets->at(popupCount-2); + static_cast<QSymbianControl*>(prevPopup->effectiveWinId())->CancelLongTapTimer(); + prevPopup->effectiveWinId()->SetPointerCapture(false); + } + + // Enable pointer capture for this (topmost) popup + Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created)); + WId id = popup->effectiveWinId(); + id->SetPointerCapture(true); + } + + // 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 + QWidget *fw = popup->focusWidget(); + if (fw) { + fw->setFocus(Qt::PopupFocusReason); + } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup + fw = QApplication::focusWidget(); + if (fw) { + QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); + q_func()->sendEvent(fw, &e); + } + } +} + +void QApplicationPrivate::closePopup(QWidget *popup) +{ + if (!QApplicationPrivate::popupWidgets) + return; + QApplicationPrivate::popupWidgets->removeAll(popup); + + // Cancel pointer capture and long tap for this popup + WId id = popup->effectiveWinId(); + id->SetPointerCapture(false); + static_cast<QSymbianControl*>(id)->CancelLongTapTimer(); + + if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup + delete QApplicationPrivate::popupWidgets; + QApplicationPrivate::popupWidgets = 0; + if (!qt_nograb()) { // grabbing not disabled + Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created)); + if (QWidgetPrivate::mouseGrabber != 0) + QWidgetPrivate::mouseGrabber->grabMouse(); + + if (QWidgetPrivate::keyboardGrabber != 0) + QWidgetPrivate::keyboardGrabber->grabKeyboard(); + + QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget() + : q_func()->focusWidget(); + if (fw) { + if (fw != q_func()->focusWidget()) { + fw->setFocus(Qt::PopupFocusReason); + } else { + QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason); + q_func()->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 = QApplication::focusWidget()) { + QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); + q_func()->sendEvent(fw, &e); + } + + // Enable pointer capture for previous popup + if (aw) { + aw->effectiveWinId()->SetPointerCapture(true); + } + } +} + +QWidget * QApplication::topLevelAt(QPoint const& point) +{ + QWidget *found = 0; + int lowestZ = INT_MAX; + QWidgetList list = QApplication::topLevelWidgets(); + for (int i = 0; i < list.count(); ++i) { + QWidget *widget = list.at(i); + if (widget->isVisible() && !(widget->windowType() == Qt::Desktop)) { + Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created)); + if (widget->geometry().adjusted(0,0,1,1).contains(point)) { + // At this point we know there is a Qt widget under the point. + // Now we need to make sure it is the top most in the z-order. + RDrawableWindow* rw = widget->d_func()->topData()->rwindow; + int z = rw->OrdinalPosition(); + if (z < lowestZ) { + lowestZ = z; + found = widget; + } + } + } + } + return found; +} + +void QApplication::alert(QWidget * /* widget */, int /* duration */) +{ + // TODO: Implement QApplication::alert(QWidget *widget, int duration) +} + +int QApplication::doubleClickInterval() +{ + TTimeIntervalMicroSeconds32 us; + TInt distance; + S60->wsSession().GetDoubleClickSettings(us, distance); + return (us.Int() / 1000); +} + +void QApplication::setDoubleClickInterval(int ms) +{ + TTimeIntervalMicroSeconds32 newUs( ms * 1000); + TTimeIntervalMicroSeconds32 us; + TInt distance; + S60->wsSession().GetDoubleClickSettings(us, distance); + if (us != newUs) + S60->wsSession().SetDoubleClick(newUs, distance); +} + +int QApplication::keyboardInputInterval() +{ + return QApplicationPrivate::keyboard_input_time; +} + +void QApplication::setKeyboardInputInterval(int ms) +{ + QApplicationPrivate::keyboard_input_time = ms; +} + +int QApplication::cursorFlashTime() +{ + return QApplicationPrivate::cursor_flash_time; +} + +void QApplication::setCursorFlashTime(int msecs) +{ + QApplicationPrivate::cursor_flash_time = msecs; +} + +void QApplication::beep() +{ + TInt frequency=440; + TTimeIntervalMicroSeconds duration(500000); + QS60Beep* beep=NULL; + TRAPD(err, beep=QS60Beep::NewL(frequency, duration)); + if(!err) { + beep->Play(); + } + delete beep; + beep=NULL; +} + +/*! \fn int QApplication::s60ProcessEvent(TWsEvent *event) + This function does the core processing of individual s60 + \a{event}s. It returns 1 if the event was handled, 0 if + the \a event was not handled, and -1 if the event was + not handled because the event handle was not in the map. + */ +int QApplication::s60ProcessEvent(TWsEvent *event) +{ + bool handled = s60EventFilter(event); + if (handled) + return 1; + + // Qt event handling. Handle some events regardless of if the handle is in our + // widget map or not. + CCoeControl* control = reinterpret_cast<CCoeControl*>(event->Handle()); + const bool controlInMap = QWidgetPrivate::mapper && QWidgetPrivate::mapper->contains(control); + switch (event->Type()) { +#if !defined(QT_NO_IM) && defined(Q_WS_S60) + case EEventKey: + case EEventKeyUp: + case EEventKeyDown: + { + // The control doesn't seem to be any of our widgets, so rely on the focused + // widget instead. If the user needs the control, it can be found inside the + // event structure. + QWidget *w = qApp ? qApp->focusWidget() : 0; + if (w) { + QInputContext *ic = w->inputContext(); + if (ic && ic->s60FilterEvent(w, event)) { + return 1; + } else { + return 0; + } + } + break; + } +#endif + case EEventPointerEnter: + if (controlInMap) + return 1; // Qt::Enter will be generated in HandlePointerL + break; + case EEventPointerExit: + if (controlInMap) { + if (S60) { + // mouseEvent outside our window, send leave event to last focused widget + QMouseEvent mEvent(QEvent::Leave, S60->lastPointerEventPos, S60->lastCursorPos, + Qt::NoButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier); + if (S60->lastPointerEventTarget) + qt_sendSpontaneousEvent(S60->lastPointerEventTarget,&mEvent); + S60->lastPointerEventTarget = 0; + } + return 1; + } + break; + case EEventScreenDeviceChanged: + if (S60) + S60->updateScreenSize(); + if (qt_desktopWidget) { + QSize oldSize = qt_desktopWidget->size(); + qt_desktopWidget->data->crect.setWidth(S60->screenWidthInPixels); + qt_desktopWidget->data->crect.setHeight(S60->screenHeightInPixels); + QResizeEvent e(qt_desktopWidget->size(), oldSize); + QApplication::sendEvent(qt_desktopWidget, &e); + } + return 0; // Propagate to CONE + case EEventWindowVisibilityChanged: + if (controlInMap) { + const TWsVisibilityChangedEvent *visChangedEvent = event->VisibilityChanged(); + QWidget *w = QWidgetPrivate::mapper->value(control); + if (!w->d_func()->maybeTopData()) + break; + if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) { + delete w->d_func()->topData()->backingStore; + w->d_func()->topData()->backingStore = 0; + } else if ((visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible) + && !w->d_func()->maybeBackingStore()) { + w->d_func()->topData()->backingStore = new QWidgetBackingStore(w); + w->update(); + } + return 1; + } + break; + default: + break; + } + + if (!controlInMap) + return -1; + + return 0; +} + +/*! + Returns false. Does nothing with the TWsEvent \a aEvent. + */ +bool QApplication::s60EventFilter(TWsEvent * /* aEvent */) +{ + return false; +} + +/*! + Handles \a{command}s which are typically handled by + CAknAppUi::HandleCommandL(). Qts Ui integration into Symbian is + partially achieved by deriving from CAknAppUi. Currently, exit, + menu and softkey commands are handled. + + \sa s60EventFilter(), s60ProcessEvent() +*/ +void QApplication::symbianHandleCommand(int command) +{ + switch (command) { + case EEikCmdExit: +#ifdef Q_WS_S60 + case EAknSoftkeyExit: +#endif + exit(); + break; + default: + if (command >= SOFTKEYSTART && command <= SOFTKEYEND) { + int index= command-SOFTKEYSTART; + QWidget *focused = QApplication::focusWidget(); + QWidget *softKeySource = focused ? focused : QApplication::activeWindow(); + const QList<QAction*>& softKeys = softKeySource->softKeys(); + Q_ASSERT(index < softKeys.count()); + softKeys.at(index)->activate(QAction::Trigger); + } +#ifdef Q_WS_S60 + else + QMenuBarPrivate::symbianCommands(command); +#endif + break; + } +} + +/*! + Handles the resource change specified by \a type. + */ +void QApplication::symbianResourceChange(int type) +{ + switch (type) { +#ifdef Q_WS_S60 + case KEikDynamicLayoutVariantSwitch: + { + if (S60) + S60->updateScreenSize(); + +#ifndef QT_NO_STYLE_S60 + QS60Style *s60Style = 0; + +#ifndef QT_NO_STYLE_STYLESHEET + QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle*>(QApplication::style()); + if (proxy) + s60Style = qobject_cast<QS60Style*>(proxy->baseStyle()); + else +#endif + s60Style = qobject_cast<QS60Style*>(QApplication::style()); + + if (s60Style) + s60Style->d_func()->handleDynamicLayoutVariantSwitch(); +#endif + } + break; + +#ifndef QT_NO_STYLE_S60 + case KAknsMessageSkinChange: + if (QS60Style *s60Style = qobject_cast<QS60Style*>(QApplication::style())) + s60Style->d_func()->handleSkinChange(); + break; +#endif +#endif // Q_WS_S60 + default: + break; + } +} + +#ifndef QT_NO_WHEELEVENT +int QApplication::wheelScrollLines() +{ + return QApplicationPrivate::wheel_scroll_lines; +} + +void QApplication::setWheelScrollLines(int n) +{ + QApplicationPrivate::wheel_scroll_lines = n; +} +#endif //QT_NO_WHEELEVENT + +bool QApplication::isEffectEnabled(Qt::UIEffect /* effect */) +{ + // TODO: Implement QApplication::isEffectEnabled(Qt::UIEffect effect) + return false; +} + +void QApplication::setEffectEnabled(Qt::UIEffect /* effect */, bool /* enable */) +{ + // TODO: Implement QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable) +} + +TUint QApplicationPrivate::resolveS60ScanCode(TInt scanCode, TUint keysym) +{ + if (keysym) { + // If keysym is specified, cache it. + scanCodeCache.insert(scanCode, keysym); + return keysym; + } else { + // If not, retrieve the cached version. + return scanCodeCache[scanCode]; + } +} + + +void QApplicationPrivate::initializeMultitouch_sys() +{ } +void QApplicationPrivate::cleanupMultitouch_sys() +{ } + +#ifndef QT_NO_SESSIONMANAGER +QSessionManager::QSessionManager(QApplication * /* app */, QString & /* id */, QString& /* key */) +{ + +} + +QSessionManager::~QSessionManager() +{ + +} + +bool QSessionManager::allowsInteraction() +{ + return false; +} + +void QSessionManager::cancel() +{ + +} +#endif //QT_NO_SESSIONMANAGER +QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index ddc491b..d23494e 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE #include "qguifunctions_wince.h" #include "qmenubar.h" extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp @@ -48,9 +48,12 @@ extern bool qt_wince_is_smartphone(); //defined in qguifunctions_wince.c extern bool qt_wince_is_pocket_pc(); //defined in qguifunctions_wince.cpp extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.cpp #endif -#ifdef Q_OS_WINCE_WM +#ifdef Q_WS_WINCE_WM #include <windowsm.h> #include <tpcshell.h> +#ifdef QT_WINCE_GESTURES +#include <gesture.h> +#endif #endif #include "qapplication.h" @@ -88,6 +91,9 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c #include "qdebug.h" #include <private/qkeymapper_p.h> #include <private/qlocale_p.h> +#include "qevent_p.h" +#include "qstandardgestures.h" +#include "qstandardgestures_p.h" //#define ALIEN_DEBUG @@ -104,32 +110,44 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c #endif #endif // QT_NO_ACCESSIBILITY -#include <winuser.h> #if !defined(WINABLEAPI) -# if defined(Q_OS_WINCE) +# if defined(Q_WS_WINCE) # include <bldver.h> # endif # include <winable.h> #endif +#ifndef WM_TOUCH +# define WM_TOUCH 0x0240 + +# define TOUCHEVENTF_MOVE 0x0001 +# define TOUCHEVENTF_DOWN 0x0002 +# define TOUCHEVENTF_UP 0x0004 +# define TOUCHEVENTF_INRANGE 0x0008 +# define TOUCHEVENTF_PRIMARY 0x0010 +# define TOUCHEVENTF_NOCOALESCE 0x0020 +# define TOUCHEVENTF_PEN 0x0040 +# define TOUCHEVENTF_PALM 0x0080 + +# define TOUCHINPUTMASKF_TIMEFROMSYSTEM 0x0001 +# define TOUCHINPUTMASKF_EXTRAINFO 0x0002 +# define TOUCHINPUTMASKF_CONTACTAREA 0x0004 -#ifndef FLASHW_STOP -typedef struct { - UINT cbSize; - HWND hwnd; +typedef struct tagTOUCHINPUT +{ + LONG x; + LONG y; + HANDLE hSource; + DWORD dwID; DWORD dwFlags; - UINT uCount; - DWORD dwTimeout; -} FLASHWINFO, *PFLASHWINFO; -#define FLASHW_STOP 0 -#define FLASHW_CAPTION 0x00000001 -#define FLASHW_TRAY 0x00000002 -#define FLASHW_ALL (FLASHW_CAPTION | FLASHW_TRAY) -#define FLASHW_TIMER 0x00000004 -#define FLASHW_TIMERNOFG 0x0000000C -#endif /* FLASHW_STOP */ -typedef BOOL (WINAPI *PtrFlashWindowEx)(PFLASHWINFO pfwi); -static PtrFlashWindowEx pFlashWindowEx = 0; + DWORD dwMask; + DWORD dwTime; + ULONG_PTR dwExtraInfo; + DWORD cxContact; + DWORD cyContact; +} TOUCHINPUT, *PTOUCHINPUT; + +#endif #include <windowsx.h> #include <limits.h> @@ -153,9 +171,13 @@ static PtrFlashWindowEx pFlashWindowEx = 0; #include <mywinsock.h> #endif +#ifndef IMR_CONFIRMRECONVERTSTRING +#define IMR_CONFIRMRECONVERTSTRING 0x0005 +#endif + QT_BEGIN_NAMESPACE -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE #ifndef SHRG_RETURNCMD struct SHRGINFO { DWORD cbSize; @@ -240,10 +262,6 @@ QTabletDeviceData currentTabletPointer; // from qregion_win.cpp extern HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom); -Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin, - UINT wMsgFilterMax, UINT wRemoveMsg); -Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - // support for on-the-fly changes of the XP theme engine #ifndef WM_THEMECHANGED #define WM_THEMECHANGED 0x031A @@ -258,22 +276,24 @@ Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa #define WM_XBUTTONDOWN 0x020B #define WM_XBUTTONUP 0x020C #define WM_XBUTTONDBLCLK 0x020D +#endif +#ifndef GET_KEYSTATE_WPARAM #define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam)) #define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam)) #define XBUTTON1 0x0001 #define XBUTTON2 0x0002 +#endif +#ifndef MK_XBUTTON1 #define MK_XBUTTON1 0x0020 #define MK_XBUTTON2 0x0040 #endif -#ifdef Q_OS_WINCE -#define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam)) -#endif - -// support for multi-media-keys on ME/2000/XP +// support for multi-media-keys #ifndef WM_APPCOMMAND #define WM_APPCOMMAND 0x0319 +#endif +#ifndef FAPPCOMMAND_MOUSE #define FAPPCOMMAND_MOUSE 0x8000 #define FAPPCOMMAND_KEY 0 #define FAPPCOMMAND_OEM 0x1000 @@ -307,6 +327,7 @@ Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa #define APPCOMMAND_BASS_UP 21 #define APPCOMMAND_TREBLE_DOWN 22 #define APPCOMMAND_TREBLE_UP 23 +#endif // FAPPCOMMAND_MOUSE // New commands from Windows XP (some even Sp1) #ifndef APPCOMMAND_MICROPHONE_VOLUME_MUTE @@ -341,10 +362,6 @@ Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa #define APPCOMMAND_MEDIA_CHANNEL_DOWN 52 #endif // APPCOMMAND_MICROPHONE_VOLUME_MUTE -#endif // WM_APPCOMMAND - -static UINT WM95_MOUSEWHEEL = 0; - #if (_WIN32_WINNT < 0x0400) // This struct is defined in winuser.h if the _WIN32_WINNT >= 0x0400 -- in the // other cases we have to define it on our own. @@ -376,11 +393,6 @@ QRgb qt_colorref2qrgb(COLORREF col) Internal variables and functions *****************************************************************************/ -extern Q_CORE_EXPORT char theAppName[]; -extern Q_CORE_EXPORT char appFileName[]; -extern Q_CORE_EXPORT HINSTANCE appInst; // handle to app instance -extern Q_CORE_EXPORT HINSTANCE appPrevInst; // handle to prev app instance -extern Q_CORE_EXPORT int appCmdShow; // main window show command static HWND curWin = 0; // current window static HDC displayDC = 0; // display device context @@ -422,11 +434,6 @@ extern QCursor *qt_grab_cursor(); #define __export #endif -QApplicationPrivate* getQApplicationPrivateInternal() -{ - return qApp->d_func(); -} - extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM); class QETWidget : public QWidget // event translator widget @@ -448,6 +455,7 @@ public: bool translateConfigEvent(const MSG &msg); bool translateCloseEvent(const MSG &msg); bool translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, int numPackets); + bool translateGestureEvent(const MSG &msg, const GESTUREINFO &gi); void repolishStyle(QStyle &style); inline void showChildren(bool spontaneous) { d_func()->showChildren(spontaneous); } inline void hideChildren(bool spontaneous) { d_func()->hideChildren(spontaneous); } @@ -497,7 +505,7 @@ static void qt_set_windows_color_resources() pal.setColor(QPalette::HighlightedText, QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHTTEXT)))); -#if defined(Q_OS_WINCE) +#if defined(Q_WS_WINCE) // ### hardcoded until I find out how to get it from the system settings. pal.setColor(QPalette::LinkVisited, pal.highlight().color().dark(150)); pal.setColor(QPalette::Link, pal.highlight().color().light(130)); @@ -516,14 +524,13 @@ static void qt_set_windows_color_resources() pal.setColor(QPalette::Inactive, QPalette::Light, pal.light().color()); pal.setColor(QPalette::Inactive, QPalette::Dark, pal.dark().color()); - if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95) { - if (pal.midlight() == pal.button()) - pal.setColor(QPalette::Midlight, pal.button().color().lighter(110)); - if (pal.background() != pal.base()) { - pal.setColor(QPalette::Inactive, QPalette::Highlight, pal.color(QPalette::Inactive, QPalette::Window)); - pal.setColor(QPalette::Inactive, QPalette::HighlightedText, pal.color(QPalette::Inactive, QPalette::Text)); - } + if (pal.midlight() == pal.button()) + pal.setColor(QPalette::Midlight, pal.button().color().lighter(110)); + if (pal.background() != pal.base()) { + pal.setColor(QPalette::Inactive, QPalette::Highlight, pal.color(QPalette::Inactive, QPalette::Window)); + pal.setColor(QPalette::Inactive, QPalette::HighlightedText, pal.color(QPalette::Inactive, QPalette::Text)); } + const QColor bg = pal.background().color(); const QColor fg = pal.foreground().color(), btn = pal.button().color(); QColor disabled((fg.red()+btn.red())/2,(fg.green()+btn.green())/2, @@ -573,36 +580,19 @@ static void qt_set_windows_color_resources() static void qt_set_windows_font_resources() { -#ifndef Q_OS_WINCE - QFont menuFont; - QFont messageFont; - QFont statusFont; - QFont titleFont; - QFont iconTitleFont; - QT_WA({ - NONCLIENTMETRICS ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONTW); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); - menuFont = qt_LOGFONTtoQFont(ncm.lfMenuFont,true); - messageFont = qt_LOGFONTtoQFont(ncm.lfMessageFont,true); - statusFont = qt_LOGFONTtoQFont(ncm.lfStatusFont,true); - titleFont = qt_LOGFONTtoQFont(ncm.lfCaptionFont,true); - LOGFONTW lfIconTitleFont; - SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0); - iconTitleFont = qt_LOGFONTtoQFont(lfIconTitleFont,true); - } , { - // A version - NONCLIENTMETRICSA ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, lfMessageFont) + sizeof(LOGFONTA); - SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0); - menuFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfMenuFont,true); - messageFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfMessageFont,true); - statusFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfStatusFont,true); - titleFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfCaptionFont,true); - LOGFONTA lfIconTitleFont; - SystemParametersInfoA(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0); - iconTitleFont = qt_LOGFONTtoQFont((LOGFONT&)lfIconTitleFont,true); - }); +#ifndef Q_WS_WINCE + NONCLIENTMETRICS ncm; + ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); + + QFont menuFont = qt_LOGFONTtoQFont(ncm.lfMenuFont, true); + QFont messageFont = qt_LOGFONTtoQFont(ncm.lfMessageFont, true); + QFont statusFont = qt_LOGFONTtoQFont(ncm.lfStatusFont, true); + QFont titleFont = qt_LOGFONTtoQFont(ncm.lfCaptionFont, true); + + LOGFONT lfIconTitleFont; + SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0); + QFont iconTitleFont = qt_LOGFONTtoQFont(lfIconTitleFont, true); QApplication::setFont(menuFont, "QMenu"); QApplication::setFont(menuFont, "QMenuBar"); @@ -625,24 +615,19 @@ static void qt_set_windows_font_resources() smallerFont.setPointSize(systemFont.pointSize()-1); QApplication::setFont(smallerFont, "QTabBar"); } -#endif// Q_OS_WINCE +#endif// Q_WS_WINCE } static void qt_win_read_cleartype_settings() { - QT_WA({ - UINT result; - BOOL ok; - ok = SystemParametersInfoW(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0); - if (ok) - qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE); - }, { - UINT result; - BOOL ok; - ok = SystemParametersInfoA(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0); - if (ok) - qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE); - }); + UINT result = 0; +#ifdef Q_OS_WINCE + if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &result, 0)) + qt_cleartype_enabled = result; +#else + if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0)) + qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE); +#endif } @@ -659,10 +644,10 @@ void QApplicationPrivate::initializeWidgetPaletteHash() QPalette pal = *QApplicationPrivate::sys_pal; QColor menuCol(qt_colorref2qrgb(GetSysColor(COLOR_MENU))); QColor menuText(qt_colorref2qrgb(GetSysColor(COLOR_MENUTEXT))); - BOOL isFlat = 0; + BOOL isFlat = false; if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) - SystemParametersInfo(0x1022 /*SPI_GETFLATMENU*/, 0, &isFlat, 0); + SystemParametersInfo(SPI_GETFLATMENU, 0, &isFlat, 0); QPalette menu(pal); // we might need a special color group for the menu. menu.setColor(QPalette::Active, QPalette::Button, menuCol); @@ -677,8 +662,7 @@ void QApplicationPrivate::initializeWidgetPaletteHash() QColor(qt_colorref2qrgb(GetSysColor( (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) - && isFlat ? COLOR_MENUHILIGHT - : COLOR_HIGHLIGHT)))); + && isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT)))); menu.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled); menu.setColor(QPalette::Disabled, QPalette::Button, menu.color(QPalette::Active, QPalette::Button)); @@ -694,10 +678,8 @@ void QApplicationPrivate::initializeWidgetPaletteHash() menu.color(QPalette::Active, QPalette::Highlight)); menu.setColor(QPalette::Inactive, QPalette::HighlightedText, menu.color(QPalette::Active, QPalette::HighlightedText)); - - if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95) - menu.setColor(QPalette::Inactive, QPalette::ButtonText, - pal.color(QPalette::Inactive, QPalette::Dark)); + menu.setColor(QPalette::Inactive, QPalette::ButtonText, + pal.color(QPalette::Inactive, QPalette::Dark)); QApplication::setPalette(menu, "QMenu"); if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP @@ -714,11 +696,10 @@ void QApplicationPrivate::initializeWidgetPaletteHash() qt_init() - initializes Qt for Windows *****************************************************************************/ -typedef BOOL (WINAPI *PtrUpdateLayeredWindow)(HWND hwnd, HDC hdcDst, const POINT *pptDst, - const SIZE *psize, HDC hdcSrc, const POINT *pptSrc, COLORREF crKey, - const Q_BLENDFUNCTION *pblend, DWORD dwflags); -static PtrUpdateLayeredWindow ptrUpdateLayeredWindow = 0; - +typedef BOOL (WINAPI *PtrSetProcessDPIAware) (VOID); +static PtrSetProcessDPIAware ptrSetProcessDPIAware = 0; +PtrUpdateLayeredWindow ptrUpdateLayeredWindow = 0; +PtrUpdateLayeredWindowIndirect ptrUpdateLayeredWindowIndirect = 0; static BOOL WINAPI qt_updateLayeredWindowIndirect(HWND hwnd, const Q_UPDATELAYEREDWINDOWINFO *info) { return (*ptrUpdateLayeredWindow)(hwnd, info->hdcDst, info->pptDst, info->psize, info->hdcSrc, @@ -745,9 +726,6 @@ void qt_init(QApplicationPrivate *priv, int) appNoGrab = !appNoGrab; else #endif // QT_DEBUG - if (qstrcmp(argv[i], "-direct3d") == 0) - QApplication::setAttribute(Qt::AA_MSWindowsUseDirect3DByDefault); - else argv[j++] = argv[i]; } if(j < priv->argc) { @@ -755,21 +733,12 @@ void qt_init(QApplicationPrivate *priv, int) priv->argc = j; } - // Get the application name/instance if qWinMain() was not invoked -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE // No message boxes but important ones SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); #endif - if (appInst == 0) { - QT_WA({ - appInst = GetModuleHandle(0); - }, { - appInst = GetModuleHandleA(0); - }); - } - -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE // Initialize OLE/COM // S_OK means success and S_FALSE means that it has already // been initialized @@ -781,7 +750,7 @@ void qt_init(QApplicationPrivate *priv, int) #endif // Misc. initialization -#if defined(QT_DEBUG) && !defined(Q_OS_WINCE) +#if defined(QT_DEBUG) && !defined(Q_WS_WINCE) GdiSetBatchLimit(1); #endif @@ -793,48 +762,32 @@ void qt_init(QApplicationPrivate *priv, int) #ifndef QT_NO_CURSOR QCursorData::initialize(); #endif - qApp->setObjectName(QLatin1String(theAppName)); + qApp->setObjectName(priv->appName()); -#if !defined(Q_OS_WINCE) // default font - HFONT hfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); - QFont f(QLatin1String("MS Sans Serif"),8); - int result = 0; - QT_WA({ - LOGFONT lf; - if (result = GetObject(hfont, sizeof(lf), &lf)) - f = qt_LOGFONTtoQFont((LOGFONT&)lf,true); - } , { - LOGFONTA lf; - if (result = GetObjectA(hfont, sizeof(lf), &lf)) - f = qt_LOGFONTtoQFont((LOGFONT&)lf,true); - }); - if (result - && QSysInfo::WindowsVersion >= QSysInfo::WV_2000 - && QSysInfo::WindowsVersion <= QSysInfo::WV_NT_based - && f.family() == QLatin1String("MS Shell Dlg")) - f.setFamily(QLatin1String("MS Shell Dlg 2")); - QApplicationPrivate::setSystemFont(f); -#else //Q_OS_WINCE - LOGFONT lf; - HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT); - int result = 0; - result = GetObject(stockFont, sizeof(lf), &lf); - QFont font = qt_LOGFONTtoQFont(lf, true); - if (result) - QApplicationPrivate::setSystemFont(font); -#endif //Q_OS_WINCE +#ifndef Q_WS_WINCE + HGDIOBJ stockFont = GetStockObject(DEFAULT_GUI_FONT); +#else + HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT); +#endif + + LOGFONT lf; + GetObject(stockFont, sizeof(lf), &lf); + QFont systemFont = qt_LOGFONTtoQFont(lf, true); + +#ifndef Q_WS_WINCE + if (systemFont.family() == QLatin1String("MS Shell Dlg")) { + systemFont.setFamily(QLatin1String("MS Shell Dlg 2")); + } +#endif + + QApplicationPrivate::setSystemFont(systemFont); // QFont::locale_init(); ### Uncomment when it does something on Windows if (QApplication::desktopSettingsAware()) qt_set_windows_resources(); - QT_WA({ - WM95_MOUSEWHEEL = RegisterWindowMessage(L"MSWHEEL_ROLLMSG"); - } , { - WM95_MOUSEWHEEL = RegisterWindowMessageA("MSWHEEL_ROLLMSG"); - }); initWinTabFunctions(); QApplicationPrivate::inputContext = new QWinInputContext(0); @@ -855,7 +808,50 @@ void qt_init(QApplicationPrivate *priv, int) if (ptrUpdateLayeredWindow && !ptrUpdateLayeredWindowIndirect) ptrUpdateLayeredWindowIndirect = qt_updateLayeredWindowIndirect; -#endif + + // Notify Vista and Windows 7 that we support highter DPI settings + ptrSetProcessDPIAware = (PtrSetProcessDPIAware) + QLibrary::resolve(QLatin1String("user32"), "SetProcessDPIAware"); + if (ptrSetProcessDPIAware) + ptrSetProcessDPIAware(); +#endif + + priv->GetGestureInfo = 0; + priv->GetGestureExtraArgs = 0; + +#if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES) + priv->GetGestureInfo = (PtrGetGestureInfo) &TKGetGestureInfo; + priv->GetGestureExtraArgs = (PtrGetGestureExtraArgs) &TKGetGestureExtraArguments; + priv->CloseGestureInfoHandle = (PtrCloseGestureInfoHandle) 0; + priv->SetGestureConfig = (PtrSetGestureConfig) 0; + priv->GetGestureConfig = (PtrGetGestureConfig) 0; +#elif !defined(Q_WS_WINCE) + priv->GetGestureInfo = + (PtrGetGestureInfo)QLibrary::resolve(QLatin1String("user32"), + "GetGestureInfo"); + priv->GetGestureExtraArgs = + (PtrGetGestureExtraArgs)QLibrary::resolve(QLatin1String("user32"), + "GetGestureExtraArgs"); + priv->CloseGestureInfoHandle = + (PtrCloseGestureInfoHandle)QLibrary::resolve(QLatin1String("user32"), + "CloseGestureInfoHandle"); + priv->SetGestureConfig = + (PtrSetGestureConfig)QLibrary::resolve(QLatin1String("user32"), + "SetGestureConfig"); + priv->GetGestureConfig = + (PtrGetGestureConfig)QLibrary::resolve(QLatin1String("user32"), + "GetGestureConfig"); + priv->BeginPanningFeedback = + (PtrBeginPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"), + "BeginPanningFeedback"); + priv->UpdatePanningFeedback = + (PtrUpdatePanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"), + "UpdatePanningFeedback"); + priv->EndPanningFeedback = + (PtrEndPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"), + "EndPanningFeedback"); +#endif + priv->gestureWidget = 0; } /***************************************************************************** @@ -880,7 +876,7 @@ void qt_cleanup() delete QApplicationPrivate::inputContext; QApplicationPrivate::inputContext = 0; -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE // Deinitialize OLE/COM OleUninitialize(); #endif @@ -891,12 +887,6 @@ void qt_cleanup() Platform specific global and internal functions *****************************************************************************/ -Q_GUI_EXPORT int qWinAppCmdShow() // get main window show command -{ - return appCmdShow; -} - - Q_GUI_EXPORT HDC qt_win_display_dc() // get display DC { Q_ASSERT(qApp && qApp->thread() == QThread::currentThread()); @@ -928,7 +918,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class if (flags & Qt::MSWindowsOwnDC) { cname = QLatin1String("QWidgetOwnDC"); style = CS_DBLCLKS; -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE style |= CS_OWNDC; #endif icon = true; @@ -937,25 +927,25 @@ const QString qt_reg_winclass(QWidget *w) // register window class if (w->inherits("QTipLabel") || w->inherits("QAlphaWidget")) { if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) { - style |= 0x00020000; // CS_DROPSHADOW + style |= CS_DROPSHADOW; } cname = QLatin1String("QToolTip"); } else { cname = QLatin1String("QTool"); } -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE style |= CS_SAVEBITS; #endif icon = false; } else if (type == Qt::Popup) { cname = QLatin1String("QPopup"); style = CS_DBLCLKS; -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE style |= CS_SAVEBITS; #endif if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) - style |= 0x00020000; // CS_DROPSHADOW + style |= CS_DROPSHADOW; icon = false; } else { cname = QLatin1String("QWidget"); @@ -963,7 +953,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class icon = true; } -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE // force CS_OWNDC when the GL graphics system is // used as the default renderer if (qt_win_owndc_required) @@ -975,11 +965,11 @@ const QString qt_reg_winclass(QWidget *w) // register window class // unique ID on WinCE to make sure we can // move the windows to the front when starting // a second instance. - wchar_t uniqueAppID[256]; - GetModuleFileNameW(0, uniqueAppID, 255); - cname = QString::number(RegisterWindowMessageW( - (const wchar_t *) QString::fromUtf16((const ushort *)uniqueAppID).toLower().replace(QString(QString::fromLatin1("\\")), - QString(QString::fromLatin1("_"))).utf16())); + wchar_t uniqueAppID[MAX_PATH]; + GetModuleFileName(0, uniqueAppID, MAX_PATH); + cname = QString::number(RegisterWindowMessage( + (const wchar_t *) QString::fromWCharArray(uniqueAppID).toLower().replace(QLatin1Char('\\'), + QLatin1Char('_')).utf16())); #endif // since multiple Qt versions can be used in one process @@ -990,15 +980,9 @@ const QString qt_reg_winclass(QWidget *w) // register window class static int classExists = -1; if (classExists == -1) { - QT_WA({ - WNDCLASS wcinfo; - classExists = GetClassInfo((HINSTANCE)qWinAppInst(), (TCHAR*)cname.utf16(), &wcinfo); - classExists = classExists && wcinfo.lpfnWndProc != QtWndProc; - }, { - WNDCLASSA wcinfo; - classExists = GetClassInfoA((HINSTANCE)qWinAppInst(), cname.toLatin1(), &wcinfo); - classExists = classExists && wcinfo.lpfnWndProc != QtWndProc; - }); + WNDCLASS wcinfo; + classExists = GetClassInfo((HINSTANCE)qWinAppInst(), (wchar_t*)cname.utf16(), &wcinfo); + classExists = classExists && wcinfo.lpfnWndProc != QtWndProc; } if (classExists) @@ -1007,73 +991,37 @@ const QString qt_reg_winclass(QWidget *w) // register window class if (winclassNames()->contains(cname)) // already registered in our list return cname; - ATOM atom; -#ifndef Q_OS_WINCE - HBRUSH bgBrush = (HBRUSH)GetSysColorBrush(COLOR_WINDOW); - QT_WA({ - WNDCLASS wc; - wc.style = style; - wc.lpfnWndProc = (WNDPROC)QtWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = (HINSTANCE)qWinAppInst(); - if (icon) { - wc.hIcon = LoadIcon(appInst, L"IDI_ICON1"); - if (!wc.hIcon) - wc.hIcon = LoadIcon(0, IDI_APPLICATION); - } else { - wc.hIcon = 0; - } - wc.hCursor = 0; - wc.hbrBackground= bgBrush; - wc.lpszMenuName = 0; - wc.lpszClassName= (TCHAR*)cname.utf16(); - atom = RegisterClass(&wc); - } , { - WNDCLASSA wc; - wc.style = style; - wc.lpfnWndProc = (WNDPROC)QtWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = (HINSTANCE)qWinAppInst(); - if (icon) { - wc.hIcon = LoadIconA(appInst, (char*)"IDI_ICON1"); - if (!wc.hIcon) - wc.hIcon = LoadIconA(0, (char*)IDI_APPLICATION); - } else { - wc.hIcon = 0; - } - wc.hCursor = 0; - wc.hbrBackground= bgBrush; - wc.lpszMenuName = 0; - QByteArray tempArray = cname.toLatin1(); - wc.lpszClassName= tempArray; - atom = RegisterClassA(&wc); - }); + WNDCLASS wc; + wc.style = style; + wc.lpfnWndProc = (WNDPROC)QtWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = qWinAppInst(); + if (icon) { + wc.hIcon = (HICON)LoadImage(qWinAppInst(), L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); +#ifndef Q_WS_WINCE + if (!wc.hIcon) + wc.hIcon = (HICON)LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); +#endif + } else { + wc.hIcon = 0; + } + wc.hCursor = 0; +#ifndef Q_WS_WINCE + wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW); #else - WNDCLASS wc; - wc.style = style; - wc.lpfnWndProc = (WNDPROC)QtWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = (HINSTANCE)qWinAppInst(); - if (icon) { - wc.hIcon = LoadIcon(appInst, L"IDI_ICON1"); -// if (!wc.hIcon) -// wc.hIcon = LoadIcon(0, IDI_APPLICATION); - } else { - wc.hIcon = 0; - } - wc.hCursor = 0; - wc.hbrBackground= 0; - wc.lpszMenuName = 0; - wc.lpszClassName= (TCHAR*)cname.utf16(); - atom = RegisterClass(&wc); + wc.hbrBackground = 0; #endif + wc.lpszMenuName = 0; + wc.lpszClassName = (wchar_t*)cname.utf16(); + + ATOM atom = RegisterClass(&wc); #ifndef QT_NO_DEBUG if (!atom) qErrnoWarning("QApplication::regClass: Registering window class failed."); +#else + Q_UNUSED(atom); #endif winclassNames()->insert(cname, 1); @@ -1091,11 +1039,7 @@ static void unregWinClasses() WinClassNameHash *hash = winclassNames(); QHash<QString, int>::ConstIterator it = hash->constBegin(); while (it != hash->constEnd()) { - QT_WA({ - UnregisterClass((TCHAR*)it.key().utf16(), (HINSTANCE)qWinAppInst()); - } , { - UnregisterClassA(it.key().toLatin1(), (HINSTANCE)qWinAppInst()); - }); + UnregisterClass((wchar_t*)it.key().utf16(), qWinAppInst()); ++it; } hash->clear(); @@ -1129,7 +1073,7 @@ void qWinRequestConfig(WId id, int req, int x, int y, int w, int h) configRequests->append(r); // store request in queue } -Q_GUI_EXPORT void qWinProcessConfigRequests() // perform requests in queue +static void qWinProcessConfigRequests() // perform requests in queue { if (!configRequests) return; @@ -1312,16 +1256,13 @@ void QApplication::beep() static void alert_widget(QWidget *widget, int duration) { +#ifdef Q_OS_WINCE + Q_UNUSED(widget); + Q_UNUSED(duration); +#else bool stopFlash = duration < 0; - if (!pFlashWindowEx) { -#ifndef Q_OS_WINCE - QLibrary themeLib(QLatin1String("user32")); - pFlashWindowEx = (PtrFlashWindowEx)themeLib.resolve("FlashWindowEx"); -#endif - } - - if (pFlashWindowEx && widget && (!widget->isActiveWindow() || stopFlash)) { + if (widget && (!widget->isActiveWindow() || stopFlash)) { DWORD timeOut = GetCaretBlinkTime(); if (timeOut <= 0) timeOut = 250; @@ -1339,8 +1280,9 @@ static void alert_widget(QWidget *widget, int duration) info.dwTimeout = stopFlash ? 0 : timeOut; info.uCount = stopFlash ? 0 : flashCount; - pFlashWindowEx(&info); + FlashWindowEx(&info); } +#endif } void QApplication::alert(QWidget *widget, int duration) @@ -1381,7 +1323,7 @@ void QApplication::winFocus(QWidget *widget, bool gotFocus) && (QApplicationPrivate::active_window->windowType() == Qt::Dialog)) { // raise the entire application, not just the dialog QWidget* mw = QApplicationPrivate::active_window; -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE while(mw->parentWidget() && (mw->windowType() == Qt::Dialog)) mw = mw->parentWidget()->window(); if (mw->testAttribute(Qt::WA_WState_Created) && mw != QApplicationPrivate::active_window) @@ -1428,12 +1370,13 @@ static int inputcharset = CP_ACP; static bool qt_is_translatable_mouse_event(UINT message) { - return (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST || - message >= WM_XBUTTONDOWN && message <= WM_XBUTTONDBLCLK) + return (((message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) || + (message >= WM_XBUTTONDOWN && message <= WM_XBUTTONDBLCLK)) && message != WM_MOUSEWHEEL + && message != WM_MOUSEHWHEEL) -#ifndef Q_OS_WINCE - || message >= WM_NCMOUSEMOVE && message <= WM_NCMBUTTONDBLCLK +#ifndef Q_WS_WINCE + || (message >= WM_NCMOUSEMOVE && message <= WM_NCMBUTTONDBLCLK) #endif ; } @@ -1472,7 +1415,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam msg.pt.y = GET_Y_LPARAM(lParam); // If it's a non-client-area message the coords are screen coords, otherwise they are // client coords. -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE if (message < WM_NCMOUSEMOVE || message > WM_NCMBUTTONDBLCLK) #endif ClientToScreen(msg.hwnd, &msg.pt); @@ -1502,7 +1445,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam if (imeParentWnd && QApplication::activePopupWidget() && (message == WM_MBUTTONDOWN || message == WM_XBUTTONDOWN || message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE || message == WM_NCMBUTTONDOWN || message == WM_NCLBUTTONDOWN || message == WM_NCRBUTTONDOWN)) { #else @@ -1512,7 +1455,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam } switch (message) { -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE case WM_QUERYENDSESSION: { if (sm_smActive) // bogus message from windows RETURN(true); @@ -1534,19 +1477,19 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam // we receive the message for each toplevel window included internal hidden ones, // but the aboutToQuit signal should be emitted only once. - QApplicationPrivate *qAppPriv = getQApplicationPrivateInternal(); + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); if (endsession && !qAppPriv->aboutToQuitEmitted) { qAppPriv->aboutToQuitEmitted = true; int index = QApplication::staticMetaObject.indexOfSignal("aboutToQuit()"); qApp->qt_metacall(QMetaObject::InvokeMetaMethod, index,0); // since the process will be killed immediately quit() has no real effect - qApp->quit(); + QApplication::quit(); } RETURN(0); } case WM_DISPLAYCHANGE: - if (qApp->type() == QApplication::Tty) + if (QApplication::type() == QApplication::Tty) break; if (qt_desktopWidget) { qt_desktopWidget->move(GetSystemMetrics(76), GetSystemMetrics(77)); @@ -1563,7 +1506,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam #endif case WM_SETTINGCHANGE: -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE // CE SIP hide/show if (wParam == SPI_SETSIPINFO) { QResizeEvent re(QSize(0, 0), QSize(0, 0)); // Calculated by QDesktopWidget @@ -1572,7 +1515,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam } #endif // ignore spurious XP message when user logs in again after locking - if (qApp->type() == QApplication::Tty) + if (QApplication::type() == QApplication::Tty) break; if (QApplication::desktopSettingsAware() && wParam != SPI_SETWORKAREA) { widget = (QETWidget*)QWidget::find(hwnd); @@ -1595,7 +1538,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam if (wParam == SPI_SETFONTSMOOTHINGTYPE) { qt_win_read_cleartype_settings(); - foreach (QWidget *w, qApp->topLevelWidgets()) { + foreach (QWidget *w, QApplication::topLevelWidgets()) { if (!w->isVisible()) continue; ((QETWidget *) w)->forceUpdate(); @@ -1604,7 +1547,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam break; case WM_SYSCOLORCHANGE: - if (qApp->type() == QApplication::Tty) + if (QApplication::type() == QApplication::Tty) break; if (QApplication::desktopSettingsAware()) { widget = (QETWidget*)QWidget::find(hwnd); @@ -1656,7 +1599,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam RETURN(res); if (qt_is_translatable_mouse_event(message)) { - if (qApp->activePopupWidget() != 0) { // in popup mode + if (QApplication::activePopupWidget() != 0) { // in popup mode POINT curPos = msg.pt; QWidget* w = QApplication::widgetAt(curPos.x, curPos.y); if (w) @@ -1665,10 +1608,10 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam if (!qt_tabletChokeMouse) { result = widget->translateMouseEvent(msg); // mouse event -#if defined(Q_OS_WINCE) && !defined(QT_NO_CONTEXTMENU) - if (message == WM_LBUTTONDOWN && widget != qApp->activePopupWidget()) { +#if defined(Q_WS_WINCE) && !defined(QT_NO_CONTEXTMENU) + if (message == WM_LBUTTONDOWN && widget != QApplication::activePopupWidget()) { QWidget* alienWidget = widget; - if ((alienWidget != qApp->activePopupWidget()) && (alienWidget->contextMenuPolicy() != Qt::PreventContextMenu)) { + if ((alienWidget != QApplication::activePopupWidget()) && (alienWidget->contextMenuPolicy() != Qt::PreventContextMenu)) { QPoint pos(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); QPoint globalPos(msg.pt.x, msg.pt.y); // In case we are using Alien, then the widget to @@ -1687,8 +1630,8 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam shrg.dwFlags = SHRG_RETURNCMD | SHRG_NOANIMATION; resolveAygLibs(); if (ptrRecognizeGesture && (ptrRecognizeGesture(&shrg) == GN_CONTEXTMENU)) { - if (qApp->activePopupWidget()) - qApp->activePopupWidget()->close(); + if (QApplication::activePopupWidget()) + QApplication::activePopupWidget()->close(); QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos); result = qt_sendSpontaneousEvent(alienWidget, &e); } @@ -1700,7 +1643,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam // Sometimes we only get a WM_MOUSEMOVE message // and sometimes we get both a WM_MOUSEMOVE and // a WM_LBUTTONDOWN/UP, this creates a spurious mouse - // press/release event, using the winPeekMessage + // press/release event, using the PeekMessage // will help us fix this. This leaves us with a // question: // This effectively kills using the mouse AND the @@ -1710,18 +1653,19 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam bool is_mouse_move = (message == WM_MOUSEMOVE); if (is_mouse_move) { MSG msg1; - if (winPeekMessage(&msg1, msg.hwnd, WM_MOUSEFIRST, - WM_MOUSELAST, PM_NOREMOVE)) + if (PeekMessage(&msg1, msg.hwnd, WM_MOUSEFIRST, + WM_MOUSELAST, PM_NOREMOVE)) next_is_button = (msg1.message == WM_LBUTTONUP || msg1.message == WM_LBUTTONDOWN); } if (!is_mouse_move || (is_mouse_move && !next_is_button)) qt_tabletChokeMouse = false; } - } else if (message == WM95_MOUSEWHEEL) { - result = widget->translateWheelEvent(msg); } else { switch (message) { + case WM_TOUCH: + result = QApplicationPrivate::instance()->translateTouchEvent(msg); + break; case WM_KEYDOWN: // keyboard event case WM_SYSKEYDOWN: qt_keymapper_private()->updateKeyMap(msg); @@ -1747,7 +1691,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam case WM_IME_KEYDOWN: case WM_CHAR: { MSG msg1; - bool anyMsg = winPeekMessage(&msg1, msg.hwnd, 0, 0, PM_NOREMOVE); + bool anyMsg = PeekMessage(&msg1, msg.hwnd, 0, 0, PM_NOREMOVE); if (anyMsg && msg1.message == WM_DEADCHAR) { result = true; // consume event since there is a dead char next break; @@ -1766,7 +1710,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam widget = (QETWidget*)QApplication::activePopupWidget()->focusWidget() ? (QETWidget*)QApplication::activePopupWidget()->focusWidget() : (QETWidget*)QApplication::activePopupWidget(); - else if (qApp->focusWidget()) + else if (QApplication::focusWidget()) widget = (QETWidget*)QApplication::focusWidget(); else if (!widget || widget->internalWinId() == GetFocus()) // We faked the message to go to exactly that widget. widget = (QETWidget*)widget->window(); @@ -1781,6 +1725,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam break; case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: result = widget->translateWheelEvent(msg); break; @@ -1888,8 +1833,8 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam QWidget *g = QWidget::keyboardGrabber(); if (g) widget = (QETWidget*)g; - else if (qApp->focusWidget()) - widget = (QETWidget*)qApp->focusWidget(); + else if (QApplication::focusWidget()) + widget = (QETWidget*)QApplication::focusWidget(); else widget = (QETWidget*)widget->window(); if (widget->isEnabled()) { @@ -1911,17 +1856,21 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam } break; -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE case WM_NCHITTEST: if (widget->isWindow()) { QPoint pos = widget->mapFromGlobal(QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); // don't show resize-cursors for fixed-size widgets QRect fs = widget->frameStrut(); if (!widget->isMinimized()) { + if (widget->minimumHeight() == widget->maximumHeight()) { + if (pos.y() < -(fs.top() - fs.left())) + return HTCAPTION; + if (pos.y() >= widget->height()) + return HTBORDER; + } if (widget->minimumWidth() == widget->maximumWidth() && (pos.x() < 0 || pos.x() >= widget->width())) - break; - if (widget->minimumHeight() == widget->maximumHeight() && (pos.y() < -(fs.top() - fs.left()) || pos.y() >= widget->height())) - break; + return HTBORDER; } } @@ -1930,7 +1879,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam #endif case WM_SYSCOMMAND: { -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE bool window_state_change = false; Qt::WindowStates oldstate = Qt::WindowStates(widget->dataPtr()->window_state); // MSDN:In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are @@ -1942,11 +1891,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam #ifndef QT_NO_WHATSTHIS QWhatsThis::enterWhatsThisMode(); #endif - QT_WA({ - DefWindowProc(hwnd, WM_NCPAINT, 1, 0); - } , { - DefWindowProcA(hwnd, WM_NCPAINT, 1, 0); - }); + DefWindowProc(hwnd, WM_NCPAINT, 1, 0); break; #if defined(QT_NON_COMMERCIAL) QT_NC_SYSCOMMAND @@ -2000,12 +1945,11 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam } case WM_SETTINGCHANGE: - if ( qApp->type() == QApplication::Tty ) + if ( QApplication::type() == QApplication::Tty ) break; if (!msg.wParam) { - QString area = QT_WA_INLINE(QString::fromUtf16((unsigned short *)msg.lParam), - QString::fromLocal8Bit((char*)msg.lParam)); + QString area = QString::fromWCharArray((wchar_t*)msg.lParam); if (area == QLatin1String("intl")) { QLocalePrivate::updateSystemPrivate(); if (!widget->testAttribute(Qt::WA_SetLocale)) @@ -2013,7 +1957,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam } } else if (msg.wParam == SPI_SETICONTITLELOGFONT) { - if (qApp->desktopSettingsAware()) { + if (QApplication::desktopSettingsAware()) { widget = (QETWidget*)QWidget::find(hwnd); if (widget && !widget->parentWidget()) { qt_set_windows_font_resources(); @@ -2027,7 +1971,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam result = widget->translatePaintEvent(msg); break; -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE case WM_ENTERSIZEMOVE: autoCaptureWnd = hwnd; QApplicationPrivate::inSizeMove = true; @@ -2056,7 +2000,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam break; case WM_ACTIVATE: - if ( qApp->type() == QApplication::Tty ) + if ( QApplication::type() == QApplication::Tty ) break; if (ptrWTOverlap && ptrWTEnable) { @@ -2082,9 +2026,13 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam // WM_ACTIVATEAPP handles the "true" false case, as this is only when the application // loses focus. Doing it here would result in the widget getting focus to not know // where it got it from; it would simply get a 0 value as the old focus widget. +#ifndef Q_WS_WINCE_WM if (!(widget->windowState() & Qt::WindowMinimized)) { // Ignore the activate message send by WindowsXP to a minimized window -#ifdef Q_OS_WINCE_WM +#else + { + if (widget->windowState() & Qt::WindowMinimized) + widget->dataPtr()->window_state &= ~Qt::WindowMinimized; if (widget->windowState() & Qt::WindowFullScreen) qt_wince_hide_taskbar(widget->winId()); #endif @@ -2111,7 +2059,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam } break; -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE case WM_MOUSEACTIVATE: if (widget->window()->windowType() == Qt::Tool) { QWidget *w = widget; @@ -2200,7 +2148,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam result = false; break; -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE case WM_WINDOWPOSCHANGING: { result = false; @@ -2281,12 +2229,12 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam QWidget *fw = QWidget::keyboardGrabber(); if (!fw) { - if (qApp->activePopupWidget()) - fw = (qApp->activePopupWidget()->focusWidget() - ? qApp->activePopupWidget()->focusWidget() - : qApp->activePopupWidget()); - else if (qApp->focusWidget()) - fw = qApp->focusWidget(); + if (QApplication::activePopupWidget()) + fw = (QApplication::activePopupWidget()->focusWidget() + ? QApplication::activePopupWidget()->focusWidget() + : QApplication::activePopupWidget()); + else if (QApplication::focusWidget()) + fw = QApplication::focusWidget(); else if (widget) fw = widget->window(); } @@ -2303,7 +2251,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION: case WM_IME_COMPOSITION: { - QWidget *fw = qApp->focusWidget(); + QWidget *fw = QApplication::focusWidget(); QWinInputContext *im = fw ? qobject_cast<QWinInputContext *>(fw->inputContext()) : 0; if (fw && im) { if(message == WM_IME_STARTCOMPOSITION) @@ -2315,8 +2263,27 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam } break; } - -#ifndef Q_OS_WINCE + case WM_IME_REQUEST: { + QWidget *fw = QApplication::focusWidget(); + QWinInputContext *im = fw ? qobject_cast<QWinInputContext *>(fw->inputContext()) : 0; + if (fw && im) { + if(wParam == IMR_RECONVERTSTRING) { + int ret = im->reconvertString((RECONVERTSTRING *)lParam); + if (ret == -1) { + result = false; + } else { + return ret; + } + } else if (wParam == IMR_CONFIRMRECONVERTSTRING) { + RETURN(TRUE); + } else { + // in all other cases, call DefWindowProc() + result = false; + } + } + break; + } +#ifndef Q_WS_WINCE case WM_CHANGECBCHAIN: case WM_DRAWCLIPBOARD: #endif @@ -2336,7 +2303,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam case WM_GETOBJECT: { // Ignoring all requests while starting up - if (qApp->startingUp() || qApp->closingDown() || (DWORD)lParam != OBJID_CLIENT) { + if (QApplication::startingUp() || QApplication::closingDown() || (DWORD)lParam != OBJID_CLIENT) { result = false; break; } @@ -2379,11 +2346,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam text = widget->objectName(); ret = qMin<int>(wParam - 1, text.size()); text.resize(ret); - QT_WA({ - memcpy((void *)lParam, text.utf16(), (text.size() + 1) * 2); - }, { - memcpy((void *)lParam, text.toLocal8Bit().data(), text.size() + 1); - }); + memcpy((void *)lParam, text.utf16(), (text.size() + 1) * sizeof(ushort)); delete acc; } if (!ret) { @@ -2423,7 +2386,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam #endif // QT_NO_TABLETEVENT } break; -#ifdef Q_OS_WINCE_WM +#ifdef Q_WS_WINCE_WM case WM_SETFOCUS: { HIMC hC; hC = ImmGetContext(hwnd); @@ -2436,7 +2399,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam case WM_KILLFOCUS: if (!QWidget::find((HWND)wParam)) { // we don't get focus, so unset it now if (!widget->hasFocus()) // work around Windows bug after minimizing/restoring - widget = (QETWidget*)qApp->focusWidget(); + widget = (QETWidget*)QApplication::focusWidget(); HWND focus = ::GetFocus(); //if there is a current widget and the new widget belongs to the same toplevel window //or if the current widget was embedded into non-qt window (i.e. we won't get WM_ACTIVATEAPP) @@ -2455,27 +2418,27 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam } break; case WM_THEMECHANGED: - if ((widget->windowType() == Qt::Desktop) || !qApp || qApp->closingDown() - || qApp->type() == QApplication::Tty) + if ((widget->windowType() == Qt::Desktop) || !qApp || QApplication::closingDown() + || QApplication::type() == QApplication::Tty) break; if (widget->testAttribute(Qt::WA_WState_Polished)) - qApp->style()->unpolish(widget); + QApplication::style()->unpolish(widget); if (widget->testAttribute(Qt::WA_WState_Polished)) - qApp->style()->polish(widget); - widget->repolishStyle(*qApp->style()); + QApplication::style()->polish(widget); + widget->repolishStyle(*QApplication::style()); if (widget->isVisible()) widget->update(); break; -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE case WM_INPUTLANGCHANGE: { - char info[7]; - if (!GetLocaleInfoA(MAKELCID(lParam, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, info, 6)) { + wchar_t info[7]; + if (!GetLocaleInfo(MAKELCID(lParam, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, info, 6)) { inputcharset = CP_ACP; } else { - inputcharset = QString::fromLatin1(info).toInt(); + inputcharset = QString::fromWCharArray(info).toInt(); } QKeyMapper::changeKeyboard(); break; @@ -2569,6 +2532,38 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam } result = false; break; + case WM_GESTURE: { + GESTUREINFO gi; + memset(&gi, 0, sizeof(GESTUREINFO)); + gi.cbSize = sizeof(GESTUREINFO); + + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); + BOOL bResult = false; + if (qAppPriv->GetGestureInfo) + bResult = qAppPriv->GetGestureInfo((HANDLE)msg.lParam, &gi); + if (bResult) { + if (gi.dwID == GID_BEGIN) { + // find the alien widget for the gesture position. + // This might not be accurate as the position is the center + // point of two fingers for multi-finger gestures. + QPoint pt(gi.ptsLocation.x, gi.ptsLocation.y); + QWidget *w = widget->childAt(widget->mapFromGlobal(pt)); + qAppPriv->gestureWidget = w ? w : widget; + } + if (qAppPriv->gestureWidget) + static_cast<QETWidget*>(qAppPriv->gestureWidget)->translateGestureEvent(msg, gi); + if (qAppPriv->CloseGestureInfoHandle) + qAppPriv->CloseGestureInfoHandle((HANDLE)msg.lParam); + if (gi.dwID == GID_END) + qAppPriv->gestureWidget = 0; + } else { + DWORD dwErr = GetLastError(); + if (dwErr > 0) + qWarning() << "translateGestureEvent: error = " << dwErr; + } + result = true; + break; + } default: result = false; // event was not processed break; @@ -2667,19 +2662,19 @@ bool qt_try_modal(QWidget *widget, MSG *msg, int& ret) int type = msg->message; bool block_event = false; -#ifndef Q_OS_WINCE - if (type != WM_NCHITTEST) +#ifndef Q_WS_WINCE + if (type != WM_NCHITTEST) { #endif if ((type >= WM_MOUSEFIRST && type <= WM_MOUSELAST) || - type == WM_MOUSEWHEEL || type == (int)WM95_MOUSEWHEEL || + type == WM_MOUSEWHEEL || type == WM_MOUSEHWHEEL || type == WM_MOUSELEAVE || (type >= WM_KEYFIRST && type <= WM_KEYLAST) -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE || type == WM_NCMOUSEMOVE #endif ) { if (type == WM_MOUSEMOVE -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE || type == WM_NCMOUSEMOVE #endif ) { @@ -2697,18 +2692,19 @@ bool qt_try_modal(QWidget *widget, MSG *msg, int& ret) } else if (type == WM_CLOSE) { block_event = true; } -#ifndef Q_OS_WINCE - else if (type == WM_MOUSEACTIVATE || type == WM_NCLBUTTONDOWN){ - if (!top->isActiveWindow()) { - top->activateWindow(); - } else { - QApplication::beep(); - } - block_event = true; - ret = MA_NOACTIVATEANDEAT; - } else if (type == WM_SYSCOMMAND) { - if (!(msg->wParam == SC_RESTORE && widget->isMinimized())) +#ifndef Q_WS_WINCE + else if (type == WM_MOUSEACTIVATE || type == WM_NCLBUTTONDOWN){ + if (!top->isActiveWindow()) { + top->activateWindow(); + } else { + QApplication::beep(); + } block_event = true; + ret = MA_NOACTIVATEANDEAT; + } else if (type == WM_SYSCOMMAND) { + if (!(msg->wParam == SC_RESTORE && widget->isMinimized())) + block_event = true; + } } #endif @@ -2752,9 +2748,9 @@ void QApplicationPrivate::openPopup(QWidget *popup) if (popup->focusWidget()) { popup->focusWidget()->setFocus(Qt::PopupFocusReason); } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup - if (QWidget *fw = q_func()->focusWidget()) { + if (QWidget *fw = QApplication::focusWidget()) { QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); - q_func()->sendEvent(fw, &e); + QApplication::sendEvent(fw, &e); } } } @@ -2781,13 +2777,13 @@ void QApplicationPrivate::closePopup(QWidget *popup) if (!qt_nograb()) // grabbing not disabled releaseAutoCapture(); QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget() - : q_func()->focusWidget(); + : QApplication::focusWidget(); if (fw) { - if (fw != q_func()->focusWidget()) { + if (fw != QApplication::focusWidget()) { fw->setFocus(Qt::PopupFocusReason); } else { QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason); - q_func()->sendEvent(fw, &e); + QApplication::sendEvent(fw, &e); } } } else { @@ -2855,7 +2851,7 @@ static const ushort mouseTbl[] = { WM_XBUTTONUP, QEvent::MouseButtonRelease, Qt::XButton1, WM_XBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::XButton1, -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE WM_NCMOUSEMOVE, QEvent::NonClientAreaMouseMove, 0, WM_NCLBUTTONDOWN, QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton, WM_NCLBUTTONUP, QEvent::NonClientAreaMouseButtonRelease, Qt::LeftButton, @@ -2910,20 +2906,11 @@ void qt_win_eatMouseMove() // remove all those messages (usually 1) and post the last one with a // reset button state - MSG msg = {0, 0, 0, 0, 0, 0, 0}; - QT_WA( { - while (PeekMessage(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) - ; - if (msg.message == WM_MOUSEMOVE) - PostMessage(msg.hwnd, msg.message, 0, msg.lParam); - }, { - MSG msg; - msg.message = 0; - while (PeekMessageA(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) - ; - if (msg.message == WM_MOUSEMOVE) - PostMessageA(msg.hwnd, msg.message, 0, msg.lParam); - } ); + MSG msg = {0, 0, 0, 0, 0, {0, 0} }; + while (PeekMessage(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) + ; + if (msg.message == WM_MOUSEMOVE) + PostMessage(msg.hwnd, msg.message, 0, msg.lParam); } // In DnD, the mouse release event never appears, so the @@ -2958,8 +2945,8 @@ bool QETWidget::translateMouseEvent(const MSG &msg) // Compress mouse move events if (msg.message == WM_MOUSEMOVE) { MSG mouseMsg; - while (winPeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEFIRST, - WM_MOUSELAST, PM_NOREMOVE)) { + while (PeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEFIRST, + WM_MOUSELAST, PM_NOREMOVE)) { if (mouseMsg.message == WM_MOUSEMOVE) { #define PEEKMESSAGE_IS_BROKEN 1 #ifdef PEEKMESSAGE_IS_BROKEN @@ -2970,12 +2957,12 @@ bool QETWidget::translateMouseEvent(const MSG &msg) // key release events (kls 2003-05-13): MSG keyMsg; bool done = false; - while (winPeekMessage(&keyMsg, 0, WM_KEYFIRST, WM_KEYLAST, - PM_NOREMOVE)) { + while (PeekMessage(&keyMsg, 0, WM_KEYFIRST, WM_KEYLAST, + PM_NOREMOVE)) { if (keyMsg.time < mouseMsg.time) { if ((keyMsg.lParam & 0xC0000000) == 0x40000000) { - winPeekMessage(&keyMsg, 0, keyMsg.message, - keyMsg.message, PM_REMOVE); + PeekMessage(&keyMsg, 0, keyMsg.message, + keyMsg.message, PM_REMOVE); } else { done = true; break; @@ -3001,8 +2988,8 @@ bool QETWidget::translateMouseEvent(const MSG &msg) msgPtr->wParam = mouseMsg.wParam; msgPtr->pt = mouseMsg.pt; // Remove the mouse move message - winPeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEMOVE, - WM_MOUSEMOVE, PM_REMOVE); + PeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEMOVE, + WM_MOUSEMOVE, PM_REMOVE); } else { break; // there was no more WM_MOUSEMOVE event } @@ -3031,7 +3018,9 @@ bool QETWidget::translateMouseEvent(const MSG &msg) if (alienWidget && alienWidget->internalWinId()) alienWidget = 0; - if (type == QEvent::MouseMove || type == QEvent::NonClientAreaMouseMove) { + if (type == QEvent::MouseMove || type == QEvent::NonClientAreaMouseMove + || type == QEvent::TabletMove) { + if (!(state & Qt::MouseButtonMask)) qt_button_down = 0; #ifndef QT_NO_CURSOR @@ -3051,7 +3040,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg) HWND id = effectiveWinId(); QWidget *mouseGrabber = QWidget::mouseGrabber(); - QWidget *activePopupWidget = qApp->activePopupWidget(); + QWidget *activePopupWidget = QApplication::activePopupWidget(); if (mouseGrabber) { if (!activePopupWidget || (activePopupWidget == this && !rect().contains(widgetPos))) id = mouseGrabber->effectiveWinId(); @@ -3144,7 +3133,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg) return false; replayPopupMouseEvent = false; - QWidget* activePopupWidget = qApp->activePopupWidget(); + QWidget* activePopupWidget = QApplication::activePopupWidget(); QWidget *target = activePopupWidget; const QPoint globalPos(gpos.x, gpos.y); @@ -3162,6 +3151,8 @@ bool QETWidget::translateMouseEvent(const MSG &msg) popupButtonFocus = popupChild; break; case QEvent::MouseButtonRelease: + case QEvent::TabletRelease: + releaseAfter = true; break; default: @@ -3172,10 +3163,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg) if (popupButtonFocus) { target = popupButtonFocus; } else if (popupChild) { - // forward mouse events to the popup child. mouse move events - // are only forwarded to popup children that enable mouse tracking. - if (type != QEvent::MouseMove || popupChild->hasMouseTracking()) - target = popupChild; + target = popupChild; } pos = target->mapFromGlobal(globalPos); @@ -3205,7 +3193,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg) } if (type == QEvent::MouseButtonPress - && qApp->activePopupWidget() != activePopupWidget + && QApplication::activePopupWidget() != activePopupWidget && replayPopupMouseEvent) { // the popup dissappeared. Replay the event QWidget* w = QApplication::widgetAt(gpos.x, gpos.y); @@ -3219,10 +3207,10 @@ bool QETWidget::translateMouseEvent(const MSG &msg) POINT widgetpt = gpos; ScreenToClient(hwndTarget, &widgetpt); LPARAM lParam = MAKELPARAM(widgetpt.x, widgetpt.y); - winPostMessage(hwndTarget, msg.message, msg.wParam, lParam); + PostMessage(hwndTarget, msg.message, msg.wParam, lParam); } } else if (type == QEvent::MouseButtonRelease && button == Qt::RightButton - && qApp->activePopupWidget() == activePopupWidget) { + && QApplication::activePopupWidget() == activePopupWidget) { // popup still alive and received right-button-release #if !defined(QT_NO_CONTEXTMENU) QContextMenuEvent e2(QContextMenuEvent::Mouse, pos, globalPos, @@ -3286,12 +3274,12 @@ bool QETWidget::translateWheelEvent(const MSG &msg) state = translateButtonState(GET_KEYSTATE_WPARAM(msg.wParam), 0, 0); int delta; - if (msg.message == WM_MOUSEWHEEL) + if (msg.message == WM_MOUSEWHEEL || msg.message == WM_MOUSEHWHEEL) delta = (short) HIWORD (msg.wParam); else delta = (int) msg.wParam; - Qt::Orientation orient = (state&Qt::AltModifier + Qt::Orientation orient = (msg.message == WM_MOUSEHWHEEL || state&Qt::AltModifier #if 0 // disabled for now - Trenton's one-wheel mouse makes trouble... // "delta" for usual wheels is +-120. +-240 seems to indicate @@ -3305,6 +3293,13 @@ bool QETWidget::translateWheelEvent(const MSG &msg) #endif ) ? Qt::Horizontal : Qt::Vertical; + // according to the MSDN documentation on WM_MOUSEHWHEEL: + // a positive value indicates that the wheel was rotated to the right; + // a negative value indicates that the wheel was rotated to the left. + // Qt defines this value as the exact opposite, so we have to flip the value! + if (msg.message == WM_MOUSEHWHEEL) + delta = -delta; + QPoint globalPos; globalPos.rx() = (short)LOWORD (msg.lParam); @@ -3325,7 +3320,7 @@ bool QETWidget::translateWheelEvent(const MSG &msg) // send the event to the widget or its ancestors { - QWidget* popup = qApp->activePopupWidget(); + QWidget* popup = QApplication::activePopupWidget(); if (popup && w->window() != popup) popup->close(); #ifndef QT_NO_WHEELEVENT @@ -3341,8 +3336,8 @@ bool QETWidget::translateWheelEvent(const MSG &msg) } // send the event to the widget that has the focus or its ancestors, if different - if (w != qApp->focusWidget() && (w = qApp->focusWidget())) { - QWidget* popup = qApp->activePopupWidget(); + if (w != QApplication::focusWidget() && (w = QApplication::focusWidget())) { + QWidget* popup = QApplication::activePopupWidget(); if (popup && w->window() != popup) popup->close(); #ifndef QT_NO_WHEELEVENT @@ -3395,17 +3390,19 @@ static void tabletInit(UINT wActiveCsr, HCTX hTab) tdd.minTanPressure = int(np.axMin); tdd.maxTanPressure = int(np.axMax); - ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_X, &np); - tdd.minX = int(np.axMin); - tdd.maxX = int(np.axMax); + LOGCONTEXT lcMine; - ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_Y, &np); - tdd.minY = int(np.axMin); - tdd.maxY = int(np.axMax); + /* get default region */ + ptrWTInfo(WTI_DEFCONTEXT, 0, &lcMine); - ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_Z, &np); - tdd.minZ = int(np.axMin); - tdd.maxZ = int(np.axMax); + tdd.minX = 0; + tdd.maxX = int(lcMine.lcInExtX) - int(lcMine.lcInOrgX); + + tdd.minY = 0; + tdd.maxY = int(lcMine.lcInExtY) - int(lcMine.lcInOrgY); + + tdd.minZ = 0; + tdd.maxZ = int(lcMine.lcInExtZ) - int(lcMine.lcInOrgZ); int csr_type, csr_physid; @@ -3515,13 +3512,34 @@ bool QETWidget::translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, } QPoint globalPos(qRound(hiResGlobal.x()), qRound(hiResGlobal.y())); + if (t == QEvent::TabletPress) + { + qt_button_down = QApplication::widgetAt(globalPos); + } + // make sure the tablet event get's sent to the proper widget... - QWidget *w = QApplication::widgetAt(globalPos); + QWidget *w = 0; + if (qt_button_down) w = qt_button_down; // Pass it to the thing that's grabbed it. + else + w = QApplication::widgetAt(globalPos); if (!w) w = this; + + if (t == QEvent::TabletRelease) + { + if (qt_win_ignoreNextMouseReleaseEvent) { + qt_win_ignoreNextMouseReleaseEvent = false; + if (qt_button_down && qt_button_down->internalWinId() == autoCaptureWnd) { + releaseAutoCapture(); + qt_button_down = 0; + } + } + + } + QPoint localPos = w->mapFromGlobal(globalPos); #ifndef QT_NO_TABLETEVENT if (currentTabletPointer.currentDevice == QTabletEvent::Airbrush) { @@ -3579,14 +3597,8 @@ static void initWinTabFunctions() QLibrary library(QLatin1String("wintab32")); if (library.load()) { - QT_WA({ - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); - ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); - } , { - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoA"); - ptrWTGet = (PtrWTGet)library.resolve("WTGetA"); - }); - + ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); + ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable"); ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap"); ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet"); @@ -3657,7 +3669,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg) WORD b = HIWORD(msg.lParam); QSize oldSize = size(); QSize newSize(a, b); -#ifdef Q_OS_WINCE_WM +#ifdef Q_WS_WINCE_WM if (isFullScreen() && (oldSize.width() == newSize.height()) && (oldSize.height() == newSize.width())) qt_wince_hide_taskbar(internalWinId()); #endif @@ -3669,7 +3681,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg) // Capture SIZE_MINIMIZED without preceding WM_SYSCOMMAND // (like Windows+M) if (msg.wParam == SIZE_MINIMIZED && !isMinimized()) { -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE const QString title = windowIconText(); if (!title.isEmpty()) d_func()->setWindowTitle_helper(title); @@ -3681,7 +3693,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg) hideChildren(true); } } else if (msg.wParam != SIZE_MINIMIZED && isMinimized()) { -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE const QString title = windowTitle(); if (!title.isEmpty()) d_func()->setWindowTitle_helper(title); @@ -3727,7 +3739,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg) QPoint oldPos = geometry().topLeft(); QPoint newCPos(a, b); // Ignore silly Windows move event to wild pos after iconify. -#if !defined(Q_OS_WINCE) +#if !defined(Q_WS_WINCE) if (!IsIconic(internalWinId()) && newCPos != oldPos) { #endif cr.moveTopLeft(newCPos); @@ -3739,7 +3751,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg) QMoveEvent * e = new QMoveEvent(newCPos, oldPos); QApplication::postEvent(this, e); } -#if !defined(Q_OS_WINCE) +#if !defined(Q_WS_WINCE) } #endif } @@ -3760,6 +3772,45 @@ bool QETWidget::translateCloseEvent(const MSG &) return d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); } +bool QETWidget::translateGestureEvent(const MSG &, const GESTUREINFO &gi) +{ + const QPoint widgetPos = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); + QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos); + if (alienWidget && alienWidget->internalWinId()) + alienWidget = 0; + QWidget *widget = alienWidget ? alienWidget : this; + + QNativeGestureEvent event; + event.sequenceId = gi.dwSequenceID; + event.position = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); + event.argument = gi.ullArguments; + + switch (gi.dwID) { + case GID_BEGIN: + event.gestureType = QNativeGestureEvent::GestureBegin; + break; + case GID_END: + event.gestureType = QNativeGestureEvent::GestureEnd; + break; + case GID_ZOOM: + event.gestureType = QNativeGestureEvent::Zoom; + break; + case GID_PAN: + event.gestureType = QNativeGestureEvent::Pan; + break; + case GID_ROTATE: + event.gestureType = QNativeGestureEvent::Rotate; + break; + case GID_TWOFINGERTAP: + case GID_ROLLOVER: + default: + break; + } + if (event.gestureType != QNativeGestureEvent::None) + qt_sendSpontaneousEvent(widget, &event); + return true; +} + void QApplication::setCursorFlashTime(int msecs) { @@ -3781,7 +3832,7 @@ int QApplication::cursorFlashTime() void QApplication::setDoubleClickInterval(int ms) { -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE SetDoubleClickTime(ms); #endif QApplicationPrivate::mouse_double_click_time = ms; @@ -3813,11 +3864,7 @@ void QApplication::setWheelScrollLines(int n) #ifdef SPI_SETWHEELSCROLLLINES if (n < 0) n = 0; - QT_WA({ - SystemParametersInfo(SPI_SETWHEELSCROLLLINES, (uint)n, 0, 0); - } , { - SystemParametersInfoA(SPI_SETWHEELSCROLLLINES, (uint)n, 0, 0); - }); + SystemParametersInfo(SPI_SETWHEELSCROLLLINES, (uint)n, 0, 0); #else QApplicationPrivate::wheel_scroll_lines = n; #endif @@ -3827,11 +3874,7 @@ int QApplication::wheelScrollLines() { #ifdef SPI_GETWHEELSCROLLLINES uint i = 3; - QT_WA({ - SystemParametersInfo(SPI_GETWHEELSCROLLLINES, sizeof(uint), &i, 0); - } , { - SystemParametersInfoA(SPI_GETWHEELSCROLLLINES, sizeof(uint), &i, 0); - }); + SystemParametersInfo(SPI_GETWHEELSCROLLLINES, sizeof(uint), &i, 0); if (i > INT_MAX) i = INT_MAX; return i; @@ -3876,8 +3919,7 @@ bool QApplication::isEffectEnabled(Qt::UIEffect effect) if (QColormap::instance().depth() < 16) return false; - if (!effect_override && desktopSettingsAware() - && !(QSysInfo::WindowsVersion == QSysInfo::WV_95 || QSysInfo::WindowsVersion == QSysInfo::WV_NT)) { + if (!effect_override && desktopSettingsAware()) { // we know that they can be used when we are here BOOL enabled = false; UINT api; @@ -3886,33 +3928,22 @@ bool QApplication::isEffectEnabled(Qt::UIEffect effect) api = SPI_GETMENUANIMATION; break; case Qt::UI_FadeMenu: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) - return false; api = SPI_GETMENUFADE; break; case Qt::UI_AnimateCombo: api = SPI_GETCOMBOBOXANIMATION; break; case Qt::UI_AnimateTooltip: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) - api = SPI_GETMENUANIMATION; - else - api = SPI_GETTOOLTIPANIMATION; + api = SPI_GETTOOLTIPANIMATION; break; case Qt::UI_FadeTooltip: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) - return false; api = SPI_GETTOOLTIPFADE; break; default: api = SPI_GETUIEFFECTS; break; } - QT_WA({ - SystemParametersInfo(api, 0, &enabled, 0); - } , { - SystemParametersInfoA(api, 0, &enabled, 0); - }); + SystemParametersInfo(api, 0, &enabled, 0); return enabled; } @@ -3961,4 +3992,90 @@ void QSessionManager::cancel() #endif //QT_NO_SESSIONMANAGER + +PtrRegisterTouchWindow QApplicationPrivate::RegisterTouchWindow = 0; +PtrGetTouchInputInfo QApplicationPrivate::GetTouchInputInfo = 0; +PtrCloseTouchInputHandle QApplicationPrivate::CloseTouchInputHandle = 0; + +void QApplicationPrivate::initializeMultitouch_sys() +{ + QLibrary library(QLatin1String("user32")); + // MinGW (g++ 3.4.5) accepts only C casts. + RegisterTouchWindow = (PtrRegisterTouchWindow)(library.resolve("RegisterTouchWindow")); + GetTouchInputInfo = (PtrGetTouchInputInfo)(library.resolve("GetTouchInputInfo")); + CloseTouchInputHandle = (PtrCloseTouchInputHandle)(library.resolve("CloseTouchInputHandle")); + + touchInputIDToTouchPointID.clear(); +} + +void QApplicationPrivate::cleanupMultitouch_sys() +{ + touchInputIDToTouchPointID.clear(); +} + +bool QApplicationPrivate::translateTouchEvent(const MSG &msg) +{ + QWidget *widgetForHwnd = QWidget::find(msg.hwnd); + if (!widgetForHwnd) + return false; + + QRect screenGeometry = QApplication::desktop()->screenGeometry(widgetForHwnd); + + QList<QTouchEvent::TouchPoint> touchPoints; + + QVector<TOUCHINPUT> winTouchInputs(msg.wParam); + memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * winTouchInputs.count()); + Qt::TouchPointStates allStates = 0; + QApplicationPrivate::GetTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT)); + for (int i = 0; i < winTouchInputs.count(); ++i) { + const TOUCHINPUT &touchInput = winTouchInputs.at(i); + + int touchPointID = touchInputIDToTouchPointID.value(touchInput.dwID, -1); + if (touchPointID == -1) { + touchPointID = touchInputIDToTouchPointID.count(); + touchInputIDToTouchPointID.insert(touchInput.dwID, touchPointID); + } + + QTouchEvent::TouchPoint touchPoint(touchPointID); + + // update state + QPointF screenPos(qreal(touchInput.x) / qreal(100.), qreal(touchInput.y) / qreal(100.)); + QRectF screenRect; + if (touchInput.dwMask & TOUCHINPUTMASKF_CONTACTAREA) + screenRect.setSize(QSizeF(qreal(touchInput.cxContact) / qreal(100.), + qreal(touchInput.cyContact) / qreal(100.))); + screenRect.moveCenter(screenPos); + + Qt::TouchPointStates state; + if (touchInput.dwFlags & TOUCHEVENTF_DOWN) { + state = Qt::TouchPointPressed; + } else if (touchInput.dwFlags & TOUCHEVENTF_UP) { + state = Qt::TouchPointReleased; + } else { + state = (screenPos == touchPoint.screenPos() + ? Qt::TouchPointStationary + : Qt::TouchPointMoved); + } + if (touchInput.dwFlags & TOUCHEVENTF_PRIMARY) + state |= Qt::TouchPointPrimary; + touchPoint.setState(state); + touchPoint.setScreenRect(screenRect); + touchPoint.setNormalizedPos(QPointF(screenPos.x() / screenGeometry.width(), + screenPos.y() / screenGeometry.height())); + + allStates |= state; + + touchPoints.append(touchPoint); + } + QApplicationPrivate::CloseTouchInputHandle((HANDLE) msg.lParam); + + if ((allStates & Qt::TouchPointStateMask) == Qt::TouchPointReleased) { + // all touch points released, forget the ids we've seen, they may not be reused + touchInputIDToTouchPointID.clear(); + } + + translateRawTouchEvent(widgetForHwnd, QTouchEvent::TouchScreen, touchPoints); + return true; +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index bf1251e..a7a6504 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -78,11 +78,14 @@ #include <private/qcrashhandler_p.h> #include <private/qcolor_p.h> #include <private/qcursor_p.h> +#include <private/qiconloader_p.h> +#include <private/gtksymbols_p.h> #include "qstyle.h" #include "qmetaobject.h" #include "qtimer.h" #include "qlibrary.h" #include <private/qgraphicssystemfactory_p.h> +#include "qkde_p.h" #if !defined (QT_NO_TABLET) extern "C" { @@ -130,6 +133,16 @@ extern "C" { #include <private/qbackingstore_p.h> +#ifdef QT_RX71_MULTITOUCH +# include <qsocketnotifier.h> +# include <linux/input.h> +# include <errno.h> +#endif + +#if _POSIX_VERSION+0 < 200112L && !defined(Q_OS_BSD4) +# define QT_NO_UNSETENV +#endif + QT_BEGIN_NAMESPACE //#define X_NOT_BROKEN @@ -159,6 +172,8 @@ static const char * x11_atomnames = { "WM_TAKE_FOCUS\0" "_NET_WM_PING\0" "_NET_WM_CONTEXT_HELP\0" + "_NET_WM_SYNC_REQUEST\0" + "_NET_WM_SYNC_REQUEST_COUNTER\0" // ICCCM window state "WM_STATE\0" @@ -296,6 +311,10 @@ static const char * x11_atomnames = { // XEMBED "_XEMBED\0" "_XEMBED_INFO\0" + + "Wacom Stylus\0" + "Wacom Cursor\0" + "Wacom Eraser\0" }; Q_GUI_EXPORT QX11Data *qt_x11Data = 0; @@ -506,6 +525,7 @@ static Bool qt_xfixes_scanner(Display*, XEvent *event, XPointer arg) class QETWidget : public QWidget // event translator widget { public: + QWidgetPrivate* d_func() { return QWidget::d_func(); } bool translateMouseEvent(const XEvent *); void translatePaintEvent(const XEvent *); bool translateConfigEvent(const XEvent *); @@ -718,6 +738,44 @@ static int qt_xio_errhandler(Display *) } #endif +#ifndef QT_NO_XSYNC +struct qt_sync_request_event_data +{ + WId window; +}; + +#if defined(Q_C_CALLBACKS) +extern "C" { +#endif + +static Bool qt_sync_request_scanner(Display*, XEvent *event, XPointer arg) +{ + qt_sync_request_event_data *data = + reinterpret_cast<qt_sync_request_event_data*>(arg); + if (event->type == ClientMessage && + event->xany.window == data->window && + event->xclient.message_type == ATOM(WM_PROTOCOLS) && + (Atom)event->xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST)) { + QWidget *w = QWidget::find(event->xany.window); + if (QTLWExtra *tlw = ((QETWidget*)w)->d_func()->maybeTopData()) { + const ulong timestamp = (const ulong) event->xclient.data.l[1]; + if (timestamp > X11->time) + X11->time = timestamp; + if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) { + tlw->syncRequestTimestamp = timestamp; + tlw->newCounterValueLo = event->xclient.data.l[2]; + tlw->newCounterValueHi = event->xclient.data.l[3]; + } + } + return true; + } + return false; +} + +#if defined(Q_C_CALLBACKS) +} +#endif +#endif // QT_NO_XSYNC static void qt_x11_create_intern_atoms() { @@ -759,26 +817,6 @@ Q_GUI_EXPORT void qt_x11_apply_settings_in_all_apps() } /*! \internal - Gets the current KDE 3 or 4 home path -*/ -QString QApplicationPrivate::kdeHome() -{ - static QString kdeHomePath; - if (kdeHomePath.isEmpty()) { - kdeHomePath = QString::fromLocal8Bit(qgetenv("KDEHOME")); - if (kdeHomePath.isEmpty()) { - int kdeSessionVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt(); - QDir homeDir(QDir::homePath()); - QString kdeConfDir(QLatin1String("/.kde")); - if (4 == kdeSessionVersion && homeDir.exists(QLatin1String(".kde4"))) - kdeConfDir = QLatin1String("/.kde4"); - kdeHomePath = QDir::homePath() + kdeConfDir; - } - } - return kdeHomePath; -} - -/*! \internal apply the settings to the application */ bool QApplicationPrivate::x11_apply_settings() @@ -834,30 +872,32 @@ bool QApplicationPrivate::x11_apply_settings() } // ### Fix properly for 4.6 - if (!(QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle"))) { + bool usingGtkSettings = QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle"); + if (!usingGtkSettings) { if (groupCount == QPalette::NColorGroups) QApplicationPrivate::setSystemPalette(pal); } - int kdeSessionVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt(); - if (!appFont) { - QFont font(QApplication::font()); - QString fontDescription; - // Override Qt font if KDE4 settings can be used - if (4 == kdeSessionVersion) { - QSettings kdeSettings(kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); - fontDescription = kdeSettings.value(QLatin1String("font")).toString(); - if (fontDescription.isEmpty()) { - // KDE stores fonts without quotes - fontDescription = kdeSettings.value(QLatin1String("font")).toStringList().join(QLatin1String(",")); + // ### Fix properly for 4.6 + if (!usingGtkSettings) { + QFont font(QApplication::font()); + QString fontDescription; + // Override Qt font if KDE4 settings can be used + if (X11->desktopVersion == 4) { + QSettings kdeSettings(QKde::kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); + fontDescription = kdeSettings.value(QLatin1String("font")).toString(); + if (fontDescription.isEmpty()) { + // KDE stores fonts without quotes + fontDescription = kdeSettings.value(QLatin1String("font")).toStringList().join(QLatin1String(",")); + } + } + if (fontDescription.isEmpty()) + fontDescription = settings.value(QLatin1String("font")).toString(); + if (!fontDescription .isEmpty()) { + font.fromString(fontDescription ); + QApplicationPrivate::setSystemFont(font); } - } - if (fontDescription.isEmpty()) - fontDescription = settings.value(QLatin1String("font")).toString(); - if (!fontDescription .isEmpty()) { - font.fromString(fontDescription ); - QApplicationPrivate::setSystemFont(font); } } @@ -875,29 +915,15 @@ bool QApplicationPrivate::x11_apply_settings() // read new QStyle QString stylename = settings.value(QLatin1String("style")).toString(); - if (stylename.isEmpty() && !QApplicationPrivate::styleOverride && X11->use_xrender) { - QStringList availableStyles = QStyleFactory::keys(); - // Override Qt style if KDE4 settings can be used - if (4 == kdeSessionVersion) { - QSettings kdeSettings(kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); - QString kde4Style = kdeSettings.value(QLatin1String("widgetStyle"), - QLatin1String("Oxygen")).toString(); - foreach (const QString &style, availableStyles) { - if (style.toLower() == kde4Style.toLower()) - stylename = kde4Style; - } - // Set QGtkStyle for GNOME - } else if (X11->desktopEnvironment == DE_GNOME) { - QString gtkStyleKey = QString::fromLatin1("GTK+"); - if (availableStyles.contains(gtkStyleKey)) - stylename = gtkStyleKey; - } + + if (stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull() && X11->use_xrender) { + stylename = x11_desktop_style(); } static QString currentStyleName = stylename; if (QCoreApplication::startingUp()) { - if (!stylename.isEmpty() && !QApplicationPrivate::styleOverride) - QApplicationPrivate::styleOverride = new QString(stylename); + if (!stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull()) + QApplicationPrivate::styleOverride = stylename; } else { if (currentStyleName != stylename) { currentStyleName = stylename; @@ -1047,24 +1073,6 @@ static void qt_set_input_encoding() XFree((char *)data); } -// Reads a KDE color setting -static QColor kdeColor(const QString &key) -{ - QSettings kdeSettings(QApplicationPrivate::kdeHome() + - QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); - QVariant variant = kdeSettings.value(key); - if (variant.isValid()) { - QStringList values = variant.toStringList(); - if (values.size() == 3) { - int r = values[0].toInt(); - int g = values[1].toInt(); - int b = values[2].toInt(); - return QColor(r, g, b); - } - } - return QColor(); -} - // set font, foreground and background from x11 resources. The // arguments may override the resource settings. static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, @@ -1085,7 +1093,6 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, if (QApplication::desktopSettingsAware()) { // first, read from settings QApplicationPrivate::x11_apply_settings(); - // the call to QApplication::style() below creates the system // palette, which breaks the logic after the RESOURCE_MANAGER // loop... so I have to save this value to be able to use it later @@ -1231,9 +1238,10 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, QApplicationPrivate::setSystemFont(fnt); } + // QGtkStyle sets it's own system palette + bool gtkStyle = QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle"); bool kdeColors = (QApplication::desktopSettingsAware() && X11->desktopEnvironment == DE_KDE); - - if (kdeColors || (button || !resBG.isEmpty() || !resFG.isEmpty())) {// set app colors + if (!gtkStyle && (kdeColors || (button || !resBG.isEmpty() || !resFG.isEmpty()))) {// set app colors bool allowX11ColorNames = QColor::allowX11ColorNames(); QColor::setAllowX11ColorNames(true); @@ -1269,41 +1277,6 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, bright_mode = true; } - if (kdeColors) { - // Setup KDE palette - QColor color; - color = kdeColor(QLatin1String("buttonBackground")); - if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:Button/BackgroundNormal")); - if (color.isValid()) - btn = color; - - color = kdeColor(QLatin1String("background")); - if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:Window/BackgroundNormal")); - if (color.isValid()) - bg = color; - - color = kdeColor(QLatin1String("foreground")); - if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:View/ForegroundNormal")); - if (color.isValid()) { - fg = color; - } - - color = kdeColor(QLatin1String("windowForeground")); - if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:Window/ForegroundNormal")); - if (color.isValid()) - wfg = color; - - color = kdeColor(QLatin1String("windowBackground")); - if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:View/BackgroundNormal")); - if (color.isValid()) - base = color; - } - QPalette pal(fg, btn, btn.lighter(125), btn.darker(130), btn.darker(120), wfg.isValid() ? wfg : fg, Qt::white, base, bg); QColor disabled((fg.red() + btn.red()) / 2, (fg.green() + btn.green())/ 2, @@ -1316,34 +1289,6 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, highlight = QColor(selectBackground); highlightText = QColor(selectForeground); } - // Use KDE3 or KDE4 color settings if present - if (kdeColors) { - QColor color = kdeColor(QLatin1String("selectBackground")); - if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:Selection/BackgroundNormal")); - if (color.isValid()) - highlight = color; - - color = kdeColor(QLatin1String("selectForeground")); - if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:Selection/ForegroundNormal")); - if (color.isValid()) - highlightText = color; - - color = kdeColor(QLatin1String("alternateBackground")); - if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:View/BackgroundAlternate")); - if (color.isValid()) - pal.setColor(QPalette::AlternateBase, color); - else - pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(110)); - - color = kdeColor(QLatin1String("buttonForeground")); - if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:Button/ForegroundNormal")); - if (color.isValid()) - pal.setColor(QPalette::ButtonText, color); - } if (highlight.isValid() && highlightText.isValid()) { pal.setColor(QPalette::Highlight, highlight); @@ -1366,10 +1311,9 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::darkBlue); } - // QGtkStyle sets it's own system palette - if (!(QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle"))) { - QApplicationPrivate::setSystemPalette(pal); - } + if (kdeColors) + pal = QKde::kdePalette().resolve(pal); + QApplicationPrivate::setSystemPalette(pal); QColor::setAllowX11ColorNames(allowX11ColorNames); } @@ -1389,6 +1333,8 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, effects.contains(QLatin1String("animatetoolbox"))); } + + QIconLoader::instance()->updateSystemTheme(); } @@ -1583,6 +1529,7 @@ static PtrWacomConfigOpenDevice ptrWacomConfigOpenDevice = 0; static PtrWacomConfigGetRawParam ptrWacomConfigGetRawParam = 0; static PtrWacomConfigCloseDevice ptrWacomConfigCloseDevice = 0; static PtrWacomConfigTerm ptrWacomConfigTerm = 0; +Q_GLOBAL_STATIC(QByteArray, wacomDeviceName) #endif #endif @@ -1723,7 +1670,7 @@ void qt_init(QApplicationPrivate *priv, int, X11->pattern_fills[i].screen = -1; #endif - X11->startupId = X11->originalStartupId = 0; + X11->startupId = 0; int argc = priv->argc; char **argv = priv->argv; @@ -1905,10 +1852,20 @@ void qt_init(QApplicationPrivate *priv, int, QX11InfoData *screen = X11->screens + s; screen->ref = 1; // ensures it doesn't get deleted screen->screen = s; - screen->dpiX = (DisplayWidth(X11->display, s) * 254 + DisplayWidthMM(X11->display, s)*5) - / (DisplayWidthMM(X11->display, s)*10); - screen->dpiY = (DisplayHeight(X11->display, s) * 254 + DisplayHeightMM(X11->display, s)*5) - / (DisplayHeightMM(X11->display, s)*10); + + int widthMM = DisplayWidthMM(X11->display, s); + if (widthMM != 0) { + screen->dpiX = (DisplayWidth(X11->display, s) * 254 + widthMM * 5) / (widthMM * 10); + } else { + screen->dpiX = 72; + } + + int heightMM = DisplayHeightMM(X11->display, s); + if (heightMM != 0) { + screen->dpiY = (DisplayHeight(X11->display, s) * 254 + heightMM * 5) / (heightMM * 10); + } else { + screen->dpiY = 72; + } X11->argbVisuals[s] = 0; X11->argbColormaps[s] = 0; @@ -2084,6 +2041,13 @@ void qt_init(QApplicationPrivate *priv, int, #endif // QT_RUNTIME_XCURSOR #endif // QT_NO_XCURSOR +#ifndef QT_NO_XSYNC + int xsync_evbase, xsync_errbase; + int major, minor; + if (XSyncQueryExtension(X11->display, &xsync_evbase, &xsync_errbase)) + XSyncInitialize(X11->display, &major, &minor); +#endif // QT_NO_XSYNC + #ifndef QT_NO_XINERAMA #ifdef QT_RUNTIME_XINERAMA X11->ptrXineramaQueryExtension = 0; @@ -2245,6 +2209,7 @@ void qt_init(QApplicationPrivate *priv, int, X11->compositingManagerRunning = XGetSelectionOwner(X11->display, ATOM(_NET_WM_CM_S0)); X11->desktopEnvironment = DE_UNKNOWN; + X11->desktopVersion = 0; // See if the current window manager is using the freedesktop.org spec to give its name Window windowManagerWindow = XNone; @@ -2320,6 +2285,15 @@ void qt_init(QApplicationPrivate *priv, int, XFree((char *)data); } + if (X11->desktopEnvironment == DE_KDE) + X11->desktopVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt(); + +#if !defined(QT_NO_STYLE_GTK) + if (X11->desktopEnvironment == DE_GNOME) { + static bool menusHaveIcons = QGtk::getGConfBool(QLatin1String("/desktop/gnome/interface/menus_have_icons"), true); + QApplication::setAttribute(Qt::AA_DontShowIconsInMenus, !menusHaveIcons); + } +#endif qt_set_input_encoding(); qt_set_x11_resources(appFont, appFGCol, appBGCol, appBTNCol); @@ -2355,13 +2329,6 @@ void qt_init(QApplicationPrivate *priv, int, XAxisInfoPtr a; XDevice *dev = 0; -#if !defined(Q_OS_IRIX) - // XFree86 divides a stylus and eraser into 2 devices, so we must do for both... - const QString XFREENAMESTYLUS = QLatin1String("stylus"); - const QString XFREENAMEPEN = QLatin1String("pen"); - const QString XFREENAMEERASER = QLatin1String("eraser"); -#endif - if (X11->ptrXListInputDevices) { devices = X11->ptrXListInputDevices(X11->display, &ndev); if (!devices) @@ -2376,18 +2343,19 @@ void qt_init(QApplicationPrivate *priv, int, gotStylus = false; gotEraser = false; - QString devName = QString::fromLocal8Bit(devs->name).toLower(); #if defined(Q_OS_IRIX) + QString devName = QString::fromLocal8Bit(devs->name).toLower(); if (devName == QLatin1String(WACOM_NAME)) { deviceType = QTabletEvent::Stylus; gotStylus = true; } #else - if (devName.startsWith(XFREENAMEPEN) - || devName.startsWith(XFREENAMESTYLUS)) { + if (devs->type == ATOM(XWacomStylus)) { deviceType = QTabletEvent::Stylus; + if (wacomDeviceName()->isEmpty()) + wacomDeviceName()->append(devs->name); gotStylus = true; - } else if (devName.startsWith(XFREENAMEERASER)) { + } else if (devs->type == ATOM(XWacomEraser)) { deviceType = QTabletEvent::XFreeEraser; gotEraser = true; } @@ -2523,10 +2491,15 @@ void qt_init(QApplicationPrivate *priv, int, #endif // QT_NO_TABLET X11->startupId = getenv("DESKTOP_STARTUP_ID"); - X11->originalStartupId = X11->startupId; - static char desktop_startup_id[] = "DESKTOP_STARTUP_ID="; - putenv(desktop_startup_id); - + if (X11->startupId) { +#ifndef QT_NO_UNSETENV + unsetenv("DESKTOP_STARTUP_ID"); +#else + // it's a small memory leak, however we won't crash if Qt is + // unloaded and someones tries to use the envoriment. + putenv(strdup("DESKTOP_STARTUP_ID=")); +#endif + } } else { // read some non-GUI settings when not using the X server... @@ -2585,31 +2558,35 @@ void qt_init(QApplicationPrivate *priv, int, /*! \internal */ -void QApplicationPrivate::x11_initialize_style() +QString QApplicationPrivate::x11_desktop_style() { - if (QApplicationPrivate::app_style) - return; - + QString stylename; switch(X11->desktopEnvironment) { - case DE_KDE: - if (X11->use_xrender) - QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("plastique")); - else - QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("windows")); - break; - case DE_GNOME: - if (X11->use_xrender) - QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cleanlooks")); - else - QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("windows")); - break; - case DE_CDE: - QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cde")); - break; - default: - // Don't do anything + case DE_KDE: + stylename = QKde::kdeStyle(); + break; + case DE_GNOME: { + QStringList availableStyles = QStyleFactory::keys(); + // Set QGtkStyle for GNOME if available + QString gtkStyleKey = QString::fromLatin1("GTK+"); + if (availableStyles.contains(gtkStyleKey)) { + stylename = gtkStyleKey; break; + } + if (X11->use_xrender) + stylename = QLatin1String("cleanlooks"); + else + stylename = QLatin1String("windows"); + break; + } + case DE_CDE: + stylename = QLatin1String("cde"); + break; + default: + // Don't do anything + break; } + return stylename; } void QApplicationPrivate::initializeWidgetPaletteHash() @@ -2640,10 +2617,6 @@ void qt_cleanup() #endif } - // restore original value back. This is also done in QWidgetPrivate::show_sys. - if (X11->originalStartupId) - putenv(X11->originalStartupId); - #ifndef QT_NO_XRENDER for (int i = 0; i < X11->solid_fill_count; ++i) { if (X11->solid_fills[i].picture) @@ -2978,7 +2951,7 @@ QWidget *QApplication::topLevelAt(const QPoint &p) void QApplication::syncX() { if (X11->display) - XSync(X11->display, False); // don't discard events + XSync(X11->display, False); // don't discard events } @@ -3116,6 +3089,19 @@ int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only) XSendEvent(event->xclient.display, event->xclient.window, False, SubstructureNotifyMask|SubstructureRedirectMask, event); } +#ifndef QT_NO_XSYNC + } else if (a == ATOM(_NET_WM_SYNC_REQUEST)) { + const ulong timestamp = (const ulong) event->xclient.data.l[1]; + if (timestamp > X11->time) + X11->time = timestamp; + if (QTLWExtra *tlw = w->d_func()->maybeTopData()) { + if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) { + tlw->syncRequestTimestamp = timestamp; + tlw->newCounterValueLo = event->xclient.data.l[2]; + tlw->newCounterValueHi = event->xclient.data.l[3]; + } + } +#endif } } else if (event->xclient.message_type == ATOM(_QT_SCROLL_DONE)) { widget->translateScrollDoneEvent(event); @@ -3146,6 +3132,7 @@ int QApplication::x11ProcessEvent(XEvent* event) { Q_D(QApplication); QScopedLoopLevelCounter loopLevelCounter(d->threadData); + #ifdef ALIEN_DEBUG //qDebug() << "QApplication::x11ProcessEvent:" << event->type; #endif @@ -3351,19 +3338,10 @@ int QApplication::x11ProcessEvent(XEvent* event) QSize oldSize(w->size()); w->data->crect.setWidth(DisplayWidth(X11->display, scr)); w->data->crect.setHeight(DisplayHeight(X11->display, scr)); - QVarLengthArray<QRect> oldSizes(desktop->numScreens()); - for (int i = 0; i < desktop->numScreens(); ++i) - oldSizes[i] = desktop->screenGeometry(i); QResizeEvent e(w->size(), oldSize); QApplication::sendEvent(w, &e); - for (int i = 0; i < qMin(oldSizes.count(), desktop->numScreens()); ++i) { - if (oldSizes[i] != desktop->screenGeometry(i)) - emit desktop->resized(i); - } - for (int i = oldSizes.count(); i < desktop->numScreens(); ++i) - emit desktop->resized(i); // added - for (int i = desktop->numScreens(); i < oldSizes.count(); ++i) - emit desktop->resized(i); // removed + if (w != desktop) + QApplication::sendEvent(desktop, &e); } #endif // QT_NO_XRANDR @@ -4139,7 +4117,9 @@ bool QETWidget::translateMouseEvent(const XEvent *event) || ((nextEvent.type == EnterNotify || nextEvent.type == LeaveNotify) && qt_button_down == this) || (nextEvent.type == ClientMessage - && nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE))) { + && (nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE) || + (nextEvent.xclient.message_type == ATOM(WM_PROTOCOLS) && + (Atom)nextEvent.xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST))))) { qApp->x11ProcessEvent(&nextEvent); continue; } else if (nextEvent.type != MotionNotify || @@ -4409,7 +4389,6 @@ bool QETWidget::translateMouseEvent(const XEvent *event) QMouseEvent e(type, pos, globalPos, button, buttons, modifiers); QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down, qt_last_mouse_receiver); - if (type == QEvent::MouseButtonPress && button == Qt::RightButton && (openPopupCount == oldOpenPopupCount)) { @@ -4478,8 +4457,7 @@ void fetchWacomToolId(int &deviceType, qint64 &serialId) WACOMCONFIG *config = ptrWacomConfigInit(X11->display, 0); if (config == 0) return; - const char *name = "stylus"; // TODO get this from the X config instead (users may have called it differently) - WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, name); + WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, wacomDeviceName()->constData()); if (device == 0) return; unsigned keys[1]; @@ -4537,6 +4515,53 @@ void fetchWacomToolId(int &deviceType, qint64 &serialId) } #endif +struct qt_tablet_motion_data +{ + bool filterByWidget; + const QWidget *widget; + const QWidget *etWidget; + int tabletMotionType; + bool error; // found a reason to stop searching +}; + +static Bool qt_mouseMotion_scanner(Display *, XEvent *event, XPointer arg) +{ + qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg; + if (data->error) + return false; + + if (event->type == MotionNotify) + return true; + + data->error = event->type != data->tabletMotionType; // we stop compression when another event gets in between. + return false; +} + +static Bool qt_tabletMotion_scanner(Display *, XEvent *event, XPointer arg) +{ + qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg; + if (data->error) + return false; + if (event->type == data->tabletMotionType) { + const XDeviceMotionEvent *const motion = reinterpret_cast<const XDeviceMotionEvent*>(event); + if (data->filterByWidget) { + const QPoint curr(motion->x, motion->y); + const QWidget *w = data->etWidget; + const QWidget *const child = w->childAt(curr); + if (child) { + w = child; + } + if (w == data->widget) + return true; + } else { + return true; + } + } + + data->error = event->type != MotionNotify; // we stop compression when another event gets in between. + return false; +} + bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet) { #if defined (Q_OS_IRIX) @@ -4563,91 +4588,17 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet qreal rotation = 0; int deviceType = QTabletEvent::NoDevice; int pointerType = QTabletEvent::UnknownPointer; - XEvent xinputMotionEvent; - XEvent mouseMotionEvent; const XDeviceMotionEvent *motion = 0; XDeviceButtonEvent *button = 0; const XProximityNotifyEvent *proximity = 0; QEvent::Type t; Qt::KeyboardModifiers modifiers = 0; - bool reinsertMouseEvent = false; - bool neverFoundMouseEvent = true; - XEvent xinputMotionEventNext; - XEvent mouseMotionEventSave; #if !defined (Q_OS_IRIX) XID device_id; #endif if (ev->type == tablet->xinput_motion) { motion = reinterpret_cast<const XDeviceMotionEvent*>(ev); - for (;;) { - // get the corresponding mouseMotionEvent for motion - if (XCheckTypedWindowEvent(X11->display, internalWinId(), MotionNotify, &mouseMotionEvent)) { - mouseMotionEventSave = mouseMotionEvent; - reinsertMouseEvent = true; - neverFoundMouseEvent = false; - - if (mouseMotionEvent.xmotion.time > motion->time) { - XEvent xinputMotionEventLoop = *ev; - - // xinput event is older than the mouse event --> search for the corresponding xinput event for the given mouse event - while (mouseMotionEvent.xmotion.time > (reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEventLoop))->time) { - if (XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventLoop)) { - xinputMotionEvent = xinputMotionEventLoop; - } - else { - break; - } - } - motion = reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent); - } - - // get the next xinputMotionEvent, for the next loop run - if (!XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventNext)) { - XPutBackEvent(X11->display, &mouseMotionEvent); - reinsertMouseEvent = false; - break; - } - - if (mouseMotionEvent.xmotion.time != motion->time) { - // reinsert in order - if (mouseMotionEvent.xmotion.time >= motion->time) { - XPutBackEvent(X11->display, &mouseMotionEvent); - XPutBackEvent(X11->display, &xinputMotionEventNext); - // next entry in queue is xinputMotionEventNext - } - else { - XPutBackEvent(X11->display, &xinputMotionEventNext); - XPutBackEvent(X11->display, &mouseMotionEvent); - // next entry in queue is mouseMotionEvent - } - reinsertMouseEvent = false; - break; - } - } - else { - break; - } - - xinputMotionEvent = xinputMotionEventNext; - motion = (reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent)); - } - - if (reinsertMouseEvent) { - XPutBackEvent(X11->display, &mouseMotionEventSave); - } - - if (neverFoundMouseEvent) { - XEvent xinputMotionEventLoop; - bool eventFound = false; - // xinput event without mouseMotionEvent --> search the newest xinputMotionEvent - while (XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventLoop)) { - xinputMotionEvent = xinputMotionEventLoop; - eventFound = true; - } - if (eventFound) motion = reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent); - } - t = QEvent::TabletMove; global = QPoint(motion->x_root, motion->y_root); curr = QPoint(motion->x, motion->y); @@ -4800,11 +4751,14 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet } #endif - QWidget *child = w->childAt(curr); - if (child) { - w = child; - curr = w->mapFromGlobal(global); + if (tablet->widgetToGetPress) { + w = tablet->widgetToGetPress; + } else { + QWidget *child = w->childAt(curr); + if (child) + w = child; } + curr = w->mapFromGlobal(global); if (t == QEvent::TabletPress) { tablet->widgetToGetPress = w; @@ -4818,10 +4772,45 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet deviceType, pointerType, qreal(pressure / qreal(tablet->maxPressure - tablet->minPressure)), xTilt, yTilt, tangentialPressure, rotation, z, modifiers, uid); - if (proximity) + if (proximity) { QApplication::sendSpontaneousEvent(qApp, &e); - else + } else { QApplication::sendSpontaneousEvent(w, &e); + const bool accepted = e.isAccepted(); + if (!accepted && ev->type == tablet->xinput_motion) { + // If the widget does not accept tablet events, we drop the next ones from the event queue + // for this widget so it is not overloaded with the numerous tablet events. + qt_tablet_motion_data tabletMotionData; + tabletMotionData.tabletMotionType = tablet->xinput_motion; + tabletMotionData.widget = w; + tabletMotionData.etWidget = this; + // if nothing is pressed, the events are filtered by position + tabletMotionData.filterByWidget = (tablet->widgetToGetPress == 0); + + bool reinsertMouseEvent = false; + XEvent mouseMotionEvent; + while (true) { + // Find first mouse event since we expect them in pairs inside Qt + tabletMotionData.error =false; + if (XCheckIfEvent(X11->display, &mouseMotionEvent, &qt_mouseMotion_scanner, (XPointer) &tabletMotionData)) { + reinsertMouseEvent = true; + } else { + break; + } + + // Now discard any duplicate tablet events. + tabletMotionData.error = false; + XEvent dummy; + while (XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) { + // just discard the event + } + } + + if (reinsertMouseEvent) { + XPutBackEvent(X11->display, &mouseMotionEvent); + } + } + } return true; } #endif @@ -5018,6 +5007,7 @@ bool QETWidget::translatePropertyEvent(const XEvent *event) return true; } + // // Paint event translation // @@ -5196,6 +5186,14 @@ bool QETWidget::translateConfigEvent(const XEvent *event) otherEvent.xconfigure.border_width; } } +#ifndef QT_NO_XSYNC + qt_sync_request_event_data sync_event; + sync_event.window = internalWinId(); + for (XEvent ev;;) { + if (!XCheckIfEvent(X11->display, &ev, &qt_sync_request_scanner, (XPointer)&sync_event)) + break; + } +#endif // QT_NO_XSYNC } QRect cr (geometry()); @@ -5281,6 +5279,20 @@ bool QETWidget::translateConfigEvent(const XEvent *event) if (d->extra && d->extra->topextra) d->extra->topextra->inTopLevelResize = false; } +#ifndef QT_NO_XSYNC + if (QTLWExtra *tlwExtra = d->maybeTopData()) { + if (tlwExtra->newCounterValueLo != 0 || tlwExtra->newCounterValueHi != 0) { + XSyncValue value; + XSyncIntsToValue(&value, + tlwExtra->newCounterValueLo, + tlwExtra->newCounterValueHi); + + XSyncSetCounter(X11->display, tlwExtra->syncUpdateCounter, value); + tlwExtra->newCounterValueHi = 0; + tlwExtra->newCounterValueLo = 0; + } + } +#endif return true; } @@ -5898,4 +5910,225 @@ void QSessionManager::requestPhase2() #endif // QT_NO_SESSIONMANAGER +#if defined(QT_RX71_MULTITOUCH) + +static inline int testBit(const char *array, int bit) +{ + return (array[bit/8] & (1<<(bit%8))); +} + +static int openRX71Device(const QByteArray &deviceName) +{ + int fd = open(deviceName, O_RDONLY | O_NONBLOCK); + if (fd == -1) { + fd = -errno; + return fd; + } + + // fetch the event type mask and check that the device reports absolute coordinates + char eventTypeMask[(EV_MAX + sizeof(char) - 1) * sizeof(char) + 1]; + memset(eventTypeMask, 0, sizeof(eventTypeMask)); + if (ioctl(fd, EVIOCGBIT(0, sizeof(eventTypeMask)), eventTypeMask) < 0) { + close(fd); + return -1; + } + if (!testBit(eventTypeMask, EV_ABS)) { + close(fd); + return -1; + } + + // make sure that we can get the absolute X and Y positions from the device + char absMask[(ABS_MAX + sizeof(char) - 1) * sizeof(char) + 1]; + memset(absMask, 0, sizeof(absMask)); + if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absMask)), absMask) < 0) { + close(fd); + return -1; + } + if (!testBit(absMask, ABS_X) || !testBit(absMask, ABS_Y)) { + close(fd); + return -1; + } + + return fd; +} + +void QApplicationPrivate::initializeMultitouch_sys() +{ + Q_Q(QApplication); + + QByteArray deviceName = QByteArray("/dev/input/event"); + int currentDeviceNumber = 0; + for (;;) { + int fd = openRX71Device(QByteArray(deviceName + QByteArray::number(currentDeviceNumber++))); + if (fd == -ENOENT) { + // no more devices + break; + } + if (fd < 0) { + // not a touch device + continue; + } + + struct input_absinfo abs_x, abs_y, abs_z; + ioctl(fd, EVIOCGABS(ABS_X), &abs_x); + ioctl(fd, EVIOCGABS(ABS_Y), &abs_y); + ioctl(fd, EVIOCGABS(ABS_Z), &abs_z); + + int deviceNumber = allRX71TouchPoints.count(); + + QSocketNotifier *socketNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, q); + QObject::connect(socketNotifier, SIGNAL(activated(int)), q, SLOT(_q_readRX71MultiTouchEvents())); + + RX71TouchPointState touchPointState = { + socketNotifier, + QTouchEvent::TouchPoint(deviceNumber), + + abs_x.minimum, abs_x.maximum, q->desktop()->screenGeometry().width(), + abs_y.minimum, abs_y.maximum, q->desktop()->screenGeometry().height(), + abs_z.minimum, abs_z.maximum + }; + allRX71TouchPoints.append(touchPointState); + } + + hasRX71MultiTouch = allRX71TouchPoints.count() > 1; + if (!hasRX71MultiTouch) { + for (int i = 0; i < allRX71TouchPoints.count(); ++i) { + QSocketNotifier *socketNotifier = allRX71TouchPoints.at(i).socketNotifier; + close(socketNotifier->socket()); + delete socketNotifier; + } + allRX71TouchPoints.clear(); + } +} + +void QApplicationPrivate::cleanupMultitouch_sys() +{ + hasRX71MultiTouch = false; + for (int i = 0; i < allRX71TouchPoints.count(); ++i) { + QSocketNotifier *socketNotifier = allRX71TouchPoints.at(i).socketNotifier; + close(socketNotifier->socket()); + delete socketNotifier; + } + allRX71TouchPoints.clear(); +} + +bool QApplicationPrivate::readRX71MultiTouchEvents(int deviceNumber) +{ + RX71TouchPointState &touchPointState = allRX71TouchPoints[deviceNumber]; + QSocketNotifier *socketNotifier = touchPointState.socketNotifier; + int fd = socketNotifier->socket(); + + QTouchEvent::TouchPoint &touchPoint = touchPointState.touchPoint; + + bool down = touchPoint.state() != Qt::TouchPointReleased; + if (down) + touchPoint.setState(Qt::TouchPointStationary); + + bool changed = false; + for (;;) { + struct input_event inputEvent; + int bytesRead = read(fd, &inputEvent, sizeof(inputEvent)); + if (bytesRead <= 0) + break; + if (bytesRead != sizeof(inputEvent)) { + qWarning("Qt: INTERNAL ERROR: short read in readRX71MultiTouchEvents()"); + return false; + } + + switch (inputEvent.type) { + case EV_SYN: + changed = true; + switch (touchPoint.state()) { + case Qt::TouchPointPressed: + case Qt::TouchPointReleased: + // make sure we don't compress pressed and releases with any other events + return changed; + default: + break; + } + continue; + case EV_KEY: + case EV_ABS: + break; + default: + qWarning("Qt: WARNING: unknown event type %d on multitouch device", inputEvent.type); + continue; + } + + QPointF screenPos = touchPoint.screenPos(); + switch (inputEvent.code) { + case BTN_TOUCH: + if (!down && inputEvent.value != 0) + touchPoint.setState(Qt::TouchPointPressed); + else if (down && inputEvent.value == 0) + touchPoint.setState(Qt::TouchPointReleased); + break; + case ABS_TOOL_WIDTH: + case ABS_VOLUME: + case ABS_PRESSURE: + // ignore for now + break; + case ABS_X: + { + qreal newValue = ((qreal(inputEvent.value - touchPointState.minX) + / qreal(touchPointState.maxX - touchPointState.minX)) + * touchPointState.scaleX); + screenPos.rx() = newValue; + touchPoint.setScreenPos(screenPos); + break; + } + case ABS_Y: + { + qreal newValue = ((qreal(inputEvent.value - touchPointState.minY) + / qreal(touchPointState.maxY - touchPointState.minY)) + * touchPointState.scaleY); + screenPos.ry() = newValue; + touchPoint.setScreenPos(screenPos); + break; + } + case ABS_Z: + { + // map Z (signal strength) to pressure for now + qreal newValue = (qreal(inputEvent.value - touchPointState.minZ) + / qreal(touchPointState.maxZ - touchPointState.minZ)); + touchPoint.setPressure(newValue); + break; + } + default: + qWarning("Qt: WARNING: unknown event code %d on multitouch device", inputEvent.code); + continue; + } + } + + if (down && touchPoint.state() != Qt::TouchPointReleased) + touchPoint.setState(changed ? Qt::TouchPointMoved : Qt::TouchPointStationary); + + return changed; +} + +void QApplicationPrivate::_q_readRX71MultiTouchEvents() +{ + // read touch events from all devices + bool changed = false; + for (int i = 0; i < allRX71TouchPoints.count(); ++i) + changed = readRX71MultiTouchEvents(i) || changed; + if (!changed) + return; + + QList<QTouchEvent::TouchPoint> touchPoints; + for (int i = 0; i < allRX71TouchPoints.count(); ++i) + touchPoints.append(allRX71TouchPoints.at(i).touchPoint); + + translateRawTouchEvent(0, QTouchEvent::TouchScreen, touchPoints); +} + +#else // !QT_RX71_MULTITOUCH + +void QApplicationPrivate::initializeMultitouch_sys() +{ } +void QApplicationPrivate::cleanupMultitouch_sys() +{ } + +#endif // QT_RX71_MULTITOUCH + QT_END_NAMESPACE diff --git a/src/gui/kernel/qboxlayout.cpp b/src/gui/kernel/qboxlayout.cpp index 0eb7ff1..273df31 100644 --- a/src/gui/kernel/qboxlayout.cpp +++ b/src/gui/kernel/qboxlayout.cpp @@ -452,7 +452,6 @@ void QBoxLayoutPrivate::calcHfw(int w) vertically. \ingroup geomanagement - \ingroup appearance QBoxLayout takes the space it gets (from its parent layout or from the parentWidget()), divides it up into a row of boxes, and makes @@ -527,7 +526,7 @@ void QBoxLayoutPrivate::calcHfw(int w) You will almost always want to use QVBoxLayout and QHBoxLayout rather than QBoxLayout because of their convenient constructors. - \sa QGridLayout, QStackedLayout, {Layout Classes} + \sa QGridLayout, QStackedLayout, {Layout Management} */ /*! @@ -925,9 +924,15 @@ void QBoxLayout::insertSpacing(int index, int size) else b = QLayoutPrivate::createSpacerItem(this, 0, size, QSizePolicy::Minimum, QSizePolicy::Fixed); - QBoxLayoutItem *it = new QBoxLayoutItem(b); - it->magic = true; - d->list.insert(index, it); + QT_TRY { + QBoxLayoutItem *it = new QBoxLayoutItem(b); + it->magic = true; + d->list.insert(index, it); + + } QT_CATCH(...) { + delete b; + QT_RETHROW; + } invalidate(); } @@ -1027,8 +1032,21 @@ void QBoxLayout::insertWidget(int index, QWidget *widget, int stretch, index = d->list.count(); QWidgetItem *b = QLayoutPrivate::createWidgetItem(this, widget); b->setAlignment(alignment); - QBoxLayoutItem *it = new QBoxLayoutItem(b, stretch); - d->list.insert(index, it); + + QBoxLayoutItem *it; + QT_TRY{ + it = new QBoxLayoutItem(b, stretch); + } QT_CATCH(...) { + delete b; + QT_RETHROW; + } + + QT_TRY{ + d->list.insert(index, it); + } QT_CATCH(...) { + delete it; + QT_RETHROW; + } invalidate(); } @@ -1271,8 +1289,6 @@ QBoxLayout::Direction QBoxLayout::direction() const \brief The QHBoxLayout class lines up widgets horizontally. \ingroup geomanagement - \ingroup appearance - \mainclass This class is used to construct horizontal box layout objects. See QBoxLayout for details. @@ -1295,7 +1311,7 @@ QBoxLayout::Direction QBoxLayout::direction() const \image qhboxlayout-with-5-children.png Horizontal box layout with five child widgets - \sa QVBoxLayout, QGridLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example} + \sa QVBoxLayout, QGridLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example} */ @@ -1389,8 +1405,6 @@ QHBoxLayout::~QHBoxLayout() \brief The QVBoxLayout class lines up widgets vertically. \ingroup geomanagement - \ingroup appearance - \mainclass This class is used to construct vertical box layout objects. See QBoxLayout for details. @@ -1413,7 +1427,7 @@ QHBoxLayout::~QHBoxLayout() \image qvboxlayout-with-5-children.png Horizontal box layout with five child widgets - \sa QHBoxLayout, QGridLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example} + \sa QHBoxLayout, QGridLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example} */ /*! diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp index 0ace9d3..dd39aa3 100644 --- a/src/gui/kernel/qclipboard.cpp +++ b/src/gui/kernel/qclipboard.cpp @@ -50,6 +50,7 @@ #include "qvariant.h" #include "qbuffer.h" #include "qimage.h" +#include "qtextcodec.h" QT_BEGIN_NAMESPACE @@ -57,10 +58,6 @@ QT_BEGIN_NAMESPACE \class QClipboard \brief The QClipboard class provides access to the window system clipboard. - \ingroup io - \ingroup environment - \mainclass - The clipboard offers a simple mechanism to copy and paste data between applications. @@ -276,11 +273,12 @@ QClipboard::~QClipboard() */ QString QClipboard::text(QString &subtype, Mode mode) const { - const QMimeData *data = mimeData(mode); + const QMimeData *const data = mimeData(mode); if (!data) return QString(); + + const QStringList formats = data->formats(); if (subtype.isEmpty()) { - QStringList formats = data->formats(); if (formats.contains(QLatin1String("text/plain"))) subtype = QLatin1String("plain"); else { @@ -289,13 +287,21 @@ QString QClipboard::text(QString &subtype, Mode mode) const subtype = formats.at(i).mid(5); break; } + if (subtype.isEmpty()) + return QString(); } - } - if (subtype.isEmpty()) + } else if (!formats.contains(QLatin1String("text/") + subtype)) { return QString(); - if (subtype == QLatin1String("plain")) - return data->text(); - return QString::fromUtf8(data->data(QLatin1String("text/") + subtype)); + } + + const QByteArray rawData = data->data(QLatin1String("text/") + subtype); + + QTextCodec* codec = QTextCodec::codecForMib(106); // utf-8 is default + if (subtype == QLatin1String("html")) + codec = QTextCodec::codecForHtml(rawData, codec); + else + codec = QTextCodec::codecForUtfText(rawData, codec); + return codec->toUnicode(rawData); } /*! diff --git a/src/gui/kernel/qclipboard_mac.cpp b/src/gui/kernel/qclipboard_mac.cpp index b800973..af24bd5 100644 --- a/src/gui/kernel/qclipboard_mac.cpp +++ b/src/gui/kernel/qclipboard_mac.cpp @@ -50,6 +50,7 @@ #include "qurl.h" #include <stdlib.h> #include <string.h> +#include "qt_cocoa_helpers_mac_p.h" QT_BEGIN_NAMESPACE @@ -525,8 +526,17 @@ QMacPasteboard::retrieveData(const QString &format, QVariant::Type) const QString c_flavor = c->flavorFor(format); if(!c_flavor.isEmpty()) { // Handle text/plain a little differently. Try handling Unicode first. - if((c_flavor == QLatin1String("com.apple.traditional-mac-plain-text") || c_flavor == QLatin1String("public.utf8-plain-text")) && - hasFlavor(QLatin1String("public.utf16-plain-text"))) + 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(); + if (!str.isEmpty()) + return str; + } + if (checkForUtf16 && hasFlavor(QLatin1String("public.utf16-plain-text"))) c_flavor = QLatin1String("public.utf16-plain-text"); QVariant ret; diff --git a/src/gui/kernel/qclipboard_s60.cpp b/src/gui/kernel/qclipboard_s60.cpp new file mode 100644 index 0000000..a98550d --- /dev/null +++ b/src/gui/kernel/qclipboard_s60.cpp @@ -0,0 +1,266 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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" + +#ifndef QT_NO_CLIPBOARD + +#include "qapplication.h" +#include "qbitmap.h" +#include "qdatetime.h" +#include "qbuffer.h" +#include "qwidget.h" +#include "qevent.h" +#include "private/qcore_symbian_p.h" +#include <QtDebug> + +// Symbian's clipboard +#include <baclipb.h> +QT_BEGIN_NAMESPACE + +//### Mime Type mapping to UIDs + +const TUid KQtCbDataStream = {0x2001B2DD}; + + +class QClipboardData +{ +public: + QClipboardData(); + ~QClipboardData(); + + void setSource(QMimeData* s) + { + if (s == src) + return; + delete src; + src = s; + } + QMimeData* source() + { return src; } + bool connected() + { return connection; } + void clear(); + +private: + QMimeData* src; + bool connection; +}; + +QClipboardData::QClipboardData():src(0),connection(true) +{ + clear(); +} + +QClipboardData::~QClipboardData() +{ + connection = false; + delete src; +} + +void QClipboardData::clear() +{ + QMimeData* newSrc = new QMimeData; + delete src; + src = newSrc; +} + +static QClipboardData *internalCbData = 0; + +static void cleanupClipboardData() +{ + delete internalCbData; + internalCbData = 0; +} + +static QClipboardData *clipboardData() +{ + if (internalCbData == 0) { + internalCbData = new QClipboardData; + if (internalCbData) + { + if (!internalCbData->connected()) + { + delete internalCbData; + internalCbData = 0; + } + else + { + qAddPostRoutine(cleanupClipboardData); + } + } + } + return internalCbData; +} + +void writeToStreamLX(const QMimeData* aData, RWriteStream& aStream) +{ + // This function both leaves and throws exceptions. There must be no destructor + // dependencies between cleanup styles, and no cleanup stack dependencies on stacked objects. + QStringList headers = aData->formats(); + aStream << TCardinality(headers.count()); + for (QStringList::const_iterator iter= headers.constBegin();iter != headers.constEnd();iter++) + { + HBufC* stringData = TPtrC(reinterpret_cast<const TUint16*>((*iter).utf16())).AllocLC(); + QByteArray ba = aData->data((*iter)); + qDebug() << "copy to clipboard mime: " << *iter << " data: " << ba; + // mime type + aStream << TCardinality(stringData->Size()); + aStream << *(stringData); + // mime data + aStream << TCardinality(ba.size()); + aStream.WriteL(reinterpret_cast<const uchar*>(ba.constData()),ba.size()); + CleanupStack::PopAndDestroy(stringData); + } +} + +void readFromStreamLX(QMimeData* aData,RReadStream& aStream) +{ + // This function both leaves and throws exceptions. There must be no destructor + // dependencies between cleanup styles, and no cleanup stack dependencies on stacked objects. + TCardinality mimeTypeCount; + aStream >> mimeTypeCount; + for (int i = 0; i< mimeTypeCount;i++) + { + // mime type + TCardinality mimeTypeSize; + aStream >> mimeTypeSize; + HBufC* mimeTypeBuf = HBufC::NewLC(aStream,mimeTypeSize); + QString mimeType = QString::fromUtf16(mimeTypeBuf->Des().Ptr(),mimeTypeBuf->Length()); + CleanupStack::PopAndDestroy(mimeTypeBuf); + // mime data + TCardinality dataSize; + aStream >> dataSize; + QByteArray ba; + ba.reserve(dataSize); + aStream.ReadL(reinterpret_cast<uchar*>(ba.data_ptr()->data),dataSize); + ba.data_ptr()->size = dataSize; + qDebug() << "paste from clipboard mime: " << mimeType << " data: " << ba; + aData->setData(mimeType,ba); + } +} + + +/***************************************************************************** + QClipboard member functions + *****************************************************************************/ + +void QClipboard::clear(Mode mode) +{ + setText(QString(), mode); +} +const QMimeData* QClipboard::mimeData(Mode mode) const +{ + if (mode != Clipboard) return 0; + QClipboardData *d = clipboardData(); + if (d) + { + TRAPD(err,{ + RFs fs = qt_s60GetRFs(); + CClipboard* cb = CClipboard::NewForReadingLC(fs); + Q_ASSERT(cb); + RStoreReadStream stream; + TStreamId stid = (cb->StreamDictionary()).At(KQtCbDataStream); + stream.OpenLC(cb->Store(),stid); + QT_TRYCATCH_LEAVING(readFromStreamLX(d->source(),stream)); + CleanupStack::PopAndDestroy(2,cb); + return d->source(); + }); + if (err != KErrNone){ + qDebug()<< "clipboard is empty/err: " << err; + } + + } + return 0; +} + + +void QClipboard::setMimeData(QMimeData* src, Mode mode) +{ + if (mode != Clipboard) return; + QClipboardData *d = clipboardData(); + if (d) + { + TRAPD(err,{ + RFs fs = qt_s60GetRFs(); + CClipboard* cb = CClipboard::NewForWritingLC(fs); + RStoreWriteStream stream; + TStreamId stid = stream.CreateLC(cb->Store()); + QT_TRYCATCH_LEAVING(writeToStreamLX(src,stream)); + d->setSource(src); + stream.CommitL(); + (cb->StreamDictionary()).AssignL(KQtCbDataStream,stid); + cb->CommitL(); + CleanupStack::PopAndDestroy(2,cb); + }); + if (err != KErrNone){ + qDebug()<< "clipboard write err :" << err; + } + } + emitChanged(QClipboard::Clipboard); +} + +bool QClipboard::supportsMode(Mode mode) const +{ + return (mode == Clipboard); +} + +bool QClipboard::ownsMode(Mode mode) const +{ + if (mode == Clipboard) + qWarning("QClipboard::ownsClipboard: UNIMPLEMENTED!"); + return false; +} + +bool QClipboard::event(QEvent * /* e */) +{ + return true; +} + +void QClipboard::connectNotify( const char * ) +{ +} + +void QClipboard::ownerDestroyed() +{ +} +QT_END_NAMESPACE +#endif // QT_NO_CLIPBOARD diff --git a/src/gui/kernel/qclipboard_win.cpp b/src/gui/kernel/qclipboard_win.cpp index 7154571..ea7db2f 100644 --- a/src/gui/kernel/qclipboard_win.cpp +++ b/src/gui/kernel/qclipboard_win.cpp @@ -200,7 +200,7 @@ HRESULT QtCeGetClipboard(IDataObject** obj) if (clipData == 0) { clipData = GetClipboardData(CF_UNICODETEXT); if (clipData != 0) - clipText = QString::fromUtf16((unsigned short *)clipData); + clipText = QString::fromWCharArray((wchar_t *)clipData); } else { clipText = QString::fromLatin1((const char*)clipData); } @@ -325,13 +325,7 @@ bool QClipboard::event(QEvent *e) } if (propagate && d->nextClipboardViewer) { - QT_WA({ - SendMessage(d->nextClipboardViewer, m->message, - m->wParam, m->lParam); - } , { - SendMessageA(d->nextClipboardViewer, m->message, - m->wParam, m->lParam); - }); + SendMessage(d->nextClipboardViewer, m->message, m->wParam, m->lParam); } return true; diff --git a/src/gui/kernel/qclipboard_x11.cpp b/src/gui/kernel/qclipboard_x11.cpp index d37781f..12950ea 100644 --- a/src/gui/kernel/qclipboard_x11.cpp +++ b/src/gui/kernel/qclipboard_x11.cpp @@ -800,7 +800,7 @@ static Atom send_selection(QClipboardData *d, Atom target, Window window, Atom p QByteArray data; QByteArray fmt = X11->xdndAtomToString(target); - if (fmt.isEmpty() || !QInternalMimeData::hasFormatHelper(QString::fromAscii(fmt), d->source())) { // Not a MIME type we have + if (fmt.isEmpty()) { // Not a MIME type we have DEBUG("QClipboard: send_selection(): converting to type '%s' is not supported", fmt.data()); return XNone; } diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm index 2d4b3b8..b6aa454 100644 --- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm +++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm @@ -194,11 +194,19 @@ static void cleanupCocoaApplicationDelegate() } } - // Prevent Cocoa from terminating the application, since this simply - // exits the program whithout allowing QApplication::exec() to return. - // The call to QApplication::quit() above will instead quit the - // application from the Qt side. - return NSTerminateCancel; + 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; + } else { + // Prevent Cocoa from terminating the application, since this simply + // exits the program whithout allowing QApplication::exec() to return. + // The call to QApplication::quit() above will instead quit the + // application from the Qt side. + return NSTerminateCancel; + } } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm index 201f374..a2be9eb 100644 --- a/src/gui/kernel/qcocoapanel_mac.mm +++ b/src/gui/kernel/qcocoapanel_mac.mm @@ -85,6 +85,12 @@ QT_USE_NAMESPACE last resort (i.e., this is code that can potentially be removed). */ +- (void)toggleToolbarShown:(id)sender +{ + macSendToolbarChangeEvent([self QT_MANGLE_NAMESPACE(qt_qwidget)]); + [super toggleToolbarShown:sender]; +} + - (void)keyDown:(NSEvent *)theEvent { bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 1389b44..59494a7 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -49,6 +49,8 @@ #include <private/qt_cocoa_helpers_mac_p.h> #include <private/qdnd_p.h> #include <private/qmacinputcontext_p.h> +#include <private/qmultitouch_mac_p.h> +#include <private/qevent_p.h> #include <qscrollarea.h> #include <qhash.h> @@ -100,7 +102,7 @@ static dndenum_mapper dnd_enums[] = { { NSDragOperationCopy, Qt::CopyAction, true }, { NSDragOperationGeneric, Qt::CopyAction, false }, { NSDragOperationEvery, Qt::ActionMask, false }, - { NSDragOperationNone, Qt::IgnoreAction, false } + { NSDragOperationNone, Qt::IgnoreAction, false } }; static NSDragOperation qt_mac_mapDropAction(Qt::DropAction action) @@ -196,6 +198,7 @@ extern "C" { if (self) { [self finishInitWithQWidget:widget widgetPrivate:widgetprivate]; } + composingText = new QString(); composing = false; sendKeyEvents = true; currentCustomTypes = 0; @@ -224,14 +227,14 @@ extern "C" { currentCustomTypes = new QStringList(); *currentCustomTypes = 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, + NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType, + NSFilenamesPboardType, NSStringPboardType, + NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType, + NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType, + NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType, + NSRTFDPboardType, NSHTMLPboardType, NSPICTPboardType, NSURLPboardType, NSPDFPboardType, NSVCardPboardType, - NSFilesPromisePboardType, NSInkTextPboardType, + NSFilesPromisePboardType, NSInkTextPboardType, NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil]; // Add custom types supported by the application. for (int i = 0; i < customTypes.size(); i++) { @@ -276,16 +279,16 @@ extern "C" { dropData = 0; } } - -- (void)addDropData:(id <NSDraggingInfo>)sender + +- (void)addDropData:(id <NSDraggingInfo>)sender { [self removeDropData]; - CFStringRef dropPasteboard = (CFStringRef) [[sender draggingPasteboard] name]; + CFStringRef dropPasteboard = (CFStringRef) [[sender draggingPasteboard] name]; dropData = new QCocoaDropData(dropPasteboard); -} +} -- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender -{ +- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender +{ if (qwidget->testAttribute(Qt::WA_DropSiteRegistered) == false) return NSDragOperationNone; NSPoint windowPoint = [sender draggingLocation]; @@ -303,7 +306,7 @@ extern "C" { NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint]; NSPoint localPoint = [self convertPoint:windowPoint fromView:nil]; QPoint posDrag(localPoint.x, localPoint.y); - NSDragOperation nsActions = [sender draggingSourceOperationMask]; + 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; @@ -332,8 +335,8 @@ extern "C" { 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. + // since we accepted the drag enter event, the widget expects + // future drage move events. // ### check if we need to treat this like the drag enter event. nsActions = QT_PREPEND_NAMESPACE(qt_mac_mapDropAction)(qDEEvent.dropAction()); } else { @@ -341,7 +344,7 @@ extern "C" { } QT_PREPEND_NAMESPACE(qt_mac_copy_answer_rect)(qDMEvent); return nsActions; - } + } } - (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender @@ -369,7 +372,7 @@ extern "C" { if (qt_mac_mouse_inside_answer_rect(posDrag) && QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) == nsActions) return QT_PREPEND_NAMESPACE(qt_mac_mapDropActions)(QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastAction)); - // send drag move event to the widget + // send drag move event to the widget 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; @@ -432,7 +435,7 @@ extern "C" { NSPoint localPoint = [self convertPoint:windowPoint fromView:nil]; QPoint posDrop(localPoint.x, localPoint.y); - NSDragOperation nsActions = [sender draggingSourceOperationMask]; + NSDragOperation nsActions = [sender draggingSourceOperationMask]; Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations(nsActions); QMimeData *mimeData = dropData; if (QDragManager::self()->source()) @@ -453,6 +456,7 @@ extern "C" { - (void)dealloc { + delete composingText; [[NSNotificationCenter defaultCenter] removeObserver:self]; delete currentCustomTypes; [self unregisterDraggedTypes]; @@ -547,15 +551,7 @@ extern "C" { qwidget->objectName().local8Bit().data()); #endif QPainter p(qwidget); - QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(qwidget->parent()); - QPoint scrollAreaOffset; - if (scrollArea && scrollArea->viewport() == qwidget) { - QAbstractScrollAreaPrivate *priv - = static_cast<QAbstractScrollAreaPrivate *>(qt_widget_private(scrollArea)); - scrollAreaOffset = priv->contentsOffset(); - p.translate(-scrollAreaOffset); - } - qwidgetprivate->paintBackground(&p, qrgn, scrollAreaOffset, + qwidgetprivate->paintBackground(&p, qrgn, qwidget->isWindow() ? QWidgetPrivate::DrawAsRoot : 0); p.end(); } @@ -566,11 +562,6 @@ extern "C" { qt_sendSpontaneousEvent(qwidget, &e); if (!redirectionOffset.isNull()) QPainter::restoreRedirected(qwidget); -#ifdef QT_RASTER_PAINTENGINE - if(engine && engine->type() == QPaintEngine::Raster) - static_cast<QRasterPaintEngine*>(engine)->flush(qwidget, - qrgn.boundingRect().topLeft()); -#endif if (engine) engine->setSystemClip(QRegion()); qwidget->setAttribute(Qt::WA_WState_InPaintEvent, false); @@ -641,7 +632,7 @@ extern "C" { QHoverEvent he(QEvent::HoverEnter, QPoint(viewPoint.x, viewPoint.y), QPoint(-1, -1)); QApplicationPrivate::instance()->notify_helper(qwidget, &he); } - } + } } - (void)mouseExited:(NSEvent *)event @@ -650,7 +641,7 @@ extern "C" { NSPoint globalPoint = [[event window] convertBaseToScreen:[event locationInWindow]]; if (!qAppInstance()->activeModalWidget() || QApplicationPrivate::tryModalHelper(qwidget, 0)) { QApplication::sendEvent(qwidget, &leaveEvent); - + // ### Think about if it is necessary to update the cursor, should only be for a few cases. qt_mac_update_cursor_at_global_pos(flipPoint(globalPoint).toPoint()); if (qwidget->testAttribute(Qt::WA_Hover) @@ -675,14 +666,22 @@ extern "C" { - (void)mouseMoved:(NSEvent *)theEvent { - qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); + // We always enable mouse tracking for all QCocoaView-s. In cases where we have + // child views, we will receive mouseMoved for both parent & the child (if + // mouse is over the child). We need to ignore the parent mouseMoved in such + // cases. + NSPoint windowPoint = [theEvent locationInWindow]; + NSView *candidateView = [[[self window] contentView] hitTest:windowPoint]; + if (candidateView && candidateView == self) { + qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); + } } - (void)mouseDown:(NSEvent *)theEvent { qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, Qt::LeftButton); // 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. + // which we need to send even if the mouseDown event was not accepted. // (this is standard Qt behavior.) } @@ -696,7 +695,7 @@ extern "C" { } - (void)rightMouseDown:(NSEvent *)theEvent -{ +{ bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, Qt::RightButton); if (!mouseOK) @@ -845,6 +844,102 @@ extern "C" { [super tabletPoint:tabletEvent]; } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +- (void)touchesBeganWithEvent:(NSEvent *)event; +{ + bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents); + qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all)); +} + +- (void)touchesMovedWithEvent:(NSEvent *)event; +{ + bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents); + qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all)); +} + +- (void)touchesEndedWithEvent:(NSEvent *)event; +{ + bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents); + qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all)); +} + +- (void)touchesCancelledWithEvent:(NSEvent *)event; +{ + bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents); + qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all)); +} + +- (void)magnifyWithEvent:(NSEvent *)event; +{ + if (!QApplicationPrivate::tryModalHelper(qwidget, 0)) + return; + + QNativeGestureEvent qNGEvent; + qNGEvent.gestureType = QNativeGestureEvent::Zoom; + NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]]; + qNGEvent.position = flipPoint(p).toPoint(); + qNGEvent.percentage = [event magnification]; + qt_sendSpontaneousEvent(qwidget, &qNGEvent); +} + +- (void)rotateWithEvent:(NSEvent *)event; +{ + if (!QApplicationPrivate::tryModalHelper(qwidget, 0)) + return; + + QNativeGestureEvent qNGEvent; + qNGEvent.gestureType = QNativeGestureEvent::Rotate; + NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]]; + qNGEvent.position = flipPoint(p).toPoint(); + qNGEvent.percentage = -[event rotation]; + qt_sendSpontaneousEvent(qwidget, &qNGEvent); +} + +- (void)swipeWithEvent:(NSEvent *)event; +{ + if (!QApplicationPrivate::tryModalHelper(qwidget, 0)) + return; + + 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(qwidget, &qNGEvent); +} + +- (void)beginGestureWithEvent:(NSEvent *)event; +{ + if (!QApplicationPrivate::tryModalHelper(qwidget, 0)) + return; + + QNativeGestureEvent qNGEvent; + qNGEvent.gestureType = QNativeGestureEvent::GestureBegin; + NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]]; + qNGEvent.position = flipPoint(p).toPoint(); + qt_sendSpontaneousEvent(qwidget, &qNGEvent); +} + +- (void)endGestureWithEvent:(NSEvent *)event; +{ + if (!QApplicationPrivate::tryModalHelper(qwidget, 0)) + return; + + QNativeGestureEvent qNGEvent; + qNGEvent.gestureType = QNativeGestureEvent::GestureEnd; + NSPoint p = [[event window] convertBaseToScreen:[event locationInWindow]]; + qNGEvent.position = flipPoint(p).toPoint(); + qt_sendSpontaneousEvent(qwidget, &qNGEvent); +} +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + - (void)frameDidChange:(NSNotification *)note { Q_UNUSED(note); @@ -887,6 +982,15 @@ extern "C" { return qwidget->focusPolicy() != Qt::NoFocus; } +- (BOOL)resignFirstResponder +{ + // Seems like the following test only triggers if this + // view is inside a QMacNativeWidget: + if (qwidget == QApplication::focusWidget()) + QApplicationPrivate::setFocusWidget(0, Qt::OtherFocusReason); + return YES; +} + - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal { Q_UNUSED(isLocal); @@ -988,20 +1092,31 @@ extern "C" { - (void) insertText:(id)aString { - if (composing) { - // Send the commit string to the widget. - QString commitText; + QString commitText; + if ([aString length]) { if ([aString isKindOfClass:[NSAttributedString class]]) { - commitText = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string])); + commitText = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string])); } else { commitText = QCFString::toQString(reinterpret_cast<CFStringRef>(aString)); }; + } + + if ([aString length] && composing) { + // Send the commit string to the widget. composing = false; sendKeyEvents = false; QInputMethodEvent e; e.setCommitString(commitText); qt_sendSpontaneousEvent(qwidget, &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 @@ -1023,7 +1138,7 @@ extern "C" { while (index < composingLength) { NSRange effectiveRange; NSRange range = NSMakeRange(index, composingLength-index); - NSDictionary *attributes = [aString attributesAtIndex:index + NSDictionary *attributes = [aString attributesAtIndex:index longestEffectiveRange:&effectiveRange inRange:range]; NSNumber *underlineStyle = [attributes objectForKey:NSUnderlineStyleAttributeName]; @@ -1032,7 +1147,7 @@ extern "C" { NSColor *color = [attributes objectForKey:NSUnderlineColorAttributeName]; if (color) { clr = colorFrom(color); - } + } QTextCharFormat format; format.setFontUnderline(true); format.setUnderlineColor(clr); @@ -1055,12 +1170,21 @@ extern "C" { attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, composingLength, format); } + *composingText = qtText; QInputMethodEvent e(qtText, attrs); qt_sendSpontaneousEvent(qwidget, &e); + if (!composingLength) + composing = false; } - (void) unmarkText { + if (composing) { + QInputMethodEvent e; + e.setCommitString(*composingText); + qt_sendSpontaneousEvent(qwidget, &e); + } + composingText->clear(); composing = false; } @@ -1099,7 +1223,7 @@ extern "C" { - (NSRange) markedRange { - NSRange range; + NSRange range; if (composing) { range.location = 0; range.length = composingLength; @@ -1124,13 +1248,13 @@ extern "C" { selRange.length = 0; } return selRange; - + } - (NSRect) firstRectForCharacterRange:(NSRange)theRange { Q_UNUSED(theRange); - // The returned rect is always based on the internal cursor. + // The returned rect is always based on the internal cursor. QRect mr(qwidget->inputMethodQuery(Qt::ImMicroFocus).toRect()); QPoint mp(qwidget->mapToGlobal(QPoint(mr.bottomLeft()))); NSRect rect ; @@ -1278,7 +1402,7 @@ Qt::DropAction QDragManager::drag(QDrag *o) NSImage *image = (NSImage *)qt_mac_create_nsimage(pix); [image retain]; DnDParams *dndParams = [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]; - // save supported actions + // save supported actions [dndParams->view setSupportedActions: qt_mac_mapDropActions(dragPrivate()->possible_actions)]; NSPoint imageLoc = {dndParams->localPoint.x - hotspot.x(), dndParams->localPoint.y + pix.height() - hotspot.y()}; @@ -1302,7 +1426,7 @@ Qt::DropAction QDragManager::drag(QDrag *o) 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. + // 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); diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h index 6e00400..3810a2b 100644 --- a/src/gui/kernel/qcocoaview_mac_p.h +++ b/src/gui/kernel/qcocoaview_mac_p.h @@ -59,6 +59,7 @@ QT_FORWARD_DECLARE_CLASS(QWidgetPrivate); QT_FORWARD_DECLARE_CLASS(QWidget); QT_FORWARD_DECLARE_CLASS(QEvent); QT_FORWARD_DECLARE_CLASS(QCocoaDropData); +QT_FORWARD_DECLARE_CLASS(QString); QT_FORWARD_DECLARE_CLASS(QStringList); QT_BEGIN_NAMESPACE @@ -85,6 +86,7 @@ Q_GUI_EXPORT bool composing; int composingLength; bool sendKeyEvents; + QString *composingText; QStringList *currentCustomTypes; NSInteger dragEnterSequence; } diff --git a/src/gui/kernel/qcocoawindow_mac.mm b/src/gui/kernel/qcocoawindow_mac.mm index 523ee0d..57dca6d 100644 --- a/src/gui/kernel/qcocoawindow_mac.mm +++ b/src/gui/kernel/qcocoawindow_mac.mm @@ -101,6 +101,12 @@ QT_USE_NAMESPACE last resort (i.e., this is code that can potentially be removed). */ +- (void)toggleToolbarShown:(id)sender +{ + macSendToolbarChangeEvent([self QT_MANGLE_NAMESPACE(qt_qwidget)]); + [super toggleToolbarShown:sender]; +} + - (void)keyDown:(NSEvent *)theEvent { bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp index fbbc6bf..e26a592 100644 --- a/src/gui/kernel/qcursor.cpp +++ b/src/gui/kernel/qcursor.cpp @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE \ingroup appearance \ingroup shared - \mainclass + This class is mainly used to create mouse cursors that are associated with particular widgets and to get and set the position @@ -403,7 +403,7 @@ void QCursorData::initialize() QCursor::QCursor() { if (!QCursorData::initialized) { - if (qApp->startingUp()) { + if (QApplication::startingUp()) { d = 0; return; } @@ -561,7 +561,6 @@ QCursor::operator QVariant() const { return QVariant(QVariant::Cursor, this); } - +QT_END_NAMESPACE #endif // QT_NO_CURSOR -QT_END_NAMESPACE diff --git a/src/gui/kernel/qcursor_qws.cpp b/src/gui/kernel/qcursor_qws.cpp index b6fd149..fb44df8 100644 --- a/src/gui/kernel/qcursor_qws.cpp +++ b/src/gui/kernel/qcursor_qws.cpp @@ -66,7 +66,11 @@ QCursorData::~QCursorData() { delete bm; delete bmm; - QPaintDevice::qwsDisplay()->destroyCursor(id); + QT_TRY { + QPaintDevice::qwsDisplay()->destroyCursor(id); + } QT_CATCH(const std::bad_alloc &) { + // do nothing. + } } diff --git a/src/gui/kernel/qcursor_s60.cpp b/src/gui/kernel/qcursor_s60.cpp new file mode 100644 index 0000000..cc4a32d --- /dev/null +++ b/src/gui/kernel/qcursor_s60.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 <qcursor.h> +#include <qt_s60_p.h> + +#ifdef QT_NO_CURSOR +QT_BEGIN_NAMESPACE + +QPoint QCursor::pos() +{ + return S60->lastCursorPos; +} + +void QCursor::setPos(int x, int y) +{ + S60->lastCursorPos = QPoint(x, y); +} + +QT_END_NAMESPACE +#endif // QT_NO_CURSOR diff --git a/src/gui/kernel/qcursor_win.cpp b/src/gui/kernel/qcursor_win.cpp index a4a94c1..2867e62 100644 --- a/src/gui/kernel/qcursor_win.cpp +++ b/src/gui/kernel/qcursor_win.cpp @@ -66,7 +66,7 @@ QCursorData::~QCursorData() { delete bm; delete bmm; -#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS) +#if !defined(Q_WS_WINCE) || defined(GWES_ICONCURS) if (hcurs) DestroyCursor(hcurs); #endif @@ -129,7 +129,7 @@ extern HBITMAP qt_createIconMask(const QBitmap &bitmap); static HCURSOR create32BitCursor(const QPixmap &pixmap, int hx, int hy) { HCURSOR cur = 0; -#if !defined(Q_OS_WINCE) +#if !defined(Q_WS_WINCE) QBitmap mask = pixmap.mask(); if (mask.isNull()) { mask = QBitmap(pixmap.size()); @@ -317,54 +317,50 @@ void QCursorData::update() phand_bits, phandm_bits }; - unsigned short *sh; + wchar_t *sh = 0; switch (cshape) { // map to windows cursor case Qt::ArrowCursor: - sh = (unsigned short*)IDC_ARROW; + sh = IDC_ARROW; break; case Qt::UpArrowCursor: - sh = (unsigned short*)IDC_UPARROW; + sh = IDC_UPARROW; break; case Qt::CrossCursor: - sh = (unsigned short*)IDC_CROSS; + sh = IDC_CROSS; break; case Qt::WaitCursor: - sh = (unsigned short*)IDC_WAIT; + sh = IDC_WAIT; break; case Qt::IBeamCursor: - sh = (unsigned short*)IDC_IBEAM; + sh = IDC_IBEAM; break; case Qt::SizeVerCursor: - sh = (unsigned short*)IDC_SIZENS; + sh = IDC_SIZENS; break; case Qt::SizeHorCursor: - sh = (unsigned short*)IDC_SIZEWE; + sh = IDC_SIZEWE; break; case Qt::SizeBDiagCursor: - sh = (unsigned short*)IDC_SIZENESW; + sh = IDC_SIZENESW; break; case Qt::SizeFDiagCursor: - sh = (unsigned short*)IDC_SIZENWSE; + sh = IDC_SIZENWSE; break; case Qt::SizeAllCursor: - sh = (unsigned short*)IDC_SIZEALL; + sh = IDC_SIZEALL; break; case Qt::ForbiddenCursor: - sh = (unsigned short*)IDC_NO; + sh = IDC_NO; break; case Qt::WhatsThisCursor: - sh = (unsigned short*)IDC_HELP; + sh = IDC_HELP; break; case Qt::BusyCursor: - sh = (unsigned short*)IDC_APPSTARTING; + sh = IDC_APPSTARTING; break; case Qt::PointingHandCursor: - if ((QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) > QSysInfo::WV_95 || - (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) > QSysInfo::WV_NT) { - sh = (unsigned short*)IDC_HAND; - break; - } - // fall through + sh = IDC_HAND; + break; case Qt::BlankCursor: case Qt::SplitVCursor: case Qt::SplitHCursor: @@ -407,7 +403,7 @@ void QCursorData::update() } int n = qMax(1, bbits.width() / 8); int h = bbits.height(); -#if !defined(Q_OS_WINCE) +#if !defined(Q_WS_WINCE) uchar* xBits = new uchar[h * n]; uchar* xMask = new uchar[h * n]; int x = 0; @@ -430,7 +426,7 @@ void QCursorData::update() xBits, xMask); delete [] xBits; delete [] xMask; -#elif defined(GWES_ICONCURS) // Q_OS_WINCE +#elif defined(GWES_ICONCURS) // Q_WS_WINCE // Windows CE only supports fixed cursor size. int sysW = GetSystemMetrics(SM_CXCURSOR); int sysH = GetSystemMetrics(SM_CYCURSOR); @@ -480,13 +476,11 @@ void QCursorData::update() qWarning("QCursor::update: Invalid cursor shape %d", cshape); return; } - // ### From MSDN: - // ### LoadCursor has been superseded by the LoadImage function. - QT_WA({ - hcurs = LoadCursorW(0, reinterpret_cast<const TCHAR *>(sh)); - } , { - hcurs = LoadCursorA(0, reinterpret_cast<const char*>(sh)); - }); +#ifdef Q_WS_WINCE + hcurs = LoadCursor(0, sh); +#else + hcurs = (HCURSOR)LoadImage(0, sh, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); +#endif } QT_END_NAMESPACE diff --git a/src/gui/kernel/qdesktopwidget.h b/src/gui/kernel/qdesktopwidget.h index 38f88b8..cc95795 100644 --- a/src/gui/kernel/qdesktopwidget.h +++ b/src/gui/kernel/qdesktopwidget.h @@ -56,6 +56,9 @@ class QDesktopWidgetPrivate; class Q_GUI_EXPORT QDesktopWidget : public QWidget { Q_OBJECT + Q_PROPERTY(bool virtualDesktop READ isVirtualDesktop) + Q_PROPERTY(int screenCount READ screenCount NOTIFY screenCountChanged) + Q_PROPERTY(int primaryScreen READ primaryScreen) public: QDesktopWidget(); ~QDesktopWidget(); @@ -63,6 +66,7 @@ public: bool isVirtualDesktop() const; int numScreens() const; + int screenCount() const; int primaryScreen() const; int screenNumber(const QWidget *widget = 0) const; @@ -85,6 +89,7 @@ public: Q_SIGNALS: void resized(int); void workAreaResized(int); + void screenCountChanged(int); protected: void resizeEvent(QResizeEvent *e); @@ -97,6 +102,9 @@ private: friend class QApplicationPrivate; }; +inline int QDesktopWidget::screenCount() const +{ return numScreens(); } + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/kernel/qdesktopwidget.qdoc b/src/gui/kernel/qdesktopwidget.qdoc new file mode 100644 index 0000000..0c2c8a5 --- /dev/null +++ b/src/gui/kernel/qdesktopwidget.qdoc @@ -0,0 +1,264 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +/*! + \class QDesktopWidget + \brief The QDesktopWidget class provides access to screen information on multi-head systems. + + \ingroup advanced + \ingroup desktop + + QApplication::desktop() function should be used to get an instance + of the QDesktopWidget. + + Systems with more than one graphics card and monitor can manage the + physical screen space available either as multiple desktops, or as a + large virtual desktop, which usually has the size of the bounding + rectangle of all the screens (see virtualDesktop). For an + application, one of the available screens is the primary screen, i.e. + the screen where the main widget resides (see primaryScreen). All + windows opened in the context of the application should be + constrained to the boundaries of the primary screen; for example, + it would be inconvenient if a dialog box popped up on a different + screen, or split over two screens. + + The QDesktopWidget provides information about the geometry of the + available screens with screenGeometry(). The number of screens + available is returned by screenCount, and the screenCountChanged + signal is emitted when screens are added or removed during runtime. + The screen number that a particular point or widget is located in + is returned by screenNumber(). + + Widgets provided by Qt use this class, for example, to place + tooltips, menus and dialog boxes according to the parent or + application widget. Applications can use this class to save window + positions, or to place child widgets and dialogs on one particular + screen. + + \img qdesktopwidget.png Managing Multiple Screens + + In the illustration above, Application One's primary screen is + screen 0, and App Two's primary screen is screen 1. + + \target multiple screens note + \note QDesktopWidget inherits the QWidget properties, width() and + height(), which specify the size of the desktop. However, for + desktops with multiple screens, the size of the desktop is the union + of all the screen sizes, so width() and height() should \e not be + used for computing the size of a widget to be placed on one of the + screens. The correct width and height values are obtained using + availableGeometry() or screenGeometry() for a particular screen. + + \sa QApplication, QApplication::desktop(), QX11Info::appRootWindow() +*/ + +/*! + \fn QDesktopWidget::QDesktopWidget() + + \internal + + Creates the desktop widget. + + If the system supports a virtual desktop, this widget will have + the size of the virtual desktop; otherwise this widget will have + the size of the primary screen. + + Instead of using QDesktopWidget directly, use QApplication::desktop(). +*/ + +/*! + \fn QDesktopWidget::~QDesktopWidget() + + \internal + + Destroys the desktop widget and frees any allocated resources. +*/ + +/*! + \fn int QDesktopWidget::numScreens() const + + Returns the number of available screens. + + \obsolete + + This function is deprecated. Use screenCount instead. + + \sa primaryScreen +*/ + +/*! + \fn QWidget *QDesktopWidget::screen(int screen) + + Returns a widget that represents the screen with index \a screen + (a value of -1 means the default screen). + + If the system uses a virtual desktop, the returned widget will + have the geometry of the entire virtual desktop; i.e., bounding + every \a screen. + + \sa primaryScreen, screenCount, virtualDesktop +*/ + +/*! + \fn const QRect QDesktopWidget::availableGeometry(int screen) const + + Returns the available geometry of the screen with index \a screen. What + is available will be subrect of screenGeometry() based on what the + platform decides is available (for example excludes the dock and menu bar + on Mac OS X, or the task bar on Windows). The default screen is used if + \a screen is -1. + + \sa screenNumber(), screenGeometry() +*/ + +/*! + \fn const QRect QDesktopWidget::availableGeometry(const QWidget *widget) const + \overload + + Returns the available geometry of the screen which contains \a widget. + + \sa screenGeometry() +*/ + +/*! + \fn const QRect QDesktopWidget::availableGeometry(const QPoint &p) const + \overload + + Returns the available geometry of the screen which contains \a p. + + \sa screenGeometry() +*/ + + +/*! + \fn const QRect QDesktopWidget::screenGeometry(int screen) const + + Returns the geometry of the screen with index \a screen. The default + screen is used if \a screen is -1. + + \sa screenNumber() +*/ + +/*! + \fn const QRect QDesktopWidget::screenGeometry(const QWidget *widget) const + \overload + + Returns the geometry of the screen which contains \a widget. +*/ + +/*! + \fn const QRect QDesktopWidget::screenGeometry(const QPoint &p) const + \overload + + Returns the geometry of the screen which contains \a p. +*/ + + +/*! + \fn int QDesktopWidget::screenNumber(const QWidget *widget) const + + Returns the index of the screen that contains the largest + part of \a widget, or -1 if the widget not on a screen. + + \sa primaryScreen +*/ + +/*! + \fn int QDesktopWidget::screenNumber(const QPoint &point) const + + \overload + Returns the index of the screen that contains the \a point, or the + screen which is the shortest distance from the \a point. + + \sa primaryScreen +*/ + +/*! + \fn void QDesktopWidget::resizeEvent(QResizeEvent *event) + \reimp +*/ + +/*! + \fn void QDesktopWidget::resized(int screen) + + This signal is emitted when the size of \a screen changes. +*/ + +/*! + \fn void QDesktopWidget::workAreaResized(int screen) + + This signal is emitted when the work area available on \a screen changes. +*/ + +/*! + \property QDesktopWidget::screenCount + \brief the number of screens currently available on the system. + + \since 4.6 + + \sa screenCountChanged() +*/ + +/*! + \property QDesktopWidget::primaryScreen + \brief the index of the screen that is configured to be the primary screen + on the system. +*/ + +/*! + \property QDesktopWidget::virtualDesktop + + \brief if the system manages the available screens in a virtual desktop. + + For virtual desktops, screen() will always return the same widget. + The size of the virtual desktop is the size of this desktop + widget. +*/ + +/*! + \fn void QDesktopWidget::screenCountChanged(int newCount) + + \since 4.6 + + This signal is emitted when the number of screens changes to \a newCount. + + \sa screenCount +*/ diff --git a/src/gui/kernel/qdesktopwidget_mac.mm b/src/gui/kernel/qdesktopwidget_mac.mm index 1ada345..da8a1d1 100644 --- a/src/gui/kernel/qdesktopwidget_mac.mm +++ b/src/gui/kernel/qdesktopwidget_mac.mm @@ -97,15 +97,13 @@ QT_USE_NAMESPACE Q_GLOBAL_STATIC(QDesktopWidgetImplementation, qdesktopWidgetImplementation) QDesktopWidgetImplementation::QDesktopWidgetImplementation() - : appScreen(0), displays(0) + : appScreen(0) { onResize(); } QDesktopWidgetImplementation::~QDesktopWidgetImplementation() { - if (displays) - [displays release]; } QDesktopWidgetImplementation *QDesktopWidgetImplementation::instance() @@ -118,13 +116,7 @@ QRect QDesktopWidgetImplementation::availableRect(int screenIndex) const if (screenIndex < 0 || screenIndex >= screenCount) screenIndex = appScreen; - NSRect r = [[displays objectAtIndex:screenIndex] visibleFrame]; - NSRect primaryRect = [[displays objectAtIndex:0] frame]; - - const int flippedY = - r.origin.y + // account for position offset and - primaryRect.size.height - r.size.height; // height difference. - return QRectF(r.origin.x, flippedY, - r.size.width, r.size.height).toRect(); + return availableRects[screenIndex].toRect(); } QRect QDesktopWidgetImplementation::screenRect(int screenIndex) const @@ -132,22 +124,28 @@ QRect QDesktopWidgetImplementation::screenRect(int screenIndex) const if (screenIndex < 0 || screenIndex >= screenCount) screenIndex = appScreen; - NSRect r = [[displays objectAtIndex:screenIndex] frame]; - NSRect primaryRect = [[displays objectAtIndex:0] frame]; - - const int flippedY = - r.origin.y + // account for position offset and - primaryRect.size.height - r.size.height; // height difference. - return QRectF(r.origin.x, flippedY, - r.size.width, r.size.height).toRect(); + return screenRects[screenIndex].toRect(); } void QDesktopWidgetImplementation::onResize() { - if (displays) - [displays release]; - - displays = [[NSScreen screens] retain]; - screenCount = [displays count]; + 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]; + const 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]; + availableRects.append(QRectF(r.origin.x, flippedY, + r.size.width, r.size.height)); + } } @@ -195,7 +193,7 @@ const QRect QDesktopWidget::screenGeometry(int screen) const int QDesktopWidget::screenNumber(const QWidget *widget) const { - QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); + QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); if (!widget) return d->appScreen; QRect frame = widget->frameGeometry(); @@ -216,7 +214,7 @@ int QDesktopWidget::screenNumber(const QWidget *widget) const int QDesktopWidget::screenNumber(const QPoint &point) const { - QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); + QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); int closestScreen = -1; int shortestDistance = INT_MAX; for (int i = 0; i < d->screenCount; ++i) { @@ -232,13 +230,25 @@ int QDesktopWidget::screenNumber(const QPoint &point) const void QDesktopWidget::resizeEvent(QResizeEvent *) { - QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); + 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 < d->screenCount; ++i) { - emit resized(i); + 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/kernel/qdesktopwidget_mac_p.h b/src/gui/kernel/qdesktopwidget_mac_p.h index 77af8f7..91d970e 100644 --- a/src/gui/kernel/qdesktopwidget_mac_p.h +++ b/src/gui/kernel/qdesktopwidget_mac_p.h @@ -64,7 +64,8 @@ public: int appScreen; int screenCount; - NSArray *displays; + QVector<QRectF> availableRects; + QVector<QRectF> screenRects; QRect availableRect(int screenIndex) const; QRect screenRect(int screenIndex) const; diff --git a/src/gui/kernel/qdesktopwidget_s60.cpp b/src/gui/kernel/qdesktopwidget_s60.cpp new file mode 100644 index 0000000..9155430 --- /dev/null +++ b/src/gui/kernel/qdesktopwidget_s60.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qdesktopwidget.h" +#include "qapplication_p.h" +#include "qwidget_p.h" +#include "qt_s60_p.h" +#include <w32std.h> + +#include "hal.h" +#include "hal_data.h" + +QT_BEGIN_NAMESPACE + +class QDesktopWidgetPrivate : public QWidgetPrivate +{ + +public: + QDesktopWidgetPrivate(); + ~QDesktopWidgetPrivate(); + + static void init(QDesktopWidget *that); + static void cleanup(); + + static int screenCount; + static int primaryScreen; + + static QVector<QRect> *rects; + static QVector<QRect> *workrects; + + static int refcount; +}; + +int QDesktopWidgetPrivate::screenCount = 1; +int QDesktopWidgetPrivate::primaryScreen = 0; +QVector<QRect> *QDesktopWidgetPrivate::rects = 0; +QVector<QRect> *QDesktopWidgetPrivate::workrects = 0; +int QDesktopWidgetPrivate::refcount = 0; + +QDesktopWidgetPrivate::QDesktopWidgetPrivate() +{ + ++refcount; +} + +QDesktopWidgetPrivate::~QDesktopWidgetPrivate() +{ + if (!--refcount) + cleanup(); +} + +void QDesktopWidgetPrivate::init(QDesktopWidget *that) +{ + int screenCount=0; + + if (HAL::Get(0, HALData::EDisplayNumberOfScreens, screenCount) == KErrNone) + QDesktopWidgetPrivate::screenCount = screenCount; + else + QDesktopWidgetPrivate::screenCount = 0; + + rects = new QVector<QRect>(); + workrects = new QVector<QRect>(); + + rects->resize(QDesktopWidgetPrivate::screenCount); + workrects->resize(QDesktopWidgetPrivate::screenCount); + + // ### TODO: Implement proper multi-display support + rects->resize(1); + rects->replace(0, that->rect()); + workrects->resize(1); + workrects->replace(0, that->rect()); +} + +void QDesktopWidgetPrivate::cleanup() +{ + delete rects; + rects = 0; + delete workrects; + workrects = 0; +} + + +QDesktopWidget::QDesktopWidget() + : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop) +{ + setObjectName(QLatin1String("desktop")); + QDesktopWidgetPrivate::init(this); +} + +QDesktopWidget::~QDesktopWidget() +{ +} + +bool QDesktopWidget::isVirtualDesktop() const +{ + return true; +} + +int QDesktopWidget::primaryScreen() const +{ + return QDesktopWidgetPrivate::primaryScreen; +} + +int QDesktopWidget::numScreens() const +{ + Q_D(const QDesktopWidget); + return QDesktopWidgetPrivate::screenCount; +} + +QWidget *QDesktopWidget::screen(int /* screen */) +{ + return this; +} + +const QRect QDesktopWidget::availableGeometry(int /* screen */) const +{ + TRect clientRect = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); + return qt_TRect2QRect(clientRect); +} + +const QRect QDesktopWidget::screenGeometry(int /* screen */) const +{ + Q_D(const QDesktopWidget); + return QRect(0, 0, S60->screenWidthInPixels, S60->screenHeightInPixels); + } + +int QDesktopWidget::screenNumber(const QWidget * /* widget */) const +{ + return QDesktopWidgetPrivate::primaryScreen; +} + +int QDesktopWidget::screenNumber(const QPoint & /* point */) const +{ + return QDesktopWidgetPrivate::primaryScreen; +} + +void QDesktopWidget::resizeEvent(QResizeEvent *) +{ + Q_D(QDesktopWidget); + QVector<QRect> oldrects; + oldrects = *d->rects; + QVector<QRect> oldworkrects; + oldworkrects = *d->workrects; + int oldscreencount = d->screenCount; + + QDesktopWidgetPrivate::cleanup(); + QDesktopWidgetPrivate::init(this); + + for (int i = 0; i < qMin(oldscreencount, d->screenCount); ++i) { + QRect oldrect = oldrects[i]; + QRect newrect = d->rects->at(i); + if (oldrect != newrect) + emit resized(i); + } + + for (int j = 0; j < qMin(oldscreencount, d->screenCount); ++j) { + QRect oldrect = oldworkrects[j]; + QRect newrect = d->workrects->at(j); + if (oldrect != newrect) + emit workAreaResized(j); + } +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp index 68cfa91..0caf473 100644 --- a/src/gui/kernel/qdesktopwidget_win.cpp +++ b/src/gui/kernel/qdesktopwidget_win.cpp @@ -45,7 +45,7 @@ #include "qlibrary.h" #include <qvector.h> #include <limits.h> -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE #include <sipapi.h> #endif #include "qwidget_p.h" @@ -92,7 +92,7 @@ QVector<QRect> *QDesktopWidgetPrivate::rects = 0; QVector<QRect> *QDesktopWidgetPrivate::workrects = 0; static int screen_number = 0; int QDesktopWidgetPrivate::refcount = 0; -#ifdef Q_OS_WINCE_WM +#ifdef Q_WS_WINCE_WM // Use SIP information, if available // SipGetInfo is not supported by SSDK (no definition!). static inline void qt_get_sip_info(QRect &rect) @@ -152,41 +152,27 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) rects = new QVector<QRect>(); workrects = new QVector<QRect>(); + screenCount = 0; #ifndef Q_OS_WINCE - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - screenCount = 0; - // Trying to get the function pointers to Win98/2000 only functions - QLibrary user32Lib(QLatin1String("user32")); - if (!user32Lib.load()) - return; + QLibrary user32Lib(QLatin1String("user32")); + if (user32Lib.load()) { enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors"); - QT_WA({ - getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); - } , { - getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoA"); - }); - - if (!enumDisplayMonitors || !getMonitorInfo) { - screenCount = GetSystemMetrics(80); // SM_CMONITORS - rects->resize(screenCount); - for (int i = 0; i < screenCount; ++i) - rects->replace(i, that->rect()); - return; - } - // Calls enumCallback - enumDisplayMonitors(0, 0, enumCallback, 0); - enumDisplayMonitors = 0; - getMonitorInfo = 0; - } else { - rects->resize(1); - rects->replace(0, that->rect()); - workrects->resize(1); - workrects->replace(0, that->rect()); + getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); } -#else - screenCount = 0; + if (!enumDisplayMonitors || !getMonitorInfo) { + screenCount = GetSystemMetrics(80); // SM_CMONITORS + rects->resize(screenCount); + for (int i = 0; i < screenCount; ++i) + rects->replace(i, that->rect()); + return; + } + // Calls enumCallback + enumDisplayMonitors(0, 0, enumCallback, 0); + enumDisplayMonitors = 0; + getMonitorInfo = 0; +#else QLibrary coreLib(QLatin1String("coredll")); if (coreLib.load()) { // CE >= 4.0 case @@ -208,7 +194,7 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); QRect qr = QRect(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1)); -#if defined(Q_OS_WINCE_WM) +#if defined(Q_WS_WINCE_WM) qt_get_sip_info(qr); #endif @@ -222,7 +208,7 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) enumDisplayMonitors(0, 0, enumCallback, 0); enumDisplayMonitors = 0; getMonitorInfo = 0; -#endif // Q_OS_WINCE +#endif // Q_WS_WINCE } QDesktopWidgetPrivate::~QDesktopWidgetPrivate() @@ -303,106 +289,99 @@ QWidget *QDesktopWidget::screen(int /* screen */) const QRect QDesktopWidget::availableGeometry(int screen) const { Q_D(const QDesktopWidget); -#ifdef Q_OS_WINCE_WM +#ifdef Q_WS_WINCE_WM for(int i=0; i < d->workrects->size(); ++i) qt_get_sip_info((*d->workrects)[i]); #endif - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - if (screen < 0 || screen >= d->screenCount) - screen = d->primaryScreen; + if (screen < 0 || screen >= d->screenCount) + screen = d->primaryScreen; - return d->workrects->at(screen); - } else { - return d->workrects->at(d->primaryScreen); - } + return d->workrects->at(screen); } const QRect QDesktopWidget::screenGeometry(int screen) const { const QDesktopWidgetPrivate *d = d_func(); - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - if (screen < 0 || screen >= d->screenCount) - screen = d->primaryScreen; + if (screen < 0 || screen >= d->screenCount) + screen = d->primaryScreen; - return d->rects->at(screen); - } else { - return d->rects->at(d->primaryScreen); - } + return d->rects->at(screen); } int QDesktopWidget::screenNumber(const QWidget *widget) const { Q_D(const QDesktopWidget); - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - if (!widget) - return d->primaryScreen; - QRect frame = widget->frameGeometry(); - if (!widget->isWindow()) - frame.moveTopLeft(widget->mapToGlobal(QPoint(0,0))); - - int maxSize = -1; - int maxScreen = -1; - - for (int i = 0; i < d->screenCount; ++i) { - QRect sect = d->rects->at(i).intersected(frame); - int size = sect.width() * sect.height(); - if (size > maxSize && sect.width() > 0 && sect.height() > 0) { - maxSize = size; - maxScreen = i; - } - } - return maxScreen; - } else { + if (!widget) return d->primaryScreen; + + QRect frame = widget->frameGeometry(); + if (!widget->isWindow()) + frame.moveTopLeft(widget->mapToGlobal(QPoint(0,0))); + + int maxSize = -1; + int maxScreen = -1; + + for (int i = 0; i < d->screenCount; ++i) { + QRect sect = d->rects->at(i).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 { Q_D(const QDesktopWidget); + int closestScreen = -1; - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - int shortestDistance = INT_MAX; - for (int i = 0; i < d->screenCount; ++i) { - int thisDistance = d->pointToRect(point, d->rects->at(i)); - if (thisDistance < shortestDistance) { - shortestDistance = thisDistance; - closestScreen = i; - } + int shortestDistance = INT_MAX; + + for (int i = 0; i < d->screenCount; ++i) { + int thisDistance = d->pointToRect(point, d->rects->at(i)); + if (thisDistance < shortestDistance) { + shortestDistance = thisDistance; + closestScreen = i; } } + return closestScreen; } void QDesktopWidget::resizeEvent(QResizeEvent *) { Q_D(QDesktopWidget); - QVector<QRect> oldrects; - oldrects = *d->rects; - QVector<QRect> oldworkrects; - oldworkrects = *d->workrects; + const QVector<QRect> oldrects(*d->rects); + const QVector<QRect> oldworkrects(*d->workrects); int oldscreencount = d->screenCount; QDesktopWidgetPrivate::cleanup(); QDesktopWidgetPrivate::init(this); -#ifdef Q_OS_WINCE_WM +#ifdef Q_WS_WINCE_WM for(int i=0; i < d->workrects->size(); ++i) qt_get_sip_info((*d->workrects)[i]); #endif for (int i = 0; i < qMin(oldscreencount, d->screenCount); ++i) { - QRect oldrect = oldrects[i]; - QRect newrect = d->rects->at(i); + const QRect oldrect = oldrects[i]; + const QRect newrect = d->rects->at(i); if (oldrect != newrect) emit resized(i); } for (int j = 0; j < qMin(oldscreencount, d->screenCount); ++j) { - QRect oldrect = oldworkrects[j]; - QRect newrect = d->workrects->at(j); + const QRect oldrect = oldworkrects[j]; + const QRect newrect = d->workrects->at(j); if (oldrect != newrect) emit workAreaResized(j); } + + if (oldscreencount != d->screenCount) { + emit screenCountChanged(d->screenCount); + } } #ifdef Q_CC_MSVC diff --git a/src/gui/kernel/qdesktopwidget_x11.cpp b/src/gui/kernel/qdesktopwidget_x11.cpp index 2fc322d..b4ad31d 100644 --- a/src/gui/kernel/qdesktopwidget_x11.cpp +++ b/src/gui/kernel/qdesktopwidget_x11.cpp @@ -197,7 +197,7 @@ void QDesktopWidgetPrivate::init() if (screens) { // leaks QWidget* pointers on purpose, can't delete them as pointer escapes - screens = (QWidget**) realloc(screens, j * sizeof(QWidget*)); + screens = q_check_ptr((QWidget**) realloc(screens, j * sizeof(QWidget*))); if (j > screenCount) memset(&screens[screenCount], 0, (j-screenCount) * sizeof(QWidget*)); } @@ -285,26 +285,36 @@ const QRect QDesktopWidget::availableGeometry(int screen) const if (d->workareas[screen].isValid()) return d->workareas[screen]; - if ((d->screenCount == 1 || !isVirtualDesktop()) - && X11->isSupportedByWM(ATOM(_NET_WORKAREA))) { + if (X11->isSupportedByWM(ATOM(_NET_WORKAREA))) { + int x11Screen = isVirtualDesktop() ? DefaultScreen(X11->display) : screen; + Atom ret; int format, e; unsigned char *data = 0; unsigned long nitems, after; e = XGetWindowProperty(X11->display, - QX11Info::appRootWindow(screen), - ATOM(_NET_WORKAREA), 0, 4, False, XA_CARDINAL, - &ret, &format, &nitems, &after, &data); + QX11Info::appRootWindow(x11Screen), + ATOM(_NET_WORKAREA), 0, 4, False, XA_CARDINAL, + &ret, &format, &nitems, &after, &data); + QRect workArea; if (e == Success && ret == XA_CARDINAL && format == 32 && nitems == 4) { long *workarea = (long *) data; - d->workareas[screen].setRect(workarea[0], workarea[1], - workarea[2], workarea[3]); + workArea = QRect(workarea[0], workarea[1], workarea[2], workarea[3]); } else { - d->workareas[screen] = screenGeometry(screen); + workArea = screenGeometry(screen); + } + + if (isVirtualDesktop()) { + // intersect the workarea (which spawns all Xinerama screens) with the rect for the + // requested screen + workArea &= screenGeometry(screen); } + + d->workareas[screen] = workArea; + if (data) XFree(data); } else { @@ -372,7 +382,32 @@ int QDesktopWidget::screenNumber(const QPoint &point) const void QDesktopWidget::resizeEvent(QResizeEvent *event) { Q_D(QDesktopWidget); + int oldScreenCount = d->screenCount; + QVector<QRect> oldRects(oldScreenCount); + QVector<QRect> oldWorks(oldScreenCount); + for (int i = 0; i < oldScreenCount; ++i) { + oldRects[i] = d->rects[i]; + oldWorks[i] = d->workareas[i]; + } + d->init(); + + for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) { + if (oldRects.at(i) != d->rects[i]) + emit resized(i); + } + + // ### workareas are just reset by init, not filled with new values + // ### so this will not work correctly + for (int j = 0; j < qMin(oldScreenCount, d->screenCount); ++j) { + if (oldWorks.at(j) != d->workareas[j]) + emit workAreaResized(j); + } + + if (oldScreenCount != d->screenCount) { + emit screenCountChanged(d->screenCount); + } + qt_desktopwidget_workarea_dirty = true; QWidget::resizeEvent(event); } diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp index b6ed979..fcf140e 100644 --- a/src/gui/kernel/qdnd.cpp +++ b/src/gui/kernel/qdnd.cpp @@ -368,7 +368,7 @@ QDragManager::~QDragManager() QDragManager *QDragManager::self() { - if (!instance && qApp && !qApp->closingDown()) + if (!instance && !QApplication::closingDown()) instance = new QDragManager; return instance; } diff --git a/src/gui/kernel/qdnd_mac.mm b/src/gui/kernel/qdnd_mac.mm index 911983a..507ff18 100644 --- a/src/gui/kernel/qdnd_mac.mm +++ b/src/gui/kernel/qdnd_mac.mm @@ -405,12 +405,12 @@ bool QWidgetPrivate::qt_mac_dnd_event(uint kind, DragRef dragRef) SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDEEvent.dropAction())); if (!qDEEvent.isAccepted()) - // The widget is simply not interrested in this + // 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 sendt immidiatly after + // 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, diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h index 43e884a..1f64015 100644 --- a/src/gui/kernel/qdnd_p.h +++ b/src/gui/kernel/qdnd_p.h @@ -65,7 +65,7 @@ #endif #if defined(Q_WS_WIN) -# include <windows.h> +# include <qt_windows.h> # include <objidl.h> #endif @@ -202,7 +202,7 @@ public: #endif }; -class Q_GUI_EXPORT QDragManager: public QObject { +class QDragManager: public QObject { Q_OBJECT QDragManager(); diff --git a/src/gui/kernel/qdnd_s60.cpp b/src/gui/kernel/qdnd_s60.cpp new file mode 100644 index 0000000..6089f2b --- /dev/null +++ b/src/gui/kernel/qdnd_s60.cpp @@ -0,0 +1,395 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qwidget.h" +#include "qdatetime.h" +#include "qbitmap.h" +#include "qcursor.h" +#include "qevent.h" +#include "qpainter.h" +#include "qdnd_p.h" + +#include <COECNTRL.H> +// pointer cursor +#include <w32std.h> +#include <gdi.h> +QT_BEGIN_NAMESPACE +//### artistic impression of Symbians default DnD cursor ? + +static QPixmap *defaultPm = 0; +static const int default_pm_hotx = -50; +static const int default_pm_hoty = -50; +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", +}; +//### actions need to be redefined for S60 +// Shift/Ctrl handling, and final drop status +static Qt::DropAction global_accepted_action = Qt::MoveAction; +static Qt::DropActions possible_actions = Qt::IgnoreAction; + + +// static variables in place of a proper cross-process solution +static QDrag *drag_object; +static bool qt_symbian_dnd_dragging = false; + + +static Qt::KeyboardModifiers oldstate; + +class QShapedPixmapWidget +{ +public: + QShapedPixmapWidget(RWsSession aWsSession,RWindowTreeNode* aNode) + { + sprite = RWsSprite(aWsSession); + cursorSprite.iBitmap = 0; + cursorSprite.iMaskBitmap = 0; + cursorSprite.iInvertMask = EFalse; + cursorSprite.iOffset = TPoint(0,0); + cursorSprite.iInterval = TTimeIntervalMicroSeconds32(0); + cursorSprite.iDrawMode = CGraphicsContext::EDrawModePEN; + sprite.Construct(*aNode,TPoint(0,0), ESpriteNoShadows | ESpriteNoChildClip); + sprite.AppendMember(cursorSprite); + sprite.Activate(); + } + ~QShapedPixmapWidget() + { + sprite.Close(); + cursorSprite.iBitmap = 0; + delete cursorBitmap; + cursorBitmap = 0; //redundant... + } + void disableCursor() + { + cursorSprite.iBitmap = 0; + sprite.UpdateMember(0,cursorSprite); + } + void enableCursor() + { + cursorSprite.iBitmap = cursorBitmap; + sprite.UpdateMember(0,cursorSprite); + } + void setPixmap(QPixmap pm) + { + //### heaplock centralized. + QImage temp = pm.toImage(); + QSize size = pm.size(); + temp.bits(); + CFbsBitmap *curbm = q_check_ptr(new CFbsBitmap()); // CBase derived object needs check on new + curbm->Create(TSize(size.width(),size.height()),EColor16MA); + curbm->LockHeap(ETrue); + memcpy((uchar*)curbm->DataAddress(),temp.bits(),temp.numBytes()); + curbm->UnlockHeap(ETrue); + delete cursorSprite.iBitmap; + cursorSprite.iBitmap = curbm; + cursorBitmap = curbm; + sprite.UpdateMember(0,cursorSprite); + } + CFbsBitmap *cursorBitmap; + RWsPointerCursor pointerCursor; + RWsSprite sprite; + TSpriteMember cursorSprite; + +}; + + +static QShapedPixmapWidget *qt_symbian_dnd_deco = 0; + +void QDragManager::updatePixmap() +{ + if (qt_symbian_dnd_deco) { + QPixmap pm; + QPoint pm_hot(default_pm_hotx,default_pm_hoty); + if (drag_object) { + pm = drag_object->pixmap(); + if (!pm.isNull()) + pm_hot = drag_object->hotSpot(); + } + if (pm.isNull()) { + if (!defaultPm) + defaultPm = new QPixmap(default_pm); + pm = *defaultPm; + } + qt_symbian_dnd_deco->setPixmap(pm); + } +} + +void QDragManager::timerEvent(QTimerEvent *) { } + +void QDragManager::move(const QPoint&) { +} + +void QDragManager::updateCursor() +{ +} + + +bool QDragManager::eventFilter(QObject *o, QEvent *e) +{ + if (beingCancelled) { + return false; + } + if (!o->isWidgetType()) + return false; + + switch(e->type()) { + case QEvent::MouseButtonPress: + { + } + case QEvent::MouseMove: + { + if (!object) { //#### this should not happen + qWarning("QDragManager::eventFilter: No object"); + return true; + } + QDragManager *manager = QDragManager::self(); + QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData; + if (manager->object) + possible_actions = manager->dragPrivate()->possible_actions; + else + possible_actions = Qt::IgnoreAction; + + QMouseEvent *me = (QMouseEvent *)e; + + if (me->buttons()) { + Qt::DropAction prevAction = global_accepted_action; + QWidget *cw = QApplication::widgetAt(me->globalPos()); + // map the Coords relative to the window. + if (!cw) + return true; + TPoint windowPos = cw->effectiveWinId()->PositionRelativeToScreen(); + qt_symbian_dnd_deco->sprite.SetPosition(TPoint(me->globalX()- windowPos.iX,me->globalY()- windowPos.iY)); + + while (cw && !cw->acceptDrops() && !cw->isWindow()) + cw = cw->parentWidget(); + + if (object->target() != cw) { + if (object->target()) { + QDragLeaveEvent dle; + QApplication::sendEvent(object->target(), &dle); + willDrop = false; + global_accepted_action = Qt::IgnoreAction; + updateCursor(); + restoreCursor = true; + object->d_func()->target = 0; + } + if (cw && cw->acceptDrops()) { + object->d_func()->target = cw; + QDragEnterEvent dee(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData, + me->buttons(), me->modifiers()); + QApplication::sendEvent(object->target(), &dee); + willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction; + global_accepted_action = willDrop ? dee.dropAction() : Qt::IgnoreAction; + updateCursor(); + restoreCursor = true; + } + } else if (cw) { + QDragMoveEvent dme(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData, + me->buttons(), me->modifiers()); + if (global_accepted_action != Qt::IgnoreAction) { + dme.setDropAction(global_accepted_action); + dme.accept(); + } + QApplication::sendEvent(cw, &dme); + willDrop = dme.isAccepted(); + global_accepted_action = willDrop ? dme.dropAction() : Qt::IgnoreAction; + updatePixmap(); + updateCursor(); + } + if (global_accepted_action != prevAction) + emitActionChanged(global_accepted_action); + } + return true; // Eat all mouse events + } + + case QEvent::MouseButtonRelease: + { + qApp->removeEventFilter(this); + if (restoreCursor) { + qt_symbian_dnd_deco->disableCursor(); + willDrop = false; + restoreCursor = false; + } + if (object && object->target()) { + + QMouseEvent *me = (QMouseEvent *)e; + + QDragManager *manager = QDragManager::self(); + QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData; + + QDropEvent de(object->target()->mapFromGlobal(me->globalPos()), possible_actions, dropData, + me->buttons(), me->modifiers()); + QApplication::sendEvent(object->target(), &de); + if (de.isAccepted()) + global_accepted_action = de.dropAction(); + else + global_accepted_action = Qt::IgnoreAction; + + if (object) + object->deleteLater(); + drag_object = object = 0; + } + eventLoop->exit(); + return true; // Eat all mouse events + } + + default: + break; + } + return false; +} + +Qt::DropAction QDragManager::drag(QDrag *o) +{ + Q_ASSERT(!qt_symbian_dnd_dragging); + if (object == o || !o || !o->source()) + return Qt::IgnoreAction; + + if (object) { + cancel(); + qApp->removeEventFilter(this); + beingCancelled = false; + } + + object = drag_object = o; + RWsSession winSession = o->source()->effectiveWinId()->ControlEnv()->WsSession(); + Q_ASSERT(!qt_symbian_dnd_deco); + qt_symbian_dnd_deco = new QShapedPixmapWidget(winSession, o->source()->effectiveWinId()->DrawableWindow()); + + oldstate = Qt::NoModifier; // #### Should use state that caused the drag + willDrop = false; + updatePixmap(); + updateCursor(); + restoreCursor = true; + + object->d_func()->target = 0; + TPoint windowPos = source()->effectiveWinId()->PositionRelativeToScreen(); + qt_symbian_dnd_deco->sprite.SetPosition(TPoint(QCursor::pos().x()- windowPos.iX ,QCursor::pos().y() - windowPos.iY)); + + QPoint hotspot = drag_object->hotSpot(); + qt_symbian_dnd_deco->cursorSprite.iOffset = TPoint(- hotspot.x(),- hotspot.y()); + qt_symbian_dnd_deco->sprite.UpdateMember(0,qt_symbian_dnd_deco->cursorSprite); + + qApp->installEventFilter(this); + + global_accepted_action = Qt::MoveAction; + qt_symbian_dnd_dragging = true; + + eventLoop = new QEventLoop; + // block + (void) eventLoop->exec(QEventLoop::AllEvents); + delete eventLoop; + eventLoop = 0; + + delete qt_symbian_dnd_deco; + qt_symbian_dnd_deco = 0; + qt_symbian_dnd_dragging = false; + + + return global_accepted_action; +} + + +void QDragManager::cancel(bool deleteSource) +{ + beingCancelled = true; + + if (object->target()) { + QDragLeaveEvent dle; + QApplication::sendEvent(object->target(), &dle); + } + + if (drag_object) { + if (deleteSource) + object->deleteLater(); + drag_object = object = 0; + } + + delete qt_symbian_dnd_deco; + qt_symbian_dnd_deco = 0; + + global_accepted_action = Qt::IgnoreAction; +} + + +void QDragManager::drop() +{ +} + +QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type type) const +{ + if (!drag_object) + return QVariant(); + QByteArray data = drag_object->mimeData()->data(mimetype); + if (type == QVariant::String) + return QString::fromUtf8(data); + return data; +} + +bool QDropData::hasFormat_sys(const QString &format) const +{ + return formats().contains(format); +} + +QStringList QDropData::formats_sys() const +{ + if (drag_object) + return drag_object->mimeData()->formats(); + return QStringList(); +} + +QT_END_NAMESPACE +#endif // QT_NO_DRAGANDDROP diff --git a/src/gui/kernel/qdnd_win.cpp b/src/gui/kernel/qdnd_win.cpp index 547476e..53392b5 100644 --- a/src/gui/kernel/qdnd_win.cpp +++ b/src/gui/kernel/qdnd_win.cpp @@ -154,9 +154,9 @@ QOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) #ifdef QDND_DEBUG qDebug("QOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)"); #ifndef Q_OS_WINCE - char buf[256] = {0}; - GetClipboardFormatNameA(pformatetc->cfFormat, buf, 255); - qDebug("CF = %d : %s", pformatetc->cfFormat, buf); + wchar_t buf[256] = {0}; + GetClipboardFormatName(pformatetc->cfFormat, buf, 255); + qDebug("CF = %d : %s", pformatetc->cfFormat, QString::fromWCharArray(buf)); #endif #endif @@ -398,52 +398,47 @@ void QOleDropSource::createCursors() int h = cpm.height(); if (!pm.isNull()) { - int x1 = qMin(-hotSpot.x(),0); - int x2 = qMax(pm.width()-hotSpot.x(),cpm.width()); - int y1 = qMin(-hotSpot.y(),0); - int y2 = qMax(pm.height()-hotSpot.y(),cpm.height()); + int x1 = qMin(-hotSpot.x(), 0); + int x2 = qMax(pm.width() - hotSpot.x(), cpm.width()); + int y1 = qMin(-hotSpot.y(), 0); + int y2 = qMax(pm.height() - hotSpot.y(), cpm.height()); - w = x2-x1+1; - h = y2-y1+1; + w = x2 - x1 + 1; + h = y2 - y1 + 1; } QRect srcRect = pm.rect(); QPoint pmDest = QPoint(qMax(0, -hotSpot.x()), qMax(0, -hotSpot.y())); QPoint newHotSpot = hotSpot; -#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS) - bool limitedCursorSize = (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) - || (QSysInfo::WindowsVersion == QSysInfo::WV_NT) - || (QSysInfo::WindowsVersion == QSysInfo::WV_CE); - - if (limitedCursorSize) { - // Limited cursor size - int reqw = GetSystemMetrics(SM_CXCURSOR); - int reqh = GetSystemMetrics(SM_CYCURSOR); - - QPoint hotspotInPM = newHotSpot - pmDest; - if (reqw < w) { - // Not wide enough - move objectpm right - qreal r = qreal(newHotSpot.x()) / w; - newHotSpot = QPoint(int(r * reqw), newHotSpot.y()); - if (newHotSpot.x() + cpm.width() > reqw) - newHotSpot.setX(reqw - cpm.width()); - - srcRect = QRect(QPoint(hotspotInPM.x() - newHotSpot.x(), srcRect.top()), QSize(reqw, srcRect.height())); - } - if (reqh < h) { - qreal r = qreal(newHotSpot.y()) / h; - newHotSpot = QPoint(newHotSpot.x(), int(r * reqh)); - if (newHotSpot.y() + cpm.height() > reqh) - newHotSpot.setY(reqh - cpm.height()); - - srcRect = QRect(QPoint(srcRect.left(), hotspotInPM.y() - newHotSpot.y()), QSize(srcRect.width(), reqh)); - } - // Always use system cursor size - w = reqw; - h = reqh; +#if defined(Q_OS_WINCE) + // Limited cursor size + int reqw = GetSystemMetrics(SM_CXCURSOR); + int reqh = GetSystemMetrics(SM_CYCURSOR); + + QPoint hotspotInPM = newHotSpot - pmDest; + if (reqw < w) { + // Not wide enough - move objectpm right + qreal r = qreal(newHotSpot.x()) / w; + newHotSpot = QPoint(int(r * reqw), newHotSpot.y()); + if (newHotSpot.x() + cpm.width() > reqw) + newHotSpot.setX(reqw - cpm.width()); + + srcRect = QRect(QPoint(hotspotInPM.x() - newHotSpot.x(), srcRect.top()), QSize(reqw, srcRect.height())); } + if (reqh < h) { + qreal r = qreal(newHotSpot.y()) / h; + newHotSpot = QPoint(newHotSpot.x(), int(r * reqh)); + if (newHotSpot.y() + cpm.height() > reqh) + newHotSpot.setY(reqh - cpm.height()); + + srcRect = QRect(QPoint(srcRect.left(), hotspotInPM.y() - newHotSpot.y()), QSize(srcRect.width(), reqh)); + } + // Always use system cursor size + w = reqw; + h = reqh; #endif + QPixmap newCursor(w, h); if (!pm.isNull()) { newCursor.fill(QColor(0, 0, 0, 0)); @@ -549,7 +544,7 @@ QOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) return ResultFromScode(DRAGDROP_S_DROP); } #endif - qApp->processEvents(); + QApplication::processEvents(); return NOERROR; } } diff --git a/src/gui/kernel/qdnd_x11.cpp b/src/gui/kernel/qdnd_x11.cpp index 9babfdc..bb586c2 100644 --- a/src/gui/kernel/qdnd_x11.cpp +++ b/src/gui/kernel/qdnd_x11.cpp @@ -542,6 +542,8 @@ bool QX11Data::xdndMimeDataForAtom(Atom a, QMimeData *mimeData, QByteArray *data dm->xdndMimeTransferedPixmapIndex = (dm->xdndMimeTransferedPixmapIndex + 1) % 2; } + } else { + DEBUG("QClipboard: xdndMimeDataForAtom(): converting to type '%s' is not supported", qPrintable(atomName)); } } return data; @@ -622,28 +624,12 @@ QVariant QX11Data::xdndMimeConvertToFormat(Atom a, const QByteArray &data, const if (format == QLatin1String("image/ppm")) { if (a == XA_PIXMAP && data.size() == sizeof(Pixmap)) { Pixmap xpm = *((Pixmap*)data.data()); - Display *dpy = display; - Window r; - int x,y; - uint w,h,bw,d; if (!xpm) return QByteArray(); - XGetGeometry(dpy,xpm, &r,&x,&y,&w,&h,&bw,&d); + QPixmap qpm = QPixmap::fromX11Pixmap(xpm); QImageWriter imageWriter; - GC gc = XCreateGC(dpy, xpm, 0, 0); - QImage imageToWrite; - if (d == 1) { - QBitmap qbm(w,h); - XCopyArea(dpy,xpm,qbm.handle(),gc,0,0,w,h,0,0); - imageWriter.setFormat("PBMRAW"); - imageToWrite = qbm.toImage(); - } else { - QPixmap qpm(w,h); - XCopyArea(dpy,xpm,qpm.handle(),gc,0,0,w,h,0,0); - imageWriter.setFormat("PPMRAW"); - imageToWrite = qpm.toImage(); - } - XFreeGC(dpy,gc); + imageWriter.setFormat("PPMRAW"); + QImage imageToWrite = qpm.toImage(); QBuffer buf; buf.open(QIODevice::WriteOnly); imageWriter.setDevice(&buf); @@ -1087,12 +1073,14 @@ void qt_xdnd_send_leave() if (!qt_xdnd_current_target) return; + QDragManager *manager = QDragManager::self(); + XClientMessageEvent leave; leave.type = ClientMessage; leave.window = qt_xdnd_current_target; leave.format = 32; leave.message_type = ATOM(XdndLeave); - leave.data.l[0] = qt_xdnd_dragsource_xid; + leave.data.l[0] = manager->dragPrivate()->source->effectiveWinId(); leave.data.l[1] = 0; // flags leave.data.l[2] = 0; // x, y leave.data.l[3] = 0; // w, h @@ -1108,8 +1096,8 @@ void qt_xdnd_send_leave() else XSendEvent(X11->display, qt_xdnd_current_proxy_target, False, NoEventMask, (XEvent*)&leave); + // reset the drag manager state - QDragManager *manager = QDragManager::self(); manager->willDrop = false; if (global_accepted_action != Qt::IgnoreAction) manager->emitActionChanged(Qt::IgnoreAction); diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index b19d791..a61b6fa 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -83,6 +83,13 @@ QInputEvent::~QInputEvent() \sa QApplication::keyboardModifiers() */ +/*! \fn void QInputEvent::setModifiers(Qt::KeyboardModifiers modifiers) + + \internal + + Sets the keyboard modifiers flags for this event. +*/ + /*! \class QMouseEvent \ingroup events @@ -106,8 +113,12 @@ QInputEvent::~QInputEvent() propagated up the parent widget chain until a widget accepts it with accept(), or an event filter consumes it. + \note If a mouse event is propagated to a \l{QWidget}{widget} for + which Qt::WA_NoMousePropagation has been set, that mouse event + will not be propagated further up the parent widget chain. + The state of the keyboard modifier keys can be found by calling the - \l{QInputEvent::modifiers()}{modifiers()} function, inhertied from + \l{QInputEvent::modifiers()}{modifiers()} function, inherited from QInputEvent. The functions pos(), x(), and y() give the cursor position @@ -663,8 +674,9 @@ QWheelEvent::QWheelEvent(const QPoint &pos, const QPoint& globalPos, int delta, The QWidget::setEnable() function can be used to enable or disable mouse and keyboard events for a widget. - The event handlers QWidget::keyPressEvent() and - QWidget::keyReleaseEvent() receive key events. + The event handlers QWidget::keyPressEvent(), QWidget::keyReleaseEvent(), + QGraphicsItem::keyPressEvent() and QGraphicsItem::keyReleaseEvent() + receive key events. \sa QFocusEvent, QWidget::grabKeyboard() */ @@ -861,6 +873,17 @@ bool QKeyEvent::matches(QKeySequence::StandardKey matchKey) const uint searchkey = (modifiers() | key()) & ~(Qt::KeypadModifier); //The keypad modifier should not make a difference uint platform = QApplicationPrivate::currentPlatform(); +#ifdef Q_WS_MAC + if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { + uint oldSearchKey = searchkey; + searchkey &= ~(Qt::ControlModifier | Qt::MetaModifier); + if (oldSearchKey & Qt::ControlModifier) + searchkey |= Qt::MetaModifier; + if (oldSearchKey & Qt::MetaModifier) + searchkey |= Qt::ControlModifier; + } +#endif + uint N = QKeySequencePrivate::numberOfKeyBindings; int first = 0; int last = N - 1; @@ -969,8 +992,9 @@ bool QKeyEvent::matches(QKeySequence::StandardKey matchKey) const The reason for a particular focus event is returned by reason() in the appropriate event handler. - The event handlers QWidget::focusInEvent() and - QWidget::focusOutEvent() receive focus events. + The event handlers QWidget::focusInEvent(), + QWidget::focusOutEvent(), QGraphicsItem::focusInEvent and + QGraphicsItem::focusOutEvent() receive focus events. \sa QWidget::setFocus(), QWidget::setFocusPolicy(), {Keyboard Focus} */ @@ -1056,8 +1080,17 @@ Qt::FocusReason QFocusEvent::reason() const rect() that is the bounding rectangle of that region. Both are provided because many widgets can't make much use of region(), and rect() can be much faster than region().boundingRect(). + + \section1 Automatic Clipping + Painting is clipped to region() during the processing of a paint - event. + event. This clipping is performed by Qt's paint system and is + independent of any clipping that may be applied to a QPainter used to + draw on the paint device. + + As a result, the value returned by QPainter::clipRegion() on + a newly-constructed QPainter will not reflect the clip region that is + used by the paint system. \sa QPainter, QWidget::update(), QWidget::repaint(), QWidget::paintEvent() @@ -1588,12 +1621,14 @@ Qt::ButtonState QContextMenuEvent::state() const string is controlled by the widget only). The AttributeType enum describes the different attributes that can be set. - A class implementing QWidget::inputMethodEvent() should at least - understand and honor the \l TextFormat and \l Cursor attributes. + A class implementing QWidget::inputMethodEvent() or + QGraphicsItem::inputMethodEvent() should at least understand and + honor the \l TextFormat and \l Cursor attributes. Since input methods need to be able to query certain properties - from the widget, the widget must also implement - QWidget::inputMethodQuery(). + from the widget or graphics item, subclasses must also implement + QWidget::inputMethodQuery() and QGraphicsItem::inputMethodQuery(), + respectively. When receiving an input method event, the text widget has to performs the following steps: @@ -1665,6 +1700,17 @@ Qt::ButtonState QContextMenuEvent::state() const several are specified for any character in the string the behaviour is undefined. + \value Selection + If set, the edit cursor should be moved to the specified position + in the editor text contents. In contrast with \c Cursor, this + attribute does not work on the preedit text, but on the surrounding + text. The cursor will be moved after the commit string has been + committed, and the preedit string will be located at the new edit + position. + The start position specifies the new position and the length + variable can be used to set a selection starting from that point. + The value is unused. + \sa Attribute */ @@ -3070,7 +3116,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e) { << ", " << me->button() << ", " << hex << (int)me->buttons() << ", " << hex << (int)me->modifiers() - << ")"; + << ')'; } return dbg.space(); @@ -3091,7 +3137,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e) { #ifndef QT_NO_WHEELEVENT case QEvent::Wheel: dbg.nospace() << "QWheelEvent(" << static_cast<const QWheelEvent *>(e)->delta() - << ")"; + << ')'; return dbg.space(); #endif case QEvent::KeyPress: @@ -3117,7 +3163,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e) { << ", \"" << ke->text() << "\", " << ke->isAutoRepeat() << ", " << ke->count() - << ")"; + << ')'; } return dbg.space(); case QEvent::FocusIn: @@ -3507,4 +3553,637 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) #endif +/*! + \class QTouchEvent + \brief The QTouchEvent class contains parameters that describe a touch event. + \since 4.6 + \ingroup events + + \section1 Enabling Touch Events + + Touch events occur when pressing, releasing, or moving one or more touch points on a touch + device (such as a touch-screen or track-pad). To receive touch events, widgets have to have the + Qt::WA_AcceptTouchEvents attribute set and graphics items need to have the + \l{QGraphicsItem::setAcceptTouchEvents()}{acceptTouchEvents} attribute set to true. + + When using QAbstractScrollArea based widgets, you should enabled the Qt::WA_AcceptTouchEvents + attribute on the scroll area's \l{QAbstractScrollArea::viewport()}{viewport}. + + Similarly to QMouseEvent, Qt automatically grabs each touch point on the first press inside a + widget, and the widget will receive all updates for the touch point until it is released. + Note that it is possible for a widget to receive events for multiple touch points, and that + multiple widgets may be receiving touch events at the same time. + + \section1 Event Handling + + All touch events are of type QEvent::TouchBegin, QEvent::TouchUpdate, or QEvent::TouchEnd. + Reimplement QWidget::event() or QAbstractScrollArea::viewportEvent() for widgets and + QGraphicsItem::sceneEvent() for items in a graphics view to receive touch events. + + The QEvent::TouchUpdate and QEvent::TouchEnd events are sent to the widget or item that + accepted the QEvent::TouchBegin event. If the QEvent::TouchBegin event is not accepted and not + filtered by an event filter, then no further touch events are sent until the next + QEvent::TouchBegin. + + The touchPoints() function returns a list of all touch points contained in the event. + Information about each touch point can be retrieved using the QTouchEvent::TouchPoint class. + The Qt::TouchPointState enum describes the different states that a touch point may have. + + \section1 Event Delivery and Propagation + + By default, QWidget::event() translates the first non-primary touch point in a QTouchEvent into + a QMouseEvent. This makes it possible to enable touch events on existing widgets that do not + normally handle QTouchEvent. See below for information on some special considerations needed + when doing this. + + QEvent::TouchBegin is the first touch event sent to a widget. The QEvent::TouchBegin event + contains a special accept flag that indicates whether the receiver wants the event. By default, + the event is accepted. You should call ignore() if the touch event is not handled by your + widget. The QEvent::TouchBegin event is propagated up the parent widget chain until a widget + accepts it with accept(), or an event filter consumes it. For QGraphicsItems, the + QEvent::TouchBegin event is propagated to items under the mouse (similar to mouse event + propagation for QGraphicsItems). + + \section1 Touch Point Grouping + + As mentioned above, it is possible that several widgets can be receiving QTouchEvents at the + same time. However, Qt makes sure to never send duplicate QEvent::TouchBegin events to the same + widget, which could theoretically happen during propagation if, for example, the user touched 2 + separate widgets in a QGroupBox and both widgets ignored the QEvent::TouchBegin event. + + To avoid this, Qt will group new touch points together using the following rules: + + \list + + \i When the first touch point is detected, the destination widget is determined firstly by the + location on screen and secondly by the propagation rules. + + \i When additional touch points are detected, Qt first looks to see if there are any active + touch points on any ancestor or descendent of the widget under the new touch point. If there + are, the new touch point is grouped with the first, and the new touch point will be sent in a + single QTouchEvent to the widget that handled the first touch point. (The widget under the new + touch point will not receive an event). + + \endlist + + This makes it possible for sibling widgets to handle touch events independently while making + sure that the sequence of QTouchEvents is always correct. + + \section1 Mouse Events and the Primary Touch Point + + QTouchEvent delivery is independent from that of QMouseEvent. On some windowing systems, mouse + events are also sent for the \l{QTouchEvent::TouchPoint::isPrimary()}{primary touch point}. + This means it is possible for your widget to receive both QTouchEvent and QMouseEvent for the + same user interaction point. You can use the QTouchEvent::TouchPoint::isPrimary() function to + identify the primary touch point. + + Note that on some systems, it is possible to receive touch events without a primary touch + point. All this means is that there will be no mouse event generated for the touch points in + the QTouchEvent. + + \section1 Caveats + + \list + + \i As mentioned above, enabling touch events means multiple widgets can be receiving touch + events simultaneously. Combined with the default QWidget::event() handling for QTouchEvents, + this gives you great flexibility in designing multi-touch user interfaces. Be aware of the + implications. For example, is is possible that the user is moving a QSlider with one finger and + pressing a QPushButton with another. The signals emitted by these widgets will be + interleaved. + + \i Recursion into the event loop using one of the exec() methods (e.g., QDialog::exec() or + QMenu::exec()) in a QTouchEvent event handler is not supported. Since there are multiple event + recipients, unexpected recursion may cause problems, including but not limited to lost events + and unexpected infinite recursion. + + \i QTouchEvents are not affected by a \l{QWidget::grabMouse()}{mouse grab} or an + \l{QApplication::activePopupWidget()}{active pop-up widget}. The behavior of QTouchEvents is + undefined when opening a pop-up or grabbing the mouse while there are multiple active touch + points. + + \endlist + + \sa QTouchEvent::TouchPoint, Qt::TouchPointState, Qt::WA_AcceptTouchEvents, + QGraphicsItem::acceptTouchEvents() +*/ + +/*! \enum Qt::TouchPointState + \since 4.6 + + This enum represents the state of a touch point at the time the + QTouchEvent occurred. + + \value TouchPointPressed The touch point is now pressed. + \value TouchPointMoved The touch point moved. + \value TouchPointStationary The touch point did not move. + \value TouchPointReleased The touch point was released. + + \omitvalue TouchPointStateMask + \omitvalue TouchPointPrimary +*/ + +/*! \enum QTouchEvent::DeviceType + + This enum represents the type of device that generated a QTouchEvent. + + \value TouchScreen In this type of device, the touch surface and display are integrated. This + means the surface and display typically have the same size, such that there + is a direct relationship between the touch points' physical positions and the + coordinate reported by QTouchEvent::TouchPoint. As a result, Qt allows the + user to interact directly with multiple QWidgets and QGraphicsItems at the + same time. + + \value TouchPad In this type of device, the touch surface is separate from the display. There + is not a direct relationship between the physical touch location and the + on-screen coordinates. Instead, they are calculated relative to the current + mouse position, and the user must use the touch-pad to move this reference + point. Unlike touch-screens, Qt allows users to only interact with a single + QWidget or QGraphicsItem at a time. +*/ + +/*! + Constructs a QTouchEvent with the given \a eventType, \a deviceType, and \a touchPoints. + The \a touchPointStates and \a modifiers are the current touch point states and keyboard + modifiers at the time of the event. +*/ +QTouchEvent::QTouchEvent(QEvent::Type eventType, + QTouchEvent::DeviceType deviceType, + Qt::KeyboardModifiers modifiers, + Qt::TouchPointStates touchPointStates, + const QList<QTouchEvent::TouchPoint> &touchPoints) + : QInputEvent(eventType, modifiers), + _widget(0), + _deviceType(deviceType), + _touchPointStates(touchPointStates), + _touchPoints(touchPoints) +{ } + +/*! + Destroys the QTouchEvent. +*/ +QTouchEvent::~QTouchEvent() +{ } + +/*! \fn QWidget *QTouchEvent::widget() const + + Returns the widget on which the event occurred. +*/ + + +/*! \fn Qt::TouchPointStates QTouchEvent::touchPointStates() const + + Returns a bitwise OR of all the touch point states for this event. +*/ + +/*! \fn const QList<QTouchEvent::TouchPoint> &QTouchEvent::touchPoints() const + + Returns the list of touch points contained in the touch event. +*/ + +/*! \fn QTouchEvent::DeviceType QTouchEvent::deviceType() const + + Returns the touch device Type, which is of type \l {QTouchEvent::DeviceType} {DeviceType}. +*/ + +/*! \fn void QTouchEvent::setWidget(QWidget *widget) + + \internal + + Sets the widget for this event. +*/ + +/*! \fn void QTouchEvent::setTouchPointStates(Qt::TouchPointStates touchPointStates) + + \internal + + Sets a bitwise OR of all the touch point states for this event. +*/ + +/*! \fn void QTouchEvent::setTouchPoints(const QList<QTouchEvent::TouchPoint> &touchPoints) + + \internal + + Sets the list of touch points for this event. +*/ + +/*! \fn void QTouchEvent::setDeviceType(DeviceType deviceType) + + \internal + + Sets the device type to \a deviceType, which is of type \l {QTouchEvent::DeviceType} + {DeviceType}. +*/ + +/*! \class QTouchEvent::TouchPoint + \brief The QTouchEvent::TouchPoint class provides information about a touch point in a QTouchEvent. + \since 4.6 +*/ + +/*! \internal + + Constructs a QTouchEvent::TouchPoint for use in a QTouchEvent. +*/ +QTouchEvent::TouchPoint::TouchPoint(int id) + : d(new QTouchEventTouchPointPrivate(id)) +{ } + +/*! \internal + + Constructs a copy of \a other. +*/ +QTouchEvent::TouchPoint::TouchPoint(const QTouchEvent::TouchPoint &other) + : d(other.d) +{ + d->ref.ref(); +} + +/*! \internal + + Destroys the QTouchEvent::TouchPoint. +*/ +QTouchEvent::TouchPoint::~TouchPoint() +{ + if (!d->ref.deref()) + delete d; +} + +/*! + Returns the id number of this touch point. + + Id numbers are globally sequential, starting at zero, meaning the + first touch point in the application has id 0, the second has id 1, + and so on. +*/ +int QTouchEvent::TouchPoint::id() const +{ + return d->id; +} + +/*! + Returns the current state of this touch point. +*/ +Qt::TouchPointState QTouchEvent::TouchPoint::state() const +{ + return Qt::TouchPointState(int(d->state) & Qt::TouchPointStateMask); +} + +/*! + Returns true if this touch point is the primary touch point. The primary touch point is the + point for which the windowing system generates mouse events. +*/ +bool QTouchEvent::TouchPoint::isPrimary() const +{ + return (d->state & Qt::TouchPointPrimary) != 0; +} + +/*! + Returns the position of this touch point, relative to the widget + or QGraphicsItem that received the event. + + \sa startPos(), lastPos(), screenPos(), scenePos(), normalizedPos() +*/ +QPointF QTouchEvent::TouchPoint::pos() const +{ + return d->rect.center(); +} + +/*! + Returns the scene position of this touch point. + + The scene position is the position in QGraphicsScene coordinates + if the QTouchEvent is handled by a QGraphicsItem::touchEvent() + reimplementation, and identical to the screen position for + widgets. + + \sa startScenePos(), lastScenePos(), pos() +*/ +QPointF QTouchEvent::TouchPoint::scenePos() const +{ + return d->sceneRect.center(); +} + +/*! + Returns the screen position of this touch point. + + \sa startScreenPos(), lastScreenPos(), pos() +*/ +QPointF QTouchEvent::TouchPoint::screenPos() const +{ + return d->screenRect.center(); +} + +/*! + Returns the normalized position of this touch point. + + The coordinates are normalized to the size of the touch device, + i.e. (0,0) is the top-left corner and (1,1) is the bottom-right corner. + + \sa startNormalizedPos(), lastNormalizedPos(), pos() +*/ +QPointF QTouchEvent::TouchPoint::normalizedPos() const +{ + return d->normalizedPos; +} + +/*! + Returns the starting position of this touch point, relative to the + widget or QGraphicsItem that received the event. + + \sa pos(), lastPos() +*/ +QPointF QTouchEvent::TouchPoint::startPos() const +{ + return d->startPos; +} + +/*! + Returns the starting scene position of this touch point. + + The scene position is the position in QGraphicsScene coordinates + if the QTouchEvent is handled by a QGraphicsItem::touchEvent() + reimplementation, and identical to the screen position for + widgets. + + \sa scenePos(), lastScenePos() +*/ +QPointF QTouchEvent::TouchPoint::startScenePos() const +{ + return d->startScenePos; +} + +/*! + Returns the starting screen position of this touch point. + + \sa screenPos(), lastScreenPos() +*/ +QPointF QTouchEvent::TouchPoint::startScreenPos() const +{ + return d->startScreenPos; +} + +/*! + Returns the normalized starting position of this touch point. + + The coordinates are normalized to the size of the touch device, + i.e. (0,0) is the top-left corner and (1,1) is the bottom-right corner. + + \sa normalizedPos(), lastNormalizedPos() +*/ +QPointF QTouchEvent::TouchPoint::startNormalizedPos() const +{ + return d->startNormalizedPos; +} + +/*! + Returns the position of this touch point from the previous touch + event, relative to the widget or QGraphicsItem that received the event. + + \sa pos(), startPos() +*/ +QPointF QTouchEvent::TouchPoint::lastPos() const +{ + return d->lastPos; +} + +/*! + Returns the scene position of this touch point from the previous + touch event. + + The scene position is the position in QGraphicsScene coordinates + if the QTouchEvent is handled by a QGraphicsItem::touchEvent() + reimplementation, and identical to the screen position for + widgets. + + \sa scenePos(), startScenePos() +*/ +QPointF QTouchEvent::TouchPoint::lastScenePos() const +{ + return d->lastScenePos; +} + +/*! + Returns the screen position of this touch point from the previous + touch event. + + \sa screenPos(), startScreenPos() +*/ +QPointF QTouchEvent::TouchPoint::lastScreenPos() const +{ + return d->lastScreenPos; +} + +/*! + Returns the normalized position of this touch point from the + previous touch event. + + The coordinates are normalized to the size of the touch device, + i.e. (0,0) is the top-left corner and (1,1) is the bottom-right corner. + + \sa normalizedPos(), startNormalizedPos() +*/ +QPointF QTouchEvent::TouchPoint::lastNormalizedPos() const +{ + return d->lastNormalizedPos; +} + +/*! + Returns the rect for this touch point, relative to the widget + or QGraphicsItem that received the event. The rect is centered + around the point returned by pos(). + + \note This function returns an empty rect if the device does not report touch point sizes. +*/ +QRectF QTouchEvent::TouchPoint::rect() const +{ + return d->rect; +} + +/*! + Returns the rect for this touch point in scene coordinates. + + \note This function returns an empty rect if the device does not report touch point sizes. + + \sa scenePos(), rect() +*/ +QRectF QTouchEvent::TouchPoint::sceneRect() const +{ + return d->sceneRect; +} + +/*! + Returns the rect for this touch point in screen coordinates. + + \note This function returns an empty rect if the device does not report touch point sizes. + + \sa screenPos(), rect() +*/ +QRectF QTouchEvent::TouchPoint::screenRect() const +{ + return d->screenRect; +} + +/*! + Returns the pressure of this touch point. The return value is in + the range 0.0 to 1.0. +*/ +qreal QTouchEvent::TouchPoint::pressure() const +{ + return d->pressure; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setId(int id) +{ + if (d->ref != 1) + d = d->detach(); + d->id = id; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setState(Qt::TouchPointStates state) +{ + if (d->ref != 1) + d = d->detach(); + d->state = state; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setPos(const QPointF &pos) +{ + if (d->ref != 1) + d = d->detach(); + d->rect.moveCenter(pos); +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setScenePos(const QPointF &scenePos) +{ + if (d->ref != 1) + d = d->detach(); + d->sceneRect.moveCenter(scenePos); +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setScreenPos(const QPointF &screenPos) +{ + if (d->ref != 1) + d = d->detach(); + d->screenRect.moveCenter(screenPos); +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setNormalizedPos(const QPointF &normalizedPos) +{ + if (d->ref != 1) + d = d->detach(); + d->normalizedPos = normalizedPos; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setStartPos(const QPointF &startPos) +{ + if (d->ref != 1) + d = d->detach(); + d->startPos = startPos; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setStartScenePos(const QPointF &startScenePos) +{ + if (d->ref != 1) + d = d->detach(); + d->startScenePos = startScenePos; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setStartScreenPos(const QPointF &startScreenPos) +{ + if (d->ref != 1) + d = d->detach(); + d->startScreenPos = startScreenPos; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setStartNormalizedPos(const QPointF &startNormalizedPos) +{ + if (d->ref != 1) + d = d->detach(); + d->startNormalizedPos = startNormalizedPos; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setLastPos(const QPointF &lastPos) +{ + if (d->ref != 1) + d = d->detach(); + d->lastPos = lastPos; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setLastScenePos(const QPointF &lastScenePos) +{ + if (d->ref != 1) + d = d->detach(); + d->lastScenePos = lastScenePos; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setLastScreenPos(const QPointF &lastScreenPos) +{ + if (d->ref != 1) + d = d->detach(); + d->lastScreenPos = lastScreenPos; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setLastNormalizedPos(const QPointF &lastNormalizedPos) +{ + if (d->ref != 1) + d = d->detach(); + d->lastNormalizedPos = lastNormalizedPos; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setRect(const QRectF &rect) +{ + if (d->ref != 1) + d = d->detach(); + d->rect = rect; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setSceneRect(const QRectF &sceneRect) +{ + if (d->ref != 1) + d = d->detach(); + d->sceneRect = sceneRect; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setScreenRect(const QRectF &screenRect) +{ + if (d->ref != 1) + d = d->detach(); + d->screenRect = screenRect; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setPressure(qreal pressure) +{ + if (d->ref != 1) + d = d->detach(); + d->pressure = pressure; +} + +/*! \internal */ +QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::TouchPoint &other) +{ + other.d->ref.ref(); + if (!d->ref.deref()) + delete d; + d = other.d; + return *this; +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 7dc14cc..5f3b29b 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -52,6 +52,8 @@ #include <QtGui/qmime.h> #include <QtGui/qdrag.h> #include <QtCore/qvariant.h> +#include <QtCore/qmap.h> +#include <QtCore/qset.h> QT_BEGIN_HEADER @@ -60,6 +62,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) class QAction; +class QGesture; class Q_GUI_EXPORT QInputEvent : public QEvent { @@ -67,6 +70,7 @@ public: QInputEvent(Type type, Qt::KeyboardModifiers modifiers = Qt::NoModifier); ~QInputEvent(); inline Qt::KeyboardModifiers modifiers() const { return modState; } + inline void setModifiers(Qt::KeyboardModifiers modifiers) { modState = modifiers; } protected: Qt::KeyboardModifiers modState; }; @@ -241,7 +245,7 @@ public: inline QT3_SUPPORT_CONSTRUCTOR QKeyEvent(Type type, int key, int /*ascii*/, int modifiers, const QString& text = QString(), bool autorep = false, ushort count = 1) - : QInputEvent(type, (Qt::KeyboardModifiers)(modifiers & (int)Qt::KeyButtonMask)), txt(text), k(key), + : QInputEvent(type, Qt::KeyboardModifiers(modifiers & (int)Qt::KeyButtonMask)), txt(text), k(key), c(count), autor(autorep) { if (key >= Qt::Key_Back && key <= Qt::Key_MediaLast) @@ -424,7 +428,8 @@ public: TextFormat, Cursor, Language, - Ruby + Ruby, + Selection }; class Attribute { public: @@ -719,6 +724,101 @@ inline bool operator==(QKeyEvent *e, QKeySequence::StandardKey key){return (e ? inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);} #endif // QT_NO_SHORTCUT +class QTouchEventTouchPointPrivate; +class Q_GUI_EXPORT QTouchEvent : public QInputEvent +{ +public: + class Q_GUI_EXPORT TouchPoint + { + public: + TouchPoint(int id = -1); + TouchPoint(const QTouchEvent::TouchPoint &other); + ~TouchPoint(); + + int id() const; + + Qt::TouchPointState state() const; + bool isPrimary() const; + + QPointF pos() const; + QPointF startPos() const; + QPointF lastPos() const; + + QPointF scenePos() const; + QPointF startScenePos() const; + QPointF lastScenePos() const; + + QPointF screenPos() const; + QPointF startScreenPos() const; + QPointF lastScreenPos() const; + + QPointF normalizedPos() const; + QPointF startNormalizedPos() const; + QPointF lastNormalizedPos() const; + + QRectF rect() const; + QRectF sceneRect() const; + QRectF screenRect() const; + + qreal pressure() const; + + // internal + void setId(int id); + void setState(Qt::TouchPointStates state); + void setPos(const QPointF &pos); + void setScenePos(const QPointF &scenePos); + void setScreenPos(const QPointF &screenPos); + void setNormalizedPos(const QPointF &normalizedPos); + void setStartPos(const QPointF &startPos); + void setStartScenePos(const QPointF &startScenePos); + void setStartScreenPos(const QPointF &startScreenPos); + void setStartNormalizedPos(const QPointF &startNormalizedPos); + void setLastPos(const QPointF &lastPos); + void setLastScenePos(const QPointF &lastScenePos); + void setLastScreenPos(const QPointF &lastScreenPos); + void setLastNormalizedPos(const QPointF &lastNormalizedPos); + void setRect(const QRectF &rect); + void setSceneRect(const QRectF &sceneRect); + void setScreenRect(const QRectF &screenRect); + void setPressure(qreal pressure); + QTouchEvent::TouchPoint &operator=(const QTouchEvent::TouchPoint &other); + + private: + QTouchEventTouchPointPrivate *d; + }; + + enum DeviceType { + TouchScreen, + TouchPad + }; + + QTouchEvent(QEvent::Type eventType, + QTouchEvent::DeviceType deviceType = TouchScreen, + Qt::KeyboardModifiers modifiers = Qt::NoModifier, + Qt::TouchPointStates touchPointStates = 0, + const QList<QTouchEvent::TouchPoint> &touchPoints = QList<QTouchEvent::TouchPoint>()); + ~QTouchEvent(); + + inline QWidget *widget() const { return _widget; } + inline QTouchEvent::DeviceType deviceType() const { return _deviceType; } + inline Qt::TouchPointStates touchPointStates() const { return _touchPointStates; } + inline const QList<QTouchEvent::TouchPoint> &touchPoints() const { return _touchPoints; } + + // internal + inline void setWidget(QWidget *widget) { _widget = widget; } + inline void setDeviceType(DeviceType deviceType) { _deviceType = deviceType; } + inline void setTouchPointStates(Qt::TouchPointStates touchPointStates) { _touchPointStates = touchPointStates; } + inline void setTouchPoints(const QList<QTouchEvent::TouchPoint> &touchPoints) { _touchPoints = touchPoints; } + +protected: + QWidget *_widget; + QTouchEvent::DeviceType _deviceType; + Qt::TouchPointStates _touchPointStates; + QList<QTouchEvent::TouchPoint> _touchPoints; + + friend class QApplicationPrivate; +}; + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index fe5ebdd..7cfa36e 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -43,6 +43,7 @@ #define QEVENT_P_H #include <QtCore/qglobal.h> +#include <QtGui/qevent.h> QT_BEGIN_NAMESPACE @@ -58,7 +59,7 @@ QT_BEGIN_NAMESPACE // // ### Qt 5: remove -class Q_GUI_EXPORT QKeyEventEx : public QKeyEvent +class QKeyEventEx : public QKeyEvent { public: QKeyEventEx(Type type, int key, Qt::KeyboardModifiers modifiers, @@ -76,7 +77,7 @@ protected: }; // ### Qt 5: remove -class Q_GUI_EXPORT QMouseEventEx : public QMouseEvent +class QMouseEventEx : public QMouseEvent { public: QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos, @@ -89,6 +90,66 @@ protected: friend class QMouseEvent; }; +class QTouchEventTouchPointPrivate +{ +public: + inline QTouchEventTouchPointPrivate(int id) + : ref(1), + id(id), + state(Qt::TouchPointReleased), + pressure(qreal(-1.)) + { } + + inline QTouchEventTouchPointPrivate *detach() + { + QTouchEventTouchPointPrivate *d = new QTouchEventTouchPointPrivate(*this); + d->ref = 1; + if (!this->ref.deref()) + delete this; + return d; + } + + QAtomicInt ref; + int id; + Qt::TouchPointStates state; + QRectF rect, sceneRect, screenRect; + QPointF normalizedPos, + startPos, startScenePos, startScreenPos, startNormalizedPos, + lastPos, lastScenePos, lastScreenPos, lastNormalizedPos; + qreal pressure; +}; + +class QNativeGestureEvent : public QEvent +{ +public: + enum Type { + None, + GestureBegin, + GestureEnd, + Pan, + Zoom, + Rotate, + Swipe + }; + + QNativeGestureEvent() + : QEvent(QEvent::NativeGesture), gestureType(None), percentage(0) +#ifdef Q_WS_WIN + , sequenceId(0), argument(0) +#endif + { + } + + Type gestureType; + float percentage; + QPoint position; + float angle; +#ifdef Q_WS_WIN + ulong sequenceId; + quint64 argument; +#endif +}; + QT_END_NAMESPACE #endif // QEVENT_P_H diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm index 25bcb32..1667da8 100644 --- a/src/gui/kernel/qeventdispatcher_mac.mm +++ b/src/gui/kernel/qeventdispatcher_mac.mm @@ -497,6 +497,40 @@ static bool IsMouseOrKeyEvent( NSEvent* event ) } #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); @@ -506,16 +540,6 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags) wakeUp(); emit awake(); -#ifndef QT_MAC_NO_QUICKDRAW - if(!qt_mac_safe_pdev) { //create an empty widget and this can be used for a port anytime - QWidget *tlw = new QWidget; - tlw->setAttribute(Qt::WA_DeleteOnClose); - tlw->setObjectName(QLatin1String("empty_widget")); - tlw->hide(); - qt_mac_safe_pdev = tlw; - } -#endif - bool retVal = false; forever { if (d->interrupt) @@ -525,55 +549,42 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags) QMacCocoaAutoReleasePool pool; NSEvent* event = 0; - if (flags & QEventLoop::DialogExec || flags & QEventLoop::EventLoopExec) { - // The point of the CocoaRequestModal event is to make sure that a - // non-execed app modal window recurses into it's own dialog exec - // once cocoa is spinning the event loop for us (e.g on top of [NSApp run]). - // We expect only one event to notify us about this, regardless of how many - // widgets that are waiting to be modal. So we remove all other pending - // events, if any. And since cocoa will now take over event processing for us, - // we allow new app modal widgets to recurse on top of us, hence the release of - // the block: - QBoolBlocker block(d->blockCocoaRequestModal, false); - QCoreApplication::removePostedEvents(qApp, QEvent::CocoaRequestModal); - - if (NSModalSession session = d->activeModalSession()) - while ([NSApp runModalSession:session] == NSRunContinuesResponse) { - // runModalSession will not wait for events, so we do it - // ourselves (otherwise we would spend 100% CPU inside this loop): - event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantFuture] inMode:NSModalPanelRunLoopMode dequeue:YES]; - if (event) - [NSApp postEvent:event atStart:YES]; - } - else + // If Qt is used as a plugin, or just added into a native cocoa + // application, we should not run or stop NSApplication; + // This will be done from outside Qt. + // And if processEvents is called manually (rather than from QEventLoop), we + // cannot enter a tight loop and block the call, but instead return after one flush: + bool canExec_3rdParty = d->nsAppRunCalledByQt || ![NSApp isRunning]; + bool canExec_Qt = 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 also allow us + // to use [NSApp run], which is the recommended way of running applications + // in cocoa. [NSApp run] should be called at least once for any cocoa app. + if (NSModalSession session = d->currentModalSession()) { + QBoolBlocker execGuard(d->currentExecIsNSAppRun, false); + while (!d->interrupt && [NSApp runModalSession:session] == NSRunContinuesResponse) + qt_mac_waitForMoreModalSessionEvents(); + } else { + d->nsAppRunCalledByQt = true; + QBoolBlocker execGuard(d->currentExecIsNSAppRun, true); [NSApp run]; - - d->rebuildModalSessionStack(false); + } retVal = true; } else do { - // Since we now are going to spin the event loop just _one_ round - // we need to block all incoming CocoaRequestModal events to ensure - // that we don't recurse into a new exec-ing event loop while doing - // so (and as such, 'hang' the thread inside the recursion): - QBoolBlocker block(d->blockCocoaRequestModal, true); + // INVARIANT: We cannot block the thread (and run in a tight loop). + // Instead we will process all current pending events and return. bool mustRelease = false; if (!(flags & QEventLoop::ExcludeUserInputEvents) && !d->queuedUserInputEvents.isEmpty()) { - // process a pending user input event + // Process a pending user input event mustRelease = true; event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst()); } else { - if (NSModalSession session = d->activeModalSession()) { - // There's s a modal widget showing, run it's session: - if (flags & QEventLoop::WaitForMoreEvents) { - // Wait for at least one event - // before spinning the session: - event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantFuture] inMode:NSModalPanelRunLoopMode dequeue:YES]; - if (event) - [NSApp postEvent:event atStart:YES]; - } + if (NSModalSession session = d->currentModalSession()) { + if (flags & QEventLoop::WaitForMoreEvents) + qt_mac_waitForMoreModalSessionEvents(); [NSApp runModalSession:session]; retVal = true; break; @@ -644,41 +655,35 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags) && (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 - // (WaitForMoreEvents). So we wait on the window server: -#ifndef QT_MAC_USE_COCOA - while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e20, true) == kCFRunLoopRunTimedOut); -#else - QMacCocoaAutoReleasePool pool; - NSEvent *manualEvent = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantFuture] inMode:NSDefaultRunLoopMode - dequeue:YES]; - if (manualEvent) - [NSApp sendEvent:manualEvent]; -#endif + // 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: + // Done with event processing for now. + // Leave the function: break; } } - // Because pending deffered-delete events are only sendt after - // returning from the loop level they were posted in, we schedule - // an extra wakup to force the _current_ run loop to process them (in - // case the application stands idle waiting for the delete event): - wakeUp(); +#ifdef QT_MAC_USE_COCOA + // In case we _now_ process events using [NSApp run], we need to stop it to + // ensure that: + // 1. the QEventLoop that called us is still executing, or + // 2. we have a modal session that needs to be spun instead. + // In case this is a plain call to processEvents (perhaps from a loop) + // from the application (rather than from a QEventLoop), we delay the + // interrupting until we/ actually enter a lower loop level (hence the + // deffered delete of the object below): + QtMacInterruptDispatcherHelp::interruptLater(); +#endif - if (d->interrupt){ - // We restart NSApplication by first stopping it, and then call 'run' - // again (NSApplication is actually already stopped, hence the need - // for a restart, but calling stop again will also make the call - // return from the current recursion). When the call returns to - // QEventLoop (mind, not from this recursion, but from the one we're - // about to stop), it will just call QEventDispatcherMac::processEvents() - // again. + if (d->interrupt) { + // We should continue to leave all recursion to processEvents until + // processEvents is called again (e.g. from a QEventLoop that + // was not yet told to quit: interrupt(); } + return retVal; } @@ -710,104 +715,169 @@ bool QEventDispatcherMacPrivate::blockSendPostedEvents = false; #ifdef QT_MAC_USE_COCOA QStack<QCocoaModalSessionInfo> QEventDispatcherMacPrivate::cocoaModalSessionStack; -bool QEventDispatcherMacPrivate::blockCocoaRequestModal = false; +bool QEventDispatcherMacPrivate::currentExecIsNSAppRun = false; +bool QEventDispatcherMacPrivate::nsAppRunCalledByQt = false; +NSModalSession QEventDispatcherMacPrivate::currentModalSessionCached = 0; -static void qt_mac_setChildDialogsResponsive(QWidget *widget, bool responsive) +int QEventDispatcherMacPrivate::activeModalSessionCount() { + // Returns the number of modal sessions created + // (and not just pushed onto the stack, pending to be created) + int count = 0; + for (int i=cocoaModalSessionStack.size()-1; i>=0; --i) { + QCocoaModalSessionInfo &info = cocoaModalSessionStack[i]; + if (info.session) + ++count; + } + return count; +} + +void QEventDispatcherMacPrivate::temporarilyStopAllModalSessions() +{ + // Stop all created modal session, and as such, make then + // pending again. The next call to currentModalSession will + // recreate the session on top again: + int stackSize = cocoaModalSessionStack.size(); + for (int i=stackSize-1; i>=0; --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; + + // Since this code will end up calling our Qt event handler + // (also from beginModalSessionForWindow), we need to block + // that to avoid side effects of events beeing delivered: + QBoolBlocker block(blockSendPostedEvents, true); + + if (![NSApp isRunning]) { + // Sadly, we need to introduce this little event flush + // to stop dialogs from blinking/poping in front if a + // modal session restart was needed: + while (NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:nil + inMode:NSDefaultRunLoopMode + dequeue: YES]) { + qt_mac_send_event(0, event, 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; + info.session = [NSApp beginModalSessionForWindow:window]; + } + currentModalSessionCached = info.session; + } + + 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:responsive]; - if (responsive && dialogs[i]->isVisible()){ + [static_cast<NSPanel *>(window) setWorksWhenModal:worksWhenModal]; + if (worksWhenModal && dialogs[i]->isVisible()){ [window orderFront:window]; } } } } -NSModalSession QEventDispatcherMacPrivate::activeModalSession() +void QEventDispatcherMacPrivate::updateChildrenWorksWhenModal() { - // Create (if needed) and return the modal session - // for the top-most modal dialog, if any: - if (cocoaModalSessionStack.isEmpty()) - return 0; - QCocoaModalSessionInfo &info = cocoaModalSessionStack.last(); - if (!info.widget) - return 0; - if (info.widget->testAttribute(Qt::WA_DontShowOnScreen)){ - // INVARIANT: We have a modal widget, but it's not visible on screen. - // This will e.g. be true for native dialogs. Make the dialog children - // of the previous modal dialog unresponsive, so that the current dialog - // (native or not) is the only reponsive dialog on screen: - int size = cocoaModalSessionStack.size(); + // Make the dialog children of the widget + // active. And make the dialog children of + // the previous modal dialog unactive again: + 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) - qt_mac_setChildDialogsResponsive(prevModal, false); + setChildrenWorksWhenModal(prevModal, false); } - return 0; } +} - if (!info.session) { - QMacCocoaAutoReleasePool pool; - NSWindow *window = qt_mac_window_for(info.widget); - if (!window) - return 0; - // 'beginModalSessionForWindow' will give the event loop a spin, and as - // such, deliver Qt events. This might lead to inconsistent behaviour - // (especially if CocoaRequestModal is delivered), so we need to block: - QBoolBlocker block(blockSendPostedEvents, true); - info.session = [NSApp beginModalSessionForWindow:window]; - // Make the dialog children of the current modal dialog - // responsive. And make the dialog children of - // the previous modal dialog unresponsive again: - qt_mac_setChildDialogsResponsive(info.widget, true); - int size = cocoaModalSessionStack.size(); - if (size > 1){ - if (QWidget *prevModal = cocoaModalSessionStack[size-2].widget) - qt_mac_setChildDialogsResponsive(prevModal, false); - } - } - return info.session; +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 endModalSession(). + QCocoaModalSessionInfo info = {widget, 0}; + cocoaModalSessionStack.push(info); + updateChildrenWorksWhenModal(); + currentModalSessionCached = 0; } -void QEventDispatcherMacPrivate::rebuildModalSessionStack(bool pop) +void QEventDispatcherMacPrivate::endModalSession(QWidget *widget) { - // Calling [NSApp stopModal], or [NSApp stop], will stop all modal dialogs - // in one go. So to to not confuse cocoa, we need to stop all our modal - // sessions as well. QMacEventDispatcher will make them modal again - // in the correct order as long as they are left on the cocoaModalSessionStack - // and a CocoaRequestModal is posted: - if (cocoaModalSessionStack.isEmpty()) - return; + // 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; + } - QMacCocoaAutoReleasePool pool; - [NSApp stopModal]; - [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint - modifierFlags:0 timestamp:0. windowNumber:0 context:0 - subtype:SHRT_MAX data1:0 data2:0] atStart:NO]; + // Now we stop, and remove, all sessions marked as pending + // to be stopped on _top_ of the stack, if any: + bool needToInterruptEventDispatcher = false; + bool needToUpdateChildrenWorksWhenModal = false; - for (int i=0; i<cocoaModalSessionStack.size(); ++i){ + for (int i=stackSize-1; i>=0; --i) { QCocoaModalSessionInfo &info = cocoaModalSessionStack[i]; + if (info.widget) + break; + cocoaModalSessionStack.remove(i); + needToUpdateChildrenWorksWhenModal = true; + currentModalSessionCached = 0; if (info.session) { [NSApp endModalSession:info.session]; - info.session = 0; + needToInterruptEventDispatcher = true; } } - if (pop) { - QCocoaModalSessionInfo info = cocoaModalSessionStack.pop(); - if (info.widget) - qt_mac_setChildDialogsResponsive(info.widget, false); - } - - if (!cocoaModalSessionStack.isEmpty()) { - // Since we now have pending modal sessions again, make - // sure that we enter modal for the one on the top later: - qApp->postEvent(qApp, new QEvent(QEvent::CocoaRequestModal)); - } else { - QCoreApplication::removePostedEvents(qApp, QEvent::CocoaRequestModal); - } + if (needToUpdateChildrenWorksWhenModal) + updateChildrenWorksWhenModal(); + if (needToInterruptEventDispatcher) + QEventDispatcherMac::instance()->interrupt(); } #endif @@ -868,27 +938,29 @@ void QEventDispatcherMacPrivate::postedEventsSourcePerformCallback(void *info) } } -#ifdef QT_MAC_USE_COCOA -static void stopNSApp() -{ - QMacCocoaAutoReleasePool pool; - static const short NSAppShouldStopForQt = SHRT_MAX; - [NSApp stop:NSApp]; - [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint - modifierFlags:0 timestamp:0. windowNumber:0 context:0 - subtype:NSAppShouldStopForQt 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 - stopNSApp(); + QMacCocoaAutoReleasePool pool; + // In case we wait for more events inside + // processEvents (or NSApp run), post a dummy to wake it up: + static const short NSAppShouldStopForQt = SHRT_MAX; + [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint + modifierFlags:0 timestamp:0. windowNumber:0 context:0 + subtype:NSAppShouldStopForQt data1:0 data2:0] atStart:NO]; + + if (d->activeModalSessionCount() == 0) { + // We should only stop NSApp if we actually started it (and + // not some 3rd party application, e.g. if we are a plugin). + if (d->nsAppRunCalledByQt) + [NSApp stop:NSApp]; + } #endif } @@ -926,5 +998,52 @@ QEventDispatcherMac::~QEventDispatcherMac() CFRelease(d->waitingObserver); } +///////////////////////////////////////////////////////////////////////////// + +#ifdef QT_MAC_USE_COCOA + +QtMacInterruptDispatcherHelp* QtMacInterruptDispatcherHelp::instance = 0; + +QtMacInterruptDispatcherHelp::QtMacInterruptDispatcherHelp() : cancelled(false) +{ + // This is the whole point of encapsulation this code + // inside a class; we can make the code (inside destructor) + // execute on lower loop level: + deleteLater(); +} + +QtMacInterruptDispatcherHelp::~QtMacInterruptDispatcherHelp() +{ + if (cancelled) + return; + + instance = 0; + + if (QEventDispatcherMacPrivate::currentExecIsNSAppRun) { + int activeCount = QEventDispatcherMacPrivate::activeModalSessionCount(); + if (activeCount > 0) { + // The problem we now have hit: [NSApp stop] will not stop NSApp + // if a session is active; it will stop the session instead. + // So to stop NSApp, we need to temporarily stop all the + // sessions, then stop NSApp, then restart the session on top again. + // We need to do this to ensure that we're not stuck inside + // [NSApp run] when we really should be running a modal session: + QEventDispatcherMacPrivate::temporarilyStopAllModalSessions(); + } + } + // Always interrupt once more in case the modal session stack changed + // while processEvents was called manually from within the application: + QEventDispatcherMac::instance()->interrupt(); +} + +void QtMacInterruptDispatcherHelp::interruptLater() { + if (instance) { + instance->cancelled = true; + delete instance; + } + instance = new QtMacInterruptDispatcherHelp; +} + +#endif QT_END_NAMESPACE diff --git a/src/gui/kernel/qeventdispatcher_mac_p.h b/src/gui/kernel/qeventdispatcher_mac_p.h index 48a33ec..41f539f 100644 --- a/src/gui/kernel/qeventdispatcher_mac_p.h +++ b/src/gui/kernel/qeventdispatcher_mac_p.h @@ -172,9 +172,15 @@ public: #ifdef QT_MAC_USE_COCOA // The following variables help organizing modal sessions: static QStack<QCocoaModalSessionInfo> cocoaModalSessionStack; - static bool blockCocoaRequestModal; - static NSModalSession activeModalSession(); - static void rebuildModalSessionStack(bool pop); + static bool currentExecIsNSAppRun; + static bool nsAppRunCalledByQt; + static NSModalSession currentModalSessionCached; + static void updateChildrenWorksWhenModal(); + static NSModalSession currentModalSession(); + static int activeModalSessionCount(); + static void temporarilyStopAllModalSessions(); + static void beginModalSession(QWidget *widget); + static void endModalSession(QWidget *widget); #endif MacSocketHash macSockets; @@ -192,6 +198,20 @@ private: CFRunLoopActivity activity, void *info); }; +#ifdef QT_MAC_USE_COCOA +class QtMacInterruptDispatcherHelp : public QObject +{ + static QtMacInterruptDispatcherHelp *instance; + bool cancelled; + + QtMacInterruptDispatcherHelp(); + ~QtMacInterruptDispatcherHelp(); + + public: + static void interruptLater(); +}; +#endif + QT_END_NAMESPACE #endif // QEVENTDISPATCHER_MAC_P_H diff --git a/src/gui/kernel/qeventdispatcher_s60.cpp b/src/gui/kernel/qeventdispatcher_s60.cpp new file mode 100644 index 0000000..323c863 --- /dev/null +++ b/src/gui/kernel/qeventdispatcher_s60.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 <qwidget.h> + +#include "qeventdispatcher_s60_p.h" + +QT_BEGIN_NAMESPACE + +QEventDispatcherS60::QEventDispatcherS60(QObject *parent) + : QEventDispatcherSymbian(parent), + m_noInputEvents(false) +{ +} + +QEventDispatcherS60::~QEventDispatcherS60() +{ + for (int c = 0; c < m_deferredInputEvents.size(); ++c) { + delete m_deferredInputEvents[c].event; + } +} + +bool QEventDispatcherS60::processEvents ( QEventLoop::ProcessEventsFlags flags ) +{ + bool ret = false; + + QT_TRY { + bool oldNoInputEventsValue = m_noInputEvents; + if (flags & QEventLoop::ExcludeUserInputEvents) { + m_noInputEvents = true; + } else { + m_noInputEvents = false; + ret = sendDeferredInputEvents() || ret; + } + + ret = QEventDispatcherSymbian::processEvents(flags) || ret; + + m_noInputEvents = oldNoInputEventsValue; + } QT_CATCH (const std::exception& ex) { +#ifndef QT_NO_EXCEPTIONS + CActiveScheduler::Current()->Error(qt_symbian_exception2Error(ex)); +#endif + } + + return ret; +} + +bool QEventDispatcherS60::hasPendingEvents() +{ + return !m_deferredInputEvents.isEmpty() || QEventDispatcherSymbian::hasPendingEvents(); +} + +void QEventDispatcherS60::saveInputEvent(QSymbianControl *control, QWidget *widget, QInputEvent *event) +{ + DeferredInputEvent inputEvent = {control, widget, event}; + m_deferredInputEvents.append(inputEvent); + connect(widget, SIGNAL(destroyed(QObject *)), SLOT(removeInputEventsForWidget(QObject *))); +} + +bool QEventDispatcherS60::sendDeferredInputEvents() +{ + bool eventsSent = false; + while (!m_deferredInputEvents.isEmpty()) { + DeferredInputEvent inputEvent = m_deferredInputEvents.takeFirst(); +#ifndef QT_NO_EXCEPTIONS + try { +#endif + inputEvent.control->sendInputEvent(inputEvent.widget, inputEvent.event); +#ifndef QT_NO_EXCEPTIONS + } catch (...) { + delete inputEvent.event; + throw; + } +#endif + delete inputEvent.event; + eventsSent = true; + } + + return eventsSent; +} + +void QEventDispatcherS60::removeInputEventsForWidget(QObject *object) +{ + for (int c = 0; c < m_deferredInputEvents.size(); ++c) { + if (m_deferredInputEvents[c].widget == object) { + delete m_deferredInputEvents[c].event; + m_deferredInputEvents.removeAt(c--); + } + } +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qeventdispatcher_s60_p.h b/src/gui/kernel/qeventdispatcher_s60_p.h new file mode 100644 index 0000000..6179a51 --- /dev/null +++ b/src/gui/kernel/qeventdispatcher_s60_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 QEVENTDISPATCHER_S60_P_H +#define QEVENTDISPATCHER_S60_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 <private/qeventdispatcher_symbian_p.h> +#include "qt_s60_p.h" + +QT_BEGIN_NAMESPACE + +class Q_GUI_EXPORT QEventDispatcherS60 : public QEventDispatcherSymbian +{ + Q_OBJECT + +public: + QEventDispatcherS60(QObject *parent = 0); + ~QEventDispatcherS60(); + + bool processEvents ( QEventLoop::ProcessEventsFlags flags ); + bool hasPendingEvents(); + + bool excludeUserInputEvents() { return m_noInputEvents; } + + void saveInputEvent(QSymbianControl *control, QWidget *widget, QInputEvent *event); + +private: + bool sendDeferredInputEvents(); + +private Q_SLOTS: + void removeInputEventsForWidget(QObject *object); + +private: + bool m_noInputEvents; + + struct DeferredInputEvent + { + QSymbianControl *control; + QWidget *widget; + QInputEvent *event; + }; + QList<DeferredInputEvent> m_deferredInputEvents; +}; + +QT_END_NAMESPACE + +#endif // QEVENTDISPATCHER_S60_P_H diff --git a/src/gui/kernel/qformlayout.cpp b/src/gui/kernel/qformlayout.cpp index f77f001..2c53145 100644 --- a/src/gui/kernel/qformlayout.cpp +++ b/src/gui/kernel/qformlayout.cpp @@ -1006,10 +1006,8 @@ QStyle* QFormLayoutPrivate::getStyle() const \since 4.4 \brief The QFormLayout class manages forms of input widgets and their associated labels. - \ingroup appearance \ingroup geomanagement - \mainclass QFormLayout is a convenience layout class that lays out its children in a two-column form. The left column consists of labels diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp new file mode 100644 index 0000000..7831893 --- /dev/null +++ b/src/gui/kernel/qgesture.cpp @@ -0,0 +1,312 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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 "qgesture.h" +#include <private/qgesture_p.h> +#include "qgraphicsitem.h" + +QT_BEGIN_NAMESPACE + + +class QEventFilterProxyGraphicsItem : public QGraphicsItem +{ +public: + QEventFilterProxyGraphicsItem(QGesture *g) + : gesture(g) + { + } + bool sceneEventFilter(QGraphicsItem *, QEvent *event) + { + return gesture ? gesture->filterEvent(event) : false; + } + QRectF boundingRect() const { return QRectF(); } + void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) { } + +private: + QGesture *gesture; +}; + +/*! + \class QGesture + \since 4.6 + + \brief The QGesture class is the base class for implementing custom + gestures. + + This class represents both an object that recognizes a gesture out of a set + of input events (a gesture recognizer), and a gesture object itself that + can be used to get extended information about the triggered gesture. + + The class has a list of properties that can be queried by the user to get + some gesture-specific parameters (for example, an offset of a Pan gesture). + + Usually gesture recognizer implements a state machine, storing its state + internally in the recognizer object. The recognizer receives input events + through the \l{QGesture::}{filterEvent()} virtual function and decides + whether the event should change the state of the recognizer by emitting an + appropriate signal. + + Input events should be either fed to the recognizer one by one with a + filterEvent() function, or the gesture recognizer should be attached to an + object it filters events for by specifying it as a parent object. The + QGesture object installs itself as an event filter to the parent object + automatically, the unsetObject() function should be used to remove an event + filter from the parent object. To make a + gesture that operates on a QGraphicsItem, both the appropriate QGraphicsView + should be passed as a parent object and setGraphicsItem() functions should + be used to attach a gesture to a graphics item. + + This is a base class, to create a custom gesture type, you should subclass + it and implement its pure virtual functions. + + \sa QPanGesture +*/ + +/*! \fn bool QGesture::filterEvent(QEvent *event) + + Parses input \a event and emits a signal when detects a gesture. + + In your reimplementation of this function, if you want to filter the \a + event out, i.e. stop it being handled further, return true; otherwise + return false; + + This is a pure virtual function that needs to be implemented in subclasses. +*/ + +/*! \fn void QGesture::started() + + The signal is emitted when the gesture is started. Extended information + about the gesture is contained in the signal sender object. + + In addition to started(), a triggered() signal should also be emitted. +*/ + +/*! \fn void QGesture::triggered() + + The signal is emitted when the gesture is detected. Extended information + about the gesture is contained in the signal sender object. +*/ + +/*! \fn void QGesture::finished() + + The signal is emitted when the gesture is finished. Extended information + about the gesture is contained in the signal sender object. +*/ + +/*! \fn void QGesture::cancelled() + + The signal is emitted when the gesture is cancelled, for example the + reset() function is called while the gesture was in the process of + emitting a triggered() signal. Extended information about the + gesture is contained in the sender object. +*/ + +/*! + Creates a new gesture handler object and marks it as a child of \a + parent. \a gestureTarget is the object that the gesture will watch + for events. + + The \a parent object is also the default event source for the + gesture, meaning that the gesture installs itself as an event filter + for the \a parent. + + \sa setGraphicsItem() +*/ +QGesture::QGesture(QObject *gestureTarget, QObject *parent) + : QObject(*new QGesturePrivate, parent) +{ + setGestureTarget(gestureTarget); +} + +/*! \internal + */ +QGesture::QGesture(QGesturePrivate &dd, QObject *gestureTarget, QObject *parent) + : QObject(dd, parent) +{ + setGestureTarget(gestureTarget); +} + +/*! + Destroys the gesture object. +*/ +QGesture::~QGesture() +{ +} + +/*! + \property QGesture::gestureTarget + + Gesture target is the object that the gesture will watch for events. + Typically this means that the gesture installs an event filter on the + target object. +*/ +void QGesture::setGestureTarget(QObject *object) +{ + d_func()->setupGestureTarget(object); +} + +QObject* QGesture::gestureTarget() const +{ + return d_func()->gestureTarget; +} + +void QGesturePrivate::setupGestureTarget(QObject *object) +{ + Q_Q(QGesture); + if (gestureTarget) + gestureTarget->removeEventFilter(q); + if (object) + object->installEventFilter(q); + gestureTarget = object; +} + +/*! \internal + */ +bool QGesture::eventFilter(QObject *receiver, QEvent *event) +{ + Q_D(QGesture); + if (d->graphicsItem && receiver == parent()) + return false; + return filterEvent(event); +} + +/*! + \property QGesture::state + + \brief The current state of the gesture. +*/ + +/*! + Returns the gesture recognition state. + */ +Qt::GestureState QGesture::state() const +{ + return d_func()->state; +} + +/*! + Sets this gesture's recognition state to \a state and emits appropriate + signals. + + This functions emits the signals according to the old state and the new + \a state, and it should be called after all the internal properties have been + initialized. + + \sa started(), triggered(), finished(), cancelled() + */ +void QGesture::updateState(Qt::GestureState state) +{ + Q_D(QGesture); + if (d->state == state) { + if (state == Qt::GestureUpdated) + emit triggered(); + return; + } + const Qt::GestureState oldState = d->state; + if (state != Qt::NoGesture && oldState > state) { + // comparing the state as ints: state should only be changed from + // started to (optionally) updated and to finished. + d->state = state; + qWarning("QGesture::updateState: incorrect new state"); + return; + } + if (oldState == Qt::NoGesture) { + d->state = Qt::GestureStarted; + emit started(); + } + d->state = state; + if (state == Qt::GestureUpdated) + emit triggered(); + else if (state == Qt::GestureFinished) + emit finished(); + else if (state == Qt::NoGesture) + emit cancelled(); + + if (state == Qt::GestureFinished) { + // gesture is finished, so we reset the internal state. + d->state = Qt::NoGesture; + } +} + +/*! + Sets the \a graphicsItem the gesture is filtering events for. + + The gesture will install an event filter to the \a graphicsItem and + redirect them to the filterEvent() function. + + \sa graphicsItem() +*/ +void QGesture::setGraphicsItem(QGraphicsItem *graphicsItem) +{ + Q_D(QGesture); + if (d->graphicsItem && d->eventFilterProxyGraphicsItem) + d->graphicsItem->removeSceneEventFilter(d->eventFilterProxyGraphicsItem); + d->graphicsItem = graphicsItem; + if (!d->eventFilterProxyGraphicsItem) + d->eventFilterProxyGraphicsItem = new QEventFilterProxyGraphicsItem(this); + if (graphicsItem) + graphicsItem->installSceneEventFilter(d->eventFilterProxyGraphicsItem); +} + +/*! + Returns the graphics item the gesture is filtering events for. + + \sa setGraphicsItem() +*/ +QGraphicsItem* QGesture::graphicsItem() const +{ + return d_func()->graphicsItem; +} + +/*! \fn void QGesture::reset() + + Resets the internal state of the gesture. This function might be called by + the filterEvent() implementation in a derived class, or by the user to + cancel a gesture. The base class implementation calls + updateState(Qt::NoGesture) which emits the cancelled() + signal if the state() of the gesture indicated it was active. +*/ +void QGesture::reset() +{ + updateState(Qt::NoGesture); +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h new file mode 100644 index 0000000..ee6f8b3 --- /dev/null +++ b/src/gui/kernel/qgesture.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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 QGESTURE_H +#define QGESTURE_H + +#include <QtCore/qobject.h> +#include <QtCore/qlist.h> +#include <QtCore/qdatetime.h> +#include <QtCore/qpoint.h> +#include <QtCore/qrect.h> +#include <QtCore/qmetatype.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QGraphicsItem; +class QGesturePrivate; +class Q_GUI_EXPORT QGesture : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QGesture) + + Q_PROPERTY(Qt::GestureState state READ state) + Q_PROPERTY(QObject* gestureTarget READ gestureTarget WRITE setGestureTarget) + +public: + explicit QGesture(QObject *gestureTarget = 0, QObject *parent = 0); + ~QGesture(); + + virtual bool filterEvent(QEvent *event) = 0; + + void setGestureTarget(QObject *object); + QObject* gestureTarget() const; + + void setGraphicsItem(QGraphicsItem *); + QGraphicsItem *graphicsItem() const; + + Qt::GestureState state() const; + +protected: + QGesture(QGesturePrivate &dd, QObject *gestureTarget, QObject *parent); + bool eventFilter(QObject*, QEvent*); + + virtual void reset(); + void updateState(Qt::GestureState state); + +Q_SIGNALS: + void started(); + void triggered(); + void finished(); + void cancelled(); + +private: + friend class QWidget; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGESTURE_H diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h new file mode 100644 index 0000000..ddca79e --- /dev/null +++ b/src/gui/kernel/qgesture_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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 QGESTURE_P_H +#define QGESTURE_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 "qrect.h" +#include "qpoint.h" +#include "qdatetime.h" +#include "qgesture.h" +#include "private/qobject_p.h" + +QT_BEGIN_NAMESPACE + +class QObject; +class QGraphicsItem; +class QGesturePrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGesture) + +public: + QGesturePrivate() + : gestureTarget(0), graphicsItem(0), eventFilterProxyGraphicsItem(0), + state(Qt::NoGesture), implicitGesture(false) + { + } + + virtual void setupGestureTarget(QObject *o); + + QPointer<QObject> gestureTarget; + QGraphicsItem *graphicsItem; + QGraphicsItem *eventFilterProxyGraphicsItem; + + Qt::GestureState state; + + // the flag specifies if the gesture was created implicitely by Qt. + bool implicitGesture; +}; + +QT_END_NAMESPACE + +#endif // QGESTURE_P_H diff --git a/src/gui/kernel/qgridlayout.cpp b/src/gui/kernel/qgridlayout.cpp index 6cded5a..0cf850e 100644 --- a/src/gui/kernel/qgridlayout.cpp +++ b/src/gui/kernel/qgridlayout.cpp @@ -980,8 +980,7 @@ QRect QGridLayoutPrivate::cellRect(int row, int col) const \brief The QGridLayout class lays out widgets in a grid. \ingroup geomanagement - \ingroup appearance - \mainclass + QGridLayout takes the space made available to it (by its parent layout or by the parentWidget()), divides it up into rows and @@ -1034,18 +1033,19 @@ QRect QGridLayoutPrivate::cellRect(int row, int col) const other layouts into the cells of your grid layout using addWidget(), addItem(), and addLayout(). - QGridLayout also includes two margin widths: the margin() and the - spacing(). The margin is the width of the reserved space along - each of the QGridLayout's four sides. The spacing is the width of - the automatically allocated spacing between neighboring boxes. + QGridLayout also includes two margin widths: + the \l{getContentsMargins()}{contents margin} and the spacing(). + The contents margin is the width of the reserved space along each + of the QGridLayout's four sides. The spacing() is the width of the + automatically allocated spacing between neighboring boxes. - The default margin() and spacing() values are provided by the - style. The default margin Qt styles specify is 9 for child - widgets and 11 for windows. The spacing defaults to the same as + The default contents margin values are provided by the + \l{QStyle::pixelMetric()}{style}. The default value Qt styles specify + is 9 for child widgets and 11 for windows. The spacing defaults to the same as the margin width for a top-level layout, or to the same as the parent layout. - \sa QBoxLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example} + \sa QBoxLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example} */ @@ -1078,7 +1078,7 @@ QGridLayout::QGridLayout() #ifdef QT3_SUPPORT /*! - \obsolete + \obsolete Constructs a new QGridLayout with \a nRows rows, \a nCols columns and parent widget, \a parent. \a parent may not be 0. The grid layout is called \a name. diff --git a/src/gui/kernel/qguifunctions_wince.cpp b/src/gui/kernel/qguifunctions_wince.cpp index e4be9a3..c96919a 100644 --- a/src/gui/kernel/qguifunctions_wince.cpp +++ b/src/gui/kernel/qguifunctions_wince.cpp @@ -215,13 +215,7 @@ int qt_wince_GetDIBits(HDC /*hdc*/ , HBITMAP hSourceBitmap, uint, uint, LPVOID l return ret; } -bool qt_wince_TextOutW(HDC hdc, int x, int y, LPWSTR lpString, UINT c) -{ - return ExtTextOutW(hdc, x, y, 0, NULL, lpString, c, NULL); -} - - -HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCTSTR, LPCTSTR file, LPCTSTR params, LPCTSTR dir, int showCmd) +HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCWSTR, LPCWSTR file, LPCWSTR params, LPCWSTR dir, int showCmd) { SHELLEXECUTEINFO info; info.hwnd = hwnd; @@ -253,21 +247,40 @@ COLORREF qt_wince_PALETTEINDEX( WORD /*wPaletteIndex*/) return 0; } -BOOL qt_wince_TextOut( HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cbString ) -{ - return ExtTextOut( hdc, nXStart, nYStart - 16, 0, NULL, lpString, cbString, NULL ); -} - // Internal Qt ----------------------------------------------------- bool qt_wince_is_platform(const QString &platformString) { - TCHAR tszPlatform[64]; - if (SystemParametersInfo(SPI_GETPLATFORMTYPE, - sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0)) - if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform)) + wchar_t tszPlatform[64]; + if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform) / sizeof(wchar_t), tszPlatform, 0)) + if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform)) return true; return false; } +int qt_wince_get_build() +{ + OSVERSIONINFO osvi; + osvi.dwOSVersionInfoSize = sizeof(osvi); + if (GetVersionEx(&osvi)) { + return osvi.dwBuildNumber; + } + return 0; +} + +int qt_wince_get_version() +{ + OSVERSIONINFO osvi; + osvi.dwOSVersionInfoSize = sizeof(osvi); + if (GetVersionEx(&osvi)) { + return (osvi.dwMajorVersion * 10 + osvi.dwMinorVersion); + } + return 0; +} + +bool qt_wince_is_windows_mobile_65() +{ + return ((qt_wince_get_version() == 52) && (qt_wince_get_build() > 2000)); +} + bool qt_wince_is_pocket_pc() { return qt_wince_is_platform(QString::fromLatin1("PocketPC")); } @@ -316,8 +329,8 @@ void qt_wince_maximize(QWidget *widget) void qt_wince_minimize(HWND hwnd) { - uint exstyle = GetWindowLongW(hwnd, GWL_EXSTYLE); - uint style = GetWindowLongW(hwnd, GWL_STYLE); + uint exstyle = GetWindowLong(hwnd, GWL_EXSTYLE); + uint style = GetWindowLong(hwnd, GWL_STYLE); RECT rect; RECT crect = {0,0,0,0}; GetWindowRect(hwnd, &rect); diff --git a/src/gui/kernel/qguifunctions_wince.h b/src/gui/kernel/qguifunctions_wince.h index 043f1b6..5d57af5 100644 --- a/src/gui/kernel/qguifunctions_wince.h +++ b/src/gui/kernel/qguifunctions_wince.h @@ -73,10 +73,6 @@ int qt_wince_GetDIBits(HDC, HBITMAP, uint, uint, void*, LPBITMAPINFO, uint); // QWidget #define SW_SHOWMINIMIZED SW_MINIMIZE -// QPaintEngine -bool qt_wince_TextOutW(HDC, int, int, LPWSTR, UINT); -#define TextOutW(a,b,c,d,e) qt_wince_TextOutW(a,b,c,d,e) - // QRegion #define ALTERNATE 0 #define WINDING 1 @@ -128,7 +124,7 @@ typedef struct tagTTPOLYCURVE #define TT_PRIM_CSPLINE 3 #define ANSI_VAR_FONT 12 -HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCTSTR operation, LPCTSTR file, LPCTSTR params, LPCTSTR dir, int showCmd); +HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCWSTR operation, LPCWSTR file, LPCWSTR params, LPCWSTR dir, int showCmd); #define ShellExecute(a,b,c,d,e,f) qt_wince_ShellExecute(a,b,c,d,e,f) @@ -150,8 +146,6 @@ HWND qt_wince_SetClipboardViewer( // Graphics --------------------------------------------------------- COLORREF qt_wince_PALETTEINDEX( WORD wPaletteIndex ); #define PALETTEINDEX(a) qt_wince_PALETTEINDEX(a) -BOOL qt_wince_TextOut( HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cbString ); -#define TextOut(a,b,c,d,e) qt_wince_TextOut(a,b,c,d,e) #endif // Q_OS_WINCE #endif // QGUIFUNCTIONS_WCE_H diff --git a/src/gui/kernel/qguivariant.cpp b/src/gui/kernel/qguivariant.cpp index 62c9117..a515a58 100644 --- a/src/gui/kernel/qguivariant.cpp +++ b/src/gui/kernel/qguivariant.cpp @@ -60,6 +60,11 @@ #include "qregion.h" #include "qsizepolicy.h" #include "qtextformat.h" +#include "qmatrix4x4.h" +#include "qvector2d.h" +#include "qvector3d.h" +#include "qvector4d.h" +#include "qquaternion.h" #include "private/qvariant_p.h" @@ -148,6 +153,31 @@ static void construct(QVariant::Private *x, const void *copy) v_construct<QColor>(x, &color); break; } +#ifndef QT_NO_MATRIX4X4 + case QVariant::Matrix4x4: + v_construct<QMatrix4x4>(x, copy); + break; +#endif +#ifndef QT_NO_VECTOR2D + case QVariant::Vector2D: + v_construct<QVector2D>(x, copy); + break; +#endif +#ifndef QT_NO_VECTOR3D + case QVariant::Vector3D: + v_construct<QVector3D>(x, copy); + break; +#endif +#ifndef QT_NO_VECTOR4D + case QVariant::Vector4D: + v_construct<QVector4D>(x, copy); + break; +#endif +#ifndef QT_NO_QUATERNION + case QVariant::Quaternion: + v_construct<QQuaternion>(x, copy); + break; +#endif default: qcoreVariantHandler()->construct(x, copy); return; @@ -221,6 +251,31 @@ static void clear(QVariant::Private *d) case QVariant::Pen: v_clear<QPen>(d); break; +#ifndef QT_NO_MATRIX4X4 + case QVariant::Matrix4x4: + v_clear<QMatrix4x4>(d); + break; +#endif +#ifndef QT_NO_VECTOR2D + case QVariant::Vector2D: + v_clear<QVector2D>(d); + break; +#endif +#ifndef QT_NO_VECTOR3D + case QVariant::Vector3D: + v_clear<QVector3D>(d); + break; +#endif +#ifndef QT_NO_VECTOR4D + case QVariant::Vector4D: + v_clear<QVector4D>(d); + break; +#endif +#ifndef QT_NO_QUATERNION + case QVariant::Quaternion: + v_clear<QVector4D>(d); + break; +#endif default: qcoreVariantHandler()->clear(d); return; @@ -266,7 +321,26 @@ static bool isNull(const QVariant::Private *d) case QVariant::KeySequence: #endif case QVariant::Pen: +#ifndef QT_NO_MATRIX4X4 + case QVariant::Matrix4x4: +#endif break; +#ifndef QT_NO_VECTOR2D + case QVariant::Vector2D: + return v_cast<QVector2D>(d)->isNull(); +#endif +#ifndef QT_NO_VECTOR3D + case QVariant::Vector3D: + return v_cast<QVector3D>(d)->isNull(); +#endif +#ifndef QT_NO_VECTOR4D + case QVariant::Vector4D: + return v_cast<QVector4D>(d)->isNull(); +#endif +#ifndef QT_NO_QUATERNION + case QVariant::Quaternion: + return v_cast<QQuaternion>(d)->isNull(); +#endif default: return qcoreVariantHandler()->isNull(d); } @@ -326,6 +400,26 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b) #endif case QVariant::Pen: return *v_cast<QPen>(a) == *v_cast<QPen>(b); +#ifndef QT_NO_MATRIX4X4 + case QVariant::Matrix4x4: + return *v_cast<QMatrix4x4>(a) == *v_cast<QMatrix4x4>(b); +#endif +#ifndef QT_NO_VECTOR2D + case QVariant::Vector2D: + return *v_cast<QVector2D>(a) == *v_cast<QVector2D>(b); +#endif +#ifndef QT_NO_VECTOR3D + case QVariant::Vector3D: + return *v_cast<QVector3D>(a) == *v_cast<QVector3D>(b); +#endif +#ifndef QT_NO_VECTOR4D + case QVariant::Vector4D: + return *v_cast<QVector4D>(a) == *v_cast<QVector4D>(b); +#endif +#ifndef QT_NO_QUATERNION + case QVariant::Quaternion: + return *v_cast<QQuaternion>(a) == *v_cast<QQuaternion>(b); +#endif default: break; } @@ -513,6 +607,31 @@ static void streamDebug(QDebug dbg, const QVariant &v) case QVariant::Pen: dbg.nospace() << qvariant_cast<QPen>(v); break; +#ifndef QT_NO_MATRIX4X4 + case QVariant::Matrix4x4: + dbg.nospace() << qvariant_cast<QMatrix4x4>(v); + break; +#endif +#ifndef QT_NO_VECTOR2D + case QVariant::Vector2D: + dbg.nospace() << qvariant_cast<QVector2D>(v); + break; +#endif +#ifndef QT_NO_VECTOR3D + case QVariant::Vector3D: + dbg.nospace() << qvariant_cast<QVector3D>(v); + break; +#endif +#ifndef QT_NO_VECTOR4D + case QVariant::Vector4D: + dbg.nospace() << qvariant_cast<QVector4D>(v); + break; +#endif +#ifndef QT_NO_QUATERNION + case QVariant::Quaternion: + dbg.nospace() << qvariant_cast<QQuaternion>(v); + break; +#endif default: qcoreVariantHandler()->debugStream(dbg, v); break; @@ -596,6 +715,21 @@ Q_DECL_METATYPE_HELPER(QTextLength) Q_DECL_METATYPE_HELPER(QTextFormat) Q_DECL_METATYPE_HELPER(QMatrix) Q_DECL_METATYPE_HELPER(QTransform) +#ifndef QT_NO_MATRIX4X4 +Q_DECL_METATYPE_HELPER(QMatrix4x4) +#endif +#ifndef QT_NO_VECTOR2D +Q_DECL_METATYPE_HELPER(QVector2D) +#endif +#ifndef QT_NO_VECTOR3D +Q_DECL_METATYPE_HELPER(QVector3D) +#endif +#ifndef QT_NO_VECTOR4D +Q_DECL_METATYPE_HELPER(QVector4D) +#endif +#ifndef QT_NO_QUATERNION +Q_DECL_METATYPE_HELPER(QQuaternion) +#endif #ifdef QT_NO_DATASTREAM # define Q_IMPL_METATYPE_HELPER(TYPE) \ @@ -645,7 +779,32 @@ static const QMetaTypeGuiHelper qVariantGuiHelper[] = { Q_IMPL_METATYPE_HELPER(QTextLength), Q_IMPL_METATYPE_HELPER(QTextFormat), Q_IMPL_METATYPE_HELPER(QMatrix), - Q_IMPL_METATYPE_HELPER(QTransform) + Q_IMPL_METATYPE_HELPER(QTransform), +#ifndef QT_NO_MATRIX4X4 + Q_IMPL_METATYPE_HELPER(QMatrix4x4), +#else + {0, 0, 0, 0}, +#endif +#ifndef QT_NO_VECTOR2D + Q_IMPL_METATYPE_HELPER(QVector2D), +#else + {0, 0, 0, 0}, +#endif +#ifndef QT_NO_VECTOR3D + Q_IMPL_METATYPE_HELPER(QVector3D), +#else + {0, 0, 0, 0}, +#endif +#ifndef QT_NO_VECTOR4D + Q_IMPL_METATYPE_HELPER(QVector4D), +#else + {0, 0, 0, 0}, +#endif +#ifndef QT_NO_QUATERNION + Q_IMPL_METATYPE_HELPER(QQuaternion) +#else + {0, 0, 0, 0} +#endif }; static const QVariant::Handler *qt_guivariant_last_handler = 0; diff --git a/src/gui/kernel/qkde.cpp b/src/gui/kernel/qkde.cpp new file mode 100644 index 0000000..9bb087c --- /dev/null +++ b/src/gui/kernel/qkde.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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 "qkde_p.h" +#include <QtCore/QLibrary> +#include <QtCore/QDir> +#include <QtCore/qdebug.h> +#include <QtCore/QSettings> +#include "QtGui/qstylefactory.h" +#include "qt_x11_p.h" + +#if defined(Q_WS_X11) + +QT_BEGIN_NAMESPACE + +/*! \internal +Gets the current KDE home path +like "/home/troll/.kde" +*/ +QString QKde::kdeHome() +{ + static QString kdeHomePath; + if (kdeHomePath.isEmpty()) { + kdeHomePath = QString::fromLocal8Bit(qgetenv("KDEHOME")); + if (kdeHomePath.isEmpty()) { + QDir homeDir(QDir::homePath()); + QString kdeConfDir(QLatin1String("/.kde")); + if (4 == X11->desktopVersion && homeDir.exists(QLatin1String(".kde4"))) + kdeConfDir = QLatin1String("/.kde4"); + kdeHomePath = QDir::homePath() + kdeConfDir; + } + } + return kdeHomePath; +} + +/*!\internal + Reads the color from the config, and store it in the palette with the given color role if found + */ +static bool kdeColor(QPalette *pal, QPalette::ColorRole role, const QSettings &kdeSettings, const QString &kde4Key, const QString &kde3Key = QString()) +{ + QVariant variant = kdeSettings.value(kde4Key); + if (!variant.isValid()) + QVariant variant = kdeSettings.value(kde3Key); + if (variant.isValid()) { + QStringList values = variant.toStringList(); + if (values.size() == 3) { + int r = values[0].toInt(); + int g = values[1].toInt(); + int b = values[2].toInt(); + pal->setBrush(role, QColor(r, g, b)); + return true; + } + } + return false; +} + + +/*!\internal + Returns the KDE palette +*/ +QPalette QKde::kdePalette() +{ + const QSettings theKdeSettings(QKde::kdeHome() + + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); + QPalette pal; + + // Setup KDE palette + kdeColor(&pal, QPalette::Button, theKdeSettings, QLatin1String("Colors:Button/BackgroundNormal"), QLatin1String("buttonBackground")); + kdeColor(&pal, QPalette::Window, theKdeSettings, QLatin1String("Colors:Window/BackgroundNormal"), QLatin1String("background")); + kdeColor(&pal, QPalette::Text, theKdeSettings, QLatin1String("Colors:View/ForegroundNormal"), QLatin1String("foreground")); + kdeColor(&pal, QPalette::WindowText, theKdeSettings, QLatin1String("Colors:Window/ForegroundNormal"), QLatin1String("windowForeground")); + kdeColor(&pal, QPalette::Base, theKdeSettings, QLatin1String("Colors:View/BackgroundNormal"), QLatin1String("windowBackground")); + kdeColor(&pal, QPalette::Highlight, theKdeSettings, QLatin1String("Colors:Selection/BackgroundNormal"), QLatin1String("selectBackground")); + kdeColor(&pal, QPalette::HighlightedText, theKdeSettings, QLatin1String("Colors:Selection/ForegroundNormal"), QLatin1String("selectForeground")); + kdeColor(&pal, QPalette::AlternateBase, theKdeSettings, QLatin1String("Colors:View/BackgroundAlternate"), QLatin1String("alternateBackground")); + kdeColor(&pal, QPalette::ButtonText, theKdeSettings, QLatin1String("Colors:Button/ForegroundNormal"), QLatin1String("buttonForeground")); + kdeColor(&pal, QPalette::Link, theKdeSettings, QLatin1String("Colors:View/ForegroundLink"), QLatin1String("linkColor")); + kdeColor(&pal, QPalette::LinkVisited, theKdeSettings, QLatin1String("Colors:View/ForegroundVisited"), QLatin1String("visitedLinkColor")); + //## TODO tooltip color + + return pal; +} + +/*!\internal + Returns the name of the QStyle to use. + (read from the kde config if needed) +*/ +QString QKde::kdeStyle() +{ + if (X11->desktopVersion >= 4) { + QSettings kdeSettings(QKde::kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); + QString style = kdeSettings.value(QLatin1String("widgetStyle"), QLatin1String("Oxygen")).toString(); + + QStringList availableStyles = QStyleFactory::keys(); + if(availableStyles.contains(style, Qt::CaseInsensitive)) + return style; + } + + if (X11->use_xrender) + return QLatin1String("plastique"); + else + return QLatin1String("windows"); +} + +/*!\internal + placeholder to load icon from kde. + to be implemented + */ +QIcon QKde::kdeIcon(const QString &name) +{ + //###todo + return QIcon(); +} + +QT_END_NAMESPACE + +#endif //Q_WS_X11 + diff --git a/src/gui/kernel/qkde_p.h b/src/gui/kernel/qkde_p.h new file mode 100644 index 0000000..d6c6494 --- /dev/null +++ b/src/gui/kernel/qkde_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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 QKDE_H +#define QKDE_H + +#include <QtCore/qglobal.h> +#include <QtGui/QPalette> +#include <QtGui/QIcon> + +// +// 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. +// +#if defined(Q_WS_X11) + + +QT_BEGIN_NAMESPACE + +// This namespace contains helper function to help KDE integration +namespace QKde { + QString kdeHome(); + QString kdeStyle(); + QPalette kdePalette(); + QIcon kdeIcon(const QString &name); +} + + +QT_END_NAMESPACE + +#endif // Q_WS_X11 +#endif // QKDE_H diff --git a/src/gui/kernel/qkeymapper.cpp b/src/gui/kernel/qkeymapper.cpp index 456f4a4..a4afa09 100644 --- a/src/gui/kernel/qkeymapper.cpp +++ b/src/gui/kernel/qkeymapper.cpp @@ -51,7 +51,6 @@ QT_BEGIN_NAMESPACE /*! \class QKeyMapper \since 4.2 - \ingroup application \internal \sa QObject @@ -116,6 +115,4 @@ QKeyMapperPrivate *qt_keymapper_private() return QKeyMapper::instance()->d_func(); } -Q_GUI_EXPORT QList<int> qt_keymapper_possibleKeys(QKeyEvent *e) { return QKeyMapper::instance()->possibleKeys(e); } - QT_END_NAMESPACE diff --git a/src/gui/kernel/qkeymapper_mac.cpp b/src/gui/kernel/qkeymapper_mac.cpp index 04a9081..b163c7b 100644 --- a/src/gui/kernel/qkeymapper_mac.cpp +++ b/src/gui/kernel/qkeymapper_mac.cpp @@ -48,6 +48,7 @@ #include <qinputcontext.h> #include <private/qkeymapper_p.h> #include <private/qapplication_p.h> +#include <private/qmacinputcontext_p.h> QT_BEGIN_NAMESPACE @@ -160,6 +161,14 @@ Qt::KeyboardModifiers qt_mac_get_modifiers(int keys) 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) @@ -176,6 +185,15 @@ static int qt_mac_get_mac_modifiers(Qt::KeyboardModifiers keys) 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) @@ -480,7 +498,8 @@ static bool translateKeyEventInternal(EventHandlerCallRef er, EventRef keyEvent, #ifdef QT_MAC_USE_COCOA if (outHandled) { qt_mac_eat_unicode_key = false; - CallNextEventHandler(er, keyEvent); + if (er) + CallNextEventHandler(er, keyEvent); *outHandled = qt_mac_eat_unicode_key; } #endif @@ -544,7 +563,7 @@ QKeyMapperPrivate::QKeyMapperPrivate() QKeyMapperPrivate::~QKeyMapperPrivate() { - clearMappings(); + deleteLayouts(); } bool @@ -639,7 +658,7 @@ QKeyMapperPrivate::updateKeyboard() } void -QKeyMapperPrivate::clearMappings() +QKeyMapperPrivate::deleteLayouts() { keyboard_mode = NullMode; for (int i = 0; i < 255; ++i) { @@ -648,6 +667,12 @@ QKeyMapperPrivate::clearMappings() keyLayout[i] = 0; } } +} + +void +QKeyMapperPrivate::clearMappings() +{ + deleteLayouts(); updateKeyboard(); } @@ -692,8 +717,14 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef e return true; } - if (qApp->inputContext() && qApp->inputContext()->isComposing()) + if (qApp->inputContext() && qApp->inputContext()->isComposing()) { + if (ekind == kEventRawKeyDown) { + QMacInputContext *context = qobject_cast<QMacInputContext*>(qApp->inputContext()); + if (context) + context->setLastKeydownEvent(event); + } return false; + } //get modifiers Qt::KeyboardModifiers modifiers; int qtKey; @@ -704,8 +735,10 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef e QString text(ourChar); /* This is actually wrong - but unfortunatly it is the best that can be done for now because of the Control/Meta mapping problems */ - if (modifiers & (Qt::ControlModifier | Qt::MetaModifier)) + if (modifiers & (Qt::ControlModifier | Qt::MetaModifier) + && !qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { text = QString(); + } if (widget) { @@ -721,7 +754,8 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef e //is it of use to text services? If so we won't bother //with a QKeyEvent. qt_mac_eat_unicode_key = false; - CallNextEventHandler(er, event); + 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; diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h index e411731..aa55d82 100644 --- a/src/gui/kernel/qkeymapper_p.h +++ b/src/gui/kernel/qkeymapper_p.h @@ -58,6 +58,7 @@ #include <qlist.h> #include <qlocale.h> #include <qevent.h> +#include <qhash.h> #if defined (Q_WS_MAC64) # include <private/qt_mac_p.h> @@ -160,6 +161,7 @@ public: bool translateKeyEvent(QWidget *receiver, const MSG &msg, bool grab); void updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 scancode, quint32 vk_key); bool isADeadKey(unsigned int vk_key, unsigned int modifiers); + void deleteLayouts(); KeyboardLayoutItem *keyLayout[256]; @@ -188,6 +190,7 @@ public: bool updateKeyboard(); void updateKeyMap(EventHandlerCallRef, EventRef, void *); bool translateKeyEvent(QWidget *, EventHandlerCallRef, EventRef, void *, bool); + void deleteLayouts(); enum { NullMode, UnicodeMode, OtherMode } keyboard_mode; union { @@ -203,6 +206,13 @@ public: UInt32 keyboard_dead; KeyboardLayoutItem *keyLayout[256]; #elif defined(Q_WS_QWS) +#elif defined(Q_OS_SYMBIAN) +private: + QHash<TUint, int> s60ToQtKeyMap; + void fillKeyMap(); +public: + QString translateKeyEvent(int keySym, Qt::KeyboardModifiers modifiers); + int mapS60KeyToQt(TUint s60key); #endif }; diff --git a/src/gui/kernel/qkeymapper_s60.cpp b/src/gui/kernel/qkeymapper_s60.cpp new file mode 100644 index 0000000..f9ea40a --- /dev/null +++ b/src/gui/kernel/qkeymapper_s60.cpp @@ -0,0 +1,247 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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/qkeymapper_p.h" +#include <e32keys.h> + +QT_BEGIN_NAMESPACE + +QKeyMapperPrivate::QKeyMapperPrivate() +{ + fillKeyMap(); +} + +QKeyMapperPrivate::~QKeyMapperPrivate() +{ +} + +QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent * /* e */) +{ + QList<int> result; + return result; +} + +void QKeyMapperPrivate::clearMappings() +{ + // stub +} + +QString QKeyMapperPrivate::translateKeyEvent(int keySym, Qt::KeyboardModifiers /* modifiers */) +{ + if (keySym >= Qt::Key_Escape) + return QString(); + + // Symbian doesn't actually use modifiers, but gives us the character code directly. + + return QString(QChar(keySym)); +} + +void QKeyMapperPrivate::fillKeyMap() +{ + using namespace Qt; + static const struct { + TUint s60Key; + int qtKey; + } map[] = { + {EKeyBell, Key_unknown}, + {EKeyBackspace, Key_Backspace}, + {EKeyTab, Key_Tab}, + {EKeyLineFeed, Key_unknown}, + {EKeyVerticalTab, Key_unknown}, + {EKeyFormFeed, Key_unknown}, + {EKeyEnter, Key_Enter}, + {EKeyEscape, Key_Escape}, + {EKeySpace, Key_Space}, + {EKeyDelete, Key_Delete}, + {EKeyPrintScreen, Key_SysReq}, + {EKeyPause, Key_Pause}, + {EKeyHome, Key_Home}, + {EKeyEnd, Key_End}, + {EKeyPageUp, Key_PageUp}, + {EKeyPageDown, Key_PageDown}, + {EKeyInsert, Key_Insert}, + {EKeyLeftArrow, Key_Left}, + {EKeyRightArrow, Key_Right}, + {EKeyUpArrow, Key_Up}, + {EKeyDownArrow, Key_Down}, + {EKeyLeftShift, Key_Shift}, + {EKeyRightShift, Key_Shift}, + {EKeyLeftAlt, Key_Alt}, + {EKeyRightAlt, Key_AltGr}, + {EKeyLeftCtrl, Key_Control}, + {EKeyRightCtrl, Key_Control}, + {EKeyLeftFunc, Key_Super_L}, + {EKeyRightFunc, Key_Super_R}, + {EKeyCapsLock, Key_CapsLock}, + {EKeyNumLock, Key_NumLock}, + {EKeyScrollLock, Key_ScrollLock}, + {EKeyF1, Key_F1}, + {EKeyF2, Key_F2}, + {EKeyF3, Key_F3}, + {EKeyF4, Key_F4}, + {EKeyF5, Key_F5}, + {EKeyF6, Key_F6}, + {EKeyF7, Key_F7}, + {EKeyF8, Key_F8}, + {EKeyF9, Key_F9}, + {EKeyF10, Key_F10}, + {EKeyF11, Key_F11}, + {EKeyF12, Key_F12}, + {EKeyF13, Key_F13}, + {EKeyF14, Key_F14}, + {EKeyF15, Key_F15}, + {EKeyF16, Key_F16}, + {EKeyF17, Key_F17}, + {EKeyF18, Key_F18}, + {EKeyF19, Key_F19}, + {EKeyF20, Key_F20}, + {EKeyF21, Key_F21}, + {EKeyF22, Key_F22}, + {EKeyF23, Key_F23}, + {EKeyF24, Key_F24}, + {EKeyOff, Key_unknown}, + {EKeyIncContrast, Key_unknown}, + {EKeyDecContrast, Key_unknown}, + {EKeyBacklightOn, Key_unknown}, + {EKeyBacklightOff, Key_unknown}, + {EKeyBacklightToggle, Key_unknown}, + {EKeySliderDown, Key_unknown}, + {EKeySliderUp, Key_unknown}, + {EKeyMenu, Key_Menu}, + {EKeyDictaphonePlay, Key_unknown}, + {EKeyDictaphoneStop, Key_unknown}, + {EKeyDictaphoneRecord, Key_unknown}, + {EKeyHelp, Key_unknown}, + {EKeyDial, Key_Call}, + {EKeyScreenDimension0, Key_unknown}, + {EKeyScreenDimension1, Key_unknown}, + {EKeyScreenDimension2, Key_unknown}, + {EKeyScreenDimension3, Key_unknown}, + {EKeyIncVolume, Key_unknown}, + {EKeyDecVolume, Key_unknown}, + {EKeyDevice0, Key_Context1}, // Found by manual testing, left softkey. + {EKeyDevice1, Key_Context2}, // Found by manual testing. + {EKeyDevice2, Key_unknown}, + {EKeyDevice3, Key_Select}, // Found by manual testing. + {EKeyDevice4, Key_unknown}, + {EKeyDevice5, Key_unknown}, + {EKeyDevice6, Key_unknown}, + {EKeyDevice7, Key_unknown}, + {EKeyDevice8, Key_unknown}, + {EKeyDevice9, Key_unknown}, + {EKeyDeviceA, Key_unknown}, + {EKeyDeviceB, Key_unknown}, + {EKeyDeviceC, Key_unknown}, + {EKeyDeviceD, Key_unknown}, + {EKeyDeviceE, Key_unknown}, + {EKeyDeviceF, Key_unknown}, + {EKeyApplication0, Key_Launch0}, + {EKeyApplication1, Key_Launch1}, + {EKeyApplication2, Key_Launch2}, + {EKeyApplication3, Key_Launch3}, + {EKeyApplication4, Key_Launch4}, + {EKeyApplication5, Key_Launch5}, + {EKeyApplication6, Key_Launch6}, + {EKeyApplication7, Key_Launch7}, + {EKeyApplication8, Key_Launch8}, + {EKeyApplication9, Key_Launch9}, + {EKeyApplicationA, Key_LaunchA}, + {EKeyApplicationB, Key_LaunchB}, + {EKeyApplicationC, Key_LaunchC}, + {EKeyApplicationD, Key_LaunchD}, + {EKeyApplicationE, Key_LaunchE}, + {EKeyApplicationF, Key_LaunchF}, + {EKeyYes, Key_Yes}, + {EKeyNo, Key_No}, + {EKeyIncBrightness, Key_unknown}, + {EKeyDecBrightness, Key_unknown}, + {EKeyKeyboardExtend, Key_unknown}, + {EKeyDevice10, Key_unknown}, + {EKeyDevice11, Key_unknown}, + {EKeyDevice12, Key_unknown}, + {EKeyDevice13, Key_unknown}, + {EKeyDevice14, Key_unknown}, + {EKeyDevice15, Key_unknown}, + {EKeyDevice16, Key_unknown}, + {EKeyDevice17, Key_unknown}, + {EKeyDevice18, Key_unknown}, + {EKeyDevice19, Key_unknown}, + {EKeyDevice1A, Key_unknown}, + {EKeyDevice1B, Key_unknown}, + {EKeyDevice1C, Key_unknown}, + {EKeyDevice1D, Key_unknown}, + {EKeyDevice1E, Key_unknown}, + {EKeyDevice1F, Key_unknown}, + {EKeyApplication10, Key_unknown}, + {EKeyApplication11, Key_unknown}, + {EKeyApplication12, Key_unknown}, + {EKeyApplication13, Key_unknown}, + {EKeyApplication14, Key_unknown}, + {EKeyApplication15, Key_unknown}, + {EKeyApplication16, Key_unknown}, + {EKeyApplication17, Key_unknown}, + {EKeyApplication18, Key_unknown}, + {EKeyApplication19, Key_unknown}, + {EKeyApplication1A, Key_unknown}, + {EKeyApplication1B, Key_unknown}, + {EKeyApplication1C, Key_unknown}, + {EKeyApplication1D, Key_unknown}, + {EKeyApplication1E, Key_unknown}, + {EKeyApplication1F, Key_unknown} + }; + const int mapSize = int(sizeof(map)/sizeof(map[0])); + s60ToQtKeyMap.reserve(mapSize + 5); // +5? docs: Ideally, slightly more than number of items + for (int i = 0; i < mapSize; ++i) + s60ToQtKeyMap.insert(map[i].s60Key, map[i].qtKey); +} + +int QKeyMapperPrivate::mapS60KeyToQt(TUint s60key) +{ + QHash<TUint, int>::const_iterator mapping; + mapping = s60ToQtKeyMap.find(s60key); + if (mapping != s60ToQtKeyMap.end()) { + return *mapping; + } else { + return Qt::Key_unknown; + } +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qkeymapper_win.cpp b/src/gui/kernel/qkeymapper_win.cpp index a51444f..2ac3f70 100644 --- a/src/gui/kernel/qkeymapper_win.cpp +++ b/src/gui/kernel/qkeymapper_win.cpp @@ -41,7 +41,7 @@ #include "qkeymapper_p.h" -#include <windows.h> +#include <qt_windows.h> #include <qdebug.h> #include <private/qevent_p.h> #include <private/qlocale_p.h> @@ -57,9 +57,7 @@ QT_BEGIN_NAMESPACE // Implemented elsewhere extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM); -Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, - UINT wRemoveMsg); + extern Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id); #ifndef LANG_PASHTO #define LANG_PASHTO 0x63 @@ -467,12 +465,7 @@ static inline int toKeyOrUnicode(int vk, int scancode, unsigned char *kbdBuffer, Q_ASSERT(vk > 0 && vk < 256); int code = 0; QChar unicodeBuffer[5]; - int res = 0; - if (QSysInfo::WindowsVersion < QSysInfo::WV_NT) - res = ToAscii(vk, scancode, kbdBuffer, reinterpret_cast<LPWORD>(unicodeBuffer), 0); - else - res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0); - + int res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0); if (res) code = unicodeBuffer[0].toUpper().unicode(); @@ -504,38 +497,6 @@ static inline int asciiToKeycode(char a, int state) return a & 0xff; } -static int inputcharset = CP_ACP; -static inline QChar wmchar_to_unicode(DWORD c) -{ - // qt_winMB2QString is the generalization of this function. - QT_WA({ - return QChar((ushort)c); - } , { - char mb[2]; - mb[0] = c & 0xff; - mb[1] = 0; - WCHAR wc[1]; - MultiByteToWideChar(inputcharset, MB_PRECOMPOSED, mb, -1, wc, 1); - return QChar(wc[0]); - }); -} - -static inline QChar imechar_to_unicode(DWORD c) -{ - // qt_winMB2QString is the generalization of this function. - QT_WA({ - return QChar((ushort)c); - } , { - char mb[3]; - mb[0] = (c >> 8) & 0xff; - mb[1] = c & 0xff; - mb[2] = 0; - WCHAR wc[1]; - MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mb, -1, wc, 1); - return QChar(wc[0]); - }); -} - static inline bool isModifierKey(int code) { return (code >= Qt::Key_Shift) && (code <= Qt::Key_ScrollLock); @@ -621,10 +582,10 @@ QKeyMapperPrivate::QKeyMapperPrivate() QKeyMapperPrivate::~QKeyMapperPrivate() { - clearMappings(); + deleteLayouts(); } -void QKeyMapperPrivate::clearMappings() +void QKeyMapperPrivate::deleteLayouts() { for (int i = 0; i < 255; ++i) { if (keyLayout[i]) { @@ -632,46 +593,23 @@ void QKeyMapperPrivate::clearMappings() keyLayout[i] = 0; } } +} + +void QKeyMapperPrivate::clearMappings() +{ + deleteLayouts(); /* MAKELCID()'s first argument is a WORD, and GetKeyboardLayout() * returns a DWORD. */ -// LCID newLCID = MAKELCID(DWORD(GetKeyboardLayout(0)), SORT_DEFAULT); + + LCID newLCID = MAKELCID((DWORD)GetKeyboardLayout(0), SORT_DEFAULT); // keyboardInputLocale = qt_localeFromLCID(newLCID); - LCID newLCID = MAKELCID( - reinterpret_cast<long>(GetKeyboardLayout(0)), - SORT_DEFAULT - ); - keyboardInputLocale = qt_localeFromLCID(newLCID); + bool bidi = false; -#ifdef UNICODE - if (QSysInfo::WindowsVersion >= QSysInfo::WV_2000) { - WCHAR wchLCIDFontSig[16]; - if (GetLocaleInfoW(newLCID, - LOCALE_FONTSIGNATURE, - &wchLCIDFontSig[0], - (sizeof(wchLCIDFontSig)/sizeof(WCHAR))) - && (wchLCIDFontSig[7] & (WCHAR)0x0800)) + wchar_t LCIDFontSig[16]; + if (GetLocaleInfo(newLCID, LOCALE_FONTSIGNATURE, LCIDFontSig, sizeof(LCIDFontSig) / sizeof(wchar_t)) + && (LCIDFontSig[7] & (wchar_t)0x0800)) bidi = true; - } else -#endif //UNICODE - { - if (newLCID == 0x0859 || //Sindhi (Arabic script) - newLCID == 0x0460) //Kashmiri (Arabic script) - bidi = true;; - - switch (PRIMARYLANGID(newLCID)) - { - case LANG_ARABIC: - case LANG_HEBREW: - case LANG_URDU: - case LANG_FARSI: - case LANG_PASHTO: - //case LANG_UIGHUR: - case LANG_SYRIAC: - case LANG_DIVEHI: - bidi = true; - } - } keyboardInputDirection = bidi ? Qt::RightToLeft : Qt::LeftToRight; } @@ -760,7 +698,7 @@ void QKeyMapperPrivate::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 keyLayout[vk_key]->qtKey[8] = fallbackKey; // If this vk_key a Dead Key - if (MapVirtualKey(vk_key, 2) & 0x80008000) { // (High-order dead key on Win 95 is 0x8000) + if (MapVirtualKey(vk_key, 2) & 0x80000000) { // Push a Space, then the original key through the low-level ToAscii functions. // We do this because these functions (ToAscii / ToUnicode) will alter the internal state of // the keyboard driver By doing the following, we set the keyboard driver state back to what @@ -837,13 +775,13 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool bool isNumpad = (msg.wParam >= VK_NUMPAD0 && msg.wParam <= VK_NUMPAD9); quint32 nModifiers = 0; - if (QSysInfo::WindowsVersion < QSysInfo::WV_NT || QSysInfo::WindowsVersion & QSysInfo::WV_CE_based) { +#if defined(Q_OS_WINCE) nModifiers |= (GetKeyState(VK_SHIFT ) < 0 ? ShiftAny : 0); nModifiers |= (GetKeyState(VK_CONTROL) < 0 ? ControlAny : 0); nModifiers |= (GetKeyState(VK_MENU ) < 0 ? AltAny : 0); nModifiers |= (GetKeyState(VK_LWIN ) < 0 ? MetaLeft : 0); nModifiers |= (GetKeyState(VK_RWIN ) < 0 ? MetaRight : 0); - } else { +#else // Map native modifiers to some bit representation nModifiers |= (GetKeyState(VK_LSHIFT ) & 0x80 ? ShiftLeft : 0); nModifiers |= (GetKeyState(VK_RSHIFT ) & 0x80 ? ShiftRight : 0); @@ -857,7 +795,8 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool nModifiers |= (GetKeyState(VK_CAPITAL ) & 0x01 ? CapsLock : 0); nModifiers |= (GetKeyState(VK_NUMLOCK ) & 0x01 ? NumLock : 0); nModifiers |= (GetKeyState(VK_SCROLL ) & 0x01 ? ScrollLock : 0); - } +#endif // Q_OS_WINCE + if (msg.lParam & ExtendedKey) nModifiers |= msg.lParam & ExtendedKey; @@ -870,12 +809,12 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool // Now we know enough to either have MapVirtualKey or our own keymap tell us if it's a deadkey bool isDeadKey = isADeadKey(msg.wParam, state) - || MapVirtualKey(msg.wParam, 2) & 0x80008000; // High-order on 95 is 0x8000 + || MapVirtualKey(msg.wParam, 2) & 0x80000000; // A multi-character key not found by our look-ahead if (msgType == WM_CHAR) { QString s; - QChar ch = wmchar_to_unicode(msg.wParam); + QChar ch = QChar((ushort)msg.wParam); if (!ch.isNull()) s += ch; @@ -886,7 +825,7 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool // Input method characters not found by our look-ahead else if (msgType == WM_IME_CHAR) { QString s; - QChar ch = imechar_to_unicode(msg.wParam); + QChar ch = QChar((ushort)msg.wParam); if (!ch.isNull()) s += ch; @@ -917,8 +856,8 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool } } else if (msgType == WM_KEYUP) { if (dirStatus == VK_LSHIFT - && (msg.wParam == VK_SHIFT && GetKeyState(VK_LCONTROL) - || msg.wParam == VK_CONTROL && GetKeyState(VK_LSHIFT))) { + && ((msg.wParam == VK_SHIFT && GetKeyState(VK_LCONTROL)) + || (msg.wParam == VK_CONTROL && GetKeyState(VK_LSHIFT)))) { k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, Qt::Key_Direction_L, 0, QString(), false, 0, scancode, msg.wParam, nModifiers); @@ -927,8 +866,8 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool scancode, msg.wParam, nModifiers); dirStatus = 0; } else if (dirStatus == VK_RSHIFT - && (msg.wParam == VK_SHIFT && GetKeyState(VK_RCONTROL) - || msg.wParam == VK_CONTROL && GetKeyState(VK_RSHIFT))) { + && ( (msg.wParam == VK_SHIFT && GetKeyState(VK_RCONTROL)) + || (msg.wParam == VK_CONTROL && GetKeyState(VK_RSHIFT)))) { k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, Qt::Key_Direction_R, 0, QString(), false, 0, scancode, msg.wParam, nModifiers); @@ -1050,11 +989,9 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool : msgType == WM_IME_KEYDOWN ? WM_IME_CHAR : WM_SYSCHAR); QChar uch; - if (winPeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) { + if (PeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) { // Found a ?_CHAR - uch = charType == WM_IME_CHAR - ? imechar_to_unicode(wm_char.wParam) - : wmchar_to_unicode(wm_char.wParam); + uch = QChar((ushort)wm_char.wParam); if (msgType == WM_SYSKEYDOWN && uch.isLetter() && (msg.lParam & KF_ALTDOWN)) uch = uch.toLower(); // (See doc of WM_SYSCHAR) Alt-letter if (!code && !uch.row()) @@ -1067,7 +1004,7 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool // to find the correct key using the current message parameters & keyboard state. if (uch.isNull() && msgType == WM_IME_KEYDOWN) { BYTE keyState[256]; - WCHAR newKey[3] = {0}; + wchar_t newKey[3] = {0}; GetKeyboardState(keyState); int val = ToUnicode(vk_key, scancode, keyState, newKey, 2, 0); if (val == 1) { @@ -1085,18 +1022,10 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool uch = QChar(QLatin1Char(0x7f)); // Windows doesn't know this one. } else { if (msgType != WM_SYSKEYDOWN || !code) { - UINT map; - QT_WA({ - map = MapVirtualKey(msg.wParam, 2); - } , { - map = MapVirtualKeyA(msg.wParam, 2); - // High-order bit is 0x8000 on '95 - if (map & 0x8000) - map = (map^0x8000)|0x80000000; - }); + UINT map = MapVirtualKey(msg.wParam, 2); // If the high bit of the return value is set, it's a deadkey if (!(map & 0x80000000)) - uch = wmchar_to_unicode((DWORD)map); + uch = QChar((ushort)map); } } if (!code && !uch.row()) @@ -1237,6 +1166,8 @@ bool QKeyMapper::sendKeyEvent(QWidget *widget, bool grab, if (QApplicationPrivate::instance()->qt_tryAccelEvent(widget, &a)) return true; } +#else + Q_UNUSED(grab); #endif if (!widget->isEnabled()) return false; diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 6293087..2e82ab5 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -105,20 +105,39 @@ static bool operator<(int key, const MacSpecialKey &entry) static const MacSpecialKey * const MacSpecialKeyEntriesEnd = entries + NumEntries; -static QChar macSymbolForQtKey(int key) +QChar qt_macSymbolForQtKey(int key) { const MacSpecialKey *i = qBinaryFind(entries, MacSpecialKeyEntriesEnd, key); if (i == MacSpecialKeyEntriesEnd) return QChar(); - return QChar(i->macSymbol); + ushort macSymbol = i->macSymbol; + if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) + && (macSymbol == kControlUnicode || macSymbol == kCommandUnicode)) { + if (macSymbol == kControlUnicode) + macSymbol = kCommandUnicode; + else + macSymbol = kControlUnicode; + } + + return QChar(macSymbol); } static int qtkeyForMacSymbol(const QChar ch) { + const ushort unicode = ch.unicode(); for (int i = 0; i < NumEntries; ++i) { const MacSpecialKey &entry = entries[i]; - if (entry.macSymbol == ch.unicode()) - return entry.key; + if (entry.macSymbol == unicode) { + int key = entry.key; + if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) + && (unicode == kControlUnicode || unicode == kCommandUnicode)) { + if (unicode == kControlUnicode) + key = Qt::Key_Control; + else + key = Qt::Key_Meta; + } + return key; + } } return -1; } @@ -126,16 +145,15 @@ static int qtkeyForMacSymbol(const QChar ch) #else static bool qt_sequence_no_mnemonics = false; #endif -void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemonics = !b; } +void Q_AUTOTEST_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemonics = !b; } /*! \class QKeySequence \brief The QKeySequence class encapsulates a key sequence as used by shortcuts. - \ingroup misc \ingroup shared - \mainclass + In its most common form, a key sequence describes a combination of keys that must be used together to perform some action. Key sequences @@ -207,70 +225,72 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni corresponds to the \key Control keys. \table - \header \i StandardKey \i Windows \i Mac OS X \i KDE \i GNOME - \row \i HelpContents \i F1 \i Ctrl+? \i F1 \i F1 - \row \i WhatsThis \i Shift+F1 \i Shift+F1 \i Shift+F1 \i Shift+F1 - \row \i Open \i Ctrl+O \i Ctrl+O \i Ctrl+O \i Ctrl+O - \row \i Close \i Ctrl+F4, Ctrl+W \i Ctrl+W, Ctrl+F4 \i Ctrl+W \i Ctrl+W - \row \i Save \i Ctrl+S \i Ctrl+S \i Ctrl+S \i Ctrl+S - \row \i SaveAs \i \i Ctrl+Shift+S \i \i Ctrl+Shift+S - \row \i New \i Ctrl+N \i Ctrl+N \i Ctrl+N \i Ctrl+N - \row \i Delete \i Del \i Del, Meta+D \i Del, Ctrl+D \i Del, Ctrl+D - \row \i Cut \i Ctrl+X, Shift+Del \i Ctrl+X \i Ctrl+X, F20, Shift+Del \i Ctrl+X, F20, Shift+Del - \row \i Copy \i Ctrl+C, Ctrl+Ins \i Ctrl+C \i Ctrl+C, F16, Ctrl+Ins \i Ctrl+C, F16, Ctrl+Ins - \row \i Paste \i Ctrl+V, Shift+Ins \i Ctrl+V \i Ctrl+V, F18, Shift+Ins \i Ctrl+V, F18, Shift+Ins - \row \i Undo \i Ctrl+Z, Alt+Backspace \i Ctrl+Z \i Ctrl+Z, F14 \i Ctrl+Z, F14 - \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z, Ctrl+Y \i Ctrl+Shift+Z \i Ctrl+Shift+Z - \row \i Back \i Alt+Left, Backspace \i Ctrl+[ \i Alt+Left \i Alt+Left - \row \i Forward \i Alt+Right, Shift+Backspace \i Ctrl+] \i Alt+Right \i Alt+Right - \row \i Refresh \i F5 \i F5 \i F5 \i Ctrl+R, F5 - \row \i ZoomIn \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus - \row \i ZoomOut \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus - \row \i Print \i Ctrl+P \i Ctrl+P \i Ctrl+P \i Ctrl+P - \row \i AddTab \i Ctrl+T \i Ctrl+T \i Ctrl+Shift+N, Ctrl+T \i Ctrl+T - \row \i NextChild \i Ctrl+Tab, Forward, Ctrl+F6 \i Ctrl+}, Forward, Ctrl+Tab \i Ctrl+Tab, Forward, Ctrl+Comma \i Ctrl+Tab, Forward - \row \i PreviousChild \i Ctrl+Shift+Tab, Back, Ctrl+Shift+F6 \i Ctrl+{, Back, Ctrl+Shift+Tab \i Ctrl+Shift+Tab, Back, Ctrl+Period \i Ctrl+Shift+Tab, Back - \row \i Find \i Ctrl+F \i Ctrl+F \i Ctrl+F \i Ctrl+F - \row \i FindNext \i F3, Ctrl+G \i Ctrl+G \i F3 \i Ctrl+G, F3 - \row \i FindPrevious \i Shift+F3, Ctrl+Shift+G \i Ctrl+Shift+G \i Shift+F3 \i Ctrl+Shift+G, Shift+F3 - \row \i Replace \i Ctrl+H \i (none) \i Ctrl+R \i Ctrl+H - \row \i SelectAll \i Ctrl+A \i Ctrl+A \i Ctrl+A \i Ctrl+A - \row \i Bold \i Ctrl+B \i Ctrl+B \i Ctrl+B \i Ctrl+B - \row \i Italic \i Ctrl+I \i Ctrl+I \i Ctrl+I \i Ctrl+I - \row \i Underline \i Ctrl+U \i Ctrl+U \i Ctrl+U \i Ctrl+U - \row \i MoveToNextChar \i Right \i Right \i Right \i Right - \row \i MoveToPreviousChar \i Left \i Left \i Left \i Left - \row \i MoveToNextWord \i Ctrl+Right \i Alt+Right \i Ctrl+Right \i Ctrl+Right - \row \i MoveToPreviousWord \i Ctrl+Left \i Alt+Left \i Ctrl+Left \i Ctrl+Left - \row \i MoveToNextLine \i Down \i Down \i Down \i Down - \row \i MoveToPreviousLine \i Up \i Up \i Up \i Up - \row \i MoveToNextPage \i PgDown \i PgDown, Alt+PgDown, Meta+Down, Meta+PgDown\i PgDown \i PgDown - \row \i MoveToPreviousPage \i PgUp \i PgUp, Alt+PgUp, Meta+Up, Meta+PgUp \i PgUp \i PgUp - \row \i MoveToStartOfLine \i Home \i Ctrl+Left, Meta+Left \i Home \i Home - \row \i MoveToEndOfLine \i End \i Ctrl+Right, Meta+Right \i End \i End - \row \i MoveToStartOfBlock \i (none) \i Alt+Up, Meta+A \i (none) \i (none) - \row \i MoveToEndOfBlock \i (none) \i Alt+Down, Meta+E \i (none) \i (none) - \row \i MoveToStartOfDocument\i Ctrl+Home \i Ctrl+Up, Home \i Ctrl+Home \i Ctrl+Home - \row \i MoveToEndOfDocument \i Ctrl+End \i Ctrl+Down, End \i Ctrl+End \i Ctrl+End - \row \i SelectNextChar \i Shift+Right \i Shift+Right \i Shift+Right \i Shift+Right - \row \i SelectPreviousChar \i Shift+Left \i Shift+Left \i Shift+Left \i Shift?left - \row \i SelectNextWord \i Ctrl+Shift+Right \i Alt+Shift+Right \i Ctrl+Shift+Right \i Ctrl+Shift+Right - \row \i SelectPreviousWord \i Ctrl+Shift+Left \i Alt+Shift+Left \i Ctrl+Shift+Left \i Ctrl+Shift+Left - \row \i SelectNextLine \i Shift+Down \i Shift+Down \i Shift+Down \i Shift+Down - \row \i SelectPreviousLine \i Shift+Up \i Shift+Up \i Shift+Up \i Shift+Up - \row \i SelectNextPage \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown - \row \i SelectPreviousPage \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp - \row \i SelectStartOfLine \i Shift+Home \i Ctrl+Shift+Left \i Shift+Home \i Shift+Home - \row \i SelectEndOfLine \i Shift+End \i Ctrl+Shift+Right \i Shift+End \i Shift+End - \row \i SelectStartOfBlock \i (none) \i Alt+Shift+Up \i (none) \i (none) - \row \i SelectEndOfBlock \i (none) \i Alt+Shift+Down \i (none) \i (none) - \row \i SelectStartOfDocument\i Ctrl+Shift+Home \i Ctrl+Shift+Up, Shift+Home \i Ctrl+Shift+Home\i Ctrl+Shift+Home - \row \i SelectEndOfDocument \i Ctrl+Shift+End \i Ctrl+Shift+Down, Shift+End \i Ctrl+Shift+End \i Ctrl+Shift+End - \row \i DeleteStartOfWord \i Ctrl+Backspace \i Alt+Backspace \i Ctrl+Backspace \i Ctrl+Backspace - \row \i DeleteEndOfWord \i Ctrl+Del \i (none) \i Ctrl+Del \i Ctrl+Del - \row \i DeleteEndOfLine \i (none) \i (none) \i Ctrl+K \i Ctrl+K - \row \i InsertParagraphSeparator \i Enter \i Enter \i Enter \i Enter - \row \i InsertLineSeparator \i Shift+Enter \i Meta+Enter \i Shift+Enter \i Shift+Enter + \header \i StandardKey \i Windows \i Mac OS X \i KDE \i GNOME \i S60 + \row \i HelpContents \i F1 \i Ctrl+? \i F1 \i F1 \i F2 + \row \i WhatsThis \i Shift+F1 \i Shift+F1 \i Shift+F1 \i Shift+F1 \i Shift+F1 + \row \i Open \i Ctrl+O \i Ctrl+O \i Ctrl+O \i Ctrl+O \i (none) + \row \i Close \i Ctrl+F4, Ctrl+W \i Ctrl+W, Ctrl+F4 \i Ctrl+W \i Ctrl+W \i (none) + \row \i Save \i Ctrl+S \i Ctrl+S \i Ctrl+S \i Ctrl+S \i (none) + \row \i Quit \i \i Ctrl+Q \i Qtrl+Q \i Qtrl+Q \i (none) + \row \i SaveAs \i \i Ctrl+Shift+S \i \i Ctrl+Shift+S \i (none) + \row \i New \i Ctrl+N \i Ctrl+N \i Ctrl+N \i Ctrl+N \i (none) + \row \i Delete \i Del \i Del, Meta+D \i Del, Ctrl+D \i Del, Ctrl+D \i Del + \row \i Cut \i Ctrl+X, Shift+Del \i Ctrl+X \i Ctrl+X, F20, Shift+Del \i Ctrl+X, F20, Shift+Del \i Ctrl+X + \row \i Copy \i Ctrl+C, Ctrl+Ins \i Ctrl+C \i Ctrl+C, F16, Ctrl+Ins \i Ctrl+C, F16, Ctrl+Ins \i Ctrl+C + \row \i Paste \i Ctrl+V, Shift+Ins \i Ctrl+V \i Ctrl+V, F18, Shift+Ins \i Ctrl+V, F18, Shift+Ins \i Ctrl+V + \row \i Preferences \i \i Ctrl+, \i \i \i (none) + \row \i Undo \i Ctrl+Z, Alt+Backspace \i Ctrl+Z \i Ctrl+Z, F14 \i Ctrl+Z, F14 \i Ctrl+Z + \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z, Ctrl+Y \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i (none) + \row \i Back \i Alt+Left, Backspace \i Ctrl+[ \i Alt+Left \i Alt+Left \i (none) + \row \i Forward \i Alt+Right, Shift+Backspace \i Ctrl+] \i Alt+Right \i Alt+Right \i (none) + \row \i Refresh \i F5 \i F5 \i F5 \i Ctrl+R, F5 \i (none) + \row \i ZoomIn \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus \i (none) + \row \i ZoomOut \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus \i (none) + \row \i Print \i Ctrl+P \i Ctrl+P \i Ctrl+P \i Ctrl+P \i (none) + \row \i AddTab \i Ctrl+T \i Ctrl+T \i Ctrl+Shift+N, Ctrl+T \i Ctrl+T \i (none) + \row \i NextChild \i Ctrl+Tab, Forward, Ctrl+F6 \i Ctrl+}, Forward, Ctrl+Tab \i Ctrl+Tab, Forward, Ctrl+Comma \i Ctrl+Tab, Forward \i (none) + \row \i PreviousChild \i Ctrl+Shift+Tab, Back, Ctrl+Shift+F6 \i Ctrl+{, Back, Ctrl+Shift+Tab \i Ctrl+Shift+Tab, Back, Ctrl+Period \i Ctrl+Shift+Tab, Back \i (none) + \row \i Find \i Ctrl+F \i Ctrl+F \i Ctrl+F \i Ctrl+F \i (none) + \row \i FindNext \i F3, Ctrl+G \i Ctrl+G \i F3 \i Ctrl+G, F3 \i (none) + \row \i FindPrevious \i Shift+F3, Ctrl+Shift+G \i Ctrl+Shift+G \i Shift+F3 \i Ctrl+Shift+G, Shift+F3 \i (none) + \row \i Replace \i Ctrl+H \i (none) \i Ctrl+R \i Ctrl+H \i (none) + \row \i SelectAll \i Ctrl+A \i Ctrl+A \i Ctrl+A \i Ctrl+A \i (none) + \row \i Bold \i Ctrl+B \i Ctrl+B \i Ctrl+B \i Ctrl+B \i (none) + \row \i Italic \i Ctrl+I \i Ctrl+I \i Ctrl+I \i Ctrl+I \i (none) + \row \i Underline \i Ctrl+U \i Ctrl+U \i Ctrl+U \i Ctrl+U \i (none) + \row \i MoveToNextChar \i Right \i Right \i Right \i Right \i Right + \row \i MoveToPreviousChar \i Left \i Left \i Left \i Left \i Left + \row \i MoveToNextWord \i Ctrl+Right \i Alt+Right \i Ctrl+Right \i Ctrl+Right \i Ctrl+Right + \row \i MoveToPreviousWord \i Ctrl+Left \i Alt+Left \i Ctrl+Left \i Ctrl+Left \i Ctrl+Left + \row \i MoveToNextLine \i Down \i Down \i Down \i Down \i Down + \row \i MoveToPreviousLine \i Up \i Up \i Up \i Up \i Up + \row \i MoveToNextPage \i PgDown \i PgDown, Alt+PgDown, Meta+Down, Meta+PgDown\i PgDown \i PgDown \i PgDown + \row \i MoveToPreviousPage \i PgUp \i PgUp, Alt+PgUp, Meta+Up, Meta+PgUp \i PgUp \i PgUp \i PgUp + \row \i MoveToStartOfLine \i Home \i Ctrl+Left, Meta+Left \i Home \i Home \i Home + \row \i MoveToEndOfLine \i End \i Ctrl+Right, Meta+Right \i End \i End \i End + \row \i MoveToStartOfBlock \i (none) \i Alt+Up, Meta+A \i (none) \i (none) \i (none) + \row \i MoveToEndOfBlock \i (none) \i Alt+Down, Meta+E \i (none) \i (none) \i (none) + \row \i MoveToStartOfDocument\i Ctrl+Home \i Ctrl+Up, Home \i Ctrl+Home \i Ctrl+Home \i Ctrl+Home + \row \i MoveToEndOfDocument \i Ctrl+End \i Ctrl+Down, End \i Ctrl+End \i Ctrl+End \i Ctrl+End + \row \i SelectNextChar \i Shift+Right \i Shift+Right \i Shift+Right \i Shift+Right \i Shift+Right + \row \i SelectPreviousChar \i Shift+Left \i Shift+Left \i Shift+Left \i Shift+Left \i Shift+Left + \row \i SelectNextWord \i Ctrl+Shift+Right \i Alt+Shift+Right \i Ctrl+Shift+Right \i Ctrl+Shift+Right \i Ctrl+Shift+Right + \row \i SelectPreviousWord \i Ctrl+Shift+Left \i Alt+Shift+Left \i Ctrl+Shift+Left \i Ctrl+Shift+Left \i Ctrl+Shift+Left + \row \i SelectNextLine \i Shift+Down \i Shift+Down \i Shift+Down \i Shift+Down \i Shift+Down + \row \i SelectPreviousLine \i Shift+Up \i Shift+Up \i Shift+Up \i Shift+Up \i Shift+Up + \row \i SelectNextPage \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown + \row \i SelectPreviousPage \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp + \row \i SelectStartOfLine \i Shift+Home \i Ctrl+Shift+Left \i Shift+Home \i Shift+Home \i Shift+Home + \row \i SelectEndOfLine \i Shift+End \i Ctrl+Shift+Right \i Shift+End \i Shift+End \i Shift+End + \row \i SelectStartOfBlock \i (none) \i Alt+Shift+Up \i (none) \i (none) \i (none) + \row \i SelectEndOfBlock \i (none) \i Alt+Shift+Down \i (none) \i (none) \i (none) + \row \i SelectStartOfDocument\i Ctrl+Shift+Home \i Ctrl+Shift+Up, Shift+Home \i Ctrl+Shift+Home\i Ctrl+Shift+Home \i Ctrl+Shift+Home + \row \i SelectEndOfDocument \i Ctrl+Shift+End \i Ctrl+Shift+Down, Shift+End \i Ctrl+Shift+End \i Ctrl+Shift+End \i Ctrl+Shift+End + \row \i DeleteStartOfWord \i Ctrl+Backspace \i Alt+Backspace \i Ctrl+Backspace \i Ctrl+Backspace \i (none) + \row \i DeleteEndOfWord \i Ctrl+Del \i (none) \i Ctrl+Del \i Ctrl+Del \i (none) + \row \i DeleteEndOfLine \i (none) \i (none) \i Ctrl+K \i Ctrl+K \i (none) + \row \i InsertParagraphSeparator \i Enter \i Enter \i Enter \i Enter \i (none) + \row \i InsertLineSeparator \i Shift+Enter \i Meta+Enter \i Shift+Enter \i Shift+Enter \i (none) \endtable Note that, since the key sequences used for the standard shortcuts differ @@ -481,9 +501,9 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::InsertParagraphSeparator,0, Qt::Key_Return, QApplicationPrivate::KB_All}, {QKeySequence::InsertParagraphSeparator,0, Qt::Key_Enter, QApplicationPrivate::KB_All}, {QKeySequence::Delete, 1, Qt::Key_Delete, QApplicationPrivate::KB_All}, - {QKeySequence::MoveToStartOfLine, 0, Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, + {QKeySequence::MoveToStartOfLine, 0, Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, {QKeySequence::MoveToStartOfDocument, 0, Qt::Key_Home, QApplicationPrivate::KB_Mac}, - {QKeySequence::MoveToEndOfLine, 0, Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, + {QKeySequence::MoveToEndOfLine, 0, Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, {QKeySequence::MoveToEndOfDocument, 0, Qt::Key_End, QApplicationPrivate::KB_Mac}, {QKeySequence::MoveToPreviousChar, 0, Qt::Key_Left, QApplicationPrivate::KB_All}, {QKeySequence::MoveToPreviousLine, 0, Qt::Key_Up, QApplicationPrivate::KB_All}, @@ -492,6 +512,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::MoveToPreviousPage, 1, Qt::Key_PageUp, QApplicationPrivate::KB_All}, {QKeySequence::MoveToNextPage, 1, Qt::Key_PageDown, QApplicationPrivate::KB_All}, {QKeySequence::HelpContents, 0, Qt::Key_F1, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, + {QKeySequence::HelpContents, 0, Qt::Key_F2, QApplicationPrivate::KB_S60}, {QKeySequence::FindNext, 0, Qt::Key_F3, QApplicationPrivate::KB_X11}, {QKeySequence::FindNext, 1, Qt::Key_F3, QApplicationPrivate::KB_Win}, {QKeySequence::Refresh, 0, Qt::Key_F5, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, @@ -502,13 +523,14 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::PreviousChild, 0, Qt::Key_Back, QApplicationPrivate::KB_All}, {QKeySequence::NextChild, 0, Qt::Key_Forward, QApplicationPrivate::KB_All}, {QKeySequence::Forward, 0, Qt::SHIFT | Qt::Key_Backspace, QApplicationPrivate::KB_Win}, + {QKeySequence::Delete, 0, Qt::SHIFT | Qt::Key_Backspace, QApplicationPrivate::KB_S60}, {QKeySequence::InsertLineSeparator, 0, Qt::SHIFT | Qt::Key_Return, QApplicationPrivate::KB_All}, {QKeySequence::InsertLineSeparator, 0, Qt::SHIFT | Qt::Key_Enter, QApplicationPrivate::KB_All}, {QKeySequence::Paste, 0, Qt::SHIFT | Qt::Key_Insert, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, {QKeySequence::Cut, 0, Qt::SHIFT | Qt::Key_Delete, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, //## Check if this should work on mac - {QKeySequence::SelectStartOfLine, 0, Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, + {QKeySequence::SelectStartOfLine, 0, Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, {QKeySequence::SelectStartOfDocument, 0, Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Mac}, - {QKeySequence::SelectEndOfLine, 0, Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, + {QKeySequence::SelectEndOfLine, 0, Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, {QKeySequence::SelectEndOfDocument, 0, Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Mac}, {QKeySequence::SelectPreviousChar, 0, Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_All}, {QKeySequence::SelectPreviousLine, 0, Qt::SHIFT | Qt::Key_Up, QApplicationPrivate::KB_All}, @@ -521,6 +543,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::FindPrevious, 1, Qt::SHIFT | Qt::Key_F3, QApplicationPrivate::KB_Win}, {QKeySequence::ZoomIn, 1, Qt::CTRL | Qt::Key_Plus, QApplicationPrivate::KB_All}, {QKeySequence::NextChild, 0, Qt::CTRL | Qt::Key_Comma, QApplicationPrivate::KB_KDE}, + {QKeySequence::Preferences, 0, Qt::CTRL | Qt::Key_Comma, QApplicationPrivate::KB_Mac}, {QKeySequence::ZoomOut, 1, Qt::CTRL | Qt::Key_Minus, QApplicationPrivate::KB_All}, {QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::Key_Period, QApplicationPrivate::KB_KDE}, {QKeySequence::HelpContents, 1, Qt::CTRL | Qt::Key_Question, QApplicationPrivate::KB_Mac}, @@ -538,6 +561,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::New, 1, Qt::CTRL | Qt::Key_N, QApplicationPrivate::KB_All}, {QKeySequence::Open, 1, Qt::CTRL | Qt::Key_O, QApplicationPrivate::KB_All}, {QKeySequence::Print, 1, Qt::CTRL | Qt::Key_P, QApplicationPrivate::KB_All}, + {QKeySequence::Quit, 0, Qt::CTRL | Qt::Key_Q, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_KDE | QApplicationPrivate::KB_Mac}, {QKeySequence::Refresh, 1, Qt::CTRL | Qt::Key_R, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_Mac}, {QKeySequence::Replace, 0, Qt::CTRL | Qt::Key_R, QApplicationPrivate::KB_KDE}, {QKeySequence::Save, 1, Qt::CTRL | Qt::Key_S, QApplicationPrivate::KB_All}, @@ -559,15 +583,15 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::DeleteStartOfWord, 0, Qt::CTRL | Qt::Key_Backspace, QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_Win}, {QKeySequence::Copy, 0, Qt::CTRL | Qt::Key_Insert, QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_Win}, {QKeySequence::DeleteEndOfWord, 0, Qt::CTRL | Qt::Key_Delete, QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_Win}, - {QKeySequence::MoveToStartOfDocument, 0, Qt::CTRL | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, - {QKeySequence::MoveToEndOfDocument, 0, Qt::CTRL | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, + {QKeySequence::MoveToStartOfDocument, 0, Qt::CTRL | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, + {QKeySequence::MoveToEndOfDocument, 0, Qt::CTRL | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, {QKeySequence::Back, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Mac}, - {QKeySequence::MoveToPreviousWord, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, + {QKeySequence::MoveToPreviousWord, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, {QKeySequence::MoveToStartOfLine, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Mac }, {QKeySequence::MoveToStartOfDocument, 1, Qt::CTRL | Qt::Key_Up, QApplicationPrivate::KB_Mac}, {QKeySequence::Forward, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Mac}, {QKeySequence::MoveToEndOfLine, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Mac }, - {QKeySequence::MoveToNextWord, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, + {QKeySequence::MoveToNextWord, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, {QKeySequence::MoveToEndOfDocument, 1, Qt::CTRL | Qt::Key_Down, QApplicationPrivate::KB_Mac}, {QKeySequence::Close, 1, Qt::CTRL | Qt::Key_F4, QApplicationPrivate::KB_Win}, {QKeySequence::Close, 0, Qt::CTRL | Qt::Key_F4, QApplicationPrivate::KB_Mac}, @@ -580,12 +604,12 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::Redo, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, //different priority from above {QKeySequence::PreviousChild, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, {QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Mac },//different priority from above - {QKeySequence::SelectStartOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, - {QKeySequence::SelectEndOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, - {QKeySequence::SelectPreviousWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, + {QKeySequence::SelectStartOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, + {QKeySequence::SelectEndOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, + {QKeySequence::SelectPreviousWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, {QKeySequence::SelectStartOfLine, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Mac }, {QKeySequence::SelectStartOfDocument, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Up, QApplicationPrivate::KB_Mac}, - {QKeySequence::SelectNextWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, + {QKeySequence::SelectNextWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, {QKeySequence::SelectEndOfLine, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Mac }, {QKeySequence::SelectEndOfDocument, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Down, QApplicationPrivate::KB_Mac}, {QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_F6, QApplicationPrivate::KB_Win}, @@ -669,12 +693,14 @@ const uint QKeySequencePrivate::numberOfKeyBindings = sizeof(QKeySequencePrivate \value NextChild Navigate to next tab or child window. \value Open Open document. \value Paste Paste. + \value Preferences Open the preferences dialog. \value PreviousChild Navigate to previous tab or child window. \value Print Print document. + \value Quit Quit the application. \value Redo Redo. \value Refresh Refresh or reload current document. \value Replace Find and replace. - \value SaveAs Save document after prompting the user for a file name. + \value SaveAs Save document after prompting the user for a file name. \value Save Save document. \value SelectAll Select all text. \value SelectEndOfBlock Extend selection to the end of a text block. This shortcut is only used on OS X. @@ -726,7 +752,9 @@ QKeySequence::QKeySequence(StandardKey key) */ QKeySequence::QKeySequence() { - d = new QKeySequencePrivate(); + static QKeySequencePrivate shared_empty; + d = &shared_empty; + d->ref.ref(); } /*! @@ -780,6 +808,21 @@ QKeySequence::QKeySequence(const QKeySequence& keysequence) d->ref.ref(); } +#ifdef Q_WS_MAC +static inline int maybeSwapShortcut(int shortcut) +{ + if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { + uint oldshortcut = shortcut; + shortcut &= ~(Qt::CTRL | Qt::META); + if (oldshortcut & Qt::CTRL) + shortcut |= Qt::META; + if (oldshortcut & Qt::META) + shortcut |= Qt::CTRL; + } + return shortcut; +} +#endif + /*! \since 4.2 @@ -796,10 +839,16 @@ QList<QKeySequence> QKeySequence::keyBindings(StandardKey key) for (uint i = 0; i < QKeySequencePrivate::numberOfKeyBindings ; ++i) { QKeyBinding keyBinding = QKeySequencePrivate::keyBindings[i]; if (keyBinding.standardKey == key && (keyBinding.platform & platform)) { - if (keyBinding.priority > 0) - list.prepend(QKeySequence(QKeySequencePrivate::keyBindings[i].shortcut)); - else - list.append(QKeySequence(QKeySequencePrivate::keyBindings[i].shortcut)); + uint shortcut = +#ifdef Q_WS_MAC + maybeSwapShortcut(QKeySequencePrivate::keyBindings[i].shortcut); +#else + QKeySequencePrivate::keyBindings[i].shortcut; +#endif + if (keyBinding.priority > 0) + list.prepend(QKeySequence(shortcut)); + else + list.append(QKeySequence(shortcut)); } } return list; @@ -967,9 +1016,16 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence gmodifs = globalModifs(); if (gmodifs->isEmpty()) { #ifdef Q_WS_MAC - *gmodifs << QModifKeyName(Qt::CTRL, QChar(kCommandUnicode)); + const bool dontSwap = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta); + if (dontSwap) + *gmodifs << QModifKeyName(Qt::META, QChar(kCommandUnicode)); + else + *gmodifs << QModifKeyName(Qt::CTRL, QChar(kCommandUnicode)); *gmodifs << QModifKeyName(Qt::ALT, QChar(kOptionUnicode)); - *gmodifs << QModifKeyName(Qt::META, QChar(kControlUnicode)); + if (dontSwap) + *gmodifs << QModifKeyName(Qt::CTRL, QChar(kControlUnicode)); + else + *gmodifs << QModifKeyName(Qt::META, QChar(kControlUnicode)); *gmodifs << QModifKeyName(Qt::SHIFT, QChar(kShiftUnicode)); #endif *gmodifs << QModifKeyName(Qt::CTRL, QLatin1String("ctrl+")) @@ -1067,8 +1123,6 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence if (found) break; } -#ifdef Q_WS_MAC -#endif } return ret; } @@ -1097,15 +1151,30 @@ QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat QString s; #if defined(Q_WS_MAC) if (nativeText) { - // On MAC the order is Meta, Alt, Shift, Control. - if ((key & Qt::META) == Qt::META) - s += macSymbolForQtKey(Qt::Key_Meta); - if ((key & Qt::ALT) == Qt::ALT) - s += macSymbolForQtKey(Qt::Key_Alt); - if ((key & Qt::SHIFT) == Qt::SHIFT) - s += macSymbolForQtKey(Qt::Key_Shift); - if ((key & Qt::CTRL) == Qt::CTRL) - s += macSymbolForQtKey(Qt::Key_Control); + // On Mac OS X the order (by default) is Meta, Alt, Shift, Control. + // If the AA_MacDontSwapCtrlAndMeta is enabled, then the order + // is Ctrl, Alt, Shift, Meta. The macSymbolForQtKey does this swap + // for us, which means that we have to adjust our order here. + // The upshot is a lot more infrastructure to keep the number of + // if tests down and the code relatively clean. + static const int ModifierOrder[] = { Qt::META, Qt::ALT, Qt::SHIFT, Qt::CTRL, 0 }; + static const int QtKeyOrder[] = { Qt::Key_Meta, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Control, 0 }; + static const int DontSwapModifierOrder[] = { Qt::CTRL, Qt::ALT, Qt::SHIFT, Qt::META, 0 }; + static const int DontSwapQtKeyOrder[] = { Qt::Key_Control, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Meta, 0 }; + const int *modifierOrder; + const int *qtkeyOrder; + if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { + modifierOrder = DontSwapModifierOrder; + qtkeyOrder = DontSwapQtKeyOrder; + } else { + modifierOrder = ModifierOrder; + qtkeyOrder = QtKeyOrder; + } + + for (int i = 0; modifierOrder[i] != 0; ++i) { + if (key & modifierOrder[i]) + s += qt_macSymbolForQtKey(qtkeyOrder[i]); + } } else #endif { @@ -1138,7 +1207,7 @@ QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat int i=0; #if defined(Q_WS_MAC) if (nativeText) { - QChar ch = macSymbolForQtKey(key); + QChar ch = qt_macSymbolForQtKey(key); if (!ch.isNull()) p = ch; else diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h index b9a326c..157249c 100644 --- a/src/gui/kernel/qkeysequence.h +++ b/src/gui/kernel/qkeysequence.h @@ -136,7 +136,9 @@ public: DeleteEndOfLine, InsertParagraphSeparator, InsertLineSeparator, - SaveAs + SaveAs, + Preferences, + Quit }; QKeySequence(); diff --git a/src/gui/kernel/qlayout.cpp b/src/gui/kernel/qlayout.cpp index ee16d1c..e58a995 100644 --- a/src/gui/kernel/qlayout.cpp +++ b/src/gui/kernel/qlayout.cpp @@ -61,7 +61,10 @@ static int menuBarHeightForWidth(QWidget *menubar, int w) int result = menubar->heightForWidth(qMax(w, menubar->minimumWidth())); if (result != -1) return result; - result = menubar->sizeHint().height(); + result = menubar->sizeHint() + .expandedTo(menubar->minimumSize()) + .expandedTo(menubar->minimumSizeHint()) + .boundedTo(menubar->maximumSize()).height(); if (result != -1) return result; } @@ -72,7 +75,6 @@ static int menuBarHeightForWidth(QWidget *menubar, int w) \class QLayout \brief The QLayout class is the base class of geometry managers. - \ingroup appearance \ingroup geomanagement This is an abstract base class inherited by the concrete classes @@ -80,7 +82,7 @@ static int menuBarHeightForWidth(QWidget *menubar, int w) For users of QLayout subclasses or of QMainWindow there is seldom any need to use the basic functions provided by QLayout, such as - setSizeConstraint() or setMenuBar(). See \l{Layout Classes} + setSizeConstraint() or setMenuBar(). See \l{Layout Management} for more information. To make your own layout manager, implement the functions @@ -95,7 +97,7 @@ static int menuBarHeightForWidth(QWidget *menubar, int w) Geometry management stops when the layout manager is deleted. - \sa QLayoutItem, {Layout Classes}, {Basic Layouts Example}, + \sa QLayoutItem, {Layout Management}, {Basic Layouts Example}, {Border Layout Example}, {Flow Layout Example} */ @@ -145,7 +147,12 @@ QLayout::QLayout(QLayoutPrivate &dd, QLayout *lay, QWidget *w) } else { d->topLevel = true; w->d_func()->layout = this; - invalidate(); + QT_TRY { + invalidate(); + } QT_CATCH(...) { + w->d_func()->layout = 0; + QT_RETHROW; + } } } } @@ -230,7 +237,12 @@ QLayout::QLayout(QWidget *parent, int margin, int spacing, const char *name) } else { d->topLevel = true; parent->d_func()->layout = this; - invalidate(); + QT_TRY { + invalidate(); + } QT_CATCH(...) { + parent->d_func()->layout = 0; + QT_RETHROW; + } } } } @@ -1583,8 +1595,6 @@ QDataStream &operator>>(QDataStream &stream, QSizePolicy &policy) { return stream >> policy.data; } - -#endif - +#endif // QT_NO_DATASTREAM QT_END_NAMESPACE diff --git a/src/gui/kernel/qlayoutengine.cpp b/src/gui/kernel/qlayoutengine.cpp index ed50263..aaac965 100644 --- a/src/gui/kernel/qlayoutengine.cpp +++ b/src/gui/kernel/qlayoutengine.cpp @@ -329,7 +329,7 @@ void qGeomCalc(QVector<QLayoutStruct> &chain, int start, int count, qDebug() << "qGeomCalc" << "start" << start << "count" << count << "pos" << pos << "space" << space << "spacer" << spacer; for (i = start; i < start + count; ++i) { - qDebug() << i << ":" << chain[i].minimumSize << chain[i].smartSizeHint() + qDebug() << i << ':' << chain[i].minimumSize << chain[i].smartSizeHint() << chain[i].maximumSize << "stretch" << chain[i].stretch << "empty" << chain[i].empty << "expansive" << chain[i].expansive << "spacing" << chain[i].spacing; diff --git a/src/gui/kernel/qlayoutitem.cpp b/src/gui/kernel/qlayoutitem.cpp index 43758a6..2774d83 100644 --- a/src/gui/kernel/qlayoutitem.cpp +++ b/src/gui/kernel/qlayoutitem.cpp @@ -54,7 +54,8 @@ QT_BEGIN_NAMESPACE inline static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect) { - return priv->fromOrToLayoutItemRect(rect, -1); + return rect.adjusted(priv->leftLayoutItemMargin, priv->topLayoutItemMargin, + -priv->rightLayoutItemMargin, -priv->bottomLayoutItemMargin); } inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size) @@ -64,7 +65,8 @@ inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size) inline static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect) { - return priv->fromOrToLayoutItemRect(rect, +1); + return rect.adjusted(-priv->leftLayoutItemMargin, -priv->topLayoutItemMargin, + priv->rightLayoutItemMargin, priv->bottomLayoutItemMargin); } inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size) @@ -85,7 +87,6 @@ QSizePolicy::operator QVariant() const \brief The QLayoutItem class provides an abstract item that a QLayout manipulates. - \ingroup appearance \ingroup geomanagement This is used by custom layouts. @@ -114,7 +115,6 @@ QSizePolicy::operator QVariant() const /*! \class QSpacerItem - \ingroup appearance \ingroup geomanagement \brief The QSpacerItem class provides blank space in a layout. @@ -142,7 +142,6 @@ QSizePolicy::operator QVariant() const /*! \class QWidgetItem - \ingroup appearance \ingroup geomanagement \brief The QWidgetItem class is a layout item that represents a widget. diff --git a/src/gui/kernel/qmime_mac.cpp b/src/gui/kernel/qmime_mac.cpp index dcc04af..e86564f 100644 --- a/src/gui/kernel/qmime_mac.cpp +++ b/src/gui/kernel/qmime_mac.cpp @@ -68,9 +68,10 @@ #include "qmap.h" #include <private/qt_mac_p.h> + #ifdef Q_WS_MAC32 #include <QuickTime/QuickTime.h> -#include "qlibrary.h" +#include <qlibrary.h> #endif QT_BEGIN_NAMESPACE @@ -127,32 +128,43 @@ CFStringRef qt_mac_mime_typeUTI = CFSTR("com.pasteboard.trolltech.marker"); /*! \class QMacPasteboardMime - \brief The QMacPasteboardMime class maps open-standard MIME to Mac flavors. + \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 io + \ingroup draganddrop - \ingroup misc - Qt's drag and drop support and clipboard facilities use the MIME - standard. On X11, this maps trivially to the Xdnd protocol, but on - Mac although some applications use MIME types to describe clipboard - formats, others use arbitrary non-standardized naming conventions, - or unnamed built-in Mac formats. + 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. - By instantiating subclasses of QMacPasteboardMime that provide conversions - between Mac flavors and MIME formats, you can convert proprietary - clipboard formats to MIME formats. + A subclass of QMacPasteboardMime will automatically be registered, and active, upon instantiation. - Qt has predefined support for the following Mac flavors: + Qt has predefined support for the following UTIs: \list - \i kScrapFlavorTypeUnicode - converted to "text/plain;charset=ISO-10646-UCS-2" - \i kScrapFlavorTypeText - converted to "text/plain;charset=system" or "text/plain" - \i kScrapFlavorTypePicture - converted to "application/x-qt-image" - \i typeFileURL - converted to "text/uri-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 com.apple.traditional-mac-plain-text - converts to "text/plain" + \i com.apple.pict - converts to "application/x-qt-image" \endlist - You can check if a MIME type is convertible using canConvert() and - can perform conversions with convertToMime() and convertFromMime(). + 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 @@ -206,7 +218,7 @@ QString QMacPasteboardMimeAny::flavorFor(const QString &mime) if(mime == QLatin1String("application/x-qt-mime-type-name")) return QString(); QString ret = QLatin1String("com.trolltech.anymime.") + mime; - return ret.replace(QLatin1String("/"), QLatin1String("--")); + return ret.replace(QLatin1Char('/'), QLatin1String("--")); } QString QMacPasteboardMimeAny::mimeFor(QString flav) @@ -382,7 +394,7 @@ QString QMacPasteboardMimeUnicodeText::flavorFor(const QString &mime) int i = mime.indexOf(QLatin1String("charset=")); if (i >= 0) { QString cs(mime.mid(i+8).toLower()); - i = cs.indexOf(QLatin1String(";")); + i = cs.indexOf(QLatin1Char(';')); if (i>=0) cs = cs.left(i); if (cs == QLatin1String("system")) @@ -495,6 +507,8 @@ QList<QByteArray> QMacPasteboardMimeHTMLText::convertFromMime(const QString &mim #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); @@ -625,7 +639,9 @@ QList<QByteArray> QMacPasteboardMimePict::convertFromMime(const QString &mime, Q DisposeHandle(pic); return ret; } -#endif + + +#endif //Q_WS_MAC32 class QMacPasteboardMimeTiff : public QMacPasteboardMime { public: @@ -672,33 +688,11 @@ QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteA return ret; const QByteArray &a = data.first(); QCFType<CGImageRef> image; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - QCFType<CFDataRef> data = CFDataCreateWithBytesNoCopy(0, - reinterpret_cast<const UInt8 *>(a.constData()), - a.size(), kCFAllocatorNull); - QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(data, 0); - image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0); - } else -#endif - { -#ifdef Q_WS_MAC32 - if (resolveMimeQuickTimeSymbols()) { - Handle tiff = NewHandle(a.size()); - memcpy(*tiff, a.constData(), a.size()); - GraphicsImportComponent graphicsImporter; - ComponentResult result = OpenADefaultComponent(GraphicsImporterComponentType, - kQTFileTypeTIFF, &graphicsImporter); - if (!result) - result = ptrGraphicsImportSetDataHandle(graphicsImporter, tiff); - if (!result) - result = ptrGraphicsImportCreateCGImage(graphicsImporter, &image, - kGraphicsImportCreateCGImageUsingCurrentSettings); - CloseComponent(graphicsImporter); - DisposeHandle(tiff); - } -#endif - } + 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()); @@ -841,6 +835,80 @@ QList<QByteArray> QMacPasteboardMimeFileUri::convertFromMime(const QString &mime 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; +} + #ifdef QT3_SUPPORT class QMacPasteboardMimeQt3Any : public QMacPasteboardMime { private: @@ -1037,12 +1105,16 @@ void QMacPasteboardMime::initialize() //standard types that we wrap new QMacPasteboardMimeTiff; #ifdef Q_WS_MAC32 - new QMacPasteboardMimePict; + // 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; //make sure our "non-standard" types are always last! --Sam new QMacPasteboardMimeAny; diff --git a/src/gui/kernel/qmime_win.cpp b/src/gui/kernel/qmime_win.cpp index 6633dfd..e81d511 100644 --- a/src/gui/kernel/qmime_win.cpp +++ b/src/gui/kernel/qmime_win.cpp @@ -170,7 +170,7 @@ static QByteArray getData(int cf, IDataObject *pDataObj) if (pDataObj->GetData(&formatetc, &s) == S_OK) { char szBuffer[4096]; ULONG actualRead = 0; - LARGE_INTEGER pos = {0, 0}; + LARGE_INTEGER pos = {{0, 0}}; //Move to front (can fail depending on the data model implemented) HRESULT hr = s.pstm->Seek(pos, STREAM_SEEK_SET, NULL); while(SUCCEEDED(hr)){ @@ -219,9 +219,7 @@ Q_GLOBAL_STATIC(QWindowsMimeList, theMimeList); /*! \class QWindowsMime \brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats. - \ingroup io \ingroup draganddrop - \ingroup misc Qt's drag-and-drop and clipboard facilities use the MIME standard. On X11, this maps trivially to the Xdnd protocol, but on Windows @@ -281,11 +279,7 @@ QWindowsMime::~QWindowsMime() */ int QWindowsMime::registerMimeType(const QString &mime) { -#ifdef Q_OS_WINCE int f = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (mime.utf16())); -#else - int f = RegisterClipboardFormatA(mime.toLocal8Bit()); -#endif if (!f) qErrnoWarning("QWindowsMime::registerMimeType: Failed to register clipboard format"); @@ -401,9 +395,9 @@ QStringList QWindowsMime::allMimesForFormats(IDataObject *pDataObj) while (S_OK == fmtenum->Next(1, &fmtetc, 0)) { #if defined(QMIME_DEBUG) && !defined(Q_OS_WINCE) qDebug("QWindowsMime::allMimesForFormats()"); - char buf[256] = {0}; - GetClipboardFormatNameA(fmtetc.cfFormat, buf, 255); - qDebug("CF = %d : %s", fmtetc.cfFormat, buf); + wchar_t buf[256] = {0}; + GetClipboardFormatName(fmtetc.cfFormat, buf, 255); + qDebug("CF = %d : %s", fmtetc.cfFormat, QString::fromWCharArray(buf)); #endif for (int i=mimes.size()-1; i>=0; --i) { QString format = mimes.at(i)->mimeForFormat(fmtetc); @@ -504,7 +498,7 @@ bool QWindowsMimeText::convertFromMime(const FORMATETC &formatetc, const QMimeDa ++u; } res.truncate(ri); - const int byteLength = res.length()*2; + const int byteLength = res.length() * sizeof(ushort); QByteArray r(byteLength + 2, '\0'); memcpy(r.data(), res.unicode(), byteLength); r[byteLength] = 0; @@ -549,7 +543,7 @@ QVariant QWindowsMimeText::convertToMime(const QString &mime, LPDATAOBJECT pData QString str; QByteArray data = getData(CF_UNICODETEXT, pDataObj); if (!data.isEmpty()) { - str = QString::fromUtf16((const unsigned short *)data.data()); + str = QString::fromWCharArray((const wchar_t *)data.data()); str.replace(QLatin1String("\r\n"), QLatin1String("\n")); } else { data = getData(CF_TEXT, pDataObj); @@ -620,11 +614,7 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat for (int i=0; i<urls.size(); i++) { QString fn = QDir::toNativeSeparators(urls.at(i).toLocalFile()); if (!fn.isEmpty()) { - QT_WA({ - size += sizeof(TCHAR)*(fn.length()+1); - } , { - size += fn.toLocal8Bit().length()+1; - }); + size += sizeof(ushort) * (fn.length() + 1); fileNames.append(fn); } } @@ -636,36 +626,22 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat d->fNC = true; char* files = ((char*)d) + d->pFiles; - QT_WA({ - d->fWide = true; - TCHAR* f = (TCHAR*)files; - for (int i=0; i<fileNames.size(); i++) { - int l = fileNames.at(i).length(); - memcpy(f, fileNames.at(i).utf16(), l*sizeof(TCHAR)); - f += l; - *f++ = 0; - } - *f = 0; - } , { - d->fWide = false; - char* f = files; - for (int i=0; i<fileNames.size(); i++) { - QByteArray c = fileNames.at(i).toLocal8Bit(); - if (!c.isEmpty()) { - int l = c.length(); - memcpy(f, c.constData(), l); - f += l; - *f++ = 0; - } - } - *f = 0; - }); + d->fWide = true; + wchar_t* f = (wchar_t*)files; + for (int i=0; i<fileNames.size(); i++) { + int l = fileNames.at(i).length(); + memcpy(f, fileNames.at(i).utf16(), l * sizeof(ushort)); + f += l; + *f++ = 0; + } + *f = 0; + return setData(result, pmedium); } else if (getCf(formatetc) == CF_INETURL_W) { QList<QUrl> urls = mimeData->urls(); QByteArray result; QString url = urls.at(0).toString(); - result = QByteArray((const char *)url.utf16(), url.length() * 2); + result = QByteArray((const char *)url.utf16(), url.length() * sizeof(ushort)); result.append('\0'); result.append('\0'); return setData(result, pmedium); @@ -720,15 +696,15 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD LPDROPFILES hdrop = (LPDROPFILES)data.data(); if (hdrop->fWide) { - const ushort* filesw = (const ushort*)(data.data() + hdrop->pFiles); - int i=0; + const wchar_t* filesw = (const wchar_t *)(data.data() + hdrop->pFiles); + int i = 0; while (filesw[i]) { - QString fileurl = QString::fromUtf16(filesw+i); + QString fileurl = QString::fromWCharArray(filesw + i); urls += QUrl::fromLocalFile(fileurl); i += fileurl.length()+1; } } else { - const char* files = (const char*)data.data() + hdrop->pFiles; + const char* files = (const char *)data.data() + hdrop->pFiles; int i=0; while (files[i]) { urls += QUrl::fromLocalFile(QString::fromLocal8Bit(files+i)); @@ -744,7 +720,7 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD QByteArray data = getData(CF_INETURL_W, pDataObj); if (data.isEmpty()) return QVariant(); - return QUrl(QString::fromUtf16((const unsigned short *)data.constData())); + return QUrl(QString::fromWCharArray((const wchar_t *)data.constData())); } else if (canGetData(CF_INETURL, pDataObj)) { QByteArray data = getData(CF_INETURL, pDataObj); if (data.isEmpty()) @@ -852,7 +828,7 @@ QVariant QWindowsMimeHtml::convertToMime(const QString &mime, IDataObject *pData if (end > start && start > 0) { html = "<!--StartFragment-->" + html.mid(start, end - start); html += "<!--EndFragment-->"; - html.replace("\r", ""); + html.replace('\r', ""); result = QString::fromUtf8(html); } } @@ -913,11 +889,7 @@ private: QWindowsMimeImage::QWindowsMimeImage() { -#ifdef Q_OS_WINCE - CF_PNG = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (QString::fromLatin1("PNG").utf16())); -#else - CF_PNG = RegisterClipboardFormatA("PNG"); -#endif + CF_PNG = RegisterClipboardFormat(L"PNG"); } QVector<FORMATETC> QWindowsMimeImage::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const @@ -1114,7 +1086,7 @@ bool QBuiltInMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData ++u; } res.truncate(ri); - const int byteLength = res.length()*2; + const int byteLength = res.length() * sizeof(ushort); QByteArray r(byteLength + 2, '\0'); memcpy(r.data(), res.unicode(), byteLength); r[byteLength] = 0; @@ -1154,8 +1126,8 @@ QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDat qDebug("QBuiltInMimes::convertToMime()"); #endif if (mimeType == QLatin1String("text/html") && preferredType == QVariant::String) { - // text/html is in wide chars on windows (compatible with mozillia) - val = QString::fromUtf16((const unsigned short *)data.data()); + // text/html is in wide chars on windows (compatible with Mozilla) + val = QString::fromWCharArray((const wchar_t *)data.data()); } else { val = data; // it should be enough to return the data and let QMimeData do the rest. } @@ -1262,16 +1234,16 @@ QVector<FORMATETC> QLastResortMimes::formatsForMime(const QString &mimeType, con } return formatetcs; } -static const char *x_qt_windows_mime = "application/x-qt-windows-mime;value=\""; +static const char x_qt_windows_mime[] = "application/x-qt-windows-mime;value=\""; -bool isCustomMimeType(const QString &mimeType) +static bool isCustomMimeType(const QString &mimeType) { return mimeType.startsWith(QLatin1String(x_qt_windows_mime), Qt::CaseInsensitive); } -QString customMimeType(const QString &mimeType) +static QString customMimeType(const QString &mimeType) { - int len = QString(QLatin1String(x_qt_windows_mime)).length(); + int len = sizeof(x_qt_windows_mime) - 1; int n = mimeType.lastIndexOf(QLatin1Char('\"'))-len; return mimeType.mid(len, n); } @@ -1280,11 +1252,7 @@ bool QLastResortMimes::canConvertToMime(const QString &mimeType, IDataObject *pD { if (isCustomMimeType(mimeType)) { QString clipFormat = customMimeType(mimeType); -#ifdef Q_OS_WINCE int cf = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (clipFormat.utf16())); -#else - int cf = RegisterClipboardFormatA(clipFormat.toLocal8Bit()); -#endif return canGetData(cf, pDataObj); } else if (formats.keys(mimeType).isEmpty()) { // if it is not in there then register it an see if we can get it @@ -1304,11 +1272,7 @@ QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *p QByteArray data; if (isCustomMimeType(mimeType)) { QString clipFormat = customMimeType(mimeType); -#ifdef Q_OS_WINCE int cf = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (clipFormat.utf16())); -#else - int cf = RegisterClipboardFormatA(clipFormat.toLocal8Bit()); -#endif data = getData(cf, pDataObj); } else if (formats.keys(mimeType).isEmpty()) { int cf = QWindowsMime::registerMimeType(mimeType); @@ -1325,46 +1289,38 @@ QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *p QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const { QString format = formats.value(getCf(formatetc)); - if (format.isEmpty()) { - QByteArray ba; - QString clipFormat; - int len; - QT_WA({ - ba.resize(256*2); - len = GetClipboardFormatNameW(getCf(formatetc), (TCHAR*)ba.data(), 255); - if (len) - clipFormat = QString::fromUtf16((ushort *)ba.data(), len); - } , { - ba.resize(256); - len = GetClipboardFormatNameA(getCf(formatetc), ba.data(), 255); - if (len) - clipFormat = QString::fromLocal8Bit(ba.data(), len); - }); - if (len) { + if (!format.isEmpty()) + return format; + + wchar_t buffer[256]; + int len = GetClipboardFormatName(getCf(formatetc), buffer, 256); + + if (len) { + QString clipFormat = QString::fromWCharArray(buffer, len); #ifndef QT_NO_DRAGANDDROP - if (QInternalMimeData::canReadData(clipFormat)) - format = clipFormat; - else if((formatetc.cfFormat >= 0xC000)){ - //create the mime as custom. not registered. - if (!excludeList.contains(clipFormat, Qt::CaseInsensitive)) { - //check if this is a mime type - bool ianaType = false; - int sz = ianaTypes.size(); - for (int i = 0; i < sz; i++) { - if (clipFormat.startsWith(ianaTypes[i], Qt::CaseInsensitive)) { - ianaType = true; - break; - } + if (QInternalMimeData::canReadData(clipFormat)) + format = clipFormat; + else if((formatetc.cfFormat >= 0xC000)){ + //create the mime as custom. not registered. + if (!excludeList.contains(clipFormat, Qt::CaseInsensitive)) { + //check if this is a mime type + bool ianaType = false; + int sz = ianaTypes.size(); + for (int i = 0; i < sz; i++) { + if (clipFormat.startsWith(ianaTypes[i], Qt::CaseInsensitive)) { + ianaType = true; + break; } - if (!ianaType) - format = QLatin1String(x_qt_windows_mime) + clipFormat + QLatin1Char('\"'); - else - format = clipFormat; } + if (!ianaType) + format = QLatin1String(x_qt_windows_mime) + clipFormat + QLatin1Char('\"'); + else + format = clipFormat; } -#endif //QT_NO_DRAGANDDROP } +#endif //QT_NO_DRAGANDDROP } + return format; } diff --git a/src/gui/kernel/qmotifdnd_x11.cpp b/src/gui/kernel/qmotifdnd_x11.cpp index bdf7092..5783970 100644 --- a/src/gui/kernel/qmotifdnd_x11.cpp +++ b/src/gui/kernel/qmotifdnd_x11.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ /* The following copyright notice pertains to the code as contributed -to Nokia, not to Nokia's modifications. It is replicated +to Qt, not to Nokia's modifications. It is replicated in doc/dnd.doc, where the documentation system can see it. */ /* Copyright 1996 Daniel Dardailler. diff --git a/src/gui/kernel/qmultitouch_mac.mm b/src/gui/kernel/qmultitouch_mac.mm new file mode 100644 index 0000000..8261658 --- /dev/null +++ b/src/gui/kernel/qmultitouch_mac.mm @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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(); + QList<QCocoaTouch *> list = _currentTouches.values(); + 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/kernel/qmultitouch_mac_p.h b/src/gui/kernel/qmultitouch_mac_p.h new file mode 100644 index 0000000..83400cd --- /dev/null +++ b/src/gui/kernel/qmultitouch_mac_p.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp index 4ea5685..4c7a6a6 100644 --- a/src/gui/kernel/qpalette.cpp +++ b/src/gui/kernel/qpalette.cpp @@ -125,7 +125,7 @@ QDataStream &operator>>(QDataStream &s, QColorGroup &g) { return qt_stream_in_qcolorgroup(s, g); } -#endif +#endif // QT_NO_DATASTREAM /*! Constructs a palette with the specified \a active, \a disabled and @@ -158,7 +158,7 @@ void QPalette::setColorGroup(ColorGroup cg, const QColorGroup &g) g.brush(LinkVisited), g.brush(ToolTipBase), g.brush(ToolTipText)); } -#endif +#endif // QT3_SUPPORT /*! \fn const QColor &QPalette::color(ColorRole role) const @@ -399,8 +399,8 @@ void QPalette::setColorGroup(ColorGroup cg, const QColorGroup &g) \ingroup appearance \ingroup shared - \ingroup multimedia - \mainclass + \ingroup painting + A palette consists of three color groups: \e Active, \e Disabled, and \e Inactive. All widgets in Qt contain a palette and diff --git a/src/gui/kernel/qshortcut.cpp b/src/gui/kernel/qshortcut.cpp index ea08c6c..69efe01 100644 --- a/src/gui/kernel/qshortcut.cpp +++ b/src/gui/kernel/qshortcut.cpp @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE \brief The QShortcut class is used to create keyboard shortcuts. \ingroup events - \mainclass + The QShortcut class provides a way of connecting keyboard shortcuts to Qt's \l{signals and slots} mechanism, so that @@ -163,7 +163,6 @@ public: void QShortcutPrivate::redoGrab(QShortcutMap &map) { Q_Q(QShortcut); - QWidget *parent = q->parentWidget(); if (!parent) { qWarning("QShortcut: No widget parent defined"); return; diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp index b8cee02..d2779e0 100644 --- a/src/gui/kernel/qshortcutmap.cpp +++ b/src/gui/kernel/qshortcutmap.cpp @@ -61,8 +61,6 @@ QT_BEGIN_NAMESPACE -extern bool qt_mac_no_native_menubar; // qmenu_mac.cpp - // To enable verbose output uncomment below //#define DEBUG_QSHORTCUTMAP @@ -101,17 +99,17 @@ struct QShortcutEntry QObject *owner; }; -#ifndef QT_NO_DEBUG_STREAM +#if 0 //ndef QT_NO_DEBUG_STREAM /*! \internal QDebug operator<< for easy debug output of the shortcut entries. */ -QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se) { +static QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se) { if (!se) return dbg << "QShortcutEntry(0x0)"; dbg.nospace() << "QShortcutEntry(" << se->keyseq << "), id(" << se->id << "), enabled(" << se->enabled << "), autorepeat(" << se->autorepeat - << "), owner(" << se->owner << ")"; + << "), owner(" << se->owner << ')'; return dbg.space(); } #endif // QT_NO_DEBUGSTREAM @@ -148,9 +146,8 @@ public: QShortcutMap constructor. */ QShortcutMap::QShortcutMap() + : d_ptr(new QShortcutMapPrivate(this)) { - d_ptr = new QShortcutMapPrivate(this); - Q_ASSERT(d_ptr != 0); resetState(); } @@ -159,8 +156,6 @@ QShortcutMap::QShortcutMap() */ QShortcutMap::~QShortcutMap() { - delete d_ptr; - d_ptr = 0; } /*! \internal @@ -630,13 +625,13 @@ QKeySequence::SequenceMatch QShortcutMap::matches(const QKeySequence &seq1, bool QShortcutMap::correctContext(const QShortcutEntry &item) const { Q_ASSERT_X(item.owner, "QShortcutMap", "Shortcut has no owner. Illegal map state!"); - QWidget *active_window = qApp->activeWindow(); + QWidget *active_window = QApplication::activeWindow(); // popups do not become the active window, // so we fake it here to get the correct context // for the shortcut system. - if (qApp->activePopupWidget()) - active_window = qApp->activePopupWidget(); + if (QApplication::activePopupWidget()) + active_window = QApplication::activePopupWidget(); if (!active_window) return false; @@ -660,7 +655,7 @@ bool QShortcutMap::correctWidgetContext(Qt::ShortcutContext context, QWidget *w, { bool visible = w->isVisible(); #ifdef Q_WS_MAC - if (!qt_mac_no_native_menubar && qobject_cast<QMenuBar *>(w)) + if (!qApp->testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w)) visible = true; #endif @@ -723,7 +718,7 @@ bool QShortcutMap::correctGraphicsWidgetContext(Qt::ShortcutContext context, QGr { bool visible = w->isVisible(); #ifdef Q_WS_MAC - if (!qt_mac_no_native_menubar && qobject_cast<QMenuBar *>(w)) + if (!qApp->testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w)) visible = true; #endif @@ -878,7 +873,7 @@ void QShortcutMap::dispatchEvent(QKeyEvent *e) qDebug().nospace() << "QShortcutMap::dispatchEvent(): Sending QShortcutEvent(\"" << (QString)next->keyseq << "\", " << next->id << ", " - << (bool)(enabledShortcuts>1) << ") to object(" << next->owner << ")"; + << (bool)(enabledShortcuts>1) << ") to object(" << next->owner << ')'; #endif QShortcutEvent se(next->keyseq, next->id, enabledShortcuts>1); QApplication::sendEvent(const_cast<QObject *>(next->owner), &se); diff --git a/src/gui/kernel/qshortcutmap_p.h b/src/gui/kernel/qshortcutmap_p.h index 0be45be..f90113f 100644 --- a/src/gui/kernel/qshortcutmap_p.h +++ b/src/gui/kernel/qshortcutmap_p.h @@ -55,6 +55,7 @@ #include "QtGui/qkeysequence.h" #include "QtCore/qvector.h" +#include "QtCore/qscopedpointer.h" QT_BEGIN_NAMESPACE @@ -104,7 +105,7 @@ private: #ifndef QT_NO_ACTION bool correctContext(Qt::ShortcutContext context,QAction *a, QWidget *active_window) const; #endif - QShortcutMapPrivate *d_ptr; + QScopedPointer<QShortcutMapPrivate> d_ptr; QKeySequence::SequenceMatch find(QKeyEvent *e); QKeySequence::SequenceMatch matches(const QKeySequence &seq1, const QKeySequence &seq2) const; diff --git a/src/gui/kernel/qsizepolicy.h b/src/gui/kernel/qsizepolicy.h index 8120ab8..4261dda 100644 --- a/src/gui/kernel/qsizepolicy.h +++ b/src/gui/kernel/qsizepolicy.h @@ -203,9 +203,11 @@ private: Q_DECLARE_OPERATORS_FOR_FLAGS(QSizePolicy::ControlTypes) +#ifndef QT_NO_DATASTREAM // implemented in qlayout.cpp Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QSizePolicy &); Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QSizePolicy &); +#endif inline void QSizePolicy::transpose() { Policy hData = horizontalPolicy(); diff --git a/src/gui/kernel/qsizepolicy.qdoc b/src/gui/kernel/qsizepolicy.qdoc new file mode 100644 index 0000000..6a739da --- /dev/null +++ b/src/gui/kernel/qsizepolicy.qdoc @@ -0,0 +1,521 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +/*! + \class QSizePolicy + \brief The QSizePolicy class is a layout attribute describing horizontal + and vertical resizing policy. + + \ingroup geomanagement + + The size policy of a widget is an expression of its willingness to + be resized in various ways, and affects how the widget is treated + by the \l{Layout Management}{layout engine}. Each widget returns a + QSizePolicy that describes the horizontal and vertical resizing + policy it prefers when being laid out. You can change this for + a specific widget by changing its QWidget::sizePolicy property. + + QSizePolicy contains two independent QSizePolicy::Policy values + and two stretch factors; one describes the widgets's horizontal + size policy, and the other describes its vertical size policy. It + also contains a flag to indicate whether the height and width of + its preferred size are related. + + The horizontal and vertical policies can be set in the + constructor, and altered using the setHorizontalPolicy() and + setVerticalPolicy() functions. The stretch factors can be set + using the setHorizontalStretch() and setVerticalStretch() + functions. The flag indicating whether the widget's + \l{QWidget::sizeHint()}{sizeHint()} is width-dependent (such as a + menu bar or a word-wrapping label) can be set using the + setHeightForWidth() function. + + The current size policies and stretch factors be retrieved using + the horizontalPolicy(), verticalPolicy(), horizontalStretch() and + verticalStretch() functions. Alternatively, use the transpose() + function to swap the horizontal and vertical policies and + stretches. The hasHeightForWidth() function returns the current + status of the flag indicating the size hint dependencies. + + Use the expandingDirections() function to determine whether the + associated widget can make use of more space than its + \l{QWidget::sizeHint()}{sizeHint()} function indicates, as well as + find out in which directions it can expand. + + Finally, the QSizePolicy class provides operators comparing this + size policy to a given policy, as well as a QVariant operator + storing this QSizePolicy as a QVariant object. + + \sa QSize, QWidget::sizeHint(), QWidget::sizePolicy, + QLayoutItem::sizeHint() +*/ + +/*! + \enum QSizePolicy::PolicyFlag + + These flags are combined together to form the various \l{Policy} + values: + + \value GrowFlag The widget can grow beyond its size hint if necessary. + \value ExpandFlag The widget should get as much space as possible. + \value ShrinkFlag The widget can shrink below its size hint if necessary. + \value IgnoreFlag The widget's size hint is ignored. The widget will get + as much space as possible. + + \sa Policy +*/ + +/*! + \enum QSizePolicy::Policy + + This enum describes the various per-dimension sizing types used + when constructing a QSizePolicy. + + \value Fixed The QWidget::sizeHint() is the only acceptable + alternative, so the widget can never grow or shrink (e.g. the + vertical direction of a push button). + + \value Minimum The sizeHint() is minimal, and sufficient. The + widget can be expanded, but there is no advantage to it being + larger (e.g. the horizontal direction of a push button). + It cannot be smaller than the size provided by sizeHint(). + + \value Maximum The sizeHint() is a maximum. The widget can be + shrunk any amount without detriment if other widgets need the + space (e.g. a separator line). + It cannot be larger than the size provided by sizeHint(). + + \value Preferred The sizeHint() is best, but the widget can be + shrunk and still be useful. The widget can be expanded, but there + is no advantage to it being larger than sizeHint() (the default + QWidget policy). + + \value Expanding The sizeHint() is a sensible size, but the + widget can be shrunk and still be useful. The widget can make use + of extra space, so it should get as much space as possible (e.g. + the horizontal direction of a horizontal slider). + + \value MinimumExpanding The sizeHint() is minimal, and sufficient. + The widget can make use of extra space, so it should get as much + space as possible (e.g. the horizontal direction of a horizontal + slider). + + \value Ignored The sizeHint() is ignored. The widget will get as + much space as possible. + + \sa PolicyFlag, setHorizontalPolicy(), setVerticalPolicy() +*/ + +/*! + \fn QSizePolicy::QSizePolicy() + + Constructs a QSizePolicy object with \l Fixed as its horizontal + and vertical policies. + + The policies can be altered using the setHorizontalPolicy() and + setVerticalPolicy() functions. Use the setHeightForWidth() + function if the preferred height of the widget is dependent on the + width of the widget (for example, a QLabel with line wrapping). + + \sa setHorizontalStretch(), setVerticalStretch() +*/ + +/*! + \fn QSizePolicy::QSizePolicy(Policy horizontal, Policy vertical) + + Constructs a QSizePolicy object with the given \a horizontal and + \a vertical policies, and DefaultType as the control type. + + Use setHeightForWidth() if the preferred height of the widget is + dependent on the width of the widget (for example, a QLabel with + line wrapping). + + \sa setHorizontalStretch(), setVerticalStretch() +*/ + +/*! + \fn QSizePolicy::QSizePolicy(Policy horizontal, Policy vertical, ControlType type) + \since 4.3 + + Constructs a QSizePolicy object with the given \a horizontal and + \a vertical policies, and the specified control \a type. + + Use setHeightForWidth() if the preferred height of the widget is + dependent on the width of the widget (for example, a QLabel with + line wrapping). + + \sa setHorizontalStretch(), setVerticalStretch(), controlType() +*/ + +/*! + \fn QSizePolicy::Policy QSizePolicy::horizontalPolicy() const + + Returns the horizontal component of the size policy. + + \sa setHorizontalPolicy(), verticalPolicy(), horizontalStretch() +*/ + +/*! + \fn QSizePolicy::Policy QSizePolicy::verticalPolicy() const + + Returns the vertical component of the size policy. + + \sa setVerticalPolicy(), horizontalPolicy(), verticalStretch() +*/ + +/*! + \fn void QSizePolicy::setHorizontalPolicy(Policy policy) + + Sets the horizontal component to the given \a policy. + + \sa horizontalPolicy(), setVerticalPolicy(), setHorizontalStretch() +*/ + +/*! + \fn void QSizePolicy::setVerticalPolicy(Policy policy) + + Sets the vertical component to the given \a policy. + + \sa verticalPolicy(), setHorizontalPolicy(), setVerticalStretch() +*/ + +/*! + \fn Qt::Orientations QSizePolicy::expandingDirections() const + + Returns whether a widget can make use of more space than the + QWidget::sizeHint() function indicates. + + A value of Qt::Horizontal or Qt::Vertical means that the widget + can grow horizontally or vertically (i.e., the horizontal or + vertical policy is \l Expanding or \l MinimumExpanding), whereas + Qt::Horizontal | Qt::Vertical means that it can grow in both + dimensions. + + \sa horizontalPolicy(), verticalPolicy() +*/ + +/*! + \fn ControlType QSizePolicy::controlType() const + \since 4.3 + + Returns the control type associated with the widget for which + this size policy applies. +*/ + +/*! + \fn void QSizePolicy::setControlType(ControlType type) + \since 4.3 + + Sets the control type associated with the widget for which this + size policy applies to \a type. + + The control type specifies the type of the widget for which this + size policy applies. It is used by some styles, notably + QMacStyle, to insert proper spacing between widgets. For example, + the Mac OS X Aqua guidelines specify that push buttons should be + separated by 12 pixels, whereas vertically stacked radio buttons + only require 6 pixels. + + \sa QStyle::layoutSpacing() +*/ + +/*! + \fn void QSizePolicy::setHeightForWidth(bool dependent) + + Sets the flag determining whether the widget's preferred height + depends on its width, to \a dependent. + + \sa hasHeightForWidth() +*/ + +/*! + \fn bool QSizePolicy::hasHeightForWidth() const + + Returns true if the widget's preferred height depends on its + width; otherwise returns false. + + \sa setHeightForWidth() +*/ + +/*! + \fn bool QSizePolicy::operator==(const QSizePolicy &other) const + + Returns true if this policy is equal to \a other; otherwise + returns false. + + \sa operator!=() +*/ + +/*! + \fn bool QSizePolicy::operator!=(const QSizePolicy &other) const + + Returns true if this policy is different from \a other; otherwise + returns false. + + \sa operator==() +*/ + +/*! + \fn int QSizePolicy::horizontalStretch() const + + Returns the horizontal stretch factor of the size policy. + + \sa setHorizontalStretch(), verticalStretch(), horizontalPolicy() +*/ + +/*! + \fn int QSizePolicy::verticalStretch() const + + Returns the vertical stretch factor of the size policy. + + \sa setVerticalStretch(), horizontalStretch(), verticalPolicy() +*/ + +/*! + \fn void QSizePolicy::setHorizontalStretch(uchar stretchFactor) + + Sets the horizontal stretch factor of the size policy to the given \a + stretchFactor. + + \sa horizontalStretch(), setVerticalStretch(), setHorizontalPolicy() +*/ + +/*! + \fn void QSizePolicy::setVerticalStretch(uchar stretchFactor) + + Sets the vertical stretch factor of the size policy to the given + \a stretchFactor. + + \sa verticalStretch(), setHorizontalStretch(), setVerticalPolicy() +*/ + +/*! + \fn void QSizePolicy::transpose() + + Swaps the horizontal and vertical policies and stretches. +*/ + +/*! + \enum QSizePolicy::ControlType + \since 4.3 + + This enum specifies the different types of widgets in terms of + layout interaction: + + \value DefaultType The default type, when none is specified. + \value ButtonBox A QDialogButtonBox instance. + \value CheckBox A QCheckBox instance. + \value ComboBox A QComboBox instance. + \value Frame A QFrame instance. + \value GroupBox A QGroupBox instance. + \value Label A QLabel instance. + \value Line A QFrame instance with QFrame::HLine or QFrame::VLine. + \value LineEdit A QLineEdit instance. + \value PushButton A QPushButton instance. + \value RadioButton A QRadioButton instance. + \value Slider A QAbstractSlider instance. + \value SpinBox A QAbstractSpinBox instance. + \value TabWidget A QTabWidget instance. + \value ToolButton A QToolButton instance. + + \sa setControlType(), controlType() +*/ + +#ifdef QT3_SUPPORT +/*! + \typedef QSizePolicy::SizeType + \compat + + Use the QSizePolicy::Policy enum instead. +*/ + +/*! + \enum QSizePolicy::ExpandData + \compat + + Use the Qt::Orientations enum instead. + + \value NoDirection Use 0 instead. + \value Horizontally Use Qt::Horizontal instead. + \value Vertically Use Qt::Vertical instead. + \value BothDirections Use Qt::Horizontal | Qt::Vertical instead. +*/ + +/*! + \fn bool QSizePolicy::mayShrinkHorizontally() const + + Use the horizontalPolicy() function combined with the + QSizePolicy::PolicyFlag enum instead. + + \oldcode + bool policy = mayShrinkHorizontally(); + \newcode + bool policy = horizontalPolicy() & QSizePolicy::ShrinkFlag; + \endcode +*/ + +/*! + \fn bool QSizePolicy::mayShrinkVertically() const + + Use the verticalPolicy() function combined with the + QSizePolicy::PolicyFlag enum instead. + + \oldcode + bool policy = mayShrinkVertically(); + \newcode + bool policy = verticalPolicy() & QSizePolicy::ShrinkFlag; + \endcode +*/ + +/*! + \fn bool QSizePolicy::mayGrowHorizontally() const + + Use the horizontalPolicy() function combined with the + QSizePolicy::PolicyFlag enum instead. + + \oldcode + bool policy = mayGrowHorizontally(); + \newcode + bool policy = horizontalPolicy() & QSizePolicy::GrowFlag; + \endcode +*/ + +/*! + \fn bool QSizePolicy::mayGrowVertically() const + + Use the verticalPolicy() function combined with the + QSizePolicy::PolicyFlag enum instead. + + \oldcode + bool policy = mayGrowVertically(); + \newcode + bool policy = verticalPolicy() & QSizePolicy::GrowFlag; + \endcode +*/ + +/*! + \fn Qt::QSizePolicy::Orientations QSizePolicy::expanding() const + + Use expandingDirections() instead. +*/ + +/*! + \fn QSizePolicy::QSizePolicy(Policy horizontal, Policy vertical, bool dependent) + + Use the QSizePolicy() constructor and the setHeightForWidth() + function instead. + + \oldcode + QSizePolicy *policy = new QSizePolicy(horizontal, vertical, dependent); + \newcode + QSizePolicy *policy = new QSizePolicy(horizontal, vertical); + policy->setHeightForWidth(dependent); + \endcode +*/ + +/*! + \fn QSizePolicy::QSizePolicy(Policy horizontal, Policy vertical, uchar horizontalStretch, + uchar verticalStretch, bool dependent) + + Use the QSizePolicy() constructor and call the + setHorizontalStretch(), setVerticalStretch(), and + setHeightForWidth() functions instead. + + \oldcode + QSizePolicy *policy = new QSizePolicy(horizontal, vertical, + horizontalStretch, verticalStretch, + dependent); + \newcode + QSizePolicy *policy = new QSizePolicy(horizontal, vertical); + policy->setHorizontalStretch(horizontalStretch); + policy->setVerticalStretch(verticalStretch); + policy->setHeightForWidth(dependent); + \endcode +*/ + +/*! + \fn QSizePolicy::Policy QSizePolicy::horData() const + + Use horizontalPolicy() instead. +*/ + +/*! + \fn QSizePolicy::Policy QSizePolicy::verData() const + + Use verticalPolicy() instead. +*/ + +/*! + \fn void QSizePolicy::setHorData(Policy policy) + + Use setHorizontalPolicy() instead. +*/ + +/*! + \fn void QSizePolicy::setVerData(Policy policy) + + Use setVerticalPolicy() instead. +*/ + +/*! + \fn uint QSizePolicy::horStretch() const + + Use horizontalStretch() instead. +*/ + +/*! + \fn uint QSizePolicy::verStretch() const + + Use verticalStretch() instead. +*/ + +/*! + \fn void QSizePolicy::setHorStretch(uchar stretch) + + Use setHorizontalStretch() instead. +*/ + +/*! + \fn void QSizePolicy::setVerStretch(uchar stretch) + + Use setVerticalStretch() instead. +*/ +#endif diff --git a/src/gui/kernel/qsound.cpp b/src/gui/kernel/qsound.cpp index 2250d61..3213c1b 100644 --- a/src/gui/kernel/qsound.cpp +++ b/src/gui/kernel/qsound.cpp @@ -106,7 +106,7 @@ public: \brief The QSound class provides access to the platform audio facilities. \ingroup multimedia - \mainclass + Qt provides the most commonly required audio operation in GUI applications: asynchronously playing a sound file. This is most @@ -153,6 +153,9 @@ public: \o Qt for Embedded Linux \o A built-in mixing sound server is used, accessing \c /dev/dsp directly. Only the WAVE format is supported. + \o Symbian + \o CMdaAudioPlayerUtility is used. All formats that Symbian OS or devices support + are supported also by Qt. \endtable Note that QSound does not support \l{resources.html}{resources}. diff --git a/src/gui/kernel/qsound_qws.cpp b/src/gui/kernel/qsound_qws.cpp index 7eea8c0..c802261 100644 --- a/src/gui/kernel/qsound_qws.cpp +++ b/src/gui/kernel/qsound_qws.cpp @@ -53,16 +53,16 @@ #include "qhash.h" #include "qfileinfo.h" -#ifdef MEDIA_SERVER #include "qbytearray.h" #include "quuid.h" #include "qdatastream.h" #include "qcopchannel_qws.h" #include "qbuffer.h" + QT_BEGIN_NAMESPACE -QT_USE_NAMESPACE +#ifdef MEDIA_SERVER #define SERVER_CHANNEL "QPE/MediaServer" @@ -279,7 +279,7 @@ QAuBucketQWS::QAuBucketQWS( QAuServerQWS *server, QSound *sound, QObject* parent sound->setObjectName( m_id.toString() ); - m_channel = new QCopChannel(QString( QLatin1String("QPE/QSound/") ).append( m_id ), this ); + m_channel = new QCopChannel(QLatin1String("QPE/QSound/") + m_id ), this ); connect( m_channel, SIGNAL(received(QString,QByteArray)), this, SLOT(processMessage(QString,QByteArray)) ); diff --git a/src/gui/kernel/qsound_s60.cpp b/src/gui/kernel/qsound_s60.cpp new file mode 100644 index 0000000..0cd9ea1 --- /dev/null +++ b/src/gui/kernel/qsound_s60.cpp @@ -0,0 +1,206 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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_NO_SOUND + +#include "qdir.h" +#include "qapplication.h" +#include "qsound.h" +#include "qsound_p.h" +#include "qfileinfo.h" +#include <private/qcore_symbian_p.h> + +#include <e32std.h> +#include <MdaAudioSamplePlayer.h> + +QT_BEGIN_NAMESPACE + +class QAuServerS60; + +class QAuBucketS60 : public QAuBucket, public MMdaAudioPlayerCallback +{ +public: + QAuBucketS60( QAuServerS60 *server, QSound *sound); + ~QAuBucketS60(); + + void play(); + void stop(); + + inline QSound* sound() const { return m_sound; } + +public: // from MMdaAudioPlayerCallback + void MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration); + void MapcPlayComplete(TInt aError); + +private: + QSound *m_sound; + QAuServerS60 *m_server; + bool m_prepared; + bool m_playCalled; + CMdaAudioPlayerUtility* m_playUtility; +}; + + +class QAuServerS60 : public QAuServer +{ +public: + QAuServerS60( QObject* parent ); + + void init( QSound* s ) + { + QAuBucketS60 *bucket = new QAuBucketS60( this, s ); + setBucket( s, bucket ); + } + + void play( QSound* s ) + { + bucket( s )->play(); + } + + void stop( QSound* s ) + { + bucket( s )->stop(); + } + + bool okay() { return true; } + +protected: + void playCompleted(QAuBucketS60* bucket, int error) + { + QSound *sound = bucket->sound(); + if(!error) { + // We need to handle repeats by ourselves, since with Symbian API we don't + // know how many loops have been played when user asks it + if( decLoop( sound ) ) { + play( sound ); + } + } else { + // We don't have a way to inform about errors -> just decrement loops + // in order that QSound::isFinished will return true; + while(decLoop(sound)) {} + } + } + +protected: + QAuBucketS60* bucket( QSound *s ) + { + return (QAuBucketS60*)QAuServer::bucket( s ); + } + + friend class QAuBucketS60; + +}; + +QAuServerS60::QAuServerS60(QObject* parent) : + QAuServer(parent) +{ + setObjectName(QLatin1String("QAuServerS60")); +} + + +QAuServer* qt_new_audio_server() +{ + return new QAuServerS60(qApp); +} + +QAuBucketS60::QAuBucketS60( QAuServerS60 *server, QSound *sound ) + : m_sound( sound ), m_server( server ), m_prepared(false), m_playCalled(false) +{ + QString filepath = QFileInfo( m_sound->fileName() ).absoluteFilePath(); + filepath = QDir::toNativeSeparators(filepath); + TPtrC filepathPtr(qt_QString2TPtrC(filepath)); + TRAPD(err, m_playUtility = CMdaAudioPlayerUtility::NewL(*this); + m_playUtility->OpenFileL(filepathPtr)); + if(err){ + m_server->playCompleted(this, err); + } +} + +void QAuBucketS60::play() +{ + if(m_prepared) { + // OpenFileL call is completed we can start playing immediately + m_playUtility->Play(); + } else { + m_playCalled = true; + } + +} + +void QAuBucketS60::stop() +{ + m_playCalled = false; + m_playUtility->Stop(); +} + +void QAuBucketS60::MapcPlayComplete(TInt aError) +{ + m_server->playCompleted(this, aError); +} + +void QAuBucketS60::MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& /*aDuration*/) +{ + if(aError) { + m_server->playCompleted(this, aError); + } else { + m_prepared = true; + if(m_playCalled){ + play(); + } + } +} + +QAuBucketS60::~QAuBucketS60() +{ + if(m_playUtility){ + m_playUtility->Stop(); + m_playUtility->Close(); + } + + delete m_playUtility; +} + + +#endif // QT_NO_SOUND + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qsound_win.cpp b/src/gui/kernel/qsound_win.cpp index b5fe123..d998868 100644 --- a/src/gui/kernel/qsound_win.cpp +++ b/src/gui/kernel/qsound_win.cpp @@ -77,13 +77,8 @@ public: QAuServerWindows::QAuServerWindows(QObject* parent) : QAuServer(parent), current(0) { - QT_WA({ - mutex = CreateMutexW(0, 0, 0); - event = CreateEventW(0, FALSE, FALSE, 0); - } , { - mutex = CreateMutexA(0, 0, 0); - event = CreateEventA(0, FALSE, FALSE, 0); - }); + mutex = CreateMutex(0, 0, 0); + event = CreateEvent(0, FALSE, FALSE, 0); } QAuServerWindows::~QAuServerWindows() @@ -133,13 +128,9 @@ DWORD WINAPI SoundPlayProc(LPVOID param) if (loops == -1) flags |= SND_LOOP; - QT_WA({ - PlaySoundW((TCHAR*)filename.utf16(), 0, flags); - } , { - PlaySoundA(QFile::encodeName(filename).data(), 0, flags); - }); - if (sound && loops == 1) - server->decLoop(sound); + PlaySound((wchar_t*)filename.utf16(), 0, flags); + if (sound && loops == 1) + server->decLoop(sound); // GUI thread continues, but we are done as well. SetEvent(event); @@ -148,18 +139,13 @@ DWORD WINAPI SoundPlayProc(LPVOID param) QPointer<QSound> guarded_sound = sound; SetEvent(event); - for (int l = 0; l < loops && server->current; ++l) { - QT_WA( { - PlaySoundW( (TCHAR*)filename.utf16(), 0, SND_FILENAME|SND_SYNC ); - } , { - PlaySoundA( QFile::encodeName(filename).data(), 0, - SND_FILENAME|SND_SYNC ); - } ); - - if (guarded_sound) - server->decLoop(guarded_sound); - } - server->current = 0; + for (int l = 0; l < loops && server->current; ++l) { + PlaySound((wchar_t*)filename.utf16(), 0, SND_FILENAME | SND_SYNC); + + if (guarded_sound) + server->decLoop(guarded_sound); + } + server->current = 0; } ReleaseMutex(mutex); @@ -169,7 +155,7 @@ DWORD WINAPI SoundPlayProc(LPVOID param) void QAuServerWindows::playHelper(const QString &filename, int loop, QSound *snd) { if (loop == 0) - return; + return; // busy? if (WaitForSingleObject(mutex, 0) == WAIT_TIMEOUT) return; diff --git a/src/gui/kernel/qstackedlayout.cpp b/src/gui/kernel/qstackedlayout.cpp index 732f2ce..e489c66 100644 --- a/src/gui/kernel/qstackedlayout.cpp +++ b/src/gui/kernel/qstackedlayout.cpp @@ -65,8 +65,6 @@ public: only one widget is visible at a time. \ingroup geomanagement - \ingroup appearance - \mainclass QStackedLayout can be used to create a user interface similar to the one provided by QTabWidget. There is also a convenience diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp new file mode 100644 index 0000000..8e76715 --- /dev/null +++ b/src/gui/kernel/qstandardgestures.cpp @@ -0,0 +1,792 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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 "qstandardgestures.h" +#include "qstandardgestures_p.h" + +#include <qabstractscrollarea.h> +#include <qscrollbar.h> +#include <private/qapplication_p.h> +#include <private/qevent_p.h> +#include <private/qwidget_p.h> +#include <qmath.h> + +QT_BEGIN_NAMESPACE + +#ifdef Q_WS_WIN +QWidgetPrivate *qt_widget_private(QWidget *widget); +#endif + +/*! + \class QPanGesture + \since 4.6 + + \brief The QPanGesture class represents a Pan gesture, + providing additional information related to panning. +*/ + +/*! + \enum QSwipeGesture::SwipeDirection + \brief This enum specifies the direction of the swipe gesture. + + \value NoDirection + \value Left + \value Right + \value Up + \value Down +*/ + +/*! + Creates a new pan gesture handler object and marks it as a child of + \a parent. The pan gesture handler watches \a gestureTarget for its + events. + + On some platform like Windows it's necessary to provide a non-null + widget as \a parent to get native gesture support. +*/ +QPanGesture::QPanGesture(QWidget *gestureTarget, QObject *parent) + : QGesture(*new QPanGesturePrivate, gestureTarget, parent) +{ + setObjectName(QLatin1String("QPanGesture")); +} + +void QPanGesturePrivate::setupGestureTarget(QObject *newGestureTarget) +{ + Q_Q(QPanGesture); + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); + + if (gestureTarget && gestureTarget->isWidgetType()) { + QWidget *w = static_cast<QWidget*>(gestureTarget.data()); + if (qAppPriv->widgetGestures[w].pan == q) + qAppPriv->widgetGestures[w].pan = 0; +#if defined(Q_WS_WIN) + qt_widget_private(w)->winSetupGestures(); +#elif defined(Q_WS_MAC) + w->setAttribute(Qt::WA_AcceptTouchEvents, false); + w->setAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents, false); +#endif + } + + if (newGestureTarget && newGestureTarget->isWidgetType()) { + QWidget *w = static_cast<QWidget*>(newGestureTarget); + qAppPriv->widgetGestures[w].pan = q; +#if defined(Q_WS_WIN) + qt_widget_private(w)->winSetupGestures(); +#elif defined(Q_WS_MAC) + w->setAttribute(Qt::WA_AcceptTouchEvents); + w->setAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents); +#endif + } + QGesturePrivate::setupGestureTarget(newGestureTarget); +} + +/*! \internal */ +bool QPanGesture::event(QEvent *event) +{ +#if defined(QT_MAC_USE_COCOA) + Q_D(QPanGesture); + if (event->type() == QEvent::Timer) { + const QTimerEvent *te = static_cast<QTimerEvent *>(event); + if (te->timerId() == d->singleTouchPanTimer.timerId()) { + d->singleTouchPanTimer.stop(); + updateState(Qt::GestureStarted); + } + } +#endif + + return QObject::event(event); +} + +bool QPanGesture::eventFilter(QObject *receiver, QEvent *event) +{ + Q_D(QPanGesture); + + if (d->implicitGesture && d->gestureTarget && d->gestureTarget->isWidgetType() && + static_cast<QWidget*>(d->gestureTarget.data())->testAttribute(Qt::WA_DontUseStandardGestures)) + return false; + +#ifdef Q_WS_WIN + if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) { + QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event); + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); + QApplicationPrivate::WidgetStandardGesturesMap::iterator it; + it = qAppPriv->widgetGestures.find(static_cast<QWidget*>(receiver)); + if (it == qAppPriv->widgetGestures.end()) + return false; + if (this != it.value().pan) + return false; + Qt::GestureState nextState = Qt::NoGesture; + switch(ev->gestureType) { + case QNativeGestureEvent::GestureBegin: + // next we might receive the first gesture update event, so we + // prepare for it. + d->state = Qt::NoGesture; + return false; + case QNativeGestureEvent::Pan: + nextState = Qt::GestureUpdated; + event->accept(); + break; + case QNativeGestureEvent::GestureEnd: + if (state() == Qt::NoGesture) + return false; // some other gesture has ended + nextState = Qt::GestureFinished; + break; + default: + return false; + } + if (state() == Qt::NoGesture) { + d->lastOffset = d->totalOffset = d->offset = QSize(); + } else { + d->lastOffset = d->offset; + d->offset = QSize(ev->position.x() - d->lastPosition.x(), + ev->position.y() - d->lastPosition.y()); + d->totalOffset += d->offset; + } + d->lastPosition = ev->position; + updateState(nextState); + return true; + } +#endif + return QGesture::eventFilter(receiver, event); +} + +/*! \internal */ +bool QPanGesture::filterEvent(QEvent *event) +{ + Q_D(QPanGesture); + + if (d->implicitGesture && d->gestureTarget && d->gestureTarget->isWidgetType() && + static_cast<QWidget*>(d->gestureTarget.data())->testAttribute(Qt::WA_DontUseStandardGestures)) + return false; + +#if defined(Q_WS_WIN) + const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); + + if (event->type() == QEvent::TouchBegin) { + QTouchEvent::TouchPoint p = ev->touchPoints().at(0); + d->lastPosition = p.pos().toPoint(); + d->lastOffset = d->totalOffset = d->offset = QSize(); + } else if (event->type() == QEvent::TouchEnd) { + if (state() != Qt::NoGesture) { + if (ev->touchPoints().size() == 2) { + QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); + QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); + d->lastOffset = d->offset; + d->offset = + QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), + p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2; + d->totalOffset += d->offset; + } + updateState(Qt::GestureFinished); + } + reset(); + } else if (event->type() == QEvent::TouchUpdate) { + if (ev->touchPoints().size() == 2) { + QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); + QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); + d->lastOffset = d->offset; + d->offset = + QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), + p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2; + d->totalOffset += d->offset; + if (d->totalOffset.width() > 10 || d->totalOffset.height() > 10 || + d->totalOffset.width() < -10 || d->totalOffset.height() < -10) { + updateState(Qt::GestureUpdated); + } + } + } +#elif defined(QT_MAC_USE_COCOA) + // The following implements single touch + // panning on Mac: + const int panBeginDelay = 300; + const int panBeginRadius = 3; + const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); + + switch (event->type()) { + case QEvent::TouchBegin: { + if (ev->touchPoints().size() == 1) { + d->lastPosition = QCursor::pos(); + d->singleTouchPanTimer.start(panBeginDelay, this); + } + break;} + case QEvent::TouchEnd: { + if (state() != Qt::NoGesture) + updateState(Qt::GestureFinished); + reset(); + break;} + case QEvent::TouchUpdate: { + if (ev->touchPoints().size() == 1) { + if (state() == Qt::NoGesture) { + // INVARIANT: The singleTouchTimer has still not fired. + // Lets check if the user moved his finger so much from + // the starting point that it makes sense to cancel: + const QPointF startPos = ev->touchPoints().at(0).startPos().toPoint(); + const QPointF p = ev->touchPoints().at(0).pos().toPoint(); + if ((startPos - p).manhattanLength() > panBeginRadius) + reset(); + else + d->lastPosition = QCursor::pos(); + } else { + QPointF mousePos = QCursor::pos(); + QPointF dist = mousePos - d->lastPosition; + d->lastPosition = mousePos; + d->lastOffset = d->offset; + d->offset = QSizeF(dist.x(), dist.y()); + d->totalOffset += d->offset; + updateState(Qt::GestureUpdated); + } + } else if (state() == Qt::NoGesture) { + reset(); + } + break;} + default: + return false; + } +#else + Q_UNUSED(event); +#endif + return false; +} + +/*! \internal */ +void QPanGesture::reset() +{ + Q_D(QPanGesture); + d->lastOffset = d->totalOffset = d->offset = QSize(0, 0); + d->lastPosition = QPoint(0, 0); + +#if defined(QT_MAC_USE_COCOA) + d->singleTouchPanTimer.stop(); + d->prevMousePos = QPointF(0, 0); +#endif + + QGesture::reset(); +} + +/*! + \property QPanGesture::totalOffset + + Specifies a total pan offset since the start of the gesture. +*/ +QSizeF QPanGesture::totalOffset() const +{ + Q_D(const QPanGesture); + return d->totalOffset; +} + +/*! + \property QPanGesture::lastOffset + + Specifies a pan offset the last time the gesture was triggered. +*/ +QSizeF QPanGesture::lastOffset() const +{ + Q_D(const QPanGesture); + return d->lastOffset; +} + +/*! + \property QPanGesture::offset + + Specifies the current pan offset since the last time the gesture was + triggered. +*/ +QSizeF QPanGesture::offset() const +{ + Q_D(const QPanGesture); + return d->offset; +} + +////////////////////////////////////////////////////////////////////////////// + +/*! + \class QPinchGesture + \since 4.6 + + \brief The QPinchGesture class represents a Pinch gesture, + providing additional information related to zooming and/or rotation. +*/ + +/*! + Creates a new Pinch gesture handler object and marks it as a child + of \a parent. The pan gesture handler watches \a gestureTarget for its + events. + + On some platform like Windows it's necessary to provide a non-null + widget as \a parent to get native gesture support. +*/ +QPinchGesture::QPinchGesture(QWidget *gestureTarget, QObject *parent) + : QGesture(*new QPinchGesturePrivate, gestureTarget, parent) +{ + setObjectName(QLatin1String("QPinchGesture")); +} + +void QPinchGesturePrivate::setupGestureTarget(QObject *newGestureTarget) +{ + Q_Q(QPinchGesture); + if (gestureTarget && gestureTarget->isWidgetType()) { + QWidget *w = static_cast<QWidget*>(gestureTarget.data()); + QApplicationPrivate::instance()->widgetGestures[w].pinch = 0; +#ifdef Q_WS_WIN + qt_widget_private(w)->winSetupGestures(); +#endif + } + + if (newGestureTarget && newGestureTarget->isWidgetType()) { + QWidget *w = static_cast<QWidget*>(newGestureTarget); + QApplicationPrivate::instance()->widgetGestures[w].pinch = q; +#ifdef Q_WS_WIN + qt_widget_private(w)->winSetupGestures(); +#endif + } + QGesturePrivate::setupGestureTarget(newGestureTarget); +} + +/*! \internal */ +bool QPinchGesture::event(QEvent *event) +{ + return QObject::event(event); +} + +bool QPinchGesture::eventFilter(QObject *receiver, QEvent *event) +{ + Q_D(QPinchGesture); + + if (d->implicitGesture && d->gestureTarget && d->gestureTarget->isWidgetType() && + static_cast<QWidget*>(d->gestureTarget.data())->testAttribute(Qt::WA_DontUseStandardGestures)) + return false; + +#if defined(Q_WS_WIN) || defined(Q_WS_MAC) + if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) { + QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event); +#if defined(Q_WS_WIN) + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); + QApplicationPrivate::WidgetStandardGesturesMap::iterator it; + it = qAppPriv->widgetGestures.find(static_cast<QWidget*>(receiver)); + if (it == qAppPriv->widgetGestures.end()) + return false; + if (this != it.value().pinch) + return false; +#endif + Qt::GestureState nextState = Qt::NoGesture; + + switch(ev->gestureType) { + case QNativeGestureEvent::GestureBegin: + // next we might receive the first gesture update event, so we + // prepare for it. + d->state = Qt::NoGesture; + d->changes = 0; + d->totalScaleFactor = d->scaleFactor = d->lastScaleFactor = 1.; + d->totalRotationAngle = d->rotationAngle = d->lastRotationAngle = 0.; + d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPointF(); +#if defined(Q_WS_WIN) + d->initialDistance = 0; + d->lastSequenceId = ev->sequenceId; +#endif + return false; + case QNativeGestureEvent::Rotate: { + d->lastScaleFactor = d->scaleFactor; + d->lastRotationAngle = d->rotationAngle; +#if defined(Q_WS_MAC) + d->rotationAngle += ev->percentage; + nextState = Qt::GestureUpdated; +#elif defined(Q_WS_WIN) + // This is a workaround for an issue with the native rotation + // gesture on Windows 7. For some reason the rotation angle in the + // first WM_GESTURE message in a sequence contains value that is + // off a little bit and causes the rotating item to "jump", so + // we just ignore the first WM_GESTURE in every sequence. + bool windowsRotateWorkaround = false; + if (!d->lastSequenceId) { + windowsRotateWorkaround = true; + d->lastSequenceId = ev->sequenceId; + } + if (d->lastSequenceId > 0 && d->lastSequenceId != (ulong)-1 && ev->sequenceId != d->lastSequenceId) { + // this is the first WM_GESTURE message in a sequence. + d->totalRotationAngle += d->rotationAngle; + windowsRotateWorkaround = true; + // a magic value to mark that the next WM_GESTURE message is + // the second message in a sequence and we should clear the + // lastRotationAngle + d->lastSequenceId = (ulong)-1; + } + if (!windowsRotateWorkaround) { + d->rotationAngle = -1 * GID_ROTATE_ANGLE_FROM_ARGUMENT(ev->argument) * 180. / M_PI; + if (d->lastSequenceId == (ulong)-1) { + // a special case since we need to set the lastRotationAngle to + // rotationAngle when the first WM_GESTURE is received in each + // sequence. + d->lastRotationAngle = d->rotationAngle; + } + d->lastSequenceId = ev->sequenceId; + } + if (!windowsRotateWorkaround) + nextState = Qt::GestureUpdated; +#endif + d->changes = QPinchGesture::RotationAngleChanged; + event->accept(); + break; + } + case QNativeGestureEvent::Zoom: + d->lastRotationAngle = d->rotationAngle; + d->lastScaleFactor = d->scaleFactor; +#if defined(Q_WS_WIN) + if (d->initialDistance != 0) { + int distance = int(qint64(ev->argument)); + if (d->lastSequenceId && ev->sequenceId != d->lastSequenceId) { + d->totalScaleFactor *= d->scaleFactor; + d->initialDistance = int(qint64(ev->argument)); + d->lastScaleFactor = d->scaleFactor = (qreal) distance / d->initialDistance; + } else { + d->scaleFactor = (qreal) distance / d->initialDistance; + } + d->lastSequenceId = ev->sequenceId; + } else { + d->initialDistance = int(qint64(ev->argument)); + } +#elif defined(Q_WS_MAC) + d->scaleFactor += ev->percentage; +#endif + nextState = Qt::GestureUpdated; + d->changes = QPinchGesture::ScaleFactorChanged; + event->accept(); + break; + case QNativeGestureEvent::GestureEnd: + if (state() == Qt::NoGesture) + return false; // some other gesture has ended + nextState = Qt::GestureFinished; + break; + default: + return false; + } + if (d->startCenterPoint.isNull()) + d->startCenterPoint = d->centerPoint; + d->lastCenterPoint = d->centerPoint; + d->centerPoint = static_cast<QWidget*>(receiver)->mapFromGlobal(ev->position); + if (d->lastCenterPoint != d->centerPoint) + d->changes |= QPinchGesture::CenterPointChanged; + updateState(nextState); + return true; + } +#endif + return QGesture::eventFilter(receiver, event); +} + + +/*! \internal */ +bool QPinchGesture::filterEvent(QEvent *event) +{ + Q_D(QPinchGesture); + + if (d->implicitGesture && d->gestureTarget && d->gestureTarget->isWidgetType() && + static_cast<QWidget*>(d->gestureTarget.data())->testAttribute(Qt::WA_DontUseStandardGestures)) + return false; + + Q_UNUSED(event); + return false; +} + +/*! \internal */ +void QPinchGesture::reset() +{ + Q_D(QPinchGesture); + d->changes = 0; + d->totalScaleFactor = d->scaleFactor = d->lastScaleFactor = 1.; + d->totalRotationAngle = d->rotationAngle = d->lastRotationAngle = 0.; + d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPointF(); + QGesture::reset(); +} + +/*! + \property QPinchGesture::whatChanged + + Specifies which values were changed in the gesture. +*/ +QPinchGesture::WhatChanged QPinchGesture::whatChanged() const +{ + return d_func()->changes; +} + +/*! + \property QPinchGesture::totalScaleFactor + + Specifies a total scale factor of the pinch gesture since the gesture + started. +*/ +qreal QPinchGesture::totalScaleFactor() const +{ + Q_D(const QPinchGesture); + return d->totalScaleFactor * d->scaleFactor; +} + +/*! + \property QPinchGesture::scaleFactor + + Specifies a scale factor of the pinch gesture. + + If the gesture consists of several pinch sequences (i.e. zoom and rotate + sequences), then this property specifies the scale factor in the current + sequence. When pinching changes the rotation angle only, the value of this + property is 1. +*/ +qreal QPinchGesture::scaleFactor() const +{ + return d_func()->scaleFactor; +} + +/*! + \property QPinchGesture::lastScaleFactor + + Specifies a previous scale factor of the pinch gesture. +*/ +qreal QPinchGesture::lastScaleFactor() const +{ + return d_func()->lastScaleFactor; +} + +/*! + \property QPinchGesture::totalRotationAngle + + Specifies a total rotation angle of the gesture since the gesture started. + + The angle is specified in degrees. +*/ +qreal QPinchGesture::totalRotationAngle() const +{ + Q_D(const QPinchGesture); + return d->totalRotationAngle + d->rotationAngle; +} + +/*! + \property QPinchGesture::rotationAngle + + Specifies a rotation angle of the gesture. + + If the gesture consists of several pinch sequences (i.e. zoom and rotate + sequences), then this property specifies the rotation angle in the current + sequence. When pinching changes the scale factor only, the value of this + property is 0. + + The angle is specified in degrees. +*/ +qreal QPinchGesture::rotationAngle() const +{ + return d_func()->rotationAngle; +} + +/*! + \property QPinchGesture::lastRotationAngle + + Specifies a previous rotation angle of the gesture. + + The angle is specified in degrees. +*/ +qreal QPinchGesture::lastRotationAngle() const +{ + return d_func()->lastRotationAngle; +} + +/*! + \property QPinchGesture::centerPoint + + Specifies a center point of the gesture. The point can be used as a center + point that the object is rotated around. +*/ +QPointF QPinchGesture::centerPoint() const +{ + return d_func()->centerPoint; +} + +/*! + \property QPinchGesture::lastCenterPoint + + Specifies a previous center point of the gesture. +*/ +QPointF QPinchGesture::lastCenterPoint() const +{ + return d_func()->lastCenterPoint; +} + +/*! + \property QPinchGesture::startCenterPoint + + Specifies an initial center point of the gesture. Difference between the + startCenterPoint and the centerPoint is the distance at which pinching + fingers has shifted. +*/ +QPointF QPinchGesture::startCenterPoint() const +{ + return d_func()->startCenterPoint; +} + +////////////////////////////////////////////////////////////////////////////// + +/*! + \class QSwipeGesture + \since 4.6 + + \brief The QSwipeGesture class represents a swipe gesture, + providing additional information related to swiping. +*/ + +/*! + Creates a new Swipe gesture handler object and marks it as a + child of \a parent. The swipe gesture handler watches \a + gestureTarget for its events. + + On some platform like Windows it's necessary to provide a non-null + widget as \a parent to get native gesture support. +*/ +QSwipeGesture::QSwipeGesture(QWidget *gestureTarget, QObject *parent) + : QGesture(*new QSwipeGesturePrivate, gestureTarget, parent) +{ + setObjectName(QLatin1String("QSwipeGesture")); +} + +void QSwipeGesturePrivate::setupGestureTarget(QObject *newGestureTarget) +{ + Q_Q(QSwipeGesture); + if (gestureTarget && gestureTarget->isWidgetType()) { + QWidget *w = static_cast<QWidget*>(gestureTarget.data()); + QApplicationPrivate::instance()->widgetGestures[w].swipe = 0; +#if defined(Q_WS_WIN) + qt_widget_private(w)->winSetupGestures(); +#endif + } + + if (newGestureTarget && newGestureTarget->isWidgetType()) { + QWidget *w = static_cast<QWidget*>(newGestureTarget); + QApplicationPrivate::instance()->widgetGestures[w].swipe = q; +#if defined(Q_WS_WIN) + qt_widget_private(w)->winSetupGestures(); +#endif + } + QGesturePrivate::setupGestureTarget(newGestureTarget); +} + +/*! + \property QSwipeGesture::swipeAngle + + Holds the angle of the swipe gesture, 0..360. +*/ +qreal QSwipeGesture::swipeAngle() const +{ + Q_D(const QSwipeGesture); + return d->swipeAngle; +} + +/*! + \property QSwipeGesture::horizontalDirection + + Holds the direction for the horizontal component of the swipe + gesture, SwipeDirection::Left or SwipeDirection::Right. + SwipeDirection::NoDirection if there is no horizontal + component to the swipe gesture. +*/ +QSwipeGesture::SwipeDirection QSwipeGesture::horizontalDirection() const +{ + Q_D(const QSwipeGesture); + if (d->swipeAngle < 0 || d->swipeAngle == 90 || d->swipeAngle == 270) + return QSwipeGesture::NoDirection; + else if (d->swipeAngle < 90 || d->swipeAngle > 270) + return QSwipeGesture::Right; + else + return QSwipeGesture::Left; +} + + +/*! + \property QSwipeGesture::verticalDirection + + Holds the direction for the vertical component of the swipe + gesture, SwipeDirection::Down or SwipeDirection::Up. + SwipeDirection::NoDirection if there is no vertical + component to the swipe gesture. +*/ +QSwipeGesture::SwipeDirection QSwipeGesture::verticalDirection() const +{ + Q_D(const QSwipeGesture); + if (d->swipeAngle <= 0 || d->swipeAngle == 180) + return QSwipeGesture::NoDirection; + else if (d->swipeAngle < 180) + return QSwipeGesture::Up; + else + return QSwipeGesture::Down; +} + +bool QSwipeGesture::eventFilter(QObject *receiver, QEvent *event) +{ + Q_D(QSwipeGesture); + if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) { + QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event); + switch (ev->gestureType) { + case QNativeGestureEvent::Swipe: + d->swipeAngle = ev->angle; + updateState(Qt::GestureStarted); + updateState(Qt::GestureUpdated); + updateState(Qt::GestureFinished); + break; + default: + return false; + } + return true; + } + return QGesture::eventFilter(receiver, event); +} + +/*! \internal */ +bool QSwipeGesture::filterEvent(QEvent *) +{ + return false; +} + +/*! \internal */ +void QSwipeGesture::reset() +{ + Q_D(QSwipeGesture); + d->swipeAngle = -1; + QGesture::reset(); +} + +QT_END_NAMESPACE + +#include "moc_qstandardgestures.cpp" + diff --git a/src/gui/kernel/qstandardgestures.h b/src/gui/kernel/qstandardgestures.h new file mode 100644 index 0000000..53c4416 --- /dev/null +++ b/src/gui/kernel/qstandardgestures.h @@ -0,0 +1,174 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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 QSTANDARDGESTURES_H +#define QSTANDARDGESTURES_H + +#include <QtGui/qevent.h> +#include <QtCore/qbasictimer.h> + +#include <QtGui/qgesture.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPanGesturePrivate; +class Q_GUI_EXPORT QPanGesture : public QGesture +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QPanGesture) + + Q_PROPERTY(QSizeF totalOffset READ totalOffset) + Q_PROPERTY(QSizeF lastOffset READ lastOffset) + Q_PROPERTY(QSizeF offset READ offset) + +public: + QPanGesture(QWidget *gestureTarget, QObject *parent = 0); + + bool filterEvent(QEvent *event); + + QSizeF totalOffset() const; + QSizeF lastOffset() const; + QSizeF offset() const; + +protected: + void reset(); + +private: + bool event(QEvent *event); + bool eventFilter(QObject *receiver, QEvent *event); + + friend class QWidget; + friend class QAbstractScrollAreaPrivate; +}; + +class QPinchGesturePrivate; +class Q_GUI_EXPORT QPinchGesture : public QGesture +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QPinchGesture) + +public: + enum WhatChange { + ScaleFactorChanged = 0x1, + RotationAngleChanged = 0x2, + CenterPointChanged = 0x4 + }; + Q_DECLARE_FLAGS(WhatChanged, WhatChange) + + Q_PROPERTY(WhatChanged whatChanged READ whatChanged) + + Q_PROPERTY(qreal totalScaleFactor READ totalScaleFactor) + Q_PROPERTY(qreal lastScaleFactor READ lastScaleFactor) + Q_PROPERTY(qreal scaleFactor READ scaleFactor) + + Q_PROPERTY(qreal totalRotationAngle READ totalRotationAngle) + Q_PROPERTY(qreal lastRotationAngle READ lastRotationAngle) + Q_PROPERTY(qreal rotationAngle READ rotationAngle) + + Q_PROPERTY(QPointF startCenterPoint READ startCenterPoint) + Q_PROPERTY(QPointF lastCenterPoint READ lastCenterPoint) + Q_PROPERTY(QPointF centerPoint READ centerPoint) + +public: + + QPinchGesture(QWidget *gestureTarget, QObject *parent = 0); + + bool filterEvent(QEvent *event); + void reset(); + + WhatChanged whatChanged() const; + + QPointF startCenterPoint() const; + QPointF lastCenterPoint() const; + QPointF centerPoint() const; + + qreal totalScaleFactor() const; + qreal lastScaleFactor() const; + qreal scaleFactor() const; + + qreal totalRotationAngle() const; + qreal lastRotationAngle() const; + qreal rotationAngle() const; + +private: + bool event(QEvent *event); + bool eventFilter(QObject *receiver, QEvent *event); + + friend class QWidget; +}; + +class QSwipeGesturePrivate; +class Q_GUI_EXPORT QSwipeGesture : public QGesture +{ + Q_OBJECT + Q_ENUMS(SwipeDirection) + + Q_PROPERTY(SwipeDirection horizontalDirection READ horizontalDirection) + Q_PROPERTY(SwipeDirection verticalDirection READ verticalDirection) + Q_PROPERTY(qreal swipeAngle READ swipeAngle) + + Q_DECLARE_PRIVATE(QSwipeGesture) + +public: + enum SwipeDirection { NoDirection, Left, Right, Up, Down }; + QSwipeGesture(QWidget *gestureTarget, QObject *parent = 0); + + bool filterEvent(QEvent *event); + void reset(); + + SwipeDirection horizontalDirection() const; + SwipeDirection verticalDirection() const; + qreal swipeAngle() const; + +private: + bool eventFilter(QObject *receiver, QEvent *event); + + friend class QWidget; +}; +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSTANDARDGESTURES_H diff --git a/src/gui/kernel/qstandardgestures_p.h b/src/gui/kernel/qstandardgestures_p.h new file mode 100644 index 0000000..354ebee --- /dev/null +++ b/src/gui/kernel/qstandardgestures_p.h @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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 QSTANDARDGESTURES_P_H +#define QSTANDARDGESTURES_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 "qevent.h" +#include "qbasictimer.h" +#include "qdebug.h" + +#include "qgesture.h" +#include "qgesture_p.h" + +#include "qstandardgestures.h" +#include "qbasictimer.h" + +QT_BEGIN_NAMESPACE + +class QPanGesturePrivate : public QGesturePrivate +{ + Q_DECLARE_PUBLIC(QPanGesture) + +public: + void setupGestureTarget(QObject *o); + + QSizeF totalOffset; + QSizeF lastOffset; + QSizeF offset; + QPointF lastPosition; + +#if defined(QT_MAC_USE_COCOA) + QBasicTimer singleTouchPanTimer; + QPointF prevMousePos; +#endif +}; + +class QPinchGesturePrivate : public QGesturePrivate +{ + Q_DECLARE_PUBLIC(QPinchGesture) + +public: + QPinchGesturePrivate() + : changes(0), totalScaleFactor(0.), lastScaleFactor(0.), scaleFactor(0.), + totalRotationAngle(0.), lastRotationAngle(0.), rotationAngle(0.) +#ifdef Q_WS_WIN + ,initialDistance(0), lastSequenceId(0) +#endif + { + } + + void setupGestureTarget(QObject *o); + + QPinchGesture::WhatChanged changes; + + qreal totalScaleFactor; // total scale factor, excluding the current sequence. + qreal lastScaleFactor; + qreal scaleFactor; // scale factor in the current sequence. + + qreal totalRotationAngle; // total rotation angle, excluding the current sequence. + qreal lastRotationAngle; + qreal rotationAngle; // rotation angle in the current sequence. + + QPointF startCenterPoint; + QPointF lastCenterPoint; + QPointF centerPoint; +#ifdef Q_WS_WIN + int initialDistance; + ulong lastSequenceId; +#endif +}; + +class QSwipeGesturePrivate : public QGesturePrivate +{ + Q_DECLARE_PUBLIC(QSwipeGesture) + +public: + QSwipeGesturePrivate() + : swipeAngle(-1) + { + } + + void setupGestureTarget(QObject *o); + qreal swipeAngle; +}; + +QT_END_NAMESPACE + +#endif // QSTANDARDGESTURES_P_H diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 2bffdf8..1129818 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -74,9 +74,11 @@ ****************************************************************************/ #include <private/qcore_mac_p.h> +#include <qaction.h> #include <qwidget.h> #include <qdesktopwidget.h> #include <qevent.h> +#include <qpixmapcache.h> #include <private/qevent_p.h> #include <private/qt_cocoa_helpers_mac_p.h> #include <private/qt_mac_p.h> @@ -88,6 +90,52 @@ QT_BEGIN_NAMESPACE +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 Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm extern QWidget * mac_mouse_grabber; @@ -95,29 +143,26 @@ extern QWidget * mac_mouse_grabber; void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds) { OSWindowRef wnd = static_cast<OSWindowRef>(window); - if( wnd ) { + if (wnd) { + QWidget *widget; #if QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; - [NSAnimationContext beginGrouping]; - [[wnd animator] setAlphaValue:0.0]; - if (durationSeconds > 0) { - [[NSAnimationContext currentContext] setDuration:NSTimeInterval(durationSeconds)]; - } else { - durationSeconds = [[NSAnimationContext currentContext] duration]; - } - [NSAnimationContext endGrouping]; - QTimer::singleShot(qRound(durationSeconds * 1000), [wnd QT_MANGLE_NAMESPACE(qt_qwidget)], SLOT(hide())); + widget = [wnd QT_MANGLE_NAMESPACE(qt_qwidget)]; #else - if (durationSeconds <= 0) - durationSeconds = 0.15; - TransitionWindowOptions options = {0, durationSeconds, 0, 0}; - TransitionWindowWithOptions(wnd, kWindowFadeTransitionEffect, kWindowHideTransitionAction, 0, 1, &options); + 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(); + } + } } - - bool macWindowIsTextured( void * /*OSWindowRef*/ window ) { OSWindowRef wnd = static_cast<OSWindowRef>(window); @@ -134,11 +179,10 @@ void macWindowToolbarShow(const QWidget *widget, bool show ) { OSWindowRef wnd = qt_mac_window_for(widget); #if QT_MAC_USE_COCOA - NSToolbar *toolbar = [wnd toolbar]; - if (toolbar) { + if (NSToolbar *toolbar = [wnd toolbar]) { QMacCocoaAutoReleasePool pool; if (show != [toolbar isVisible]) { - [wnd toggleToolbarShown:wnd]; + [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(); @@ -154,22 +198,21 @@ void macWindowToolbarSet( void * /*OSWindowRef*/ window, void *toolbarRef ) { OSWindowRef wnd = static_cast<OSWindowRef>(window); #if QT_MAC_USE_COCOA - [wnd setToolbar:static_cast<NSToolbar *>(toolbarRef)]; + [wnd setToolbar:static_cast<NSToolbar *>(toolbarRef)]; #else SetWindowToolbar(wnd, static_cast<HIToolbarRef>(toolbarRef)); #endif } -bool macWindowToolbarVisible( void * /*OSWindowRef*/ window ) +bool macWindowToolbarIsVisible( void * /*OSWindowRef*/ window ) { OSWindowRef wnd = static_cast<OSWindowRef>(window); #if QT_MAC_USE_COCOA - NSToolbar *toolbar = [wnd toolbar]; - if (toolbar) + if (NSToolbar *toolbar = [wnd toolbar]) return [toolbar isVisible]; return false; #else - return IsWindowToolbarVisible(wnd); + return IsWindowToolbarVisible(wnd); #endif } @@ -177,12 +220,12 @@ void macWindowSetHasShadow( void * /*OSWindowRef*/ window, bool hasShadow ) { OSWindowRef wnd = static_cast<OSWindowRef>(window); #if QT_MAC_USE_COCOA - [wnd setHasShadow:BOOL(hasShadow)]; + [wnd setHasShadow:BOOL(hasShadow)]; #else - if (hasShadow) - ChangeWindowAttributes(wnd, 0, kWindowNoShadowAttribute); - else - ChangeWindowAttributes(wnd, kWindowNoShadowAttribute, 0); + if (hasShadow) + ChangeWindowAttributes(wnd, 0, kWindowNoShadowAttribute); + else + ChangeWindowAttributes(wnd, kWindowNoShadowAttribute, 0); #endif } @@ -190,9 +233,9 @@ void macWindowFlush(void * /*OSWindowRef*/ window) { OSWindowRef wnd = static_cast<OSWindowRef>(window); #if QT_MAC_USE_COCOA - [wnd flushWindowIfNeeded]; + [wnd flushWindowIfNeeded]; #else - HIWindowFlush(wnd); + HIWindowFlush(wnd); #endif } @@ -309,6 +352,12 @@ Qt::MouseButton qt_mac_get_button(EventMouseButton button) 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() { @@ -1020,6 +1069,17 @@ void qt_mac_updateContentBorderMetricts(void * /*OSWindowRef */window, const ::H #endif } +void qt_mac_showBaseLineSeparator(void * /*OSWindowRef */window, bool show) +{ +#if QT_MAC_USE_COCOA + QMacCocoaAutoReleasePool pool; + OSWindowRef theWindow = static_cast<OSWindowRef>(window); + NSToolbar *macToolbar = [theWindow toolbar]; + if (macToolbar) + [macToolbar setShowsBaselineSeparator: show]; +#endif +} + QStringList qt_mac_NSArrayToQStringList(void *nsarray) { QStringList result; @@ -1079,4 +1139,111 @@ CGContextRef qt_mac_graphicsContextFor(QWidget *widget) return context; } +CGFloat qt_mac_get_scalefactor() +{ +#ifndef QT_MAC_USE_COCOA + return HIGetScaleFactor(); +#else + return [[NSScreen mainScreen] userSpaceScaleFactor]; +#endif +} + +QString qt_mac_get_pasteboardString() +{ + QMacCocoaAutoReleasePool pool; + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + NSString *text = [pb stringForType:NSStringPboardType]; + if (text) { + return qt_mac_NSStringToQString(text); + } else { + 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 + } +} + +void qt_mac_menu_collapseSeparators(void */*NSMenu **/ theMenu, bool collapse) +{ + 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()]; + } + } +} + +#ifdef QT_MAC_USE_COCOA +void qt_cocoaChangeOverrideCursor(const QCursor &cursor) +{ + QMacCocoaAutoReleasePool pool; + [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) set]; +} +#endif + QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index 6576c1a..d87a7f8 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -120,10 +120,12 @@ void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds = 0); bool macWindowIsTextured(void * /*OSWindowRef*/ window); void macWindowToolbarShow(const QWidget *widget, bool show ); void macWindowToolbarSet( void * /*OSWindowRef*/ window, void* toolbarRef ); -bool macWindowToolbarVisible( void * /*OSWindowRef*/ window ); +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_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); @@ -131,7 +133,9 @@ 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); +void qt_cocoaChangeOverrideCursor(const QCursor &cursor); #endif +void qt_mac_menu_collapseSeparators(void * /*NSMenu */ menu, bool collapse); bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent); void qt_dispatchModifiersChanged(void * /*NSEvent * */flagsChangedEvent, QWidget *widgetToGetEvent); void qt_mac_dispatchNCMouseMessage(void */* NSWindow* */eventWindow, void */* NSEvent* */mouseEvent, @@ -143,6 +147,9 @@ 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); inline int flipYCoordinate(int y) { return QApplication::desktop()->screenGeometry(0).height() - y; @@ -162,6 +169,9 @@ void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list); void qt_syncCocoaTitleBarButtons(OSWindowRef window, QWidget *widgetForWindow); +CGFloat qt_mac_get_scalefactor(); +QString qt_mac_get_pasteboardString(); + #ifdef __OBJC__ inline NSMutableArray *qt_mac_QStringListToNSMutableArray(const QStringList &qstrlist) { return reinterpret_cast<NSMutableArray *>(qt_mac_QStringListToNSMutableArrayVoid(qstrlist)); } diff --git a/src/gui/kernel/qt_mac_p.h b/src/gui/kernel/qt_mac_p.h index 7ce5ffd..a1b7378 100644 --- a/src/gui/kernel/qt_mac_p.h +++ b/src/gui/kernel/qt_mac_p.h @@ -120,6 +120,21 @@ public: } }; +// 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: diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h new file mode 100644 index 0000000..78301af --- /dev/null +++ b/src/gui/kernel/qt_s60_p.h @@ -0,0 +1,291 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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_S60_P_H +#define QT_S60_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 "private/qcore_symbian_p.h" +#include "qhash.h" +#include "qpoint.h" +#include "QtGui/qfont.h" +#include "QtGui/qimage.h" +#include "QtGui/qevent.h" +#include "qpointer.h" +#include <w32std.h> +#include <coecntrl.h> +#include <eikenv.h> +#include <eikappui.h> + +#ifdef Q_WS_S60 +#include <aknutils.h> // AknLayoutUtils +#include <avkon.hrh> // EEikStatusPaneUidTitle +#include <akntitle.h> // CAknTitlePane +#include <akncontext.h> // CAknContextPane +#include <eikspane.h> // CEikStatusPane +#endif + +QT_BEGIN_NAMESPACE + +// Application internal HandleResourceChangeL events, +// system evens seems to start with 0x10 +const TInt KInternalStatusPaneChange = 0x50000000; + +class QS60Data +{ +public: + TUid uid; + int screenDepth; + QPoint lastCursorPos; + QPoint lastPointerEventPos; + QPointer<QWidget> lastPointerEventTarget; + QPointer<QWidget> mousePressTarget; + int screenWidthInPixels; + int screenHeightInPixels; + int screenWidthInTwips; + int screenHeightInTwips; + int defaultDpiX; + int defaultDpiY; + static inline void updateScreenSize(); + static inline RWsSession& wsSession(); + static inline RWindowGroup& windowGroup(); + static inline CWsScreenDevice* screenDevice(); + static inline CCoeAppUi* appUi(); +#ifdef Q_WS_S60 + static inline CEikStatusPane* statusPane(); + static inline CCoeControl* statusPaneSubPane(TInt aPaneId); + static inline CAknTitlePane* titlePane(); + static inline CAknContextPane* contextPane(); + static inline CEikButtonGroupContainer* buttonGroupContainer(); +#endif +}; + +QS60Data* qGlobalS60Data(); +#define S60 qGlobalS60Data() + +class QAbstractLongTapObserver +{ +public: + virtual void HandleLongTapEventL( const TPoint& aPenEventLocation, + const TPoint& aPenEventScreenLocation ) = 0; +}; +class QLongTapTimer; + +class QSymbianControl : public CCoeControl, public QAbstractLongTapObserver +{ +public: + DECLARE_TYPE_ID(0x51740000) // Fun fact: the two first values are "Qt" in ASCII. + +public: + QSymbianControl(QWidget *w); + void ConstructL(bool topLevel = false, bool desktop = false); + ~QSymbianControl(); + void HandleResourceChange(int resourceType); + void HandlePointerEventL(const TPointerEvent& aPointerEvent); + TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType); +#if !defined(QT_NO_IM) && defined(Q_WS_S60) + TCoeInputCapabilities InputCapabilities() const; +#endif + TTypeUid::Ptr MopSupplyObject(TTypeUid id); + + inline QWidget* widget() const { return qwidget; }; + void setWidget(QWidget *w); + void sendInputEvent(QWidget *widget, QInputEvent *inputEvent); + void setIgnoreFocusChanged(bool enabled) { m_ignoreFocusChanged = enabled; } + void CancelLongTapTimer(); + +protected: + void Draw(const TRect& aRect) const; + void SizeChanged(); + void PositionChanged(); + void FocusChanged(TDrawNow aDrawNow); + +private: + void HandlePointerEvent(const TPointerEvent& aPointerEvent); + TKeyResponse OfferKeyEvent(const TKeyEvent& aKeyEvent,TEventCode aType); + TKeyResponse sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent); + bool sendMouseEvent(QWidget *widget, QMouseEvent *mEvent); + void HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation ); + +private: + QWidget *qwidget; + bool m_ignoreFocusChanged; + QLongTapTimer* m_longTapDetector; + bool m_previousEventLongTap; +}; + +inline void QS60Data::updateScreenSize() +{ + TPixelsTwipsAndRotation params; + int mode = S60->screenDevice()->CurrentScreenMode(); + S60->screenDevice()->GetScreenModeSizeAndRotation(mode, params); + S60->screenWidthInPixels = params.iPixelSize.iWidth; + S60->screenHeightInPixels = params.iPixelSize.iHeight; + S60->screenWidthInTwips = params.iTwipsSize.iWidth; + S60->screenHeightInTwips = params.iTwipsSize.iHeight; + + TReal inches = S60->screenHeightInTwips / (TReal)KTwipsPerInch; + S60->defaultDpiY = S60->screenHeightInPixels / inches; + inches = S60->screenWidthInTwips / (TReal)KTwipsPerInch; + S60->defaultDpiX = S60->screenWidthInPixels / inches; +} + +inline RWsSession& QS60Data::wsSession() +{ + return CCoeEnv::Static()->WsSession(); +} + +inline RWindowGroup& QS60Data::windowGroup() +{ + return CCoeEnv::Static()->RootWin(); +} + +inline CWsScreenDevice* QS60Data::screenDevice() +{ + return CCoeEnv::Static()->ScreenDevice(); +} + +inline CCoeAppUi* QS60Data::appUi() +{ + return CCoeEnv::Static()-> AppUi(); +} + +#ifdef Q_WS_S60 +inline CEikStatusPane* QS60Data::statusPane() +{ + return CEikonEnv::Static()->AppUiFactory()->StatusPane(); +} + +// Returns the application's status pane control, if not present returns NULL. +inline CCoeControl* QS60Data::statusPaneSubPane( TInt aPaneId ) +{ + const TUid paneUid = { aPaneId }; + CEikStatusPane* statusPane = S60->statusPane(); + if (statusPane && statusPane->PaneCapabilities(paneUid).IsPresent()) { + CCoeControl* control = NULL; + // ControlL shouldn't leave because the pane is present + TRAPD(err, control = statusPane->ControlL(paneUid)); + return err != KErrNone ? NULL : control; + } + return NULL; +} + +// Returns the application's title pane, if not present returns NULL. +inline CAknTitlePane* QS60Data::titlePane() +{ + return static_cast<CAknTitlePane*>(S60->statusPaneSubPane(EEikStatusPaneUidTitle)); +} + +// Returns the application's title pane, if not present returns NULL. +inline CAknContextPane* QS60Data::contextPane() +{ + return static_cast<CAknContextPane*>(S60->statusPaneSubPane(EEikStatusPaneUidContext)); +} + +inline CEikButtonGroupContainer* QS60Data::buttonGroupContainer() +{ + return CEikonEnv::Static()->AppUiFactory()->Cba(); +} +#endif // Q_WS_S60 + +static inline QFont qt_TFontSpec2QFontL(const TFontSpec &fontSpec) +{ + return QFont( + qt_TDesC2QString(fontSpec.iTypeface.iName), + fontSpec.iHeight / KTwipsPerPoint, + fontSpec.iFontStyle.StrokeWeight() == EStrokeWeightNormal ? QFont::Normal : QFont::Bold, + fontSpec.iFontStyle.Posture() == EPostureItalic + ); +} + +static inline QImage::Format qt_TDisplayMode2Format(TDisplayMode mode) +{ + QImage::Format format; + switch(mode) { + case EGray2: + format = QImage::Format_MonoLSB; + break; + case EColor256: + case EGray256: + format = QImage::Format_Indexed8; + break; + case EColor4K: + format = QImage::Format_RGB444; + break; + case EColor64K: + format = QImage::Format_RGB16; + break; + case EColor16M: + format = QImage::Format_RGB666; + break; + case EColor16MU: + format = QImage::Format_RGB32; + break; + case EColor16MA: + format = QImage::Format_ARGB32; + break; +#if !defined(__SERIES60_31__) && !defined(__S60_32__) + case EColor16MAP: + format = QImage::Format_ARGB32_Premultiplied; + break; +#endif + default: + format = QImage::Format_Invalid; + break; + } + return format; +} + + +QT_END_NAMESPACE + +#endif // QT_S60_P_H diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h index 6e546a4..74cec82 100644 --- a/src/gui/kernel/qt_x11_p.h +++ b/src/gui/kernel/qt_x11_p.h @@ -74,11 +74,19 @@ #include <X11/Xutil.h> #include <X11/Xos.h> #ifdef index -# undef index +# undef index #endif #ifdef rindex -# undef rindex +# undef rindex #endif +#ifdef Q_OS_VXWORS +# ifdef open +# undef open +# endif +# ifdef getpid +# undef getpid +# endif +#endif // Q_OS_VXWORKS #include <X11/Xatom.h> //#define QT_NO_SHAPE @@ -154,6 +162,10 @@ extern "C" { # include <X11/extensions/Xrender.h> #endif // QT_NO_XRENDER +#ifndef QT_NO_XSYNC +# include "X11/extensions/sync.h" +#endif + // #define QT_NO_XKB #ifndef QT_NO_XKB # include <X11/XKBlib.h> @@ -502,9 +514,9 @@ struct QX11Data int fc_hint_style; char *startupId; - char *originalStartupId; - DesktopEnvironment desktopEnvironment; + DesktopEnvironment desktopEnvironment : 8; + uint desktopVersion : 8; /* Used only for KDE */ /* Warning: if you modify this list, modify the names of atoms in qapplication_x11.cpp as well! */ enum X11Atom { @@ -514,6 +526,8 @@ struct QX11Data WM_TAKE_FOCUS, _NET_WM_PING, _NET_WM_CONTEXT_HELP, + _NET_WM_SYNC_REQUEST, + _NET_WM_SYNC_REQUEST_COUNTER, // ICCCM window state WM_STATE, @@ -652,6 +666,10 @@ struct QX11Data _XEMBED, _XEMBED_INFO, + XWacomStylus, + XWacomCursor, + XWacomEraser, + NPredefinedAtoms, _QT_SETTINGS_TIMESTAMP = NPredefinedAtoms, diff --git a/src/gui/kernel/qtooltip.cpp b/src/gui/kernel/qtooltip.cpp index 575eb8b..4cc22d5 100644 --- a/src/gui/kernel/qtooltip.cpp +++ b/src/gui/kernel/qtooltip.cpp @@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE widget. \ingroup helpsystem - \mainclass + The tip is a short piece of text reminding the user of the widget's function. It is drawn immediately below the given @@ -126,14 +126,15 @@ public: bool eventFilter(QObject *, QEvent *); - QBasicTimer hideTimer; + QBasicTimer hideTimer, expireTimer; + bool fadingOut; void reuseTip(const QString &text); void hideTip(); void hideTipImmediately(); void setTipRect(QWidget *w, const QRect &r); - void restartHideTimer(); + void restartExpireTimer(); bool tipChanged(const QPoint &pos, const QString &text, QObject *o); void placeTip(const QPoint &pos, QWidget *w); @@ -190,16 +191,17 @@ QTipLabel::QTipLabel(const QString &text, QWidget *w) reuseTip(text); } -void QTipLabel::restartHideTimer() +void QTipLabel::restartExpireTimer() { int time = 10000 + 40 * qMax(0, text().length()-100); - hideTimer.start(time, this); + expireTimer.start(time, this); + hideTimer.stop(); } void QTipLabel::reuseTip(const QString &text) { #ifndef QT_NO_STYLE_STYLESHEET - if (styleSheetParent) { + if (styleSheetParent){ disconnect(styleSheetParent, SIGNAL(destroyed()), QTipLabel::instance, SLOT(styleSheetParentDestroyed())); styleSheetParent = 0; @@ -213,7 +215,7 @@ void QTipLabel::reuseTip(const QString &text) if (fm.descent() == 2 && fm.ascent() >= 11) ++extra.rheight(); resize(sizeHint() + extra); - restartHideTimer(); + restartExpireTimer(); } void QTipLabel::paintEvent(QPaintEvent *ev) @@ -257,7 +259,8 @@ QTipLabel::~QTipLabel() void QTipLabel::hideTip() { - hideTimer.start(300, this); + if (!hideTimer.isActive()) + hideTimer.start(300, this); } void QTipLabel::hideTipImmediately() @@ -278,8 +281,10 @@ void QTipLabel::setTipRect(QWidget *w, const QRect &r) void QTipLabel::timerEvent(QTimerEvent *e) { - if (e->timerId() == hideTimer.timerId()){ + if (e->timerId() == hideTimer.timerId() + || e->timerId() == expireTimer.timerId()){ hideTimer.stop(); + expireTimer.stop(); #if defined(Q_WS_MAC) && !defined(QT_NO_EFFECTS) if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip)){ // Fade out tip on mac (makes it invisible). diff --git a/src/gui/kernel/qwhatsthis.cpp b/src/gui/kernel/qwhatsthis.cpp index 3e5866a..512200f 100644 --- a/src/gui/kernel/qwhatsthis.cpp +++ b/src/gui/kernel/qwhatsthis.cpp @@ -78,7 +78,7 @@ QT_BEGIN_NAMESPACE widget, i.e. answering the question "What's This?". \ingroup helpsystem - \mainclass + "What's This?" help is part of an application's online help system, and provides users with information about the @@ -226,7 +226,9 @@ QWhatsThat::QWhatsThat(const QString& txt, QWidget* parent, QWidget *showTextFor text); } #if defined(Q_WS_WIN) - if ((QSysInfo::WindowsVersion&QSysInfo::WV_NT_based) > QSysInfo::WV_2000) { + if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP + && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) + { BOOL shadow; SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0); shadowWidth = shadow ? 0 : 6; @@ -302,7 +304,9 @@ void QWhatsThat::paintEvent(QPaintEvent*) { bool drawShadow = true; #if defined(Q_WS_WIN) - if ((QSysInfo::WindowsVersion&QSysInfo::WV_NT_based) > QSysInfo::WV_2000) { + if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP + && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) + { BOOL shadow; SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0); drawShadow = !shadow; @@ -347,6 +351,7 @@ void QWhatsThat::paintEvent(QPaintEvent*) rect.translate(-r.x(), -r.y()); p.setClipRect(rect); QAbstractTextDocumentLayout::PaintContext context; + context.palette.setBrush(QPalette::Text, context.palette.toolTipText()); doc->documentLayout()->draw(&p, context); } else diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 25299a9..44f9db1 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -99,6 +99,10 @@ #endif #include <private/qpaintengine_raster_p.h> +#if defined(Q_OS_SYMBIAN) +#include "private/qt_s60_p.h" +#endif + #include "qwidget_p.h" #include "qaction_p.h" #include "qlayout_p.h" @@ -107,6 +111,7 @@ #include "private/qgraphicsproxywidget_p.h" #include "QtGui/qabstractscrollarea.h" #include "private/qabstractscrollarea_p.h" +#include "private/qevent_p.h" #include "private/qgraphicssystem_p.h" @@ -167,39 +172,52 @@ static inline bool bypassGraphicsProxyWidget(QWidget *p) extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp -QWidgetPrivate::QWidgetPrivate(int version) : - QObjectPrivate(version), extra(0), focus_child(0) - ,layout(0), widgetItem(0) - ,leftmargin(0), topmargin(0), rightmargin(0), bottommargin(0) - ,leftLayoutItemMargin(0), topLayoutItemMargin(0), rightLayoutItemMargin(0) - ,bottomLayoutItemMargin(0) - ,fg_role(QPalette::NoRole) - ,bg_role(QPalette::NoRole) - ,hd(0) - ,dirty(0) - ,needsFlush(0) - ,dirtyOpaqueChildren(1) - ,isOpaque(0) - ,inDirtyList(0) - ,isScrolled(0) - ,isMoved(0) - ,usesDoubleBufferedGLContext(0) -#ifdef Q_WS_WIN - ,noPaintOnScreen(0) -#endif - ,inheritedFontResolveMask(0) - ,inheritedPaletteResolveMask(0) +QWidgetPrivate::QWidgetPrivate(int version) + : QObjectPrivate(version) + , extra(0) + , focus_next(0) + , focus_prev(0) + , focus_child(0) + , layout(0) + , needsFlush(0) + , redirectDev(0) + , widgetItem(0) + , extraPaintEngine(0) + , polished(0) + , graphicsEffect(0) +#if !defined(QT_NO_IM) + , imHints(Qt::ImhNone) +#endif + , inheritedFontResolveMask(0) + , inheritedPaletteResolveMask(0) + , leftmargin(0) + , topmargin(0) + , rightmargin(0) + , bottommargin(0) + , leftLayoutItemMargin(0) + , topLayoutItemMargin(0) + , rightLayoutItemMargin(0) + , bottomLayoutItemMargin(0) + , hd(0) + , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred) + , fg_role(QPalette::NoRole) + , bg_role(QPalette::NoRole) + , dirtyOpaqueChildren(1) + , isOpaque(0) + , inDirtyList(0) + , isScrolled(0) + , isMoved(0) + , usesDoubleBufferedGLContext(0) #if defined(Q_WS_X11) - ,picture(0) -#endif -#ifdef Q_WS_MAC - ,needWindowChange(0) - ,isGLWidget(0) + , picture(0) +#elif defined(Q_WS_WIN) + , noPaintOnScreen(0) +#elif defined(Q_WS_MAC) + , needWindowChange(0) + , isGLWidget(0) + , window_event(0) + , qd_hd(0) #endif - ,polished(0) - - , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred) - , redirectDev(0) { if (!qApp) { qFatal("QWidget: Must construct a QApplication before a QPaintDevice"); @@ -225,6 +243,8 @@ QWidgetPrivate::~QWidgetPrivate() if (extra) deleteExtra(); + + delete graphicsEffect; } QWindowSurface *QWidgetPrivate::createDefaultWindowSurface() @@ -390,6 +410,7 @@ void QWidget::setEditFocus(bool on) QApplication::sendEvent(f, &event); QApplication::sendEvent(f->style(), &event); } + f->repaint(); // Widget might want to repaint a focus indicator } #endif @@ -442,7 +463,7 @@ void QWidget::setAutoFillBackground(bool enabled) \brief The QWidget class is the base class of all user interface objects. \ingroup basicwidgets - \mainclass + The widget is the atom of the user interface: it receives mouse, keyboard and other events from the window system, and paints a representation of @@ -493,7 +514,7 @@ void QWidget::setAutoFillBackground(bool enabled) been outlined to indicate their full sizes. If you want to use a QWidget to hold child widgets you will usually want to - add a layout to the parent QWidget. See \l{Layout Classes} for more + add a layout to the parent QWidget. See \l{Layout Management} for more information. @@ -851,8 +872,8 @@ void QWidget::setAutoFillBackground(bool enabled) \list \o X11: This feature relies on the use of an X server that supports ARGB visuals and a compositing window manager. - \o Windows: This feature requires Windows 2000 or later. The widget needs to have - the Qt::FramelessWindowHint window flag set for the translucency to work. + \o Windows: The widget needs to have the Qt::FramelessWindowHint window flag set + for the translucency to work. \endlist @@ -878,10 +899,34 @@ void QWidget::setAutoFillBackground(bool enabled) \endlist \sa QEvent, QPainter, QGridLayout, QBoxLayout + + \section1 SoftKeys + \since 4.6 + \preliminary + + Softkeys API is a platform independent way of mapping actions to (hardware)keys + and toolbars provided by the underlying platform. + + There are three major use cases supported. First one is a mobile device + with keypad navigation and no touch ui. Second use case is a mobile + device with touch ui. Third use case is desktop. For now the softkey API is + only implemented for Series60. + + QActions are set to widget(s) via softkey API. Actions in focused widget are + mapped to native toolbar or hardware keys. Even though the API allows to set + any amount of widgets there might be physical restrictions to amount of + softkeys that can be used by the device. + + \e Series60: For series60 menu button is automatically mapped to left + soft key if there is QMainWindow with QMenuBar in widgets parent hierarchy. + + \sa softKeys() + \sa setSoftKey() + */ -QWidgetMapper *QWidgetPrivate::mapper = 0; // widget with wid -QWidgetSet *QWidgetPrivate::uncreatedWidgets = 0; // widgets with no wid +QWidgetMapper *QWidgetPrivate::mapper = 0; // widget with wid +QWidgetSet *QWidgetPrivate::allWidgets = 0; // widgets with no wid /***************************************************************************** @@ -921,6 +966,26 @@ QRegion qt_dirtyRegion(QWidget *widget) \endlist */ +struct QWidgetExceptionCleaner +{ + /* this cleans up when the constructor throws an exception */ + static inline void cleanup(QWidget *that, QWidgetPrivate *d) + { +#ifdef QT_NO_EXCEPTIONS + Q_UNUSED(that); + Q_UNUSED(d); +#else + QWidgetPrivate::allWidgets->remove(that); + if (d->focus_next != that) { + if (d->focus_next) + d->focus_next->d_func()->focus_prev = d->focus_prev; + if (d->focus_prev) + d->focus_prev->d_func()->focus_next = d->focus_next; + } +#endif + } +}; + /*! Constructs a widget which is a child of \a parent, with widget flags set to \a f. @@ -950,7 +1015,12 @@ QRegion qt_dirtyRegion(QWidget *widget) QWidget::QWidget(QWidget *parent, Qt::WindowFlags f) : QObject(*new QWidgetPrivate, 0), QPaintDevice() { - d_func()->init(parent, f); + QT_TRY { + d_func()->init(parent, f); + } QT_CATCH(...) { + QWidgetExceptionCleaner::cleanup(this, d_func()); + QT_RETHROW; + } } #ifdef QT3_SUPPORT @@ -961,8 +1031,13 @@ QWidget::QWidget(QWidget *parent, Qt::WindowFlags f) QWidget::QWidget(QWidget *parent, const char *name, Qt::WindowFlags f) : QObject(*new QWidgetPrivate, 0), QPaintDevice() { - d_func()->init(parent , f); - setObjectName(QString::fromAscii(name)); + QT_TRY { + d_func()->init(parent , f); + setObjectName(QString::fromAscii(name)); + } QT_CATCH(...) { + QWidgetExceptionCleaner::cleanup(this, d_func()); + QT_RETHROW; + } } #endif @@ -971,7 +1046,13 @@ QWidget::QWidget(QWidget *parent, const char *name, Qt::WindowFlags f) QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f) : QObject(dd, 0), QPaintDevice() { - d_func()->init(parent, f); + Q_D(QWidget); + QT_TRY { + d->init(parent, f); + } QT_CATCH(...) { + QWidgetExceptionCleaner::cleanup(this, d_func()); + QT_RETHROW; + } } /*! @@ -1027,7 +1108,7 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w) if (customize) ; // don't modify window flags if the user explicitely set them. else if (type == Qt::Dialog || type == Qt::Sheet) -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint | Qt::WindowCloseButtonHint; #else flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint; @@ -1043,11 +1124,11 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w) void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) { Q_Q(QWidget); - if (qApp->type() == QApplication::Tty) + if (QApplication::type() == QApplication::Tty) qFatal("QWidget: Cannot create a QWidget when no GUI is being used"); - Q_ASSERT(uncreatedWidgets); - uncreatedWidgets->insert(q); + Q_ASSERT(allWidgets); + allWidgets->insert(q); QWidget *desktopWidget = 0; if (parentWidget && parentWidget->windowType() == Qt::Desktop) { @@ -1058,7 +1139,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) q->data = &data; #ifndef QT_NO_THREAD - if (!q->parent()) { + if (!parent) { Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget", "Widgets must be created in the GUI thread."); } @@ -1094,7 +1175,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) if (f & Qt::MSWindowsOwnDC) q->setAttribute(Qt::WA_NativeWindow); -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE data.window_state_internal = 0; #endif @@ -1253,7 +1334,7 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow) d->create_sys(window, initializeWindow, destroyOldWindow); // a real toplevel window needs a backing store - if (isWindow()) { + if (isWindow() && windowType() != Qt::Desktop) { delete d->topData()->backingStore; // QWidgetBackingStore will check this variable, hence it must be 0 d->topData()->backingStore = 0; @@ -1336,19 +1417,35 @@ QWidget::~QWidget() #ifdef QT3_SUPPORT if (QApplicationPrivate::main_widget == this) { // reset main widget QApplicationPrivate::main_widget = 0; - qApp->quit(); + QApplication::quit(); } #endif - clearFocus(); + QT_TRY { + clearFocus(); + } QT_CATCH(...) { + // swallow this problem because we are in a destructor + } d->setDirtyOpaqueRegion(); - if (isWindow() && isVisible() && internalWinId()) - hide(); + if (isWindow() && isVisible() && internalWinId()) { + QT_TRY { + d->close_helper(QWidgetPrivate::CloseNoEvent); + } QT_CATCH(...) { + // if we're out of memory, at least hide the window. + QT_TRY { + hide(); + } QT_CATCH(...) { + // and if that also doesn't work, then give up + } + } + } + #if defined(Q_WS_WIN) || defined(Q_WS_X11) - else if (!internalWinId() && isVisible()) + else if (!internalWinId() && isVisible()) { qApp->d_func()->sendSyntheticEnterLeave(this); + } #endif if (QWidgetBackingStore *bs = d->maybeBackingStore()) { @@ -1363,17 +1460,25 @@ QWidget::~QWidget() // set all QPointers for this object to zero QObjectPrivate::clearGuards(this); + if (d->declarativeData) { + d->declarativeData->destroyed(this); + d->declarativeData = 0; // don't activate again in ~QObject + } + if (!d->children.isEmpty()) d->deleteChildren(); QApplication::removePostedEvents(this); - destroy(); // platform-dependent cleanup - + QT_TRY { + destroy(); // platform-dependent cleanup + } QT_CATCH(...) { + // if this fails we can't do anything about it but at least we are not allowed to throw. + } --QWidgetPrivate::instanceCounter; - if (QWidgetPrivate::uncreatedWidgets) // might have been deleted by ~QApplication - QWidgetPrivate::uncreatedWidgets->remove(this); + if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication + QWidgetPrivate::allWidgets->remove(this); QEvent e(QEvent::Destroy); QCoreApplication::sendEvent(this, &e); @@ -1393,7 +1498,6 @@ void QWidgetPrivate::setWinId(WId id) // set widget identifier bool userDesktopWidget = qt_desktopWidget != 0 && qt_desktopWidget != q && q->windowType() == Qt::Desktop; if (mapper && data.winid && !userDesktopWidget) { mapper->remove(data.winid); - uncreatedWidgets->insert(q); } data.winid = id; @@ -1402,7 +1506,6 @@ void QWidgetPrivate::setWinId(WId id) // set widget identifier #endif if (mapper && id && !userDesktopWidget) { mapper->insert(data.winid, q); - uncreatedWidgets->remove(q); } } @@ -1412,36 +1515,26 @@ void QWidgetPrivate::createTLExtra() createExtra(); if (!extra->topextra) { QTLWExtra* x = extra->topextra = new QTLWExtra; + x->icon = 0; + x->iconPixmap = 0; + x->backingStore = 0; x->windowSurface = 0; + x->sharedPainter = 0; + x->incw = x->inch = 0; + x->basew = x->baseh = 0; + x->frameStrut.setCoords(0, 0, 0, 0); + x->normalGeometry = QRect(0,0,-1,-1); + x->savedFlags = 0; x->opacity = 255; x->posFromMove = false; x->sizeAdjusted = false; x->inTopLevelResize = false; x->inRepaint = false; - x->backingStore = 0; - x->icon = 0; - x->iconPixmap = 0; - x->frameStrut.setCoords(0, 0, 0, 0); - x->incw = x->inch = 0; - x->basew = x->baseh = 0; - x->normalGeometry = QRect(0,0,-1,-1); -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_MAC) x->embedded = 0; -#endif -#if defined(Q_WS_X11) - x->parentWinId = 0; - x->spont_unmapped = 0; - x->dnd = 0; -#endif - x->savedFlags = 0; -#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER) - x->qwsManager = 0; -#endif - x->sharedPainter = 0; createTLSysExtra(); #ifdef QWIDGET_EXTRA_DEBUG - static int count = 0; - qDebug() << "tlextra" << ++count; + static int count = 0; + qDebug() << "tlextra" << ++count; #endif } } @@ -1455,27 +1548,28 @@ void QWidgetPrivate::createExtra() { if (!extra) { // if not exists extra = new QWExtra; - extra->minw = extra->minh = 0; - extra->maxw = extra->maxh = QWIDGETSIZE_MAX; + extra->glContext = 0; + extra->topextra = 0; + extra->proxyWidget = 0; +#ifndef QT_NO_CURSOR + extra->curs = 0; +#endif + extra->minw = 0; + extra->minh = 0; + extra->maxw = QWIDGETSIZE_MAX; + extra->maxh = QWIDGETSIZE_MAX; + extra->customDpiX = 0; + extra->customDpiY = 0; extra->explicitMinSize = 0; extra->explicitMaxSize = 0; extra->autoFillBackground = 0; extra->nativeChildrenForced = 0; extra->inRenderWithPainter = 0; extra->hasMask = 0; -#ifndef QT_NO_CURSOR - extra->curs = 0; -#endif - extra->style = 0; - extra->topextra = 0; - extra->proxyWidget = 0; - extra->glContext = 0; - extra->customDpiX = 0; - extra->customDpiY = 0; createSysExtra(); #ifdef QWIDGET_EXTRA_DEBUG - static int count = 0; - qDebug() << "extra" << ++count; + static int count = 0; + qDebug() << "extra" << ++count; #endif } } @@ -1516,45 +1610,6 @@ void QWidgetPrivate::deleteExtra() } /* - Returns true if the background is inherited; otherwise returns - false. - - Mainly used in the paintOnScreen case. -*/ - -bool QWidgetPrivate::isBackgroundInherited() const -{ - Q_Q(const QWidget); - - // windows do not inherit their background - if (q->isWindow() || q->windowType() == Qt::SubWindow) - return false; - - if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent)) - return false; - - const QPalette &pal = q->palette(); - QPalette::ColorRole bg = q->backgroundRole(); - QBrush brush = pal.brush(bg); - - // non opaque brushes leaves us no choice, we must inherit - if (!q->autoFillBackground() || !brush.isOpaque()) - return true; - - if (brush.style() == Qt::SolidPattern) { - // the background is just a solid color. If there is no - // propagated contents, then we claim as performance - // optimization that it was not inheritet. This is the normal - // case in standard Windows or Motif style. - const QWidget *w = q->parentWidget(); - if (!w->d_func()->isBackgroundInherited()) - return false; - } - - return true; -} - -/* Returns true if there are widgets above this which overlap with \a rect, which is in parent's coordinate system (same as crect). */ @@ -1579,9 +1634,9 @@ bool QWidgetPrivate::isOverlapped(const QRect &rect) const continue; } - if (qRectIntersects(sibling->data->crect, r)) { + if (qRectIntersects(sibling->d_func()->effectiveRectFor(sibling->data->crect), r)) { const QWExtra *siblingExtra = sibling->d_func()->extra; - if (siblingExtra && siblingExtra->hasMask + if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) { continue; } @@ -1680,7 +1735,7 @@ QRect QWidgetPrivate::clipRect() const const QWidget * w = q; if (!w->isVisible()) return QRect(); - QRect r = q->rect(); + QRect r = effectiveRectFor(q->rect()); int ox = 0; int oy = 0; while (w @@ -1822,12 +1877,14 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt break; QWidgetPrivate *pd = w->parentWidget()->d_func(); const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w)); + const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect); for (int i = myIndex + 1; i < pd->children.size(); ++i) { QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i)); if (!sibling || !sibling->isVisible() || sibling->isWindow()) continue; - if (!qRectIntersects(sibling->data->crect, w->data->crect)) + const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect); + if (!qRectIntersects(siblingGeometry, widgetGeometry)) continue; if (dirtyClipBoundingRect) { @@ -1835,7 +1892,7 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt dirtyClipBoundingRect = false; } - if (!qRectIntersects(sibling->data->crect, clipBoundingRect.translated(parentOffset))) + if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset))) continue; if (dirtyParentClip) { @@ -1847,7 +1904,8 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt const QRect siblingClipRect(sibling->d_func()->clipRect()); QRegion siblingDirty(parentClip); siblingDirty &= (siblingClipRect.translated(siblingPos)); - const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask; + const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask + && !sibling->d_func()->graphicsEffect; if (hasMask) siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos); if (siblingDirty.isEmpty()) @@ -1858,7 +1916,7 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt siblingDirty.translate(-parentOffset); sourceRegion -= siblingDirty; } else { - sourceRegion -= sibling->data->crect.translated(-parentOffset); + sourceRegion -= siblingGeometry.translated(-parentOffset); } } else { if (hasDirtySiblingsAbove) @@ -1889,6 +1947,11 @@ void QWidgetPrivate::clipToEffectiveMask(QRegion ®ion) const const QWidget *w = q; QPoint offset; + if (graphicsEffect) { + w = q->parentWidget(); + offset -= data.crect.topLeft(); + } + while (w) { const QWidgetPrivate *wd = w->d_func(); if (wd->extra && wd->extra->hasMask) @@ -1900,24 +1963,6 @@ void QWidgetPrivate::clipToEffectiveMask(QRegion ®ion) const } } -bool QWidgetPrivate::hasBackground() const -{ - Q_Q(const QWidget); - if (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_PaintOnScreen)) - return true; - if (q->testAttribute(Qt::WA_PaintOnScreen)) - return true; - if (!q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) { - const QPalette &pal = q->palette(); - QPalette::ColorRole bg = q->backgroundRole(); - QBrush bgBrush = pal.brush(bg); - return (bgBrush.style() != Qt::NoBrush && - ((q->isWindow() || q->windowType() == Qt::SubWindow) - || (QPalette::ColorRole(bg_role) != QPalette::NoRole || (pal.resolve() & (1<<bg))))); - } - return false; -} - bool QWidgetPrivate::paintOnScreen() const { #if defined(Q_WS_QWS) @@ -1940,6 +1985,12 @@ void QWidgetPrivate::updateIsOpaque() // hw: todo: only needed if opacity actually changed setDirtyOpaqueRegion(); + if (graphicsEffect) { + // ### We should probably add QGraphicsEffect::isOpaque at some point. + setOpaque(false); + return; + } + Q_Q(QWidget); #ifdef Q_WS_X11 if (q->testAttribute(Qt::WA_X11OpenGLOverlay)) { @@ -1987,6 +2038,9 @@ void QWidgetPrivate::setOpaque(bool opaque) #ifdef Q_WS_WIN winUpdateIsOpaque(); #endif +#ifdef Q_OS_SYMBIAN + s60UpdateIsOpaque(); +#endif } void QWidgetPrivate::updateIsTranslucent() @@ -2000,6 +2054,9 @@ void QWidgetPrivate::updateIsTranslucent() #ifdef Q_WS_WIN winUpdateIsOpaque(); #endif +#ifdef Q_OS_SYMBIAN + s60UpdateIsOpaque(); +#endif } /*! @@ -2020,10 +2077,9 @@ void QPixmap::fill( const QWidget *widget, const QPoint &off ) QPainter p(this); p.translate(-off); widget->d_func()->paintBackground(&p, QRect(off, size())); - } -static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QPoint &offset, const QBrush &brush) +static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush) { Q_ASSERT(painter); @@ -2032,26 +2088,46 @@ static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QPoin // Optimize pattern filling on mac by using HITheme directly // when filling with the standard widget background. // Defined in qmacstyle_mac.cpp - extern void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QPoint &offset, const QBrush &brush); - qt_mac_fill_background(painter, rgn, offset, brush); + extern void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush); + qt_mac_fill_background(painter, rgn, brush); #else - const QRegion translated = rgn.translated(offset); - const QRect rect(translated.boundingRect()); - painter->setClipRegion(translated); - painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); -#endif +#if !defined(QT_NO_STYLE_S60) + // Defined in qs60style.cpp + extern bool qt_s60_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush); + if (!qt_s60_fill_background(painter, rgn, brush)) +#endif // !defined(QT_NO_STYLE_S60) + { + const QRect rect(rgn.boundingRect()); + painter->setClipRegion(rgn); + painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); + } +#endif // Q_WS_MAC } else { const QVector<QRect> &rects = rgn.rects(); for (int i = 0; i < rects.size(); ++i) - painter->fillRect(rects.at(i).translated(offset), brush); + painter->fillRect(rects.at(i), brush); } } - -void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, const QPoint &offset, int flags) const +void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int flags) const { Q_Q(const QWidget); +#ifndef QT_NO_SCROLLAREA + bool resetBrushOrigin = false; + QPointF oldBrushOrigin; + //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture + QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent); + if (scrollArea && scrollArea->viewport() == q) { + QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data(); + QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate); + oldBrushOrigin = painter->brushOrigin(); + resetBrushOrigin = true; + painter->setBrushOrigin(-priv->contentsOffset()); + + } +#endif // QT_NO_SCROLLAREA + const QBrush autoFillBrush = q->palette().brush(q->backgroundRole()); if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) { @@ -2060,18 +2136,24 @@ void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, cons if (!(flags & DontSetCompositionMode) && painter->paintEngine()->hasFeature(QPaintEngine::PorterDuff)) painter->setCompositionMode(QPainter::CompositionMode_Source); //copy alpha straight in #endif - fillRegion(painter, rgn, offset, bg); + fillRegion(painter, rgn, bg); } if (q->autoFillBackground()) - fillRegion(painter, rgn, offset, autoFillBrush); + fillRegion(painter, rgn, autoFillBrush); + if (q->testAttribute(Qt::WA_StyledBackground)) { - painter->setClipRegion(rgn.translated(offset)); + painter->setClipRegion(rgn); QStyleOption opt; opt.initFrom(q); q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q); } + +#ifndef QT_NO_SCROLLAREA + if (resetBrushOrigin) + painter->setBrushOrigin(oldBrushOrigin); +#endif // QT_NO_SCROLLAREA } /* @@ -2091,8 +2173,8 @@ void QWidgetPrivate::deactivateWidgetCleanup() { Q_Q(QWidget); // If this was the active application window, reset it - if (qApp->activeWindow() == q) - qApp->setActiveWindow(0); + if (QApplication::activeWindow() == q) + QApplication::setActiveWindow(0); // If the is the active mouse press widget, reset it if (q == qt_button_down) qt_button_down = 0; @@ -2293,7 +2375,7 @@ QStyle *QWidget::style() const if (d->extra && d->extra->style) return d->extra->style; - return qApp->style(); + return QApplication::style(); } /*! @@ -2612,7 +2694,7 @@ bool QWidget::isMaximized() const */ Qt::WindowStates QWidget::windowState() const { - return (Qt::WindowStates)data->window_state; + return Qt::WindowStates(data->window_state); } /*!\internal @@ -2624,7 +2706,7 @@ Qt::WindowStates QWidget::windowState() const */ void QWidget::overrideWindowState(Qt::WindowStates newstate) { - QWindowStateChangeEvent e((Qt::WindowStates)data->window_state, true); + QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true); data->window_state = newstate; QApplication::sendEvent(this, &e); } @@ -2723,7 +2805,7 @@ void QWidget::showFullScreen() Calling this function only affects \l{isWindow()}{windows}. On X11, this function may not work properly with certain window - managers. See \l{geometry.html}{Window Geometry} for an explanation. + managers. See the \l{Window Geometry} documentation for an explanation. \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible() */ @@ -2778,7 +2860,7 @@ void QWidget::showNormal() bool QWidget::isEnabledTo(QWidget* ancestor) const { const QWidget * w = this; - while (w && !w->testAttribute(Qt::WA_ForceDisabled) + while (!w->testAttribute(Qt::WA_ForceDisabled) && !w->isWindow() && w->parentWidget() && w->parentWidget() != ancestor) @@ -2969,10 +3051,15 @@ void QWidgetPrivate::setEnabled_helper(bool enable) #if defined(Q_WS_MAC) setEnabled_helper_sys(enable); #endif -#if defined (Q_WS_WIN) - if (q->hasFocus()) - QInputContextPrivate::updateImeStatus(q, true); -#endif + if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) { + QInputContext *qic = inputContext(); + if (enable) { + qic->setFocusWidget(q); + } else { + qic->reset(); + qic->setFocusWidget(0); + } + } QEvent e(QEvent::EnabledChange); QApplication::sendEvent(q, &e); #ifdef QT3_SUPPORT @@ -3067,8 +3154,8 @@ void QWidget::setDisabled(bool disable) \brief geometry of the widget relative to its parent including any window frame - See the \link geometry.html Window Geometry documentation\endlink - for an overview of geometry issues with windows. + See the \l{Window Geometry} documentation for an overview of geometry + issues with windows. By default, this property contains a value that depends on the user's platform and screen geometry. @@ -3094,8 +3181,8 @@ QRect QWidget::frameGeometry() const \brief the x coordinate of the widget relative to its parent including any window frame - See the \link geometry.html Window Geometry documentation\endlink - for an overview of window geometry. + See the \l{Window Geometry} documentation for an overview of geometry + issues with windows. By default, this property has a value of 0. @@ -3114,8 +3201,8 @@ int QWidget::x() const \brief the y coordinate of the widget relative to its parent and including any window frame - See the \link geometry.html Window Geometry documentation\endlink - for an overview of window geometry. + See the \l{Window Geometry} documentation for an overview of geometry + issues with windows. By default, this property has a value of 0. @@ -3147,8 +3234,8 @@ int QWidget::y() const \warning Calling move() or setGeometry() inside moveEvent() can lead to infinite recursion. - See the \link geometry.html Window Geometry documentation\endlink - for an overview of window geometry. + See the \l{Window Geometry} documentation for an overview of geometry + issues with windows. \sa frameGeometry, size x(), y() */ @@ -3178,8 +3265,8 @@ QPoint QWidget::pos() const \warning Calling setGeometry() inside resizeEvent() or moveEvent() can lead to infinite recursion. - See the \link geometry.html Window Geometry documentation\endlink - for an overview of window geometry. + See the \l{Window Geometry} documentation for an overview of geometry + issues with windows. By default, this property contains a value that depends on the user's platform and screen geometry. @@ -3228,8 +3315,8 @@ QPoint QWidget::pos() const \property QWidget::width \brief the width of the widget excluding any window frame - See the \link geometry.html Window Geometry documentation\endlink - for an overview of window geometry. + See the \l{Window Geometry} documentation for an overview of geometry + issues with windows. \note Do not use this function to find the width of a screen on a \l{QDesktopWidget}{multiple screen desktop}. Read @@ -3245,8 +3332,8 @@ QPoint QWidget::pos() const \property QWidget::height \brief the height of the widget excluding any window frame - See the \link geometry.html Window Geometry documentation\endlink - for an overview of window geometry. + See the \l{Window Geometry} documentation for an overview of geometry + issues with windows. \note Do not use this function to find the height of a screen on a \l {QDesktopWidget} {multiple screen desktop}. Read @@ -3265,8 +3352,8 @@ QPoint QWidget::pos() const The rect property equals QRect(0, 0, width(), height()). - See the \link geometry.html Window Geometry documentation\endlink - for an overview of window geometry. + See the \l{Window Geometry} documentation for an overview of geometry + issues with windows. By default, this property contains a value that depends on the user's platform and screen geometry. @@ -3506,27 +3593,32 @@ bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh) } } #endif + int mw = minw, mh = minh; + if (mw == QWIDGETSIZE_MAX) + mw = 0; + if (mh == QWIDGETSIZE_MAX) + mh = 0; if (minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX) { qWarning("QWidget::setMinimumSize: (%s/%s) " "The largest allowed size is (%d,%d)", q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); - minw = qMin<int>(minw, QWIDGETSIZE_MAX); - minh = qMin<int>(minh, QWIDGETSIZE_MAX); + minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX); + minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX); } if (minw < 0 || minh < 0) { qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) " "are not possible", q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh); - minw = qMax(minw, 0); - minh = qMax(minh, 0); + minw = mw = qMax(minw, 0); + minh = mh = qMax(minh, 0); } createExtra(); - if (extra->minw == minw && extra->minh == minh) + if (extra->minw == mw && extra->minh == mh) return false; - extra->minw = minw; - extra->minh = minh; - extra->explicitMinSize = (minw ? Qt::Horizontal : 0) | (minh ? Qt::Vertical : 0); + extra->minw = mw; + extra->minh = mh; + extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0); return true; } @@ -3586,7 +3678,8 @@ bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh) return false; extra->maxw = maxw; extra->maxh = maxh; - extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) | (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0); + extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) | + (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0); return true; } @@ -3665,6 +3758,8 @@ void QWidget::setBaseSize(int basew, int baseh) This will override the default size constraints set by QLayout. + To remove constraints, set the size to QWIDGETSIZE_MAX. + Alternatively, if you want the widget to have a fixed size based on its contents, you can call QLayout::setSizeConstraint(QLayout::SetFixedSize); @@ -3706,7 +3801,8 @@ void QWidget::setFixedSize(int w, int h) else d->updateGeometry_helper(true); - resize(w, h); + if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX) + resize(w, h); } void QWidget::setMinimumWidth(int w) @@ -4079,6 +4175,10 @@ QPalette::ColorRole QWidget::backgroundRole() const If \a role is QPalette::NoRole, then the widget inherits its parent's background role. + Note that styles are free to choose any color from the palette. + You can modify the palette or set a style sheet if you don't + achieve the result you want with setBackgroundRole(). + \sa backgroundRole(), foregroundRole() */ @@ -4141,6 +4241,10 @@ QPalette::ColorRole QWidget::foregroundRole() const If \a role is QPalette::NoRole, the widget uses a foreground role that contrasts with the background role. + Note that styles are free to choose any color from the palette. + You can modify the palette or set a style sheet if you don't + achieve the result you want with setForegroundRole(). + \sa foregroundRole(), backgroundRole() */ void QWidget::setForegroundRole(QPalette::ColorRole role) @@ -4209,7 +4313,7 @@ const QPalette &QWidget::palette() const if (!isEnabled()) { data->pal.setCurrentColorGroup(QPalette::Disabled); } else if ((!isVisible() || isActiveWindow()) -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_OS_WIN) && !defined(Q_WS_WINCE) && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this)) #endif ) { @@ -4621,8 +4725,9 @@ void QWidget::setCursor(const QCursor &cursor) #endif { d->createExtra(); + QCursor *newCursor = new QCursor(cursor); delete d->extra->curs; - d->extra->curs = new QCursor(cursor); + d->extra->curs = newCursor; } setAttribute(Qt::WA_SetCursor); d->setCursor_sys(cursor); @@ -4802,7 +4907,7 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset, } const qreal opacity = painter->opacity(); - if (qFuzzyCompare(opacity + 1, qreal(1.0))) + if (qFuzzyIsNull(opacity)) return; // Fully transparent. Q_D(QWidget); @@ -4864,6 +4969,70 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset, d->extra->inRenderWithPainter = false; } +#if !defined(Q_OS_SYMBIAN) +void QWidgetPrivate::setSoftKeys_sys(const QList<QAction*> &softkeys) +{ + Q_UNUSED(softkeys) +} +#endif // !defined(Q_OS_SYMBIAN) + +/*! + Returns a pointer to this widget's effect if it has one; otherwise 0. + + \since 4.6 + + \sa setGraphicsEffect() +*/ +QGraphicsEffect *QWidget::graphicsEffect() const +{ + Q_D(const QWidget); + return d->graphicsEffect; +} + +/*! + Sets \a effect as the widget's effect. If there already is an effect installed + on this widget, QWidget will delete the existing effect before installing + the new \a effect. + + If \a effect is the installed on a different widget, setGraphicsEffect() will remove + the effect from the widget and install it on this widget. + + \note This function will apply the effect on itself and all its children. + + \since 4.6 + + \sa graphicsEffect() +*/ +void QWidget::setGraphicsEffect(QGraphicsEffect *effect) +{ + Q_D(QWidget); + if (d->graphicsEffect == effect) + return; + + if (d->graphicsEffect && effect) { + delete d->graphicsEffect; + d->graphicsEffect = 0; + } + + if (!effect) { + // Unset current effect. + QGraphicsEffectPrivate *oldEffectPrivate = d->graphicsEffect->d_func(); + d->graphicsEffect = 0; + if (oldEffectPrivate) { + oldEffectPrivate->setGraphicsEffectSource(0); // deletes the current source. + } + } else { + // Set new effect. + QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this); + QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced); + d->graphicsEffect = effect; + effect->d_func()->setGraphicsEffectSource(source); + } + + d->updateIsOpaque(); + update(); +} + bool QWidgetPrivate::isAboutToShow() const { if (data.in_show) @@ -5008,6 +5177,33 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP return; Q_Q(QWidget); + if (graphicsEffect && graphicsEffect->isEnabled()) { + QGraphicsEffectSource *source = graphicsEffect->d_func()->source; + QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *> + (source->d_func()); + if (!sourced->context) { + QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore); + sourced->context = &context; + if (!sharedPainter) { + QPaintEngine *paintEngine = pdev->paintEngine(); + paintEngine->d_func()->systemClip = rgn.translated(offset); + QPainter p(pdev); + p.translate(offset); + context.painter = &p; + graphicsEffect->draw(&p, source); + paintEngine->d_func()->systemClip = QRegion(); + } else { + context.painter = sharedPainter; + sharedPainter->save(); + sharedPainter->translate(offset); + graphicsEffect->draw(sharedPainter, source); + sharedPainter->restore(); + } + sourced->context = 0; + return; + } + } + const bool asRoot = flags & DrawAsRoot; const bool alsoOnScreen = flags & DrawPaintOnScreen; const bool recursive = flags & DrawRecursive; @@ -5040,26 +5236,14 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP if (sharedPainter) paintEngine->d_func()->systemClip = toBePainted; else - paintEngine->setSystemRect(q->data->crect); + paintEngine->d_func()->systemRect = q->data->crect; //paint the background if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground)) && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) { QPainter p(q); - QPoint scrollAreaOffset; - -#ifndef QT_NO_SCROLLAREA - QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(q->parent()); - if (scrollArea && scrollArea->viewport() == q) { - QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr; - QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate); - scrollAreaOffset = priv->contentsOffset(); - p.translate(-scrollAreaOffset); - } -#endif // QT_NO_SCROLLAREA - - paintBackground(&p, toBePainted, scrollAreaOffset, (asRoot || onScreen) ? flags | DrawAsRoot : 0); + paintBackground(&p, toBePainted, (asRoot || onScreen) ? flags | DrawAsRoot : 0); } if (!sharedPainter) @@ -5091,7 +5275,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP if (paintEngine) { restoreRedirected(); if (!sharedPainter) - paintEngine->setSystemRect(QRect()); + paintEngine->d_func()->systemRect = QRect(); else paintEngine->d_func()->currentClipWidget = 0; paintEngine->d_func()->systemClip = QRegion(); @@ -5154,7 +5338,7 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis dirtyBoundingRect = false; } - if (qRectIntersects(boundingRect, x->data->crect)) { + if (qRectIntersects(boundingRect, x->d_func()->effectiveRectFor(x->data->crect))) { #ifdef Q_BACKINGSTORE_SUBSURFACES if (x->windowSurface() == currentSurface) #endif @@ -5172,7 +5356,7 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis QWidgetPrivate *wd = w->d_func(); const QPoint widgetPos(w->data->crect.topLeft()); - const bool hasMask = wd->extra && wd->extra->hasMask; + const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect; if (index > 0) { QRegion wr(rgn); @@ -5187,7 +5371,7 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis if (w->updatesEnabled() && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)) { QRegion wRegion(rgn); - wRegion &= w->data->crect; + wRegion &= wd->effectiveRectFor(w->data->crect); wRegion.translate(-widgetPos); if (hasMask) wRegion &= wd->extra->mask; @@ -5195,6 +5379,93 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis } } +QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const +{ + if (system != Qt::DeviceCoordinates) + return m_widget->rect(); + + if (!context) { + // Device coordinates without context not yet supported. + qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context"); + return QRectF(); + } + + return context->painter->worldTransform().mapRect(m_widget->rect()); +} + +void QWidgetEffectSourcePrivate::draw(QPainter *painter) +{ + if (!context || context->painter != painter) { + m_widget->render(painter); + return; + } + + // The region saved in the context is neither clipped to the rect + // nor the mask, so we have to clip it here before calling drawWidget. + QRegion toBePainted = context->rgn; + toBePainted &= m_widget->rect(); + QWidgetPrivate *wd = qt_widget_private(m_widget); + if (wd->extra && wd->extra->hasMask) + toBePainted &= wd->extra->mask; + + wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags, + context->sharedPainter, context->backingStore); +} + +QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const +{ + const bool deviceCoordinates = (system == Qt::DeviceCoordinates); + if (!context && deviceCoordinates) { + // Device coordinates without context not yet supported. + qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context"); + return QPixmap(); + } + + QPoint pixmapOffset; + QRectF sourceRect = m_widget->rect(); + + if (deviceCoordinates) { + const QTransform &painterTransform = context->painter->worldTransform(); + sourceRect = painterTransform.mapRect(sourceRect); + pixmapOffset = painterTransform.map(pixmapOffset); + } + + QRect effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); + if (offset) + *offset = effectRect.topLeft(); + + if (deviceCoordinates) { + // Clip to device rect. + int left, top, right, bottom; + effectRect.getCoords(&left, &top, &right, &bottom); + if (left < 0) { + if (offset) + offset->rx() += -left; + effectRect.setX(0); + } + if (top < 0) { + if (offset) + offset->ry() += -top; + effectRect.setY(0); + } + // NB! We use +-1 for historical reasons (see QRect documentation). + QPaintDevice *device = context->painter->device(); + const int deviceWidth = device->width(); + const int deviceHeight = device->height(); + if (right + 1 > deviceWidth) + effectRect.setRight(deviceWidth - 1); + if (bottom + 1 > deviceHeight) + effectRect.setBottom(deviceHeight -1); + } + + pixmapOffset -= effectRect.topLeft(); + + QPixmap pixmap(effectRect.size()); + pixmap.fill(Qt::transparent); + m_widget->render(&pixmap, pixmapOffset); + return pixmap; +} + /*! \internal @@ -5293,7 +5564,7 @@ static QString constructWindowTitleFromFilePath(const QString &filePath) #ifndef Q_WS_MAC QString appName = QApplication::applicationName(); if (!appName.isEmpty()) - windowTitle += QLatin1String(" ") + QChar(0x2014) + QLatin1String(" ") + appName; + windowTitle += QLatin1Char(' ') + QChar(0x2014) + QLatin1Char(' ') + appName; #endif return windowTitle; } @@ -5328,6 +5599,17 @@ QString QWidget::windowTitle() const return QString(); } +/*! + Returns a modified window title with the [*] place holder + replaced according to the rules described in QWidget::setWindowTitle + + This function assumes that "[*]" can be quoted by another + "[*]", so it will replace two place holders by one and + a single last one by either "*" or nothing depending on + the modified flag. + + \internal +*/ QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget) { Q_ASSERT(widget); @@ -5339,16 +5621,21 @@ QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widg QString cap = title; #endif - QString placeHolder(QLatin1String("[*]")); + if (cap.isEmpty()) + return cap; + + QLatin1String placeHolder("[*]"); + int placeHolderLength = 3; // QLatin1String doesn't have length() int index = cap.indexOf(placeHolder); + // here the magic begins while (index != -1) { - index += placeHolder.length(); + index += placeHolderLength; int count = 1; while (cap.indexOf(placeHolder, index) == index) { ++count; - index += placeHolder.length(); + index += placeHolderLength; } if (count%2) { // odd number of [*] -> replace last one @@ -5357,13 +5644,13 @@ QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widg && widget->style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, 0, widget)) cap.replace(lastIndex, 3, QWidget::tr("*")); else - cap.replace(lastIndex, 3, QLatin1String("")); + cap.remove(lastIndex, 3); } index = cap.indexOf(placeHolder, index); } - cap.replace(QLatin1String("[*][*]"), QLatin1String("[*]")); + cap.replace(QLatin1String("[*][*]"), placeHolder); return cap; } @@ -5429,7 +5716,7 @@ QIcon QWidget::windowIcon() const return *d->extra->topextra->icon; w = w->parentWidget(); } - return qApp->windowIcon(); + return QApplication::windowIcon(); } void QWidgetPrivate::setWindowIcon_helper() @@ -5492,8 +5779,6 @@ QString QWidget::windowIconText() const \list \o The file name of the specified path, obtained using QFileInfo::fileName(). - \o An optional \c{*} character, if the \l windowModified property is set, - as per the Apple Human Interface Guidelines. \endlist On Windows and X11: @@ -5542,7 +5827,7 @@ void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath) { if (extra->topextra && extra->topextra->caption.isEmpty()) { #ifdef Q_WS_MAC - setWindowTitle_helper(filePath); + setWindowTitle_helper(QFileInfo(filePath).fileName()); #else Q_Q(QWidget); Q_UNUSED(filePath); @@ -5675,6 +5960,8 @@ bool QWidget::hasFocus() const isActiveWindow() active window\endlink. The \a reason argument will be passed into any focus event sent from this function, it is used to give an explanation of what caused the widget to get focus. + If the window is not active, the widget will be given the focus when + the window becomes active. First, a focus out event is sent to the focus widget (if any) to tell it that it is about to lose the focus. Then a focus in event @@ -5692,7 +5979,7 @@ bool QWidget::hasFocus() const called from focusOutEvent() or focusInEvent(), you may get an infinite recursion. - \sa focus(), hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(), + \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(), setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(), grabMouse(), {Keyboard Focus} */ @@ -5913,6 +6200,8 @@ QWidget *QWidget::focusWidget() const /*! Returns the next widget in this widget's focus chain. + + \sa previousInFocusChain() */ QWidget *QWidget::nextInFocusChain() const { @@ -5920,6 +6209,18 @@ QWidget *QWidget::nextInFocusChain() const } /*! + Returns the previous widget in this widget's focus chain. + + \sa nextInFocusChain() + + \since 4.6 +*/ +QWidget *QWidget::previousInFocusChain() const +{ + return const_cast<QWidget *>(d_func()->focus_prev); +} + +/*! \property QWidget::isActiveWindow \brief whether this widget's window is the active window @@ -5937,7 +6238,7 @@ QWidget *QWidget::nextInFocusChain() const bool QWidget::isActiveWindow() const { QWidget *tlw = window(); - if(tlw == qApp->activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup))) + if(tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup))) return true; #ifndef QT_NO_GRAPHICSVIEW @@ -5952,13 +6253,17 @@ bool QWidget::isActiveWindow() const if(qt_mac_is_macdrawer(tlw) && tlw->parentWidget() && tlw->parentWidget()->isActiveWindow()) return true; + + extern bool qt_mac_insideKeyWindow(const QWidget *); //qwidget_mac.cpp + if (QApplication::testAttribute(Qt::AA_MacPluginApplication) && qt_mac_insideKeyWindow(tlw)) + return true; #endif if(style()->styleHint(QStyle::SH_Widget_ShareActivation, 0, this)) { if(tlw->windowType() == Qt::Tool && !tlw->isModal() && (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow())) return true; - QWidget *w = qApp->activeWindow(); + QWidget *w = QApplication::activeWindow(); while(w && tlw->windowType() == Qt::Tool && !w->isModal() && w->parentWidget()) { w = w->parentWidget()->window(); @@ -6157,14 +6462,6 @@ int QWidgetPrivate::pointToRect(const QPoint &p, const QRect &r) return dx + dy; } -QRect QWidgetPrivate::fromOrToLayoutItemRect(const QRect &rect, int sign) const -{ - QRect r = rect; - r.adjust(-sign * leftLayoutItemMargin, -sign * topLayoutItemMargin, - +sign * rightLayoutItemMargin, +sign * bottomLayoutItemMargin); - return r; -} - /*! \property QWidget::frameSize \brief the size of the widget including any window frame @@ -6253,8 +6550,8 @@ void QWidget::setGeometry(const QRect &r) \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 11 - See the \link geometry.html Window Geometry documentation\endlink - for an overview of geometry issues with windows. + See the \l{Window Geometry} documentation for an overview of geometry + issues with windows. Use QMainWindow::saveState() to save the geometry and the state of toolbars and dock widgets. @@ -6295,8 +6592,8 @@ QByteArray QWidget::saveGeometry() const \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 12 - See the \link geometry.html Window Geometry documentation\endlink - for an overview of geometry issues with windows. + See the \l{Window Geometry} documentation for an overview of geometry + issues with windows. Use QMainWindow::restoreState() to restore the geometry and the state of toolbars and dock widgets. @@ -6451,7 +6748,27 @@ void QWidget::setContentsMargins(int left, int top, int right, int bottom) QApplication::sendEvent(this, &e); } -/*! Returns the widget's contents margins for \a left, \a top, \a +/*! + \overload + \since 4.6 + + Sets the margins around the contents of the widget to have the + sizes determined by \a margins. The margins are + used by the layout system, and may be used by subclasses to + specify the area to draw in (e.g. excluding the frame). + + Changing the margins will trigger a resizeEvent(). + + \sa contentsRect(), getContentsMargins() +*/ +void QWidget::setContentsMargins(const QMargins &margins) +{ + setContentsMargins(margins.left(), margins.top(), + margins.right(), margins.bottom()); +} + +/*! + Returns the widget's contents margins for \a left, \a top, \a right, and \a bottom. \sa setContentsMargins(), contentsRect() @@ -6470,6 +6787,20 @@ void QWidget::getContentsMargins(int *left, int *top, int *right, int *bottom) c } /*! + \since 4.6 + + Returns the widget's contents margins. + + \sa getContentsMargins(), setContentsMargins(), contentsRect() + */ +QMargins QWidget::contentsMargins() const +{ + Q_D(const QWidget); + return QMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin); +} + + +/*! Returns the area inside the widget's margins. \sa setContentsMargins(), getContentsMargins() @@ -6751,7 +7082,7 @@ void QWidgetPrivate::show_helper() // On Windows, show the popup now so that our own focus handling // stores the correct old focus widget even if it's stolen in the // showevent -#if defined(Q_WS_WIN) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_OS_SYMBIAN) if (!isEmbedded && q->windowType() == Qt::Popup) qApp->d_func()->openPopup(q); #endif @@ -6768,7 +7099,7 @@ void QWidgetPrivate::show_helper() show_sys(); -#if !defined(Q_WS_WIN) && !defined(Q_WS_MAC) +#if !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN) if (!isEmbedded && q->windowType() == Qt::Popup) qApp->d_func()->openPopup(q); #endif @@ -6888,9 +7219,12 @@ void QWidgetPrivate::hide_helper() widgets that are not visible. - Widgets are hidden if they were created as independent - windows or as children of visible widgets, or if hide() or setVisible(false) was called. - + Widgets are hidden if: + \list + \o they were created as independent windows, + \o they were created as children of visible widgets, + \o hide() or setVisible(false) was called. + \endlist */ @@ -7136,7 +7470,7 @@ bool QWidgetPrivate::close_helper(CloseMode mode) #ifdef QT3_SUPPORT if (isMain) - qApp->quit(); + QApplication::quit(); #endif // Attempt to close the application only if this widget has the // WA_QuitOnClose flag set set and has a non-visible parent @@ -7261,8 +7595,7 @@ bool QWidget::isVisibleTo(QWidget* ancestor) const if (!ancestor) return isVisible(); const QWidget * w = this; - while (w - && !w->isHidden() + while (!w->isHidden() && !w->isWindow() && w->parentWidget() && w->parentWidget() != ancestor) @@ -7319,10 +7652,10 @@ QSize QWidgetPrivate::adjustedSize() const if (q->isWindow()) { Qt::Orientations exp; - if (QLayout *l = q->layout()) { - if (l->hasHeightForWidth()) - s.setHeight(l->totalHeightForWidth(s.width())); - exp = l->expandingDirections(); + if (layout) { + if (layout->hasHeightForWidth()) + s.setHeight(layout->totalHeightForWidth(s.width())); + exp = layout->expandingDirections(); } else { if (q->sizePolicy().hasHeightForWidth()) @@ -7338,7 +7671,7 @@ QSize QWidgetPrivate::adjustedSize() const #else // all others QRect screen = QApplication::desktop()->screenGeometry(q->pos()); #endif -#if defined (Q_OS_WINCE) +#if defined (Q_WS_WINCE) || defined (Q_OS_SYMBIAN) s.setWidth(qMin(s.width(), screen.width())); s.setHeight(qMin(s.height(), screen.height())); #else @@ -7525,6 +7858,9 @@ bool QWidget::event(QEvent *event) case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::MouseMove: + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: case QEvent::ContextMenu: #ifndef QT_NO_WHEELEVENT case QEvent::Wheel: @@ -7646,16 +7982,11 @@ bool QWidget::event(QEvent *event) } break; case QEvent::FocusIn: -#if defined(Q_WS_WIN) - QInputContextPrivate::updateImeStatus(this, true); -#endif + d->setSoftKeys_sys(softKeys()); focusInEvent((QFocusEvent*)event); break; case QEvent::FocusOut: -#if defined(Q_WS_WIN) - QInputContextPrivate::updateImeStatus(this, false); -#endif focusOutEvent((QFocusEvent*)event); break; @@ -7801,6 +8132,10 @@ bool QWidget::event(QEvent *event) if (w && w->isVisible() && !w->isWindow()) QApplication::sendEvent(w, event); } + + if (isWindow() && isActiveWindow()) + d->setSoftKeys_sys(softKeys()); + break; } case QEvent::LanguageChange: @@ -7841,7 +8176,7 @@ bool QWidget::event(QEvent *event) QList<QObject*> childList = d->children; for (int i = 0; i < childList.size(); ++i) { QObject *o = childList.at(i); - if (o != qApp->activeModalWidget()) { + if (o != QApplication::activeModalWidget()) { if (qobject_cast<QWidget *>(o) && static_cast<QWidget *>(o)->isWindow()) { // do not forward the event to child windows, // QApplication does this for us @@ -7930,6 +8265,49 @@ bool QWidget::event(QEvent *event) d->needWindowChange = false; break; #endif + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + { + QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event); + const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().first(); + if (touchPoint.isPrimary()) + break; + + // fake a mouse event! + QEvent::Type eventType = QEvent::None; + switch (touchEvent->type()) { + case QEvent::TouchBegin: + eventType = QEvent::MouseButtonPress; + break; + case QEvent::TouchUpdate: + eventType = QEvent::MouseMove; + break; + case QEvent::TouchEnd: + eventType = QEvent::MouseButtonRelease; + break; + default: + Q_ASSERT(!true); + break; + } + if (eventType == QEvent::None) + break; + + QMouseEvent mouseEvent(eventType, + touchPoint.pos().toPoint(), + touchPoint.screenPos().toPoint(), + Qt::LeftButton, + Qt::LeftButton, + touchEvent->modifiers()); + (void) QApplication::sendEvent(this, &mouseEvent); + break; + } + case QEvent::SymbianDeferredFocusChanged: { +#ifdef Q_OS_SYMBIAN + d->handleSymbianDeferredFocusChanged(); +#endif + break; + } #ifndef QT_NO_PROPERTIES case QEvent::DynamicPropertyChange: { const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName(); @@ -7981,10 +8359,12 @@ void QWidget::changeEvent(QEvent * event) case QEvent::FontChange: case QEvent::StyleChange: { + Q_D(QWidget); update(); updateGeometry(); + if (d->layout) + d->layout->invalidate(); #ifdef Q_WS_QWS - Q_D(QWidget); if (isWindow()) d->data.fstrut_dirty = true; #endif @@ -8064,9 +8444,9 @@ void QWidget::mousePressEvent(QMouseEvent *event) if ((windowType() == Qt::Popup)) { event->accept(); QWidget* w; - while ((w = qApp->activePopupWidget()) && w != this){ + while ((w = QApplication::activePopupWidget()) && w != this){ w->close(); - if (qApp->activePopupWidget() == w) // widget does not want to dissappear + if (QApplication::activePopupWidget() == w) // widget does not want to dissappear w->hide(); // hide at least } if (!rect().contains(event->pos())){ @@ -8476,7 +8856,7 @@ void QWidget::inputMethodEvent(QInputMethodEvent *event) \a query specifies which property is queried. - \sa inputMethodEvent(), QInputMethodEvent, QInputContext + \sa inputMethodEvent(), QInputMethodEvent, QInputContext, inputMethodHints */ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const { @@ -8485,11 +8865,54 @@ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const return QRect(width()/2, 0, 1, height()); case Qt::ImFont: return font(); + case Qt::ImAnchorPosition: + // Fallback. + return inputMethodQuery(Qt::ImCursorPosition); default: return QVariant(); } } +/*! + \property QWidget::inputMethodHints + \brief What input method specific hints the widget has. + + This is only relevant for input widgets. It is used by + the input method to retrieve hints as to how the input method + should operate. For example, if the Qt::ImhFormattedNumbersOnly flag + is set, the input method may change its visual components to reflect + that only numbers can be entered. + + \note The flags are only hints, so the particular input method + implementation is free to ignore them. If you want to be + sure that a certain type of characters are entered, + you should also set a QValidator on the widget. + + The default value is Qt::ImhNone. + + \since 4.6 + + \sa inputMethodQuery(), QInputContext +*/ +Qt::InputMethodHints QWidget::inputMethodHints() const +{ + Q_D(const QWidget); + return d->imHints; +} + +void QWidget::setInputMethodHints(Qt::InputMethodHints hints) +{ + Q_D(QWidget); + d->imHints = hints; + // Optimisation to update input context only it has already been created. + if (d->ic || qApp->d_func()->inputContext) { + QInputContext *ic = inputContext(); + if (ic) + ic->update(); + } +} + + #ifndef QT_NO_DRAGANDDROP /*! @@ -8806,7 +9229,7 @@ QRegion QWidget::mask() const The layout manager sets the geometry of the widget's children that have been added to the layout. - \sa setLayout(), sizePolicy(), {Layout Classes} + \sa setLayout(), sizePolicy(), {Layout Management} */ QLayout *QWidget::layout() const { @@ -8836,7 +9259,7 @@ QLayout *QWidget::layout() const The QWidget will take ownership of \a layout. - \sa layout(), {Layout Classes} + \sa layout(), {Layout Management} */ void QWidget::setLayout(QLayout *l) @@ -9261,11 +9684,12 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) d->resolveLayoutDirection(); d->resolveLocale(); - // Note: GL widgets under Windows will always need a ParentChange - // event to handle recreation/rebinding of the GL context, hence - // the (f & Qt::MSWindowsOwnDC) clause + // Note: GL widgets under WGL or EGL will always need a ParentChange + // event to handle recreation/rebinding of the GL context, hence the + // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all + // platforms). if (newParent -#ifdef Q_WS_WIN +#if defined(Q_WS_WIN) || defined(QT_OPENGL_ES) || (f & Qt::MSWindowsOwnDC) #endif ) { @@ -9815,27 +10239,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) QEvent e(QEvent::MouseTrackingChange); QApplication::sendEvent(this, &e); break; } -#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN) - case Qt::WA_MSWindowsUseDirect3D: - if (!qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault)) { - if (on) { - if (!d->extra) - d->createExtra(); - d->extra->had_auto_fill_bg = d->extra->autoFillBackground; - d->extra->had_no_system_bg = testAttribute(Qt::WA_NoSystemBackground); - d->extra->had_paint_on_screen = testAttribute(Qt::WA_PaintOnScreen); - // enforce the opaque widget state D3D needs - d->extra->autoFillBackground = true; - setAttribute(Qt::WA_PaintOnScreen); - setAttribute(Qt::WA_NoSystemBackground); - } else if (d->extra) { - d->extra->autoFillBackground = d->extra->had_auto_fill_bg; - setAttribute(Qt::WA_PaintOnScreen, d->extra->had_paint_on_screen); - setAttribute(Qt::WA_NoSystemBackground, d->extra->had_no_system_bg); - } - } - break; -#endif case Qt::WA_NativeWindow: { QInputContext *ic = 0; if (on && !internalWinId() && testAttribute(Qt::WA_InputMethodEnabled) && hasFocus()) { @@ -9847,7 +10250,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) parentWidget()->d_func()->enforceNativeChildren(); if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created)) d->createWinId(); - if (ic) + if (ic && isEnabled()) ic->setFocusWidget(this); break; } @@ -9878,15 +10281,11 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) #endif break; case Qt::WA_InputMethodEnabled: { -#if defined(Q_WS_WIN) || (defined(Q_WS_QWS) && !defined(QT_NO_QWS_INPUTMETHODS)) - if (hasFocus()) - QInputContextPrivate::updateImeStatus(this, true); -#endif QInputContext *ic = d->ic; if (!ic && (!on || hasFocus())) ic = d->inputContext(); if (ic) { - if (on && hasFocus() && ic->focusWidget() != this) { + if (on && hasFocus() && ic->focusWidget() != this && isEnabled()) { ic->setFocusWidget(this); } else if (!on && ic->focusWidget() == this) { ic->reset(); @@ -9963,6 +10362,12 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) } break; + case Qt::WA_AcceptTouchEvents: +#if defined(Q_WS_WIN) || defined(Q_WS_MAC) + if (on) + d->registerTouchWindow(); +#endif + break; default: break; } @@ -9993,8 +10398,8 @@ bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const By default the value of this property is 1.0. - This feature is available on Embedded Linux, Mac OS X, X11 platforms that - support the Composite extension, and Windows 2000 and later. + This feature is available on Embedded Linux, Mac OS X, Windows, + and X11 platforms that support the Composite extension. This feature is not available on Windows CE. @@ -10318,7 +10723,7 @@ void QWidget::setShortcutAutoRepeat(int id, bool enable) */ void QWidget::updateMicroFocus() { -#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS)) +#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) Q_D(QWidget); // and optimisation to update input context only it has already been created. if (d->ic || qApp->d_func()->inputContext) { @@ -11123,8 +11528,6 @@ Q_GUI_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget) } - - #ifndef QT_NO_GRAPHICSVIEW /*! \since 4.5 @@ -11452,6 +11855,67 @@ void QWidget::clearMask() setMask(QRegion()); } +/*! + \preliminary + \since 4.6 + + Returns the (possibly empty) list of this widget's softkeys. + Returned list cannot be changed. Softkeys should be added + and removed via method called setSoftKeys + + \sa setSoftKey(), setSoftKeys() +*/ +const QList<QAction*>& QWidget::softKeys() const +{ + Q_D(const QWidget); + if( d->softKeys.count() > 0) + return d->softKeys; + if (isWindow() || !parentWidget()) + return d->softKeys; + + return parentWidget()->softKeys(); +} + +/*! + \preliminary + \since 4.6 + + Sets the softkey \a softKey to this widget's list of softkeys. + Setting 0 as softkey will clear all the existing softkeys set + to the widget. A QWidget can have 0 or more softkeys. + + \sa softKeys(), setSoftKeys() +*/ +void QWidget::setSoftKey(QAction *softKey) +{ + Q_D(QWidget); + qDeleteAll(d->softKeys); + d->softKeys.clear(); + if (softKey) + d->softKeys.append(softKey); + if ((!QApplication::focusWidget() && this == QApplication::activeWindow()) + || QApplication::focusWidget() == this) + d->setSoftKeys_sys(this->softKeys()); +} + +/*! + Sets the list of softkeys \a softKeys to this widget's list of softkeys. + A QWidget can have 0 or more softkeys. + + \sa softKeys(), setSoftKey() +*/ +void QWidget::setSoftKeys(const QList<QAction*> &softKeys) +{ + Q_D(QWidget); + qDeleteAll(d->softKeys); + d->softKeys.clear(); + d->softKeys = softKeys; + + if ((!QApplication::focusWidget() && this == QApplication::activeWindow()) + || QApplication::focusWidget() == this) + d->setSoftKeys_sys(this->softKeys()); +} + /*! \fn const QX11Info &QWidget::x11Info() const Returns information about the configuration of the X display used to display the widget. diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 0bb95a4..f398dbd 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -44,6 +44,7 @@ #include <QtGui/qwindowdefs.h> #include <QtCore/qobject.h> +#include <QtCore/qmargins.h> #include <QtGui/qpaintdevice.h> #include <QtGui/qpalette.h> #include <QtGui/qfont.h> @@ -95,6 +96,8 @@ class QIcon; class QWindowSurface; class QLocale; class QGraphicsProxyWidget; +class QGestureManager; +class QGraphicsEffect; #if defined(Q_WS_X11) class QX11Info; #endif @@ -130,7 +133,7 @@ public: int alloc_region_index; // int alloc_region_revision; #endif -#if defined(Q_OS_WINCE) +#if defined(Q_WS_WINCE) uint window_state_internal : 4; #endif QRect wrect; @@ -212,6 +215,7 @@ class Q_GUI_EXPORT QWidget : public QObject, public QPaintDevice #endif Q_PROPERTY(QLocale locale READ locale WRITE setLocale RESET unsetLocale) Q_PROPERTY(QString windowFilePath READ windowFilePath WRITE setWindowFilePath DESIGNABLE isWindow) + Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints) public: enum RenderFlag { @@ -351,6 +355,9 @@ public: const QRegion &sourceRegion = QRegion(), RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren)); + QGraphicsEffect *graphicsEffect() const; + void setGraphicsEffect(QGraphicsEffect *effect); + public Q_SLOTS: void setWindowTitle(const QString &); #ifndef QT_NO_STYLE_STYLESHEET @@ -469,7 +476,7 @@ public Q_SLOTS: virtual void setVisible(bool visible); inline void setHidden(bool hidden) { setVisible(!hidden); } -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE inline void show() { setVisible(true); } #else void show(); @@ -521,7 +528,10 @@ public: QRegion visibleRegion() const; void setContentsMargins(int left, int top, int right, int bottom); + void setContentsMargins(const QMargins &margins); void getContentsMargins(int *left, int *top, int *right, int *bottom) const; + QMargins contentsMargins() const; + QRect contentsRect() const; public: @@ -539,6 +549,7 @@ public: QWidget *focusWidget() const; QWidget *nextInFocusChain() const; + QWidget *previousInFocusChain() const; // drag and drop bool acceptDrops() const; @@ -553,6 +564,9 @@ public: void removeAction(QAction *action); QList<QAction*> actions() const; #endif + const QList<QAction*>& softKeys() const; + void setSoftKey(QAction *softKey); + void setSoftKeys(const QList<QAction*> &softKeys); QWidget *parentWidget() const; @@ -673,6 +687,10 @@ protected: virtual void inputMethodEvent(QInputMethodEvent *); public: virtual QVariant inputMethodQuery(Qt::InputMethodQuery) const; + + Qt::InputMethodHints inputMethodHints() const; + void setInputMethodHints(Qt::InputMethodHints hints); + protected: void resetInputContext(); protected Q_SLOTS: @@ -723,6 +741,7 @@ private: friend class QGraphicsProxyWidget; friend class QGraphicsProxyWidgetPrivate; friend class QStyleSheetStyle; + friend struct QWidgetExceptionCleaner; #ifdef Q_WS_MAC friend class QCoreGraphicsPaintEnginePrivate; @@ -744,6 +763,10 @@ private: friend bool isWidgetOpaque(const QWidget *); friend class QGLWidgetPrivate; #endif +#ifdef Q_OS_SYMBIAN + friend class QSymbianControl; + friend class QS60WindowSurface; +#endif #ifdef Q_WS_X11 friend void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp); friend void qt_net_remove_user_time(QWidget *tlw); diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 00f658e..6869887 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -72,7 +72,6 @@ ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** ****************************************************************************/ -//#define QT_RASTER_PAINTENGINE #include <private/qt_mac_p.h> #include <private/qeventdispatcher_mac_p.h> @@ -83,13 +82,11 @@ #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> -#ifdef QT_RASTER_PAINTENGINE -# include <private/qpaintengine_raster_p.h> -#endif #include <private/qwindowsurface_mac_p.h> #include <private/qpaintengine_mac_p.h> #include "qpainter.h" @@ -110,6 +107,7 @@ #include <private/qcocoapanel_mac_p.h> #include "qwidget_p.h" +#include "qevent_p.h" #include "qdnd_p.h" #include <QtGui/qgraphicsproxywidget.h> @@ -303,6 +301,14 @@ 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->winId()) window] isKeyWindow]; +#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)) @@ -390,21 +396,15 @@ QWidget *qt_mac_find_window(OSWindowRef window) inline static void qt_mac_set_fullscreen_mode(bool b) { - extern bool qt_mac_app_fullscreen; //qapplication_mac.cpp + extern bool qt_mac_app_fullscreen; //qapplication_mac.mm if(qt_mac_app_fullscreen == b) return; qt_mac_app_fullscreen = b; -#if QT_MAC_USE_COCOA - if(b) - SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar); - else + if (b) { + SetSystemUIMode(kUIModeAllSuppressed, 0); + } else { SetSystemUIMode(kUIModeNormal, 0); -#else - if(b) - HideMenuBar(); - else - ShowMenuBar(); -#endif + } } Q_GUI_EXPORT OSViewRef qt_mac_nativeview_for(const QWidget *w) @@ -511,16 +511,9 @@ static void qt_mac_release_window_group(WindowGroupRef group) SInt32 qt_mac_get_group_level(WindowClass wclass) { SInt32 group_level; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - CGWindowLevel tmpLevel; - GetWindowGroupLevelOfType(GetWindowGroupOfClass(wclass), kWindowGroupLevelActive, &tmpLevel); - group_level = tmpLevel; - } else -#endif - { - GetWindowGroupLevel(GetWindowGroupOfClass(wclass), &group_level); - } + CGWindowLevel tmpLevel; + GetWindowGroupLevelOfType(GetWindowGroupOfClass(wclass), kWindowGroupLevelActive, &tmpLevel); + group_level = tmpLevel; return group_level; } #endif @@ -734,6 +727,7 @@ static OSWindowRef qt_mac_create_window(QWidget *, WindowClass wclass, WindowAtt static EventTypeSpec window_events[] = { { kEventClassWindow, kEventWindowClose }, { kEventClassWindow, kEventWindowExpanded }, + { kEventClassWindow, kEventWindowHidden }, { kEventClassWindow, kEventWindowZoomed }, { kEventClassWindow, kEventWindowCollapsed }, { kEventClassWindow, kEventWindowToolbarSwitchMode }, @@ -741,12 +735,16 @@ static EventTypeSpec window_events[] = { { kEventClassWindow, kEventWindowProxyEndDrag }, { kEventClassWindow, kEventWindowResizeCompleted }, { kEventClassWindow, kEventWindowBoundsChanging }, - { kEventClassWindow, kEventWindowBoundsChanged }, { kEventClassWindow, kEventWindowGetRegion }, -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 { kEventClassWindow, kEventWindowGetClickModality }, -#endif { kEventClassWindow, kEventWindowTransitionCompleted }, +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + { kEventClassGesture, kEventGestureStarted }, + { kEventClassGesture, kEventGestureEnded }, + { kEventClassGesture, kEventGestureMagnify }, + { kEventClassGesture, kEventGestureSwipe }, + { kEventClassGesture, kEventGestureRotate }, +#endif { kEventClassMouse, kEventMouseDown } }; static EventHandlerUPP mac_win_eventUPP = 0; @@ -775,7 +773,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, QWidget *widget = qt_mac_find_window(wid); if(!widget) { handled_event = false; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 } else if(ekind == kEventWindowGetClickModality) { // Carbon will send us kEventWindowGetClickModality before every // mouse press / release event. By returning 'true', we tell Carbon @@ -786,7 +783,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, // 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; -#endif } else if(ekind == kEventWindowClose) { widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); QMenuBar::macUpdateMenuBar(); @@ -860,8 +856,7 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp qt_button_down = 0; } else if(ekind == kEventWindowToolbarSwitchMode) { - QToolBarChangeEvent ev(!(GetCurrentKeyModifiers() & cmdKey)); - QApplication::sendSpontaneousEvent(widget, &ev); + macSendToolbarChangeEvent(widget); HIToolbarRef toolbar; if (GetWindowToolbar(wid, &toolbar) == noErr) { if (toolbar) { @@ -909,90 +904,94 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, SetEventParameter(mouseUpEvent, kEventParamMouseLocation, typeQDPoint, sizeof(pos), &pos); SendEventToApplication(mouseUpEvent); ReleaseEvent(mouseUpEvent); - } else if(ekind == kEventWindowBoundsChanging || ekind == kEventWindowBoundsChanged) { - // Panther doesn't send Changing for sheets, only changed, so only - // bother handling Changed event if we are on 10.3 and we are a - // sheet. - if (ekind == kEventWindowBoundsChanged - && (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 - || !(widget->windowFlags() & Qt::Sheet))) { - handled_event = false; + } 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 { - 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); + //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); - } + 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((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); - } + 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; } @@ -1030,6 +1029,76 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, return SendEventToApplication(event); handled_event = false; break; } + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + 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, typeCGFloat, 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, typeCGFloat, 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 // gestures + default: handled_event = false; } @@ -1129,23 +1198,9 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, //update handles GrafPtr qd = 0; CGContextRef cg = 0; -#ifndef QT_MAC_NO_QUICKDRAW - { - if(GetEventParameter(event, kEventParamGrafPort, typeGrafPtr, 0, sizeof(qd), 0, &qd) != noErr) { - GDHandle dev = 0; - GetGWorld(&qd, &dev); //just use the global port.. - } - } - bool end_cg_context = false; - if(GetEventParameter(event, kEventParamCGContextRef, typeCGContextRef, 0, sizeof(cg), 0, &cg) != noErr && qd) { - end_cg_context = true; - QDBeginCGContext(qd, &cg); - } -#else if(GetEventParameter(event, kEventParamCGContextRef, typeCGContextRef, 0, sizeof(cg), 0, &cg) != noErr) { Q_ASSERT(false); } -#endif widget->d_func()->hd = cg; widget->d_func()->qd_hd = qd; CGContextSaveGState(cg); @@ -1211,22 +1266,13 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, p.setClipping(false); if(was_unclipped) widget->setAttribute(Qt::WA_PaintUnclipped); - - QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(widget->parent()); - QPoint scrollAreaOffset; - if (scrollArea && scrollArea->viewport() == widget) { - QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(static_cast<QWidget *>(scrollArea)->d_ptr); - scrollAreaOffset = priv->contentsOffset(); - p.translate(-scrollAreaOffset); - } - - widget->d_func()->paintBackground(&p, qrgn, scrollAreaOffset, widget->isWindow() ? DrawAsRoot : 0); + 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).translated(scrollAreaOffset), tint); + p.fillRect(rects.at(i), tint); } p.end(); if (!redirectionOffset.isNull()) @@ -1256,11 +1302,6 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, QApplication::sendSpontaneousEvent(widget, &e); if (!redirectionOffset.isNull()) widget->d_func()->restoreRedirected(); -#ifdef QT_RASTER_PAINTENGINE - if(engine && engine->type() == QPaintEngine::Raster) - static_cast<QRasterPaintEngine*>(engine)->flush(widget, - qrgn.boundingRect().topLeft()); -#endif //cleanup if (engine) @@ -1274,10 +1315,6 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, widget->d_func()->hd = 0; widget->d_func()->qd_hd = 0; CGContextRestoreGState(cg); -#ifndef QT_MAC_NO_QUICKDRAW - if(end_cg_context) - QDEndCGContext(qd, &cg); -#endif } else if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) { CallNextEventHandler(er, event); } @@ -1382,6 +1419,14 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, // 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; } } } @@ -1598,24 +1643,6 @@ bool QWidgetPrivate::qt_create_root_win() return true; } -bool QWidgetPrivate::qt_recreate_root_win() -{ - if(!qt_root_win) //sanity check - return false; - //store old - OSWindowRef old_root_win = qt_root_win; - //recreate - qt_root_win = 0; - qt_create_root_win(); - //cleanup old window -#ifdef QT_MAC_USE_COCOA - [old_root_win release]; -#else - CFRelease(old_root_win); -#endif - return true; -} - bool QWidgetPrivate::qt_widget_rgn(QWidget *widget, short wcode, RgnHandle rgn, bool force = false) { bool ret = false; @@ -1716,17 +1743,11 @@ void QWidgetPrivate::determineWindowClass() bool framelessWindow = (flags & Qt::FramelessWindowHint || (customize && !(flags & Qt::WindowTitleHint))); if (framelessWindow) { if(wclass == kDocumentWindowClass) { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - wattr |= kWindowNoTitleBarAttribute; - else - wclass = kPlainWindowClass; + wattr |= kWindowNoTitleBarAttribute; } else if(wclass == kFloatingWindowClass) { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - wattr |= kWindowNoTitleBarAttribute; - else - wclass = kToolbarWindowClass; + wattr |= kWindowNoTitleBarAttribute; } else if (wclass == kMovableModalWindowClass) { - wclass = kModalWindowClass; + wclass = kModalWindowClass; } } else { if(wclass != kModalWindowClass) @@ -2024,14 +2045,10 @@ void QWidgetPrivate::finishCreateWindow_sys_Carbon(OSWindowRef windowRef) if (!desktop) SetAutomaticControlDragTrackingEnabledForWindow(windowRef, true); HIWindowChangeFeatures(windowRef, kWindowCanCollapse, 0); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - if (wattr & kWindowHideOnSuspendAttribute) - HIWindowChangeAvailability(windowRef, kHIWindowExposeHidden, 0); - else - HIWindowChangeAvailability(windowRef, 0, kHIWindowExposeHidden); - } -#endif + 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) @@ -2305,7 +2322,7 @@ void QWidgetPrivate::createWindow_sys() 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 Trolltech and include the\n" + 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); @@ -2524,9 +2541,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO setFocus_sys(); if (!topLevel && initializeWindow) setWSGeometry(); - if (destroyid) qt_mac_destructView(destroyid); + if (q->testAttribute(Qt::WA_AcceptTouchEvents)) + registerTouchWindow(); } /*! @@ -2564,7 +2582,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); if (!isWindow() && parentWidget()) - parentWidget()->d_func()->invalidateBuffer(geometry()); + parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); qt_mac_event_release(this); if(testAttribute(Qt::WA_WState_Created)) { @@ -2615,7 +2633,11 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) qt_mac_destructWindow(window); } } - d->setWinId(0); + QT_TRY { + d->setWinId(0); + } QT_CATCH (const std::bad_alloc &) { + // swallow - destructors must not throw + } } } @@ -2666,7 +2688,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) OSViewRef old_id = 0; if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) - q->parentWidget()->d_func()->invalidateBuffer(q->geometry()); + 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. @@ -2897,8 +2919,7 @@ void QWidgetPrivate::setWindowTitle_sys(const QString &caption) SetWindowTitleWithCFString(qt_mac_window_for(q), QCFString(caption)); #else QMacCocoaAutoReleasePool pool; - [qt_mac_window_for(q) - setTitle:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(caption)))]; + [qt_mac_window_for(q) setTitle:qt_mac_QStringToNSString(caption)]; #endif } } @@ -2920,7 +2941,8 @@ void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath) Q_Q(QWidget); #ifdef QT_MAC_USE_COCOA QMacCocoaAutoReleasePool pool; - [qt_mac_window_for(q) setRepresentedFilename:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(filePath)))]; + QFileInfo fi(filePath); + [qt_mac_window_for(q) setRepresentedFilename:fi.exists() ? qt_mac_QStringToNSString(filePath) : @""]; #else bool validRef = false; FSRef ref; @@ -2933,21 +2955,10 @@ void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath) } // Set the proxy regardless, since this is our way of clearing it as well, but ignore the // return value as well. - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - if (validRef) { - status = HIWindowSetProxyFSRef(qt_mac_window_for(q), &ref); - } else { - status = RemoveWindowProxy(qt_mac_window_for(q)); - } + if (validRef) { + status = HIWindowSetProxyFSRef(qt_mac_window_for(q), &ref); } else { - // Convert to an FSSpec and set it. It's deprecated but it works for where we don't have the other call. - if (validRef) { - FSSpec fsspec; - FSGetCatalogInfo(&ref, kFSCatInfoNone, 0, 0, &fsspec, 0); - status = SetWindowProxyFSSpec(qt_mac_window_for(q), &fsspec); - } else { - status = RemoveWindowProxy(qt_mac_window_for(q)); - } + status = RemoveWindowProxy(qt_mac_window_for(q)); } if (status != noErr) qWarning("QWidget::setWindowFilePath: Error setting proxyicon for path (%s):%ld", @@ -3021,8 +3032,7 @@ void QWidgetPrivate::setWindowIconText_sys(const QString &iconText) SetWindowAlternateTitle(qt_mac_window_for(q), QCFString(iconText)); #else QMacCocoaAutoReleasePool pool; - [qt_mac_window_for(q) - setMiniwindowTitle:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(iconText)))]; + [qt_mac_window_for(q) setMiniwindowTitle:qt_mac_QStringToNSString(iconText)]; #endif } } @@ -3155,16 +3165,9 @@ void QWidgetPrivate::update_sys(const QRect &r) if (updateRedirectedToGraphicsProxyWidget(q, updateRect)) return; #ifndef QT_MAC_USE_COCOA -# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - dirtyOnWidget += updateRect; - HIRect r = CGRectMake(x, y, w, h); - HIViewSetNeedsDisplayInRect(qt_mac_nativeview_for(q), &r, true); - } else - #endif - { - q->update(QRegion(updateRect)); - } + dirtyOnWidget += updateRect; + HIRect r = CGRectMake(x, y, w, h); + HIViewSetNeedsDisplayInRect(qt_mac_nativeview_for(q), &r, true); #else [qt_mac_nativeview_for(q) setNeedsDisplayInRect:NSMakeRect(x, y, w, h)]; #endif @@ -3178,7 +3181,12 @@ void QWidgetPrivate::update_sys(const QRegion &rgn) return; dirtyOnWidget += rgn; #ifndef QT_MAC_USE_COCOA - HIViewSetNeedsDisplayInRegion(qt_mac_nativeview_for(q), QMacSmartQuickDrawRegion(rgn.toQDRgn()), true); + RgnHandle rgnHandle = rgn.toQDRgnForUpdate_sys(); + if (rgnHandle) + HIViewSetNeedsDisplayInRegion(qt_mac_nativeview_for(q), QMacSmartQuickDrawRegion(rgnHandle), true); + else { + HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true); // do a complete repaint on overflow. + } #else // Cocoa doesn't do regions, it seems more efficient to just update the bounding rect instead of a potential number of message passes for each rect. const QRect &boundingRect = rgn.boundingRect(); @@ -3270,10 +3278,13 @@ void QWidgetPrivate::show_sys() #else // sync the opacity value back (in case of a fade). [window setAlphaValue:q->windowOpacity()]; - [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) - QCoreApplication::postEvent(qApp, new QEvent(QEvent::CocoaRequestModal)); + QEventDispatcherMac::instance()->interrupt(); #endif if (q->windowType() == Qt::Popup) { if (q->focusWidget()) @@ -3291,13 +3302,6 @@ void QWidgetPrivate::show_sys() #endif } else if (!q->testAttribute(Qt::WA_ShowWithoutActivating)) { qt_event_request_activate(q); -#ifdef QT_MAC_USE_COCOA - if (q->windowModality() == Qt::ApplicationModal) { - // We call 'activeModalSession' early to force creation of q's modal - // session. This seems neccessary for child dialogs to pop to front: - QEventDispatcherMacPrivate::activeModalSession(); - } -#endif } } else if(topData()->embedded || !q->parentWidget() || q->parentWidget()->isVisible()) { #ifndef QT_MAC_USE_COCOA @@ -3882,8 +3886,6 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect) Qt coordinate system for parent X coordinate system for parent (relative to parent's wrect). */ - QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX); - QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX); QRect wrect; //xrect is the X geometry of my X widget. (starts out in parent's Qt coord sys, and ends up in parent's X coord sys) QRect xrect = data.crect; @@ -3905,6 +3907,7 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect) 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; } } else { @@ -3960,15 +3963,24 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect) } } + const QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX); if (!validRange.contains(xrect)) { // we are too big, and must clip - xrect &=wrectRange; + 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); + + xrect &=cropRect; wrect = xrect; - wrect.translate(-data.crect.topLeft()); - //parent's X coord system is equal to parent's Qt coord - //sys, so we don't need to map xrect. + wrect.translate(-data.crect.topLeft()); // translate wrect in my Qt coordinates } - } // unmap if we are outside the valid window system coord system @@ -4008,10 +4020,9 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect) qt_mac_update_widget_posisiton(q, oldRect, xrect); - if (jump) { - updateSystemBackground(); + if (jump) q->update(); - } + if (mapWindow && !dontShow) { q->setAttribute(Qt::WA_Mapped); #ifndef QT_MAC_USE_COCOA @@ -4173,12 +4184,12 @@ void QWidgetPrivate::setGeometry_sys_helper(int x, int y, int w, int h, bool isM setWSGeometry(false, oldRect); if (isResize && QApplicationPrivate::graphicsSystem()) { invalidateBuffer(q->rect()); - if (extra && !extra->mask.isEmpty()) { + if (extra && !graphicsEffect && !extra->mask.isEmpty()) { QRegion oldRegion(extra->mask.translated(oldp)); oldRegion &= oldRect; q->parentWidget()->d_func()->invalidateBuffer(oldRegion); } else { - q->parentWidget()->d_func()->invalidateBuffer(oldRect); + q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(oldRect)); } } } @@ -4332,32 +4343,14 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) OSViewRef view = qt_mac_nativeview_for(q); #ifndef QT_MAC_USE_COCOA HIRect scrollrect = CGRectMake(r.x(), r.y(), r.width(), r.height()); -# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - OSStatus err = _HIViewScrollRectWithOptions(view, valid_rect ? &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(r.x(), 0), qMax(r.y(), 0), - qMin(r.width(), q->width()), qMin(r.height(), q->height())); - _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid); - } - } else { - if (HIViewGetNeedsDisplay(view)) { - q->update(valid_rect ? r : q->rect()); - return; - } - HIRect scrollrect = CGRectMake(r.x(), r.y(), r.width(), r.height()); - OSStatus err = HIViewScrollRect(view, valid_rect ? &scrollrect : 0, dx, dy); - 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(r.x(), 0), qMax(r.y(), 0), - qMin(r.width(), q->width()), qMin(r.height(), q->height())); - HIViewScrollRect(view, valid_rect ? &scrollrect : 0, dx, dy); - } + OSStatus err = _HIViewScrollRectWithOptions(view, valid_rect ? &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(r.x(), 0), qMax(r.y(), 0), + qMin(r.width(), q->width()), qMin(r.height(), q->height())); + _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid); } -# endif #else NSRect scrollRect = valid_rect ? NSMakeRect(r.x(), r.y(), r.width(), r.height()) : NSMakeRect(0, 0, q->width(), q->height()); @@ -4385,20 +4378,9 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) } } - // ### Scroll the dirty regions as well, the following is not correct. - QRegion displayRegion = r.isNull() ? dirtyOnWidget : (dirtyOnWidget & r); - const QVector<QRect> &rects = dirtyOnWidget.rects(); - const QVector<QRect>::const_iterator end = rects.end(); - QVector<QRect>::const_iterator it = rects.begin(); - while (it != end) { - const QRect rect = *it; - const NSRect dirtyRect = NSMakeRect(rect.x() + dx, rect.y() + dy, - rect.width(), rect.height()); - [view setNeedsDisplayInRect:dirtyRect]; - ++it; - } - [view scrollRect:scrollRect by:NSMakeSize(dx, dy)]; - // Yes, we potentially send a duplicate area, but I think Cocoa can handle it. + NSSize deltaSize = NSMakeSize(dx, dy); + [view translateRectsNeedingDisplayInRect:scrollRect by:deltaSize]; + [view scrollRect:scrollRect by:deltaSize]; [view setNeedsDisplayInRect:deltaXRect]; [view setNeedsDisplayInRect:deltaYRect]; #endif // QT_MAC_USE_COCOA @@ -4468,11 +4450,13 @@ void QWidgetPrivate::deleteSysExtra() 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->resizer = 0; - extra->topextra->isSetGeometry = 0; extra->topextra->savedWindowAttributesFromMaximized = 0; } @@ -4527,6 +4511,23 @@ void QWidgetPrivate::registerDropSite(bool on) #endif } +void QWidgetPrivate::registerTouchWindow() +{ +#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 (!q->testAttribute(Qt::WA_WState_Created)) + return; +#ifndef QT_MAC_USE_COCOA + // Needs implementation! +#else + NSView *view = qt_mac_nativeview_for(q); + [view setAcceptsTouchEvents:YES]; +#endif +#endif +} + void QWidgetPrivate::setMask_sys(const QRegion ®ion) { Q_UNUSED(region); @@ -4547,14 +4548,6 @@ void QWidgetPrivate::setMask_sys(const QRegion ®ion) #endif } -extern "C" { - typedef struct CGSConnection *CGSConnectionRef; - typedef struct CGSWindow *CGSWindowRef; - extern OSStatus CGSSetWindowAlpha(CGSConnectionRef, CGSWindowRef, float); - extern CGSWindowRef GetNativeWindowFromWindowRef(WindowRef); - extern CGSConnectionRef _CGSDefaultConnection(); -} - void QWidgetPrivate::setWindowOpacity_sys(qreal level) { Q_Q(QWidget); @@ -4567,12 +4560,11 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level) if (!q->testAttribute(Qt::WA_WState_Created)) return; -#if QT_MAC_USE_COCOA OSWindowRef oswindow = qt_mac_window_for(q); +#if QT_MAC_USE_COCOA [oswindow setAlphaValue:level]; #else - CGSSetWindowAlpha(_CGSDefaultConnection(), - GetNativeWindowFromWindowRef(qt_mac_window_for(q)), level); + SetWindowAlpha(oswindow, level); #endif } @@ -4644,21 +4636,6 @@ Q_GLOBAL_STATIC(QPaintEngineCleanupHandler, engineHandler) QPaintEngine *QWidget::paintEngine() const { QPaintEngine *&pe = engineHandler()->engine; -#ifdef QT_RASTER_PAINTENGINE - if (!pe) { - if(qgetenv("QT_MAC_USE_COREGRAPHICS").isNull()) - pe = new QRasterPaintEngine(); - else - pe = new QCoreGraphicsPaintEngine(); - } - if (pe->isActive()) { - QPaintEngine *engine = - qgetenv("QT_MAC_USE_COREGRAPHICS").isNull() - ? (QPaintEngine*)new QRasterPaintEngine() : (QPaintEngine*)new QCoreGraphicsPaintEngine(); - engine->setAutoDestruct(true); - return engine; - } -#else if (!pe) pe = new QCoreGraphicsPaintEngine(); if (pe->isActive()) { @@ -4666,7 +4643,6 @@ QPaintEngine *QWidget::paintEngine() const engine->setAutoDestruct(true); return engine; } -#endif return pe; } @@ -4926,11 +4902,9 @@ void QWidgetPrivate::macUpdateMetalAttribute() if (layout) layout->updateHIToolBarStatus(); ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalAttribute, 0); - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalNoContentSeparatorAttribute, 0); + ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalNoContentSeparatorAttribute, 0); } else { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalNoContentSeparatorAttribute); + ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalNoContentSeparatorAttribute); ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalAttribute); if (layout) layout->updateHIToolBarStatus(); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 4bbedfc..f69c3a7 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -57,9 +57,12 @@ #include "private/qobject_p.h" #include "QtCore/qrect.h" #include "QtCore/qlocale.h" +#include "QtCore/qset.h" #include "QtGui/qregion.h" #include "QtGui/qsizepolicy.h" #include "QtGui/qstyle.h" +#include "QtGui/qapplication.h" +#include <private/qgraphicseffect_p.h> #ifdef Q_WS_WIN #include "QtCore/qt_windows.h" @@ -79,6 +82,14 @@ #include "QtGui/qscreen_qws.h" #endif +#if defined(Q_OS_SYMBIAN) +class RDrawableWindow; +class CCoeControl; +// The following 2 defines may only be needed for s60. To be seen. +const int SOFTKEYSTART=5000; +const int SOFTKEYEND=5004; +#endif + QT_BEGIN_NAMESPACE // Extra QWidget data @@ -99,93 +110,101 @@ class QWidgetItemV2; class QStyle; struct QTLWExtra { + // *************************** Cross-platform variables ***************************** + + // Regular pointers (keep them together to avoid gaps on 64 bits architectures). + QIcon *icon; // widget icon + QPixmap *iconPixmap; + QWidgetBackingStore *backingStore; + QWindowSurface *windowSurface; + QPainter *sharedPainter; + + // Implicit pointers (shared_null). QString caption; // widget caption QString iconText; // widget icon text QString role; // widget role QString filePath; // widget file path - QIcon *icon; // widget icon - QPixmap *iconPixmap; + + // Other variables. short incw, inch; // size increments + short basew, baseh; // base sizes // frame strut, don't use these directly, use QWidgetPrivate::frameStrut() instead. QRect frameStrut; + QRect normalGeometry; // used by showMin/maximized/FullScreen + Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen + + // *************************** Cross-platform bit fields **************************** uint opacity : 8; uint posFromMove : 1; uint sizeAdjusted : 1; uint inTopLevelResize : 1; uint inRepaint : 1; - QWidgetBackingStore *backingStore; -#if defined(Q_WS_WIN) - ulong savedFlags; // Save window flags while showing fullscreen - uint embedded : 1; // window is embedded in another application -#else - Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen -#endif - short basew, baseh; // base sizes -#if defined(Q_WS_X11) - WId parentWinId; // parent window Id (valid after reparenting) - uint embedded : 1; // window is embedded in another Qt application + uint embedded : 1; + + // *************************** Platform specific values (bit fields first) ********** +#if defined(Q_WS_X11) // <----------------------------------------------------------- X11 uint spont_unmapped: 1; // window was spontaneously unmapped uint dnd : 1; // DND properties installed uint validWMState : 1; // is WM_STATE valid? uint waitingForMapNotify : 1; // show() has been called, haven't got the MapNotify yet + WId parentWinId; // parent window Id (valid after reparenting) WId userTimeWindow; // window id that contains user-time timestamp when WM supports a _NET_WM_USER_TIME_WINDOW atom QPoint fullScreenOffset; +#ifndef QT_NO_XSYNC + WId syncUpdateCounter; + ulong syncRequestTimestamp; + qint32 newCounterValueHi; + quint32 newCounterValueLo; #endif -#if defined(Q_WS_MAC) +#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN + HICON winIconBig; // internal big Windows icon + HICON winIconSmall; // internal small Windows icon +#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC + uint resizer : 4; + uint isSetGeometry : 1; + uint isMove : 1; quint32 wattr; quint32 wclass; WindowGroupRef group; IconRef windowIcon; // the current window icon, if set with setWindowIcon_sys. quint32 savedWindowAttributesFromMaximized; // Saved attributes from when the calling updateMaximizeButton_sys() - uint resizer : 4; - uint isSetGeometry : 1; - uint isMove : 1; - uint embedded : 1; -#endif -#if defined(Q_WS_QWS) && !defined (QT_NO_QWS_MANAGER) +#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS +#ifndef QT_NO_QWS_MANAGER QWSManager *qwsManager; #endif -#if defined(Q_WS_WIN) - HICON winIconBig; // internal big Windows icon - HICON winIconSmall; // internal small Windows icon +#elif defined(Q_OS_SYMBIAN) // <--------------------------------------------------------- SYMBIAN + uint activated : 1; // RWindowBase::Activated has been called + RDrawableWindow *rwindow; #endif - QRect normalGeometry; // used by showMin/maximized/FullScreen - QWindowSurface *windowSurface; - QPainter *sharedPainter; }; struct QWExtra { - qint32 minw, minh; // minimum size - qint32 maxw, maxh; // maximum size - QPointer<QWidget> focus_proxy; -#ifndef QT_NO_CURSOR - QCursor *curs; -#endif + // *************************** Cross-platform variables ***************************** + + // Regular pointers (keep them together to avoid gaps on 64 bits architectures). + void *glContext; // if the widget is hijacked by QGLWindowSurface QTLWExtra *topextra; // only useful for TLWs QGraphicsProxyWidget *proxyWidget; // if the widget is embedded - void *glContext; // if the widget is hijacked by QGLWindowSurface -#if defined(Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP) - QOleDropTarget *dropTarget; // drop target - QList<QPointer<QWidget> > oleDropWidgets; -#endif -#if defined(Q_WS_X11) - WId xDndProxy; // XDND forwarding to embedded windows +#ifndef QT_NO_CURSOR + QCursor *curs; #endif + QPointer<QStyle> style; + QPointer<QWidget> focus_proxy; + + // Implicit pointers (shared_empty/shared_null). QRegion mask; // widget mask + QString styleSheet; + + // Other variables. + qint32 minw; + qint32 minh; // minimum size + qint32 maxw; + qint32 maxh; // maximum size + quint16 customDpiX; + quint16 customDpiY; QSize staticContentsSize; -//bit flags at the end to improve packing -#if defined(Q_WS_WIN) - uint shown_mode : 8; // widget show mode -#ifndef QT_NO_DIRECT3D - uint had_paint_on_screen : 1; - uint had_no_system_bg : 1; - uint had_auto_fill_bg : 1; -#endif -#endif -#if defined(Q_WS_X11) - uint compress_events : 1; -#endif + // *************************** Cross-platform bit fields **************************** uint explicitMinSize : 2; uint explicitMaxSize : 2; uint autoFillBackground : 1; @@ -193,16 +212,22 @@ struct QWExtra { uint inRenderWithPainter : 1; uint hasMask : 1; - QPointer<QStyle> style; - QString styleSheet; - - quint16 customDpiX; - quint16 customDpiY; -#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA) + // *************************** Platform specific values (bit fields first) ********** +#if defined(Q_WS_WIN) // <----------------------------------------------------------- WIN +#ifndef QT_NO_DRAGANDDROP + QOleDropTarget *dropTarget; // drop target + QList<QPointer<QWidget> > oleDropWidgets; +#endif +#elif defined(Q_WS_X11) // <--------------------------------------------------------- X11 + uint compress_events : 1; + WId xDndProxy; // XDND forwarding to embedded windows +#elif defined(Q_WS_MAC) // <------------------------------------------------------ MAC +#ifdef QT_MAC_USE_COCOA // Cocoa Mask stuff QImage maskBits; CGImageRef imageMask; #endif +#endif }; class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate @@ -210,19 +235,34 @@ class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QWidget) public: + // *************************** Cross-platform *************************************** + enum DrawWidgetFlags { + DrawAsRoot = 0x01, + DrawPaintOnScreen = 0x02, + DrawRecursive = 0x04, + DrawInvisible = 0x08, + DontSubtractOpaqueChildren = 0x10, + DontSetCompositionMode = 0x20, + DontDrawOpaqueChildren = 0x40 + }; + + enum CloseMode { + CloseNoEvent, + CloseWithEvent, + CloseWithSpontaneousEvent + }; + + // Functions. explicit QWidgetPrivate(int version = QObjectPrivateVersion); ~QWidgetPrivate(); + void setSoftKeys_sys(const QList<QAction*> &softkeys); QWExtra *extraData() const; QTLWExtra *topData() const; QTLWExtra *maybeTopData() const; QPainter *sharedPainter() const; void setSharedPainter(QPainter *painter); QWidgetBackingStore *maybeBackingStore() const; -#ifdef Q_WS_QWS - void setMaxWindowState_helper(); - void setFullScreenSize_helper(); -#endif void init(QWidget *desktopWidget, Qt::WindowFlags f); void create_sys(WId window, bool initializeWindow, bool destroyOldWindow); void createRecursively(); @@ -243,22 +283,8 @@ public: QPalette naturalWidgetPalette(uint inheritedMask) const; void setMask_sys(const QRegion &); -#ifdef Q_WS_WIN - bool shouldShowMaximizeButton(); - void winUpdateIsOpaque(); -#endif - -#ifdef Q_WS_MAC - void macUpdateSizeAttribute(); - void macUpdateHideOnSuspend(); - void macUpdateOpaqueSizeGrip(); - void macUpdateIgnoreMouseEvents(); - void macUpdateMetalAttribute(); - void macUpdateIsOpaque(); - void setEnabled_helper_sys(bool enable); - bool isRealWindow() const; - void adjustWithinMaxAndMinSize(int &w, int &h); - void applyMaxAndMinSizeOnWindow(); +#ifdef Q_OS_SYMBIAN + void handleSymbianDeferredFocusChanged(); #endif void raise_sys(); @@ -285,20 +311,9 @@ public: void setStyle_helper(QStyle *newStyle, bool propagate, bool metalHack = false); void inheritStyle(); - bool isBackgroundInherited() const; - void setUpdatesEnabled_helper(bool ); - void paintBackground(QPainter *, const QRegion &, const QPoint & = QPoint(), int flags = DrawAsRoot) const; - enum DrawWidgetFlags { - DrawAsRoot = 0x01, - DrawPaintOnScreen = 0x02, - DrawRecursive = 0x04, - DrawInvisible = 0x08, - DontSubtractOpaqueChildren = 0x10, - DontSetCompositionMode = 0x20, - DontDrawOpaqueChildren = 0x40 - }; + void paintBackground(QPainter *, const QRegion &, int flags = DrawAsRoot) const; bool isAboutToShow() const; QRegion prepareToRender(const QRegion ®ion, QWidget::RenderFlags renderFlags); void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion, @@ -321,10 +336,6 @@ public: QWindowSurface *createDefaultWindowSurface(); QWindowSurface *createDefaultWindowSurface_sys(); void repaint_sys(const QRegion &rgn); -#ifdef Q_WS_MAC - void update_sys(const QRect &rect); - void update_sys(const QRegion &rgn); -#endif QRect clipRect() const; QRegion clipRegion() const; @@ -335,42 +346,20 @@ public: void updateIsOpaque(); void setOpaque(bool opaque); void updateIsTranslucent(); - bool hasBackground() const; bool paintOnScreen() const; QRegion getOpaqueRegion() const; const QRegion &getOpaqueChildren() const; void setDirtyOpaqueRegion(); - QRegion opaqueChildren; - - enum CloseMode { - CloseNoEvent, - CloseWithEvent, - CloseWithSpontaneousEvent - }; bool close_helper(CloseMode mode); - bool compositeEvent(QEvent *e); void setWindowIcon_helper(); void setWindowIcon_sys(bool forceReset = false); void setWindowOpacity_sys(qreal opacity); - void adjustQuitOnCloseAttribute(); -#if defined(Q_WS_X11) - void setWindowRole(); - void sendStartupMessage(const char *message) const; - void setNetWmWindowTypes(); - void x11UpdateIsOpaque(); -#endif - -#if defined (Q_WS_WIN) - void reparentChildren(); -#endif - void scrollChildren(int dx, int dy); - void moveRect(const QRect &, int dx, int dy); void scrollRect(const QRect &, int dx, int dy); void invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize); @@ -384,7 +373,6 @@ public: void reparentFocusWidgets(QWidget *oldtlw); static int pointToRect(const QPoint &p, const QRect &r); - QRect fromOrToLayoutItemRect(const QRect &rect, int sign) const; void setWinId(WId); void showChildren(bool spontaneous); @@ -394,9 +382,6 @@ public: void scroll_sys(int dx, int dy, const QRect &r); void deactivateWidgetCleanup(); void setGeometry_sys(int, int, int, int, bool); -#ifdef Q_WS_MAC - void setGeometry_sys_helper(int, int, int, int, bool); -#endif void sendPendingMoveAndResizeEvents(bool recursive = false, bool disableUpdates = false); void activateChildLayoutsRecursively(); void show_recursive(); @@ -408,10 +393,6 @@ public: void setEnabled_helper(bool); void registerDropSite(bool); -#if defined(Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP) - QOleDropTarget *registerOleDnd(QWidget *widget); - void unregisterOleDnd(QWidget *widget, QOleDropTarget *target); -#endif static void adjustFlags(Qt::WindowFlags &flags, QWidget *w = 0); void updateFrameStrut(); @@ -421,32 +402,11 @@ public: void setWindowIconText_helper(const QString &cap); void setWindowTitle_sys(const QString &cap); -#ifdef Q_OS_WIN - void grabMouseWhileInWindow(); -#endif - #ifndef QT_NO_CURSOR void setCursor_sys(const QCursor &cursor); void unsetCursor_sys(); #endif -#ifdef Q_WS_MAC - void setWindowModified_sys(bool b); - void updateMaximizeButton_sys(); - void setWindowFilePath_sys(const QString &filePath); - void createWindow_sys(); - void recreateMacWindow(); -#ifndef QT_MAC_USE_COCOA - void initWindowPtr(); - void finishCreateWindow_sys_Carbon(OSWindowRef windowRef); -#else - void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef); - void syncCocoaMask(); - void finishCocoaMaskSetup(); -#endif - void determineWindowClass(); - void transferChildren(); -#endif void setWindowTitle_helper(const QString &cap); void setWindowFilePath_helper(const QString &filePath); @@ -462,59 +422,113 @@ public: QInputContext *inputContext() const; -#if defined(Q_WS_QWS) - void moveSurface(QWindowSurface *surface, const QPoint &offset); + void setModal_sys(); - QRegion localRequestedRegion() const; - QRegion localAllocatedRegion() const; + inline void setRedirected(QPaintDevice *replacement, const QPoint &offset) + { + Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent)); + redirectDev = replacement; + redirectOffset = offset; + } - void blitToScreen(const QRegion &globalrgn); -#ifndef QT_NO_CURSOR - void updateCursor() const; -#endif + inline QPaintDevice *redirected(QPoint *offset) const + { + if (offset) + *offset = redirectDev ? redirectOffset : QPoint(); + return redirectDev; + } - QScreen* getScreen() const; + inline void restoreRedirected() + { redirectDev = 0; } - friend class QWSManager; - friend class QWSManagerPrivate; - friend class QDecoration; -#endif + inline void enforceNativeChildren() + { + if (!extra) + createExtra(); - static int instanceCounter; // Current number of widget instances - static int maxInstances; // Maximum number of widget instances + if (extra->nativeChildrenForced) + return; + extra->nativeChildrenForced = 1; -#ifdef QT_KEYPAD_NAVIGATION - static QPointer<QWidget> editingWidget; -#endif + for (int i = 0; i < children.size(); ++i) { + if (QWidget *child = qobject_cast<QWidget *>(children.at(i))) + child->setAttribute(Qt::WA_NativeWindow); + } + } - QWidgetData data; + inline bool nativeChildrenForced() const + { + return extra ? extra->nativeChildrenForced : false; + } + + inline QRect effectiveRectFor(const QRect &rect) const + { + if (graphicsEffect && graphicsEffect->isEnabled()) + return graphicsEffect->boundingRectFor(rect).toAlignedRect(); + return rect; + } + + QSize adjustedSize() const; + + inline void handleSoftwareInputPanel(Qt::MouseButton button, bool clickCausedFocus) + { + Q_Q(QWidget); + if (button == Qt::LeftButton && qApp->autoSipEnabled()) { + QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel( + q->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel)); + if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) { + QEvent event(QEvent::RequestSoftwareInputPanel); + QApplication::sendEvent(q, &event); + } + } + } + +#ifndef Q_WS_QWS // Almost cross-platform :-) + void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect()); + + inline QPoint mapToWS(const QPoint &p) const + { return p - data.wrect.topLeft(); } + + inline QPoint mapFromWS(const QPoint &p) const + { return p + data.wrect.topLeft(); } + + inline QRect mapToWS(const QRect &r) const + { QRect rr(r); rr.translate(-data.wrect.topLeft()); return rr; } + + inline QRect mapFromWS(const QRect &r) const + { QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; } +#endif + // Variables. + // Regular pointers (keep them together to avoid gaps on 64 bit architectures). QWExtra *extra; QWidget *focus_next; QWidget *focus_prev; QWidget *focus_child; -#ifndef QT_NO_ACTION - QList<QAction*> actions; -#endif + QList<QAction*> softKeys; QLayout *layout; + QRegion *needsFlush; + QPaintDevice *redirectDev; QWidgetItemV2 *widgetItem; + QPaintEngine *extraPaintEngine; + mutable const QMetaObject *polished; + QGraphicsEffect *graphicsEffect; + // All widgets are added into the allWidgets set. Once + // they receive a window id they are also added to the mapper. + // This should just ensure that all widgets are deleted by QApplication + static QWidgetMapper *mapper; + static QWidgetSet *allWidgets; #if !defined(QT_NO_IM) QPointer<QInputContext> ic; + Qt::InputMethodHints imHints; +#endif +#ifdef QT_KEYPAD_NAVIGATION + static QPointer<QWidget> editingWidget; #endif - // All widgets are initially added into the uncreatedWidgets set. Once - // they receive a window id they are removed and added to the mapper - static QWidgetMapper *mapper; - static QWidgetSet *uncreatedWidgets; - - short leftmargin, topmargin, rightmargin, bottommargin; - - signed char leftLayoutItemMargin; - signed char topLayoutItemMargin; - signed char rightLayoutItemMargin; - signed char bottomLayoutItemMargin; - // ### TODO: reorganize private/extra/topextra to save memory - QPointer<QWidget> compositeChildGrab; + // Implicit pointers (shared_null/shared_empty). + QRegion opaqueChildren; + QRegion dirty; #ifndef QT_NO_TOOLTIP QString toolTip; #endif @@ -524,14 +538,37 @@ public: #ifndef QT_NO_WHATSTHIS QString whatsThis; #endif - QString accessibleName, accessibleDescription; +#ifndef QT_NO_ACCESSIBILITY + QString accessibleName; + QString accessibleDescription; +#endif + // Other variables. + uint inheritedFontResolveMask; + uint inheritedPaletteResolveMask; + short leftmargin; + short topmargin; + short rightmargin; + short bottommargin; + signed char leftLayoutItemMargin; + signed char topLayoutItemMargin; + signed char rightLayoutItemMargin; + signed char bottomLayoutItemMargin; + static int instanceCounter; // Current number of widget instances + static int maxInstances; // Maximum number of widget instances + Qt::HANDLE hd; + QWidgetData data; + QSizePolicy size_policy; + QLocale locale; + QPoint redirectOffset; +#ifndef QT_NO_ACTION + QList<QAction*> actions; +#endif + + // Bit fields. + uint high_attributes[3]; // the low ones are in QWidget::widget_attributes QPalette::ColorRole fg_role : 8; QPalette::ColorRole bg_role : 8; - uint high_attributes[3]; // the low ones are in QWidget::widget_attributes - Qt::HANDLE hd; - QRegion dirty; - QRegion *needsFlush; uint dirtyOpaqueChildren : 1; uint isOpaque : 1; uint inDirtyList : 1; @@ -539,35 +576,35 @@ public: uint isMoved : 1; uint usesDoubleBufferedGLContext : 1; -#ifdef Q_WS_WIN - uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine() -#endif - - uint inheritedFontResolveMask; - uint inheritedPaletteResolveMask; -#if defined(Q_WS_X11) + // *************************** Platform specific ************************************ +#if defined(Q_WS_X11) // <----------------------------------------------------------- X11 QX11Info xinfo; Qt::HANDLE picture; + static QWidget *mouseGrabber; + static QWidget *keyboardGrabber; + + void setWindowRole(); + void sendStartupMessage(const char *message) const; + void setNetWmWindowTypes(); + void x11UpdateIsOpaque(); + bool isBackgroundInherited() const; +#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN + uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine() + + bool shouldShowMaximizeButton(); + void winUpdateIsOpaque(); + void reparentChildren(); +#ifndef QT_NO_DRAGANDDROP + QOleDropTarget *registerOleDnd(QWidget *widget); + void unregisterOleDnd(QWidget *widget, QOleDropTarget *target); #endif -#if defined(Q_WS_MAC) - enum PaintChildrenOPs { - PC_None = 0x00, - PC_Now = 0x01, - PC_NoPaint = 0x04, - PC_Later = 0x10 - }; - EventHandlerRef window_event; - bool qt_mac_dnd_event(uint, DragRef); - void toggleDrawers(bool); - //mac event functions - static bool qt_create_root_win(); - static void qt_clean_root_win(); - static bool qt_recreate_root_win(); - static bool qt_mac_update_sizer(QWidget *, int up = 0); - static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *); - static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *); - static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool); - static bool qt_widget_shape(QWidget *, short, HIMutableShapeRef, bool); + void grabMouseWhileInWindow(); + void registerTouchWindow(); + void winSetupGestures(); +#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC + // This is new stuff + uint needWindowChange : 1; + uint isGLWidget : 1; // Each wiget keeps a list of all its child and grandchild OpenGL widgets. // This list is used to update the gl context whenever a parent and a granparent @@ -580,95 +617,138 @@ public: QWidget * widget; QWidget * lastUpdateWidget; }; - QList<GlWidgetInfo> glWidgets; // dirtyOnWidget contains the areas in the widget that needs to be repained, // in the same way as dirtyOnScreen does for the window. Areas are added in // dirtyWidget_sys and cleared in the paint event. In scroll_sys we then use // this information repaint invalid areas when widgets are scrolled. QRegion dirtyOnWidget; + EventHandlerRef window_event; + QList<GlWidgetInfo> glWidgets; //these are here just for code compat (HIViews) Qt::HANDLE qd_hd; - // This is new stuff - uint needWindowChange : 1; - uint isGLWidget : 1; -#endif - -#if defined(Q_WS_X11) || defined (Q_WS_WIN) || defined(Q_WS_MAC) -#ifdef Q_WS_MAC - void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect()); + void macUpdateSizeAttribute(); + void macUpdateHideOnSuspend(); + void macUpdateOpaqueSizeGrip(); + void macUpdateIgnoreMouseEvents(); + void macUpdateMetalAttribute(); + void macUpdateIsOpaque(); + void setEnabled_helper_sys(bool enable); + bool isRealWindow() const; + void adjustWithinMaxAndMinSize(int &w, int &h); + void applyMaxAndMinSizeOnWindow(); + void update_sys(const QRect &rect); + void update_sys(const QRegion &rgn); + void setGeometry_sys_helper(int, int, int, int, bool); + void setWindowModified_sys(bool b); + void updateMaximizeButton_sys(); + void setWindowFilePath_sys(const QString &filePath); + void createWindow_sys(); + void recreateMacWindow(); +#ifndef QT_MAC_USE_COCOA + void initWindowPtr(); + void finishCreateWindow_sys_Carbon(OSWindowRef windowRef); #else - void setWSGeometry(bool dontShow=false); + void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef); + void syncCocoaMask(); + void finishCocoaMaskSetup(); #endif + void determineWindowClass(); + void transferChildren(); + bool qt_mac_dnd_event(uint, DragRef); + void toggleDrawers(bool); + //mac event functions + static bool qt_create_root_win(); + static void qt_clean_root_win(); + static bool qt_mac_update_sizer(QWidget *, int up = 0); + static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *); + static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *); + static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool); + void registerTouchWindow(); +#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS + void setMaxWindowState_helper(); + void setFullScreenSize_helper(); + void moveSurface(QWindowSurface *surface, const QPoint &offset); + QRegion localRequestedRegion() const; + QRegion localAllocatedRegion() const; - inline QPoint mapToWS(const QPoint &p) const - { return p - data.wrect.topLeft(); } + friend class QWSManager; + friend class QWSManagerPrivate; + friend class QDecoration; +#ifndef QT_NO_CURSOR + void updateCursor() const; +#endif + QScreen* getScreen() const; +#elif defined(Q_OS_SYMBIAN) // <--------------------------------------------------------- SYMBIAN + static QWidget *mouseGrabber; + static QWidget *keyboardGrabber; + void s60UpdateIsOpaque(); + void reparentChildren(); +#endif - inline QPoint mapFromWS(const QPoint &p) const - { return p + data.wrect.topLeft(); } +}; - inline QRect mapToWS(const QRect &r) const - { QRect rr(r); rr.translate(-data.wrect.topLeft()); return rr; } +struct QWidgetPaintContext +{ + inline QWidgetPaintContext(QPaintDevice *d, const QRegion &r, const QPoint &o, int f, + QPainter *p, QWidgetBackingStore *b) + : pdev(d), rgn(r), offset(o), flags(f), sharedPainter(p), backingStore(b), painter(0) {} + + QPaintDevice *pdev; + QRegion rgn; + QPoint offset; + int flags; + QPainter *sharedPainter; + QWidgetBackingStore *backingStore; + QPainter *painter; +}; - inline QRect mapFromWS(const QRect &r) const - { QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; } -#endif +class QWidgetEffectSourcePrivate : public QGraphicsEffectSourcePrivate +{ +public: + QWidgetEffectSourcePrivate(QWidget *widget) + : QGraphicsEffectSourcePrivate(), m_widget(widget), context(0) + {} - QPaintEngine *extraPaintEngine; + inline void detach() + { m_widget->setGraphicsEffect(0); } - mutable const QMetaObject *polished; + inline const QGraphicsItem *graphicsItem() const + { return 0; } - void setModal_sys(); - QSizePolicy size_policy; - QLocale locale; + inline const QWidget *widget() const + { return m_widget; } -#ifdef Q_WS_X11 - static QWidget *mouseGrabber; - static QWidget *keyboardGrabber; -#endif - QPaintDevice *redirectDev; - QPoint redirectOffset; + inline void update() + { m_widget->update(); } - inline void setRedirected(QPaintDevice *replacement, const QPoint &offset) - { - Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent)); - redirectDev = replacement; - redirectOffset = offset; - } + inline bool isPixmap() const + { return false; } - inline QPaintDevice *redirected(QPoint *offset) const + inline void effectBoundingRectChanged() { - if (offset) - *offset = redirectDev ? redirectOffset : QPoint(); - return redirectDev; + // ### This function should take a rect parameter; then we can avoid + // updating too much on the parent widget. + if (QWidget *parent = m_widget->parentWidget()) + parent->update(); + else + m_widget->update(); } - inline void restoreRedirected() - { redirectDev = 0; } + inline const QStyleOption *styleOption() const + { return 0; } - inline void enforceNativeChildren() - { - if (!extra) - createExtra(); + inline QRect deviceRect() const + { return m_widget->window()->rect(); } - if (extra->nativeChildrenForced) - return; - extra->nativeChildrenForced = 1; - - for (int i = 0; i < children.size(); ++i) { - if (QWidget *child = qobject_cast<QWidget *>(children.at(i))) - child->setAttribute(Qt::WA_NativeWindow); - } - } + QRectF boundingRect(Qt::CoordinateSystem system) const; + void draw(QPainter *p); + QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const; - inline bool nativeChildrenForced() const - { - return extra ? extra->nativeChildrenForced : false; - } - - QSize adjustedSize() const; + QWidget *m_widget; + QWidgetPaintContext *context; }; inline QWExtra *QWidgetPrivate::extraData() const diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp index ae82cd2..82a88ac 100644 --- a/src/gui/kernel/qwidget_qws.cpp +++ b/src/gui/kernel/qwidget_qws.cpp @@ -258,7 +258,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) Q_D(QWidget); if (!isWindow() && parentWidget()) - parentWidget()->d_func()->invalidateBuffer(geometry()); + parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); if (testAttribute(Qt::WA_WState_Created)) { @@ -298,11 +298,16 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) d->hide_sys(); } if (destroyWindow && isWindow()) { - d->extra->topextra->backingStore->windowSurface->setGeometry(QRect()); + if (d->extra && d->extra->topextra && d->extra->topextra->backingStore) + d->extra->topextra->backingStore->windowSurface->setGeometry(QRect()); qwsDisplay()->destroyRegion(internalWinId()); } } - d->setWinId(0); + QT_TRY { + d->setWinId(0); + } QT_CATCH (const std::bad_alloc &) { + // swallow - destructors must not throw + } } } @@ -312,7 +317,7 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) Q_Q(QWidget); bool wasCreated = q->testAttribute(Qt::WA_WState_Created); if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) - q->parentWidget()->d_func()->invalidateBuffer(q->geometry()); + q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); #ifndef QT_NO_CURSOR QCursor oldcurs; bool setcurs=q->testAttribute(Qt::WA_SetCursor); @@ -565,20 +570,6 @@ void QWidget::activateWindow() } } -/* - Should we require that q is a toplevel window ??? - - Used by QWSManager - */ -void QWidgetPrivate::blitToScreen(const QRegion &globalrgn) -{ - Q_Q(QWidget); - QWidget *win = q->window(); - QBrush bgBrush = win->palette().brush(win->backgroundRole()); - bool opaque = bgBrush.style() == Qt::NoBrush || bgBrush.isOpaque(); - QWidget::qwsDisplay()->repaintRegion(win->data->winid, win->windowFlags(), opaque, globalrgn); -} - void QWidgetPrivate::show_sys() { Q_Q(QWidget); @@ -590,6 +581,15 @@ void QWidgetPrivate::show_sys() if (q->isWindow()) { + + if (!q->testAttribute(Qt::WA_ShowWithoutActivating) + && q->windowType() != Qt::Popup + && q->windowType() != Qt::Tool + && q->windowType() != Qt::ToolTip) { + QWidget::qwsDisplay()->requestFocus(data.winid,true); + } + + if (QWindowSurface *surface = q->windowSurface()) { const QRect frameRect = q->frameGeometry(); if (surface->geometry() != frameRect) @@ -606,12 +606,6 @@ void QWidgetPrivate::show_sys() #endif data.fstrut_dirty = true; invalidateBuffer(r); - if (!q->testAttribute(Qt::WA_ShowWithoutActivating) - && q->windowType() != Qt::Popup - && q->windowType() != Qt::Tool - && q->windowType() != Qt::ToolTip) { - QWidget::qwsDisplay()->requestFocus(data.winid,true); - } bool staysontop = (q->windowFlags() & Qt::WindowStaysOnTopHint) || q->windowType() == Qt::Popup; @@ -652,7 +646,8 @@ void QWidgetPrivate::hide_sys() q->releaseMouse(); // requestWindowRegion(QRegion()); - extra->topextra->backingStore->releaseBuffer(); + if (extra->topextra->backingStore) + extra->topextra->backingStore->releaseBuffer(); QWidget::qwsDisplay()->requestFocus(data.winid,false); @@ -819,7 +814,7 @@ void QWidgetPrivate::lower_sys() QWSChangeAltitudeCommand::Lower); } else if (QWidget *p = q->parentWidget()) { setDirtyOpaqueRegion(); - p->d_func()->invalidateBuffer(q->geometry()); + p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); } } @@ -828,7 +823,7 @@ void QWidgetPrivate::stackUnder_sys(QWidget*) Q_Q(QWidget); if (QWidget *p = q->parentWidget()) { setDirtyOpaqueRegion(); - p->d_func()->invalidateBuffer(q->geometry()); + p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); } } @@ -1037,6 +1032,9 @@ void QWidgetPrivate::deleteSysExtra() void QWidgetPrivate::createTLSysExtra() { +#ifndef QT_NO_QWS_MANAGER + extra->topextra->qwsManager = 0; +#endif } void QWidgetPrivate::deleteTLSysExtra() diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp new file mode 100644 index 0000000..6da35d8 --- /dev/null +++ b/src/gui/kernel/qwidget_s60.cpp @@ -0,0 +1,1206 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qwidget_p.h" +#include "qdesktopwidget.h" +#include "qapplication.h" +#include "qapplication_p.h" +#include "private/qbackingstore_p.h" +#include "qevent.h" +#include "qt_s60_p.h" + +#include "qbitmap.h" +#include "private/qwindowsurface_s60_p.h" + +#include <qinputcontext.h> + +#ifdef Q_WS_S60 +#include <aknappui.h> +#endif + +QT_BEGIN_NAMESPACE + +extern bool qt_nograb(); + +QWidget *QWidgetPrivate::mouseGrabber = 0; +QWidget *QWidgetPrivate::keyboardGrabber = 0; + +static bool isEqual(const QList<QAction*>& a, const QList<QAction*>& b) +{ + if ( a.count() != b.count()) + return false; + int index=0; + while (index<a.count()) { + if (a.at(index)->softKeyRole() != b.at(index)->softKeyRole()) + return false; + if (a.at(index)->text().compare(b.at(index)->text())!=0) + return false; + index++; + } + return true; +} + + +void QWidgetPrivate::setSoftKeys_sys(const QList<QAction*> &softkeys) +{ +#ifdef Q_WS_S60 + Q_Q(QWidget); + if (QApplication::focusWidget() && q!=QApplication::focusWidget()) { + QList<QAction *> old = QApplication::focusWidget()->softKeys(); + if (isEqual(old, softkeys )) + return; + } + CEikButtonGroupContainer* nativeContainer = S60->buttonGroupContainer(); + QT_TRAP_THROWING(nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS)); + + int position = -1; + int command; + bool needsExitButton = true; + + for (int index = 0; index < softkeys.count(); index++) { + const QAction* softKeyAction = softkeys.at(index); + switch (softKeyAction->softKeyRole()) { + // Positive Actions go on LSK + case QAction::OptionsSoftKey: + case QAction::MenuSoftKey: + case QAction::ContextMenuSoftKey: + command = EAknSoftkeyOptions; //Calls DynInitMenuPane in AppUI + position = 0; + break; + case QAction::SelectSoftKey: + case QAction::PreviousSoftKey: + case QAction::OkSoftKey: + case QAction::EditSoftKey: + case QAction::ViewSoftKey: + case QAction::EndEditSoftKey: + case QAction::FinishSoftKey: + command = SOFTKEYSTART + index; + position = 0; + break; + // Negative Actions on the RSK + case QAction::BackSoftKey: + case QAction::NextSoftKey: + case QAction::CancelSoftKey: + case QAction::BackSpaceSoftKey: + case QAction::RevertEditSoftKey: + case QAction::DeselectSoftKey: + needsExitButton = false; + command = SOFTKEYSTART + index; + position = 2; + break; + case QAction::ExitSoftKey: + needsExitButton = false; + command = EAknSoftkeyExit; //Calls HandleCommand in AppUI + position = 2; + break; + default: + break; + } + + if (position != -1) { + TPtrC text = qt_QString2TPtrC(softKeyAction->text()); + QT_TRAP_THROWING(nativeContainer->SetCommandL(position, command, text)); + } + } + + if (needsExitButton) + QT_TRAP_THROWING(nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QObject::tr("Exit")))); + + nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation +#else + Q_UNUSED(softkeys) +#endif +} + +void QWidgetPrivate::setWSGeometry(bool /* dontShow */, const QRect & /* rect */) +{ + +} + +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; + if (extra) { // any size restrictions? + w = qMin(w,extra->maxw); + h = qMin(h,extra->maxh); + w = qMax(w,extra->minw); + h = qMax(h,extra->minh); + } + + if (q->isWindow()) + topData()->normalGeometry = QRect(0, 0, -1, -1); + else { + uint s = data.window_state; + s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen); + data.window_state = s; + } + + QPoint oldPos(q->pos()); + QSize oldSize(q->size()); + QRect oldGeom(data.crect); + + bool isResize = w != oldSize.width() || h != oldSize.height(); + if (!isMove && !isResize) + return; + + if (isResize) + data.window_state &= ~Qt::WindowMaximized; + + if(q->isWindow()) { + if (w == 0 || h == 0) { + q->setAttribute(Qt::WA_OutsideWSRange, true); + if (q->isVisible() && q->testAttribute(Qt::WA_Mapped)) + hide_sys(); + data.crect = QRect(x, y, w, h); + data.window_state &= ~Qt::WindowFullScreen; + } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) { + q->setAttribute(Qt::WA_OutsideWSRange, false); + + // put the window in its place and show it + q->internalWinId()->SetRect(TRect(TPoint(x, y), TSize(w, h))); + data.crect.setRect(x, y, w, h); + + show_sys(); + } else { + QRect r = QRect(x, y, w, h); + data.crect = r; + q->internalWinId()->SetRect(TRect(TPoint(x, y), TSize(w, h))); + topData()->normalGeometry = data.crect; + } + } else { + data.crect.setRect(x, y, w, h); + + QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); + const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false; + + if (q->isVisible() && (!inTopLevelResize || q->internalWinId())) { + // Top-level resize optimization does not work for native child widgets; + // disable it for this particular widget. + if (inTopLevelResize) + tlwExtra->inTopLevelResize = false; + if (!isResize && maybeBackingStore()) + moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y()); + else + invalidateBuffer_resizeHelper(oldPos, oldSize); + + if (inTopLevelResize) + tlwExtra->inTopLevelResize = true; + } + if (q->testAttribute(Qt::WA_WState_Created)) + setWSGeometry(); + } + + if (q->isVisible()) { + if (isMove && q->pos() != oldPos) { + QMoveEvent e(q->pos(), oldPos); + QApplication::sendEvent(q, &e); + } + if (isResize) { + bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt(); + const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra + && !extra->topextra->inTopLevelResize; + if (setTopLevelResize) + extra->topextra->inTopLevelResize = true; + QResizeEvent e(q->size(), oldSize); + QApplication::sendEvent(q, &e); + if (!q->testAttribute(Qt::WA_StaticContents) && q->internalWinId()) + q->internalWinId()->DrawDeferred(); + if (setTopLevelResize) + extra->topextra->inTopLevelResize = false; + } + } else { + if (isMove && q->pos() != oldPos) + q->setAttribute(Qt::WA_PendingMoveEvent, true); + if (isResize) + q->setAttribute(Qt::WA_PendingResizeEvent, true); + } +} + +void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool destroyOldWindow) +{ + Q_Q(QWidget); + + 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 + || (flags & Qt::MSWindowsFixedSizeDialogHint)); + bool desktop = (type == Qt::Desktop); + //bool tool = (type == Qt::Tool || type == Qt::Drawer); + + WId id = 0; + + if (popup) + flags |= Qt::WindowStaysOnTopHint; // a popup stays on top + + TRect clientRect = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); + int sw = clientRect.Width(); + int sh = clientRect.Height(); + + if (desktop) { + TSize screenSize = S60->screenDevice()->SizeInPixels(); + data.crect.setRect(0, 0, screenSize.iWidth, screenSize.iHeight); + q->setAttribute(Qt::WA_DontShowOnScreen); + } else if(topLevel && !q->testAttribute(Qt::WA_Resized)){ + int width = sw; + int height = sh; + if (extra) { + width = qMax(qMin(width, extra->maxw), extra->minw); + height = qMax(qMin(height, extra->maxh), extra->minh); + } + data.crect.setSize(QSize(width, height)); + } + + CCoeControl *destroyw = 0; + + createExtra(); + if(window) { + if (destroyOldWindow) + destroyw = data.winid; + id = window; + setWinId(window); + TRect tr = window->Rect(); + data.crect.setRect(tr.iTl.iX, tr.iTl.iY, tr.Width(), tr.Height()); + + } else if (topLevel) { + if (!q->testAttribute(Qt::WA_Moved) && !q->testAttribute(Qt::WA_DontShowOnScreen)) + data.crect.moveTopLeft(QPoint(clientRect.iTl.iX, clientRect.iTl.iY)); + QSymbianControl *control= q_check_ptr(new QSymbianControl(q)); + id = (WId)control; + setWinId(id); + QT_TRAP_THROWING(control->ConstructL(true,desktop)); + + if (!desktop) { + TInt stackingFlags; + if ((q->windowType() & Qt::Popup) == Qt::Popup) { + stackingFlags = ECoeStackFlagRefusesAllKeys | ECoeStackFlagRefusesFocus; + } else { + stackingFlags = ECoeStackFlagStandard; + } + QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control, ECoeStackPriorityDefault, stackingFlags)); + + QTLWExtra *topExtra = topData(); + topExtra->rwindow = control->DrawableWindow(); + // Request mouse move events. + topExtra->rwindow->PointerFilter(EPointerFilterEnterExit + | EPointerFilterMove | EPointerFilterDrag, 0); + topExtra->rwindow->EnableVisibilityChangeEvents(); + + if (!isOpaque) { + RWindow *rwindow = static_cast<RWindow*>(topExtra->rwindow); + TDisplayMode gotDM = (TDisplayMode)rwindow->SetRequiredDisplayMode(EColor16MA); + if (rwindow->SetTransparencyAlphaChannel() == KErrNone) + rwindow->SetBackgroundColor(TRgb(255, 255, 255, 0)); + } + } + + q->setAttribute(Qt::WA_WState_Created); + + int x, y, w, h; + data.crect.getRect(&x, &y, &w, &h); + control->SetRect(TRect(TPoint(x, y), TSize(w, h))); + } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create native child widget + QSymbianControl *control = new QSymbianControl(q); + setWinId(control); + QT_TRAP_THROWING(control->ConstructL(!parentWidget)); + + TInt stackingFlags; + if ((q->windowType() & Qt::Popup) == Qt::Popup) { + stackingFlags = ECoeStackFlagRefusesAllKeys | ECoeStackFlagRefusesFocus; + } else { + stackingFlags = ECoeStackFlagStandard; + } + QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control, ECoeStackPriorityDefault, stackingFlags)); + + WId parentw = parentWidget->effectiveWinId(); + QT_TRAP_THROWING(control->SetContainerWindowL(*parentw)); + + q->setAttribute(Qt::WA_WState_Created); + int x, y, w, h; + data.crect.getRect(&x, &y, &w, &h); + control->SetRect(TRect(TPoint(x, y), TSize(w, h))); + } + + if (destroyw) { + destroyw->ControlEnv()->AppUi()->RemoveFromStack(destroyw); + CBase::Delete(destroyw); + } +} + + +void QWidgetPrivate::show_sys() +{ + Q_Q(QWidget); + + if (q->testAttribute(Qt::WA_OutsideWSRange)) + return; + + Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); + + q->setAttribute(Qt::WA_Mapped); + + if (q->testAttribute(Qt::WA_DontShowOnScreen)) { + invalidateBuffer(q->rect()); + return; + } + + if (q->isWindow() && q->internalWinId()) { + + WId id = q->internalWinId(); + if (!extra->topextra->activated) { + QT_TRAP_THROWING(id->ActivateL()); + extra->topextra->activated = 1; + } + id->MakeVisible(true); + id->SetFocus(true); + + // Force setting of the icon after window is made visible, + // this is needed even WA_SetWindowIcon is not set, as in that case we need + // to reset to the application level window icon + setWindowIcon_sys(true); + } + + invalidateBuffer(q->rect()); +} + +void QWidgetPrivate::hide_sys() +{ + Q_Q(QWidget); + Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); + deactivateWidgetCleanup(); + WId id = q->internalWinId(); + if (q->isWindow() && id) { + if(id->IsFocused()) // Avoid unnecessary calls to FocusChanged() + id->SetFocus(false); + id->MakeVisible(false); + if (QWidgetBackingStore *bs = maybeBackingStore()) + bs->releaseBuffer(); + } else { + invalidateBuffer(q->rect()); + } + + q->setAttribute(Qt::WA_Mapped, false); +} + +void QWidgetPrivate::setFocus_sys() +{ + Q_Q(QWidget); + if (q->testAttribute(Qt::WA_WState_Created) && q->window()->windowType() != Qt::Popup) + if(!q->effectiveWinId()->IsFocused()) // Avoid unnecessry calls to FocusChanged() + q->effectiveWinId()->SetFocus(true); +} + +void QWidgetPrivate::handleSymbianDeferredFocusChanged() +{ + Q_Q(QWidget); + WId control = q->internalWinId(); + if (!control) { + // This could happen if the widget was reparented, while the focuschange + // was in the event queue. + return; + } + + if (control->IsFocused()) { + QApplication::setActiveWindow(q); +#ifdef Q_WS_S60 + // If widget is fullscreen, hide status pane and button container + // otherwise show them. + CEikStatusPane* statusPane = S60->statusPane(); + CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer(); + bool isFullscreen = q->windowState() & Qt::WindowFullScreen; + if (statusPane && (statusPane->IsVisible() == isFullscreen)) + statusPane->MakeVisible(!isFullscreen); + if (buttonGroup && (buttonGroup->IsVisible() == isFullscreen)) + buttonGroup->MakeVisible(!isFullscreen); +#endif + } else { + QApplication::setActiveWindow(0); + } +} + +void QWidgetPrivate::raise_sys() +{ + Q_Q(QWidget); + Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); + QTLWExtra *tlwExtra = maybeTopData(); + if (q->internalWinId() && tlwExtra) { + tlwExtra->rwindow->SetOrdinalPosition(0); + } +} + +void QWidgetPrivate::lower_sys() +{ + Q_Q(QWidget); + Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); + QTLWExtra *tlwExtra = maybeTopData(); + if (q->internalWinId() && tlwExtra) { + tlwExtra->rwindow->SetOrdinalPosition(-1); + } + if(!q->isWindow()) + invalidateBuffer(q->rect()); +} + +void QWidgetPrivate::setModal_sys() +{ + +} + +void QWidgetPrivate::stackUnder_sys(QWidget* w) +{ + Q_Q(QWidget); + Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); + QTLWExtra *tlwExtra = maybeTopData(); + QTLWExtra *tlwExtraSibling = w->d_func()->maybeTopData(); + if (q->internalWinId() && tlwExtra && w->internalWinId() && tlwExtraSibling) + tlwExtra->rwindow->SetOrdinalPosition(tlwExtraSibling->rwindow->OrdinalPosition() + 1); + if(!q->isWindow() || !w->internalWinId()) + invalidateBuffer(q->rect()); +} + +void QWidgetPrivate::reparentChildren() +{ + Q_Q(QWidget); + QObjectList chlist = q->children(); + for (int i = 0; i < chlist.size(); ++i) { // reparent children + QObject *obj = chlist.at(i); + if (obj->isWidgetType()) { + QWidget *w = (QWidget *)obj; + if (!w->testAttribute(Qt::WA_WState_Created)) + continue; + if (!w->isWindow()) { + w->d_func()->invalidateBuffer(w->rect()); + WId parent = q->effectiveWinId(); + WId child = w->effectiveWinId(); + if (parent != child) + child->SetParent(parent); + // ### TODO: We probably also need to update the component array here + w->d_func()->reparentChildren(); + } else { + bool showIt = w->isVisible(); + QPoint old_pos = w->pos(); + w->setParent(q, w->windowFlags()); + w->move(old_pos); + if (showIt) + w->show(); + } + } + } +} + +void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) +{ + Q_Q(QWidget); + bool wasCreated = q->testAttribute(Qt::WA_WState_Created); + + if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) + q->parentWidget()->d_func()->invalidateBuffer(q->geometry()); + + if (q->testAttribute(Qt::WA_DropSiteRegistered)) + q->setAttribute(Qt::WA_DropSiteRegistered, false); + + WId old_winid = wasCreated ? data.winid : 0; + if ((q->windowType() == Qt::Desktop)) + old_winid = 0; + setWinId(0); + + // hide and reparent our own window away. Otherwise we might get + // destroyed when emitting the child remove event below. See QWorkspace. + if (wasCreated && old_winid) { + old_winid->MakeVisible(false); + if(old_winid->IsFocused()) // Avoid unnecessary calls to FocusChanged() + old_winid->SetFocus(false); + old_winid->SetParent(0); + } + + QObjectPrivate::setParent_helper(parent); + bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide); + + data.window_flags = f; + data.fstrut_dirty = true; + 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) + if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created))) + createWinId(); + if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden) + q->setAttribute(Qt::WA_WState_Hidden); + q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden); + + if (wasCreated) + reparentChildren(); + + if (old_winid) { + CBase::Delete(old_winid); + } + + if (q->testAttribute(Qt::WA_AcceptDrops) + || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) + q->setAttribute(Qt::WA_DropSiteRegistered, true); + + invalidateBuffer(q->rect()); +} + +void QWidgetPrivate::setConstraints_sys() +{ + +} + + +void QWidgetPrivate::s60UpdateIsOpaque() +{ + Q_Q(QWidget); + + if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground)) + return; + + if ((data.window_flags & Qt::FramelessWindowHint) == 0) + return; + + if (!isOpaque) { + QTLWExtra *topExtra = topData(); + RWindow *rwindow = static_cast<RWindow*>(topExtra->rwindow); + TDisplayMode gotDM = (TDisplayMode)rwindow->SetRequiredDisplayMode(EColor16MA); + if (rwindow->SetTransparencyAlphaChannel() == KErrNone) + rwindow->SetBackgroundColor(TRgb(255, 255, 255, 0)); + } else { + QTLWExtra *topExtra = topData(); + RWindow *rwindow = static_cast<RWindow*>(topExtra->rwindow); + rwindow->SetTransparentRegion(TRegionFix<1>()); + } +} + +CFbsBitmap* qt_pixmapToNativeBitmap(QPixmap pixmap, bool invert) +{ + CFbsBitmap* fbsBitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new + TSize size(pixmap.size().width(), pixmap.size().height()); + TDisplayMode mode(EColor16MU); + + bool isNull = pixmap.isNull(); + int depth = pixmap.depth(); + + // TODO: dummy assumptions from bit amounts for each color + // Will fix later on when native pixmap is implemented + switch(pixmap.depth()) { + case 1: + mode = EGray2; + break; + case 4: + mode = EColor16; + break; + case 8: + mode = EColor256; + break; + case 12: + mode = EColor4K; + break; + case 16: + mode = EColor64K; + break; + case 24: + mode = EColor16M; + break; + case 32: + case EColor16MU: + break; + default: + qFatal("Unsupported pixmap depth"); + break; + } + + qt_symbian_throwIfError(fbsBitmap->Create(size, mode)); + fbsBitmap->LockHeap(); + QImage image = pixmap.toImage(); + + if(invert) + image.invertPixels(); + + int height = pixmap.size().height(); + for(int i=0;i<height;i++ ) + { + TPtr8 scanline(image.scanLine(i), image.bytesPerLine(), image.bytesPerLine()); + fbsBitmap->SetScanLine( scanline, i ); + } + + fbsBitmap->UnlockHeap(); + return fbsBitmap; +} + +void QWidgetPrivate::setWindowIcon_sys(bool forceReset) +{ +#ifdef Q_WS_S60 + Q_Q(QWidget); + + if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow() ) + return; + + QTLWExtra* topData = this->topData(); + if (topData->iconPixmap && !forceReset) + // already been set + return; + + TRect cPaneRect; + TBool found = AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EContextPane, cPaneRect ); + CAknContextPane* contextPane = S60->contextPane(); + if (found && contextPane) { // We have context pane with valid metrics + QIcon icon = q->windowIcon(); + if (!icon.isNull()) { + // Valid icon -> set it as an context pane picture + QSize size = icon.actualSize(QSize(cPaneRect.Size().iWidth, cPaneRect.Size().iHeight)); + QPixmap pm = icon.pixmap(size); + QBitmap mask = pm.mask(); + if (mask.isNull()) { + mask = QBitmap(pm.size()); + mask.fill(Qt::color1); + } + + // Convert to CFbsBitmp + // TODO: When QPixmap is adapted to use native CFbsBitmap, + // it could be set directly to context pane + CFbsBitmap* nBitmap = qt_pixmapToNativeBitmap(pm, false); + CFbsBitmap* nMask = qt_pixmapToNativeBitmap(mask, true); + + contextPane->SetPicture(nBitmap,nMask); + } else { + // Icon set to null -> set context pane picture to default + QT_TRAP_THROWING(contextPane->SetPictureToDefaultL()); + } + } else { + // Context pane does not exist, try setting small icon to title pane + TRect titlePaneRect; + TBool found = AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::ETitlePane, titlePaneRect ); + CAknTitlePane* titlePane = S60->titlePane(); + if (found && titlePane) { // We have title pane with valid metrics + // The API to get title_pane graphics size is not public -> assume square space based + // on titlebar font height. CAknBitmap would be optimum, wihtout setting the size, since + // then title pane would automatically scale the bitmap. Unfortunately it is not public API + const CFont * font = AknLayoutUtils::FontFromId(EAknLogicalFontTitleFont); + TSize iconSize(font->HeightInPixels(), font->HeightInPixels()); + + QIcon icon = q->windowIcon(); + if (!icon.isNull()) { + // Valid icon -> set it as an title pane small picture + QSize size = icon.actualSize(QSize(iconSize.iWidth, iconSize.iHeight)); + QPixmap pm = icon.pixmap(size); + QBitmap mask = pm.mask(); + if (mask.isNull()) { + mask = QBitmap(pm.size()); + mask.fill(Qt::color1); + } + + // Convert to CFbsBitmp + // TODO: When QPixmap is adapted to use native CFbsBitmap, + // it could be set directly to context pane + CFbsBitmap* nBitmap = qt_pixmapToNativeBitmap(pm, false); + CFbsBitmap* nMask = qt_pixmapToNativeBitmap(mask, true); + + titlePane->SetSmallPicture( nBitmap, nMask, ETrue ); + } else { + // Icon set to null -> set context pane picture to default + titlePane->SetSmallPicture( NULL, NULL, EFalse ); + } + } + } + +#else + Q_UNUSED(forceReset) +#endif +} + +void QWidgetPrivate::setWindowTitle_sys(const QString &caption) +{ +#ifdef Q_WS_S60 + Q_Q(QWidget); + if (q->isWindow()) { + Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); + CAknTitlePane* titlePane = S60->titlePane(); + if(titlePane) { + if(caption.isEmpty()) { + QT_TRAP_THROWING(titlePane->SetTextToDefaultL()); + } else { + QT_TRAP_THROWING(titlePane->SetTextL(qt_QString2TPtrC(caption))); + } + } + } +#else + Q_UNUSED(caption) +#endif +} + +void QWidgetPrivate::setWindowIconText_sys(const QString & /*iconText */) +{ + +} + +void QWidgetPrivate::scroll_sys(int dx, int dy) +{ + Q_Q(QWidget); + + scrollChildren(dx, dy); + if (!paintOnScreen() || !q->internalWinId() || !q->internalWinId()->OwnsWindow()) { + scrollRect(q->rect(), dx, dy); + } else { + Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); + RDrawableWindow* rw = topData()->rwindow; + rw->Scroll(TPoint(dx, dy)); + } +} + +void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) +{ + Q_Q(QWidget); + + if (!paintOnScreen() || !q->internalWinId() || !q->internalWinId()->OwnsWindow()) { + scrollRect(r, dx, dy); + } else { + Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); + RDrawableWindow* rw = topData()->rwindow; + rw->Scroll(TPoint(dx, dy), qt_QRect2TRect(r)); + } +} + +/*! + For this function to work in the emulator, you must add: + TRANSPARENCY + To a line in the wsini.ini file. +*/ +void QWidgetPrivate::setWindowOpacity_sys(qreal) +{ + // ### TODO: Implement uniform window transparency +} + +void QWidgetPrivate::updateFrameStrut() +{ + +} + +void QWidgetPrivate::updateSystemBackground() +{ + +} + +void QWidgetPrivate::registerDropSite(bool /* on */) +{ + +} + +void QWidgetPrivate::createTLSysExtra() +{ + extra->topextra->backingStore = 0; + extra->topextra->activated = 0; + extra->topextra->rwindow = 0; +} + +void QWidgetPrivate::deleteTLSysExtra() +{ + delete extra->topextra->backingStore; + extra->topextra->backingStore = 0; +} + +void QWidgetPrivate::createSysExtra() +{ + +} + +void QWidgetPrivate::deleteSysExtra() +{ + // this should only be non-zero if destroy() has not run due to constructor fail + if (data.winid) { + data.winid->ControlEnv()->AppUi()->RemoveFromStack(data.winid); + delete data.winid; + data.winid = 0; + } +} + +QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys() +{ + return new QS60WindowSurface(q_func()); +} + +void QWidgetPrivate::setMask_sys(const QRegion& /* region */) +{ + +} + +int QWidget::metric(PaintDeviceMetric m) const +{ + Q_D(const QWidget); + int val; + if (m == PdmWidth) { + val = data->crect.width(); + } else if (m == PdmHeight) { + val = data->crect.height(); + } else { + CWsScreenDevice *scr = S60->screenDevice(); + switch(m) { + case PdmDpiX: + case PdmPhysicalDpiX: + if (d->extra && d->extra->customDpiX) { + val = d->extra->customDpiX; + } else { + const QWidgetPrivate *p = d; + while (p->parent) { + p = static_cast<const QWidget *>(p->parent)->d_func(); + if (p->extra && p->extra->customDpiX) { + val = p->extra->customDpiX; + break; + } + } + if (p == d || !(p->extra && p->extra->customDpiX)) + val = S60->defaultDpiX; + } + break; + case PdmDpiY: + case PdmPhysicalDpiY: + if (d->extra && d->extra->customDpiY) { + val = d->extra->customDpiY; + } else { + const QWidgetPrivate *p = d; + while (p->parent) { + p = static_cast<const QWidget *>(p->parent)->d_func(); + if (p->extra && p->extra->customDpiY) { + val = p->extra->customDpiY; + break; + } + } + if (p == d || !(p->extra && p->extra->customDpiY)) + val = S60->defaultDpiY; + } + break; + case PdmWidthMM: + { + TInt twips = scr->HorizontalPixelsToTwips(data->crect.width()); + val = (int)(twips * (25.4/KTwipsPerInch)); + break; + } + case PdmHeightMM: + { + TInt twips = scr->VerticalPixelsToTwips(data->crect.height()); + val = (int)(twips * (25.4/KTwipsPerInch)); + break; + } + case PdmNumColors: + val = TDisplayModeUtils::NumDisplayModeColors(scr->DisplayMode()); + break; + case PdmDepth: + val = TDisplayModeUtils::NumDisplayModeBitsPerPixel(scr->DisplayMode()); + break; + default: + val = 0; + qWarning("QWidget::metric: Invalid metric command"); + } + } + return val; +} + +QPaintEngine *QWidget::paintEngine() const +{ + return 0; +} + +QPoint QWidget::mapToGlobal(const QPoint &pos) const +{ + Q_D(const QWidget); + if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) { + + QPoint p = pos + data->crect.topLeft(); + return (isWindow() || !parentWidget()) ? p : parentWidget()->mapToGlobal(p); + + } else if ((d->data.window_flags & Qt::Window) && internalWinId()) { //toplevel + QPoint tp = geometry().topLeft(); + return pos + tp; + } + + // This is the native window case. Consider using CCoeControl::PositionRelativeToScreen() + // if we decide to go with CCoeControl + return QPoint(); +} + +QPoint QWidget::mapFromGlobal(const QPoint &pos) const +{ + Q_D(const QWidget); + if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) { + QPoint p = (isWindow() || !parentWidget()) ? pos : parentWidget()->mapFromGlobal(pos); + return p - data->crect.topLeft(); + } else if ((d->data.window_flags & Qt::Window) && internalWinId()) { //toplevel + QPoint tp = geometry().topLeft(); + return pos - tp; + } + + // ### TODO native window + return QPoint(); +} + +void QWidget::setWindowState(Qt::WindowStates newstate) +{ + Q_D(QWidget); + Qt::WindowStates oldstate = windowState(); + if (oldstate == newstate) + return; + + if (isWindow()) { + createWinId(); + Q_ASSERT(testAttribute(Qt::WA_WState_Created)); + QTLWExtra *top = d->topData(); + + // Ensure the initial size is valid, since we store it as normalGeometry below. + if (!testAttribute(Qt::WA_Resized) && !isVisible()) + adjustSize(); + + if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) { + if ((newstate & Qt::WindowMaximized)) { + const QRect normalGeometry = geometry(); + + const QRect r = top->normalGeometry; + setGeometry(qApp->desktop()->availableGeometry(this)); + top->normalGeometry = r; + + if (top->normalGeometry.width() < 0) + top->normalGeometry = normalGeometry; + } else { + // restore original geometry + setGeometry(top->normalGeometry); + } + } + if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) { +#ifdef Q_WS_S60 + CEikStatusPane* statusPane = S60->statusPane(); + CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer(); +#endif + if (newstate & Qt::WindowFullScreen) { + const QRect normalGeometry = geometry(); + const QRect r = top->normalGeometry; + setGeometry(qApp->desktop()->screenGeometry(this)); +#ifdef Q_WS_S60 + if (statusPane) + statusPane->MakeVisible(false); + if (buttonGroup) + buttonGroup->MakeVisible(false); +#endif + top->normalGeometry = r; + if (top->normalGeometry.width() < 0) + top->normalGeometry = normalGeometry; + } else { +#ifdef Q_WS_S60 + if (statusPane) + statusPane->MakeVisible(true); + if (buttonGroup) + buttonGroup->MakeVisible(true); +#endif + if (newstate & Qt::WindowMaximized) { + const QRect r = top->normalGeometry; + setGeometry(qApp->desktop()->availableGeometry(this)); + top->normalGeometry = r; + } else { + setGeometry(top->normalGeometry); + } + } + } + if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) { + if (newstate & Qt::WindowMinimized) { + if (isVisible()) { + WId id = effectiveWinId(); + if(id->IsFocused()) // Avoid unnecessary calls to FocusChanged() + id->SetFocus(false); + id->MakeVisible(false); + } + } else { + if (isVisible()) { + WId id = effectiveWinId(); + id->MakeVisible(true); + if(!id->IsFocused()) // Avoid unnecessary calls to FocusChanged() + id->SetFocus(true); + } + const QRect normalGeometry = geometry(); + const QRect r = top->normalGeometry; + top->normalGeometry = r; + if (top->normalGeometry.width() < 0) + top->normalGeometry = normalGeometry; + } + } + } + + data->window_state = newstate; + + if (newstate & Qt::WindowActive) + activateWindow(); + + QWindowStateChangeEvent e(oldstate); + QApplication::sendEvent(this, &e); +} + + +void QWidget::destroy(bool destroyWindow, bool destroySubWindows) +{ + Q_D(QWidget); + if (!isWindow() && parentWidget()) + parentWidget()->d_func()->invalidateBuffer(geometry()); + d->deactivateWidgetCleanup(); + WId id = internalWinId(); + if (testAttribute(Qt::WA_WState_Created)) { + +#ifndef QT_NO_IM + if (d->ic) { + delete d->ic; + } else { + QInputContext *ic = inputContext(); + if (ic) { + ic->widgetDestroyed(this); + } + } +#endif + + setAttribute(Qt::WA_WState_Created, false); + QObjectList childList = children(); + for (int i = 0; i < childList.size(); ++i) { // destroy all widget children + register QObject *obj = childList.at(i); + if (obj->isWidgetType()) + static_cast<QWidget*>(obj)->destroy(destroySubWindows, + destroySubWindows); + } + if (QWidgetPrivate::mouseGrabber == this) + releaseMouse(); + if (QWidgetPrivate::keyboardGrabber == this) + releaseKeyboard(); + if (destroyWindow && !(windowType() == Qt::Desktop) && id) { + if(id->IsFocused()) // Avoid unnecessry calls to FocusChanged() + id->SetFocus(false); + id->ControlEnv()->AppUi()->RemoveFromStack(id); + + // Hack to activate window under destroyed one. With this activation + // the next visible window will get keyboard focus + WId wid = CEikonEnv::Static()->AppUi()->TopFocusedControl(); + if (wid) { + QWidget *widget = QWidget::find(wid); + QApplication::setActiveWindow(widget); + if (widget) { + // Reset global window title for focusing window + widget->d_func()->setWindowTitle_sys(widget->windowTitle()); + } + } + } + } + + QT_TRY { + d->setWinId(0); + } QT_CATCH (const std::bad_alloc &) { + // swallow - destructors must not throw + } + + if (destroyWindow) { + delete id; + } +} + +QWidget *QWidget::mouseGrabber() +{ + return QWidgetPrivate::mouseGrabber; +} + +QWidget *QWidget::keyboardGrabber() +{ + return QWidgetPrivate::keyboardGrabber; +} + +void QWidget::grabKeyboard() +{ + if (!qt_nograb()) { + if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this) + QWidgetPrivate::keyboardGrabber->releaseKeyboard(); + + // ### TODO: Native keyboard grab + + QWidgetPrivate::keyboardGrabber = this; + } +} + +void QWidget::releaseKeyboard() +{ + if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) { + // ### TODO: Native keyboard release + QWidgetPrivate::keyboardGrabber = 0; + } +} + +void QWidget::grabMouse() +{ + if (!qt_nograb()) { + if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this) + QWidgetPrivate::mouseGrabber->releaseMouse(); + Q_ASSERT(testAttribute(Qt::WA_WState_Created)); + WId id = effectiveWinId(); + id->SetPointerCapture(true); + QWidgetPrivate::mouseGrabber = this; + } +} + +void QWidget::releaseMouse() +{ + if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) { + Q_ASSERT(testAttribute(Qt::WA_WState_Created)); + WId id = effectiveWinId(); + id->SetPointerCapture(false); + QWidgetPrivate::mouseGrabber = 0; + } +} + +void QWidget::activateWindow() +{ + Q_D(QWidget); + QWidget *tlw = window(); + if (tlw->isVisible()) { + S60->windowGroup().SetOrdinalPosition(0); + window()->createWinId(); + RDrawableWindow* rw = tlw->d_func()->topData()->rwindow; + rw->SetOrdinalPosition(0); + } +} +QT_END_NAMESPACE diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index b94a490..0ec7e7e 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -56,11 +56,9 @@ #include "private/qbackingstore_p.h" #include "private/qwindowsurface_raster_p.h" -#ifndef QT_NO_DIRECT3D -#include "private/qpaintengine_d3d_p.h" -#include "private/qwindowsurface_d3d_p.h" -#endif - +#include "qscrollbar.h" +#include "qabstractscrollarea.h" +#include <private/qabstractscrollarea_p.h> #include <qdebug.h> @@ -68,7 +66,7 @@ #include <private/qwininputcontext_p.h> #include <private/qpaintengine_raster_p.h> -#if defined(Q_OS_WINCE) +#if defined(Q_WS_WINCE) #include "qguifunctions_wince.h" QT_USE_NAMESPACE extern void qt_wince_maximize(QWidget *widget); //defined in qguifunctions_wince.cpp @@ -146,14 +144,8 @@ static void init_wintab_functions() if (!qt_is_gui_used) return; QLibrary library(QLatin1String("wintab32")); - QT_WA({ - ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenW"); - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); - } , { - ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenA"); - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoA"); - }); - + ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenW"); + ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); ptrWTClose = (PtrWTClose)library.resolve("WTClose"); ptrWTQueueSizeGet = (PtrWTQueueSizeGet)library.resolve("WTQueueSizeGet"); ptrWTQueueSizeSet = (PtrWTQueueSizeSet)library.resolve("WTQueueSizeSet"); @@ -257,7 +249,7 @@ extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM); QWidget member functions *****************************************************************************/ -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow) { Q_Q(QWidget); @@ -276,7 +268,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO HINSTANCE appinst = qWinAppInst(); HWND parentw, destroyw = 0; - WId id; + WId id = 0; QString windowClassName = qt_reg_winclass(q); @@ -293,25 +285,18 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO if (desktop && !q->testAttribute(Qt::WA_DontShowOnScreen)) { // desktop widget popup = false; // force this flags off - if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95) - data.crect.setRect(GetSystemMetrics(76 /* SM_XVIRTUALSCREEN */), GetSystemMetrics(77 /* SM_YVIRTUALSCREEN */), + data.crect.setRect(GetSystemMetrics(76 /* SM_XVIRTUALSCREEN */), GetSystemMetrics(77 /* SM_YVIRTUALSCREEN */), GetSystemMetrics(78 /* SM_CXVIRTUALSCREEN */), GetSystemMetrics(79 /* SM_CYVIRTUALSCREEN */)); - else - data.crect.setRect(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); } parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : 0; -#ifdef UNICODE QString title; - const TCHAR *ttitle = 0; -#endif - QByteArray title95; int style = WS_CHILD; int exsty = 0; if (window) { - style = GetWindowLongA(window, GWL_STYLE); + style = GetWindowLong(window, GWL_STYLE); if (!style) qErrnoWarning("QWidget::create: GetWindowLong failed"); topLevel = false; // #### needed for some IE plugins?? @@ -367,12 +352,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } if (flags & Qt::WindowTitleHint) { - QT_WA({ - title = q->isWindow() ? qAppName() : q->objectName(); - ttitle = (TCHAR*)title.utf16(); - } , { - title95 = q->isWindow() ? qAppName().toLocal8Bit() : q->objectName().toLatin1(); - }); + title = q->isWindow() ? qAppName() : q->objectName(); } // The Qt::WA_WState_Created flag is checked by translateConfigEvent() in @@ -385,13 +365,13 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO destroyw = data.winid; id = window; setWinId(window); - LONG res = SetWindowLongA(window, GWL_STYLE, style); + LONG res = SetWindowLong(window, GWL_STYLE, style); if (!res) qErrnoWarning("QWidget::create: Failed to set window style"); #ifdef _WIN64 - res = SetWindowLongPtrA( window, GWLP_WNDPROC, (LONG_PTR)QtWndProc ); + res = SetWindowLongPtr( window, GWLP_WNDPROC, (LONG_PTR)QtWndProc ); #else - res = SetWindowLongA( window, GWL_WNDPROC, (LONG)QtWndProc ); + res = SetWindowLong( window, GWL_WNDPROC, (LONG)QtWndProc ); #endif if (!res) qErrnoWarning("QWidget::create: Failed to set window procedure"); @@ -442,16 +422,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } } - QT_WA({ - const TCHAR *cname = (TCHAR*)windowClassName.utf16(); - id = CreateWindowEx(exsty, cname, ttitle, style, - x, y, w, h, - parentw, 0, appinst, 0); - } , { - id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style, - x, y, w, h, - parentw, 0, appinst, 0); - }); + id = CreateWindowEx(exsty, reinterpret_cast<const wchar_t *>(windowClassName.utf16()), + reinterpret_cast<const wchar_t *>(title.utf16()), style, + x, y, w, h, + parentw, NULL, appinst, NULL); if (!id) qErrnoWarning("QWidget::create: Failed to create window"); setWinId(id); @@ -463,16 +437,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO SetWindowPos(id, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); winUpdateIsOpaque(); } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget - QT_WA({ - const TCHAR *cname = (TCHAR*)windowClassName.utf16(); - id = CreateWindowEx(exsty, cname, ttitle, style, - data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), + id = CreateWindowEx(exsty, reinterpret_cast<const wchar_t *>(windowClassName.utf16()), + reinterpret_cast<const wchar_t *>(title.utf16()), style, + data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), parentw, NULL, appinst, NULL); - } , { - id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style, - data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), - parentw, NULL, appinst, NULL); - }); if (!id) qErrnoWarning("QWidget::create: Failed to create window"); SetWindowPos(id, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); @@ -503,9 +471,23 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } } + if (topLevel) { + if (data.window_flags & Qt::CustomizeWindowHint + && data.window_flags & Qt::WindowTitleHint) { + HMENU systemMenu = GetSystemMenu((HWND)q->internalWinId(), FALSE); + if (data.window_flags & Qt::WindowCloseButtonHint) + EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED); + else + EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED); + } + } + q->setAttribute(Qt::WA_WState_Created); // accept move/resize events hd = 0; // no display context + if (q->testAttribute(Qt::WA_AcceptTouchEvents)) + registerTouchWindow(); + if (window) { // got window from outside if (IsWindowVisible(window)) q->setAttribute(Qt::WA_WState_Visible); @@ -546,14 +528,14 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } } -#endif //Q_OS_WINCE +#endif //Q_WS_WINCE void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); if (!isWindow() && parentWidget()) - parentWidget()->d_func()->invalidateBuffer(geometry()); + parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); if (testAttribute(Qt::WA_WState_Created)) { setAttribute(Qt::WA_WState_Created, false); @@ -574,13 +556,17 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) if (destroyWindow && !(windowType() == Qt::Desktop) && internalWinId()) { DestroyWindow(internalWinId()); } -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE if (destroyWindow && (windowType() == Qt::Desktop) && !GetDesktopWindow()) { DestroyWindow(internalWinId()); } #endif - d->setWinId(0); + QT_TRY { + d->setWinId(0); + } QT_CATCH (const std::bad_alloc &) { + // swallow - destructors must not throw + } } } @@ -615,7 +601,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) Q_Q(QWidget); bool wasCreated = q->testAttribute(Qt::WA_WState_Created); if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) - q->parentWidget()->d_func()->invalidateBuffer(q->geometry()); + q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); WId old_winid = data.winid; // hide and reparent our own window away. Otherwise we might get @@ -671,21 +657,11 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) q->setAttribute(Qt::WA_DropSiteRegistered, true); - - if (data.window_flags & Qt::CustomizeWindowHint - && data.window_flags & Qt::WindowTitleHint) { - HMENU systemMenu = GetSystemMenu((HWND)q->internalWinId(), FALSE); - if (data.window_flags & Qt::WindowCloseButtonHint) - EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED); - else - EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED); - } - -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE // Show borderless toplevel windows in tasklist & NavBar if (!parent) { QString txt = q->windowTitle().isEmpty()?qAppName():q->windowTitle(); - SetWindowText(q->internalWinId(), (TCHAR*)txt.utf16()); + SetWindowText(q->internalWinId(), (wchar_t*)txt.utf16()); } #endif invalidateBuffer(q->rect()); @@ -770,11 +746,7 @@ void QWidgetPrivate::setWindowTitle_sys(const QString &caption) return; Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - QT_WA({ - SetWindowText(q->internalWinId(), (TCHAR*)caption.utf16()); - } , { - SetWindowTextA(q->internalWinId(), caption.toLocal8Bit()); - }); + SetWindowText(q->internalWinId(), (wchar_t*)caption.utf16()); } /* @@ -856,11 +828,11 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset) GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), &(x->iconPixmap)); if (x->winIconBig) { - SendMessageA(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall); - SendMessageA(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconBig); + SendMessage(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall); + SendMessage(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconBig); } else { - SendMessageA(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall); - SendMessageA(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconSmall); + SendMessage(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall); + SendMessage(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconSmall); } } @@ -877,17 +849,17 @@ QCursor *qt_grab_cursor() } // The procedure does nothing, but is required for mousegrabbing to work -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE LRESULT CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam) { return CallNextHookEx(journalRec, nCode, wParam, lParam); } -#endif //Q_OS_WINCE +#endif //Q_WS_WINCE /* Works only as long as pointer is inside the application's window, which is good enough for QDockWidget. - Doesn't call SetWindowsHookExA() - this function causes a system-wide + Doesn't call SetWindowsHookEx() - this function causes a system-wide freeze if any other app on the system installs a hook and fails to process events. */ void QWidgetPrivate::grabMouseWhileInWindow() @@ -905,13 +877,13 @@ void QWidgetPrivate::grabMouseWhileInWindow() } } -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE void QWidget::grabMouse() { if (!qt_nograb()) { if (mouseGrb) mouseGrb->releaseMouse(); - journalRec = SetWindowsHookExA(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandleA(0), 0); + journalRec = SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandle(0), 0); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); SetCapture(effectiveWinId()); mouseGrb = this; @@ -924,7 +896,7 @@ void QWidget::grabMouse(const QCursor &cursor) if (!qt_nograb()) { if (mouseGrb) mouseGrb->releaseMouse(); - journalRec = SetWindowsHookExA(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandleA(0), 0); + journalRec = SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandle(0), 0); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); SetCapture(effectiveWinId()); mouseGrbCur = new QCursor(cursor); @@ -982,7 +954,7 @@ void QWidget::activateWindow() SetForegroundWindow(window()->internalWinId()); } -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE void QWidget::setWindowState(Qt::WindowStates newstate) { Q_D(QWidget); @@ -1031,18 +1003,18 @@ void QWidget::setWindowState(Qt::WindowStates newstate) if (newstate & Qt::WindowFullScreen) { if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized)) d->topData()->normalGeometry = geometry(); - d->topData()->savedFlags = GetWindowLongA(internalWinId(), GWL_STYLE); + d->topData()->savedFlags = Qt::WindowFlags(GetWindowLong(internalWinId(), GWL_STYLE)); #ifndef Q_FLATTEN_EXPOSE UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP; #else UINT style = WS_POPUP; #endif - if (d->topData()->savedFlags & WS_SYSMENU) + if (ulong(d->topData()->savedFlags) & WS_SYSMENU) style |= WS_SYSMENU; if (isVisible()) style |= WS_VISIBLE; - SetWindowLongA(internalWinId(), GWL_STYLE, style); - QRect r = qApp->desktop()->screenGeometry(this); + SetWindowLong(internalWinId(), GWL_STYLE, style); + QRect r = QApplication::desktop()->screenGeometry(this); UINT swpf = SWP_FRAMECHANGED; if (newstate & Qt::WindowActive) swpf |= SWP_NOACTIVATE; @@ -1053,7 +1025,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) UINT style = d->topData()->savedFlags; if (isVisible()) style |= WS_VISIBLE; - SetWindowLongA(internalWinId(), GWL_STYLE, style); + SetWindowLong(internalWinId(), GWL_STYLE, style); UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE; if (newstate & Qt::WindowActive) @@ -1084,7 +1056,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) QWindowStateChangeEvent e(oldstate); QApplication::sendEvent(this, &e); } -#endif //Q_OS_WINCE +#endif //Q_WS_WINCE /* @@ -1097,7 +1069,7 @@ void QWidgetPrivate::hide_sys() Q_Q(QWidget); deactivateWidgetCleanup(); Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE if (!qt_wince_is_mobile() && q->isFullScreen()) { HWND handle = FindWindow(L"HHTaskBar", L""); if (handle) { @@ -1126,7 +1098,7 @@ void QWidgetPrivate::hide_sys() \internal Platform-specific part of QWidget::show(). */ -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE void QWidgetPrivate::show_sys() { Q_Q(QWidget); @@ -1192,9 +1164,11 @@ void QWidgetPrivate::show_sys() data.window_state |= Qt::WindowMaximized; } + winSetupGestures(); + invalidateBuffer(q->rect()); } -#endif //Q_OS_WINCE +#endif //Q_WS_WINCE void QWidgetPrivate::setFocus_sys() { @@ -1240,7 +1214,7 @@ void QWidgetPrivate::stackUnder_sys(QWidget* w) (In all comments below: s/X/Windows/g) */ -void QWidgetPrivate::setWSGeometry(bool dontShow) +void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &) { Q_Q(QWidget); Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); @@ -1398,7 +1372,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) UINT style = top->savedFlags; if (q->isVisible()) style |= WS_VISIBLE; - SetWindowLongA(q->internalWinId(), GWL_STYLE, style); + SetWindowLong(q->internalWinId(), GWL_STYLE, style); UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE; if (data.window_state & Qt::WindowActive) @@ -1413,7 +1387,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false; const bool isTranslucentWindow = !isOpaque && ptrUpdateLayeredWindowIndirect && (data.window_flags & Qt::FramelessWindowHint) - && GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED; + && GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED; if (q->testAttribute(Qt::WA_WState_ConfigPending)) { // processing config event if (q->internalWinId()) @@ -1452,7 +1426,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) show_sys(); } else if (!q->testAttribute(Qt::WA_DontShowOnScreen)) { q->setAttribute(Qt::WA_OutsideWSRange, false); -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE // If the window is hidden and in maximized state or minimized, instead of moving the // window, set the normal position of the window. WINDOWPLACEMENT wndpl; @@ -1573,7 +1547,7 @@ bool QWidgetPrivate::shouldShowMaximizeButton() void QWidgetPrivate::winUpdateIsOpaque() { -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE Q_Q(QWidget); if (!q->isWindow() || !q->testAttribute(Qt::WA_TranslucentBackground)) @@ -1583,26 +1557,26 @@ void QWidgetPrivate::winUpdateIsOpaque() return; if (!isOpaque && ptrUpdateLayeredWindowIndirect) { - SetWindowLongA(q->internalWinId(), GWL_EXSTYLE, - GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) | Q_WS_EX_LAYERED); + SetWindowLong(q->internalWinId(), GWL_EXSTYLE, + GetWindowLong(q->internalWinId(), GWL_EXSTYLE) | Q_WS_EX_LAYERED); } else { - SetWindowLongA(q->internalWinId(), GWL_EXSTYLE, - GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) & ~Q_WS_EX_LAYERED); + SetWindowLong(q->internalWinId(), GWL_EXSTYLE, + GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & ~Q_WS_EX_LAYERED); } #endif } void QWidgetPrivate::setConstraints_sys() { -#ifndef Q_OS_WINCE_WM +#ifndef Q_WS_WINCE_WM Q_Q(QWidget); if (q->isWindow() && q->testAttribute(Qt::WA_WState_Created)) { - int style = GetWindowLongA(q->internalWinId(), GWL_STYLE); + int style = GetWindowLong(q->internalWinId(), GWL_STYLE); if (shouldShowMaximizeButton()) style |= WS_MAXIMIZEBOX; else style &= ~WS_MAXIMIZEBOX; - SetWindowLongA(q->internalWinId(), GWL_STYLE, style); + SetWindowLong(q->internalWinId(), GWL_STYLE, style); } #endif } @@ -1712,28 +1686,24 @@ int QWidget::metric(PaintDeviceMetric m) const return val; } -#ifndef Q_OS_WINCE void QWidgetPrivate::createSysExtra() { #ifndef QT_NO_DRAGANDDROP extra->dropTarget = 0; #endif -#ifndef QT_NO_DIRECT3D - extra->had_auto_fill_bg = 0; - extra->had_paint_on_screen = 0; - extra->had_no_system_bg = 0; -#endif } +#ifndef Q_WS_WINCE void QWidgetPrivate::deleteSysExtra() { } -#endif //Q_OS_WINCE +#endif //Q_WS_WINCE void QWidgetPrivate::createTLSysExtra() { - extra->topextra->winIconSmall = 0; + extra->topextra->savedFlags = 0; extra->topextra->winIconBig = 0; + extra->topextra->winIconSmall = 0; } void QWidgetPrivate::deleteTLSysExtra() @@ -1857,7 +1827,8 @@ void QWidgetPrivate::setMask_sys(const QRegion ®ion) OffsetRgn(wr, offset.x(), offset.y()); Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - SetWindowRgn(data.winid, wr, true); + if (!SetWindowRgn(data.winid, wr, true)) + DeleteObject(wr); } void QWidgetPrivate::updateFrameStrut() @@ -1875,11 +1846,9 @@ void QWidgetPrivate::updateFrameStrut() RECT rect = {0,0,0,0}; QTLWExtra *top = topData(); - uint exstyle = QT_WA_INLINE(GetWindowLongW(q->internalWinId(), GWL_EXSTYLE), - GetWindowLongA(q->internalWinId(), GWL_EXSTYLE)); - uint style = QT_WA_INLINE(GetWindowLongW(q->internalWinId(), GWL_STYLE), - GetWindowLongA(q->internalWinId(), GWL_STYLE)); -#ifndef Q_OS_WINCE + uint exstyle = GetWindowLong(q->internalWinId(), GWL_EXSTYLE); + uint style = GetWindowLong(q->internalWinId(), GWL_STYLE); +#ifndef Q_WS_WINCE if (AdjustWindowRectEx(&rect, style & ~(WS_OVERLAPPED), FALSE, exstyle)) { #else if (AdjustWindowRectEx(&rect, style, FALSE, exstyle)) { @@ -1889,16 +1858,15 @@ void QWidgetPrivate::updateFrameStrut() } } -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE void QWidgetPrivate::setWindowOpacity_sys(qreal level) { Q_Q(QWidget); - if (!isOpaque && ptrUpdateLayeredWindowIndirect && (data.window_flags & Qt::FramelessWindowHint)) { - if (GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED) { - Q_BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * level), Q_AC_SRC_ALPHA}; - Q_UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, NULL, NULL, NULL, NULL, 0, &blend, Q_ULW_ALPHA, NULL}; - (*ptrUpdateLayeredWindowIndirect)(q->internalWinId(), &info); + if (!isOpaque && ptrUpdateLayeredWindow && (data.window_flags & Qt::FramelessWindowHint)) { + if (GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED) { + BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * level), AC_SRC_ALPHA}; + ptrUpdateLayeredWindow(q->internalWinId(), NULL, NULL, NULL, NULL, NULL, 0, &blend, Q_ULW_ALPHA); } return; } @@ -1914,17 +1882,17 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level) if (!ptrSetLayeredWindowAttributes) return; - int wl = GetWindowLongA(q->internalWinId(), GWL_EXSTYLE); + int wl = GetWindowLong(q->internalWinId(), GWL_EXSTYLE); if (level != 1.0) { if ((wl&Q_WS_EX_LAYERED) == 0) - SetWindowLongA(q->internalWinId(), GWL_EXSTYLE, wl|Q_WS_EX_LAYERED); + SetWindowLong(q->internalWinId(), GWL_EXSTYLE, wl | Q_WS_EX_LAYERED); } else if (wl&Q_WS_EX_LAYERED) { - SetWindowLongA(q->internalWinId(), GWL_EXSTYLE, wl & ~Q_WS_EX_LAYERED); + SetWindowLong(q->internalWinId(), GWL_EXSTYLE, wl & ~Q_WS_EX_LAYERED); } - (*ptrSetLayeredWindowAttributes)(q->internalWinId(), 0, (int)(level * 255), Q_LWA_ALPHA); + ptrSetLayeredWindowAttributes(q->internalWinId(), 0, (int)(level * 255), Q_LWA_ALPHA); } -#endif //Q_OS_WINCE +#endif //Q_WS_WINCE // class QGlobalRasterPaintEngine: public QRasterPaintEngine // { @@ -1933,22 +1901,6 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level) // }; // Q_GLOBAL_STATIC(QGlobalRasterPaintEngine, globalRasterPaintEngine) -#ifndef QT_NO_DIRECT3D -static void cleanup_d3d_engine(); -Q_GLOBAL_STATIC_WITH_INITIALIZER(QDirect3DPaintEngine, _qt_d3dEngine, - { - qAddPostRoutine(cleanup_d3d_engine); - }) -static void cleanup_d3d_engine() -{ - _qt_d3dEngine()->cleanup(); -} -QDirect3DPaintEngine* qt_d3dEngine() -{ - return _qt_d3dEngine(); -} -#endif - #ifndef QT_NO_DIRECTDRAW static uchar *qt_primary_surface_bits; @@ -2004,8 +1956,8 @@ public: // in QOnScreenRasterPaintEngine() : QRasterPaintEngine(new QImage(qt_primary_surface_bits, - qApp->desktop()->width(), - qApp->desktop()->height(), + QApplication::desktop()->width(), + QApplication::desktop()->height(), qt_primary_surface_stride, qt_primary_surface_format)) { @@ -2061,19 +2013,6 @@ void qt_win_initialize_directdraw() { } QPaintEngine *QWidget::paintEngine() const { -#ifndef QT_NO_DIRECT3D - if ((qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault) - || testAttribute(Qt::WA_MSWindowsUseDirect3D)) - && qt_d3dEngine()->hasDirect3DSupport()) - { - QDirect3DPaintEngine *engine = qt_d3dEngine(); - if (qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault)) - engine->setFlushOnEnd(false); - else - engine->setFlushOnEnd(true); - return engine; - } -#endif #ifndef QT_NO_DIRECTDRAW QOnScreenRasterPaintEngine *pe = onScreenPaintEngine(); pe->widget = this; @@ -2102,13 +2041,6 @@ QPaintEngine *QWidget::paintEngine() const QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys() { Q_Q(QWidget); -#ifndef QT_NO_DIRECT3D - extern QDirect3DPaintEngine *qt_d3dEngine(); - if (qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault) && (q->windowOpacity() == 1.0f) - && qt_d3dEngine()->hasDirect3DSupport()) { - return new QD3DWindowSurface(q); - } -#endif return new QRasterWindowSurface(q); } @@ -2116,11 +2048,80 @@ void QWidgetPrivate::setModal_sys() { } +void QWidgetPrivate::registerTouchWindow() +{ + Q_Q(QWidget); + + // enable WM_TOUCH* messages on our window + if (q->testAttribute(Qt::WA_WState_Created) + && QApplicationPrivate::RegisterTouchWindow + && q->windowType() != Qt::Desktop) + QApplicationPrivate::RegisterTouchWindow(q->effectiveWinId(), 0); +} + +void QWidgetPrivate::winSetupGestures() +{ + Q_Q(QWidget); + if (!q || !q->isVisible()) + return; + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); + QApplicationPrivate::WidgetStandardGesturesMap::const_iterator it = + qAppPriv->widgetGestures.find(q); + if (it == qAppPriv->widgetGestures.end()) + return; + const QStandardGestures &gestures = it.value(); + WId winid = q->effectiveWinId(); + + bool needh = false; + bool needv = false; + bool singleFingerPanEnabled = false; + + if (QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea*>(q->parent())) { + QScrollBar *hbar = asa->horizontalScrollBar(); + QScrollBar *vbar = asa->verticalScrollBar(); + Qt::ScrollBarPolicy hbarpolicy = asa->horizontalScrollBarPolicy(); + Qt::ScrollBarPolicy vbarpolicy = asa->verticalScrollBarPolicy(); + needh = (hbarpolicy == Qt::ScrollBarAlwaysOn || + (hbarpolicy == Qt::ScrollBarAsNeeded && hbar->minimum() < hbar->maximum())); + needv = (vbarpolicy == Qt::ScrollBarAlwaysOn || + (vbarpolicy == Qt::ScrollBarAsNeeded && vbar->minimum() < vbar->maximum())); + singleFingerPanEnabled = asa->d_func()->singleFingerPanEnabled; + } + if (winid && qAppPriv->SetGestureConfig) { + GESTURECONFIG gc[3]; + memset(gc, 0, sizeof(gc)); + gc[0].dwID = GID_PAN; + if (gestures.pan) { + gc[0].dwWant = GC_PAN; + if (needv && singleFingerPanEnabled) + gc[0].dwWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY; + else + gc[0].dwBlock |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY; + if (needh && singleFingerPanEnabled) + gc[0].dwWant |= GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY; + else + gc[0].dwBlock |= GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY; + } else { + gc[0].dwBlock = GC_PAN; + } + gc[1].dwID = GID_ZOOM; + if (gestures.pinch) + gc[1].dwWant = GC_ZOOM; + else + gc[1].dwBlock = GC_ZOOM; + gc[2].dwID = GID_ROTATE; + if (gestures.pinch) + gc[2].dwWant = GC_ROTATE; + else + gc[2].dwBlock = GC_ROTATE; + qAppPriv->SetGestureConfig(winid, 0, sizeof(gc)/sizeof(gc[0]), gc, sizeof(gc[0])); + } +} QT_END_NAMESPACE -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE # include "qwidget_wince.cpp" #endif diff --git a/src/gui/kernel/qwidget_wince.cpp b/src/gui/kernel/qwidget_wince.cpp index 20d434b..878ed5b 100644 --- a/src/gui/kernel/qwidget_wince.cpp +++ b/src/gui/kernel/qwidget_wince.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE #include "qguifunctions_wince.h" @@ -188,11 +188,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : 0; -#ifdef UNICODE QString title; - const TCHAR *ttitle = 0; -#endif - QByteArray title95; int style = WS_CHILD; int exsty = WS_EX_NOPARENTNOTIFY; @@ -211,7 +207,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO style |= WS_SYSMENU; if (flags & Qt::WindowContextHelpButtonHint) exsty |= WS_EX_CONTEXTHELP; -#ifndef Q_OS_WINCE_WM +#ifndef Q_WS_WINCE_WM if (flags & Qt::WindowMinimizeButtonHint) style |= WS_MINIMIZEBOX; if (shouldShowMaximizeButton()) @@ -236,12 +232,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } if (flags & Qt::WindowTitleHint) { - QT_WA({ - title = q->isWindow() ? qAppName() : q->objectName(); - ttitle = (TCHAR*)title.utf16(); - } , { - title95 = q->isWindow() ? qAppName().toLocal8Bit() : q->objectName().toLatin1(); - }); + title = q->isWindow() ? qAppName() : q->objectName(); } // The Qt::WA_WState_Created flag is checked by translateConfigEvent() in @@ -254,11 +245,11 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO destroyw = data.winid; id = window; setWinId(window); - LONG res = SetWindowLongA(window, GWL_STYLE, style); + LONG res = SetWindowLong(window, GWL_STYLE, style); if (!res) qErrnoWarning("QWidget::create: Failed to set window style"); - res = SetWindowLongA( window, GWL_WNDPROC, (LONG)QtWndProc ); + res = SetWindowLong( window, GWL_WNDPROC, (LONG)QtWndProc ); if (!res) qErrnoWarning("QWidget::create: Failed to set window procedure"); @@ -267,10 +258,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO if (!id) { //Create a dummy desktop RECT r; SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); - const TCHAR *cname = reinterpret_cast<const TCHAR *> (windowClassName.utf16()); - id = CreateWindow(cname, ttitle, style, - r.left, r.top, r.right - r.left, r.bottom - r.top, - 0, 0, appinst, 0); + id = CreateWindow(reinterpret_cast<const wchar_t *>(windowClassName.utf16()), + reinterpret_cast<const wchar_t *>(title.utf16()), style, + r.left, r.top, r.right - r.left, r.bottom - r.top, + 0, 0, appinst, 0); } setWinId(id); } else if (topLevel) { // create top-level widget @@ -303,8 +294,8 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } } - const TCHAR *cname = reinterpret_cast<const TCHAR *> (windowClassName.utf16()); - id = CreateWindowEx(exsty, cname, ttitle, style, + id = CreateWindowEx(exsty, reinterpret_cast<const wchar_t *>(windowClassName.utf16()), + reinterpret_cast<const wchar_t *>(title.utf16()), style, x, y, w, h, 0, 0, appinst, 0); @@ -314,16 +305,9 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip)) SetWindowPos(id, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget - QT_WA({ - const TCHAR *cname = (TCHAR*)windowClassName.utf16(); - id = CreateWindowEx(exsty, cname, ttitle, style, - data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), - parentw, NULL, appinst, NULL); - } , { - id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style, - data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), + id = CreateWindowEx(exsty, (wchar_t*)windowClassName.utf16(), (wchar_t*)title.utf16(), style, + data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), parentw, NULL, appinst, NULL); - }); if (!id) qErrnoWarning("QWidget::create: Failed to create window"); SetWindowPos(id, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); @@ -414,7 +398,7 @@ void QWidgetPrivate::show_sys() { int sm = SW_SHOW; bool fakedMaximize = false; if (q->isWindow()) { -#ifndef Q_OS_WINCE_WM +#ifndef Q_WS_WINCE_WM if (q->isMinimized()) { sm = SW_SHOWMINIMIZED; } else if (q->isMaximized()) { @@ -450,7 +434,7 @@ void QWidgetPrivate::show_sys() { if (q->isMaximized() && q->isWindow()) qt_wince_maximize(q); -#ifndef Q_OS_WINCE_WM +#ifndef Q_WS_WINCE_WM if (!qt_wince_is_mobile() && q->isFullScreen()) { HWND handle = FindWindow(L"HHTaskBar", L""); if (handle) { @@ -510,7 +494,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) } if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) { if (!(newstate & Qt::WindowMaximized)) { - int style = GetWindowLongW(internalWinId(), GWL_STYLE) | WS_BORDER | WS_POPUP | WS_CAPTION; + int style = GetWindowLong(internalWinId(), GWL_STYLE) | WS_BORDER | WS_POPUP | WS_CAPTION; SetWindowLong(internalWinId(), GWL_STYLE, style); SetWindowLong(internalWinId(), GWL_EXSTYLE, GetWindowLong (internalWinId(), GWL_EXSTYLE) & ~ WS_EX_NODRAG); } @@ -535,11 +519,11 @@ void QWidget::setWindowState(Qt::WindowStates newstate) if (newstate & Qt::WindowFullScreen) { if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized)) d->topData()->normalGeometry = geometry(); - d->topData()->savedFlags = GetWindowLongA(internalWinId(), GWL_STYLE); + d->topData()->savedFlags = (Qt::WindowFlags)GetWindowLong(internalWinId(), GWL_STYLE); UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP; if (isVisible()) style |= WS_VISIBLE; - SetWindowLongA(internalWinId(), GWL_STYLE, style); + SetWindowLong(internalWinId(), GWL_STYLE, style); QRect r = qApp->desktop()->screenGeometry(this); UINT swpf = SWP_FRAMECHANGED; if (newstate & Qt::WindowActive) @@ -550,7 +534,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) UINT style = d->topData()->savedFlags; if (isVisible()) style |= WS_VISIBLE; - SetWindowLongA(internalWinId(), GWL_STYLE, style); + SetWindowLong(internalWinId(), GWL_STYLE, style); UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE; if (newstate & Qt::WindowActive) swpf |= SWP_NOACTIVATE; @@ -583,7 +567,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) } if ((newstate & Qt::WindowMaximized) && !(newstate & Qt::WindowFullScreen)) { QRect r = d->topData()->normalGeometry; -#ifdef Q_OS_WINCE_WM +#ifdef Q_WS_WINCE_WM if (!inherits("QDialog") && !inherits("QMdiArea") && !isVisible()) { d->data.crect.setRect(0, 0, -1, -1); } @@ -598,13 +582,6 @@ void QWidget::setWindowState(Qt::WindowStates newstate) QApplication::sendEvent(this, &e); } - -void QWidgetPrivate::createSysExtra() { -#ifndef QT_NO_DRAGANDDROP - extra->dropTarget = 0; -#endif -} - void QWidgetPrivate::deleteSysExtra() { Q_Q(QWidget); @@ -704,4 +681,4 @@ void QWidget::show() QT_END_NAMESPACE -#endif Q_OS_WINCE +#endif // Q_WS_WINCE diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index aae1355..7bb7933 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -512,6 +512,13 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO dialog = popup = false; // force these flags off data.crect.setRect(0, 0, sw, sh); } else if (topLevel && !q->testAttribute(Qt::WA_Resized)) { + QDesktopWidget *desktopWidget = qApp->desktop(); + if (desktopWidget->isVirtualDesktop()) { + QRect r = desktopWidget->screenGeometry(); + sw = r.width(); + sh = r.height(); + } + int width = sw / 2; int height = 4 * sh / 10; if (extra) { @@ -754,11 +761,14 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO qBound(1, data.crect.width(), XCOORD_MAX), qBound(1, data.crect.height(), XCOORD_MAX)); XStoreName(dpy, id, appName.data()); - Atom protocols[4]; + Atom protocols[5]; int n = 0; protocols[n++] = ATOM(WM_DELETE_WINDOW); // support del window protocol protocols[n++] = ATOM(WM_TAKE_FOCUS); // support take focus window protocol protocols[n++] = ATOM(_NET_WM_PING); // support _NET_WM_PING protocol +#ifndef QT_NO_XSYNC + protocols[n++] = ATOM(_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol +#endif // QT_NO_XSYNC if (flags & Qt::WindowContextHelpButtonHint) protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP); XSetWMProtocols(dpy, id, protocols, n); @@ -893,24 +903,75 @@ void QWidgetPrivate::x11UpdateIsOpaque() int screen = xinfo.screen(); if (topLevel && X11->use_xrender && X11->argbVisuals[screen] && xinfo.depth() != 32) { - // recreate widget - QPoint pos = q->pos(); - bool visible = q->isVisible(); - if (visible) - q->hide(); - q->setParent(q->parentWidget(), q->windowFlags()); - q->move(pos); - if (visible) - q->show(); + + if (q->inherits("QGLWidget")) { + // We send QGLWidgets a ParentChange event which causes them to + // recreate their GL context, which in turn causes them to choose + // their visual again. Now that WA_TranslucentBackground is set, + // QGLContext::chooseVisual will select an ARGB visual. + QEvent e(QEvent::ParentChange); + QApplication::sendEvent(q, &e); + } + else { + // For regular widgets, reparent them with their parent which + // also triggers a recreation of the native window + QPoint pos = q->pos(); + bool visible = q->isVisible(); + if (visible) + q->hide(); + + q->setParent(q->parentWidget(), q->windowFlags()); + q->move(pos); + if (visible) + q->show(); + } } #endif } +/* + Returns true if the background is inherited; otherwise returns + false. + + Mainly used in the paintOnScreen case. +*/ +bool QWidgetPrivate::isBackgroundInherited() const +{ + Q_Q(const QWidget); + + // windows do not inherit their background + if (q->isWindow() || q->windowType() == Qt::SubWindow) + return false; + + if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent)) + return false; + + const QPalette &pal = q->palette(); + QPalette::ColorRole bg = q->backgroundRole(); + QBrush brush = pal.brush(bg); + + // non opaque brushes leaves us no choice, we must inherit + if (!q->autoFillBackground() || !brush.isOpaque()) + return true; + + if (brush.style() == Qt::SolidPattern) { + // the background is just a solid color. If there is no + // propagated contents, then we claim as performance + // optimization that it was not inheritet. This is the normal + // case in standard Windows or Motif style. + const QWidget *w = q->parentWidget(); + if (!w->d_func()->isBackgroundInherited()) + return false; + } + + return true; +} + void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); if (!isWindow() && parentWidget()) - parentWidget()->d_func()->invalidateBuffer(geometry()); + parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); if (testAttribute(Qt::WA_WState_Created)) { setAttribute(Qt::WA_WState_Created, false); @@ -954,7 +1015,11 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) if (destroyWindow) qt_XDestroyWindow(this, X11->display, data->winid); } - d->setWinId(0); + QT_TRY { + d->setWinId(0); + } QT_CATCH (const std::bad_alloc &) { + // swallow - destructors must not throw + } extern void qPRCleanup(QWidget *widget); // from qapplication_x11.cpp if (testAttribute(Qt::WA_WState_Reparented)) @@ -989,7 +1054,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) QTLWExtra *topData = maybeTopData(); bool wasCreated = q->testAttribute(Qt::WA_WState_Created); if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) - q->parentWidget()->d_func()->invalidateBuffer(q->geometry()); + q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); extern void qPRCreate(const QWidget *, Window); #ifndef QT_NO_CURSOR QCursor oldcurs; @@ -1215,7 +1280,7 @@ void QWidgetPrivate::updateSystemBackground() else if (brush.style() == Qt::TexturePattern) { extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), - static_cast<QX11PixmapData*>(qt_toX11Pixmap(brush.texture()).data)->x11ConvertToDefaultDepth()); + static_cast<QX11PixmapData*>(qt_toX11Pixmap(brush.texture()).data.data())->x11ConvertToDefaultDepth()); } else XSetWindowBackground(X11->display, q->internalWinId(), QColormap::instance(xinfo.screen()).pixel(brush.color())); @@ -1308,17 +1373,10 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset) // already been set return; - XWMHints *h = 0; - if (q->internalWinId()) - h = XGetWMHints(X11->display, q->internalWinId()); - XWMHints wm_hints; - if (!h) { - memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy - h = &wm_hints; - } - // preparing images to set the _NET_WM_ICON property QIcon icon = q->windowIcon(); + QVector<long> icon_data; + Qt::HANDLE pixmap_handle = 0; if (!icon.isNull()) { QList<QSize> availableSizes = icon.availableSizes(); if(availableSizes.isEmpty()) { @@ -1328,7 +1386,6 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset) availableSizes.push_back(QSize(64,64)); availableSizes.push_back(QSize(128,128)); } - QVector<long> icon_data; for(int i = 0; i < availableSizes.size(); ++i) { QSize size = availableSizes.at(i); QPixmap pixmap = icon.pixmap(size); @@ -1350,11 +1407,6 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset) } } if (!icon_data.isEmpty()) { - if (q->internalWinId()) { - XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON), XA_CARDINAL, 32, - PropModeReplace, (unsigned char *) icon_data.data(), - icon_data.size()); - } extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); /* if the app is running on an unknown desktop, or it is not @@ -1368,22 +1420,44 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset) // unknown DE or non-default visual/colormap, use 1bpp bitmap if (!forceReset || !topData->iconPixmap) topData->iconPixmap = new QBitmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64)))); - h->icon_pixmap = topData->iconPixmap->handle(); + pixmap_handle = topData->iconPixmap->handle(); } else { // default depth, use a normal pixmap (even though this // violates the ICCCM), since this works on all DEs known to Qt if (!forceReset || !topData->iconPixmap) topData->iconPixmap = new QPixmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64)))); - h->icon_pixmap = static_cast<QX11PixmapData*>(topData->iconPixmap->data)->x11ConvertToDefaultDepth(); + pixmap_handle = static_cast<QX11PixmapData*>(topData->iconPixmap->data.data())->x11ConvertToDefaultDepth(); } - h->flags |= IconPixmapHint; - } else { - h->flags &= ~(IconPixmapHint | IconMaskHint); } } - if (q->internalWinId()) - XSetWMHints(X11->display, q->internalWinId(), h); + if (!q->internalWinId()) + return; + + if (!icon_data.isEmpty()) { + XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON), XA_CARDINAL, 32, + PropModeReplace, (unsigned char *) icon_data.data(), + icon_data.size()); + } else { + XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON)); + } + + XWMHints *h = XGetWMHints(X11->display, q->internalWinId()); + XWMHints wm_hints; + if (!h) { + memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy + h = &wm_hints; + } + + if (pixmap_handle) { + h->icon_pixmap = pixmap_handle; + h->flags |= IconPixmapHint; + } else { + h->icon_pixmap = 0; + h->flags &= ~(IconPixmapHint | IconMaskHint); + } + + XSetWMHints(X11->display, q->internalWinId(), h); if (h != &wm_hints) XFree((char *)h); } @@ -1817,6 +1891,23 @@ void QWidgetPrivate::show_sys() if (setUserTime) qt_net_update_user_time(q, userTime); +#ifndef QT_NO_XSYNC + if (!topData()->syncUpdateCounter) { + XSyncValue value; + XSyncIntToValue(&value, 0); + topData()->syncUpdateCounter = XSyncCreateCounter(X11->display, value); + + XChangeProperty(X11->display, q->internalWinId(), + ATOM(_NET_WM_SYNC_REQUEST_COUNTER), + XA_CARDINAL, + 32, PropModeReplace, + (uchar *) &topData()->syncUpdateCounter, 1); + + topData()->newCounterValueHi = 0; + topData()->newCounterValueLo = 0; + } +#endif + if (!topData()->embedded && (topData()->validWMState || topData()->waitingForMapNotify) && !q->isMinimized()) { @@ -2151,7 +2242,7 @@ static void do_size_hints(QWidget* widget, QWExtra *x) parentWRect is the geometry of the parent's X rect, measured in parent's coord sys */ -void QWidgetPrivate::setWSGeometry(bool dontShow) +void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &) { Q_Q(QWidget); Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); @@ -2611,8 +2702,8 @@ int QWidget::metric(PaintDeviceMetric m) const void QWidgetPrivate::createSysExtra() { - extra->xDndProxy = 0; extra->compress_events = true; + extra->xDndProxy = 0; } void QWidgetPrivate::deleteSysExtra() @@ -2621,9 +2712,18 @@ void QWidgetPrivate::deleteSysExtra() void QWidgetPrivate::createTLSysExtra() { + extra->topextra->spont_unmapped = 0; + extra->topextra->dnd = 0; extra->topextra->validWMState = 0; extra->topextra->waitingForMapNotify = 0; + extra->topextra->parentWinId = 0; extra->topextra->userTimeWindow = 0; +#ifndef QT_NO_XSYNC + extra->topextra->syncUpdateCounter = 0; + extra->topextra->syncRequestTimestamp = 0; + extra->topextra->newCounterValueHi = 0; + extra->topextra->newCounterValueLo = 0; +#endif } void QWidgetPrivate::deleteTLSysExtra() diff --git a/src/gui/kernel/qwidgetaction.cpp b/src/gui/kernel/qwidgetaction.cpp index 5598413..cf314a7 100644 --- a/src/gui/kernel/qwidgetaction.cpp +++ b/src/gui/kernel/qwidgetaction.cpp @@ -54,6 +54,8 @@ QT_BEGIN_NAMESPACE for inserting custom widgets into action based containers, such as toolbars. + \ingroup mainwindow-classes + Most actions in an application are represented as items in menus or buttons in toolbars. However sometimes more complex widgets are necessary. For example a zoom action in a word processor may be @@ -100,9 +102,6 @@ QT_BEGIN_NAMESPACE DirectConnection. \endlist - \ingroup application - \mainclass - \sa QAction, QActionGroup, QWidget */ @@ -228,8 +227,8 @@ bool QWidgetAction::event(QEvent *event) if (event->type() == QEvent::ActionChanged) { if (d->defaultWidget) d->defaultWidget->setEnabled(isEnabled()); - foreach (QWidget *w, d->createdWidgets) - w->setEnabled(isEnabled()); + for (int i = 0; i < d->createdWidgets.count(); ++i) + d->createdWidgets.at(i)->setEnabled(isEnabled()); } return QAction::event(event); } diff --git a/src/gui/kernel/qwindowdefs.h b/src/gui/kernel/qwindowdefs.h index e3e0cff..da3425d 100644 --- a/src/gui/kernel/qwindowdefs.h +++ b/src/gui/kernel/qwindowdefs.h @@ -131,6 +131,11 @@ QT_END_HEADER #endif // Q_WS_QWS +#if defined(Q_OS_SYMBIAN) +class CCoeControl; +typedef CCoeControl * WId; +#endif // Q_OS_SYMBIAN + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE diff --git a/src/gui/kernel/qwindowdefs_win.h b/src/gui/kernel/qwindowdefs_win.h index eb99020..aab9cf5 100644 --- a/src/gui/kernel/qwindowdefs_win.h +++ b/src/gui/kernel/qwindowdefs_win.h @@ -122,7 +122,7 @@ QT_BEGIN_NAMESPACE Q_CORE_EXPORT HINSTANCE qWinAppInst(); Q_CORE_EXPORT HINSTANCE qWinAppPrevInst(); -Q_GUI_EXPORT int qWinAppCmdShow(); +Q_CORE_EXPORT int qWinAppCmdShow(); Q_GUI_EXPORT HDC qt_win_display_dc(); QT_END_NAMESPACE diff --git a/src/gui/kernel/qx11embed_x11.cpp b/src/gui/kernel/qx11embed_x11.cpp index d654386..8e2eb1e 100644 --- a/src/gui/kernel/qx11embed_x11.cpp +++ b/src/gui/kernel/qx11embed_x11.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include "qplatformdefs.h" #include "qx11embed_x11.h" #include <qapplication.h> #include <qevent.h> @@ -826,7 +827,7 @@ bool QX11EmbedWidget::x11Event(XEvent *event) &actual_format_return, &nitems_return, &bytes_after_return, &prop_return) == Success) { if (nitems_return > 1) { - if (((int * )prop_return)[1] & XEMBED_MAPPED) { + if (((long * )prop_return)[1] & XEMBED_MAPPED) { XMapWindow(x11Info().display(), internalWinId()); } else { XUnmapWindow(x11Info().display(), internalWinId()); @@ -1297,9 +1298,6 @@ bool QX11EmbedContainer::eventFilter(QObject *o, QEvent *event) // focus is set to our focus proxy. We want to intercept all // keypresses. if (o == window() && d->client) { - if (!d->isEmbedded() && d->activeContainer == this) - d->moveInputToProxy(); - if (d->clientIsXEmbed) { sendXEmbedMessage(d->client, x11Info().display(), XEMBED_WINDOW_ACTIVATE); } else { @@ -1307,6 +1305,8 @@ bool QX11EmbedContainer::eventFilter(QObject *o, QEvent *event) if (hasFocus()) XSetInputFocus(x11Info().display(), d->client, XRevertToParent, x11Time()); } + if (!d->isEmbedded()) + d->moveInputToProxy(); } break; case QEvent::WindowDeactivate: @@ -1671,9 +1671,9 @@ void QX11EmbedContainerPrivate::acceptClient(WId window) // Clients with the _XEMBED_INFO property are XEMBED clients. clientIsXEmbed = true; - unsigned int *p = (unsigned int *)prop_return; + long *p = (long *)prop_return; if (nitems_return >= 2) - clientversion = p[0]; + clientversion = (unsigned int)p[0]; } XFree(prop_return); @@ -1729,10 +1729,10 @@ void QX11EmbedContainerPrivate::acceptClient(WId window) checkGrab(); if (q->hasFocus()) { XSetInputFocus(q->x11Info().display(), client, XRevertToParent, x11Time()); - } else { - if (!isEmbedded()) - moveInputToProxy(); } + } else { + if (!isEmbedded()) + moveInputToProxy(); } emit q->clientIsEmbedded(); @@ -1749,11 +1749,9 @@ void QX11EmbedContainerPrivate::acceptClient(WId window) void QX11EmbedContainerPrivate::moveInputToProxy() { Q_Q(QX11EmbedContainer); - WId focus; - int revert_to; - XGetInputFocus(q->x11Info().display(), &focus, &revert_to); - if (focus != focusProxy->internalWinId()) - XSetInputFocus(q->x11Info().display(), focusProxy->internalWinId(), XRevertToParent, x11Time()); + // Following Owen Taylor's advice from the XEmbed specification to + // always use CurrentTime when no explicit user action is involved. + XSetInputFocus(q->x11Info().display(), focusProxy->internalWinId(), XRevertToParent, CurrentTime); } /*! \internal diff --git a/src/gui/kernel/qx11info_x11.cpp b/src/gui/kernel/qx11info_x11.cpp index 28a327d..87c16ef 100644 --- a/src/gui/kernel/qx11info_x11.cpp +++ b/src/gui/kernel/qx11info_x11.cpp @@ -179,6 +179,7 @@ QX11InfoData* QX11Info::getX11Data(bool def) const QX11InfoData* res = 0; if (def) { res = new QX11InfoData; + res->ref = 0; res->screen = appScreen(); res->depth = appDepth(); res->cells = appCells(); @@ -189,8 +190,8 @@ QX11InfoData* QX11Info::getX11Data(bool def) const } else if (x11data) { res = new QX11InfoData; *res = *x11data; + res->ref = 0; } - res->ref = 0; return res; } diff --git a/src/gui/kernel/symbian.pri b/src/gui/kernel/symbian.pri new file mode 100644 index 0000000..d267a53 --- /dev/null +++ b/src/gui/kernel/symbian.pri @@ -0,0 +1,3 @@ +symbian { + contains(QT_CONFIG, s60): LIBS+= $$QMAKE_LIBS_S60 +} diff --git a/src/gui/kernel/x11.pri b/src/gui/kernel/x11.pri index ac40f69..82de1b6 100644 --- a/src/gui/kernel/x11.pri +++ b/src/gui/kernel/x11.pri @@ -1,4 +1,4 @@ x11 { - contains(QT_CONFIG, nas): LIBS += -laudio -lXt + contains(QT_CONFIG, nas): LIBS_PRIVATE += -laudio -lXt } |