1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 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 #if QT_CONFIG(menu)
49 #include "qmenu.h"
50 #endif
51 #include "qmetaobject.h"
52 #include "qpixmap.h"
53 #include "qpointer.h"
54 #include "qstack.h"
55 #include "qstyle.h"
56 #include "qstylefactory.h"
57 #include "qvariant.h"
58 #include "qwidget.h"
59 #include "qstyleoption.h"
60 #include "qstylehints.h"
61 #ifndef QT_NO_ACCESSIBILITY
62 # include "qaccessible.h"
63 #endif
64 #include <qpa/qplatformwindow.h>
65 #include "private/qwidgetwindow_p.h"
66 #include "qpainter.h"
67 #include "qtooltip.h"
68 #if QT_CONFIG(whatsthis)
69 #include "qwhatsthis.h"
70 #endif
71 #include "qdebug.h"
72 #include "private/qstylesheetstyle_p.h"
73 #include "private/qstyle_p.h"
74 #include "qfileinfo.h"
75 #include "qscopeguard.h"
76 #include <QtGui/private/qhighdpiscaling_p.h>
77 #include <QtGui/qinputmethod.h>
78 #include <QtGui/qopenglcontext.h>
79 #include <QtGui/private/qopenglcontext_p.h>
80 #include <QtGui/qoffscreensurface.h>
81 
82 #if QT_CONFIG(graphicseffect)
83 #include <private/qgraphicseffect_p.h>
84 #endif
85 #include <qbackingstore.h>
86 #include <private/qwidgetrepaintmanager_p.h>
87 #include <private/qpaintengine_raster_p.h>
88 
89 #include "qwidget_p.h"
90 #include <QtGui/private/qwindow_p.h>
91 #include "qaction_p.h"
92 #include "qlayout_p.h"
93 #if QT_CONFIG(graphicsview)
94 #include "QtWidgets/qgraphicsproxywidget.h"
95 #include "QtWidgets/qgraphicsscene.h"
96 #include "private/qgraphicsproxywidget_p.h"
97 #endif
98 #include "QtWidgets/qabstractscrollarea.h"
99 #include "private/qabstractscrollarea_p.h"
100 #include "private/qevent_p.h"
101 
102 #include "private/qgesturemanager_p.h"
103 
104 #ifdef QT_KEYPAD_NAVIGATION
105 #if QT_CONFIG(tabwidget)
106 #include "qtabwidget.h" // Needed in inTabWidget()
107 #endif
108 #endif // QT_KEYPAD_NAVIGATION
109 
110 #include "qwindowcontainer_p.h"
111 
112 #include <QtPlatformHeaders/qxcbwindowfunctions.h>
113 
114 #include <private/qmemory_p.h>
115 
116 // widget/widget data creation count
117 //#define QWIDGET_EXTRA_DEBUG
118 //#define ALIEN_DEBUG
119 
120 QT_BEGIN_NAMESPACE
121 
122 Q_LOGGING_CATEGORY(lcWidgetPainting, "qt.widgets.painting", QtWarningMsg);
123 
qRectIntersects(const QRect & r1,const QRect & r2)124 static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
125 {
126     return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) &&
127             qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));
128 }
129 
130 extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
131 extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp
132 
QWidgetPrivate(int version)133 QWidgetPrivate::QWidgetPrivate(int version)
134     : QObjectPrivate(version)
135       , focus_next(nullptr)
136       , focus_prev(nullptr)
137       , focus_child(nullptr)
138       , layout(nullptr)
139       , needsFlush(nullptr)
140       , redirectDev(nullptr)
141       , widgetItem(nullptr)
142       , extraPaintEngine(nullptr)
143       , polished(nullptr)
144       , graphicsEffect(nullptr)
145 #if !defined(QT_NO_IM)
146       , imHints(Qt::ImhNone)
147 #endif
148 #ifndef QT_NO_TOOLTIP
149       , toolTipDuration(-1)
150 #endif
151       , directFontResolveMask(0)
152       , inheritedFontResolveMask(0)
153       , directPaletteResolveMask(0)
154       , inheritedPaletteResolveMask(0)
155       , leftmargin(0)
156       , topmargin(0)
157       , rightmargin(0)
158       , bottommargin(0)
159       , leftLayoutItemMargin(0)
160       , topLayoutItemMargin(0)
161       , rightLayoutItemMargin(0)
162       , bottomLayoutItemMargin(0)
163       , hd(nullptr)
164       , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
165       , fg_role(QPalette::NoRole)
166       , bg_role(QPalette::NoRole)
167       , dirtyOpaqueChildren(1)
168       , isOpaque(0)
169       , retainSizeWhenHiddenChanged(0)
170       , inDirtyList(0)
171       , isScrolled(0)
172       , isMoved(0)
173       , usesDoubleBufferedGLContext(0)
174       , mustHaveWindowHandle(0)
175       , renderToTexture(0)
176       , textureChildSeen(0)
177 #ifndef QT_NO_IM
178       , inheritsInputMethodHints(0)
179 #endif
180 #ifndef QT_NO_OPENGL
181       , renderToTextureReallyDirty(1)
182       , renderToTextureComposeActive(0)
183 #endif
184       , childrenHiddenByWState(0)
185       , childrenShownByExpose(0)
186 #if defined(Q_OS_WIN)
187       , noPaintOnScreen(0)
188 #endif
189 {
190     if (Q_UNLIKELY(!qApp)) {
191         qFatal("QWidget: Must construct a QApplication before a QWidget");
192         return;
193     }
194 
195     checkForIncompatibleLibraryVersion(version);
196 
197     isWidget = true;
198     memset(high_attributes, 0, sizeof(high_attributes));
199 
200 #ifdef QWIDGET_EXTRA_DEBUG
201     static int count = 0;
202     qDebug() << "widgets" << ++count;
203 #endif
204 }
205 
206 
~QWidgetPrivate()207 QWidgetPrivate::~QWidgetPrivate()
208 {
209     if (widgetItem)
210         widgetItem->wid = nullptr;
211 
212     if (extra)
213         deleteExtra();
214 }
215 
216 /*!
217     \internal
218 */
scrollChildren(int dx,int dy)219 void QWidgetPrivate::scrollChildren(int dx, int dy)
220 {
221     Q_Q(QWidget);
222     if (q->children().size() > 0) {        // scroll children
223         QPoint pd(dx, dy);
224         QObjectList childObjects = q->children();
225         for (int i = 0; i < childObjects.size(); ++i) { // move all children
226             QWidget *w = qobject_cast<QWidget*>(childObjects.at(i));
227             if (w && !w->isWindow()) {
228                 QPoint oldp = w->pos();
229                 QRect  r(w->pos() + pd, w->size());
230                 w->data->crect = r;
231                 if (w->testAttribute(Qt::WA_WState_Created))
232                     w->d_func()->setWSGeometry();
233                 w->d_func()->setDirtyOpaqueRegion();
234                 QMoveEvent e(r.topLeft(), oldp);
235                 QCoreApplication::sendEvent(w, &e);
236             }
237         }
238     }
239 }
240 
setWSGeometry()241 void QWidgetPrivate::setWSGeometry()
242 {
243     Q_Q(QWidget);
244     if (QWindow *window = q->windowHandle())
245         window->setGeometry(data.crect);
246 }
247 
updateWidgetTransform(QEvent * event)248 void QWidgetPrivate::updateWidgetTransform(QEvent *event)
249 {
250     Q_Q(QWidget);
251     if (q == QGuiApplication::focusObject() || event->type() == QEvent::FocusIn) {
252         QTransform t;
253         QPoint p = q->mapTo(q->topLevelWidget(), QPoint(0,0));
254         t.translate(p.x(), p.y());
255         QGuiApplication::inputMethod()->setInputItemTransform(t);
256         QGuiApplication::inputMethod()->setInputItemRectangle(q->rect());
257         QGuiApplication::inputMethod()->update(Qt::ImInputItemClipRectangle);
258     }
259 }
260 
261 #ifdef QT_KEYPAD_NAVIGATION
262 QPointer<QWidget> QWidgetPrivate::editingWidget;
263 
264 /*!
265     Returns \c true if this widget currently has edit focus; otherwise false.
266 
267     This feature is only available in Qt for Embedded Linux.
268 
269     \sa setEditFocus(), QApplication::navigationMode()
270 */
hasEditFocus() const271 bool QWidget::hasEditFocus() const
272 {
273     const QWidget* w = this;
274     while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
275         w = w->d_func()->extra->focus_proxy;
276     return QWidgetPrivate::editingWidget == w;
277 }
278 
279 /*!
280     \fn void QWidget::setEditFocus(bool enable)
281 
282     If \a enable is true, make this widget have edit focus, in which
283     case Qt::Key_Up and Qt::Key_Down will be delivered to the widget
284     normally; otherwise, Qt::Key_Up and Qt::Key_Down are used to
285     change focus.
286 
287     This feature is only available in Qt for Embedded Linux.
288 
289     \sa hasEditFocus(), QApplication::navigationMode()
290 */
setEditFocus(bool on)291 void QWidget::setEditFocus(bool on)
292 {
293     QWidget *f = this;
294     while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
295         f = f->d_func()->extra->focus_proxy;
296 
297     if (QWidgetPrivate::editingWidget && QWidgetPrivate::editingWidget != f)
298         QWidgetPrivate::editingWidget->setEditFocus(false);
299 
300     if (on && !f->hasFocus())
301         f->setFocus();
302 
303     if ((!on && !QWidgetPrivate::editingWidget)
304         || (on && QWidgetPrivate::editingWidget == f)) {
305         return;
306     }
307 
308     if (!on && QWidgetPrivate::editingWidget == f) {
309         QWidgetPrivate::editingWidget = 0;
310         QEvent event(QEvent::LeaveEditFocus);
311         QCoreApplication::sendEvent(f, &event);
312         QCoreApplication::sendEvent(f->style(), &event);
313     } else if (on) {
314         QWidgetPrivate::editingWidget = f;
315         QEvent event(QEvent::EnterEditFocus);
316         QCoreApplication::sendEvent(f, &event);
317         QCoreApplication::sendEvent(f->style(), &event);
318     }
319 }
320 #endif
321 
322 /*!
323     \property QWidget::autoFillBackground
324     \brief whether the widget background is filled automatically
325     \since 4.1
326 
327     If enabled, this property will cause Qt to fill the background of the
328     widget before invoking the paint event. The color used is defined by the
329     QPalette::Window color role from the widget's \l{QPalette}{palette}.
330 
331     In addition, Windows are always filled with QPalette::Window, unless the
332     WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
333 
334     This property cannot be turned off (i.e., set to false) if a widget's
335     parent has a static gradient for its background.
336 
337     \warning Use this property with caution in conjunction with
338     \l{Qt Style Sheets}. When a widget has a style sheet with a valid
339     background or a border-image, this property is automatically disabled.
340 
341     By default, this property is \c false.
342 
343     \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
344     {QWidget#Transparency and Double Buffering}{Transparency and Double Buffering}
345 */
autoFillBackground() const346 bool QWidget::autoFillBackground() const
347 {
348     Q_D(const QWidget);
349     return d->extra && d->extra->autoFillBackground;
350 }
351 
setAutoFillBackground(bool enabled)352 void QWidget::setAutoFillBackground(bool enabled)
353 {
354     Q_D(QWidget);
355     if (!d->extra)
356         d->createExtra();
357     if (d->extra->autoFillBackground == enabled)
358         return;
359 
360     d->extra->autoFillBackground = enabled;
361     d->updateIsOpaque();
362     update();
363     d->updateIsOpaque();
364 }
365 
366 /*!
367     \class QWidget
368     \brief The QWidget class is the base class of all user interface objects.
369 
370     \ingroup basicwidgets
371     \inmodule QtWidgets
372 
373     The widget is the atom of the user interface: it receives mouse, keyboard
374     and other events from the window system, and paints a representation of
375     itself on the screen. Every widget is rectangular, and they are sorted in a
376     Z-order. A widget is clipped by its parent and by the widgets in front of
377     it.
378 
379     A widget that is not embedded in a parent widget is called a window.
380     Usually, windows have a frame and a title bar, although it is also possible
381     to create windows without such decoration using suitable
382     \l{Qt::WindowFlags}{window flags}). In Qt, QMainWindow and the various
383     subclasses of QDialog are the most common window types.
384 
385     Every widget's constructor accepts one or two standard arguments:
386 
387     \list 1
388         \li  \c{QWidget *parent = nullptr} is the parent of the new widget.
389             If it is \nullptr (the default), the new widget will be a window.
390             If not, it will be a child of \e parent, and be constrained by
391             \e parent's geometry (unless you specify Qt::Window as window flag).
392         \li  \c{Qt::WindowFlags f = { }} (where available) sets the window flags;
393             the default is suitable for almost all widgets, but to get, for
394             example, a window without a window system frame, you must use
395             special flags.
396     \endlist
397 
398     QWidget has many member functions, but some of them have little direct
399     functionality; for example, QWidget has a font property, but never uses
400     this itself. There are many subclasses which provide real functionality,
401     such as QLabel, QPushButton, QListWidget, and QTabWidget.
402 
403 
404     \section1 Top-Level and Child Widgets
405 
406     A widget without a parent widget is always an independent window (top-level
407     widget). For these widgets, setWindowTitle() and setWindowIcon() set the
408     title bar and icon respectively.
409 
410     Non-window widgets are child widgets, displayed within their parent
411     widgets. Most widgets in Qt are mainly useful as child widgets. For
412     example, it is possible to display a button as a top-level window, but most
413     people prefer to put their buttons inside other widgets, such as QDialog.
414 
415     \image parent-child-widgets.png A parent widget containing various child widgets.
416 
417     The diagram above shows a QGroupBox widget being used to hold various child
418     widgets in a layout provided by QGridLayout. The QLabel child widgets have
419     been outlined to indicate their full sizes.
420 
421     If you want to use a QWidget to hold child widgets you will usually want to
422     add a layout to the parent QWidget. See \l{Layout Management} for more
423     information.
424 
425 
426     \section1 Composite Widgets
427 
428     When a widget is used as a container to group a number of child widgets, it
429     is known as a composite widget. These can be created by constructing a
430     widget with the required visual properties - a QFrame, for example - and
431     adding child widgets to it, usually managed by a layout. The above diagram
432     shows such a composite widget that was created using Qt Designer.
433 
434     Composite widgets can also be created by subclassing a standard widget,
435     such as QWidget or QFrame, and adding the necessary layout and child
436     widgets in the constructor of the subclass. Many of the \l{Qt Widgets Examples}
437     {examples provided with Qt} use this approach, and it is also covered in
438     the Qt \l{Tutorials}.
439 
440 
441     \section1 Custom Widgets and Painting
442 
443     Since QWidget is a subclass of QPaintDevice, subclasses can be used to
444     display custom content that is composed using a series of painting
445     operations with an instance of the QPainter class. This approach contrasts
446     with the canvas-style approach used by the \l{Graphics View}
447     {Graphics View Framework} where items are added to a scene by the
448     application and are rendered by the framework itself.
449 
450     Each widget performs all painting operations from within its paintEvent()
451     function. This is called whenever the widget needs to be redrawn, either
452     as a result of some external change or when requested by the application.
453 
454     The \l{widgets/analogclock}{Analog Clock example} shows how a simple widget
455     can handle paint events.
456 
457 
458     \section1 Size Hints and Size Policies
459 
460     When implementing a new widget, it is almost always useful to reimplement
461     sizeHint() to provide a reasonable default size for the widget and to set
462     the correct size policy with setSizePolicy().
463 
464     By default, composite widgets which do not provide a size hint will be
465     sized according to the space requirements of their child widgets.
466 
467     The size policy lets you supply good default behavior for the layout
468     management system, so that other widgets can contain and manage yours
469     easily. The default size policy indicates that the size hint represents
470     the preferred size of the widget, and this is often good enough for many
471     widgets.
472 
473     \note The size of top-level widgets are constrained to 2/3 of the desktop's
474     height and width. You can resize() the widget manually if these bounds are
475     inadequate.
476 
477 
478     \section1 Events
479 
480     Widgets respond to events that are typically caused by user actions. Qt
481     delivers events to widgets by calling specific event handler functions with
482     instances of QEvent subclasses containing information about each event.
483 
484     If your widget only contains child widgets, you probably do not need to
485     implement any event handlers. If you want to detect a mouse click in a
486     child widget call the child's underMouse() function inside the widget's
487     mousePressEvent().
488 
489     The \l{widgets/scribble}{Scribble example} implements a wider set of
490     events to handle mouse movement, button presses, and window resizing.
491 
492     You will need to supply the behavior and content for your own widgets, but
493     here is a brief overview of the events that are relevant to QWidget,
494     starting with the most common ones:
495 
496     \list
497         \li  paintEvent() is called whenever the widget needs to be repainted.
498             Every widget displaying custom content must implement it. Painting
499             using a QPainter can only take place in a paintEvent() or a
500             function called by a paintEvent().
501         \li  resizeEvent() is called when the widget has been resized.
502         \li  mousePressEvent() is called when a mouse button is pressed while
503             the mouse cursor is inside the widget, or when the widget has
504             grabbed the mouse using grabMouse(). Pressing the mouse without
505             releasing it is effectively the same as calling grabMouse().
506         \li  mouseReleaseEvent() is called when a mouse button is released. A
507             widget receives mouse release events when it has received the
508             corresponding mouse press event. This means that if the user
509             presses the mouse inside \e your widget, then drags the mouse
510             somewhere else before releasing the mouse button, \e your widget
511             receives the release event. There is one exception: if a popup menu
512             appears while the mouse button is held down, this popup immediately
513             steals the mouse events.
514         \li  mouseDoubleClickEvent() is called when the user double-clicks in
515             the widget. If the user double-clicks, the widget receives a mouse
516             press event, a mouse release event, (a mouse click event,) a second
517             mouse press, this event and finally a second mouse release event.
518             (Some mouse move events may also be
519             received if the mouse is not held steady during this operation.) It
520             is \e{not possible} to distinguish a click from a double-click
521             until the second click arrives. (This is one reason why most GUI
522             books recommend that double-clicks be an extension of
523             single-clicks, rather than trigger a different action.)
524     \endlist
525 
526     Widgets that accept keyboard input need to reimplement a few more event
527     handlers:
528 
529     \list
530         \li  keyPressEvent() is called whenever a key is pressed, and again when
531             a key has been held down long enough for it to auto-repeat. The
532             \uicontrol Tab and \uicontrol Shift+Tab keys are only passed to the widget if
533             they are not used by the focus-change mechanisms. To force those
534             keys to be processed by your widget, you must reimplement
535             QWidget::event().
536         \li  focusInEvent() is called when the widget gains keyboard focus
537             (assuming you have called setFocusPolicy()). Well-behaved widgets
538             indicate that they own the keyboard focus in a clear but discreet
539             way.
540         \li  focusOutEvent() is called when the widget loses keyboard focus.
541     \endlist
542 
543     You may be required to also reimplement some of the less common event
544     handlers:
545 
546     \list
547         \li  mouseMoveEvent() is called whenever the mouse moves while a mouse
548             button is held down. This can be useful during drag and drop
549             operations. If you call \l{setMouseTracking()}{setMouseTracking}(true),
550             you get mouse move events even when no buttons are held down.
551             (See also the \l{Drag and Drop} guide.)
552         \li  keyReleaseEvent() is called whenever a key is released and while it
553             is held down (if the key is auto-repeating). In that case, the
554             widget will receive a pair of key release and key press event for
555             every repeat. The \uicontrol Tab and \uicontrol Shift+Tab keys are only passed
556             to the widget if they are not used by the focus-change mechanisms.
557             To force those keys to be processed by your widget, you must
558             reimplement QWidget::event().
559         \li  wheelEvent() is called whenever the user turns the mouse wheel
560             while the widget has the focus.
561         \li  enterEvent() is called when the mouse enters the widget's screen
562             space. (This excludes screen space owned by any of the widget's
563             children.)
564         \li  leaveEvent() is called when the mouse leaves the widget's screen
565             space. If the mouse enters a child widget it will not cause a
566             leaveEvent().
567         \li  moveEvent() is called when the widget has been moved relative to
568             its parent.
569         \li  closeEvent() is called when the user closes the widget (or when
570             close() is called).
571     \endlist
572 
573     There are also some rather obscure events described in the documentation
574     for QEvent::Type. To handle these events, you need to reimplement event()
575     directly.
576 
577     The default implementation of event() handles \uicontrol Tab and \uicontrol Shift+Tab
578     (to move the keyboard focus), and passes on most of the other events to
579     one of the more specialized handlers above.
580 
581     Events and the mechanism used to deliver them are covered in
582     \l{The Event System}.
583 
584     \section1 Groups of Functions and Properties
585 
586     \table
587     \header \li Context \li Functions and Properties
588 
589     \row \li Window functions \li
590         show(),
591         hide(),
592         raise(),
593         lower(),
594         close().
595 
596     \row \li Top-level windows \li
597         \l windowModified, \l windowTitle, \l windowIcon,
598         \l isActiveWindow, activateWindow(), \l minimized, showMinimized(),
599         \l maximized, showMaximized(), \l fullScreen, showFullScreen(),
600         showNormal().
601 
602     \row \li Window contents \li
603         update(),
604         repaint(),
605         scroll().
606 
607     \row \li Geometry \li
608         \l pos, x(), y(), \l rect, \l size, width(), height(), move(), resize(),
609         \l sizePolicy, sizeHint(), minimumSizeHint(),
610         updateGeometry(), layout(),
611         \l frameGeometry, \l geometry, \l childrenRect, \l childrenRegion,
612         adjustSize(),
613         mapFromGlobal(), mapToGlobal(),
614         mapFromParent(), mapToParent(),
615         \l maximumSize, \l minimumSize, \l sizeIncrement,
616         \l baseSize, setFixedSize()
617 
618     \row \li Mode \li
619         \l visible, isVisibleTo(),
620         \l enabled, isEnabledTo(),
621         \l modal,
622         isWindow(),
623         \l mouseTracking,
624         \l updatesEnabled,
625         visibleRegion().
626 
627     \row \li Look and feel \li
628         style(),
629         setStyle(),
630         \l styleSheet,
631         \l cursor,
632         \l font,
633         \l palette,
634         backgroundRole(), setBackgroundRole(),
635         fontInfo(), fontMetrics().
636 
637     \row \li Keyboard focus functions \li
638         \l focus, \l focusPolicy,
639         setFocus(), clearFocus(), setTabOrder(), setFocusProxy(),
640         focusNextChild(), focusPreviousChild().
641 
642     \row \li Mouse and keyboard grabbing \li
643         grabMouse(), releaseMouse(),
644         grabKeyboard(), releaseKeyboard(),
645         mouseGrabber(), keyboardGrabber().
646 
647     \row \li Event handlers \li
648         event(),
649         mousePressEvent(),
650         mouseReleaseEvent(),
651         mouseDoubleClickEvent(),
652         mouseMoveEvent(),
653         keyPressEvent(),
654         keyReleaseEvent(),
655         focusInEvent(),
656         focusOutEvent(),
657         wheelEvent(),
658         enterEvent(),
659         leaveEvent(),
660         paintEvent(),
661         moveEvent(),
662         resizeEvent(),
663         closeEvent(),
664         dragEnterEvent(),
665         dragMoveEvent(),
666         dragLeaveEvent(),
667         dropEvent(),
668         childEvent(),
669         showEvent(),
670         hideEvent(),
671         customEvent().
672         changeEvent(),
673 
674     \row \li System functions \li
675         parentWidget(), window(), setParent(), winId(),
676         find(), metric().
677 
678     \row \li Context menu \li
679        contextMenuPolicy, contextMenuEvent(),
680        customContextMenuRequested(), actions()
681 
682     \row \li Interactive help \li
683         setToolTip(), setWhatsThis()
684 
685     \endtable
686 
687 
688     \section1 Widget Style Sheets
689 
690     In addition to the standard widget styles for each platform, widgets can
691     also be styled according to rules specified in a \l{styleSheet}
692     {style sheet}. This feature enables you to customize the appearance of
693     specific widgets to provide visual cues to users about their purpose. For
694     example, a button could be styled in a particular way to indicate that it
695     performs a destructive action.
696 
697     The use of widget style sheets is described in more detail in the
698     \l{Qt Style Sheets} document.
699 
700 
701     \section1 Transparency and Double Buffering
702 
703     Since Qt 4.0, QWidget automatically double-buffers its painting, so there
704     is no need to write double-buffering code in paintEvent() to avoid
705     flicker.
706 
707     Since Qt 4.1, the contents of parent widgets are propagated by
708     default to each of their children as long as Qt::WA_PaintOnScreen is not
709     set. Custom widgets can be written to take advantage of this feature by
710     updating irregular regions (to create non-rectangular child widgets), or
711     painting with colors that have less than full alpha component. The
712     following diagram shows how attributes and properties of a custom widget
713     can be fine-tuned to achieve different effects.
714 
715     \image propagation-custom.png
716 
717     In the above diagram, a semi-transparent rectangular child widget with an
718     area removed is constructed and added to a parent widget (a QLabel showing
719     a pixmap). Then, different properties and widget attributes are set to
720     achieve different effects:
721 
722     \list
723         \li  The left widget has no additional properties or widget attributes
724             set. This default state suits most custom widgets using
725             transparency, are irregularly-shaped, or do not paint over their
726             entire area with an opaque brush.
727         \li  The center widget has the \l autoFillBackground property set. This
728             property is used with custom widgets that rely on the widget to
729             supply a default background, and do not paint over their entire
730             area with an opaque brush.
731         \li  The right widget has the Qt::WA_OpaquePaintEvent widget attribute
732             set. This indicates that the widget will paint over its entire area
733             with opaque colors. The widget's area will initially be
734             \e{uninitialized}, represented in the diagram with a red diagonal
735             grid pattern that shines through the overpainted area. The
736             Qt::WA_OpaquePaintArea attribute is useful for widgets that need to
737             paint their own specialized contents quickly and do not need a
738             default filled background.
739     \endlist
740 
741     To rapidly update custom widgets with simple background colors, such as
742     real-time plotting or graphing widgets, it is better to define a suitable
743     background color (using setBackgroundRole() with the
744     QPalette::Window role), set the \l autoFillBackground property, and only
745     implement the necessary drawing functionality in the widget's paintEvent().
746 
747     To rapidly update custom widgets that constantly paint over their entire
748     areas with opaque content, e.g., video streaming widgets, it is better to
749     set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary overhead
750     associated with repainting the widget's background.
751 
752     If a widget has both the Qt::WA_OpaquePaintEvent widget attribute \e{and}
753     the \l autoFillBackground property set, the Qt::WA_OpaquePaintEvent
754     attribute takes precedence. Depending on your requirements, you should
755     choose either one of them.
756 
757     Since Qt 4.1, the contents of parent widgets are also propagated to
758     standard Qt widgets. This can lead to some unexpected results if the
759     parent widget is decorated in a non-standard way, as shown in the diagram
760     below.
761 
762     \image propagation-standard.png
763 
764     The scope for customizing the painting behavior of standard Qt widgets,
765     without resorting to subclassing, is slightly less than that possible for
766     custom widgets. Usually, the desired appearance of a standard widget can be
767     achieved by setting its \l autoFillBackground property.
768 
769 
770     \section1 Creating Translucent Windows
771 
772     Since Qt 4.5, it has been possible to create windows with translucent regions
773     on window systems that support compositing.
774 
775     To enable this feature in a top-level widget, set its Qt::WA_TranslucentBackground
776     attribute with setAttribute() and ensure that its background is painted with
777     non-opaque colors in the regions you want to be partially transparent.
778 
779     Platform notes:
780 
781     \list
782     \li X11: This feature relies on the use of an X server that supports ARGB visuals
783     and a compositing window manager.
784     \li Windows: The widget needs to have the Qt::FramelessWindowHint window flag set
785     for the translucency to work.
786     \endlist
787 
788 
789     \section1 Native Widgets vs Alien Widgets
790 
791     Introduced in Qt 4.4, alien widgets are widgets unknown to the windowing
792     system. They do not have a native window handle associated with them. This
793     feature significantly speeds up widget painting, resizing, and removes flicker.
794 
795     Should you require the old behavior with native windows, you can choose
796     one of the following options:
797 
798     \list 1
799         \li  Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
800         \li  Set the Qt::AA_NativeWindows attribute on your application. All
801             widgets will be native widgets.
802         \li  Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
803             and all of its ancestors will become native (unless
804             Qt::WA_DontCreateNativeAncestors is set).
805         \li  Call QWidget::winId to enforce a native window (this implies 3).
806         \li  Set the Qt::WA_PaintOnScreen attribute to enforce a native window
807             (this implies 3).
808     \endlist
809 
810     \sa QEvent, QPainter, QGridLayout, QBoxLayout
811 
812 */
813 
814 QWidgetMapper *QWidgetPrivate::mapper = nullptr;          // widget with wid
815 QWidgetSet *QWidgetPrivate::allWidgets = nullptr;         // widgets with no wid
816 
817 
818 /*****************************************************************************
819   QWidget member functions
820  *****************************************************************************/
821 
822 /*
823     Widget state flags:
824   \list
825   \li Qt::WA_WState_Created The widget has a valid winId().
826   \li Qt::WA_WState_Visible The widget is currently visible.
827   \li Qt::WA_WState_Hidden The widget is hidden, i.e. it won't
828   become visible unless you call show() on it. Qt::WA_WState_Hidden
829   implies !Qt::WA_WState_Visible.
830   \li Qt::WA_WState_CompressKeys Compress keyboard events.
831   \li Qt::WA_WState_BlockUpdates Repaints and updates are disabled.
832   \li Qt::WA_WState_InPaintEvent Currently processing a paint event.
833   \li Qt::WA_WState_Reparented The widget has been reparented.
834   \li Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending.
835   \li Qt::WA_WState_DND (Deprecated) The widget supports drag and drop, see setAcceptDrops().
836   \endlist
837 */
838 
839 struct QWidgetExceptionCleaner
840 {
841     /* this cleans up when the constructor throws an exception */
cleanupQWidgetExceptionCleaner842     static inline void cleanup(QWidget *that, QWidgetPrivate *d)
843     {
844 #ifdef QT_NO_EXCEPTIONS
845         Q_UNUSED(that);
846         Q_UNUSED(d);
847 #else
848         QWidgetPrivate::allWidgets->remove(that);
849         if (d->focus_next != that) {
850             if (d->focus_next)
851                 d->focus_next->d_func()->focus_prev = d->focus_prev;
852             if (d->focus_prev)
853                 d->focus_prev->d_func()->focus_next = d->focus_next;
854         }
855 #endif
856     }
857 };
858 
859 /*!
860     Constructs a widget which is a child of \a parent, with  widget
861     flags set to \a f.
862 
863     If \a parent is \nullptr, the new widget becomes a window. If
864     \a parent is another widget, this widget becomes a child window
865     inside \a parent. The new widget is deleted when its \a parent is
866     deleted.
867 
868     The widget flags argument, \a f, is normally 0, but it can be set
869     to customize the frame of a window (i.e. \a parent must be
870     \nullptr). To customize the frame, use a value composed
871     from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
872 
873     If you add a child widget to an already visible widget you must
874     explicitly show the child to make it visible.
875 
876     Note that the X11 version of Qt may not be able to deliver all
877     combinations of style flags on all systems. This is because on
878     X11, Qt can only ask the window manager, and the window manager
879     can override the application's settings. On Windows, Qt can set
880     whatever flags you want.
881 
882     \sa windowFlags
883 */
QWidget(QWidget * parent,Qt::WindowFlags f)884 QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
885     : QObject(*new QWidgetPrivate, nullptr), QPaintDevice()
886 {
887     QT_TRY {
888         d_func()->init(parent, f);
889     } QT_CATCH(...) {
890         QWidgetExceptionCleaner::cleanup(this, d_func());
891         QT_RETHROW;
892     }
893 }
894 
895 
896 /*! \internal
897 */
QWidget(QWidgetPrivate & dd,QWidget * parent,Qt::WindowFlags f)898 QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
899     : QObject(dd, nullptr), QPaintDevice()
900 {
901     Q_D(QWidget);
902     QT_TRY {
903         d->init(parent, f);
904     } QT_CATCH(...) {
905         QWidgetExceptionCleaner::cleanup(this, d_func());
906         QT_RETHROW;
907     }
908 }
909 
910 /*!
911     \internal
912 */
devType() const913 int QWidget::devType() const
914 {
915     return QInternal::Widget;
916 }
917 
918 
919 //### w is a "this" ptr, passed as a param because QWorkspace needs special logic
adjustFlags(Qt::WindowFlags & flags,QWidget * w)920 void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
921 {
922     bool customize =  (flags & (Qt::CustomizeWindowHint
923             | Qt::FramelessWindowHint
924             | Qt::WindowTitleHint
925             | Qt::WindowSystemMenuHint
926             | Qt::WindowMinimizeButtonHint
927             | Qt::WindowMaximizeButtonHint
928             | Qt::WindowCloseButtonHint
929             | Qt::WindowContextHelpButtonHint));
930 
931     uint type = (flags & Qt::WindowType_Mask);
932 
933     if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) {
934         type = Qt::Window;
935         flags |= Qt::Window;
936     }
937 
938     if (flags & Qt::CustomizeWindowHint) {
939         // modify window flags to make them consistent.
940         // Only enable this on non-Mac platforms. Since the old way of doing this would
941         // interpret WindowSystemMenuHint as a close button and we can't change that behavior
942         // we can't just add this in.
943         if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
944 #  ifdef Q_OS_WIN
945             && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
946 #  endif
947            ) {
948             flags |= Qt::WindowSystemMenuHint;
949             flags |= Qt::WindowTitleHint;
950             flags &= ~Qt::FramelessWindowHint;
951         }
952     } else if (customize && !(flags & Qt::FramelessWindowHint)) {
953         // if any of the window hints that affect the titlebar are set
954         // and the window is supposed to have frame, we add a titlebar
955         // and system menu by default.
956         flags |= Qt::WindowSystemMenuHint;
957         flags |= Qt::WindowTitleHint;
958     }
959     if (customize)
960         ; // don't modify window flags if the user explicitly set them.
961     else if (type == Qt::Dialog || type == Qt::Sheet) {
962         flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
963         // ### fixme: Qt 6: Never set Qt::WindowContextHelpButtonHint flag automatically
964         if (!QApplicationPrivate::testAttribute(Qt::AA_DisableWindowContextHelpButton))
965             flags |= Qt::WindowContextHelpButtonHint;
966     } else if (type == Qt::Tool)
967         flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
968     else
969         flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint |
970                 Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint | Qt::WindowFullscreenButtonHint;
971     if (w->testAttribute(Qt::WA_TransparentForMouseEvents))
972         flags |= Qt::WindowTransparentForInput;
973 }
974 
init(QWidget * parentWidget,Qt::WindowFlags f)975 void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
976 {
977     Q_Q(QWidget);
978     Q_ASSERT_X(q != parentWidget, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
979 
980     if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
981         qFatal("QWidget: Cannot create a QWidget without QApplication");
982 
983     Q_ASSERT(allWidgets);
984     if (allWidgets)
985         allWidgets->insert(q);
986 
987     int targetScreen = -1;
988     if (parentWidget && parentWidget->windowType() == Qt::Desktop) {
989         const QDesktopScreenWidget *sw = qobject_cast<const QDesktopScreenWidget *>(parentWidget);
990         targetScreen = sw ? sw->screenNumber() : 0;
991         parentWidget = nullptr;
992     }
993 
994     q->data = &data;
995 
996 #if QT_CONFIG(thread)
997     if (!parent) {
998         Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
999                    "Widgets must be created in the GUI thread.");
1000     }
1001 #endif
1002 
1003     if (targetScreen >= 0) {
1004         topData()->initialScreenIndex = targetScreen;
1005         if (QWindow *window = q->windowHandle())
1006             window->setScreen(QGuiApplication::screens().value(targetScreen, nullptr));
1007     }
1008 
1009     data.fstrut_dirty = true;
1010 
1011     data.winid = 0;
1012     data.widget_attributes = 0;
1013     data.window_flags = f;
1014     data.window_state = 0;
1015     data.focus_policy = 0;
1016     data.context_menu_policy = Qt::DefaultContextMenu;
1017     data.window_modality = Qt::NonModal;
1018 
1019     data.sizehint_forced = 0;
1020     data.is_closing = 0;
1021     data.in_show = 0;
1022     data.in_set_window_state = 0;
1023     data.in_destructor = false;
1024 
1025     // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
1026     if (f & Qt::MSWindowsOwnDC) {
1027         mustHaveWindowHandle = 1;
1028         q->setAttribute(Qt::WA_NativeWindow);
1029     }
1030 
1031     q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
1032     adjustQuitOnCloseAttribute();
1033 
1034     q->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea);
1035     q->setAttribute(Qt::WA_WState_Hidden);
1036 
1037     //give potential windows a bigger "pre-initial" size; create() will give them a new size later
1038     data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
1039     focus_next = focus_prev = q;
1040 
1041     if ((f & Qt::WindowType_Mask) == Qt::Desktop)
1042         q->create();
1043     else if (parentWidget)
1044         q->setParent(parentWidget, data.window_flags);
1045     else {
1046         adjustFlags(data.window_flags, q);
1047         resolveLayoutDirection();
1048         // opaque system background?
1049         const QBrush &background = q->palette().brush(QPalette::Window);
1050         setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
1051     }
1052     data.fnt = QFont(data.fnt, q);
1053 
1054     q->setAttribute(Qt::WA_PendingMoveEvent);
1055     q->setAttribute(Qt::WA_PendingResizeEvent);
1056 
1057     if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
1058         QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
1059 
1060     if (QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation)) // ### fixme: Qt 6: Remove AA_ImmediateWidgetCreation.
1061         q->create();
1062 
1063     QEvent e(QEvent::Create);
1064     QCoreApplication::sendEvent(q, &e);
1065     QCoreApplication::postEvent(q, new QEvent(QEvent::PolishRequest));
1066 
1067     extraPaintEngine = nullptr;
1068 }
1069 
createRecursively()1070 void QWidgetPrivate::createRecursively()
1071 {
1072     Q_Q(QWidget);
1073     q->create(0, true, true);
1074     for (int i = 0; i < children.size(); ++i) {
1075         QWidget *child = qobject_cast<QWidget *>(children.at(i));
1076         if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(Qt::WA_WState_Created))
1077             child->d_func()->createRecursively();
1078     }
1079 }
1080 
windowHandle(WindowHandleMode mode) const1081 QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
1082 {
1083     if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) {
1084         if (QTLWExtra *x = maybeTopData()) {
1085             if (x->window != nullptr || mode == WindowHandleMode::Direct)
1086                 return x->window;
1087         }
1088     }
1089     if (mode == WindowHandleMode::Closest) {
1090         if (auto nativeParent = q_func()->nativeParentWidget()) {
1091             if (auto window = nativeParent->windowHandle())
1092                 return window;
1093         }
1094     }
1095     if (mode == WindowHandleMode::TopLevel || mode == WindowHandleMode::Closest) {
1096         if (auto topLevel = q_func()->topLevelWidget()) {
1097             if (auto window = topLevel ->windowHandle())
1098                 return window;
1099         }
1100     }
1101     return nullptr;
1102 }
1103 
associatedScreen() const1104 QScreen *QWidgetPrivate::associatedScreen() const
1105 {
1106     if (auto window = windowHandle(WindowHandleMode::Closest))
1107         return window->screen();
1108     return nullptr;
1109 }
1110 
1111 // ### fixme: Qt 6: Remove parameter window from QWidget::create()
1112 
1113 /*!
1114     Creates a new widget window.
1115 
1116     The parameters \a window, \a initializeWindow, and \a destroyOldWindow
1117     are ignored in Qt 5. Please use QWindow::fromWinId() to create a
1118     QWindow wrapping a foreign window and pass it to
1119     QWidget::createWindowContainer() instead.
1120 
1121     \sa createWindowContainer(), QWindow::fromWinId()
1122 */
1123 
create(WId window,bool initializeWindow,bool destroyOldWindow)1124 void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
1125 {
1126     Q_UNUSED(initializeWindow);
1127     Q_UNUSED(destroyOldWindow);
1128 
1129     Q_D(QWidget);
1130     if (Q_UNLIKELY(window))
1131         qWarning("QWidget::create(): Parameter 'window' does not have any effect.");
1132     if (testAttribute(Qt::WA_WState_Created) && window == 0 && internalWinId())
1133         return;
1134 
1135     if (d->data.in_destructor)
1136         return;
1137 
1138     Qt::WindowType type = windowType();
1139     Qt::WindowFlags &flags = data->window_flags;
1140 
1141     if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
1142         type = Qt::Window;
1143         flags |= Qt::Window;
1144     }
1145 
1146     if (QWidget *parent = parentWidget()) {
1147         if (type & Qt::Window) {
1148             if (!parent->testAttribute(Qt::WA_WState_Created))
1149                 parent->createWinId();
1150         } else if (testAttribute(Qt::WA_NativeWindow) && !parent->internalWinId()
1151                    && !testAttribute(Qt::WA_DontCreateNativeAncestors)) {
1152             // We're about to create a native child widget that doesn't have a native parent;
1153             // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
1154             // attribute is set.
1155             d->createWinId();
1156             // Nothing more to do.
1157             Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1158             Q_ASSERT(internalWinId());
1159             return;
1160         }
1161     }
1162 
1163 
1164     static const bool paintOnScreenEnv = qEnvironmentVariableIntValue("QT_ONSCREEN_PAINT") > 0;
1165     if (paintOnScreenEnv)
1166         setAttribute(Qt::WA_PaintOnScreen);
1167 
1168     if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
1169         setAttribute(Qt::WA_NativeWindow);
1170 
1171 #ifdef ALIEN_DEBUG
1172     qDebug() << "QWidget::create:" << this << "parent:" << parentWidget()
1173              << "Alien?" << !testAttribute(Qt::WA_NativeWindow);
1174 #endif
1175 
1176     d->updateIsOpaque();
1177 
1178     setAttribute(Qt::WA_WState_Created);                        // set created flag
1179     d->create();
1180 
1181     // A real toplevel window needs a paint manager
1182     if (isWindow() && windowType() != Qt::Desktop)
1183         d->topData()->repaintManager.reset(new QWidgetRepaintManager(this));
1184 
1185     d->setModal_sys();
1186 
1187     if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))
1188         setAttribute(Qt::WA_DropSiteRegistered, true);
1189 
1190     // need to force the resting of the icon after changing parents
1191     if (testAttribute(Qt::WA_SetWindowIcon))
1192         d->setWindowIcon_sys();
1193 
1194     if (isWindow() && !d->topData()->iconText.isEmpty())
1195         d->setWindowIconText_helper(d->topData()->iconText);
1196     if (isWindow() && !d->topData()->caption.isEmpty())
1197         d->setWindowTitle_helper(d->topData()->caption);
1198     if (isWindow() && !d->topData()->filePath.isEmpty())
1199         d->setWindowFilePath_helper(d->topData()->filePath);
1200     if (windowType() != Qt::Desktop) {
1201         d->updateSystemBackground();
1202 
1203         if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon))
1204             d->setWindowIcon_sys();
1205     }
1206 
1207     // Frame strut update needed in cases where there are native widgets such as QGLWidget,
1208     // as those force native window creation on their ancestors before they are shown.
1209     // If the strut is not updated, any subsequent move of the top level window before show
1210     // will cause window frame to be ignored when positioning the window.
1211     // Note that this only helps on platforms that handle window creation synchronously.
1212     d->updateFrameStrut();
1213 }
1214 
q_createNativeChildrenAndSetParent(const QWidget * parentWidget)1215 void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
1216 {
1217     QObjectList children = parentWidget->children();
1218     for (int i = 0; i < children.size(); i++) {
1219         if (children.at(i)->isWidgetType()) {
1220             const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
1221             if (childWidget) { // should not be necessary
1222                 if (childWidget->testAttribute(Qt::WA_NativeWindow)) {
1223                     if (!childWidget->internalWinId())
1224                         childWidget->winId();
1225                     if (childWidget->windowHandle()) {
1226                         if (childWidget->isWindow()) {
1227                             childWidget->windowHandle()->setTransientParent(parentWidget->window()->windowHandle());
1228                         } else {
1229                             childWidget->windowHandle()->setParent(childWidget->nativeParentWidget()->windowHandle());
1230                         }
1231                     }
1232                 } else {
1233                     q_createNativeChildrenAndSetParent(childWidget);
1234                 }
1235             }
1236         }
1237     }
1238 
1239 }
1240 
create()1241 void QWidgetPrivate::create()
1242 {
1243     Q_Q(QWidget);
1244 
1245     if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
1246         return; // we only care about real toplevels
1247 
1248     QWidgetWindow *win = topData()->window;
1249     // topData() ensures the extra is created but does not ensure 'window' is non-null
1250     // in case the extra was already valid.
1251     if (!win) {
1252         createTLSysExtra();
1253         win = topData()->window;
1254     }
1255 
1256     const auto dynamicPropertyNames = q->dynamicPropertyNames();
1257     for (const QByteArray &propertyName : dynamicPropertyNames) {
1258         if (!qstrncmp(propertyName, "_q_platform_", 12))
1259             win->setProperty(propertyName, q->property(propertyName));
1260     }
1261 
1262     Qt::WindowFlags &flags = data.window_flags;
1263 
1264 #if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
1265     if (q->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
1266         flags |= Qt::MaximizeUsingFullscreenGeometryHint;
1267 #endif
1268 
1269     if (q->testAttribute(Qt::WA_ShowWithoutActivating))
1270         win->setProperty("_q_showWithoutActivating", QVariant(true));
1271     if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow))
1272         win->setProperty("_q_macAlwaysShowToolWindow", QVariant(true));
1273     setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
1274     win->setFlags(flags);
1275     fixPosIncludesFrame();
1276     if (q->testAttribute(Qt::WA_Moved)
1277         || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
1278         win->setGeometry(q->geometry());
1279     else
1280         win->resize(q->size());
1281     if (win->isTopLevel()) {
1282         int screenNumber = topData()->initialScreenIndex;
1283         topData()->initialScreenIndex = -1;
1284         if (screenNumber < 0) {
1285             screenNumber = q->windowType() != Qt::Desktop
1286                 ? QDesktopWidgetPrivate::screenNumber(q) : 0;
1287         }
1288         win->setScreen(QGuiApplication::screens().value(screenNumber, nullptr));
1289     }
1290 
1291     QSurfaceFormat format = win->requestedFormat();
1292     if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
1293             && q->testAttribute(Qt::WA_TranslucentBackground)) {
1294         format.setAlphaBufferSize(8);
1295     }
1296     win->setFormat(format);
1297 
1298     if (QWidget *nativeParent = q->nativeParentWidget()) {
1299         if (nativeParent->windowHandle()) {
1300             if (flags & Qt::Window) {
1301                 win->setTransientParent(nativeParent->window()->windowHandle());
1302                 win->setParent(nullptr);
1303             } else {
1304                 win->setTransientParent(nullptr);
1305                 win->setParent(nativeParent->windowHandle());
1306             }
1307         }
1308     }
1309 
1310     qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
1311         QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
1312 
1313     if (q->windowType() != Qt::Desktop || q->testAttribute(Qt::WA_NativeWindow)) {
1314         win->create();
1315         // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
1316         if (QPlatformWindow *platformWindow = win->handle())
1317             platformWindow->setFrameStrutEventsEnabled(true);
1318     }
1319 
1320     data.window_flags = win->flags();
1321     if (!win->isTopLevel()) // In a Widget world foreign windows can only be top level
1322       data.window_flags &= ~Qt::ForeignWindow;
1323 
1324     if (!topData()->role.isNull())
1325         QXcbWindowFunctions::setWmWindowRole(win, topData()->role.toLatin1());
1326 
1327     QBackingStore *store = q->backingStore();
1328 
1329     if (!store) {
1330         if (q->windowType() != Qt::Desktop) {
1331             if (q->isTopLevel())
1332                 q->setBackingStore(new QBackingStore(win));
1333         } else {
1334             q->setAttribute(Qt::WA_PaintOnScreen, true);
1335         }
1336     }
1337 
1338     setWindowModified_helper();
1339 
1340     if (win->handle()) {
1341         WId id = win->winId();
1342         // See the QPlatformWindow::winId() documentation
1343         Q_ASSERT(id != WId(0));
1344         setWinId(id);
1345     }
1346 
1347     // Check children and create windows for them if necessary
1348     q_createNativeChildrenAndSetParent(q);
1349 
1350     if (extra && !extra->mask.isEmpty())
1351         setMask_sys(extra->mask);
1352 
1353     if (data.crect.width() == 0 || data.crect.height() == 0) {
1354         q->setAttribute(Qt::WA_OutsideWSRange, true);
1355     } else if (q->isVisible()) {
1356         // If widget is already shown, set window visible, too
1357         win->setNativeWindowVisibility(true);
1358     }
1359 }
1360 
1361 #ifdef Q_OS_WIN
1362 static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1363 #endif
1364 
createTLSysExtra()1365 void QWidgetPrivate::createTLSysExtra()
1366 {
1367     Q_Q(QWidget);
1368     if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
1369         extra->topextra->window = new QWidgetWindow(q);
1370         if (extra->minw || extra->minh)
1371             extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
1372         if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
1373             extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
1374         if (extra->topextra->opacity != 255 && q->isWindow())
1375             extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
1376 
1377         const bool isTipLabel = q->inherits("QTipLabel");
1378         const bool isAlphaWidget = !isTipLabel && q->inherits("QAlphaWidget");
1379 #ifdef Q_OS_WIN
1380         // Pass on native parent handle for Widget embedded into Active X.
1381         const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
1382         if (activeXNativeParentHandle.isValid())
1383             extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
1384         if (isTipLabel || isAlphaWidget)
1385             extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
1386 #endif
1387         if (isTipLabel || isAlphaWidget || q->inherits("QRollEffect"))
1388             qt_window_private(extra->topextra->window)->setAutomaticPositionAndResizeEnabled(false);
1389     }
1390 
1391 }
1392 
1393 /*!
1394     Destroys the widget.
1395 
1396     All this widget's children are deleted first. The application
1397     exits if this widget is the main widget.
1398 */
1399 
~QWidget()1400 QWidget::~QWidget()
1401 {
1402     Q_D(QWidget);
1403     d->data.in_destructor = true;
1404 
1405 #if defined (QT_CHECK_STATE)
1406     if (Q_UNLIKELY(paintingActive()))
1407         qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
1408 #endif
1409 
1410 #ifndef QT_NO_GESTURES
1411     if (QGestureManager *manager = QGestureManager::instance(QGestureManager::DontForceCreation)) {
1412         // \forall Qt::GestureType type : ungrabGesture(type) (inlined)
1413         for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
1414             manager->cleanupCachedGestures(this, *it);
1415     }
1416     d->gestureContext.clear();
1417 #endif
1418 
1419 #ifndef QT_NO_ACTION
1420     // remove all actions from this widget
1421     for (int i = 0; i < d->actions.size(); ++i) {
1422         QActionPrivate *apriv = d->actions.at(i)->d_func();
1423         apriv->widgets.removeAll(this);
1424     }
1425     d->actions.clear();
1426 #endif
1427 
1428 #ifndef QT_NO_SHORTCUT
1429     // Remove all shortcuts grabbed by this
1430     // widget, unless application is closing
1431     if (!QApplicationPrivate::is_app_closing && testAttribute(Qt::WA_GrabbedShortcut))
1432         QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(0, this, QKeySequence());
1433 #endif
1434 
1435     // delete layout while we still are a valid widget
1436     delete d->layout;
1437     d->layout = nullptr;
1438     // Remove myself from focus list
1439 
1440     Q_ASSERT(d->focus_next->d_func()->focus_prev == this);
1441     Q_ASSERT(d->focus_prev->d_func()->focus_next == this);
1442 
1443     if (d->focus_next != this) {
1444         d->focus_next->d_func()->focus_prev = d->focus_prev;
1445         d->focus_prev->d_func()->focus_next = d->focus_next;
1446         d->focus_next = d->focus_prev = nullptr;
1447     }
1448 
1449 
1450     QT_TRY {
1451 #if QT_CONFIG(graphicsview)
1452         const QWidget* w = this;
1453         while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1454             w = w->d_func()->extra->focus_proxy;
1455         QWidget *window = w->window();
1456         QWExtra *e = window ? window->d_func()->extra.get() : nullptr ;
1457         if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1458 #endif
1459         clearFocus();
1460     } QT_CATCH(...) {
1461         // swallow this problem because we are in a destructor
1462     }
1463 
1464     d->setDirtyOpaqueRegion();
1465 
1466     if (isWindow() && isVisible() && internalWinId()) {
1467         QT_TRY {
1468             d->close_helper(QWidgetPrivate::CloseNoEvent);
1469         } QT_CATCH(...) {
1470             // if we're out of memory, at least hide the window.
1471             QT_TRY {
1472                 hide();
1473             } QT_CATCH(...) {
1474                 // and if that also doesn't work, then give up
1475             }
1476         }
1477     } else if (isVisible()) {
1478         qApp->d_func()->sendSyntheticEnterLeave(this);
1479     }
1480 
1481     if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
1482         repaintManager->removeDirtyWidget(this);
1483         if (testAttribute(Qt::WA_StaticContents))
1484             repaintManager->removeStaticWidget(this);
1485     }
1486 
1487     delete d->needsFlush;
1488     d->needsFlush = nullptr;
1489 
1490     // The next 20 lines are duplicated from QObject, but required here
1491     // since QWidget deletes is children itself
1492     bool blocked = d->blockSig;
1493     d->blockSig = 0; // unblock signals so we always emit destroyed()
1494 
1495     if (d->isSignalConnected(0)) {
1496         QT_TRY {
1497             emit destroyed(this);
1498         } QT_CATCH(...) {
1499             // all the signal/slots connections are still in place - if we don't
1500             // quit now, we will crash pretty soon.
1501             qWarning("Detected an unexpected exception in ~QWidget while emitting destroyed().");
1502             QT_RETHROW;
1503         }
1504     }
1505 
1506     if (d->declarativeData) {
1507         d->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1508         if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) {
1509             if (QAbstractDeclarativeData::destroyed_qml1)
1510                 QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
1511         } else {
1512             if (QAbstractDeclarativeData::destroyed)
1513                 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1514         }
1515         d->declarativeData = nullptr;                 // don't activate again in ~QObject
1516         d->wasDeleted = false;
1517     }
1518 
1519     d->blockSig = blocked;
1520 
1521     if (!d->children.isEmpty())
1522         d->deleteChildren();
1523 
1524     QCoreApplication::removePostedEvents(this);
1525 
1526     QT_TRY {
1527         destroy();                                        // platform-dependent cleanup
1528     } QT_CATCH(...) {
1529         // if this fails we can't do anything about it but at least we are not allowed to throw.
1530     }
1531     --QWidgetPrivate::instanceCounter;
1532 
1533     if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1534         QWidgetPrivate::allWidgets->remove(this);
1535 
1536     QT_TRY {
1537         QEvent e(QEvent::Destroy);
1538         QCoreApplication::sendEvent(this, &e);
1539     } QT_CATCH(const std::exception&) {
1540         // if this fails we can't do anything about it but at least we are not allowed to throw.
1541     }
1542 
1543 #if QT_CONFIG(graphicseffect)
1544     delete d->graphicsEffect;
1545 #endif
1546 }
1547 
1548 int QWidgetPrivate::instanceCounter = 0;  // Current number of widget instances
1549 int QWidgetPrivate::maxInstances = 0;     // Maximum number of widget instances
1550 
setWinId(WId id)1551 void QWidgetPrivate::setWinId(WId id)                // set widget identifier
1552 {
1553     Q_Q(QWidget);
1554     // the user might create a widget with Qt::Desktop window
1555     // attribute (or create another QDesktopWidget instance), which
1556     // will have the same windowid (the root window id) as the
1557     // qt_desktopWidget. We should not add the second desktop widget
1558     // to the mapper.
1559     bool userDesktopWidget = qt_desktopWidget != nullptr && qt_desktopWidget != q && q->windowType() == Qt::Desktop;
1560     if (mapper && data.winid && !userDesktopWidget) {
1561         mapper->remove(data.winid);
1562     }
1563 
1564     const WId oldWinId = data.winid;
1565 
1566     data.winid = id;
1567     if (mapper && id && !userDesktopWidget) {
1568         mapper->insert(data.winid, q);
1569     }
1570 
1571     if(oldWinId != id) {
1572         QEvent e(QEvent::WinIdChange);
1573         QCoreApplication::sendEvent(q, &e);
1574     }
1575 }
1576 
createTLExtra()1577 void QWidgetPrivate::createTLExtra()
1578 {
1579     if (!extra)
1580         createExtra();
1581     if (!extra->topextra) {
1582         extra->topextra = qt_make_unique<QTLWExtra>();
1583         QTLWExtra* x = extra->topextra.get();
1584         x->backingStore = nullptr;
1585         x->sharedPainter = nullptr;
1586         x->incw = x->inch = 0;
1587         x->basew = x->baseh = 0;
1588         x->frameStrut.setCoords(0, 0, 0, 0);
1589         x->normalGeometry = QRect(0,0,-1,-1);
1590         x->savedFlags = { };
1591         x->opacity = 255;
1592         x->posIncludesFrame = 0;
1593         x->sizeAdjusted = false;
1594         x->embedded = 0;
1595         x->window = nullptr;
1596         x->initialScreenIndex = -1;
1597 
1598 #ifdef QWIDGET_EXTRA_DEBUG
1599         static int count = 0;
1600         qDebug() << "tlextra" << ++count;
1601 #endif
1602     }
1603 }
1604 
1605 /*!
1606   \internal
1607   Creates the widget extra data.
1608 */
1609 
createExtra()1610 void QWidgetPrivate::createExtra()
1611 {
1612     if (!extra) {                                // if not exists
1613         extra = qt_make_unique<QWExtra>();
1614         extra->glContext = nullptr;
1615 #if QT_CONFIG(graphicsview)
1616         extra->proxyWidget = nullptr;
1617 #endif
1618         extra->minw = 0;
1619         extra->minh = 0;
1620         extra->maxw = QWIDGETSIZE_MAX;
1621         extra->maxh = QWIDGETSIZE_MAX;
1622         extra->customDpiX = 0;
1623         extra->customDpiY = 0;
1624         extra->explicitMinSize = 0;
1625         extra->explicitMaxSize = 0;
1626         extra->autoFillBackground = 0;
1627         extra->nativeChildrenForced = 0;
1628         extra->inRenderWithPainter = 0;
1629         extra->hasWindowContainer = false;
1630         extra->hasMask = 0;
1631         createSysExtra();
1632 #ifdef QWIDGET_EXTRA_DEBUG
1633         static int count = 0;
1634         qDebug() << "extra" << ++count;
1635 #endif
1636     }
1637 }
1638 
createSysExtra()1639 void QWidgetPrivate::createSysExtra()
1640 {
1641 }
1642 
1643 /*!
1644   \internal
1645   Deletes the widget extra data.
1646 */
1647 
deleteExtra()1648 void QWidgetPrivate::deleteExtra()
1649 {
1650     if (extra) {                                // if exists
1651         deleteSysExtra();
1652 #ifndef QT_NO_STYLE_STYLESHEET
1653         // dereference the stylesheet style
1654         if (QStyleSheetStyle *proxy = qt_styleSheet(extra->style))
1655             proxy->deref();
1656 #endif
1657         if (extra->topextra) {
1658             deleteTLSysExtra();
1659             // extra->topextra->backingStore destroyed in QWidgetPrivate::deleteTLSysExtra()
1660         }
1661         // extra->xic destroyed in QWidget::destroy()
1662         extra.reset();
1663     }
1664 }
1665 
deleteSysExtra()1666 void QWidgetPrivate::deleteSysExtra()
1667 {
1668 }
1669 
deleteBackingStore(QWidgetPrivate * d)1670 static void deleteBackingStore(QWidgetPrivate *d)
1671 {
1672     QTLWExtra *topData = d->topData();
1673 
1674     delete topData->backingStore;
1675     topData->backingStore = nullptr;
1676 }
1677 
deleteTLSysExtra()1678 void QWidgetPrivate::deleteTLSysExtra()
1679 {
1680     if (extra && extra->topextra) {
1681         //the qplatformbackingstore may hold a reference to the window, so the backingstore
1682         //needs to be deleted first.
1683 
1684         extra->topextra->repaintManager.reset(nullptr);
1685         deleteBackingStore(this);
1686 #ifndef QT_NO_OPENGL
1687         extra->topextra->widgetTextures.clear();
1688         extra->topextra->shareContext.reset();
1689 #endif
1690 
1691         //the toplevel might have a context with a "qglcontext associated with it. We need to
1692         //delete the qglcontext before we delete the qplatformopenglcontext.
1693         //One unfortunate thing about this is that we potentially create a glContext just to
1694         //delete it straight afterwards.
1695         if (extra->topextra->window) {
1696             extra->topextra->window->destroy();
1697         }
1698         delete extra->topextra->window;
1699         extra->topextra->window = nullptr;
1700 
1701     }
1702 }
1703 
1704 /*
1705   Returns \c region of widgets above this which overlap with
1706   \a rect, which is in parent's coordinate system (same as crect).
1707 */
1708 
overlappedRegion(const QRect & rect,bool breakAfterFirst) const1709 QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
1710 {
1711     Q_Q(const QWidget);
1712 
1713     const QWidget *w = q;
1714     QRect r = rect;
1715     QPoint p;
1716     QRegion region;
1717     while (w) {
1718         if (w->isWindow())
1719             break;
1720         QWidgetPrivate *pd = w->parentWidget()->d_func();
1721         bool above = false;
1722         for (int i = 0; i < pd->children.size(); ++i) {
1723             QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
1724             if (!sibling || !sibling->isVisible() || sibling->isWindow())
1725                 continue;
1726             if (!above) {
1727                 above = (sibling == w);
1728                 continue;
1729             }
1730 
1731             const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect);
1732             if (qRectIntersects(siblingRect, r)) {
1733                 const auto &siblingExtra = sibling->d_func()->extra;
1734                 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1735                     && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
1736                     continue;
1737                 }
1738                 region += siblingRect.translated(-p);
1739                 if (breakAfterFirst)
1740                     break;
1741             }
1742         }
1743         w = w->parentWidget();
1744         r.translate(pd->data.crect.topLeft());
1745         p += pd->data.crect.topLeft();
1746     }
1747     return region;
1748 }
1749 
syncBackingStore()1750 void QWidgetPrivate::syncBackingStore()
1751 {
1752     if (shouldPaintOnScreen()) {
1753         paintOnScreen(dirty);
1754         dirty = QRegion();
1755     } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1756         repaintManager->sync();
1757     }
1758 }
1759 
syncBackingStore(const QRegion & region)1760 void QWidgetPrivate::syncBackingStore(const QRegion &region)
1761 {
1762     if (shouldPaintOnScreen())
1763         paintOnScreen(region);
1764     else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1765         repaintManager->sync(q_func(), region);
1766     }
1767 }
1768 
paintOnScreen(const QRegion & rgn)1769 void QWidgetPrivate::paintOnScreen(const QRegion &rgn)
1770 {
1771     if (data.in_destructor)
1772         return;
1773 
1774     if (shouldDiscardSyncRequest())
1775         return;
1776 
1777     Q_Q(QWidget);
1778     if (q->testAttribute(Qt::WA_StaticContents)) {
1779         if (!extra)
1780             createExtra();
1781         extra->staticContentsSize = data.crect.size();
1782     }
1783 
1784     QPaintEngine *engine = q->paintEngine();
1785 
1786     // QGLWidget does not support partial updates if:
1787     // 1) The context is double buffered
1788     // 2) The context is single buffered and auto-fill background is enabled.
1789     const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
1790                                                 || engine->type() == QPaintEngine::OpenGL2))
1791                                         && (usesDoubleBufferedGLContext || q->autoFillBackground());
1792     QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
1793 
1794     toBePainted &= clipRect();
1795     clipToEffectiveMask(toBePainted);
1796     if (toBePainted.isEmpty())
1797         return; // Nothing to repaint.
1798 
1799     drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, nullptr);
1800 
1801     if (Q_UNLIKELY(q->paintingActive()))
1802         qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
1803 }
1804 
setUpdatesEnabled_helper(bool enable)1805 void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1806 {
1807     Q_Q(QWidget);
1808 
1809     if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1810         return; // nothing we can do
1811 
1812     if (enable != q->testAttribute(Qt::WA_UpdatesDisabled))
1813         return; // nothing to do
1814 
1815     q->setAttribute(Qt::WA_UpdatesDisabled, !enable);
1816     if (enable)
1817         q->update();
1818 
1819     Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1820     for (int i = 0; i < children.size(); ++i) {
1821         QWidget *w = qobject_cast<QWidget *>(children.at(i));
1822         if (w && !w->isWindow() && !w->testAttribute(attribute))
1823             w->d_func()->setUpdatesEnabled_helper(enable);
1824     }
1825 }
1826 
1827 /*!
1828     \internal
1829 
1830     Propagate this widget's palette to all children, except style sheet
1831     widgets, and windows that don't enable window propagation (palettes don't
1832     normally propagate to windows).
1833 */
propagatePaletteChange()1834 void QWidgetPrivate::propagatePaletteChange()
1835 {
1836     Q_Q(QWidget);
1837     // Propagate a new inherited mask to all children.
1838 #if QT_CONFIG(graphicsview)
1839     if (!q->parentWidget() && extra && extra->proxyWidget) {
1840         QGraphicsProxyWidget *p = extra->proxyWidget;
1841         inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolve();
1842     } else
1843 #endif // QT_CONFIG(graphicsview)
1844         if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
1845         inheritedPaletteResolveMask = 0;
1846     }
1847 
1848     directPaletteResolveMask = data.pal.resolve();
1849     auto mask = directPaletteResolveMask | inheritedPaletteResolveMask;
1850 
1851     const bool useStyleSheetPropagationInWidgetStyles =
1852         QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
1853 
1854     QEvent pc(QEvent::PaletteChange);
1855     QCoreApplication::sendEvent(q, &pc);
1856     for (int i = 0; i < children.size(); ++i) {
1857         QWidget *w = qobject_cast<QWidget*>(children.at(i));
1858         if (w && (!w->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
1859             && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
1860             QWidgetPrivate *wd = w->d_func();
1861             wd->inheritedPaletteResolveMask = mask;
1862             wd->resolvePalette();
1863         }
1864     }
1865 }
1866 
1867 /*
1868   Returns the widget's clipping rectangle.
1869 */
clipRect() const1870 QRect QWidgetPrivate::clipRect() const
1871 {
1872     Q_Q(const QWidget);
1873     const QWidget * w = q;
1874     if (!w->isVisible())
1875         return QRect();
1876     QRect r = effectiveRectFor(q->rect());
1877     int ox = 0;
1878     int oy = 0;
1879     while (w
1880             && w->isVisible()
1881             && !w->isWindow()
1882             && w->parentWidget()) {
1883         ox -= w->x();
1884         oy -= w->y();
1885         w = w->parentWidget();
1886         r &= QRect(ox, oy, w->width(), w->height());
1887     }
1888     return r;
1889 }
1890 
1891 /*
1892   Returns the widget's clipping region (without siblings).
1893 */
clipRegion() const1894 QRegion QWidgetPrivate::clipRegion() const
1895 {
1896     Q_Q(const QWidget);
1897     if (!q->isVisible())
1898         return QRegion();
1899     QRegion r(q->rect());
1900     const QWidget * w = q;
1901     const QWidget *ignoreUpTo;
1902     int ox = 0;
1903     int oy = 0;
1904     while (w
1905            && w->isVisible()
1906            && !w->isWindow()
1907            && w->parentWidget()) {
1908         ox -= w->x();
1909         oy -= w->y();
1910         ignoreUpTo = w;
1911         w = w->parentWidget();
1912         r &= QRegion(ox, oy, w->width(), w->height());
1913 
1914         int i = 0;
1915         while(w->d_func()->children.at(i++) != static_cast<const QObject *>(ignoreUpTo))
1916             ;
1917         for ( ; i < w->d_func()->children.size(); ++i) {
1918             if(QWidget *sibling = qobject_cast<QWidget *>(w->d_func()->children.at(i))) {
1919                 if(sibling->isVisible() && !sibling->isWindow()) {
1920                     QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
1921                                       sibling->width(), sibling->height());
1922                     if (qRectIntersects(siblingRect, q->rect()))
1923                         r -= QRegion(siblingRect);
1924                 }
1925             }
1926         }
1927     }
1928     return r;
1929 }
1930 
setSystemClip(QPaintEngine * paintEngine,qreal devicePixelRatio,const QRegion & region)1931 void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
1932 {
1933 // Transform the system clip region from device-independent pixels to device pixels
1934     QTransform scaleTransform;
1935     scaleTransform.scale(devicePixelRatio, devicePixelRatio);
1936 
1937     paintEngine->d_func()->baseSystemClip = region;
1938     paintEngine->d_func()->setSystemTransform(scaleTransform);
1939 
1940 }
1941 
1942 #if QT_CONFIG(graphicseffect)
invalidateGraphicsEffectsRecursively()1943 void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
1944 {
1945     Q_Q(QWidget);
1946     QWidget *w = q;
1947     do {
1948         if (w->graphicsEffect()) {
1949             QWidgetEffectSourcePrivate *sourced =
1950                 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
1951             if (!sourced->updateDueToGraphicsEffect)
1952                 w->graphicsEffect()->source()->d_func()->invalidateCache();
1953         }
1954         w = w->parentWidget();
1955     } while (w);
1956 }
1957 #endif // QT_CONFIG(graphicseffect)
1958 
setDirtyOpaqueRegion()1959 void QWidgetPrivate::setDirtyOpaqueRegion()
1960 {
1961     Q_Q(QWidget);
1962 
1963     dirtyOpaqueChildren = true;
1964 
1965 #if QT_CONFIG(graphicseffect)
1966     invalidateGraphicsEffectsRecursively();
1967 #endif // QT_CONFIG(graphicseffect)
1968 
1969     if (q->isWindow())
1970         return;
1971 
1972     QWidget *parent = q->parentWidget();
1973     if (!parent)
1974         return;
1975 
1976     // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
1977     QWidgetPrivate *pd = parent->d_func();
1978     if (!pd->dirtyOpaqueChildren)
1979         pd->setDirtyOpaqueRegion();
1980 }
1981 
getOpaqueChildren() const1982 const QRegion &QWidgetPrivate::getOpaqueChildren() const
1983 {
1984     if (!dirtyOpaqueChildren)
1985         return opaqueChildren;
1986 
1987     QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
1988     that->opaqueChildren = QRegion();
1989 
1990     for (int i = 0; i < children.size(); ++i) {
1991         QWidget *child = qobject_cast<QWidget *>(children.at(i));
1992         if (!child || !child->isVisible() || child->isWindow())
1993             continue;
1994 
1995         const QPoint offset = child->geometry().topLeft();
1996         QWidgetPrivate *childd = child->d_func();
1997         QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
1998         if (childd->extra && childd->extra->hasMask)
1999             r &= childd->extra->mask;
2000         if (r.isEmpty())
2001             continue;
2002         r.translate(offset);
2003         that->opaqueChildren += r;
2004     }
2005 
2006     that->opaqueChildren &= q_func()->rect();
2007     that->dirtyOpaqueChildren = false;
2008 
2009     return that->opaqueChildren;
2010 }
2011 
subtractOpaqueChildren(QRegion & source,const QRect & clipRect) const2012 void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2013 {
2014     if (children.isEmpty() || clipRect.isEmpty())
2015         return;
2016 
2017     const QRegion &r = getOpaqueChildren();
2018     if (!r.isEmpty())
2019         source -= (r & clipRect);
2020 }
2021 
2022 //subtract any relatives that are higher up than me --- this is too expensive !!!
subtractOpaqueSiblings(QRegion & sourceRegion,bool * hasDirtySiblingsAbove,bool alsoNonOpaque) const2023 void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2024                                             bool alsoNonOpaque) const
2025 {
2026     Q_Q(const QWidget);
2027     static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue("QT_NO_SUBTRACTOPAQUESIBLINGS");
2028     if (disableSubtractOpaqueSiblings || q->isWindow())
2029         return;
2030 
2031     QRect clipBoundingRect;
2032     bool dirtyClipBoundingRect = true;
2033 
2034     QRegion parentClip;
2035     bool dirtyParentClip = true;
2036 
2037     QPoint parentOffset = data.crect.topLeft();
2038 
2039     const QWidget *w = q;
2040 
2041     while (w) {
2042         if (w->isWindow())
2043             break;
2044         QWidgetPrivate *pd = w->parentWidget()->d_func();
2045         const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w));
2046         const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect);
2047         for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2048             QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
2049             if (!sibling || !sibling->isVisible() || sibling->isWindow())
2050                 continue;
2051 
2052             const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect);
2053             if (!qRectIntersects(siblingGeometry, widgetGeometry))
2054                 continue;
2055 
2056             if (dirtyClipBoundingRect) {
2057                 clipBoundingRect = sourceRegion.boundingRect();
2058                 dirtyClipBoundingRect = false;
2059             }
2060 
2061             if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset)))
2062                 continue;
2063 
2064             if (dirtyParentClip) {
2065                 parentClip = sourceRegion.translated(parentOffset);
2066                 dirtyParentClip = false;
2067             }
2068 
2069             const QPoint siblingPos(sibling->data->crect.topLeft());
2070             const QRect siblingClipRect(sibling->d_func()->clipRect());
2071             QRegion siblingDirty(parentClip);
2072             siblingDirty &= (siblingClipRect.translated(siblingPos));
2073             const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2074                                  && !sibling->d_func()->graphicsEffect;
2075             if (hasMask)
2076                 siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos);
2077             if (siblingDirty.isEmpty())
2078                 continue;
2079 
2080             if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2081                 if (hasMask) {
2082                     siblingDirty.translate(-parentOffset);
2083                     sourceRegion -= siblingDirty;
2084                 } else {
2085                     sourceRegion -= siblingGeometry.translated(-parentOffset);
2086                 }
2087             } else {
2088                 if (hasDirtySiblingsAbove)
2089                     *hasDirtySiblingsAbove = true;
2090                 if (sibling->d_func()->children.isEmpty())
2091                     continue;
2092                 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2093                 opaqueSiblingChildren.translate(-parentOffset + siblingPos);
2094                 sourceRegion -= opaqueSiblingChildren;
2095             }
2096             if (sourceRegion.isEmpty())
2097                 return;
2098 
2099             dirtyClipBoundingRect = true;
2100             dirtyParentClip = true;
2101         }
2102 
2103         w = w->parentWidget();
2104         parentOffset += pd->data.crect.topLeft();
2105         dirtyParentClip = true;
2106     }
2107 }
2108 
clipToEffectiveMask(QRegion & region) const2109 void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2110 {
2111     Q_Q(const QWidget);
2112 
2113     const QWidget *w = q;
2114     QPoint offset;
2115 
2116 #if QT_CONFIG(graphicseffect)
2117     if (graphicsEffect) {
2118         w = q->parentWidget();
2119         offset -= data.crect.topLeft();
2120     }
2121 #endif // QT_CONFIG(graphicseffect)
2122 
2123     while (w) {
2124         const QWidgetPrivate *wd = w->d_func();
2125         if (wd->extra && wd->extra->hasMask)
2126             region &= (w != q) ? wd->extra->mask.translated(offset) : wd->extra->mask;
2127         if (w->isWindow())
2128             return;
2129         offset -= wd->data.crect.topLeft();
2130         w = w->parentWidget();
2131     }
2132 }
2133 
shouldPaintOnScreen() const2134 bool QWidgetPrivate::shouldPaintOnScreen() const
2135 {
2136 #if defined(QT_NO_BACKINGSTORE)
2137     return true;
2138 #else
2139     Q_Q(const QWidget);
2140     if (q->testAttribute(Qt::WA_PaintOnScreen)
2141             || (!q->isWindow() && q->window()->testAttribute(Qt::WA_PaintOnScreen))) {
2142         return true;
2143     }
2144 
2145     return false;
2146 #endif
2147 }
2148 
updateIsOpaque()2149 void QWidgetPrivate::updateIsOpaque()
2150 {
2151     // hw: todo: only needed if opacity actually changed
2152     setDirtyOpaqueRegion();
2153 
2154 #if QT_CONFIG(graphicseffect)
2155     if (graphicsEffect) {
2156         // ### We should probably add QGraphicsEffect::isOpaque at some point.
2157         setOpaque(false);
2158         return;
2159     }
2160 #endif // QT_CONFIG(graphicseffect)
2161 
2162     Q_Q(QWidget);
2163     if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) {
2164         setOpaque(true);
2165         return;
2166     }
2167 
2168     const QPalette &pal = q->palette();
2169 
2170     if (q->autoFillBackground()) {
2171         const QBrush &autoFillBrush = pal.brush(q->backgroundRole());
2172         if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2173             setOpaque(true);
2174             return;
2175         }
2176     }
2177 
2178     if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) {
2179         const QBrush &windowBrush = q->palette().brush(QPalette::Window);
2180         if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2181             setOpaque(true);
2182             return;
2183         }
2184     }
2185     setOpaque(false);
2186 }
2187 
setOpaque(bool opaque)2188 void QWidgetPrivate::setOpaque(bool opaque)
2189 {
2190     if (isOpaque != opaque) {
2191         isOpaque = opaque;
2192         updateIsTranslucent();
2193     }
2194 }
2195 
updateIsTranslucent()2196 void QWidgetPrivate::updateIsTranslucent()
2197 {
2198     Q_Q(QWidget);
2199     if (QWindow *window = q->windowHandle()) {
2200         QSurfaceFormat format = window->format();
2201         const int oldAlpha = format.alphaBufferSize();
2202         const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground)? 8 : 0;
2203         if (oldAlpha != newAlpha) {
2204             format.setAlphaBufferSize(newAlpha);
2205             window->setFormat(format);
2206         }
2207     }
2208 }
2209 
fillRegion(QPainter * painter,const QRegion & rgn,const QBrush & brush)2210 static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2211 {
2212     Q_ASSERT(painter);
2213 
2214     if (brush.style() == Qt::TexturePattern) {
2215         const QRect rect(rgn.boundingRect());
2216         painter->setClipRegion(rgn);
2217         painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
2218     } else if (brush.gradient()
2219                && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode
2220                    || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) {
2221         painter->save();
2222         painter->setClipRegion(rgn);
2223         painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush);
2224         painter->restore();
2225     } else {
2226         for (const QRect &rect : rgn)
2227             painter->fillRect(rect, brush);
2228     }
2229 }
2230 
updateBrushOrigin(QPainter * painter,const QBrush & brush) const2231 bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
2232 {
2233 #if QT_CONFIG(scrollarea)
2234     Q_Q(const QWidget);
2235     //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2236     if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
2237         return false;
2238     QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
2239     if (scrollArea && scrollArea->viewport() == q) {
2240         QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2241         QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2242         painter->setBrushOrigin(-priv->contentsOffset());
2243     }
2244 #endif // QT_CONFIG(scrollarea)
2245     return true;
2246 }
2247 
paintBackground(QPainter * painter,const QRegion & rgn,DrawWidgetFlags flags) const2248 void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, DrawWidgetFlags flags) const
2249 {
2250     Q_Q(const QWidget);
2251 
2252     bool brushOriginSet = false;
2253     const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
2254 
2255     if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2256         const QBrush bg = q->palette().brush(QPalette::Window);
2257         if (!brushOriginSet)
2258             brushOriginSet = updateBrushOrigin(painter, bg);
2259         if (!(flags & DontSetCompositionMode)) {
2260             //copy alpha straight in
2261             QPainter::CompositionMode oldMode = painter->compositionMode();
2262             painter->setCompositionMode(QPainter::CompositionMode_Source);
2263             fillRegion(painter, rgn, bg);
2264             painter->setCompositionMode(oldMode);
2265         } else {
2266             fillRegion(painter, rgn, bg);
2267         }
2268     }
2269 
2270     if (q->autoFillBackground()) {
2271         if (!brushOriginSet)
2272             brushOriginSet = updateBrushOrigin(painter, autoFillBrush);
2273         fillRegion(painter, rgn, autoFillBrush);
2274     }
2275 
2276     if (q->testAttribute(Qt::WA_StyledBackground)) {
2277         painter->setClipRegion(rgn);
2278         QStyleOption opt;
2279         opt.initFrom(q);
2280         q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
2281     }
2282 }
2283 
2284 /*
2285   \internal
2286   This function is called when a widget is hidden or destroyed.
2287   It resets some application global pointers that should only refer active,
2288   visible widgets.
2289 */
2290 
2291 extern QWidget *qt_button_down;
2292 
deactivateWidgetCleanup()2293 void QWidgetPrivate::deactivateWidgetCleanup()
2294 {
2295     Q_Q(QWidget);
2296     // If this was the active application window, reset it
2297     if (QApplication::activeWindow() == q)
2298         QApplication::setActiveWindow(nullptr);
2299     // If the is the active mouse press widget, reset it
2300     if (q == qt_button_down)
2301         qt_button_down = nullptr;
2302 }
2303 
2304 
2305 /*!
2306     Returns a pointer to the widget with window identifer/handle \a
2307     id.
2308 
2309     The window identifier type depends on the underlying window
2310     system, see \c qwindowdefs.h for the actual definition. If there
2311     is no widget with this identifier, \nullptr is returned.
2312 */
2313 
find(WId id)2314 QWidget *QWidget::find(WId id)
2315 {
2316     return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : nullptr;
2317 }
2318 
2319 
2320 
2321 /*!
2322     \fn WId QWidget::internalWinId() const
2323     \internal
2324     Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2325 
2326 */
2327 
2328 /*!
2329     \fn WId QWidget::winId() const
2330 
2331     Returns the window system identifier of the widget.
2332 
2333     Portable in principle, but if you use it you are probably about to
2334     do something non-portable. Be careful.
2335 
2336     If a widget is non-native (alien) and winId() is invoked on it, that widget
2337     will be provided a native handle.
2338 
2339     This value may change at run-time. An event with type QEvent::WinIdChange
2340     will be sent to the widget following a change in window system identifier.
2341 
2342     \sa find()
2343 */
winId() const2344 WId QWidget::winId() const
2345 {
2346     if (!data->in_destructor
2347         && (!testAttribute(Qt::WA_WState_Created) || !internalWinId()))
2348     {
2349 #ifdef ALIEN_DEBUG
2350         qDebug() << "QWidget::winId: creating native window for" << this;
2351 #endif
2352         QWidget *that = const_cast<QWidget*>(this);
2353         that->setAttribute(Qt::WA_NativeWindow);
2354         that->d_func()->createWinId();
2355         return that->data->winid;
2356     }
2357     return data->winid;
2358 }
2359 
createWinId()2360 void QWidgetPrivate::createWinId()
2361 {
2362     Q_Q(QWidget);
2363 
2364 #ifdef ALIEN_DEBUG
2365     qDebug() << "QWidgetPrivate::createWinId for" << q;
2366 #endif
2367     const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
2368     if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2369         if (!q->isWindow()) {
2370             QWidget *parent = q->parentWidget();
2371             QWidgetPrivate *pd = parent->d_func();
2372             if (forceNativeWindow && !q->testAttribute(Qt::WA_DontCreateNativeAncestors))
2373                 parent->setAttribute(Qt::WA_NativeWindow);
2374             if (!parent->internalWinId()) {
2375                 pd->createWinId();
2376             }
2377 
2378             for (int i = 0; i < pd->children.size(); ++i) {
2379                 QWidget *w = qobject_cast<QWidget *>(pd->children.at(i));
2380                 if (w && !w->isWindow() && (!w->testAttribute(Qt::WA_WState_Created)
2381                                             || (!w->internalWinId() && w->testAttribute(Qt::WA_NativeWindow)))) {
2382                     w->create();
2383                 }
2384             }
2385         } else {
2386             q->create();
2387         }
2388     }
2389 }
2390 
2391 /*!
2392 \internal
2393 Ensures that the widget is set on the screen point is on. This is handy getting a correct
2394 size hint before a resize in e.g QMenu and QToolTip.
2395 Returns if the screen was changed.
2396 */
2397 
setScreenForPoint(const QPoint & pos)2398 bool QWidgetPrivate::setScreenForPoint(const QPoint &pos)
2399 {
2400     Q_Q(QWidget);
2401     if (!q->isWindow())
2402         return false;
2403     // Find the screen for pos and make the widget understand it is on that screen.
2404     return setScreen(QGuiApplication::screenAt(pos));
2405 }
2406 
2407 /*!
2408 \internal
2409 Ensures that the widget's QWindow is set to be on the given \a screen.
2410 Returns true if the screen was changed.
2411 */
2412 
setScreen(QScreen * screen)2413 bool QWidgetPrivate::setScreen(QScreen *screen)
2414 {
2415     Q_Q(QWidget);
2416     if (!screen || !q->isWindow())
2417         return false;
2418     const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
2419     if (currentScreen != screen) {
2420         if (!windowHandle()) // Try to create a window handle if not created.
2421             createWinId();
2422         if (windowHandle())
2423             windowHandle()->setScreen(screen);
2424         return true;
2425     }
2426     return false;
2427 }
2428 
2429 /*!
2430 \internal
2431 Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2432 
2433 */
2434 
createWinId()2435 void QWidget::createWinId()
2436 {
2437     Q_D(QWidget);
2438 #ifdef ALIEN_DEBUG
2439     qDebug()  << "QWidget::createWinId" << this;
2440 #endif
2441 //    qWarning("QWidget::createWinId is obsolete, please fix your code.");
2442     d->createWinId();
2443 }
2444 
2445 /*!
2446     \since 4.4
2447 
2448     Returns the effective window system identifier of the widget, i.e. the
2449     native parent's window system identifier.
2450 
2451     If the widget is native, this function returns the native widget ID.
2452     Otherwise, the window ID of the first native parent widget, i.e., the
2453     top-level widget that contains this widget, is returned.
2454 
2455     \note We recommend that you do not store this value as it is likely to
2456     change at run-time.
2457 
2458     \sa nativeParentWidget()
2459 */
effectiveWinId() const2460 WId QWidget::effectiveWinId() const
2461 {
2462     const WId id = internalWinId();
2463     if (id || !testAttribute(Qt::WA_WState_Created))
2464         return id;
2465     if (const QWidget *realParent = nativeParentWidget())
2466         return realParent->internalWinId();
2467     return 0;
2468 }
2469 
2470 /*!
2471     If this is a native widget, return the associated QWindow.
2472     Otherwise return null.
2473 
2474     Native widgets include toplevel widgets, QGLWidget, and child widgets
2475     on which winId() was called.
2476 
2477     \since 5.0
2478 
2479     \sa winId(), screen()
2480 */
windowHandle() const2481 QWindow *QWidget::windowHandle() const
2482 {
2483     Q_D(const QWidget);
2484     return d->windowHandle();
2485 }
2486 
2487 /*!
2488     Returns the screen the widget is on.
2489 
2490     \since 5.14
2491 
2492     \sa windowHandle()
2493 */
screen() const2494 QScreen *QWidget::screen() const
2495 {
2496     Q_D(const QWidget);
2497     if (auto associatedScreen = d->associatedScreen())
2498         return associatedScreen;
2499     if (auto topLevel = window()) {
2500         if (auto topData = qt_widget_private(topLevel)->topData()) {
2501             if (auto initialScreen = QGuiApplicationPrivate::screen_list.value(topData->initialScreenIndex))
2502                 return initialScreen;
2503         }
2504         if (auto screenByPos = QGuiApplication::screenAt(topLevel->geometry().center()))
2505             return screenByPos;
2506     }
2507     return QGuiApplication::primaryScreen();
2508 }
2509 
2510 #ifndef QT_NO_STYLE_STYLESHEET
2511 
2512 /*!
2513     \property QWidget::styleSheet
2514     \brief the widget's style sheet
2515     \since 4.2
2516 
2517     The style sheet contains a textual description of customizations to the
2518     widget's style, as described in the \l{Qt Style Sheets} document.
2519 
2520     Since Qt 4.5, Qt style sheets fully supports \macos.
2521 
2522     \warning Qt style sheets are currently not supported for custom QStyle
2523     subclasses. We plan to address this in some future release.
2524 
2525     \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2526 */
styleSheet() const2527 QString QWidget::styleSheet() const
2528 {
2529     Q_D(const QWidget);
2530     if (!d->extra)
2531         return QString();
2532     return d->extra->styleSheet;
2533 }
2534 
setStyleSheet(const QString & styleSheet)2535 void QWidget::setStyleSheet(const QString& styleSheet)
2536 {
2537     Q_D(QWidget);
2538     if (data->in_destructor)
2539         return;
2540     d->createExtra();
2541 
2542     QStyleSheetStyle *proxy = qt_styleSheet(d->extra->style);
2543     d->extra->styleSheet = styleSheet;
2544     if (styleSheet.isEmpty()) { // stylesheet removed
2545         if (!proxy)
2546             return;
2547 
2548         d->inheritStyle();
2549         return;
2550     }
2551 
2552     if (proxy) { // style sheet update
2553         if (d->polished)
2554             proxy->repolish(this);
2555         return;
2556     }
2557 
2558     if (testAttribute(Qt::WA_SetStyle)) {
2559         d->setStyle_helper(new QStyleSheetStyle(d->extra->style), true);
2560     } else {
2561         d->setStyle_helper(new QStyleSheetStyle(nullptr), true);
2562     }
2563 }
2564 
2565 #endif // QT_NO_STYLE_STYLESHEET
2566 
2567 /*!
2568     \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2569 */
2570 
style() const2571 QStyle *QWidget::style() const
2572 {
2573     Q_D(const QWidget);
2574 
2575     if (d->extra && d->extra->style)
2576         return d->extra->style;
2577     return QApplication::style();
2578 }
2579 
2580 /*!
2581     Sets the widget's GUI style to \a style. The ownership of the style
2582     object is not transferred.
2583 
2584     If no style is set, the widget uses the application's style,
2585     QApplication::style() instead.
2586 
2587     Setting a widget's style has no effect on existing or future child
2588     widgets.
2589 
2590     \warning This function is particularly useful for demonstration
2591     purposes, where you want to show Qt's styling capabilities. Real
2592     applications should avoid it and use one consistent GUI style
2593     instead.
2594 
2595     \warning Qt style sheets are currently not supported for custom QStyle
2596     subclasses. We plan to address this in some future release.
2597 
2598     \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2599 */
2600 
setStyle(QStyle * style)2601 void QWidget::setStyle(QStyle *style)
2602 {
2603     Q_D(QWidget);
2604     setAttribute(Qt::WA_SetStyle, style != nullptr);
2605     d->createExtra();
2606 #ifndef QT_NO_STYLE_STYLESHEET
2607     if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2608         //if for some reason someone try to set a QStyleSheetStyle, ref it
2609         //(this may happen for exemple in QButtonDialogBox which propagates its style)
2610         styleSheetStyle->ref();
2611         d->setStyle_helper(style, false);
2612     } else if (qt_styleSheet(d->extra->style) || !qApp->styleSheet().isEmpty()) {
2613         // if we have an application stylesheet or have a proxy already, propagate
2614         d->setStyle_helper(new QStyleSheetStyle(style), true);
2615     } else
2616 #endif
2617         d->setStyle_helper(style, false);
2618 }
2619 
setStyle_helper(QStyle * newStyle,bool propagate)2620 void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2621 {
2622     Q_Q(QWidget);
2623     QStyle *oldStyle = q->style();
2624 
2625     createExtra();
2626 
2627 #ifndef QT_NO_STYLE_STYLESHEET
2628     QPointer<QStyle> origStyle = extra->style;
2629 #endif
2630     extra->style = newStyle;
2631 
2632     // repolish
2633     if (polished && q->windowType() != Qt::Desktop) {
2634         oldStyle->unpolish(q);
2635         q->style()->polish(q);
2636     }
2637 
2638     if (propagate) {
2639         // We copy the list because the order may be modified
2640         const QObjectList childrenList = children;
2641         for (int i = 0; i < childrenList.size(); ++i) {
2642             QWidget *c = qobject_cast<QWidget*>(childrenList.at(i));
2643             if (c)
2644                 c->d_func()->inheritStyle();
2645         }
2646     }
2647 
2648 #ifndef QT_NO_STYLE_STYLESHEET
2649     if (!qt_styleSheet(newStyle)) {
2650         if (const QStyleSheetStyle* cssStyle = qt_styleSheet(origStyle)) {
2651             cssStyle->clearWidgetFont(q);
2652         }
2653     }
2654 #endif
2655 
2656     QEvent e(QEvent::StyleChange);
2657     QCoreApplication::sendEvent(q, &e);
2658 
2659 #ifndef QT_NO_STYLE_STYLESHEET
2660     // dereference the old stylesheet style
2661     if (QStyleSheetStyle *proxy = qt_styleSheet(origStyle))
2662         proxy->deref();
2663 #endif
2664 }
2665 
2666 // Inherits style from the current parent and propagates it as necessary
inheritStyle()2667 void QWidgetPrivate::inheritStyle()
2668 {
2669 #ifndef QT_NO_STYLE_STYLESHEET
2670     Q_Q(QWidget);
2671 
2672     QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2673 
2674     QStyleSheetStyle *proxy = qt_styleSheet(extraStyle);
2675 
2676     if (!q->styleSheet().isEmpty()) {
2677         Q_ASSERT(proxy);
2678         proxy->repolish(q);
2679         return;
2680     }
2681 
2682     QStyle *origStyle = proxy ? proxy->base : extraStyle;
2683     QWidget *parent = q->parentWidget();
2684     QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : nullptr;
2685     // If we have stylesheet on app or parent has stylesheet style, we need
2686     // to be running a proxy
2687     if (!qApp->styleSheet().isEmpty() || qt_styleSheet(parentStyle)) {
2688         QStyle *newStyle = parentStyle;
2689         if (q->testAttribute(Qt::WA_SetStyle))
2690             newStyle = new QStyleSheetStyle(origStyle);
2691         else if (QStyleSheetStyle *newProxy = qt_styleSheet(parentStyle))
2692             newProxy->ref();
2693 
2694         setStyle_helper(newStyle, true);
2695         return;
2696     }
2697 
2698     // So, we have no stylesheet on parent/app and we have an empty stylesheet
2699     // we just need our original style back
2700     if (origStyle == extraStyle) // is it any different?
2701         return;
2702 
2703     // We could have inherited the proxy from our parent (which has a custom style)
2704     // In such a case we need to start following the application style (i.e revert
2705     // the propagation behavior of QStyleSheetStyle)
2706     if (!q->testAttribute(Qt::WA_SetStyle))
2707         origStyle = nullptr;
2708 
2709     setStyle_helper(origStyle, true);
2710 #endif // QT_NO_STYLE_STYLESHEET
2711 }
2712 
2713 
2714 /*!
2715     \fn bool QWidget::isWindow() const
2716 
2717     Returns \c true if the widget is an independent window, otherwise
2718     returns \c false.
2719 
2720     A window is a widget that isn't visually the child of any other
2721     widget and that usually has a frame and a
2722     \l{QWidget::setWindowTitle()}{window title}.
2723 
2724     A window can have a \l{QWidget::parentWidget()}{parent widget}.
2725     It will then be grouped with its parent and deleted when the
2726     parent is deleted, minimized when the parent is minimized etc. If
2727     supported by the window manager, it will also have a common
2728     taskbar entry with its parent.
2729 
2730     QDialog and QMainWindow widgets are by default windows, even if a
2731     parent widget is specified in the constructor. This behavior is
2732     specified by the Qt::Window flag.
2733 
2734     \sa window(), isModal(), parentWidget()
2735 */
2736 
2737 /*!
2738     \property QWidget::modal
2739     \brief whether the widget is a modal widget
2740 
2741     This property only makes sense for windows. A modal widget
2742     prevents widgets in all other windows from getting any input.
2743 
2744     By default, this property is \c false.
2745 
2746     \sa isWindow(), windowModality, QDialog
2747 */
2748 
2749 /*!
2750     \property QWidget::windowModality
2751     \brief which windows are blocked by the modal widget
2752     \since 4.1
2753 
2754     This property only makes sense for windows. A modal widget
2755     prevents widgets in other windows from getting input. The value of
2756     this property controls which windows are blocked when the widget
2757     is visible. Changing this property while the window is visible has
2758     no effect; you must hide() the widget first, then show() it again.
2759 
2760     By default, this property is Qt::NonModal.
2761 
2762     \sa isWindow(), QWidget::modal, QDialog
2763 */
2764 
windowModality() const2765 Qt::WindowModality QWidget::windowModality() const
2766 {
2767     return static_cast<Qt::WindowModality>(data->window_modality);
2768 }
2769 
setWindowModality(Qt::WindowModality windowModality)2770 void QWidget::setWindowModality(Qt::WindowModality windowModality)
2771 {
2772     data->window_modality = windowModality;
2773     // setModal_sys() will be called by setAttribute()
2774     setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
2775     setAttribute(Qt::WA_SetWindowModality, true);
2776 }
2777 
setModal_sys()2778 void QWidgetPrivate::setModal_sys()
2779 {
2780     Q_Q(QWidget);
2781     if (q->windowHandle())
2782         q->windowHandle()->setModality(q->windowModality());
2783 }
2784 
2785 /*!
2786     \fn bool QWidget::underMouse() const
2787 
2788     Returns \c true if the widget is under the mouse cursor; otherwise
2789     returns \c false.
2790 
2791     This value is not updated properly during drag and drop
2792     operations.
2793 
2794     \sa enterEvent(), leaveEvent()
2795 */
2796 
2797 /*!
2798     \property QWidget::minimized
2799     \brief whether this widget is minimized (iconified)
2800 
2801     This property is only relevant for windows.
2802 
2803     By default, this property is \c false.
2804 
2805     \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2806 */
isMinimized() const2807 bool QWidget::isMinimized() const
2808 { return data->window_state & Qt::WindowMinimized; }
2809 
2810 /*!
2811     Shows the widget minimized, as an icon.
2812 
2813     Calling this function only affects \l{isWindow()}{windows}.
2814 
2815     \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2816         isMinimized()
2817 */
showMinimized()2818 void QWidget::showMinimized()
2819 {
2820     bool isMin = isMinimized();
2821     if (isMin && isVisible())
2822         return;
2823 
2824     ensurePolished();
2825 
2826     if (!isMin)
2827         setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2828     setVisible(true);
2829 }
2830 
2831 /*!
2832     \property QWidget::maximized
2833     \brief whether this widget is maximized
2834 
2835     This property is only relevant for windows.
2836 
2837     \note Due to limitations on some window systems, this does not always
2838     report the expected results (e.g., if the user on X11 maximizes the
2839     window via the window manager, Qt has no way of distinguishing this
2840     from any other resize). This is expected to improve as window manager
2841     protocols evolve.
2842 
2843     By default, this property is \c false.
2844 
2845     \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2846 */
isMaximized() const2847 bool QWidget::isMaximized() const
2848 { return data->window_state & Qt::WindowMaximized; }
2849 
2850 
2851 
2852 /*!
2853     Returns the current window state. The window state is a OR'ed
2854     combination of Qt::WindowState: Qt::WindowMinimized,
2855     Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2856 
2857   \sa Qt::WindowState, setWindowState()
2858  */
windowState() const2859 Qt::WindowStates QWidget::windowState() const
2860 {
2861     return Qt::WindowStates(data->window_state);
2862 }
2863 
2864 /*!\internal
2865 
2866    The function sets the window state on child widgets similar to
2867    setWindowState(). The difference is that the window state changed
2868    event has the isOverride() flag set. It exists mainly to keep
2869    QWorkspace working.
2870  */
overrideWindowState(Qt::WindowStates newstate)2871 void QWidget::overrideWindowState(Qt::WindowStates newstate)
2872 {
2873     QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
2874     data->window_state  = newstate;
2875     QCoreApplication::sendEvent(this, &e);
2876 }
2877 
2878 /*!
2879     \fn void QWidget::setWindowState(Qt::WindowStates windowState)
2880 
2881     Sets the window state to \a windowState. The window state is a OR'ed
2882     combination of Qt::WindowState: Qt::WindowMinimized,
2883     Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2884 
2885     If the window is not visible (i.e. isVisible() returns \c false), the
2886     window state will take effect when show() is called. For visible
2887     windows, the change is immediate. For example, to toggle between
2888     full-screen and normal mode, use the following code:
2889 
2890     \snippet code/src_gui_kernel_qwidget.cpp 0
2891 
2892     In order to restore and activate a minimized window (while
2893     preserving its maximized and/or full-screen state), use the following:
2894 
2895     \snippet code/src_gui_kernel_qwidget.cpp 1
2896 
2897     Calling this function will hide the widget. You must call show() to make
2898     the widget visible again.
2899 
2900     \note On some window systems Qt::WindowActive is not immediate, and may be
2901     ignored in certain cases.
2902 
2903     When the window state changes, the widget receives a changeEvent()
2904     of type QEvent::WindowStateChange.
2905 
2906     \sa Qt::WindowState, windowState()
2907 */
setWindowState(Qt::WindowStates newstate)2908 void QWidget::setWindowState(Qt::WindowStates newstate)
2909 {
2910     Q_D(QWidget);
2911     Qt::WindowStates oldstate = windowState();
2912     if (newstate.testFlag(Qt::WindowMinimized)) // QTBUG-46763
2913        newstate.setFlag(Qt::WindowActive, false);
2914     if (oldstate == newstate)
2915         return;
2916     if (isWindow() && !testAttribute(Qt::WA_WState_Created))
2917         create();
2918 
2919     data->window_state = newstate;
2920     data->in_set_window_state = 1;
2921     if (isWindow()) {
2922         // Ensure the initial size is valid, since we store it as normalGeometry below.
2923         if (!testAttribute(Qt::WA_Resized) && !isVisible())
2924             adjustSize();
2925 
2926         d->createTLExtra();
2927         if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
2928             d->topData()->normalGeometry = geometry();
2929 
2930         Q_ASSERT(windowHandle());
2931         windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
2932     }
2933     data->in_set_window_state = 0;
2934 
2935     if (newstate & Qt::WindowActive)
2936         activateWindow();
2937 
2938     QWindowStateChangeEvent e(oldstate);
2939     QCoreApplication::sendEvent(this, &e);
2940 }
2941 
2942 /*!
2943     \property QWidget::fullScreen
2944     \brief whether the widget is shown in full screen mode
2945 
2946     A widget in full screen mode occupies the whole screen area and does not
2947     display window decorations, such as a title bar.
2948 
2949     By default, this property is \c false.
2950 
2951     \sa windowState(), minimized, maximized
2952 */
isFullScreen() const2953 bool QWidget::isFullScreen() const
2954 { return data->window_state & Qt::WindowFullScreen; }
2955 
2956 /*!
2957     Shows the widget in full-screen mode.
2958 
2959     Calling this function only affects \l{isWindow()}{windows}.
2960 
2961     To return from full-screen mode, call showNormal().
2962 
2963     Full-screen mode works fine under Windows, but has certain
2964     problems under X. These problems are due to limitations of the
2965     ICCCM protocol that specifies the communication between X11
2966     clients and the window manager. ICCCM simply does not understand
2967     the concept of non-decorated full-screen windows. Therefore, the
2968     best we can do is to request a borderless window and place and
2969     resize it to fill the entire screen. Depending on the window
2970     manager, this may or may not work. The borderless window is
2971     requested using MOTIF hints, which are at least partially
2972     supported by virtually all modern window managers.
2973 
2974     An alternative would be to bypass the window manager entirely and
2975     create a window with the Qt::X11BypassWindowManagerHint flag. This
2976     has other severe problems though, like totally broken keyboard focus
2977     and very strange effects on desktop changes or when the user raises
2978     other windows.
2979 
2980     X11 window managers that follow modern post-ICCCM specifications
2981     support full-screen mode properly.
2982 
2983     \sa showNormal(), showMaximized(), show(), hide(), isVisible()
2984 */
showFullScreen()2985 void QWidget::showFullScreen()
2986 {
2987     ensurePolished();
2988 
2989     setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
2990                    | Qt::WindowFullScreen);
2991     setVisible(true);
2992 #if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
2993                       // activating it here before libscreen activates it causes problems
2994     activateWindow();
2995 #endif
2996 }
2997 
2998 /*!
2999     Shows the widget maximized.
3000 
3001     Calling this function only affects \l{isWindow()}{windows}.
3002 
3003     On X11, this function may not work properly with certain window
3004     managers. See the \l{Window Geometry} documentation for an explanation.
3005 
3006     \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3007 */
showMaximized()3008 void QWidget::showMaximized()
3009 {
3010     ensurePolished();
3011 
3012     setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3013                    | Qt::WindowMaximized);
3014     setVisible(true);
3015 }
3016 
3017 /*!
3018     Restores the widget after it has been maximized or minimized.
3019 
3020     Calling this function only affects \l{isWindow()}{windows}.
3021 
3022     \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3023 */
showNormal()3024 void QWidget::showNormal()
3025 {
3026     ensurePolished();
3027 
3028     setWindowState(windowState() & ~(Qt::WindowMinimized
3029                                      | Qt::WindowMaximized
3030                                      | Qt::WindowFullScreen));
3031     setVisible(true);
3032 }
3033 
3034 /*!
3035     Returns \c true if this widget would become enabled if \a ancestor is
3036     enabled; otherwise returns \c false.
3037 
3038 
3039 
3040     This is the case if neither the widget itself nor every parent up
3041     to but excluding \a ancestor has been explicitly disabled.
3042 
3043     isEnabledTo(0) returns false if this widget or any if its ancestors
3044     was explicitly disabled.
3045 
3046     The word ancestor here means a parent widget within the same window.
3047 
3048     Therefore isEnabledTo(0) stops at this widget's window, unlike
3049     isEnabled() which also takes parent windows into considerations.
3050 
3051     \sa setEnabled(), enabled
3052 */
3053 
isEnabledTo(const QWidget * ancestor) const3054 bool QWidget::isEnabledTo(const QWidget *ancestor) const
3055 {
3056     const QWidget * w = this;
3057     while (!w->testAttribute(Qt::WA_ForceDisabled)
3058             && !w->isWindow()
3059             && w->parentWidget()
3060             && w->parentWidget() != ancestor)
3061         w = w->parentWidget();
3062     return !w->testAttribute(Qt::WA_ForceDisabled);
3063 }
3064 
3065 #ifndef QT_NO_ACTION
3066 /*!
3067     Appends the action \a action to this widget's list of actions.
3068 
3069     All QWidgets have a list of \l{QAction}s, however they can be
3070     represented graphically in many different ways. The default use of
3071     the QAction list (as returned by actions()) is to create a context
3072     QMenu.
3073 
3074     A QWidget should only have one of each action and adding an action
3075     it already has will not cause the same action to be in the widget twice.
3076 
3077     The ownership of \a action is not transferred to this QWidget.
3078 
3079     \sa removeAction(), insertAction(), actions(), QMenu
3080 */
addAction(QAction * action)3081 void QWidget::addAction(QAction *action)
3082 {
3083     insertAction(nullptr, action);
3084 }
3085 
3086 /*!
3087     Appends the actions \a actions to this widget's list of actions.
3088 
3089     \sa removeAction(), QMenu, addAction()
3090 */
3091 #if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
addActions(const QList<QAction * > & actions)3092 void QWidget::addActions(const QList<QAction *> &actions)
3093 #else
3094 void QWidget::addActions(QList<QAction*> actions)
3095 #endif
3096 {
3097     for(int i = 0; i < actions.count(); i++)
3098         insertAction(nullptr, actions.at(i));
3099 }
3100 
3101 /*!
3102     Inserts the action \a action to this widget's list of actions,
3103     before the action \a before. It appends the action if \a before is \nullptr or
3104     \a before is not a valid action for this widget.
3105 
3106     A QWidget should only have one of each action.
3107 
3108     \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3109 */
insertAction(QAction * before,QAction * action)3110 void QWidget::insertAction(QAction *before, QAction *action)
3111 {
3112     if (Q_UNLIKELY(!action)) {
3113         qWarning("QWidget::insertAction: Attempt to insert null action");
3114         return;
3115     }
3116 
3117     Q_D(QWidget);
3118     if(d->actions.contains(action))
3119         removeAction(action);
3120 
3121     int pos = d->actions.indexOf(before);
3122     if (pos < 0) {
3123         before = nullptr;
3124         pos = d->actions.size();
3125     }
3126     d->actions.insert(pos, action);
3127 
3128     QActionPrivate *apriv = action->d_func();
3129     apriv->widgets.append(this);
3130 
3131     QActionEvent e(QEvent::ActionAdded, action, before);
3132     QCoreApplication::sendEvent(this, &e);
3133 }
3134 
3135 /*!
3136     Inserts the actions \a actions to this widget's list of actions,
3137     before the action \a before. It appends the action if \a before is \nullptr or
3138     \a before is not a valid action for this widget.
3139 
3140     A QWidget can have at most one of each action.
3141 
3142     \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3143 */
3144 #if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
insertActions(QAction * before,const QList<QAction * > & actions)3145 void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3146 #else
3147 void QWidget::insertActions(QAction *before, QList<QAction*> actions)
3148 #endif
3149 {
3150     for(int i = 0; i < actions.count(); ++i)
3151         insertAction(before, actions.at(i));
3152 }
3153 
3154 /*!
3155     Removes the action \a action from this widget's list of actions.
3156     \sa insertAction(), actions(), insertAction()
3157 */
removeAction(QAction * action)3158 void QWidget::removeAction(QAction *action)
3159 {
3160     if (!action)
3161         return;
3162 
3163     Q_D(QWidget);
3164 
3165     QActionPrivate *apriv = action->d_func();
3166     apriv->widgets.removeAll(this);
3167 
3168     if (d->actions.removeAll(action)) {
3169         QActionEvent e(QEvent::ActionRemoved, action);
3170         QCoreApplication::sendEvent(this, &e);
3171     }
3172 }
3173 
3174 /*!
3175     Returns the (possibly empty) list of this widget's actions.
3176 
3177     \sa contextMenuPolicy, insertAction(), removeAction()
3178 */
actions() const3179 QList<QAction*> QWidget::actions() const
3180 {
3181     Q_D(const QWidget);
3182     return d->actions;
3183 }
3184 #endif // QT_NO_ACTION
3185 
3186 /*!
3187   \fn bool QWidget::isEnabledToTLW() const
3188   \obsolete
3189 
3190   This function is deprecated. It is equivalent to isEnabled()
3191 */
3192 
3193 /*!
3194     \property QWidget::enabled
3195     \brief whether the widget is enabled
3196 
3197     In general an enabled widget handles keyboard and mouse events; a disabled
3198     widget does not. An exception is made with \l{QAbstractButton}.
3199 
3200     Some widgets display themselves differently when they are
3201     disabled. For example a button might draw its label grayed out. If
3202     your widget needs to know when it becomes enabled or disabled, you
3203     can use the changeEvent() with type QEvent::EnabledChange.
3204 
3205     Disabling a widget implicitly disables all its children. Enabling
3206     respectively enables all child widgets unless they have been
3207     explicitly disabled. It it not possible to explicitly enable a child
3208     widget which is not a window while its parent widget remains disabled.
3209 
3210     By default, this property is \c true.
3211 
3212     \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3213 */
setEnabled(bool enable)3214 void QWidget::setEnabled(bool enable)
3215 {
3216     Q_D(QWidget);
3217     setAttribute(Qt::WA_ForceDisabled, !enable);
3218     d->setEnabled_helper(enable);
3219 }
3220 
setEnabled_helper(bool enable)3221 void QWidgetPrivate::setEnabled_helper(bool enable)
3222 {
3223     Q_Q(QWidget);
3224 
3225     if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3226         return; // nothing we can do
3227 
3228     if (enable != q->testAttribute(Qt::WA_Disabled))
3229         return; // nothing to do
3230 
3231     q->setAttribute(Qt::WA_Disabled, !enable);
3232     updateSystemBackground();
3233 
3234     if (!enable && q->window()->focusWidget() == q) {
3235         bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3236         if (!parentIsEnabled || !q->focusNextChild())
3237             q->clearFocus();
3238     }
3239 
3240     Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3241     for (int i = 0; i < children.size(); ++i) {
3242         QWidget *w = qobject_cast<QWidget *>(children.at(i));
3243         if (w && !w->testAttribute(attribute))
3244             w->d_func()->setEnabled_helper(enable);
3245     }
3246 #ifndef QT_NO_CURSOR
3247     if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3248         // enforce the windows behavior of clearing the cursor on
3249         // disabled widgets
3250         qt_qpa_set_cursor(q, false);
3251     }
3252 #endif
3253 #ifndef QT_NO_IM
3254     if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3255         QWidget *focusWidget = effectiveFocusWidget();
3256 
3257         if (enable) {
3258             if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
3259                 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3260         } else {
3261             QGuiApplication::inputMethod()->commit();
3262             QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3263         }
3264     }
3265 #endif //QT_NO_IM
3266     QEvent e(QEvent::EnabledChange);
3267     QCoreApplication::sendEvent(q, &e);
3268 }
3269 
3270 /*!
3271     \property QWidget::acceptDrops
3272     \brief whether drop events are enabled for this widget
3273 
3274     Setting this property to true announces to the system that this
3275     widget \e may be able to accept drop events.
3276 
3277     If the widget is the desktop (windowType() == Qt::Desktop), this may
3278     fail if another application is using the desktop; you can call
3279     acceptDrops() to test if this occurs.
3280 
3281     \warning Do not modify this property in a drag and drop event handler.
3282 
3283     By default, this property is \c false.
3284 
3285     \sa {Drag and Drop}
3286 */
acceptDrops() const3287 bool QWidget::acceptDrops() const
3288 {
3289     return testAttribute(Qt::WA_AcceptDrops);
3290 }
3291 
setAcceptDrops(bool on)3292 void QWidget::setAcceptDrops(bool on)
3293 {
3294     setAttribute(Qt::WA_AcceptDrops, on);
3295 
3296 }
3297 
3298 /*!
3299     Disables widget input events if \a disable is true; otherwise
3300     enables input events.
3301 
3302     See the \l enabled documentation for more information.
3303 
3304     \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3305 */
setDisabled(bool disable)3306 void QWidget::setDisabled(bool disable)
3307 {
3308     setEnabled(!disable);
3309 }
3310 
3311 /*!
3312     \property QWidget::frameGeometry
3313     \brief geometry of the widget relative to its parent including any
3314     window frame
3315 
3316     See the \l{Window Geometry} documentation for an overview of geometry
3317     issues with windows.
3318 
3319     By default, this property contains a value that depends on the user's
3320     platform and screen geometry.
3321 
3322     \sa geometry(), x(), y(), pos()
3323 */
frameGeometry() const3324 QRect QWidget::frameGeometry() const
3325 {
3326     Q_D(const QWidget);
3327     if (isWindow() && ! (windowType() == Qt::Popup)) {
3328         QRect fs = d->frameStrut();
3329         return QRect(data->crect.x() - fs.left(),
3330                      data->crect.y() - fs.top(),
3331                      data->crect.width() + fs.left() + fs.right(),
3332                      data->crect.height() + fs.top() + fs.bottom());
3333     }
3334     return data->crect;
3335 }
3336 
3337 /*!
3338     \property QWidget::x
3339 
3340     \brief the x coordinate of the widget relative to its parent including
3341     any window frame
3342 
3343     See the \l{Window Geometry} documentation for an overview of geometry
3344     issues with windows.
3345 
3346     By default, this property has a value of 0.
3347 
3348     \sa frameGeometry, y, pos
3349 */
x() const3350 int QWidget::x() const
3351 {
3352     Q_D(const QWidget);
3353     if (isWindow() && ! (windowType() == Qt::Popup))
3354         return data->crect.x() - d->frameStrut().left();
3355     return data->crect.x();
3356 }
3357 
3358 /*!
3359     \property QWidget::y
3360     \brief the y coordinate of the widget relative to its parent and
3361     including any window frame
3362 
3363     See the \l{Window Geometry} documentation for an overview of geometry
3364     issues with windows.
3365 
3366     By default, this property has a value of 0.
3367 
3368     \sa frameGeometry, x, pos
3369 */
y() const3370 int QWidget::y() const
3371 {
3372     Q_D(const QWidget);
3373     if (isWindow() && ! (windowType() == Qt::Popup))
3374         return data->crect.y() - d->frameStrut().top();
3375     return data->crect.y();
3376 }
3377 
3378 /*!
3379     \property QWidget::pos
3380     \brief the position of the widget within its parent widget
3381 
3382     If the widget is a window, the position is that of the widget on
3383     the desktop, including its frame.
3384 
3385     When changing the position, the widget, if visible, receives a
3386     move event (moveEvent()) immediately. If the widget is not
3387     currently visible, it is guaranteed to receive an event before it
3388     is shown.
3389 
3390     By default, this property contains a position that refers to the
3391     origin.
3392 
3393     \warning Calling move() or setGeometry() inside moveEvent() can
3394     lead to infinite recursion.
3395 
3396     See the \l{Window Geometry} documentation for an overview of geometry
3397     issues with windows.
3398 
3399     \sa frameGeometry, size, x(), y()
3400 */
pos() const3401 QPoint QWidget::pos() const
3402 {
3403     Q_D(const QWidget);
3404     QPoint result = data->crect.topLeft();
3405     if (isWindow() && ! (windowType() == Qt::Popup))
3406         if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3407             result -= d->frameStrut().topLeft();
3408     return result;
3409 }
3410 
3411 /*!
3412     \property QWidget::geometry
3413     \brief the geometry of the widget relative to its parent and
3414     excluding the window frame
3415 
3416     When changing the geometry, the widget, if visible, receives a
3417     move event (moveEvent()) and/or a resize event (resizeEvent())
3418     immediately. If the widget is not currently visible, it is
3419     guaranteed to receive appropriate events before it is shown.
3420 
3421     The size component is adjusted if it lies outside the range
3422     defined by minimumSize() and maximumSize().
3423 
3424     \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3425     can lead to infinite recursion.
3426 
3427     See the \l{Window Geometry} documentation for an overview of geometry
3428     issues with windows.
3429 
3430     By default, this property contains a value that depends on the user's
3431     platform and screen geometry.
3432 
3433     \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3434         resizeEvent(), minimumSize(), maximumSize()
3435 */
3436 
3437 /*!
3438     \property QWidget::normalGeometry
3439 
3440     \brief the geometry of the widget as it will appear when shown as
3441     a normal (not maximized or full screen) top-level widget
3442 
3443     For child widgets this property always holds an empty rectangle.
3444 
3445     By default, this property contains an empty rectangle.
3446 
3447     \sa QWidget::windowState(), QWidget::geometry
3448 */
3449 
3450 /*!
3451     \property QWidget::size
3452     \brief the size of the widget excluding any window frame
3453 
3454     If the widget is visible when it is being resized, it receives a resize event
3455     (resizeEvent()) immediately. If the widget is not currently
3456     visible, it is guaranteed to receive an event before it is shown.
3457 
3458     The size is adjusted if it lies outside the range defined by
3459     minimumSize() and maximumSize().
3460 
3461     By default, this property contains a value that depends on the user's
3462     platform and screen geometry.
3463 
3464     \warning Calling resize() or setGeometry() inside resizeEvent() can
3465     lead to infinite recursion.
3466 
3467     \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3468     appear on screen. This also applies to windows.
3469 
3470     \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3471 */
3472 
3473 /*!
3474     \property QWidget::width
3475     \brief the width of the widget excluding any window frame
3476 
3477     See the \l{Window Geometry} documentation for an overview of geometry
3478     issues with windows.
3479 
3480     \note Do not use this function to find the width of a screen on
3481     a \l{QDesktopWidget}{multiple screen desktop}. Read
3482     \l{QDesktopWidget#Screen Geometry}{this note} for details.
3483 
3484     By default, this property contains a value that depends on the user's
3485     platform and screen geometry.
3486 
3487     \sa geometry, height, size
3488 */
3489 
3490 /*!
3491     \property QWidget::height
3492     \brief the height of the widget excluding any window frame
3493 
3494     See the \l{Window Geometry} documentation for an overview of geometry
3495     issues with windows.
3496 
3497     \note Do not use this function to find the height of a screen
3498     on a \l{QDesktopWidget}{multiple screen desktop}. Read
3499     \l{QDesktopWidget#Screen Geometry}{this note} for details.
3500 
3501     By default, this property contains a value that depends on the user's
3502     platform and screen geometry.
3503 
3504     \sa geometry, width, size
3505 */
3506 
3507 /*!
3508     \property QWidget::rect
3509     \brief the internal geometry of the widget excluding any window
3510     frame
3511 
3512     The rect property equals QRect(0, 0, width(), height()).
3513 
3514     See the \l{Window Geometry} documentation for an overview of geometry
3515     issues with windows.
3516 
3517     By default, this property contains a value that depends on the user's
3518     platform and screen geometry.
3519 
3520     \sa size
3521 */
3522 
3523 
normalGeometry() const3524 QRect QWidget::normalGeometry() const
3525 {
3526     Q_D(const QWidget);
3527     if (!d->extra || !d->extra->topextra)
3528         return QRect();
3529 
3530     if (!isMaximized() && !isFullScreen())
3531         return geometry();
3532 
3533     return d->topData()->normalGeometry;
3534 }
3535 
3536 
3537 /*!
3538     \property QWidget::childrenRect
3539     \brief the bounding rectangle of the widget's children
3540 
3541     Hidden children are excluded.
3542 
3543     By default, for a widget with no children, this property contains a
3544     rectangle with zero width and height located at the origin.
3545 
3546     \sa childrenRegion(), geometry()
3547 */
3548 
childrenRect() const3549 QRect QWidget::childrenRect() const
3550 {
3551     Q_D(const QWidget);
3552     QRect r(0, 0, 0, 0);
3553     for (int i = 0; i < d->children.size(); ++i) {
3554         QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3555         if (w && !w->isWindow() && !w->isHidden())
3556             r |= w->geometry();
3557     }
3558     return r;
3559 }
3560 
3561 /*!
3562     \property QWidget::childrenRegion
3563     \brief the combined region occupied by the widget's children
3564 
3565     Hidden children are excluded.
3566 
3567     By default, for a widget with no children, this property contains an
3568     empty region.
3569 
3570     \sa childrenRect(), geometry(), mask()
3571 */
3572 
childrenRegion() const3573 QRegion QWidget::childrenRegion() const
3574 {
3575     Q_D(const QWidget);
3576     QRegion r;
3577     for (int i = 0; i < d->children.size(); ++i) {
3578         QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3579         if (w && !w->isWindow() && !w->isHidden()) {
3580             QRegion mask = w->mask();
3581             if (mask.isEmpty())
3582                 r |= w->geometry();
3583             else
3584                 r |= mask.translated(w->pos());
3585         }
3586     }
3587     return r;
3588 }
3589 
3590 
3591 /*!
3592     \property QWidget::minimumSize
3593     \brief the widget's minimum size
3594 
3595     The widget cannot be resized to a smaller size than the minimum
3596     widget size. The widget's size is forced to the minimum size if
3597     the current size is smaller.
3598 
3599     The minimum size set by this function will override the minimum size
3600     defined by QLayout. In order to unset the minimum size, use a
3601     value of \c{QSize(0, 0)}.
3602 
3603     By default, this property contains a size with zero width and height.
3604 
3605     \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3606 */
3607 
minimumSize() const3608 QSize QWidget::minimumSize() const
3609 {
3610     Q_D(const QWidget);
3611     return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3612 }
3613 
3614 /*!
3615     \property QWidget::maximumSize
3616     \brief the widget's maximum size in pixels
3617 
3618     The widget cannot be resized to a larger size than the maximum
3619     widget size.
3620 
3621     By default, this property contains a size in which both width and height
3622     have values of 16777215.
3623 
3624     \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3625     of widgets.
3626 
3627     \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3628 */
3629 
maximumSize() const3630 QSize QWidget::maximumSize() const
3631 {
3632     Q_D(const QWidget);
3633     return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3634                  : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
3635 }
3636 
3637 
3638 /*!
3639     \property QWidget::minimumWidth
3640     \brief the widget's minimum width in pixels
3641 
3642     This property corresponds to the width held by the \l minimumSize property.
3643 
3644     By default, this property has a value of 0.
3645 
3646     \sa minimumSize, minimumHeight
3647 */
3648 
3649 /*!
3650     \property QWidget::minimumHeight
3651     \brief the widget's minimum height in pixels
3652 
3653     This property corresponds to the height held by the \l minimumSize property.
3654 
3655     By default, this property has a value of 0.
3656 
3657     \sa minimumSize, minimumWidth
3658 */
3659 
3660 /*!
3661     \property QWidget::maximumWidth
3662     \brief the widget's maximum width in pixels
3663 
3664     This property corresponds to the width held by the \l maximumSize property.
3665 
3666     By default, this property contains a value of 16777215.
3667 
3668     \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3669     of widgets.
3670 
3671     \sa maximumSize, maximumHeight
3672 */
3673 
3674 /*!
3675     \property QWidget::maximumHeight
3676     \brief the widget's maximum height in pixels
3677 
3678     This property corresponds to the height held by the \l maximumSize property.
3679 
3680     By default, this property contains a value of 16777215.
3681 
3682     \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3683     of widgets.
3684 
3685     \sa maximumSize, maximumWidth
3686 */
3687 
3688 /*!
3689     \property QWidget::sizeIncrement
3690     \brief the size increment of the widget
3691 
3692     When the user resizes the window, the size will move in steps of
3693     sizeIncrement().width() pixels horizontally and
3694     sizeIncrement.height() pixels vertically, with baseSize() as the
3695     basis. Preferred widget sizes are for non-negative integers \e i
3696     and \e j:
3697     \snippet code/src_gui_kernel_qwidget.cpp 2
3698 
3699     Note that while you can set the size increment for all widgets, it
3700     only affects windows.
3701 
3702     By default, this property contains a size with zero width and height.
3703 
3704     \warning The size increment has no effect under Windows, and may
3705     be disregarded by the window manager on X11.
3706 
3707     \sa size, minimumSize, maximumSize
3708 */
sizeIncrement() const3709 QSize QWidget::sizeIncrement() const
3710 {
3711     Q_D(const QWidget);
3712     return (d->extra && d->extra->topextra)
3713         ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3714         : QSize(0, 0);
3715 }
3716 
3717 /*!
3718     \property QWidget::baseSize
3719     \brief the base size of the widget
3720 
3721     The base size is used to calculate a proper widget size if the
3722     widget defines sizeIncrement().
3723 
3724     By default, for a newly-created widget, this property contains a size with
3725     zero width and height.
3726 
3727     \sa setSizeIncrement()
3728 */
3729 
baseSize() const3730 QSize QWidget::baseSize() const
3731 {
3732     Q_D(const QWidget);
3733     return (d->extra && d->extra->topextra)
3734         ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3735         : QSize(0, 0);
3736 }
3737 
setMinimumSize_helper(int & minw,int & minh)3738 bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3739 {
3740     Q_Q(QWidget);
3741 
3742     int mw = minw, mh = minh;
3743     if (mw == QWIDGETSIZE_MAX)
3744         mw = 0;
3745     if (mh == QWIDGETSIZE_MAX)
3746         mh = 0;
3747     if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3748         qWarning("QWidget::setMinimumSize: (%s/%s) "
3749                 "The largest allowed size is (%d,%d)",
3750                  q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3751                 QWIDGETSIZE_MAX);
3752         minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX);
3753         minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX);
3754     }
3755     if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3756         qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3757                 "are not possible",
3758                 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3759         minw = mw = qMax(minw, 0);
3760         minh = mh = qMax(minh, 0);
3761     }
3762     createExtra();
3763     if (extra->minw == mw && extra->minh == mh)
3764         return false;
3765     extra->minw = mw;
3766     extra->minh = mh;
3767     extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3768     return true;
3769 }
3770 
setConstraints_sys()3771 void QWidgetPrivate::setConstraints_sys()
3772 {
3773     Q_Q(QWidget);
3774     if (extra && q->windowHandle()) {
3775         QWindow *win = q->windowHandle();
3776         QWindowPrivate *winp = qt_window_private(win);
3777 
3778         winp->minimumSize = QSize(extra->minw, extra->minh);
3779         winp->maximumSize = QSize(extra->maxw, extra->maxh);
3780 
3781         if (extra->topextra) {
3782             winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3783             winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3784         }
3785 
3786         if (winp->platformWindow) {
3787             fixPosIncludesFrame();
3788             winp->platformWindow->propagateSizeHints();
3789         }
3790     }
3791 }
3792 
3793 /*!
3794     \overload
3795 
3796     This function corresponds to setMinimumSize(QSize(minw, minh)).
3797     Sets the minimum width to \a minw and the minimum height to \a
3798     minh.
3799 */
3800 
setMinimumSize(int minw,int minh)3801 void QWidget::setMinimumSize(int minw, int minh)
3802 {
3803     Q_D(QWidget);
3804     if (!d->setMinimumSize_helper(minw, minh))
3805         return;
3806 
3807     if (isWindow())
3808         d->setConstraints_sys();
3809     if (minw > width() || minh > height()) {
3810         bool resized = testAttribute(Qt::WA_Resized);
3811         bool maximized = isMaximized();
3812         resize(qMax(minw,width()), qMax(minh,height()));
3813         setAttribute(Qt::WA_Resized, resized); //not a user resize
3814         if (maximized)
3815             data->window_state = data->window_state | Qt::WindowMaximized;
3816     }
3817 #if QT_CONFIG(graphicsview)
3818     if (d->extra) {
3819         if (d->extra->proxyWidget)
3820             d->extra->proxyWidget->setMinimumSize(minw, minh);
3821     }
3822 #endif
3823     d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
3824 }
3825 
setMaximumSize_helper(int & maxw,int & maxh)3826 bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
3827 {
3828     Q_Q(QWidget);
3829     if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
3830         qWarning("QWidget::setMaximumSize: (%s/%s) "
3831                 "The largest allowed size is (%d,%d)",
3832                  q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3833                 QWIDGETSIZE_MAX);
3834         maxw = qMin<int>(maxw, QWIDGETSIZE_MAX);
3835         maxh = qMin<int>(maxh, QWIDGETSIZE_MAX);
3836     }
3837     if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
3838         qWarning("QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
3839                 "are not possible",
3840                 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
3841         maxw = qMax(maxw, 0);
3842         maxh = qMax(maxh, 0);
3843     }
3844     createExtra();
3845     if (extra->maxw == maxw && extra->maxh == maxh)
3846         return false;
3847     extra->maxw = maxw;
3848     extra->maxh = maxh;
3849     extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
3850                              (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
3851     return true;
3852 }
3853 
3854 /*!
3855     \overload
3856 
3857     This function corresponds to setMaximumSize(QSize(\a maxw, \a
3858     maxh)). Sets the maximum width to \a maxw and the maximum height
3859     to \a maxh.
3860 */
setMaximumSize(int maxw,int maxh)3861 void QWidget::setMaximumSize(int maxw, int maxh)
3862 {
3863     Q_D(QWidget);
3864     if (!d->setMaximumSize_helper(maxw, maxh))
3865         return;
3866 
3867     if (isWindow())
3868         d->setConstraints_sys();
3869     if (maxw < width() || maxh < height()) {
3870         bool resized = testAttribute(Qt::WA_Resized);
3871         resize(qMin(maxw,width()), qMin(maxh,height()));
3872         setAttribute(Qt::WA_Resized, resized); //not a user resize
3873     }
3874 
3875 #if QT_CONFIG(graphicsview)
3876     if (d->extra) {
3877         if (d->extra->proxyWidget)
3878             d->extra->proxyWidget->setMaximumSize(maxw, maxh);
3879     }
3880 #endif
3881 
3882     d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
3883 }
3884 
3885 /*!
3886     \overload
3887 
3888     Sets the x (width) size increment to \a w and the y (height) size
3889     increment to \a h.
3890 */
setSizeIncrement(int w,int h)3891 void QWidget::setSizeIncrement(int w, int h)
3892 {
3893     Q_D(QWidget);
3894     d->createTLExtra();
3895     QTLWExtra* x = d->topData();
3896     if (x->incw == w && x->inch == h)
3897         return;
3898     x->incw = w;
3899     x->inch = h;
3900     if (isWindow())
3901         d->setConstraints_sys();
3902 }
3903 
3904 /*!
3905     \overload
3906 
3907     This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
3908     the widgets base size to width \a basew and height \a baseh.
3909 */
setBaseSize(int basew,int baseh)3910 void QWidget::setBaseSize(int basew, int baseh)
3911 {
3912     Q_D(QWidget);
3913     d->createTLExtra();
3914     QTLWExtra* x = d->topData();
3915     if (x->basew == basew && x->baseh == baseh)
3916         return;
3917     x->basew = basew;
3918     x->baseh = baseh;
3919     if (isWindow())
3920         d->setConstraints_sys();
3921 }
3922 
3923 /*!
3924     Sets both the minimum and maximum sizes of the widget to \a s,
3925     thereby preventing it from ever growing or shrinking.
3926 
3927     This will override the default size constraints set by QLayout.
3928 
3929     To remove constraints, set the size to QWIDGETSIZE_MAX.
3930 
3931     Alternatively, if you want the widget to have a
3932     fixed size based on its contents, you can call
3933     QLayout::setSizeConstraint(QLayout::SetFixedSize);
3934 
3935     \sa maximumSize, minimumSize
3936 */
3937 
setFixedSize(const QSize & s)3938 void QWidget::setFixedSize(const QSize & s)
3939 {
3940     setFixedSize(s.width(), s.height());
3941 }
3942 
3943 
3944 /*!
3945     \fn void QWidget::setFixedSize(int w, int h)
3946     \overload
3947 
3948     Sets the width of the widget to \a w and the height to \a h.
3949 */
3950 
setFixedSize(int w,int h)3951 void QWidget::setFixedSize(int w, int h)
3952 {
3953     Q_D(QWidget);
3954     bool minSizeSet = d->setMinimumSize_helper(w, h);
3955     bool maxSizeSet = d->setMaximumSize_helper(w, h);
3956     if (!minSizeSet && !maxSizeSet)
3957         return;
3958 
3959     if (isWindow())
3960         d->setConstraints_sys();
3961     else
3962         d->updateGeometry_helper(true);
3963 
3964     if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
3965         resize(w, h);
3966 }
3967 
setMinimumWidth(int w)3968 void QWidget::setMinimumWidth(int w)
3969 {
3970     Q_D(QWidget);
3971     d->createExtra();
3972     uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
3973     setMinimumSize(w, minimumSize().height());
3974     d->extra->explicitMinSize = expl;
3975 }
3976 
setMinimumHeight(int h)3977 void QWidget::setMinimumHeight(int h)
3978 {
3979     Q_D(QWidget);
3980     d->createExtra();
3981     uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
3982     setMinimumSize(minimumSize().width(), h);
3983     d->extra->explicitMinSize = expl;
3984 }
3985 
setMaximumWidth(int w)3986 void QWidget::setMaximumWidth(int w)
3987 {
3988     Q_D(QWidget);
3989     d->createExtra();
3990     uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
3991     setMaximumSize(w, maximumSize().height());
3992     d->extra->explicitMaxSize = expl;
3993 }
3994 
setMaximumHeight(int h)3995 void QWidget::setMaximumHeight(int h)
3996 {
3997     Q_D(QWidget);
3998     d->createExtra();
3999     uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
4000     setMaximumSize(maximumSize().width(), h);
4001     d->extra->explicitMaxSize = expl;
4002 }
4003 
4004 /*!
4005     Sets both the minimum and maximum width of the widget to \a w
4006     without changing the heights. Provided for convenience.
4007 
4008     \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4009 */
4010 
setFixedWidth(int w)4011 void QWidget::setFixedWidth(int w)
4012 {
4013     Q_D(QWidget);
4014     d->createExtra();
4015     uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4016     uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4017     setMinimumSize(w, minimumSize().height());
4018     setMaximumSize(w, maximumSize().height());
4019     d->extra->explicitMinSize = explMin;
4020     d->extra->explicitMaxSize = explMax;
4021 }
4022 
4023 
4024 /*!
4025     Sets both the minimum and maximum heights of the widget to \a h
4026     without changing the widths. Provided for convenience.
4027 
4028     \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4029 */
4030 
setFixedHeight(int h)4031 void QWidget::setFixedHeight(int h)
4032 {
4033     Q_D(QWidget);
4034     d->createExtra();
4035     uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4036     uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4037     setMinimumSize(minimumSize().width(), h);
4038     setMaximumSize(maximumSize().width(), h);
4039     d->extra->explicitMinSize = explMin;
4040     d->extra->explicitMaxSize = explMax;
4041 }
4042 
4043 
4044 /*!
4045     Translates the widget coordinate \a pos to the coordinate system
4046     of \a parent. The \a parent must not be \nullptr and must be a parent
4047     of the calling widget.
4048 
4049     \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4050 */
4051 
mapTo(const QWidget * parent,const QPoint & pos) const4052 QPoint QWidget::mapTo(const QWidget * parent, const QPoint & pos) const
4053 {
4054     QPoint p = pos;
4055     if (parent) {
4056         const QWidget * w = this;
4057         while (w != parent) {
4058             Q_ASSERT_X(w, "QWidget::mapTo(const QWidget *parent, const QPoint &pos)",
4059                        "parent must be in parent hierarchy");
4060             p = w->mapToParent(p);
4061             w = w->parentWidget();
4062         }
4063     }
4064     return p;
4065 }
4066 
4067 
4068 /*!
4069     Translates the widget coordinate \a pos from the coordinate system
4070     of \a parent to this widget's coordinate system. The \a parent
4071     must not be \nullptr and must be a parent of the calling widget.
4072 
4073     \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4074 */
4075 
mapFrom(const QWidget * parent,const QPoint & pos) const4076 QPoint QWidget::mapFrom(const QWidget * parent, const QPoint & pos) const
4077 {
4078     QPoint p(pos);
4079     if (parent) {
4080         const QWidget * w = this;
4081         while (w != parent) {
4082             Q_ASSERT_X(w, "QWidget::mapFrom(const QWidget *parent, const QPoint &pos)",
4083                        "parent must be in parent hierarchy");
4084 
4085             p = w->mapFromParent(p);
4086             w = w->parentWidget();
4087         }
4088     }
4089     return p;
4090 }
4091 
4092 
4093 /*!
4094     Translates the widget coordinate \a pos to a coordinate in the
4095     parent widget.
4096 
4097     Same as mapToGlobal() if the widget has no parent.
4098 
4099     \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4100 */
4101 
mapToParent(const QPoint & pos) const4102 QPoint QWidget::mapToParent(const QPoint &pos) const
4103 {
4104     return pos + data->crect.topLeft();
4105 }
4106 
4107 /*!
4108     Translates the parent widget coordinate \a pos to widget
4109     coordinates.
4110 
4111     Same as mapFromGlobal() if the widget has no parent.
4112 
4113     \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4114 */
4115 
mapFromParent(const QPoint & pos) const4116 QPoint QWidget::mapFromParent(const QPoint &pos) const
4117 {
4118     return pos - data->crect.topLeft();
4119 }
4120 
4121 
4122 /*!
4123     Returns the window for this widget, i.e. the next ancestor widget
4124     that has (or could have) a window-system frame.
4125 
4126     If the widget is a window, the widget itself is returned.
4127 
4128     Typical usage is changing the window title:
4129 
4130     \snippet code/src_gui_kernel_qwidget.cpp 3
4131 
4132     \sa isWindow()
4133 */
4134 
window() const4135 QWidget *QWidget::window() const
4136 {
4137     QWidget *w = const_cast<QWidget *>(this);
4138     QWidget *p = w->parentWidget();
4139     while (!w->isWindow() && p) {
4140         w = p;
4141         p = p->parentWidget();
4142     }
4143     return w;
4144 }
4145 
4146 /*!
4147     \since 4.4
4148 
4149     Returns the native parent for this widget, i.e. the next ancestor widget
4150     that has a system identifier, or \nullptr if it does not have any native
4151     parent.
4152 
4153     \sa effectiveWinId()
4154 */
nativeParentWidget() const4155 QWidget *QWidget::nativeParentWidget() const
4156 {
4157     QWidget *parent = parentWidget();
4158     while (parent && !parent->internalWinId())
4159         parent = parent->parentWidget();
4160     return parent;
4161 }
4162 
4163 /*! \fn QWidget *QWidget::topLevelWidget() const
4164     \obsolete
4165 
4166     Use window() instead.
4167 */
4168 
4169 
4170 
4171 /*!
4172   Returns the background role of the widget.
4173 
4174   The background role defines the brush from the widget's \l palette that
4175   is used to render the background.
4176 
4177   If no explicit background role is set, the widget inherts its parent
4178   widget's background role.
4179 
4180   \sa setBackgroundRole(), foregroundRole()
4181  */
backgroundRole() const4182 QPalette::ColorRole QWidget::backgroundRole() const
4183 {
4184 
4185     const QWidget *w = this;
4186     do {
4187         QPalette::ColorRole role = w->d_func()->bg_role;
4188         if (role != QPalette::NoRole)
4189             return role;
4190         if (w->isWindow() || w->windowType() == Qt::SubWindow)
4191             break;
4192         w = w->parentWidget();
4193     } while (w);
4194     return QPalette::Window;
4195 }
4196 
4197 /*!
4198   Sets the background role of the widget to \a role.
4199 
4200   The background role defines the brush from the widget's \l palette that
4201   is used to render the background.
4202 
4203   If \a role is QPalette::NoRole, then the widget inherits its
4204   parent's background role.
4205 
4206   Note that styles are free to choose any color from the palette.
4207   You can modify the palette or set a style sheet if you don't
4208   achieve the result you want with setBackgroundRole().
4209 
4210   \sa backgroundRole(), foregroundRole()
4211  */
4212 
setBackgroundRole(QPalette::ColorRole role)4213 void QWidget::setBackgroundRole(QPalette::ColorRole role)
4214 {
4215     Q_D(QWidget);
4216     d->bg_role = role;
4217     d->updateSystemBackground();
4218     d->propagatePaletteChange();
4219     d->updateIsOpaque();
4220 }
4221 
4222 /*!
4223   Returns the foreground role.
4224 
4225   The foreground role defines the color from the widget's \l palette that
4226   is used to draw the foreground.
4227 
4228   If no explicit foreground role is set, the function returns a role
4229   that contrasts with the background role.
4230 
4231   \sa setForegroundRole(), backgroundRole()
4232  */
foregroundRole() const4233 QPalette::ColorRole QWidget::foregroundRole() const
4234 {
4235     Q_D(const QWidget);
4236     QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4237     if (rl != QPalette::NoRole)
4238         return rl;
4239     QPalette::ColorRole role = QPalette::WindowText;
4240     switch (backgroundRole()) {
4241     case QPalette::Button:
4242         role = QPalette::ButtonText;
4243         break;
4244     case QPalette::Base:
4245         role = QPalette::Text;
4246         break;
4247     case QPalette::Dark:
4248     case QPalette::Shadow:
4249         role = QPalette::Light;
4250         break;
4251     case QPalette::Highlight:
4252         role = QPalette::HighlightedText;
4253         break;
4254     case QPalette::ToolTipBase:
4255         role = QPalette::ToolTipText;
4256         break;
4257     default:
4258         ;
4259     }
4260     return role;
4261 }
4262 
4263 /*!
4264   Sets the foreground role of the widget to \a role.
4265 
4266   The foreground role defines the color from the widget's \l palette that
4267   is used to draw the foreground.
4268 
4269   If \a role is QPalette::NoRole, the widget uses a foreground role
4270   that contrasts with the background role.
4271 
4272   Note that styles are free to choose any color from the palette.
4273   You can modify the palette or set a style sheet if you don't
4274   achieve the result you want with setForegroundRole().
4275 
4276   \sa foregroundRole(), backgroundRole()
4277  */
setForegroundRole(QPalette::ColorRole role)4278 void QWidget::setForegroundRole(QPalette::ColorRole role)
4279 {
4280     Q_D(QWidget);
4281     d->fg_role = role;
4282     d->updateSystemBackground();
4283     d->propagatePaletteChange();
4284 }
4285 
4286 /*!
4287     \property QWidget::palette
4288     \brief the widget's palette
4289 
4290     This property describes the widget's palette. The palette is used by the
4291     widget's style when rendering standard components, and is available as a
4292     means to ensure that custom widgets can maintain consistency with the
4293     native platform's look and feel. It's common that different platforms, or
4294     different styles, have different palettes.
4295 
4296     When you assign a new palette to a widget, the color roles from this
4297     palette are combined with the widget's default palette to form the
4298     widget's final palette. The palette entry for the widget's background role
4299     is used to fill the widget's background (see QWidget::autoFillBackground),
4300     and the foreground role initializes QPainter's pen.
4301 
4302     The default depends on the system environment. QApplication maintains a
4303     system/theme palette which serves as a default for all widgets.  There may
4304     also be special palette defaults for certain types of widgets (e.g., on
4305     Windows Vista, all classes that derive from QMenuBar have a special
4306     default palette). You can also define default palettes for widgets
4307     yourself by passing a custom palette and the name of a widget to
4308     QApplication::setPalette(). Finally, the style always has the option of
4309     polishing the palette as it's assigned (see QStyle::polish()).
4310 
4311     QWidget propagates explicit palette roles from parent to child. If you
4312     assign a brush or color to a specific role on a palette and assign that
4313     palette to a widget, that role will propagate to all the widget's
4314     children, overriding any system defaults for that role. Note that palettes
4315     by default don't propagate to windows (see isWindow()) unless the
4316     Qt::WA_WindowPropagation attribute is enabled.
4317 
4318     QWidget's palette propagation is similar to its font propagation.
4319 
4320     The current style, which is used to render the content of all standard Qt
4321     widgets, is free to choose colors and brushes from the widget palette, or
4322     in some cases, to ignore the palette (partially, or completely). In
4323     particular, certain styles like GTK style, Mac style, and Windows Vista
4324     style, depend on third party APIs to render the content of widgets,
4325     and these styles typically do not follow the palette. Because of this,
4326     assigning roles to a widget's palette is not guaranteed to change the
4327     appearance of the widget. Instead, you may choose to apply a \l {styleSheet}.
4328 
4329     \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4330     When using style sheets, the palette of a widget can be customized using
4331     the "color", "background-color", "selection-color",
4332     "selection-background-color" and "alternate-background-color".
4333 
4334     \sa QGuiApplication::palette(), QWidget::font(), {Qt Style Sheets}
4335 */
palette() const4336 const QPalette &QWidget::palette() const
4337 {
4338     if (!isEnabled()) {
4339         data->pal.setCurrentColorGroup(QPalette::Disabled);
4340     } else if ((!isVisible() || isActiveWindow())
4341 #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
4342         && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4343 #endif
4344         ) {
4345         data->pal.setCurrentColorGroup(QPalette::Active);
4346     } else {
4347         data->pal.setCurrentColorGroup(QPalette::Inactive);
4348     }
4349     return data->pal;
4350 }
4351 
setPalette(const QPalette & palette)4352 void QWidget::setPalette(const QPalette &palette)
4353 {
4354     Q_D(QWidget);
4355     setAttribute(Qt::WA_SetPalette, palette.resolve() != 0);
4356 
4357     // Determine which palette is inherited from this widget's ancestors and
4358     // QApplication::palette, resolve this against \a palette (attributes from
4359     // the inherited palette are copied over this widget's palette). Then
4360     // propagate this palette to this widget's children.
4361     QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
4362     QPalette resolvedPalette = palette.resolve(naturalPalette);
4363     d->setPalette_helper(resolvedPalette);
4364 }
4365 
4366 /*!
4367     \internal
4368 
4369     Returns the palette that the widget \a w inherits from its ancestors and
4370     QApplication::palette. \a inheritedMask is the combination of the widget's
4371     ancestors palette request masks (i.e., which attributes from the parent
4372     widget's palette are implicitly imposed on this widget by the user). Note
4373     that this font does not take into account the palette set on \a w itself.
4374 */
naturalWidgetPalette(uint inheritedMask) const4375 QPalette QWidgetPrivate::naturalWidgetPalette(uint inheritedMask) const
4376 {
4377     Q_Q(const QWidget);
4378 
4379     const bool useStyleSheetPropagationInWidgetStyles =
4380         QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4381 
4382     QPalette naturalPalette = QApplication::palette(q);
4383     if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4384         && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4385 #if QT_CONFIG(graphicsview)
4386             || (extra && extra->proxyWidget)
4387 #endif // QT_CONFIG(graphicsview)
4388             )) {
4389         if (QWidget *p = q->parentWidget()) {
4390             if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4391                 if (!naturalPalette.isCopyOf(QGuiApplication::palette())) {
4392                     QPalette inheritedPalette = p->palette();
4393                     inheritedPalette.resolve(inheritedMask);
4394                     naturalPalette = inheritedPalette.resolve(naturalPalette);
4395                 } else {
4396                     naturalPalette = p->palette();
4397                 }
4398             }
4399         }
4400 #if QT_CONFIG(graphicsview)
4401         else if (extra && extra->proxyWidget) {
4402             QPalette inheritedPalette = extra->proxyWidget->palette();
4403             inheritedPalette.resolve(inheritedMask);
4404             naturalPalette = inheritedPalette.resolve(naturalPalette);
4405         }
4406 #endif // QT_CONFIG(graphicsview)
4407     }
4408     naturalPalette.resolve(0);
4409     return naturalPalette;
4410 }
4411 /*!
4412     \internal
4413 
4414     Determine which palette is inherited from this widget's ancestors and
4415     QApplication::palette, resolve this against this widget's palette
4416     (attributes from the inherited palette are copied over this widget's
4417     palette). Then propagate this palette to this widget's children.
4418 */
resolvePalette()4419 void QWidgetPrivate::resolvePalette()
4420 {
4421     QPalette naturalPalette = naturalWidgetPalette(inheritedPaletteResolveMask);
4422     QPalette resolvedPalette = data.pal.resolve(naturalPalette);
4423     setPalette_helper(resolvedPalette);
4424 }
4425 
setPalette_helper(const QPalette & palette)4426 void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4427 {
4428     Q_Q(QWidget);
4429     if (data.pal == palette && data.pal.resolve() == palette.resolve())
4430         return;
4431     data.pal = palette;
4432     updateSystemBackground();
4433     propagatePaletteChange();
4434     updateIsOpaque();
4435     q->update();
4436     updateIsOpaque();
4437 }
4438 
updateSystemBackground()4439 void QWidgetPrivate::updateSystemBackground()
4440 {
4441 }
4442 
4443 /*!
4444     \property QWidget::font
4445     \brief the font currently set for the widget
4446 
4447     This property describes the widget's requested font. The font is used by
4448     the widget's style when rendering standard components, and is available as
4449     a means to ensure that custom widgets can maintain consistency with the
4450     native platform's look and feel. It's common that different platforms, or
4451     different styles, define different fonts for an application.
4452 
4453     When you assign a new font to a widget, the properties from this font are
4454     combined with the widget's default font to form the widget's final
4455     font. You can call fontInfo() to get a copy of the widget's final
4456     font. The final font is also used to initialize QPainter's font.
4457 
4458     The default depends on the system environment. QApplication maintains a
4459     system/theme font which serves as a default for all widgets.  There may
4460     also be special font defaults for certain types of widgets. You can also
4461     define default fonts for widgets yourself by passing a custom font and the
4462     name of a widget to QApplication::setFont(). Finally, the font is matched
4463     against Qt's font database to find the best match.
4464 
4465     QWidget propagates explicit font properties from parent to child. If you
4466     change a specific property on a font and assign that font to a widget,
4467     that property will propagate to all the widget's children, overriding any
4468     system defaults for that property. Note that fonts by default don't
4469     propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4470     attribute is enabled.
4471 
4472     QWidget's font propagation is similar to its palette propagation.
4473 
4474     The current style, which is used to render the content of all standard Qt
4475     widgets, is free to choose to use the widget font, or in some cases, to
4476     ignore it (partially, or completely). In particular, certain styles like
4477     GTK style, Mac style, and Windows Vista style, apply special
4478     modifications to the widget font to match the platform's native look and
4479     feel. Because of this, assigning properties to a widget's font is not
4480     guaranteed to change the appearance of the widget. Instead, you may choose
4481     to apply a \l styleSheet.
4482 
4483     \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4484     style sheets will take precedence if the settings conflict.
4485 
4486     \sa fontInfo(), fontMetrics()
4487 */
4488 
setFont(const QFont & font)4489 void QWidget::setFont(const QFont &font)
4490 {
4491     Q_D(QWidget);
4492 
4493 #ifndef QT_NO_STYLE_STYLESHEET
4494     const QStyleSheetStyle* style;
4495     if (d->extra && (style = qt_styleSheet(d->extra->style)))
4496         style->saveWidgetFont(this, font);
4497 #endif
4498 
4499     setAttribute(Qt::WA_SetFont, font.resolve() != 0);
4500 
4501     // Determine which font is inherited from this widget's ancestors and
4502     // QApplication::font, resolve this against \a font (attributes from the
4503     // inherited font are copied over). Then propagate this font to this
4504     // widget's children.
4505     QFont naturalFont = d->naturalWidgetFont(d->inheritedFontResolveMask);
4506     QFont resolvedFont = font.resolve(naturalFont);
4507     d->setFont_helper(resolvedFont);
4508 }
4509 
4510 /*
4511     \internal
4512 
4513     Returns the font that the widget \a w inherits from its ancestors and
4514     QApplication::font. \a inheritedMask is the combination of the widget's
4515     ancestors font request masks (i.e., which attributes from the parent
4516     widget's font are implicitly imposed on this widget by the user). Note
4517     that this font does not take into account the font set on \a w itself.
4518 
4519     ### Stylesheet has a different font propagation mechanism. When a stylesheet
4520         is applied, fonts are not propagated anymore
4521 */
naturalWidgetFont(uint inheritedMask) const4522 QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4523 {
4524     Q_Q(const QWidget);
4525 
4526     const bool useStyleSheetPropagationInWidgetStyles =
4527         QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4528 
4529     QFont naturalFont = QApplication::font(q);
4530     if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4531         && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4532 #if QT_CONFIG(graphicsview)
4533             || (extra && extra->proxyWidget)
4534 #endif // QT_CONFIG(graphicsview)
4535             )) {
4536         if (QWidget *p = q->parentWidget()) {
4537             if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4538                 if (!naturalFont.isCopyOf(QApplication::font())) {
4539                     if (inheritedMask != 0) {
4540                         QFont inheritedFont = p->font();
4541                         inheritedFont.resolve(inheritedMask);
4542                         naturalFont = inheritedFont.resolve(naturalFont);
4543                     } // else nothing to do (naturalFont = naturalFont)
4544                 } else {
4545                     naturalFont = p->font();
4546                 }
4547             }
4548         }
4549 #if QT_CONFIG(graphicsview)
4550         else if (extra && extra->proxyWidget) {
4551             if (inheritedMask != 0) {
4552                 QFont inheritedFont = extra->proxyWidget->font();
4553                 inheritedFont.resolve(inheritedMask);
4554                 naturalFont = inheritedFont.resolve(naturalFont);
4555             } // else nothing to do (naturalFont = naturalFont)
4556         }
4557 #endif // QT_CONFIG(graphicsview)
4558     }
4559     naturalFont.resolve(0);
4560     return naturalFont;
4561 }
4562 
4563 /*!
4564     \internal
4565 
4566     Returns a font suitable for inheritance, where only locally set attributes are considered resolved.
4567 */
localFont() const4568 QFont QWidgetPrivate::localFont() const
4569 {
4570     QFont localfont = data.fnt;
4571     localfont.resolve(directFontResolveMask);
4572     return localfont;
4573 }
4574 
4575 /*!
4576     \internal
4577 
4578     Determine which font is implicitly imposed on this widget by its ancestors
4579     and QApplication::font, resolve this against its own font (attributes from
4580     the implicit font are copied over). Then propagate this font to this
4581     widget's children.
4582 */
resolveFont()4583 void QWidgetPrivate::resolveFont()
4584 {
4585     QFont naturalFont = naturalWidgetFont(inheritedFontResolveMask);
4586     QFont resolvedFont = localFont().resolve(naturalFont);
4587     setFont_helper(resolvedFont);
4588 }
4589 
4590 /*!
4591     \internal
4592 
4593     Assign \a font to this widget, and propagate it to all children, except
4594     style sheet widgets (handled differently) and windows that don't enable
4595     window propagation.  \a implicitMask is the union of all ancestor widgets'
4596     font request masks, and determines which attributes from this widget's
4597     font should propagate.
4598 */
updateFont(const QFont & font)4599 void QWidgetPrivate::updateFont(const QFont &font)
4600 {
4601     Q_Q(QWidget);
4602 #ifndef QT_NO_STYLE_STYLESHEET
4603     const QStyleSheetStyle* cssStyle;
4604     cssStyle = extra ? qt_styleSheet(extra->style) : nullptr;
4605     const bool useStyleSheetPropagationInWidgetStyles =
4606         QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4607 #endif
4608 
4609     data.fnt = QFont(font, q);
4610 
4611     // Combine new mask with natural mask and propagate to children.
4612 #if QT_CONFIG(graphicsview)
4613     if (!q->parentWidget() && extra && extra->proxyWidget) {
4614         QGraphicsProxyWidget *p = extra->proxyWidget;
4615         inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolve();
4616     } else
4617 #endif // QT_CONFIG(graphicsview)
4618     if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
4619         inheritedFontResolveMask = 0;
4620     }
4621     uint newMask = data.fnt.resolve() | inheritedFontResolveMask;
4622     // Set the font as also having resolved inherited traits, so the result of reading QWidget::font()
4623     // isn't all weak information, but save the original mask to be able to let new changes on the
4624     // parent widget font propagate correctly.
4625     directFontResolveMask = data.fnt.resolve();
4626     data.fnt.resolve(newMask);
4627 
4628     for (int i = 0; i < children.size(); ++i) {
4629         QWidget *w = qobject_cast<QWidget*>(children.at(i));
4630         if (w) {
4631             if (0) {
4632 #ifndef QT_NO_STYLE_STYLESHEET
4633             } else if (!useStyleSheetPropagationInWidgetStyles && w->testAttribute(Qt::WA_StyleSheet)) {
4634                 // Style sheets follow a different font propagation scheme.
4635                 if (cssStyle)
4636                     cssStyle->updateStyleSheetFont(w);
4637 #endif
4638             } else if ((!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
4639                 // Propagate font changes.
4640                 QWidgetPrivate *wd = w->d_func();
4641                 wd->inheritedFontResolveMask = newMask;
4642                 wd->resolveFont();
4643             }
4644         }
4645     }
4646 
4647 #ifndef QT_NO_STYLE_STYLESHEET
4648     if (!useStyleSheetPropagationInWidgetStyles && cssStyle) {
4649         cssStyle->updateStyleSheetFont(q);
4650     }
4651 #endif
4652 
4653     QEvent e(QEvent::FontChange);
4654     QCoreApplication::sendEvent(q, &e);
4655 }
4656 
setLayoutDirection_helper(Qt::LayoutDirection direction)4657 void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
4658 {
4659     Q_Q(QWidget);
4660 
4661     if ( (direction == Qt::RightToLeft) == q->testAttribute(Qt::WA_RightToLeft))
4662         return;
4663     q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));
4664     if (!children.isEmpty()) {
4665         for (int i = 0; i < children.size(); ++i) {
4666             QWidget *w = qobject_cast<QWidget*>(children.at(i));
4667             if (w && !w->isWindow() && !w->testAttribute(Qt::WA_SetLayoutDirection))
4668                 w->d_func()->setLayoutDirection_helper(direction);
4669         }
4670     }
4671     QEvent e(QEvent::LayoutDirectionChange);
4672     QCoreApplication::sendEvent(q, &e);
4673 }
4674 
resolveLayoutDirection()4675 void QWidgetPrivate::resolveLayoutDirection()
4676 {
4677     Q_Q(const QWidget);
4678     if (!q->testAttribute(Qt::WA_SetLayoutDirection))
4679         setLayoutDirection_helper(q->isWindow() ? QGuiApplication::layoutDirection() : q->parentWidget()->layoutDirection());
4680 }
4681 
4682 /*!
4683     \property QWidget::layoutDirection
4684 
4685     \brief the layout direction for this widget
4686 
4687     By default, this property is set to Qt::LeftToRight.
4688 
4689     When the layout direction is set on a widget, it will propagate to
4690     the widget's children, but not to a child that is a window and not
4691     to a child for which setLayoutDirection() has been explicitly
4692     called. Also, child widgets added \e after setLayoutDirection()
4693     has been called for the parent do not inherit the parent's layout
4694     direction.
4695 
4696     This method no longer affects text layout direction since Qt 4.7.
4697 
4698     \sa QApplication::layoutDirection
4699 */
setLayoutDirection(Qt::LayoutDirection direction)4700 void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
4701 {
4702     Q_D(QWidget);
4703 
4704     if (direction == Qt::LayoutDirectionAuto) {
4705         unsetLayoutDirection();
4706         return;
4707     }
4708 
4709     setAttribute(Qt::WA_SetLayoutDirection);
4710     d->setLayoutDirection_helper(direction);
4711 }
4712 
layoutDirection() const4713 Qt::LayoutDirection QWidget::layoutDirection() const
4714 {
4715     return testAttribute(Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
4716 }
4717 
unsetLayoutDirection()4718 void QWidget::unsetLayoutDirection()
4719 {
4720     Q_D(QWidget);
4721     setAttribute(Qt::WA_SetLayoutDirection, false);
4722     d->resolveLayoutDirection();
4723 }
4724 
4725 /*!
4726     \fn QFontMetrics QWidget::fontMetrics() const
4727 
4728     Returns the font metrics for the widget's current font.
4729     Equivalent to \c QFontMetrics(widget->font()).
4730 
4731     \sa font(), fontInfo(), setFont()
4732 */
4733 
4734 /*!
4735     \fn QFontInfo QWidget::fontInfo() const
4736 
4737     Returns the font info for the widget's current font.
4738     Equivalent to \c QFontInfo(widget->font()).
4739 
4740     \sa font(), fontMetrics(), setFont()
4741 */
4742 
4743 
4744 /*!
4745     \property QWidget::cursor
4746     \brief the cursor shape for this widget
4747 
4748     The mouse cursor will assume this shape when it's over this
4749     widget. See the \l{Qt::CursorShape}{list of predefined cursor objects} for a range of useful shapes.
4750 
4751     An editor widget might use an I-beam cursor:
4752     \snippet code/src_gui_kernel_qwidget.cpp 6
4753 
4754     If no cursor has been set, or after a call to unsetCursor(), the
4755     parent's cursor is used.
4756 
4757     By default, this property contains a cursor with the Qt::ArrowCursor
4758     shape.
4759 
4760     Some underlying window implementations will reset the cursor if it
4761     leaves a widget even if the mouse is grabbed. If you want to have
4762     a cursor set for all widgets, even when outside the window, consider
4763     QGuiApplication::setOverrideCursor().
4764 
4765     \sa QGuiApplication::setOverrideCursor()
4766 */
4767 
4768 #ifndef QT_NO_CURSOR
cursor() const4769 QCursor QWidget::cursor() const
4770 {
4771     Q_D(const QWidget);
4772     if (testAttribute(Qt::WA_SetCursor))
4773         return (d->extra && d->extra->curs)
4774             ? *d->extra->curs
4775             : QCursor(Qt::ArrowCursor);
4776     if (isWindow() || !parentWidget())
4777         return QCursor(Qt::ArrowCursor);
4778     return parentWidget()->cursor();
4779 }
4780 
setCursor(const QCursor & cursor)4781 void QWidget::setCursor(const QCursor &cursor)
4782 {
4783     Q_D(QWidget);
4784     if (cursor.shape() != Qt::ArrowCursor
4785         || (d->extra && d->extra->curs))
4786     {
4787         d->createExtra();
4788         d->extra->curs = qt_make_unique<QCursor>(cursor);
4789     }
4790     setAttribute(Qt::WA_SetCursor);
4791     d->setCursor_sys(cursor);
4792 
4793     QEvent event(QEvent::CursorChange);
4794     QCoreApplication::sendEvent(this, &event);
4795 }
4796 
setCursor_sys(const QCursor & cursor)4797 void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
4798 {
4799     Q_UNUSED(cursor);
4800     Q_Q(QWidget);
4801     qt_qpa_set_cursor(q, false);
4802 }
4803 
unsetCursor()4804 void QWidget::unsetCursor()
4805 {
4806     Q_D(QWidget);
4807     if (d->extra)
4808         d->extra->curs.reset();
4809     if (!isWindow())
4810         setAttribute(Qt::WA_SetCursor, false);
4811     d->unsetCursor_sys();
4812 
4813     QEvent event(QEvent::CursorChange);
4814     QCoreApplication::sendEvent(this, &event);
4815 }
4816 
unsetCursor_sys()4817 void QWidgetPrivate::unsetCursor_sys()
4818 {
4819     Q_Q(QWidget);
4820     qt_qpa_set_cursor(q, false);
4821 }
4822 
applyCursor(QWidget * w,const QCursor & c)4823 static inline void applyCursor(QWidget *w, const QCursor &c)
4824 {
4825     if (QWindow *window = w->windowHandle())
4826         window->setCursor(c);
4827 }
4828 
unsetCursor(QWidget * w)4829 static inline void unsetCursor(QWidget *w)
4830 {
4831     if (QWindow *window = w->windowHandle())
4832         window->unsetCursor();
4833 }
4834 
qt_qpa_set_cursor(QWidget * w,bool force)4835 void qt_qpa_set_cursor(QWidget *w, bool force)
4836 {
4837     if (!w->testAttribute(Qt::WA_WState_Created))
4838         return;
4839 
4840     static QPointer<QWidget> lastUnderMouse = nullptr;
4841     if (force) {
4842         lastUnderMouse = w;
4843     } else if (lastUnderMouse) {
4844         const WId lastWinId = lastUnderMouse->effectiveWinId();
4845         const WId winId = w->effectiveWinId();
4846         if (lastWinId && lastWinId == winId)
4847             w = lastUnderMouse;
4848     } else if (!w->internalWinId()) {
4849         return; // The mouse is not under this widget, and it's not native, so don't change it.
4850     }
4851 
4852     while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
4853            && !w->testAttribute(Qt::WA_SetCursor))
4854         w = w->parentWidget();
4855 
4856     QWidget *nativeParent = w;
4857     if (!w->internalWinId())
4858         nativeParent = w->nativeParentWidget();
4859     if (!nativeParent || !nativeParent->internalWinId())
4860         return;
4861 
4862     if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
4863         if (w->isEnabled())
4864             applyCursor(nativeParent, w->cursor());
4865         else
4866             // Enforce the windows behavior of clearing the cursor on
4867             // disabled widgets.
4868             unsetCursor(nativeParent);
4869     } else {
4870         unsetCursor(nativeParent);
4871     }
4872 }
4873 #endif
4874 
4875 /*!
4876     \enum QWidget::RenderFlag
4877 
4878     This enum describes how to render the widget when calling QWidget::render().
4879 
4880     \value DrawWindowBackground If you enable this option, the widget's background
4881     is rendered into the target even if autoFillBackground is not set. By default,
4882     this option is enabled.
4883 
4884     \value DrawChildren If you enable this option, the widget's children
4885     are rendered recursively into the target. By default, this option is enabled.
4886 
4887     \value IgnoreMask If you enable this option, the widget's QWidget::mask()
4888     is ignored when rendering into the target. By default, this option is disabled.
4889 
4890     \since 4.3
4891 */
4892 
4893 /*!
4894     \since 4.3
4895 
4896     Renders the \a sourceRegion of this widget into the \a target
4897     using \a renderFlags to determine how to render. Rendering
4898     starts at \a targetOffset in the \a target. For example:
4899 
4900     \snippet code/src_gui_kernel_qwidget.cpp 7
4901 
4902     If \a sourceRegion is a null region, this function will use QWidget::rect() as
4903     the region, i.e. the entire widget.
4904 
4905     Ensure that you call QPainter::end() for the \a target device's
4906     active painter (if any) before rendering. For example:
4907 
4908     \snippet code/src_gui_kernel_qwidget.cpp 8
4909 
4910     \note To obtain the contents of a QOpenGLWidget, use QOpenGLWidget::grabFramebuffer()
4911     instead.
4912 
4913     \note To obtain the contents of a QGLWidget (deprecated), use
4914     QGLWidget::grabFrameBuffer() or QGLWidget::renderPixmap() instead.
4915 */
render(QPaintDevice * target,const QPoint & targetOffset,const QRegion & sourceRegion,RenderFlags renderFlags)4916 void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
4917                      const QRegion &sourceRegion, RenderFlags renderFlags)
4918 {
4919     QPainter p(target);
4920     render(&p, targetOffset, sourceRegion, renderFlags);
4921 }
4922 
4923 /*!
4924     \overload
4925 
4926     Renders the widget into the \a painter's QPainter::device().
4927 
4928     Transformations and settings applied to the \a painter will be used
4929     when rendering.
4930 
4931     \note The \a painter must be active. On \macos the widget will be
4932     rendered into a QPixmap and then drawn by the \a painter.
4933 
4934     \sa QPainter::device()
4935 */
render(QPainter * painter,const QPoint & targetOffset,const QRegion & sourceRegion,RenderFlags renderFlags)4936 void QWidget::render(QPainter *painter, const QPoint &targetOffset,
4937                      const QRegion &sourceRegion, RenderFlags renderFlags)
4938 {
4939     if (Q_UNLIKELY(!painter)) {
4940         qWarning("QWidget::render: Null pointer to painter");
4941         return;
4942     }
4943 
4944     if (Q_UNLIKELY(!painter->isActive())) {
4945         qWarning("QWidget::render: Cannot render with an inactive painter");
4946         return;
4947     }
4948 
4949     const qreal opacity = painter->opacity();
4950     if (qFuzzyIsNull(opacity))
4951         return; // Fully transparent.
4952 
4953     Q_D(QWidget);
4954     const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
4955     const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
4956                                                      : sourceRegion;
4957     if (toBePainted.isEmpty())
4958         return;
4959 
4960     if (!d->extra)
4961         d->createExtra();
4962     d->extra->inRenderWithPainter = true;
4963 
4964     QPaintEngine *engine = painter->paintEngine();
4965     Q_ASSERT(engine);
4966     QPaintEnginePrivate *enginePriv = engine->d_func();
4967     Q_ASSERT(enginePriv);
4968     QPaintDevice *target = engine->paintDevice();
4969     Q_ASSERT(target);
4970 
4971     // Render via a pixmap when dealing with non-opaque painters or printers.
4972     if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
4973         d->render_helper(painter, targetOffset, toBePainted, renderFlags);
4974         d->extra->inRenderWithPainter = inRenderWithPainter;
4975         return;
4976     }
4977 
4978     // Set new shared painter.
4979     QPainter *oldPainter = d->sharedPainter();
4980     d->setSharedPainter(painter);
4981 
4982     // Save current system clip, viewport and transform,
4983     const QTransform oldTransform = enginePriv->systemTransform;
4984     const QRegion oldSystemClip = enginePriv->systemClip;
4985     const QRegion oldBaseClip = enginePriv->baseSystemClip;
4986     const QRegion oldSystemViewport = enginePriv->systemViewport;
4987 
4988     // This ensures that all painting triggered by render() is clipped to the current engine clip.
4989     if (painter->hasClipping()) {
4990         const QRegion painterClip = painter->deviceTransform().map(painter->clipRegion());
4991         enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip);
4992     } else {
4993         enginePriv->setSystemViewport(oldSystemClip);
4994     }
4995 
4996     d->render(target, targetOffset, toBePainted, renderFlags);
4997 
4998     // Restore system clip, viewport and transform.
4999     enginePriv->baseSystemClip = oldBaseClip;
5000     enginePriv->setSystemTransformAndViewport(oldTransform, oldSystemViewport);
5001     enginePriv->systemStateChanged();
5002 
5003     // Restore shared painter.
5004     d->setSharedPainter(oldPainter);
5005 
5006     d->extra->inRenderWithPainter = inRenderWithPainter;
5007 }
5008 
sendResizeEvents(QWidget * target)5009 static void sendResizeEvents(QWidget *target)
5010 {
5011     QResizeEvent e(target->size(), QSize());
5012     QCoreApplication::sendEvent(target, &e);
5013 
5014     const QObjectList children = target->children();
5015     for (int i = 0; i < children.size(); ++i) {
5016         if (!children.at(i)->isWidgetType())
5017             continue;
5018         QWidget *child = static_cast<QWidget*>(children.at(i));
5019         if (!child->isWindow() && child->testAttribute(Qt::WA_PendingResizeEvent))
5020             sendResizeEvents(child);
5021     }
5022 }
5023 
5024 /*!
5025     \since 5.0
5026 
5027     Renders the widget into a pixmap restricted by the
5028     given \a rectangle. If the widget has any children, then
5029     they are also painted in the appropriate positions.
5030 
5031     If a rectangle with an invalid size is specified  (the default),
5032     the entire widget is painted.
5033 
5034     \sa render(), QPixmap
5035 */
grab(const QRect & rectangle)5036 QPixmap QWidget::grab(const QRect &rectangle)
5037 {
5038     Q_D(QWidget);
5039     if (testAttribute(Qt::WA_PendingResizeEvent) || !testAttribute(Qt::WA_WState_Created))
5040         sendResizeEvents(this);
5041 
5042     const QWidget::RenderFlags renderFlags = QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask;
5043 
5044     const bool oldDirtyOpaqueChildren =  d->dirtyOpaqueChildren;
5045     QRect r(rectangle);
5046     if (r.width() < 0 || r.height() < 0) {
5047         // For grabbing widgets that haven't been shown yet,
5048         // we trigger the layouting mechanism to determine the widget's size.
5049         r = d->prepareToRender(QRegion(), renderFlags).boundingRect();
5050         r.setTopLeft(rectangle.topLeft());
5051     }
5052 
5053     if (!r.intersects(rect()))
5054         return QPixmap();
5055 
5056     const qreal dpr = devicePixelRatioF();
5057     QPixmap res((QSizeF(r.size()) * dpr).toSize());
5058     res.setDevicePixelRatio(dpr);
5059     if (!d->isOpaque)
5060         res.fill(Qt::transparent);
5061     d->render(&res, QPoint(), QRegion(r), renderFlags);
5062 
5063     d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
5064     return res;
5065 }
5066 
5067 /*!
5068     \brief The graphicsEffect function returns a pointer to the
5069     widget's graphics effect.
5070 
5071     If the widget has no graphics effect, \nullptr is returned.
5072 
5073     \since 4.6
5074 
5075     \sa setGraphicsEffect()
5076 */
5077 #if QT_CONFIG(graphicseffect)
graphicsEffect() const5078 QGraphicsEffect *QWidget::graphicsEffect() const
5079 {
5080     Q_D(const QWidget);
5081     return d->graphicsEffect;
5082 }
5083 #endif // QT_CONFIG(graphicseffect)
5084 
5085 /*!
5086 
5087   \brief The setGraphicsEffect function is for setting the widget's graphics effect.
5088 
5089     Sets \a effect as the widget's effect. If there already is an effect installed
5090     on this widget, QWidget will delete the existing effect before installing
5091     the new \a effect.
5092 
5093     If \a effect is the installed effect on a different widget, setGraphicsEffect() will remove
5094     the effect from the widget and install it on this widget.
5095 
5096     QWidget takes ownership of \a effect.
5097 
5098     \note This function will apply the effect on itself and all its children.
5099 
5100     \note Graphics effects are not supported for OpenGL-based widgets, such as QGLWidget,
5101     QOpenGLWidget and QQuickWidget.
5102 
5103     \since 4.6
5104 
5105     \sa graphicsEffect()
5106 */
5107 #if QT_CONFIG(graphicseffect)
setGraphicsEffect(QGraphicsEffect * effect)5108 void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
5109 {
5110     Q_D(QWidget);
5111     if (d->graphicsEffect == effect)
5112         return;
5113 
5114     if (d->graphicsEffect) {
5115         d->invalidateBackingStore(rect());
5116         delete d->graphicsEffect;
5117         d->graphicsEffect = nullptr;
5118     }
5119 
5120     if (effect) {
5121         // Set new effect.
5122         QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
5123         QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
5124         d->graphicsEffect = effect;
5125         effect->d_func()->setGraphicsEffectSource(source);
5126         update();
5127     }
5128 
5129     d->updateIsOpaque();
5130 }
5131 #endif // QT_CONFIG(graphicseffect)
5132 
isAboutToShow() const5133 bool QWidgetPrivate::isAboutToShow() const
5134 {
5135     if (data.in_show)
5136         return true;
5137 
5138     Q_Q(const QWidget);
5139     if (q->isHidden())
5140         return false;
5141 
5142     // The widget will be shown if any of its ancestors are about to show.
5143     QWidget *parent = q->parentWidget();
5144     return parent ? parent->d_func()->isAboutToShow() : false;
5145 }
5146 
prepareToRender(const QRegion & region,QWidget::RenderFlags renderFlags)5147 QRegion QWidgetPrivate::prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags)
5148 {
5149     Q_Q(QWidget);
5150     const bool isVisible = q->isVisible();
5151 
5152     // Make sure the widget is laid out correctly.
5153     if (!isVisible && !isAboutToShow()) {
5154         QWidget *topLevel = q->window();
5155         (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
5156         topLevel->ensurePolished();
5157 
5158         // Invalidate the layout of hidden ancestors (incl. myself) and pretend
5159         // they're not explicitly hidden.
5160         QWidget *widget = q;
5161         QWidgetList hiddenWidgets;
5162         while (widget) {
5163             if (widget->isHidden()) {
5164                 widget->setAttribute(Qt::WA_WState_Hidden, false);
5165                 hiddenWidgets.append(widget);
5166                 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5167                     widget->d_func()->updateGeometry_helper(true);
5168             }
5169             widget = widget->parentWidget();
5170         }
5171 
5172         // Activate top-level layout.
5173         if (topLevel->d_func()->layout)
5174             topLevel->d_func()->layout->activate();
5175 
5176         // Adjust size if necessary.
5177         QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
5178         if (topLevelExtra && !topLevelExtra->sizeAdjusted
5179             && !topLevel->testAttribute(Qt::WA_Resized)) {
5180             topLevel->adjustSize();
5181             topLevel->setAttribute(Qt::WA_Resized, false);
5182         }
5183 
5184         // Activate child layouts.
5185         topLevel->d_func()->activateChildLayoutsRecursively();
5186 
5187         // We're not cheating with WA_WState_Hidden anymore.
5188         for (int i = 0; i < hiddenWidgets.size(); ++i) {
5189             QWidget *widget = hiddenWidgets.at(i);
5190             widget->setAttribute(Qt::WA_WState_Hidden);
5191             if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5192                 widget->parentWidget()->d_func()->layout->invalidate();
5193         }
5194     } else if (isVisible) {
5195         q->window()->d_func()->sendPendingMoveAndResizeEvents(true, true);
5196     }
5197 
5198     // Calculate the region to be painted.
5199     QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
5200     if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
5201         toBePainted &= extra->mask;
5202     return toBePainted;
5203 }
5204 
render_helper(QPainter * painter,const QPoint & targetOffset,const QRegion & toBePainted,QWidget::RenderFlags renderFlags)5205 void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
5206                                    QWidget::RenderFlags renderFlags)
5207 {
5208     Q_ASSERT(painter);
5209     Q_ASSERT(!toBePainted.isEmpty());
5210 
5211     Q_Q(QWidget);
5212     const QTransform originalTransform = painter->worldTransform();
5213     const bool useDeviceCoordinates = originalTransform.isScaling();
5214     if (!useDeviceCoordinates) {
5215         // Render via a pixmap.
5216         const QRect rect = toBePainted.boundingRect();
5217         const QSize size = rect.size();
5218         if (size.isNull())
5219             return;
5220 
5221         const qreal pixmapDevicePixelRatio = painter->device()->devicePixelRatioF();
5222         QPixmap pixmap(size * pixmapDevicePixelRatio);
5223         pixmap.setDevicePixelRatio(pixmapDevicePixelRatio);
5224 
5225         if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque)
5226             pixmap.fill(Qt::transparent);
5227         q->render(&pixmap, QPoint(), toBePainted, renderFlags);
5228 
5229         const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
5230         painter->setRenderHints(QPainter::SmoothPixmapTransform, true);
5231 
5232         painter->drawPixmap(targetOffset, pixmap);
5233 
5234         if (restore)
5235             painter->setRenderHints(QPainter::SmoothPixmapTransform, false);
5236 
5237     } else {
5238         // Render via a pixmap in device coordinates (to avoid pixmap scaling).
5239         QTransform transform = originalTransform;
5240         transform.translate(targetOffset.x(), targetOffset.y());
5241 
5242         QPaintDevice *device = painter->device();
5243         Q_ASSERT(device);
5244 
5245         // Calculate device rect.
5246         const QRectF rect(toBePainted.boundingRect());
5247         QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
5248         deviceRect &= QRect(0, 0, device->width(), device->height());
5249 
5250         QPixmap pixmap(deviceRect.size());
5251         pixmap.fill(Qt::transparent);
5252 
5253         // Create a pixmap device coordinate painter.
5254         QPainter pixmapPainter(&pixmap);
5255         pixmapPainter.setRenderHints(painter->renderHints());
5256         transform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
5257         pixmapPainter.setTransform(transform);
5258 
5259         q->render(&pixmapPainter, QPoint(), toBePainted, renderFlags);
5260         pixmapPainter.end();
5261 
5262         // And then draw the pixmap.
5263         painter->setTransform(QTransform());
5264         painter->drawPixmap(deviceRect.topLeft(), pixmap);
5265         painter->setTransform(originalTransform);
5266     }
5267 }
5268 
drawWidget(QPaintDevice * pdev,const QRegion & rgn,const QPoint & offset,DrawWidgetFlags flags,QPainter * sharedPainter,QWidgetRepaintManager * repaintManager)5269 void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
5270                                 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5271 {
5272     if (rgn.isEmpty())
5273         return;
5274 
5275     Q_Q(QWidget);
5276 
5277     qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset
5278         << "into paint device" << pdev << "with" << flags;
5279 
5280     const bool asRoot = flags & DrawAsRoot;
5281     bool onScreen = shouldPaintOnScreen();
5282 
5283 #if QT_CONFIG(graphicseffect)
5284     if (graphicsEffect && graphicsEffect->isEnabled()) {
5285         QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
5286         QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
5287                                                          (source->d_func());
5288         if (!sourced->context) {
5289             QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, repaintManager);
5290             sourced->context = &context;
5291             if (!sharedPainter) {
5292                 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), rgn.translated(offset));
5293                 QPainter p(pdev);
5294                 p.translate(offset);
5295                 context.painter = &p;
5296                 graphicsEffect->draw(&p);
5297                 setSystemClip(pdev->paintEngine(), 1, QRegion());
5298             } else {
5299                 context.painter = sharedPainter;
5300                 if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
5301                     sourced->invalidateCache();
5302                     sourced->lastEffectTransform = sharedPainter->worldTransform();
5303                 }
5304                 sharedPainter->save();
5305                 sharedPainter->translate(offset);
5306                 setSystemClip(sharedPainter->paintEngine(), sharedPainter->device()->devicePixelRatioF(), rgn.translated(offset));
5307                 graphicsEffect->draw(sharedPainter);
5308                 setSystemClip(sharedPainter->paintEngine(), 1, QRegion());
5309                 sharedPainter->restore();
5310             }
5311             sourced->context = nullptr;
5312 
5313             if (repaintManager)
5314                 repaintManager->markNeedsFlush(q, rgn, offset);
5315 
5316             return;
5317         }
5318     }
5319 #endif // QT_CONFIG(graphicseffect)
5320 
5321     const bool alsoOnScreen = flags & DrawPaintOnScreen;
5322     const bool recursive = flags & DrawRecursive;
5323     const bool alsoInvisible = flags & DrawInvisible;
5324 
5325     Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
5326 
5327     QRegion toBePainted(rgn);
5328     if (asRoot && !alsoInvisible)
5329         toBePainted &= clipRect(); //(rgn & visibleRegion());
5330     if (!(flags & DontSubtractOpaqueChildren))
5331         subtractOpaqueChildren(toBePainted, q->rect());
5332 
5333     if (!toBePainted.isEmpty()) {
5334         if (!onScreen || alsoOnScreen) {
5335             //update the "in paint event" flag
5336             if (Q_UNLIKELY(q->testAttribute(Qt::WA_WState_InPaintEvent)))
5337                 qWarning("QWidget::repaint: Recursive repaint detected");
5338             q->setAttribute(Qt::WA_WState_InPaintEvent);
5339 
5340             //clip away the new area
5341             QPaintEngine *paintEngine = pdev->paintEngine();
5342             if (paintEngine) {
5343                 setRedirected(pdev, -offset);
5344 
5345                 if (sharedPainter)
5346                     setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted);
5347                 else
5348                     paintEngine->d_func()->systemRect = q->data->crect;
5349 
5350                 //paint the background
5351                 if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
5352                     && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
5353 #ifndef QT_NO_OPENGL
5354                     beginBackingStorePainting();
5355 #endif
5356                     QPainter p(q);
5357                     paintBackground(&p, toBePainted, (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags());
5358 #ifndef QT_NO_OPENGL
5359                     endBackingStorePainting();
5360 #endif
5361                 }
5362 
5363                 if (!sharedPainter)
5364                     setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted.translated(offset));
5365 
5366                 if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
5367 #ifndef QT_NO_OPENGL
5368                     beginBackingStorePainting();
5369 #endif
5370                     QPainter p(q);
5371                     QColor tint = q->palette().window().color();
5372                     tint.setAlphaF(qreal(.6));
5373                     p.fillRect(toBePainted.boundingRect(), tint);
5374 #ifndef QT_NO_OPENGL
5375                     endBackingStorePainting();
5376 #endif
5377                 }
5378             }
5379 
5380 #if 0
5381             qDebug() << "painting" << q << "opaque ==" << isOpaque();
5382             qDebug() << "clipping to" << toBePainted << "location == " << offset
5383                      << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
5384 #endif
5385 
5386             bool skipPaintEvent = false;
5387 #ifndef QT_NO_OPENGL
5388             if (renderToTexture) {
5389                 // This widget renders into a texture which is composed later. We just need to
5390                 // punch a hole in the backingstore, so the texture will be visible.
5391                 beginBackingStorePainting();
5392                 if (!q->testAttribute(Qt::WA_AlwaysStackOnTop) && repaintManager) {
5393                     QPainter p(q);
5394                     p.setCompositionMode(QPainter::CompositionMode_Source);
5395                     p.fillRect(q->rect(), Qt::transparent);
5396                 } else if (!repaintManager) {
5397                     // We are not drawing to a backingstore: fall back to QImage
5398                     QImage img = grabFramebuffer();
5399                     // grabFramebuffer() always sets the format to RGB32
5400                     // regardless of whether it is transparent or not.
5401                     if (img.format() == QImage::Format_RGB32)
5402                         img.reinterpretAsFormat(QImage::Format_ARGB32_Premultiplied);
5403                     QPainter p(q);
5404                     p.drawImage(q->rect(), img);
5405                     skipPaintEvent = true;
5406                 }
5407                 endBackingStorePainting();
5408                 if (renderToTextureReallyDirty)
5409                     renderToTextureReallyDirty = 0;
5410                 else
5411                     skipPaintEvent = true;
5412             }
5413 #endif // QT_NO_OPENGL
5414 
5415             if (!skipPaintEvent) {
5416                 //actually send the paint event
5417                 sendPaintEvent(toBePainted);
5418             }
5419 
5420             if (repaintManager)
5421                 repaintManager->markNeedsFlush(q, toBePainted, offset);
5422 
5423             //restore
5424             if (paintEngine) {
5425                 restoreRedirected();
5426                 if (!sharedPainter)
5427                     paintEngine->d_func()->systemRect = QRect();
5428                 else
5429                     paintEngine->d_func()->currentClipDevice = nullptr;
5430 
5431                 setSystemClip(pdev->paintEngine(), 1, QRegion());
5432             }
5433             q->setAttribute(Qt::WA_WState_InPaintEvent, false);
5434             if (Q_UNLIKELY(q->paintingActive()))
5435                 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
5436 
5437             if (paintEngine && paintEngine->autoDestruct()) {
5438                 delete paintEngine;
5439             }
5440         } else if (q->isWindow()) {
5441             QPaintEngine *engine = pdev->paintEngine();
5442             if (engine) {
5443                 QPainter p(pdev);
5444                 p.setClipRegion(toBePainted);
5445                 const QBrush bg = q->palette().brush(QPalette::Window);
5446                 if (bg.style() == Qt::TexturePattern)
5447                     p.drawTiledPixmap(q->rect(), bg.texture());
5448                 else
5449                     p.fillRect(q->rect(), bg);
5450 
5451                 if (engine->autoDestruct())
5452                     delete engine;
5453             }
5454         }
5455     }
5456 
5457     if (recursive && !children.isEmpty()) {
5458         paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot,
5459                                sharedPainter, repaintManager);
5460     }
5461 }
5462 
sendPaintEvent(const QRegion & toBePainted)5463 void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
5464 {
5465     Q_Q(QWidget);
5466     QPaintEvent e(toBePainted);
5467     QCoreApplication::sendSpontaneousEvent(q, &e);
5468 
5469 #ifndef QT_NO_OPENGL
5470     if (renderToTexture)
5471         resolveSamples();
5472 #endif // QT_NO_OPENGL
5473 }
5474 
render(QPaintDevice * target,const QPoint & targetOffset,const QRegion & sourceRegion,QWidget::RenderFlags renderFlags)5475 void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
5476                             const QRegion &sourceRegion, QWidget::RenderFlags renderFlags)
5477 {
5478     if (Q_UNLIKELY(!target)) {
5479         qWarning("QWidget::render: null pointer to paint device");
5480         return;
5481     }
5482 
5483     const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
5484     QRegion paintRegion = !inRenderWithPainter
5485                           ? prepareToRender(sourceRegion, renderFlags)
5486                           : sourceRegion;
5487     if (paintRegion.isEmpty())
5488         return;
5489 
5490     QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : nullptr;
5491 
5492     // Use the target's shared painter if set (typically set when doing
5493     // "other->render(widget);" in the widget's paintEvent.
5494     if (target->devType() == QInternal::Widget) {
5495         QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
5496         if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
5497             QPainter *targetPainter = targetPrivate->sharedPainter();
5498             if (targetPainter && targetPainter->isActive())
5499                 setSharedPainter(targetPainter);
5500         }
5501     }
5502 
5503     // Use the target's redirected device if set and adjust offset and paint
5504     // region accordingly. This is typically the case when people call render
5505     // from the paintEvent.
5506     QPoint offset = targetOffset;
5507     offset -= paintRegion.boundingRect().topLeft();
5508     QPoint redirectionOffset;
5509     QPaintDevice *redirected = nullptr;
5510 
5511     if (target->devType() == QInternal::Widget)
5512         redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
5513 
5514     if (redirected) {
5515         target = redirected;
5516         offset -= redirectionOffset;
5517     }
5518 
5519     if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
5520         if (QPaintEngine *targetEngine = target->paintEngine()) {
5521             const QRegion targetSystemClip = targetEngine->systemClip();
5522             if (!targetSystemClip.isEmpty())
5523                 paintRegion &= targetSystemClip.translated(-offset);
5524         }
5525     }
5526 
5527     // Set backingstore flags.
5528     DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible;
5529     if (renderFlags & QWidget::DrawWindowBackground)
5530         flags |= DrawAsRoot;
5531 
5532     if (renderFlags & QWidget::DrawChildren)
5533         flags |= DrawRecursive;
5534     else
5535         flags |= DontSubtractOpaqueChildren;
5536 
5537     flags |= DontSetCompositionMode;
5538 
5539     // Render via backingstore.
5540     drawWidget(target, paintRegion, offset, flags, sharedPainter());
5541 
5542     // Restore shared painter.
5543     if (oldSharedPainter)
5544         setSharedPainter(oldSharedPainter);
5545 }
5546 
paintSiblingsRecursive(QPaintDevice * pdev,const QObjectList & siblings,int index,const QRegion & rgn,const QPoint & offset,DrawWidgetFlags flags,QPainter * sharedPainter,QWidgetRepaintManager * repaintManager)5547 void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
5548                                             const QPoint &offset, DrawWidgetFlags flags
5549                                             , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5550 {
5551     QWidget *w = nullptr;
5552     QRect boundingRect;
5553     bool dirtyBoundingRect = true;
5554     const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
5555     const bool excludeNativeChildren = (flags & DontDrawNativeChildren);
5556 
5557     do {
5558         QWidget *x =  qobject_cast<QWidget*>(siblings.at(index));
5559         if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()
5560             && !(excludeNativeChildren && x->internalWinId())) {
5561             if (dirtyBoundingRect) {
5562                 boundingRect = rgn.boundingRect();
5563                 dirtyBoundingRect = false;
5564             }
5565 
5566             if (qRectIntersects(boundingRect, x->d_func()->effectiveRectFor(x->data->crect))) {
5567                 w = x;
5568                 break;
5569             }
5570         }
5571         --index;
5572     } while (index >= 0);
5573 
5574     if (!w)
5575         return;
5576 
5577     QWidgetPrivate *wd = w->d_func();
5578     const QPoint widgetPos(w->data->crect.topLeft());
5579     const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
5580     if (index > 0) {
5581         QRegion wr(rgn);
5582         if (wd->isOpaque)
5583             wr -= hasMask ? wd->extra->mask.translated(widgetPos) : w->data->crect;
5584         paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags,
5585                                sharedPainter, repaintManager);
5586     }
5587 
5588     if (w->updatesEnabled()
5589 #if QT_CONFIG(graphicsview)
5590             && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)
5591 #endif // QT_CONFIG(graphicsview)
5592        ) {
5593         QRegion wRegion(rgn);
5594         wRegion &= wd->effectiveRectFor(w->data->crect);
5595         wRegion.translate(-widgetPos);
5596         if (hasMask)
5597             wRegion &= wd->extra->mask;
5598         wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, repaintManager);
5599     }
5600 }
5601 
5602 #if QT_CONFIG(graphicseffect)
boundingRect(Qt::CoordinateSystem system) const5603 QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
5604 {
5605     if (system != Qt::DeviceCoordinates)
5606         return m_widget->rect();
5607 
5608     if (Q_UNLIKELY(!context)) {
5609         // Device coordinates without context not yet supported.
5610         qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
5611         return QRectF();
5612     }
5613 
5614     return context->painter->worldTransform().mapRect(m_widget->rect());
5615 }
5616 
draw(QPainter * painter)5617 void QWidgetEffectSourcePrivate::draw(QPainter *painter)
5618 {
5619     if (!context || context->painter != painter) {
5620         m_widget->render(painter);
5621         return;
5622     }
5623 
5624     // The region saved in the context is neither clipped to the rect
5625     // nor the mask, so we have to clip it here before calling drawWidget.
5626     QRegion toBePainted = context->rgn;
5627     toBePainted &= m_widget->rect();
5628     QWidgetPrivate *wd = qt_widget_private(m_widget);
5629     if (wd->extra && wd->extra->hasMask)
5630         toBePainted &= wd->extra->mask;
5631 
5632     wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags,
5633                    context->sharedPainter, context->repaintManager);
5634 }
5635 
pixmap(Qt::CoordinateSystem system,QPoint * offset,QGraphicsEffect::PixmapPadMode mode) const5636 QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
5637                                            QGraphicsEffect::PixmapPadMode mode) const
5638 {
5639     const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
5640     if (Q_UNLIKELY(!context && deviceCoordinates)) {
5641         // Device coordinates without context not yet supported.
5642         qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
5643         return QPixmap();
5644     }
5645 
5646     QPoint pixmapOffset;
5647     QRectF sourceRect = m_widget->rect();
5648 
5649     if (deviceCoordinates) {
5650         const QTransform &painterTransform = context->painter->worldTransform();
5651         sourceRect = painterTransform.mapRect(sourceRect);
5652         pixmapOffset = painterTransform.map(pixmapOffset);
5653     }
5654 
5655     QRect effectRect;
5656 
5657     if (mode == QGraphicsEffect::PadToEffectiveBoundingRect)
5658         effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
5659     else if (mode == QGraphicsEffect::PadToTransparentBorder)
5660         effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect();
5661     else
5662         effectRect = sourceRect.toAlignedRect();
5663 
5664     if (offset)
5665         *offset = effectRect.topLeft();
5666 
5667     pixmapOffset -= effectRect.topLeft();
5668 
5669     qreal dpr(1.0);
5670     if (const auto *paintDevice = context->painter->device())
5671         dpr = paintDevice->devicePixelRatioF();
5672     else
5673         qWarning("QWidgetEffectSourcePrivate::pixmap: Painter not active");
5674     QPixmap pixmap(effectRect.size() * dpr);
5675     pixmap.setDevicePixelRatio(dpr);
5676 
5677     pixmap.fill(Qt::transparent);
5678     m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren);
5679     return pixmap;
5680 }
5681 #endif // QT_CONFIG(graphicseffect)
5682 
5683 #if QT_CONFIG(graphicsview)
5684 /*!
5685     \internal
5686 
5687     Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
5688     widget and its ancestors. The search starts at \a origin (inclusive).
5689     If successful, the function returns the proxy that embeds the widget, or \nullptr if no
5690     embedded widget was found.
5691 */
nearestGraphicsProxyWidget(const QWidget * origin)5692 QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
5693 {
5694     if (origin) {
5695         const auto &extra = origin->d_func()->extra;
5696         if (extra && extra->proxyWidget)
5697             return extra->proxyWidget;
5698         return nearestGraphicsProxyWidget(origin->parentWidget());
5699     }
5700     return nullptr;
5701 }
5702 #endif
5703 
5704 /*!
5705     \property QWidget::locale
5706     \brief the widget's locale
5707     \since 4.3
5708 
5709     As long as no special locale has been set, this is either
5710     the parent's locale or (if this widget is a top level widget),
5711     the default locale.
5712 
5713     If the widget displays dates or numbers, these should be formatted
5714     using the widget's locale.
5715 
5716     \sa QLocale, QLocale::setDefault()
5717 */
5718 
setLocale_helper(const QLocale & loc,bool forceUpdate)5719 void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
5720 {
5721     Q_Q(QWidget);
5722     if (locale == loc && !forceUpdate)
5723         return;
5724 
5725     locale = loc;
5726 
5727     if (!children.isEmpty()) {
5728         for (int i = 0; i < children.size(); ++i) {
5729             QWidget *w = qobject_cast<QWidget*>(children.at(i));
5730             if (!w)
5731                 continue;
5732             if (w->testAttribute(Qt::WA_SetLocale))
5733                 continue;
5734             if (w->isWindow() && !w->testAttribute(Qt::WA_WindowPropagation))
5735                 continue;
5736             w->d_func()->setLocale_helper(loc, forceUpdate);
5737         }
5738     }
5739     QEvent e(QEvent::LocaleChange);
5740     QCoreApplication::sendEvent(q, &e);
5741 }
5742 
setLocale(const QLocale & locale)5743 void QWidget::setLocale(const QLocale &locale)
5744 {
5745     Q_D(QWidget);
5746 
5747     setAttribute(Qt::WA_SetLocale);
5748     d->setLocale_helper(locale);
5749 }
5750 
locale() const5751 QLocale QWidget::locale() const
5752 {
5753     Q_D(const QWidget);
5754 
5755     return d->locale;
5756 }
5757 
resolveLocale()5758 void QWidgetPrivate::resolveLocale()
5759 {
5760     Q_Q(const QWidget);
5761 
5762     if (!q->testAttribute(Qt::WA_SetLocale)) {
5763         QWidget *parent = q->parentWidget();
5764         setLocale_helper(!parent || (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
5765                          ? QLocale() : parent->locale());
5766     }
5767 }
5768 
unsetLocale()5769 void QWidget::unsetLocale()
5770 {
5771     Q_D(QWidget);
5772     setAttribute(Qt::WA_SetLocale, false);
5773     d->resolveLocale();
5774 }
5775 
5776 /*!
5777     \property QWidget::windowTitle
5778     \brief the window title (caption)
5779 
5780     This property only makes sense for top-level widgets, such as
5781     windows and dialogs. If no caption has been set, the title is based of the
5782     \l windowFilePath. If neither of these is set, then the title is
5783     an empty string.
5784 
5785     If you use the \l windowModified mechanism, the window title must
5786     contain a "[*]" placeholder, which indicates where the '*' should
5787     appear. Normally, it should appear right after the file name
5788     (e.g., "document1.txt[*] - Text Editor"). If the \l
5789     windowModified property is \c false (the default), the placeholder
5790     is simply removed.
5791 
5792     On some desktop platforms (including Windows and Unix), the application name
5793     (from QGuiApplication::applicationDisplayName) is added at the end of the
5794     window title, if set. This is done by the QPA plugin, so it is shown to the
5795     user, but isn't part of the windowTitle string.
5796 
5797     \sa windowIcon, windowModified, windowFilePath
5798 */
windowTitle() const5799 QString QWidget::windowTitle() const
5800 {
5801     Q_D(const QWidget);
5802     if (d->extra && d->extra->topextra) {
5803         if (!d->extra->topextra->caption.isEmpty())
5804             return d->extra->topextra->caption;
5805         if (!d->extra->topextra->filePath.isEmpty())
5806             return QFileInfo(d->extra->topextra->filePath).fileName() + QLatin1String("[*]");
5807     }
5808     return QString();
5809 }
5810 
5811 /*!
5812     Returns a modified window title with the [*] place holder
5813     replaced according to the rules described in QWidget::setWindowTitle
5814 
5815     This function assumes that "[*]" can be quoted by another
5816     "[*]", so it will replace two place holders by one and
5817     a single last one by either "*" or nothing depending on
5818     the modified flag.
5819 
5820     \internal
5821 */
qt_setWindowTitle_helperHelper(const QString & title,const QWidget * widget)5822 QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
5823 {
5824     Q_ASSERT(widget);
5825 
5826     QString cap = title;
5827     if (cap.isEmpty())
5828         return cap;
5829 
5830     QLatin1String placeHolder("[*]");
5831     int index = cap.indexOf(placeHolder);
5832 
5833     // here the magic begins
5834     while (index != -1) {
5835         index += placeHolder.size();
5836         int count = 1;
5837         while (cap.indexOf(placeHolder, index) == index) {
5838             ++count;
5839             index += placeHolder.size();
5840         }
5841 
5842         if (count%2) { // odd number of [*] -> replace last one
5843             int lastIndex = cap.lastIndexOf(placeHolder, index - 1);
5844             if (widget->isWindowModified()
5845              && widget->style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, nullptr, widget))
5846                 cap.replace(lastIndex, 3, QWidget::tr("*"));
5847             else
5848                 cap.remove(lastIndex, 3);
5849         }
5850 
5851         index = cap.indexOf(placeHolder, index);
5852     }
5853 
5854     cap.replace(QLatin1String("[*][*]"), placeHolder);
5855 
5856     return cap;
5857 }
5858 
setWindowTitle_helper(const QString & title)5859 void QWidgetPrivate::setWindowTitle_helper(const QString &title)
5860 {
5861     Q_Q(QWidget);
5862     if (q->testAttribute(Qt::WA_WState_Created))
5863         setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, q));
5864 }
5865 
setWindowTitle_sys(const QString & caption)5866 void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
5867 {
5868     Q_Q(QWidget);
5869     if (!q->isWindow())
5870         return;
5871 
5872     if (QWindow *window = q->windowHandle())
5873         window->setTitle(caption);
5874 
5875 }
5876 
setWindowIconText_helper(const QString & title)5877 void QWidgetPrivate::setWindowIconText_helper(const QString &title)
5878 {
5879     Q_Q(QWidget);
5880     if (q->testAttribute(Qt::WA_WState_Created))
5881         setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, q));
5882 }
5883 
setWindowIconText_sys(const QString & iconText)5884 void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
5885 {
5886     Q_Q(QWidget);
5887     // ### The QWidget property is deprecated, but the XCB window function is not.
5888     // It should remain available for the rare application that needs it.
5889     if (QWindow *window = q->windowHandle())
5890         QXcbWindowFunctions::setWmWindowIconText(window, iconText);
5891 }
5892 
5893 /*!
5894     \fn void QWidget::windowIconTextChanged(const QString &iconText)
5895 
5896     This signal is emitted when the window's icon text has changed, with the
5897     new \a iconText as an argument.
5898 
5899     \since 5.2
5900     \obsolete
5901 
5902     This signal is deprecated.
5903 */
5904 
setWindowIconText(const QString & iconText)5905 void QWidget::setWindowIconText(const QString &iconText)
5906 {
5907     if (QWidget::windowIconText() == iconText)
5908         return;
5909 
5910     Q_D(QWidget);
5911     d->topData()->iconText = iconText;
5912     d->setWindowIconText_helper(iconText);
5913 
5914     QEvent e(QEvent::IconTextChange);
5915     QCoreApplication::sendEvent(this, &e);
5916 
5917     emit windowIconTextChanged(iconText);
5918 }
5919 
5920 /*!
5921     \fn void QWidget::windowTitleChanged(const QString &title)
5922 
5923     This signal is emitted when the window's title has changed, with the
5924     new \a title as an argument.
5925 
5926     \since 5.2
5927 */
5928 
setWindowTitle(const QString & title)5929 void QWidget::setWindowTitle(const QString &title)
5930 {
5931     if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
5932         return;
5933 
5934     Q_D(QWidget);
5935     d->topData()->caption = title;
5936     d->setWindowTitle_helper(title);
5937 
5938     QEvent e(QEvent::WindowTitleChange);
5939     QCoreApplication::sendEvent(this, &e);
5940 
5941     emit windowTitleChanged(title);
5942 }
5943 
5944 
5945 /*!
5946     \property QWidget::windowIcon
5947     \brief the widget's icon
5948 
5949     This property only makes sense for windows. If no icon
5950     has been set, windowIcon() returns the application icon
5951     (QApplication::windowIcon()).
5952 
5953     \note On \macos, window icons represent the active document,
5954     and will not be displayed unless a file path has also been
5955     set using setWindowFilePath.
5956 
5957     \sa windowTitle, setWindowFilePath
5958 */
windowIcon() const5959 QIcon QWidget::windowIcon() const
5960 {
5961     const QWidget *w = this;
5962     while (w) {
5963         const QWidgetPrivate *d = w->d_func();
5964         if (d->extra && d->extra->topextra && d->extra->topextra->icon)
5965             return *d->extra->topextra->icon;
5966         w = w->parentWidget();
5967     }
5968     return QApplication::windowIcon();
5969 }
5970 
setWindowIcon_helper()5971 void QWidgetPrivate::setWindowIcon_helper()
5972 {
5973     Q_Q(QWidget);
5974     QEvent e(QEvent::WindowIconChange);
5975 
5976     // Do not send the event if the widget is a top level.
5977     // In that case, setWindowIcon_sys does it, and event propagation from
5978     // QWidgetWindow to the top level QWidget ensures that the event reaches
5979     // the top level anyhow
5980     if (!q->windowHandle())
5981         QCoreApplication::sendEvent(q, &e);
5982     for (int i = 0; i < children.size(); ++i) {
5983         QWidget *w = qobject_cast<QWidget *>(children.at(i));
5984         if (w && !w->isWindow())
5985             QCoreApplication::sendEvent(w, &e);
5986     }
5987 }
5988 
5989 /*!
5990     \fn void QWidget::windowIconChanged(const QIcon &icon)
5991 
5992     This signal is emitted when the window's icon has changed, with the
5993     new \a icon as an argument.
5994 
5995     \since 5.2
5996 */
5997 
setWindowIcon(const QIcon & icon)5998 void QWidget::setWindowIcon(const QIcon &icon)
5999 {
6000     Q_D(QWidget);
6001 
6002     setAttribute(Qt::WA_SetWindowIcon, !icon.isNull());
6003     d->createTLExtra();
6004 
6005     if (!d->extra->topextra->icon)
6006         d->extra->topextra->icon = qt_make_unique<QIcon>(icon);
6007     else
6008         *d->extra->topextra->icon = icon;
6009 
6010     d->setWindowIcon_sys();
6011     d->setWindowIcon_helper();
6012 
6013     emit windowIconChanged(icon);
6014 }
6015 
setWindowIcon_sys()6016 void QWidgetPrivate::setWindowIcon_sys()
6017 {
6018     Q_Q(QWidget);
6019     if (QWindow *window = q->windowHandle())
6020         window->setIcon(q->windowIcon());
6021 }
6022 
6023 /*!
6024     \property QWidget::windowIconText
6025     \brief the text to be displayed on the icon of a minimized window
6026 
6027     This property only makes sense for windows. If no icon
6028     text has been set, this accessor returns an empty string.
6029     It is only implemented on the X11 platform, and only certain
6030     window managers use this window property.
6031 
6032     \obsolete
6033     This property is deprecated.
6034 
6035     \sa windowIcon, windowTitle
6036 */
6037 
windowIconText() const6038 QString QWidget::windowIconText() const
6039 {
6040     Q_D(const QWidget);
6041     return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
6042 }
6043 
6044 /*!
6045     \property QWidget::windowFilePath
6046     \since 4.4
6047     \brief the file path associated with a widget
6048 
6049     This property only makes sense for windows. It associates a file path with
6050     a window. If you set the file path, but have not set the window title, Qt
6051     sets the window title to the file name of the specified path, obtained using
6052     QFileInfo::fileName().
6053 
6054     If the window title is set at any point, then the window title takes precedence and
6055     will be shown instead of the file path string.
6056 
6057     Additionally, on \macos, this has an added benefit that it sets the
6058     \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
6059     for the window, assuming that the file path exists.
6060 
6061     If no file path is set, this property contains an empty string.
6062 
6063     By default, this property contains an empty string.
6064 
6065     \sa windowTitle, windowIcon
6066 */
6067 
windowFilePath() const6068 QString QWidget::windowFilePath() const
6069 {
6070     Q_D(const QWidget);
6071     return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
6072 }
6073 
setWindowFilePath(const QString & filePath)6074 void QWidget::setWindowFilePath(const QString &filePath)
6075 {
6076     if (filePath == windowFilePath())
6077         return;
6078 
6079     Q_D(QWidget);
6080 
6081     d->createTLExtra();
6082     d->extra->topextra->filePath = filePath;
6083     d->setWindowFilePath_helper(filePath);
6084 }
6085 
setWindowFilePath_helper(const QString & filePath)6086 void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
6087 {
6088     if (extra->topextra && extra->topextra->caption.isEmpty()) {
6089 #ifdef Q_OS_MAC
6090         setWindowTitle_helper(QFileInfo(filePath).fileName());
6091 #else
6092         Q_Q(QWidget);
6093         Q_UNUSED(filePath);
6094         setWindowTitle_helper(q->windowTitle());
6095 #endif
6096     }
6097 #ifdef Q_OS_MAC
6098     setWindowFilePath_sys(filePath);
6099 #endif
6100 }
6101 
setWindowFilePath_sys(const QString & filePath)6102 void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
6103 {
6104     Q_Q(QWidget);
6105     if (!q->isWindow())
6106         return;
6107 
6108     if (QWindow *window = q->windowHandle())
6109         window->setFilePath(filePath);
6110 }
6111 
6112 /*!
6113     Returns the window's role, or an empty string.
6114 
6115     \sa windowIcon, windowTitle
6116 */
6117 
windowRole() const6118 QString QWidget::windowRole() const
6119 {
6120     Q_D(const QWidget);
6121     return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
6122 }
6123 
6124 /*!
6125     Sets the window's role to \a role. This only makes sense for
6126     windows on X11.
6127 */
setWindowRole(const QString & role)6128 void QWidget::setWindowRole(const QString &role)
6129 {
6130     Q_D(QWidget);
6131     d->createTLExtra();
6132     d->topData()->role = role;
6133     if (windowHandle())
6134         QXcbWindowFunctions::setWmWindowRole(windowHandle(), role.toLatin1());
6135 }
6136 
6137 /*!
6138     \property QWidget::mouseTracking
6139     \brief whether mouse tracking is enabled for the widget
6140 
6141     If mouse tracking is disabled (the default), the widget only
6142     receives mouse move events when at least one mouse button is
6143     pressed while the mouse is being moved.
6144 
6145     If mouse tracking is enabled, the widget receives mouse move
6146     events even if no buttons are pressed.
6147 
6148     \sa mouseMoveEvent()
6149 */
6150 
6151 /*!
6152     \property QWidget::tabletTracking
6153     \brief whether tablet tracking is enabled for the widget
6154     \since 5.9
6155 
6156     If tablet tracking is disabled (the default), the widget only
6157     receives tablet move events when the stylus is in contact with
6158     the tablet, or at least one stylus button is pressed,
6159     while the stylus is being moved.
6160 
6161     If tablet tracking is enabled, the widget receives tablet move
6162     events even while hovering in proximity.  This is useful for
6163     monitoring position as well as the auxiliary properties such
6164     as rotation and tilt, and providing feedback in the UI.
6165 
6166     \sa tabletEvent()
6167 */
6168 
6169 
6170 /*!
6171     Sets the widget's focus proxy to widget \a w. If \a w is \nullptr, the
6172     function resets this widget to have no focus proxy.
6173 
6174     Some widgets can "have focus", but create a child widget, such as
6175     QLineEdit, to actually handle the focus. In this case, the widget
6176     can set the line edit to be its focus proxy.
6177 
6178     setFocusProxy() sets the widget which will actually get focus when
6179     "this widget" gets it. If there is a focus proxy, setFocus() and
6180     hasFocus() operate on the focus proxy. If "this widget" is the focus
6181     widget, then setFocusProxy() moves focus to the new focus proxy.
6182 
6183     \sa focusProxy()
6184 */
6185 
setFocusProxy(QWidget * w)6186 void QWidget::setFocusProxy(QWidget * w)
6187 {
6188     Q_D(QWidget);
6189     if (!w && !d->extra)
6190         return;
6191 
6192     for (QWidget* fp  = w; fp; fp = fp->focusProxy()) {
6193         if (Q_UNLIKELY(fp == this)) {
6194             qWarning("QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
6195             return;
6196         }
6197     }
6198 
6199     const bool moveFocusToProxy = (QApplicationPrivate::focus_widget == this);
6200 
6201     d->createExtra();
6202     d->extra->focus_proxy = w;
6203 
6204     if (moveFocusToProxy)
6205         setFocus(Qt::OtherFocusReason);
6206 }
6207 
6208 
6209 /*!
6210     Returns the focus proxy, or \nullptr if there is no focus proxy.
6211 
6212     \sa setFocusProxy()
6213 */
6214 
focusProxy() const6215 QWidget *QWidget::focusProxy() const
6216 {
6217     Q_D(const QWidget);
6218     return d->extra ? d->extra->focus_proxy.data() : nullptr;
6219 }
6220 
6221 
6222 /*!
6223     \property QWidget::focus
6224     \brief whether this widget (or its focus proxy) has the keyboard
6225     input focus
6226 
6227     By default, this property is \c false.
6228 
6229     \note Obtaining the value of this property for a widget is effectively equivalent
6230     to checking whether QApplication::focusWidget() refers to the widget.
6231 
6232     \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
6233 */
hasFocus() const6234 bool QWidget::hasFocus() const
6235 {
6236     const QWidget* w = this;
6237     while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
6238         w = w->d_func()->extra->focus_proxy;
6239 #if QT_CONFIG(graphicsview)
6240     if (QWidget *window = w->window()) {
6241         const auto &e = window->d_func()->extra;
6242         if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
6243             return true;
6244     }
6245 #endif // QT_CONFIG(graphicsview)
6246     return (QApplication::focusWidget() == w);
6247 }
6248 
6249 /*!
6250     Gives the keyboard input focus to this widget (or its focus
6251     proxy) if this widget or one of its parents is the \l{isActiveWindow()}{active window}. The \a reason argument will
6252     be passed into any focus event sent from this function, it is used
6253     to give an explanation of what caused the widget to get focus.
6254     If the window is not active, the widget will be given the focus when
6255     the window becomes active.
6256 
6257     First, a focus about to change event is sent to the focus widget (if any) to
6258     tell it that it is about to lose the focus. Then focus is changed, a
6259     focus out event is sent to the previous focus item and a focus in event is sent
6260     to the new item to tell it that it just received the focus.
6261     (Nothing happens if the focus in and focus out widgets are the
6262     same.)
6263 
6264     \note On embedded platforms, setFocus() will not cause an input panel
6265     to be opened by the input method. If you want this to happen, you
6266     have to send a QEvent::RequestSoftwareInputPanel event to the
6267     widget yourself.
6268 
6269     setFocus() gives focus to a widget regardless of its focus policy,
6270     but does not clear any keyboard grab (see grabKeyboard()).
6271 
6272     Be aware that if the widget is hidden, it will not accept focus
6273     until it is shown.
6274 
6275     \warning If you call setFocus() in a function which may itself be
6276     called from focusOutEvent() or focusInEvent(), you may get an
6277     infinite recursion.
6278 
6279     \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
6280     setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
6281     grabMouse(), {Keyboard Focus in Widgets}, QEvent::RequestSoftwareInputPanel
6282 */
6283 
setFocus(Qt::FocusReason reason)6284 void QWidget::setFocus(Qt::FocusReason reason)
6285 {
6286     if (!isEnabled())
6287         return;
6288 
6289     QWidget *f = d_func()->deepestFocusProxy();
6290     if (!f)
6291         f = this;
6292 
6293     if (QApplication::focusWidget() == f)
6294         return;
6295 
6296 #if QT_CONFIG(graphicsview)
6297     QWidget *previousProxyFocus = nullptr;
6298     if (const auto &topData = window()->d_func()->extra) {
6299         if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
6300             previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
6301             if (previousProxyFocus && previousProxyFocus->focusProxy())
6302                 previousProxyFocus = previousProxyFocus->focusProxy();
6303             if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
6304                 return;
6305         }
6306     }
6307 #endif
6308 
6309 #if QT_CONFIG(graphicsview)
6310     // Update proxy state
6311     if (const auto &topData = window()->d_func()->extra) {
6312         if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
6313             f->d_func()->updateFocusChild();
6314             topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
6315             topData->proxyWidget->setFocus(reason);
6316             topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
6317         }
6318     }
6319 #endif
6320 
6321     if (f->isActiveWindow()) {
6322         QWidget *prev = QApplicationPrivate::focus_widget;
6323         if (prev) {
6324             if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
6325                 && prev->testAttribute(Qt::WA_InputMethodEnabled)) {
6326                 QGuiApplication::inputMethod()->commit();
6327             }
6328 
6329             if (reason != Qt::NoFocusReason) {
6330                 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
6331                 QCoreApplication::sendEvent(prev, &focusAboutToChange);
6332             }
6333         }
6334 
6335         f->d_func()->updateFocusChild();
6336 
6337         QApplicationPrivate::setFocusWidget(f, reason);
6338 #ifndef QT_NO_ACCESSIBILITY
6339         // menus update the focus manually and this would create bogus events
6340         if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem")))
6341         {
6342             QAccessibleEvent event(f, QAccessible::Focus);
6343             QAccessible::updateAccessibility(&event);
6344         }
6345 #endif
6346 #if QT_CONFIG(graphicsview)
6347         if (const auto &topData = window()->d_func()->extra) {
6348             if (topData->proxyWidget) {
6349                 if (previousProxyFocus && previousProxyFocus != f) {
6350                     // Send event to self
6351                     QFocusEvent event(QEvent::FocusOut, reason);
6352                     QPointer<QWidget> that = previousProxyFocus;
6353                     QCoreApplication::sendEvent(previousProxyFocus, &event);
6354                     if (that)
6355                         QCoreApplication::sendEvent(that->style(), &event);
6356                 }
6357                 if (!isHidden()) {
6358 #if QT_CONFIG(graphicsview)
6359                     // Update proxy state
6360                     if (const auto &topData = window()->d_func()->extra)
6361                         if (topData->proxyWidget && topData->proxyWidget->hasFocus())
6362                             topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget();
6363 #endif
6364                     // Send event to self
6365                     QFocusEvent event(QEvent::FocusIn, reason);
6366                     QPointer<QWidget> that = f;
6367                     QCoreApplication::sendEvent(f, &event);
6368                     if (that)
6369                         QCoreApplication::sendEvent(that->style(), &event);
6370                 }
6371             }
6372         }
6373 #endif
6374     } else {
6375         f->d_func()->updateFocusChild();
6376     }
6377 }
6378 
6379 
6380 /*!\internal
6381  * A focus proxy can have its own focus proxy, which can have its own
6382  * proxy, and so on. This helper function returns the widget that sits
6383  * at the bottom of the proxy chain, and therefore the one that should
6384  * normally get focus if this widget receives a focus request.
6385  */
deepestFocusProxy() const6386 QWidget *QWidgetPrivate::deepestFocusProxy() const
6387 {
6388     Q_Q(const QWidget);
6389 
6390     QWidget *focusProxy = q->focusProxy();
6391     if (!focusProxy)
6392         return nullptr;
6393 
6394     while (QWidget *nextFocusProxy = focusProxy->focusProxy())
6395         focusProxy = nextFocusProxy;
6396 
6397     return focusProxy;
6398 }
6399 
isEmbedded(const QWindow * w)6400 static inline bool isEmbedded(const QWindow *w)
6401 {
6402      const auto platformWindow = w->handle();
6403      return platformWindow && platformWindow->isEmbedded();
6404 }
6405 
setFocus_sys()6406 void QWidgetPrivate::setFocus_sys()
6407 {
6408     Q_Q(QWidget);
6409     // Embedded native widget may have taken the focus; get it back to toplevel
6410     // if that is the case (QTBUG-25852)
6411     // Do not activate in case the popup menu opens another application (QTBUG-70810)
6412     // unless the application is embedded (QTBUG-71991).
6413     if (QWindow *nativeWindow = q->testAttribute(Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) {
6414         if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow()
6415             && (QGuiApplication::applicationState() == Qt::ApplicationActive
6416                 || QCoreApplication::testAttribute(Qt::AA_PluginApplication)
6417                 || isEmbedded(nativeWindow))) {
6418             nativeWindow->requestActivate();
6419         }
6420     }
6421 }
6422 
6423 // updates focus_child on parent widgets to point into this widget
updateFocusChild()6424 void QWidgetPrivate::updateFocusChild()
6425 {
6426     Q_Q(QWidget);
6427 
6428     QWidget *w = q;
6429     if (q->isHidden()) {
6430         while (w && w->isHidden()) {
6431             w->d_func()->focus_child = q;
6432             w = w->isWindow() ? nullptr : w->parentWidget();
6433         }
6434     } else {
6435         while (w) {
6436             w->d_func()->focus_child = q;
6437             w = w->isWindow() ? nullptr : w->parentWidget();
6438         }
6439     }
6440 
6441     if (QTLWExtra *extra = q->window()->d_func()->maybeTopData()) {
6442         if (extra->window)
6443             emit extra->window->focusObjectChanged(q);
6444     }
6445 }
6446 
6447 /*!
6448     \fn void QWidget::setFocus()
6449     \overload
6450 
6451     Gives the keyboard input focus to this widget (or its focus
6452     proxy) if this widget or one of its parents is the
6453     \l{isActiveWindow()}{active window}.
6454 */
6455 
6456 /*!
6457     Takes keyboard input focus from the widget.
6458 
6459     If the widget has active focus, a \l{focusOutEvent()}{focus out event} is sent to this widget to tell it that it has
6460     lost the focus.
6461 
6462     This widget must enable focus setting in order to get the keyboard
6463     input focus, i.e. it must call setFocusPolicy().
6464 
6465     \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
6466     setFocusPolicy(), QApplication::focusWidget()
6467 */
6468 
clearFocus()6469 void QWidget::clearFocus()
6470 {
6471     if (hasFocus()) {
6472         if (testAttribute(Qt::WA_InputMethodEnabled))
6473             QGuiApplication::inputMethod()->commit();
6474 
6475         QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
6476         QCoreApplication::sendEvent(this, &focusAboutToChange);
6477     }
6478 
6479     QTLWExtra *extra = window()->d_func()->maybeTopData();
6480     QObject *originalFocusObject = (extra && extra->window) ? extra->window->focusObject() : nullptr;
6481 
6482     QWidget *w = this;
6483     while (w) {
6484         // Just like setFocus(), we update (clear) the focus_child of our parents
6485         if (w->d_func()->focus_child == this)
6486             w->d_func()->focus_child = nullptr;
6487         w = w->parentWidget();
6488     }
6489 
6490     // We've potentially cleared the focus_child of our parents, so we need
6491     // to report this to the rest of Qt. Note that the focus_child is not the same
6492     // thing as the application's focusWidget, which is why this piece of code is
6493     // not inside a hasFocus() block.
6494     if (originalFocusObject && originalFocusObject != extra->window->focusObject())
6495         emit extra->window->focusObjectChanged(extra->window->focusObject());
6496 
6497 #if QT_CONFIG(graphicsview)
6498     const auto &topData = d_func()->extra;
6499     if (topData && topData->proxyWidget)
6500         topData->proxyWidget->clearFocus();
6501 #endif
6502 
6503     if (hasFocus()) {
6504         // Update proxy state
6505         QApplicationPrivate::setFocusWidget(nullptr, Qt::OtherFocusReason);
6506 #ifndef QT_NO_ACCESSIBILITY
6507         QAccessibleEvent event(this, QAccessible::Focus);
6508         QAccessible::updateAccessibility(&event);
6509 #endif
6510     }
6511 }
6512 
6513 
6514 /*!
6515     \fn bool QWidget::focusNextChild()
6516 
6517     Finds a new widget to give the keyboard focus to, as appropriate
6518     for \uicontrol Tab, and returns \c true if it can find a new widget, or
6519     false if it can't.
6520 
6521     \sa focusPreviousChild()
6522 */
6523 
6524 /*!
6525     \fn bool QWidget::focusPreviousChild()
6526 
6527     Finds a new widget to give the keyboard focus to, as appropriate
6528     for \uicontrol Shift+Tab, and returns \c true if it can find a new widget,
6529     or false if it can't.
6530 
6531     \sa focusNextChild()
6532 */
6533 
6534 /*!
6535     Finds a new widget to give the keyboard focus to, as appropriate
6536     for Tab and Shift+Tab, and returns \c true if it can find a new
6537     widget, or false if it can't.
6538 
6539     If \a next is true, this function searches forward, if \a next
6540     is false, it searches backward.
6541 
6542     Sometimes, you will want to reimplement this function. For
6543     example, a web browser might reimplement it to move its "current
6544     active link" forward or backward, and call
6545     focusNextPrevChild() only when it reaches the last or
6546     first link on the "page".
6547 
6548     Child widgets call focusNextPrevChild() on their parent widgets,
6549     but only the window that contains the child widgets decides where
6550     to redirect focus. By reimplementing this function for an object,
6551     you thus gain control of focus traversal for all child widgets.
6552 
6553     \sa focusNextChild(), focusPreviousChild()
6554 */
6555 
focusNextPrevChild(bool next)6556 bool QWidget::focusNextPrevChild(bool next)
6557 {
6558     QWidget* p = parentWidget();
6559     bool isSubWindow = (windowType() == Qt::SubWindow);
6560     if (!isWindow() && !isSubWindow && p)
6561         return p->focusNextPrevChild(next);
6562 #if QT_CONFIG(graphicsview)
6563     Q_D(QWidget);
6564     if (d->extra && d->extra->proxyWidget)
6565         return d->extra->proxyWidget->focusNextPrevChild(next);
6566 #endif
6567 
6568     bool wrappingOccurred = false;
6569     QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(this, next,
6570                                                                 &wrappingOccurred);
6571     if (!w) return false;
6572 
6573     Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
6574 
6575     /* If we are about to wrap the focus chain, give the platform
6576      * implementation a chance to alter the wrapping behavior.  This is
6577      * especially needed when the window is embedded in a window created by
6578      * another process.
6579      */
6580     if (wrappingOccurred) {
6581         QWindow *window = windowHandle();
6582         if (window != nullptr) {
6583             QWindowPrivate *winp = qt_window_private(window);
6584 
6585             if (winp->platformWindow != nullptr) {
6586                 QFocusEvent event(QEvent::FocusIn, reason);
6587                 event.ignore();
6588                 winp->platformWindow->windowEvent(&event);
6589                 if (event.isAccepted()) return true;
6590             }
6591         }
6592     }
6593 
6594     w->setFocus(reason);
6595     return true;
6596 }
6597 
6598 /*!
6599     Returns the last child of this widget that setFocus had been
6600     called on.  For top level widgets this is the widget that will get
6601     focus in case this window gets activated
6602 
6603     This is not the same as QApplication::focusWidget(), which returns
6604     the focus widget in the currently active window.
6605 */
6606 
focusWidget() const6607 QWidget *QWidget::focusWidget() const
6608 {
6609     return const_cast<QWidget *>(d_func()->focus_child);
6610 }
6611 
6612 /*!
6613     Returns the next widget in this widget's focus chain.
6614 
6615     \sa previousInFocusChain()
6616 */
nextInFocusChain() const6617 QWidget *QWidget::nextInFocusChain() const
6618 {
6619     return const_cast<QWidget *>(d_func()->focus_next);
6620 }
6621 
6622 /*!
6623     \brief The previousInFocusChain function returns the previous
6624     widget in this widget's focus chain.
6625 
6626     \sa nextInFocusChain()
6627 
6628     \since 4.6
6629 */
previousInFocusChain() const6630 QWidget *QWidget::previousInFocusChain() const
6631 {
6632     return const_cast<QWidget *>(d_func()->focus_prev);
6633 }
6634 
6635 /*!
6636     \property QWidget::isActiveWindow
6637     \brief whether this widget's window is the active window
6638 
6639     The active window is the window that contains the widget that has
6640     keyboard focus (The window may still have focus if it has no
6641     widgets or none of its widgets accepts keyboard focus).
6642 
6643     When popup windows are visible, this property is \c true for both the
6644     active window \e and for the popup.
6645 
6646     By default, this property is \c false.
6647 
6648     \sa activateWindow(), QApplication::activeWindow()
6649 */
isActiveWindow() const6650 bool QWidget::isActiveWindow() const
6651 {
6652     QWidget *tlw = window();
6653     if(tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
6654         return true;
6655 
6656 #if QT_CONFIG(graphicsview)
6657     if (const auto &tlwExtra = tlw->d_func()->extra) {
6658         if (isVisible() && tlwExtra->proxyWidget)
6659             return tlwExtra->proxyWidget->isActiveWindow();
6660     }
6661 #endif
6662 
6663     if (style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, this)) {
6664         if(tlw->windowType() == Qt::Tool &&
6665            !tlw->isModal() &&
6666            (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
6667            return true;
6668         QWidget *w = QApplication::activeWindow();
6669         while(w && tlw->windowType() == Qt::Tool &&
6670               !w->isModal() && w->parentWidget()) {
6671             w = w->parentWidget()->window();
6672             if(w == tlw)
6673                 return true;
6674         }
6675     }
6676 
6677     // Check for an active window container
6678     if (QWindow *ww = QGuiApplication::focusWindow()) {
6679         while (ww) {
6680             QWidgetWindow *qww = qobject_cast<QWidgetWindow *>(ww);
6681             QWindowContainer *qwc = qww ? qobject_cast<QWindowContainer *>(qww->widget()) : 0;
6682             if (qwc && qwc->topLevelWidget() == tlw)
6683                 return true;
6684             ww = ww->parent();
6685         }
6686     }
6687 
6688     // Check if platform adaptation thinks the window is active. This is necessary for
6689     // example in case of ActiveQt servers that are embedded into another application.
6690     // Those are separate processes that are not part of the parent application Qt window/widget
6691     // hierarchy, so they need to rely on native methods to determine if they are part of the
6692     // active window.
6693     if (const QWindow *w = tlw->windowHandle()) {
6694         if (w->handle())
6695             return w->handle()->isActive();
6696     }
6697 
6698     return false;
6699 }
6700 
6701 /*!
6702     Puts the \a second widget after the \a first widget in the focus order.
6703 
6704     It effectively removes the \a second widget from its focus chain and
6705     inserts it after the \a first widget.
6706 
6707     Note that since the tab order of the \a second widget is changed, you
6708     should order a chain like this:
6709 
6710     \snippet code/src_gui_kernel_qwidget.cpp 9
6711 
6712     \e not like this:
6713 
6714     \snippet code/src_gui_kernel_qwidget.cpp 10
6715 
6716     If \a first or \a second has a focus proxy, setTabOrder()
6717     correctly substitutes the proxy.
6718 
6719     \note Since Qt 5.10: A widget that has a child as focus proxy is understood as
6720     a compound widget. When setting a tab order between one or two compound widgets, the
6721     local tab order inside each will be preserved. This means that if both widgets are
6722     compound widgets, the resulting tab order will be from the last child inside
6723     \a first, to the first child inside \a second.
6724 
6725     \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
6726 */
setTabOrder(QWidget * first,QWidget * second)6727 void QWidget::setTabOrder(QWidget* first, QWidget *second)
6728 {
6729     if (!first || !second || first == second
6730             || first->focusPolicy() == Qt::NoFocus
6731             || second->focusPolicy() == Qt::NoFocus)
6732         return;
6733 
6734     if (Q_UNLIKELY(first->window() != second->window())) {
6735         qWarning("QWidget::setTabOrder: 'first' and 'second' must be in the same window");
6736         return;
6737     }
6738 
6739     auto determineLastFocusChild = [](QWidget *target, QWidget *&lastFocusChild)
6740     {
6741         // Since we need to repeat the same logic for both 'first' and 'second', we add a function that
6742         // determines the last focus child for a widget, taking proxies and compound widgets into account.
6743         // If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
6744         // 'lastFocusChild' will be set to the target itself.
6745         lastFocusChild = target;
6746 
6747         QWidget *focusProxy = target->d_func()->deepestFocusProxy();
6748         if (!focusProxy || !target->isAncestorOf(focusProxy))
6749             return;
6750 
6751         lastFocusChild = focusProxy;
6752 
6753         for (QWidget *focusNext = lastFocusChild->d_func()->focus_next;
6754              focusNext != focusProxy && target->isAncestorOf(focusNext) && focusNext->window() == focusProxy->window();
6755              focusNext = focusNext->d_func()->focus_next) {
6756             if (focusNext->focusPolicy() != Qt::NoFocus)
6757                 lastFocusChild = focusNext;
6758         }
6759     };
6760     auto setPrev = [](QWidget *w, QWidget *prev)
6761     {
6762         w->d_func()->focus_prev = prev;
6763     };
6764     auto setNext = [](QWidget *w, QWidget *next)
6765     {
6766         w->d_func()->focus_next = next;
6767     };
6768 
6769     // remove the second widget from the chain
6770     QWidget *lastFocusChildOfSecond;
6771     determineLastFocusChild(second, lastFocusChildOfSecond);
6772     {
6773         QWidget *oldPrev = second->d_func()->focus_prev;
6774         QWidget *prevWithFocus = oldPrev;
6775         while (prevWithFocus->focusPolicy() == Qt::NoFocus)
6776             prevWithFocus = prevWithFocus->d_func()->focus_prev;
6777         // only widgets between first and second -> all is fine
6778         if (prevWithFocus == first)
6779             return;
6780         QWidget *oldNext = lastFocusChildOfSecond->d_func()->focus_next;
6781         setPrev(oldNext, oldPrev);
6782         setNext(oldPrev, oldNext);
6783     }
6784 
6785     // insert the second widget into the chain
6786     QWidget *lastFocusChildOfFirst;
6787     determineLastFocusChild(first, lastFocusChildOfFirst);
6788     {
6789         QWidget *oldNext = lastFocusChildOfFirst->d_func()->focus_next;
6790         setPrev(second, lastFocusChildOfFirst);
6791         setNext(lastFocusChildOfFirst, second);
6792         setPrev(oldNext, lastFocusChildOfSecond);
6793         setNext(lastFocusChildOfSecond, oldNext);
6794     }
6795 }
6796 
6797 /*!\internal
6798 
6799   Moves the relevant subwidgets of this widget from the \a oldtlw's
6800   tab chain to that of the new parent, if there's anything to move and
6801   we're really moving
6802 
6803   This function is called from QWidget::reparent() *after* the widget
6804   has been reparented.
6805 
6806   \sa reparent()
6807 */
6808 
reparentFocusWidgets(QWidget * oldtlw)6809 void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
6810 {
6811     Q_Q(QWidget);
6812     if (oldtlw == q->window())
6813         return; // nothing to do
6814 
6815     if(focus_child)
6816         focus_child->clearFocus();
6817 
6818     // separate the focus chain into new (children of myself) and old (the rest)
6819     QWidget *firstOld = nullptr;
6820     //QWidget *firstNew = q; //invariant
6821     QWidget *o = nullptr; // last in the old list
6822     QWidget *n = q; // last in the new list
6823 
6824     bool prevWasNew = true;
6825     QWidget *w = focus_next;
6826 
6827     //Note: for efficiency, we do not maintain the list invariant inside the loop
6828     //we append items to the relevant list, and we optimize by not changing pointers
6829     //when subsequent items are going into the same list.
6830     while (w  != q) {
6831         bool currentIsNew =  q->isAncestorOf(w);
6832         if (currentIsNew) {
6833             if (!prevWasNew) {
6834                 //prev was old -- append to new list
6835                 n->d_func()->focus_next = w;
6836                 w->d_func()->focus_prev = n;
6837             }
6838             n = w;
6839         } else {
6840             if (prevWasNew) {
6841                 //prev was new -- append to old list, if there is one
6842                 if (o) {
6843                     o->d_func()->focus_next = w;
6844                     w->d_func()->focus_prev = o;
6845                 } else {
6846                     // "create" the old list
6847                     firstOld = w;
6848                 }
6849             }
6850             o = w;
6851         }
6852         w = w->d_func()->focus_next;
6853         prevWasNew = currentIsNew;
6854     }
6855 
6856     //repair the old list:
6857     if (firstOld) {
6858         o->d_func()->focus_next = firstOld;
6859         firstOld->d_func()->focus_prev = o;
6860     }
6861 
6862     if (!q->isWindow()) {
6863         QWidget *topLevel = q->window();
6864         //insert new chain into toplevel's chain
6865 
6866         QWidget *prev = topLevel->d_func()->focus_prev;
6867 
6868         topLevel->d_func()->focus_prev = n;
6869         prev->d_func()->focus_next = q;
6870 
6871         focus_prev = prev;
6872         n->d_func()->focus_next = topLevel;
6873     } else {
6874         //repair the new list
6875             n->d_func()->focus_next = q;
6876             focus_prev = n;
6877     }
6878 
6879 }
6880 
6881 /*!\internal
6882 
6883   Measures the shortest distance from a point to a rect.
6884 
6885   This function is called from QDesktopwidget::screen(QPoint) to find the
6886   closest screen for a point.
6887   In directional KeypadNavigation, it is called to find the closest
6888   widget to the current focus widget center.
6889 */
pointToRect(const QPoint & p,const QRect & r)6890 int QWidgetPrivate::pointToRect(const QPoint &p, const QRect &r)
6891 {
6892     int dx = 0;
6893     int dy = 0;
6894     if (p.x() < r.left())
6895         dx = r.left() - p.x();
6896     else if (p.x() > r.right())
6897         dx = p.x() - r.right();
6898     if (p.y() < r.top())
6899         dy = r.top() - p.y();
6900     else if (p.y() > r.bottom())
6901         dy = p.y() - r.bottom();
6902     return dx + dy;
6903 }
6904 
6905 /*!
6906     \property QWidget::frameSize
6907     \brief the size of the widget including any window frame
6908 
6909     By default, this property contains a value that depends on the user's
6910     platform and screen geometry.
6911 */
frameSize() const6912 QSize QWidget::frameSize() const
6913 {
6914     Q_D(const QWidget);
6915     if (isWindow() && !(windowType() == Qt::Popup)) {
6916         QRect fs = d->frameStrut();
6917         return QSize(data->crect.width() + fs.left() + fs.right(),
6918                       data->crect.height() + fs.top() + fs.bottom());
6919     }
6920     return data->crect.size();
6921 }
6922 
6923 /*! \fn void QWidget::move(int x, int y)
6924 
6925     \overload
6926 
6927     This corresponds to move(QPoint(\a x, \a y)).
6928 */
6929 
move(const QPoint & p)6930 void QWidget::move(const QPoint &p)
6931 {
6932     Q_D(QWidget);
6933     setAttribute(Qt::WA_Moved);
6934     if (testAttribute(Qt::WA_WState_Created)) {
6935         if (isWindow())
6936             d->topData()->posIncludesFrame = false;
6937         d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
6938                        p.y() + geometry().y() - QWidget::y(),
6939                        width(), height(), true);
6940         d->setDirtyOpaqueRegion();
6941     } else {
6942         // no frame yet: see also QWidgetPrivate::fixPosIncludesFrame(), QWindowPrivate::PositionPolicy.
6943         if (isWindow())
6944             d->topData()->posIncludesFrame = true;
6945         data->crect.moveTopLeft(p); // no frame yet
6946         setAttribute(Qt::WA_PendingMoveEvent);
6947     }
6948 
6949     if (d->extra && d->extra->hasWindowContainer)
6950         QWindowContainer::parentWasMoved(this);
6951 }
6952 
6953 // move() was invoked with Qt::WA_WState_Created not set (frame geometry
6954 // unknown), that is, crect has a position including the frame.
6955 // If we can determine the frame strut, fix that and clear the flag.
6956 // FIXME: This does not play well with window states other than
6957 // Qt::WindowNoState, as we depend on calling setGeometry() on the
6958 // platform window after fixing up the position so that the new
6959 // geometry is reflected in the platform window, but when the frame
6960 // comes in after the window has been shown (e.g. maximized), we're
6961 // not in a position to do that kind of fixup.
fixPosIncludesFrame()6962 void QWidgetPrivate::fixPosIncludesFrame()
6963 {
6964     Q_Q(QWidget);
6965     if (QTLWExtra *te = maybeTopData()) {
6966         if (te->posIncludesFrame) {
6967             // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
6968             // example, in QGraphicsProxyWidget).
6969             if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
6970                 te->posIncludesFrame = 0;
6971             } else {
6972                 if (q->windowHandle() && q->windowHandle()->handle()) {
6973                     updateFrameStrut();
6974                     if (!q->data->fstrut_dirty) {
6975                         data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
6976                         te->posIncludesFrame = 0;
6977                     }
6978                 } // windowHandle()
6979             } // !WA_DontShowOnScreen
6980         } // posIncludesFrame
6981     } // QTLWExtra
6982 }
6983 
6984 /*! \fn void QWidget::resize(int w, int h)
6985     \overload
6986 
6987     This corresponds to resize(QSize(\a w, \a h)).
6988 */
6989 
resize(const QSize & s)6990 void QWidget::resize(const QSize &s)
6991 {
6992     Q_D(QWidget);
6993     setAttribute(Qt::WA_Resized);
6994     if (testAttribute(Qt::WA_WState_Created)) {
6995         d->fixPosIncludesFrame();
6996         d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
6997         d->setDirtyOpaqueRegion();
6998     } else {
6999         const auto oldRect = data->crect;
7000         data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize()));
7001         if (oldRect != data->crect)
7002             setAttribute(Qt::WA_PendingResizeEvent);
7003     }
7004 }
7005 
setGeometry(const QRect & r)7006 void QWidget::setGeometry(const QRect &r)
7007 {
7008     Q_D(QWidget);
7009     setAttribute(Qt::WA_Resized);
7010     setAttribute(Qt::WA_Moved);
7011     if (isWindow())
7012         d->topData()->posIncludesFrame = 0;
7013     if (testAttribute(Qt::WA_WState_Created)) {
7014         d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
7015         d->setDirtyOpaqueRegion();
7016     } else {
7017         const auto oldRect = data->crect;
7018         data->crect.setTopLeft(r.topLeft());
7019         data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
7020         if (oldRect != data->crect) {
7021             setAttribute(Qt::WA_PendingMoveEvent);
7022             setAttribute(Qt::WA_PendingResizeEvent);
7023         }
7024     }
7025 
7026     if (d->extra && d->extra->hasWindowContainer)
7027         QWindowContainer::parentWasMoved(this);
7028 }
7029 
setGeometry_sys(int x,int y,int w,int h,bool isMove)7030 void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
7031 {
7032     Q_Q(QWidget);
7033     if (extra) {                                // any size restrictions?
7034         w = qMin(w,extra->maxw);
7035         h = qMin(h,extra->maxh);
7036         w = qMax(w,extra->minw);
7037         h = qMax(h,extra->minh);
7038     }
7039 
7040     if (q->isWindow() && q->windowHandle()) {
7041         QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
7042         if (!integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)) {
7043             x = 0;
7044             y = 0;
7045             w = q->windowHandle()->width();
7046             h = q->windowHandle()->height();
7047         }
7048     }
7049 
7050     QPoint oldp = q->geometry().topLeft();
7051     QSize olds = q->size();
7052     QRect r(x, y, w, h);
7053 
7054     bool isResize = olds != r.size();
7055     if (!isMove)
7056         isMove = oldp != r.topLeft();
7057 
7058 
7059     // We only care about stuff that changes the geometry, or may
7060     // cause the window manager to change its state
7061     if (r.size() == olds && oldp == r.topLeft())
7062         return;
7063 
7064     if (!data.in_set_window_state) {
7065         q->data->window_state &= ~Qt::WindowMaximized;
7066         q->data->window_state &= ~Qt::WindowFullScreen;
7067         if (q->isWindow())
7068             topData()->normalGeometry = QRect(0, 0, -1, -1);
7069     }
7070 
7071     QPoint oldPos = q->pos();
7072     data.crect = r;
7073 
7074     bool needsShow = false;
7075 
7076     if (q->isWindow() || q->windowHandle()) {
7077         if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
7078             q->setAttribute(Qt::WA_OutsideWSRange, true);
7079             if (q->isVisible())
7080                 hide_sys();
7081             data.crect = QRect(x, y, w, h);
7082         } else if (q->testAttribute(Qt::WA_OutsideWSRange)) {
7083             q->setAttribute(Qt::WA_OutsideWSRange, false);
7084             needsShow = true;
7085         }
7086     }
7087 
7088     if (q->isVisible()) {
7089         if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
7090             if (QWindow *win = q->windowHandle()) {
7091                 if (q->isWindow()) {
7092                     if (isResize && !isMove)
7093                         win->resize(w, h);
7094                     else if (isMove && !isResize)
7095                         win->setPosition(x, y);
7096                     else
7097                         win->setGeometry(q->geometry());
7098                 } else {
7099                     QPoint posInNativeParent =  q->mapTo(q->nativeParentWidget(),QPoint());
7100                     win->setGeometry(QRect(posInNativeParent,r.size()));
7101                 }
7102 
7103                 if (needsShow)
7104                     show_sys();
7105             }
7106 
7107             if (!q->isWindow()) {
7108                 if (renderToTexture) {
7109                     QRegion updateRegion(q->geometry());
7110                     updateRegion += QRect(oldPos, olds);
7111                     q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
7112                 } else if (isMove && !isResize) {
7113                     moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
7114                 } else {
7115                     invalidateBackingStore_resizeHelper(oldPos, olds);
7116                 }
7117             }
7118         }
7119 
7120         if (isMove) {
7121             QMoveEvent e(q->pos(), oldPos);
7122             QCoreApplication::sendEvent(q, &e);
7123         }
7124         if (isResize) {
7125             QResizeEvent e(r.size(), olds);
7126             QCoreApplication::sendEvent(q, &e);
7127             if (q->windowHandle())
7128                 q->update();
7129         }
7130     } else { // not visible
7131         if (isMove && q->pos() != oldPos)
7132             q->setAttribute(Qt::WA_PendingMoveEvent, true);
7133         if (isResize)
7134             q->setAttribute(Qt::WA_PendingResizeEvent, true);
7135     }
7136 
7137 }
7138 
7139 /*!
7140     \since 4.2
7141     Saves the current geometry and state for top-level widgets.
7142 
7143     To save the geometry when the window closes, you can
7144     implement a close event like this:
7145 
7146     \snippet code/src_gui_kernel_qwidget.cpp 11
7147 
7148     See the \l{Window Geometry} documentation for an overview of geometry
7149     issues with windows.
7150 
7151     Use QMainWindow::saveState() to save the geometry and the state of
7152     toolbars and dock widgets.
7153 
7154     \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
7155 */
saveGeometry() const7156 QByteArray QWidget::saveGeometry() const
7157 {
7158     QByteArray array;
7159     QDataStream stream(&array, QIODevice::WriteOnly);
7160     stream.setVersion(QDataStream::Qt_4_0);
7161     const quint32 magicNumber = 0x1D9D0CB;
7162     // Version history:
7163     // - Qt 4.2 - 4.8.6, 5.0 - 5.3    : Version 1.0
7164     // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
7165     // - Qt 5.12 - today              : Version 3.0, save QWidget::geometry()
7166     quint16 majorVersion = 3;
7167     quint16 minorVersion = 0;
7168     const int screenNumber = QDesktopWidgetPrivate::screenNumber(this);
7169     stream << magicNumber
7170            << majorVersion
7171            << minorVersion
7172            << frameGeometry()
7173            << normalGeometry()
7174            << qint32(screenNumber)
7175            << quint8(windowState() & Qt::WindowMaximized)
7176            << quint8(windowState() & Qt::WindowFullScreen)
7177            << qint32(QDesktopWidgetPrivate::screenGeometry(screenNumber).width()) // added in 2.0
7178            << geometry(); // added in 3.0
7179     return array;
7180 }
7181 
checkRestoredGeometry(const QRect & availableGeometry,QRect * restoredGeometry,int frameHeight)7182 static void checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
7183                                   int frameHeight)
7184 {
7185     if (!restoredGeometry->intersects(availableGeometry)) {
7186         restoredGeometry->moveBottom(qMin(restoredGeometry->bottom(), availableGeometry.bottom()));
7187         restoredGeometry->moveLeft(qMax(restoredGeometry->left(), availableGeometry.left()));
7188         restoredGeometry->moveRight(qMin(restoredGeometry->right(), availableGeometry.right()));
7189     }
7190     restoredGeometry->moveTop(qMax(restoredGeometry->top(), availableGeometry.top() + frameHeight));
7191 }
7192 
7193 /*!
7194     \since 4.2
7195 
7196     Restores the geometry and state of top-level widgets stored in the
7197     byte array \a geometry. Returns \c true on success; otherwise
7198     returns \c false.
7199 
7200     If the restored geometry is off-screen, it will be modified to be
7201     inside the available screen geometry.
7202 
7203     To restore geometry saved using QSettings, you can use code like
7204     this:
7205 
7206     \snippet code/src_gui_kernel_qwidget.cpp 12
7207 
7208     See the \l{Window Geometry} documentation for an overview of geometry
7209     issues with windows.
7210 
7211     Use QMainWindow::restoreState() to restore the geometry and the
7212     state of toolbars and dock widgets.
7213 
7214     \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
7215 */
restoreGeometry(const QByteArray & geometry)7216 bool QWidget::restoreGeometry(const QByteArray &geometry)
7217 {
7218     if (geometry.size() < 4)
7219         return false;
7220     QDataStream stream(geometry);
7221     stream.setVersion(QDataStream::Qt_4_0);
7222 
7223     const quint32 magicNumber = 0x1D9D0CB;
7224     quint32 storedMagicNumber;
7225     stream >> storedMagicNumber;
7226     if (storedMagicNumber != magicNumber)
7227         return false;
7228 
7229     const quint16 currentMajorVersion = 3;
7230     quint16 majorVersion = 0;
7231     quint16 minorVersion = 0;
7232 
7233     stream >> majorVersion >> minorVersion;
7234 
7235     if (majorVersion > currentMajorVersion)
7236         return false;
7237     // (Allow all minor versions.)
7238 
7239     QRect restoredFrameGeometry;
7240     QRect restoredGeometry;
7241     QRect restoredNormalGeometry;
7242     qint32 restoredScreenNumber;
7243     quint8 maximized;
7244     quint8 fullScreen;
7245     qint32 restoredScreenWidth = 0;
7246 
7247     stream >> restoredFrameGeometry // Only used for sanity checks in version 0
7248            >> restoredNormalGeometry
7249            >> restoredScreenNumber
7250            >> maximized
7251            >> fullScreen;
7252 
7253     if (majorVersion > 1)
7254         stream >> restoredScreenWidth;
7255     if (majorVersion > 2)
7256         stream >> restoredGeometry;
7257 
7258     // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
7259 
7260     if (restoredScreenNumber >= QDesktopWidgetPrivate::numScreens())
7261         restoredScreenNumber = QDesktopWidgetPrivate::primaryScreen();
7262     const qreal screenWidthF = qreal(QDesktopWidgetPrivate::screenGeometry(restoredScreenNumber).width());
7263     // Sanity check bailing out when large variations of screen sizes occur due to
7264     // high DPI scaling or different levels of DPI awareness.
7265     if (restoredScreenWidth) {
7266         const qreal factor = qreal(restoredScreenWidth) / screenWidthF;
7267         if (factor < 0.8 || factor > 1.25)
7268             return false;
7269     } else {
7270         // Saved by Qt 5.3 and earlier, try to prevent too large windows
7271         // unless the size will be adapted by maximized or fullscreen.
7272         if (!maximized && !fullScreen && qreal(restoredFrameGeometry.width()) / screenWidthF > 1.5)
7273             return false;
7274     }
7275 
7276     const int frameHeight = 20;
7277 
7278     if (!restoredNormalGeometry.isValid())
7279         restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
7280     if (!restoredNormalGeometry.isValid()) {
7281         // use the widget's adjustedSize if the sizeHint() doesn't help
7282         restoredNormalGeometry.setSize(restoredNormalGeometry
7283                                        .size()
7284                                        .expandedTo(d_func()->adjustedSize()));
7285     }
7286 
7287     const QRect availableGeometry = QDesktopWidgetPrivate::availableGeometry(restoredScreenNumber);
7288 
7289     // Modify the restored geometry if we are about to restore to coordinates
7290     // that would make the window "lost". This happens if:
7291     // - The restored geometry is completely oustside the available geometry
7292     // - The title bar is outside the available geometry.
7293 
7294     checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight);
7295     checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight);
7296 
7297     if (maximized || fullScreen) {
7298         // set geometry before setting the window state to make
7299         // sure the window is maximized to the right screen.
7300         Qt::WindowStates ws = windowState();
7301 #ifndef Q_OS_WIN
7302         setGeometry(restoredNormalGeometry);
7303 #else
7304         if (ws & Qt::WindowFullScreen) {
7305             // Full screen is not a real window state on Windows.
7306             move(availableGeometry.topLeft());
7307         } else if (ws & Qt::WindowMaximized) {
7308             // Setting a geometry on an already maximized window causes this to be
7309             // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
7310             // Move the window in normal state if needed.
7311             if (restoredScreenNumber != QDesktopWidgetPrivate::screenNumber(this)) {
7312                 setWindowState(Qt::WindowNoState);
7313                 setGeometry(restoredNormalGeometry);
7314             }
7315         } else {
7316             setGeometry(restoredNormalGeometry);
7317         }
7318 #endif // Q_OS_WIN
7319         if (maximized)
7320             ws |= Qt::WindowMaximized;
7321         if (fullScreen)
7322             ws |= Qt::WindowFullScreen;
7323        setWindowState(ws);
7324        d_func()->topData()->normalGeometry = restoredNormalGeometry;
7325     } else {
7326         setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
7327         if (majorVersion > 2)
7328             setGeometry(restoredGeometry);
7329         else
7330             setGeometry(restoredNormalGeometry);
7331     }
7332     return true;
7333 }
7334 
7335 /*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
7336     \overload
7337 
7338     This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
7339 */
7340 
7341 /*!
7342   Sets the margins around the contents of the widget to have the sizes
7343   \a left, \a top, \a right, and \a bottom. The margins are used by
7344   the layout system, and may be used by subclasses to specify the area
7345   to draw in (e.g. excluding the frame).
7346 
7347   Changing the margins will trigger a resizeEvent().
7348 
7349   \sa contentsRect(), contentsMargins()
7350 */
setContentsMargins(int left,int top,int right,int bottom)7351 void QWidget::setContentsMargins(int left, int top, int right, int bottom)
7352 {
7353     Q_D(QWidget);
7354     if (left == d->leftmargin && top == d->topmargin
7355          && right == d->rightmargin && bottom == d->bottommargin)
7356         return;
7357     d->leftmargin = left;
7358     d->topmargin = top;
7359     d->rightmargin = right;
7360     d->bottommargin = bottom;
7361 
7362     d->updateContentsRect();
7363 }
7364 
7365 /*!
7366   \overload
7367   \since 4.6
7368 
7369   \brief The setContentsMargins function sets the margins around the
7370   widget's contents.
7371 
7372   Sets the margins around the contents of the widget to have the
7373   sizes determined by \a margins. The margins are
7374   used by the layout system, and may be used by subclasses to
7375   specify the area to draw in (e.g. excluding the frame).
7376 
7377   Changing the margins will trigger a resizeEvent().
7378 
7379   \sa contentsRect(), contentsMargins()
7380 */
setContentsMargins(const QMargins & margins)7381 void QWidget::setContentsMargins(const QMargins &margins)
7382 {
7383     setContentsMargins(margins.left(), margins.top(),
7384                        margins.right(), margins.bottom());
7385 }
7386 
updateContentsRect()7387 void QWidgetPrivate::updateContentsRect()
7388 {
7389     Q_Q(QWidget);
7390 
7391     if (layout)
7392         layout->update(); //force activate; will do updateGeometry
7393     else
7394         q->updateGeometry();
7395 
7396     if (q->isVisible()) {
7397         q->update();
7398         QResizeEvent e(q->data->crect.size(), q->data->crect.size());
7399         QCoreApplication::sendEvent(q, &e);
7400     } else {
7401         q->setAttribute(Qt::WA_PendingResizeEvent, true);
7402     }
7403 
7404     QEvent e(QEvent::ContentsRectChange);
7405     QCoreApplication::sendEvent(q, &e);
7406 }
7407 
7408 #if QT_DEPRECATED_SINCE(5, 14)
7409 /*!
7410     \obsolete
7411     Use contentsMargins().
7412 
7413   Returns the widget's contents margins for \a left, \a top, \a
7414   right, and \a bottom.
7415 
7416   \sa setContentsMargins(), contentsRect()
7417  */
getContentsMargins(int * left,int * top,int * right,int * bottom) const7418 void QWidget::getContentsMargins(int *left, int *top, int *right, int *bottom) const
7419 {
7420     QMargins m = contentsMargins();
7421     if (left)
7422         *left = m.left();
7423     if (top)
7424         *top = m.top();
7425     if (right)
7426         *right = m.right();
7427     if (bottom)
7428         *bottom = m.bottom();
7429 }
7430 #endif
7431 
7432 // FIXME: Move to qmargins.h for next minor Qt release
operator |(const QMargins & m1,const QMargins & m2)7433 QMargins operator|(const QMargins &m1, const QMargins &m2)
7434 {
7435     return QMargins(qMax(m1.left(), m2.left()), qMax(m1.top(), m2.top()),
7436         qMax(m1.right(), m2.right()), qMax(m1.bottom(), m2.bottom()));
7437 }
7438 
7439 /*!
7440   \since 4.6
7441 
7442   \brief The contentsMargins function returns the widget's contents margins.
7443 
7444   \sa setContentsMargins(), contentsRect()
7445  */
contentsMargins() const7446 QMargins QWidget::contentsMargins() const
7447 {
7448     Q_D(const QWidget);
7449     QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
7450     return testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea) ?
7451         userMargins | d->safeAreaMargins() : userMargins;
7452 }
7453 
7454 /*!
7455     Returns the area inside the widget's margins.
7456 
7457     \sa setContentsMargins(), contentsMargins()
7458 */
contentsRect() const7459 QRect QWidget::contentsRect() const
7460 {
7461     return rect() - contentsMargins();
7462 }
7463 
safeAreaMargins() const7464 QMargins QWidgetPrivate::safeAreaMargins() const
7465 {
7466     Q_Q(const QWidget);
7467     QWidget *nativeWidget = q->window();
7468     if (!nativeWidget->windowHandle())
7469         return QMargins();
7470 
7471     QPlatformWindow *platformWindow = nativeWidget->windowHandle()->handle();
7472     if (!platformWindow)
7473         return QMargins();
7474 
7475     QMargins safeAreaMargins = platformWindow->safeAreaMargins();
7476 
7477     if (!q->isWindow()) {
7478         // In theory the native parent widget already has a contents rect reflecting
7479         // the safe area of that widget, but we can't be sure that the widget or child
7480         // widgets of that widget have respected the contents rect when setting their
7481         // geometry, so we need to manually compute the safe area.
7482 
7483         // Unless the native widget doesn't have any margins, in which case there's
7484         // nothing for us to compute.
7485         if (safeAreaMargins.isNull())
7486             return QMargins();
7487 
7488         // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
7489         // set, then we know that the layout has already taken care of placing us inside the
7490         // safe area, by taking the contents rect of its parent widget into account.
7491         const QWidget *assumedSafeWidget = nullptr;
7492         for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
7493             QWidget *parentWidget = w->parentWidget();
7494             if (parentWidget->testAttribute(Qt::WA_LayoutOnEntireRect))
7495                 continue; // Layout not going to help us
7496 
7497             QLayout *layout = parentWidget->layout();
7498             if (!layout)
7499                 continue;
7500 
7501             if (layout->geometry().isNull())
7502                 continue; // Layout hasn't been activated yet
7503 
7504             if (layout->indexOf(const_cast<QWidget *>(w)) < 0)
7505                 continue; // Widget is not in layout
7506 
7507             assumedSafeWidget = w;
7508             break;
7509         }
7510 
7511 #if !defined(QT_DEBUG)
7512         if (assumedSafeWidget) {
7513             // We found a layout that we assume will take care of keeping us within the safe area
7514             // For debug builds we still map the safe area using the fallback logic, so that we
7515             // can detect any misbehaving layouts.
7516             return QMargins();
7517         }
7518 #endif
7519 
7520         // In all other cases we need to map the safe area of the native parent to the widget.
7521         // This depends on the widget being positioned and sized already, which means the initial
7522         // layout will be wrong, but the layout will then adjust itself.
7523         QPoint topLeftMargins = q->mapFrom(nativeWidget, QPoint(safeAreaMargins.left(), safeAreaMargins.top()));
7524         QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect();
7525         QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(nativeWidget,
7526             nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom()));
7527 
7528         // Margins should never be negative
7529         safeAreaMargins = QMargins(qMax(0, topLeftMargins.x()), qMax(0, topLeftMargins.y()),
7530             qMax(0, bottomRightMargins.x()), qMax(0, bottomRightMargins.y()));
7531 
7532         if (!safeAreaMargins.isNull() && assumedSafeWidget) {
7533             QLayout *layout = assumedSafeWidget->parentWidget()->layout();
7534             qWarning() << layout << "is laying out" << assumedSafeWidget
7535                 << "outside of the contents rect of" << layout->parentWidget();
7536             return QMargins(); // Return empty margin to visually highlight the error
7537         }
7538     }
7539 
7540     return safeAreaMargins;
7541 }
7542 
7543 /*!
7544   \fn void QWidget::customContextMenuRequested(const QPoint &pos)
7545 
7546   This signal is emitted when the widget's \l contextMenuPolicy is
7547   Qt::CustomContextMenu, and the user has requested a context menu on
7548   the widget. The position \a pos is the position of the context menu
7549   event that the widget receives. Normally this is in widget
7550   coordinates. The exception to this rule is QAbstractScrollArea and
7551   its subclasses that map the context menu event to coordinates of the
7552   \l{QAbstractScrollArea::viewport()}{viewport()}.
7553 
7554 
7555   \sa mapToGlobal(), QMenu, contextMenuPolicy
7556 */
7557 
7558 
7559 /*!
7560     \property QWidget::contextMenuPolicy
7561     \brief how the widget shows a context menu
7562 
7563     The default value of this property is Qt::DefaultContextMenu,
7564     which means the contextMenuEvent() handler is called. Other values
7565     are Qt::NoContextMenu, Qt::PreventContextMenu,
7566     Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
7567     Qt::CustomContextMenu, the signal customContextMenuRequested() is
7568     emitted.
7569 
7570     \sa contextMenuEvent(), customContextMenuRequested(), actions()
7571 */
7572 
contextMenuPolicy() const7573 Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
7574 {
7575     return (Qt::ContextMenuPolicy)data->context_menu_policy;
7576 }
7577 
setContextMenuPolicy(Qt::ContextMenuPolicy policy)7578 void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
7579 {
7580     data->context_menu_policy = (uint) policy;
7581 }
7582 
7583 /*!
7584     \property QWidget::focusPolicy
7585     \brief the way the widget accepts keyboard focus
7586 
7587     The policy is Qt::TabFocus if the widget accepts keyboard
7588     focus by tabbing, Qt::ClickFocus if the widget accepts
7589     focus by clicking, Qt::StrongFocus if it accepts both, and
7590     Qt::NoFocus (the default) if it does not accept focus at
7591     all.
7592 
7593     You must enable keyboard focus for a widget if it processes
7594     keyboard events. This is normally done from the widget's
7595     constructor. For instance, the QLineEdit constructor calls
7596     setFocusPolicy(Qt::StrongFocus).
7597 
7598     If the widget has a focus proxy, then the focus policy will
7599     be propagated to it.
7600 
7601     \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
7602 */
7603 
7604 
focusPolicy() const7605 Qt::FocusPolicy QWidget::focusPolicy() const
7606 {
7607     return (Qt::FocusPolicy)data->focus_policy;
7608 }
7609 
setFocusPolicy(Qt::FocusPolicy policy)7610 void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
7611 {
7612     data->focus_policy = (uint) policy;
7613     Q_D(QWidget);
7614     if (d->extra && d->extra->focus_proxy)
7615         d->extra->focus_proxy->setFocusPolicy(policy);
7616 }
7617 
7618 /*!
7619     \property QWidget::updatesEnabled
7620     \brief whether updates are enabled
7621 
7622     An updates enabled widget receives paint events and has a system
7623     background; a disabled widget does not. This also implies that
7624     calling update() and repaint() has no effect if updates are
7625     disabled.
7626 
7627     By default, this property is \c true.
7628 
7629     setUpdatesEnabled() is normally used to disable updates for a
7630     short period of time, for instance to avoid screen flicker during
7631     large changes. In Qt, widgets normally do not generate screen
7632     flicker, but on X11 the server might erase regions on the screen
7633     when widgets get hidden before they can be replaced by other
7634     widgets. Disabling updates solves this.
7635 
7636     Example:
7637     \snippet code/src_gui_kernel_qwidget.cpp 13
7638 
7639     Disabling a widget implicitly disables all its children. Enabling a widget
7640     enables all child widgets \e except top-level widgets or those that
7641     have been explicitly disabled. Re-enabling updates implicitly calls
7642     update() on the widget.
7643 
7644     \sa paintEvent()
7645 */
setUpdatesEnabled(bool enable)7646 void QWidget::setUpdatesEnabled(bool enable)
7647 {
7648     Q_D(QWidget);
7649     setAttribute(Qt::WA_ForceUpdatesDisabled, !enable);
7650     d->setUpdatesEnabled_helper(enable);
7651 }
7652 
7653 /*!
7654     Shows the widget and its child widgets.
7655 
7656     This is equivalent to calling showFullScreen(), showMaximized(), or setVisible(true),
7657     depending on the platform's default behavior for the window flags.
7658 
7659      \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
7660     showNormal(), isVisible(), windowFlags()
7661 */
show()7662 void QWidget::show()
7663 {
7664     Qt::WindowState defaultState = QGuiApplicationPrivate::platformIntegration()->defaultWindowState(data->window_flags);
7665     if (defaultState == Qt::WindowFullScreen)
7666         showFullScreen();
7667     else if (defaultState == Qt::WindowMaximized)
7668         showMaximized();
7669     else
7670         setVisible(true); // Don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
7671 }
7672 
7673 /*! \internal
7674 
7675    Makes the widget visible in the isVisible() meaning of the word.
7676    It is only called for toplevels or widgets with visible parents.
7677  */
show_recursive()7678 void QWidgetPrivate::show_recursive()
7679 {
7680     Q_Q(QWidget);
7681     // polish if necessary
7682 
7683     if (!q->testAttribute(Qt::WA_WState_Created))
7684         createRecursively();
7685     q->ensurePolished();
7686 
7687     if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
7688         q->parentWidget()->d_func()->layout->activate();
7689     // activate our layout before we and our children become visible
7690     if (layout)
7691         layout->activate();
7692 
7693     show_helper();
7694 }
7695 
sendPendingMoveAndResizeEvents(bool recursive,bool disableUpdates)7696 void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
7697 {
7698     Q_Q(QWidget);
7699 
7700     disableUpdates = disableUpdates && q->updatesEnabled();
7701     if (disableUpdates)
7702         q->setAttribute(Qt::WA_UpdatesDisabled);
7703 
7704     if (q->testAttribute(Qt::WA_PendingMoveEvent)) {
7705         QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
7706         QCoreApplication::sendEvent(q, &e);
7707         q->setAttribute(Qt::WA_PendingMoveEvent, false);
7708     }
7709 
7710     if (q->testAttribute(Qt::WA_PendingResizeEvent)) {
7711         QResizeEvent e(data.crect.size(), QSize());
7712         QCoreApplication::sendEvent(q, &e);
7713         q->setAttribute(Qt::WA_PendingResizeEvent, false);
7714     }
7715 
7716     if (disableUpdates)
7717         q->setAttribute(Qt::WA_UpdatesDisabled, false);
7718 
7719     if (!recursive)
7720         return;
7721 
7722     for (int i = 0; i < children.size(); ++i) {
7723         if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
7724             child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
7725     }
7726 }
7727 
activateChildLayoutsRecursively()7728 void QWidgetPrivate::activateChildLayoutsRecursively()
7729 {
7730     sendPendingMoveAndResizeEvents(false, true);
7731 
7732     for (int i = 0; i < children.size(); ++i) {
7733         QWidget *child = qobject_cast<QWidget *>(children.at(i));
7734         if (!child || child->isHidden() || child->isWindow())
7735             continue;
7736 
7737         child->ensurePolished();
7738 
7739         // Activate child's layout
7740         QWidgetPrivate *childPrivate = child->d_func();
7741         if (childPrivate->layout)
7742             childPrivate->layout->activate();
7743 
7744         // Pretend we're visible.
7745         const bool wasVisible = child->isVisible();
7746         if (!wasVisible)
7747             child->setAttribute(Qt::WA_WState_Visible);
7748 
7749         // Do the same for all my children.
7750         childPrivate->activateChildLayoutsRecursively();
7751 
7752         // We're not cheating anymore.
7753         if (!wasVisible)
7754             child->setAttribute(Qt::WA_WState_Visible, false);
7755     }
7756 }
7757 
show_helper()7758 void QWidgetPrivate::show_helper()
7759 {
7760     Q_Q(QWidget);
7761     data.in_show = true; // qws optimization
7762     // make sure we receive pending move and resize events
7763     sendPendingMoveAndResizeEvents();
7764 
7765     // become visible before showing all children
7766     q->setAttribute(Qt::WA_WState_Visible);
7767 
7768     // finally show all children recursively
7769     showChildren(false);
7770 
7771 
7772 
7773     const bool isWindow = q->isWindow();
7774 #if QT_CONFIG(graphicsview)
7775     bool isEmbedded = isWindow && q->graphicsProxyWidget() != nullptr;
7776 #else
7777     bool isEmbedded = false;
7778 #endif
7779 
7780     // popup handling: new popups and tools need to be raised, and
7781     // existing popups must be closed. Also propagate the current
7782     // windows's KeyboardFocusChange status.
7783     if (isWindow && !isEmbedded) {
7784         if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
7785             q->raise();
7786             if (q->parentWidget() && q->parentWidget()->window()->testAttribute(Qt::WA_KeyboardFocusChange))
7787                 q->setAttribute(Qt::WA_KeyboardFocusChange);
7788         } else {
7789             while (QApplication::activePopupWidget()) {
7790                 if (!QApplication::activePopupWidget()->close())
7791                     break;
7792             }
7793         }
7794     }
7795 
7796     // Automatic embedding of child windows of widgets already embedded into
7797     // QGraphicsProxyWidget when they are shown the first time.
7798 #if QT_CONFIG(graphicsview)
7799     if (isWindow) {
7800         if (!isEmbedded && !bypassGraphicsProxyWidget(q)) {
7801             QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(q->parentWidget());
7802             if (ancestorProxy) {
7803                 isEmbedded = true;
7804                 ancestorProxy->d_func()->embedSubWindow(q);
7805             }
7806         }
7807     }
7808 #else
7809     Q_UNUSED(isEmbedded);
7810 #endif
7811 
7812     // send the show event before showing the window
7813     QShowEvent showEvent;
7814     QCoreApplication::sendEvent(q, &showEvent);
7815 
7816     show_sys();
7817 
7818     if (!isEmbedded && q->windowType() == Qt::Popup)
7819         qApp->d_func()->openPopup(q);
7820 
7821 #ifndef QT_NO_ACCESSIBILITY
7822     if (q->windowType() != Qt::ToolTip) {    // Tooltips are read aloud twice in MS narrator.
7823         QAccessibleEvent event(q, QAccessible::ObjectShow);
7824         QAccessible::updateAccessibility(&event);
7825     }
7826 #endif
7827 
7828     if (QApplicationPrivate::hidden_focus_widget == q) {
7829         QApplicationPrivate::hidden_focus_widget = nullptr;
7830         q->setFocus(Qt::OtherFocusReason);
7831     }
7832 
7833     // Process events when showing a Qt::SplashScreen widget before the event loop
7834     // is spinnning; otherwise it might not show up on particular platforms.
7835     // This makes QSplashScreen behave the same on all platforms.
7836     if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
7837         QCoreApplication::processEvents();
7838 
7839     data.in_show = false;  // reset qws optimization
7840 }
7841 
show_sys()7842 void QWidgetPrivate::show_sys()
7843 {
7844     Q_Q(QWidget);
7845 
7846     auto window = qobject_cast<QWidgetWindow *>(windowHandle());
7847 
7848     if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
7849         invalidateBackingStore(q->rect());
7850         q->setAttribute(Qt::WA_Mapped);
7851         // add our window the modal window list (native dialogs)
7852         if (window && q->isWindow()
7853 #if QT_CONFIG(graphicsview)
7854             && (!extra || !extra->proxyWidget)
7855 #endif
7856             && q->windowModality() != Qt::NonModal) {
7857             QGuiApplicationPrivate::showModalWindow(window);
7858         }
7859         return;
7860     }
7861 
7862     if (renderToTexture && !q->isWindow())
7863         QCoreApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry()));
7864     else
7865         QCoreApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
7866 
7867     if ((!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
7868             || q->testAttribute(Qt::WA_OutsideWSRange)) {
7869         return;
7870     }
7871 
7872     if (window) {
7873         if (q->isWindow())
7874             fixPosIncludesFrame();
7875         QRect geomRect = q->geometry();
7876         if (!q->isWindow()) {
7877             QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint());
7878             geomRect.moveTopLeft(topLeftOfWindow);
7879         }
7880         const QRect windowRect = window->geometry();
7881         if (windowRect != geomRect) {
7882             if (q->testAttribute(Qt::WA_Moved)
7883                 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
7884                 window->setGeometry(geomRect);
7885             else
7886                 window->resize(geomRect.size());
7887         }
7888 
7889 #ifndef QT_NO_CURSOR
7890         qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
7891 #endif
7892         invalidateBackingStore(q->rect());
7893         window->setNativeWindowVisibility(true);
7894         // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
7895         if (window->isTopLevel()) {
7896             const QPoint crectTopLeft = q->data->crect.topLeft();
7897             const QPoint windowTopLeft = window->geometry().topLeft();
7898             if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
7899                 q->data->crect.moveTopLeft(windowTopLeft);
7900         }
7901     }
7902 }
7903 
7904 /*!
7905     Hides the widget. This function is equivalent to
7906     setVisible(false).
7907 
7908 
7909     \note If you are working with QDialog or its subclasses and you invoke
7910     the show() function after this function, the dialog will be displayed in
7911     its original position.
7912 
7913     \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
7914 */
hide()7915 void QWidget::hide()
7916 {
7917     setVisible(false);
7918 }
7919 
7920 /*!\internal
7921  */
hide_helper()7922 void QWidgetPrivate::hide_helper()
7923 {
7924     Q_Q(QWidget);
7925 
7926     bool isEmbedded = false;
7927 #if QT_CONFIG(graphicsview)
7928     isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(q) && nearestGraphicsProxyWidget(q->parentWidget()) != nullptr;
7929 #else
7930     Q_UNUSED(isEmbedded);
7931 #endif
7932 
7933     if (!isEmbedded && (q->windowType() == Qt::Popup))
7934         qApp->d_func()->closePopup(q);
7935 
7936     q->setAttribute(Qt::WA_Mapped, false);
7937     hide_sys();
7938 
7939     bool wasVisible = q->testAttribute(Qt::WA_WState_Visible);
7940 
7941     if (wasVisible) {
7942         q->setAttribute(Qt::WA_WState_Visible, false);
7943 
7944     }
7945 
7946     QHideEvent hideEvent;
7947     QCoreApplication::sendEvent(q, &hideEvent);
7948     hideChildren(false);
7949 
7950     // next bit tries to move the focus if the focus widget is now
7951     // hidden.
7952     if (wasVisible) {
7953         qApp->d_func()->sendSyntheticEnterLeave(q);
7954         QWidget *fw = QApplication::focusWidget();
7955         while (fw &&  !fw->isWindow()) {
7956             if (fw == q) {
7957                 q->focusNextPrevChild(true);
7958                 break;
7959             }
7960             fw = fw->parentWidget();
7961         }
7962     }
7963 
7964     if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
7965         repaintManager->removeDirtyWidget(q);
7966 
7967 #ifndef QT_NO_ACCESSIBILITY
7968     if (wasVisible) {
7969         QAccessibleEvent event(q, QAccessible::ObjectHide);
7970         QAccessible::updateAccessibility(&event);
7971     }
7972 #endif
7973 }
7974 
hide_sys()7975 void QWidgetPrivate::hide_sys()
7976 {
7977     Q_Q(QWidget);
7978 
7979     auto window = qobject_cast<QWidgetWindow *>(windowHandle());
7980 
7981     if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
7982         q->setAttribute(Qt::WA_Mapped, false);
7983         // remove our window from the modal window list (native dialogs)
7984         if (window && q->isWindow()
7985 #if QT_CONFIG(graphicsview)
7986             && (!extra || !extra->proxyWidget)
7987 #endif
7988             && q->windowModality() != Qt::NonModal) {
7989             QGuiApplicationPrivate::hideModalWindow(window);
7990         }
7991         // do not return here, if window non-zero, we must hide it
7992     }
7993 
7994     deactivateWidgetCleanup();
7995 
7996     if (!q->isWindow()) {
7997         QWidget *p = q->parentWidget();
7998         if (p &&p->isVisible()) {
7999             if (renderToTexture)
8000                 p->d_func()->invalidateBackingStore(q->geometry());
8001             else
8002                 invalidateBackingStore(q->rect());
8003         }
8004     } else {
8005         invalidateBackingStore(q->rect());
8006     }
8007 
8008     if (window)
8009         window->setNativeWindowVisibility(false);
8010 }
8011 
8012 /*!
8013     \fn bool QWidget::isHidden() const
8014 
8015     Returns \c true if the widget is hidden, otherwise returns \c false.
8016 
8017     A hidden widget will only become visible when show() is called on
8018     it. It will not be automatically shown when the parent is shown.
8019 
8020     To check visibility, use !isVisible() instead (notice the exclamation mark).
8021 
8022     isHidden() implies !isVisible(), but a widget can be not visible
8023     and not hidden at the same time. This is the case for widgets that are children of
8024     widgets that are not visible.
8025 
8026 
8027     Widgets are hidden if:
8028     \list
8029         \li they were created as independent windows,
8030         \li they were created as children of visible widgets,
8031         \li hide() or setVisible(false) was called.
8032     \endlist
8033 */
8034 
setVisible(bool visible)8035 void QWidget::setVisible(bool visible)
8036 {
8037     if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) == !visible)
8038         return;
8039 
8040     // Remember that setVisible was called explicitly
8041     setAttribute(Qt::WA_WState_ExplicitShowHide);
8042 
8043     Q_D(QWidget);
8044     d->setVisible(visible);
8045 }
8046 
8047 // This method is called from QWidgetWindow in response to QWindow::setVisible,
8048 // and should match the semantics of QWindow::setVisible. QWidget::setVisible on
8049 // the other hand keeps track of WA_WState_ExplicitShowHide in addition.
setVisible(bool visible)8050 void QWidgetPrivate::setVisible(bool visible)
8051 {
8052     Q_Q(QWidget);
8053     if (visible) { // show
8054         // Designer uses a trick to make grabWidget work without showing
8055         if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
8056             && !q->parentWidget()->testAttribute(Qt::WA_WState_Created))
8057             q->parentWidget()->window()->d_func()->createRecursively();
8058 
8059         //create toplevels but not children of non-visible parents
8060         QWidget *pw = q->parentWidget();
8061         if (!q->testAttribute(Qt::WA_WState_Created)
8062             && (q->isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
8063             q->create();
8064         }
8065 
8066         bool wasResized = q->testAttribute(Qt::WA_Resized);
8067         Qt::WindowStates initialWindowState = q->windowState();
8068 
8069         // polish if necessary
8070         q->ensurePolished();
8071 
8072         // whether we need to inform the parent widget immediately
8073         bool needUpdateGeometry = !q->isWindow() && q->testAttribute(Qt::WA_WState_Hidden);
8074         // we are no longer hidden
8075         q->setAttribute(Qt::WA_WState_Hidden, false);
8076 
8077         if (needUpdateGeometry)
8078             updateGeometry_helper(true);
8079 
8080         // activate our layout before we and our children become visible
8081         if (layout)
8082             layout->activate();
8083 
8084         if (!q->isWindow()) {
8085             QWidget *parent = q->parentWidget();
8086             while (parent && parent->isVisible() && parent->d_func()->layout  && !parent->data->in_show) {
8087                 parent->d_func()->layout->activate();
8088                 if (parent->isWindow())
8089                     break;
8090                 parent = parent->parentWidget();
8091             }
8092             if (parent)
8093                 parent->d_func()->setDirtyOpaqueRegion();
8094         }
8095 
8096         // adjust size if necessary
8097         if (!wasResized
8098             && (q->isWindow() || !q->parentWidget()->d_func()->layout))  {
8099             if (q->isWindow()) {
8100                 q->adjustSize();
8101                 if (q->windowState() != initialWindowState)
8102                     q->setWindowState(initialWindowState);
8103             } else {
8104                 q->adjustSize();
8105             }
8106             q->setAttribute(Qt::WA_Resized, false);
8107         }
8108 
8109         q->setAttribute(Qt::WA_KeyboardFocusChange, false);
8110 
8111         if (q->isWindow() || q->parentWidget()->isVisible()) {
8112             show_helper();
8113 
8114             qApp->d_func()->sendSyntheticEnterLeave(q);
8115         }
8116 
8117         QEvent showToParentEvent(QEvent::ShowToParent);
8118         QCoreApplication::sendEvent(q, &showToParentEvent);
8119     } else { // hide
8120         if (QApplicationPrivate::hidden_focus_widget == q)
8121             QApplicationPrivate::hidden_focus_widget = nullptr;
8122 
8123         // hw: The test on getOpaqueRegion() needs to be more intelligent
8124         // currently it doesn't work if the widget is hidden (the region will
8125         // be clipped). The real check should be testing the cached region
8126         // (and dirty flag) directly.
8127         if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty())
8128             q->parentWidget()->d_func()->setDirtyOpaqueRegion();
8129 
8130         if (!q->testAttribute(Qt::WA_WState_Hidden)) {
8131             q->setAttribute(Qt::WA_WState_Hidden);
8132             if (q->testAttribute(Qt::WA_WState_Created))
8133                 hide_helper();
8134         }
8135 
8136         // invalidate layout similar to updateGeometry()
8137         if (!q->isWindow() && q->parentWidget()) {
8138             if (q->parentWidget()->d_func()->layout)
8139                 q->parentWidget()->d_func()->layout->invalidate();
8140             else if (q->parentWidget()->isVisible())
8141                 QCoreApplication::postEvent(q->parentWidget(), new QEvent(QEvent::LayoutRequest));
8142         }
8143 
8144         QEvent hideToParentEvent(QEvent::HideToParent);
8145         QCoreApplication::sendEvent(q, &hideToParentEvent);
8146     }
8147 }
8148 
8149 /*!
8150     Convenience function, equivalent to setVisible(!\a hidden).
8151 */
setHidden(bool hidden)8152 void QWidget::setHidden(bool hidden)
8153 {
8154     setVisible(!hidden);
8155 }
8156 
_q_showIfNotHidden()8157 void QWidgetPrivate::_q_showIfNotHidden()
8158 {
8159     Q_Q(QWidget);
8160     if ( !(q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide)) )
8161         q->setVisible(true);
8162 }
8163 
showChildren(bool spontaneous)8164 void QWidgetPrivate::showChildren(bool spontaneous)
8165 {
8166     QList<QObject*> childList = children;
8167     for (int i = 0; i < childList.size(); ++i) {
8168         QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8169         if (widget && widget->windowHandle() && !widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
8170             widget->setAttribute(Qt::WA_WState_Hidden, false);
8171         if (!widget
8172             || widget->isWindow()
8173             || widget->testAttribute(Qt::WA_WState_Hidden))
8174             continue;
8175         if (spontaneous) {
8176             widget->setAttribute(Qt::WA_Mapped);
8177             widget->d_func()->showChildren(true);
8178             QShowEvent e;
8179             QApplication::sendSpontaneousEvent(widget, &e);
8180         } else {
8181             if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
8182                 widget->d_func()->show_recursive();
8183             else
8184                 widget->show();
8185         }
8186     }
8187 }
8188 
hideChildren(bool spontaneous)8189 void QWidgetPrivate::hideChildren(bool spontaneous)
8190 {
8191     QList<QObject*> childList = children;
8192     for (int i = 0; i < childList.size(); ++i) {
8193         QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8194         if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
8195             continue;
8196 
8197         if (spontaneous)
8198             widget->setAttribute(Qt::WA_Mapped, false);
8199         else
8200             widget->setAttribute(Qt::WA_WState_Visible, false);
8201         widget->d_func()->hideChildren(spontaneous);
8202         QHideEvent e;
8203         if (spontaneous) {
8204             QApplication::sendSpontaneousEvent(widget, &e);
8205         } else {
8206             QCoreApplication::sendEvent(widget, &e);
8207             if (widget->internalWinId()
8208                 && widget->testAttribute(Qt::WA_DontCreateNativeAncestors)) {
8209                 // hide_sys() on an ancestor won't have any affect on this
8210                 // widget, so it needs an explicit hide_sys() of its own
8211                 widget->d_func()->hide_sys();
8212             }
8213         }
8214         qApp->d_func()->sendSyntheticEnterLeave(widget);
8215 #ifndef QT_NO_ACCESSIBILITY
8216         if (!spontaneous) {
8217             QAccessibleEvent event(widget, QAccessible::ObjectHide);
8218             QAccessible::updateAccessibility(&event);
8219         }
8220 #endif
8221     }
8222 }
8223 
close_helper(CloseMode mode)8224 bool QWidgetPrivate::close_helper(CloseMode mode)
8225 {
8226     if (data.is_closing)
8227         return true;
8228 
8229     Q_Q(QWidget);
8230     data.is_closing = 1;
8231 
8232     QPointer<QWidget> that = q;
8233     QPointer<QWidget> parentWidget = (q->parentWidget() && !QObjectPrivate::get(q->parentWidget())->wasDeleted) ? q->parentWidget() : nullptr;
8234 
8235     bool quitOnClose = q->testAttribute(Qt::WA_QuitOnClose);
8236     if (mode != CloseNoEvent) {
8237         QCloseEvent e;
8238         if (mode == CloseWithSpontaneousEvent)
8239             QApplication::sendSpontaneousEvent(q, &e);
8240         else
8241             QCoreApplication::sendEvent(q, &e);
8242         if (!that.isNull() && !e.isAccepted()) {
8243             data.is_closing = 0;
8244             return false;
8245         }
8246     }
8247 
8248     if (!that.isNull() && !q->isHidden())
8249         q->hide();
8250 
8251     // Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent
8252     quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible());
8253 
8254     if (quitOnClose) {
8255         /* if there is no non-withdrawn primary window left (except
8256            the ones without QuitOnClose), we emit the lastWindowClosed
8257            signal */
8258         QWidgetList list = QApplication::topLevelWidgets();
8259         bool lastWindowClosed = true;
8260         for (int i = 0; i < list.size(); ++i) {
8261             QWidget *w = list.at(i);
8262             if (!w->isVisible() || w->parentWidget() || !w->testAttribute(Qt::WA_QuitOnClose))
8263                 continue;
8264             lastWindowClosed = false;
8265             break;
8266         }
8267         if (lastWindowClosed) {
8268             QGuiApplicationPrivate::emitLastWindowClosed();
8269             QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()));
8270             applicationPrivate->maybeQuit();
8271         }
8272     }
8273 
8274 
8275     if (!that.isNull()) {
8276         data.is_closing = 0;
8277         if (q->testAttribute(Qt::WA_DeleteOnClose)) {
8278             q->setAttribute(Qt::WA_DeleteOnClose, false);
8279             q->deleteLater();
8280         }
8281     }
8282     return true;
8283 }
8284 
8285 
8286 /*!
8287     Closes this widget. Returns \c true if the widget was closed;
8288     otherwise returns \c false.
8289 
8290     First it sends the widget a QCloseEvent. The widget is
8291     \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
8292     the close event. If it \l{QEvent::ignore()}{ignores}
8293     the event, nothing happens. The default
8294     implementation of QWidget::closeEvent() accepts the close event.
8295 
8296     If the widget has the Qt::WA_DeleteOnClose flag, the widget
8297     is also deleted. A close events is delivered to the widget no
8298     matter if the widget is visible or not.
8299 
8300     The \l QApplication::lastWindowClosed() signal is emitted when the
8301     last visible primary window (i.e. window with no parent) with the
8302     Qt::WA_QuitOnClose attribute set is closed. By default this
8303     attribute is set for all widgets except transient windows such as
8304     splash screens, tool windows, and popup menus.
8305 
8306 */
8307 
close()8308 bool QWidget::close()
8309 {
8310     return d_func()->close_helper(QWidgetPrivate::CloseWithEvent);
8311 }
8312 
8313 /*!
8314     \property QWidget::visible
8315     \brief whether the widget is visible
8316 
8317     Calling setVisible(true) or show() sets the widget to visible
8318     status if all its parent widgets up to the window are visible. If
8319     an ancestor is not visible, the widget won't become visible until
8320     all its ancestors are shown. If its size or position has changed,
8321     Qt guarantees that a widget gets move and resize events just
8322     before it is shown. If the widget has not been resized yet, Qt
8323     will adjust the widget's size to a useful default using
8324     adjustSize().
8325 
8326     Calling setVisible(false) or hide() hides a widget explicitly. An
8327     explicitly hidden widget will never become visible, even if all
8328     its ancestors become visible, unless you show it.
8329 
8330     A widget receives show and hide events when its visibility status
8331     changes. Between a hide and a show event, there is no need to
8332     waste CPU cycles preparing or displaying information to the user.
8333     A video application, for example, might simply stop generating new
8334     frames.
8335 
8336     A widget that happens to be obscured by other windows on the
8337     screen is considered to be visible. The same applies to iconified
8338     windows and windows that exist on another virtual
8339     desktop (on platforms that support this concept). A widget
8340     receives spontaneous show and hide events when its mapping status
8341     is changed by the window system, e.g. a spontaneous hide event
8342     when the user minimizes the window, and a spontaneous show event
8343     when the window is restored again.
8344 
8345     You almost never have to reimplement the setVisible() function. If
8346     you need to change some settings before a widget is shown, use
8347     showEvent() instead. If you need to do some delayed initialization
8348     use the Polish event delivered to the event() function.
8349 
8350     \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
8351     showEvent(), hideEvent()
8352 */
8353 
8354 
8355 /*!
8356     Returns \c true if this widget would become visible if \a ancestor is
8357     shown; otherwise returns \c false.
8358 
8359     The true case occurs if neither the widget itself nor any parent
8360     up to but excluding \a ancestor has been explicitly hidden.
8361 
8362     This function will still return true if the widget is obscured by
8363     other windows on the screen, but could be physically visible if it
8364     or they were to be moved.
8365 
8366     isVisibleTo(0) is identical to isVisible().
8367 
8368     \sa show(), hide(), isVisible()
8369 */
8370 
isVisibleTo(const QWidget * ancestor) const8371 bool QWidget::isVisibleTo(const QWidget *ancestor) const
8372 {
8373     if (!ancestor)
8374         return isVisible();
8375     const QWidget * w = this;
8376     while (!w->isHidden()
8377             && !w->isWindow()
8378             && w->parentWidget()
8379             && w->parentWidget() != ancestor)
8380         w = w->parentWidget();
8381     return !w->isHidden();
8382 }
8383 
8384 
8385 /*!
8386     Returns the unobscured region where paint events can occur.
8387 
8388     For visible widgets, this is an approximation of the area not
8389     covered by other widgets; otherwise, this is an empty region.
8390 
8391     The repaint() function calls this function if necessary, so in
8392     general you do not need to call it.
8393 
8394 */
visibleRegion() const8395 QRegion QWidget::visibleRegion() const
8396 {
8397     Q_D(const QWidget);
8398 
8399     QRect clipRect = d->clipRect();
8400     if (clipRect.isEmpty())
8401         return QRegion();
8402     QRegion r(clipRect);
8403     d->subtractOpaqueChildren(r, clipRect);
8404     d->subtractOpaqueSiblings(r);
8405     return r;
8406 }
8407 
8408 
adjustedSize() const8409 QSize QWidgetPrivate::adjustedSize() const
8410 {
8411     Q_Q(const QWidget);
8412 
8413     QSize s = q->sizeHint();
8414 
8415     if (q->isWindow()) {
8416         Qt::Orientations exp;
8417         if (layout) {
8418             if (layout->hasHeightForWidth())
8419                 s.setHeight(layout->totalHeightForWidth(s.width()));
8420             exp = layout->expandingDirections();
8421         } else
8422         {
8423             if (q->sizePolicy().hasHeightForWidth())
8424                 s.setHeight(q->heightForWidth(s.width()));
8425             exp = q->sizePolicy().expandingDirections();
8426         }
8427         if (exp & Qt::Horizontal)
8428             s.setWidth(qMax(s.width(), 200));
8429         if (exp & Qt::Vertical)
8430             s.setHeight(qMax(s.height(), 100));
8431 
8432         QRect screen = QDesktopWidgetPrivate::screenGeometry(q->pos());
8433 
8434         s.setWidth(qMin(s.width(), screen.width()*2/3));
8435         s.setHeight(qMin(s.height(), screen.height()*2/3));
8436 
8437         if (QTLWExtra *extra = maybeTopData())
8438             extra->sizeAdjusted = true;
8439     }
8440 
8441     if (!s.isValid()) {
8442         QRect r = q->childrenRect(); // get children rectangle
8443         if (r.isNull())
8444             return s;
8445         s = r.size() + QSize(2 * r.x(), 2 * r.y());
8446     }
8447 
8448     return s;
8449 }
8450 
8451 /*!
8452     Adjusts the size of the widget to fit its contents.
8453 
8454     This function uses sizeHint() if it is valid, i.e., the size hint's width
8455     and height are \>= 0. Otherwise, it sets the size to the children
8456     rectangle that covers all child widgets (the union of all child widget
8457     rectangles).
8458 
8459     For windows, the screen size is also taken into account. If the sizeHint()
8460     is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
8461     {expanding}, the window will be at least (200, 100). The maximum size of
8462     a window is 2/3 of the screen's width and height.
8463 
8464     \sa sizeHint(), childrenRect()
8465 */
8466 
adjustSize()8467 void QWidget::adjustSize()
8468 {
8469     Q_D(QWidget);
8470     ensurePolished();
8471     QSize s = d->adjustedSize();
8472 
8473     if (d->layout)
8474         d->layout->activate();
8475 
8476     if (s.isValid())
8477         resize(s);
8478 }
8479 
8480 
8481 /*!
8482     \property QWidget::sizeHint
8483     \brief the recommended size for the widget
8484 
8485     If the value of this property is an invalid size, no size is
8486     recommended.
8487 
8488     The default implementation of sizeHint() returns an invalid size
8489     if there is no layout for this widget, and returns the layout's
8490     preferred size otherwise.
8491 
8492     \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
8493     setMinimumSize(), updateGeometry()
8494 */
8495 
sizeHint() const8496 QSize QWidget::sizeHint() const
8497 {
8498     Q_D(const QWidget);
8499     if (d->layout)
8500         return d->layout->totalSizeHint();
8501     return QSize(-1, -1);
8502 }
8503 
8504 /*!
8505     \property QWidget::minimumSizeHint
8506     \brief the recommended minimum size for the widget
8507 
8508     If the value of this property is an invalid size, no minimum size
8509     is recommended.
8510 
8511     The default implementation of minimumSizeHint() returns an invalid
8512     size if there is no layout for this widget, and returns the
8513     layout's minimum size otherwise. Most built-in widgets reimplement
8514     minimumSizeHint().
8515 
8516     \l QLayout will never resize a widget to a size smaller than the
8517     minimum size hint unless minimumSize() is set or the size policy is
8518     set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
8519     size hint will be ignored.
8520 
8521     \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
8522 */
minimumSizeHint() const8523 QSize QWidget::minimumSizeHint() const
8524 {
8525     Q_D(const QWidget);
8526     if (d->layout)
8527         return d->layout->totalMinimumSize();
8528     return QSize(-1, -1);
8529 }
8530 
8531 
8532 /*!
8533     \fn QWidget *QWidget::parentWidget() const
8534 
8535     Returns the parent of this widget, or \nullptr if it does not have any
8536     parent widget.
8537 */
8538 
8539 
8540 /*!
8541     Returns \c true if this widget is a parent, (or grandparent and so on
8542     to any level), of the given \a child, and both widgets are within
8543     the same window; otherwise returns \c false.
8544 */
8545 
isAncestorOf(const QWidget * child) const8546 bool QWidget::isAncestorOf(const QWidget *child) const
8547 {
8548     while (child) {
8549         if (child == this)
8550             return true;
8551         if (child->isWindow())
8552             return false;
8553         child = child->parentWidget();
8554     }
8555     return false;
8556 }
8557 
8558 /*****************************************************************************
8559   QWidget event handling
8560  *****************************************************************************/
8561 
8562 /*!
8563     This is the main event handler; it handles event \a event. You can
8564     reimplement this function in a subclass, but we recommend using
8565     one of the specialized event handlers instead.
8566 
8567     Key press and release events are treated differently from other
8568     events. event() checks for Tab and Shift+Tab and tries to move the
8569     focus appropriately. If there is no widget to move the focus to
8570     (or the key press is not Tab or Shift+Tab), event() calls
8571     keyPressEvent().
8572 
8573     Mouse and tablet event handling is also slightly special: only
8574     when the widget is \l enabled, event() will call the specialized
8575     handlers such as mousePressEvent(); otherwise it will discard the
8576     event.
8577 
8578     This function returns \c true if the event was recognized, otherwise
8579     it returns \c false.  If the recognized event was accepted (see \l
8580     QEvent::accepted), any further processing such as event
8581     propagation to the parent widget stops.
8582 
8583     \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
8584     keyPressEvent(), keyReleaseEvent(), leaveEvent(),
8585     mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
8586     mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
8587     QObject::event(), QObject::timerEvent()
8588 */
8589 
event(QEvent * event)8590 bool QWidget::event(QEvent *event)
8591 {
8592     Q_D(QWidget);
8593 
8594     // ignore mouse and key events when disabled
8595     if (!isEnabled()) {
8596         switch(event->type()) {
8597         case QEvent::TabletPress:
8598         case QEvent::TabletRelease:
8599         case QEvent::TabletMove:
8600         case QEvent::MouseButtonPress:
8601         case QEvent::MouseButtonRelease:
8602         case QEvent::MouseButtonDblClick:
8603         case QEvent::MouseMove:
8604         case QEvent::TouchBegin:
8605         case QEvent::TouchUpdate:
8606         case QEvent::TouchEnd:
8607         case QEvent::TouchCancel:
8608         case QEvent::ContextMenu:
8609         case QEvent::KeyPress:
8610         case QEvent::KeyRelease:
8611 #if QT_CONFIG(wheelevent)
8612         case QEvent::Wheel:
8613 #endif
8614             return false;
8615         default:
8616             break;
8617         }
8618     }
8619     switch (event->type()) {
8620     case QEvent::PlatformSurface: {
8621         // Sync up QWidget's view of whether or not the widget has been created
8622         switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
8623         case QPlatformSurfaceEvent::SurfaceCreated:
8624             if (!testAttribute(Qt::WA_WState_Created))
8625                 create();
8626             break;
8627         case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
8628             if (testAttribute(Qt::WA_WState_Created)) {
8629                 // Child windows have already been destroyed by QWindow,
8630                 // so we skip them here.
8631                 destroy(false, false);
8632             }
8633             break;
8634         }
8635         break;
8636     }
8637     case QEvent::MouseMove:
8638         mouseMoveEvent((QMouseEvent*)event);
8639         break;
8640 
8641     case QEvent::MouseButtonPress:
8642         mousePressEvent((QMouseEvent*)event);
8643         break;
8644 
8645     case QEvent::MouseButtonRelease:
8646         mouseReleaseEvent((QMouseEvent*)event);
8647         break;
8648 
8649     case QEvent::MouseButtonDblClick:
8650         mouseDoubleClickEvent((QMouseEvent*)event);
8651         break;
8652 #if QT_CONFIG(wheelevent)
8653     case QEvent::Wheel:
8654         wheelEvent((QWheelEvent*)event);
8655         break;
8656 #endif
8657 #if QT_CONFIG(tabletevent)
8658     case QEvent::TabletMove:
8659         if (static_cast<QTabletEvent *>(event)->buttons() == Qt::NoButton && !testAttribute(Qt::WA_TabletTracking))
8660             break;
8661         Q_FALLTHROUGH();
8662     case QEvent::TabletPress:
8663     case QEvent::TabletRelease:
8664         tabletEvent((QTabletEvent*)event);
8665         break;
8666 #endif
8667     case QEvent::KeyPress: {
8668         QKeyEvent *k = (QKeyEvent *)event;
8669         bool res = false;
8670         if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) {  //### Add MetaModifier?
8671             if (k->key() == Qt::Key_Backtab
8672                 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
8673                 res = focusNextPrevChild(false);
8674             else if (k->key() == Qt::Key_Tab)
8675                 res = focusNextPrevChild(true);
8676             if (res)
8677                 break;
8678         }
8679         keyPressEvent(k);
8680 #ifdef QT_KEYPAD_NAVIGATION
8681         if (!k->isAccepted() && QApplication::keypadNavigationEnabled()
8682             && !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier))) {
8683             if (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder) {
8684                 if (k->key() == Qt::Key_Up)
8685                     res = focusNextPrevChild(false);
8686                 else if (k->key() == Qt::Key_Down)
8687                     res = focusNextPrevChild(true);
8688             } else if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
8689                 if (k->key() == Qt::Key_Up)
8690                     res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionNorth);
8691                 else if (k->key() == Qt::Key_Right)
8692                     res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionEast);
8693                 else if (k->key() == Qt::Key_Down)
8694                     res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionSouth);
8695                 else if (k->key() == Qt::Key_Left)
8696                     res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionWest);
8697             }
8698             if (res) {
8699                 k->accept();
8700                 break;
8701             }
8702         }
8703 #endif
8704 #if QT_CONFIG(whatsthis)
8705         if (!k->isAccepted()
8706             && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
8707             && d->whatsThis.size()) {
8708             QWhatsThis::showText(mapToGlobal(inputMethodQuery(Qt::ImCursorRectangle).toRect().center()), d->whatsThis, this);
8709             k->accept();
8710         }
8711 #endif
8712     }
8713         break;
8714 
8715     case QEvent::KeyRelease:
8716         keyReleaseEvent((QKeyEvent*)event);
8717         Q_FALLTHROUGH();
8718     case QEvent::ShortcutOverride:
8719         break;
8720 
8721     case QEvent::InputMethod:
8722         inputMethodEvent((QInputMethodEvent *) event);
8723         break;
8724 
8725     case QEvent::InputMethodQuery:
8726         if (testAttribute(Qt::WA_InputMethodEnabled)) {
8727             QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
8728             Qt::InputMethodQueries queries = query->queries();
8729             for (uint i = 0; i < 32; ++i) {
8730                 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
8731                 if (q) {
8732                     QVariant v = inputMethodQuery(q);
8733                     if (q == Qt::ImEnabled && !v.isValid() && isEnabled())
8734                         v = QVariant(true); // special case for Qt4 compatibility
8735                     query->setValue(q, v);
8736                 }
8737             }
8738             query->accept();
8739         }
8740         break;
8741 
8742     case QEvent::PolishRequest:
8743         ensurePolished();
8744         break;
8745 
8746     case QEvent::Polish: {
8747         style()->polish(this);
8748         setAttribute(Qt::WA_WState_Polished);
8749         if (!QApplication::font(this).isCopyOf(QApplication::font()))
8750             d->resolveFont();
8751         if (!QApplication::palette(this).isCopyOf(QGuiApplication::palette()))
8752             d->resolvePalette();
8753     }
8754         break;
8755 
8756     case QEvent::ApplicationWindowIconChange:
8757         if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon)) {
8758             d->setWindowIcon_sys();
8759             d->setWindowIcon_helper();
8760         }
8761         break;
8762     case QEvent::FocusIn:
8763         focusInEvent((QFocusEvent*)event);
8764         d->updateWidgetTransform(event);
8765         break;
8766 
8767     case QEvent::FocusOut:
8768         focusOutEvent((QFocusEvent*)event);
8769         break;
8770 
8771     case QEvent::Enter:
8772 #if QT_CONFIG(statustip)
8773         if (d->statusTip.size()) {
8774             QStatusTipEvent tip(d->statusTip);
8775             QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
8776         }
8777 #endif
8778         enterEvent(event);
8779         break;
8780 
8781     case QEvent::Leave:
8782 #if QT_CONFIG(statustip)
8783         if (d->statusTip.size()) {
8784             QString empty;
8785             QStatusTipEvent tip(empty);
8786             QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
8787         }
8788 #endif
8789         leaveEvent(event);
8790         break;
8791 
8792     case QEvent::HoverEnter:
8793     case QEvent::HoverLeave:
8794         update();
8795         break;
8796 
8797     case QEvent::Paint:
8798         // At this point the event has to be delivered, regardless
8799         // whether the widget isVisible() or not because it
8800         // already went through the filters
8801         paintEvent((QPaintEvent*)event);
8802         break;
8803 
8804     case QEvent::Move:
8805         moveEvent((QMoveEvent*)event);
8806         d->updateWidgetTransform(event);
8807         break;
8808 
8809     case QEvent::Resize:
8810         resizeEvent((QResizeEvent*)event);
8811         d->updateWidgetTransform(event);
8812         break;
8813 
8814     case QEvent::Close:
8815         closeEvent((QCloseEvent *)event);
8816         break;
8817 
8818 #ifndef QT_NO_CONTEXTMENU
8819     case QEvent::ContextMenu:
8820         switch (data->context_menu_policy) {
8821         case Qt::PreventContextMenu:
8822             break;
8823         case Qt::DefaultContextMenu:
8824             contextMenuEvent(static_cast<QContextMenuEvent *>(event));
8825             break;
8826         case Qt::CustomContextMenu:
8827             emit customContextMenuRequested(static_cast<QContextMenuEvent *>(event)->pos());
8828             break;
8829 #if QT_CONFIG(menu)
8830         case Qt::ActionsContextMenu:
8831             if (d->actions.count()) {
8832                 QMenu::exec(d->actions, static_cast<QContextMenuEvent *>(event)->globalPos(),
8833                             nullptr, this);
8834                 break;
8835             }
8836             Q_FALLTHROUGH();
8837 #endif
8838         default:
8839             event->ignore();
8840             break;
8841         }
8842         break;
8843 #endif // QT_NO_CONTEXTMENU
8844 
8845 #if QT_CONFIG(draganddrop)
8846     case QEvent::Drop:
8847         dropEvent((QDropEvent*) event);
8848         break;
8849 
8850     case QEvent::DragEnter:
8851         dragEnterEvent((QDragEnterEvent*) event);
8852         break;
8853 
8854     case QEvent::DragMove:
8855         dragMoveEvent((QDragMoveEvent*) event);
8856         break;
8857 
8858     case QEvent::DragLeave:
8859         dragLeaveEvent((QDragLeaveEvent*) event);
8860         break;
8861 #endif
8862 
8863     case QEvent::Show:
8864         showEvent((QShowEvent*) event);
8865         break;
8866 
8867     case QEvent::Hide:
8868         hideEvent((QHideEvent*) event);
8869         break;
8870 
8871     case QEvent::ShowWindowRequest:
8872         if (!isHidden())
8873             d->show_sys();
8874         break;
8875 
8876     case QEvent::ApplicationFontChange:
8877         d->resolveFont();
8878         break;
8879     case QEvent::ApplicationPaletteChange:
8880         if (!(windowType() == Qt::Desktop))
8881             d->resolvePalette();
8882         break;
8883 
8884     case QEvent::ToolBarChange:
8885     case QEvent::ActivationChange:
8886     case QEvent::EnabledChange:
8887     case QEvent::FontChange:
8888     case QEvent::StyleChange:
8889     case QEvent::PaletteChange:
8890     case QEvent::WindowTitleChange:
8891     case QEvent::IconTextChange:
8892     case QEvent::ModifiedChange:
8893     case QEvent::MouseTrackingChange:
8894     case QEvent::TabletTrackingChange:
8895     case QEvent::ParentChange:
8896     case QEvent::LocaleChange:
8897     case QEvent::MacSizeChange:
8898     case QEvent::ContentsRectChange:
8899     case QEvent::ThemeChange:
8900     case QEvent::ReadOnlyChange:
8901         changeEvent(event);
8902         break;
8903 
8904     case QEvent::WindowStateChange: {
8905         const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
8906         if (wasMinimized != isMinimized()) {
8907             QWidget *widget = const_cast<QWidget *>(this);
8908             if (wasMinimized) {
8909                 // Always send the spontaneous events here, otherwise it can break the application!
8910                 if (!d->childrenShownByExpose) {
8911                     // Show widgets only when they are not yet shown by the expose event
8912                     d->showChildren(true);
8913                     QShowEvent showEvent;
8914                     QCoreApplication::sendSpontaneousEvent(widget, &showEvent);
8915                 }
8916                 d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
8917             } else {
8918                 QHideEvent hideEvent;
8919                 QCoreApplication::sendSpontaneousEvent(widget, &hideEvent);
8920                 d->hideChildren(true);
8921                 d->childrenHiddenByWState = true;
8922             }
8923             d->childrenShownByExpose = false; // Set it always to "false" when window state changes
8924         }
8925         changeEvent(event);
8926     }
8927         break;
8928 
8929     case QEvent::WindowActivate:
8930     case QEvent::WindowDeactivate: {
8931         if (isVisible() && !palette().isEqual(QPalette::Active, QPalette::Inactive))
8932             update();
8933         QList<QObject*> childList = d->children;
8934         for (int i = 0; i < childList.size(); ++i) {
8935             QWidget *w = qobject_cast<QWidget *>(childList.at(i));
8936             if (w && w->isVisible() && !w->isWindow())
8937                 QCoreApplication::sendEvent(w, event);
8938         }
8939         break; }
8940 
8941     case QEvent::LanguageChange:
8942         changeEvent(event);
8943         {
8944             QList<QObject*> childList = d->children;
8945             for (int i = 0; i < childList.size(); ++i) {
8946                 QObject *o = childList.at(i);
8947                 if (o)
8948                     QCoreApplication::sendEvent(o, event);
8949             }
8950         }
8951         update();
8952         break;
8953 
8954     case QEvent::ApplicationLayoutDirectionChange:
8955         d->resolveLayoutDirection();
8956         break;
8957 
8958     case QEvent::LayoutDirectionChange:
8959         if (d->layout)
8960             d->layout->invalidate();
8961         update();
8962         changeEvent(event);
8963         break;
8964     case QEvent::UpdateRequest:
8965         d->syncBackingStore();
8966         break;
8967     case QEvent::UpdateLater:
8968         update(static_cast<QUpdateLaterEvent*>(event)->region());
8969         break;
8970     case QEvent::StyleAnimationUpdate:
8971         if (isVisible() && !window()->isMinimized()) {
8972             event->accept();
8973             update();
8974         }
8975         break;
8976 
8977     case QEvent::WindowBlocked:
8978     case QEvent::WindowUnblocked:
8979         if (!d->children.isEmpty()) {
8980             QWidget *modalWidget = QApplication::activeModalWidget();
8981             for (int i = 0; i < d->children.size(); ++i) {
8982                 QObject *o = d->children.at(i);
8983                 if (o && o != modalWidget && o->isWidgetType()) {
8984                     QWidget *w  = static_cast<QWidget *>(o);
8985                     // do not forward the event to child windows; QApplication does this for us
8986                     if (!w->isWindow())
8987                         QCoreApplication::sendEvent(w, event);
8988                 }
8989             }
8990         }
8991         break;
8992 #ifndef QT_NO_TOOLTIP
8993     case QEvent::ToolTip:
8994         if (!d->toolTip.isEmpty())
8995             QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), d->toolTip, this, QRect(), d->toolTipDuration);
8996         else
8997             event->ignore();
8998         break;
8999 #endif
9000 #if QT_CONFIG(whatsthis)
9001     case QEvent::WhatsThis:
9002         if (d->whatsThis.size())
9003             QWhatsThis::showText(static_cast<QHelpEvent *>(event)->globalPos(), d->whatsThis, this);
9004         else
9005             event->ignore();
9006         break;
9007     case QEvent::QueryWhatsThis:
9008         if (d->whatsThis.isEmpty())
9009             event->ignore();
9010         break;
9011 #endif
9012     case QEvent::EmbeddingControl:
9013         d->topData()->frameStrut.setCoords(0 ,0, 0, 0);
9014         data->fstrut_dirty = false;
9015         break;
9016 #ifndef QT_NO_ACTION
9017     case QEvent::ActionAdded:
9018     case QEvent::ActionRemoved:
9019     case QEvent::ActionChanged:
9020         actionEvent((QActionEvent*)event);
9021         break;
9022 #endif
9023 
9024     case QEvent::KeyboardLayoutChange:
9025         {
9026             changeEvent(event);
9027 
9028             // inform children of the change
9029             QList<QObject*> childList = d->children;
9030             for (int i = 0; i < childList.size(); ++i) {
9031                 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9032                 if (w && w->isVisible() && !w->isWindow())
9033                     QCoreApplication::sendEvent(w, event);
9034             }
9035             break;
9036         }
9037     case QEvent::TouchBegin:
9038     case QEvent::TouchUpdate:
9039     case QEvent::TouchEnd:
9040     case QEvent::TouchCancel:
9041     {
9042         event->ignore();
9043         break;
9044     }
9045 #ifndef QT_NO_GESTURES
9046     case QEvent::Gesture:
9047         event->ignore();
9048         break;
9049 #endif
9050     case QEvent::ScreenChangeInternal:
9051         if (const QTLWExtra *te = d->maybeTopData()) {
9052             const QWindow *win = te->window;
9053             d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
9054         }
9055         if (d->data.fnt.d->dpi != logicalDpiY())
9056             d->updateFont(d->data.fnt);
9057 #ifndef QT_NO_OPENGL
9058         d->renderToTextureReallyDirty = 1;
9059 #endif
9060         break;
9061 #ifndef QT_NO_PROPERTIES
9062     case QEvent::DynamicPropertyChange: {
9063         const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
9064         if (propName.length() == 13 && !qstrncmp(propName, "_q_customDpi", 12)) {
9065             uint value = property(propName.constData()).toUInt();
9066             if (!d->extra)
9067                 d->createExtra();
9068             const char axis = propName.at(12);
9069             if (axis == 'X')
9070                 d->extra->customDpiX = value;
9071             else if (axis == 'Y')
9072                 d->extra->customDpiY = value;
9073             d->updateFont(d->data.fnt);
9074         }
9075         if (windowHandle() && !qstrncmp(propName, "_q_platform_", 12))
9076             windowHandle()->setProperty(propName, property(propName));
9077         Q_FALLTHROUGH();
9078     }
9079 #endif
9080     default:
9081         return QObject::event(event);
9082     }
9083     return true;
9084 }
9085 
9086 /*!
9087   This event handler can be reimplemented to handle state changes.
9088 
9089   The state being changed in this event can be retrieved through the \a event
9090   supplied.
9091 
9092   Change events include: QEvent::ToolBarChange,
9093   QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
9094   QEvent::StyleChange, QEvent::PaletteChange,
9095   QEvent::WindowTitleChange, QEvent::IconTextChange,
9096   QEvent::ModifiedChange, QEvent::MouseTrackingChange,
9097   QEvent::ParentChange, QEvent::WindowStateChange,
9098   QEvent::LanguageChange, QEvent::LocaleChange,
9099   QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
9100 
9101 */
changeEvent(QEvent * event)9102 void QWidget::changeEvent(QEvent * event)
9103 {
9104     switch(event->type()) {
9105     case QEvent::EnabledChange: {
9106         update();
9107 #ifndef QT_NO_ACCESSIBILITY
9108         QAccessible::State s;
9109         s.disabled = true;
9110         QAccessibleStateChangeEvent event(this, s);
9111         QAccessible::updateAccessibility(&event);
9112 #endif
9113         break;
9114     }
9115 
9116     case QEvent::FontChange:
9117     case QEvent::StyleChange: {
9118         Q_D(QWidget);
9119         update();
9120         updateGeometry();
9121         if (d->layout)
9122             d->layout->invalidate();
9123         break;
9124     }
9125 
9126     case QEvent::PaletteChange:
9127         update();
9128         break;
9129 
9130     case QEvent::ThemeChange:
9131         if (QGuiApplication::desktopSettingsAware() && windowType() != Qt::Desktop
9132             && qApp && !QCoreApplication::closingDown()) {
9133             if (testAttribute(Qt::WA_WState_Polished))
9134                 QApplication::style()->unpolish(this);
9135             if (testAttribute(Qt::WA_WState_Polished))
9136                 QApplication::style()->polish(this);
9137             QEvent styleChangedEvent(QEvent::StyleChange);
9138             QCoreApplication::sendEvent(this, &styleChangedEvent);
9139             if (isVisible())
9140                 update();
9141         }
9142         break;
9143 
9144 #ifdef Q_OS_MAC
9145     case QEvent::MacSizeChange:
9146         updateGeometry();
9147         break;
9148 #endif
9149 
9150     default:
9151         break;
9152     }
9153 }
9154 
9155 /*!
9156     This event handler, for event \a event, can be reimplemented in a
9157     subclass to receive mouse move events for the widget.
9158 
9159     If mouse tracking is switched off, mouse move events only occur if
9160     a mouse button is pressed while the mouse is being moved. If mouse
9161     tracking is switched on, mouse move events occur even if no mouse
9162     button is pressed.
9163 
9164     QMouseEvent::pos() reports the position of the mouse cursor,
9165     relative to this widget. For press and release events, the
9166     position is usually the same as the position of the last mouse
9167     move event, but it might be different if the user's hand shakes.
9168     This is a feature of the underlying window system, not Qt.
9169 
9170     If you want to show a tooltip immediately, while the mouse is
9171     moving (e.g., to get the mouse coordinates with QMouseEvent::pos()
9172     and show them as a tooltip), you must first enable mouse tracking
9173     as described above. Then, to ensure that the tooltip is updated
9174     immediately, you must call QToolTip::showText() instead of
9175     setToolTip() in your implementation of mouseMoveEvent().
9176 
9177     \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
9178     mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
9179 */
9180 
mouseMoveEvent(QMouseEvent * event)9181 void QWidget::mouseMoveEvent(QMouseEvent *event)
9182 {
9183     event->ignore();
9184 }
9185 
9186 /*!
9187     This event handler, for event \a event, can be reimplemented in a
9188     subclass to receive mouse press events for the widget.
9189 
9190     If you create new widgets in the mousePressEvent() the
9191     mouseReleaseEvent() may not end up where you expect, depending on
9192     the underlying window system (or X11 window manager), the widgets'
9193     location and maybe more.
9194 
9195     The default implementation implements the closing of popup widgets
9196     when you click outside the window. For other widget types it does
9197     nothing.
9198 
9199     \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
9200     mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9201 */
9202 
mousePressEvent(QMouseEvent * event)9203 void QWidget::mousePressEvent(QMouseEvent *event)
9204 {
9205     event->ignore();
9206     if ((windowType() == Qt::Popup)) {
9207         event->accept();
9208         QWidget* w;
9209         while ((w = QApplication::activePopupWidget()) && w != this){
9210             w->close();
9211             if (QApplication::activePopupWidget() == w) // widget does not want to disappear
9212                 w->hide(); // hide at least
9213         }
9214         if (!rect().contains(event->pos())){
9215             close();
9216         }
9217     }
9218 }
9219 
9220 /*!
9221     This event handler, for event \a event, can be reimplemented in a
9222     subclass to receive mouse release events for the widget.
9223 
9224     \sa mousePressEvent(), mouseDoubleClickEvent(),
9225     mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9226 */
9227 
mouseReleaseEvent(QMouseEvent * event)9228 void QWidget::mouseReleaseEvent(QMouseEvent *event)
9229 {
9230     event->ignore();
9231 }
9232 
9233 /*!
9234     This event handler, for event \a event, can be reimplemented in a
9235     subclass to receive mouse double click events for the widget.
9236 
9237     The default implementation calls mousePressEvent().
9238 
9239     \note The widget will also receive mouse press and mouse release
9240     events in addition to the double click event. And if another widget
9241     that overlaps this widget disappears in response to press or
9242     release events, then this widget will only receive the double click
9243     event. It is up to the developer to ensure that the application
9244     interprets these events correctly.
9245 
9246     \sa mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(),
9247     event(), QMouseEvent
9248 */
9249 
mouseDoubleClickEvent(QMouseEvent * event)9250 void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
9251 {
9252     mousePressEvent(event);
9253 }
9254 
9255 #if QT_CONFIG(wheelevent)
9256 /*!
9257     This event handler, for event \a event, can be reimplemented in a
9258     subclass to receive wheel events for the widget.
9259 
9260     If you reimplement this handler, it is very important that you
9261     \l{QEvent}{ignore()} the event if you do not handle
9262     it, so that the widget's parent can interpret it.
9263 
9264     The default implementation ignores the event.
9265 
9266     \sa QEvent::ignore(), QEvent::accept(), event(),
9267     QWheelEvent
9268 */
9269 
wheelEvent(QWheelEvent * event)9270 void QWidget::wheelEvent(QWheelEvent *event)
9271 {
9272     event->ignore();
9273 }
9274 #endif // QT_CONFIG(wheelevent)
9275 
9276 #if QT_CONFIG(tabletevent)
9277 /*!
9278     This event handler, for event \a event, can be reimplemented in a
9279     subclass to receive tablet events for the widget.
9280 
9281     If you reimplement this handler, it is very important that you
9282     \l{QEvent}{ignore()} the event if you do not handle
9283     it, so that the widget's parent can interpret it.
9284 
9285     The default implementation ignores the event.
9286 
9287     If tablet tracking is switched off, tablet move events only occur if the
9288     stylus is in contact with the tablet, or at least one stylus button is
9289     pressed, while the stylus is being moved. If tablet tracking is switched on,
9290     tablet move events occur even while the stylus is hovering in proximity of
9291     the tablet, with no buttons pressed.
9292 
9293     \sa QEvent::ignore(), QEvent::accept(), event(), setTabletTracking(),
9294     QTabletEvent
9295 */
9296 
tabletEvent(QTabletEvent * event)9297 void QWidget::tabletEvent(QTabletEvent *event)
9298 {
9299     event->ignore();
9300 }
9301 #endif // QT_CONFIG(tabletevent)
9302 
9303 /*!
9304     This event handler, for event \a event, can be reimplemented in a
9305     subclass to receive key press events for the widget.
9306 
9307     A widget must call setFocusPolicy() to accept focus initially and
9308     have focus in order to receive a key press event.
9309 
9310     If you reimplement this handler, it is very important that you
9311     call the base class implementation if you do not act upon the key.
9312 
9313     The default implementation closes popup widgets if the user
9314     presses the key sequence for QKeySequence::Cancel (typically the
9315     Escape key). Otherwise the event is ignored, so that the widget's
9316     parent can interpret it.
9317 
9318     Note that QKeyEvent starts with isAccepted() == true, so you do not
9319     need to call QKeyEvent::accept() - just do not call the base class
9320     implementation if you act upon the key.
9321 
9322     \sa keyReleaseEvent(), setFocusPolicy(),
9323     focusInEvent(), focusOutEvent(), event(), QKeyEvent, {Tetrix Example}
9324 */
9325 
keyPressEvent(QKeyEvent * event)9326 void QWidget::keyPressEvent(QKeyEvent *event)
9327 {
9328 #ifndef QT_NO_SHORTCUT
9329     if ((windowType() == Qt::Popup) && event->matches(QKeySequence::Cancel)) {
9330         event->accept();
9331         close();
9332     } else
9333 #endif
9334     {
9335         event->ignore();
9336     }
9337 }
9338 
9339 /*!
9340     This event handler, for event \a event, can be reimplemented in a
9341     subclass to receive key release events for the widget.
9342 
9343     A widget must \l{setFocusPolicy()}{accept focus}
9344     initially and \l{hasFocus()}{have focus} in order to
9345     receive a key release event.
9346 
9347     If you reimplement this handler, it is very important that you
9348     call the base class implementation if you do not act upon the key.
9349 
9350     The default implementation ignores the event, so that the widget's
9351     parent can interpret it.
9352 
9353     Note that QKeyEvent starts with isAccepted() == true, so you do not
9354     need to call QKeyEvent::accept() - just do not call the base class
9355     implementation if you act upon the key.
9356 
9357     \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(),
9358     focusInEvent(), focusOutEvent(), event(), QKeyEvent
9359 */
9360 
keyReleaseEvent(QKeyEvent * event)9361 void QWidget::keyReleaseEvent(QKeyEvent *event)
9362 {
9363     event->ignore();
9364 }
9365 
9366 /*!
9367     \fn void QWidget::focusInEvent(QFocusEvent *event)
9368 
9369     This event handler can be reimplemented in a subclass to receive
9370     keyboard focus events (focus received) for the widget. The event
9371     is passed in the \a event parameter
9372 
9373     A widget normally must setFocusPolicy() to something other than
9374     Qt::NoFocus in order to receive focus events. (Note that the
9375     application programmer can call setFocus() on any widget, even
9376     those that do not normally accept focus.)
9377 
9378     The default implementation updates the widget (except for windows
9379     that do not specify a focusPolicy()).
9380 
9381     \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
9382     keyReleaseEvent(), event(), QFocusEvent
9383 */
9384 
focusInEvent(QFocusEvent *)9385 void QWidget::focusInEvent(QFocusEvent *)
9386 {
9387     if (focusPolicy() != Qt::NoFocus || !isWindow()) {
9388         update();
9389     }
9390 }
9391 
9392 /*!
9393     \fn void QWidget::focusOutEvent(QFocusEvent *event)
9394 
9395     This event handler can be reimplemented in a subclass to receive
9396     keyboard focus events (focus lost) for the widget. The events is
9397     passed in the \a event parameter.
9398 
9399     A widget normally must setFocusPolicy() to something other than
9400     Qt::NoFocus in order to receive focus events. (Note that the
9401     application programmer can call setFocus() on any widget, even
9402     those that do not normally accept focus.)
9403 
9404     The default implementation updates the widget (except for windows
9405     that do not specify a focusPolicy()).
9406 
9407     \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
9408     keyReleaseEvent(), event(), QFocusEvent
9409 */
9410 
focusOutEvent(QFocusEvent *)9411 void QWidget::focusOutEvent(QFocusEvent *)
9412 {
9413     if (focusPolicy() != Qt::NoFocus || !isWindow())
9414         update();
9415 
9416 #if !defined(QT_PLATFORM_UIKIT)
9417     // FIXME: revisit autoSIP logic, QTBUG-42906
9418     if (qApp->autoSipEnabled() && testAttribute(Qt::WA_InputMethodEnabled))
9419         QGuiApplication::inputMethod()->hide();
9420 #endif
9421 }
9422 
9423 /*!
9424     \fn void QWidget::enterEvent(QEvent *event)
9425 
9426     This event handler can be reimplemented in a subclass to receive
9427     widget enter events which are passed in the \a event parameter.
9428 
9429     An event is sent to the widget when the mouse cursor enters the
9430     widget.
9431 
9432     \sa leaveEvent(), mouseMoveEvent(), event()
9433 */
9434 
enterEvent(QEvent *)9435 void QWidget::enterEvent(QEvent *)
9436 {
9437 }
9438 
9439 // ### Qt 6: void QWidget::enterEvent(QEnterEvent *).
9440 
9441 /*!
9442     \fn void QWidget::leaveEvent(QEvent *event)
9443 
9444     This event handler can be reimplemented in a subclass to receive
9445     widget leave events which are passed in the \a event parameter.
9446 
9447     A leave event is sent to the widget when the mouse cursor leaves
9448     the widget.
9449 
9450     \sa enterEvent(), mouseMoveEvent(), event()
9451 */
9452 
leaveEvent(QEvent *)9453 void QWidget::leaveEvent(QEvent *)
9454 {
9455 }
9456 
9457 /*!
9458     \fn void QWidget::paintEvent(QPaintEvent *event)
9459 
9460     This event handler can be reimplemented in a subclass to receive paint
9461     events passed in \a event.
9462 
9463     A paint event is a request to repaint all or part of a widget. It can
9464     happen for one of the following reasons:
9465 
9466     \list
9467         \li repaint() or update() was invoked,
9468         \li the widget was obscured and has now been uncovered, or
9469         \li many other reasons.
9470     \endlist
9471 
9472     Many widgets can simply repaint their entire surface when asked to, but
9473     some slow widgets need to optimize by painting only the requested region:
9474     QPaintEvent::region(). This speed optimization does not change the result,
9475     as painting is clipped to that region during event processing. QListView
9476     and QTableView do this, for example.
9477 
9478     Qt also tries to speed up painting by merging multiple paint events into
9479     one. When update() is called several times or the window system sends
9480     several paint events, Qt merges these events into one event with a larger
9481     region (see QRegion::united()). The repaint() function does not permit this
9482     optimization, so we suggest using update() whenever possible.
9483 
9484     When the paint event occurs, the update region has normally been erased, so
9485     you are painting on the widget's background.
9486 
9487     The background can be set using setBackgroundRole() and setPalette().
9488 
9489     Since Qt 4.0, QWidget automatically double-buffers its painting, so there
9490     is no need to write double-buffering code in paintEvent() to avoid flicker.
9491 
9492     \note Generally, you should refrain from calling update() or repaint()
9493     \b{inside} a paintEvent(). For example, calling update() or repaint() on
9494     children inside a paintEvent() results in undefined behavior; the child may
9495     or may not get a paint event.
9496 
9497     \warning If you are using a custom paint engine without Qt's backingstore,
9498     Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
9499     never be called; the backingstore will be used instead.
9500 
9501     \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
9502     {Analog Clock Example}
9503 */
9504 
paintEvent(QPaintEvent *)9505 void QWidget::paintEvent(QPaintEvent *)
9506 {
9507 }
9508 
9509 
9510 /*!
9511     \fn void QWidget::moveEvent(QMoveEvent *event)
9512 
9513     This event handler can be reimplemented in a subclass to receive
9514     widget move events which are passed in the \a event parameter.
9515     When the widget receives this event, it is already at the new
9516     position.
9517 
9518     The old position is accessible through QMoveEvent::oldPos().
9519 
9520     \sa resizeEvent(), event(), move(), QMoveEvent
9521 */
9522 
moveEvent(QMoveEvent *)9523 void QWidget::moveEvent(QMoveEvent *)
9524 {
9525 }
9526 
9527 
9528 /*!
9529     This event handler can be reimplemented in a subclass to receive
9530     widget resize events which are passed in the \a event parameter.
9531     When resizeEvent() is called, the widget already has its new
9532     geometry. The old size is accessible through
9533     QResizeEvent::oldSize().
9534 
9535     The widget will be erased and receive a paint event immediately
9536     after processing the resize event. No drawing need be (or should
9537     be) done inside this handler.
9538 
9539 
9540     \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
9541         {Scribble Example}
9542 */
9543 
resizeEvent(QResizeEvent *)9544 void QWidget::resizeEvent(QResizeEvent * /* event */)
9545 {
9546 }
9547 
9548 #ifndef QT_NO_ACTION
9549 /*!
9550     \fn void QWidget::actionEvent(QActionEvent *event)
9551 
9552     This event handler is called with the given \a event whenever the
9553     widget's actions are changed.
9554 
9555     \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
9556 */
actionEvent(QActionEvent *)9557 void QWidget::actionEvent(QActionEvent *)
9558 {
9559 
9560 }
9561 #endif
9562 
9563 /*!
9564     This event handler is called with the given \a event when Qt receives a window
9565     close request for a top-level widget from the window system.
9566 
9567     By default, the event is accepted and the widget is closed. You can reimplement
9568     this function to change the way the widget responds to window close requests.
9569     For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
9570     on all events.
9571 
9572     Main window applications typically use reimplementations of this function to check
9573     whether the user's work has been saved and ask for permission before closing.
9574     For example, the \l{Application Example} uses a helper function to determine whether
9575     or not to close the window:
9576 
9577     \snippet mainwindows/application/mainwindow.cpp 3
9578     \snippet mainwindows/application/mainwindow.cpp 4
9579 
9580     \sa event(), hide(), close(), QCloseEvent, {Application Example}
9581 */
9582 
closeEvent(QCloseEvent * event)9583 void QWidget::closeEvent(QCloseEvent *event)
9584 {
9585     event->accept();
9586 }
9587 
9588 #ifndef QT_NO_CONTEXTMENU
9589 /*!
9590     This event handler, for event \a event, can be reimplemented in a
9591     subclass to receive widget context menu events.
9592 
9593     The handler is called when the widget's \l contextMenuPolicy is
9594     Qt::DefaultContextMenu.
9595 
9596     The default implementation ignores the context event.
9597     See the \l QContextMenuEvent documentation for more details.
9598 
9599     \sa event(), QContextMenuEvent, customContextMenuRequested()
9600 */
9601 
contextMenuEvent(QContextMenuEvent * event)9602 void QWidget::contextMenuEvent(QContextMenuEvent *event)
9603 {
9604     event->ignore();
9605 }
9606 #endif // QT_NO_CONTEXTMENU
9607 
9608 
9609 /*!
9610     This event handler, for event \a event, can be reimplemented in a
9611     subclass to receive Input Method composition events. This handler
9612     is called when the state of the input method changes.
9613 
9614     Note that when creating custom text editing widgets, the
9615     Qt::WA_InputMethodEnabled window attribute must be set explicitly
9616     (using the setAttribute() function) in order to receive input
9617     method events.
9618 
9619     The default implementation calls event->ignore(), which rejects the
9620     Input Method event. See the \l QInputMethodEvent documentation for more
9621     details.
9622 
9623     \sa event(), QInputMethodEvent
9624 */
inputMethodEvent(QInputMethodEvent * event)9625 void QWidget::inputMethodEvent(QInputMethodEvent *event)
9626 {
9627     event->ignore();
9628 }
9629 
9630 /*!
9631     This method is only relevant for input widgets. It is used by the
9632     input method to query a set of properties of the widget to be
9633     able to support complex input method operations as support for
9634     surrounding text and reconversions.
9635 
9636     \a query specifies which property is queried.
9637 
9638     \sa inputMethodEvent(), QInputMethodEvent, QInputMethodQueryEvent, inputMethodHints
9639 */
inputMethodQuery(Qt::InputMethodQuery query) const9640 QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
9641 {
9642     switch(query) {
9643     case Qt::ImCursorRectangle:
9644         return QRect(width()/2, 0, 1, height());
9645     case Qt::ImFont:
9646         return font();
9647     case Qt::ImAnchorPosition:
9648         // Fallback.
9649         return inputMethodQuery(Qt::ImCursorPosition);
9650     case Qt::ImHints:
9651         return (int)inputMethodHints();
9652     case Qt::ImInputItemClipRectangle:
9653         return d_func()->clipRect();
9654     default:
9655         return QVariant();
9656     }
9657 }
9658 
9659 /*!
9660     \property QWidget::inputMethodHints
9661     \brief What input method specific hints the widget has.
9662 
9663     This is only relevant for input widgets. It is used by
9664     the input method to retrieve hints as to how the input method
9665     should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
9666     is set, the input method may change its visual components to reflect
9667     that only numbers can be entered.
9668 
9669     \warning Some widgets require certain flags in order to work as
9670     intended. To set a flag, do \c{w->setInputMethodHints(w->inputMethodHints()|f)}
9671     instead of \c{w->setInputMethodHints(f)}.
9672 
9673     \note The flags are only hints, so the particular input method
9674           implementation is free to ignore them. If you want to be
9675           sure that a certain type of characters are entered,
9676           you should also set a QValidator on the widget.
9677 
9678     The default value is Qt::ImhNone.
9679 
9680     \since 4.6
9681 
9682     \sa inputMethodQuery()
9683 */
inputMethodHints() const9684 Qt::InputMethodHints QWidget::inputMethodHints() const
9685 {
9686 #ifndef QT_NO_IM
9687     const QWidgetPrivate *priv = d_func();
9688     while (priv->inheritsInputMethodHints) {
9689         priv = priv->q_func()->parentWidget()->d_func();
9690         Q_ASSERT(priv);
9691     }
9692     return priv->imHints;
9693 #else //QT_NO_IM
9694     return 0;
9695 #endif //QT_NO_IM
9696 }
9697 
setInputMethodHints(Qt::InputMethodHints hints)9698 void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
9699 {
9700 #ifndef QT_NO_IM
9701     Q_D(QWidget);
9702     if (d->imHints == hints)
9703         return;
9704     d->imHints = hints;
9705     if (this == QGuiApplication::focusObject())
9706         QGuiApplication::inputMethod()->update(Qt::ImHints);
9707 #else
9708     Q_UNUSED(hints);
9709 #endif //QT_NO_IM
9710 }
9711 
9712 
9713 #if QT_CONFIG(draganddrop)
9714 
9715 /*!
9716     \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
9717 
9718     This event handler is called when a drag is in progress and the
9719     mouse enters this widget. The event is passed in the \a event parameter.
9720 
9721     If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
9722     move events}.
9723 
9724     See the \l{dnd.html}{Drag-and-drop documentation} for an
9725     overview of how to provide drag-and-drop in your application.
9726 
9727     \sa QDrag, QDragEnterEvent
9728 */
dragEnterEvent(QDragEnterEvent *)9729 void QWidget::dragEnterEvent(QDragEnterEvent *)
9730 {
9731 }
9732 
9733 /*!
9734     \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
9735 
9736     This event handler is called if a drag is in progress, and when
9737     any of the following conditions occur: the cursor enters this widget,
9738     the cursor moves within this widget, or a modifier key is pressed on
9739     the keyboard while this widget has the focus. The event is passed
9740     in the \a event parameter.
9741 
9742     See the \l{dnd.html}{Drag-and-drop documentation} for an
9743     overview of how to provide drag-and-drop in your application.
9744 
9745     \sa QDrag, QDragMoveEvent
9746 */
dragMoveEvent(QDragMoveEvent *)9747 void QWidget::dragMoveEvent(QDragMoveEvent *)
9748 {
9749 }
9750 
9751 /*!
9752     \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
9753 
9754     This event handler is called when a drag is in progress and the
9755     mouse leaves this widget. The event is passed in the \a event
9756     parameter.
9757 
9758     See the \l{dnd.html}{Drag-and-drop documentation} for an
9759     overview of how to provide drag-and-drop in your application.
9760 
9761     \sa QDrag, QDragLeaveEvent
9762 */
dragLeaveEvent(QDragLeaveEvent *)9763 void QWidget::dragLeaveEvent(QDragLeaveEvent *)
9764 {
9765 }
9766 
9767 /*!
9768     \fn void QWidget::dropEvent(QDropEvent *event)
9769 
9770     This event handler is called when the drag is dropped on this
9771     widget. The event is passed in the \a event parameter.
9772 
9773     See the \l{dnd.html}{Drag-and-drop documentation} for an
9774     overview of how to provide drag-and-drop in your application.
9775 
9776     \sa QDrag, QDropEvent
9777 */
dropEvent(QDropEvent *)9778 void QWidget::dropEvent(QDropEvent *)
9779 {
9780 }
9781 
9782 #endif // QT_CONFIG(draganddrop)
9783 
9784 /*!
9785     \fn void QWidget::showEvent(QShowEvent *event)
9786 
9787     This event handler can be reimplemented in a subclass to receive
9788     widget show events which are passed in the \a event parameter.
9789 
9790     Non-spontaneous show events are sent to widgets immediately
9791     before they are shown. The spontaneous show events of windows are
9792     delivered afterwards.
9793 
9794     Note: A widget receives spontaneous show and hide events when its
9795     mapping status is changed by the window system, e.g. a spontaneous
9796     hide event when the user minimizes the window, and a spontaneous
9797     show event when the window is restored again. After receiving a
9798     spontaneous hide event, a widget is still considered visible in
9799     the sense of isVisible().
9800 
9801     \sa visible, event(), QShowEvent
9802 */
showEvent(QShowEvent *)9803 void QWidget::showEvent(QShowEvent *)
9804 {
9805 }
9806 
9807 /*!
9808     \fn void QWidget::hideEvent(QHideEvent *event)
9809 
9810     This event handler can be reimplemented in a subclass to receive
9811     widget hide events. The event is passed in the \a event parameter.
9812 
9813     Hide events are sent to widgets immediately after they have been
9814     hidden.
9815 
9816     Note: A widget receives spontaneous show and hide events when its
9817     mapping status is changed by the window system, e.g. a spontaneous
9818     hide event when the user minimizes the window, and a spontaneous
9819     show event when the window is restored again. After receiving a
9820     spontaneous hide event, a widget is still considered visible in
9821     the sense of isVisible().
9822 
9823     \sa visible, event(), QHideEvent
9824 */
hideEvent(QHideEvent *)9825 void QWidget::hideEvent(QHideEvent *)
9826 {
9827 }
9828 
9829 /*!
9830     This special event handler can be reimplemented in a subclass to
9831     receive native platform events identified by \a eventType
9832     which are passed in the \a message parameter.
9833 
9834     In your reimplementation of this function, if you want to stop the
9835     event being handled by Qt, return true and set \a result. The \a result
9836     parameter has meaning only on Windows. If you return false, this native
9837     event is passed back to Qt, which translates the event into a Qt event
9838     and sends it to the widget.
9839 
9840     \note Events are only delivered to this event handler if the widget
9841     has a native window handle.
9842 
9843     \note This function superseedes the event filter functions
9844     x11Event(), winEvent() and macEvent() of Qt 4.
9845 
9846     \sa QAbstractNativeEventFilter
9847 
9848     \table
9849     \header \li Platform \li Event Type Identifier \li Message Type \li Result Type
9850     \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
9851     \row \li macOS \li "NSEvent" \li NSEvent * \li
9852     \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li
9853     \endtable
9854 */
9855 
9856 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
nativeEvent(const QByteArray & eventType,void * message,qintptr * result)9857 bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
9858 #else
9859 bool QWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)
9860 #endif
9861 {
9862     Q_UNUSED(eventType);
9863     Q_UNUSED(message);
9864     Q_UNUSED(result);
9865     return false;
9866 }
9867 
9868 /*!
9869     Ensures that the widget and its children have been polished by
9870     QStyle (i.e., have a proper font and palette).
9871 
9872     QWidget calls this function after it has been fully constructed
9873     but before it is shown the very first time. You can call this
9874     function if you want to ensure that the widget is polished before
9875     doing an operation, e.g., the correct font size might be needed in
9876     the widget's sizeHint() reimplementation. Note that this function
9877     \e is called from the default implementation of sizeHint().
9878 
9879     Polishing is useful for final initialization that must happen after
9880     all constructors (from base classes as well as from subclasses)
9881     have been called.
9882 
9883     If you need to change some settings when a widget is polished,
9884     reimplement event() and handle the QEvent::Polish event type.
9885 
9886     \b{Note:} The function is declared const so that it can be called from
9887     other const functions (e.g., sizeHint()).
9888 
9889     \sa event()
9890 */
ensurePolished() const9891 void QWidget::ensurePolished() const
9892 {
9893     Q_D(const QWidget);
9894 
9895     const QMetaObject *m = metaObject();
9896     if (m == d->polished)
9897         return;
9898     d->polished = m;
9899 
9900     QEvent e(QEvent::Polish);
9901     QCoreApplication::sendEvent(const_cast<QWidget *>(this), &e);
9902 
9903     // polish children after 'this'
9904     QList<QObject*> children = d->children;
9905     for (int i = 0; i < children.size(); ++i) {
9906         QObject *o = children.at(i);
9907         if(!o->isWidgetType())
9908             continue;
9909         if (QWidget *w = qobject_cast<QWidget *>(o))
9910             w->ensurePolished();
9911     }
9912 
9913     if (d->parent && d->sendChildEvents) {
9914         QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
9915         QCoreApplication::sendEvent(d->parent, &e);
9916     }
9917 }
9918 
9919 /*!
9920     Returns the mask currently set on a widget. If no mask is set the
9921     return value will be an empty region.
9922 
9923     \sa setMask(), clearMask(), QRegion::isEmpty(), {Shaped Clock Example}
9924 */
mask() const9925 QRegion QWidget::mask() const
9926 {
9927     Q_D(const QWidget);
9928     return d->extra ? d->extra->mask : QRegion();
9929 }
9930 
9931 /*!
9932     Returns the layout manager that is installed on this widget, or \nullptr
9933     if no layout manager is installed.
9934 
9935     The layout manager sets the geometry of the widget's children
9936     that have been added to the layout.
9937 
9938     \sa setLayout(), sizePolicy(), {Layout Management}
9939 */
layout() const9940 QLayout *QWidget::layout() const
9941 {
9942     return d_func()->layout;
9943 }
9944 
9945 
9946 /*!
9947     \fn void QWidget::setLayout(QLayout *layout)
9948 
9949     Sets the layout manager for this widget to \a layout.
9950 
9951     If there already is a layout manager installed on this widget,
9952     QWidget won't let you install another. You must first delete the
9953     existing layout manager (returned by layout()) before you can
9954     call setLayout() with the new layout.
9955 
9956     If \a layout is the layout manager on a different widget, setLayout()
9957     will reparent the layout and make it the layout manager for this widget.
9958 
9959     Example:
9960 
9961     \snippet layouts/layouts.cpp 24
9962 
9963     An alternative to calling this function is to pass this widget to
9964     the layout's constructor.
9965 
9966     The QWidget will take ownership of \a layout.
9967 
9968     \sa layout(), {Layout Management}
9969 */
9970 
setLayout(QLayout * l)9971 void QWidget::setLayout(QLayout *l)
9972 {
9973     if (Q_UNLIKELY(!l)) {
9974         qWarning("QWidget::setLayout: Cannot set layout to 0");
9975         return;
9976     }
9977     if (layout()) {
9978         if (Q_UNLIKELY(layout() != l))
9979             qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
9980                      " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
9981                      objectName().toLocal8Bit().data());
9982         return;
9983     }
9984 
9985     QObject *oldParent = l->parent();
9986     if (oldParent && oldParent != this) {
9987         if (oldParent->isWidgetType()) {
9988             // Steal the layout off a widget parent. Takes effect when
9989             // morphing laid-out container widgets in Designer.
9990             QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
9991             oldParentWidget->takeLayout();
9992         } else {
9993             qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
9994                      l->objectName().toLocal8Bit().data(), metaObject()->className(),
9995                      objectName().toLocal8Bit().data());
9996             return;
9997         }
9998     }
9999 
10000     Q_D(QWidget);
10001     l->d_func()->topLevel = true;
10002     d->layout = l;
10003     if (oldParent != this) {
10004         l->setParent(this);
10005         l->d_func()->reparentChildWidgets(this);
10006         l->invalidate();
10007     }
10008 
10009     if (isWindow() && d->maybeTopData())
10010         d->topData()->sizeAdjusted = false;
10011 }
10012 
10013 /*!
10014     \fn QLayout *QWidget::takeLayout()
10015 
10016     Remove the layout from the widget.
10017     \since 4.5
10018 */
10019 
takeLayout()10020 QLayout *QWidget::takeLayout()
10021 {
10022     Q_D(QWidget);
10023     QLayout *l =  layout();
10024     if (!l)
10025         return nullptr;
10026     d->layout = nullptr;
10027     l->setParent(nullptr);
10028     return l;
10029 }
10030 
10031 /*!
10032     \property QWidget::sizePolicy
10033     \brief the default layout behavior of the widget
10034 
10035     If there is a QLayout that manages this widget's children, the
10036     size policy specified by that layout is used. If there is no such
10037     QLayout, the result of this function is used.
10038 
10039     The default policy is Preferred/Preferred, which means that the
10040     widget can be freely resized, but prefers to be the size
10041     sizeHint() returns. Button-like widgets set the size policy to
10042     specify that they may stretch horizontally, but are fixed
10043     vertically. The same applies to lineedit controls (such as
10044     QLineEdit, QSpinBox or an editable QComboBox) and other
10045     horizontally orientated widgets (such as QProgressBar).
10046     QToolButton's are normally square, so they allow growth in both
10047     directions. Widgets that support different directions (such as
10048     QSlider, QScrollBar or QHeader) specify stretching in the
10049     respective direction only. Widgets that can provide scroll bars
10050     (usually subclasses of QScrollArea) tend to specify that they can
10051     use additional space, and that they can make do with less than
10052     sizeHint().
10053 
10054     \sa sizeHint(), QLayout, QSizePolicy, updateGeometry()
10055 */
sizePolicy() const10056 QSizePolicy QWidget::sizePolicy() const
10057 {
10058     Q_D(const QWidget);
10059     return d->size_policy;
10060 }
10061 
setSizePolicy(QSizePolicy policy)10062 void QWidget::setSizePolicy(QSizePolicy policy)
10063 {
10064     Q_D(QWidget);
10065     setAttribute(Qt::WA_WState_OwnSizePolicy);
10066     if (policy == d->size_policy)
10067         return;
10068 
10069     if (d->size_policy.retainSizeWhenHidden() != policy.retainSizeWhenHidden())
10070         d->retainSizeWhenHiddenChanged = 1;
10071 
10072     d->size_policy = policy;
10073 
10074 #if QT_CONFIG(graphicsview)
10075     if (const auto &extra = d->extra) {
10076         if (extra->proxyWidget)
10077             extra->proxyWidget->setSizePolicy(policy);
10078     }
10079 #endif
10080 
10081     updateGeometry();
10082     d->retainSizeWhenHiddenChanged = 0;
10083 
10084     if (isWindow() && d->maybeTopData())
10085         d->topData()->sizeAdjusted = false;
10086 }
10087 
10088 /*!
10089     \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
10090     \overload
10091 
10092     Sets the size policy of the widget to \a horizontal and \a
10093     vertical, with standard stretch and no height-for-width.
10094 
10095     \sa QSizePolicy::QSizePolicy()
10096 */
10097 
10098 /*!
10099     Returns the preferred height for this widget, given the width \a w.
10100 
10101     If this widget has a layout, the default implementation returns
10102     the layout's preferred height.  if there is no layout, the default
10103     implementation returns -1 indicating that the preferred height
10104     does not depend on the width.
10105 */
10106 
heightForWidth(int w) const10107 int QWidget::heightForWidth(int w) const
10108 {
10109     if (layout() && layout()->hasHeightForWidth())
10110         return layout()->totalHeightForWidth(w);
10111     return -1;
10112 }
10113 
10114 
10115 /*!
10116     \since 5.0
10117 
10118     Returns \c true if the widget's preferred height depends on its width; otherwise returns \c false.
10119 */
hasHeightForWidth() const10120 bool QWidget::hasHeightForWidth() const
10121 {
10122     Q_D(const QWidget);
10123     return d->layout ? d->layout->hasHeightForWidth() : d->size_policy.hasHeightForWidth();
10124 }
10125 
10126 /*!
10127     \fn QWidget *QWidget::childAt(int x, int y) const
10128 
10129     Returns the visible child widget at the position (\a{x}, \a{y})
10130     in the widget's coordinate system. If there is no visible child
10131     widget at the specified position, the function returns \nullptr.
10132 */
10133 
10134 /*!
10135     \overload
10136 
10137     Returns the visible child widget at point \a p in the widget's own
10138     coordinate system.
10139 */
10140 
childAt(const QPoint & p) const10141 QWidget *QWidget::childAt(const QPoint &p) const
10142 {
10143     return d_func()->childAt_helper(p, false);
10144 }
10145 
childAt_helper(const QPoint & p,bool ignoreChildrenInDestructor) const10146 QWidget *QWidgetPrivate::childAt_helper(const QPoint &p, bool ignoreChildrenInDestructor) const
10147 {
10148     if (children.isEmpty())
10149         return nullptr;
10150 
10151     if (!pointInsideRectAndMask(p))
10152         return nullptr;
10153     return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
10154 }
10155 
childAtRecursiveHelper(const QPoint & p,bool ignoreChildrenInDestructor) const10156 QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPoint &p, bool ignoreChildrenInDestructor) const
10157 {
10158     for (int i = children.size() - 1; i >= 0; --i) {
10159         QWidget *child = qobject_cast<QWidget *>(children.at(i));
10160         if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents)
10161             || (ignoreChildrenInDestructor && child->data->in_destructor)) {
10162             continue;
10163         }
10164 
10165         // Map the point 'p' from parent coordinates to child coordinates.
10166         QPoint childPoint = p;
10167         childPoint -= child->data->crect.topLeft();
10168 
10169         // Check if the point hits the child.
10170         if (!child->d_func()->pointInsideRectAndMask(childPoint))
10171             continue;
10172 
10173         // Do the same for the child's descendants.
10174         if (QWidget *w = child->d_func()->childAtRecursiveHelper(childPoint, ignoreChildrenInDestructor))
10175             return w;
10176 
10177         // We have found our target; namely the child at position 'p'.
10178         return child;
10179     }
10180     return nullptr;
10181 }
10182 
updateGeometry_helper(bool forceUpdate)10183 void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
10184 {
10185     Q_Q(QWidget);
10186     if (widgetItem)
10187         widgetItem->invalidateSizeCache();
10188     QWidget *parent;
10189     if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
10190         const int isHidden = q->isHidden() && !size_policy.retainSizeWhenHidden() && !retainSizeWhenHiddenChanged;
10191 
10192         if (!q->isWindow() && !isHidden && (parent = q->parentWidget())) {
10193             if (parent->d_func()->layout)
10194                 parent->d_func()->layout->invalidate();
10195             else if (parent->isVisible())
10196                 QCoreApplication::postEvent(parent, new QEvent(QEvent::LayoutRequest));
10197         }
10198     }
10199 }
10200 
10201 /*!
10202     Notifies the layout system that this widget has changed and may
10203     need to change geometry.
10204 
10205     Call this function if the sizeHint() or sizePolicy() have changed.
10206 
10207     For explicitly hidden widgets, updateGeometry() is a no-op. The
10208     layout system will be notified as soon as the widget is shown.
10209 */
10210 
updateGeometry()10211 void QWidget::updateGeometry()
10212 {
10213     Q_D(QWidget);
10214     d->updateGeometry_helper(false);
10215 }
10216 
10217 /*! \property QWidget::windowFlags
10218 
10219     Window flags are a combination of a type (e.g. Qt::Dialog) and
10220     zero or more hints to the window system (e.g.
10221     Qt::FramelessWindowHint).
10222 
10223     If the widget had type Qt::Widget or Qt::SubWindow and becomes a
10224     window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
10225     0) on the desktop. If the widget is a window and becomes a
10226     Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
10227     relative to its parent widget.
10228 
10229     \note This function calls setParent() when changing the flags for
10230     a window, causing the widget to be hidden. You must call show() to make
10231     the widget visible again..
10232 
10233     \sa windowType(), setWindowFlag(), {Window Flags Example}
10234 */
setWindowFlags(Qt::WindowFlags flags)10235 void QWidget::setWindowFlags(Qt::WindowFlags flags)
10236 {
10237     Q_D(QWidget);
10238     d->setWindowFlags(flags);
10239 }
10240 
10241 /*!
10242     \since 5.9
10243 
10244     Sets the window flag \a flag on this widget if \a on is true;
10245     otherwise clears the flag.
10246 
10247     \sa setWindowFlags(), windowFlags(), windowType()
10248 */
setWindowFlag(Qt::WindowType flag,bool on)10249 void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
10250 {
10251     Q_D(QWidget);
10252     if (on)
10253         d->setWindowFlags(data->window_flags | flag);
10254     else
10255         d->setWindowFlags(data->window_flags & ~flag);
10256 }
10257 
10258 /*! \internal
10259 
10260     Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
10261 */
setWindowFlags(Qt::WindowFlags flags)10262 void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
10263 {
10264     Q_Q(QWidget);
10265     if (q->data->window_flags == flags)
10266         return;
10267 
10268     if ((q->data->window_flags | flags) & Qt::Window) {
10269         // the old type was a window and/or the new type is a window
10270         QPoint oldPos = q->pos();
10271         bool visible = q->isVisible();
10272         const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
10273         q->setParent(q->parentWidget(), flags);
10274 
10275         // if both types are windows or neither of them are, we restore
10276         // the old position
10277         if (!windowFlagChanged && (visible || q->testAttribute(Qt::WA_Moved)))
10278             q->move(oldPos);
10279         // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
10280         adjustQuitOnCloseAttribute();
10281     } else {
10282         q->data->window_flags = flags;
10283     }
10284 }
10285 
10286 /*!
10287     Sets the window flags for the widget to \a flags,
10288     \e without telling the window system.
10289 
10290     \warning Do not call this function unless you really know what
10291     you're doing.
10292 
10293     \sa setWindowFlags()
10294 */
overrideWindowFlags(Qt::WindowFlags flags)10295 void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
10296 {
10297     data->window_flags = flags;
10298 }
10299 
10300 /*!
10301     \fn Qt::WindowType QWidget::windowType() const
10302 
10303     Returns the window type of this widget. This is identical to
10304     windowFlags() & Qt::WindowType_Mask.
10305 
10306     \sa windowFlags
10307 */
10308 
10309 /*!
10310     Sets the parent of the widget to \a parent, and resets the window
10311     flags. The widget is moved to position (0, 0) in its new parent.
10312 
10313     If the new parent widget is in a different window, the
10314     reparented widget and its children are appended to the end of the
10315     \l{setFocusPolicy()}{tab chain} of the new parent
10316     widget, in the same internal order as before. If one of the moved
10317     widgets had keyboard focus, setParent() calls clearFocus() for that
10318     widget.
10319 
10320     If the new parent widget is in the same window as the
10321     old parent, setting the parent doesn't change the tab order or
10322     keyboard focus.
10323 
10324     If the "new" parent widget is the old parent widget, this function
10325     does nothing.
10326 
10327     \note The widget becomes invisible as part of changing its parent,
10328     even if it was previously visible. You must call show() to make the
10329     widget visible again.
10330 
10331     \warning It is very unlikely that you will ever need this
10332     function. If you have a widget that changes its content
10333     dynamically, it is far easier to use \l QStackedWidget.
10334 
10335     \sa setWindowFlags()
10336 */
setParent(QWidget * parent)10337 void QWidget::setParent(QWidget *parent)
10338 {
10339     if (parent == parentWidget())
10340         return;
10341     setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask);
10342 }
10343 
10344 #ifndef QT_NO_OPENGL
sendWindowChangeToTextureChildrenRecursively(QWidget * widget)10345 static void sendWindowChangeToTextureChildrenRecursively(QWidget *widget)
10346 {
10347     QWidgetPrivate *d = QWidgetPrivate::get(widget);
10348     if (d->renderToTexture) {
10349         QEvent e(QEvent::WindowChangeInternal);
10350         QCoreApplication::sendEvent(widget, &e);
10351     }
10352 
10353     for (int i = 0; i < d->children.size(); ++i) {
10354         QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
10355         if (w && !w->isWindow() && QWidgetPrivate::get(w)->textureChildSeen)
10356             sendWindowChangeToTextureChildrenRecursively(w);
10357     }
10358 }
10359 #endif
10360 
10361 /*!
10362     \overload
10363 
10364     This function also takes widget flags, \a f as an argument.
10365 */
10366 
setParent(QWidget * parent,Qt::WindowFlags f)10367 void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
10368 {
10369     Q_D(QWidget);
10370     Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
10371 #ifdef QT_DEBUG
10372     const auto checkForParentChildLoops = qScopeGuard([&](){
10373         int depth = 0;
10374         auto p = parentWidget();
10375         while (p) {
10376             if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
10377                 qWarning("QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
10378                          "this is undefined behavior",
10379                          this, metaObject()->className(), qPrintable(objectName()));
10380             }
10381             p = p->parentWidget();
10382         }
10383     });
10384 #endif
10385 
10386     bool resized = testAttribute(Qt::WA_Resized);
10387     bool wasCreated = testAttribute(Qt::WA_WState_Created);
10388     QWidget *oldtlw = window();
10389 
10390     if (f & Qt::Window) // Frame geometry likely changes, refresh.
10391         d->data.fstrut_dirty = true;
10392 
10393     QWidget *desktopWidget = nullptr;
10394     if (parent && parent->windowType() == Qt::Desktop)
10395         desktopWidget = parent;
10396     bool newParent = (parent != parentWidget()) || !wasCreated || desktopWidget;
10397 
10398     if (newParent && parent && !desktopWidget) {
10399         if (testAttribute(Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
10400             parent->d_func()->enforceNativeChildren();
10401         else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(Qt::WA_PaintOnScreen))
10402             setAttribute(Qt::WA_NativeWindow);
10403     }
10404 
10405     if (wasCreated) {
10406         if (!testAttribute(Qt::WA_WState_Hidden)) {
10407             hide();
10408             setAttribute(Qt::WA_WState_ExplicitShowHide, false);
10409         }
10410         if (newParent) {
10411             QEvent e(QEvent::ParentAboutToChange);
10412             QCoreApplication::sendEvent(this, &e);
10413         }
10414     }
10415     if (newParent && isAncestorOf(focusWidget()))
10416         focusWidget()->clearFocus();
10417 
10418     d->setParent_sys(parent, f);
10419 
10420     if (desktopWidget)
10421         parent = nullptr;
10422 
10423 #ifndef QT_NO_OPENGL
10424     if (d->textureChildSeen && parent) {
10425         // set the textureChildSeen flag up the whole parent chain
10426         QWidgetPrivate::get(parent)->setTextureChildSeen();
10427     }
10428 #endif
10429 
10430     if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
10431         if (newParent)
10432             oldPaintManager->removeDirtyWidget(this);
10433         // Move the widget and all its static children from
10434         // the old backing store to the new one.
10435         oldPaintManager->moveStaticWidgets(this);
10436     }
10437 
10438     // ### fixme: Qt 6: Remove AA_ImmediateWidgetCreation.
10439     if (QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation) && !testAttribute(Qt::WA_WState_Created))
10440         create();
10441 
10442     d->reparentFocusWidgets(oldtlw);
10443     setAttribute(Qt::WA_Resized, resized);
10444 
10445     const bool useStyleSheetPropagationInWidgetStyles =
10446         QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
10447 
10448     if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(Qt::WA_StyleSheet)
10449         && (!parent || !parent->testAttribute(Qt::WA_StyleSheet))) {
10450         // if the parent has a font set or inherited, then propagate the mask to the new child
10451         if (parent) {
10452             const auto pd = parent->d_func();
10453             d->inheritedFontResolveMask = pd->directFontResolveMask | pd->inheritedFontResolveMask;
10454             d->inheritedPaletteResolveMask = pd->directPaletteResolveMask | pd->inheritedPaletteResolveMask;
10455         }
10456         d->resolveFont();
10457         d->resolvePalette();
10458     }
10459     d->resolveLayoutDirection();
10460     d->resolveLocale();
10461 
10462     // Note: GL widgets under WGL or EGL will always need a ParentChange
10463     // event to handle recreation/rebinding of the GL context, hence the
10464     // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
10465     // platforms).
10466     if (newParent
10467 #if defined(QT_OPENGL_ES)
10468         || (f & Qt::MSWindowsOwnDC)
10469 #endif
10470         ) {
10471         // propagate enabled updates enabled state to non-windows
10472         if (!isWindow()) {
10473             if (!testAttribute(Qt::WA_ForceDisabled))
10474                 d->setEnabled_helper(parent ? parent->isEnabled() : true);
10475             if (!testAttribute(Qt::WA_ForceUpdatesDisabled))
10476                 d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
10477         }
10478         d->inheritStyle();
10479 
10480         // send and post remaining QObject events
10481         if (parent && d->sendChildEvents) {
10482             QChildEvent e(QEvent::ChildAdded, this);
10483             QCoreApplication::sendEvent(parent, &e);
10484         }
10485 
10486         if (parent && d->sendChildEvents && d->polished) {
10487             QChildEvent e(QEvent::ChildPolished, this);
10488             QCoreApplication::sendEvent(parent, &e);
10489         }
10490 
10491         QEvent e(QEvent::ParentChange);
10492         QCoreApplication::sendEvent(this, &e);
10493     }
10494 #ifndef QT_NO_OPENGL
10495     //renderToTexture widgets also need to know when their top-level window changes
10496     if (d->textureChildSeen && oldtlw != window()) {
10497         sendWindowChangeToTextureChildrenRecursively(this);
10498     }
10499 #endif
10500 
10501     if (!wasCreated) {
10502         if (isWindow() || parentWidget()->isVisible())
10503             setAttribute(Qt::WA_WState_Hidden, true);
10504         else if (!testAttribute(Qt::WA_WState_ExplicitShowHide))
10505             setAttribute(Qt::WA_WState_Hidden, false);
10506     }
10507 
10508     d->updateIsOpaque();
10509 
10510 #if QT_CONFIG(graphicsview)
10511     // Embed the widget into a proxy if the parent is embedded.
10512     // ### Doesn't handle reparenting out of an embedded widget.
10513     if (oldtlw->graphicsProxyWidget()) {
10514         if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(oldtlw))
10515             ancestorProxy->d_func()->unembedSubWindow(this);
10516     }
10517     if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(this)) {
10518         if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(parent))
10519             ancestorProxy->d_func()->embedSubWindow(this);
10520     }
10521 #endif
10522 
10523     if (d->extra && d->extra->hasWindowContainer)
10524         QWindowContainer::parentWasChanged(this);
10525 }
10526 
setParent_sys(QWidget * newparent,Qt::WindowFlags f)10527 void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
10528 {
10529     Q_Q(QWidget);
10530 
10531     Qt::WindowFlags oldFlags = data.window_flags;
10532     bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
10533 
10534     int targetScreen = -1;
10535     // Handle a request to move the widget to a particular screen
10536     if (newparent && newparent->windowType() == Qt::Desktop) {
10537         // make sure the widget is created on the same screen as the
10538         // programmer specified desktop widget
10539         const QDesktopScreenWidget *sw = qobject_cast<const QDesktopScreenWidget *>(newparent);
10540         targetScreen = sw ? sw->screenNumber() : 0;
10541         newparent = nullptr;
10542     }
10543 
10544     setWinId(0);
10545 
10546     if (parent != newparent) {
10547         QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
10548         if (q->windowHandle()) {
10549             q->windowHandle()->setFlags(f);
10550             QWidget *parentWithWindow =
10551                 newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : nullptr;
10552             if (parentWithWindow) {
10553                 QWidget *topLevel = parentWithWindow->window();
10554                 if ((f & Qt::Window) && topLevel && topLevel->windowHandle()) {
10555                     q->windowHandle()->setTransientParent(topLevel->windowHandle());
10556                     q->windowHandle()->setParent(nullptr);
10557                 } else {
10558                     q->windowHandle()->setTransientParent(nullptr);
10559                     q->windowHandle()->setParent(parentWithWindow->windowHandle());
10560                 }
10561             } else {
10562                 q->windowHandle()->setTransientParent(nullptr);
10563                 q->windowHandle()->setParent(nullptr);
10564             }
10565         }
10566     }
10567 
10568     if (!newparent) {
10569         f |= Qt::Window;
10570         if (targetScreen == -1) {
10571             if (parent)
10572                 targetScreen = QDesktopWidgetPrivate::screenNumber(q->parentWidget()->window());
10573         }
10574     }
10575 
10576     bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
10577 
10578     // Reparenting toplevel to child
10579     if (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
10580         if (extra && extra->hasWindowContainer)
10581             QWindowContainer::toplevelAboutToBeDestroyed(q);
10582 
10583         QWindow *newParentWindow = newparent->windowHandle();
10584         if (!newParentWindow)
10585             if (QWidget *npw = newparent->nativeParentWidget())
10586                 newParentWindow = npw->windowHandle();
10587 
10588         Q_FOREACH (QObject *child, q->windowHandle()->children()) {
10589             QWindow *childWindow = qobject_cast<QWindow *>(child);
10590             if (!childWindow)
10591                 continue;
10592 
10593             QWidgetWindow *childWW = qobject_cast<QWidgetWindow *>(childWindow);
10594             QWidget *childWidget = childWW ? childWW->widget() : nullptr;
10595             if (!childWW || (childWidget && childWidget->testAttribute(Qt::WA_NativeWindow)))
10596                 childWindow->setParent(newParentWindow);
10597         }
10598         q->destroy();
10599     }
10600 
10601     adjustFlags(f, q);
10602     data.window_flags = f;
10603     q->setAttribute(Qt::WA_WState_Created, false);
10604     q->setAttribute(Qt::WA_WState_Visible, false);
10605     q->setAttribute(Qt::WA_WState_Hidden, false);
10606 
10607     if (newparent && wasCreated && (q->testAttribute(Qt::WA_NativeWindow) || (f & Qt::Window)))
10608         q->createWinId();
10609 
10610     if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
10611         q->setAttribute(Qt::WA_WState_Hidden);
10612     q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
10613 
10614     // move the window to the selected screen
10615     if (!newparent && targetScreen != -1) {
10616         // only if it is already created
10617         if (q->testAttribute(Qt::WA_WState_Created))
10618             q->windowHandle()->setScreen(QGuiApplication::screens().value(targetScreen, 0));
10619         else
10620             topData()->initialScreenIndex = targetScreen;
10621     }
10622 }
10623 
10624 /*!
10625     Scrolls the widget including its children \a dx pixels to the
10626     right and \a dy downward. Both \a dx and \a dy may be negative.
10627 
10628     After scrolling, the widgets will receive paint events for
10629     the areas that need to be repainted. For widgets that Qt knows to
10630     be opaque, this is only the newly exposed parts.
10631     For example, if an opaque widget is scrolled 8 pixels to the left,
10632     only an 8-pixel wide stripe at the right edge needs updating.
10633 
10634     Since widgets propagate the contents of their parents by default,
10635     you need to set the \l autoFillBackground property, or use
10636     setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
10637     a widget opaque.
10638 
10639     For widgets that use contents propagation, a scroll will cause an
10640     update of the entire scroll area.
10641 
10642     \sa {Transparency and Double Buffering}
10643 */
10644 
scroll(int dx,int dy)10645 void QWidget::scroll(int dx, int dy)
10646 {
10647     if ((!updatesEnabled() && children().size() == 0) || !isVisible())
10648         return;
10649     if (dx == 0 && dy == 0)
10650         return;
10651     Q_D(QWidget);
10652 #if QT_CONFIG(graphicsview)
10653     if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
10654         // Graphics View maintains its own dirty region as a list of rects;
10655         // until we can connect item updates directly to the view, we must
10656         // separately add a translated dirty region.
10657         for (const QRect &rect : d->dirty)
10658             proxy->update(rect.translated(dx, dy));
10659         proxy->scroll(dx, dy, proxy->subWidgetRect(this));
10660         return;
10661     }
10662 #endif
10663     d->setDirtyOpaqueRegion();
10664     d->scroll_sys(dx, dy);
10665 }
10666 
scroll_sys(int dx,int dy)10667 void QWidgetPrivate::scroll_sys(int dx, int dy)
10668 {
10669     Q_Q(QWidget);
10670     scrollChildren(dx, dy);
10671     scrollRect(q->rect(), dx, dy);
10672 }
10673 
10674 /*!
10675     \overload
10676 
10677     This version only scrolls \a r and does not move the children of
10678     the widget.
10679 
10680     If \a r is empty or invalid, the result is undefined.
10681 
10682     \sa QScrollArea
10683 */
scroll(int dx,int dy,const QRect & r)10684 void QWidget::scroll(int dx, int dy, const QRect &r)
10685 {
10686 
10687     if ((!updatesEnabled() && children().size() == 0) || !isVisible())
10688         return;
10689     if (dx == 0 && dy == 0)
10690         return;
10691     Q_D(QWidget);
10692 #if QT_CONFIG(graphicsview)
10693     if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
10694         // Graphics View maintains its own dirty region as a list of rects;
10695         // until we can connect item updates directly to the view, we must
10696         // separately add a translated dirty region.
10697         if (!d->dirty.isEmpty()) {
10698             for (const QRect &rect : d->dirty.translated(dx, dy) & r)
10699                 proxy->update(rect);
10700         }
10701         proxy->scroll(dx, dy, r.translated(proxy->subWidgetRect(this).topLeft().toPoint()));
10702         return;
10703     }
10704 #endif
10705     d->scroll_sys(dx, dy, r);
10706 }
10707 
scroll_sys(int dx,int dy,const QRect & r)10708 void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
10709 {
10710     scrollRect(r, dx, dy);
10711 }
10712 
10713 /*!
10714     Repaints the widget directly by calling paintEvent() immediately,
10715     unless updates are disabled or the widget is hidden.
10716 
10717     We suggest only using repaint() if you need an immediate repaint,
10718     for example during animation. In almost all circumstances update()
10719     is better, as it permits Qt to optimize for speed and minimize
10720     flicker.
10721 
10722     \warning If you call repaint() in a function which may itself be
10723     called from paintEvent(), you may get infinite recursion. The
10724     update() function never causes recursion.
10725 
10726     \sa update(), paintEvent(), setUpdatesEnabled()
10727 */
10728 
repaint()10729 void QWidget::repaint()
10730 {
10731     repaint(rect());
10732 }
10733 
10734 /*! \overload
10735 
10736     This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
10737     the widget.
10738 
10739     If \a w is negative, it is replaced with \c{width() - x}, and if
10740     \a h is negative, it is replaced width \c{height() - y}.
10741 */
repaint(int x,int y,int w,int h)10742 void QWidget::repaint(int x, int y, int w, int h)
10743 {
10744     if (x > data->crect.width() || y > data->crect.height())
10745         return;
10746 
10747     if (w < 0)
10748         w = data->crect.width()  - x;
10749     if (h < 0)
10750         h = data->crect.height() - y;
10751 
10752     repaint(QRect(x, y, w, h));
10753 }
10754 
10755 /*! \overload
10756 
10757     This version repaints a rectangle \a rect inside the widget.
10758 */
repaint(const QRect & rect)10759 void QWidget::repaint(const QRect &rect)
10760 {
10761     Q_D(QWidget);
10762     d->repaint(rect);
10763 }
10764 
10765 /*!
10766     \overload
10767 
10768     This version repaints a region \a rgn inside the widget.
10769 */
repaint(const QRegion & rgn)10770 void QWidget::repaint(const QRegion &rgn)
10771 {
10772     Q_D(QWidget);
10773     d->repaint(rgn);
10774 }
10775 
10776 template <typename T>
repaint(T r)10777 void QWidgetPrivate::repaint(T r)
10778 {
10779     Q_Q(QWidget);
10780 
10781     if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
10782         return;
10783 
10784     QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
10785     if (tlwExtra && tlwExtra->backingStore)
10786         tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
10787 }
10788 
10789 /*!
10790     Updates the widget unless updates are disabled or the widget is
10791     hidden.
10792 
10793     This function does not cause an immediate repaint; instead it
10794     schedules a paint event for processing when Qt returns to the main
10795     event loop. This permits Qt to optimize for more speed and less
10796     flicker than a call to repaint() does.
10797 
10798     Calling update() several times normally results in just one
10799     paintEvent() call.
10800 
10801     Qt normally erases the widget's area before the paintEvent() call.
10802     If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
10803     responsible for painting all its pixels with an opaque color.
10804 
10805     \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock Example}
10806 */
update()10807 void QWidget::update()
10808 {
10809     update(rect());
10810 }
10811 
10812 /*! \fn void QWidget::update(int x, int y, int w, int h)
10813     \overload
10814 
10815     This version updates a rectangle (\a x, \a y, \a w, \a h) inside
10816     the widget.
10817 */
10818 
10819 /*!
10820     \overload
10821 
10822     This version updates a rectangle \a rect inside the widget.
10823 */
update(const QRect & rect)10824 void QWidget::update(const QRect &rect)
10825 {
10826     Q_D(QWidget);
10827     d->update(rect);
10828 }
10829 
10830 /*!
10831     \overload
10832 
10833     This version repaints a region \a rgn inside the widget.
10834 */
update(const QRegion & rgn)10835 void QWidget::update(const QRegion &rgn)
10836 {
10837     Q_D(QWidget);
10838     d->update(rgn);
10839 }
10840 
10841 template <typename T>
update(T r)10842 void QWidgetPrivate::update(T r)
10843 {
10844     Q_Q(QWidget);
10845 
10846     if (!q->isVisible() || !q->updatesEnabled())
10847         return;
10848 
10849     T clipped = r & q->rect();
10850 
10851     if (clipped.isEmpty())
10852         return;
10853 
10854     if (q->testAttribute(Qt::WA_WState_InPaintEvent)) {
10855         QCoreApplication::postEvent(q, new QUpdateLaterEvent(clipped));
10856         return;
10857     }
10858 
10859     QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
10860     if (tlwExtra && tlwExtra->backingStore)
10861         tlwExtra->repaintManager->markDirty(clipped, q);
10862 }
10863 
10864  /*!
10865   \internal
10866 
10867   This just sets the corresponding attribute bit to 1 or 0
10868  */
setAttribute_internal(Qt::WidgetAttribute attribute,bool on,QWidgetData * data,QWidgetPrivate * d)10869 static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
10870                                   QWidgetPrivate *d)
10871 {
10872     if (attribute < int(8*sizeof(uint))) {
10873         if (on)
10874             data->widget_attributes |= (1<<attribute);
10875         else
10876             data->widget_attributes &= ~(1<<attribute);
10877     } else {
10878         const int x = attribute - 8*sizeof(uint);
10879         const int int_off = x / (8*sizeof(uint));
10880         if (on)
10881             d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
10882         else
10883             d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
10884     }
10885 }
10886 
10887 #ifdef Q_OS_MAC
macUpdateSizeAttribute()10888 void QWidgetPrivate::macUpdateSizeAttribute()
10889 {
10890     Q_Q(QWidget);
10891     QEvent event(QEvent::MacSizeChange);
10892     QCoreApplication::sendEvent(q, &event);
10893     for (int i = 0; i < children.size(); ++i) {
10894         QWidget *w = qobject_cast<QWidget *>(children.at(i));
10895         if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
10896               && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
10897               && !w->testAttribute(Qt::WA_MacSmallSize)
10898               && !w->testAttribute(Qt::WA_MacNormalSize))
10899             w->d_func()->macUpdateSizeAttribute();
10900     }
10901     resolveFont();
10902 }
10903 #endif
10904 
10905 /*!
10906     Sets the attribute \a attribute on this widget if \a on is true;
10907     otherwise clears the attribute.
10908 
10909     \sa testAttribute()
10910 */
setAttribute(Qt::WidgetAttribute attribute,bool on)10911 void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
10912 {
10913     if (testAttribute(attribute) == on)
10914         return;
10915 
10916     Q_D(QWidget);
10917     Q_STATIC_ASSERT_X(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
10918                       "QWidget::setAttribute(WidgetAttribute, bool): "
10919                       "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
10920 #ifdef Q_OS_WIN
10921     // ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
10922     if (attribute == Qt::WA_PaintOnScreen && on && windowType() != Qt::Desktop && !inherits("QGLWidget")) {
10923         // see ::paintEngine for details
10924         paintEngine();
10925         if (d->noPaintOnScreen)
10926             return;
10927     }
10928 #endif
10929 
10930     // Don't set WA_NativeWindow on platforms that don't support it -- except for QGLWidget, which depends on it
10931     if (attribute == Qt::WA_NativeWindow && !d->mustHaveWindowHandle) {
10932         QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
10933         if (!platformIntegration->hasCapability(QPlatformIntegration::NativeWidgets))
10934             return;
10935     }
10936 
10937     setAttribute_internal(attribute, on, data, d);
10938 
10939     switch (attribute) {
10940 
10941 #if QT_CONFIG(draganddrop)
10942     case Qt::WA_AcceptDrops:  {
10943         if (on && !testAttribute(Qt::WA_DropSiteRegistered))
10944             setAttribute(Qt::WA_DropSiteRegistered, true);
10945         else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
10946             setAttribute(Qt::WA_DropSiteRegistered, false);
10947         QEvent e(QEvent::AcceptDropsChange);
10948         QCoreApplication::sendEvent(this, &e);
10949         break;
10950     }
10951     case Qt::WA_DropSiteRegistered:  {
10952         for (int i = 0; i < d->children.size(); ++i) {
10953             QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
10954             if (w && !w->isWindow() && !w->testAttribute(Qt::WA_AcceptDrops) && w->testAttribute(Qt::WA_DropSiteRegistered) != on)
10955                 w->setAttribute(Qt::WA_DropSiteRegistered, on);
10956         }
10957         break;
10958     }
10959 #endif
10960 
10961     case Qt::WA_NoChildEventsForParent:
10962         d->sendChildEvents = !on;
10963         break;
10964     case Qt::WA_NoChildEventsFromChildren:
10965         d->receiveChildEvents = !on;
10966         break;
10967     case Qt::WA_MacNormalSize:
10968     case Qt::WA_MacSmallSize:
10969     case Qt::WA_MacMiniSize:
10970 #ifdef Q_OS_MAC
10971         {
10972             // We can only have one of these set at a time
10973             const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
10974                                                      Qt::WA_MacMiniSize };
10975             for (int i = 0; i < 3; ++i) {
10976                 if (MacSizes[i] != attribute)
10977                     setAttribute_internal(MacSizes[i], false, data, d);
10978             }
10979             d->macUpdateSizeAttribute();
10980         }
10981 #endif
10982         break;
10983     case Qt::WA_ShowModal:
10984         if (!on) {
10985             // reset modality type to NonModal when clearing WA_ShowModal
10986             data->window_modality = Qt::NonModal;
10987         } else if (data->window_modality == Qt::NonModal) {
10988             // determine the modality type if it hasn't been set prior
10989             // to setting WA_ShowModal. set the default to WindowModal
10990             // if we are the child of a group leader; otherwise use
10991             // ApplicationModal.
10992             QWidget *w = parentWidget();
10993             if (w)
10994                 w = w->window();
10995             while (w && !w->testAttribute(Qt::WA_GroupLeader)) {
10996                 w = w->parentWidget();
10997                 if (w)
10998                     w = w->window();
10999             }
11000             data->window_modality = (w && w->testAttribute(Qt::WA_GroupLeader))
11001                                     ? Qt::WindowModal
11002                                     : Qt::ApplicationModal;
11003             // Some window managers do not allow us to enter modality after the
11004             // window is visible.The window must be hidden before changing the
11005             // windowModality property and then reshown.
11006         }
11007         if (testAttribute(Qt::WA_WState_Created)) {
11008             // don't call setModal_sys() before create()
11009             d->setModal_sys();
11010         }
11011         break;
11012     case Qt::WA_MouseTracking: {
11013         QEvent e(QEvent::MouseTrackingChange);
11014         QCoreApplication::sendEvent(this, &e);
11015         break; }
11016     case Qt::WA_TabletTracking: {
11017         QEvent e(QEvent::TabletTrackingChange);
11018         QCoreApplication::sendEvent(this, &e);
11019         break; }
11020     case Qt::WA_NativeWindow: {
11021         d->createTLExtra();
11022         if (on)
11023             d->createTLSysExtra();
11024 #ifndef QT_NO_IM
11025         QWidget *focusWidget = d->effectiveFocusWidget();
11026         if (on && !internalWinId() && this == QGuiApplication::focusObject()
11027             && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11028             QGuiApplication::inputMethod()->commit();
11029             QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11030         }
11031         if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
11032             parentWidget()->d_func()->enforceNativeChildren();
11033         if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
11034             d->createWinId();
11035         if (isEnabled() && focusWidget->isEnabled() && this == QGuiApplication::focusObject()
11036             && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11037             QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11038         }
11039 #endif //QT_NO_IM
11040         break;
11041     }
11042     case Qt::WA_PaintOnScreen:
11043         d->updateIsOpaque();
11044         Q_FALLTHROUGH();
11045     case Qt::WA_OpaquePaintEvent:
11046         d->updateIsOpaque();
11047         break;
11048     case Qt::WA_NoSystemBackground:
11049         d->updateIsOpaque();
11050         Q_FALLTHROUGH();
11051     case Qt::WA_UpdatesDisabled:
11052         d->updateSystemBackground();
11053         break;
11054     case Qt::WA_TransparentForMouseEvents:
11055         break;
11056     case Qt::WA_InputMethodEnabled: {
11057 #ifndef QT_NO_IM
11058         if (QGuiApplication::focusObject() == this) {
11059             if (!on)
11060                 QGuiApplication::inputMethod()->commit();
11061             QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11062         }
11063 #endif //QT_NO_IM
11064         break;
11065     }
11066     case Qt::WA_WindowPropagation:
11067         d->resolvePalette();
11068         d->resolveFont();
11069         d->resolveLocale();
11070         break;
11071     case Qt::WA_DontShowOnScreen: {
11072         if (on && isVisible()) {
11073             // Make sure we keep the current state and only hide the widget
11074             // from the desktop. show_sys will only update platform specific
11075             // attributes at this point.
11076             d->hide_sys();
11077             d->show_sys();
11078         }
11079         break;
11080     }
11081 
11082     case Qt::WA_X11NetWmWindowTypeDesktop:
11083     case Qt::WA_X11NetWmWindowTypeDock:
11084     case Qt::WA_X11NetWmWindowTypeToolBar:
11085     case Qt::WA_X11NetWmWindowTypeMenu:
11086     case Qt::WA_X11NetWmWindowTypeUtility:
11087     case Qt::WA_X11NetWmWindowTypeSplash:
11088     case Qt::WA_X11NetWmWindowTypeDialog:
11089     case Qt::WA_X11NetWmWindowTypeDropDownMenu:
11090     case Qt::WA_X11NetWmWindowTypePopupMenu:
11091     case Qt::WA_X11NetWmWindowTypeToolTip:
11092     case Qt::WA_X11NetWmWindowTypeNotification:
11093     case Qt::WA_X11NetWmWindowTypeCombo:
11094     case Qt::WA_X11NetWmWindowTypeDND:
11095         d->setNetWmWindowTypes();
11096         break;
11097 
11098     case Qt::WA_StaticContents:
11099         if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
11100             if (on)
11101                 repaintManager->addStaticWidget(this);
11102             else
11103                 repaintManager->removeStaticWidget(this);
11104         }
11105         break;
11106     case Qt::WA_TranslucentBackground:
11107         if (on)
11108             setAttribute(Qt::WA_NoSystemBackground);
11109         d->updateIsTranslucent();
11110 
11111         break;
11112     case Qt::WA_AcceptTouchEvents:
11113         break;
11114     default:
11115         break;
11116     }
11117 }
11118 
11119 /*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
11120 
11121   Returns \c true if attribute \a attribute is set on this widget;
11122   otherwise returns \c false.
11123 
11124   \sa setAttribute()
11125  */
testAttribute_helper(Qt::WidgetAttribute attribute) const11126 bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
11127 {
11128     Q_D(const QWidget);
11129     const int x = attribute - 8*sizeof(uint);
11130     const int int_off = x / (8*sizeof(uint));
11131     return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
11132 }
11133 
11134 /*!
11135   \property QWidget::windowOpacity
11136 
11137   \brief The level of opacity for the window.
11138 
11139   The valid range of opacity is from 1.0 (completely opaque) to
11140   0.0 (completely transparent).
11141 
11142   By default the value of this property is 1.0.
11143 
11144   This feature is available on Embedded Linux, \macos, Windows,
11145   and X11 platforms that support the Composite extension.
11146 
11147   \note On X11 you need to have a composite manager running,
11148   and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
11149   supported by the window manager you are using.
11150 
11151   \warning Changing this property from opaque to transparent might issue a
11152   paint event that needs to be processed before the window is displayed
11153   correctly. This affects mainly the use of QScreen::grabWindow(). Also note
11154   that semi-transparent windows update and resize significantly slower than
11155   opaque windows.
11156 
11157   \sa setMask()
11158 */
windowOpacity() const11159 qreal QWidget::windowOpacity() const
11160 {
11161     Q_D(const QWidget);
11162     return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
11163 }
11164 
setWindowOpacity(qreal opacity)11165 void QWidget::setWindowOpacity(qreal opacity)
11166 {
11167     Q_D(QWidget);
11168     if (!isWindow())
11169         return;
11170 
11171     opacity = qBound(qreal(0.0), opacity, qreal(1.0));
11172     QTLWExtra *extra = d->topData();
11173     extra->opacity = uint(opacity * 255);
11174     setAttribute(Qt::WA_WState_WindowOpacitySet);
11175     d->setWindowOpacity_sys(opacity);
11176 
11177     if (!testAttribute(Qt::WA_WState_Created))
11178         return;
11179 
11180 #if QT_CONFIG(graphicsview)
11181     if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
11182         // Avoid invalidating the cache if set.
11183         if (proxy->cacheMode() == QGraphicsItem::NoCache)
11184             proxy->update();
11185         else if (QGraphicsScene *scene = proxy->scene())
11186             scene->update(proxy->sceneBoundingRect());
11187         return;
11188     }
11189 #endif
11190 }
11191 
setWindowOpacity_sys(qreal level)11192 void QWidgetPrivate::setWindowOpacity_sys(qreal level)
11193 {
11194     Q_Q(QWidget);
11195     if (q->windowHandle())
11196         q->windowHandle()->setOpacity(level);
11197 }
11198 
11199 /*!
11200     \property QWidget::windowModified
11201     \brief whether the document shown in the window has unsaved changes
11202 
11203     A modified window is a window whose content has changed but has
11204     not been saved to disk. This flag will have different effects
11205     varied by the platform. On \macos the close button will have a
11206     modified look; on other platforms, the window title will have an
11207     '*' (asterisk).
11208 
11209     The window title must contain a "[*]" placeholder, which
11210     indicates where the '*' should appear. Normally, it should appear
11211     right after the file name (e.g., "document1.txt[*] - Text
11212     Editor"). If the window isn't modified, the placeholder is simply
11213     removed.
11214 
11215     Note that if a widget is set as modified, all its ancestors will
11216     also be set as modified. However, if you call \c
11217     {setWindowModified(false)} on a widget, this will not propagate to
11218     its parent because other children of the parent might have been
11219     modified.
11220 
11221     \sa windowTitle, {Application Example}, {SDI Example}, {MDI Example}
11222 */
isWindowModified() const11223 bool QWidget::isWindowModified() const
11224 {
11225     return testAttribute(Qt::WA_WindowModified);
11226 }
11227 
setWindowModified(bool mod)11228 void QWidget::setWindowModified(bool mod)
11229 {
11230     Q_D(QWidget);
11231     setAttribute(Qt::WA_WindowModified, mod);
11232 
11233     d->setWindowModified_helper();
11234 
11235     QEvent e(QEvent::ModifiedChange);
11236     QCoreApplication::sendEvent(this, &e);
11237 }
11238 
setWindowModified_helper()11239 void QWidgetPrivate::setWindowModified_helper()
11240 {
11241     Q_Q(QWidget);
11242     QWindow *window = q->windowHandle();
11243     if (!window)
11244         return;
11245     QPlatformWindow *platformWindow = window->handle();
11246     if (!platformWindow)
11247         return;
11248     bool on = q->testAttribute(Qt::WA_WindowModified);
11249     if (!platformWindow->setWindowModified(on)) {
11250         if (Q_UNLIKELY(on && !q->windowTitle().contains(QLatin1String("[*]"))))
11251             qWarning("QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
11252         setWindowTitle_helper(q->windowTitle());
11253         setWindowIconText_helper(q->windowIconText());
11254     }
11255 }
11256 
11257 #ifndef QT_NO_TOOLTIP
11258 /*!
11259   \property QWidget::toolTip
11260 
11261   \brief the widget's tooltip
11262 
11263   Note that by default tooltips are only shown for widgets that are
11264   children of the active window. You can change this behavior by
11265   setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
11266   not on the widget with the tooltip.
11267 
11268   If you want to control a tooltip's behavior, you can intercept the
11269   event() function and catch the QEvent::ToolTip event (e.g., if you
11270   want to customize the area for which the tooltip should be shown).
11271 
11272   By default, this property contains an empty string.
11273 
11274   \sa QToolTip, statusTip, whatsThis
11275 */
setToolTip(const QString & s)11276 void QWidget::setToolTip(const QString &s)
11277 {
11278     Q_D(QWidget);
11279     d->toolTip = s;
11280 
11281     QEvent event(QEvent::ToolTipChange);
11282     QCoreApplication::sendEvent(this, &event);
11283 }
11284 
toolTip() const11285 QString QWidget::toolTip() const
11286 {
11287     Q_D(const QWidget);
11288     return d->toolTip;
11289 }
11290 
11291 /*!
11292   \property QWidget::toolTipDuration
11293   \brief the widget's tooltip duration
11294   \since 5.2
11295 
11296   Specifies how long time the tooltip will be displayed, in milliseconds.
11297   If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
11298 
11299   \sa toolTip
11300 */
11301 
setToolTipDuration(int msec)11302 void QWidget::setToolTipDuration(int msec)
11303 {
11304     Q_D(QWidget);
11305     d->toolTipDuration = msec;
11306 }
11307 
toolTipDuration() const11308 int QWidget::toolTipDuration() const
11309 {
11310     Q_D(const QWidget);
11311     return d->toolTipDuration;
11312 }
11313 
11314 #endif // QT_NO_TOOLTIP
11315 
11316 
11317 #if QT_CONFIG(statustip)
11318 /*!
11319   \property QWidget::statusTip
11320   \brief the widget's status tip
11321 
11322   By default, this property contains an empty string.
11323 
11324   \sa toolTip, whatsThis
11325 */
setStatusTip(const QString & s)11326 void QWidget::setStatusTip(const QString &s)
11327 {
11328     Q_D(QWidget);
11329     d->statusTip = s;
11330 }
11331 
statusTip() const11332 QString QWidget::statusTip() const
11333 {
11334     Q_D(const QWidget);
11335     return d->statusTip;
11336 }
11337 #endif // QT_CONFIG(statustip)
11338 
11339 #if QT_CONFIG(whatsthis)
11340 /*!
11341   \property QWidget::whatsThis
11342 
11343   \brief the widget's What's This help text.
11344 
11345   By default, this property contains an empty string.
11346 
11347   \sa QWhatsThis, QWidget::toolTip, QWidget::statusTip
11348 */
setWhatsThis(const QString & s)11349 void QWidget::setWhatsThis(const QString &s)
11350 {
11351     Q_D(QWidget);
11352     d->whatsThis = s;
11353 }
11354 
whatsThis() const11355 QString QWidget::whatsThis() const
11356 {
11357     Q_D(const QWidget);
11358     return d->whatsThis;
11359 }
11360 #endif // QT_CONFIG(whatsthis)
11361 
11362 #ifndef QT_NO_ACCESSIBILITY
11363 /*!
11364   \property QWidget::accessibleName
11365 
11366   \brief the widget's name as seen by assistive technologies
11367 
11368   This is the primary name by which assistive technology such as screen readers
11369   announce this widget. For most widgets setting this property is not required.
11370   For example for QPushButton the button's text will be used.
11371 
11372   It is important to set this property when the widget does not provide any
11373   text. For example a button that only contains an icon needs to set this
11374   property to work with screen readers.
11375   The name should be short and equivalent to the visual information conveyed
11376   by the widget.
11377 
11378   This property has to be \l{Internationalization with Qt}{localized}.
11379 
11380   By default, this property contains an empty string.
11381 
11382   \sa QWidget::accessibleDescription, QAccessibleInterface::text()
11383 */
setAccessibleName(const QString & name)11384 void QWidget::setAccessibleName(const QString &name)
11385 {
11386     Q_D(QWidget);
11387     d->accessibleName = name;
11388     QAccessibleEvent event(this, QAccessible::NameChanged);
11389     QAccessible::updateAccessibility(&event);
11390 }
11391 
accessibleName() const11392 QString QWidget::accessibleName() const
11393 {
11394     Q_D(const QWidget);
11395     return d->accessibleName;
11396 }
11397 
11398 /*!
11399   \property QWidget::accessibleDescription
11400 
11401   \brief the widget's description as seen by assistive technologies
11402 
11403   The accessible description of a widget should convey what a widget does.
11404   While the \l accessibleName should be a short and concise string (e.g. \gui{Save}),
11405   the description should give more context, such as \gui{Saves the current document}.
11406 
11407   This property has to be \l{Internationalization with Qt}{localized}.
11408 
11409   By default, this property contains an empty string and Qt falls back
11410   to using the tool tip to provide this information.
11411 
11412   \sa QWidget::accessibleName, QAccessibleInterface::text()
11413 */
setAccessibleDescription(const QString & description)11414 void QWidget::setAccessibleDescription(const QString &description)
11415 {
11416     Q_D(QWidget);
11417     d->accessibleDescription = description;
11418     QAccessibleEvent event(this, QAccessible::DescriptionChanged);
11419     QAccessible::updateAccessibility(&event);
11420 }
11421 
accessibleDescription() const11422 QString QWidget::accessibleDescription() const
11423 {
11424     Q_D(const QWidget);
11425     return d->accessibleDescription;
11426 }
11427 #endif // QT_NO_ACCESSIBILITY
11428 
11429 #ifndef QT_NO_SHORTCUT
11430 /*!
11431     Adds a shortcut to Qt's shortcut system that watches for the given
11432     \a key sequence in the given \a context. If the \a context is
11433     Qt::ApplicationShortcut, the shortcut applies to the application as a
11434     whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
11435     or to the window itself, Qt::WindowShortcut.
11436 
11437     If the same \a key sequence has been grabbed by several widgets,
11438     when the \a key sequence occurs a QEvent::Shortcut event is sent
11439     to all the widgets to which it applies in a non-deterministic
11440     order, but with the ``ambiguous'' flag set to true.
11441 
11442     \warning You should not normally need to use this function;
11443     instead create \l{QAction}s with the shortcut key sequences you
11444     require (if you also want equivalent menu options and toolbar
11445     buttons), or create \l{QShortcut}s if you just need key sequences.
11446     Both QAction and QShortcut handle all the event filtering for you,
11447     and provide signals which are triggered when the user triggers the
11448     key sequence, so are much easier to use than this low-level
11449     function.
11450 
11451     \sa releaseShortcut(), setShortcutEnabled()
11452 */
grabShortcut(const QKeySequence & key,Qt::ShortcutContext context)11453 int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
11454 {
11455     Q_ASSERT(qApp);
11456     if (key.isEmpty())
11457         return 0;
11458     setAttribute(Qt::WA_GrabbedShortcut);
11459     return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, key, context, qWidgetShortcutContextMatcher);
11460 }
11461 
11462 /*!
11463     Removes the shortcut with the given \a id from Qt's shortcut
11464     system. The widget will no longer receive QEvent::Shortcut events
11465     for the shortcut's key sequence (unless it has other shortcuts
11466     with the same key sequence).
11467 
11468     \warning You should not normally need to use this function since
11469     Qt's shortcut system removes shortcuts automatically when their
11470     parent widget is destroyed. It is best to use QAction or
11471     QShortcut to handle shortcuts, since they are easier to use than
11472     this low-level function. Note also that this is an expensive
11473     operation.
11474 
11475     \sa grabShortcut(), setShortcutEnabled()
11476 */
releaseShortcut(int id)11477 void QWidget::releaseShortcut(int id)
11478 {
11479     Q_ASSERT(qApp);
11480     if (id)
11481         QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this, 0);
11482 }
11483 
11484 /*!
11485     If \a enable is true, the shortcut with the given \a id is
11486     enabled; otherwise the shortcut is disabled.
11487 
11488     \warning You should not normally need to use this function since
11489     Qt's shortcut system enables/disables shortcuts automatically as
11490     widgets become hidden/visible and gain or lose focus. It is best
11491     to use QAction or QShortcut to handle shortcuts, since they are
11492     easier to use than this low-level function.
11493 
11494     \sa grabShortcut(), releaseShortcut()
11495 */
setShortcutEnabled(int id,bool enable)11496 void QWidget::setShortcutEnabled(int id, bool enable)
11497 {
11498     Q_ASSERT(qApp);
11499     if (id)
11500         QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, this, 0);
11501 }
11502 
11503 /*!
11504     \since 4.2
11505 
11506     If \a enable is true, auto repeat of the shortcut with the
11507     given \a id is enabled; otherwise it is disabled.
11508 
11509     \sa grabShortcut(), releaseShortcut()
11510 */
setShortcutAutoRepeat(int id,bool enable)11511 void QWidget::setShortcutAutoRepeat(int id, bool enable)
11512 {
11513     Q_ASSERT(qApp);
11514     if (id)
11515         QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(enable, id, this, 0);
11516 }
11517 #endif // QT_NO_SHORTCUT
11518 
11519 /*!
11520     Updates the widget's micro focus.
11521 */
updateMicroFocus()11522 void QWidget::updateMicroFocus()
11523 {
11524     // updating everything since this is currently called for any kind of state change
11525     if (this == QGuiApplication::focusObject())
11526         QGuiApplication::inputMethod()->update(Qt::ImQueryAll);
11527 }
11528 
11529 /*!
11530     Raises this widget to the top of the parent widget's stack.
11531 
11532     After this call the widget will be visually in front of any
11533     overlapping sibling widgets.
11534 
11535     \note When using activateWindow(), you can call this function to
11536     ensure that the window is stacked on top.
11537 
11538     \sa lower(), stackUnder()
11539 */
11540 
raise()11541 void QWidget::raise()
11542 {
11543     Q_D(QWidget);
11544     if (!isWindow()) {
11545         QWidget *p = parentWidget();
11546         const int parentChildCount = p->d_func()->children.size();
11547         if (parentChildCount < 2)
11548             return;
11549         const int from = p->d_func()->children.indexOf(this);
11550         Q_ASSERT(from >= 0);
11551         // Do nothing if the widget is already in correct stacking order _and_ created.
11552         if (from != parentChildCount -1)
11553             p->d_func()->children.move(from, parentChildCount - 1);
11554         if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
11555             create();
11556         else if (from == parentChildCount - 1)
11557             return;
11558 
11559         QRegion region(rect());
11560         d->subtractOpaqueSiblings(region);
11561         d->invalidateBackingStore(region);
11562     }
11563     if (testAttribute(Qt::WA_WState_Created))
11564         d->raise_sys();
11565 
11566     if (d->extra && d->extra->hasWindowContainer)
11567         QWindowContainer::parentWasRaised(this);
11568 
11569     QEvent e(QEvent::ZOrderChange);
11570     QCoreApplication::sendEvent(this, &e);
11571 }
11572 
raise_sys()11573 void QWidgetPrivate::raise_sys()
11574 {
11575     Q_Q(QWidget);
11576     if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
11577         q->windowHandle()->raise();
11578     } else if (renderToTexture) {
11579         if (QWidget *p = q->parentWidget()) {
11580             setDirtyOpaqueRegion();
11581             p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
11582         }
11583     }
11584 }
11585 
11586 /*!
11587     Lowers the widget to the bottom of the parent widget's stack.
11588 
11589     After this call the widget will be visually behind (and therefore
11590     obscured by) any overlapping sibling widgets.
11591 
11592     \sa raise(), stackUnder()
11593 */
11594 
lower()11595 void QWidget::lower()
11596 {
11597     Q_D(QWidget);
11598     if (!isWindow()) {
11599         QWidget *p = parentWidget();
11600         const int parentChildCount = p->d_func()->children.size();
11601         if (parentChildCount < 2)
11602             return;
11603         const int from = p->d_func()->children.indexOf(this);
11604         Q_ASSERT(from >= 0);
11605         // Do nothing if the widget is already in correct stacking order _and_ created.
11606         if (from != 0)
11607             p->d_func()->children.move(from, 0);
11608         if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
11609             create();
11610         else if (from == 0)
11611             return;
11612     }
11613     if (testAttribute(Qt::WA_WState_Created))
11614         d->lower_sys();
11615 
11616     if (d->extra && d->extra->hasWindowContainer)
11617         QWindowContainer::parentWasLowered(this);
11618 
11619     QEvent e(QEvent::ZOrderChange);
11620     QCoreApplication::sendEvent(this, &e);
11621 }
11622 
lower_sys()11623 void QWidgetPrivate::lower_sys()
11624 {
11625     Q_Q(QWidget);
11626     if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
11627         Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
11628         q->windowHandle()->lower();
11629     } else if (QWidget *p = q->parentWidget()) {
11630         setDirtyOpaqueRegion();
11631         p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
11632     }
11633 }
11634 
11635 /*!
11636     Places the widget under \a w in the parent widget's stack.
11637 
11638     To make this work, the widget itself and \a w must be siblings.
11639 
11640     \sa raise(), lower()
11641 */
stackUnder(QWidget * w)11642 void QWidget::stackUnder(QWidget* w)
11643 {
11644     Q_D(QWidget);
11645     QWidget *p = parentWidget();
11646     if (!w || isWindow() || p != w->parentWidget() || this == w)
11647         return;
11648     if (p) {
11649         int from = p->d_func()->children.indexOf(this);
11650         int to = p->d_func()->children.indexOf(w);
11651         Q_ASSERT(from >= 0);
11652         Q_ASSERT(to >= 0);
11653         if (from < to)
11654             --to;
11655         // Do nothing if the widget is already in correct stacking order _and_ created.
11656         if (from != to)
11657             p->d_func()->children.move(from, to);
11658         if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
11659             create();
11660         else if (from == to)
11661             return;
11662     }
11663     if (testAttribute(Qt::WA_WState_Created))
11664         d->stackUnder_sys(w);
11665 
11666     QEvent e(QEvent::ZOrderChange);
11667     QCoreApplication::sendEvent(this, &e);
11668 }
11669 
stackUnder_sys(QWidget *)11670 void QWidgetPrivate::stackUnder_sys(QWidget*)
11671 {
11672     Q_Q(QWidget);
11673     if (QWidget *p = q->parentWidget()) {
11674         setDirtyOpaqueRegion();
11675         p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
11676     }
11677 }
11678 
11679 /*!
11680     \fn bool QWidget::isTopLevel() const
11681     \obsolete
11682 
11683     Use isWindow() instead.
11684 */
11685 
11686 /*!
11687     \fn bool QWidget::isRightToLeft() const
11688     \internal
11689 */
11690 
11691 /*!
11692     \fn bool QWidget::isLeftToRight() const
11693     \internal
11694 */
11695 
11696 /*!
11697      \macro QWIDGETSIZE_MAX
11698      \relates QWidget
11699 
11700      Defines the maximum size for a QWidget object.
11701 
11702      The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
11703      QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
11704 
11705      \sa QWidget::setMaximumSize()
11706 */
11707 
11708 /*!
11709     \fn QWidget::setupUi(QWidget *widget)
11710 
11711     Sets up the user interface for the specified \a widget.
11712 
11713     \note This function is available with widgets that derive from user
11714     interface descriptions created using \l{uic}.
11715 
11716     \sa {Using a Designer UI File in Your C++ Application}
11717 */
11718 
frameStrut() const11719 QRect QWidgetPrivate::frameStrut() const
11720 {
11721     Q_Q(const QWidget);
11722     if (!q->isWindow() || (q->windowType() == Qt::Desktop) || q->testAttribute(Qt::WA_DontShowOnScreen)) {
11723         // x2 = x1 + w - 1, so w/h = 1
11724         return QRect(0, 0, 1, 1);
11725     }
11726 
11727     if (data.fstrut_dirty
11728         // ### Fix properly for 4.3
11729         && q->isVisible()
11730         && q->testAttribute(Qt::WA_WState_Created))
11731         const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
11732 
11733     return maybeTopData() ? maybeTopData()->frameStrut : QRect();
11734 }
11735 
updateFrameStrut()11736 void QWidgetPrivate::updateFrameStrut()
11737 {
11738     Q_Q(QWidget);
11739     if (q->data->fstrut_dirty) {
11740         if (QTLWExtra *te = maybeTopData()) {
11741             if (te->window && te->window->handle()) {
11742                 const QMargins margins = te->window->frameMargins();
11743                 if (!margins.isNull()) {
11744                     te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
11745                     q->data->fstrut_dirty = false;
11746                 }
11747             }
11748         }
11749     }
11750 }
11751 
11752 #ifdef QT_KEYPAD_NAVIGATION
11753 /*!
11754     \internal
11755 
11756     Changes the focus  from the current focusWidget to a widget in
11757     the \a direction.
11758 
11759     Returns \c true, if there was a widget in that direction
11760 */
navigateToDirection(Direction direction)11761 bool QWidgetPrivate::navigateToDirection(Direction direction)
11762 {
11763     QWidget *targetWidget = widgetInNavigationDirection(direction);
11764     if (targetWidget)
11765         targetWidget->setFocus();
11766     return (targetWidget != 0);
11767 }
11768 
11769 /*!
11770     \internal
11771 
11772     Searches for a widget that is positioned in the \a direction, starting
11773     from the current focusWidget.
11774 
11775     Returns the pointer to a found widget or \nullptr, if there was no widget
11776     in that direction.
11777 */
widgetInNavigationDirection(Direction direction)11778 QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction)
11779 {
11780     const QWidget *sourceWidget = QApplication::focusWidget();
11781     if (!sourceWidget)
11782         return nullptr;
11783     const QRect sourceRect = sourceWidget->rect().translated(sourceWidget->mapToGlobal(QPoint()));
11784     const int sourceX =
11785             (direction == DirectionNorth || direction == DirectionSouth) ?
11786                 (sourceRect.left() + (sourceRect.right() - sourceRect.left()) / 2)
11787                 :(direction == DirectionEast ? sourceRect.right() : sourceRect.left());
11788     const int sourceY =
11789             (direction == DirectionEast || direction == DirectionWest) ?
11790                 (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2)
11791                 :(direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top());
11792     const QPoint sourcePoint(sourceX, sourceY);
11793     const QPoint sourceCenter = sourceRect.center();
11794     const QWidget *sourceWindow = sourceWidget->window();
11795 
11796     QWidget *targetWidget = nullptr;
11797     int shortestDistance = INT_MAX;
11798 
11799     const auto targetCandidates = QApplication::allWidgets();
11800     for (QWidget *targetCandidate : targetCandidates) {
11801 
11802         const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint()));
11803 
11804         // For focus proxies, the child widget handling the focus can have keypad navigation focus,
11805         // but the owner of the proxy cannot.
11806         // Additionally, empty widgets should be ignored.
11807         if (targetCandidate->focusProxy() || targetCandidateRect.isEmpty())
11808             continue;
11809 
11810         // Only navigate to a target widget that...
11811         if (       targetCandidate != sourceWidget
11812                    // ...takes the focus,
11813                 && targetCandidate->focusPolicy() & Qt::TabFocus
11814                    // ...is above if DirectionNorth,
11815                 && !(direction == DirectionNorth && targetCandidateRect.bottom() > sourceRect.top())
11816                    // ...is on the right if DirectionEast,
11817                 && !(direction == DirectionEast  && targetCandidateRect.left()   < sourceRect.right())
11818                    // ...is below if DirectionSouth,
11819                 && !(direction == DirectionSouth && targetCandidateRect.top()    < sourceRect.bottom())
11820                    // ...is on the left if DirectionWest,
11821                 && !(direction == DirectionWest  && targetCandidateRect.right()  > sourceRect.left())
11822                    // ...is enabled,
11823                 && targetCandidate->isEnabled()
11824                    // ...is visible,
11825                 && targetCandidate->isVisible()
11826                    // ...is in the same window,
11827                 && targetCandidate->window() == sourceWindow) {
11828             const int targetCandidateDistance = pointToRect(sourcePoint, targetCandidateRect);
11829             if (targetCandidateDistance < shortestDistance) {
11830                 shortestDistance = targetCandidateDistance;
11831                 targetWidget = targetCandidate;
11832             }
11833         }
11834     }
11835     return targetWidget;
11836 }
11837 
11838 /*!
11839     \internal
11840 
11841     Tells us if it there is currently a reachable widget by keypad navigation in
11842     a certain \a orientation.
11843     If no navigation is possible, occurring key events in that \a orientation may
11844     be used to interact with the value in the focused widget, even though it
11845     currently has not the editFocus.
11846 
11847     \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus()
11848 */
canKeypadNavigate(Qt::Orientation orientation)11849 bool QWidgetPrivate::canKeypadNavigate(Qt::Orientation orientation)
11850 {
11851     return orientation == Qt::Horizontal?
11852             (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast)
11853                     || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest))
11854             :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth)
11855                     || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth));
11856 }
11857 /*!
11858     \internal
11859 
11860     Checks, if the \a widget is inside a QTabWidget. If is is inside
11861     one, left/right key events will be used to switch between tabs in keypad
11862     navigation. If there is no QTabWidget, the horizontal key events can be used
11863 to
11864     interact with the value in the focused widget, even though it currently has
11865     not the editFocus.
11866 
11867     \sa QWidget::hasEditFocus()
11868 */
inTabWidget(QWidget * widget)11869 bool QWidgetPrivate::inTabWidget(QWidget *widget)
11870 {
11871     for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget())
11872         if (qobject_cast<const QTabWidget*>(tabWidget))
11873             return true;
11874     return false;
11875 }
11876 #endif
11877 
11878 /*!
11879     \since 5.0
11880     \internal
11881 
11882     Sets the backing store to be the \a store specified.
11883     The QWidget will take ownership of the \a store.
11884 */
setBackingStore(QBackingStore * store)11885 void QWidget::setBackingStore(QBackingStore *store)
11886 {
11887     // ### createWinId() ??
11888 
11889     if (!isTopLevel())
11890         return;
11891 
11892     Q_D(QWidget);
11893 
11894     QTLWExtra *topData = d->topData();
11895     if (topData->backingStore == store)
11896         return;
11897 
11898     QBackingStore *oldStore = topData->backingStore;
11899     deleteBackingStore(d);
11900     topData->backingStore = store;
11901 
11902     QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
11903     if (!repaintManager)
11904         return;
11905 
11906     if (isTopLevel()) {
11907         if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store)
11908             delete repaintManager->backingStore();
11909         repaintManager->setBackingStore(store);
11910     }
11911 }
11912 
11913 /*!
11914     \since 5.0
11915 
11916     Returns the QBackingStore this widget will be drawn into.
11917 */
backingStore() const11918 QBackingStore *QWidget::backingStore() const
11919 {
11920     Q_D(const QWidget);
11921     QTLWExtra *extra = d->maybeTopData();
11922     if (extra && extra->backingStore)
11923         return extra->backingStore;
11924 
11925     QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
11926     return repaintManager ? repaintManager->backingStore() : nullptr;
11927 }
11928 
getLayoutItemMargins(int * left,int * top,int * right,int * bottom) const11929 void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
11930 {
11931     if (left)
11932         *left = (int)leftLayoutItemMargin;
11933     if (top)
11934         *top = (int)topLayoutItemMargin;
11935     if (right)
11936         *right = (int)rightLayoutItemMargin;
11937     if (bottom)
11938         *bottom = (int)bottomLayoutItemMargin;
11939 }
11940 
setLayoutItemMargins(int left,int top,int right,int bottom)11941 void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
11942 {
11943     if (leftLayoutItemMargin == left
11944         && topLayoutItemMargin == top
11945         && rightLayoutItemMargin == right
11946         && bottomLayoutItemMargin == bottom)
11947         return;
11948 
11949     Q_Q(QWidget);
11950     leftLayoutItemMargin = (signed char)left;
11951     topLayoutItemMargin = (signed char)top;
11952     rightLayoutItemMargin = (signed char)right;
11953     bottomLayoutItemMargin = (signed char)bottom;
11954     q->updateGeometry();
11955 }
11956 
setLayoutItemMargins(QStyle::SubElement element,const QStyleOption * opt)11957 void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
11958 {
11959     Q_Q(QWidget);
11960     QStyleOption myOpt;
11961     if (!opt) {
11962         myOpt.initFrom(q);
11963         myOpt.rect.setRect(0, 0, 32768, 32768);     // arbitrary
11964         opt = &myOpt;
11965     }
11966 
11967     QRect liRect = q->style()->subElementRect(element, opt, q);
11968     if (liRect.isValid()) {
11969         leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
11970         topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
11971         rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
11972         bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
11973     } else {
11974         leftLayoutItemMargin = 0;
11975         topLayoutItemMargin = 0;
11976         rightLayoutItemMargin = 0;
11977         bottomLayoutItemMargin = 0;
11978     }
11979 }
11980 // resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
adjustQuitOnCloseAttribute()11981 void QWidgetPrivate::adjustQuitOnCloseAttribute()
11982 {
11983     Q_Q(QWidget);
11984 
11985     if (!q->parentWidget()) {
11986         Qt::WindowType type = q->windowType();
11987         if (type == Qt::Widget || type == Qt::SubWindow)
11988             type = Qt::Window;
11989         if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
11990             q->setAttribute(Qt::WA_QuitOnClose, false);
11991     }
11992 }
11993 
shareContext() const11994 QOpenGLContext *QWidgetPrivate::shareContext() const
11995 {
11996 #ifdef QT_NO_OPENGL
11997     return 0;
11998 #else
11999     if (!extra || !extra->topextra || !extra->topextra->window)
12000         return nullptr;
12001 
12002     if (!extra->topextra->shareContext) {
12003         auto ctx = qt_make_unique<QOpenGLContext>();
12004         ctx->setShareContext(qt_gl_global_share_context());
12005         ctx->setFormat(extra->topextra->window->format());
12006         ctx->setScreen(extra->topextra->window->screen());
12007         ctx->create();
12008         extra->topextra->shareContext = std::move(ctx);
12009     }
12010     return extra->topextra->shareContext.get();
12011 #endif // QT_NO_OPENGL
12012 }
12013 
12014 #ifndef QT_NO_OPENGL
sendComposeStatus(QWidget * w,bool end)12015 void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
12016 {
12017     QWidgetPrivate *wd = QWidgetPrivate::get(w);
12018     if (!wd->textureChildSeen)
12019         return;
12020     if (end)
12021         wd->endCompose();
12022     else
12023         wd->beginCompose();
12024     for (int i = 0; i < wd->children.size(); ++i) {
12025         w = qobject_cast<QWidget *>(wd->children.at(i));
12026         if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
12027             sendComposeStatus(w, end);
12028     }
12029 }
12030 #endif // QT_NO_OPENGL
12031 
qt_qwidget_data(QWidget * widget)12032 Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
12033 {
12034     return widget->data;
12035 }
12036 
qt_widget_private(QWidget * widget)12037 Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
12038 {
12039     return widget->d_func();
12040 }
12041 
12042 
12043 #if QT_CONFIG(graphicsview)
12044 /*!
12045    \since 4.5
12046 
12047    Returns the proxy widget for the corresponding embedded widget in a graphics
12048    view; otherwise returns \nullptr.
12049 
12050    \sa QGraphicsProxyWidget::createProxyForChildWidget(),
12051        QGraphicsScene::addWidget()
12052  */
graphicsProxyWidget() const12053 QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
12054 {
12055     Q_D(const QWidget);
12056     if (d->extra) {
12057         return d->extra->proxyWidget;
12058     }
12059     return nullptr;
12060 }
12061 #endif
12062 
12063 #ifndef QT_NO_GESTURES
12064 /*!
12065     Subscribes the widget to a given \a gesture with specific \a flags.
12066 
12067     \sa ungrabGesture(), QGestureEvent
12068     \since 4.6
12069 */
grabGesture(Qt::GestureType gesture,Qt::GestureFlags flags)12070 void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
12071 {
12072     Q_D(QWidget);
12073     d->gestureContext.insert(gesture, flags);
12074     (void)QGestureManager::instance(); // create a gesture manager
12075 }
12076 
12077 /*!
12078     Unsubscribes the widget from a given \a gesture type
12079 
12080     \sa grabGesture(), QGestureEvent
12081     \since 4.6
12082 */
ungrabGesture(Qt::GestureType gesture)12083 void QWidget::ungrabGesture(Qt::GestureType gesture)
12084 {
12085     // if you modify this function, check the inlined version in ~QWidget, too
12086     Q_D(QWidget);
12087     if (d->gestureContext.remove(gesture)) {
12088         if (QGestureManager *manager = QGestureManager::instance())
12089             manager->cleanupCachedGestures(this, gesture);
12090     }
12091 }
12092 #endif // QT_NO_GESTURES
12093 
12094 /*!
12095     \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12096 
12097     Frees up window system resources. Destroys the widget window if \a
12098     destroyWindow is true.
12099 
12100     destroy() calls itself recursively for all the child widgets,
12101     passing \a destroySubWindows for the \a destroyWindow parameter.
12102     To have more control over destruction of subwidgets, destroy
12103     subwidgets selectively first.
12104 
12105     This function is usually called from the QWidget destructor.
12106 */
destroy(bool destroyWindow,bool destroySubWindows)12107 void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12108 {
12109     Q_D(QWidget);
12110 
12111     d->aboutToDestroy();
12112     if (!isWindow() && parentWidget())
12113         parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(geometry()));
12114     d->deactivateWidgetCleanup();
12115 
12116     if ((windowType() == Qt::Popup) && qApp)
12117         qApp->d_func()->closePopup(this);
12118 
12119     if (this == QApplicationPrivate::active_window)
12120         QApplication::setActiveWindow(nullptr);
12121     if (QWidget::mouseGrabber() == this)
12122         releaseMouse();
12123     if (QWidget::keyboardGrabber() == this)
12124         releaseKeyboard();
12125 
12126     setAttribute(Qt::WA_WState_Created, false);
12127 
12128     if (windowType() != Qt::Desktop) {
12129         if (destroySubWindows) {
12130             QObjectList childList(children());
12131             for (int i = 0; i < childList.size(); i++) {
12132                 QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
12133                 if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
12134                     if (widget->windowHandle()) {
12135                         widget->destroy();
12136                     }
12137                 }
12138             }
12139         }
12140         if (destroyWindow) {
12141             d->deleteTLSysExtra();
12142         } else {
12143             if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
12144                 d->hide_sys();
12145             }
12146         }
12147 
12148         d->setWinId(0);
12149     }
12150 }
12151 
12152 /*!
12153     \fn QPaintEngine *QWidget::paintEngine() const
12154 
12155     Returns the widget's paint engine.
12156 
12157     Note that this function should not be called explicitly by the
12158     user, since it's meant for reimplementation purposes only. The
12159     function is called by Qt internally, and the default
12160     implementation may not always return a valid pointer.
12161 */
paintEngine() const12162 QPaintEngine *QWidget::paintEngine() const
12163 {
12164     qWarning("QWidget::paintEngine: Should no longer be called");
12165 
12166 #ifdef Q_OS_WIN
12167     // We set this bit which is checked in setAttribute for
12168     // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
12169     //
12170     // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
12171     // Windows which would mean suddenly their widgets stop working.
12172     //
12173     // 2. Users set paint on screen and subclass paintEngine() to
12174     // return 0, in which case we have a "hole" in the backingstore
12175     // allowing use of GDI or DirectX directly.
12176     //
12177     // 1 is WRONG, but to minimize silent failures, we have set this
12178     // bit to ignore the setAttribute call. 2. needs to be
12179     // supported because its our only means of embedding native
12180     // graphics stuff.
12181     const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
12182 #endif
12183 
12184     return nullptr; //##### @@@
12185 }
12186 
12187 // Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing.
canMapPosition(QWindow * window)12188 static inline bool canMapPosition(QWindow *window)
12189 {
12190     return window->handle() && !qt_window_private(window)->resizeEventPending;
12191 }
12192 
12193 #if QT_CONFIG(graphicsview)
graphicsProxyWidget(const QWidget * w)12194 static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w)
12195 {
12196     QGraphicsProxyWidget *result = nullptr;
12197     const QWidgetPrivate *d = qt_widget_private(const_cast<QWidget *>(w));
12198     if (d->extra)
12199         result = d->extra->proxyWidget;
12200     return result;
12201 }
12202 #endif // QT_CONFIG(graphicsview)
12203 
12204 struct MapToGlobalTransformResult {
12205     QTransform transform;
12206     QWindow *window;
12207 };
12208 
mapToGlobalTransform(const QWidget * w)12209 static MapToGlobalTransformResult mapToGlobalTransform(const QWidget *w)
12210 {
12211     MapToGlobalTransformResult result;
12212     result.window = nullptr;
12213     for ( ; w ; w = w->parentWidget()) {
12214 #if QT_CONFIG(graphicsview)
12215         if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) {
12216             if (const QGraphicsScene *scene = qgpw->scene()) {
12217                 const QList <QGraphicsView *> views = scene->views();
12218                 if (!views.isEmpty()) {
12219                     result.transform *= qgpw->sceneTransform();
12220                     result.transform *= views.first()->viewportTransform();
12221                     w = views.first()->viewport();
12222                 }
12223             }
12224         }
12225 #endif // QT_CONFIG(graphicsview)
12226         QWindow *window = w->windowHandle();
12227         if (window && canMapPosition(window)) {
12228             result.window = window;
12229             break;
12230         }
12231 
12232         const QPoint topLeft = w->geometry().topLeft();
12233         result.transform.translate(topLeft.x(), topLeft.y());
12234         if (w->isWindow())
12235             break;
12236     }
12237     return result;
12238 }
12239 
12240 /*!
12241     \fn QPoint QWidget::mapToGlobal(const QPoint &pos) const
12242 
12243     Translates the widget coordinate \a pos to global screen
12244     coordinates. For example, \c{mapToGlobal(QPoint(0,0))} would give
12245     the global coordinates of the top-left pixel of the widget.
12246 
12247     \sa mapFromGlobal(), mapTo(), mapToParent()
12248 */
mapToGlobal(const QPoint & pos) const12249 QPoint QWidget::mapToGlobal(const QPoint &pos) const
12250 {
12251     const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12252     const QPoint g = t.transform.map(pos);
12253     return t.window ? t.window->mapToGlobal(g) : g;
12254 }
12255 
12256 /*!
12257     \fn QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12258 
12259     Translates the global screen coordinate \a pos to widget
12260     coordinates.
12261 
12262     \sa mapToGlobal(), mapFrom(), mapFromParent()
12263 */
mapFromGlobal(const QPoint & pos) const12264 QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12265 {
12266    const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12267    const QPoint windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos;
12268    return t.transform.inverted().map(windowLocal);
12269 }
12270 
12271 QWidget *qt_pressGrab = nullptr;
12272 QWidget *qt_mouseGrb = nullptr;
12273 static bool mouseGrabWithCursor = false;
12274 static QWidget *keyboardGrb = nullptr;
12275 
grabberWindow(const QWidget * w)12276 static inline QWindow *grabberWindow(const QWidget *w)
12277 {
12278     QWindow *window = w->windowHandle();
12279     if (!window)
12280         if (const QWidget *nativeParent = w->nativeParentWidget())
12281             window = nativeParent->windowHandle();
12282     return window;
12283 }
12284 
12285 #ifndef QT_NO_CURSOR
grabMouseForWidget(QWidget * widget,const QCursor * cursor=nullptr)12286 static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = nullptr)
12287 #else
12288 static void grabMouseForWidget(QWidget *widget)
12289 #endif
12290 {
12291     if (qt_mouseGrb)
12292         qt_mouseGrb->releaseMouse();
12293 
12294     mouseGrabWithCursor = false;
12295     if (QWindow *window = grabberWindow(widget)) {
12296 #ifndef QT_NO_CURSOR
12297         if (cursor) {
12298             mouseGrabWithCursor = true;
12299             QGuiApplication::setOverrideCursor(*cursor);
12300         }
12301 #endif // !QT_NO_CURSOR
12302         window->setMouseGrabEnabled(true);
12303     }
12304 
12305     qt_mouseGrb = widget;
12306     qt_pressGrab = nullptr;
12307 }
12308 
releaseMouseGrabOfWidget(QWidget * widget)12309 static void releaseMouseGrabOfWidget(QWidget *widget)
12310 {
12311     if (qt_mouseGrb == widget) {
12312         if (QWindow *window = grabberWindow(widget)) {
12313 #ifndef QT_NO_CURSOR
12314             if (mouseGrabWithCursor) {
12315                 QGuiApplication::restoreOverrideCursor();
12316                 mouseGrabWithCursor = false;
12317             }
12318 #endif // !QT_NO_CURSOR
12319             window->setMouseGrabEnabled(false);
12320         }
12321     }
12322     qt_mouseGrb = nullptr;
12323 }
12324 
12325 /*!
12326     \fn void QWidget::grabMouse()
12327 
12328     Grabs the mouse input.
12329 
12330     This widget receives all mouse events until releaseMouse() is
12331     called; other widgets get no mouse events at all. Keyboard
12332     events are not affected. Use grabKeyboard() if you want to grab
12333     that.
12334 
12335     \warning Bugs in mouse-grabbing applications very often lock the
12336     terminal. Use this function with extreme caution, and consider
12337     using the \c -nograb command line option while debugging.
12338 
12339     It is almost never necessary to grab the mouse when using Qt, as
12340     Qt grabs and releases it sensibly. In particular, Qt grabs the
12341     mouse when a mouse button is pressed and keeps it until the last
12342     button is released.
12343 
12344     \note Only visible widgets can grab mouse input. If isVisible()
12345     returns \c false for a widget, that widget cannot call grabMouse().
12346 
12347     \note On Windows, grabMouse() only works when the mouse is inside a window
12348     owned by the process.
12349     On \macos, grabMouse() only works when the mouse is inside the frame of that widget.
12350 
12351     \sa releaseMouse(), grabKeyboard(), releaseKeyboard()
12352 */
grabMouse()12353 void QWidget::grabMouse()
12354 {
12355     grabMouseForWidget(this);
12356 }
12357 
12358 /*!
12359     \fn void QWidget::grabMouse(const QCursor &cursor)
12360     \overload grabMouse()
12361 
12362     Grabs the mouse input and changes the cursor shape.
12363 
12364     The cursor will assume shape \a cursor (for as long as the mouse
12365     focus is grabbed) and this widget will be the only one to receive
12366     mouse events until releaseMouse() is called().
12367 
12368     \warning Grabbing the mouse might lock the terminal.
12369 
12370     \note See the note in QWidget::grabMouse().
12371 
12372     \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
12373 */
12374 #ifndef QT_NO_CURSOR
grabMouse(const QCursor & cursor)12375 void QWidget::grabMouse(const QCursor &cursor)
12376 {
12377     grabMouseForWidget(this, &cursor);
12378 }
12379 #endif
12380 
stealMouseGrab(bool grab)12381 bool QWidgetPrivate::stealMouseGrab(bool grab)
12382 {
12383     // This is like a combination of grab/releaseMouse() but with error checking
12384     // and it has no effect on the result of mouseGrabber().
12385     Q_Q(QWidget);
12386     QWindow *window = grabberWindow(q);
12387     return window ? window->setMouseGrabEnabled(grab) : false;
12388 }
12389 
12390 /*!
12391     \fn void QWidget::releaseMouse()
12392 
12393     Releases the mouse grab.
12394 
12395     \sa grabMouse(), grabKeyboard(), releaseKeyboard()
12396 */
releaseMouse()12397 void QWidget::releaseMouse()
12398 {
12399     releaseMouseGrabOfWidget(this);
12400 }
12401 
12402 /*!
12403     \fn void QWidget::grabKeyboard()
12404 
12405     Grabs the keyboard input.
12406 
12407     This widget receives all keyboard events until releaseKeyboard()
12408     is called; other widgets get no keyboard events at all. Mouse
12409     events are not affected. Use grabMouse() if you want to grab that.
12410 
12411     The focus widget is not affected, except that it doesn't receive
12412     any keyboard events. setFocus() moves the focus as usual, but the
12413     new focus widget receives keyboard events only after
12414     releaseKeyboard() is called.
12415 
12416     If a different widget is currently grabbing keyboard input, that
12417     widget's grab is released first.
12418 
12419     \sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
12420 */
grabKeyboard()12421 void QWidget::grabKeyboard()
12422 {
12423     if (keyboardGrb)
12424         keyboardGrb->releaseKeyboard();
12425     if (QWindow *window = grabberWindow(this))
12426         window->setKeyboardGrabEnabled(true);
12427     keyboardGrb = this;
12428 }
12429 
stealKeyboardGrab(bool grab)12430 bool QWidgetPrivate::stealKeyboardGrab(bool grab)
12431 {
12432     // This is like a combination of grab/releaseKeyboard() but with error
12433     // checking and it has no effect on the result of keyboardGrabber().
12434     Q_Q(QWidget);
12435     QWindow *window = grabberWindow(q);
12436     return window ? window->setKeyboardGrabEnabled(grab) : false;
12437 }
12438 
12439 /*!
12440     \fn void QWidget::releaseKeyboard()
12441 
12442     Releases the keyboard grab.
12443 
12444     \sa grabKeyboard(), grabMouse(), releaseMouse()
12445 */
releaseKeyboard()12446 void QWidget::releaseKeyboard()
12447 {
12448     if (keyboardGrb == this) {
12449         if (QWindow *window = grabberWindow(this))
12450             window->setKeyboardGrabEnabled(false);
12451         keyboardGrb = nullptr;
12452     }
12453 }
12454 
12455 /*!
12456     \fn QWidget *QWidget::mouseGrabber()
12457 
12458     Returns the widget that is currently grabbing the mouse input.
12459 
12460     If no widget in this application is currently grabbing the mouse,
12461     \nullptr is returned.
12462 
12463     \sa grabMouse(), keyboardGrabber()
12464 */
mouseGrabber()12465 QWidget *QWidget::mouseGrabber()
12466 {
12467     if (qt_mouseGrb)
12468         return qt_mouseGrb;
12469     return qt_pressGrab;
12470 }
12471 
12472 /*!
12473     \fn QWidget *QWidget::keyboardGrabber()
12474 
12475     Returns the widget that is currently grabbing the keyboard input.
12476 
12477     If no widget in this application is currently grabbing the
12478     keyboard, \nullptr is returned.
12479 
12480     \sa grabMouse(), mouseGrabber()
12481 */
keyboardGrabber()12482 QWidget *QWidget::keyboardGrabber()
12483 {
12484     return keyboardGrb;
12485 }
12486 
12487 /*!
12488     \fn void QWidget::activateWindow()
12489 
12490     Sets the top-level widget containing this widget to be the active
12491     window.
12492 
12493     An active window is a visible top-level window that has the
12494     keyboard input focus.
12495 
12496     This function performs the same operation as clicking the mouse on
12497     the title bar of a top-level window. On X11, the result depends on
12498     the Window Manager. If you want to ensure that the window is
12499     stacked on top as well you should also call raise(). Note that the
12500     window must be visible, otherwise activateWindow() has no effect.
12501 
12502     On Windows, if you are calling this when the application is not
12503     currently the active one then it will not make it the active
12504     window.  It will change the color of the taskbar entry to indicate
12505     that the window has changed in some way. This is because Microsoft
12506     does not allow an application to interrupt what the user is currently
12507     doing in another application.
12508 
12509     \sa isActiveWindow(), window(), show(), QWindowsWindowFunctions::setWindowActivationBehavior()
12510 */
activateWindow()12511 void QWidget::activateWindow()
12512 {
12513     QWindow *const wnd = window()->windowHandle();
12514 
12515     if (wnd)
12516         wnd->requestActivate();
12517 }
12518 
12519 /*!
12520 
12521     Internal implementation of the virtual QPaintDevice::metric()
12522     function.
12523 
12524     \a m is the metric to get.
12525 */
metric(PaintDeviceMetric m) const12526 int QWidget::metric(PaintDeviceMetric m) const
12527 {
12528     QWindow *topLevelWindow = nullptr;
12529     QScreen *screen = nullptr;
12530     if (QWidget *topLevel = window()) {
12531         topLevelWindow = topLevel->windowHandle();
12532         if (topLevelWindow)
12533             screen = topLevelWindow->screen();
12534     }
12535     if (!screen && QGuiApplication::primaryScreen())
12536         screen = QGuiApplication::primaryScreen();
12537 
12538     if (!screen) {
12539         if (m == PdmDpiX || m == PdmDpiY)
12540               return 72;
12541         return QPaintDevice::metric(m);
12542     }
12543     int val;
12544     if (m == PdmWidth) {
12545         val = data->crect.width();
12546     } else if (m == PdmWidthMM) {
12547         val = data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
12548     } else if (m == PdmHeight) {
12549         val = data->crect.height();
12550     } else if (m == PdmHeightMM) {
12551         val = data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
12552     } else if (m == PdmDepth) {
12553         return screen->depth();
12554     } else if (m == PdmDpiX) {
12555         for (const QWidget *p = this; p; p = p->parentWidget()) {
12556             if (p->d_func()->extra && p->d_func()->extra->customDpiX)
12557                 return p->d_func()->extra->customDpiX;
12558         }
12559         return qRound(screen->logicalDotsPerInchX());
12560     } else if (m == PdmDpiY) {
12561         for (const QWidget *p = this; p; p = p->parentWidget()) {
12562             if (p->d_func()->extra && p->d_func()->extra->customDpiY)
12563                 return p->d_func()->extra->customDpiY;
12564         }
12565         return qRound(screen->logicalDotsPerInchY());
12566     } else if (m == PdmPhysicalDpiX) {
12567         return qRound(screen->physicalDotsPerInchX());
12568     } else if (m == PdmPhysicalDpiY) {
12569         return qRound(screen->physicalDotsPerInchY());
12570     } else if (m == PdmDevicePixelRatio) {
12571         return topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio();
12572     } else if (m == PdmDevicePixelRatioScaled) {
12573         return (QPaintDevice::devicePixelRatioFScale() *
12574                 (topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio()));
12575     } else {
12576         val = QPaintDevice::metric(m);// XXX
12577     }
12578     return val;
12579 }
12580 
12581 /*!
12582     Initializes the \a painter pen, background and font to the same as
12583     the given widget's. This function is called automatically when the
12584     painter is opened on a QWidget.
12585 */
initPainter(QPainter * painter) const12586 void QWidget::initPainter(QPainter *painter) const
12587 {
12588     const QPalette &pal = palette();
12589     painter->d_func()->state->pen = QPen(pal.brush(foregroundRole()), 1);
12590     painter->d_func()->state->bgBrush = pal.brush(backgroundRole());
12591     QFont f(font(), const_cast<QWidget *>(this));
12592     painter->d_func()->state->deviceFont = f;
12593     painter->d_func()->state->font = f;
12594 }
12595 
12596 /*!
12597     \internal
12598 
12599     Do PaintDevice rendering with the specified \a offset.
12600 */
redirected(QPoint * offset) const12601 QPaintDevice *QWidget::redirected(QPoint *offset) const
12602 {
12603     return d_func()->redirected(offset);
12604 }
12605 
12606 /*!
12607     \internal
12608 
12609     A painter that is shared among other instances of QPainter.
12610 */
sharedPainter() const12611 QPainter *QWidget::sharedPainter() const
12612 {
12613     // Someone sent a paint event directly to the widget
12614     if (!d_func()->redirectDev)
12615         return nullptr;
12616 
12617     QPainter *sp = d_func()->sharedPainter();
12618     if (!sp || !sp->isActive())
12619         return nullptr;
12620 
12621     if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
12622         return nullptr;
12623 
12624     return sp;
12625 }
12626 
12627 /*!
12628     \fn void QWidget::setMask(const QRegion &region)
12629     \overload
12630 
12631     Causes only the parts of the widget which overlap \a region to be
12632     visible. If the region includes pixels outside the rect() of the
12633     widget, window system controls in that area may or may not be
12634     visible, depending on the platform.
12635 
12636     Note that this effect can be slow if the region is particularly
12637     complex.
12638 
12639     \sa windowOpacity
12640 */
setMask(const QRegion & newMask)12641 void QWidget::setMask(const QRegion &newMask)
12642 {
12643     Q_D(QWidget);
12644 
12645     d->createExtra();
12646     if (newMask == d->extra->mask)
12647         return;
12648 
12649 #ifndef QT_NO_BACKINGSTORE
12650     const QRegion oldMask(d->extra->mask);
12651 #endif
12652 
12653     d->extra->mask = newMask;
12654     d->extra->hasMask = !newMask.isEmpty();
12655 
12656     if (!testAttribute(Qt::WA_WState_Created))
12657         return;
12658 
12659     d->setMask_sys(newMask);
12660 
12661 #ifndef QT_NO_BACKINGSTORE
12662     if (!isVisible())
12663         return;
12664 
12665     if (!d->extra->hasMask) {
12666         // Mask was cleared; update newly exposed area.
12667         QRegion expose(rect());
12668         expose -= oldMask;
12669         if (!expose.isEmpty()) {
12670             d->setDirtyOpaqueRegion();
12671             update(expose);
12672         }
12673         return;
12674     }
12675 
12676     if (!isWindow()) {
12677         // Update newly exposed area on the parent widget.
12678         QRegion parentExpose(rect());
12679         parentExpose -= newMask;
12680         if (!parentExpose.isEmpty()) {
12681             d->setDirtyOpaqueRegion();
12682             parentExpose.translate(data->crect.topLeft());
12683             parentWidget()->update(parentExpose);
12684         }
12685 
12686         // Update newly exposed area on this widget
12687         if (!oldMask.isEmpty())
12688             update(newMask - oldMask);
12689     }
12690 #endif
12691 }
12692 
setMask_sys(const QRegion & region)12693 void QWidgetPrivate::setMask_sys(const QRegion &region)
12694 {
12695     Q_Q(QWidget);
12696     if (QWindow *window = q->windowHandle())
12697         window->setMask(region);
12698 }
12699 
12700 /*!
12701     \fn void QWidget::setMask(const QBitmap &bitmap)
12702 
12703     Causes only the pixels of the widget for which \a bitmap has a
12704     corresponding 1 bit to be visible. If the region includes pixels
12705     outside the rect() of the widget, window system controls in that
12706     area may or may not be visible, depending on the platform.
12707 
12708     Note that this effect can be slow if the region is particularly
12709     complex.
12710 
12711     The following code shows how an image with an alpha channel can be
12712     used to generate a mask for a widget:
12713 
12714     \snippet widget-mask/main.cpp 0
12715 
12716     The label shown by this code is masked using the image it contains,
12717     giving the appearance that an irregularly-shaped image is being drawn
12718     directly onto the screen.
12719 
12720     Masked widgets receive mouse events only on their visible
12721     portions.
12722 
12723     \sa clearMask(), windowOpacity(), {Shaped Clock Example}
12724 */
setMask(const QBitmap & bitmap)12725 void QWidget::setMask(const QBitmap &bitmap)
12726 {
12727     setMask(QRegion(bitmap));
12728 }
12729 
12730 /*!
12731     \fn void QWidget::clearMask()
12732 
12733     Removes any mask set by setMask().
12734 
12735     \sa setMask()
12736 */
clearMask()12737 void QWidget::clearMask()
12738 {
12739     Q_D(QWidget);
12740     if (!d->extra || !d->extra->hasMask)
12741         return;
12742     setMask(QRegion());
12743 }
12744 
setWidgetParentHelper(QObject * widgetAsObject,QObject * newParent)12745 void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent)
12746 {
12747     Q_ASSERT(widgetAsObject->isWidgetType());
12748     Q_ASSERT(!newParent || newParent->isWidgetType());
12749     QWidget *widget = static_cast<QWidget*>(widgetAsObject);
12750     widget->setParent(static_cast<QWidget*>(newParent));
12751 }
12752 
setNetWmWindowTypes(bool skipIfMissing)12753 void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
12754 {
12755     Q_Q(QWidget);
12756 
12757     if (!q->windowHandle())
12758         return;
12759 
12760     int wmWindowType = 0;
12761     if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
12762         wmWindowType |= QXcbWindowFunctions::Desktop;
12763     if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
12764         wmWindowType |= QXcbWindowFunctions::Dock;
12765     if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
12766         wmWindowType |= QXcbWindowFunctions::Toolbar;
12767     if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
12768         wmWindowType |= QXcbWindowFunctions::Menu;
12769     if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
12770         wmWindowType |= QXcbWindowFunctions::Utility;
12771     if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
12772         wmWindowType |= QXcbWindowFunctions::Splash;
12773     if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
12774         wmWindowType |= QXcbWindowFunctions::Dialog;
12775     if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
12776         wmWindowType |= QXcbWindowFunctions::DropDownMenu;
12777     if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
12778         wmWindowType |= QXcbWindowFunctions::PopupMenu;
12779     if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
12780         wmWindowType |= QXcbWindowFunctions::Tooltip;
12781     if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
12782         wmWindowType |= QXcbWindowFunctions::Notification;
12783     if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
12784         wmWindowType |= QXcbWindowFunctions::Combo;
12785     if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
12786         wmWindowType |= QXcbWindowFunctions::Dnd;
12787 
12788     if (wmWindowType == 0 && skipIfMissing)
12789         return;
12790 
12791     QXcbWindowFunctions::setWmWindowType(q->windowHandle(), static_cast<QXcbWindowFunctions::WmWindowType>(wmWindowType));
12792 }
12793 
12794 #ifndef QT_NO_DEBUG_STREAM
12795 
formatWidgetAttributes(QDebug debug,const QWidget * widget)12796 static inline void formatWidgetAttributes(QDebug debug, const QWidget *widget)
12797 {
12798     const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
12799     const QMetaEnum me = qtMo->enumerator(qtMo->indexOfEnumerator("WidgetAttribute"));
12800     debug << ", attributes=[";
12801     int count = 0;
12802     for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
12803         if (widget->testAttribute(static_cast<Qt::WidgetAttribute>(a))) {
12804             if (count++)
12805                 debug << ',';
12806             debug << me.valueToKey(a);
12807         }
12808     }
12809     debug << ']';
12810 }
12811 
operator <<(QDebug debug,const QWidget * widget)12812 QDebug operator<<(QDebug debug, const QWidget *widget)
12813 {
12814     const QDebugStateSaver saver(debug);
12815     debug.nospace();
12816     if (widget) {
12817         debug << widget->metaObject()->className() << '(' << (const void *)widget;
12818         if (!widget->objectName().isEmpty())
12819             debug << ", name=" << widget->objectName();
12820         if (debug.verbosity() > 2) {
12821             const QRect geometry = widget->geometry();
12822             const QRect frameGeometry = widget->frameGeometry();
12823             if (widget->isVisible())
12824                 debug << ", visible";
12825             if (!widget->isEnabled())
12826                 debug << ", disabled";
12827             debug << ", states=" << widget->windowState()
12828                 << ", type=" << widget->windowType() << ", flags=" <<  widget->windowFlags();
12829             formatWidgetAttributes(debug, widget);
12830             if (widget->isWindow())
12831                 debug << ", window";
12832             debug << ", " << geometry.width() << 'x' << geometry.height()
12833                 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
12834             if (frameGeometry != geometry) {
12835                 const QMargins margins(geometry.x() - frameGeometry.x(),
12836                                        geometry.y() - frameGeometry.y(),
12837                                        frameGeometry.right() - geometry.right(),
12838                                        frameGeometry.bottom() - geometry.bottom());
12839                 debug << ", margins=" << margins;
12840             }
12841             debug << ", devicePixelRatio=" << widget->devicePixelRatioF();
12842             if (const WId wid = widget->internalWinId())
12843                 debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
12844         }
12845         debug << ')';
12846     } else {
12847         debug << "QWidget(0x0)";
12848     }
12849     return debug;
12850 }
12851 #endif // !QT_NO_DEBUG_STREAM
12852 
12853 QT_END_NAMESPACE
12854 
12855 #include "moc_qwidget.cpp"
12856 
12857