diff options
Diffstat (limited to 'src/gui/kernel')
-rw-r--r-- | src/gui/kernel/qapplication.cpp | 17 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 219 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_win.cpp | 4 | ||||
-rw-r--r-- | src/gui/kernel/qcocoawindowdelegate_mac.mm | 21 | ||||
-rw-r--r-- | src/gui/kernel/qcursor.cpp | 4 | ||||
-rw-r--r-- | src/gui/kernel/qdnd_qws.cpp | 4 | ||||
-rw-r--r-- | src/gui/kernel/qdnd_x11.cpp | 6 | ||||
-rw-r--r-- | src/gui/kernel/qgesture.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager.cpp | 77 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager_p.h | 5 | ||||
-rw-r--r-- | src/gui/kernel/qsound_mac.mm | 6 | ||||
-rw-r--r-- | src/gui/kernel/qt_mac_p.h | 2 | ||||
-rw-r--r-- | src/gui/kernel/qt_s60_p.h | 15 | ||||
-rw-r--r-- | src/gui/kernel/qwidget.cpp | 91 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_mac.mm | 30 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_p.h | 8 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_s60.cpp | 4 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_win.cpp | 7 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_wince.cpp | 4 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_x11.cpp | 2 |
20 files changed, 340 insertions, 188 deletions
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index ec635d4..7b62de1 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -788,6 +788,10 @@ void QApplicationPrivate::construct( qt_gui_eval_init(application_type); #endif +#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE) + symbianInit(); +#endif + #ifndef QT_NO_LIBRARY if(load_testability) { QLibrary testLib(QLatin1String("qttestability")); @@ -2364,6 +2368,19 @@ bool QApplication::event(QEvent *e) if (!(w->windowType() == Qt::Desktop)) postEvent(w, new QEvent(QEvent::LanguageChange)); } +#ifndef Q_OS_WIN + } else if (e->type() == QEvent::LocaleChange) { + // on Windows the event propagation is taken care by the + // WM_SETTINGCHANGE event handler. + QWidgetList list = topLevelWidgets(); + for (int i = 0; i < list.size(); ++i) { + QWidget *w = list.at(i); + if (!(w->windowType() == Qt::Desktop)) { + if (!w->testAttribute(Qt::WA_SetLocale)) + w->d_func()->setLocale_helper(QLocale(), true); + } + } +#endif } else if (e->type() == QEvent::Timer) { QTimerEvent *te = static_cast<QTimerEvent*>(e); Q_ASSERT(te != 0); diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index f4c7304..fa07b1a 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -364,6 +364,7 @@ void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) SetFocusing(true); m_longTapDetector = QLongTapTimer::NewL(this); + m_doubleClickTimer.invalidate(); DrawableWindow()->SetPointerGrab(ETrue); } @@ -589,120 +590,158 @@ TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCod case EEventKeyUp: case EEventKey: { - // S60 has a confusing way of delivering key events. There are three types of - // events: EKeyEvent, EKeyEventDown and EKeyEventUp. When a key is pressed, the - // two first events are generated. When releasing the key, the last one is - // generated. - // Because S60 does not generate keysyms for EKeyEventDown and EKeyEventUp events, - // we need to do some special tricks to map it to the Qt way. First, we completely - // discard EKeyEventDown events, since they are redundant. Second, since - // EKeyEventUp does not give us a keysym, we need to cache the keysyms from - // the EKeyEvent events. This is what resolveS60ScanCode does. - - - // ### hackish way to send Qt application to background when pressing right softkey - /* - if( keyEvent.iScanCode == EStdKeyDevice1 ) { - S60->window_group->SetOrdinalPosition(-1); - qApp->setActiveWindow(0); - return EKeyWasNotConsumed; - } - */ - - TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode, - keyEvent.iCode); - int keyCode; - if (s60Keysym == EKeyNull){ //some key events have 0 in iCode, for them iScanCode should be used - keyCode = qt_keymapper_private()->mapS60ScanCodesToQt(keyEvent.iScanCode); - } else if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) { - // Normal characters keys. - keyCode = s60Keysym; - } else { - // Special S60 keys. - keyCode = qt_keymapper_private()->mapS60KeyToQt(s60Keysym); - } - #ifndef QT_NO_CURSOR if (S60->mouseInteractionEnabled && S60->virtualMouseRequired) { //translate keys to pointer - if (keyCode >= Qt::Key_Left && keyCode <= Qt::Key_Down || keyCode == Qt::Key_Select) { - /*Explanation about virtualMouseAccel: - Tapping an arrow key allows precise pixel positioning - Holding an arrow key down, acceleration is applied to allow cursor - to be quickly moved to another part of the screen by key repeats. - */ - if (S60->virtualMouseLastKey == keyCode) { - S60->virtualMouseAccel *= 2; - if (S60->virtualMouseAccel > S60->virtualMouseMaxAccel) - S60->virtualMouseAccel = S60->virtualMouseMaxAccel; - } - else - S60->virtualMouseAccel = 1; - S60->virtualMouseLastKey = keyCode; - + if ((keyEvent.iScanCode >= EStdKeyLeftArrow && keyEvent.iScanCode <= EStdKeyDownArrow) || + (keyEvent.iScanCode >= EStdKeyDevice10 && keyEvent.iScanCode <= EStdKeyDevice13) || + keyEvent.iScanCode == EStdKeyDevice3) { QPoint pos = QCursor::pos(); TPointerEvent fakeEvent; + fakeEvent.iType = (TPointerEvent::TType)(-1); + fakeEvent.iModifiers = keyEvent.iModifiers; TInt x = pos.x(); TInt y = pos.y(); if (type == EEventKeyUp) { - if (keyCode == Qt::Key_Select) - fakeEvent.iType = TPointerEvent::EButton1Up; - S60->virtualMouseAccel = 1; - S60->virtualMouseLastKey = 0; - switch (keyCode) { - case Qt::Key_Left: + S60->virtualMouseAccelTimeout.start(); + switch (keyEvent.iScanCode) { + case EStdKeyLeftArrow: S60->virtualMousePressedKeys &= ~QS60Data::Left; break; - case Qt::Key_Right: + case EStdKeyRightArrow: S60->virtualMousePressedKeys &= ~QS60Data::Right; break; - case Qt::Key_Up: + case EStdKeyUpArrow: S60->virtualMousePressedKeys &= ~QS60Data::Up; break; - case Qt::Key_Down: + case EStdKeyDownArrow: S60->virtualMousePressedKeys &= ~QS60Data::Down; break; - case Qt::Key_Select: + // diagonal keys (named aliases don't exist in 3.1 SDK) + case EStdKeyDevice10: + S60->virtualMousePressedKeys &= ~QS60Data::LeftUp; + break; + case EStdKeyDevice11: + S60->virtualMousePressedKeys &= ~QS60Data::RightUp; + break; + case EStdKeyDevice12: + S60->virtualMousePressedKeys &= ~QS60Data::RightDown; + break; + case EStdKeyDevice13: + S60->virtualMousePressedKeys &= ~QS60Data::LeftDown; + break; + case EStdKeyDevice3: //select + if (S60->virtualMousePressedKeys & QS60Data::Select) + fakeEvent.iType = TPointerEvent::EButton1Up; S60->virtualMousePressedKeys &= ~QS60Data::Select; break; } } else if (type == EEventKey) { - switch (keyCode) { - case Qt::Key_Left: + int dx = 0; + int dy = 0; + if (keyEvent.iScanCode != EStdKeyDevice3) { + m_doubleClickTimer.invalidate(); + //reset mouse accelleration after a short time with no moves + const int maxTimeBetweenKeyEventsMs = 500; + if (S60->virtualMouseAccelTimeout.isValid() && + S60->virtualMouseAccelTimeout.hasExpired(maxTimeBetweenKeyEventsMs)) { + S60->virtualMouseAccelDX = 0; + S60->virtualMouseAccelDY = 0; + } + S60->virtualMouseAccelTimeout.invalidate(); + } + switch (keyEvent.iScanCode) { + case EStdKeyLeftArrow: S60->virtualMousePressedKeys |= QS60Data::Left; - x -= S60->virtualMouseAccel; + dx = -1; fakeEvent.iType = TPointerEvent::EMove; break; - case Qt::Key_Right: + case EStdKeyRightArrow: S60->virtualMousePressedKeys |= QS60Data::Right; - x += S60->virtualMouseAccel; + dx = 1; fakeEvent.iType = TPointerEvent::EMove; break; - case Qt::Key_Up: + case EStdKeyUpArrow: S60->virtualMousePressedKeys |= QS60Data::Up; - y -= S60->virtualMouseAccel; + dy = -1; fakeEvent.iType = TPointerEvent::EMove; break; - case Qt::Key_Down: + case EStdKeyDownArrow: S60->virtualMousePressedKeys |= QS60Data::Down; - y += S60->virtualMouseAccel; + dy = 1; + fakeEvent.iType = TPointerEvent::EMove; + break; + case EStdKeyDevice10: + S60->virtualMousePressedKeys |= QS60Data::LeftUp; + dx = -1; + dy = -1; fakeEvent.iType = TPointerEvent::EMove; break; - case Qt::Key_Select: + case EStdKeyDevice11: + S60->virtualMousePressedKeys |= QS60Data::RightUp; + dx = 1; + dy = -1; + fakeEvent.iType = TPointerEvent::EMove; + break; + case EStdKeyDevice12: + S60->virtualMousePressedKeys |= QS60Data::RightDown; + dx = 1; + dy = 1; + fakeEvent.iType = TPointerEvent::EMove; + break; + case EStdKeyDevice13: + S60->virtualMousePressedKeys |= QS60Data::LeftDown; + dx = -1; + dy = 1; + fakeEvent.iType = TPointerEvent::EMove; + break; + case EStdKeyDevice3: // Platform bug. If you start pressing several keys simultaneously (for // example for drag'n'drop), Symbian starts producing spurious up and // down messages for some keys. Therefore, make sure we have a clean slate // of pressed keys before starting a new button press. - if (S60->virtualMousePressedKeys != 0) { - S60->virtualMousePressedKeys |= QS60Data::Select; + if (S60->virtualMousePressedKeys & QS60Data::Select) { return EKeyWasConsumed; } else { S60->virtualMousePressedKeys |= QS60Data::Select; fakeEvent.iType = TPointerEvent::EButton1Down; + if (m_doubleClickTimer.isValid() + && !m_doubleClickTimer.hasExpired(QApplication::doubleClickInterval())) { + fakeEvent.iModifiers |= EModifierDoubleClick; + m_doubleClickTimer.invalidate(); + } else { + m_doubleClickTimer.start(); + } } break; } + if (dx) { + int cdx = S60->virtualMouseAccelDX; + //reset accel on change of sign, else double accel + if (dx * cdx <= 0) + cdx = dx; + else + cdx *= 4; + //cap accelleration + if (dx * cdx > S60->virtualMouseMaxAccel) + cdx = dx * S60->virtualMouseMaxAccel; + //move mouse position + x += cdx; + S60->virtualMouseAccelDX = cdx; + } + + if (dy) { + int cdy = S60->virtualMouseAccelDY; + if (dy * cdy <= 0) + cdy = dy; + else + cdy *= 4; + if (dy * cdy > S60->virtualMouseMaxAccel) + cdy = dy * S60->virtualMouseMaxAccel; + y += cdy; + S60->virtualMouseAccelDY = cdy; + } } //clip to screen size (window server allows a sprite hotspot to be outside the screen) if (x < 0) @@ -715,18 +754,46 @@ TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCod y = S60->screenHeightInPixels - 1; TPoint epos(x, y); TPoint cpos = epos - PositionRelativeToScreen(); - fakeEvent.iModifiers = keyEvent.iModifiers; fakeEvent.iPosition = cpos; fakeEvent.iParentPosition = epos; - HandlePointerEvent(fakeEvent); + if(fakeEvent.iType != -1) + HandlePointerEvent(fakeEvent); return EKeyWasConsumed; } - else { - S60->virtualMouseLastKey = keyCode; - S60->virtualMouseAccel = 1; - } } #endif + // S60 has a confusing way of delivering key events. There are three types of + // events: EKeyEvent, EKeyEventDown and EKeyEventUp. When a key is pressed, the + // two first events are generated. When releasing the key, the last one is + // generated. + // Because S60 does not generate keysyms for EKeyEventDown and EKeyEventUp events, + // we need to do some special tricks to map it to the Qt way. First, we completely + // discard EKeyEventDown events, since they are redundant. Second, since + // EKeyEventUp does not give us a keysym, we need to cache the keysyms from + // the EKeyEvent events. This is what resolveS60ScanCode does. + + + // ### hackish way to send Qt application to background when pressing right softkey + /* + if( keyEvent.iScanCode == EStdKeyDevice1 ) { + S60->window_group->SetOrdinalPosition(-1); + qApp->setActiveWindow(0); + return EKeyWasNotConsumed; + } + */ + + TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode, + keyEvent.iCode); + int keyCode; + if (s60Keysym == EKeyNull){ //some key events have 0 in iCode, for them iScanCode should be used + keyCode = qt_keymapper_private()->mapS60ScanCodesToQt(keyEvent.iScanCode); + } else if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) { + // Normal characters keys. + keyCode = s60Keysym; + } else { + // Special S60 keys. + keyCode = qt_keymapper_private()->mapS60KeyToQt(s60Keysym); + } Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers); QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode, diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index fb2837e..60fc5e1 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -1936,6 +1936,8 @@ extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wPa QLocalePrivate::updateSystemPrivate(); if (!widget->testAttribute(Qt::WA_SetLocale)) widget->dptr()->setLocale_helper(QLocale(), true); + QEvent e(QEvent::LocaleChange); + QApplication::sendEvent(qApp, &e); } } else if (msg.wParam == SPI_SETICONTITLELOGFONT) { @@ -2475,7 +2477,7 @@ extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wPa QApplication::postEvent(widget, new QEvent(QEvent::Close)); else #ifndef QT_NO_MENUBAR - QMenuBar::wceCommands(LOWORD(wParam), (HWND) lParam); + QMenuBar::wceCommands(LOWORD(wParam)); #endif result = true; } diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm index 24498f8..2b9cf85 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac.mm +++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm @@ -202,6 +202,11 @@ static void cleanupCocoaWindowDelegate() QWindowStateChangeEvent e(Qt::WindowStates(widgetData->window_state & ~Qt::WindowMaximized)); qt_sendSpontaneousEvent(qwidget, &e); + } else { + widgetData->window_state = widgetData->window_state & ~Qt::WindowMaximized; + QWindowStateChangeEvent e(Qt::WindowStates(widgetData->window_state + | Qt::WindowMaximized)); + qt_sendSpontaneousEvent(qwidget, &e); } NSRect rect = [[window contentView] frame]; const QSize newSize(rect.size.width, rect.size.height); @@ -305,9 +310,19 @@ static void cleanupCocoaWindowDelegate() Q_UNUSED(newFrame); // saving the current window geometry before the window is maximized QWidget *qwidget = m_windowHash->value(window); - if (qwidget->isWindow() && !(qwidget->windowState() & Qt::WindowMaximized)) { - QWidgetPrivate *widgetPrivate = qt_widget_private(qwidget); - widgetPrivate->topData()->normalGeometry = qwidget->geometry(); + QWidgetPrivate *widgetPrivate = qt_widget_private(qwidget); + if (qwidget->isWindow()) { + if(qwidget->windowState() & Qt::WindowMaximized) { + // Restoring + widgetPrivate->topData()->wasMaximized = false; + } else { + // Maximizing + widgetPrivate->topData()->normalGeometry = qwidget->geometry(); + // If the window was maximized we need to update the coordinates since now it will start at 0,0. + // We do this in a special field that is only used when not restoring but manually resizing the window. + // Since the coordinates are fixed we just set a boolean flag. + widgetPrivate->topData()->wasMaximized = true; + } } return YES; } diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp index ae1f60d..5b58984 100644 --- a/src/gui/kernel/qcursor.cpp +++ b/src/gui/kernel/qcursor.cpp @@ -229,7 +229,7 @@ QT_BEGIN_NAMESPACE Writes the \a cursor to the \a stream. - \sa {Format of the QDataStream operators} + \sa {Serializing Qt Data Types} */ QDataStream &operator<<(QDataStream &s, const QCursor &c) @@ -256,7 +256,7 @@ QDataStream &operator<<(QDataStream &s, const QCursor &c) Reads the \a cursor from the \a stream. - \sa {Format of the QDataStream operators} + \sa {Serializing Qt Data Types} */ QDataStream &operator>>(QDataStream &s, QCursor &c) diff --git a/src/gui/kernel/qdnd_qws.cpp b/src/gui/kernel/qdnd_qws.cpp index e47de00..7e5afc7 100644 --- a/src/gui/kernel/qdnd_qws.cpp +++ b/src/gui/kernel/qdnd_qws.cpp @@ -192,6 +192,10 @@ bool QDragManager::eventFilter(QObject *o, QEvent *e) return false; switch(e->type()) { + case QEvent::ShortcutOverride: + // prevent accelerators from firing while dragging + e->accept(); + return true; case QEvent::KeyPress: case QEvent::KeyRelease: diff --git a/src/gui/kernel/qdnd_x11.cpp b/src/gui/kernel/qdnd_x11.cpp index 0a05d8e..2b12317 100644 --- a/src/gui/kernel/qdnd_x11.cpp +++ b/src/gui/kernel/qdnd_x11.cpp @@ -1299,6 +1299,12 @@ bool QDragManager::eventFilter(QObject * o, QEvent * e) return true; } + if (e->type() == QEvent::ShortcutOverride) { + // prevent accelerators from firing while dragging + e->accept(); + return true; + } + if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) { QKeyEvent *ke = ((QKeyEvent*)e); if (ke->key() == Qt::Key_Escape && e->type() == QEvent::KeyPress) { diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index 956499b..49bdea7 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -612,7 +612,7 @@ void QPinchGesture::setRotationAngle(qreal value) If the gesture has either a horizontal or vertical component, the swipe angle describes the angle between the direction of motion and the x-axis as defined using the standard widget - \l{The Coordinate System}{coordinate system}. + \l{Coordinate System}{coordinate system}. \sa horizontalDirection, verticalDirection */ diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index aa6720e..43facef 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -132,20 +132,21 @@ void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type) QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g); if (list.contains(recognizer)) { m_deletedRecognizers.insert(g, recognizer); - m_gestureToRecognizer.remove(g); } } - foreach (QGestureRecognizer *recognizer, list) { - QList<QGesture *> obsoleteGestures; - QMap<ObjectGesture, QList<QGesture *> >::Iterator iter = m_objectGestures.begin(); - while (iter != m_objectGestures.end()) { - ObjectGesture objectGesture = iter.key(); - if (objectGesture.gesture == type) - obsoleteGestures << iter.value(); - ++iter; + QMap<ObjectGesture, QList<QGesture *> >::const_iterator iter = m_objectGestures.begin(); + while (iter != m_objectGestures.end()) { + ObjectGesture objectGesture = iter.key(); + if (objectGesture.gesture == type) { + foreach (QGesture *g, iter.value()) { + if (QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g)) { + m_gestureToRecognizer.remove(g); + m_obsoleteGestures[recognizer].insert(g); + } + } } - m_obsoleteGestures.insert(recognizer, obsoleteGestures); + ++iter; } } @@ -155,7 +156,16 @@ void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType typ while (iter != m_objectGestures.end()) { ObjectGesture objectGesture = iter.key(); if (objectGesture.gesture == type && target == objectGesture.object.data()) { - qDeleteAll(iter.value()); + QSet<QGesture *> gestures = iter.value().toSet(); + for (QHash<QGestureRecognizer *, QSet<QGesture *> >::iterator + it = m_obsoleteGestures.begin(), e = m_obsoleteGestures.end(); it != e; ++it) { + it.value() -= gestures; + } + foreach (QGesture *g, gestures) { + m_deletedRecognizers.remove(g); + m_gestureToRecognizer.remove(g); + } + qDeleteAll(gestures); iter = m_objectGestures.erase(iter); } else { ++iter; @@ -177,6 +187,9 @@ QGesture *QGestureManager::getState(QObject *object, QGestureRecognizer *recogni #ifndef QT_NO_GRAPHICSVIEW } else { Q_ASSERT(qobject_cast<QGraphicsObject *>(object)); + QGraphicsObject *graphicsObject = static_cast<QGraphicsObject *>(object); + if (graphicsObject->QGraphicsItem::d_func()->inDestructor) + return 0; #endif } @@ -275,24 +288,14 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *, // i.e. were canceled QSet<QGesture *> canceledGestures = m_activeGestures & notGestures; - // start timers for new gestures in maybe state - foreach (QGesture *state, newMaybeGestures) { - QBasicTimer &timer = m_maybeGestures[state]; - if (!timer.isActive()) - timer.start(3000, this); - } - // kill timers for gestures that were in maybe state + // new gestures in maybe state + m_maybeGestures += newMaybeGestures; + + // gestures that were in maybe state QSet<QGesture *> notMaybeGestures = (startedGestures | triggeredGestures | finishedGestures | canceledGestures | notGestures); - foreach(QGesture *gesture, notMaybeGestures) { - QHash<QGesture *, QBasicTimer>::iterator it = - m_maybeGestures.find(gesture); - if (it != m_maybeGestures.end()) { - it.value().stop(); - m_maybeGestures.erase(it); - } - } + m_maybeGestures -= notMaybeGestures; Q_ASSERT((startedGestures & finishedGestures).isEmpty()); Q_ASSERT((startedGestures & newMaybeGestures).isEmpty()); @@ -336,7 +339,7 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *, !finishedGestures.isEmpty() || !canceledGestures.isEmpty()) { DEBUG() << "QGestureManager::filterEventThroughContexts:" << "\n\tactiveGestures:" << m_activeGestures - << "\n\tmaybeGestures:" << m_maybeGestures.keys() + << "\n\tmaybeGestures:" << m_maybeGestures << "\n\tstarted:" << startedGestures << "\n\ttriggered:" << triggeredGestures << "\n\tfinished:" << finishedGestures @@ -675,26 +678,6 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures, } } -void QGestureManager::timerEvent(QTimerEvent *event) -{ - QHash<QGesture *, QBasicTimer>::iterator it = m_maybeGestures.begin(), - e = m_maybeGestures.end(); - for (; it != e; ) { - QBasicTimer &timer = it.value(); - Q_ASSERT(timer.isActive()); - if (timer.timerId() == event->timerId()) { - timer.stop(); - QGesture *gesture = it.key(); - it = m_maybeGestures.erase(it); - DEBUG() << "QGestureManager::timerEvent: gesture stopped due to timeout:" - << gesture; - recycle(gesture); - } else { - ++it; - } - } -} - void QGestureManager::recycle(QGesture *gesture) { QGestureRecognizer *recognizer = m_gestureToRecognizer.value(gesture, 0); diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index a0ff83f..c452f49 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -85,7 +85,6 @@ public: void recycle(QGesture *gesture); protected: - void timerEvent(QTimerEvent *event); bool filterEventThroughContexts(const QMultiMap<QObject *, Qt::GestureType> &contexts, QEvent *event); @@ -93,7 +92,7 @@ private: QMultiMap<Qt::GestureType, QGestureRecognizer *> m_recognizers; QSet<QGesture *> m_activeGestures; - QHash<QGesture *, QBasicTimer> m_maybeGestures; + QSet<QGesture *> m_maybeGestures; enum State { Gesture, @@ -127,7 +126,7 @@ private: int m_lastCustomGestureId; - QHash<QGestureRecognizer *, QList<QGesture *> > m_obsoleteGestures; + QHash<QGestureRecognizer *, QSet<QGesture *> > m_obsoleteGestures; QHash<QGesture *, QGestureRecognizer *> m_deletedRecognizers; void cleanupGesturesForRemovedRecognizer(QGesture *gesture); diff --git a/src/gui/kernel/qsound_mac.mm b/src/gui/kernel/qsound_mac.mm index 71fd663..2aff44d 100644 --- a/src/gui/kernel/qsound_mac.mm +++ b/src/gui/kernel/qsound_mac.mm @@ -88,14 +88,14 @@ QT_END_NAMESPACE QT_USE_NAMESPACE -@interface QMacSoundDelegate : NSObject<NSSoundDelegate> { +@interface QT_MANGLE_NAMESPACE(QMacSoundDelegate) : NSObject<NSSoundDelegate> { QSound *qSound; // may be null. QAuServerMac* server; } -(id)initWithQSound:(QSound*)sound:(QAuServerMac*)server; @end -@implementation QMacSoundDelegate +@implementation QT_MANGLE_NAMESPACE(QMacSoundDelegate) -(id)initWithQSound:(QSound*)s:(QAuServerMac*)serv { self = [super init]; if(self) { @@ -172,7 +172,7 @@ NSSound *QAuServerMac::createNSSound(const QString &fileName, QSound *qSound) { NSString *nsFileName = const_cast<NSString *>(reinterpret_cast<const NSString *>(QCFString::toCFStringRef(fileName))); NSSound * const nsSound = [[NSSound alloc] initWithContentsOfFile: nsFileName byReference:YES]; - QMacSoundDelegate * const delegate = [[QMacSoundDelegate alloc] initWithQSound:qSound:this]; + QT_MANGLE_NAMESPACE(QMacSoundDelegate) * const delegate = [[QT_MANGLE_NAMESPACE(QMacSoundDelegate) alloc] initWithQSound:qSound:this]; [nsSound setDelegate:delegate]; [nsFileName release]; return nsSound; diff --git a/src/gui/kernel/qt_mac_p.h b/src/gui/kernel/qt_mac_p.h index 3341ce1..ca9541a 100644 --- a/src/gui/kernel/qt_mac_p.h +++ b/src/gui/kernel/qt_mac_p.h @@ -57,7 +57,9 @@ #ifdef __OBJC__ #include <Cocoa/Cocoa.h> +#ifdef QT_MAC_USE_COCOA #include <objc/runtime.h> +#endif // QT_MAC_USE_COCOA #endif #include <CoreServices/CoreServices.h> diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 58da302..f560458 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -62,6 +62,7 @@ #include "QtGui/qevent.h" #include "qpointer.h" #include "qapplication.h" +#include "qelapsedtimer.h" #include <w32std.h> #include <coecntrl.h> #include <eikenv.h> @@ -102,16 +103,21 @@ public: int defaultDpiX; int defaultDpiY; WId curWin; - int virtualMouseLastKey; enum PressedKeys { Select = 0x1, Right = 0x2, Down = 0x4, Left = 0x8, - Up = 0x10 + Up = 0x10, + LeftUp = 0x20, + RightUp = 0x40, + RightDown = 0x80, + LeftDown = 0x100 }; int virtualMousePressedKeys; // of the above type, but avoids casting problems - int virtualMouseAccel; + int virtualMouseAccelDX; + int virtualMouseAccelDY; + QElapsedTimer virtualMouseAccelTimeout; int virtualMouseMaxAccel; #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS int brokenPointerCursors : 1; @@ -222,6 +228,7 @@ private: private: QWidget *qwidget; QLongTapTimer* m_longTapDetector; + QElapsedTimer m_doubleClickTimer; bool m_ignoreFocusChanged : 1; bool m_symbianPopupIsOpen : 1; @@ -246,7 +253,7 @@ inline void QS60Data::updateScreenSize() S60->screenWidthInTwips = params.iTwipsSize.iWidth; S60->screenHeightInTwips = params.iTwipsSize.iHeight; - S60->virtualMouseMaxAccel = qMax(S60->screenHeightInPixels, S60->screenWidthInPixels) / 20; + S60->virtualMouseMaxAccel = qMax(S60->screenHeightInPixels, S60->screenWidthInPixels) / 10; TReal inches = S60->screenHeightInTwips / (TReal)KTwipsPerInch; S60->defaultDpiY = S60->screenHeightInPixels / inches; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 6f4a20f..6d48e0e 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -1388,6 +1388,9 @@ QWidget::~QWidget() qWarning("QWidget: %s (%s) deleted while being painted", className(), name()); #endif + foreach (Qt::GestureType type, d->gestureContext.keys()) + ungrabGesture(type); + // force acceptDrops false before winId is destroyed. d->registerDropSite(false); @@ -1480,7 +1483,8 @@ QWidget::~QWidget() d->needsFlush = 0; // set all QPointers for this object to zero - QObjectPrivate::clearGuards(this); + if (d->hasGuards) + QObjectPrivate::clearGuards(this); if (d->declarativeData) { QAbstractDeclarativeData::destroyed(d->declarativeData, this); @@ -1578,6 +1582,11 @@ void QWidgetPrivate::createTLExtra() x->inTopLevelResize = false; x->inRepaint = false; x->embedded = 0; +#ifdef Q_WS_MAC +#ifdef QT_MAC_USE_COCOA + x->wasMaximized = false; +#endif // QT_MAC_USE_COCOA +#endif // Q_WS_MAC createTLSysExtra(); #ifdef QWIDGET_EXTRA_DEBUG static int count = 0; @@ -2535,7 +2544,7 @@ void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool Q_Q(QWidget); QStyle *oldStyle = q->style(); #ifndef QT_NO_STYLE_STYLESHEET - QStyle *origStyle = 0; + QWeakPointer<QStyle> origStyle; #endif #ifdef Q_WS_MAC @@ -2549,7 +2558,7 @@ void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool createExtra(); #ifndef QT_NO_STYLE_STYLESHEET - origStyle = extra->style; + origStyle = extra->style.data(); #endif extra->style = newStyle; } @@ -2578,23 +2587,23 @@ void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool } } - QEvent e(QEvent::StyleChange); - QApplication::sendEvent(q, &e); -#ifdef QT3_SUPPORT - q->styleChange(*oldStyle); -#endif - #ifndef QT_NO_STYLE_STYLESHEET if (!qobject_cast<QStyleSheetStyle*>(newStyle)) { - if (const QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(origStyle)) { + if (const QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(origStyle.data())) { cssStyle->clearWidgetFont(q); } } #endif + QEvent e(QEvent::StyleChange); + QApplication::sendEvent(q, &e); +#ifdef QT3_SUPPORT + q->styleChange(*oldStyle); +#endif + #ifndef QT_NO_STYLE_STYLESHEET // dereference the old stylesheet style - if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(origStyle)) + if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(origStyle.data())) proxy->deref(); #endif } @@ -5583,52 +5592,23 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * pixmapOffset = painterTransform.map(pixmapOffset); } - QRect effectRect; - if (mode == QGraphicsEffect::PadToEffectiveBoundingRect) { + if (mode == QGraphicsEffect::PadToEffectiveBoundingRect) effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); - - } else if (mode == QGraphicsEffect::PadToTransparentBorder) { + else if (mode == QGraphicsEffect::PadToTransparentBorder) effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect(); - - } else { + else effectRect = sourceRect.toAlignedRect(); - } - if (offset) *offset = effectRect.topLeft(); - if (deviceCoordinates) { - // Clip to device rect. - int left, top, right, bottom; - effectRect.getCoords(&left, &top, &right, &bottom); - if (left < 0) { - if (offset) - offset->rx() += -left; - effectRect.setX(0); - } - if (top < 0) { - if (offset) - offset->ry() += -top; - effectRect.setY(0); - } - // NB! We use +-1 for historical reasons (see QRect documentation). - QPaintDevice *device = context->painter->device(); - const int deviceWidth = device->width(); - const int deviceHeight = device->height(); - if (right + 1 > deviceWidth) - effectRect.setRight(deviceWidth - 1); - if (bottom + 1 > deviceHeight) - effectRect.setBottom(deviceHeight -1); - } - pixmapOffset -= effectRect.topLeft(); QPixmap pixmap(effectRect.size()); pixmap.fill(Qt::transparent); - m_widget->render(&pixmap, pixmapOffset); + m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren); return pixmap; } #endif //QT_NO_GRAPHICSEFFECT @@ -6232,6 +6212,12 @@ void QWidget::setFocus(Qt::FocusReason reason) QApplication::sendEvent(that->style(), &event); } if (!isHidden()) { +#ifndef QT_NO_GRAPHICSVIEW + // Update proxy state + if (QWExtra *topData = window()->d_func()->extra) + if (topData->proxyWidget && topData->proxyWidget->hasFocus()) + topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget(); +#endif // Send event to self QFocusEvent event(QEvent::FocusIn, reason); QPointer<QWidget> that = f; @@ -6740,6 +6726,18 @@ void QWidget::setGeometry(const QRect &r) */ QByteArray QWidget::saveGeometry() const { +#ifdef QT_MAC_USE_COCOA + // We check if the window was maximized during this invocation. If so, we need to record the + // starting position as 0,0. + Q_D(const QWidget); + QRect newFramePosition = frameGeometry(); + QRect newNormalPosition = normalGeometry(); + if(d->topData()->wasMaximized && !(windowState() & Qt::WindowMaximized)) { + // Change the starting position + newFramePosition.moveTo(0, 0); + newNormalPosition.moveTo(0, 0); + } +#endif // QT_MAC_USE_COCOA QByteArray array; QDataStream stream(&array, QIODevice::WriteOnly); stream.setVersion(QDataStream::Qt_4_0); @@ -6749,8 +6747,13 @@ QByteArray QWidget::saveGeometry() const stream << magicNumber << majorVersion << minorVersion +#ifdef QT_MAC_USE_COCOA + << newFramePosition + << newNormalPosition +#else << frameGeometry() << normalGeometry() +#endif // QT_MAC_USE_COCOA << qint32(QApplication::desktop()->screenNumber(this)) << quint8(windowState() & Qt::WindowMaximized) << quint8(windowState() & Qt::WindowFullScreen); diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index e29b755..f12c956 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -3824,9 +3824,35 @@ void QWidgetPrivate::raise_sys() #if QT_MAC_USE_COCOA QMacCocoaAutoReleasePool pool; if (isRealWindow()) { - // Calling orderFront shows the window on Cocoa too. + // With the introduction of spaces it is not as simple as just raising the window. + // First we need to check if we are in the right space. If we are, then we just continue + // as usual. The problem comes when we are not in the active space. There are two main cases: + // 1. Our parent was moved to a new space. In this case we want the window to be raised + // in the same space as its parent. + // 2. We don't have a parent. For this case we will just raise the window and let Cocoa + // switch to the corresponding space. + // NOTICE: There are a lot of corner cases here. We are keeping this simple for now, if + // required we will introduce special handling for some of them. if (!q->testAttribute(Qt::WA_DontShowOnScreen) && q->isVisible()) { - [qt_mac_window_for(q) orderFront:qt_mac_window_for(q)]; + OSWindowRef window = qt_mac_window_for(q); + // isOnActiveSpace is available only from 10.6 onwards, so we need to check if it is + // available before calling it. + if([window respondsToSelector:@selector(isOnActiveSpace)]) { + if(![window performSelector:@selector(isOnActiveSpace)]) { + QWidget *parentWidget = q->parentWidget(); + if(parentWidget) { + OSWindowRef parentWindow = qt_mac_window_for(parentWidget); + if(parentWindow && [parentWindow isOnActiveSpace]) { + // The window was created in a different space. Therefore if we want + // to show it in the current space we need to recreate it in the new + // space. + recreateMacWindow(); + window = qt_mac_window_for(q); + } + } + } + } + [window orderFront:window]; } if (qt_mac_raise_process) { //we get to be the active process now ProcessSerialNumber psn; diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 9926b2c..412705a 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -170,6 +170,14 @@ struct QTLWExtra { WindowGroupRef group; IconRef windowIcon; // the current window icon, if set with setWindowIcon_sys. quint32 savedWindowAttributesFromMaximized; // Saved attributes from when the calling updateMaximizeButton_sys() +#ifdef QT_MAC_USE_COCOA + // This value is just to make sure we maximize and restore to the right location, yet we allow apps to be maximized and + // manually resized. + // The name is misleading, since this is set when maximizing the window. It is a hint to saveGeometry(..) to record the + // starting position as 0,0 instead of the normal starting position. + bool wasMaximized; +#endif // QT_MAC_USE_COCOA + #elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS #ifndef QT_NO_QWS_MANAGER QWSManager *qwsManager; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index a0429d3..02e7cb8 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -387,7 +387,6 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de | EPointerFilterMove | EPointerFilterDrag, 0); drawableWindow->EnableVisibilityChangeEvents(); - s60UpdateIsOpaque(); } q->setAttribute(Qt::WA_WState_Created); @@ -400,6 +399,9 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de // this generates a WinIdChanged event. setWinId(control.take()); + if (!desktop) + s60UpdateIsOpaque(); // must be called after setWinId() + } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create native child widget QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) ); diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 7d647b7..5482da3 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -123,9 +123,11 @@ static PtrWTClose ptrWTClose = 0; static PtrWTInfo ptrWTInfo = 0; static PtrWTQueueSizeGet ptrWTQueueSizeGet = 0; static PtrWTQueueSizeSet ptrWTQueueSizeSet = 0; +#ifndef QT_NO_TABLETEVENT static void init_wintab_functions(); static void qt_tablet_init(); static void qt_tablet_cleanup(); +#endif // QT_NO_TABLETEVENT extern HCTX qt_tablet_context; extern bool qt_tablet_tilt_support; @@ -136,6 +138,8 @@ QWidget* qt_get_tablet_widget() } extern bool qt_is_gui_used; + +#ifndef QT_NO_TABLETEVENT static void init_wintab_functions() { #if defined(Q_OS_WINCE) @@ -227,6 +231,7 @@ static void qt_tablet_cleanup() delete qt_tablet_widget; qt_tablet_widget = 0; } +#endif // QT_NO_TABLETEVENT const QString qt_reg_winclass(QWidget *w); // defined in qapplication_win.cpp @@ -512,8 +517,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO DestroyWindow(destroyw); } +#ifndef QT_NO_TABLETEVENT if (q != qt_tablet_widget && QWidgetPrivate::mapper) qt_tablet_init(); +#endif // QT_NO_TABLETEVENT if (q->testAttribute(Qt::WA_DropSiteRegistered)) registerDropSite(true); diff --git a/src/gui/kernel/qwidget_wince.cpp b/src/gui/kernel/qwidget_wince.cpp index 509847b..fc1e52c 100644 --- a/src/gui/kernel/qwidget_wince.cpp +++ b/src/gui/kernel/qwidget_wince.cpp @@ -63,6 +63,7 @@ typedef BOOL (API *PtrWTGet)(HCTX, LPLOGCONTEXT); typedef int (API *PtrWTQueueSizeGet)(HCTX); typedef BOOL (API *PtrWTQueueSizeSet)(HCTX, int); +#ifndef QT_NO_TABLETEVENT static void qt_tablet_init_wce(); static void qt_tablet_cleanup_wce(); @@ -135,6 +136,7 @@ static void qt_tablet_cleanup_wce() { delete qt_tablet_widget; qt_tablet_widget = 0; } +#endif // QT_NO_TABLETEVENT // The internal qWinRequestConfig, defined in qapplication_win.cpp, stores move, @@ -358,8 +360,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO DestroyWindow(destroyw); } +#ifndef QT_NO_TABLETEVENT if (q != qt_tablet_widget && QWidgetPrivate::mapper) qt_tablet_init_wce(); +#endif // QT_NO_TABLETEVENT if (q->testAttribute(Qt::WA_DropSiteRegistered)) registerDropSite(true); diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 37ac6bf..43f510c 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -3000,7 +3000,7 @@ Picture QX11Data::getSolidFill(int screen, const QColor &c) return X11->solid_fills[i].picture; } // none found, replace one - int i = rand() % 16; + int i = qrand() % 16; if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) { XRenderFreePicture (X11->display, X11->solid_fills[i].picture); |