1 /**************************************************************************** |
1 /**************************************************************************** |
2 ** |
2 ** |
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
4 ** All rights reserved. |
4 ** All rights reserved. |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
6 ** |
6 ** |
7 ** This file is part of the QtGui module of the Qt Toolkit. |
7 ** This file is part of the QtGui module of the Qt Toolkit. |
8 ** |
8 ** |
116 #include "private/qevent_p.h" |
116 #include "private/qevent_p.h" |
117 |
117 |
118 #include "private/qgraphicssystem_p.h" |
118 #include "private/qgraphicssystem_p.h" |
119 #include "private/qgesturemanager_p.h" |
119 #include "private/qgesturemanager_p.h" |
120 |
120 |
|
121 #ifdef QT_KEYPAD_NAVIGATION |
|
122 #include "qtabwidget.h" // Needed in inTabWidget() |
|
123 #endif // QT_KEYPAD_NAVIGATION |
|
124 |
121 // widget/widget data creation count |
125 // widget/widget data creation count |
122 //#define QWIDGET_EXTRA_DEBUG |
126 //#define QWIDGET_EXTRA_DEBUG |
123 //#define ALIEN_DEBUG |
127 //#define ALIEN_DEBUG |
124 |
128 |
125 QT_BEGIN_NAMESPACE |
129 QT_BEGIN_NAMESPACE |
190 , dirtyOpaqueChildren(1) |
194 , dirtyOpaqueChildren(1) |
191 , isOpaque(0) |
195 , isOpaque(0) |
192 , inDirtyList(0) |
196 , inDirtyList(0) |
193 , isScrolled(0) |
197 , isScrolled(0) |
194 , isMoved(0) |
198 , isMoved(0) |
|
199 , isGLWidget(0) |
195 , usesDoubleBufferedGLContext(0) |
200 , usesDoubleBufferedGLContext(0) |
196 #if defined(Q_WS_X11) |
201 #if defined(Q_WS_X11) |
197 , picture(0) |
202 , picture(0) |
198 #elif defined(Q_WS_WIN) |
203 #elif defined(Q_WS_WIN) |
199 , noPaintOnScreen(0) |
204 , noPaintOnScreen(0) |
200 , nativeGesturePanEnabled(0) |
205 , nativeGesturePanEnabled(0) |
201 #elif defined(Q_WS_MAC) |
206 #elif defined(Q_WS_MAC) |
202 , needWindowChange(0) |
207 , needWindowChange(0) |
203 , isGLWidget(0) |
|
204 , window_event(0) |
208 , window_event(0) |
205 , qd_hd(0) |
209 , qd_hd(0) |
206 #endif |
210 #endif |
207 { |
211 { |
208 if (!qApp) { |
212 if (!qApp) { |
1437 qApp->d_func()->sendSyntheticEnterLeave(this); |
1441 qApp->d_func()->sendSyntheticEnterLeave(this); |
1438 #endif |
1442 #endif |
1439 } |
1443 } |
1440 #endif |
1444 #endif |
1441 |
1445 |
|
1446 #ifdef Q_OS_SYMBIAN |
|
1447 if (d->extra && d->extra->topextra && d->extra->topextra->backingStore) { |
|
1448 // Okay, we are about to destroy the top-level window that owns |
|
1449 // the backing store. Make sure we delete the backing store right away |
|
1450 // before the window handle is invalid. This is important because |
|
1451 // the backing store will delete its window surface, which may or may |
|
1452 // not have a reference to this widget that will be used later to |
|
1453 // notify the window it no longer has a surface. |
|
1454 delete d->extra->topextra->backingStore; |
|
1455 d->extra->topextra->backingStore = 0; |
|
1456 } |
|
1457 #endif |
1442 if (QWidgetBackingStore *bs = d->maybeBackingStore()) { |
1458 if (QWidgetBackingStore *bs = d->maybeBackingStore()) { |
1443 bs->removeDirtyWidget(this); |
1459 bs->removeDirtyWidget(this); |
1444 if (testAttribute(Qt::WA_StaticContents)) |
1460 if (testAttribute(Qt::WA_StaticContents)) |
1445 bs->removeStaticWidget(this); |
1461 bs->removeStaticWidget(this); |
1446 } |
1462 } |
1658 { |
1674 { |
1659 if (paintOnScreen()) { |
1675 if (paintOnScreen()) { |
1660 repaint_sys(dirty); |
1676 repaint_sys(dirty); |
1661 dirty = QRegion(); |
1677 dirty = QRegion(); |
1662 } else if (QWidgetBackingStore *bs = maybeBackingStore()) { |
1678 } else if (QWidgetBackingStore *bs = maybeBackingStore()) { |
|
1679 #ifdef QT_MAC_USE_COCOA |
|
1680 Q_UNUSED(bs); |
|
1681 void qt_mac_set_needs_display(QWidget *, QRegion); |
|
1682 qt_mac_set_needs_display(q_func(), QRegion()); |
|
1683 #else |
1663 bs->sync(); |
1684 bs->sync(); |
|
1685 #endif |
1664 } |
1686 } |
1665 } |
1687 } |
1666 |
1688 |
1667 void QWidgetPrivate::syncBackingStore(const QRegion ®ion) |
1689 void QWidgetPrivate::syncBackingStore(const QRegion ®ion) |
1668 { |
1690 { |
1669 if (paintOnScreen()) |
1691 if (paintOnScreen()) |
1670 repaint_sys(region); |
1692 repaint_sys(region); |
1671 else if (QWidgetBackingStore *bs = maybeBackingStore()) |
1693 else if (QWidgetBackingStore *bs = maybeBackingStore()) { |
|
1694 #ifdef QT_MAC_USE_COCOA |
|
1695 Q_UNUSED(bs); |
|
1696 void qt_mac_set_needs_display(QWidget *, QRegion); |
|
1697 qt_mac_set_needs_display(q_func(), region); |
|
1698 #else |
1672 bs->sync(q_func(), region); |
1699 bs->sync(q_func(), region); |
|
1700 #endif |
|
1701 } |
1673 } |
1702 } |
1674 |
1703 |
1675 void QWidgetPrivate::setUpdatesEnabled_helper(bool enable) |
1704 void QWidgetPrivate::setUpdatesEnabled_helper(bool enable) |
1676 { |
1705 { |
1677 Q_Q(QWidget); |
1706 Q_Q(QWidget); |
3086 #ifndef QT_NO_IM |
3123 #ifndef QT_NO_IM |
3087 if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) { |
3124 if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) { |
3088 QWidget *focusWidget = effectiveFocusWidget(); |
3125 QWidget *focusWidget = effectiveFocusWidget(); |
3089 QInputContext *qic = focusWidget->d_func()->inputContext(); |
3126 QInputContext *qic = focusWidget->d_func()->inputContext(); |
3090 if (enable) { |
3127 if (enable) { |
3091 qic->setFocusWidget(focusWidget); |
3128 if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) |
|
3129 qic->setFocusWidget(focusWidget); |
3092 } else { |
3130 } else { |
3093 qic->reset(); |
3131 qic->reset(); |
3094 qic->setFocusWidget(0); |
3132 qic->setFocusWidget(0); |
3095 } |
3133 } |
3096 } |
3134 } |
3341 lead to infinite recursion. |
3379 lead to infinite recursion. |
3342 |
3380 |
3343 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not |
3381 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not |
3344 appear on screen. This also applies to windows. |
3382 appear on screen. This also applies to windows. |
3345 |
3383 |
3346 \sa pos, geometry, minimumSize, maximumSize, resizeEvent() |
3384 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize() |
3347 */ |
3385 */ |
3348 |
3386 |
3349 /*! |
3387 /*! |
3350 \property QWidget::width |
3388 \property QWidget::width |
3351 \brief the width of the widget excluding any window frame |
3389 \brief the width of the widget excluding any window frame |
6083 if (QWExtra *topData = window()->d_func()->extra) { |
6121 if (QWExtra *topData = window()->d_func()->extra) { |
6084 if (topData->proxyWidget && topData->proxyWidget->hasFocus()) { |
6122 if (topData->proxyWidget && topData->proxyWidget->hasFocus()) { |
6085 previousProxyFocus = topData->proxyWidget->widget()->focusWidget(); |
6123 previousProxyFocus = topData->proxyWidget->widget()->focusWidget(); |
6086 if (previousProxyFocus && previousProxyFocus->focusProxy()) |
6124 if (previousProxyFocus && previousProxyFocus->focusProxy()) |
6087 previousProxyFocus = previousProxyFocus->focusProxy(); |
6125 previousProxyFocus = previousProxyFocus->focusProxy(); |
|
6126 if (previousProxyFocus == this && !topData->proxyWidget->d_func()->proxyIsGivingFocus) |
|
6127 return; |
6088 } |
6128 } |
6089 } |
6129 } |
6090 #endif |
6130 #endif |
6091 |
6131 |
6092 QWidget *w = f; |
6132 QWidget *w = f; |
7493 QList<QObject*> childList = children; |
7535 QList<QObject*> childList = children; |
7494 for (int i = 0; i < childList.size(); ++i) { |
7536 for (int i = 0; i < childList.size(); ++i) { |
7495 QWidget *widget = qobject_cast<QWidget*>(childList.at(i)); |
7537 QWidget *widget = qobject_cast<QWidget*>(childList.at(i)); |
7496 if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden)) |
7538 if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden)) |
7497 continue; |
7539 continue; |
|
7540 #ifdef QT_MAC_USE_COCOA |
|
7541 // Before doing anything we need to make sure that we don't leave anything in a non-consistent state. |
|
7542 // When hiding a widget we need to make sure that no mouse_down events are active, because |
|
7543 // the mouse_up event will never be received by a hidden widget or one of its descendants. |
|
7544 // The solution is simple, before going through with this we check if there are any mouse_down events in |
|
7545 // progress, if so we check if it is related to this widget or not. If so, we just reset the mouse_down and |
|
7546 // then we continue. |
|
7547 // In X11 and Windows we send a mouse_release event, however we don't do that here because we were already |
|
7548 // ignoring that from before. I.e. Carbon did not send the mouse release event, so we will not send the |
|
7549 // mouse release event. There are two ways to interpret this: |
|
7550 // 1. If we don't send the mouse release event, the widget might get into an inconsistent state, i.e. it |
|
7551 // might be waiting for a release event that will never arrive. |
|
7552 // 2. If we send the mouse release event, then the widget might decide to trigger an action that is not |
|
7553 // supposed to trigger because it is not visible. |
|
7554 if(widget == qt_button_down) |
|
7555 qt_button_down = 0; |
|
7556 #endif // QT_MAC_USE_COCOA |
7498 if (spontaneous) |
7557 if (spontaneous) |
7499 widget->setAttribute(Qt::WA_Mapped, false); |
7558 widget->setAttribute(Qt::WA_Mapped, false); |
7500 else |
7559 else |
7501 widget->setAttribute(Qt::WA_WState_Visible, false); |
7560 widget->setAttribute(Qt::WA_WState_Visible, false); |
7502 widget->d_func()->hideChildren(spontaneous); |
7561 widget->d_func()->hideChildren(spontaneous); |
7887 inline void setDisabledStyle(QWidget *w, bool setStyle) |
7946 inline void setDisabledStyle(QWidget *w, bool setStyle) |
7888 { |
7947 { |
7889 // set/reset WS_DISABLED style. |
7948 // set/reset WS_DISABLED style. |
7890 if(w && w->isWindow() && w->isVisible() && w->isEnabled()) { |
7949 if(w && w->isWindow() && w->isVisible() && w->isEnabled()) { |
7891 LONG dwStyle = GetWindowLong(w->winId(), GWL_STYLE); |
7950 LONG dwStyle = GetWindowLong(w->winId(), GWL_STYLE); |
|
7951 LONG newStyle = dwStyle; |
7892 if (setStyle) |
7952 if (setStyle) |
7893 dwStyle |= WS_DISABLED; |
7953 newStyle |= WS_DISABLED; |
7894 else |
7954 else |
7895 dwStyle &= ~WS_DISABLED; |
7955 newStyle &= ~WS_DISABLED; |
7896 SetWindowLong(w->winId(), GWL_STYLE, dwStyle); |
7956 if (newStyle != dwStyle) { |
7897 // we might need to repaint in some situations (eg. menu) |
7957 SetWindowLong(w->winId(), GWL_STYLE, newStyle); |
7898 w->repaint(); |
7958 // we might need to repaint in some situations (eg. menu) |
|
7959 w->repaint(); |
|
7960 } |
7899 } |
7961 } |
7900 } |
7962 } |
7901 #endif |
7963 #endif |
7902 |
7964 |
7903 /***************************************************************************** |
7965 /***************************************************************************** |
9772 newBs->subSurfaces.append(windowSurface); |
9834 newBs->subSurfaces.append(windowSurface); |
9773 } |
9835 } |
9774 } |
9836 } |
9775 #endif |
9837 #endif |
9776 |
9838 |
9777 if (newParent) { |
9839 if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) { |
9778 if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) { |
9840 if (newParent) |
9779 oldBs->removeDirtyWidget(this); |
9841 oldBs->removeDirtyWidget(this); |
9780 // Move the widget and all its static children from |
9842 // Move the widget and all its static children from |
9781 // the old backing store to the new one. |
9843 // the old backing store to the new one. |
9782 oldBs->moveStaticWidgets(this); |
9844 oldBs->moveStaticWidgets(this); |
9783 } |
|
9784 } |
9845 } |
9785 |
9846 |
9786 if ((QApplicationPrivate::app_compile_version < 0x040200 |
9847 if ((QApplicationPrivate::app_compile_version < 0x040200 |
9787 || QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation)) |
9848 || QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation)) |
9788 && !testAttribute(Qt::WA_WState_Created)) |
9849 && !testAttribute(Qt::WA_WState_Created)) |
10356 break; } |
10417 break; } |
10357 case Qt::WA_NativeWindow: { |
10418 case Qt::WA_NativeWindow: { |
10358 #ifndef QT_NO_IM |
10419 #ifndef QT_NO_IM |
10359 QWidget *focusWidget = d->effectiveFocusWidget(); |
10420 QWidget *focusWidget = d->effectiveFocusWidget(); |
10360 QInputContext *ic = 0; |
10421 QInputContext *ic = 0; |
10361 if (on && !internalWinId() && testAttribute(Qt::WA_InputMethodEnabled) && hasFocus()) { |
10422 if (on && !internalWinId() && hasFocus() |
|
10423 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) { |
10362 ic = focusWidget->d_func()->inputContext(); |
10424 ic = focusWidget->d_func()->inputContext(); |
10363 ic->reset(); |
10425 if (ic) { |
10364 ic->setFocusWidget(0); |
10426 ic->reset(); |
|
10427 ic->setFocusWidget(0); |
|
10428 } |
10365 } |
10429 } |
10366 if (!qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget()) |
10430 if (!qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget()) |
10367 parentWidget()->d_func()->enforceNativeChildren(); |
10431 parentWidget()->d_func()->enforceNativeChildren(); |
10368 if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created)) |
10432 if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created)) |
10369 d->createWinId(); |
10433 d->createWinId(); |
10370 if (ic && isEnabled()) |
10434 if (ic && isEnabled() && focusWidget->isEnabled() |
|
10435 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) { |
10371 ic->setFocusWidget(focusWidget); |
10436 ic->setFocusWidget(focusWidget); |
|
10437 } |
10372 #endif //QT_NO_IM |
10438 #endif //QT_NO_IM |
10373 break; |
10439 break; |
10374 } |
10440 } |
10375 case Qt::WA_PaintOnScreen: |
10441 case Qt::WA_PaintOnScreen: |
10376 d->updateIsOpaque(); |
10442 d->updateIsOpaque(); |
10403 QWidget *focusWidget = d->effectiveFocusWidget(); |
10469 QWidget *focusWidget = d->effectiveFocusWidget(); |
10404 QInputContext *ic = focusWidget->d_func()->ic; |
10470 QInputContext *ic = focusWidget->d_func()->ic; |
10405 if (!ic && (!on || hasFocus())) |
10471 if (!ic && (!on || hasFocus())) |
10406 ic = focusWidget->d_func()->inputContext(); |
10472 ic = focusWidget->d_func()->inputContext(); |
10407 if (ic) { |
10473 if (ic) { |
10408 if (on && hasFocus() && ic->focusWidget() != focusWidget && isEnabled()) { |
10474 if (on && hasFocus() && ic->focusWidget() != focusWidget && isEnabled() |
|
10475 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) { |
10409 ic->setFocusWidget(focusWidget); |
10476 ic->setFocusWidget(focusWidget); |
10410 } else if (!on && ic->focusWidget() == focusWidget) { |
10477 } else if (!on && ic->focusWidget() == focusWidget) { |
10411 ic->reset(); |
10478 ic->reset(); |
10412 ic->setFocusWidget(0); |
10479 ic->setFocusWidget(0); |
10413 } |
10480 } |
11583 } |
11650 } |
11584 } |
11651 } |
11585 } |
11652 } |
11586 return targetWidget; |
11653 return targetWidget; |
11587 } |
11654 } |
|
11655 |
|
11656 /*! |
|
11657 \internal |
|
11658 |
|
11659 Tells us if it there is currently a reachable widget by keypad navigation in |
|
11660 a certain \a orientation. |
|
11661 If no navigation is possible, occuring key events in that \a orientation may |
|
11662 be used to interact with the value in the focussed widget, even though it |
|
11663 currently has not the editFocus. |
|
11664 |
|
11665 \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus() |
|
11666 */ |
|
11667 bool QWidgetPrivate::canKeypadNavigate(Qt::Orientation orientation) |
|
11668 { |
|
11669 return orientation == Qt::Horizontal? |
|
11670 (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast) |
|
11671 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest)) |
|
11672 :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth) |
|
11673 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth)); |
|
11674 } |
|
11675 /*! |
|
11676 \internal |
|
11677 |
|
11678 Checks, if the \a widget is inside a QTabWidget. If is is inside |
|
11679 one, left/right key events will be used to switch between tabs in keypad |
|
11680 navigation. If there is no QTabWidget, the horizontal key events can be used |
|
11681 to |
|
11682 interact with the value in the focussed widget, even though it currently has |
|
11683 not the editFocus. |
|
11684 |
|
11685 \sa QWidget::hasEditFocus() |
|
11686 */ |
|
11687 bool QWidgetPrivate::inTabWidget(QWidget *widget) |
|
11688 { |
|
11689 for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget()) |
|
11690 if (qobject_cast<const QTabWidget*>(tabWidget)) |
|
11691 return true; |
|
11692 return false; |
|
11693 } |
11588 #endif |
11694 #endif |
11589 |
11695 |
11590 /*! |
11696 /*! |
11591 \preliminary |
11697 \preliminary |
11592 \since 4.2 |
11698 \since 4.2 |
11870 It is almost never necessary to grab the mouse when using Qt, as |
11976 It is almost never necessary to grab the mouse when using Qt, as |
11871 Qt grabs and releases it sensibly. In particular, Qt grabs the |
11977 Qt grabs and releases it sensibly. In particular, Qt grabs the |
11872 mouse when a mouse button is pressed and keeps it until the last |
11978 mouse when a mouse button is pressed and keeps it until the last |
11873 button is released. |
11979 button is released. |
11874 |
11980 |
11875 Note that only visible widgets can grab mouse input. If |
11981 \note Only visible widgets can grab mouse input. If isVisible() |
11876 isVisible() returns false for a widget, that widget cannot call |
11982 returns false for a widget, that widget cannot call grabMouse(). |
11877 grabMouse(). |
11983 |
|
11984 \note \bold{(Mac OS X developers)} For \e Cocoa, calling |
|
11985 grabMouse() on a widget only works when the mouse is inside the |
|
11986 frame of that widget. For \e Carbon, it works outside the widget's |
|
11987 frame as well, like for Windows and X11. |
11878 |
11988 |
11879 \sa releaseMouse() grabKeyboard() releaseKeyboard() |
11989 \sa releaseMouse() grabKeyboard() releaseKeyboard() |
11880 */ |
11990 */ |
11881 |
11991 |
11882 /*! |
11992 /*! |
11883 \fn void QWidget::grabMouse(const QCursor &cursor) |
11993 \fn void QWidget::grabMouse(const QCursor &cursor) |
11884 \overload |
11994 \overload grabMouse() |
11885 |
11995 |
11886 Grabs the mouse input and changes the cursor shape. |
11996 Grabs the mouse input and changes the cursor shape. |
11887 |
11997 |
11888 The cursor will assume shape \a cursor (for as long as the mouse |
11998 The cursor will assume shape \a cursor (for as long as the mouse |
11889 focus is grabbed) and this widget will be the only one to receive |
11999 focus is grabbed) and this widget will be the only one to receive |
11890 mouse events until releaseMouse() is called(). |
12000 mouse events until releaseMouse() is called(). |
11891 |
12001 |
11892 \warning Grabbing the mouse might lock the terminal. |
12002 \warning Grabbing the mouse might lock the terminal. |
|
12003 |
|
12004 \note \bold{(Mac OS X developers)} See the note in QWidget::grabMouse(). |
11893 |
12005 |
11894 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor() |
12006 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor() |
11895 */ |
12007 */ |
11896 |
12008 |
11897 /*! |
12009 /*! |