diff -r 5dc02b23752f -r 3e2da88830cd src/gui/kernel/qwidget.cpp --- a/src/gui/kernel/qwidget.cpp Tue Jul 06 15:10:48 2010 +0300 +++ b/src/gui/kernel/qwidget.cpp Wed Aug 18 10:37:55 2010 +0300 @@ -67,6 +67,7 @@ # include "qt_mac_p.h" # include "qt_cocoa_helpers_mac_p.h" # include "qmainwindow.h" +# include "qtoolbar.h" #endif #if defined(Q_WS_QWS) # include "qwsdisplay_qws.h" @@ -161,6 +162,47 @@ extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp +QRefCountedWidgetBackingStore::QRefCountedWidgetBackingStore() + : m_ptr(0) +{ + +} + +QRefCountedWidgetBackingStore::~QRefCountedWidgetBackingStore() +{ + delete m_ptr; +} + +void QRefCountedWidgetBackingStore::create(QWidget *widget) +{ + destroy(); + m_ptr = new QWidgetBackingStore(widget); +} + +void QRefCountedWidgetBackingStore::destroy() +{ + delete m_ptr; + m_ptr = 0; + m_visibleWidgets.clear(); +} + +void QRefCountedWidgetBackingStore::widgetShown(QWidget *w) +{ + Q_ASSERT(m_ptr); + Q_ASSERT(w->internalWinId()); + Q_ASSERT(qt_widget_private(w)->maybeBackingStore() == m_ptr); + m_visibleWidgets.insert(w); +} + +void QRefCountedWidgetBackingStore::widgetHidden(QWidget *w) +{ + if (m_visibleWidgets.remove(w) && m_visibleWidgets.isEmpty()) { + delete m_ptr; + m_ptr = 0; + } +} + + QWidgetPrivate::QWidgetPrivate(int version) : QObjectPrivate(version) , extra(0) @@ -202,7 +244,9 @@ , picture(0) #elif defined(Q_WS_WIN) , noPaintOnScreen(0) + #ifndef QT_NO_GESTURES , nativeGesturePanEnabled(0) + #endif #elif defined(Q_WS_MAC) , needWindowChange(0) , hasAlienChildren(0) @@ -248,9 +292,14 @@ QWindowSurface *QWidgetPrivate::createDefaultWindowSurface() { Q_Q(QWidget); + + QWindowSurface *surface; if (QApplicationPrivate::graphicsSystem()) - return QApplicationPrivate::graphicsSystem()->createWindowSurface(q); - return createDefaultWindowSurface_sys(); + surface = QApplicationPrivate::graphicsSystem()->createWindowSurface(q); + else + surface = createDefaultWindowSurface_sys(); + + return surface; } /*! @@ -285,8 +334,10 @@ #ifndef QT_NO_IM if (ic) return ic; -#endif return qApp->inputContext(); +#else + return 0; +#endif } /*! @@ -312,6 +363,8 @@ This function sets the input context \a context on this widget. + Qt takes ownership of the given input \a context. + \sa inputContext() */ void QWidget::setInputContext(QInputContext *context) @@ -320,9 +373,13 @@ if (!testAttribute(Qt::WA_InputMethodEnabled)) return; #ifndef QT_NO_IM + if (context == d->ic) + return; if (d->ic) delete d->ic; d->ic = context; + if (d->ic) + d->ic->setParent(this); #endif } @@ -670,8 +727,8 @@ (to move the keyboard focus), and passes on most of the other events to one of the more specialized handlers above. - Events and the mechanism used to deliver them are covered in the - \l{Events and Event Filters} document. + Events and the mechanism used to deliver them are covered in + \l{The Event System}. \section1 Groups of Functions and Properties @@ -1010,7 +1067,6 @@ \sa windowFlags */ - QWidget::QWidget(QWidget *parent, Qt::WindowFlags f) : QObject(*new QWidgetPrivate, 0), QPaintDevice() { @@ -1339,11 +1395,9 @@ // a real toplevel window needs a backing store if (isWindow() && windowType() != Qt::Desktop) { - delete d->topData()->backingStore; - // QWidgetBackingStore will check this variable, hence it must be 0 - d->topData()->backingStore = 0; + d->topData()->backingStore.destroy(); if (hasBackingStoreSupport()) - d->topData()->backingStore = new QWidgetBackingStore(this); + d->topData()->backingStore.create(this); } d->setModal_sys(); @@ -1388,8 +1442,10 @@ qWarning("QWidget: %s (%s) deleted while being painted", className(), name()); #endif +#ifndef QT_NO_GESTURES foreach (Qt::GestureType type, d->gestureContext.keys()) ungrabGesture(type); +#endif // force acceptDrops false before winId is destroyed. d->registerDropSite(false); @@ -1469,8 +1525,7 @@ // the backing store will delete its window surface, which may or may // not have a reference to this widget that will be used later to // notify the window it no longer has a surface. - delete d->extra->topextra->backingStore; - d->extra->topextra->backingStore = 0; + d->extra->topextra->backingStore.destroy(); } #endif if (QWidgetBackingStore *bs = d->maybeBackingStore()) { @@ -1567,7 +1622,6 @@ QTLWExtra* x = extra->topextra = new QTLWExtra; x->icon = 0; x->iconPixmap = 0; - x->backingStore = 0; x->windowSurface = 0; x->sharedPainter = 0; x->incw = x->inch = 0; @@ -1651,7 +1705,7 @@ #endif if (extra->topextra) { deleteTLSysExtra(); - delete extra->topextra->backingStore; + extra->topextra->backingStore.destroy(); delete extra->topextra->icon; delete extra->topextra->iconPixmap; #if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER) @@ -4774,6 +4828,11 @@ { Q_D(QWidget); + if (direction == Qt::LayoutDirectionAuto) { + unsetLayoutDirection(); + return; + } + setAttribute(Qt::WA_SetLayoutDirection); d->setLayoutDirection_helper(direction); } @@ -8530,9 +8589,11 @@ #endif // Q_WS_MAC break; } +#ifndef QT_NO_GESTURES case QEvent::Gesture: event->ignore(); break; +#endif #ifndef QT_NO_PROPERTIES case QEvent::DynamicPropertyChange: { const QByteArray &propName = static_cast(event)->propertyName(); @@ -9655,46 +9716,58 @@ QWidget *QWidgetPrivate::childAt_helper(const QPoint &p, bool ignoreChildrenInDestructor) const { + if (children.isEmpty()) + return 0; + +#ifdef Q_WS_MAC Q_Q(const QWidget); -#ifdef Q_WS_MAC + // Unified tool bars on the Mac require special handling since they live outside + // QMainWindow's geometry(). See commit: 35667fd45ada49269a5987c235fdedfc43e92bb8 bool includeFrame = q->isWindow() && qobject_cast(q) && static_cast(q)->unifiedTitleAndToolBarOnMac(); -#endif - - if ( -#ifdef Q_WS_MAC - !includeFrame && -#endif - !q->rect().contains(p)) + if (includeFrame) + return childAtRecursiveHelper(p, ignoreChildrenInDestructor, includeFrame); +#endif + + if (!pointInsideRectAndMask(p)) return 0; - - for (int i = children.size(); i > 0 ;) { - --i; - QWidget *w = qobject_cast(children.at(i)); - if (w && !w->isWindow() && !w->isHidden() - && (w->geometry().contains(p) + return childAtRecursiveHelper(p, ignoreChildrenInDestructor); +} + +QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPoint &p, bool ignoreChildrenInDestructor, bool includeFrame) const +{ +#ifndef Q_WS_MAC + Q_UNUSED(includeFrame); +#endif + for (int i = children.size() - 1; i >= 0; --i) { + QWidget *child = qobject_cast(children.at(i)); + if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents) + || (ignoreChildrenInDestructor && child->data->in_destructor)) { + continue; + } + + // Map the point 'p' from parent coordinates to child coordinates. + QPoint childPoint = p; #ifdef Q_WS_MAC - || (includeFrame && w->geometry().contains(qt_mac_nativeMapFromParent(w, p))) -#endif - )) { - if (ignoreChildrenInDestructor && w->data->in_destructor) - continue; - if (w->testAttribute(Qt::WA_TransparentForMouseEvents)) - continue; - QPoint childPoint = w->mapFromParent(p); -#ifdef Q_WS_MAC - if (includeFrame && !w->geometry().contains(p)) - childPoint = qt_mac_nativeMapFromParent(w, p); -#endif - if (QWidget *t = w->d_func()->childAt_helper(childPoint, ignoreChildrenInDestructor)) - return t; - // if WMouseNoMask is set the widget mask is ignored, if - // the widget has no mask then the WMouseNoMask flag has no - // effect - if (w->testAttribute(Qt::WA_MouseNoMask) || w->mask().contains(childPoint) - || w->mask().isEmpty()) - return w; - } + // 'includeFrame' is true if the child's parent is a top-level QMainWindow with an unified tool bar. + // An unified tool bar on the Mac lives outside QMainWindow's geometry(), so a normal + // QWidget::mapFromParent won't do the trick. + if (includeFrame && qobject_cast(child)) + childPoint = qt_mac_nativeMapFromParent(child, p); + else +#endif + childPoint -= child->data->crect.topLeft(); + + // Check if the point hits the child. + if (!child->d_func()->pointInsideRectAndMask(childPoint)) + continue; + + // Do the same for the child's descendants. + if (QWidget *w = child->d_func()->childAtRecursiveHelper(childPoint, ignoreChildrenInDestructor)) + return w; + + // We have found our target; namely the child at position 'p'. + return child; } return 0; } @@ -10620,7 +10693,7 @@ break; case Qt::WA_AcceptTouchEvents: -#if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_WS_S60) +#if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_OS_SYMBIAN) if (on) d->registerTouchWindow(); #endif @@ -11948,6 +12021,7 @@ Synonym for QList. */ +#ifndef QT_NO_GESTURES /*! Subscribes the widget to a given \a gesture with specific \a flags. @@ -11975,7 +12049,7 @@ manager->cleanupCachedGestures(this, gesture); } } - +#endif // QT_NO_GESTURES /*! \typedef WId