diff options
Diffstat (limited to 'src/gui/kernel')
53 files changed, 1177 insertions, 833 deletions
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 8859358..f2bd288 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -188,9 +188,8 @@ embedded { HEADERS += \ kernel/qeventdispatcher_glib_qws_p.h QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB + LIBS_PRIVATE +=$$QT_LIBS_GLIB } - - } !embedded:!x11:mac { @@ -207,7 +206,8 @@ embedded { qcocoaapplication_mac_p.h \ qcocoaapplicationdelegate_mac_p.h \ qmacgesturerecognizer_mac_p.h \ - qmultitouch_mac_p.h + qmultitouch_mac_p.h \ + qcocoasharedwindowmethods_mac_p.h OBJECTIVE_SOURCES += \ kernel/qcursor_mac.mm \ diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp index 5f5650f..3eaf2e1 100644 --- a/src/gui/kernel/qaction.cpp +++ b/src/gui/kernel/qaction.cpp @@ -100,6 +100,21 @@ QActionPrivate::~QActionPrivate() { } +bool QActionPrivate::showStatusText(QWidget *widget, const QString &str) +{ +#ifdef QT_NO_STATUSTIP + Q_UNUSED(widget); + Q_UNUSED(str); +#else + if(QObject *object = widget ? widget : parent) { + QStatusTipEvent tip(str); + QApplication::sendEvent(object, &tip); + return true; + } +#endif + return false; +} + void QActionPrivate::sendDataChanged() { Q_Q(QAction); @@ -286,7 +301,7 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map) Actions with a softkey role defined are only visible in the softkey bar when the widget containing the action has focus. If no widget currently has focus, the softkey framework will traverse up the - widget parent heirarchy looking for a widget containing softkey actions. + widget parent hierarchy looking for a widget containing softkey actions. */ /*! @@ -1206,16 +1221,7 @@ QAction::setData(const QVariant &data) bool QAction::showStatusText(QWidget *widget) { -#ifdef QT_NO_STATUSTIP - Q_UNUSED(widget); -#else - if(QObject *object = widget ? widget : parent()) { - QStatusTipEvent tip(statusTip()); - QApplication::sendEvent(object, &tip); - return true; - } -#endif - return false; + return d_func()->showStatusText(widget, statusTip()); } /*! diff --git a/src/gui/kernel/qaction_p.h b/src/gui/kernel/qaction_p.h index 2527a02..f7b035b 100644 --- a/src/gui/kernel/qaction_p.h +++ b/src/gui/kernel/qaction_p.h @@ -75,6 +75,8 @@ public: QActionPrivate(); ~QActionPrivate(); + bool showStatusText(QWidget *w, const QString &str); + QPointer<QActionGroup> group; QString text; QString iconText; diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 987aa26..bd13423 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -791,7 +791,8 @@ void QApplicationPrivate::construct( } //make sure the plugin is loaded - qt_guiPlatformPlugin(); + if (qt_is_gui_used) + qt_guiPlatformPlugin(); #endif } @@ -932,7 +933,8 @@ void QApplicationPrivate::initialize() QApplicationPrivate::wheel_scroll_lines = 3; #endif - initializeMultitouch(); + if (qt_is_gui_used) + initializeMultitouch(); } /*! @@ -3627,12 +3629,46 @@ bool QApplication::notify(QObject *receiver, QEvent *e) // walk through parents and check for gestures if (qt_gestureManager) { - if (receiver->isWidgetType()) { - if (qt_gestureManager->filterEvent(static_cast<QWidget *>(receiver), e)) - return true; - } else if (QGesture *gesture = qobject_cast<QGesture *>(receiver)) { - if (qt_gestureManager->filterEvent(gesture, e)) - return true; + switch (e->type()) { + case QEvent::Paint: + case QEvent::MetaCall: + case QEvent::DeferredDelete: + case QEvent::DragEnter: case QEvent::DragMove: case QEvent::DragLeave: + case QEvent::Drop: case QEvent::DragResponse: + case QEvent::ChildAdded: case QEvent::ChildPolished: +#ifdef QT3_SUPPORT + case QEvent::ChildInsertedRequest: + case QEvent::ChildInserted: + case QEvent::LayoutHint: +#endif + case QEvent::ChildRemoved: + case QEvent::UpdateRequest: + case QEvent::UpdateLater: + case QEvent::AccessibilityPrepare: + case QEvent::LocaleChange: + case QEvent::Style: + case QEvent::IconDrag: + case QEvent::StyleChange: + case QEvent::AccessibilityHelp: + case QEvent::AccessibilityDescription: + case QEvent::GraphicsSceneDragEnter: + case QEvent::GraphicsSceneDragMove: + case QEvent::GraphicsSceneDragLeave: + case QEvent::GraphicsSceneDrop: + case QEvent::DynamicPropertyChange: + case QEvent::NetworkReplyUpdated: + break; + default: + if (receiver->isWidgetType()) { + if (qt_gestureManager->filterEvent(static_cast<QWidget *>(receiver), e)) + return true; + } else { + // a special case for events that go to QGesture objects. + // We pass the object to the gesture manager and it'll figure + // out if it's QGesture or not. + if (qt_gestureManager->filterEvent(receiver, e)) + return true; + } } } @@ -4090,9 +4126,15 @@ bool QApplication::notify(QObject *receiver, QEvent *e) bool acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents); touchEvent->setWidget(widget); touchEvent->setAccepted(acceptTouchEvents); + QWeakPointer<QWidget> p = widget; res = acceptTouchEvents && d->notify_helper(widget, touchEvent); eventAccepted = touchEvent->isAccepted(); - widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, res && eventAccepted); + if (p.isNull()) { + // widget was deleted + widget = 0; + } else { + 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. @@ -4101,11 +4143,20 @@ bool QApplication::notify(QObject *receiver, QEvent *e) d->widgetForTouchPointId[touchPoint.id()] = widget; } break; - } else if (widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) { + } else if (p.isNull() || widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) { break; } + QPoint offset = widget->pos(); widget = widget->parentWidget(); - d->updateTouchPointsForWidget(widget, touchEvent); + touchEvent->setWidget(widget); + for (int i = 0; i < touchEvent->_touchPoints.size(); ++i) { + QTouchEvent::TouchPoint &pt = touchEvent->_touchPoints[i]; + QRectF rect = pt.rect(); + rect.moveCenter(offset); + pt.d->rect = rect; + pt.d->startPos = pt.startPos() + offset; + pt.d->lastPos = pt.lastPos() + offset; + } } touchEvent->setAccepted(eventAccepted); @@ -5416,9 +5467,11 @@ void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven 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); + touchPoint.d->rect = rect; + if (touchPoint.state() == Qt::TouchPointPressed) { + touchPoint.d->startPos = widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta; + touchPoint.d->lastPos = widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta; + } } } @@ -5462,16 +5515,20 @@ void QApplicationPrivate::translateRawTouchEvent(QWidget *window, for (int i = 0; i < touchPoints.count(); ++i) { QTouchEvent::TouchPoint touchPoint = touchPoints.at(i); + // explicitly detach from the original touch point that we got, so even + // if the touchpoint structs are reused, we will make a copy that we'll + // deliver to the user (which might want to store the struct for later use). + touchPoint.d = touchPoint.d->detach(); // update state - QWidget *widget = 0; + QWeakPointer<QWidget> widget; 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 + ? QWeakPointer<QWidget>() : d->widgetForTouchPointId.constBegin().value(); } @@ -5488,20 +5545,21 @@ void QApplicationPrivate::translateRawTouchEvent(QWidget *window, if (deviceType == QTouchEvent::TouchScreen) { int closestTouchPointId = d->findClosestTouchPointId(touchPoint.screenPos()); - QWidget *closestWidget = d->widgetForTouchPointId.value(closestTouchPointId); + QWidget *closestWidget = d->widgetForTouchPointId.value(closestTouchPointId).data(); if (closestWidget - && (widget->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget))) { + && (widget.data()->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget.data()))) { widget = closestWidget; } } d->widgetForTouchPointId[touchPoint.id()] = widget; - touchPoint.setStartScreenPos(touchPoint.screenPos()); - touchPoint.setLastScreenPos(touchPoint.screenPos()); - touchPoint.setStartNormalizedPos(touchPoint.normalizedPos()); - touchPoint.setLastNormalizedPos(touchPoint.normalizedPos()); + touchPoint.d->startScreenPos = touchPoint.screenPos(); + touchPoint.d->lastScreenPos = touchPoint.screenPos(); + touchPoint.d->startNormalizedPos = touchPoint.normalizedPos(); + touchPoint.d->lastNormalizedPos = touchPoint.normalizedPos(); if (touchPoint.pressure() < qreal(0.)) - touchPoint.setPressure(qreal(1.)); + touchPoint.d->pressure = qreal(1.); + d->appCurrentTouchPoints.insert(touchPoint.id(), touchPoint); break; } @@ -5512,12 +5570,14 @@ void QApplicationPrivate::translateRawTouchEvent(QWidget *window, 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()); + touchPoint.d->startScreenPos = previousTouchPoint.startScreenPos(); + touchPoint.d->lastScreenPos = previousTouchPoint.screenPos(); + touchPoint.d->startPos = previousTouchPoint.startPos(); + touchPoint.d->lastPos = previousTouchPoint.pos(); + touchPoint.d->startNormalizedPos = previousTouchPoint.startNormalizedPos(); + touchPoint.d->lastNormalizedPos = previousTouchPoint.normalizedPos(); if (touchPoint.pressure() < qreal(0.)) - touchPoint.setPressure(qreal(0.)); + touchPoint.d->pressure = qreal(0.); break; } default: @@ -5527,23 +5587,25 @@ void QApplicationPrivate::translateRawTouchEvent(QWidget *window, 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()); + touchPoint.d->startScreenPos = previousTouchPoint.startScreenPos(); + touchPoint.d->lastScreenPos = previousTouchPoint.screenPos(); + touchPoint.d->startPos = previousTouchPoint.startPos(); + touchPoint.d->lastPos = previousTouchPoint.pos(); + touchPoint.d->startNormalizedPos = previousTouchPoint.startNormalizedPos(); + touchPoint.d->lastNormalizedPos = previousTouchPoint.normalizedPos(); if (touchPoint.pressure() < qreal(0.)) - touchPoint.setPressure(qreal(1.)); + touchPoint.d->pressure = qreal(1.); d->appCurrentTouchPoints[touchPoint.id()] = touchPoint; break; } - Q_ASSERT(widget != 0); + Q_ASSERT(widget.data() != 0); // make the *scene* functions return the same as the *screen* functions - touchPoint.setSceneRect(touchPoint.screenRect()); - touchPoint.setStartScenePos(touchPoint.startScreenPos()); - touchPoint.setLastScenePos(touchPoint.lastScreenPos()); + touchPoint.d->sceneRect = touchPoint.screenRect(); + touchPoint.d->startScenePos = touchPoint.startScreenPos(); + touchPoint.d->lastScenePos = touchPoint.lastScreenPos(); - StatesAndTouchPoints &maskAndPoints = widgetsNeedingEvents[widget]; + StatesAndTouchPoints &maskAndPoints = widgetsNeedingEvents[widget.data()]; maskAndPoints.first |= touchPoint.state(); if (touchPoint.isPrimary()) maskAndPoints.first |= Qt::TouchPointPrimary; diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index 84da56e..688e51f 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1687,7 +1687,10 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event UInt32 mac_buttons = 0; GetEventParameter(event, kEventParamMouseChord, typeUInt32, 0, sizeof(mac_buttons), 0, &mac_buttons); - buttons = qt_mac_get_buttons(mac_buttons); + if (ekind != kEventMouseWheelMoved) + buttons = qt_mac_get_buttons(mac_buttons); + else + buttons = QApplication::mouseButtons(); } int wheel_deltaX = 0; @@ -2449,7 +2452,7 @@ OSStatus QApplicationPrivate::globalAppleEventProcessor(const AppleEvent *ae, Ap switch(aeID) { case kAEQuitApplication: { extern bool qt_mac_quit_menu_item_enabled; // qmenu_mac.cpp - if(!QApplicationPrivate::modalState() && qt_mac_quit_menu_item_enabled) { + if (qt_mac_quit_menu_item_enabled) { QCloseEvent ev; QApplication::sendSpontaneousEvent(app, &ev); if(ev.isAccepted()) { diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 992e4be..14d7215 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -511,7 +511,7 @@ public: QWidget *gestureWidget; - QMap<int, QWidget *> widgetForTouchPointId; + QMap<int, QWeakPointer<QWidget> > widgetForTouchPointId; QMap<int, QTouchEvent::TouchPoint> appCurrentTouchPoints; static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); void initializeMultitouch(); diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index d23b071..1a103ef 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -133,36 +133,46 @@ private: TTimeIntervalMicroSeconds iDuration; }; +static QS60Beep* qt_S60Beep = 0; + QS60Beep::~QS60Beep() { + if (iToneUtil) { + switch (iState) { + case EBeepPlaying: + iToneUtil->CancelPlay(); + break; + case EBeepNotPrepared: + iToneUtil->CancelPrepare(); + break; + } + } delete iToneUtil; } QS60Beep* QS60Beep::NewL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration) { - QS60Beep* self=new (ELeave) QS60Beep(); + QS60Beep* self = new (ELeave) QS60Beep(); CleanupStack::PushL(self); self->ConstructL(aFrequency, aDuration); CleanupStack::Pop(); return self; -}; +} void QS60Beep::ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration) { - iToneUtil=CMdaAudioToneUtility::NewL(*this); - iState=EBeepNotPrepared; - iFrequency=aFrequency; - iDuration=aDuration; - iToneUtil->PrepareToPlayTone(iFrequency,iDuration); + iToneUtil = CMdaAudioToneUtility::NewL(*this); + iState = EBeepNotPrepared; + iFrequency = aFrequency; + iDuration = aDuration; + iToneUtil->PrepareToPlayTone(iFrequency, iDuration); } void QS60Beep::Play() { - if (iState != EBeepNotPrepared) { - if (iState == EBeepPlaying) { - iToneUtil->CancelPlay(); - iState = EBeepPrepared; - } + if (iState == EBeepPlaying) { + iToneUtil->CancelPlay(); + iState = EBeepPrepared; } iToneUtil->Play(); @@ -173,13 +183,14 @@ void QS60Beep::MatoPrepareComplete(TInt aError) { if (aError == KErrNone) { iState = EBeepPrepared; + Play(); } } void QS60Beep::MatoPlayComplete(TInt aError) { Q_UNUSED(aError); - iState=EBeepPrepared; + iState = EBeepPrepared; } @@ -319,7 +330,11 @@ void QLongTapTimer::RunL() } QSymbianControl::QSymbianControl(QWidget *w) - : CCoeControl(), qwidget(w), m_ignoreFocusChanged(false) + : CCoeControl() + , qwidget(w) + , m_longTapDetector(0) + , m_ignoreFocusChanged(0) + , m_symbianPopupIsOpen(0) { } @@ -346,6 +361,8 @@ void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) SetFocusing(true); m_longTapDetector = QLongTapTimer::NewL(this); + + DrawableWindow()->SetPointerGrab(ETrue); } } @@ -357,9 +374,6 @@ QSymbianControl::~QSymbianControl() setFocusSafely(false); S60->appUi()->RemoveFromStack(this); delete m_longTapDetector; - - if(m_previousEventLongTap) - QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & ~Qt::RightButton; } void QSymbianControl::setWidget(QWidget *w) @@ -374,19 +388,11 @@ void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, cons alienWidget = qwidget->childAt(widgetPos); if (!alienWidget) alienWidget = qwidget; - QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons &(~Qt::LeftButton); - QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | Qt::RightButton; - QMouseEvent mEvent(QEvent::MouseButtonPress, alienWidget->mapFrom(qwidget, widgetPos), globalPos, - Qt::RightButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier); - - bool res = sendMouseEvent(alienWidget, &mEvent); #if !defined(QT_NO_CONTEXTMENU) - QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse, widgetPos, globalPos, mEvent.modifiers()); + QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse, widgetPos, globalPos, Qt::NoModifier); qt_sendSpontaneousEvent(alienWidget, &contextMenuEvent); #endif - - m_previousEventLongTap = true; } #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER @@ -468,41 +474,6 @@ void QSymbianControl::HandlePointerEventL(const TPointerEvent& pEvent) QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent)); } -typedef QPair<QWidget*,QMouseEvent> Event; - -/* - * Helper function called by HandlePointerEvent - separated to keep that function readable - */ -static void generateEnterLeaveEvents(QList<Event> &events, QWidget *widgetUnderPointer, - QPoint globalPos, Qt::MouseButton button, Qt::KeyboardModifiers modifiers) -{ - //moved to another widget, create enter and leave events - if (S60->lastPointerEventTarget) { - QMouseEvent mEventLeave(QEvent::Leave, S60->lastPointerEventTarget->mapFromGlobal( - S60->lastCursorPos), S60->lastCursorPos, button, QApplicationPrivate::mouse_buttons, - modifiers); - events.append(Event(S60->lastPointerEventTarget, mEventLeave)); - } - if (widgetUnderPointer) { - QMouseEvent mEventEnter(QEvent::Enter, widgetUnderPointer->mapFromGlobal(globalPos), - globalPos, button, QApplicationPrivate::mouse_buttons, modifiers); - - events.append(Event(widgetUnderPointer, mEventEnter)); -#ifndef QT_NO_CURSOR - S60->curWin = widgetUnderPointer->effectiveWinId(); - if (!QApplication::overrideCursor()) { -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - if (S60->brokenPointerCursors) - qt_symbian_set_pointer_sprite(widgetUnderPointer->cursor()); - else -#endif - qt_symbian_setWindowCursor(widgetUnderPointer->cursor(), S60->curWin); - } -#endif - } -} - - void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent) { QMouseEvent::Type type; @@ -510,91 +481,77 @@ void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent) mapS60MouseEventTypeToQt(&type, &button, &pEvent); Qt::KeyboardModifiers modifiers = mapToQtModifiers(pEvent.iModifiers); - if (m_previousEventLongTap) - if (type == QEvent::MouseButtonRelease){ - button = Qt::RightButton; - QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & ~Qt::RightButton; - m_previousEventLongTap = false; - } - if (type == QMouseEvent::None) - return; - - // store events for later sending/saving - QList<Event > events; - QPoint widgetPos = QPoint(pEvent.iPosition.iX, pEvent.iPosition.iY); TPoint controlScreenPos = PositionRelativeToScreen(); QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos; + S60->lastCursorPos = globalPos; + S60->lastPointerEventPos = widgetPos; - // widgets interested in the event - QWidget *widgetUnderPointer = qwidget->childAt(widgetPos); - if (!widgetUnderPointer) - widgetUnderPointer = qwidget; //i.e. this container widget + QWidget *mouseGrabber = QWidget::mouseGrabber(); - QWidget *widgetWithMouseGrab = QWidget::mouseGrabber(); + QWidget *popupWidget = qApp->activePopupWidget(); + QWidget *popupReceiver = 0; + if (popupWidget) { + QWidget *popupChild = popupWidget->childAt(popupWidget->mapFromGlobal(globalPos)); + popupReceiver = popupChild ? popupChild : popupWidget; + } - // handle auto grab of pointer when pressing / releasing - if (!widgetWithMouseGrab && type == QEvent::MouseButtonPress) { - //if previously auto-grabbed, generate a fake mouse release (platform bug: mouse release event was lost) - if (S60->mousePressTarget) { - QMouseEvent mEvent(QEvent::MouseButtonRelease, S60->mousePressTarget->mapFromGlobal(globalPos), globalPos, - button, QApplicationPrivate::mouse_buttons, modifiers); - events.append(Event(S60->mousePressTarget,mEvent)); + if (mouseGrabber) { + if (popupReceiver) { + sendMouseEvent(popupReceiver, type, globalPos, button, modifiers); + } else { + sendMouseEvent(mouseGrabber, type, globalPos, button, modifiers); } - //auto grab the mouse - widgetWithMouseGrab = S60->mousePressTarget = widgetUnderPointer; - widgetWithMouseGrab->grabMouse(); - } - if (widgetWithMouseGrab && widgetWithMouseGrab == S60->mousePressTarget && type == QEvent::MouseButtonRelease) { - //release the auto grab - note this release event still goes to the autograb widget - S60->mousePressTarget = 0; - widgetWithMouseGrab->releaseMouse(); + // No Enter/Leave events in grabbing mode. + return; } - QWidget *widgetToReceiveMouseEvent; - if (widgetWithMouseGrab) - widgetToReceiveMouseEvent = widgetWithMouseGrab; - else - widgetToReceiveMouseEvent = widgetUnderPointer; - - //queue QEvent::Enter and QEvent::Leave, if the pointer has moved - if (widgetUnderPointer != S60->lastPointerEventTarget && (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick || type == QEvent::MouseMove)) - generateEnterLeaveEvents(events, widgetUnderPointer, globalPos, button, modifiers); + QWidget *widgetUnderPointer = qwidget->childAt(widgetPos); + if (!widgetUnderPointer) + widgetUnderPointer = qwidget; - //save global state - S60->lastCursorPos = globalPos; - S60->lastPointerEventPos = widgetPos; + QApplicationPrivate::dispatchEnterLeave(widgetUnderPointer, S60->lastPointerEventTarget); S60->lastPointerEventTarget = widgetUnderPointer; + QWidget *receiver; + if (!popupReceiver && S60->mousePressTarget && type != QEvent::MouseButtonPress) { + receiver = S60->mousePressTarget; + if (type == QEvent::MouseButtonRelease) + S60->mousePressTarget = 0; + } else { + receiver = popupReceiver ? popupReceiver : widgetUnderPointer; + if (type == QEvent::MouseButtonPress) + S60->mousePressTarget = receiver; + } + #if !defined(QT_NO_CURSOR) && !defined(Q_SYMBIAN_FIXED_POINTER_CURSORS) if (S60->brokenPointerCursors) qt_symbian_move_cursor_sprite(); #endif - //queue this event. - Q_ASSERT(widgetToReceiveMouseEvent); - QMouseEvent mEvent(type, widgetToReceiveMouseEvent->mapFromGlobal(globalPos), globalPos, + sendMouseEvent(receiver, type, globalPos, button, modifiers); +} + +void QSymbianControl::sendMouseEvent( + QWidget *receiver, + QEvent::Type type, + const QPoint &globalPos, + Qt::MouseButton button, + Qt::KeyboardModifiers modifiers) +{ + Q_ASSERT(receiver); + QMouseEvent mEvent(type, receiver->mapFromGlobal(globalPos), globalPos, button, QApplicationPrivate::mouse_buttons, modifiers); - events.append(Event(widgetToReceiveMouseEvent,mEvent)); QEventDispatcherS60 *dispatcher; // It is theoretically possible for someone to install a different event dispatcher. - if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widgetToReceiveMouseEvent->d_func()->threadData->eventDispatcher)) != 0) { + if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(receiver->d_func()->threadData->eventDispatcher)) != 0) { if (dispatcher->excludeUserInputEvents()) { - for (int i=0;i < events.count();++i) - { - Event next = events[i]; - dispatcher->saveInputEvent(this, next.first, new QMouseEvent(next.second)); - } + dispatcher->saveInputEvent(this, receiver, new QMouseEvent(mEvent)); return; } } - //send events in the queue - for (int i=0;i < events.count();++i) - { - Event next = events[i]; - sendMouseEvent(next.first, &(next.second)); - } + sendMouseEvent(receiver, &mEvent); } bool QSymbianControl::sendMouseEvent(QWidget *widget, QMouseEvent *mEvent) @@ -674,27 +631,58 @@ TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCod fakeEvent.iType = TPointerEvent::EButton1Up; S60->virtualMouseAccel = 1; S60->virtualMouseLastKey = 0; + switch (keyCode) { + case Qt::Key_Left: + S60->virtualMousePressedKeys &= ~QS60Data::Left; + break; + case Qt::Key_Right: + S60->virtualMousePressedKeys &= ~QS60Data::Right; + break; + case Qt::Key_Up: + S60->virtualMousePressedKeys &= ~QS60Data::Up; + break; + case Qt::Key_Down: + S60->virtualMousePressedKeys &= ~QS60Data::Down; + break; + case Qt::Key_Select: + S60->virtualMousePressedKeys &= ~QS60Data::Select; + break; + } } else if (type == EEventKey) { switch (keyCode) { case Qt::Key_Left: + S60->virtualMousePressedKeys |= QS60Data::Left; x -= S60->virtualMouseAccel; fakeEvent.iType = TPointerEvent::EMove; break; case Qt::Key_Right: + S60->virtualMousePressedKeys |= QS60Data::Right; x += S60->virtualMouseAccel; fakeEvent.iType = TPointerEvent::EMove; break; case Qt::Key_Up: + S60->virtualMousePressedKeys |= QS60Data::Up; y -= S60->virtualMouseAccel; fakeEvent.iType = TPointerEvent::EMove; break; case Qt::Key_Down: + S60->virtualMousePressedKeys |= QS60Data::Down; y += S60->virtualMouseAccel; fakeEvent.iType = TPointerEvent::EMove; break; case Qt::Key_Select: - fakeEvent.iType = TPointerEvent::EButton1Down; + // 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; + return EKeyWasConsumed; + } else { + S60->virtualMousePressedKeys |= QS60Data::Select; + fakeEvent.iType = TPointerEvent::EButton1Down; + } break; } } @@ -725,7 +713,7 @@ TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCod Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers); QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode, mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods), - false, 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers); + (keyEvent.iRepeats != 0), 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers); // WId wid = reinterpret_cast<RWindowGroup *>(keyEvent.Handle())->Child(); // if (!wid) // Could happen if window isn't shown yet. @@ -825,6 +813,12 @@ void QSymbianControl::Draw(const TRect& controlRect) const if (!engine) return; + const bool sendNativePaintEvents = qwidget->d_func()->extraData()->receiveNativePaintEvents; + if (sendNativePaintEvents) { + const QRect r = qt_TRect2QRect(controlRect); + QMetaObject::invokeMethod(qwidget, "beginNativePaintEvent", Qt::DirectConnection, Q_ARG(QRect, r)); + } + // Map source rectangle into coordinates of the backing store. const QPoint controlBase(controlRect.iTl.iX, controlRect.iTl.iY); const QPoint backingStoreBase = qwidget->mapTo(qwidget->window(), controlBase); @@ -835,14 +829,48 @@ void QSymbianControl::Draw(const TRect& controlRect) const CFbsBitmap *bitmap = s60Surface->symbianBitmap(); CWindowGc &gc = SystemGc(); - if(!qwidget->d_func()->extraData()->disableBlit) { + switch(qwidget->d_func()->extraData()->nativePaintMode) { + case QWExtra::Disable: + // Do nothing + break; + + case QWExtra::Blit: if (qwidget->d_func()->isOpaque) gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); gc.BitBlt(controlRect.iTl, bitmap, backingStoreRect); + break; + + case QWExtra::ZeroFill: + if (Window().DisplayMode() == EColor16MA) { + gc.SetBrushStyle(CGraphicsContext::ESolidBrush); + gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); + gc.SetBrushColor(TRgb::Color16MA(0)); + gc.Clear(controlRect); + } else { + gc.SetBrushColor(TRgb(0x000000)); + gc.Clear(controlRect); + }; + break; + + default: + Q_ASSERT(false); } } else { surface->flush(qwidget, QRegion(qt_TRect2QRect(backingStoreRect)), QPoint()); } + + if (sendNativePaintEvents) { + const QRect r = qt_TRect2QRect(controlRect); + // The draw ops aren't actually sent to WSERV until the graphics + // context is deactivated, which happens in the function calling + // this one. We therefore delay the delivery of endNativePaintEvent, + // to ensure that drawing has completed by the time the widget + // receives the event. Note that, if the widget needs to ensure + // that the draw ops have actually been executed into the output + // framebuffer, a call to RWsSession::Flush is required in the + // endNativePaintEvent implementation. + QMetaObject::invokeMethod(qwidget, "endNativePaintEvent", Qt::QueuedConnection, Q_ARG(QRect, r)); + } } void QSymbianControl::SizeChanged() @@ -911,7 +939,18 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) return; if (IsFocused() && IsVisible()) { + if (m_symbianPopupIsOpen) { + QWidget *fw = QApplication::focusWidget(); + if (fw) { + QFocusEvent event(QEvent::FocusIn, Qt::PopupFocusReason); + QCoreApplication::sendEvent(fw, &event); + } + m_symbianPopupIsOpen = false; + } + QApplication::setActiveWindow(qwidget->window()); + qwidget->d_func()->setWindowIcon_sys(true); + qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle()); #ifdef Q_WS_S60 // If widget is fullscreen, hide status pane and button container // otherwise show them. @@ -924,6 +963,16 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) buttonGroup->MakeVisible(!isFullscreen); #endif } else if (QApplication::activeWindow() == qwidget->window()) { + if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog()) { + QWidget *fw = QApplication::focusWidget(); + if (fw) { + QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason); + QCoreApplication::sendEvent(fw, &event); + } + m_symbianPopupIsOpen = true; + return; + } + QApplication::setActiveWindow(0); } // else { We don't touch the active window unless we were explicitly activated or deactivated } @@ -939,7 +988,10 @@ void QSymbianControl::HandleResourceChange(int resourceType) TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); SetExtent(r.iTl, r.Size()); } - qwidget->d_func()->setWindowIcon_sys(true); + if (IsFocused() && IsVisible()) { + qwidget->d_func()->setWindowIcon_sys(true); + qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle()); + } break; case KUidValueCoeFontChangeEvent: // font change event @@ -1217,6 +1269,10 @@ void qt_init(QApplicationPrivate * /* priv */, int) *****************************************************************************/ void qt_cleanup() { + if(qt_S60Beep) { + delete qt_S60Beep; + qt_S60Beep = 0; + } QFontCache::cleanup(); // Has to happen now, since QFontEngineS60 has FBS handles // S60 structure and window server session are freed in eventdispatcher destructor as they are needed there @@ -1458,14 +1514,13 @@ void QApplication::setCursorFlashTime(int msecs) void QApplication::beep() { - TInt frequency=440; - TTimeIntervalMicroSeconds duration(500000); - QS60Beep* beep=NULL; - TRAPD(err, beep=QS60Beep::NewL(frequency, duration)); - if (!err) - beep->Play(); - delete beep; - beep=NULL; + if (!qt_S60Beep) { + TInt frequency = 880; + TTimeIntervalMicroSeconds duration(500000); + TRAP_IGNORE(qt_S60Beep=QS60Beep::NewL(frequency, duration)); + } + if (qt_S60Beep) + qt_S60Beep->Play(); } /*! diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 387c29b..b677228 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -243,8 +243,12 @@ static PtrWTGet ptrWTGet = 0; static PACKET localPacketBuf[QT_TABLET_NPACKETQSIZE]; // our own tablet packet queue. HCTX qt_tablet_context; // the hardware context for the tablet (like a window handle) bool qt_tablet_tilt_support; -static void tabletInit(UINT wActiveCsr, HCTX hTab); + +#ifndef QT_NO_TABLETEVENT +static void tabletInit(const quint64 uniqueId, const UINT csr_type, HCTX hTab); +static void tabletUpdateCursor(QTabletDeviceData &tdd, const UINT currentCursor); static void initWinTabFunctions(); // resolve the WINTAB api functions +#endif // QT_NO_TABLETEVENT #ifndef QT_NO_ACCESSIBILITY @@ -256,7 +260,7 @@ extern QWidget* qt_get_tablet_widget(); extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); extern QRegion qt_dirtyRegion(QWidget *); -typedef QHash<UINT, QTabletDeviceData> QTabletCursorInfo; +typedef QHash<quint64, QTabletDeviceData> QTabletCursorInfo; Q_GLOBAL_STATIC(QTabletCursorInfo, tCursorInfo) QTabletDeviceData currentTabletPointer; @@ -791,7 +795,9 @@ void qt_init(QApplicationPrivate *priv, int) if (QApplication::desktopSettingsAware()) qt_set_windows_resources(); +#ifndef QT_NO_TABLETEVENT initWinTabFunctions(); +#endif // QT_NO_TABLETEVENT QApplicationPrivate::inputContext = new QWinInputContext(0); // Read the initial cleartype settings... @@ -832,6 +838,7 @@ void qt_init(QApplicationPrivate *priv, int) priv->GetGestureInfo = (PtrGetGestureInfo) &TKGetGestureInfo; priv->GetGestureExtraArgs = (PtrGetGestureExtraArgs) &TKGetGestureExtraArguments; #elif !defined(Q_WS_WINCE) + #if !defined(QT_NO_NATIVE_GESTURES) priv->GetGestureInfo = (PtrGetGestureInfo)QLibrary::resolve(QLatin1String("user32"), "GetGestureInfo"); @@ -847,6 +854,7 @@ void qt_init(QApplicationPrivate *priv, int) priv->GetGestureConfig = (PtrGetGestureConfig)QLibrary::resolve(QLatin1String("user32"), "GetGestureConfig"); + #endif // QT_NO_NATIVE_GESTURES priv->BeginPanningFeedback = (PtrBeginPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"), "BeginPanningFeedback"); @@ -2323,25 +2331,43 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam } break; case WT_PROXIMITY: - if (ptrWTPacketsGet) { - bool enteredProximity = LOWORD(lParam) != 0; - PACKET proximityBuffer[QT_TABLET_NPACKETQSIZE]; - int totalPacks = ptrWTPacketsGet(qt_tablet_context, QT_TABLET_NPACKETQSIZE, proximityBuffer); - if (totalPacks > 0 && enteredProximity) { - uint currentCursor = proximityBuffer[0].pkCursor; - if (!tCursorInfo()->contains(currentCursor)) - tabletInit(currentCursor, qt_tablet_context); - currentTabletPointer = tCursorInfo()->value(currentCursor); + + #ifndef QT_NO_TABLETEVENT + if (ptrWTPacketsGet && ptrWTInfo) { + const bool enteredProximity = LOWORD(lParam) != 0; + PACKET proximityBuffer[1]; // we are only interested in the first packet in this case + const int totalPacks = ptrWTPacketsGet(qt_tablet_context, 1, proximityBuffer); + if (totalPacks > 0) { + const UINT currentCursor = proximityBuffer[0].pkCursor; + + UINT csr_physid; + ptrWTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &csr_physid); + UINT csr_type; + ptrWTInfo(WTI_CURSORS + currentCursor, CSR_TYPE, &csr_type); + const UINT deviceIdMask = 0xFF6; // device type mask && device color mask + quint64 uniqueId = (csr_type & deviceIdMask); + uniqueId = (uniqueId << 32) | csr_physid; + + // initialising and updating the cursor should be done in response to + // WT_CSRCHANGE. We do it in WT_PROXIMITY because some wintab never send + // the event WT_CSRCHANGE even if asked with CXO_CSRMESSAGES + const QTabletCursorInfo *const globalCursorInfo = tCursorInfo(); + if (!globalCursorInfo->contains(uniqueId)) + tabletInit(uniqueId, csr_type, qt_tablet_context); + + currentTabletPointer = globalCursorInfo->value(uniqueId); + tabletUpdateCursor(currentTabletPointer, currentCursor); } qt_tabletChokeMouse = false; -#ifndef QT_NO_TABLETEVENT + QTabletEvent tabletProximity(enteredProximity ? QEvent::TabletEnterProximity : QEvent::TabletLeaveProximity, QPoint(), QPoint(), QPointF(), currentTabletPointer.currentDevice, currentTabletPointer.currentPointerType, 0, 0, 0, 0, 0, 0, 0, currentTabletPointer.llId); QApplication::sendEvent(qApp, &tabletProximity); -#endif // QT_NO_TABLETEVENT } + #endif // QT_NO_TABLETEVENT + break; #ifdef Q_WS_WINCE_WM case WM_SETFOCUS: { @@ -3315,63 +3341,57 @@ bool QETWidget::translateWheelEvent(const MSG &msg) // the following is adapted from the wintab syspress example (public domain) /* -------------------------------------------------------------------------- */ -static void tabletInit(UINT wActiveCsr, HCTX hTab) +// Initialize the "static" information of a cursor device (pen, airbrush, etc). +// The QTabletDeviceData is initialized with the data that do not change in time +// (number of button, type of device, etc) but do not initialize the variable data +// (e.g.: pen or eraser) +#ifndef QT_NO_TABLETEVENT + +static void tabletInit(const quint64 uniqueId, const UINT csr_type, HCTX hTab) { + Q_ASSERT(ptrWTInfo); + Q_ASSERT(ptrWTGet); + + Q_ASSERT(!tCursorInfo()->contains(uniqueId)); + /* browse WinTab's many info items to discover pressure handling. */ - if (ptrWTInfo && ptrWTGet) { - AXIS np; - LOGCONTEXT lc; - BYTE wPrsBtn; - BYTE logBtns[32]; - UINT size; - - /* discover the LOGICAL button generated by the pressure channel. */ - /* get the PHYSICAL button from the cursor category and run it */ - /* through that cursor's button map (usually the identity map). */ - wPrsBtn = (BYTE)-1; - ptrWTInfo(WTI_CURSORS + wActiveCsr, CSR_NPBUTTON, &wPrsBtn); - size = ptrWTInfo(WTI_CURSORS + wActiveCsr, CSR_BUTTONMAP, &logBtns); - if ((UINT)wPrsBtn < size) - wPrsBtn = logBtns[wPrsBtn]; - - /* get the current context for its device variable. */ - ptrWTGet(hTab, &lc); - - /* get the size of the pressure axis. */ - QTabletDeviceData tdd; - ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_NPRESSURE, &np); - tdd.minPressure = int(np.axMin); - tdd.maxPressure = int(np.axMax); - - ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_TPRESSURE, &np); - tdd.minTanPressure = int(np.axMin); - tdd.maxTanPressure = int(np.axMax); - - LOGCONTEXT lcMine; - - /* get default region */ - ptrWTInfo(WTI_DEFCONTEXT, 0, &lcMine); - - tdd.minX = 0; - tdd.maxX = int(lcMine.lcInExtX) - int(lcMine.lcInOrgX); - - tdd.minY = 0; - tdd.maxY = int(lcMine.lcInExtY) - int(lcMine.lcInOrgY); - - tdd.minZ = 0; - tdd.maxZ = int(lcMine.lcInExtZ) - int(lcMine.lcInOrgZ); - - int csr_type, - csr_physid; - ptrWTInfo(WTI_CURSORS + wActiveCsr, CSR_TYPE, &csr_type); - ptrWTInfo(WTI_CURSORS + wActiveCsr, CSR_PHYSID, &csr_physid); - tdd.llId = csr_type & 0x0F06; - tdd.llId = (tdd.llId << 24) | csr_physid; -#ifndef QT_NO_TABLETEVENT - if (((csr_type & 0x0006) == 0x0002) && ((csr_type & 0x0F06) != 0x0902)) { - tdd.currentDevice = QTabletEvent::Stylus; - } else { - switch (csr_type & 0x0F06) { + AXIS np; + LOGCONTEXT lc; + + /* get the current context for its device variable. */ + ptrWTGet(hTab, &lc); + + /* get the size of the pressure axis. */ + QTabletDeviceData tdd; + tdd.llId = uniqueId; + + ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_NPRESSURE, &np); + tdd.minPressure = int(np.axMin); + tdd.maxPressure = int(np.axMax); + + ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_TPRESSURE, &np); + tdd.minTanPressure = int(np.axMin); + tdd.maxTanPressure = int(np.axMax); + + LOGCONTEXT lcMine; + + /* get default region */ + ptrWTInfo(WTI_DEFCONTEXT, 0, &lcMine); + + tdd.minX = 0; + tdd.maxX = int(lcMine.lcInExtX) - int(lcMine.lcInOrgX); + + tdd.minY = 0; + tdd.maxY = int(lcMine.lcInExtY) - int(lcMine.lcInOrgY); + + tdd.minZ = 0; + tdd.maxZ = int(lcMine.lcInExtZ) - int(lcMine.lcInOrgZ); + + const uint cursorTypeBitMask = 0x0F06; // bitmask to find the specific cursor type (see Wacom FAQ) + if (((csr_type & 0x0006) == 0x0002) && ((csr_type & cursorTypeBitMask) != 0x0902)) { + tdd.currentDevice = QTabletEvent::Stylus; + } else { + switch (csr_type & cursorTypeBitMask) { case 0x0802: tdd.currentDevice = QTabletEvent::Stylus; break; @@ -3389,26 +3409,34 @@ static void tabletInit(UINT wActiveCsr, HCTX hTab) break; default: tdd.currentDevice = QTabletEvent::NoDevice; - } - } - - switch (wActiveCsr % 3) { - case 2: - tdd.currentPointerType = QTabletEvent::Eraser; - break; - case 1: - tdd.currentPointerType = QTabletEvent::Pen; - break; - case 0: - tdd.currentPointerType = QTabletEvent::Cursor; - break; - default: - tdd.currentPointerType = QTabletEvent::UnknownPointer; } + } + tCursorInfo()->insert(uniqueId, tdd); +} #endif // QT_NO_TABLETEVENT - tCursorInfo()->insert(wActiveCsr, tdd); + +// Update the "dynamic" informations of a cursor device (pen, airbrush, etc). +// The dynamic information is the information of QTabletDeviceData that can change +// in time (eraser or pen if a device is turned around). +#ifndef QT_NO_TABLETEVENT + +static void tabletUpdateCursor(QTabletDeviceData &tdd, const UINT currentCursor) +{ + switch (currentCursor % 3) { // %3 for dual track + case 0: + tdd.currentPointerType = QTabletEvent::Cursor; + break; + case 1: + tdd.currentPointerType = QTabletEvent::Pen; + break; + case 2: + tdd.currentPointerType = QTabletEvent::Eraser; + break; + default: + tdd.currentPointerType = QTabletEvent::UnknownPointer; } } +#endif // QT_NO_TABLETEVENT bool QETWidget::translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, int numPackets) @@ -3544,6 +3572,10 @@ bool QETWidget::translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, } extern bool qt_is_gui_used; + + +#ifndef QT_NO_TABLETEVENT + static void initWinTabFunctions() { #if defined(Q_OS_WINCE) @@ -3562,6 +3594,7 @@ static void initWinTabFunctions() } #endif // Q_OS_WINCE } +#endif // QT_NO_TABLETEVENT // diff --git a/src/gui/kernel/qclipboard_s60.cpp b/src/gui/kernel/qclipboard_s60.cpp index de13a51..48aa331 100644 --- a/src/gui/kernel/qclipboard_s60.cpp +++ b/src/gui/kernel/qclipboard_s60.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm index 37dcc67..304e5d3 100644 --- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm +++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm @@ -178,6 +178,9 @@ static void cleanupCocoaApplicationDelegate() return [[qtMenuLoader retain] autorelease]; } +// This function will only be called when NSApp is actually running. Before +// that, the kAEQuitApplication apple event will be sendt to +// QApplicationPrivate::globalAppleEventProcessor in qapplication_mac.mm - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { Q_UNUSED(sender); diff --git a/src/gui/kernel/qcocoamenuloader_mac.mm b/src/gui/kernel/qcocoamenuloader_mac.mm index 9ab077f..990571d 100644 --- a/src/gui/kernel/qcocoamenuloader_mac.mm +++ b/src/gui/kernel/qcocoamenuloader_mac.mm @@ -76,9 +76,14 @@ QT_USE_NAMESPACE - (void)ensureAppMenuInMenu:(NSMenu *)menu { + // The application menu is the menu in the menu bar that contains the + // 'Quit' item. When changing menu bar (e.g when swithing between + // windows with different menu bars), we never recreate this menu, but + // instead pull it out the current menu bar and place into the new one: NSMenu *mainMenu = [NSApp mainMenu]; if ([NSApp mainMenu] == menu) - return; // nothing to do! + return; // nothing to do (menu is the current menu bar)! + #ifndef QT_NAMESPACE Q_ASSERT(mainMenu); #endif diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm index a26d775..9154284 100644 --- a/src/gui/kernel/qcocoapanel_mac.mm +++ b/src/gui/kernel/qcocoapanel_mac.mm @@ -50,152 +50,16 @@ #include <QtGui/QWidget> QT_FORWARD_DECLARE_CLASS(QWidget); -QT_BEGIN_NAMESPACE -extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm -QT_END_NAMESPACE QT_USE_NAMESPACE - -@interface NSWindow (QtCoverForHackWithCategory) -+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; -@end - - @implementation QT_MANGLE_NAMESPACE(QCocoaPanel) -- (BOOL)canBecomeKeyWindow -{ - QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)]; - - bool isToolTip = (widget->windowType() == Qt::ToolTip); - bool isPopup = (widget->windowType() == Qt::Popup); - return !(isPopup || isToolTip); -} - /*********************************************************************** - BEGIN Copy and Paste between QCocoaWindow and QCocoaPanel + Copy and Paste between QCocoaWindow and QCocoaPanel This is a bit unfortunate, but thanks to the dynamic dispatch we have to duplicate this code or resort to really silly forwarding methods **************************************************************************/ - -/* - The methods keyDown, keyUp, and flagsChanged... These really shouldn't ever - get hit. We automatically say we can be first responder if we are a window. - So, the handling should get handled by the view. This is here more as a - last resort (i.e., this is code that can potentially be removed). - */ - -- (void)toggleToolbarShown:(id)sender -{ - macSendToolbarChangeEvent([self QT_MANGLE_NAMESPACE(qt_qwidget)]); - [super toggleToolbarShown:sender]; -} - -- (void)keyDown:(NSEvent *)theEvent -{ - bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); - if (!keyOK) - [super keyDown:theEvent]; -} - -- (void)keyUp:(NSEvent *)theEvent -{ - bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); - if (!keyOK) - [super keyUp:theEvent]; -} - -- (void)flagsChanged:(NSEvent *)theEvent -{ - qt_dispatchModifiersChanged(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); - [super flagsChanged:theEvent]; -} - - -- (void)tabletProximity:(NSEvent *)tabletEvent -{ - qt_dispatchTabletProximityEvent(tabletEvent); -} - -- (void)sendEvent:(NSEvent *)event -{ - QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; - - // Cocoa can hold onto the window after we've disavowed its knowledge. So, - // if we get sent an event afterwards just have it go through the super's - // version and don't do any stuff with Qt. - if (!widget) { - [super sendEvent:event]; - return; - } - [self retain]; - QT_MANGLE_NAMESPACE(QCocoaView) *view = static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(qt_mac_nativeview_for(widget)); - Qt::MouseButton mouseButton = cocoaButton2QtButton([event buttonNumber]); - - // sometimes need to redirect mouse events to the popup. - QWidget *popup = qAppInstance()->activePopupWidget(); - if (popup && popup != widget) { - switch([event type]) - { - case NSLeftMouseDown: - qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton); - // Don't call super here. This prevents us from getting the mouseUp event, - // which we need to send even if the mouseDown event was not accepted. - // (this is standard Qt behavior.) - break; - case NSRightMouseDown: - case NSOtherMouseDown: - if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton)) - [super sendEvent:event]; - break; - case NSLeftMouseUp: - case NSRightMouseUp: - case NSOtherMouseUp: - if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonRelease, mouseButton)) - [super sendEvent:event]; - break; - case NSMouseMoved: - qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, Qt::NoButton); - break; - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->view = view; - [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->theEvent = event; - if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, mouseButton)) - [super sendEvent:event]; - break; - default: - [super sendEvent:event]; - break; - } - } else { - [super sendEvent:event]; - } - qt_mac_dispatchNCMouseMessage(self, event, [self QT_MANGLE_NAMESPACE(qt_qwidget)], leftButtonIsRightButton); - - - [self release]; -} - -- (BOOL)makeFirstResponder:(NSResponder *)responder -{ - // For some reason Cocoa wants to flip the first responder - // when Qt doesn't want to, sorry, but "No" :-) - if (responder == nil && qApp->focusWidget()) - return NO; - return [super makeFirstResponder:responder]; -} - -/*********************************************************************** - END Copy and Paste between QCocoaWindow and QCocoaPanel -***********************************************************************/ -+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask -{ - if (styleMask & QtMacCustomizeWindow) - return [QT_MANGLE_NAMESPACE(QCocoaWindowCustomThemeFrame) class]; - return [super frameViewClassForStyleMask:styleMask]; -} +#include "qcocoasharedwindowmethods_mac_p.h" @end #endif diff --git a/src/gui/kernel/qcocoapanel_mac_p.h b/src/gui/kernel/qcocoapanel_mac_p.h index d95cd93..69dca1e 100644 --- a/src/gui/kernel/qcocoapanel_mac_p.h +++ b/src/gui/kernel/qcocoapanel_mac_p.h @@ -54,12 +54,10 @@ #ifdef QT_MAC_USE_COCOA #import <Cocoa/Cocoa.h> - @interface QT_MANGLE_NAMESPACE(QCocoaPanel) : NSPanel { bool leftButtonIsRightButton; } + (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; - @end #endif diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h new file mode 100644 index 0000000..f347240 --- /dev/null +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/**************************************************************************** + NB: This is not a header file, dispite the file name suffix. This file is + included directly into the source code of qcocoawindow_mac.mm and + qcocoapanel_mac.mm to avoid manually doing copy and paste of the exact + same code needed at both places. This solution makes it more difficult + to e.g fix a bug in qcocoawindow_mac.mm, but forget to do the same in + qcocoapanel_mac.mm. + The reason we need to do copy and paste in the first place, rather than + resolve to method overriding, is that QCocoaPanel needs to inherit from + NSPanel, while QCocoaWindow needs to inherit NSWindow rather than NSPanel). +****************************************************************************/ + +QT_BEGIN_NAMESPACE +extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm +extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp +QT_END_NAMESPACE + +- (BOOL)canBecomeKeyWindow +{ + QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)]; + + bool isToolTip = (widget->windowType() == Qt::ToolTip); + bool isPopup = (widget->windowType() == Qt::Popup); + return !(isPopup || isToolTip); +} + +- (void)toggleToolbarShown:(id)sender +{ + macSendToolbarChangeEvent([self QT_MANGLE_NAMESPACE(qt_qwidget)]); + [super toggleToolbarShown:sender]; +} + +/* + The methods keyDown, keyUp, and flagsChanged... These really shouldn't ever + get hit. We automatically say we can be first responder if we are a window. + So, the handling should get handled by the view. This is here more as a + last resort (i.e., this is code that can potentially be removed). + */ +- (void)keyDown:(NSEvent *)theEvent +{ + bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); + if (!keyOK) + [super keyDown:theEvent]; +} + +- (void)keyUp:(NSEvent *)theEvent +{ + bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); + if (!keyOK) + [super keyUp:theEvent]; +} + +- (void)flagsChanged:(NSEvent *)theEvent +{ + qt_dispatchModifiersChanged(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); + [super flagsChanged:theEvent]; +} + + +- (void)tabletProximity:(NSEvent *)tabletEvent +{ + qt_dispatchTabletProximityEvent(tabletEvent); +} + +- (void)sendEvent:(NSEvent *)event +{ + QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; + + // Cocoa can hold onto the window after we've disavowed its knowledge. So, + // if we get sent an event afterwards just have it go through the super's + // version and don't do any stuff with Qt. + if (!widget) { + [super sendEvent:event]; + return; + } + + [self retain]; + QT_MANGLE_NAMESPACE(QCocoaView) *view = static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(qt_mac_nativeview_for(widget)); + Qt::MouseButton mouseButton = cocoaButton2QtButton([event buttonNumber]); + + bool handled = false; + // sometimes need to redirect mouse events to the popup. + QWidget *popup = qAppInstance()->activePopupWidget(); + if (popup) { + switch([event type]) + { + case NSLeftMouseDown: + if (!qt_button_down) + qt_button_down = widget; + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton); + // Don't call super here. This prevents us from getting the mouseUp event, + // which we need to send even if the mouseDown event was not accepted. + // (this is standard Qt behavior.) + break; + case NSRightMouseDown: + case NSOtherMouseDown: + if (!qt_button_down) + qt_button_down = widget; + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton); + break; + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonRelease, mouseButton); + qt_button_down = 0; + break; + case NSMouseMoved: + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, Qt::NoButton); + break; + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: + [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->view = view; + [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->theEvent = event; + handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, mouseButton); + break; + default: + [super sendEvent:event]; + break; + } + } else { + [super sendEvent:event]; + } + + if (!handled) + qt_mac_dispatchNCMouseMessage(self, event, [self QT_MANGLE_NAMESPACE(qt_qwidget)], leftButtonIsRightButton); + + [self release]; +} + +- (BOOL)makeFirstResponder:(NSResponder *)responder +{ + // For some reason Cocoa wants to flip the first responder + // when Qt doesn't want to, sorry, but "No" :-) + if (responder == nil && qApp->focusWidget()) + return NO; + return [super makeFirstResponder:responder]; +} + ++ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask +{ + if (styleMask & QtMacCustomizeWindow) + return [QT_MANGLE_NAMESPACE(QCocoaWindowCustomThemeFrame) class]; + return [super frameViewClassForStyleMask:styleMask]; +} + diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index a16d1f8..6c06746 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -64,12 +64,16 @@ #include <qdebug.h> -@interface NSEvent (DeviceDelta) +@interface NSEvent (Qt_Compile_Leopard_DeviceDelta) - (CGFloat)deviceDeltaX; - (CGFloat)deviceDeltaY; - (CGFloat)deviceDeltaZ; @end +@interface NSEvent (Qt_Compile_Leopard_Gestures) + - (CGFloat)magnification; +@end + QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(DnDParams, qMacDnDParams); @@ -79,6 +83,7 @@ extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); // qapplication.cpp extern OSViewRef qt_mac_nativeview_for(const QWidget *w); // qwidget_mac.mm extern const QStringList& qEnabledDraggedTypes(); // qmime_mac.cpp extern QPointer<QWidget> qt_mouseover; //qapplication_mac.mm +extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum) { @@ -691,6 +696,9 @@ extern "C" { - (void)mouseDown:(NSEvent *)theEvent { + if (!qt_button_down) + qt_button_down = qwidget; + qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, Qt::LeftButton); // Don't call super here. This prevents us from getting the mouseUp event, // which we need to send even if the mouseDown event was not accepted. @@ -700,75 +708,62 @@ extern "C" { - (void)mouseUp:(NSEvent *)theEvent { - bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, Qt::LeftButton); + qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, Qt::LeftButton); - if (!mouseOK) - [super mouseUp:theEvent]; + qt_button_down = 0; } - (void)rightMouseDown:(NSEvent *)theEvent { - bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, Qt::RightButton); + if (!qt_button_down) + qt_button_down = qwidget; - if (!mouseOK) - [super rightMouseDown:theEvent]; + qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, Qt::RightButton); } - (void)rightMouseUp:(NSEvent *)theEvent { - bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, Qt::RightButton); + qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, Qt::RightButton); - if (!mouseOK) - [super rightMouseUp:theEvent]; + qt_button_down = 0; } - (void)otherMouseDown:(NSEvent *)theEvent { - Qt::MouseButton mouseButton = cocoaButton2QtButton([theEvent buttonNumber]); - bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, mouseButton); + if (!qt_button_down) + qt_button_down = qwidget; - if (!mouseOK) - [super otherMouseDown:theEvent]; + Qt::MouseButton mouseButton = cocoaButton2QtButton([theEvent buttonNumber]); + qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, mouseButton); } - (void)otherMouseUp:(NSEvent *)theEvent { Qt::MouseButton mouseButton = cocoaButton2QtButton([theEvent buttonNumber]); - bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, mouseButton); - - if (!mouseOK) - [super otherMouseUp:theEvent]; + qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, mouseButton); + qt_button_down = 0; } - (void)mouseDragged:(NSEvent *)theEvent { qMacDnDParams()->view = self; qMacDnDParams()->theEvent = theEvent; - bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); - - if (!mouseOK) - [super mouseDragged:theEvent]; + qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); } - (void)rightMouseDragged:(NSEvent *)theEvent { qMacDnDParams()->view = self; qMacDnDParams()->theEvent = theEvent; - bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); - - if (!mouseOK) - [super rightMouseDragged:theEvent]; + qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); } - (void)otherMouseDragged:(NSEvent *)theEvent { qMacDnDParams()->view = self; qMacDnDParams()->theEvent = theEvent; - bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); - - if (!mouseOK) - [super otherMouseDragged:theEvent]; + qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); } - (void)scrollWheel:(NSEvent *)theEvent @@ -783,11 +778,18 @@ extern "C" { NSPoint globalPoint = [[theEvent window] convertBaseToScreen:windowPoint]; NSPoint localPoint = [self convertPoint:windowPoint fromView:nil]; QPoint qlocal = QPoint(localPoint.x, localPoint.y); - QPoint qglobal = QPoint(globalPoint.x, globalPoint.y); - Qt::MouseButton buttons = cocoaButton2QtButton([theEvent buttonNumber]); + QPoint qglobal = QPoint(globalPoint.x, flipYCoordinate(globalPoint.y)); + Qt::MouseButtons buttons = QApplication::mouseButtons(); bool wheelOK = false; Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([theEvent modifierFlags]); QWidget *widgetToGetMouse = qwidget; + // if popup is open it should get wheel events if the cursor is over the popup, + // otherwise the event should be ignored. + if (QWidget *popup = qAppInstance()->activePopupWidget()) { + if (!popup->geometry().contains(qglobal)) + return; + } + int deltaX = 0; int deltaY = 0; int deltaZ = 0; @@ -893,6 +895,7 @@ extern "C" { bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents); qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all)); } +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - (void)magnifyWithEvent:(NSEvent *)event; { @@ -963,7 +966,6 @@ extern "C" { qNGEvent.position = flipPoint(p).toPoint(); qt_sendSpontaneousEvent(qwidget, &qNGEvent); } -#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - (void)frameDidChange:(NSNotification *)note { @@ -1447,11 +1449,14 @@ Qt::DropAction QDragManager::drag(QDrag *o) pasteboard:pboard source:dndParams.view slideBack:YES]; + // reset the implicit grab widget when drag ends because we will not + // receive the mouse release event when DND is active. + qt_button_down = 0; [dndParams.view release]; [image release]; dragPrivate()->executed_action = Qt::IgnoreAction; object = 0; - Qt::DropAction performedAction(qt_mac_mapNSDragOperation(dndParams.performedAction)); + Qt::DropAction performedAction(qt_mac_mapNSDragOperation(qMacDnDParams()->performedAction)); // do post drag processing, if required. if(performedAction != Qt::IgnoreAction) { // check if the receiver points us to a file location. diff --git a/src/gui/kernel/qcocoawindow_mac.mm b/src/gui/kernel/qcocoawindow_mac.mm index 263f0ac..a9aa373 100644 --- a/src/gui/kernel/qcocoawindow_mac.mm +++ b/src/gui/kernel/qcocoawindow_mac.mm @@ -50,15 +50,8 @@ #include <QtGui/QWidget> QT_FORWARD_DECLARE_CLASS(QWidget); -QT_BEGIN_NAMESPACE -extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm -QT_END_NAMESPACE QT_USE_NAMESPACE -@interface NSWindow (QtCoverForHackWithCategory) -+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; -@end - @implementation NSWindow (QT_MANGLE_NAMESPACE(QWidgetIntegration)) - (id)QT_MANGLE_NAMESPACE(qt_initWithQWidget):(QWidget*)widget contentRect:(NSRect)rect styleMask:(NSUInteger)mask; @@ -83,138 +76,12 @@ QT_USE_NAMESPACE @implementation QT_MANGLE_NAMESPACE(QCocoaWindow) -- (BOOL)canBecomeKeyWindow -{ - return YES; -} - /*********************************************************************** - BEGIN Copy and Paste between QCocoaWindow and QCocoaPanel + Copy and Paste between QCocoaWindow and QCocoaPanel This is a bit unfortunate, but thanks to the dynamic dispatch we have to duplicate this code or resort to really silly forwarding methods **************************************************************************/ - -/* - The methods keyDown, keyUp, and flagsChanged... These really shouldn't ever - get hit. We automatically say we can be first responder if we are a window. - So, the handling should get handled by the view. This is here more as a - last resort (i.e., this is code that can potentially be removed). - */ - -- (void)toggleToolbarShown:(id)sender -{ - macSendToolbarChangeEvent([self QT_MANGLE_NAMESPACE(qt_qwidget)]); - [super toggleToolbarShown:sender]; -} - -- (void)keyDown:(NSEvent *)theEvent -{ - bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); - if (!keyOK) - [super keyDown:theEvent]; -} - -- (void)keyUp:(NSEvent *)theEvent -{ - bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); - if (!keyOK) - [super keyUp:theEvent]; -} - -- (void)flagsChanged:(NSEvent *)theEvent -{ - qt_dispatchModifiersChanged(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); - [super flagsChanged:theEvent]; -} - - -- (void)tabletProximity:(NSEvent *)tabletEvent -{ - qt_dispatchTabletProximityEvent(tabletEvent); -} - -- (void)sendEvent:(NSEvent *)event -{ - QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; - - // Cocoa can hold onto the window after we've disavowed its knowledge. So, - // if we get sent an event afterwards just have it go through the super's - // version and don't do any stuff with Qt. - if (!widget) { - [super sendEvent:event]; - return; - } - - [self retain]; - QT_MANGLE_NAMESPACE(QCocoaView) *view = static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(qt_mac_nativeview_for(widget)); - Qt::MouseButton mouseButton = cocoaButton2QtButton([event buttonNumber]); - // sometimes need to redirect mouse events to the popup. - QWidget *popup = qAppInstance()->activePopupWidget(); - if (popup && popup != widget) { - switch([event type]) - { - case NSLeftMouseDown: - qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton); - // Don't call super here. This prevents us from getting the mouseUp event, - // which we need to send even if the mouseDown event was not accepted. - // (this is standard Qt behavior.) - break; - case NSRightMouseDown: - case NSOtherMouseDown: - if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton)) - [super sendEvent:event]; - break; - case NSLeftMouseUp: - case NSRightMouseUp: - case NSOtherMouseUp: - if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonRelease, mouseButton)) - [super sendEvent:event]; - break; - case NSMouseMoved: - qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, Qt::NoButton); - break; - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->view = view; - [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->theEvent = event; - if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, mouseButton)) - [super sendEvent:event]; - break; - default: - [super sendEvent:event]; - break; - } - } else { - [super sendEvent:event]; - } - qt_mac_dispatchNCMouseMessage(self, event, [self QT_MANGLE_NAMESPACE(qt_qwidget)], leftButtonIsRightButton); - - - [self release]; -} - - -- (BOOL)makeFirstResponder:(NSResponder *)responder -{ - // For some reason Cocoa wants to flip the first responder - // when Qt doesn't want to, sorry, but "No" :-) - if (responder == nil && qApp->focusWidget()) - return NO; - return [super makeFirstResponder:responder]; -} - -/*********************************************************************** - END Copy and Paste between QCocoaWindow and QCocoaPanel -***********************************************************************/ - -+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask -{ - if (styleMask & QtMacCustomizeWindow) - return [QT_MANGLE_NAMESPACE(QCocoaWindowCustomThemeFrame) class]; - return [super frameViewClassForStyleMask:styleMask]; -} +#include "qcocoasharedwindowmethods_mac_p.h" @end - #endif diff --git a/src/gui/kernel/qcocoawindow_mac_p.h b/src/gui/kernel/qcocoawindow_mac_p.h index a688d96..91c5d4e 100644 --- a/src/gui/kernel/qcocoawindow_mac_p.h +++ b/src/gui/kernel/qcocoawindow_mac_p.h @@ -50,13 +50,18 @@ // We mean it. // -#include "qmacdefines_mac.h" #ifdef QT_MAC_USE_COCOA +#include "qmacdefines_mac.h" #import <Cocoa/Cocoa.h> enum { QtMacCustomizeWindow = 1 << 21 }; // This will one day be run over by QT_FORWARD_DECLARE_CLASS(QWidget); +QT_FORWARD_DECLARE_CLASS(QStringList); + +@interface NSWindow (QtCoverForHackWithCategory) ++ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; +@end @interface NSWindow (QT_MANGLE_NAMESPACE(QWidgetIntegration)) - (id)QT_MANGLE_NAMESPACE(qt_initWithQWidget):(QWidget *)widget contentRect:(NSRect)rect styleMask:(NSUInteger)mask; @@ -70,3 +75,4 @@ QT_FORWARD_DECLARE_CLASS(QWidget); + (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; @end #endif + diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm index 9fb674e..8a22a65 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac.mm +++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm @@ -324,8 +324,13 @@ static void cleanupCocoaWindowDelegate() NSRect frameToReturn = defaultFrame; QWidget *qwidget = m_windowHash->value(window); QSizeF size = qwidget->maximumSize(); - frameToReturn.size.width = qMin<CGFloat>(frameToReturn.size.width, size.width()); - frameToReturn.size.height = qMin<CGFloat>(frameToReturn.size.height, size.height()); + NSRect windowFrameRect = [window frame]; + NSRect viewFrameRect = [[window contentView] frame]; + // consider additional size required for titlebar & frame + frameToReturn.size.width = qMin<CGFloat>(frameToReturn.size.width, + size.width()+(windowFrameRect.size.width - viewFrameRect.size.width)); + frameToReturn.size.height = qMin<CGFloat>(frameToReturn.size.height, + size.height()+(windowFrameRect.size.height - viewFrameRect.size.height)); return frameToReturn; } diff --git a/src/gui/kernel/qcursor_s60.cpp b/src/gui/kernel/qcursor_s60.cpp index 3559586..542f008 100644 --- a/src/gui/kernel/qcursor_s60.cpp +++ b/src/gui/kernel/qcursor_s60.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/kernel/qcursor_win.cpp b/src/gui/kernel/qcursor_win.cpp index 26cde1a..a4e7b1f 100644 --- a/src/gui/kernel/qcursor_win.cpp +++ b/src/gui/kernel/qcursor_win.cpp @@ -153,8 +153,8 @@ static HCURSOR create32BitCursor(const QPixmap &pixmap, int hx, int hy) bool invb, invm; bbits = pixmap.toImage().convertToFormat(QImage::Format_Mono); mbits = pixmap.toImage().convertToFormat(QImage::Format_Mono); - invb = bbits.numColors() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1)); - invm = mbits.numColors() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1)); + invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1)); + invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1)); int sysW = GetSystemMetrics(SM_CXCURSOR); int sysH = GetSystemMetrics(SM_CYCURSOR); @@ -396,8 +396,8 @@ void QCursorData::update() } else { bbits = bm->toImage().convertToFormat(QImage::Format_Mono); mbits = bmm->toImage().convertToFormat(QImage::Format_Mono); - invb = bbits.numColors() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1)); - invm = mbits.numColors() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1)); + invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1)); + invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1)); } int n = qMax(1, bbits.width() / 8); int h = bbits.height(); diff --git a/src/gui/kernel/qdesktopwidget_s60.cpp b/src/gui/kernel/qdesktopwidget_s60.cpp index 43e0b85..79b8f91 100644 --- a/src/gui/kernel/qdesktopwidget_s60.cpp +++ b/src/gui/kernel/qdesktopwidget_s60.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/kernel/qdnd_s60.cpp b/src/gui/kernel/qdnd_s60.cpp index d6c8047..319c844 100644 --- a/src/gui/kernel/qdnd_s60.cpp +++ b/src/gui/kernel/qdnd_s60.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index ff97405..eedf0a7 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -399,6 +399,40 @@ QMouseEventEx::~QMouseEventEx() The function pos() gives the current cursor position, while oldPos() gives the old mouse position. + + There are a few similarities between the events QEvent::HoverEnter + and QEvent::HoverLeave, and the events QEvent::Enter and QEvent::Leave. + However, they are slightly different because we do an update() in the event + handler of HoverEnter and HoverLeave. + + QEvent::HoverMove is also slightly different from QEvent::MouseMove. Let us + consider a top-level window A containing a child B which in turn contains a + child C (all with mouse tracking enabled): + + \image hoverevents.png + + Now, if you move the cursor from the top to the bottom in the middle of A, + you will get the following QEvent::MouseMove events: + + \list 1 + \o A::MouseMove + \o B::MouseMove + \o C::MouseMove + \endlist + + You will get the same events for QEvent::HoverMove, except that the event + always propagates to the top-level regardless whether the event is accepted + or not. It will only stop propagating with the Qt::WA_NoMousePropagation + attribute. + + In this case the events will occur in the following way: + + \list 1 + \o A::HoverMove + \o A::HoverMove, B::HoverMove + \o A::HoverMove, B::HoverMove, C::HoverMove + \endlist + */ /*! @@ -2989,7 +3023,7 @@ QShowEvent::~QShowEvent() This event is only used to notify the application of a request. It may be safely ignored. - \note This class is currently supported for Mac Os X only. + \note This class is currently supported for Mac OS X only. */ /*! @@ -3032,6 +3066,8 @@ QFileOpenEvent::~QFileOpenEvent() \fn QUrl QFileOpenEvent::url() const Returns the url that is being opened. + + \since 4.6 */ QUrl QFileOpenEvent::url() const { diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 9839269..461cc92 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -787,6 +787,8 @@ public: private: QTouchEventTouchPointPrivate *d; + friend class QApplication; + friend class QApplicationPrivate; }; enum DeviceType { @@ -818,6 +820,7 @@ protected: Qt::TouchPointStates _touchPointStates; QList<QTouchEvent::TouchPoint> _touchPoints; + friend class QApplication; friend class QApplicationPrivate; }; diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm index c9dd949..e0eebfd 100644 --- a/src/gui/kernel/qeventdispatcher_mac.mm +++ b/src/gui/kernel/qeventdispatcher_mac.mm @@ -571,6 +571,12 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags) QBoolBlocker execGuard(d->currentExecIsNSAppRun, false); while (!d->interrupt && [NSApp runModalSession:session] == NSRunContinuesResponse) qt_mac_waitForMoreModalSessionEvents(); + if (!d->interrupt && session == d->currentModalSessionCached) { + // INVARIANT: Someone called e.g. [NSApp stopModal:] from outside the event + // dispatcher (e.g to stop a native dialog). But that call wrongly stopped + // 'session' as well. As a result, we need to restart all internal sessions: + d->temporarilyStopAllModalSessions(); + } } else { d->nsAppRunCalledByQt = true; QBoolBlocker execGuard(d->currentExecIsNSAppRun, true); @@ -590,7 +596,13 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags) if (NSModalSession session = d->currentModalSession()) { if (flags & QEventLoop::WaitForMoreEvents) qt_mac_waitForMoreModalSessionEvents(); - [NSApp runModalSession:session]; + NSInteger status = [NSApp runModalSession:session]; + if (status != NSRunContinuesResponse && session == d->currentModalSessionCached) { + // INVARIANT: Someone called e.g. [NSApp stopModal:] from outside the event + // dispatcher (e.g to stop a native dialog). But that call wrongly stopped + // 'session' as well. As a result, we need to restart all internal sessions: + d->temporarilyStopAllModalSessions(); + } retVal = true; break; } else { diff --git a/src/gui/kernel/qeventdispatcher_s60.cpp b/src/gui/kernel/qeventdispatcher_s60.cpp index dcf83bc..4c1429a 100644 --- a/src/gui/kernel/qeventdispatcher_s60.cpp +++ b/src/gui/kernel/qeventdispatcher_s60.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -92,7 +92,7 @@ void QEventDispatcherS60::saveInputEvent(QSymbianControl *control, QWidget *widg { DeferredInputEvent inputEvent = {control, widget, event}; m_deferredInputEvents.append(inputEvent); - connect(widget, SIGNAL(destroyed(QObject *)), SLOT(removeInputEventsForWidget(QObject *))); + connect(widget, SIGNAL(destroyed(QObject*)), SLOT(removeInputEventsForWidget(QObject*))); } bool QEventDispatcherS60::sendDeferredInputEvents() diff --git a/src/gui/kernel/qeventdispatcher_s60_p.h b/src/gui/kernel/qeventdispatcher_s60_p.h index 94282b7..fbce60a 100644 --- a/src/gui/kernel/qeventdispatcher_s60_p.h +++ b/src/gui/kernel/qeventdispatcher_s60_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/kernel/qformlayout.cpp b/src/gui/kernel/qformlayout.cpp index 3e5dadc..33f5489 100644 --- a/src/gui/kernel/qformlayout.cpp +++ b/src/gui/kernel/qformlayout.cpp @@ -1124,14 +1124,15 @@ QStyle* QFormLayoutPrivate::getStyle() const \value DontWrapRows Fields are always laid out next to their label. This is - the default policy for all styles except Qt Extended styles. + the default policy for all styles except Qt Extended styles + and QS60Style. \value WrapLongRows Labels are given enough horizontal space to fit the widest label, and the rest of the space is given to the fields. If the minimum size of a field pair is wider than the available space, the field is wrapped to the next line. This is the default policy for - Qt Extended styles. + Qt Extended styles and and QS60Style. \value WrapAllRows Fields are always laid out below their label. @@ -1720,8 +1721,8 @@ QFormLayout::FieldGrowthPolicy QFormLayout::fieldGrowthPolicy() const \brief the way in which the form's rows wrap The default value depends on the widget or application style. For - Qt Extended styles, the default is WrapLongRows; for the other styles, - the default is DontWrapRows. + Qt Extended styles and QS60Style, the default is WrapLongRows; + for the other styles, the default is DontWrapRows. If you want to display each label above its associated field (instead of next to it), set this property to WrapAllRows. diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 375116f..d7cbebd 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -52,7 +52,7 @@ #ifdef Q_WS_MAC #include "qmacgesturerecognizer_mac_p.h" #endif -#if defined(Q_OS_WIN) +#if defined(Q_OS_WIN) && !defined(QT_NO_NATIVE_GESTURES) #include "qwinnativepangesturerecognizer_win_p.h" #endif @@ -94,7 +94,9 @@ QGestureManager::QGestureManager(QObject *parent) registerGestureRecognizer(new QTapGestureRecognizer); #endif #if defined(Q_OS_WIN) + #if !defined(QT_NO_NATIVE_GESTURES) registerGestureRecognizer(new QWinNativePanGestureRecognizer); + #endif #else registerGestureRecognizer(new QTapAndHoldGestureRecognizer); #endif @@ -179,14 +181,14 @@ QGesture *QGestureManager::getState(QObject *object, QGestureRecognizer *recogni return 0; } else if (QGesture *g = qobject_cast<QGesture *>(object)) { return g; +#ifndef QT_NO_GRAPHICSVIEW } else { Q_ASSERT(qobject_cast<QGraphicsObject *>(object)); +#endif } - QList<QGesture *> states = - m_objectGestures.value(QGestureManager::ObjectGesture(object, type)); // check if the QGesture for this recognizer has already been created - foreach (QGesture *state, states) { + foreach (QGesture *state, m_objectGestures.value(QGestureManager::ObjectGesture(object, type))) { if (m_gestureToRecognizer.value(state) == recognizer) return state; } @@ -211,14 +213,13 @@ QGesture *QGestureManager::getState(QObject *object, QGestureRecognizer *recogni return state; } -bool QGestureManager::filterEventThroughContexts(const QMultiHash<QObject *, +bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *, Qt::GestureType> &contexts, QEvent *event) { QSet<QGesture *> triggeredGestures; QSet<QGesture *> finishedGestures; QSet<QGesture *> newMaybeGestures; - QSet<QGesture *> canceledGestures; QSet<QGesture *> notGestures; // TODO: sort contexts by the gesture type and check if one of the contexts @@ -227,7 +228,7 @@ bool QGestureManager::filterEventThroughContexts(const QMultiHash<QObject *, bool ret = false; // filter the event through recognizers - typedef QHash<QObject *, Qt::GestureType>::const_iterator ContextIterator; + typedef QMultiMap<QObject *, Qt::GestureType>::const_iterator ContextIterator; for (ContextIterator cit = contexts.begin(), ce = contexts.end(); cit != ce; ++cit) { Qt::GestureType gestureType = cit.value(); QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator @@ -267,6 +268,9 @@ bool QGestureManager::filterEventThroughContexts(const QMultiHash<QObject *, } } } + if (triggeredGestures.isEmpty() && finishedGestures.isEmpty() + && newMaybeGestures.isEmpty() && notGestures.isEmpty()) + return ret; QSet<QGesture *> startedGestures = triggeredGestures - m_activeGestures; triggeredGestures &= m_activeGestures; @@ -276,8 +280,7 @@ bool QGestureManager::filterEventThroughContexts(const QMultiHash<QObject *, // check if a running gesture switched back to not gesture state, // i.e. were canceled - QSet<QGesture *> activeToCancelGestures = m_activeGestures & notGestures; - canceledGestures += activeToCancelGestures; + QSet<QGesture *> canceledGestures = m_activeGestures & notGestures; // start timers for new gestures in maybe state foreach (QGesture *state, newMaybeGestures) { @@ -445,14 +448,14 @@ void QGestureManager::cleanupGesturesForRemovedRecognizer(QGesture *gesture) // return true if accepted (consumed) bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) { - QSet<Qt::GestureType> types; - QMultiHash<QObject *, Qt::GestureType> contexts; + QMap<Qt::GestureType, int> types; + QMultiMap<QObject *, Qt::GestureType> contexts; QWidget *w = receiver; typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator; if (!w->d_func()->gestureContext.isEmpty()) { for(ContextIterator it = w->d_func()->gestureContext.begin(), e = w->d_func()->gestureContext.end(); it != e; ++it) { - types.insert(it.key()); + types.insert(it.key(), 0); contexts.insertMulti(w, it.key()); } } @@ -464,7 +467,7 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) e = w->d_func()->gestureContext.end(); it != e; ++it) { if (!(it.value() & Qt::DontStartGestureOnChildren)) { if (!types.contains(it.key())) { - types.insert(it.key()); + types.insert(it.key(), 0); contexts.insertMulti(w, it.key()); } } @@ -473,20 +476,20 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) break; w = w->parentWidget(); } - return filterEventThroughContexts(contexts, event); + return contexts.isEmpty() ? false : filterEventThroughContexts(contexts, event); } #ifndef QT_NO_GRAPHICSVIEW bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event) { - QSet<Qt::GestureType> types; - QMultiHash<QObject *, Qt::GestureType> contexts; + QMap<Qt::GestureType, int> types; + QMultiMap<QObject *, Qt::GestureType> contexts; QGraphicsObject *item = receiver; if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) { typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator; for(ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(), e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) { - types.insert(it.key()); + types.insert(it.key(), 0); contexts.insertMulti(item, it.key()); } } @@ -499,20 +502,23 @@ bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event) e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) { if (!(it.value() & Qt::DontStartGestureOnChildren)) { if (!types.contains(it.key())) { - types.insert(it.key()); + types.insert(it.key(), 0); contexts.insertMulti(item, it.key()); } } } item = item->parentObject(); } - return filterEventThroughContexts(contexts, event); + return contexts.isEmpty() ? false : filterEventThroughContexts(contexts, event); } #endif -bool QGestureManager::filterEvent(QGesture *state, QEvent *event) +bool QGestureManager::filterEvent(QObject *receiver, QEvent *event) { - QMultiHash<QObject *, Qt::GestureType> contexts; + if (!m_gestureToRecognizer.contains(static_cast<QGesture *>(receiver))) + return false; + QGesture *state = static_cast<QGesture *>(receiver); + QMultiMap<QObject *, Qt::GestureType> contexts; contexts.insert(state, state->gestureType()); return filterEventThroughContexts(contexts, event); } @@ -597,6 +603,7 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures, Qt::GestureType gestureType = gesture->gestureType(); Q_ASSERT(gestureType != Qt::CustomGesture); + Q_UNUSED(gestureType); if (target) { if (gesture->state() == Qt::GestureStarted) { diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index 4efa10b..5329d1d 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -73,7 +73,7 @@ public: void unregisterGestureRecognizer(Qt::GestureType type); bool filterEvent(QWidget *receiver, QEvent *event); - bool filterEvent(QGesture *receiver, QEvent *event); + bool filterEvent(QObject *receiver, QEvent *event); #ifndef QT_NO_GRAPHICSVIEW bool filterEvent(QGraphicsObject *receiver, QEvent *event); #endif //QT_NO_GRAPHICSVIEW @@ -86,7 +86,7 @@ public: protected: void timerEvent(QTimerEvent *event); - bool filterEventThroughContexts(const QMultiHash<QObject *, Qt::GestureType> &contexts, + bool filterEventThroughContexts(const QMultiMap<QObject *, Qt::GestureType> &contexts, QEvent *event); private: diff --git a/src/gui/kernel/qguieventdispatcher_glib.cpp b/src/gui/kernel/qguieventdispatcher_glib.cpp index f8a638c..a252499 100644 --- a/src/gui/kernel/qguieventdispatcher_glib.cpp +++ b/src/gui/kernel/qguieventdispatcher_glib.cpp @@ -152,6 +152,8 @@ static gboolean x11EventSourceDispatch(GSource *s, GSourceFunc callback, gpointe out: + source->d->runTimersOnceWithNormalPriority(); + if (callback) callback(user_data); return true; diff --git a/src/gui/kernel/qkeymapper_s60.cpp b/src/gui/kernel/qkeymapper_s60.cpp index d272d6e..ecfb7fb 100644 --- a/src/gui/kernel/qkeymapper_s60.cpp +++ b/src/gui/kernel/qkeymapper_s60.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 1a76083..2361dd0 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -282,8 +282,8 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni \row \i SelectPreviousPage \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \row \i SelectStartOfLine \i Shift+Home \i Ctrl+Shift+Left \i Shift+Home \i Shift+Home \i Shift+Home \row \i SelectEndOfLine \i Shift+End \i Ctrl+Shift+Right \i Shift+End \i Shift+End \i Shift+End - \row \i SelectStartOfBlock \i (none) \i Alt+Shift+Up \i (none) \i (none) \i (none) - \row \i SelectEndOfBlock \i (none) \i Alt+Shift+Down \i (none) \i (none) \i (none) + \row \i SelectStartOfBlock \i (none) \i Alt+Shift+Up, Meta+Shift+A \i (none) \i (none) \i (none) + \row \i SelectEndOfBlock \i (none) \i Alt+Shift+Down, Meta+Shift+E \i (none) \i (none) \i (none) \row \i SelectStartOfDocument\i Ctrl+Shift+Home \i Ctrl+Shift+Up, Shift+Home \i Ctrl+Shift+Home\i Ctrl+Shift+Home \i Ctrl+Shift+Home \row \i SelectEndOfDocument \i Ctrl+Shift+End \i Ctrl+Shift+Down, Shift+End \i Ctrl+Shift+End \i Ctrl+Shift+End \i Ctrl+Shift+End \row \i DeleteStartOfWord \i Ctrl+Backspace \i Alt+Backspace \i Ctrl+Backspace \i Ctrl+Backspace \i (none) @@ -732,6 +732,8 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::MoveToNextPage, 0, Qt::META | Qt::Key_Down, QApplicationPrivate::KB_Mac}, {QKeySequence::MoveToPreviousPage, 0, Qt::META | Qt::Key_PageUp, QApplicationPrivate::KB_Mac}, {QKeySequence::MoveToNextPage, 0, Qt::META | Qt::Key_PageDown, QApplicationPrivate::KB_Mac}, + {QKeySequence::SelectStartOfBlock, 0, Qt::META | Qt::SHIFT | Qt::Key_A, QApplicationPrivate::KB_Mac}, + {QKeySequence::SelectEndOfBlock, 0, Qt::META | Qt::SHIFT | Qt::Key_E, QApplicationPrivate::KB_Mac}, {QKeySequence::SelectStartOfLine, 0, Qt::META | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Mac}, {QKeySequence::SelectEndOfLine, 0, Qt::META | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Mac} }; @@ -1014,9 +1016,12 @@ bool QKeySequence::isEmpty() const */ QKeySequence QKeySequence::mnemonic(const QString &text) { + QKeySequence ret; + if(qt_sequence_no_mnemonics) - return QKeySequence(); + return ret; + bool found = false; int p = 0; while (p >= 0) { p = text.indexOf(QLatin1Char('&'), p) + 1; @@ -1025,13 +1030,22 @@ QKeySequence QKeySequence::mnemonic(const QString &text) if (text.at(p) != QLatin1Char('&')) { QChar c = text.at(p); if (c.isPrint()) { - c = c.toUpper(); - return QKeySequence(c.unicode() + Qt::ALT); + if (!found) { + c = c.toUpper(); + ret = QKeySequence(c.unicode() + Qt::ALT); +#ifdef QT_NO_DEBUG + return ret; +#else + found = true; + } else { + qWarning("QKeySequence::mnemonic: \"%s\" contains multiple occurences of '&'", qPrintable(text)); +#endif + } } } p++; } - return QKeySequence(); + return ret; } /*! diff --git a/src/gui/kernel/qlayout.cpp b/src/gui/kernel/qlayout.cpp index 70cd5a5..5d44b3d 100644 --- a/src/gui/kernel/qlayout.cpp +++ b/src/gui/kernel/qlayout.cpp @@ -496,6 +496,21 @@ void QLayout::setContentsMargins(int left, int top, int right, int bottom) } /*! + \since 4.6 + + Sets the \a margins to use around the layout. + + By default, QLayout uses the values provided by the style. On + most platforms, the margin is 11 pixels in all directions. + + \sa contentsMargins() +*/ +void QLayout::setContentsMargins(const QMargins &margins) +{ + setContentsMargins(margins.left(), margins.top(), margins.right(), margins.bottom()); +} + +/*! \since 4.3 Extracts the left, top, right, and bottom margins used around the @@ -521,6 +536,23 @@ void QLayout::getContentsMargins(int *left, int *top, int *right, int *bottom) c } /*! + \since 4.6 + + Returns the margins used around the layout. + + By default, QLayout uses the values provided by the style. On + most platforms, the margin is 11 pixels in all directions. + + \sa setContentsMargins() +*/ +QMargins QLayout::contentsMargins() const +{ + int left, top, right, bottom; + getContentsMargins(&left, &top, &right, &bottom); + return QMargins(left, top, right, bottom); +} + +/*! \since 4.3 Returns the layout's geometry() rectangle, but taking into account the diff --git a/src/gui/kernel/qlayout.h b/src/gui/kernel/qlayout.h index 83cbab6..2f30294 100644 --- a/src/gui/kernel/qlayout.h +++ b/src/gui/kernel/qlayout.h @@ -46,6 +46,7 @@ #include <QtGui/qlayoutitem.h> #include <QtGui/qsizepolicy.h> #include <QtCore/qrect.h> +#include <QtCore/qmargins.h> #include <limits.h> @@ -122,7 +123,9 @@ public: void setSpacing(int); void setContentsMargins(int left, int top, int right, int bottom); + void setContentsMargins(const QMargins &margins); void getContentsMargins(int *left, int *top, int *right, int *bottom) const; + QMargins contentsMargins() const; QRect contentsRect() const; bool setAlignment(QWidget *w, Qt::Alignment alignment); diff --git a/src/gui/kernel/qmacgesturerecognizer_mac.mm b/src/gui/kernel/qmacgesturerecognizer_mac.mm index f142d71..3e0ba23 100644 --- a/src/gui/kernel/qmacgesturerecognizer_mac.mm +++ b/src/gui/kernel/qmacgesturerecognizer_mac.mm @@ -67,7 +67,7 @@ QMacSwipeGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *e case QNativeGestureEvent::Swipe: { QSwipeGesture *g = static_cast<QSwipeGesture *>(gesture); g->setSwipeAngle(ev->angle); - return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; + return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; break; } default: break; diff --git a/src/gui/kernel/qmultitouch_mac.mm b/src/gui/kernel/qmultitouch_mac.mm index 2f6f9ca..f736146 100644 --- a/src/gui/kernel/qmultitouch_mac.mm +++ b/src/gui/kernel/qmultitouch_mac.mm @@ -180,7 +180,6 @@ QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch) 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); diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp index a914220..0e98f39 100644 --- a/src/gui/kernel/qsoftkeymanager.cpp +++ b/src/gui/kernel/qsoftkeymanager.cpp @@ -137,12 +137,14 @@ QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *act */ QAction *QSoftKeyManager::createKeyedAction(StandardSoftKey standardKey, Qt::Key key, QWidget *actionWidget) { +#ifndef QT_NO_ACTION QScopedPointer<QAction> action(createAction(standardKey, actionWidget)); connect(action.data(), SIGNAL(triggered()), QSoftKeyManager::instance(), SLOT(sendKeyEvent())); connect(action.data(), SIGNAL(destroyed(QObject*)), QSoftKeyManager::instance(), SLOT(cleanupHash(QObject*))); QSoftKeyManager::instance()->d_func()->keyedActions.insert(action.data(), key); return action.take(); +#endif //QT_NO_ACTION } void QSoftKeyManager::cleanupHash(QObject* obj) @@ -175,6 +177,7 @@ void QSoftKeyManager::updateSoftKeys() bool QSoftKeyManager::event(QEvent *e) { +#ifndef QT_NO_ACTION if (e->type() == QEvent::UpdateSoftKeys) { QList<QAction*> softKeys; QWidget *source = QApplication::focusWidget(); @@ -187,7 +190,7 @@ bool QSoftKeyManager::event(QEvent *e) } QWidget *parent = source->parentWidget(); - if (parent && softKeys.isEmpty()) + if (parent && softKeys.isEmpty() && !source->isWindow()) source = parent; else break; @@ -200,20 +203,29 @@ bool QSoftKeyManager::event(QEvent *e) QSoftKeyManagerPrivate::updateSoftKeys_sys(softKeys); return true; } +#endif //QT_NO_ACTION return false; } #ifdef Q_WS_S60 void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys) { + // lets not update softkeys if s60 native dialog or menu is shown + if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog()) + return; + CEikButtonGroupContainer* nativeContainer = S60->buttonGroupContainer(); nativeContainer->DrawableWindow()->SetOrdinalPosition(0); nativeContainer->DrawableWindow()->SetPointerCapturePriority(1); //keep softkeys available in modal dialog - QT_TRAP_THROWING(nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS)); + nativeContainer->DrawableWindow()->SetFaded(EFalse, RWindowTreeNode::EFadeIncludeChildren); int position = -1; - int command; bool needsExitButton = true; + QT_TRAP_THROWING( + //Using -1 instead of EAknSoftkeyEmpty to avoid flickering. + nativeContainer->SetCommandL(0, -1, KNullDesC); + nativeContainer->SetCommandL(2, -1, KNullDesC); + ); for (int index = 0; index < softkeys.count(); index++) { const QAction* softKeyAction = softkeys.at(index); @@ -234,15 +246,22 @@ void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys) break; } - command = (softKeyAction->objectName().contains("_q_menuSoftKeyAction")) + int command = (softKeyAction->objectName().contains(QLatin1String("_q_menuSoftKeyAction"))) ? EAknSoftkeyOptions : s60CommandStart + index; + // _q_menuSoftKeyAction action is set to "invisible" and all invisible actions are by default + // disabled. However we never want to dim options softkey, even it is set to "invisible" + bool dimmed = (command == EAknSoftkeyOptions) ? false : !softKeyAction->isEnabled(); + if (position != -1) { const int underlineShortCut = QApplication::style()->styleHint(QStyle::SH_UnderlineShortcut); QString iconText = softKeyAction->iconText(); TPtrC text = qt_QString2TPtrC( underlineShortCut ? softKeyAction->text() : iconText); - QT_TRAP_THROWING(nativeContainer->SetCommandL(position, command, text)); + QT_TRAP_THROWING( + nativeContainer->SetCommandL(position, command, text); + nativeContainer->DimCommand(command, dimmed); + ); } } @@ -251,7 +270,8 @@ void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys) : Qt::Widget; if (needsExitButton && sourceWindowType != Qt::Dialog && sourceWindowType != Qt::Popup) - QT_TRAP_THROWING(nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QSoftKeyManager::tr("Exit")))); + QT_TRAP_THROWING( + nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QSoftKeyManager::tr("Exit")))); nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation } diff --git a/src/gui/kernel/qsound_s60.cpp b/src/gui/kernel/qsound_s60.cpp index 7c5af64..cbbf838 100644 --- a/src/gui/kernel/qsound_s60.cpp +++ b/src/gui/kernel/qsound_s60.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index 0ea4764..6b0441b 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -56,7 +56,7 @@ QPanGestureRecognizer::QPanGestureRecognizer() QGesture *QPanGestureRecognizer::create(QObject *target) { if (target && target->isWidgetType()) { -#if defined(Q_OS_WIN) +#if defined(Q_OS_WIN) && !defined(QT_NO_NATIVE_GESTURES) // for scroll areas on Windows we want to use native gestures instead if (!qobject_cast<QAbstractScrollArea *>(target->parent())) static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); @@ -77,7 +77,6 @@ QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); QGestureRecognizer::Result result; - switch (event->type()) { case QEvent::TouchBegin: { result = QGestureRecognizer::MayBeGesture; diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index c0fb8aa..ef680a4 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -139,6 +139,7 @@ void QMacWindowFader::performFade() extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); // qapplication.cpp; extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm extern QWidget * mac_mouse_grabber; +extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds) { @@ -748,7 +749,11 @@ void qt_mac_dispatchNCMouseMessage(void * /* NSWindow* */eventWindow, void * /* NSRect frameRect = [window frame]; if (fakeNCEvents || NSMouseInRect(globalPoint, frameRect, NO)) { NSRect contentRect = [window contentRectForFrameRect:frameRect]; - if (fakeNCEvents || !NSMouseInRect(globalPoint, contentRect, NO)) { + qglobalPoint = QPoint(flipPoint(globalPoint).toPoint()); + QWidget *w = widgetToGetEvent->childAt(widgetToGetEvent->mapFromGlobal(qglobalPoint)); + // check that the mouse pointer is on the non-client area and + // there are not widgets in it. + if (fakeNCEvents || (!NSMouseInRect(globalPoint, contentRect, NO) && !w)) { qglobalPoint = QPoint(flipPoint(globalPoint).toPoint()); qlocalPoint = widgetToGetEvent->mapFromGlobal(qglobalPoint); processThisEvent = true; @@ -759,8 +764,11 @@ void qt_mac_dispatchNCMouseMessage(void * /* NSWindow* */eventWindow, void * /* // This is not an NC area mouse message. if (!processThisEvent) return; + // If the window is frame less, generate fake mouse events instead. (floating QToolBar) - if (fakeNCEvents && (widgetToGetEvent->window()->windowFlags() & Qt::FramelessWindowHint)) + // or if someone already got an explicit or implicit grab + if (mac_mouse_grabber || qt_button_down || + (fakeNCEvents && (widgetToGetEvent->window()->windowFlags() & Qt::FramelessWindowHint))) fakeMouseEvents = true; Qt::MouseButton button; @@ -838,8 +846,15 @@ void qt_mac_dispatchNCMouseMessage(void * /* NSWindow* */eventWindow, void * /* leftButtonIsRightButton = false; } } + QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, button, keyMods); qt_sendSpontaneousEvent(widgetToGetEvent, &qme); + + // We don't need to set the implicit grab widget here because we won't + // reach this point if then event type is Press over a Qt widget. + // However we might need to unset it if the event is Release. + if (eventType == QEvent::MouseButtonRelease) + qt_button_down = 0; #endif } @@ -873,15 +888,12 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev // Find the widget that *should* get the event (e.g., maybe it was a pop-up, // they always get the mouse event). QWidget *qwidget = [theView qt_qwidget]; - QWidget *widgetToGetMouse = qwidget; + QWidget *widgetToGetMouse = 0; + NSView *tmpView = 0; QWidget *popup = qAppInstance()->activePopupWidget(); - NSView *tmpView = theView; - if (mac_mouse_grabber && mac_mouse_grabber != widgetToGetMouse) { - widgetToGetMouse = mac_mouse_grabber; - tmpView = qt_mac_nativeview_for(widgetToGetMouse); - } + QPoint qglobalPoint(flipPoint(globalPoint).toPoint()); - if (popup && popup != qwidget->window()) { + if (popup) { widgetToGetMouse = popup; tmpView = qt_mac_nativeview_for(popup); windowPoint = [[tmpView window] convertScreenToBase:globalPoint]; @@ -899,7 +911,17 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev widgetToGetMouse = [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(tmpView) qt_qwidget]; } + } else { + extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp + QPoint pos; + widgetToGetMouse = QApplicationPrivate::pickMouseReceiver(qwidget, qglobalPoint, + pos, eventType, + button, qt_button_down, 0); + if (widgetToGetMouse) + tmpView = qt_mac_nativeview_for(widgetToGetMouse); } + if (!widgetToGetMouse) + return false; NSPoint localPoint = [tmpView convertPoint:windowPoint fromView:nil]; QPoint qlocalPoint(localPoint.x, localPoint.y); @@ -945,14 +967,13 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev break; } [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->localPoint = localPoint; - QPoint qglobalPoint(flipPoint(globalPoint).toPoint()); QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, buttons, keyMods); qt_sendSpontaneousEvent(widgetToGetMouse, &qme); if (eventType == QEvent::MouseButtonPress && button == Qt::RightButton) { QContextMenuEvent qcme(QContextMenuEvent::Mouse, qlocalPoint, qglobalPoint, keyMods); qt_sendSpontaneousEvent(widgetToGetMouse, &qcme); } - return qme.isAccepted(); + return true; #endif } diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 3405bcf..737e9d7 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -103,6 +103,14 @@ public: int defaultDpiY; WId curWin; int virtualMouseLastKey; + enum PressedKeys { + Select = 0x1, + Right = 0x2, + Down = 0x4, + Left = 0x8, + Up = 0x10 + }; + int virtualMousePressedKeys; // of the above type, but avoids casting problems int virtualMouseAccel; int virtualMouseMaxAccel; #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS @@ -175,7 +183,7 @@ public: protected: // from MAknFadedComponent TInt CountFadedComponents() {return 1;} - CCoeControl* FadedComponent(TInt aIndex) {return this;} + CCoeControl* FadedComponent(TInt /*aIndex*/) {return this;} #else #warning No fallback implementation for QSymbianControl::FadeBehindPopup void FadeBehindPopup(bool /*fade*/){ } @@ -192,6 +200,12 @@ private: TKeyResponse OfferKeyEvent(const TKeyEvent& aKeyEvent,TEventCode aType); TKeyResponse sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent); bool sendMouseEvent(QWidget *widget, QMouseEvent *mEvent); + void sendMouseEvent( + QWidget *receiver, + QEvent::Type type, + const QPoint &globalPos, + Qt::MouseButton button, + Qt::KeyboardModifiers modifiers); void HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation ); #ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER void translateAdvancedPointerEvent(const TAdvancedPointerEvent *event); @@ -202,9 +216,9 @@ private: private: QWidget *qwidget; - bool m_ignoreFocusChanged; QLongTapTimer* m_longTapDetector; - bool m_previousEventLongTap; + bool m_ignoreFocusChanged : 1; + bool m_symbianPopupIsOpen : 1; #ifdef Q_WS_S60 // Fader object used to fade everything except this menu and the CBA. diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h index 9f08dc6..9e4cf60 100644 --- a/src/gui/kernel/qt_x11_p.h +++ b/src/gui/kernel/qt_x11_p.h @@ -163,7 +163,9 @@ extern "C" { #endif // QT_NO_XRENDER #ifndef QT_NO_XSYNC +extern "C" { # include "X11/extensions/sync.h" +} #endif // #define QT_NO_XKB diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 271b939..e551a1d 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -366,7 +366,8 @@ bool QWidget::hasEditFocus() const normally; otherwise, Qt::Key_Up and Qt::Key_Down are used to change focus. - This feature is only available in Qt for Embedded Linux. + This feature is only available in Qt for Embedded Linux and Qt + for Symbian. \sa hasEditFocus(), QApplication::keypadNavigationEnabled() */ @@ -900,7 +901,7 @@ void QWidget::setAutoFillBackground(bool enabled) passing a \c QAction with a softkey role set on it. When the widget containing the softkey actions has focus, its softkeys should appear in the user interface. Softkeys are discovered by traversing the widget - heirarchy so it is possible to define a single set of softkeys that are + hierarchy so it is possible to define a single set of softkeys that are present at all times by calling addAction() for a given top level widget. On some platforms, this concept overlaps with \c QMenuBar such that if no @@ -3084,9 +3085,10 @@ void QWidgetPrivate::setEnabled_helper(bool enable) #endif #ifndef QT_NO_IM if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) { - QInputContext *qic = inputContext(); + QWidget *focusWidget = effectiveFocusWidget(); + QInputContext *qic = focusWidget->d_func()->inputContext(); if (enable) { - qic->setFocusWidget(q); + qic->setFocusWidget(focusWidget); } else { qic->reset(); qic->setFocusWidget(0); @@ -4604,7 +4606,7 @@ void QWidgetPrivate::updateFont(const QFont &font) if (!q->parentWidget() && extra && extra->proxyWidget) { QGraphicsProxyWidget *p = extra->proxyWidget; inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolve(); - } else + } else #endif //QT_NO_GRAPHICSVIEW if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) { inheritedFontResolveMask = 0; @@ -4676,8 +4678,10 @@ void QWidgetPrivate::resolveLayoutDirection() By default, this property is set to Qt::LeftToRight. When the layout direction is set on a widget, it will propagate to - the widget's children. Children added after the call to \c - setLayoutDirection() will not inherit the parent's layout + the widget's children, but not to a child that is a window and not + to a child for which setLayoutDirection() has been explicitly + called. Also, child widgets added \e after setLayoutDirection() + has been called for the parent do not inherit the parent's layout direction. \sa QApplication::layoutDirection @@ -5042,6 +5046,8 @@ QGraphicsEffect *QWidget::graphicsEffect() const If \a effect is the installed on a different widget, setGraphicsEffect() will remove the effect from the widget and install it on this widget. + QWidget takes ownership of \a effect. + \note This function will apply the effect on itself and all its children. \since 4.6 @@ -5055,28 +5061,22 @@ void QWidget::setGraphicsEffect(QGraphicsEffect *effect) if (d->graphicsEffect == effect) return; - if (d->graphicsEffect && effect) { + if (d->graphicsEffect) { + d->invalidateBuffer(rect()); delete d->graphicsEffect; d->graphicsEffect = 0; } - if (!effect) { - // Unset current effect. - QGraphicsEffectPrivate *oldEffectPrivate = d->graphicsEffect->d_func(); - d->graphicsEffect = 0; - if (oldEffectPrivate) { - oldEffectPrivate->setGraphicsEffectSource(0); // deletes the current source. - } - } else { + if (effect) { // Set new effect. QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this); QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced); d->graphicsEffect = effect; effect->d_func()->setGraphicsEffectSource(source); + update(); } d->updateIsOpaque(); - update(); } #endif //QT_NO_GRAPHICSEFFECT @@ -5238,7 +5238,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP QPainter p(pdev); p.translate(offset); context.painter = &p; - graphicsEffect->draw(&p, source); + graphicsEffect->draw(&p); paintEngine->d_func()->systemClip = QRegion(); } else { context.painter = sharedPainter; @@ -5248,7 +5248,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP } sharedPainter->save(); sharedPainter->translate(offset); - graphicsEffect->draw(sharedPainter, source); + graphicsEffect->draw(sharedPainter); sharedPainter->restore(); } sourced->context = 0; @@ -5470,7 +5470,7 @@ void QWidgetEffectSourcePrivate::draw(QPainter *painter) } QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset, - QGraphicsEffectSource::PixmapPadMode mode) const + QGraphicsEffect::PixmapPadMode mode) const { const bool deviceCoordinates = (system == Qt::DeviceCoordinates); if (!context && deviceCoordinates) { @@ -5491,10 +5491,10 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * QRect effectRect; - if (mode == QGraphicsEffectSource::ExpandToEffectRectPadMode) { + if (mode == QGraphicsEffect::PadToEffectiveBoundingRect) { effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); - } else if (mode == QGraphicsEffectSource::ExpandToTransparentBorderPadMode) { + } else if (mode == QGraphicsEffect::PadToTransparentBorder) { effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect(); } else { @@ -6042,6 +6042,11 @@ bool QWidget::hasFocus() const (Nothing happens if the focus in and focus out widgets are the same.) + \note On embedded platforms, setFocus() will not cause an input panel + to be opened by the input method. If you want this to happen, you + have to send a QEvent::RequestSoftwareInputPanel event to the + widget yourself. + setFocus() gives focus to a widget regardless of its focus policy, but does not clear any keyboard grab (see grabKeyboard()). @@ -6054,7 +6059,7 @@ bool QWidget::hasFocus() const \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(), setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(), - grabMouse(), {Keyboard Focus} + grabMouse(), {Keyboard Focus}, QEvent::RequestSoftwareInputPanel */ void QWidget::setFocus(Qt::FocusReason reason) @@ -8245,7 +8250,8 @@ bool QWidget::event(QEvent *event) QList<QObject*> childList = d->children; for (int i = 0; i < childList.size(); ++i) { QObject *o = childList.at(i); - QApplication::sendEvent(o, event); + if (o) + QApplication::sendEvent(o, event); } } update(); @@ -8274,7 +8280,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 != QApplication::activeModalWidget()) { + if (o && 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 @@ -8370,9 +8376,10 @@ bool QWidget::event(QEvent *event) case QEvent::TouchUpdate: case QEvent::TouchEnd: { +#ifndef Q_WS_MAC QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event); const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().first(); - if (touchPoint.isPrimary()) + if (touchPoint.isPrimary() || touchEvent->deviceType() == QTouchEvent::TouchPad) break; // fake a mouse event! @@ -8401,6 +8408,7 @@ bool QWidget::event(QEvent *event) Qt::LeftButton, touchEvent->modifiers()); (void) QApplication::sendEvent(this, &mouseEvent); +#endif // Q_WS_MAC break; } case QEvent::Gesture: @@ -9893,13 +9901,13 @@ void QWidget::scroll(int dx, int dy) Q_D(QWidget); #ifndef QT_NO_GRAPHICSVIEW if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) { - // Graphics View maintains its own dirty region as a list of rects; - // until we can connect item updates directly to the view, we must - // separately add a translated dirty region. - if (!d->dirty.isEmpty()) { - foreach (const QRect &rect, (d->dirty.translated(dx, dy)).rects()) - proxy->update(rect); - } + // Graphics View maintains its own dirty region as a list of rects; + // until we can connect item updates directly to the view, we must + // separately add a translated dirty region. + if (!d->dirty.isEmpty()) { + foreach (const QRect &rect, (d->dirty.translated(dx, dy)).rects()) + proxy->update(rect); + } proxy->scroll(dx, dy, proxy->subWidgetRect(this)); return; } @@ -9928,13 +9936,13 @@ void QWidget::scroll(int dx, int dy, const QRect &r) Q_D(QWidget); #ifndef QT_NO_GRAPHICSVIEW if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) { - // Graphics View maintains its own dirty region as a list of rects; - // until we can connect item updates directly to the view, we must - // separately add a translated dirty region. - if (!d->dirty.isEmpty()) { - foreach (const QRect &rect, (d->dirty.translated(dx, dy) & r).rects()) - proxy->update(rect); - } + // Graphics View maintains its own dirty region as a list of rects; + // until we can connect item updates directly to the view, we must + // separately add a translated dirty region. + if (!d->dirty.isEmpty()) { + foreach (const QRect &rect, (d->dirty.translated(dx, dy) & r).rects()) + proxy->update(rect); + } proxy->scroll(dx, dy, r.translated(proxy->subWidgetRect(this).topLeft().toPoint())); return; } @@ -10348,9 +10356,10 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) break; } case Qt::WA_NativeWindow: { #ifndef QT_NO_IM + QWidget *focusWidget = d->effectiveFocusWidget(); QInputContext *ic = 0; if (on && !internalWinId() && testAttribute(Qt::WA_InputMethodEnabled) && hasFocus()) { - ic = d->inputContext(); + ic = focusWidget->d_func()->inputContext(); ic->reset(); ic->setFocusWidget(0); } @@ -10359,7 +10368,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created)) d->createWinId(); if (ic && isEnabled()) - ic->setFocusWidget(this); + ic->setFocusWidget(focusWidget); #endif //QT_NO_IM break; } @@ -10391,13 +10400,14 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) break; case Qt::WA_InputMethodEnabled: { #ifndef QT_NO_IM - QInputContext *ic = d->ic; + QWidget *focusWidget = d->effectiveFocusWidget(); + QInputContext *ic = focusWidget->d_func()->ic; if (!ic && (!on || hasFocus())) - ic = d->inputContext(); + ic = focusWidget->d_func()->inputContext(); if (ic) { - if (on && hasFocus() && ic->focusWidget() != this && isEnabled()) { - ic->setFocusWidget(this); - } else if (!on && ic->focusWidget() == this) { + if (on && hasFocus() && ic->focusWidget() != focusWidget && isEnabled()) { + ic->setFocusWidget(focusWidget); + } else if (!on && ic->focusWidget() == focusWidget) { ic->reset(); ic->setFocusWidget(0); } @@ -11462,6 +11472,17 @@ void QWidget::languageChange() { } // compat \sa QWidget::setMaximumSize() */ +/*! + \fn QWidget::setupUi(QWidget *widget) + + Sets up the user interface for the specified \a widget. + + \note This function is available with widgets that derive from user + interface descriptions created using \l{uic}. + + \sa {Using a Designer UI File in Your Application} +*/ + QRect QWidgetPrivate::frameStrut() const { Q_Q(const QWidget); @@ -11781,10 +11802,6 @@ void QWidget::ungrabGesture(Qt::GestureType gesture) } -QT_END_NAMESPACE - -#include "moc_qwidget.cpp" - /*! \typedef WId \relates QWidget @@ -11859,8 +11876,7 @@ QT_END_NAMESPACE isVisible() returns false for a widget, that widget cannot call grabMouse(). - \sa releaseMouse() grabKeyboard() releaseKeyboard() grabKeyboard() - focusWidget() + \sa releaseMouse() grabKeyboard() releaseKeyboard() */ /*! @@ -12101,3 +12117,8 @@ void QWidgetPrivate::_q_delayedDestroy(WId winId) delete winId; } #endif + +QT_END_NAMESPACE + +#include "moc_qwidget.cpp" + diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index b7c55f9..0824db3 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -288,6 +288,10 @@ public: void setMaximumWidth(int maxw); void setMaximumHeight(int maxh); +#ifdef Q_QDOC + void setupUi(QWidget *widget); +#endif + QSize sizeIncrement() const; void setSizeIncrement(const QSize &); void setSizeIncrement(int w, int h); @@ -740,6 +744,7 @@ private: friend struct QWidgetExceptionCleaner; friend class QGestureManager; friend class QWinNativePanGestureRecognizer; + friend class QWidgetEffectSourcePrivate; #ifdef Q_WS_MAC friend class QCoreGraphicsPaintEnginePrivate; diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 75f9a59..7dc4d85 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -725,6 +725,23 @@ static OSWindowRef qt_mac_create_window(QWidget *, WindowClass wclass, WindowAtt return window; } +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 +/* We build the release package against the 10.4 SDK. + So, to enable gestures for applications running on + 10.6+, we define the missing constants here: */ +enum { + kEventClassGesture = 'gest', + kEventGestureStarted = 1, + kEventGestureEnded = 2, + kEventGestureMagnify = 4, + kEventGestureSwipe = 5, + kEventGestureRotate = 6, + kEventParamRotationAmount = 'rota', + kEventParamSwipeDirection = 'swip', + kEventParamMagnificationAmount = 'magn' +}; +#endif + // window events static EventTypeSpec window_events[] = { { kEventClassWindow, kEventWindowClose }, @@ -741,13 +758,11 @@ static EventTypeSpec window_events[] = { { kEventClassWindow, kEventWindowGetRegion }, { kEventClassWindow, kEventWindowGetClickModality }, { kEventClassWindow, kEventWindowTransitionCompleted }, -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 { kEventClassGesture, kEventGestureStarted }, { kEventClassGesture, kEventGestureEnded }, { kEventClassGesture, kEventGestureMagnify }, { kEventClassGesture, kEventGestureSwipe }, { kEventClassGesture, kEventGestureRotate }, -#endif { kEventClassMouse, kEventMouseDown } }; static EventHandlerUPP mac_win_eventUPP = 0; @@ -1036,7 +1051,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, handled_event = false; break; } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 case kEventClassGesture: { // First, find the widget that was under // the mouse when the gesture happened: @@ -1064,7 +1078,7 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, break; case kEventGestureRotate: { CGFloat amount; - if (GetEventParameter(event, kEventParamRotationAmount, typeCGFloat, 0, + if (GetEventParameter(event, kEventParamRotationAmount, 'cgfl', 0, sizeof(amount), 0, &amount) != noErr) { handled_event = false; break; @@ -1091,7 +1105,7 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, break; } case kEventGestureMagnify: { CGFloat amount; - if (GetEventParameter(event, kEventParamMagnificationAmount, typeCGFloat, 0, + if (GetEventParameter(event, kEventParamMagnificationAmount, 'cgfl', 0, sizeof(amount), 0, &amount) != noErr) { handled_event = false; break; @@ -1103,7 +1117,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, QApplication::sendSpontaneousEvent(widget, &qNGEvent); break; } -#endif // gestures default: handled_event = false; @@ -2604,8 +2617,6 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) releaseMouse(); if(mac_keyboard_grabber == this) releaseKeyboard(); - if(acceptDrops()) - setAcceptDrops(false); if(testAttribute(Qt::WA_ShowModal)) // just be sure we leave modal QApplicationPrivate::leaveModal(this); @@ -2673,7 +2684,10 @@ void QWidgetPrivate::transferChildren() // site disabled until it is part of the new hierarchy. bool oldRegistered = w->testAttribute(Qt::WA_DropSiteRegistered); w->setAttribute(Qt::WA_DropSiteRegistered, false); + [qt_mac_nativeview_for(w) retain]; + [qt_mac_nativeview_for(w) removeFromSuperview]; [qt_mac_nativeview_for(q) addSubview:qt_mac_nativeview_for(w)]; + [qt_mac_nativeview_for(w) release]; w->setAttribute(Qt::WA_DropSiteRegistered, oldRegistered); #endif } @@ -3640,6 +3654,16 @@ void QWidgetPrivate::setFocus_sys() } } +NSComparisonResult compareViews2Raise(id view1, id view2, void *context) +{ + id topView = reinterpret_cast<id>(context); + if (view1 == topView) + return NSOrderedDescending; + if (view2 == topView) + return NSOrderedAscending; + return NSOrderedSame; +} + void QWidgetPrivate::raise_sys() { Q_Q(QWidget); @@ -3647,7 +3671,6 @@ void QWidgetPrivate::raise_sys() return; #if QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; if (isRealWindow()) { // Calling orderFront shows the window on Cocoa too. if (!q->testAttribute(Qt::WA_DontShowOnScreen) && q->isVisible()) { @@ -3659,16 +3682,9 @@ void QWidgetPrivate::raise_sys() SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly); } } else { - // Cocoa doesn't really have an idea of Z-ordering, but you can - // fake it by changing the order of it. But beware, removing an - // NSView will also remove it as the first responder. So we re-set - // the first responder just in case: NSView *view = qt_mac_nativeview_for(q); NSView *parentView = [view superview]; - NSResponder *firstResponder = [[view window] firstResponder]; - [view removeFromSuperview]; - [parentView addSubview:view]; - [[view window] makeFirstResponder:firstResponder]; + [parentView sortSubviewsUsingFunction:compareViews2Raise context:reinterpret_cast<void *>(view)]; } #else if(q->isWindow()) { @@ -3686,47 +3702,29 @@ void QWidgetPrivate::raise_sys() #endif } +NSComparisonResult compareViews2Lower(id view1, id view2, void *context) +{ + id topView = reinterpret_cast<id>(context); + if (view1 == topView) + return NSOrderedAscending; + if (view2 == topView) + return NSOrderedDescending; + return NSOrderedSame; +} + void QWidgetPrivate::lower_sys() { Q_Q(QWidget); if((q->windowType() == Qt::Desktop)) return; #ifdef QT_MAC_USE_COCOA - QMacCocoaAutoReleasePool pool; if (isRealWindow()) { OSWindowRef window = qt_mac_window_for(q); [window orderBack:window]; } else { - // Cocoa doesn't really have an idea of Z-ordering, but you can - // fake it by changing the order of it. In this case - // we put the item at the beginning of the list, but that means - // we must re-insert everything since we cannot modify the list directly. - NSView *myview = qt_mac_nativeview_for(q); - NSView *parentView = [myview superview]; - NSArray *tmpViews = [parentView subviews]; - NSMutableArray *subviews = [[NSMutableArray alloc] initWithCapacity:[tmpViews count]]; - [subviews addObjectsFromArray:tmpViews]; - NSResponder *firstResponder = [[myview window] firstResponder]; - // Implicit assumption that myViewIndex is included in subviews, that's why I'm not checking - // myViewIndex. - NSUInteger index = 0; - NSUInteger myViewIndex = 0; - bool foundMyView = false; - for (NSView *subview in subviews) { - [subview removeFromSuperview]; - if (subview == myview) { - foundMyView = true; - myViewIndex = index; - } - ++index; - } - [parentView addSubview:myview]; - if (foundMyView) - [subviews removeObjectAtIndex:myViewIndex]; - for (NSView *subview in subviews) - [parentView addSubview:subview]; - [subviews release]; - [[myview window] makeFirstResponder:firstResponder]; + NSView *view = qt_mac_nativeview_for(q); + NSView *parentView = [view superview]; + [parentView sortSubviewsUsingFunction:compareViews2Lower context:reinterpret_cast<void *>(view)]; } #else if(q->isWindow()) { @@ -3739,6 +3737,16 @@ void QWidgetPrivate::lower_sys() #endif } +NSComparisonResult compareViews2StackUnder(id view1, id view2, void *context) +{ + const QHash<NSView *, int> &viewOrder = *reinterpret_cast<QHash<NSView *, int> *>(context); + if (viewOrder[view1] < viewOrder[view2]) + return NSOrderedAscending; + if (viewOrder[view1] > viewOrder[view2]) + return NSOrderedDescending; + return NSOrderedSame; +} + void QWidgetPrivate::stackUnder_sys(QWidget *w) { // stackUnder @@ -3747,37 +3755,23 @@ void QWidgetPrivate::stackUnder_sys(QWidget *w) return; #ifdef QT_MAC_USE_COCOA // Do the same trick as lower_sys() and put this widget before the widget passed in. - QMacCocoaAutoReleasePool pool; - NSView *myview = qt_mac_nativeview_for(q); + NSView *myView = qt_mac_nativeview_for(q); NSView *wView = qt_mac_nativeview_for(w); - NSView *parentView = [myview superview]; - NSArray *tmpViews = [parentView subviews]; - NSMutableArray *subviews = [[NSMutableArray alloc] initWithCapacity:[tmpViews count]]; - [subviews addObjectsFromArray:tmpViews]; - // Implicit assumption that myViewIndex and wViewIndex is included in subviews, - // that's why I'm not checking myViewIndex. - NSUInteger index = 0; - NSUInteger myViewIndex = 0; - NSUInteger wViewIndex = 0; - for (NSView *subview in subviews) { - [subview removeFromSuperview]; - if (subview == myview) - myViewIndex = index; - else if (subview == wView) - wViewIndex = index; - ++index; - } - index = 0; + QHash<NSView *, int> viewOrder; + NSView *parentView = [myView superview]; + NSArray *subviews = [parentView subviews]; + NSUInteger index = 1; + // make a hash of view->zorderindex and make sure z-value is always odd, + // so that when we modify the order we create a new (even) z-value which + // will not interfere with others. for (NSView *subview in subviews) { - if (index == myViewIndex) - continue; - if (index == wViewIndex) - [parentView addSubview:myview]; - [parentView addSubview:subview]; + viewOrder.insert(subview, index * 2); ++index; } - [subviews release]; + viewOrder[myView] = viewOrder[wView] - 1; + + [parentView sortSubviewsUsingFunction:compareViews2StackUnder context:reinterpret_cast<void *>(&viewOrder)]; #else QWidget *p = q->parentWidget(); if(!p || p != w->parentWidget()) diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 151b90a..5d73951 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -230,12 +230,42 @@ struct QWExtra { #elif defined(Q_OS_SYMBIAN) // <----------------------------------------------------- Symbian uint activated : 1; // RWindowBase::Activated has been called - // If set, QSymbianControl::Draw does not blit this widget - // This is to allow, for use cases such as video, widgets which, from the Qt point - // of view, are just placeholders in the scene. For these widgets, any necessary - // drawing to the UI framebuffer is done by the relevant Symbian subsystem. For - // video rendering, this would be an MMF controller, or MDF post-processor. - uint disableBlit : 1; + /** + * Defines the behaviour of QSymbianControl::Draw. + */ + enum NativePaintMode { + /** + * Normal drawing mode: blits the required region of the backing store + * via WSERV. + */ + Blit, + + /** + * Disable drawing for this widget. + */ + Disable, + + /** + * Paint zeros into the WSERV framebuffer, using BitGDI APIs. For windows + * with an EColor16MU display mode, zero is written only into the R, G and B + * channels of the pixel. + */ + ZeroFill, + + Default = Blit + }; + + NativePaintMode nativePaintMode : 2; + + /** + * If this bit is set, each native widget receives the signals from the + * Symbian control immediately before and immediately after draw ops are + * sent to the window server for this control: + * void beginNativePaintEvent(const QRect &paintRect); + * void endNativePaintEvent(const QRect &paintRect); + */ + uint receiveNativePaintEvents : 1; + #endif }; @@ -465,6 +495,12 @@ public: void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0); QInputContext *inputContext() const; + inline QWidget *effectiveFocusWidget() { + QWidget *w = q_func(); + while (w->focusProxy()) + w = w->focusProxy(); + return w; + } void setModal_sys(); @@ -479,7 +515,7 @@ public: QGraphicsProxyWidget *ancestorProxy = widget->d_func()->nearestGraphicsProxyWidget(widget); //It's embedded if it has an ancestor if (ancestorProxy) { - if (!bypassGraphicsProxyWidget(widget)) { + if (!bypassGraphicsProxyWidget(widget) && ancestorProxy->scene() != 0) { // One view, let be smart and return the viewport rect then the popup is aligned if (ancestorProxy->scene()->views().size() == 1) { QGraphicsView *view = ancestorProxy->scene()->views().at(0); @@ -787,7 +823,7 @@ public: {} inline void detach() - { m_widget->setGraphicsEffect(0); } + { m_widget->d_func()->graphicsEffect = 0; } inline const QGraphicsItem *graphicsItem() const { return 0; } @@ -824,7 +860,7 @@ public: QRectF boundingRect(Qt::CoordinateSystem system) const; void draw(QPainter *p); QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset, - QGraphicsEffectSource::PixmapPadMode mode) const; + QGraphicsEffect::PixmapPadMode mode) const; QWidget *m_widget; QWidgetPaintContext *context; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 88cd63d..37614c7 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -213,6 +213,15 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) if ((q->windowType() == Qt::Desktop)) return; + + QPoint oldPos(q->pos()); + QSize oldSize(q->size()); + QRect oldGeom(data.crect); + + // Lose maximized status if deliberate resize + if (w != oldSize.width() || h != oldSize.height()) + data.window_state &= ~Qt::WindowMaximized; + if (extra) { // any size restrictions? w = qMin(w,extra->maxw); h = qMin(h,extra->maxh); @@ -228,17 +237,10 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) data.window_state = s; } - QPoint oldPos(q->pos()); - QSize oldSize(q->size()); - QRect oldGeom(data.crect); - bool isResize = w != oldSize.width() || h != oldSize.height(); if (!isMove && !isResize) return; - if (isResize) - data.window_state &= ~Qt::WindowMaximized; - if (q->isWindow()) { if (w == 0 || h == 0) { q->setAttribute(Qt::WA_OutsideWSRange, true); @@ -359,6 +361,7 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) ); QT_TRAP_THROWING(control->ConstructL(true, desktop)); + control->SetMopParent(static_cast<CEikAppUi*>(S60->appUi())); // Symbian windows are always created in an inactive state // We perform this assignment for the case where the window is being re-created @@ -485,12 +488,6 @@ void QWidgetPrivate::show_sys() if(q->isWindow()) id->setFocusSafely(true); - - // Force setting of the icon after window is made visible, - // this is needed even WA_SetWindowIcon is not set, as in that case we need - // to reset to the application level window icon - if(q->isWindow()) - setWindowIcon_sys(true); } invalidateBuffer(q->rect()); @@ -884,7 +881,8 @@ void QWidgetPrivate::deleteTLSysExtra() void QWidgetPrivate::createSysExtra() { extra->activated = 0; - extra->disableBlit = 0; + extra->nativePaintMode = QWExtra::Default; + extra->receiveNativePaintEvents = 0; } void QWidgetPrivate::deleteSysExtra() @@ -1177,18 +1175,6 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) if (id->IsFocused()) // Avoid unnecessry calls to FocusChanged() id->setFocusSafely(false); id->ControlEnv()->AppUi()->RemoveFromStack(id); - - // Hack to activate window under destroyed one. With this activation - // the next visible window will get keyboard focus - WId wid = CEikonEnv::Static()->AppUi()->TopFocusedControl(); - if (wid) { - QWidget *widget = QWidget::find(wid); - QApplication::setActiveWindow(widget); - if (widget) { - // Reset global window title for focusing window - widget->d_func()->setWindowTitle_sys(widget->windowTitle()); - } - } } } @@ -1235,7 +1221,7 @@ void QWidget::releaseKeyboard() void QWidget::grabMouse() { - if (!qt_nograb()) { + if (isVisible() && !qt_nograb()) { if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this) QWidgetPrivate::mouseGrabber->releaseMouse(); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); @@ -1252,7 +1238,7 @@ void QWidget::grabMouse() #ifndef QT_NO_CURSOR void QWidget::grabMouse(const QCursor &cursor) { - if (!qt_nograb()) { + if (isVisible() && !qt_nograb()) { if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this) QWidgetPrivate::mouseGrabber->releaseMouse(); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 22a94b9..fde0d45 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -677,7 +677,11 @@ QPoint QWidget::mapToGlobal(const QPoint &pos) const QWidget *parentWindow = window(); QWExtra *extra = parentWindow->d_func()->extra; if (!isVisible() || parentWindow->isMinimized() || !testAttribute(Qt::WA_WState_Created) || !internalWinId() - || (extra && extra->proxyWidget)) { + || (extra +#ifndef QT_NO_GRAPHICSVIEW + && extra->proxyWidget +#endif //QT_NO_GRAPHICSVIEW + )) { if (extra && extra->topextra && extra->topextra->embedded) { QPoint pt = mapTo(parentWindow, pos); POINT p = {pt.x(), pt.y()}; @@ -704,7 +708,11 @@ QPoint QWidget::mapFromGlobal(const QPoint &pos) const QWidget *parentWindow = window(); QWExtra *extra = parentWindow->d_func()->extra; if (!isVisible() || parentWindow->isMinimized() || !testAttribute(Qt::WA_WState_Created) || !internalWinId() - || (extra && extra->proxyWidget)) { + || (extra +#ifndef QT_NO_GRAPHICSVIEW + && extra->proxyWidget +#endif //QT_NO_GRAPHICSVIEW + )) { if (extra && extra->topextra && extra->topextra->embedded) { POINT p = {pos.x(), pos.y()}; ScreenToClient(parentWindow->effectiveWinId(), &p); @@ -1331,8 +1339,15 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) if (isResize && !q->testAttribute(Qt::WA_StaticContents) && q->internalWinId()) ValidateRgn(q->internalWinId(), 0); +#ifdef Q_WS_WINCE + // On Windows CE we can't just fiddle around with the window state. + // Too much magic in setWindowState. + if (isResize && q->isMaximized()) + q->setWindowState(q->windowState() & ~Qt::WindowMaximized); +#else if (isResize) data.window_state &= ~Qt::WindowMaximized; +#endif if (data.window_state & Qt::WindowFullScreen) { QTLWExtra *top = topData(); @@ -2032,16 +2047,21 @@ void QWidgetPrivate::registerTouchWindow() void QWidgetPrivate::winSetupGestures() { +#if !defined(QT_NO_NATIVE_GESTURES) Q_Q(QWidget); - if (!q || !q->isVisible()) + if (!q || !q->isVisible() || !nativeGesturePanEnabled) return; + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); + if (!qAppPriv->SetGestureConfig) + return; WId winid = q->internalWinId(); bool needh = false; bool needv = false; bool singleFingerPanEnabled = false; +#ifndef QT_NO_SCROLLAREA if (QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea*>(q->parent())) { QScrollBar *hbar = asa->horizontalScrollBar(); QScrollBar *vbar = asa->verticalScrollBar(); @@ -2052,10 +2072,12 @@ void QWidgetPrivate::winSetupGestures() needv = (vbarpolicy == Qt::ScrollBarAlwaysOn || (vbarpolicy == Qt::ScrollBarAsNeeded && vbar->minimum() < vbar->maximum())); singleFingerPanEnabled = asa->d_func()->singleFingerPanEnabled; - if (!winid) + if (!winid) { winid = q->winId(); // enforces the native winid on the viewport + } } - if (winid && qAppPriv->SetGestureConfig) { +#endif //QT_NO_SCROLLAREA + if (winid) { GESTURECONFIG gc[1]; memset(gc, 0, sizeof(gc)); gc[0].dwID = GID_PAN; @@ -2075,6 +2097,7 @@ void QWidgetPrivate::winSetupGestures() qAppPriv->SetGestureConfig(winid, 0, sizeof(gc)/sizeof(gc[0]), gc, sizeof(gc[0])); } +#endif } QT_END_NAMESPACE diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 28676da..0bc9cbc 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -527,8 +527,13 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO QX11InfoData *xd = &X11->screens[qt_x11_create_desktop_on_screen]; xinfo.setX11Data(xd); } else if (parentXinfo && (parentXinfo->screen() != xinfo.screen() - || parentXinfo->visual() != xinfo.visual())) + || (parentXinfo->visual() != xinfo.visual() + && !q->inherits("QGLWidget")))) { + // QGLWidgets have to be excluded here as they have a + // specially crafted QX11Info structure which can't be swapped + // out with the parent widgets QX11Info. The parent visual, + // for instance, might not even be GL capable. xinfo = *parentXinfo; } @@ -1445,7 +1450,7 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset) icon_data[pos++] = image.width(); icon_data[pos++] = image.height(); if (sizeof(long) == sizeof(quint32)) { - memcpy(icon_data.data() + pos, image.scanLine(0), image.numBytes()); + memcpy(icon_data.data() + pos, image.scanLine(0), image.byteCount()); } else { for (int y = 0; y < image.height(); ++y) { uint *scanLine = reinterpret_cast<uint *>(image.scanLine(y)); diff --git a/src/gui/kernel/qwidgetaction.cpp b/src/gui/kernel/qwidgetaction.cpp index 7dc2c67..b72a41a 100644 --- a/src/gui/kernel/qwidgetaction.cpp +++ b/src/gui/kernel/qwidgetaction.cpp @@ -212,8 +212,8 @@ void QWidgetAction::releaseWidget(QWidget *widget) if (!d->createdWidgets.contains(widget)) return; - disconnect(widget, SIGNAL(destroyed(QObject *)), - this, SLOT(_q_widgetDestroyed(QObject *))); + disconnect(widget, SIGNAL(destroyed(QObject*)), + this, SLOT(_q_widgetDestroyed(QObject*))); d->createdWidgets.removeAll(widget); deleteWidget(widget); } diff --git a/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp b/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp index 5fceb13..7dff543 100644 --- a/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp +++ b/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp @@ -52,6 +52,8 @@ QT_BEGIN_NAMESPACE +#if !defined(QT_NO_NATIVE_GESTURES) + QWinNativePanGestureRecognizer::QWinNativePanGestureRecognizer() { } @@ -122,4 +124,6 @@ void QWinNativePanGestureRecognizer::reset(QGesture *state) QGestureRecognizer::reset(state); } +#endif // QT_NO_NATIVE_GESTURES + QT_END_NAMESPACE diff --git a/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h b/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h index 8fb0d50..7d53ed2 100644 --- a/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h +++ b/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h @@ -57,6 +57,8 @@ QT_BEGIN_NAMESPACE +#if !defined(QT_NO_NATIVE_GESTURES) + class QWinNativePanGestureRecognizer : public QGestureRecognizer { public: @@ -67,6 +69,8 @@ public: void reset(QGesture *state); }; +#endif // QT_NO_NATIVE_GESTURES + QT_END_NAMESPACE #endif // QWINNATIVEPANGESTURERECOGNIZER_WIN_P_H |