diff options
Diffstat (limited to 'src/gui/kernel')
69 files changed, 6460 insertions, 1488 deletions
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index cb2b014..2917592 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -41,7 +41,15 @@ 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/qgesturemanager_p.h \ + kernel/qgesturerecognizer_p.h \ + kernel/qgesturerecognizer.h \ + kernel/qgesturestandardrecognizers_p.h \ + kernel/qdirectionrecognizer_p.h \ + kernel/qdirectionsimplificator_p.h SOURCES += \ kernel/qaction.cpp \ @@ -70,7 +78,12 @@ SOURCES += \ kernel/qwhatsthis.cpp \ kernel/qwidget.cpp \ kernel/qwidgetaction.cpp \ - kernel/qkeymapper.cpp + kernel/qkeymapper.cpp \ + kernel/qgesture.cpp \ + kernel/qgesturemanager.cpp \ + kernel/qgesturerecognizer.cpp \ + kernel/qgesturestandardrecognizers.cpp \ + kernel/qdirectionrecognizer.cpp win32 { DEFINES += QT_NO_DIRECTDRAW @@ -164,24 +177,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 \ @@ -193,7 +208,7 @@ embedded { MENU_NIB.path = Resources MENU_NIB.version = Versions QMAKE_BUNDLE_DATA += MENU_NIB - RESOURCES += mac/maccursors.qrc + RESOURCES += mac/macresources.qrc LIBS += -framework AppKit } diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp index 26baad5..4ee17f4 100644 --- a/src/gui/kernel/qaction.cpp +++ b/src/gui/kernel/qaction.cpp @@ -76,7 +76,7 @@ static QString qt_strippedText(QString s) s.remove(i-1,1); } return s.trimmed(); -}; +} QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0), @@ -136,25 +136,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 +169,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 @@ -617,8 +624,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 } @@ -1153,6 +1162,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; } @@ -1370,7 +1381,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/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 40795d1..05d9b3c 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -85,11 +85,14 @@ #include <stdlib.h> #include "qapplication_p.h" +#include "qevent_p.h" #include "qwidget_p.h" #include "qapplication.h" -#ifdef Q_OS_WINCE +#include <private/qgesturemanager_p.h> + +#ifdef Q_WS_WINCE #include "qdatetime.h" #include "qguifunctions_wince.h" extern bool qt_wince_is_smartphone(); //qguifunctions_wince.cpp @@ -97,19 +100,18 @@ extern bool qt_wince_is_mobile(); //qguifunctions_wince.cpp extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp #endif +#include "qdatetime.h" + //#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,11 +132,19 @@ QInputContext *QApplicationPrivate::inputContext; bool QApplicationPrivate::quitOnLastWindowClosed = true; -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE int QApplicationPrivate::autoMaximizeThreshold = -1; bool QApplicationPrivate::autoSipEnabled = false; #endif +QGestureManager* QGestureManager::instance() +{ + QApplicationPrivate *d = qApp->d_func(); + if (!d->gestureManager) + d->gestureManager = new QGestureManager(qApp); + return d->gestureManager; +} + QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type) : QCoreApplicationPrivate(argc, argv) { @@ -158,6 +168,8 @@ QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::T directPainters = 0; #endif + gestureManager = 0; + if (!self) self = this; } @@ -394,6 +406,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 +421,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 @@ -441,8 +454,7 @@ 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 @@ -466,15 +478,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 +503,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 +547,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 +560,7 @@ void QApplicationPrivate::process_cmdline() delete app_style; app_style = 0; } - if (!styleOverride) - styleOverride = new QString; - *styleOverride = s; + styleOverride = s; } } @@ -620,13 +625,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). @@ -848,6 +846,11 @@ void QApplicationPrivate::initialize() // trigger registering of QVariant's GUI types extern int qRegisterGuiVariant(); qRegisterGuiVariant(); +#ifndef QT_NO_STATEMACHINE + // trigger registering of QStateMachine's GUI types + extern int qRegisterGuiStateMachine(); + qRegisterGuiStateMachine(); +#endif is_app_running = true; // no longer starting up @@ -866,7 +869,7 @@ void QApplicationPrivate::initialize() 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 +878,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 +896,8 @@ void QApplicationPrivate::initialize() QApplicationPrivate::wheel_scroll_lines = 3; #endif #endif + + initializeMultitouch(); } /*! @@ -1043,6 +1048,8 @@ QApplication::~QApplication() delete QDragManager::self(); #endif + d->cleanupMultitouch(); + qt_cleanup(); if (QApplicationPrivate::widgetCount) @@ -1069,6 +1076,11 @@ QApplication::~QApplication() QApplicationPrivate::fade_tooltip = false; QApplicationPrivate::widgetCount = false; +#ifndef QT_NO_STATEMACHINE + // trigger unregistering of QStateMachine's GUI types + extern int qUnregisterGuiStateMachine(); + qUnregisterGuiStateMachine(); +#endif // trigger unregistering of QVariant's GUI types extern int qUnregisterGuiVariant(); qUnregisterGuiVariant(); @@ -1227,7 +1239,7 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis the WA_InputMethodEnabled attribute set. */ -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE void QApplication::setAutoMaximizeThreshold(const int threshold) { QApplicationPrivate::autoMaximizeThreshold = threshold; @@ -1289,44 +1301,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 +1396,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 @@ -1938,6 +1919,40 @@ 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_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 @@ -2089,8 +2104,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; @@ -2576,14 +2592,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 +2610,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 +2687,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 +2776,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 +2785,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 +2799,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 +2808,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 +2831,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) @@ -2868,7 +2884,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 +2898,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 +2938,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) { @@ -3496,7 +3517,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. @@ -3562,26 +3583,32 @@ 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(); } #endif // !QT_NO_WHEELEVENT || !QT_NO_TABLETEVENT } + if (!d->grabbedGestures.isEmpty() && e->spontaneous() && receiver->isWidgetType()) { + const QEvent::Type t = e->type(); + if (t != QEvent::Gesture && t != QEvent::GraphicsSceneGesture) { + if (QGestureManager::instance()->filterEvent(static_cast<QWidget*>(receiver), e)) + return true; + } + } + // User input and window activation makes tooltips sleep switch (e->type()) { case QEvent::Wheel: @@ -3709,19 +3736,10 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QPoint relpos = mouse->pos(); if (e->spontaneous()) { - 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); } if (e->type() == QEvent::MouseMove && mouse->buttons() == 0) { @@ -3780,7 +3798,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); } @@ -3803,17 +3821,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) { @@ -4018,7 +4028,45 @@ 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; + } default: res = d->notify_helper(receiver, e); break; @@ -4036,10 +4084,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); @@ -4569,9 +4617,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 */ @@ -4590,7 +4638,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. */ /*! @@ -4985,6 +5033,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; @@ -4998,6 +5063,57 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy) return true; } +/*! + \since 4.6 + + Adds custom gesture \a recognizer object. + + Qt takes ownership of the provided \a recognizer. + + \sa Qt::AA_EnableGestures, QGestureEvent +*/ +void QApplication::addGestureRecognizer(QGestureRecognizer *recognizer) +{ + QGestureManager::instance()->addRecognizer(recognizer); +} + +/*! + \since 4.6 + + Removes custom gesture \a recognizer object. + + \sa Qt::AA_EnableGestures, QGestureEvent +*/ +void QApplication::removeGestureRecognizer(QGestureRecognizer *recognizer) +{ + Q_D(QApplication); + if (!d->gestureManager) + return; + d->gestureManager->removeRecognizer(recognizer); +} + +/*! + \property QApplication::eventDeliveryDelayForGestures + \since 4.6 + + Specifies the \a delay before input events are delivered to the + gesture enabled widgets. + + The delay allows to postpone widget's input event handling until + gestures framework can successfully recognize a gesture. + + \sa QWidget::grabGesture +*/ +void QApplication::setEventDeliveryDelayForGestures(int delay) +{ + QGestureManager::instance()->setEventDeliveryDelay(delay); +} + +int QApplication::eventDeliveryDelayForGestures() +{ + return QGestureManager::instance()->eventDeliveryDelay(); +} + /*! \fn QDecoration &QApplication::qwsDecoration() Return the QWSDecoration used for decorating windows. @@ -5129,6 +5245,213 @@ 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; + QApplication *q = self->q_func(); + + 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 = q->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, + q->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 3c0e598..954f824 100644 --- a/src/gui/kernel/qapplication.h +++ b/src/gui/kernel/qapplication.h @@ -71,6 +71,7 @@ class QStyle; class QEventLoop; class QIcon; class QInputContext; +class QGestureRecognizer; template <typename T> class QList; class QLocale; #if defined(Q_WS_QWS) @@ -102,10 +103,11 @@ 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(int eventDeliveryDelayForGestures READ eventDeliveryDelayForGestures WRITE setEventDeliveryDelayForGestures) public: enum Type { Tty, GuiClient, GuiServer }; @@ -266,6 +268,12 @@ public: static bool keypadNavigationEnabled(); #endif + void addGestureRecognizer(QGestureRecognizer *recognizer); + void removeGestureRecognizer(QGestureRecognizer *recognizer); + + void setEventDeliveryDelayForGestures(int delay); + int eventDeliveryDelayForGestures(); + Q_SIGNALS: void lastWindowClosed(); void focusChanged(QWidget *old, QWidget *now); @@ -281,7 +289,7 @@ 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; void setAutoSipEnabled(const bool enabled); @@ -374,6 +382,7 @@ private: friend class QDirectPainter; friend class QDirectPainterPrivate; #endif + friend class QGestureManager; #if defined(Q_WS_WIN) friend QApplicationPrivate* getQApplicationPrivateInternal(); @@ -382,6 +391,9 @@ private: #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 5ded153..ad9f220 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,11 +1042,29 @@ 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" @@ -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) { @@ -1642,15 +1664,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) { @@ -2983,4 +2996,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 ddd5624..4b2bf15 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 @@ -189,6 +189,12 @@ extern "C" { } #endif +#if defined(Q_WS_WIN) +typedef BOOL (WINAPI *qt_RegisterTouchWindowPtr)(HWND, ULONG); +typedef BOOL (WINAPI *qt_GetTouchInputInfoPtr)(HANDLE, UINT, PVOID, int); +typedef BOOL (WINAPI *qt_CloseTouchInputHandlePtr)(HANDLE); +#endif + class QScopedLoopLevelCounter { QThreadData *threadData; @@ -200,6 +206,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) @@ -210,6 +222,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 +232,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 QString desktopStyleKey(); static QGraphicsSystem *graphicsSystem() #if !defined(Q_WS_QWS) @@ -358,7 +372,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 @@ -392,7 +406,7 @@ public: static QApplicationPrivate *instance() { return self; } - static QString *styleOverride; + static QString styleOverride; static int app_compile_version; @@ -419,20 +433,75 @@ 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); #if defined(Q_WS_WIN) || defined(Q_WS_X11) void sendSyntheticEnterLeave(QWidget *widget); #endif + QGestureManager *gestureManager; + // map<gesture name -> number of widget subscribed to it> + QMap<QString, int> grabbedGestures; + + 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); + +#if defined(Q_WS_WIN) + static qt_RegisterTouchWindowPtr RegisterTouchWindow; + static qt_GetTouchInputInfoPtr GetTouchInputInfo; + static qt_CloseTouchInputHandlePtr CloseTouchInputHandle; + + QHash<DWORD, int> touchInputIDToTouchPointID; + QList<QTouchEvent::TouchPoint> appAllTouchPoints; + bool translateTouchEvent(const MSG &msg); +#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 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 1e158fc..f568438 100644 --- a/src/gui/kernel/qapplication_qws.cpp +++ b/src/gui/kernel/qapplication_qws.cpp @@ -194,15 +194,15 @@ 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 = QString::fromLatin1("/tmp/qtembedded-%1").arg(qws_display_id).toLocal8Bit(); + 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)) @@ -215,7 +215,7 @@ QString qws_dataDir() 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 +224,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) @@ -2011,8 +2011,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); } @@ -2280,7 +2280,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) { @@ -3745,4 +3746,9 @@ void QApplication::setArgs(int c, char **v) d->argv = v; } +void QApplicationPrivate::initializeMultitouch_sys() +{ } +void QApplicationPrivate::cleanupMultitouch_sys() +{ } + QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 6fbdae2..bb7d931 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,7 +48,7 @@ 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> #endif @@ -88,6 +88,7 @@ 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" //#define ALIEN_DEBUG @@ -106,12 +107,43 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c #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 + +typedef struct tagTOUCHINPUT +{ + LONG x; + LONG y; + HANDLE hSource; + DWORD dwID; + DWORD dwFlags; + DWORD dwMask; + DWORD dwTime; + ULONG_PTR dwExtraInfo; + DWORD cxContact; + DWORD cyContact; +} TOUCHINPUT, *PTOUCHINPUT; + +#endif #ifndef FLASHW_STOP typedef struct { @@ -155,7 +187,7 @@ static PtrFlashWindowEx pFlashWindowEx = 0; QT_BEGIN_NAMESPACE -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE #ifndef SHRG_RETURNCMD struct SHRGINFO { DWORD cbSize; @@ -266,7 +298,7 @@ Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa #define MK_XBUTTON2 0x0040 #endif -#ifdef Q_OS_WINCE +#ifdef Q_WS_WINCE #define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam)) #endif @@ -376,11 +408,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 @@ -497,7 +524,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)); @@ -573,7 +600,7 @@ static void qt_set_windows_color_resources() static void qt_set_windows_font_resources() { -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE QFont menuFont; QFont messageFont; QFont statusFont; @@ -625,11 +652,18 @@ 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() { +#ifdef Q_OS_WINCE + UINT result; + BOOL ok; + ok = SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &result, 0); + if (ok) + qt_cleartype_enabled = result; +#else QT_WA({ UINT result; BOOL ok; @@ -643,6 +677,7 @@ static void qt_win_read_cleartype_settings() if (ok) qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE); }); +#endif } @@ -717,7 +752,11 @@ void QApplicationPrivate::initializeWidgetPaletteHash() 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); + +typedef BOOL (WINAPI *PtrSetProcessDPIAware) (VOID); + static PtrUpdateLayeredWindow ptrUpdateLayeredWindow = 0; +static PtrSetProcessDPIAware ptrSetProcessDPIAware = 0; static BOOL WINAPI qt_updateLayeredWindowIndirect(HWND hwnd, const Q_UPDATELAYEREDWINDOWINFO *info) { @@ -745,9 +784,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 +791,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 +808,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,9 +820,9 @@ 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) +#if !defined(Q_WS_WINCE) // default font HFONT hfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); QFont f(QLatin1String("MS Sans Serif"),8); @@ -815,7 +842,7 @@ void qt_init(QApplicationPrivate *priv, int) && f.family() == QLatin1String("MS Shell Dlg")) f.setFamily(QLatin1String("MS Shell Dlg 2")); QApplicationPrivate::setSystemFont(f); -#else //Q_OS_WINCE +#else //Q_WS_WINCE LOGFONT lf; HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT); int result = 0; @@ -823,7 +850,7 @@ void qt_init(QApplicationPrivate *priv, int) QFont font = qt_LOGFONTtoQFont(lf, true); if (result) QApplicationPrivate::setSystemFont(font); -#endif //Q_OS_WINCE +#endif //Q_WS_WINCE // QFont::locale_init(); ### Uncomment when it does something on Windows @@ -855,6 +882,11 @@ void qt_init(QApplicationPrivate *priv, int) if (ptrUpdateLayeredWindow && !ptrUpdateLayeredWindowIndirect) ptrUpdateLayeredWindowIndirect = qt_updateLayeredWindowIndirect; + + // Notify Vista and Windows 7 that we support highter DPI settings + if (ptrSetProcessDPIAware = (PtrSetProcessDPIAware) + QLibrary::resolve(QLatin1String("user32"), "SetProcessDPIAware")) + ptrSetProcessDPIAware(); #endif } @@ -880,7 +912,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 +923,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 +954,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; @@ -943,14 +969,14 @@ const QString qt_reg_winclass(QWidget *w) // register window class } 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 @@ -963,7 +989,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) @@ -978,8 +1004,8 @@ const QString qt_reg_winclass(QWidget *w) // register window class 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())); + (const wchar_t *) QString::fromUtf16((const ushort *)uniqueAppID).toLower().replace(QLatin1Char('\\'), + QLatin1Char('_')).utf16())); #endif // since multiple Qt versions can be used in one process @@ -992,11 +1018,11 @@ const QString qt_reg_winclass(QWidget *w) // register window class if (classExists == -1) { QT_WA({ WNDCLASS wcinfo; - classExists = GetClassInfo((HINSTANCE)qWinAppInst(), (TCHAR*)cname.utf16(), &wcinfo); + classExists = GetClassInfo(qWinAppInst(), (TCHAR*)cname.utf16(), &wcinfo); classExists = classExists && wcinfo.lpfnWndProc != QtWndProc; }, { WNDCLASSA wcinfo; - classExists = GetClassInfoA((HINSTANCE)qWinAppInst(), cname.toLatin1(), &wcinfo); + classExists = GetClassInfoA(qWinAppInst(), cname.toLatin1(), &wcinfo); classExists = classExists && wcinfo.lpfnWndProc != QtWndProc; }); } @@ -1008,7 +1034,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class return cname; ATOM atom; -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE HBRUSH bgBrush = (HBRUSH)GetSysColorBrush(COLOR_WINDOW); QT_WA({ WNDCLASS wc; @@ -1016,9 +1042,9 @@ const QString qt_reg_winclass(QWidget *w) // register window class wc.lpfnWndProc = (WNDPROC)QtWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; - wc.hInstance = (HINSTANCE)qWinAppInst(); + wc.hInstance = qWinAppInst(); if (icon) { - wc.hIcon = LoadIcon(appInst, L"IDI_ICON1"); + wc.hIcon = LoadIcon(qWinAppInst(), L"IDI_ICON1"); if (!wc.hIcon) wc.hIcon = LoadIcon(0, IDI_APPLICATION); } else { @@ -1035,9 +1061,9 @@ const QString qt_reg_winclass(QWidget *w) // register window class wc.lpfnWndProc = (WNDPROC)QtWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; - wc.hInstance = (HINSTANCE)qWinAppInst(); + wc.hInstance = qWinAppInst(); if (icon) { - wc.hIcon = LoadIconA(appInst, (char*)"IDI_ICON1"); + wc.hIcon = LoadIconA(qWinAppInst(), (char*)"IDI_ICON1"); if (!wc.hIcon) wc.hIcon = LoadIconA(0, (char*)IDI_APPLICATION); } else { @@ -1056,9 +1082,9 @@ const QString qt_reg_winclass(QWidget *w) // register window class wc.lpfnWndProc = (WNDPROC)QtWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; - wc.hInstance = (HINSTANCE)qWinAppInst(); + wc.hInstance = qWinAppInst(); if (icon) { - wc.hIcon = LoadIcon(appInst, L"IDI_ICON1"); + wc.hIcon = LoadIcon(qWinAppInst(), L"IDI_ICON1"); // if (!wc.hIcon) // wc.hIcon = LoadIcon(0, IDI_APPLICATION); } else { @@ -1092,9 +1118,9 @@ static void unregWinClasses() QHash<QString, int>::ConstIterator it = hash->constBegin(); while (it != hash->constEnd()) { QT_WA({ - UnregisterClass((TCHAR*)it.key().utf16(), (HINSTANCE)qWinAppInst()); + UnregisterClass((TCHAR*)it.key().utf16(), qWinAppInst()); } , { - UnregisterClassA(it.key().toLatin1(), (HINSTANCE)qWinAppInst()); + UnregisterClassA(it.key().toLatin1(), qWinAppInst()); }); ++it; } @@ -1129,7 +1155,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; @@ -1381,7 +1407,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) @@ -1431,8 +1457,9 @@ static bool qt_is_translatable_mouse_event(UINT message) return (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST || message >= WM_XBUTTONDOWN && message <= WM_XBUTTONDBLCLK) && message != WM_MOUSEWHEEL + && message != WM_MOUSEHWHEEL -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE || message >= WM_NCMOUSEMOVE && message <= WM_NCMBUTTONDBLCLK #endif ; @@ -1472,7 +1499,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 +1529,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 +1539,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); @@ -1540,13 +1567,13 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam 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 +1590,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 +1599,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 +1622,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 +1631,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 +1683,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 +1692,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 +1714,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); } @@ -1722,6 +1749,9 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam result = widget->translateWheelEvent(msg); } else { switch (message) { + case WM_TOUCH: + result = getQApplicationPrivateInternal()->translateTouchEvent(msg); + break; case WM_KEYDOWN: // keyboard event case WM_SYSKEYDOWN: qt_keymapper_private()->updateKeyMap(msg); @@ -1766,7 +1796,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 +1811,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 +1919,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 +1942,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 +1965,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 @@ -1958,7 +1993,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam QHideEvent e; qt_sendSpontaneousEvent(widget, &e); widget->hideChildren(true); -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE const QString title = widget->windowIconText(); if (!title.isEmpty()) widget->setWindowTitle_helper(title); @@ -1981,7 +2016,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam widget->showChildren(true); QShowEvent e; qt_sendSpontaneousEvent(widget, &e); -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE const QString title = widget->windowTitle(); if (!title.isEmpty()) widget->setWindowTitle_helper(title); @@ -2004,7 +2039,7 @@ 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) { @@ -2017,7 +2052,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(); @@ -2031,7 +2066,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; @@ -2060,7 +2095,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) { @@ -2086,9 +2121,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 @@ -2115,7 +2154,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; @@ -2204,7 +2243,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; @@ -2285,12 +2324,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(); } @@ -2307,7 +2346,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) @@ -2320,7 +2359,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam break; } -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE case WM_CHANGECBCHAIN: case WM_DRAWCLIPBOARD: #endif @@ -2340,7 +2379,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; } @@ -2427,7 +2466,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); @@ -2440,7 +2479,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) @@ -2459,21 +2498,21 @@ 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)) { @@ -2671,19 +2710,20 @@ bool qt_try_modal(QWidget *widget, MSG *msg, int& ret) int type = msg->message; bool block_event = false; -#ifndef Q_OS_WINCE +#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_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 ) { @@ -2701,7 +2741,7 @@ bool qt_try_modal(QWidget *widget, MSG *msg, int& ret) } else if (type == WM_CLOSE) { block_event = true; } -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE else if (type == WM_MOUSEACTIVATE || type == WM_NCLBUTTONDOWN){ if (!top->isActiveWindow()) { top->activateWindow(); @@ -2756,9 +2796,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); } } } @@ -2785,13 +2825,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 { @@ -2859,7 +2899,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, @@ -3055,7 +3095,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(); @@ -3148,7 +3188,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); @@ -3176,10 +3216,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); @@ -3209,7 +3246,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); @@ -3226,7 +3263,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg) winPostMessage(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, @@ -3290,12 +3327,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 @@ -3309,6 +3346,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); @@ -3329,7 +3373,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 @@ -3345,8 +3389,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 @@ -3661,7 +3705,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 @@ -3673,7 +3717,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); @@ -3685,7 +3729,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); @@ -3731,7 +3775,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); @@ -3743,7 +3787,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 } @@ -3785,7 +3829,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; @@ -3965,4 +4009,90 @@ void QSessionManager::cancel() #endif //QT_NO_SESSIONMANAGER +qt_RegisterTouchWindowPtr QApplicationPrivate::RegisterTouchWindow = 0; +qt_GetTouchInputInfoPtr QApplicationPrivate::GetTouchInputInfo = 0; +qt_CloseTouchInputHandlePtr QApplicationPrivate::CloseTouchInputHandle = 0; + +void QApplicationPrivate::initializeMultitouch_sys() +{ + QLibrary library(QLatin1String("user32")); + RegisterTouchWindow = static_cast<qt_RegisterTouchWindowPtr>(library.resolve("RegisterTouchWindow")); + GetTouchInputInfo = static_cast<qt_GetTouchInputInfoPtr>(library.resolve("GetTouchInputInfo")); + CloseTouchInputHandle = static_cast<qt_CloseTouchInputHandlePtr>(library.resolve("CloseTouchInputHandle")); + + touchInputIDToTouchPointID.clear(); +} + +void QApplicationPrivate::cleanupMultitouch_sys() +{ + touchInputIDToTouchPointID.clear(); +} + +bool QApplicationPrivate::translateTouchEvent(const MSG &msg) +{ + Q_Q(QApplication); + + QWidget *widgetForHwnd = QWidget::find(msg.hwnd); + if (!widgetForHwnd) + return false; + + QRect screenGeometry = q->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 163ceb6..5ef6b2e 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -128,6 +128,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 @@ -157,6 +167,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" @@ -294,6 +306,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; @@ -504,6 +520,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 *); @@ -714,6 +731,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() { @@ -754,6 +809,14 @@ Q_GUI_EXPORT void qt_x11_apply_settings_in_all_apps() PropModeReplace, (unsigned char *)stamp.data(), stamp.size()); } +static int kdeSessionVersion() +{ + static int kdeVersion = 0; + if (!kdeVersion) + kdeVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt(); + return kdeVersion; +} + /*! \internal Gets the current KDE 3 or 4 home path */ @@ -763,10 +826,9 @@ QString QApplicationPrivate::kdeHome() 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"))) + if (4 == kdeSessionVersion() && homeDir.exists(QLatin1String(".kde4"))) kdeConfDir = QLatin1String("/.kde4"); kdeHomePath = QDir::homePath() + kdeConfDir; } @@ -835,13 +897,11 @@ bool QApplicationPrivate::x11_apply_settings() 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) { + if (4 == kdeSessionVersion()) { QSettings kdeSettings(kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); fontDescription = kdeSettings.value(QLatin1String("font")).toString(); if (fontDescription.isEmpty()) { @@ -871,29 +931,16 @@ 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; @@ -1044,10 +1091,8 @@ static void qt_set_input_encoding() } // Reads a KDE color setting -static QColor kdeColor(const QString &key) +static QColor kdeColor(const QString &key, const QSettings &kdeSettings) { - QSettings kdeSettings(QApplicationPrivate::kdeHome() + - QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); QVariant variant = kdeSettings.value(key); if (variant.isValid()) { QStringList values = variant.toStringList(); @@ -1266,36 +1311,40 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, } if (kdeColors) { + const QSettings theKdeSettings( + QApplicationPrivate::kdeHome() + + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); + // Setup KDE palette QColor color; - color = kdeColor(QLatin1String("buttonBackground")); + color = kdeColor(QLatin1String("buttonBackground"), theKdeSettings); if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:Button/BackgroundNormal")); + color = kdeColor(QLatin1String("Colors:Button/BackgroundNormal"), theKdeSettings); if (color.isValid()) btn = color; - color = kdeColor(QLatin1String("background")); + color = kdeColor(QLatin1String("background"), theKdeSettings); if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:Window/BackgroundNormal")); + color = kdeColor(QLatin1String("Colors:Window/BackgroundNormal"), theKdeSettings); if (color.isValid()) bg = color; - color = kdeColor(QLatin1String("foreground")); + color = kdeColor(QLatin1String("foreground"), theKdeSettings); if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:View/ForegroundNormal")); + color = kdeColor(QLatin1String("Colors:View/ForegroundNormal"), theKdeSettings); if (color.isValid()) { fg = color; } - color = kdeColor(QLatin1String("windowForeground")); + color = kdeColor(QLatin1String("windowForeground"), theKdeSettings); if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:Window/ForegroundNormal")); + color = kdeColor(QLatin1String("Colors:Window/ForegroundNormal"), theKdeSettings); if (color.isValid()) wfg = color; - color = kdeColor(QLatin1String("windowBackground")); + color = kdeColor(QLatin1String("windowBackground"), theKdeSettings); if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:View/BackgroundNormal")); + color = kdeColor(QLatin1String("Colors:View/BackgroundNormal"), theKdeSettings); if (color.isValid()) base = color; } @@ -1314,29 +1363,33 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, } // Use KDE3 or KDE4 color settings if present if (kdeColors) { - QColor color = kdeColor(QLatin1String("selectBackground")); + const QSettings theKdeSettings( + QApplicationPrivate::kdeHome() + + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); + + QColor color = kdeColor(QLatin1String("selectBackground"), theKdeSettings); if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:Selection/BackgroundNormal")); + color = kdeColor(QLatin1String("Colors:Selection/BackgroundNormal"), theKdeSettings); if (color.isValid()) highlight = color; - color = kdeColor(QLatin1String("selectForeground")); + color = kdeColor(QLatin1String("selectForeground"), theKdeSettings); if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:Selection/ForegroundNormal")); + color = kdeColor(QLatin1String("Colors:Selection/ForegroundNormal"), theKdeSettings); if (color.isValid()) highlightText = color; - color = kdeColor(QLatin1String("alternateBackground")); + color = kdeColor(QLatin1String("alternateBackground"), theKdeSettings); if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:View/BackgroundAlternate")); + color = kdeColor(QLatin1String("Colors:View/BackgroundAlternate"), theKdeSettings); if (color.isValid()) pal.setColor(QPalette::AlternateBase, color); else pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(110)); - color = kdeColor(QLatin1String("buttonForeground")); + color = kdeColor(QLatin1String("buttonForeground"), theKdeSettings); if (!color.isValid()) - color = kdeColor(QLatin1String("Colors:Button/ForegroundNormal")); + color = kdeColor(QLatin1String("Colors:Button/ForegroundNormal"), theKdeSettings); if (color.isValid()) pal.setColor(QPalette::ButtonText, color); } @@ -1579,6 +1632,7 @@ static PtrWacomConfigOpenDevice ptrWacomConfigOpenDevice = 0; static PtrWacomConfigGetRawParam ptrWacomConfigGetRawParam = 0; static PtrWacomConfigCloseDevice ptrWacomConfigCloseDevice = 0; static PtrWacomConfigTerm ptrWacomConfigTerm = 0; +Q_GLOBAL_STATIC(QByteArray, wacomDeviceName) #endif #endif @@ -1719,7 +1773,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; @@ -2077,6 +2131,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; @@ -2348,13 +2409,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) @@ -2369,18 +2423,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; } @@ -2516,10 +2571,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... @@ -2578,31 +2638,49 @@ void qt_init(QApplicationPrivate *priv, int, /*! \internal */ -void QApplicationPrivate::x11_initialize_style() +QString QApplicationPrivate::x11_desktop_style() { - if (QApplicationPrivate::app_style) - return; + QString stylename; + 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; + } - switch(X11->desktopEnvironment) { + if (stylename.isEmpty()) { + switch(X11->desktopEnvironment) { case DE_KDE: if (X11->use_xrender) - QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("plastique")); + stylename = QLatin1String("plastique"); else - QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("windows")); + stylename = QLatin1String("windows"); break; case DE_GNOME: if (X11->use_xrender) - QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cleanlooks")); + stylename = QLatin1String("cleanlooks"); else - QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("windows")); + stylename = QLatin1String("windows"); break; case DE_CDE: - QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cde")); + stylename = QLatin1String("cde"); break; default: // Don't do anything break; + } } + return stylename; } void QApplicationPrivate::initializeWidgetPaletteHash() @@ -2633,10 +2711,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) @@ -2971,7 +3045,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 } @@ -3109,6 +3183,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); @@ -3139,6 +3226,7 @@ int QApplication::x11ProcessEvent(XEvent* event) { Q_D(QApplication); QScopedLoopLevelCounter loopLevelCounter(d->threadData); + #ifdef ALIEN_DEBUG //qDebug() << "QApplication::x11ProcessEvent:" << event->type; #endif @@ -4137,7 +4225,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 || @@ -4407,7 +4497,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)) { @@ -4476,8 +4565,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]; @@ -4535,6 +4623,46 @@ void fetchWacomToolId(int &deviceType, qint64 &serialId) } #endif +struct qt_tablet_motion_data +{ + Time timestamp; + 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) { + if (data->timestamp > 0) { + if ((reinterpret_cast<const XDeviceMotionEvent*>(event))->time > data->timestamp) { + data->error = true; + return false; + } + } + 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) @@ -4561,7 +4689,6 @@ 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; @@ -4569,8 +4696,6 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet 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; @@ -4578,72 +4703,41 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet 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)) { + + // Do event compression. Skip over tablet+mouse move events if there are newer ones. + qt_tablet_motion_data tabletMotionData; + tabletMotionData.tabletMotionType = tablet->xinput_motion; + while (true) { + // Find first mouse event since we expect them in pairs inside Qt + tabletMotionData.error =false; + tabletMotionData.timestamp = 0; + if (XCheckIfEvent(X11->display, &mouseMotionEvent, &qt_mouseMotion_scanner, (XPointer) &tabletMotionData)) { 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 { + } else { break; } - xinputMotionEvent = xinputMotionEventNext; - motion = (reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent)); - } + // Now discard any duplicate tablet events. + XEvent dummy; + tabletMotionData.error = false; + tabletMotionData.timestamp = mouseMotionEvent.xmotion.time; + while (XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) { + motion = reinterpret_cast<const XDeviceMotionEvent*>(&dummy); + } - if (reinsertMouseEvent) { - XPutBackEvent(X11->display, &mouseMotionEventSave); + // now check if there are more recent tablet motion events since we'll compress the current one with + // newer ones in that case + tabletMotionData.error = false; + tabletMotionData.timestamp = 0; + if (! XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) { + break; // done with compression + } + motion = reinterpret_cast<const XDeviceMotionEvent*>(&dummy); } - 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); + if (reinsertMouseEvent) { + XPutBackEvent(X11->display, &mouseMotionEventSave); } t = QEvent::TabletMove; @@ -5016,6 +5110,7 @@ bool QETWidget::translatePropertyEvent(const XEvent *event) return true; } + // // Paint event translation // @@ -5194,6 +5289,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()); @@ -5279,6 +5382,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; } @@ -5895,4 +6012,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/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp index 9e14a3c..d2b9991 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 @@ -276,11 +277,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 +291,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_x11.cpp b/src/gui/kernel/qclipboard_x11.cpp index bbf8cdd..1ebc764 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/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index ae3265b..28179b7 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -49,6 +49,7 @@ #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 <qscrollarea.h> #include <qhash.h> @@ -196,6 +197,7 @@ extern "C" { if (self) { [self finishInitWithQWidget:widget widgetPrivate:widgetprivate]; } + composingText = new QString(); composing = false; sendKeyEvents = true; currentCustomTypes = 0; @@ -419,6 +421,7 @@ extern "C" { - (void)dealloc { + delete composingText; [[NSNotificationCenter defaultCenter] removeObserver:self]; delete currentCustomTypes; [self unregisterDraggedTypes]; @@ -707,7 +710,7 @@ extern "C" { } - (void)rightMouseDown:(NSEvent *)theEvent -{ +{ bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, Qt::RightButton); if (!mouseOK) @@ -866,6 +869,62 @@ 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; +{ + Q_UNUSED(event); +// qDebug() << "magnifyWithEvent"; +} + +- (void)rotateWithEvent:(NSEvent *)event; +{ + Q_UNUSED(event); +// qDebug() << "rotateWithEvent"; +} + +- (void)swipeWithEvent:(NSEvent *)event; +{ + Q_UNUSED(event); +// qDebug() << "swipeWithEvent"; +} + +- (void)beginGestureWithEvent:(NSEvent *)event; +{ + Q_UNUSED(event); +// qDebug() << "beginGestureWithEvent"; +} + +- (void)endGestureWithEvent:(NSEvent *)event; +{ + Q_UNUSED(event); +// qDebug() << "endGestureWithEvent"; +} +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + - (void)frameDidChange:(NSNotification *)note { Q_UNUSED(note); @@ -1009,7 +1068,7 @@ extern "C" { - (void) insertText:(id)aString { - if (composing) { + if ([aString length]) { // Send the commit string to the widget. QString commitText; if ([aString isKindOfClass:[NSAttributedString class]]) { @@ -1023,6 +1082,7 @@ extern "C" { e.setCommitString(commitText); qt_sendSpontaneousEvent(qwidget, &e); } + composingText->clear(); } - (void) setMarkedText:(id)aString selectedRange:(NSRange)selRange @@ -1076,12 +1136,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; } diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h index b4a60b6..6583139 100644 --- a/src/gui/kernel/qcocoaview_mac_p.h +++ b/src/gui/kernel/qcocoaview_mac_p.h @@ -84,6 +84,7 @@ Q_GUI_EXPORT bool composing; int composingLength; bool sendKeyEvents; + QString *composingText; QStringList *currentCustomTypes; } - (id)initWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate; diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp index 6fb5f5a..9cca0d6 100644 --- a/src/gui/kernel/qcursor.cpp +++ b/src/gui/kernel/qcursor.cpp @@ -403,7 +403,7 @@ void QCursorData::initialize() QCursor::QCursor() { if (!QCursorData::initialized) { - if (qApp->startingUp()) { + if (QApplication::startingUp()) { d = 0; return; } diff --git a/src/gui/kernel/qcursor_win.cpp b/src/gui/kernel/qcursor_win.cpp index a81a857..f0dc108 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()); @@ -407,7 +407,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 +430,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); diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp index 115b4c5..aa290c4 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) @@ -208,7 +208,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 +222,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,7 +303,7 @@ 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 @@ -385,7 +385,7 @@ void QDesktopWidget::resizeEvent(QResizeEvent *) 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 diff --git a/src/gui/kernel/qdirectionrecognizer.cpp b/src/gui/kernel/qdirectionrecognizer.cpp new file mode 100644 index 0000000..a1bc5b1 --- /dev/null +++ b/src/gui/kernel/qdirectionrecognizer.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdirectionrecognizer_p.h" + +#include <math.h> + +#ifndef M_PI +#define M_PI 3.141592653589793238462643 +#endif + +QT_BEGIN_NAMESPACE + +enum { + DistanceDelta = 20 +}; + +QDirectionSimpleRecognizer::QDirectionSimpleRecognizer() +{ +} + +Direction QDirectionSimpleRecognizer::addPosition(const QPoint &pos) +{ + if (!directions.isEmpty()) { + const QPoint tmp = pos - directions.back().point; + if (tmp.manhattanLength() < 5) + return Direction(); + } + if (lastPoint.isNull()) { + lastPoint = pos; + return Direction(); + } + int dx = pos.x() - lastPoint.x(); + int dy = pos.y() - lastPoint.y(); + Qt::DirectionType direction = Qt::NoDirection; + if (dx < 0) { + if (-1*dx >= DistanceDelta/2) + direction = Qt::LeftDirection; + } else { + if (dx >= DistanceDelta/2) + direction = Qt::RightDirection; + } + if (dy < 0) { + if (-1*dy >= DistanceDelta/2) + direction = Qt::UpDirection; + } else { + if (dy >= DistanceDelta/2) + direction = Qt::DownDirection; + } + if (direction == Qt::NoDirection) + return Direction(); + + lastPoint = pos; + directions.push_back(Direction(direction, pos)); + return Direction(direction, pos); +} + + +DirectionList QDirectionSimpleRecognizer::getDirections() const +{ + return directions; +} + +void QDirectionSimpleRecognizer::reset() +{ + directions.clear(); + lastPoint = QPoint(); +} + + +/// QDirectionDiagonalRecognizer + +QDirectionDiagonalRecognizer::QDirectionDiagonalRecognizer() +{ +} + +Direction QDirectionDiagonalRecognizer::addPosition(const QPoint &pos) +{ + if (!directions.isEmpty()) { + const QPoint tmp = pos - directions.back().point; + if (tmp.manhattanLength() < 5) + return Direction(); + } + if (lastPoint.isNull()) { + lastPoint = pos; + return Direction(); + } + int dx = pos.x() - lastPoint.x(); + int dy = pos.y() - lastPoint.y(); + int distance = sqrt(static_cast<double>(dx*dx + dy*dy)); + if (distance < DistanceDelta/2) + return Direction(); + + Qt::DirectionType direction = Qt::NoDirection; + double angle = atan(1.0*qAbs(lastPoint.y() - pos.y())/qAbs(pos.x() - lastPoint.x())) * 180. / M_PI; + if (dx < 0 && dy <= 0) { + angle = 180 - angle; + } else if (dx <= 0 && dy > 0) { + angle += 180; + } else if (dx > 0 && dy > 0) { + angle = 360-angle; + } + if (angle < 0) + angle += 360; + if (angle <= 20) + direction = Qt::RightDirection; + else if (angle <= 65) + direction = Qt::RightUpDirection; + else if (angle <= 110) + direction = Qt::UpDirection; + else if (angle <= 155) + direction = Qt::LeftUpDirection; + else if (angle <= 200) + direction = Qt::LeftDirection; + else if (angle <= 245) + direction = Qt::LeftDownDirection; + else if (angle <= 290) + direction = Qt::DownDirection; + else if (angle <= 335) + direction = Qt::RightDownDirection; + else + direction = Qt::RightDirection; + + if (direction == Qt::NoDirection) + return Direction(); + + lastPoint = pos; + directions.push_back(Direction(direction, pos)); + return Direction(direction, pos); +} + + +DirectionList QDirectionDiagonalRecognizer::getDirections() const +{ + return directions; +} + +void QDirectionDiagonalRecognizer::reset() +{ + directions.clear(); + lastPoint = QPoint(); +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qdirectionrecognizer_p.h b/src/gui/kernel/qdirectionrecognizer_p.h new file mode 100644 index 0000000..12307c6 --- /dev/null +++ b/src/gui/kernel/qdirectionrecognizer_p.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDIRECTIONRECOGNIZER_P_H +#define QDIRECTIONRECOGNIZER_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 "qpoint.h" +#include "qlist.h" + +QT_BEGIN_NAMESPACE + +struct Direction +{ + Qt::DirectionType direction; + QPoint point; + + Direction(Qt::DirectionType dir, const QPoint &pt) + : direction(dir), point(pt) { } + Direction() + : direction(Qt::NoDirection) { } + + inline bool isEmpty() const { return direction == Qt::NoDirection; } + inline bool isNull() const { return direction == Qt::NoDirection; } +}; + +typedef QList<Direction> DirectionList; + +class QDirectionSimpleRecognizer +{ +public: + QDirectionSimpleRecognizer(); + Direction addPosition(const QPoint &pos); + DirectionList getDirections() const; + void reset(); + +private: + QPoint lastPoint; + DirectionList directions; +}; + +class QDirectionDiagonalRecognizer +{ +public: + QDirectionDiagonalRecognizer(); + Direction addPosition(const QPoint &pos); + DirectionList getDirections() const; + void reset(); + +private: + QPoint lastPoint; + DirectionList directions; +}; + +QT_END_NAMESPACE + +#endif // QDIRECTIONRECOGNIZER_P_H diff --git a/src/gui/kernel/qdirectionsimplificator_p.h b/src/gui/kernel/qdirectionsimplificator_p.h new file mode 100644 index 0000000..d7491dc --- /dev/null +++ b/src/gui/kernel/qdirectionsimplificator_p.h @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDIRECTIONSIMPLIFICATOR_P_H +#define QDIRECTIONSIMPLIFICATOR_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/qdirectionrecognizer_p.h" + +QT_BEGIN_NAMESPACE + +class QDirectionSimplificator +{ +public: + QDirectionSimplificator(const DirectionList &dir); + + bool simplify(DirectionList *result); + +private: + DirectionList directions; + DirectionList lastResult; + enum State { + None, + Trim, // remove first and last element + AccidentalMoves, // 66866 => 6666 + ComplexAccidentalMoves, // 778788 => 777888 (swapping elements without changing direction) + ShortMoves, // (moves of length 1) + } state; + + struct SimplifyTrim + { + SimplifyTrim() : state(0) { } + bool operator()(DirectionList &directions) + { + if (state == 0) { + directions.removeFirst(); + state = 1; + } else if (state == 1) { + directions.removeLast(); + state = 2; + } else if (state == 2 && directions.size() >= 2) { + directions.removeFirst(); + directions.removeLast(); + state = 3; + } else { + return false; + } + return true; + } + int state; + }; + struct SimplifyAccidentalMoves + { + SimplifyAccidentalMoves() : state(0) { } + bool operator()(DirectionList &directions) + { + return false; + } + int state; + }; + struct SimplifyComplexAccidentalMoves + { + SimplifyComplexAccidentalMoves() : state(0) { } + bool operator()(DirectionList &directions) + { + return false; + } + int state; + }; + + SimplifyTrim trim; + SimplifyAccidentalMoves accidentalMoves; + SimplifyComplexAccidentalMoves complexAccidentalMoves; + //SimplifyShortMoves shortMoves; +}; + +QDirectionSimplificator::QDirectionSimplificator(const DirectionList &dir) + : directions(dir), state(None) +{ +} + +bool QDirectionSimplificator::simplify(DirectionList *result) +{ + if (directions.isEmpty() || !result) + return false; + *result = directions; + switch(state) { + case None: + state = Trim; + trim = SimplifyTrim(); + case Trim: + if (trim(*result)) + break; + *result = lastResult; + state = AccidentalMoves; + accidentalMoves = SimplifyAccidentalMoves(); + case AccidentalMoves: + if (accidentalMoves(*result)) + break; + *result = lastResult; + state = ComplexAccidentalMoves; + complexAccidentalMoves = SimplifyComplexAccidentalMoves(); + case ComplexAccidentalMoves: + if (complexAccidentalMoves(*result)) + break; + *result = lastResult; + // state = ShortMoves; + // shortMoves = SimplifyShortMoves(); + // case ShortMoves: + // if (shortMoves(*result)) + // break; + // state = None; + default: + return false; + } + lastResult = *result; + if (lastResult.isEmpty()) + return false; + return true; +} + +QT_END_NAMESPACE + +#endif // QDIRECTIONSIMPLIFICATOR_P_H diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp index 6e8b440..0622de2 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_p.h b/src/gui/kernel/qdnd_p.h index 0ca08b4..deb52a7 100644 --- a/src/gui/kernel/qdnd_p.h +++ b/src/gui/kernel/qdnd_p.h @@ -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_win.cpp b/src/gui/kernel/qdnd_win.cpp index d27dca8..99c960c 100644 --- a/src/gui/kernel/qdnd_win.cpp +++ b/src/gui/kernel/qdnd_win.cpp @@ -549,7 +549,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 a15c20f..7b445ea 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); diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index de4b2b9..e40ad9d 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -49,9 +49,12 @@ #include "qmime.h" #include "qdnd_p.h" #include "qevent_p.h" +#include "qgesture.h" QT_BEGIN_NAMESPACE +QString qt_getStandardGestureTypeName(Qt::GestureType type); + /*! \class QInputEvent \ingroup events @@ -83,6 +86,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 @@ -861,6 +871,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; @@ -3070,7 +3091,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e) { << ", " << me->button() << ", " << hex << (int)me->buttons() << ", " << hex << (int)me->modifiers() - << ")"; + << ')'; } return dbg.space(); @@ -3091,7 +3112,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 +3138,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e) { << ", \"" << ke->text() << "\", " << ke->isAutoRepeat() << ", " << ke->count() - << ")"; + << ')'; } return dbg.space(); case QEvent::FocusIn: @@ -3311,6 +3332,9 @@ QDebug operator<<(QDebug dbg, const QEvent *e) { case QEvent::ChildRemoved: n = n ? n : "ChildRemoved"; dbg.nospace() << "QChildEvent(" << n << ", " << (static_cast<const QChildEvent*>(e))->child(); return dbg.space(); + case QEvent::Gesture: + n = "Gesture"; + break; default: dbg.nospace() << "QEvent(" << (const void *)e << ", type = " << e->type() << ')'; return dbg.space(); @@ -3507,4 +3531,651 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) #endif +/*! + \class QGestureEvent + \since 4.6 + \ingroup events + + \brief The QGestureEvent class provides the parameters used for + gesture recognition. + + The QGestureEvent class contains a list of gestures that are being + executed right now (\l{QGestureEvent::}{gestureTypes()}) and a + list of gestures that are cancelled (the gesture might be + cancelled because the window lost focus, or because of timeout, + etc). + + \sa QGesture +*/ + +/*! + Creates new QGestureEvent containing a list of \a gestures that + are being executed and a list of gesture that were cancelled (\a + cancelledGestures). +*/ +QGestureEvent::QGestureEvent(const QSet<QGesture*> &gestures, + const QSet<QString> &cancelledGestures) + : QEvent(QEvent::Gesture), m_cancelledGestures(cancelledGestures) +{ + setAccepted(false); + foreach(QGesture *r, gestures) + m_gestures.insert(r->type(), r); +} + +/*! + Destroys the QGestureEvent object. +*/ +QGestureEvent::~QGestureEvent() +{ +} + +/*! + Returns true if the gesture event contains gesture of specific \a + type; returns false otherwise. +*/ +bool QGestureEvent::contains(Qt::GestureType type) const +{ + return contains(qt_getStandardGestureTypeName(type)); +} + +/*! + Returns true if the gesture event contains gesture of specific \a + type; returns false otherwise. +*/ +bool QGestureEvent::contains(const QString &type) const +{ + return gesture(type) != 0; +} + +/*! + Returns a list of gesture names that this event contains. +*/ +QList<QString> QGestureEvent::gestureTypes() const +{ + return m_gestures.keys(); +} + +/*! + Returns extended information about a gesture of specific \a type. +*/ +const QGesture* QGestureEvent::gesture(Qt::GestureType type) const +{ + return gesture(qt_getStandardGestureTypeName(type)); +} + +/*! + Returns extended information about a gesture of specific \a type. +*/ +const QGesture* QGestureEvent::gesture(const QString &type) const +{ + return m_gestures.value(type, 0); +} + +/*! + Returns extended information about all gestures in the event. +*/ +QList<QGesture*> QGestureEvent::gestures() const +{ + return m_gestures.values(); +} + +/*! + Returns a set of gesture names that used to be executed, but were + cancelled (i.e. they were not finished properly). +*/ +QSet<QString> QGestureEvent::cancelledGestures() const +{ + return m_cancelledGestures; +} + +/*! + Sets the accept flag of the all gestures inside the event object, + the equivalent of calling \l{QEvent::accept()}{accept()} or + \l{QEvent::setAccepted()}{setAccepted(true)}. + + Setting the accept parameter indicates that the event receiver + wants the gesture. Unwanted gestures might be propagated to the parent + widget. +*/ +void QGestureEvent::acceptAll() +{ + QHash<QString, QGesture*>::iterator it = m_gestures.begin(), + e = m_gestures.end(); + for(; it != e; ++it) + it.value()->accept(); + setAccepted(true); +} + +/*! + Sets the accept flag of the gesture specified by \a type. + This is equivalent to calling + \l{QGestureEvent::gesture()}{gesture(type)}-> + \l{QGesture::accept()}{accept()} + + Setting the accept flag indicates that the event receiver wants + the gesture. Unwanted gestures might be propagated to the parent + widget. +*/ +void QGestureEvent::accept(Qt::GestureType type) +{ + if (QGesture *g = m_gestures.value(qt_getStandardGestureTypeName(type), 0)) + g->accept(); +} + +/*! + Sets the accept flag of the gesture specified by \a type. + This is equivalent to calling + \l{QGestureEvent::gesture()}{gesture(type)}-> + \l{QGesture::accept()}{accept()} + + Setting the accept flag indicates that the event receiver wants + the gesture. Unwanted gestures might be propagated to the parent + widget. +*/ +void QGestureEvent::accept(const QString &type) +{ + if (QGesture *g = m_gestures.value(type, 0)) + g->accept(); +} + +/*! \class QTouchEvent + \brief The QTouchEvent class contains parameters that describe a touch event +. + \since 4.6 + \ingroup 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), and if the widget has the Qt::WA_AcceptTouchEvents + attribute. + + All touch events are of type QEvent::TouchBegin, + QEvent::TouchUpdate, or QEvent::TouchEnd. The touchPoints() + function returns a list of all touch points contained in the event. + Information about each touch point can be retreived using the + QTouchEvent::TouchPoint class. + + Similar to QMouseEvent, Qt automatically grabs each touch point on + the first press inside a widget; 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. + + A touch 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. A QEvent::TouchBegin event is propagated up the parent widget + chain until a widget accepts it with accept(), or an event filter + consumes it. If the QEvent::TouchBegin event is neither accepted nor consumed, + then mouse events are simulated from the state of the first touch + point. + + The Qt::TouchPointState enum describes the different states that a + touch point may have. + + QTouchEvent::TouchPoint Qt::TouchPointState Qt::WA_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 +*/ + +/*! \class QTouchEvent::TouchPoint + \brief The QTouchEvent::TouchPoint class provide information about a touch point in a QTouchEvent. + \since 4.6 +*/ + +/*! \enum QTouchEvent::DeviceType + \since 4.6 + + 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 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. +*/ + +/*! \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 item that received the event. +*/ +QPointF QTouchEvent::TouchPoint::pos() const +{ + return d->rect.center(); +} + +/*! + Returns the scene position of this touch point. +*/ +QPointF QTouchEvent::TouchPoint::scenePos() const +{ + return d->sceneRect.center(); +} + +/*! + Returns the screen position of this touch point. +*/ +QPointF QTouchEvent::TouchPoint::screenPos() const +{ + return d->screenRect.center(); +} + +/*! + Returns the position of this touch point. The coordinates are normalized to size of the touch + device, i.e. (0,0) is the top-left corner and (1,1) is the bottom-right corner. +*/ +QPointF QTouchEvent::TouchPoint::normalizedPos() const +{ + return d->normalizedPos; +} + +/*! + Returns the starting position of this touch point, relative to the + widget that received the event. +*/ +QPointF QTouchEvent::TouchPoint::startPos() const +{ + return d->startPos; +} + +/*! + Returns the starting scene position of this touch point. +*/ +QPointF QTouchEvent::TouchPoint::startScenePos() const +{ + return d->startScenePos; +} + +/*! + Returns the starting screen position of this touch point. +*/ +QPointF QTouchEvent::TouchPoint::startScreenPos() const +{ + return d->startScreenPos; +} + +/*! + Returns the starting position of this touch point. The coordinates are normalized to size of + the touch device, i.e. (0,0) is the top-left corner and (1,1) is the bottom-right corner. +*/ +QPointF QTouchEvent::TouchPoint::startNormalizedPos() const +{ + return d->startNormalizedPos; +} + +/*! + Returns the position of this touch point from the previous touch + event, relative to the widget that received the event. +*/ +QPointF QTouchEvent::TouchPoint::lastPos() const +{ + return d->lastPos; +} + +/*! + Returns the scene position of this touch point from the previous + touch event. +*/ +QPointF QTouchEvent::TouchPoint::lastScenePos() const +{ + return d->lastScenePos; +} + +/*! + Returns the screen position of this touch point from the previous + touch event. +*/ +QPointF QTouchEvent::TouchPoint::lastScreenPos() const +{ + return d->lastScreenPos; +} + +/*! + Returns the position of this touch point from the previous touch event. The coordinates are + normalized to size of the touch device, i.e. (0,0) is the top-left corner and (1,1) is the + bottom-right corner. +*/ +QPointF QTouchEvent::TouchPoint::lastNormalizedPos() const +{ + return d->lastNormalizedPos; +} + +/*! + Returns the rect for this touch point. 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. +*/ +QRectF QTouchEvent::TouchPoint::sceneRect() const +{ + return d->sceneRect; +} + +/*! + Returns the rect for this touch point in screen coordinates. +*/ +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; +} + +/*! \fn QTouchEvent::DeviceType QTouchEvent::deviceType() const + Returns the touch device Type, which is of type + \l {QTouchEvent::DeviceType} {DeviceType}. + */ + +/*! \fn void QTouchEvent::setDeviceType(DeviceType deviceType) + Sets the device type to \a deviceType, which is of type + \l {QTouchEvent::DeviceType} {DeviceType}. + */ + + QT_END_NAMESPACE diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index c2cb05f..136dd7f 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; }; @@ -710,6 +714,41 @@ private: }; #endif +class Q_GUI_EXPORT QGestureEvent : public QEvent +{ +public: + QGestureEvent(const QSet<QGesture*> &gestures, + const QSet<QString> &cancelledGestures = QSet<QString>()); + ~QGestureEvent(); + + bool contains(Qt::GestureType type) const; + bool contains(const QString &type) const; + + QList<QString> gestureTypes() const; + + const QGesture* gesture(Qt::GestureType type) const; + const QGesture* gesture(const QString &type) const; + QList<QGesture*> gestures() const; + + QSet<QString> cancelledGestures() const; + + void acceptAll(); +#ifndef Q_NO_USING_KEYWORD + using QEvent::accept; +#else + inline void accept() { QEvent::accept(); } +#endif + void accept(Qt::GestureType type); + void accept(const QString &type); + +protected: + QHash<QString, QGesture*> m_gestures; + QSet<QString> m_cancelledGestures; + + friend class QApplication; + friend class QGestureManager; +}; + #ifndef QT_NO_DEBUG_STREAM Q_GUI_EXPORT QDebug operator<<(QDebug, const QEvent *); #endif @@ -719,6 +758,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 77f7c4b..8a2bb05 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,35 @@ 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; +}; + QT_END_NAMESPACE #endif // QEVENT_P_H diff --git a/src/gui/kernel/qformlayout.cpp b/src/gui/kernel/qformlayout.cpp index de33f93..0b7656f 100644 --- a/src/gui/kernel/qformlayout.cpp +++ b/src/gui/kernel/qformlayout.cpp @@ -689,12 +689,16 @@ void QFormLayoutPrivate::setupVerticalLayoutData(int width) // are split. maxLabelWidth = 0; if (!wrapAllRows) { + int maxFieldMinWidth = 0; //the maximum minimum size of the field for (int i = 0; i < rr; ++i) { const QFormLayoutItem *label = m_matrix(i, 0); const QFormLayoutItem *field = m_matrix(i, 1); - if (label && (label->sizeHint.width() + (field ? field->minSize.width() : 0) <= width)) + if (label && field && label->sideBySide) maxLabelWidth = qMax(maxLabelWidth, label->sizeHint.width()); + if (field) + maxFieldMinWidth = qMax(maxFieldMinWidth, field->minSize.width() + field->sbsHSpace); } + maxLabelWidth = qMin(maxLabelWidth, width - maxFieldMinWidth); } else { maxLabelWidth = width; } diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp new file mode 100644 index 0000000..d7b2d1b --- /dev/null +++ b/src/gui/kernel/qgesture.cpp @@ -0,0 +1,315 @@ +/**************************************************************************** +** +** 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgesture.h" +#include <private/qgesture_p.h> + +QT_BEGIN_NAMESPACE + +QString qt_getStandardGestureTypeName(Qt::GestureType type); + +/*! + \class QGesture + \since 4.6 + + \brief The QGesture class represents a gesture, containing all + properties that describe a gesture. + + The widget receives a QGestureEvent with a list of QGesture + objects that represent gestures that are occuring on it. The class + has a list of properties that can be queried by the user to get + some gesture-specific arguments (i.e. position of the tap in the + DoubleTap gesture). + + When creating custom gesture recognizers, they might add new + properties to the gesture object, or custom gesture developers + might subclass the QGesture objects to provide some extended + information. However, if the gesture developer wants to add a new + property to the gesture object that describe coordinate (like a + QPoint or QRect), it is required to subclass the QGesture and + re-implement the \l{QGesture::}{translate()} function to make sure + the coordinates are translated properly when the gesture event is + propagated to parent widgets. + + \sa QGestureEvent, QGestureRecognizer +*/ + +/*! + Creates a new gesture object of type \a type in a \a state and + marks it as a child of \a parent. + + Usually QGesture objects should only be contructed by the + QGestureRecognizer classes. +*/ +QGesture::QGesture(QObject *parent, const QString &type, Qt::GestureState state) + : QObject(*new QGesturePrivate, parent), m_accept(0) +{ + Q_D(QGesture); + d->type = type; + d->state = state; +} + +/*! + Creates a new gesture object of type \a type in a \a state and + marks it as a child of \a parent. + + This constructor also fills some basic information about the + gesture like a \a startPos which describes the start point of the + gesture, \a lastPos - last point where the gesture happened, \a + pos - a current point, \a rect - a bounding rect of the gesture, + \a hotSpot - a center point of the gesture, \a startTime - a time + when the gesture has started, \a duration - how long the gesture + is going on. + + Usually QGesture objects should only be contructed by the + QGestureRecognizer classes. +*/ +QGesture::QGesture(QObject *parent, const QString &type, const QPoint &startPos, + const QPoint &lastPos, const QPoint &pos, const QRect &rect, + const QPoint &hotSpot, const QDateTime &startTime, + uint duration, Qt::GestureState state) + : QObject(*new QGesturePrivate, parent) +{ + Q_D(QGesture); + d->type = type; + d->state = state; + d->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration); +} + +/*! \internal +*/ +QGesture::QGesture(QGesturePrivate &dd, QObject *parent, const QString &type, + Qt::GestureState state) + : QObject(dd, parent) +{ + Q_D(QGesture); + d->type = type; + d->state = state; +} + +/*! + Destroys the gesture object. +*/ +QGesture::~QGesture() +{ +} + +/*! + \property QGesture::type + + \brief The type of the gesture. +*/ +QString QGesture::type() const +{ + return d_func()->type; +} + + +/*! + \property QGesture::state + + \brief The current state of the gesture. +*/ +Qt::GestureState QGesture::state() const +{ + return d_func()->state; +} + +/*! + Translates the internal gesture properties that represent + coordinates by \a offset. + + Custom gesture recognizer developer have to re-implement this + function if they want to store custom properties that represent + coordinates. +*/ +void QGesture::translate(const QPoint &offset) +{ + Q_D(QGesture); + d->rect.translate(offset); + d->hotSpot += offset; + d->startPos += offset; + d->lastPos += offset; + d->pos += offset; +} + +/*! + \property QGesture::rect + + \brief The bounding rect of a gesture. +*/ +QRect QGesture::rect() const +{ + return d_func()->rect; +} + +void QGesture::setRect(const QRect &rect) +{ + d_func()->rect = rect; +} + +/*! + \property QGesture::hotSpot + + \brief The center point of a gesture. +*/ +QPoint QGesture::hotSpot() const +{ + return d_func()->hotSpot; +} + +void QGesture::setHotSpot(const QPoint &point) +{ + d_func()->hotSpot = point; +} + +/*! + \property QGesture::startTime + + \brief The time when the gesture has started. +*/ +QDateTime QGesture::startTime() const +{ + return d_func()->startTime; +} + +/*! + \property QGesture::duration + + \brief The duration time of a gesture. +*/ +uint QGesture::duration() const +{ + return d_func()->duration; +} + +/*! + \property QGesture::startPos + + \brief The start position of the pointer. +*/ +QPoint QGesture::startPos() const +{ + return d_func()->startPos; +} + +void QGesture::setStartPos(const QPoint &point) +{ + d_func()->startPos = point; +} + +/*! + \property QGesture::lastPos + + \brief The last recorded position of the pointer. +*/ +QPoint QGesture::lastPos() const +{ + return d_func()->lastPos; +} + +void QGesture::setLastPos(const QPoint &point) +{ + d_func()->lastPos = point; +} + +/*! + \property QGesture::pos + + \brief The current position of the pointer. +*/ +QPoint QGesture::pos() const +{ + return d_func()->pos; +} + +void QGesture::setPos(const QPoint &point) +{ + d_func()->pos = point; +} + +/*! + \class QPanningGesture + \since 4.6 + + \brief The QPanningGesture class represents a Pan gesture, + providing additional information related to panning. + + This class is provided for convenience, panning direction + information is also contained in the QGesture object in it's + properties. +*/ + +/*! \internal +*/ +QPanningGesture::QPanningGesture(QObject *parent) + : QGesture(*new QPanningGesturePrivate, parent, + qt_getStandardGestureTypeName(Qt::PanGesture)) +{ +} + +/*! \internal +*/ +QPanningGesture::~QPanningGesture() +{ +} + +/*! + \property QPanningGesture::lastDirection + + \brief The last recorded direction of panning. +*/ +Qt::DirectionType QPanningGesture::lastDirection() const +{ + return d_func()->lastDirection; +} + +/*! + \property QPanningGesture::direction + + \brief The current direction of panning. +*/ +Qt::DirectionType QPanningGesture::direction() const +{ + return d_func()->direction; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h new file mode 100644 index 0000000..f3c95cc --- /dev/null +++ b/src/gui/kernel/qgesture.h @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGESTURE_H +#define QGESTURE_H + +#include "qobject.h" +#include "qlist.h" +#include "qdatetime.h" +#include "qpoint.h" +#include "qrect.h" +#include "qmetatype.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QGesturePrivate; +class Q_GUI_EXPORT QGesture : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QGesture) + + Q_PROPERTY(QString type READ type) + Q_PROPERTY(Qt::GestureState state READ state) + + Q_PROPERTY(QDateTime startTime READ startTime) + Q_PROPERTY(uint duration READ duration) + + Q_PROPERTY(QRect rect READ rect WRITE setRect) + Q_PROPERTY(QPoint hotSpot READ hotSpot WRITE setHotSpot) + Q_PROPERTY(QPoint startPos READ startPos WRITE setStartPos) + Q_PROPERTY(QPoint lastPos READ lastPos WRITE setLastPos) + Q_PROPERTY(QPoint pos READ pos WRITE setPos) + +public: + QGesture(QObject *parent, const QString &type, + Qt::GestureState state = Qt::GestureStarted); + QGesture(QObject *parent, + const QString &type, const QPoint &startPos, + const QPoint &lastPos, const QPoint &pos, const QRect &rect, + const QPoint &hotSpot, const QDateTime &startTime, + uint duration, Qt::GestureState state); + virtual ~QGesture(); + + inline void setAccepted(bool accepted) { m_accept = accepted; } + inline bool isAccepted() const { return m_accept; } + + inline void accept() { m_accept = true; } + inline void ignore() { m_accept = false; } + + QString type() const; + Qt::GestureState state() const; + + QDateTime startTime() const; + uint duration() const; + + QRect rect() const; + void setRect(const QRect &rect); + QPoint hotSpot() const; + void setHotSpot(const QPoint &point); + + QPoint startPos() const; + void setStartPos(const QPoint &point); + QPoint lastPos() const; + void setLastPos(const QPoint &point); + QPoint pos() const; + void setPos(const QPoint &point); + +protected: + QGesture(QGesturePrivate &dd, QObject *parent, const QString &type, + Qt::GestureState state = Qt::GestureStarted); + virtual void translate(const QPoint &offset); + +private: + ushort m_accept : 1; + + friend class QGestureManager; + friend class QApplication; + friend class QGraphicsScene; + friend class QGraphicsScenePrivate; + friend class QGestureRecognizerPan; + friend class QDoubleTapGestureRecognizer; + friend class QTapAndHoldGestureRecognizer; +}; + +class QPanningGesturePrivate; +class Q_GUI_EXPORT QPanningGesture : public QGesture +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QPanningGesture) + + Q_PROPERTY(Qt::DirectionType lastDirection READ lastDirection) + Q_PROPERTY(Qt::DirectionType direction READ direction) + +public: + Qt::DirectionType lastDirection() const; + Qt::DirectionType direction() const; + +private: + QPanningGesture(QObject *parent = 0); + ~QPanningGesture(); + + friend class QGestureRecognizerPan; +}; + +Q_DECLARE_METATYPE(Qt::DirectionType) +Q_DECLARE_METATYPE(Qt::GestureState) + +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..caf851e --- /dev/null +++ b/src/gui/kernel/qgesture_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $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 "private/qobject_p.h" + +QT_BEGIN_NAMESPACE + +class QGraphicsItem; +class QGesturePrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGesture) + +public: + QGesturePrivate() + : state(Qt::NoGesture), graphicsItem(0), singleshot(0), duration(0) { } + + void init(const QPoint &startPos, const QPoint &lastPos, + const QPoint &pos, const QRect &rect, + const QPoint &hotSpot, const QDateTime &startTime, + uint duration) + { + this->rect = rect; + this->hotSpot = hotSpot; + this->startTime = startTime; + this->duration = duration; + this->startPos = startPos; + this->lastPos = lastPos; + this->pos = pos; + } + + QString type; + Qt::GestureState state; + + QPointer<QWidget> widget; + QGraphicsItem *graphicsItem; + uint singleshot:1; + + QRect rect; + QPoint hotSpot; + QDateTime startTime; + uint duration; + QPoint startPos; + QPoint lastPos; + QPoint pos; +}; + +class QPanningGesturePrivate : public QGesturePrivate +{ + Q_DECLARE_PUBLIC(QPanningGesture) + +public: + Qt::DirectionType lastDirection; + Qt::DirectionType direction; +}; + +QT_END_NAMESPACE + +#endif // QGESTURE_P_H diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp new file mode 100644 index 0000000..20abda9 --- /dev/null +++ b/src/gui/kernel/qgesturemanager.cpp @@ -0,0 +1,644 @@ +/**************************************************************************** +** +** 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgesturemanager_p.h" +#include "qgesture.h" +#include "qgesture_p.h" +#include "qevent.h" + +#include "qapplication.h" +#include "qapplication_p.h" +#include "qwidget.h" +#include "qwidget_p.h" + +#include "qgesturestandardrecognizers_p.h" + +#include "qdebug.h" + +// #define GESTURE_DEBUG +#ifndef GESTURE_DEBUG +# define DEBUG if (0) qDebug +#else +# define DEBUG qDebug +#endif + +QT_BEGIN_NAMESPACE + +bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); + +static const unsigned int MaximumGestureRecognitionTimeout = 2000; + +QGestureManager::QGestureManager(QObject *parent) + : QObject(parent), eventDeliveryDelayTimeout(300), + delayedPressTimer(0), lastMousePressReceiver(0), lastMousePressEvent(QEvent::None, QPoint(), Qt::NoButton, 0, 0), + lastGestureId(0), state(NotGesture) +{ + qRegisterMetaType<Qt::DirectionType>(); + qRegisterMetaType<Qt::GestureState>(); + + recognizers << new QDoubleTapGestureRecognizer(this); + recognizers << new QTapAndHoldGestureRecognizer(this); + recognizers << new QGestureRecognizerPan(this); + + foreach(QGestureRecognizer *r, recognizers) + connect(r, SIGNAL(stateChanged(QGestureRecognizer::Result)), + this, SLOT(recognizerStateChanged(QGestureRecognizer::Result))); +} + +void QGestureManager::addRecognizer(QGestureRecognizer *recognizer) +{ + recognizer->setParent(this); + recognizers << recognizer; +} + +void QGestureManager::removeRecognizer(QGestureRecognizer *recognizer) +{ + recognizers.remove(recognizer); +} + +bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) +{ + QPoint currentPos; + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + currentPos = static_cast<QMouseEvent*>(event)->pos(); break; + default: break; + } + + const QMap<QString, int> &grabbedGestures = qApp->d_func()->grabbedGestures; + + bool ret = false; + QSet<QGestureRecognizer*> startedGestures; + QSet<QGestureRecognizer*> finishedGestures; + QSet<QGestureRecognizer*> newMaybeGestures; + QSet<QGestureRecognizer*> cancelledGestures; + QSet<QGestureRecognizer*> notGestures; + if (state == NotGesture || state == MaybeGesture) { + DEBUG() << "QGestureManager: current event processing state: " + << (state == NotGesture ? "NotGesture" : "MaybeGesture"); + + QSet<QGestureRecognizer*> stillMaybeGestures; + // try other recognizers. + foreach(QGestureRecognizer *r, recognizers) { + if (grabbedGestures.value(r->gestureType(), 0) <= 0) + continue; + QGestureRecognizer::Result result = r->filterEvent(event); + if (result == QGestureRecognizer::GestureStarted) { + DEBUG() << "QGestureManager: gesture started: " << r; + startedGestures << r; + } else if (result == QGestureRecognizer::GestureFinished) { + DEBUG() << "QGestureManager: gesture finished: " << r; + finishedGestures << r; + } else if (result == QGestureRecognizer::MaybeGesture) { + DEBUG() << "QGestureManager: maybe gesture: " << r; + newMaybeGestures << r; + } else if (result == QGestureRecognizer::NotGesture) { + // if it was maybe gesture, but isn't a gesture anymore. + DEBUG() << "QGestureManager: not gesture: " << r; + notGestures << r; + } + } + Q_ASSERT(activeGestures.isEmpty()); + activeGestures += startedGestures; + for(QMap<QGestureRecognizer*, int>::iterator it = maybeGestures.begin(); + it != maybeGestures.end();) { + QGestureRecognizer *r = it.key(); + if (startedGestures.contains(r) || finishedGestures.contains(r) || + notGestures.contains(r)) { + killTimer(it.value()); + it = maybeGestures.erase(it); + } else { + ++it; + } + } + foreach(QGestureRecognizer *r, newMaybeGestures) { + if (!maybeGestures.contains(r)) { + int timerId = startTimer(MaximumGestureRecognitionTimeout); + if (!timerId) + qWarning("QGestureManager: couldn't start timer!"); + maybeGestures.insert(r, timerId); + } + } + if (!finishedGestures.isEmpty() || !startedGestures.isEmpty()) { + // gesture found! + ret = true; + QSet<QGesture*> started; + foreach(QGestureRecognizer *r, finishedGestures) { + if (QGesture *gesture = r->getGesture()) { + started << gesture; + gesture->d_func()->singleshot = true; + } + } + foreach(QGestureRecognizer *r, startedGestures) { + if (QGesture *gesture = r->getGesture()) { + started << gesture; + gesture->d_func()->singleshot = false; + } + } + + if (!activeGestures.isEmpty()) { + DEBUG() << "QGestureManager: new state = Gesture"; + state = Gesture; + } else if (!maybeGestures.isEmpty()) { + DEBUG() << "QGestureManager: new state = Maybe"; + state = MaybeGesture; + } else { + DEBUG() << "QGestureManager: new state = NotGesture"; + state = NotGesture; + } + + Q_ASSERT(!started.isEmpty()); + ret = sendGestureEvent(receiver, started, QSet<QGesture*>()); + } else if (!maybeGestures.isEmpty()) { + if (state != MaybeGesture) { + // We got a new set of events that look like a start + // of some gesture, so we switch to state MaybeGesture + // and wait for more events. + DEBUG() << "QGestureManager: new state = Maybe. Waiting for events"; + state = MaybeGesture; + // start gesture timer + } else { + // we still not sure if it is a gesture or not. + } + } else if (state == MaybeGesture) { + // last time we thought it looks like gesture, but now we + // know for sure that it isn't. + DEBUG() << "QGestureManager: new state = NotGesture"; + state = NotGesture; + } + foreach(QGestureRecognizer *r, finishedGestures) + r->reset(); + foreach(QGestureRecognizer *r, cancelledGestures) + r->reset(); + foreach(QGestureRecognizer *r, notGestures) + r->reset(); + } else if (state == Gesture) { + DEBUG() << "QGestureManager: current event processing state: Gesture"; + Q_ASSERT(!activeGestures.isEmpty()); + + foreach(QGestureRecognizer *r, recognizers) { + if (grabbedGestures.value(r->gestureType(), 0) <= 0) + continue; + QGestureRecognizer::Result result = r->filterEvent(event); + if (result == QGestureRecognizer::GestureStarted) { + DEBUG() << "QGestureManager: gesture started: " << r; + startedGestures << r; + } else if (result == QGestureRecognizer::GestureFinished) { + DEBUG() << "QGestureManager: gesture finished: " << r; + finishedGestures << r; + } else if (result == QGestureRecognizer::MaybeGesture) { + DEBUG() << "QGestureManager: maybe gesture: " << r; + newMaybeGestures << r; + } else if (result == QGestureRecognizer::NotGesture) { + // if it was an active gesture, but isn't a gesture anymore. + if (activeGestures.contains(r)) { + DEBUG() << "QGestureManager: cancelled gesture: " << r; + cancelledGestures << r; + } else { + DEBUG() << "QGestureManager: not gesture: " << r; + notGestures << r; + } + } + } + + for(QMap<QGestureRecognizer*, int>::iterator it = maybeGestures.begin(); + it != maybeGestures.end();) { + QGestureRecognizer *r = it.key(); + if (startedGestures.contains(r) || finishedGestures.contains(r) || + notGestures.contains(r)) { + killTimer(it.value()); + it = maybeGestures.erase(it); + } else { + ++it; + } + } + foreach(QGestureRecognizer *r, newMaybeGestures) { + if (!maybeGestures.contains(r)) { + int timerId = startTimer(MaximumGestureRecognitionTimeout); + if (!timerId) + qWarning("QGestureManager: couldn't start timer!"); + maybeGestures.insert(r, timerId); + } + } + QSet<QGesture*> started, updated; + if (!finishedGestures.isEmpty() || !startedGestures.isEmpty()) { + // another gesture found! + ret = true; + foreach(QGestureRecognizer *r, finishedGestures) { + if (QGesture *gesture = r->getGesture()) { + gesture->d_func()->singleshot = !activeGestures.contains(r); + if (gesture->d_func()->singleshot) + started << gesture; + else + updated << gesture; + } + } + foreach(QGestureRecognizer *r, startedGestures) { + if (QGesture *gesture = r->getGesture()) { + gesture->d_func()->singleshot = !activeGestures.contains(r); + if (gesture->d_func()->singleshot) + started << gesture; + else + updated << gesture; + } + } + } + activeGestures -= newMaybeGestures; + activeGestures -= cancelledGestures; + activeGestures += startedGestures; + activeGestures -= finishedGestures; + QSet<QString> cancelledGestureNames; + foreach(QGestureRecognizer *r, cancelledGestures) + cancelledGestureNames << r->gestureType(); + ret = sendGestureEvent(receiver, started, updated, cancelledGestureNames); + + foreach(QGestureRecognizer *r, finishedGestures) + r->reset(); + foreach(QGestureRecognizer *r, cancelledGestures) + r->reset(); + foreach(QGestureRecognizer *r, notGestures) + r->reset(); + if (!activeGestures.isEmpty()) { + // nothing changed, we are still handling a gesture + } else if (!maybeGestures.isEmpty()) { + DEBUG() << "QGestureManager: new state = Maybe. Waiting for events: " << maybeGestures; + state = MaybeGesture; + } else { + DEBUG() << "QGestureManager: new state = NotGesture"; + state = NotGesture; + } + } + + if (delayedPressTimer && state == Gesture) { + DEBUG() << "QGestureManager: gesture started. Forgetting about postponed mouse press event"; + killTimer(delayedPressTimer); + delayedPressTimer = 0; + lastMousePressReceiver = 0; + } else if (delayedPressTimer && (state == NotGesture || + event->type() == QEvent::MouseButtonRelease)) { + // not a gesture or released button too fast, so replay press + // event back. + DEBUG() << "QGestureManager: replaying mouse press event"; + QMap<QGestureRecognizer*, int>::const_iterator it = maybeGestures.begin(), + e = maybeGestures.end();; + for (; it != e; ++it) { + it.key()->reset(); + killTimer(it.value()); + } + maybeGestures.clear(); + state = NotGesture; + + if (lastMousePressReceiver) { + QApplication::sendEvent(lastMousePressReceiver, &lastMousePressEvent); + if (event->type() == QEvent::MouseButtonRelease) { + QMouseEvent *me = static_cast<QMouseEvent*>(event); + QMouseEvent move(QEvent::MouseMove, me->pos(), me->globalPos(), me->button(), + me->buttons(), me->modifiers()); + QApplication::sendEvent(lastMousePressReceiver, &move); + ret = false; + } + lastMousePressReceiver = 0; + } + lastMousePressReceiver = 0; + killTimer(delayedPressTimer); + delayedPressTimer = 0; + } else if (state == MaybeGesture && event->type() == QEvent::MouseButtonPress + && eventDeliveryDelayTimeout) { + // postpone the press event delivery until we know for + // sure whether it is a gesture. + DEBUG() << "QGestureManager: postponing mouse press event"; + QMouseEvent *me = static_cast<QMouseEvent*>(event); + lastMousePressReceiver = receiver; + lastMousePressEvent = QMouseEvent(QEvent::MouseButtonPress, me->pos(), + me->globalPos(), me->button(), + me->buttons(), me->modifiers()); + Q_ASSERT(delayedPressTimer == 0); + delayedPressTimer = startTimer(eventDeliveryDelayTimeout); + if (!delayedPressTimer) + qWarning("QGestureManager: couldn't start delayed press timer!"); + ret = true; + } + if (delayedPressTimer && event->type() == QEvent::MouseMove) { + // if we have postponed a mouse press event, postpone all + // subsequent mouse move events as well. + ret = true; + } + + lastPos = currentPos; + return ret; +} + +void QGestureManager::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == delayedPressTimer) { + DEBUG() << "QGestureManager: replaying mouse press event due to timeout"; + // sanity checks + Q_ASSERT(state != Gesture); + + QMap<QGestureRecognizer*, int>::const_iterator it = maybeGestures.begin(), + e = maybeGestures.end();; + for (; it != e; ++it) { + it.key()->reset(); + killTimer(it.value()); + } + maybeGestures.clear(); + state = NotGesture; + + if (lastMousePressReceiver) { + // we neither received a mouse release event nor gesture + // started, so we replay stored mouse press event. + QApplication::sendEvent(lastMousePressReceiver, &lastMousePressEvent); + lastMousePressReceiver = 0; + } + + lastMousePressReceiver = 0; + killTimer(delayedPressTimer); + delayedPressTimer = 0; + } else { + // sanity checks, remove later + Q_ASSERT((state == Gesture && !activeGestures.isEmpty()) || (state != Gesture && activeGestures.isEmpty())); + + typedef QMap<QGestureRecognizer*, int> MaybeGestureMap; + for (MaybeGestureMap::iterator it = maybeGestures.begin(), e = maybeGestures.end(); + it != e; ++it) { + if (it.value() == event->timerId()) { + DEBUG() << "QGestureManager: gesture timeout."; + QGestureRecognizer *r = it.key(); + r->reset(); + maybeGestures.erase(it); + killTimer(event->timerId()); + break; + } + } + + if (state == MaybeGesture && maybeGestures.isEmpty()) { + DEBUG() << "QGestureManager: new state = NotGesture because of timeout"; + state = NotGesture; + } + } +} + +bool QGestureManager::inGestureMode() +{ + return state == Gesture; +} + +void QGestureManager::recognizerStateChanged(QGestureRecognizer::Result result) +{ + QGestureRecognizer *recognizer = qobject_cast<QGestureRecognizer*>(sender()); + if (!recognizer) + return; + if (qApp->d_func()->grabbedGestures.value(recognizer->gestureType(), 0) <= 0) { + recognizer->reset(); + return; + } + + switch (result) { + case QGestureRecognizer::GestureStarted: + case QGestureRecognizer::GestureFinished: { + if (result == QGestureRecognizer::GestureStarted) { + DEBUG() << "QGestureManager: gesture started: " << recognizer; + activeGestures << recognizer; + DEBUG() << "QGestureManager: new state = Gesture"; + state = Gesture; + } else { + DEBUG() << "QGestureManager: gesture finished: " << recognizer; + } + if (maybeGestures.contains(recognizer)) { + killTimer(maybeGestures.value(recognizer)); + maybeGestures.remove(recognizer); + } + QSet<QGesture*> gestures; + if (QGesture *gesture = recognizer->getGesture()) + gestures << gesture; + if(!gestures.isEmpty()) { + //FIXME: sendGestureEvent(targetWidget, gestures); + } + if (result == QGestureRecognizer::GestureFinished) + recognizer->reset(); + } + break; + case QGestureRecognizer::MaybeGesture: { + DEBUG() << "QGestureManager: maybe gesture: " << recognizer; + if (activeGestures.contains(recognizer)) { + //FIXME: sendGestureEvent(targetWidget, QSet<QGesture*>(), QSet<QString>() << recognizer->gestureType()); + } + if (!maybeGestures.contains(recognizer)) { + int timerId = startTimer(MaximumGestureRecognitionTimeout); + if (!timerId) + qWarning("QGestureManager: couldn't start timer!"); + maybeGestures.insert(recognizer, timerId); + } + } + break; + case QGestureRecognizer::NotGesture: + DEBUG() << "QGestureManager: not gesture: " << recognizer; + if (maybeGestures.contains(recognizer)) { + killTimer(maybeGestures.value(recognizer)); + maybeGestures.remove(recognizer); + } + recognizer->reset(); + break; + default: + Q_ASSERT(false); + } + + if (delayedPressTimer && state == Gesture) { + killTimer(delayedPressTimer); + delayedPressTimer = 0; + } +} + +bool QGestureManager::sendGestureEvent(QWidget *receiver, + const QSet<QGesture*> &startedGestures, + const QSet<QGesture*> &updatedGestures, + const QSet<QString> &cancelled) +{ + DEBUG() << "QGestureManager::sendGestureEvent: sending to" << receiver + << "gestures:" << startedGestures << "," << updatedGestures + << "cancelled:" << cancelled; + // grouping gesture objects by receiver widgets. + typedef QMap<QWidget*, QSet<QGesture*> > WidgetGesturesMap; + WidgetGesturesMap widgetGestures; + for(QSet<QGesture*>::const_iterator it = startedGestures.begin(), e = startedGestures.end(); + it != e; ++it) { + QGesture *g = *it; + QGesturePrivate *gd = g->d_func(); + if (receiver) { + // find the target widget + gd->widget = 0; + gd->graphicsItem = 0; + QWidget *w = receiver; + QPoint offset; + const QString gestureType = g->type(); + while (w) { + if (w->d_func()->hasGesture(gestureType)) + break; + if (w->isWindow()) { + w = 0; + break; + } + offset += w->pos(); + w = w->parentWidget(); + } + if (w && w != gd->widget) { + DEBUG() << "QGestureManager::sendGestureEvent:" << g << "propagating to widget" << w << "offset" << offset; + g->translate(offset); + } + gd->widget = w; + } + if (!gd->widget) { + DEBUG() << "QGestureManager: didn't find a widget to send gesture event (" + << g->type() << ") for tree:" << receiver; + // TODO: maybe we should reset gesture recognizers when nobody interested in its gestures. + continue; + } + widgetGestures[gd->widget].insert(g); + } + + QSet<QGesture*> ignoredGestures; + bool ret = false; + for(WidgetGesturesMap::const_iterator it = widgetGestures.begin(), e = widgetGestures.end(); + it != e; ++it) { + QWidget *receiver = it.key(); + Q_ASSERT(receiver != 0 /*should be taken care above*/); + QSet<QGesture*> gestures = it.value(); + // mark all gestures as ignored by default + for(QSet<QGesture*>::iterator it = gestures.begin(), e = gestures.end(); it != e; ++it) + (*it)->ignore(); + // TODO: send cancelled gesture event to the widget that received the original gesture! + QGestureEvent event(gestures, cancelled); + DEBUG() << "QGestureManager::sendGestureEvent: sending now to" << receiver + << "gestures" << gestures; + bool processed = qt_sendSpontaneousEvent(receiver, &event); + QSet<QGesture*> started = startedGestures & gestures; + DEBUG() << "QGestureManager::sendGestureEvent:" << + (event.isAccepted() ? "" : "not") << "all gestures were accepted"; + if (!started.isEmpty() && !(processed && event.isAccepted())) { + // there are started gestures events that weren't + // accepted, so propagating each gesture independently. + if (event.isAccepted()) { + foreach(QGesture *g, started) + g->accept(); + } + QSet<QGesture*>::const_iterator it = started.begin(), + e = started.end(); + for(; it != e; ++it) { + QGesture *g = *it; + if (processed && g->isAccepted()) { + ret = true; + continue; + } + // if it wasn't accepted, find the first parent widget + // that is subscribed to the gesture. + QGesturePrivate *gd = g->d_func(); + QWidget *w = gd->widget; + gd->widget = 0; + + if (w && !w->isWindow()) { + g->translate(w->pos()); + w = w->parentWidget(); + QPoint offset; + const QString gestureType = g->type(); + while (w) { + if (w->d_func()->hasGesture(gestureType)) { + DEBUG() << "QGestureManager::sendGestureEvent:" << receiver + << "didn't accept gesture" << g << "propagating to" << w; + ignoredGestures.insert(g); + gd->widget = w; + break; + } + if (w->isWindow()) { + w = 0; + break; + } + offset += w->pos(); + w = w->parentWidget(); + } + if (w) { + g->translate(offset); + } else { + DEBUG() << "QGestureManager::sendGestureEvent:" << receiver + << "didn't accept gesture" << g << "and nobody wants it"; + } + } + } + } + } + if (ignoredGestures.isEmpty()) + return ret; + // try to send all gestures that were ignored to the next parent + return sendGestureEvent(0, ignoredGestures, QSet<QGesture*>(), cancelled) || ret; +} + +int QGestureManager::eventDeliveryDelay() const +{ + return eventDeliveryDelayTimeout; +} + +void QGestureManager::setEventDeliveryDelay(int ms) +{ + eventDeliveryDelayTimeout = ms; +} + +int QGestureManager::makeGestureId(const QString &name) +{ + gestureIdMap[++lastGestureId] = name; + return lastGestureId; +} + +void QGestureManager::releaseGestureId(int gestureId) +{ + gestureIdMap.remove(gestureId); +} + +QString QGestureManager::gestureNameFromId(int gestureId) const +{ + return gestureIdMap.value(gestureId); +} + +QT_END_NAMESPACE + +#include "moc_qgesturemanager_p.cpp" + diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h new file mode 100644 index 0000000..8656590 --- /dev/null +++ b/src/gui/kernel/qgesturemanager_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGESTUREMANAGER_P_H +#define QGESTUREMANAGER_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 "qlist.h" +#include "qset.h" +#include "qevent.h" +#include "qbasictimer.h" +#include "qpointer.h" + +#include "qgesturerecognizer.h" + +QT_BEGIN_NAMESPACE + +class QWidget; +class Q_AUTOTEST_EXPORT QGestureManager : public QObject +{ + Q_OBJECT +public: + QGestureManager(QObject *parent); + + int eventDeliveryDelay() const; + void setEventDeliveryDelay(int ms); + + void addRecognizer(QGestureRecognizer *recognizer); + void removeRecognizer(QGestureRecognizer *recognizer); + + bool filterEvent(QWidget *receiver, QEvent *event); + bool inGestureMode(); + + int makeGestureId(const QString &name); + void releaseGestureId(int gestureId); + QString gestureNameFromId(int gestureId) const; + + // declared in qapplication.cpp + static QGestureManager* instance(); + + bool sendGestureEvent(QWidget *receiver, + const QSet<QGesture*> &startedGestures, + const QSet<QGesture*> &updatedGestures, + const QSet<QString> &cancelled = QSet<QString>()); + +protected: + void timerEvent(QTimerEvent *event); + +private slots: + void recognizerStateChanged(QGestureRecognizer::Result); + +private: + QSet<QGestureRecognizer*> activeGestures; + QMap<QGestureRecognizer*, int> maybeGestures; + QSet<QGestureRecognizer*> recognizers; + + QPoint lastPos; + + int eventDeliveryDelayTimeout; + int delayedPressTimer; + QPointer<QWidget> lastMousePressReceiver; + QMouseEvent lastMousePressEvent; + + QMap<int, QString> gestureIdMap; + int lastGestureId; + + enum State { + Gesture, + NotGesture, + MaybeGesture // that mean timers are up and waiting for some + // more events, and input events are handled by + // gesture recognizer explicitely + } state; +}; + +QT_END_NAMESPACE + +#endif // QGESTUREMANAGER_P_H diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp new file mode 100644 index 0000000..c330663 --- /dev/null +++ b/src/gui/kernel/qgesturerecognizer.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgesturerecognizer.h" +#include "qgesture.h" + +#include <private/qobject_p.h> +#include <private/qgesturerecognizer_p.h> + +QT_BEGIN_NAMESPACE + +QString qt_getStandardGestureTypeName(Qt::GestureType gestureType); + +/*! + \class QGestureRecognizer + \since 4.6 + + \brief The QGestureRecognizer class is the base class for + implementing custom gestures. + + This is a base class, to create a custom gesture type, you should + subclass it and implement its pure virtual functions. + + Usually gesture recognizer implements state machine, storing its + state internally in the recognizer object. The recognizer receives + input events through the \l{QGestureRecognizer::}{filterEvent()} + virtual function and decides whether the parsed event should + change the state of the recognizer - i.e. if the event starts or + ends a gesture or if it isn't related to gesture at all. +*/ + +/*! + \enum QGestureRecognizer::Result + \since 4.6 + + This enum type defines the state of the gesture recognizer. + + \value Ignore Gesture recognizer ignores the event. + + \value NotGesture Not a gesture. + + \value GestureStarted The continuous gesture has started. When the + recognizer is in this state, a \l{QGestureEvent}{gesture event} + containing QGesture objects returned by the + \l{QGestureRecognizer::}{getGesture()} will be sent to a widget. + + \value GestureFinished The gesture has ended. A + \l{QGestureEvent}{gesture event} will be sent to a widget. + + \value MaybeGesture Gesture recognizer hasn't decided yet if a + gesture has started, but it might start soon after the following + events are received by the recognizer. This means that gesture + manager shouldn't reset() the internal state of the gesture + recognizer. +*/ + +/*! \fn QGestureRecognizer::Result QGestureRecognizer::filterEvent(const QEvent *event) + + This is a pure virtual function that needs to be implemented in + subclasses. + + Parses input \a event and returns the result, which specifies if + the event sequence is a gesture or not. +*/ + +/*! \fn QGesture* QGestureRecognizer::getGesture() + + Returns a gesture object that will be send to the widget. This + function is called when the gesture recognizer changed its state + to QGestureRecognizer::GestureStarted or + QGestureRecognizer::GestureFinished. + + The returned QGesture object must point to the same object in a + single gesture sequence. + + The gesture object is owned by the recognizer itself. +*/ + +/*! \fn void QGestureRecognizer::reset() + + Resets the internal state of the gesture recognizer. +*/ + +/*! \fn void QGestureRecognizer::stateChanged(QGestureRecognizer::Result result) + + The gesture recognizer might emit the stateChanged() signal when + the gesture state changes asynchronously, i.e. without any event + being filtered through filterEvent(). +*/ + +QGestureRecognizerPrivate::QGestureRecognizerPrivate() + : gestureType(Qt::UnknownGesture) +{ +} + +/*! + Creates a new gesture recognizer object that handles gestures of + the specific \a gestureType as a child of \a parent. + + \sa QApplication::addGestureRecognizer(), + QApplication::removeGestureRecognizer(), +*/ +QGestureRecognizer::QGestureRecognizer(const QString &gestureType, QObject *parent) + : QObject(*new QGestureRecognizerPrivate, parent) +{ + Q_D(QGestureRecognizer); + d->customGestureType = gestureType; +} + +/*! + Returns the name of the gesture that is handled by the recognizer. +*/ +QString QGestureRecognizer::gestureType() const +{ + Q_D(const QGestureRecognizer); + if (d->gestureType == Qt::UnknownGesture) + return d->customGestureType; + return qt_getStandardGestureTypeName(d->gestureType); +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h new file mode 100644 index 0000000..2c1c61b --- /dev/null +++ b/src/gui/kernel/qgesturerecognizer.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGESTURERECOGNIZER_H +#define QGESTURERECOGNIZER_H + +#include "qevent.h" +#include "qlist.h" +#include "qset.h" + +QT_BEGIN_NAMESPACE + +class QGesture; +class QGestureRecognizerPrivate; +class Q_GUI_EXPORT QGestureRecognizer : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QGestureRecognizer) + +public: + enum Result + { + Ignore, + NotGesture, + GestureStarted, //TODO: rename to just Gesture? + GestureFinished, + MaybeGesture + }; + + explicit QGestureRecognizer(const QString &gestureType, QObject *parent = 0); + + QString gestureType() const; + + virtual QGestureRecognizer::Result filterEvent(const QEvent* event) = 0; + virtual QGesture* getGesture() = 0; + virtual void reset() = 0; + +signals: + void stateChanged(QGestureRecognizer::Result result); + +private: + friend class QDoubleTapGestureRecognizer; + friend class QTapAndHoldGestureRecognizer; + friend class QGestureRecognizerPan; +}; + +QT_END_NAMESPACE + +#endif // QGESTURERECOGNIZER_P_H diff --git a/src/gui/kernel/qgesturerecognizer_p.h b/src/gui/kernel/qgesturerecognizer_p.h new file mode 100644 index 0000000..e250201 --- /dev/null +++ b/src/gui/kernel/qgesturerecognizer_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGESTURERECOGNIZER_P_H +#define QGESTURERECOGNIZER_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 <private/qobject_p.h> + +QT_BEGIN_NAMESPACE + +class QGestureRecognizerPrivate : public QObjectPrivate +{ +public: + QGestureRecognizerPrivate(); + +public: + Qt::GestureType gestureType; + QString customGestureType; +}; + +QT_END_NAMESPACE + +#endif // QGESTURERECOGNIZER_P_H diff --git a/src/gui/kernel/qgesturestandardrecognizers.cpp b/src/gui/kernel/qgesturestandardrecognizers.cpp new file mode 100644 index 0000000..b108994 --- /dev/null +++ b/src/gui/kernel/qgesturestandardrecognizers.cpp @@ -0,0 +1,306 @@ +/**************************************************************************** +** +** 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgesturestandardrecognizers_p.h" +#include "qgesture_p.h" +#include "qgesturerecognizer_p.h" + +// #define GESTURE_RECOGNIZER_DEBUG +#ifndef GESTURE_RECOGNIZER_DEBUG +# define DEBUG if (0) qDebug +#else +# define DEBUG qDebug +#endif + +QT_BEGIN_NAMESPACE + +QString qt_getStandardGestureTypeName(Qt::GestureType gestureType) +{ + switch (gestureType) { + case Qt::TapGesture: + return QLatin1String("__QTapGesture"); + case Qt::DoubleTapGesture: + return QLatin1String("__QDoubleTapGesture"); + case Qt::TrippleTapGesture: + return QLatin1String("__QTrippleTapGesture"); + case Qt::TapAndHoldGesture: + return QLatin1String("__QTapAndHoldGesture"); + case Qt::PanGesture: + return QLatin1String("__QPanGesture"); + case Qt::PinchGesture: + return QLatin1String("__QPinchGesture"); + case Qt::UnknownGesture: + break; + } + qFatal("QGestureRecognizer::gestureType: got an unhandled gesture type."); + return QLatin1String("__unknown_gesture"); +} + +// +// QGestureRecognizerPan +// + +QGestureRecognizerPan::QGestureRecognizerPan(QObject *parent) + : QGestureRecognizer(QString(), parent), + mousePressed(false), gestureState(Qt::NoGesture), + lastDirection(Qt::NoDirection), currentDirection(Qt::NoDirection) +{ + Q_D(QGestureRecognizer); + d->gestureType = Qt::PanGesture; +} + +QGestureRecognizer::Result QGestureRecognizerPan::filterEvent(const QEvent *event) +{ + if (event->type() == QEvent::MouseButtonPress) { + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + if (currentDirection != Qt::NoDirection) { + DEBUG() << "Pan: MouseButtonPress: fail. another press during pan"; + reset(); + return QGestureRecognizer::NotGesture; + } + if (ev->button() != Qt::LeftButton) { + return QGestureRecognizer::NotGesture; + } + DEBUG() << "Pan: MouseButtonPress: maybe gesture started"; + mousePressed = true; + pressedPos = lastPos = currentPos = ev->pos(); + return QGestureRecognizer::MaybeGesture; + } else if (event->type() == QEvent::MouseButtonRelease) { + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + if (mousePressed && currentDirection != Qt::NoDirection + && ev->button() == Qt::LeftButton) { + DEBUG() << "Pan: MouseButtonRelease: pan detected"; + gestureState = Qt::GestureFinished; + currentPos = ev->pos(); + internalReset(); + return QGestureRecognizer::GestureFinished; + } + DEBUG() << "Pan: MouseButtonRelease: some weird release detected, ignoring"; + reset(); + return QGestureRecognizer::NotGesture; + } else if (event->type() == QEvent::MouseMove) { + if (!mousePressed) + return QGestureRecognizer::NotGesture; + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + lastPos = currentPos; + currentPos = ev->pos(); + Qt::DirectionType newDirection = + simpleRecognizer.addPosition(ev->pos()).direction; + DEBUG() << "Pan: MouseMove: simplerecognizer result = " << newDirection; + QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; + if (currentDirection == Qt::NoDirection) { + if (newDirection == Qt::NoDirection) { + result = QGestureRecognizer::MaybeGesture; + } else { + result = QGestureRecognizer::GestureStarted; + gestureState = Qt::GestureStarted; + } + } else { + result = QGestureRecognizer::GestureStarted; + gestureState = Qt::GestureUpdated; + } + if (newDirection != Qt::NoDirection) { + if (currentDirection != newDirection) + lastDirection = currentDirection; + currentDirection = newDirection; + } + return result; + } + return QGestureRecognizer::Ignore; +} + +QGesture* QGestureRecognizerPan::getGesture() +{ + if (currentDirection == Qt::NoDirection) + return 0; + QPanningGesturePrivate *d = gesture.d_func(); + d->startPos = pressedPos; + d->lastPos = lastPos; + d->pos = currentPos; + d->hotSpot = pressedPos; + d->state = gestureState; + d->lastDirection = lastDirection; + d->direction = currentDirection; + + return &gesture; +} + +void QGestureRecognizerPan::reset() +{ + mousePressed = false; + lastDirection = Qt::NoDirection; + currentDirection = Qt::NoDirection; + gestureState = Qt::NoGesture; + diagonalRecognizer.reset(); + simpleRecognizer.reset(); +} + +void QGestureRecognizerPan::internalReset() +{ + mousePressed = false; + diagonalRecognizer.reset(); + simpleRecognizer.reset(); +} + + +// +// QDoubleTapGestureRecognizer +// +QDoubleTapGestureRecognizer::QDoubleTapGestureRecognizer(QObject *parent) + : QGestureRecognizer(QString(), parent), + gesture(0, qt_getStandardGestureTypeName(Qt::DoubleTapGesture)) +{ + Q_D(QGestureRecognizer); + d->gestureType = Qt::DoubleTapGesture; +} + +QGestureRecognizer::Result QDoubleTapGestureRecognizer::filterEvent(const QEvent *event) +{ + if (event->type() == QEvent::MouseButtonPress) { + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + if (pressedPosition.isNull()) { + pressedPosition = ev->pos(); + return QGestureRecognizer::MaybeGesture; + } else if ((pressedPosition - ev->pos()).manhattanLength() < 10) { + return QGestureRecognizer::GestureFinished; + } + return QGestureRecognizer::NotGesture; + } else if (event->type() == QEvent::MouseButtonRelease) { + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + if (!pressedPosition.isNull() && (pressedPosition - ev->pos()).manhattanLength() < 10) + return QGestureRecognizer::MaybeGesture; + return QGestureRecognizer::NotGesture; + } else if (event->type() == QEvent::MouseButtonDblClick) { + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + pressedPosition = ev->pos(); + return QGestureRecognizer::GestureFinished; + } + return QGestureRecognizer::NotGesture; +} + +QGesture* QDoubleTapGestureRecognizer::getGesture() +{ + QGesturePrivate *d = gesture.d_func(); + d->startPos = pressedPosition; + d->lastPos = pressedPosition; + d->pos = pressedPosition; + d->hotSpot = pressedPosition; + d->state = Qt::GestureFinished; + return &gesture; +} + +void QDoubleTapGestureRecognizer::reset() +{ + pressedPosition = QPoint(); +} + +// +// QTapAndHoldGestureRecognizer +// +const int QTapAndHoldGestureRecognizer::iterationCount = 40; +const int QTapAndHoldGestureRecognizer::iterationTimeout = 50; + +QTapAndHoldGestureRecognizer::QTapAndHoldGestureRecognizer(QObject *parent) + : QGestureRecognizer(QString(), parent), + gesture(0, qt_getStandardGestureTypeName(Qt::TapAndHoldGesture)), + iteration(0) +{ + Q_D(QGestureRecognizer); + d->gestureType = Qt::TapAndHoldGesture; +} + +QGestureRecognizer::Result QTapAndHoldGestureRecognizer::filterEvent(const QEvent *event) +{ + if (event->type() == QEvent::MouseButtonPress) { + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + if (timer.isActive()) + timer.stop(); + timer.start(QTapAndHoldGestureRecognizer::iterationTimeout, this); + pressedPosition = ev->pos(); + return QGestureRecognizer::MaybeGesture; + } else if (event->type() == QEvent::MouseMove) { + const QMouseEvent *ev = static_cast<const QMouseEvent*>(event); + if ((pressedPosition - ev->pos()).manhattanLength() < 15) + return QGestureRecognizer::GestureStarted; + else + return QGestureRecognizer::NotGesture; + } else if (event->type() == QEvent::MouseButtonRelease) { + timer.stop(); + return QGestureRecognizer::NotGesture; + } + return QGestureRecognizer::Ignore; +} + +void QTapAndHoldGestureRecognizer::timerEvent(QTimerEvent *event) +{ + if (event->timerId() != timer.timerId()) + return; + if (iteration == QTapAndHoldGestureRecognizer::iterationCount) { + timer.stop(); + emit stateChanged(QGestureRecognizer::GestureFinished); + } else { + emit stateChanged(QGestureRecognizer::GestureStarted); + } + ++iteration; +} + +QGesture* QTapAndHoldGestureRecognizer::getGesture() +{ + QGesturePrivate *d = gesture.d_func(); + d->startPos = pressedPosition; + d->lastPos = pressedPosition; + d->pos = pressedPosition; + d->hotSpot = pressedPosition; + if (iteration >= QTapAndHoldGestureRecognizer::iterationCount) + d->state = Qt::GestureFinished; + else + d->state = iteration == 0 ? Qt::GestureStarted : Qt::GestureUpdated; + return &gesture; +} + +void QTapAndHoldGestureRecognizer::reset() +{ + pressedPosition = QPoint(); + timer.stop(); + iteration = 0; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturestandardrecognizers_p.h b/src/gui/kernel/qgesturestandardrecognizers_p.h new file mode 100644 index 0000000..8abc1fb --- /dev/null +++ b/src/gui/kernel/qgesturestandardrecognizers_p.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** 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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGESTURESTANDARDRECOGNIZERS_P_H +#define QGESTURESTANDARDRECOGNIZERS_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 "qgesturerecognizer.h" +#include "private/qdirectionrecognizer_p.h" + +QT_BEGIN_NAMESPACE + +class QGestureRecognizerPan : public QGestureRecognizer +{ + Q_OBJECT +public: + QGestureRecognizerPan(QObject *parent); + + QGestureRecognizer::Result filterEvent(const QEvent *event); + QGesture* getGesture(); + void reset(); + +private: + void internalReset(); + + QPanningGesture gesture; + + QPoint pressedPos; + QPoint lastPos; + QPoint currentPos; + bool mousePressed; + Qt::GestureState gestureState; + Qt::DirectionType lastDirection; + Qt::DirectionType currentDirection; + QDirectionDiagonalRecognizer diagonalRecognizer; + QDirectionSimpleRecognizer simpleRecognizer; +}; + +class QDoubleTapGestureRecognizer : public QGestureRecognizer +{ + Q_OBJECT +public: + QDoubleTapGestureRecognizer(QObject *parent); + + QGestureRecognizer::Result filterEvent(const QEvent *event); + QGesture* getGesture(); + void reset(); + +private: + QGesture gesture; + QPoint pressedPosition; +}; + +class QTapAndHoldGestureRecognizer : public QGestureRecognizer +{ + Q_OBJECT +public: + QTapAndHoldGestureRecognizer(QObject *parent); + + QGestureRecognizer::Result filterEvent(const QEvent *event); + QGesture* getGesture(); + void reset(); + +protected: + void timerEvent(QTimerEvent *event); + +private: + QGesture gesture; + QPoint pressedPosition; + QBasicTimer timer; + int iteration; + static const int iterationCount; + static const int iterationTimeout; +}; + +QT_END_NAMESPACE + +#endif // QGESTURESTANDARDRECOGNIZERS_P_H diff --git a/src/gui/kernel/qkeymapper.cpp b/src/gui/kernel/qkeymapper.cpp index fd177e3..ca631a6 100644 --- a/src/gui/kernel/qkeymapper.cpp +++ b/src/gui/kernel/qkeymapper.cpp @@ -116,6 +116,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 4868daf..017c13c 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 @@ -692,8 +711,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; @@ -721,7 +746,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/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 22dd30b..d27eacd 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,7 +145,7 @@ 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 @@ -213,12 +232,14 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni \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 Quit \i \i Ctrl+Q \i Qtrl+Q \i Qtrl+Q \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 Preferences \i \i Ctrl+, \i \i \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 @@ -521,6 +542,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 +560,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}, @@ -669,12 +692,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. @@ -780,6 +805,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 +836,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 +1013,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 +1120,6 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence if (found) break; } -#ifdef Q_WS_MAC -#endif } return ret; } @@ -1097,15 +1148,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 +1204,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 5337a00..c45b0f0 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 d09c1c5..e750088 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; } @@ -1583,8 +1586,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 0268463..b428884 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 a4f92ef..7196b4a 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) diff --git a/src/gui/kernel/qmime_mac.cpp b/src/gui/kernel/qmime_mac.cpp index 76b9dba..903b677 100644 --- a/src/gui/kernel/qmime_mac.cpp +++ b/src/gui/kernel/qmime_mac.cpp @@ -68,11 +68,6 @@ #include "qmap.h" #include <private/qt_mac_p.h> -#ifdef Q_WS_MAC32 -#include <QuickTime/QuickTime.h> -#include "qlibrary.h" -#endif - QT_BEGIN_NAMESPACE extern CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0); // qpaintengine_mac.cpp @@ -127,32 +122,44 @@ 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 +213,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 +389,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 +502,11 @@ 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. + +#include <QuickTime/QuickTime.h> +#include <qlibrary.h> + typedef ComponentResult (*PtrGraphicsImportSetDataHandle)(GraphicsImportComponent, Handle); typedef ComponentResult (*PtrGraphicsImportCreateCGImage)(GraphicsImportComponent, CGImageRef*, UInt32); typedef ComponentResult (*PtrGraphicsExportSetInputCGImage)(GraphicsExportComponent, CGImageRef); @@ -672,33 +684,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 +831,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 +1101,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 a7dce99..bc15638 100644 --- a/src/gui/kernel/qmime_win.cpp +++ b/src/gui/kernel/qmime_win.cpp @@ -852,7 +852,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); } } @@ -1262,16 +1262,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); } diff --git a/src/gui/kernel/qmultitouch_mac.mm b/src/gui/kernel/qmultitouch_mac.mm new file mode 100644 index 0000000..3fe85a9 --- /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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $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<int, 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 = int([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) +{ + int identity = int([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..3fa8f6c --- /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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $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<int, QCocoaTouch*> _currentTouches; + static QPointF _screenReferencePos; + static QPointF _trackpadReferencePos; + static int _idAssignmentCount; + static int _touchCount; + static bool _updateInternalStateOnly; + + QTouchEvent::TouchPoint _touchPoint; + int _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 e0c80ba..50b70c3 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 diff --git a/src/gui/kernel/qshortcut.cpp b/src/gui/kernel/qshortcut.cpp index fd6b4e8..1a601ed 100644 --- a/src/gui/kernel/qshortcut.cpp +++ b/src/gui/kernel/qshortcut.cpp @@ -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 16c07fb..5d56580 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 @@ -111,7 +109,7 @@ QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se) { 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 @@ -630,13 +628,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 +658,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 +721,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 +876,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/qsizepolicy.h b/src/gui/kernel/qsizepolicy.h index 77ab05b..a651f9b 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/qsound_qws.cpp b/src/gui/kernel/qsound_qws.cpp index 2a09a39..b989843 100644 --- a/src/gui/kernel/qsound_qws.cpp +++ b/src/gui/kernel/qsound_qws.cpp @@ -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/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 2dd4fdf..f5f381e 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -88,6 +88,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 +141,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); @@ -1123,4 +1166,13 @@ 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 +} + 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 5156b9c..7b975f5 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -161,6 +161,8 @@ void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list); void qt_syncCocoaTitleBarButtons(OSWindowRef window, QWidget *widgetForWindow); +CGFloat qt_mac_get_scalefactor(); + #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 892cb7f..cca527a 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_x11_p.h b/src/gui/kernel/qt_x11_p.h index b36b3f4..1c8394b 100644 --- a/src/gui/kernel/qt_x11_p.h +++ b/src/gui/kernel/qt_x11_p.h @@ -154,6 +154,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,7 +506,6 @@ struct QX11Data int fc_hint_style; char *startupId; - char *originalStartupId; DesktopEnvironment desktopEnvironment; @@ -514,6 +517,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 +657,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 870bd21..3131c40 100644 --- a/src/gui/kernel/qtooltip.cpp +++ b/src/gui/kernel/qtooltip.cpp @@ -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/qwidget.cpp b/src/gui/kernel/qwidget.cpp index e6a5ae0..304d72a 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -109,6 +109,7 @@ #include "private/qabstractscrollarea_p.h" #include "private/qgraphicssystem_p.h" +#include "private/qgesturemanager_p.h" // widget/widget data creation count //#define QWIDGET_EXTRA_DEBUG @@ -127,6 +128,8 @@ Q_GUI_EXPORT void qt_x11_set_global_double_buffer(bool enable) } #endif +QString qt_getStandardGestureTypeName(Qt::GestureType); + static inline bool qRectIntersects(const QRect &r1, const QRect &r2) { return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) && @@ -167,39 +170,48 @@ 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) + , 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) + , 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 -#ifdef Q_WS_MAC - ,needWindowChange(0) - ,isGLWidget(0) -#endif - ,polished(0) - - , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred) - , redirectDev(0) { if (!qApp) { qFatal("QWidget: Must construct a QApplication before a QPaintDevice"); @@ -1027,7 +1039,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,7 +1055,7 @@ 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); @@ -1058,7 +1070,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 +1106,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 @@ -1336,7 +1348,7 @@ QWidget::~QWidget() #ifdef QT3_SUPPORT if (QApplicationPrivate::main_widget == this) { // reset main widget QApplicationPrivate::main_widget = 0; - qApp->quit(); + QApplication::quit(); } #endif @@ -1345,7 +1357,7 @@ QWidget::~QWidget() d->setDirtyOpaqueRegion(); if (isWindow() && isVisible() && internalWinId()) - hide(); + d->close_helper(QWidgetPrivate::CloseNoEvent); #if defined(Q_WS_WIN) || defined(Q_WS_X11) else if (!internalWinId() && isVisible()) qApp->d_func()->sendSyntheticEnterLeave(this); @@ -1412,36 +1424,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 +1457,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 +1519,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). */ @@ -1900,24 +1864,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) @@ -2091,8 +2037,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 +2239,7 @@ QStyle *QWidget::style() const if (d->extra && d->extra->style) return d->extra->style; - return qApp->style(); + return QApplication::style(); } /*! @@ -2969,10 +2915,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 @@ -4209,7 +4160,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 ) { @@ -4797,7 +4748,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); @@ -5045,7 +4996,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP QPoint scrollAreaOffset; #ifndef QT_NO_SCROLLAREA - QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(q->parent()); + QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent); if (scrollArea && scrollArea->viewport() == q) { QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr; QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate); @@ -5288,7 +5239,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; } @@ -5352,7 +5303,7 @@ 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); @@ -5424,7 +5375,7 @@ QIcon QWidget::windowIcon() const return *d->extra->topextra->icon; w = w->parentWidget(); } - return qApp->windowIcon(); + return QApplication::windowIcon(); } void QWidgetPrivate::setWindowIcon_helper() @@ -5687,7 +5638,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} */ @@ -5908,6 +5859,8 @@ QWidget *QWidget::focusWidget() const /*! Returns the next widget in this widget's focus chain. + + \sa previousInFocusChain() */ QWidget *QWidget::nextInFocusChain() const { @@ -5915,6 +5868,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 @@ -5932,7 +5897,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 @@ -5953,7 +5918,7 @@ bool QWidget::isActiveWindow() const !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(); @@ -6152,14 +6117,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 @@ -7131,7 +7088,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 @@ -7314,10 +7271,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()) @@ -7333,7 +7290,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) s.setWidth(qMin(s.width(), screen.width())); s.setHeight(qMin(s.height(), screen.height())); #else @@ -7520,10 +7477,14 @@ 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: #endif + case QEvent::Gesture: return false; default: break; @@ -7641,16 +7602,10 @@ bool QWidget::event(QEvent *event) } break; case QEvent::FocusIn: -#if defined(Q_WS_WIN) - QInputContextPrivate::updateImeStatus(this, true); -#endif focusInEvent((QFocusEvent*)event); break; case QEvent::FocusOut: -#if defined(Q_WS_WIN) - QInputContextPrivate::updateImeStatus(this, false); -#endif focusOutEvent((QFocusEvent*)event); break; @@ -7836,7 +7791,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 @@ -7925,6 +7880,46 @@ bool QWidget::event(QEvent *event) d->needWindowChange = false; break; #endif + case QEvent::Gesture: + event->ignore(); + break; + 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; + } #ifndef QT_NO_PROPERTIES case QEvent::DynamicPropertyChange: { const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName(); @@ -8059,9 +8054,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())){ @@ -9256,11 +9251,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 ) { @@ -9806,27 +9802,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()) { @@ -9838,7 +9813,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; } @@ -9869,10 +9844,6 @@ 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) { // implicitly create input context only if we have a focus @@ -9880,7 +9851,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) 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(); @@ -9957,6 +9928,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; } @@ -11039,6 +11016,103 @@ QWindowSurface *QWidget::windowSurface() const return bs ? bs->windowSurface : 0; } +/*! + \since 4.6 + + Subscribes the widget to the specified \a gesture type. + + Returns the id of the gesture. + + \sa releaseGesture(), setGestureEnabled() +*/ +int QWidget::grabGesture(const QString &gesture) +{ + Q_D(QWidget); + int id = d->grabGesture(QGestureManager::instance()->makeGestureId(gesture)); + if (d->extra && d->extra->proxyWidget) + d->extra->proxyWidget->QGraphicsItem::d_ptr->grabGesture(id); + return id; +} + +int QWidgetPrivate::grabGesture(int gestureId) +{ + gestures << gestureId; + ++qApp->d_func()->grabbedGestures[QGestureManager::instance()->gestureNameFromId(gestureId)]; + return gestureId; +} + +bool QWidgetPrivate::releaseGesture(int gestureId) +{ + QApplicationPrivate *qAppPriv = qApp->d_func(); + if (gestures.contains(gestureId)) { + QString name = QGestureManager::instance()->gestureNameFromId(gestureId); + Q_ASSERT(qAppPriv->grabbedGestures[name] > 0); + --qAppPriv->grabbedGestures[name]; + gestures.remove(gestureId); + return true; + } + return false; +} + +bool QWidgetPrivate::hasGesture(const QString &name) const +{ + QGestureManager *gm = QGestureManager::instance(); + QSet<int>::const_iterator it = gestures.begin(), + e = gestures.end(); + for (; it != e; ++it) { + if (gm->gestureNameFromId(*it) == name) + return true; + } + return false; +} + +/*! + \since 4.6 + + Subscribes the widget to the specified \a gesture type. + + Returns the id of the gesture. + + \sa releaseGesture(), setGestureEnabled() +*/ +int QWidget::grabGesture(Qt::GestureType gesture) +{ + return grabGesture(qt_getStandardGestureTypeName(gesture)); +} + +/*! + \since 4.6 + + Unsubscribes the widget from a gesture, which is specified by the + \a gestureId. + + \sa grabGesture(), setGestureEnabled() +*/ +void QWidget::releaseGesture(int gestureId) +{ + Q_D(QWidget); + if (d->releaseGesture(gestureId)) { + if (d->extra && d->extra->proxyWidget) + d->extra->proxyWidget->QGraphicsItem::d_ptr->releaseGesture(gestureId); + QGestureManager::instance()->releaseGestureId(gestureId); + } +} + +/*! + \since 4.6 + + If \a enable is true, the gesture with the given \a gestureId is + enabled; otherwise the gesture is disabled. + + The id of the gesture is returned by the grabGesture(). + + \sa grabGesture(), releaseGesture() +*/ +void QWidget::setGestureEnabled(int gestureId, bool enable) +{ + //### +} + void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const { if (left) diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 40ff671..1667275 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -90,11 +90,13 @@ class QDragLeaveEvent; class QDropEvent; class QShowEvent; class QHideEvent; +class QGestureEvent; class QInputContext; class QIcon; class QWindowSurface; class QLocale; class QGraphicsProxyWidget; +class QGestureManager; #if defined(Q_WS_X11) class QX11Info; #endif @@ -130,7 +132,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; @@ -469,7 +471,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(); @@ -539,6 +541,7 @@ public: QWidget *focusWidget() const; QWidget *nextInFocusChain() const; + QWidget *previousInFocusChain() const; // drag and drop bool acceptDrops() const; @@ -609,6 +612,11 @@ public: void setWindowSurface(QWindowSurface *surface); QWindowSurface *windowSurface() const; + int grabGesture(const QString &gesture); + int grabGesture(Qt::GestureType gesture); + void releaseGesture(int gestureId); + void setGestureEnabled(int gestureId, bool enable = true); + Q_SIGNALS: void customContextMenuRequested(const QPoint &pos); @@ -744,6 +752,7 @@ private: friend bool isWidgetOpaque(const QWidget *); friend class QGLWidgetPrivate; #endif + friend class QGestureManager; #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 ec9a049..250cc35 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -390,21 +390,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 +505,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 +721,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,11 +729,8 @@ 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 }, { kEventClassMouse, kEventMouseDown } }; @@ -775,7 +760,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 +770,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(); @@ -909,90 +892,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; } @@ -1595,24 +1582,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; @@ -1713,17 +1682,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) @@ -2021,14 +1984,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) @@ -2521,9 +2480,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(); } /*! @@ -2930,21 +2890,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", @@ -3152,16 +3101,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 @@ -4323,32 +4265,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()); @@ -4376,20 +4300,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 @@ -4459,11 +4372,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; } @@ -4518,6 +4433,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); @@ -4538,14 +4470,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); @@ -4558,12 +4482,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 } @@ -4907,11 +4830,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 d6cc4f7..7385e83 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -57,6 +57,7 @@ #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" @@ -99,93 +100,98 @@ 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 #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 +199,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,6 +222,24 @@ 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(); @@ -219,10 +249,6 @@ public: 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,24 +269,6 @@ 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(); -#endif - void raise_sys(); void lower_sys(); void stackUnder_sys(QWidget *); @@ -285,20 +293,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 - }; bool isAboutToShow() const; QRegion prepareToRender(const QRegion ®ion, QWidget::RenderFlags renderFlags); void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion, @@ -321,10 +318,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 +328,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 +355,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 +364,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 +375,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 +384,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 +404,89 @@ 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; + } + + QSize adjustedSize() const; +#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 QLayout *layout; + QRegion *needsFlush; + QPaintDevice *redirectDev; QWidgetItemV2 *widgetItem; -#if !defined(QT_NO_IM) - QPointer<QInputContext> ic; -#endif + QPaintEngine *extraPaintEngine; + mutable const QMetaObject *polished; // 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; +#if !defined(QT_NO_IM) + QPointer<QInputContext> ic; +#endif +#ifdef QT_KEYPAD_NAVIGATION + static QPointer<QWidget> editingWidget; +#endif - 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 +496,42 @@ 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 + QSet<int> gestures; + int grabGesture(int gestureId); + bool releaseGesture(int gestureId); + bool hasGesture(const QString &type) const; + + // 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 +539,34 @@ 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(); +#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 +579,71 @@ 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(); } - - 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; } + friend class QWSManager; + friend class QWSManagerPrivate; + friend class QDecoration; +#ifndef QT_NO_CURSOR + void updateCursor() const; #endif - - QPaintEngine *extraPaintEngine; - - mutable const QMetaObject *polished; - - void setModal_sys(); - QSizePolicy size_policy; - QLocale locale; - -#ifdef Q_WS_X11 - static QWidget *mouseGrabber; - static QWidget *keyboardGrabber; + QScreen* getScreen() const; #endif - QPaintDevice *redirectDev; - QPoint redirectOffset; - - inline void setRedirected(QPaintDevice *replacement, const QPoint &offset) - { - Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent)); - redirectDev = replacement; - redirectOffset = offset; - } - - inline QPaintDevice *redirected(QPoint *offset) const - { - if (offset) - *offset = redirectDev ? redirectOffset : QPoint(); - return redirectDev; - } - - inline void restoreRedirected() - { redirectDev = 0; } - - inline void enforceNativeChildren() - { - if (!extra) - createExtra(); - - 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); - } - } - - inline bool nativeChildrenForced() const - { - return extra ? extra->nativeChildrenForced : false; - } - - QSize adjustedSize() const; }; inline QWExtra *QWidgetPrivate::extraData() const diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp index d61cf0c..299ed73 100644 --- a/src/gui/kernel/qwidget_qws.cpp +++ b/src/gui/kernel/qwidget_qws.cpp @@ -565,20 +565,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); @@ -1037,6 +1023,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_win.cpp b/src/gui/kernel/qwidget_win.cpp index 3ab1ccb..e39ca77 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -56,19 +56,13 @@ #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 <qdebug.h> #include <private/qapplication_p.h> #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 @@ -257,7 +251,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); @@ -506,6 +500,9 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO 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,7 +543,7 @@ 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) @@ -574,7 +571,7 @@ 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()); } @@ -681,7 +678,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) 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(); @@ -877,12 +874,12 @@ 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. @@ -905,7 +902,7 @@ void QWidgetPrivate::grabMouseWhileInWindow() } } -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE void QWidget::grabMouse() { if (!qt_nograb()) { @@ -982,7 +979,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 +1028,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(GetWindowLongA(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); + QRect r = QApplication::desktop()->screenGeometry(this); UINT swpf = SWP_FRAMECHANGED; if (newstate & Qt::WindowActive) swpf |= SWP_NOACTIVATE; @@ -1084,7 +1081,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) QWindowStateChangeEvent e(oldstate); QApplication::sendEvent(this, &e); } -#endif //Q_OS_WINCE +#endif //Q_WS_WINCE /* @@ -1097,7 +1094,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 +1123,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); @@ -1194,7 +1191,7 @@ void QWidgetPrivate::show_sys() invalidateBuffer(q->rect()); } -#endif //Q_OS_WINCE +#endif //Q_WS_WINCE void QWidgetPrivate::setFocus_sys() { @@ -1240,7 +1237,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)); @@ -1452,7 +1449,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; @@ -1571,7 +1568,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)) @@ -1592,7 +1589,7 @@ void QWidgetPrivate::winUpdateIsOpaque() 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); @@ -1710,28 +1707,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() @@ -1855,7 +1848,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() @@ -1877,7 +1871,7 @@ void QWidgetPrivate::updateFrameStrut() GetWindowLongA(q->internalWinId(), GWL_EXSTYLE)); uint style = QT_WA_INLINE(GetWindowLongW(q->internalWinId(), GWL_STYLE), GetWindowLongA(q->internalWinId(), GWL_STYLE)); -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE if (AdjustWindowRectEx(&rect, style & ~(WS_OVERLAPPED), FALSE, exstyle)) { #else if (AdjustWindowRectEx(&rect, style, FALSE, exstyle)) { @@ -1887,7 +1881,7 @@ void QWidgetPrivate::updateFrameStrut() } } -#ifndef Q_OS_WINCE +#ifndef Q_WS_WINCE void QWidgetPrivate::setWindowOpacity_sys(qreal level) { Q_Q(QWidget); @@ -1922,7 +1916,7 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level) } (*ptrSetLayeredWindowAttributes)(q->internalWinId(), 0, (int)(level * 255), Q_LWA_ALPHA); } -#endif //Q_OS_WINCE +#endif //Q_WS_WINCE // class QGlobalRasterPaintEngine: public QRasterPaintEngine // { @@ -1931,22 +1925,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; @@ -2002,8 +1980,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)) { @@ -2059,19 +2037,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; @@ -2100,13 +2065,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); } @@ -2114,11 +2072,19 @@ 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); +} 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 1430a66..24d8156 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" @@ -211,7 +211,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()) @@ -414,7 +414,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 +450,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) { @@ -535,7 +535,7 @@ 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) GetWindowLongA(internalWinId(), GWL_STYLE); UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP; if (isVisible()) style |= WS_VISIBLE; @@ -583,7 +583,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 +598,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 +697,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 c7b32f2..2a3d2f3 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -754,11 +754,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,19 +896,70 @@ 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); @@ -1308,17 +1362,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 +1375,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 +1396,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 +1409,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)->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 +1880,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 +2231,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 +2691,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 +2701,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 4b1398e..df3e47e 100644 --- a/src/gui/kernel/qwidgetaction.cpp +++ b/src/gui/kernel/qwidgetaction.cpp @@ -228,8 +228,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_win.h b/src/gui/kernel/qwindowdefs_win.h index 0d883da..d10d016 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 f70ed57..3ddde1b 100644 --- a/src/gui/kernel/qx11embed_x11.cpp +++ b/src/gui/kernel/qx11embed_x11.cpp @@ -1297,9 +1297,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 +1304,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: @@ -1729,10 +1728,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 +1748,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 |