1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2016 Intel Corporation.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtWidgets module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include "qapplication.h"
42#include "qapplication_p.h"
43#include "qbrush.h"
44#include "qcursor.h"
45#include "qdesktopwidget_p.h"
46#include "qevent.h"
47#include "qlayout.h"
48#include "qmenu.h"
49#include "qmetaobject.h"
50#include "qpixmap.h"
51#include "qpointer.h"
52#include "qstack.h"
53#include "qstyle.h"
54#include "qstylefactory.h"
55#include "qvariant.h"
56#include "qwidget.h"
57#include "qstyleoption.h"
58#include "qstylehints.h"
59#ifndef QT_NO_ACCESSIBILITY
60# include "qaccessible.h"
61#endif
62#if 0 // Used to be included in Qt4 for Q_WS_MAC
63# include "qt_mac_p.h"
64# include "qt_cocoa_helpers_mac_p.h"
65# include "qmainwindow.h"
66# include "qtoolbar.h"
67# include <private/qmainwindowlayout_p.h>
68#endif
69#include <qpa/qplatformwindow.h>
70#include "private/qwidgetwindow_p.h"
71#include "qpainter.h"
72#include "qtooltip.h"
73#include "qwhatsthis.h"
74#include "qdebug.h"
75#include "private/qstylesheetstyle_p.h"
76#include "private/qstyle_p.h"
77#include "qfileinfo.h"
78#include <QtGui/private/qhighdpiscaling_p.h>
79#include <QtGui/qinputmethod.h>
80#include <QtGui/qopenglcontext.h>
81#include <QtGui/private/qopenglcontext_p.h>
82#include <QtGui/qoffscreensurface.h>
83
84#include <private/qgraphicseffect_p.h>
85#include <qbackingstore.h>
86#include <private/qwidgetbackingstore_p.h>
87#if 0 // Used to be included in Qt4 for Q_WS_MAC
88# include <private/qpaintengine_mac_p.h>
89#endif
90#include <private/qpaintengine_raster_p.h>
91
92#include "qwidget_p.h"
93#include <QtGui/private/qwindow_p.h>
94#include "qaction_p.h"
95#include "qlayout_p.h"
96#include "QtWidgets/qgraphicsproxywidget.h"
97#include "QtWidgets/qgraphicsscene.h"
98#include "private/qgraphicsproxywidget_p.h"
99#include "QtWidgets/qabstractscrollarea.h"
100#include "private/qabstractscrollarea_p.h"
101#include "private/qevent_p.h"
102
103#include "private/qgesturemanager_p.h"
104
105#ifdef QT_KEYPAD_NAVIGATION
106#include "qtabwidget.h" // Needed in inTabWidget()
107#endif // QT_KEYPAD_NAVIGATION
108
109#include "qwindowcontainer_p.h"
110
111#include <QtPlatformHeaders/qxcbwindowfunctions.h>
112
113// widget/widget data creation count
114//#define QWIDGET_EXTRA_DEBUG
115//#define ALIEN_DEBUG
116
117QT_BEGIN_NAMESPACE
118
119static bool qt_enable_backingstore = true;
120#if 0 // Used to be included in Qt4 for Q_WS_X11
121// for compatibility with Qt 4.0
122Q_WIDGETS_EXPORT void qt_x11_set_global_double_buffer(bool enable)
123{
124 qt_enable_backingstore = enable;
125}
126#endif
127
128#if 0 // Used to be included in Qt4 for Q_WS_MAC
129bool qt_mac_clearDirtyOnWidgetInsideDrawWidget = false;
130#endif
131
132static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
133{
134 return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) &&
135 qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));
136}
137
138static inline bool hasBackingStoreSupport()
139{
140 return true;
141}
142
143#if 0 // Used to be included in Qt4 for Q_WS_MAC
144# define QT_NO_PAINT_DEBUG
145#endif
146
147extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
148extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp
149
150/*!
151 \internal
152 \class QWidgetBackingStoreTracker
153 \brief Class which allows tracking of which widgets are using a given backing store
154
155 QWidgetBackingStoreTracker is a thin wrapper around a QWidgetBackingStore pointer,
156 which maintains a list of the QWidgets which are currently using the backing
157 store. This list is modified via the registerWidget and unregisterWidget functions.
158 */
159
160QWidgetBackingStoreTracker::QWidgetBackingStoreTracker()
161 : m_ptr(0)
162{
163
164}
165
166QWidgetBackingStoreTracker::~QWidgetBackingStoreTracker()
167{
168 delete m_ptr;
169}
170
171/*!
172 \internal
173 Destroy the contained QWidgetBackingStore, if not null, and clear the list of
174 widgets using the backing store, then create a new QWidgetBackingStore, providing
175 the QWidget.
176 */
177void QWidgetBackingStoreTracker::create(QWidget *widget)
178{
179 destroy();
180 m_ptr = new QWidgetBackingStore(widget);
181}
182
183/*!
184 \internal
185 Destroy the contained QWidgetBackingStore, if not null, and clear the list of
186 widgets using the backing store.
187 */
188void QWidgetBackingStoreTracker::destroy()
189{
190 delete m_ptr;
191 m_ptr = 0;
192 m_widgets.clear();
193}
194
195/*!
196 \internal
197 Add the widget to the list of widgets currently using the backing store.
198 If the widget was already in the list, this function is a no-op.
199 */
200void QWidgetBackingStoreTracker::registerWidget(QWidget *w)
201{
202 Q_ASSERT(m_ptr);
203 Q_ASSERT(w->internalWinId());
204 Q_ASSERT(qt_widget_private(w)->maybeBackingStore() == m_ptr);
205 m_widgets.insert(w);
206}
207
208/*!
209 \internal
210 Remove the widget from the list of widgets currently using the backing store.
211 If the widget was in the list, and removing it causes the list to be empty,
212 the backing store is deleted.
213 If the widget was not in the list, this function is a no-op.
214 */
215void QWidgetBackingStoreTracker::unregisterWidget(QWidget *w)
216{
217 if (m_widgets.remove(w) && m_widgets.isEmpty()) {
218 delete m_ptr;
219 m_ptr = 0;
220 }
221}
222
223/*!
224 \internal
225 Recursively remove widget and all of its descendents.
226 */
227void QWidgetBackingStoreTracker::unregisterWidgetSubtree(QWidget *widget)
228{
229 unregisterWidget(widget);
230 foreach (QObject *child, widget->children())
231 if (QWidget *childWidget = qobject_cast<QWidget *>(child))
232 unregisterWidgetSubtree(childWidget);
233}
234
235QWidgetPrivate::QWidgetPrivate(int version)
236 : QObjectPrivate(version)
237 , extra(0)
238 , focus_next(0)
239 , focus_prev(0)
240 , focus_child(0)
241 , layout(0)
242 , needsFlush(0)
243 , redirectDev(0)
244 , widgetItem(0)
245 , extraPaintEngine(0)
246 , polished(0)
247 , graphicsEffect(0)
248#if !defined(QT_NO_IM)
249 , imHints(Qt::ImhNone)
250#endif
251#ifndef QT_NO_TOOLTIP
252 , toolTipDuration(-1)
253#endif
254 , inheritedFontResolveMask(0)
255 , inheritedPaletteResolveMask(0)
256 , leftmargin(0)
257 , topmargin(0)
258 , rightmargin(0)
259 , bottommargin(0)
260 , leftLayoutItemMargin(0)
261 , topLayoutItemMargin(0)
262 , rightLayoutItemMargin(0)
263 , bottomLayoutItemMargin(0)
264 , hd(0)
265 , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
266 , fg_role(QPalette::NoRole)
267 , bg_role(QPalette::NoRole)
268 , dirtyOpaqueChildren(1)
269 , isOpaque(0)
270 , retainSizeWhenHiddenChanged(0)
271 , inDirtyList(0)
272 , isScrolled(0)
273 , isMoved(0)
274 , usesDoubleBufferedGLContext(0)
275 , mustHaveWindowHandle(0)
276 , renderToTexture(0)
277 , textureChildSeen(0)
278#ifndef QT_NO_IM
279 , inheritsInputMethodHints(0)
280#endif
281#ifndef QT_NO_OPENGL
282 , renderToTextureReallyDirty(1)
283 , renderToTextureComposeActive(0)
284#endif
285 , childrenHiddenByWState(0)
286 , childrenShownByExpose(0)
287#if defined(Q_OS_WIN)
288 , noPaintOnScreen(0)
289#endif
290#if 0 // Used to be included in Qt4 for Q_WS_X11
291 , picture(0)
292#elif 0 // Used to be included in Qt4 for Q_WS_WIN
293 #ifndef QT_NO_GESTURES
294 , nativeGesturePanEnabled(0)
295 #endif
296#elif 0 // Used to be included in Qt4 for Q_WS_MAC
297 , needWindowChange(0)
298 , window_event(0)
299 , qd_hd(0)
300#endif
301{
302 if (Q_UNLIKELY(!qApp)) {
303 qFatal("QWidget: Must construct a QApplication before a QWidget");
304 return;
305 }
306
307#ifdef QT_BUILD_INTERNAL
308 // Don't check the version parameter in internal builds.
309 // This allows incompatible versions to be loaded, possibly for testing.
310 Q_UNUSED(version);
311#else
312 if (Q_UNLIKELY(version != QObjectPrivateVersion))
313 qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)",
314 version, QObjectPrivateVersion);
315#endif
316
317 isWidget = true;
318 memset(high_attributes, 0, sizeof(high_attributes));
319#if 0 // Used to be included in Qt4 for Q_WS_MAC
320 drawRectOriginalAdded = false;
321 originalDrawMethod = true;
322 changeMethods = false;
323 isInUnifiedToolbar = false;
324 unifiedSurface = 0;
325 toolbar_ancestor = 0;
326 flushRequested = false;
327 touchEventsEnabled = false;
328#endif
329#ifdef QWIDGET_EXTRA_DEBUG
330 static int count = 0;
331 qDebug() << "widgets" << ++count;
332#endif
333}
334
335
336QWidgetPrivate::~QWidgetPrivate()
337{
338 if (widgetItem)
339 widgetItem->wid = 0;
340
341 if (extra)
342 deleteExtra();
343}
344
345/*!
346 \internal
347*/
348void QWidgetPrivate::scrollChildren(int dx, int dy)
349{
350 Q_Q(QWidget);
351 if (q->children().size() > 0) { // scroll children
352 QPoint pd(dx, dy);
353 QObjectList childObjects = q->children();
354 for (int i = 0; i < childObjects.size(); ++i) { // move all children
355 QWidget *w = qobject_cast<QWidget*>(childObjects.at(i));
356 if (w && !w->isWindow()) {
357 QPoint oldp = w->pos();
358 QRect r(w->pos() + pd, w->size());
359 w->data->crect = r;
360 if (w->testAttribute(Qt::WA_WState_Created))
361 w->d_func()->setWSGeometry();
362 w->d_func()->setDirtyOpaqueRegion();
363 QMoveEvent e(r.topLeft(), oldp);
364 QApplication::sendEvent(w, &e);
365 }
366 }
367 }
368}
369
370void QWidgetPrivate::setWSGeometry()
371{
372 Q_Q(QWidget);
373 if (QWindow *window = q->windowHandle())
374 window->setGeometry(data.crect);
375}
376
377void QWidgetPrivate::updateWidgetTransform(QEvent *event)
378{
379 Q_Q(QWidget);
380 if (q == QGuiApplication::focusObject() || event->type() == QEvent::FocusIn) {
381 QTransform t;
382 QPoint p = q->mapTo(q->topLevelWidget(), QPoint(0,0));
383 t.translate(p.x(), p.y());
384 QGuiApplication::inputMethod()->setInputItemTransform(t);
385 QGuiApplication::inputMethod()->setInputItemRectangle(q->rect());
386 QGuiApplication::inputMethod()->update(Qt::ImInputItemClipRectangle);
387 }
388}
389
390#ifdef QT_KEYPAD_NAVIGATION
391QPointer<QWidget> QWidgetPrivate::editingWidget;
392
393/*!
394 Returns \c true if this widget currently has edit focus; otherwise false.
395
396 This feature is only available in Qt for Embedded Linux.
397
398 \sa setEditFocus(), QApplication::keypadNavigationEnabled()
399*/
400bool QWidget::hasEditFocus() const
401{
402 const QWidget* w = this;
403 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
404 w = w->d_func()->extra->focus_proxy;
405 return QWidgetPrivate::editingWidget == w;
406}
407
408/*!
409 \fn void QWidget::setEditFocus(bool enable)
410
411 If \a enable is true, make this widget have edit focus, in which
412 case Qt::Key_Up and Qt::Key_Down will be delivered to the widget
413 normally; otherwise, Qt::Key_Up and Qt::Key_Down are used to
414 change focus.
415
416 This feature is only available in Qt for Embedded Linux.
417
418 \sa hasEditFocus(), QApplication::keypadNavigationEnabled()
419*/
420void QWidget::setEditFocus(bool on)
421{
422 QWidget *f = this;
423 while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
424 f = f->d_func()->extra->focus_proxy;
425
426 if (QWidgetPrivate::editingWidget && QWidgetPrivate::editingWidget != f)
427 QWidgetPrivate::editingWidget->setEditFocus(false);
428
429 if (on && !f->hasFocus())
430 f->setFocus();
431
432 if ((!on && !QWidgetPrivate::editingWidget)
433 || (on && QWidgetPrivate::editingWidget == f)) {
434 return;
435 }
436
437 if (!on && QWidgetPrivate::editingWidget == f) {
438 QWidgetPrivate::editingWidget = 0;
439 QEvent event(QEvent::LeaveEditFocus);
440 QApplication::sendEvent(f, &event);
441 QApplication::sendEvent(f->style(), &event);
442 } else if (on) {
443 QWidgetPrivate::editingWidget = f;
444 QEvent event(QEvent::EnterEditFocus);
445 QApplication::sendEvent(f, &event);
446 QApplication::sendEvent(f->style(), &event);
447 }
448}
449#endif
450
451/*!
452 \property QWidget::autoFillBackground
453 \brief whether the widget background is filled automatically
454 \since 4.1
455
456 If enabled, this property will cause Qt to fill the background of the
457 widget before invoking the paint event. The color used is defined by the
458 QPalette::Window color role from the widget's \l{QPalette}{palette}.
459
460 In addition, Windows are always filled with QPalette::Window, unless the
461 WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
462
463 This property cannot be turned off (i.e., set to false) if a widget's
464 parent has a static gradient for its background.
465
466 \warning Use this property with caution in conjunction with
467 \l{Qt Style Sheets}. When a widget has a style sheet with a valid
468 background or a border-image, this property is automatically disabled.
469
470 By default, this property is \c false.
471
472 \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
473 {QWidget#Transparency and Double Buffering}{Transparency and Double Buffering}
474*/
475bool QWidget::autoFillBackground() const
476{
477 Q_D(const QWidget);
478 return d->extra && d->extra->autoFillBackground;
479}
480
481void QWidget::setAutoFillBackground(bool enabled)
482{
483 Q_D(QWidget);
484 if (!d->extra)
485 d->createExtra();
486 if (d->extra->autoFillBackground == enabled)
487 return;
488
489 d->extra->autoFillBackground = enabled;
490 d->updateIsOpaque();
491 update();
492 d->updateIsOpaque();
493}
494
495/*!
496 \class QWidget
497 \brief The QWidget class is the base class of all user interface objects.
498
499 \ingroup basicwidgets
500 \inmodule QtWidgets
501
502 The widget is the atom of the user interface: it receives mouse, keyboard
503 and other events from the window system, and paints a representation of
504 itself on the screen. Every widget is rectangular, and they are sorted in a
505 Z-order. A widget is clipped by its parent and by the widgets in front of
506 it.
507
508 A widget that is not embedded in a parent widget is called a window.
509 Usually, windows have a frame and a title bar, although it is also possible
510 to create windows without such decoration using suitable
511 \l{Qt::WindowFlags}{window flags}). In Qt, QMainWindow and the various
512 subclasses of QDialog are the most common window types.
513
514 Every widget's constructor accepts one or two standard arguments:
515
516 \list 1
517 \li \c{QWidget *parent = 0} is the parent of the new widget. If it is 0
518 (the default), the new widget will be a window. If not, it will be
519 a child of \e parent, and be constrained by \e parent's geometry
520 (unless you specify Qt::Window as window flag).
521 \li \c{Qt::WindowFlags f = 0} (where available) sets the window flags;
522 the default is suitable for almost all widgets, but to get, for
523 example, a window without a window system frame, you must use
524 special flags.
525 \endlist
526
527 QWidget has many member functions, but some of them have little direct
528 functionality; for example, QWidget has a font property, but never uses
529 this itself. There are many subclasses which provide real functionality,
530 such as QLabel, QPushButton, QListWidget, and QTabWidget.
531
532
533 \section1 Top-Level and Child Widgets
534
535 A widget without a parent widget is always an independent window (top-level
536 widget). For these widgets, setWindowTitle() and setWindowIcon() set the
537 title bar and icon respectively.
538
539 Non-window widgets are child widgets, displayed within their parent
540 widgets. Most widgets in Qt are mainly useful as child widgets. For
541 example, it is possible to display a button as a top-level window, but most
542 people prefer to put their buttons inside other widgets, such as QDialog.
543
544 \image parent-child-widgets.png A parent widget containing various child widgets.
545
546 The diagram above shows a QGroupBox widget being used to hold various child
547 widgets in a layout provided by QGridLayout. The QLabel child widgets have
548 been outlined to indicate their full sizes.
549
550 If you want to use a QWidget to hold child widgets you will usually want to
551 add a layout to the parent QWidget. See \l{Layout Management} for more
552 information.
553
554
555 \section1 Composite Widgets
556
557 When a widget is used as a container to group a number of child widgets, it
558 is known as a composite widget. These can be created by constructing a
559 widget with the required visual properties - a QFrame, for example - and
560 adding child widgets to it, usually managed by a layout. The above diagram
561 shows such a composite widget that was created using Qt Designer.
562
563 Composite widgets can also be created by subclassing a standard widget,
564 such as QWidget or QFrame, and adding the necessary layout and child
565 widgets in the constructor of the subclass. Many of the \l{Qt Widgets Examples}
566 {examples provided with Qt} use this approach, and it is also covered in
567 the Qt \l{Tutorials}.
568
569
570 \section1 Custom Widgets and Painting
571
572 Since QWidget is a subclass of QPaintDevice, subclasses can be used to
573 display custom content that is composed using a series of painting
574 operations with an instance of the QPainter class. This approach contrasts
575 with the canvas-style approach used by the \l{Graphics View}
576 {Graphics View Framework} where items are added to a scene by the
577 application and are rendered by the framework itself.
578
579 Each widget performs all painting operations from within its paintEvent()
580 function. This is called whenever the widget needs to be redrawn, either
581 as a result of some external change or when requested by the application.
582
583 The \l{widgets/analogclock}{Analog Clock example} shows how a simple widget
584 can handle paint events.
585
586
587 \section1 Size Hints and Size Policies
588
589 When implementing a new widget, it is almost always useful to reimplement
590 sizeHint() to provide a reasonable default size for the widget and to set
591 the correct size policy with setSizePolicy().
592
593 By default, composite widgets which do not provide a size hint will be
594 sized according to the space requirements of their child widgets.
595
596 The size policy lets you supply good default behavior for the layout
597 management system, so that other widgets can contain and manage yours
598 easily. The default size policy indicates that the size hint represents
599 the preferred size of the widget, and this is often good enough for many
600 widgets.
601
602 \note The size of top-level widgets are constrained to 2/3 of the desktop's
603 height and width. You can resize() the widget manually if these bounds are
604 inadequate.
605
606
607 \section1 Events
608
609 Widgets respond to events that are typically caused by user actions. Qt
610 delivers events to widgets by calling specific event handler functions with
611 instances of QEvent subclasses containing information about each event.
612
613 If your widget only contains child widgets, you probably do not need to
614 implement any event handlers. If you want to detect a mouse click in a
615 child widget call the child's underMouse() function inside the widget's
616 mousePressEvent().
617
618 The \l{widgets/scribble}{Scribble example} implements a wider set of
619 events to handle mouse movement, button presses, and window resizing.
620
621 You will need to supply the behavior and content for your own widgets, but
622 here is a brief overview of the events that are relevant to QWidget,
623 starting with the most common ones:
624
625 \list
626 \li paintEvent() is called whenever the widget needs to be repainted.
627 Every widget displaying custom content must implement it. Painting
628 using a QPainter can only take place in a paintEvent() or a
629 function called by a paintEvent().
630 \li resizeEvent() is called when the widget has been resized.
631 \li mousePressEvent() is called when a mouse button is pressed while
632 the mouse cursor is inside the widget, or when the widget has
633 grabbed the mouse using grabMouse(). Pressing the mouse without
634 releasing it is effectively the same as calling grabMouse().
635 \li mouseReleaseEvent() is called when a mouse button is released. A
636 widget receives mouse release events when it has received the
637 corresponding mouse press event. This means that if the user
638 presses the mouse inside \e your widget, then drags the mouse
639 somewhere else before releasing the mouse button, \e your widget
640 receives the release event. There is one exception: if a popup menu
641 appears while the mouse button is held down, this popup immediately
642 steals the mouse events.
643 \li mouseDoubleClickEvent() is called when the user double-clicks in
644 the widget. If the user double-clicks, the widget receives a mouse
645 press event, a mouse release event, (a mouse click event,) a second
646 mouse press, this event and finally a second mouse release event.
647 (Some mouse move events may also be
648 received if the mouse is not held steady during this operation.) It
649 is \e{not possible} to distinguish a click from a double-click
650 until the second click arrives. (This is one reason why most GUI
651 books recommend that double-clicks be an extension of
652 single-clicks, rather than trigger a different action.)
653 \endlist
654
655 Widgets that accept keyboard input need to reimplement a few more event
656 handlers:
657
658 \list
659 \li keyPressEvent() is called whenever a key is pressed, and again when
660 a key has been held down long enough for it to auto-repeat. The
661 \uicontrol Tab and \uicontrol Shift+Tab keys are only passed to the widget if
662 they are not used by the focus-change mechanisms. To force those
663 keys to be processed by your widget, you must reimplement
664 QWidget::event().
665 \li focusInEvent() is called when the widget gains keyboard focus
666 (assuming you have called setFocusPolicy()). Well-behaved widgets
667 indicate that they own the keyboard focus in a clear but discreet
668 way.
669 \li focusOutEvent() is called when the widget loses keyboard focus.
670 \endlist
671
672 You may be required to also reimplement some of the less common event
673 handlers:
674
675 \list
676 \li mouseMoveEvent() is called whenever the mouse moves while a mouse
677 button is held down. This can be useful during drag and drop
678 operations. If you call \l{setMouseTracking()}{setMouseTracking}(true),
679 you get mouse move events even when no buttons are held down.
680 (See also the \l{Drag and Drop} guide.)
681 \li keyReleaseEvent() is called whenever a key is released and while it
682 is held down (if the key is auto-repeating). In that case, the
683 widget will receive a pair of key release and key press event for
684 every repeat. The \uicontrol Tab and \uicontrol Shift+Tab keys are only passed
685 to the widget if they are not used by the focus-change mechanisms.
686 To force those keys to be processed by your widget, you must
687 reimplement QWidget::event().
688 \li wheelEvent() is called whenever the user turns the mouse wheel
689 while the widget has the focus.
690 \li enterEvent() is called when the mouse enters the widget's screen
691 space. (This excludes screen space owned by any of the widget's
692 children.)
693 \li leaveEvent() is called when the mouse leaves the widget's screen
694 space. If the mouse enters a child widget it will not cause a
695 leaveEvent().
696 \li moveEvent() is called when the widget has been moved relative to
697 its parent.
698 \li closeEvent() is called when the user closes the widget (or when
699 close() is called).
700 \endlist
701
702 There are also some rather obscure events described in the documentation
703 for QEvent::Type. To handle these events, you need to reimplement event()
704 directly.
705
706 The default implementation of event() handles \uicontrol Tab and \uicontrol Shift+Tab
707 (to move the keyboard focus), and passes on most of the other events to
708 one of the more specialized handlers above.
709
710 Events and the mechanism used to deliver them are covered in
711 \l{The Event System}.
712
713 \section1 Groups of Functions and Properties
714
715 \table
716 \header \li Context \li Functions and Properties
717
718 \row \li Window functions \li
719 show(),
720 hide(),
721 raise(),
722 lower(),
723 close().
724
725 \row \li Top-level windows \li
726 \l windowModified, \l windowTitle, \l windowIcon,
727 \l isActiveWindow, activateWindow(), \l minimized, showMinimized(),
728 \l maximized, showMaximized(), \l fullScreen, showFullScreen(),
729 showNormal().
730
731 \row \li Window contents \li
732 update(),
733 repaint(),
734 scroll().
735
736 \row \li Geometry \li
737 \l pos, x(), y(), \l rect, \l size, width(), height(), move(), resize(),
738 \l sizePolicy, sizeHint(), minimumSizeHint(),
739 updateGeometry(), layout(),
740 \l frameGeometry, \l geometry, \l childrenRect, \l childrenRegion,
741 adjustSize(),
742 mapFromGlobal(), mapToGlobal(),
743 mapFromParent(), mapToParent(),
744 \l maximumSize, \l minimumSize, \l sizeIncrement,
745 \l baseSize, setFixedSize()
746
747 \row \li Mode \li
748 \l visible, isVisibleTo(),
749 \l enabled, isEnabledTo(),
750 \l modal,
751 isWindow(),
752 \l mouseTracking,
753 \l updatesEnabled,
754 visibleRegion().
755
756 \row \li Look and feel \li
757 style(),
758 setStyle(),
759 \l styleSheet,
760 \l cursor,
761 \l font,
762 \l palette,
763 backgroundRole(), setBackgroundRole(),
764 fontInfo(), fontMetrics().
765
766 \row \li Keyboard focus functions \li
767 \l focus, \l focusPolicy,
768 setFocus(), clearFocus(), setTabOrder(), setFocusProxy(),
769 focusNextChild(), focusPreviousChild().
770
771 \row \li Mouse and keyboard grabbing \li
772 grabMouse(), releaseMouse(),
773 grabKeyboard(), releaseKeyboard(),
774 mouseGrabber(), keyboardGrabber().
775
776 \row \li Event handlers \li
777 event(),
778 mousePressEvent(),
779 mouseReleaseEvent(),
780 mouseDoubleClickEvent(),
781 mouseMoveEvent(),
782 keyPressEvent(),
783 keyReleaseEvent(),
784 focusInEvent(),
785 focusOutEvent(),
786 wheelEvent(),
787 enterEvent(),
788 leaveEvent(),
789 paintEvent(),
790 moveEvent(),
791 resizeEvent(),
792 closeEvent(),
793 dragEnterEvent(),
794 dragMoveEvent(),
795 dragLeaveEvent(),
796 dropEvent(),
797 childEvent(),
798 showEvent(),
799 hideEvent(),
800 customEvent().
801 changeEvent(),
802
803 \row \li System functions \li
804 parentWidget(), window(), setParent(), winId(),
805 find(), metric().
806
807 \row \li Context menu \li
808 contextMenuPolicy, contextMenuEvent(),
809 customContextMenuRequested(), actions()
810
811 \row \li Interactive help \li
812 setToolTip(), setWhatsThis()
813
814 \endtable
815
816
817 \section1 Widget Style Sheets
818
819 In addition to the standard widget styles for each platform, widgets can
820 also be styled according to rules specified in a \l{styleSheet}
821 {style sheet}. This feature enables you to customize the appearance of
822 specific widgets to provide visual cues to users about their purpose. For
823 example, a button could be styled in a particular way to indicate that it
824 performs a destructive action.
825
826 The use of widget style sheets is described in more detail in the
827 \l{Qt Style Sheets} document.
828
829
830 \section1 Transparency and Double Buffering
831
832 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
833 is no need to write double-buffering code in paintEvent() to avoid
834 flicker.
835
836 Since Qt 4.1, the Qt::WA_ContentsPropagated widget attribute has been
837 deprecated. Instead, the contents of parent widgets are propagated by
838 default to each of their children as long as Qt::WA_PaintOnScreen is not
839 set. Custom widgets can be written to take advantage of this feature by
840 updating irregular regions (to create non-rectangular child widgets), or
841 painting with colors that have less than full alpha component. The
842 following diagram shows how attributes and properties of a custom widget
843 can be fine-tuned to achieve different effects.
844
845 \image propagation-custom.png
846
847 In the above diagram, a semi-transparent rectangular child widget with an
848 area removed is constructed and added to a parent widget (a QLabel showing
849 a pixmap). Then, different properties and widget attributes are set to
850 achieve different effects:
851
852 \list
853 \li The left widget has no additional properties or widget attributes
854 set. This default state suits most custom widgets using
855 transparency, are irregularly-shaped, or do not paint over their
856 entire area with an opaque brush.
857 \li The center widget has the \l autoFillBackground property set. This
858 property is used with custom widgets that rely on the widget to
859 supply a default background, and do not paint over their entire
860 area with an opaque brush.
861 \li The right widget has the Qt::WA_OpaquePaintEvent widget attribute
862 set. This indicates that the widget will paint over its entire area
863 with opaque colors. The widget's area will initially be
864 \e{uninitialized}, represented in the diagram with a red diagonal
865 grid pattern that shines through the overpainted area. The
866 Qt::WA_OpaquePaintArea attribute is useful for widgets that need to
867 paint their own specialized contents quickly and do not need a
868 default filled background.
869 \endlist
870
871 To rapidly update custom widgets with simple background colors, such as
872 real-time plotting or graphing widgets, it is better to define a suitable
873 background color (using setBackgroundRole() with the
874 QPalette::Window role), set the \l autoFillBackground property, and only
875 implement the necessary drawing functionality in the widget's paintEvent().
876
877 To rapidly update custom widgets that constantly paint over their entire
878 areas with opaque content, e.g., video streaming widgets, it is better to
879 set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary overhead
880 associated with repainting the widget's background.
881
882 If a widget has both the Qt::WA_OpaquePaintEvent widget attribute \e{and}
883 the \l autoFillBackground property set, the Qt::WA_OpaquePaintEvent
884 attribute takes precedence. Depending on your requirements, you should
885 choose either one of them.
886
887 Since Qt 4.1, the contents of parent widgets are also propagated to
888 standard Qt widgets. This can lead to some unexpected results if the
889 parent widget is decorated in a non-standard way, as shown in the diagram
890 below.
891
892 \image propagation-standard.png
893
894 The scope for customizing the painting behavior of standard Qt widgets,
895 without resorting to subclassing, is slightly less than that possible for
896 custom widgets. Usually, the desired appearance of a standard widget can be
897 achieved by setting its \l autoFillBackground property.
898
899
900 \section1 Creating Translucent Windows
901
902 Since Qt 4.5, it has been possible to create windows with translucent regions
903 on window systems that support compositing.
904
905 To enable this feature in a top-level widget, set its Qt::WA_TranslucentBackground
906 attribute with setAttribute() and ensure that its background is painted with
907 non-opaque colors in the regions you want to be partially transparent.
908
909 Platform notes:
910
911 \list
912 \li X11: This feature relies on the use of an X server that supports ARGB visuals
913 and a compositing window manager.
914 \li Windows: The widget needs to have the Qt::FramelessWindowHint window flag set
915 for the translucency to work.
916 \endlist
917
918
919 \section1 Native Widgets vs Alien Widgets
920
921 Introduced in Qt 4.4, alien widgets are widgets unknown to the windowing
922 system. They do not have a native window handle associated with them. This
923 feature significantly speeds up widget painting, resizing, and removes flicker.
924
925 Should you require the old behavior with native windows, you can choose
926 one of the following options:
927
928 \list 1
929 \li Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
930 \li Set the Qt::AA_NativeWindows attribute on your application. All
931 widgets will be native widgets.
932 \li Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
933 and all of its ancestors will become native (unless
934 Qt::WA_DontCreateNativeAncestors is set).
935 \li Call QWidget::winId to enforce a native window (this implies 3).
936 \li Set the Qt::WA_PaintOnScreen attribute to enforce a native window
937 (this implies 3).
938 \endlist
939
940 \sa QEvent, QPainter, QGridLayout, QBoxLayout
941
942*/
943
944QWidgetMapper *QWidgetPrivate::mapper = 0; // widget with wid
945QWidgetSet *QWidgetPrivate::allWidgets = 0; // widgets with no wid
946
947
948/*****************************************************************************
949 QWidget utility functions
950 *****************************************************************************/
951
952QRegion qt_dirtyRegion(QWidget *widget)
953{
954 if (!widget)
955 return QRegion();
956
957 QWidgetBackingStore *bs = qt_widget_private(widget)->maybeBackingStore();
958 if (!bs)
959 return QRegion();
960
961 return bs->dirtyRegion(widget);
962}
963
964/*****************************************************************************
965 QWidget member functions
966 *****************************************************************************/
967
968/*
969 Widget state flags:
970 \list
971 \li Qt::WA_WState_Created The widget has a valid winId().
972 \li Qt::WA_WState_Visible The widget is currently visible.
973 \li Qt::WA_WState_Hidden The widget is hidden, i.e. it won't
974 become visible unless you call show() on it. Qt::WA_WState_Hidden
975 implies !Qt::WA_WState_Visible.
976 \li Qt::WA_WState_CompressKeys Compress keyboard events.
977 \li Qt::WA_WState_BlockUpdates Repaints and updates are disabled.
978 \li Qt::WA_WState_InPaintEvent Currently processing a paint event.
979 \li Qt::WA_WState_Reparented The widget has been reparented.
980 \li Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending.
981 \li Qt::WA_WState_DND (Deprecated) The widget supports drag and drop, see setAcceptDrops().
982 \endlist
983*/
984
985struct QWidgetExceptionCleaner
986{
987 /* this cleans up when the constructor throws an exception */
988 static inline void cleanup(QWidget *that, QWidgetPrivate *d)
989 {
990#ifdef QT_NO_EXCEPTIONS
991 Q_UNUSED(that);
992 Q_UNUSED(d);
993#else
994 QWidgetPrivate::allWidgets->remove(that);
995 if (d->focus_next != that) {
996 if (d->focus_next)
997 d->focus_next->d_func()->focus_prev = d->focus_prev;
998 if (d->focus_prev)
999 d->focus_prev->d_func()->focus_next = d->focus_next;
1000 }
1001#endif
1002 }
1003};
1004
1005/*!
1006 Constructs a widget which is a child of \a parent, with widget
1007 flags set to \a f.
1008
1009 If \a parent is 0, the new widget becomes a window. If
1010 \a parent is another widget, this widget becomes a child window
1011 inside \a parent. The new widget is deleted when its \a parent is
1012 deleted.
1013
1014 The widget flags argument, \a f, is normally 0, but it can be set
1015 to customize the frame of a window (i.e. \a
1016 parent must be 0). To customize the frame, use a value composed
1017 from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
1018
1019 If you add a child widget to an already visible widget you must
1020 explicitly show the child to make it visible.
1021
1022 Note that the X11 version of Qt may not be able to deliver all
1023 combinations of style flags on all systems. This is because on
1024 X11, Qt can only ask the window manager, and the window manager
1025 can override the application's settings. On Windows, Qt can set
1026 whatever flags you want.
1027
1028 \sa windowFlags
1029*/
1030QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
1031 : QObject(*new QWidgetPrivate, 0), QPaintDevice()
1032{
1033 QT_TRY {
1034 d_func()->init(parent, f);
1035 } QT_CATCH(...) {
1036 QWidgetExceptionCleaner::cleanup(this, d_func());
1037 QT_RETHROW;
1038 }
1039}
1040
1041
1042/*! \internal
1043*/
1044QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
1045 : QObject(dd, 0), QPaintDevice()
1046{
1047 Q_D(QWidget);
1048 QT_TRY {
1049 d->init(parent, f);
1050 } QT_CATCH(...) {
1051 QWidgetExceptionCleaner::cleanup(this, d_func());
1052 QT_RETHROW;
1053 }
1054}
1055
1056/*!
1057 \internal
1058*/
1059int QWidget::devType() const
1060{
1061 return QInternal::Widget;
1062}
1063
1064
1065//### w is a "this" ptr, passed as a param because QWorkspace needs special logic
1066void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
1067{
1068 bool customize = (flags & (Qt::CustomizeWindowHint
1069 | Qt::FramelessWindowHint
1070 | Qt::WindowTitleHint
1071 | Qt::WindowSystemMenuHint
1072 | Qt::WindowMinimizeButtonHint
1073 | Qt::WindowMaximizeButtonHint
1074 | Qt::WindowCloseButtonHint
1075 | Qt::WindowContextHelpButtonHint));
1076
1077 uint type = (flags & Qt::WindowType_Mask);
1078
1079 if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) {
1080 type = Qt::Window;
1081 flags |= Qt::Window;
1082 }
1083
1084 if (flags & Qt::CustomizeWindowHint) {
1085 // modify window flags to make them consistent.
1086 // Only enable this on non-Mac platforms. Since the old way of doing this would
1087 // interpret WindowSystemMenuHint as a close button and we can't change that behavior
1088 // we can't just add this in.
1089#if 1 // Used to be excluded in Qt4 for Q_WS_MAC
1090 if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
1091# ifdef Q_OS_WIN
1092 && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
1093# endif
1094 ) {
1095 flags |= Qt::WindowSystemMenuHint;
1096#else
1097 if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint
1098 | Qt::WindowSystemMenuHint)) {
1099#endif
1100 flags |= Qt::WindowTitleHint;
1101 flags &= ~Qt::FramelessWindowHint;
1102 }
1103 } else if (customize && !(flags & Qt::FramelessWindowHint)) {
1104 // if any of the window hints that affect the titlebar are set
1105 // and the window is supposed to have frame, we add a titlebar
1106 // and system menu by default.
1107 flags |= Qt::WindowSystemMenuHint;
1108 flags |= Qt::WindowTitleHint;
1109 }
1110 if (customize)
1111 ; // don't modify window flags if the user explicitly set them.
1112 else if (type == Qt::Dialog || type == Qt::Sheet)
1113 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint | Qt::WindowCloseButtonHint;
1114 else if (type == Qt::Tool)
1115 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
1116 else
1117 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint |
1118 Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint | Qt::WindowFullscreenButtonHint;
1119 if (w->testAttribute(Qt::WA_TransparentForMouseEvents))
1120 flags |= Qt::WindowTransparentForInput;
1121}
1122
1123void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
1124{
1125 Q_Q(QWidget);
1126 if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
1127 qFatal("QWidget: Cannot create a QWidget without QApplication");
1128
1129 Q_ASSERT(allWidgets);
1130 if (allWidgets)
1131 allWidgets->insert(q);
1132
1133 int targetScreen = -1;
1134 if (parentWidget && parentWidget->windowType() == Qt::Desktop) {
1135 const QDesktopScreenWidget *sw = qobject_cast<const QDesktopScreenWidget *>(parentWidget);
1136 targetScreen = sw ? sw->screenNumber() : 0;
1137 parentWidget = 0;
1138 }
1139
1140 q->data = &data;
1141
1142#ifndef QT_NO_THREAD
1143 if (!parent) {
1144 Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
1145 "Widgets must be created in the GUI thread.");
1146 }
1147#endif
1148
1149#if 0 // Used to be included in Qt4 for Q_WS_X11
1150 if (desktopWidget) {
1151 // make sure the widget is created on the same screen as the
1152 // programmer specified desktop widget
1153 xinfo = desktopWidget->d_func()->xinfo;
1154 }
1155#endif
1156 if (targetScreen >= 0) {
1157 topData()->initialScreenIndex = targetScreen;
1158 if (QWindow *window = q->windowHandle())
1159 window->setScreen(QGuiApplication::screens().value(targetScreen, Q_NULLPTR));
1160 }
1161
1162 data.fstrut_dirty = true;
1163
1164 data.winid = 0;
1165 data.widget_attributes = 0;
1166 data.window_flags = f;
1167 data.window_state = 0;
1168 data.focus_policy = 0;
1169 data.context_menu_policy = Qt::DefaultContextMenu;
1170 data.window_modality = Qt::NonModal;
1171
1172 data.sizehint_forced = 0;
1173 data.is_closing = 0;
1174 data.in_show = 0;
1175 data.in_set_window_state = 0;
1176 data.in_destructor = false;
1177
1178 // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
1179 if (f & Qt::MSWindowsOwnDC) {
1180 mustHaveWindowHandle = 1;
1181 q->setAttribute(Qt::WA_NativeWindow);
1182 }
1183//#if 0 // Used to be included in Qt4 for Q_WS_MAC
1184// q->setAttribute(Qt::WA_NativeWindow);
1185//#endif
1186
1187 q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
1188 adjustQuitOnCloseAttribute();
1189
1190 q->setAttribute(Qt::WA_WState_Hidden);
1191
1192 //give potential windows a bigger "pre-initial" size; create_sys() will give them a new size later
1193 data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
1194 focus_next = focus_prev = q;
1195
1196 if ((f & Qt::WindowType_Mask) == Qt::Desktop)
1197 q->create();
1198 else if (parentWidget)
1199 q->setParent(parentWidget, data.window_flags);
1200 else {
1201 adjustFlags(data.window_flags, q);
1202 resolveLayoutDirection();
1203 // opaque system background?
1204 const QBrush &background = q->palette().brush(QPalette::Window);
1205 setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
1206 }
1207 data.fnt = QFont(data.fnt, q);
1208#if 0 // Used to be included in Qt4 for Q_WS_X11
1209 data.fnt.x11SetScreen(xinfo.screen());
1210#endif
1211
1212 q->setAttribute(Qt::WA_PendingMoveEvent);
1213 q->setAttribute(Qt::WA_PendingResizeEvent);
1214
1215 if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
1216 QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
1217
1218 if (QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation)) // ### fixme: Qt 6: Remove AA_ImmediateWidgetCreation.
1219 q->create();
1220
1221 QEvent e(QEvent::Create);
1222 QApplication::sendEvent(q, &e);
1223 QApplication::postEvent(q, new QEvent(QEvent::PolishRequest));
1224
1225 extraPaintEngine = 0;
1226
1227#if 0 // Used to be included in Qt4 for Q_WS_MAC
1228 // If we add a child to the unified toolbar, we have to redirect the painting.
1229 if (parentWidget && parentWidget->d_func() && parentWidget->d_func()->isInUnifiedToolbar) {
1230 if (parentWidget->d_func()->unifiedSurface) {
1231 QWidget *toolbar = parentWidget->d_func()->toolbar_ancestor;
1232 parentWidget->d_func()->unifiedSurface->recursiveRedirect(toolbar, toolbar, toolbar->d_func()->toolbar_offset);
1233 }
1234 }
1235#endif
1236}
1237
1238
1239
1240void QWidgetPrivate::createRecursively()
1241{
1242 Q_Q(QWidget);
1243 q->create(0, true, true);
1244 for (int i = 0; i < children.size(); ++i) {
1245 QWidget *child = qobject_cast<QWidget *>(children.at(i));
1246 if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(Qt::WA_WState_Created))
1247 child->d_func()->createRecursively();
1248 }
1249}
1250
1251
1252// ### fixme: Qt 6: Remove parameter window from QWidget::create()
1253
1254/*!
1255 Creates a new widget window.
1256
1257 The parameter \a window is ignored in Qt 5. Please use
1258 QWindow::fromWinId() to create a QWindow wrapping a foreign
1259 window and pass it to QWidget::createWindowContainer() instead.
1260
1261 Initializes the window (sets the geometry etc.) if \a
1262 initializeWindow is true. If \a initializeWindow is false, no
1263 initialization is performed. This parameter only makes sense if \a
1264 window is a valid window.
1265
1266 Destroys the old window if \a destroyOldWindow is true. If \a
1267 destroyOldWindow is false, you are responsible for destroying the
1268 window yourself (using platform native code).
1269
1270 The QWidget constructor calls create(0,true,true) to create a
1271 window for this widget.
1272
1273 \sa createWindowContainer(), QWindow::fromWinId()
1274*/
1275
1276void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
1277{
1278 Q_D(QWidget);
1279 if (Q_UNLIKELY(window))
1280 qWarning("QWidget::create(): Parameter 'window' does not have any effect.");
1281 if (testAttribute(Qt::WA_WState_Created) && window == 0 && internalWinId())
1282 return;
1283
1284 if (d->data.in_destructor)
1285 return;
1286
1287 Qt::WindowType type = windowType();
1288 Qt::WindowFlags &flags = data->window_flags;
1289
1290 if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
1291 type = Qt::Window;
1292 flags |= Qt::Window;
1293 }
1294
1295 if (QWidget *parent = parentWidget()) {
1296 if (type & Qt::Window) {
1297 if (!parent->testAttribute(Qt::WA_WState_Created))
1298 parent->createWinId();
1299 } else if (testAttribute(Qt::WA_NativeWindow) && !parent->internalWinId()
1300 && !testAttribute(Qt::WA_DontCreateNativeAncestors)) {
1301 // We're about to create a native child widget that doesn't have a native parent;
1302 // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
1303 // attribute is set.
1304 d->createWinId();
1305 // Nothing more to do.
1306 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1307 Q_ASSERT(internalWinId());
1308 return;
1309 }
1310 }
1311
1312
1313 static const bool paintOnScreenEnv = qEnvironmentVariableIntValue("QT_ONSCREEN_PAINT") > 0;
1314 if (paintOnScreenEnv)
1315 setAttribute(Qt::WA_PaintOnScreen);
1316
1317 if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
1318 setAttribute(Qt::WA_NativeWindow);
1319
1320#ifdef ALIEN_DEBUG
1321 qDebug() << "QWidget::create:" << this << "parent:" << parentWidget()
1322 << "Alien?" << !testAttribute(Qt::WA_NativeWindow);
1323#endif
1324
1325#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ && !defined(QT_NO_DRAGANDDROP)
1326 // Unregister the dropsite (if already registered) before we
1327 // re-create the widget with a native window.
1328 if (testAttribute(Qt::WA_WState_Created) && !internalWinId() && testAttribute(Qt::WA_NativeWindow)
1329 && d->extra && d->extra->dropTarget) {
1330 d->registerDropSite(false);
1331 }
1332#endif
1333
1334 d->updateIsOpaque();
1335
1336 setAttribute(Qt::WA_WState_Created); // set created flag
1337 d->create_sys(window, initializeWindow, destroyOldWindow);
1338
1339 // a real toplevel window needs a backing store
1340 if (isWindow() && windowType() != Qt::Desktop) {
1341 d->topData()->backingStoreTracker.destroy();
1342 if (hasBackingStoreSupport())
1343 d->topData()->backingStoreTracker.create(this);
1344 }
1345
1346 d->setModal_sys();
1347
1348 if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))
1349 setAttribute(Qt::WA_DropSiteRegistered, true);
1350
1351#ifdef QT_EVAL
1352 extern void qt_eval_init_widget(QWidget *w);
1353 qt_eval_init_widget(this);
1354#endif
1355
1356 // need to force the resting of the icon after changing parents
1357 if (testAttribute(Qt::WA_SetWindowIcon))
1358 d->setWindowIcon_sys();
1359
1360 if (isWindow() && !d->topData()->iconText.isEmpty())
1361 d->setWindowIconText_helper(d->topData()->iconText);
1362 if (isWindow() && !d->topData()->caption.isEmpty())
1363 d->setWindowTitle_helper(d->topData()->caption);
1364 if (windowType() != Qt::Desktop) {
1365 d->updateSystemBackground();
1366
1367 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon))
1368 d->setWindowIcon_sys();
1369 }
1370
1371 // Frame strut update needed in cases where there are native widgets such as QGLWidget,
1372 // as those force native window creation on their ancestors before they are shown.
1373 // If the strut is not updated, any subsequent move of the top level window before show
1374 // will cause window frame to be ignored when positioning the window.
1375 // Note that this only helps on platforms that handle window creation synchronously.
1376 d->updateFrameStrut();
1377}
1378
1379void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
1380{
1381 QObjectList children = parentWidget->children();
1382 for (int i = 0; i < children.size(); i++) {
1383 if (children.at(i)->isWidgetType()) {
1384 const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
1385 if (childWidget) { // should not be necessary
1386 if (childWidget->testAttribute(Qt::WA_NativeWindow)) {
1387 if (!childWidget->internalWinId())
1388 childWidget->winId();
1389 if (childWidget->windowHandle()) {
1390 if (childWidget->isWindow()) {
1391 childWidget->windowHandle()->setTransientParent(parentWidget->window()->windowHandle());
1392 } else {
1393 childWidget->windowHandle()->setParent(childWidget->nativeParentWidget()->windowHandle());
1394 }
1395 }
1396 } else {
1397 q_createNativeChildrenAndSetParent(childWidget);
1398 }
1399 }
1400 }
1401 }
1402
1403}
1404
1405void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
1406{
1407 Q_Q(QWidget);
1408
1409 Q_UNUSED(window);
1410 Q_UNUSED(initializeWindow);
1411 Q_UNUSED(destroyOldWindow);
1412
1413 Qt::WindowFlags flags = data.window_flags;
1414
1415 if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
1416 return; // we only care about real toplevels
1417
1418 QWindow *win = topData()->window;
1419 // topData() ensures the extra is created but does not ensure 'window' is non-null
1420 // in case the extra was already valid.
1421 if (!win) {
1422 createTLSysExtra();
1423 win = topData()->window;
1424 }
1425
1426 const auto dynamicPropertyNames = q->dynamicPropertyNames();
1427 for (const QByteArray &propertyName : dynamicPropertyNames) {
1428 if (!qstrncmp(propertyName, "_q_platform_", 12))
1429 win->setProperty(propertyName, q->property(propertyName));
1430 }
1431
1432 if (q->testAttribute(Qt::WA_ShowWithoutActivating))
1433 win->setProperty("_q_showWithoutActivating", QVariant(true));
1434 if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow))
1435 win->setProperty("_q_macAlwaysShowToolWindow", QVariant::fromValue(QVariant(true)));
1436 setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
1437 win->setFlags(data.window_flags);
1438 fixPosIncludesFrame();
1439 if (q->testAttribute(Qt::WA_Moved)
1440 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
1441 win->setGeometry(q->geometry());
1442 else
1443 win->resize(q->size());
1444 if (win->isTopLevel()) {
1445 int screenNumber = topData()->initialScreenIndex;
1446 topData()->initialScreenIndex = -1;
1447 if (screenNumber < 0) {
1448 screenNumber = q->windowType() != Qt::Desktop
1449 ? QApplication::desktop()->screenNumber(q) : 0;
1450 }
1451 win->setScreen(QGuiApplication::screens().value(screenNumber, Q_NULLPTR));
1452 }
1453
1454 QSurfaceFormat format = win->requestedFormat();
1455 if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
1456 && q->testAttribute(Qt::WA_TranslucentBackground)) {
1457 format.setAlphaBufferSize(8);
1458 }
1459 win->setFormat(format);
1460
1461 if (QWidget *nativeParent = q->nativeParentWidget()) {
1462 if (nativeParent->windowHandle()) {
1463 if (flags & Qt::Window) {
1464 win->setTransientParent(nativeParent->window()->windowHandle());
1465 win->setParent(0);
1466 } else {
1467 win->setTransientParent(0);
1468 win->setParent(nativeParent->windowHandle());
1469 }
1470 }
1471 }
1472
1473 qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
1474 QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
1475
1476 if (q->windowType() != Qt::Desktop || q->testAttribute(Qt::WA_NativeWindow)) {
1477 win->create();
1478 // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
1479 win->handle()->setFrameStrutEventsEnabled(true);
1480 }
1481
1482 data.window_flags = win->flags();
1483 if (!win->isTopLevel()) // In a Widget world foreign windows can only be top level
1484 data.window_flags &= ~Qt::ForeignWindow;
1485
1486 if (!topData()->role.isNull())
1487 QXcbWindowFunctions::setWmWindowRole(win, topData()->role.toLatin1());
1488
1489 QBackingStore *store = q->backingStore();
1490
1491 if (!store) {
1492 if (win && q->windowType() != Qt::Desktop) {
1493 if (q->isTopLevel())
1494 q->setBackingStore(new QBackingStore(win));
1495 } else {
1496 q->setAttribute(Qt::WA_PaintOnScreen, true);
1497 }
1498 }
1499
1500 setWindowModified_helper();
1501
1502 if (win->handle()) {
1503 WId id = win->winId();
1504 // See the QPlatformWindow::winId() documentation
1505 Q_ASSERT(id != WId(0));
1506 setWinId(id);
1507 }
1508
1509 // Check children and create windows for them if necessary
1510 q_createNativeChildrenAndSetParent(q);
1511
1512 if (extra && !extra->mask.isEmpty())
1513 setMask_sys(extra->mask);
1514
1515 if (data.crect.width() == 0 || data.crect.height() == 0) {
1516 q->setAttribute(Qt::WA_OutsideWSRange, true);
1517 } else if (q->isVisible()) {
1518 // If widget is already shown, set window visible, too
1519 win->setVisible(true);
1520 }
1521}
1522
1523#ifdef Q_OS_WIN
1524static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1525#endif
1526
1527void QWidgetPrivate::createTLSysExtra()
1528{
1529 Q_Q(QWidget);
1530 if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
1531 extra->topextra->window = new QWidgetWindow(q);
1532 if (extra->minw || extra->minh)
1533 extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
1534 if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
1535 extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
1536 if (extra->topextra->opacity != 255 && q->isWindow())
1537 extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
1538#ifdef Q_OS_WIN
1539 // Pass on native parent handle for Widget embedded into Active X.
1540 const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
1541 if (activeXNativeParentHandle.isValid())
1542 extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
1543 if (q->inherits("QTipLabel") || q->inherits("QAlphaWidget"))
1544 extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
1545#endif
1546 }
1547
1548}
1549
1550/*!
1551 Destroys the widget.
1552
1553 All this widget's children are deleted first. The application
1554 exits if this widget is the main widget.
1555*/
1556
1557QWidget::~QWidget()
1558{
1559 Q_D(QWidget);
1560 d->data.in_destructor = true;
1561
1562#if defined (QT_CHECK_STATE)
1563 if (Q_UNLIKELY(paintingActive()))
1564 qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
1565#endif
1566
1567#ifndef QT_NO_GESTURES
1568 if (QGestureManager *manager = QGestureManager::instance()) {
1569 // \forall Qt::GestureType type : ungrabGesture(type) (inlined)
1570 for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
1571 manager->cleanupCachedGestures(this, *it);
1572 }
1573 d->gestureContext.clear();
1574#endif
1575
1576 // force acceptDrops false before winId is destroyed.
1577 d->registerDropSite(false);
1578
1579#ifndef QT_NO_ACTION
1580 // remove all actions from this widget
1581 for (int i = 0; i < d->actions.size(); ++i) {
1582 QActionPrivate *apriv = d->actions.at(i)->d_func();
1583 apriv->widgets.removeAll(this);
1584 }
1585 d->actions.clear();
1586#endif
1587
1588#ifndef QT_NO_SHORTCUT
1589 // Remove all shortcuts grabbed by this
1590 // widget, unless application is closing
1591 if (!QApplicationPrivate::is_app_closing && testAttribute(Qt::WA_GrabbedShortcut))
1592 qApp->d_func()->shortcutMap.removeShortcut(0, this, QKeySequence());
1593#endif
1594
1595 // delete layout while we still are a valid widget
1596 delete d->layout;
1597 d->layout = 0;
1598 // Remove myself from focus list
1599
1600 Q_ASSERT(d->focus_next->d_func()->focus_prev == this);
1601 Q_ASSERT(d->focus_prev->d_func()->focus_next == this);
1602
1603 if (d->focus_next != this) {
1604 d->focus_next->d_func()->focus_prev = d->focus_prev;
1605 d->focus_prev->d_func()->focus_next = d->focus_next;
1606 d->focus_next = d->focus_prev = 0;
1607 }
1608
1609
1610 QT_TRY {
1611#ifndef QT_NO_GRAPHICSVIEW
1612 const QWidget* w = this;
1613 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1614 w = w->d_func()->extra->focus_proxy;
1615 QWidget *window = w->window();
1616 QWExtra *e = window ? window->d_func()->extra : 0;
1617 if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1618#endif
1619 clearFocus();
1620 } QT_CATCH(...) {
1621 // swallow this problem because we are in a destructor
1622 }
1623
1624 d->setDirtyOpaqueRegion();
1625
1626 if (isWindow() && isVisible() && internalWinId()) {
1627 QT_TRY {
1628 d->close_helper(QWidgetPrivate::CloseNoEvent);
1629 } QT_CATCH(...) {
1630 // if we're out of memory, at least hide the window.
1631 QT_TRY {
1632 hide();
1633 } QT_CATCH(...) {
1634 // and if that also doesn't work, then give up
1635 }
1636 }
1637 }
1638
1639#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || 0 /* Used to be included in Qt4 for Q_WS_X11 */|| 0 /* Used to be included in Qt4 for Q_WS_MAC */
1640 else if (!internalWinId() && isVisible()) {
1641 qApp->d_func()->sendSyntheticEnterLeave(this);
1642 }
1643#endif
1644 else if (isVisible()) {
1645 qApp->d_func()->sendSyntheticEnterLeave(this);
1646 }
1647
1648 if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
1649 bs->removeDirtyWidget(this);
1650 if (testAttribute(Qt::WA_StaticContents))
1651 bs->removeStaticWidget(this);
1652 }
1653
1654 delete d->needsFlush;
1655 d->needsFlush = 0;
1656
1657 // The next 20 lines are duplicated from QObject, but required here
1658 // since QWidget deletes is children itself
1659 bool blocked = d->blockSig;
1660 d->blockSig = 0; // unblock signals so we always emit destroyed()
1661
1662 if (d->isSignalConnected(0)) {
1663 QT_TRY {
1664 emit destroyed(this);
1665 } QT_CATCH(...) {
1666 // all the signal/slots connections are still in place - if we don't
1667 // quit now, we will crash pretty soon.
1668 qWarning("Detected an unexpected exception in ~QWidget while emitting destroyed().");
1669 QT_RETHROW;
1670 }
1671 }
1672
1673 if (d->declarativeData) {
1674 if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) {
1675 if (QAbstractDeclarativeData::destroyed_qml1)
1676 QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
1677 } else {
1678 if (QAbstractDeclarativeData::destroyed)
1679 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1680 }
1681 d->declarativeData = 0; // don't activate again in ~QObject
1682 }
1683
1684 d->blockSig = blocked;
1685
1686#if 0 // Used to be included in Qt4 for Q_WS_MAC
1687 // QCocoaView holds a pointer back to this widget. Clear it now
1688 // to make sure it's not followed later on. The lifetime of the
1689 // QCocoaView might exceed the lifetime of this widget in cases
1690 // where Cocoa itself holds references to it.
1691 extern void qt_mac_clearCocoaViewQWidgetPointers(QWidget *);
1692 qt_mac_clearCocoaViewQWidgetPointers(this);
1693#endif
1694
1695 if (!d->children.isEmpty())
1696 d->deleteChildren();
1697
1698 QApplication::removePostedEvents(this);
1699
1700 QT_TRY {
1701 destroy(); // platform-dependent cleanup
1702 } QT_CATCH(...) {
1703 // if this fails we can't do anything about it but at least we are not allowed to throw.
1704 }
1705 --QWidgetPrivate::instanceCounter;
1706
1707 if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1708 QWidgetPrivate::allWidgets->remove(this);
1709
1710 QT_TRY {
1711 QEvent e(QEvent::Destroy);
1712 QCoreApplication::sendEvent(this, &e);
1713 } QT_CATCH(const std::exception&) {
1714 // if this fails we can't do anything about it but at least we are not allowed to throw.
1715 }
1716
1717#if QT_CONFIG(graphicseffect)
1718 delete d->graphicsEffect;
1719#endif
1720}
1721
1722int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1723int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1724
1725void QWidgetPrivate::setWinId(WId id) // set widget identifier
1726{
1727 Q_Q(QWidget);
1728 // the user might create a widget with Qt::Desktop window
1729 // attribute (or create another QDesktopWidget instance), which
1730 // will have the same windowid (the root window id) as the
1731 // qt_desktopWidget. We should not add the second desktop widget
1732 // to the mapper.
1733 bool userDesktopWidget = qt_desktopWidget != 0 && qt_desktopWidget != q && q->windowType() == Qt::Desktop;
1734 if (mapper && data.winid && !userDesktopWidget) {
1735 mapper->remove(data.winid);
1736 }
1737
1738 const WId oldWinId = data.winid;
1739
1740 data.winid = id;
1741#if 0 // Used to be included in Qt4 for Q_WS_X11
1742 hd = id; // X11: hd == ident
1743#endif
1744 if (mapper && id && !userDesktopWidget) {
1745 mapper->insert(data.winid, q);
1746 }
1747
1748 if(oldWinId != id) {
1749 QEvent e(QEvent::WinIdChange);
1750 QCoreApplication::sendEvent(q, &e);
1751 }
1752}
1753
1754void QWidgetPrivate::createTLExtra()
1755{
1756 if (!extra)
1757 createExtra();
1758 if (!extra->topextra) {
1759 QTLWExtra* x = extra->topextra = new QTLWExtra;
1760 x->icon = 0;
1761 x->backingStore = 0;
1762 x->sharedPainter = 0;
1763 x->incw = x->inch = 0;
1764 x->basew = x->baseh = 0;
1765 x->frameStrut.setCoords(0, 0, 0, 0);
1766 x->normalGeometry = QRect(0,0,-1,-1);
1767 x->savedFlags = 0;
1768 x->opacity = 255;
1769 x->posIncludesFrame = 0;
1770 x->sizeAdjusted = false;
1771 x->inTopLevelResize = false;
1772 x->inRepaint = false;
1773 x->embedded = 0;
1774 x->window = 0;
1775 x->shareContext = 0;
1776 x->initialScreenIndex = -1;
1777#if 0 // Used to be included in Qt4 for Q_WS_MAC
1778 x->wasMaximized = false;
1779#endif
1780#ifdef QWIDGET_EXTRA_DEBUG
1781 static int count = 0;
1782 qDebug() << "tlextra" << ++count;
1783#endif
1784 }
1785}
1786
1787/*!
1788 \internal
1789 Creates the widget extra data.
1790*/
1791
1792void QWidgetPrivate::createExtra()
1793{
1794 if (!extra) { // if not exists
1795 extra = new QWExtra;
1796 extra->glContext = 0;
1797 extra->topextra = 0;
1798#ifndef QT_NO_GRAPHICSVIEW
1799 extra->proxyWidget = 0;
1800#endif
1801#ifndef QT_NO_CURSOR
1802 extra->curs = 0;
1803#endif
1804 extra->minw = 0;
1805 extra->minh = 0;
1806 extra->maxw = QWIDGETSIZE_MAX;
1807 extra->maxh = QWIDGETSIZE_MAX;
1808 extra->customDpiX = 0;
1809 extra->customDpiY = 0;
1810 extra->explicitMinSize = 0;
1811 extra->explicitMaxSize = 0;
1812 extra->autoFillBackground = 0;
1813 extra->nativeChildrenForced = 0;
1814 extra->inRenderWithPainter = 0;
1815 extra->hasWindowContainer = false;
1816 extra->hasMask = 0;
1817 createSysExtra();
1818#ifdef QWIDGET_EXTRA_DEBUG
1819 static int count = 0;
1820 qDebug() << "extra" << ++count;
1821#endif
1822 }
1823}
1824
1825void QWidgetPrivate::createSysExtra()
1826{
1827}
1828
1829/*!
1830 \internal
1831 Deletes the widget extra data.
1832*/
1833
1834void QWidgetPrivate::deleteExtra()
1835{
1836 if (extra) { // if exists
1837#ifndef QT_NO_CURSOR
1838 delete extra->curs;
1839#endif
1840 deleteSysExtra();
1841#ifndef QT_NO_STYLE_STYLESHEET
1842 // dereference the stylesheet style
1843 if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(extra->style))
1844 proxy->deref();
1845#endif
1846 if (extra->topextra) {
1847 deleteTLSysExtra();
1848 // extra->topextra->backingStore destroyed in QWidgetPrivate::deleteTLSysExtra()
1849 delete extra->topextra->icon;
1850 delete extra->topextra;
1851 }
1852 delete extra;
1853 // extra->xic destroyed in QWidget::destroy()
1854 extra = 0;
1855 }
1856}
1857
1858void QWidgetPrivate::deleteSysExtra()
1859{
1860}
1861
1862static void deleteBackingStore(QWidgetPrivate *d)
1863{
1864 QTLWExtra *topData = d->topData();
1865
1866 // The context must be current when destroying the backing store as it may attempt to
1867 // release resources like textures and shader programs. The window may not be suitable
1868 // anymore as there will often not be a platform window underneath at this stage. Fall
1869 // back to a QOffscreenSurface in this case.
1870 QScopedPointer<QOffscreenSurface> tempSurface;
1871#ifndef QT_NO_OPENGL
1872 if (d->textureChildSeen && topData->shareContext) {
1873 if (topData->window->handle()) {
1874 topData->shareContext->makeCurrent(topData->window);
1875 } else {
1876 tempSurface.reset(new QOffscreenSurface);
1877 tempSurface->setFormat(topData->shareContext->format());
1878 tempSurface->create();
1879 topData->shareContext->makeCurrent(tempSurface.data());
1880 }
1881 }
1882#endif
1883
1884 delete topData->backingStore;
1885 topData->backingStore = 0;
1886
1887#ifndef QT_NO_OPENGL
1888 if (d->textureChildSeen && topData->shareContext)
1889 topData->shareContext->doneCurrent();
1890#endif
1891}
1892
1893void QWidgetPrivate::deleteTLSysExtra()
1894{
1895 if (extra && extra->topextra) {
1896 //the qplatformbackingstore may hold a reference to the window, so the backingstore
1897 //needs to be deleted first. If the backingstore holds GL resources, we need to
1898 // make the context current here. This is taken care of by deleteBackingStore().
1899
1900 extra->topextra->backingStoreTracker.destroy();
1901 deleteBackingStore(this);
1902#ifndef QT_NO_OPENGL
1903 qDeleteAll(extra->topextra->widgetTextures);
1904 extra->topextra->widgetTextures.clear();
1905 delete extra->topextra->shareContext;
1906 extra->topextra->shareContext = 0;
1907#endif
1908
1909 //the toplevel might have a context with a "qglcontext associated with it. We need to
1910 //delete the qglcontext before we delete the qplatformopenglcontext.
1911 //One unfortunate thing about this is that we potentially create a glContext just to
1912 //delete it straight afterwards.
1913 if (extra->topextra->window) {
1914 extra->topextra->window->destroy();
1915 }
1916 delete extra->topextra->window;
1917 extra->topextra->window = 0;
1918
1919 }
1920}
1921
1922/*
1923 Returns \c true if there are widgets above this which overlap with
1924 \a rect, which is in parent's coordinate system (same as crect).
1925*/
1926
1927bool QWidgetPrivate::isOverlapped(const QRect &rect) const
1928{
1929 Q_Q(const QWidget);
1930
1931 const QWidget *w = q;
1932 QRect r = rect;
1933 while (w) {
1934 if (w->isWindow())
1935 return false;
1936 QWidgetPrivate *pd = w->parentWidget()->d_func();
1937 bool above = false;
1938 for (int i = 0; i < pd->children.size(); ++i) {
1939 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
1940 if (!sibling || !sibling->isVisible() || sibling->isWindow())
1941 continue;
1942 if (!above) {
1943 above = (sibling == w);
1944 continue;
1945 }
1946
1947 if (qRectIntersects(sibling->d_func()->effectiveRectFor(sibling->data->crect), r)) {
1948 const QWExtra *siblingExtra = sibling->d_func()->extra;
1949 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1950 && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
1951 continue;
1952 }
1953 return true;
1954 }
1955 }
1956 w = w->parentWidget();
1957 r.translate(pd->data.crect.topLeft());
1958 }
1959 return false;
1960}
1961
1962void QWidgetPrivate::syncBackingStore()
1963{
1964 if (paintOnScreen()) {
1965 repaint_sys(dirty);
1966 dirty = QRegion();
1967 } else if (QWidgetBackingStore *bs = maybeBackingStore()) {
1968 bs->sync();
1969 }
1970}
1971
1972void QWidgetPrivate::syncBackingStore(const QRegion &region)
1973{
1974 if (paintOnScreen())
1975 repaint_sys(region);
1976 else if (QWidgetBackingStore *bs = maybeBackingStore()) {
1977 bs->sync(q_func(), region);
1978 }
1979}
1980
1981void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1982{
1983 Q_Q(QWidget);
1984
1985 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1986 return; // nothing we can do
1987
1988 if (enable != q->testAttribute(Qt::WA_UpdatesDisabled))
1989 return; // nothing to do
1990
1991 q->setAttribute(Qt::WA_UpdatesDisabled, !enable);
1992 if (enable)
1993 q->update();
1994
1995 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1996 for (int i = 0; i < children.size(); ++i) {
1997 QWidget *w = qobject_cast<QWidget *>(children.at(i));
1998 if (w && !w->isWindow() && !w->testAttribute(attribute))
1999 w->d_func()->setUpdatesEnabled_helper(enable);
2000 }
2001}
2002
2003/*!
2004 \internal
2005
2006 Propagate this widget's palette to all children, except style sheet
2007 widgets, and windows that don't enable window propagation (palettes don't
2008 normally propagate to windows).
2009*/
2010void QWidgetPrivate::propagatePaletteChange()
2011{
2012 Q_Q(QWidget);
2013 // Propagate a new inherited mask to all children.
2014#ifndef QT_NO_GRAPHICSVIEW
2015 if (!q->parentWidget() && extra && extra->proxyWidget) {
2016 QGraphicsProxyWidget *p = extra->proxyWidget;
2017 inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolve();
2018 } else
2019#endif //QT_NO_GRAPHICSVIEW
2020 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
2021 inheritedPaletteResolveMask = 0;
2022 }
2023 int mask = data.pal.resolve() | inheritedPaletteResolveMask;
2024
2025 const bool useStyleSheetPropagationInWidgetStyles =
2026 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
2027
2028 QEvent pc(QEvent::PaletteChange);
2029 QApplication::sendEvent(q, &pc);
2030 for (int i = 0; i < children.size(); ++i) {
2031 QWidget *w = qobject_cast<QWidget*>(children.at(i));
2032 if (w && (!w->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
2033 && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
2034 QWidgetPrivate *wd = w->d_func();
2035 wd->inheritedPaletteResolveMask = mask;
2036 wd->resolvePalette();
2037 }
2038 }
2039}
2040
2041/*
2042 Returns the widget's clipping rectangle.
2043*/
2044QRect QWidgetPrivate::clipRect() const
2045{
2046 Q_Q(const QWidget);
2047 const QWidget * w = q;
2048 if (!w->isVisible())
2049 return QRect();
2050 QRect r = effectiveRectFor(q->rect());
2051 int ox = 0;
2052 int oy = 0;
2053 while (w
2054 && w->isVisible()
2055 && !w->isWindow()
2056 && w->parentWidget()) {
2057 ox -= w->x();
2058 oy -= w->y();
2059 w = w->parentWidget();
2060 r &= QRect(ox, oy, w->width(), w->height());
2061 }
2062 return r;
2063}
2064
2065/*
2066 Returns the widget's clipping region (without siblings).
2067*/
2068QRegion QWidgetPrivate::clipRegion() const
2069{
2070 Q_Q(const QWidget);
2071 if (!q->isVisible())
2072 return QRegion();
2073 QRegion r(q->rect());
2074 const QWidget * w = q;
2075 const QWidget *ignoreUpTo;
2076 int ox = 0;
2077 int oy = 0;
2078 while (w
2079 && w->isVisible()
2080 && !w->isWindow()
2081 && w->parentWidget()) {
2082 ox -= w->x();
2083 oy -= w->y();
2084 ignoreUpTo = w;
2085 w = w->parentWidget();
2086 r &= QRegion(ox, oy, w->width(), w->height());
2087
2088 int i = 0;
2089 while(w->d_func()->children.at(i++) != static_cast<const QObject *>(ignoreUpTo))
2090 ;
2091 for ( ; i < w->d_func()->children.size(); ++i) {
2092 if(QWidget *sibling = qobject_cast<QWidget *>(w->d_func()->children.at(i))) {
2093 if(sibling->isVisible() && !sibling->isWindow()) {
2094 QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
2095 sibling->width(), sibling->height());
2096 if (qRectIntersects(siblingRect, q->rect()))
2097 r -= QRegion(siblingRect);
2098 }
2099 }
2100 }
2101 }
2102 return r;
2103}
2104
2105void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
2106{
2107// Transform the system clip region from device-independent pixels to device pixels
2108 QTransform scaleTransform;
2109 scaleTransform.scale(devicePixelRatio, devicePixelRatio);
2110
2111 paintEngine->d_func()->baseSystemClip = region;
2112 paintEngine->d_func()->setSystemTransform(scaleTransform);
2113
2114}
2115
2116#ifndef QT_NO_GRAPHICSEFFECT
2117void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
2118{
2119 Q_Q(QWidget);
2120 QWidget *w = q;
2121 do {
2122 if (w->graphicsEffect()) {
2123 QWidgetEffectSourcePrivate *sourced =
2124 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
2125 if (!sourced->updateDueToGraphicsEffect)
2126 w->graphicsEffect()->source()->d_func()->invalidateCache();
2127 }
2128 w = w->parentWidget();
2129 } while (w);
2130}
2131#endif //QT_NO_GRAPHICSEFFECT
2132
2133void QWidgetPrivate::setDirtyOpaqueRegion()
2134{
2135 Q_Q(QWidget);
2136
2137 dirtyOpaqueChildren = true;
2138
2139#ifndef QT_NO_GRAPHICSEFFECT
2140 invalidateGraphicsEffectsRecursively();
2141#endif //QT_NO_GRAPHICSEFFECT
2142
2143 if (q->isWindow())
2144 return;
2145
2146 QWidget *parent = q->parentWidget();
2147 if (!parent)
2148 return;
2149
2150 // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
2151 QWidgetPrivate *pd = parent->d_func();
2152 if (!pd->dirtyOpaqueChildren)
2153 pd->setDirtyOpaqueRegion();
2154}
2155
2156const QRegion &QWidgetPrivate::getOpaqueChildren() const
2157{
2158 if (!dirtyOpaqueChildren)
2159 return opaqueChildren;
2160
2161 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
2162 that->opaqueChildren = QRegion();
2163
2164 for (int i = 0; i < children.size(); ++i) {
2165 QWidget *child = qobject_cast<QWidget *>(children.at(i));
2166 if (!child || !child->isVisible() || child->isWindow())
2167 continue;
2168
2169 const QPoint offset = child->geometry().topLeft();
2170 QWidgetPrivate *childd = child->d_func();
2171 QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
2172 if (childd->extra && childd->extra->hasMask)
2173 r &= childd->extra->mask;
2174 if (r.isEmpty())
2175 continue;
2176 r.translate(offset);
2177 that->opaqueChildren += r;
2178 }
2179
2180 that->opaqueChildren &= q_func()->rect();
2181 that->dirtyOpaqueChildren = false;
2182
2183 return that->opaqueChildren;
2184}
2185
2186void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2187{
2188 if (children.isEmpty() || clipRect.isEmpty())
2189 return;
2190
2191 const QRegion &r = getOpaqueChildren();
2192 if (!r.isEmpty())
2193 source -= (r & clipRect);
2194}
2195
2196//subtract any relatives that are higher up than me --- this is too expensive !!!
2197void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2198 bool alsoNonOpaque) const
2199{
2200 Q_Q(const QWidget);
2201 static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue("QT_NO_SUBTRACTOPAQUESIBLINGS");
2202 if (disableSubtractOpaqueSiblings || q->isWindow())
2203 return;
2204
2205#if 0 // Used to be included in Qt4 for Q_WS_MAC
2206 if (q->d_func()->isInUnifiedToolbar)
2207 return;
2208#endif
2209
2210 QRect clipBoundingRect;
2211 bool dirtyClipBoundingRect = true;
2212
2213 QRegion parentClip;
2214 bool dirtyParentClip = true;
2215
2216 QPoint parentOffset = data.crect.topLeft();
2217
2218 const QWidget *w = q;
2219
2220 while (w) {
2221 if (w->isWindow())
2222 break;
2223 QWidgetPrivate *pd = w->parentWidget()->d_func();
2224 const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w));
2225 const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect);
2226 for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2227 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
2228 if (!sibling || !sibling->isVisible() || sibling->isWindow())
2229 continue;
2230
2231 const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect);
2232 if (!qRectIntersects(siblingGeometry, widgetGeometry))
2233 continue;
2234
2235 if (dirtyClipBoundingRect) {
2236 clipBoundingRect = sourceRegion.boundingRect();
2237 dirtyClipBoundingRect = false;
2238 }
2239
2240 if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset)))
2241 continue;
2242
2243 if (dirtyParentClip) {
2244 parentClip = sourceRegion.translated(parentOffset);
2245 dirtyParentClip = false;
2246 }
2247
2248 const QPoint siblingPos(sibling->data->crect.topLeft());
2249 const QRect siblingClipRect(sibling->d_func()->clipRect());
2250 QRegion siblingDirty(parentClip);
2251 siblingDirty &= (siblingClipRect.translated(siblingPos));
2252 const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2253 && !sibling->d_func()->graphicsEffect;
2254 if (hasMask)
2255 siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos);
2256 if (siblingDirty.isEmpty())
2257 continue;
2258
2259 if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2260 if (hasMask) {
2261 siblingDirty.translate(-parentOffset);
2262 sourceRegion -= siblingDirty;
2263 } else {
2264 sourceRegion -= siblingGeometry.translated(-parentOffset);
2265 }
2266 } else {
2267 if (hasDirtySiblingsAbove)
2268 *hasDirtySiblingsAbove = true;
2269 if (sibling->d_func()->children.isEmpty())
2270 continue;
2271 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2272 opaqueSiblingChildren.translate(-parentOffset + siblingPos);
2273 sourceRegion -= opaqueSiblingChildren;
2274 }
2275 if (sourceRegion.isEmpty())
2276 return;
2277
2278 dirtyClipBoundingRect = true;
2279 dirtyParentClip = true;
2280 }
2281
2282 w = w->parentWidget();
2283 parentOffset += pd->data.crect.topLeft();
2284 dirtyParentClip = true;
2285 }
2286}
2287
2288void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2289{
2290 Q_Q(const QWidget);
2291
2292 const QWidget *w = q;
2293 QPoint offset;
2294
2295#ifndef QT_NO_GRAPHICSEFFECT
2296 if (graphicsEffect) {
2297 w = q->parentWidget();
2298 offset -= data.crect.topLeft();
2299 }
2300#endif //QT_NO_GRAPHICSEFFECT
2301
2302 while (w) {
2303 const QWidgetPrivate *wd = w->d_func();
2304 if (wd->extra && wd->extra->hasMask)
2305 region &= (w != q) ? wd->extra->mask.translated(offset) : wd->extra->mask;
2306 if (w->isWindow())
2307 return;
2308 offset -= wd->data.crect.topLeft();
2309 w = w->parentWidget();
2310 }
2311}
2312
2313bool QWidgetPrivate::paintOnScreen() const
2314{
2315#if defined(QT_NO_BACKINGSTORE)
2316 return true;
2317#else
2318 Q_Q(const QWidget);
2319 if (q->testAttribute(Qt::WA_PaintOnScreen)
2320 || (!q->isWindow() && q->window()->testAttribute(Qt::WA_PaintOnScreen))) {
2321 return true;
2322 }
2323
2324 return !qt_enable_backingstore;
2325#endif
2326}
2327
2328void QWidgetPrivate::updateIsOpaque()
2329{
2330 // hw: todo: only needed if opacity actually changed
2331 setDirtyOpaqueRegion();
2332
2333#ifndef QT_NO_GRAPHICSEFFECT
2334 if (graphicsEffect) {
2335 // ### We should probably add QGraphicsEffect::isOpaque at some point.
2336 setOpaque(false);
2337 return;
2338 }
2339#endif //QT_NO_GRAPHICSEFFECT
2340
2341 Q_Q(QWidget);
2342#if 0 // Used to be included in Qt4 for Q_WS_X11
2343 if (q->testAttribute(Qt::WA_X11OpenGLOverlay)) {
2344 setOpaque(false);
2345 return;
2346 }
2347#endif
2348
2349 if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) {
2350 setOpaque(true);
2351 return;
2352 }
2353
2354 const QPalette &pal = q->palette();
2355
2356 if (q->autoFillBackground()) {
2357 const QBrush &autoFillBrush = pal.brush(q->backgroundRole());
2358 if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2359 setOpaque(true);
2360 return;
2361 }
2362 }
2363
2364 if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) {
2365 const QBrush &windowBrush = q->palette().brush(QPalette::Window);
2366 if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2367 setOpaque(true);
2368 return;
2369 }
2370 }
2371 setOpaque(false);
2372}
2373
2374void QWidgetPrivate::setOpaque(bool opaque)
2375{
2376 if (isOpaque != opaque) {
2377 isOpaque = opaque;
2378 updateIsTranslucent();
2379 }
2380}
2381
2382void QWidgetPrivate::updateIsTranslucent()
2383{
2384 Q_Q(QWidget);
2385 if (QWindow *window = q->windowHandle()) {
2386 QSurfaceFormat format = window->format();
2387 const int oldAlpha = format.alphaBufferSize();
2388 const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground)? 8 : 0;
2389 if (oldAlpha != newAlpha) {
2390 format.setAlphaBufferSize(newAlpha);
2391 window->setFormat(format);
2392 }
2393 }
2394}
2395
2396static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2397{
2398 Q_ASSERT(painter);
2399
2400 if (brush.style() == Qt::TexturePattern) {
2401#if 0 // Used to be included in Qt4 for Q_WS_MAC
2402 // Optimize pattern filling on mac by using HITheme directly
2403 // when filling with the standard widget background.
2404 // Defined in qmacstyle_mac.cpp
2405 extern void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush);
2406 qt_mac_fill_background(painter, rgn, brush);
2407#else
2408 {
2409 const QRect rect(rgn.boundingRect());
2410 painter->setClipRegion(rgn);
2411 painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
2412 }
2413#endif
2414
2415 } else if (brush.gradient()
2416 && brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode) {
2417 painter->save();
2418 painter->setClipRegion(rgn);
2419 painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush);
2420 painter->restore();
2421 } else {
2422 for (const QRect &rect : rgn)
2423 painter->fillRect(rect, brush);
2424 }
2425}
2426
2427void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int flags) const
2428{
2429 Q_Q(const QWidget);
2430
2431#ifndef QT_NO_SCROLLAREA
2432 bool resetBrushOrigin = false;
2433 QPointF oldBrushOrigin;
2434 //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2435 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
2436 if (scrollArea && scrollArea->viewport() == q) {
2437 QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2438 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2439 oldBrushOrigin = painter->brushOrigin();
2440 resetBrushOrigin = true;
2441 painter->setBrushOrigin(-priv->contentsOffset());
2442
2443 }
2444#endif // QT_NO_SCROLLAREA
2445
2446 const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
2447
2448 if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2449 const QBrush bg = q->palette().brush(QPalette::Window);
2450 if (!(flags & DontSetCompositionMode)) {
2451 //copy alpha straight in
2452 QPainter::CompositionMode oldMode = painter->compositionMode();
2453 painter->setCompositionMode(QPainter::CompositionMode_Source);
2454 fillRegion(painter, rgn, bg);
2455 painter->setCompositionMode(oldMode);
2456 } else {
2457 fillRegion(painter, rgn, bg);
2458 }
2459 }
2460
2461 if (q->autoFillBackground())
2462 fillRegion(painter, rgn, autoFillBrush);
2463
2464 if (q->testAttribute(Qt::WA_StyledBackground)) {
2465 painter->setClipRegion(rgn);
2466 QStyleOption opt;
2467 opt.initFrom(q);
2468 q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
2469 }
2470
2471#ifndef QT_NO_SCROLLAREA
2472 if (resetBrushOrigin)
2473 painter->setBrushOrigin(oldBrushOrigin);
2474#endif // QT_NO_SCROLLAREA
2475}
2476
2477/*
2478 \internal
2479 This function is called when a widget is hidden or destroyed.
2480 It resets some application global pointers that should only refer active,
2481 visible widgets.
2482*/
2483
2484#if 0 // Used to be included in Qt4 for Q_WS_MAC
2485 extern QPointer<QWidget> qt_button_down;
2486#else
2487 extern QWidget *qt_button_down;
2488#endif
2489
2490void QWidgetPrivate::deactivateWidgetCleanup()
2491{
2492 Q_Q(QWidget);
2493 // If this was the active application window, reset it
2494 if (QApplication::activeWindow() == q)
2495 QApplication::setActiveWindow(0);
2496 // If the is the active mouse press widget, reset it
2497 if (q == qt_button_down)
2498 qt_button_down = 0;
2499}
2500
2501
2502/*!
2503 Returns a pointer to the widget with window identifer/handle \a
2504 id.
2505
2506 The window identifier type depends on the underlying window
2507 system, see \c qwindowdefs.h for the actual definition. If there
2508 is no widget with this identifier, 0 is returned.
2509*/
2510
2511QWidget *QWidget::find(WId id)
2512{
2513 return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : 0;
2514}
2515
2516
2517
2518/*!
2519 \fn WId QWidget::internalWinId() const
2520 \internal
2521 Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2522
2523*/
2524
2525/*!
2526 \fn WId QWidget::winId() const
2527
2528 Returns the window system identifier of the widget.
2529
2530 Portable in principle, but if you use it you are probably about to
2531 do something non-portable. Be careful.
2532
2533 If a widget is non-native (alien) and winId() is invoked on it, that widget
2534 will be provided a native handle.
2535
2536 This value may change at run-time. An event with type QEvent::WinIdChange
2537 will be sent to the widget following a change in window system identifier.
2538
2539 \sa find()
2540*/
2541WId QWidget::winId() const
2542{
2543 if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
2544#ifdef ALIEN_DEBUG
2545 qDebug() << "QWidget::winId: creating native window for" << this;
2546#endif
2547 QWidget *that = const_cast<QWidget*>(this);
2548 that->setAttribute(Qt::WA_NativeWindow);
2549 that->d_func()->createWinId();
2550 return that->data->winid;
2551 }
2552 return data->winid;
2553}
2554
2555void QWidgetPrivate::createWinId()
2556{
2557 Q_Q(QWidget);
2558
2559#ifdef ALIEN_DEBUG
2560 qDebug() << "QWidgetPrivate::createWinId for" << q;
2561#endif
2562 const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
2563 if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2564 if (!q->isWindow()) {
2565 QWidget *parent = q->parentWidget();
2566 QWidgetPrivate *pd = parent->d_func();
2567 if (forceNativeWindow && !q->testAttribute(Qt::WA_DontCreateNativeAncestors))
2568 parent->setAttribute(Qt::WA_NativeWindow);
2569 if (!parent->internalWinId()) {
2570 pd->createWinId();
2571 }
2572
2573 for (int i = 0; i < pd->children.size(); ++i) {
2574 QWidget *w = qobject_cast<QWidget *>(pd->children.at(i));
2575 if (w && !w->isWindow() && (!w->testAttribute(Qt::WA_WState_Created)
2576 || (!w->internalWinId() && w->testAttribute(Qt::WA_NativeWindow)))) {
2577 w->create();
2578 }
2579 }
2580 } else {
2581 q->create();
2582 }
2583 }
2584}
2585
2586
2587/*!
2588\internal
2589Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2590
2591*/
2592
2593void QWidget::createWinId()
2594{
2595 Q_D(QWidget);
2596#ifdef ALIEN_DEBUG
2597 qDebug() << "QWidget::createWinId" << this;
2598#endif
2599// qWarning("QWidget::createWinId is obsolete, please fix your code.");
2600 d->createWinId();
2601}
2602
2603/*!
2604 \since 4.4
2605
2606 Returns the effective window system identifier of the widget, i.e. the
2607 native parent's window system identifier.
2608
2609 If the widget is native, this function returns the native widget ID.
2610 Otherwise, the window ID of the first native parent widget, i.e., the
2611 top-level widget that contains this widget, is returned.
2612
2613 \note We recommend that you do not store this value as it is likely to
2614 change at run-time.
2615
2616 \sa nativeParentWidget()
2617*/
2618WId QWidget::effectiveWinId() const
2619{
2620 const WId id = internalWinId();
2621 if (id || !testAttribute(Qt::WA_WState_Created))
2622 return id;
2623 if (const QWidget *realParent = nativeParentWidget())
2624 return realParent->internalWinId();
2625 return 0;
2626}
2627
2628/*!
2629 If this is a native widget, return the associated QWindow.
2630 Otherwise return null.
2631
2632 Native widgets include toplevel widgets, QGLWidget, and child widgets
2633 on which winId() was called.
2634
2635 \since 5.0
2636
2637 \sa winId()
2638*/
2639QWindow *QWidget::windowHandle() const
2640{
2641 Q_D(const QWidget);
2642 QTLWExtra *extra = d->maybeTopData();
2643 if (extra)
2644 return extra->window;
2645
2646 return 0;
2647}
2648
2649#ifndef QT_NO_STYLE_STYLESHEET
2650
2651/*!
2652 \property QWidget::styleSheet
2653 \brief the widget's style sheet
2654 \since 4.2
2655
2656 The style sheet contains a textual description of customizations to the
2657 widget's style, as described in the \l{Qt Style Sheets} document.
2658
2659 Since Qt 4.5, Qt style sheets fully supports \macos.
2660
2661 \warning Qt style sheets are currently not supported for custom QStyle
2662 subclasses. We plan to address this in some future release.
2663
2664 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2665*/
2666QString QWidget::styleSheet() const
2667{
2668 Q_D(const QWidget);
2669 if (!d->extra)
2670 return QString();
2671 return d->extra->styleSheet;
2672}
2673
2674void QWidget::setStyleSheet(const QString& styleSheet)
2675{
2676 Q_D(QWidget);
2677 if (data->in_destructor)
2678 return;
2679 d->createExtra();
2680
2681 QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(d->extra->style);
2682 d->extra->styleSheet = styleSheet;
2683 if (styleSheet.isEmpty()) { // stylesheet removed
2684 if (!proxy)
2685 return;
2686
2687 d->inheritStyle();
2688 return;
2689 }
2690
2691 if (proxy) { // style sheet update
2692 if (d->polished)
2693 proxy->repolish(this);
2694 return;
2695 }
2696
2697 if (testAttribute(Qt::WA_SetStyle)) {
2698 d->setStyle_helper(new QStyleSheetStyle(d->extra->style), true);
2699 } else {
2700 d->setStyle_helper(new QStyleSheetStyle(0), true);
2701 }
2702}
2703
2704#endif // QT_NO_STYLE_STYLESHEET
2705
2706/*!
2707 \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2708*/
2709
2710QStyle *QWidget::style() const
2711{
2712 Q_D(const QWidget);
2713
2714 if (d->extra && d->extra->style)
2715 return d->extra->style;
2716 return QApplication::style();
2717}
2718
2719/*!
2720 Sets the widget's GUI style to \a style. The ownership of the style
2721 object is not transferred.
2722
2723 If no style is set, the widget uses the application's style,
2724 QApplication::style() instead.
2725
2726 Setting a widget's style has no effect on existing or future child
2727 widgets.
2728
2729 \warning This function is particularly useful for demonstration
2730 purposes, where you want to show Qt's styling capabilities. Real
2731 applications should avoid it and use one consistent GUI style
2732 instead.
2733
2734 \warning Qt style sheets are currently not supported for custom QStyle
2735 subclasses. We plan to address this in some future release.
2736
2737 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2738*/
2739
2740void QWidget::setStyle(QStyle *style)
2741{
2742 Q_D(QWidget);
2743 setAttribute(Qt::WA_SetStyle, style != 0);
2744 d->createExtra();
2745#ifndef QT_NO_STYLE_STYLESHEET
2746 if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(style)) {
2747 //if for some reason someone try to set a QStyleSheetStyle, ref it
2748 //(this may happen for exemple in QButtonDialogBox which propagates its style)
2749 proxy->ref();
2750 d->setStyle_helper(style, false);
2751 } else if (qobject_cast<QStyleSheetStyle *>(d->extra->style) || !qApp->styleSheet().isEmpty()) {
2752 // if we have an application stylesheet or have a proxy already, propagate
2753 d->setStyle_helper(new QStyleSheetStyle(style), true);
2754 } else
2755#endif
2756 d->setStyle_helper(style, false);
2757}
2758
2759void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool
2760#if 0 // Used to be included in Qt4 for Q_WS_MAC
2761 metalHack
2762#endif
2763 )
2764{
2765 Q_Q(QWidget);
2766 QStyle *oldStyle = q->style();
2767#ifndef QT_NO_STYLE_STYLESHEET
2768 QPointer<QStyle> origStyle;
2769#endif
2770
2771#if 0 // Used to be included in Qt4 for Q_WS_MAC
2772 // the metalhack boolean allows Qt/Mac to do a proper re-polish depending
2773 // on how the Qt::WA_MacBrushedMetal attribute is set. It is only ever
2774 // set when changing that attribute and passes the widget's CURRENT style.
2775 // therefore no need to do a reassignment.
2776 if (!metalHack)
2777#endif
2778 {
2779 createExtra();
2780
2781#ifndef QT_NO_STYLE_STYLESHEET
2782 origStyle = extra->style.data();
2783#endif
2784 extra->style = newStyle;
2785 }
2786
2787 // repolish
2788 if (q->windowType() != Qt::Desktop) {
2789 if (polished) {
2790 oldStyle->unpolish(q);
2791#if 0 // Used to be included in Qt4 for Q_WS_MAC
2792 if (metalHack)
2793 macUpdateMetalAttribute();
2794#endif
2795 q->style()->polish(q);
2796#if 0 // Used to be included in Qt4 for Q_WS_MAC
2797 } else if (metalHack) {
2798 macUpdateMetalAttribute();
2799#endif
2800 }
2801 }
2802
2803 if (propagate) {
2804 // We copy the list because the order may be modified
2805 const QObjectList childrenList = children;
2806 for (int i = 0; i < childrenList.size(); ++i) {
2807 QWidget *c = qobject_cast<QWidget*>(childrenList.at(i));
2808 if (c)
2809 c->d_func()->inheritStyle();
2810 }
2811 }
2812
2813#ifndef QT_NO_STYLE_STYLESHEET
2814 if (!qobject_cast<QStyleSheetStyle*>(newStyle)) {
2815 if (const QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(origStyle.data())) {
2816 cssStyle->clearWidgetFont(q);
2817 }
2818 }
2819#endif
2820
2821 QEvent e(QEvent::StyleChange);
2822 QApplication::sendEvent(q, &e);
2823
2824#ifndef QT_NO_STYLE_STYLESHEET
2825 // dereference the old stylesheet style
2826 if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(origStyle.data()))
2827 proxy->deref();
2828#endif
2829}
2830
2831// Inherits style from the current parent and propagates it as necessary
2832void QWidgetPrivate::inheritStyle()
2833{
2834#ifndef QT_NO_STYLE_STYLESHEET
2835 Q_Q(QWidget);
2836
2837 QStyleSheetStyle *proxy = extra ? qobject_cast<QStyleSheetStyle *>(extra->style) : 0;
2838
2839 if (!q->styleSheet().isEmpty()) {
2840 Q_ASSERT(proxy);
2841 proxy->repolish(q);
2842 return;
2843 }
2844
2845 QStyle *origStyle = proxy ? proxy->base : (extra ? (QStyle*)extra->style : 0);
2846 QWidget *parent = q->parentWidget();
2847 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : 0;
2848 // If we have stylesheet on app or parent has stylesheet style, we need
2849 // to be running a proxy
2850 if (!qApp->styleSheet().isEmpty() || qobject_cast<QStyleSheetStyle *>(parentStyle)) {
2851 QStyle *newStyle = parentStyle;
2852 if (q->testAttribute(Qt::WA_SetStyle))
2853 newStyle = new QStyleSheetStyle(origStyle);
2854 else if (QStyleSheetStyle *newProxy = qobject_cast<QStyleSheetStyle *>(parentStyle))
2855 newProxy->ref();
2856
2857 setStyle_helper(newStyle, true);
2858 return;
2859 }
2860
2861 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2862 // we just need our original style back
2863 if (origStyle == (extra ? (QStyle*)extra->style : 0)) // is it any different?
2864 return;
2865
2866 // We could have inherited the proxy from our parent (which has a custom style)
2867 // In such a case we need to start following the application style (i.e revert
2868 // the propagation behavior of QStyleSheetStyle)
2869 if (!q->testAttribute(Qt::WA_SetStyle))
2870 origStyle = 0;
2871
2872 setStyle_helper(origStyle, true);
2873#endif // QT_NO_STYLE_STYLESHEET
2874}
2875
2876
2877/*!
2878 \fn bool QWidget::isWindow() const
2879
2880 Returns \c true if the widget is an independent window, otherwise
2881 returns \c false.
2882
2883 A window is a widget that isn't visually the child of any other
2884 widget and that usually has a frame and a
2885 \l{QWidget::setWindowTitle()}{window title}.
2886
2887 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2888 It will then be grouped with its parent and deleted when the
2889 parent is deleted, minimized when the parent is minimized etc. If
2890 supported by the window manager, it will also have a common
2891 taskbar entry with its parent.
2892
2893 QDialog and QMainWindow widgets are by default windows, even if a
2894 parent widget is specified in the constructor. This behavior is
2895 specified by the Qt::Window flag.
2896
2897 \sa window(), isModal(), parentWidget()
2898*/
2899
2900/*!
2901 \property QWidget::modal
2902 \brief whether the widget is a modal widget
2903
2904 This property only makes sense for windows. A modal widget
2905 prevents widgets in all other windows from getting any input.
2906
2907 By default, this property is \c false.
2908
2909 \sa isWindow(), windowModality, QDialog
2910*/
2911
2912/*!
2913 \property QWidget::windowModality
2914 \brief which windows are blocked by the modal widget
2915 \since 4.1
2916
2917 This property only makes sense for windows. A modal widget
2918 prevents widgets in other windows from getting input. The value of
2919 this property controls which windows are blocked when the widget
2920 is visible. Changing this property while the window is visible has
2921 no effect; you must hide() the widget first, then show() it again.
2922
2923 By default, this property is Qt::NonModal.
2924
2925 \sa isWindow(), QWidget::modal, QDialog
2926*/
2927
2928Qt::WindowModality QWidget::windowModality() const
2929{
2930 return static_cast<Qt::WindowModality>(data->window_modality);
2931}
2932
2933void QWidget::setWindowModality(Qt::WindowModality windowModality)
2934{
2935 data->window_modality = windowModality;
2936 // setModal_sys() will be called by setAttribute()
2937 setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
2938 setAttribute(Qt::WA_SetWindowModality, true);
2939}
2940
2941void QWidgetPrivate::setModal_sys()
2942{
2943 Q_Q(QWidget);
2944 if (q->windowHandle())
2945 q->windowHandle()->setModality(q->windowModality());
2946}
2947
2948/*!
2949 \fn bool QWidget::underMouse() const
2950
2951 Returns \c true if the widget is under the mouse cursor; otherwise
2952 returns \c false.
2953
2954 This value is not updated properly during drag and drop
2955 operations.
2956
2957 \sa enterEvent(), leaveEvent()
2958*/
2959
2960/*!
2961 \property QWidget::minimized
2962 \brief whether this widget is minimized (iconified)
2963
2964 This property is only relevant for windows.
2965
2966 By default, this property is \c false.
2967
2968 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2969*/
2970bool QWidget::isMinimized() const
2971{ return data->window_state & Qt::WindowMinimized; }
2972
2973/*!
2974 Shows the widget minimized, as an icon.
2975
2976 Calling this function only affects \l{isWindow()}{windows}.
2977
2978 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2979 isMinimized()
2980*/
2981void QWidget::showMinimized()
2982{
2983 bool isMin = isMinimized();
2984 if (isMin && isVisible())
2985 return;
2986
2987 ensurePolished();
2988
2989 if (!isMin)
2990 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2991 setVisible(true);
2992}
2993
2994/*!
2995 \property QWidget::maximized
2996 \brief whether this widget is maximized
2997
2998 This property is only relevant for windows.
2999
3000 \note Due to limitations on some window systems, this does not always
3001 report the expected results (e.g., if the user on X11 maximizes the
3002 window via the window manager, Qt has no way of distinguishing this
3003 from any other resize). This is expected to improve as window manager
3004 protocols evolve.
3005
3006 By default, this property is \c false.
3007
3008 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
3009*/
3010bool QWidget::isMaximized() const
3011{ return data->window_state & Qt::WindowMaximized; }
3012
3013
3014
3015/*!
3016 Returns the current window state. The window state is a OR'ed
3017 combination of Qt::WindowState: Qt::WindowMinimized,
3018 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
3019
3020 \sa Qt::WindowState, setWindowState()
3021 */
3022Qt::WindowStates QWidget::windowState() const
3023{
3024 return Qt::WindowStates(data->window_state);
3025}
3026
3027/*!\internal
3028
3029 The function sets the window state on child widgets similar to
3030 setWindowState(). The difference is that the window state changed
3031 event has the isOverride() flag set. It exists mainly to keep
3032 QWorkspace working.
3033 */
3034void QWidget::overrideWindowState(Qt::WindowStates newstate)
3035{
3036 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
3037 data->window_state = newstate;
3038 QApplication::sendEvent(this, &e);
3039}
3040
3041/*!
3042 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
3043
3044 Sets the window state to \a windowState. The window state is a OR'ed
3045 combination of Qt::WindowState: Qt::WindowMinimized,
3046 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
3047
3048 If the window is not visible (i.e. isVisible() returns \c false), the
3049 window state will take effect when show() is called. For visible
3050 windows, the change is immediate. For example, to toggle between
3051 full-screen and normal mode, use the following code:
3052
3053 \snippet code/src_gui_kernel_qwidget.cpp 0
3054
3055 In order to restore and activate a minimized window (while
3056 preserving its maximized and/or full-screen state), use the following:
3057
3058 \snippet code/src_gui_kernel_qwidget.cpp 1
3059
3060 Calling this function will hide the widget. You must call show() to make
3061 the widget visible again.
3062
3063 \note On some window systems Qt::WindowActive is not immediate, and may be
3064 ignored in certain cases.
3065
3066 When the window state changes, the widget receives a changeEvent()
3067 of type QEvent::WindowStateChange.
3068
3069 \sa Qt::WindowState, windowState()
3070*/
3071void QWidget::setWindowState(Qt::WindowStates newstate)
3072{
3073 Q_D(QWidget);
3074 Qt::WindowStates oldstate = windowState();
3075 if (oldstate == newstate)
3076 return;
3077 if (isWindow() && !testAttribute(Qt::WA_WState_Created))
3078 create();
3079
3080 data->window_state = newstate;
3081 data->in_set_window_state = 1;
3082 if (isWindow()) {
3083 // Ensure the initial size is valid, since we store it as normalGeometry below.
3084 if (!testAttribute(Qt::WA_Resized) && !isVisible())
3085 adjustSize();
3086
3087 d->createTLExtra();
3088 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
3089 d->topData()->normalGeometry = geometry();
3090
3091 Q_ASSERT(windowHandle());
3092 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
3093 }
3094 data->in_set_window_state = 0;
3095
3096 if (newstate & Qt::WindowActive)
3097 activateWindow();
3098
3099 QWindowStateChangeEvent e(oldstate);
3100 QApplication::sendEvent(this, &e);
3101}
3102
3103/*!
3104 \property QWidget::fullScreen
3105 \brief whether the widget is shown in full screen mode
3106
3107 A widget in full screen mode occupies the whole screen area and does not
3108 display window decorations, such as a title bar.
3109
3110 By default, this property is \c false.
3111
3112 \sa windowState(), minimized, maximized
3113*/
3114bool QWidget::isFullScreen() const
3115{ return data->window_state & Qt::WindowFullScreen; }
3116
3117/*!
3118 Shows the widget in full-screen mode.
3119
3120 Calling this function only affects \l{isWindow()}{windows}.
3121
3122 To return from full-screen mode, call showNormal().
3123
3124 Full-screen mode works fine under Windows, but has certain
3125 problems under X. These problems are due to limitations of the
3126 ICCCM protocol that specifies the communication between X11
3127 clients and the window manager. ICCCM simply does not understand
3128 the concept of non-decorated full-screen windows. Therefore, the
3129 best we can do is to request a borderless window and place and
3130 resize it to fill the entire screen. Depending on the window
3131 manager, this may or may not work. The borderless window is
3132 requested using MOTIF hints, which are at least partially
3133 supported by virtually all modern window managers.
3134
3135 An alternative would be to bypass the window manager entirely and
3136 create a window with the Qt::X11BypassWindowManagerHint flag. This
3137 has other severe problems though, like totally broken keyboard focus
3138 and very strange effects on desktop changes or when the user raises
3139 other windows.
3140
3141 X11 window managers that follow modern post-ICCCM specifications
3142 support full-screen mode properly.
3143
3144 \sa showNormal(), showMaximized(), show(), hide(), isVisible()
3145*/
3146void QWidget::showFullScreen()
3147{
3148#if 0 // Used to be included in Qt4 for Q_WS_MAC
3149 // If the unified toolbar is enabled, we have to disable it before going fullscreen.
3150 QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this);
3151 if (mainWindow && mainWindow->unifiedTitleAndToolBarOnMac()) {
3152 mainWindow->setUnifiedTitleAndToolBarOnMac(false);
3153 QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
3154 mainLayout->activateUnifiedToolbarAfterFullScreen = true;
3155 }
3156#endif
3157 ensurePolished();
3158
3159 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
3160 | Qt::WindowFullScreen);
3161 setVisible(true);
3162#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
3163 // activating it here before libscreen activates it causes problems
3164 activateWindow();
3165#endif
3166}
3167
3168/*!
3169 Shows the widget maximized.
3170
3171 Calling this function only affects \l{isWindow()}{windows}.
3172
3173 On X11, this function may not work properly with certain window
3174 managers. See the \l{Window Geometry} documentation for an explanation.
3175
3176 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3177*/
3178void QWidget::showMaximized()
3179{
3180 ensurePolished();
3181
3182 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3183 | Qt::WindowMaximized);
3184#if 0 // Used to be included in Qt4 for Q_WS_MAC
3185 // If the unified toolbar was enabled before going fullscreen, we have to enable it back.
3186 QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this);
3187 if (mainWindow)
3188 {
3189 QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
3190 if (mainLayout->activateUnifiedToolbarAfterFullScreen) {
3191 mainWindow->setUnifiedTitleAndToolBarOnMac(true);
3192 mainLayout->activateUnifiedToolbarAfterFullScreen = false;
3193 }
3194 }
3195#endif
3196 setVisible(true);
3197}
3198
3199/*!
3200 Restores the widget after it has been maximized or minimized.
3201
3202 Calling this function only affects \l{isWindow()}{windows}.
3203
3204 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3205*/
3206void QWidget::showNormal()
3207{
3208 ensurePolished();
3209
3210 setWindowState(windowState() & ~(Qt::WindowMinimized
3211 | Qt::WindowMaximized
3212 | Qt::WindowFullScreen));
3213#if 0 // Used to be included in Qt4 for Q_WS_MAC
3214 // If the unified toolbar was enabled before going fullscreen, we have to enable it back.
3215 QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this);
3216 if (mainWindow)
3217 {
3218 QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
3219 if (mainLayout->activateUnifiedToolbarAfterFullScreen) {
3220 mainWindow->setUnifiedTitleAndToolBarOnMac(true);
3221 mainLayout->activateUnifiedToolbarAfterFullScreen = false;
3222 }
3223 }
3224#endif
3225 setVisible(true);
3226}
3227
3228/*!
3229 Returns \c true if this widget would become enabled if \a ancestor is
3230 enabled; otherwise returns \c false.
3231
3232
3233
3234 This is the case if neither the widget itself nor every parent up
3235 to but excluding \a ancestor has been explicitly disabled.
3236
3237 isEnabledTo(0) returns false if this widget or any if its ancestors
3238 was explicitly disabled.
3239
3240 The word ancestor here means a parent widget within the same window.
3241
3242 Therefore isEnabledTo(0) stops at this widget's window, unlike
3243 isEnabled() which also takes parent windows into considerations.
3244
3245 \sa setEnabled(), enabled
3246*/
3247
3248bool QWidget::isEnabledTo(const QWidget *ancestor) const
3249{
3250 const QWidget * w = this;
3251 while (!w->testAttribute(Qt::WA_ForceDisabled)
3252 && !w->isWindow()
3253 && w->parentWidget()
3254 && w->parentWidget() != ancestor)
3255 w = w->parentWidget();
3256 return !w->testAttribute(Qt::WA_ForceDisabled);
3257}
3258
3259#ifndef QT_NO_ACTION
3260/*!
3261 Appends the action \a action to this widget's list of actions.
3262
3263 All QWidgets have a list of \l{QAction}s, however they can be
3264 represented graphically in many different ways. The default use of
3265 the QAction list (as returned by actions()) is to create a context
3266 QMenu.
3267
3268 A QWidget should only have one of each action and adding an action
3269 it already has will not cause the same action to be in the widget twice.
3270
3271 The ownership of \a action is not transferred to this QWidget.
3272
3273 \sa removeAction(), insertAction(), actions(), QMenu
3274*/
3275void QWidget::addAction(QAction *action)
3276{
3277 insertAction(0, action);
3278}
3279
3280/*!
3281 Appends the actions \a actions to this widget's list of actions.
3282
3283 \sa removeAction(), QMenu, addAction()
3284*/
3285#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
3286void QWidget::addActions(const QList<QAction *> &actions)
3287#else
3288void QWidget::addActions(QList<QAction*> actions)
3289#endif
3290{
3291 for(int i = 0; i < actions.count(); i++)
3292 insertAction(0, actions.at(i));
3293}
3294
3295/*!
3296 Inserts the action \a action to this widget's list of actions,
3297 before the action \a before. It appends the action if \a before is 0 or
3298 \a before is not a valid action for this widget.
3299
3300 A QWidget should only have one of each action.
3301
3302 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3303*/
3304void QWidget::insertAction(QAction *before, QAction *action)
3305{
3306 if (Q_UNLIKELY(!action)) {
3307 qWarning("QWidget::insertAction: Attempt to insert null action");
3308 return;
3309 }
3310
3311 Q_D(QWidget);
3312 if(d->actions.contains(action))
3313 removeAction(action);
3314
3315 int pos = d->actions.indexOf(before);
3316 if (pos < 0) {
3317 before = 0;
3318 pos = d->actions.size();
3319 }
3320 d->actions.insert(pos, action);
3321
3322 QActionPrivate *apriv = action->d_func();
3323 apriv->widgets.append(this);
3324
3325 QActionEvent e(QEvent::ActionAdded, action, before);
3326 QApplication::sendEvent(this, &e);
3327}
3328
3329/*!
3330 Inserts the actions \a actions to this widget's list of actions,
3331 before the action \a before. It appends the action if \a before is 0 or
3332 \a before is not a valid action for this widget.
3333
3334 A QWidget can have at most one of each action.
3335
3336 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3337*/
3338#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
3339void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3340#else
3341void QWidget::insertActions(QAction *before, QList<QAction*> actions)
3342#endif
3343{
3344 for(int i = 0; i < actions.count(); ++i)
3345 insertAction(before, actions.at(i));
3346}
3347
3348/*!
3349 Removes the action \a action from this widget's list of actions.
3350 \sa insertAction(), actions(), insertAction()
3351*/
3352void QWidget::removeAction(QAction *action)
3353{
3354 if (!action)
3355 return;
3356
3357 Q_D(QWidget);
3358
3359 QActionPrivate *apriv = action->d_func();
3360 apriv->widgets.removeAll(this);
3361
3362 if (d->actions.removeAll(action)) {
3363 QActionEvent e(QEvent::ActionRemoved, action);
3364 QApplication::sendEvent(this, &e);
3365 }
3366}
3367
3368/*!
3369 Returns the (possibly empty) list of this widget's actions.
3370
3371 \sa contextMenuPolicy, insertAction(), removeAction()
3372*/
3373QList<QAction*> QWidget::actions() const
3374{
3375 Q_D(const QWidget);
3376 return d->actions;
3377}
3378#endif // QT_NO_ACTION
3379
3380/*!
3381 \fn bool QWidget::isEnabledToTLW() const
3382 \obsolete
3383
3384 This function is deprecated. It is equivalent to isEnabled()
3385*/
3386
3387/*!
3388 \property QWidget::enabled
3389 \brief whether the widget is enabled
3390
3391 In general an enabled widget handles keyboard and mouse events; a disabled
3392 widget does not. An exception is made with \l{QAbstractButton}.
3393
3394 Some widgets display themselves differently when they are
3395 disabled. For example a button might draw its label grayed out. If
3396 your widget needs to know when it becomes enabled or disabled, you
3397 can use the changeEvent() with type QEvent::EnabledChange.
3398
3399 Disabling a widget implicitly disables all its children. Enabling
3400 respectively enables all child widgets unless they have been
3401 explicitly disabled. It it not possible to explicitly enable a child
3402 widget which is not a window while its parent widget remains disabled.
3403
3404 By default, this property is \c true.
3405
3406 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3407*/
3408void QWidget::setEnabled(bool enable)
3409{
3410 Q_D(QWidget);
3411 setAttribute(Qt::WA_ForceDisabled, !enable);
3412 d->setEnabled_helper(enable);
3413}
3414
3415void QWidgetPrivate::setEnabled_helper(bool enable)
3416{
3417 Q_Q(QWidget);
3418
3419 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3420 return; // nothing we can do
3421
3422 if (enable != q->testAttribute(Qt::WA_Disabled))
3423 return; // nothing to do
3424
3425 q->setAttribute(Qt::WA_Disabled, !enable);
3426 updateSystemBackground();
3427
3428 if (!enable && q->window()->focusWidget() == q) {
3429 bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3430 if (!parentIsEnabled || !q->focusNextChild())
3431 q->clearFocus();
3432 }
3433
3434 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3435 for (int i = 0; i < children.size(); ++i) {
3436 QWidget *w = qobject_cast<QWidget *>(children.at(i));
3437 if (w && !w->testAttribute(attribute))
3438 w->d_func()->setEnabled_helper(enable);
3439 }
3440#if 0 // Used to be included in Qt4 for Q_WS_X11
3441 if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3442 // enforce the windows behavior of clearing the cursor on
3443 // disabled widgets
3444 qt_x11_enforce_cursor(q);
3445 }
3446#endif
3447#ifndef QT_NO_CURSOR
3448 if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3449 // enforce the windows behavior of clearing the cursor on
3450 // disabled widgets
3451 qt_qpa_set_cursor(q, false);
3452 }
3453#endif
3454#if 0 // Used to be included in Qt4 for Q_WS_MAC
3455 setEnabled_helper_sys(enable);
3456#endif
3457#ifndef QT_NO_IM
3458 if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3459 QWidget *focusWidget = effectiveFocusWidget();
3460
3461 if (enable) {
3462 if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
3463 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3464 } else {
3465 QGuiApplication::inputMethod()->commit();
3466 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3467 }
3468 }
3469#endif //QT_NO_IM
3470 QEvent e(QEvent::EnabledChange);
3471 QApplication::sendEvent(q, &e);
3472}
3473
3474/*!
3475 \property QWidget::acceptDrops
3476 \brief whether drop events are enabled for this widget
3477
3478 Setting this property to true announces to the system that this
3479 widget \e may be able to accept drop events.
3480
3481 If the widget is the desktop (windowType() == Qt::Desktop), this may
3482 fail if another application is using the desktop; you can call
3483 acceptDrops() to test if this occurs.
3484
3485 \warning Do not modify this property in a drag and drop event handler.
3486
3487 By default, this property is \c false.
3488
3489 \sa {Drag and Drop}
3490*/
3491bool QWidget::acceptDrops() const
3492{
3493 return testAttribute(Qt::WA_AcceptDrops);
3494}
3495
3496void QWidget::setAcceptDrops(bool on)
3497{
3498 setAttribute(Qt::WA_AcceptDrops, on);
3499
3500}
3501
3502void QWidgetPrivate::registerDropSite(bool on)
3503{
3504 Q_UNUSED(on);
3505}
3506
3507/*!
3508 Disables widget input events if \a disable is true; otherwise
3509 enables input events.
3510
3511 See the \l enabled documentation for more information.
3512
3513 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3514*/
3515void QWidget::setDisabled(bool disable)
3516{
3517 setEnabled(!disable);
3518}
3519
3520/*!
3521 \property QWidget::frameGeometry
3522 \brief geometry of the widget relative to its parent including any
3523 window frame
3524
3525 See the \l{Window Geometry} documentation for an overview of geometry
3526 issues with windows.
3527
3528 By default, this property contains a value that depends on the user's
3529 platform and screen geometry.
3530
3531 \sa geometry(), x(), y(), pos()
3532*/
3533QRect QWidget::frameGeometry() const
3534{
3535 Q_D(const QWidget);
3536 if (isWindow() && ! (windowType() == Qt::Popup)) {
3537 QRect fs = d->frameStrut();
3538 return QRect(data->crect.x() - fs.left(),
3539 data->crect.y() - fs.top(),
3540 data->crect.width() + fs.left() + fs.right(),
3541 data->crect.height() + fs.top() + fs.bottom());
3542 }
3543 return data->crect;
3544}
3545
3546/*!
3547 \property QWidget::x
3548
3549 \brief the x coordinate of the widget relative to its parent including
3550 any window frame
3551
3552 See the \l{Window Geometry} documentation for an overview of geometry
3553 issues with windows.
3554
3555 By default, this property has a value of 0.
3556
3557 \sa frameGeometry, y, pos
3558*/
3559int QWidget::x() const
3560{
3561 Q_D(const QWidget);
3562 if (isWindow() && ! (windowType() == Qt::Popup))
3563 return data->crect.x() - d->frameStrut().left();
3564 return data->crect.x();
3565}
3566
3567/*!
3568 \property QWidget::y
3569 \brief the y coordinate of the widget relative to its parent and
3570 including any window frame
3571
3572 See the \l{Window Geometry} documentation for an overview of geometry
3573 issues with windows.
3574
3575 By default, this property has a value of 0.
3576
3577 \sa frameGeometry, x, pos
3578*/
3579int QWidget::y() const
3580{
3581 Q_D(const QWidget);
3582 if (isWindow() && ! (windowType() == Qt::Popup))
3583 return data->crect.y() - d->frameStrut().top();
3584 return data->crect.y();
3585}
3586
3587/*!
3588 \property QWidget::pos
3589 \brief the position of the widget within its parent widget
3590
3591 If the widget is a window, the position is that of the widget on
3592 the desktop, including its frame.
3593
3594 When changing the position, the widget, if visible, receives a
3595 move event (moveEvent()) immediately. If the widget is not
3596 currently visible, it is guaranteed to receive an event before it
3597 is shown.
3598
3599 By default, this property contains a position that refers to the
3600 origin.
3601
3602 \warning Calling move() or setGeometry() inside moveEvent() can
3603 lead to infinite recursion.
3604
3605 See the \l{Window Geometry} documentation for an overview of geometry
3606 issues with windows.
3607
3608 \sa frameGeometry, size, x(), y()
3609*/
3610QPoint QWidget::pos() const
3611{
3612 Q_D(const QWidget);
3613 QPoint result = data->crect.topLeft();
3614 if (isWindow() && ! (windowType() == Qt::Popup))
3615 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3616 result -= d->frameStrut().topLeft();
3617 return result;
3618}
3619
3620/*!
3621 \property QWidget::geometry
3622 \brief the geometry of the widget relative to its parent and
3623 excluding the window frame
3624
3625 When changing the geometry, the widget, if visible, receives a
3626 move event (moveEvent()) and/or a resize event (resizeEvent())
3627 immediately. If the widget is not currently visible, it is
3628 guaranteed to receive appropriate events before it is shown.
3629
3630 The size component is adjusted if it lies outside the range
3631 defined by minimumSize() and maximumSize().
3632
3633 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3634 can lead to infinite recursion.
3635
3636 See the \l{Window Geometry} documentation for an overview of geometry
3637 issues with windows.
3638
3639 By default, this property contains a value that depends on the user's
3640 platform and screen geometry.
3641
3642 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3643 resizeEvent(), minimumSize(), maximumSize()
3644*/
3645
3646/*!
3647 \property QWidget::normalGeometry
3648
3649 \brief the geometry of the widget as it will appear when shown as
3650 a normal (not maximized or full screen) top-level widget
3651
3652 For child widgets this property always holds an empty rectangle.
3653
3654 By default, this property contains an empty rectangle.
3655
3656 \sa QWidget::windowState(), QWidget::geometry
3657*/
3658
3659/*!
3660 \property QWidget::size
3661 \brief the size of the widget excluding any window frame
3662
3663 If the widget is visible when it is being resized, it receives a resize event
3664 (resizeEvent()) immediately. If the widget is not currently
3665 visible, it is guaranteed to receive an event before it is shown.
3666
3667 The size is adjusted if it lies outside the range defined by
3668 minimumSize() and maximumSize().
3669
3670 By default, this property contains a value that depends on the user's
3671 platform and screen geometry.
3672
3673 \warning Calling resize() or setGeometry() inside resizeEvent() can
3674 lead to infinite recursion.
3675
3676 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3677 appear on screen. This also applies to windows.
3678
3679 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3680*/
3681
3682/*!
3683 \property QWidget::width
3684 \brief the width of the widget excluding any window frame
3685
3686 See the \l{Window Geometry} documentation for an overview of geometry
3687 issues with windows.
3688
3689 \note Do not use this function to find the width of a screen on
3690 a \l{QDesktopWidget}{multiple screen desktop}. Read
3691 \l{QDesktopWidget#Screen Geometry}{this note} for details.
3692
3693 By default, this property contains a value that depends on the user's
3694 platform and screen geometry.
3695
3696 \sa geometry, height, size
3697*/
3698
3699/*!
3700 \property QWidget::height
3701 \brief the height of the widget excluding any window frame
3702
3703 See the \l{Window Geometry} documentation for an overview of geometry
3704 issues with windows.
3705
3706 \note Do not use this function to find the height of a screen
3707 on a \l{QDesktopWidget}{multiple screen desktop}. Read
3708 \l{QDesktopWidget#Screen Geometry}{this note} for details.
3709
3710 By default, this property contains a value that depends on the user's
3711 platform and screen geometry.
3712
3713 \sa geometry, width, size
3714*/
3715
3716/*!
3717 \property QWidget::rect
3718 \brief the internal geometry of the widget excluding any window
3719 frame
3720
3721 The rect property equals QRect(0, 0, width(), height()).
3722
3723 See the \l{Window Geometry} documentation for an overview of geometry
3724 issues with windows.
3725
3726 By default, this property contains a value that depends on the user's
3727 platform and screen geometry.
3728
3729 \sa size
3730*/
3731
3732
3733QRect QWidget::normalGeometry() const
3734{
3735 Q_D(const QWidget);
3736 if (!d->extra || !d->extra->topextra)
3737 return QRect();
3738
3739 if (!isMaximized() && !isFullScreen())
3740 return geometry();
3741
3742 return d->topData()->normalGeometry;
3743}
3744
3745
3746/*!
3747 \property QWidget::childrenRect
3748 \brief the bounding rectangle of the widget's children
3749
3750 Hidden children are excluded.
3751
3752 By default, for a widget with no children, this property contains a
3753 rectangle with zero width and height located at the origin.
3754
3755 \sa childrenRegion(), geometry()
3756*/
3757
3758QRect QWidget::childrenRect() const
3759{
3760 Q_D(const QWidget);
3761 QRect r(0, 0, 0, 0);
3762 for (int i = 0; i < d->children.size(); ++i) {
3763 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3764 if (w && !w->isWindow() && !w->isHidden())
3765 r |= w->geometry();
3766 }
3767 return r;
3768}
3769
3770/*!
3771 \property QWidget::childrenRegion
3772 \brief the combined region occupied by the widget's children
3773
3774 Hidden children are excluded.
3775
3776 By default, for a widget with no children, this property contains an
3777 empty region.
3778
3779 \sa childrenRect(), geometry(), mask()
3780*/
3781
3782QRegion QWidget::childrenRegion() const
3783{
3784 Q_D(const QWidget);
3785 QRegion r;
3786 for (int i = 0; i < d->children.size(); ++i) {
3787 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3788 if (w && !w->isWindow() && !w->isHidden()) {
3789 QRegion mask = w->mask();
3790 if (mask.isEmpty())
3791 r |= w->geometry();
3792 else
3793 r |= mask.translated(w->pos());
3794 }
3795 }
3796 return r;
3797}
3798
3799
3800/*!
3801 \property QWidget::minimumSize
3802 \brief the widget's minimum size
3803
3804 The widget cannot be resized to a smaller size than the minimum
3805 widget size. The widget's size is forced to the minimum size if
3806 the current size is smaller.
3807
3808 The minimum size set by this function will override the minimum size
3809 defined by QLayout. In order to unset the minimum size, use a
3810 value of \c{QSize(0, 0)}.
3811
3812 By default, this property contains a size with zero width and height.
3813
3814 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3815*/
3816
3817QSize QWidget::minimumSize() const
3818{
3819 Q_D(const QWidget);
3820 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3821}
3822
3823/*!
3824 \property QWidget::maximumSize
3825 \brief the widget's maximum size in pixels
3826
3827 The widget cannot be resized to a larger size than the maximum
3828 widget size.
3829
3830 By default, this property contains a size in which both width and height
3831 have values of 16777215.
3832
3833 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3834 of widgets.
3835
3836 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3837*/
3838
3839QSize QWidget::maximumSize() const
3840{
3841 Q_D(const QWidget);
3842 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3843 : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
3844}
3845
3846
3847/*!
3848 \property QWidget::minimumWidth
3849 \brief the widget's minimum width in pixels
3850
3851 This property corresponds to the width held by the \l minimumSize property.
3852
3853 By default, this property has a value of 0.
3854
3855 \sa minimumSize, minimumHeight
3856*/
3857
3858/*!
3859 \property QWidget::minimumHeight
3860 \brief the widget's minimum height in pixels
3861
3862 This property corresponds to the height held by the \l minimumSize property.
3863
3864 By default, this property has a value of 0.
3865
3866 \sa minimumSize, minimumWidth
3867*/
3868
3869/*!
3870 \property QWidget::maximumWidth
3871 \brief the widget's maximum width in pixels
3872
3873 This property corresponds to the width held by the \l maximumSize property.
3874
3875 By default, this property contains a value of 16777215.
3876
3877 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3878 of widgets.
3879
3880 \sa maximumSize, maximumHeight
3881*/
3882
3883/*!
3884 \property QWidget::maximumHeight
3885 \brief the widget's maximum height in pixels
3886
3887 This property corresponds to the height held by the \l maximumSize property.
3888
3889 By default, this property contains a value of 16777215.
3890
3891 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3892 of widgets.
3893
3894 \sa maximumSize, maximumWidth
3895*/
3896
3897/*!
3898 \property QWidget::sizeIncrement
3899 \brief the size increment of the widget
3900
3901 When the user resizes the window, the size will move in steps of
3902 sizeIncrement().width() pixels horizontally and
3903 sizeIncrement.height() pixels vertically, with baseSize() as the
3904 basis. Preferred widget sizes are for non-negative integers \e i
3905 and \e j:
3906 \snippet code/src_gui_kernel_qwidget.cpp 2
3907
3908 Note that while you can set the size increment for all widgets, it
3909 only affects windows.
3910
3911 By default, this property contains a size with zero width and height.
3912
3913 \warning The size increment has no effect under Windows, and may
3914 be disregarded by the window manager on X11.
3915
3916 \sa size, minimumSize, maximumSize
3917*/
3918QSize QWidget::sizeIncrement() const
3919{
3920 Q_D(const QWidget);
3921 return (d->extra && d->extra->topextra)
3922 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3923 : QSize(0, 0);
3924}
3925
3926/*!
3927 \property QWidget::baseSize
3928 \brief the base size of the widget
3929
3930 The base size is used to calculate a proper widget size if the
3931 widget defines sizeIncrement().
3932
3933 By default, for a newly-created widget, this property contains a size with
3934 zero width and height.
3935
3936 \sa setSizeIncrement()
3937*/
3938
3939QSize QWidget::baseSize() const
3940{
3941 Q_D(const QWidget);
3942 return (d->extra != 0 && d->extra->topextra != 0)
3943 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3944 : QSize(0, 0);
3945}
3946
3947bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3948{
3949 Q_Q(QWidget);
3950
3951 int mw = minw, mh = minh;
3952 if (mw == QWIDGETSIZE_MAX)
3953 mw = 0;
3954 if (mh == QWIDGETSIZE_MAX)
3955 mh = 0;
3956 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3957 qWarning("QWidget::setMinimumSize: (%s/%s) "
3958 "The largest allowed size is (%d,%d)",
3959 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3960 QWIDGETSIZE_MAX);
3961 minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX);
3962 minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX);
3963 }
3964 if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3965 qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3966 "are not possible",
3967 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3968 minw = mw = qMax(minw, 0);
3969 minh = mh = qMax(minh, 0);
3970 }
3971 createExtra();
3972 if (extra->minw == mw && extra->minh == mh)
3973 return false;
3974 extra->minw = mw;
3975 extra->minh = mh;
3976 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3977 return true;
3978}
3979
3980void QWidgetPrivate::setConstraints_sys()
3981{
3982 Q_Q(QWidget);
3983 if (extra && q->windowHandle()) {
3984 QWindow *win = q->windowHandle();
3985 QWindowPrivate *winp = qt_window_private(win);
3986
3987 winp->minimumSize = QSize(extra->minw, extra->minh);
3988 winp->maximumSize = QSize(extra->maxw, extra->maxh);
3989
3990 if (extra->topextra) {
3991 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3992 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3993 }
3994
3995 if (winp->platformWindow) {
3996 fixPosIncludesFrame();
3997 winp->platformWindow->propagateSizeHints();
3998 }
3999 }
4000}
4001
4002/*!
4003 \overload
4004
4005 This function corresponds to setMinimumSize(QSize(minw, minh)).
4006 Sets the minimum width to \a minw and the minimum height to \a
4007 minh.
4008*/
4009
4010void QWidget::setMinimumSize(int minw, int minh)
4011{
4012 Q_D(QWidget);
4013 if (!d->setMinimumSize_helper(minw, minh))
4014 return;
4015
4016 if (isWindow())
4017 d->setConstraints_sys();
4018 if (minw > width() || minh > height()) {
4019 bool resized = testAttribute(Qt::WA_Resized);
4020 bool maximized = isMaximized();
4021 resize(qMax(minw,width()), qMax(minh,height()));
4022 setAttribute(Qt::WA_Resized, resized); //not a user resize
4023 if (maximized)
4024 data->window_state = data->window_state | Qt::WindowMaximized;
4025 }
4026#ifndef QT_NO_GRAPHICSVIEW
4027 if (d->extra) {
4028 if (d->extra->proxyWidget)
4029 d->extra->proxyWidget->setMinimumSize(minw, minh);
4030 }
4031#endif
4032 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4033}
4034
4035bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
4036{
4037 Q_Q(QWidget);
4038 if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
4039 qWarning("QWidget::setMaximumSize: (%s/%s) "
4040 "The largest allowed size is (%d,%d)",
4041 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
4042 QWIDGETSIZE_MAX);
4043 maxw = qMin<int>(maxw, QWIDGETSIZE_MAX);
4044 maxh = qMin<int>(maxh, QWIDGETSIZE_MAX);
4045 }
4046 if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
4047 qWarning("QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
4048 "are not possible",
4049 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
4050 maxw = qMax(maxw, 0);
4051 maxh = qMax(maxh, 0);
4052 }
4053 createExtra();
4054 if (extra->maxw == maxw && extra->maxh == maxh)
4055 return false;
4056 extra->maxw = maxw;
4057 extra->maxh = maxh;
4058 extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
4059 (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
4060 return true;
4061}
4062
4063/*!
4064 \overload
4065
4066 This function corresponds to setMaximumSize(QSize(\a maxw, \a
4067 maxh)). Sets the maximum width to \a maxw and the maximum height
4068 to \a maxh.
4069*/
4070void QWidget::setMaximumSize(int maxw, int maxh)
4071{
4072 Q_D(QWidget);
4073 if (!d->setMaximumSize_helper(maxw, maxh))
4074 return;
4075
4076 if (isWindow())
4077 d->setConstraints_sys();
4078 if (maxw < width() || maxh < height()) {
4079 bool resized = testAttribute(Qt::WA_Resized);
4080 resize(qMin(maxw,width()), qMin(maxh,height()));
4081 setAttribute(Qt::WA_Resized, resized); //not a user resize
4082 }
4083
4084#ifndef QT_NO_GRAPHICSVIEW
4085 if (d->extra) {
4086 if (d->extra->proxyWidget)
4087 d->extra->proxyWidget->setMaximumSize(maxw, maxh);
4088 }
4089#endif
4090
4091 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4092}
4093
4094/*!
4095 \overload
4096
4097 Sets the x (width) size increment to \a w and the y (height) size
4098 increment to \a h.
4099*/
4100void QWidget::setSizeIncrement(int w, int h)
4101{
4102 Q_D(QWidget);
4103 d->createTLExtra();
4104 QTLWExtra* x = d->topData();
4105 if (x->incw == w && x->inch == h)
4106 return;
4107 x->incw = w;
4108 x->inch = h;
4109 if (isWindow())
4110 d->setConstraints_sys();
4111}
4112
4113/*!
4114 \overload
4115
4116 This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
4117 the widgets base size to width \a basew and height \a baseh.
4118*/
4119void QWidget::setBaseSize(int basew, int baseh)
4120{
4121 Q_D(QWidget);
4122 d->createTLExtra();
4123 QTLWExtra* x = d->topData();
4124 if (x->basew == basew && x->baseh == baseh)
4125 return;
4126 x->basew = basew;
4127 x->baseh = baseh;
4128 if (isWindow())
4129 d->setConstraints_sys();
4130}
4131
4132/*!
4133 Sets both the minimum and maximum sizes of the widget to \a s,
4134 thereby preventing it from ever growing or shrinking.
4135
4136 This will override the default size constraints set by QLayout.
4137
4138 To remove constraints, set the size to QWIDGETSIZE_MAX.
4139
4140 Alternatively, if you want the widget to have a
4141 fixed size based on its contents, you can call
4142 QLayout::setSizeConstraint(QLayout::SetFixedSize);
4143
4144 \sa maximumSize, minimumSize
4145*/
4146
4147void QWidget::setFixedSize(const QSize & s)
4148{
4149 setFixedSize(s.width(), s.height());
4150}
4151
4152
4153/*!
4154 \fn void QWidget::setFixedSize(int w, int h)
4155 \overload
4156
4157 Sets the width of the widget to \a w and the height to \a h.
4158*/
4159
4160void QWidget::setFixedSize(int w, int h)
4161{
4162 Q_D(QWidget);
4163 bool minSizeSet = d->setMinimumSize_helper(w, h);
4164 bool maxSizeSet = d->setMaximumSize_helper(w, h);
4165 if (!minSizeSet && !maxSizeSet)
4166 return;
4167
4168 if (isWindow())
4169 d->setConstraints_sys();
4170 else
4171 d->updateGeometry_helper(true);
4172
4173 if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
4174 resize(w, h);
4175}
4176
4177void QWidget::setMinimumWidth(int w)
4178{
4179 Q_D(QWidget);
4180 d->createExtra();
4181 uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
4182 setMinimumSize(w, minimumSize().height());
4183 d->extra->explicitMinSize = expl;
4184}
4185
4186void QWidget::setMinimumHeight(int h)
4187{
4188 Q_D(QWidget);
4189 d->createExtra();
4190 uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
4191 setMinimumSize(minimumSize().width(), h);
4192 d->extra->explicitMinSize = expl;
4193}
4194
4195void QWidget::setMaximumWidth(int w)
4196{
4197 Q_D(QWidget);
4198 d->createExtra();
4199 uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
4200 setMaximumSize(w, maximumSize().height());
4201 d->extra->explicitMaxSize = expl;
4202}
4203
4204void QWidget::setMaximumHeight(int h)
4205{
4206 Q_D(QWidget);
4207 d->createExtra();
4208 uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
4209 setMaximumSize(maximumSize().width(), h);
4210 d->extra->explicitMaxSize = expl;
4211}
4212
4213/*!
4214 Sets both the minimum and maximum width of the widget to \a w
4215 without changing the heights. Provided for convenience.
4216
4217 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4218*/
4219
4220void QWidget::setFixedWidth(int w)
4221{
4222 Q_D(QWidget);
4223 d->createExtra();
4224 uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4225 uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4226 setMinimumSize(w, minimumSize().height());
4227 setMaximumSize(w, maximumSize().height());
4228 d->extra->explicitMinSize = explMin;
4229 d->extra->explicitMaxSize = explMax;
4230}
4231
4232
4233/*!
4234 Sets both the minimum and maximum heights of the widget to \a h
4235 without changing the widths. Provided for convenience.
4236
4237 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4238*/
4239
4240void QWidget::setFixedHeight(int h)
4241{
4242 Q_D(QWidget);
4243 d->createExtra();
4244 uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4245 uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4246 setMinimumSize(minimumSize().width(), h);
4247 setMaximumSize(maximumSize().width(), h);
4248 d->extra->explicitMinSize = explMin;
4249 d->extra->explicitMaxSize = explMax;
4250}
4251
4252
4253/*!
4254 Translates the widget coordinate \a pos to the coordinate system
4255 of \a parent. The \a parent must not be 0 and must be a parent
4256 of the calling widget.
4257
4258 \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4259*/
4260
4261QPoint QWidget::mapTo(const QWidget * parent, const QPoint & pos) const
4262{
4263 QPoint p = pos;
4264 if (parent) {
4265 const QWidget * w = this;
4266 while (w != parent) {
4267 Q_ASSERT_X(w, "QWidget::mapTo(const QWidget *parent, const QPoint &pos)",
4268 "parent must be in parent hierarchy");
4269 p = w->mapToParent(p);
4270 w = w->parentWidget();
4271 }
4272 }
4273 return p;
4274}
4275
4276
4277/*!
4278 Translates the widget coordinate \a pos from the coordinate system
4279 of \a parent to this widget's coordinate system. The \a parent
4280 must not be 0 and must be a parent of the calling widget.
4281
4282 \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4283*/
4284
4285QPoint QWidget::mapFrom(const QWidget * parent, const QPoint & pos) const
4286{
4287 QPoint p(pos);
4288 if (parent) {
4289 const QWidget * w = this;
4290 while (w != parent) {
4291 Q_ASSERT_X(w, "QWidget::mapFrom(const QWidget *parent, const QPoint &pos)",
4292 "parent must be in parent hierarchy");
4293
4294 p = w->mapFromParent(p);
4295 w = w->parentWidget();
4296 }
4297 }
4298 return p;
4299}
4300
4301
4302/*!
4303 Translates the widget coordinate \a pos to a coordinate in the
4304 parent widget.
4305
4306 Same as mapToGlobal() if the widget has no parent.
4307
4308 \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4309*/
4310
4311QPoint QWidget::mapToParent(const QPoint &pos) const
4312{
4313 return pos + data->crect.topLeft();
4314}
4315
4316/*!
4317 Translates the parent widget coordinate \a pos to widget
4318 coordinates.
4319
4320 Same as mapFromGlobal() if the widget has no parent.
4321
4322 \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4323*/
4324
4325QPoint QWidget::mapFromParent(const QPoint &pos) const
4326{
4327 return pos - data->crect.topLeft();
4328}
4329
4330
4331/*!
4332 Returns the window for this widget, i.e. the next ancestor widget
4333 that has (or could have) a window-system frame.
4334
4335 If the widget is a window, the widget itself is returned.
4336
4337 Typical usage is changing the window title:
4338
4339 \snippet code/src_gui_kernel_qwidget.cpp 3
4340
4341 \sa isWindow()
4342*/
4343
4344QWidget *QWidget::window() const
4345{
4346 QWidget *w = const_cast<QWidget *>(this);
4347 QWidget *p = w->parentWidget();
4348 while (!w->isWindow() && p) {
4349 w = p;
4350 p = p->parentWidget();
4351 }
4352 return w;
4353}
4354
4355/*!
4356 \since 4.4
4357
4358 Returns the native parent for this widget, i.e. the next ancestor widget
4359 that has a system identifier, or 0 if it does not have any native parent.
4360
4361 \sa effectiveWinId()
4362*/
4363QWidget *QWidget::nativeParentWidget() const
4364{
4365 QWidget *parent = parentWidget();
4366 while (parent && !parent->internalWinId())
4367 parent = parent->parentWidget();
4368 return parent;
4369}
4370
4371/*! \fn QWidget *QWidget::topLevelWidget() const
4372 \obsolete
4373
4374 Use window() instead.
4375*/
4376
4377
4378
4379/*!
4380 Returns the background role of the widget.
4381
4382 The background role defines the brush from the widget's \l palette that
4383 is used to render the background.
4384
4385 If no explicit background role is set, the widget inherts its parent
4386 widget's background role.
4387
4388 \sa setBackgroundRole(), foregroundRole()
4389 */
4390QPalette::ColorRole QWidget::backgroundRole() const
4391{
4392
4393 const QWidget *w = this;
4394 do {
4395 QPalette::ColorRole role = w->d_func()->bg_role;
4396 if (role != QPalette::NoRole)
4397 return role;
4398 if (w->isWindow() || w->windowType() == Qt::SubWindow)
4399 break;
4400 w = w->parentWidget();
4401 } while (w);
4402 return QPalette::Window;
4403}
4404
4405/*!
4406 Sets the background role of the widget to \a role.
4407
4408 The background role defines the brush from the widget's \l palette that
4409 is used to render the background.
4410
4411 If \a role is QPalette::NoRole, then the widget inherits its
4412 parent's background role.
4413
4414 Note that styles are free to choose any color from the palette.
4415 You can modify the palette or set a style sheet if you don't
4416 achieve the result you want with setBackgroundRole().
4417
4418 \sa backgroundRole(), foregroundRole()
4419 */
4420
4421void QWidget::setBackgroundRole(QPalette::ColorRole role)
4422{
4423 Q_D(QWidget);
4424 d->bg_role = role;
4425 d->updateSystemBackground();
4426 d->propagatePaletteChange();
4427 d->updateIsOpaque();
4428}
4429
4430/*!
4431 Returns the foreground role.
4432
4433 The foreground role defines the color from the widget's \l palette that
4434 is used to draw the foreground.
4435
4436 If no explicit foreground role is set, the function returns a role
4437 that contrasts with the background role.
4438
4439 \sa setForegroundRole(), backgroundRole()
4440 */
4441QPalette::ColorRole QWidget::foregroundRole() const
4442{
4443 Q_D(const QWidget);
4444 QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4445 if (rl != QPalette::NoRole)
4446 return rl;
4447 QPalette::ColorRole role = QPalette::WindowText;
4448 switch (backgroundRole()) {
4449 case QPalette::Button:
4450 role = QPalette::ButtonText;
4451 break;
4452 case QPalette::Base:
4453 role = QPalette::Text;
4454 break;
4455 case QPalette::Dark:
4456 case QPalette::Shadow:
4457 role = QPalette::Light;
4458 break;
4459 case QPalette::Highlight:
4460 role = QPalette::HighlightedText;
4461 break;
4462 case QPalette::ToolTipBase:
4463 role = QPalette::ToolTipText;
4464 break;
4465 default:
4466 ;
4467 }
4468 return role;
4469}
4470
4471/*!
4472 Sets the foreground role of the widget to \a role.
4473
4474 The foreground role defines the color from the widget's \l palette that
4475 is used to draw the foreground.
4476
4477 If \a role is QPalette::NoRole, the widget uses a foreground role
4478 that contrasts with the background role.
4479
4480 Note that styles are free to choose any color from the palette.
4481 You can modify the palette or set a style sheet if you don't
4482 achieve the result you want with setForegroundRole().
4483
4484 \sa foregroundRole(), backgroundRole()
4485 */
4486void QWidget::setForegroundRole(QPalette::ColorRole role)
4487{
4488 Q_D(QWidget);
4489 d->fg_role = role;
4490 d->updateSystemBackground();
4491 d->propagatePaletteChange();
4492}
4493
4494/*!
4495 \property QWidget::palette
4496 \brief the widget's palette
4497
4498 This property describes the widget's palette. The palette is used by the
4499 widget's style when rendering standard components, and is available as a
4500 means to ensure that custom widgets can maintain consistency with the
4501 native platform's look and feel. It's common that different platforms, or
4502 different styles, have different palettes.
4503
4504 When you assign a new palette to a widget, the color roles from this
4505 palette are combined with the widget's default palette to form the
4506 widget's final palette. The palette entry for the widget's background role
4507 is used to fill the widget's background (see QWidget::autoFillBackground),
4508 and the foreground role initializes QPainter's pen.
4509
4510 The default depends on the system environment. QApplication maintains a
4511 system/theme palette which serves as a default for all widgets. There may
4512 also be special palette defaults for certain types of widgets (e.g., on
4513 Windows Vista, all classes that derive from QMenuBar have a special
4514 default palette). You can also define default palettes for widgets
4515 yourself by passing a custom palette and the name of a widget to
4516 QApplication::setPalette(). Finally, the style always has the option of
4517 polishing the palette as it's assigned (see QStyle::polish()).
4518
4519 QWidget propagates explicit palette roles from parent to child. If you
4520 assign a brush or color to a specific role on a palette and assign that
4521 palette to a widget, that role will propagate to all the widget's
4522 children, overriding any system defaults for that role. Note that palettes
4523 by default don't propagate to windows (see isWindow()) unless the
4524 Qt::WA_WindowPropagation attribute is enabled.
4525
4526 QWidget's palette propagation is similar to its font propagation.
4527
4528 The current style, which is used to render the content of all standard Qt
4529 widgets, is free to choose colors and brushes from the widget palette, or
4530 in some cases, to ignore the palette (partially, or completely). In
4531 particular, certain styles like GTK style, Mac style, and Windows Vista
4532 style, depend on third party APIs to render the content of widgets,
4533 and these styles typically do not follow the palette. Because of this,
4534 assigning roles to a widget's palette is not guaranteed to change the
4535 appearance of the widget. Instead, you may choose to apply a \l
4536 styleSheet. You can refer to our Knowledge Base article
4537 \l{http://qt.nokia.com/developer/knowledgebase/22}{here} for more
4538 information.
4539
4540 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4541 When using style sheets, the palette of a widget can be customized using
4542 the "color", "background-color", "selection-color",
4543 "selection-background-color" and "alternate-background-color".
4544
4545 \sa QApplication::palette(), QWidget::font()
4546*/
4547const QPalette &QWidget::palette() const
4548{
4549 if (!isEnabled()) {
4550 data->pal.setCurrentColorGroup(QPalette::Disabled);
4551 } else if ((!isVisible() || isActiveWindow())
4552#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
4553 && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4554#endif
4555 ) {
4556 data->pal.setCurrentColorGroup(QPalette::Active);
4557 } else {
4558#if 0 // Used to be included in Qt4 for Q_WS_MAC
4559 extern bool qt_mac_can_clickThrough(const QWidget *); //qwidget_mac.cpp
4560 if (qt_mac_can_clickThrough(this))
4561 data->pal.setCurrentColorGroup(QPalette::Active);
4562 else
4563#endif
4564 data->pal.setCurrentColorGroup(QPalette::Inactive);
4565 }
4566 return data->pal;
4567}
4568
4569void QWidget::setPalette(const QPalette &palette)
4570{
4571 Q_D(QWidget);
4572 setAttribute(Qt::WA_SetPalette, palette.resolve() != 0);
4573
4574 // Determine which palette is inherited from this widget's ancestors and
4575 // QApplication::palette, resolve this against \a palette (attributes from
4576 // the inherited palette are copied over this widget's palette). Then
4577 // propagate this palette to this widget's children.
4578 QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
4579 QPalette resolvedPalette = palette.resolve(naturalPalette);
4580 d->setPalette_helper(resolvedPalette);
4581}
4582
4583/*!
4584 \internal
4585
4586 Returns the palette that the widget \a w inherits from its ancestors and
4587 QApplication::palette. \a inheritedMask is the combination of the widget's
4588 ancestors palette request masks (i.e., which attributes from the parent
4589 widget's palette are implicitly imposed on this widget by the user). Note
4590 that this font does not take into account the palette set on \a w itself.
4591*/
4592QPalette QWidgetPrivate::naturalWidgetPalette(uint inheritedMask) const
4593{
4594 Q_Q(const QWidget);
4595
4596 const bool useStyleSheetPropagationInWidgetStyles =
4597 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4598
4599 QPalette naturalPalette = QApplication::palette(q);
4600 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4601 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4602#ifndef QT_NO_GRAPHICSVIEW
4603 || (extra && extra->proxyWidget)
4604#endif //QT_NO_GRAPHICSVIEW
4605 )) {
4606 if (QWidget *p = q->parentWidget()) {
4607 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4608 if (!naturalPalette.isCopyOf(QApplication::palette())) {
4609 QPalette inheritedPalette = p->palette();
4610 inheritedPalette.resolve(inheritedMask);
4611 naturalPalette = inheritedPalette.resolve(naturalPalette);
4612 } else {
4613 naturalPalette = p->palette();
4614 }
4615 }
4616 }
4617#ifndef QT_NO_GRAPHICSVIEW
4618 else if (extra && extra->proxyWidget) {
4619 QPalette inheritedPalette = extra->proxyWidget->palette();
4620 inheritedPalette.resolve(inheritedMask);
4621 naturalPalette = inheritedPalette.resolve(naturalPalette);
4622 }
4623#endif //QT_NO_GRAPHICSVIEW
4624 }
4625 naturalPalette.resolve(0);
4626 return naturalPalette;
4627}
4628/*!
4629 \internal
4630
4631 Determine which palette is inherited from this widget's ancestors and
4632 QApplication::palette, resolve this against this widget's palette
4633 (attributes from the inherited palette are copied over this widget's
4634 palette). Then propagate this palette to this widget's children.
4635*/
4636void QWidgetPrivate::resolvePalette()
4637{
4638 QPalette naturalPalette = naturalWidgetPalette(inheritedPaletteResolveMask);
4639 QPalette resolvedPalette = data.pal.resolve(naturalPalette);
4640 setPalette_helper(resolvedPalette);
4641}
4642
4643void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4644{
4645 Q_Q(QWidget);
4646 if (data.pal == palette && data.pal.resolve() == palette.resolve())
4647 return;
4648 data.pal = palette;
4649 updateSystemBackground();
4650 propagatePaletteChange();
4651 updateIsOpaque();
4652 q->update();
4653 updateIsOpaque();
4654}
4655
4656void QWidgetPrivate::updateSystemBackground()
4657{
4658}
4659
4660/*!
4661 \property QWidget::font
4662 \brief the font currently set for the widget
4663
4664 This property describes the widget's requested font. The font is used by
4665 the widget's style when rendering standard components, and is available as
4666 a means to ensure that custom widgets can maintain consistency with the
4667 native platform's look and feel. It's common that different platforms, or
4668 different styles, define different fonts for an application.
4669
4670 When you assign a new font to a widget, the properties from this font are
4671 combined with the widget's default font to form the widget's final
4672 font. You can call fontInfo() to get a copy of the widget's final
4673 font. The final font is also used to initialize QPainter's font.
4674
4675 The default depends on the system environment. QApplication maintains a
4676 system/theme font which serves as a default for all widgets. There may
4677 also be special font defaults for certain types of widgets. You can also
4678 define default fonts for widgets yourself by passing a custom font and the
4679 name of a widget to QApplication::setFont(). Finally, the font is matched
4680 against Qt's font database to find the best match.
4681
4682 QWidget propagates explicit font properties from parent to child. If you
4683 change a specific property on a font and assign that font to a widget,
4684 that property will propagate to all the widget's children, overriding any
4685 system defaults for that property. Note that fonts by default don't
4686 propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4687 attribute is enabled.
4688
4689 QWidget's font propagation is similar to its palette propagation.
4690
4691 The current style, which is used to render the content of all standard Qt
4692 widgets, is free to choose to use the widget font, or in some cases, to
4693 ignore it (partially, or completely). In particular, certain styles like
4694 GTK style, Mac style, and Windows Vista style, apply special
4695 modifications to the widget font to match the platform's native look and
4696 feel. Because of this, assigning properties to a widget's font is not
4697 guaranteed to change the appearance of the widget. Instead, you may choose
4698 to apply a \l styleSheet.
4699
4700 \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4701 style sheets will take precedence if the settings conflict.
4702
4703 \sa fontInfo(), fontMetrics()
4704*/
4705
4706void QWidget::setFont(const QFont &font)
4707{
4708 Q_D(QWidget);
4709
4710#ifndef QT_NO_STYLE_STYLESHEET
4711 const QStyleSheetStyle* style;
4712 if (d->extra && (style = qobject_cast<const QStyleSheetStyle*>(d->extra->style))) {
4713 style->saveWidgetFont(this, font);
4714 }
4715#endif
4716
4717 setAttribute(Qt::WA_SetFont, font.resolve() != 0);
4718
4719 // Determine which font is inherited from this widget's ancestors and
4720 // QApplication::font, resolve this against \a font (attributes from the
4721 // inherited font are copied over). Then propagate this font to this
4722 // widget's children.
4723 QFont naturalFont = d->naturalWidgetFont(d->inheritedFontResolveMask);
4724 QFont resolvedFont = font.resolve(naturalFont);
4725 d->setFont_helper(resolvedFont);
4726}
4727
4728/*
4729 \internal
4730
4731 Returns the font that the widget \a w inherits from its ancestors and
4732 QApplication::font. \a inheritedMask is the combination of the widget's
4733 ancestors font request masks (i.e., which attributes from the parent
4734 widget's font are implicitly imposed on this widget by the user). Note
4735 that this font does not take into account the font set on \a w itself.
4736
4737 ### Stylesheet has a different font propagation mechanism. When a stylesheet
4738 is applied, fonts are not propagated anymore
4739*/
4740QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4741{
4742 Q_Q(const QWidget);
4743
4744 const bool useStyleSheetPropagationInWidgetStyles =
4745 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4746
4747 QFont naturalFont = QApplication::font(q);
4748 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4749 && (!q->isWindow() || q->testAttribute(Qt::