Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwidget.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
6#include "qapplication.h"
8#include "qbrush.h"
9#include "qcursor.h"
10#include "private/qduplicatetracker_p.h"
11#include "qevent.h"
12#include "qlayout.h"
13#if QT_CONFIG(menu)
14#include "qmenu.h"
15#endif
16#include "qmetaobject.h"
17#include "qpixmap.h"
18#include "qpointer.h"
19#include "qstack.h"
20#include "qstyle.h"
21#include "qstylefactory.h"
22#include "qvariant.h"
23#include "qwidget.h"
24#include "qstyleoption.h"
25#include "qstylehints.h"
26#if QT_CONFIG(accessibility)
27# include "qaccessible.h"
28# include <private/qaccessiblecache_p.h>
29#endif
30#include <qpa/qplatformwindow.h>
31#include <qpa/qplatformwindow_p.h>
32#include "private/qwidgetwindow_p.h"
33#include "qpainter.h"
34#if QT_CONFIG(tooltip)
35#include "private/qtooltip_p.h"
36#endif
37#if QT_CONFIG(whatsthis)
38#include "qwhatsthis.h"
39#endif
40#include "qdebug.h"
41#if QT_CONFIG(style_stylesheet)
42#include "private/qstylesheetstyle_p.h"
43#endif
44#include "private/qstyle_p.h"
45#include "qfileinfo.h"
46#include "qscopeguard.h"
47#include <QtGui/qinputmethod.h>
48
49#if QT_CONFIG(graphicseffect)
50#include <private/qgraphicseffect_p.h>
51#endif
52#include <qbackingstore.h>
53#include <private/qwidgetrepaintmanager_p.h>
54#include <private/qpaintengine_raster_p.h>
55
56#include "qwidget_p.h"
57#include <QtGui/private/qwindow_p.h>
58#if QT_CONFIG(action)
59# include "QtGui/private/qaction_p.h"
60#endif
61#include "qlayout_p.h"
62#if QT_CONFIG(graphicsview)
63#include "QtWidgets/qgraphicsproxywidget.h"
64#include "QtWidgets/qgraphicsscene.h"
65#include "private/qgraphicsproxywidget_p.h"
66#include "private/qgraphicsview_p.h"
67#endif
68#include "QtWidgets/qabstractscrollarea.h"
69#include "private/qabstractscrollarea_p.h"
70#include "private/qevent_p.h"
71
72#include "private/qgesturemanager_p.h"
73
75
76#include <sstream>
77
78QT_BEGIN_NAMESPACE
79
80using namespace QNativeInterface::Private;
81using namespace Qt::StringLiterals;
82
83Q_LOGGING_CATEGORY(lcWidgetPainting, "qt.widgets.painting", QtWarningMsg);
84Q_LOGGING_CATEGORY(lcWidgetShowHide, "qt.widgets.showhide", QtWarningMsg);
85Q_STATIC_LOGGING_CATEGORY(lcWidgetWindow, "qt.widgets.window", QtWarningMsg);
86Q_STATIC_LOGGING_CATEGORY(lcWidgetFocus, "qt.widgets.focus")
87
88#ifndef QT_NO_DEBUG_STREAM
89namespace {
90 struct WidgetAttributes { const QWidget *widget; };
91 QDebug operator<<(QDebug debug, const WidgetAttributes &attributes);
92}
93#endif
94
95static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
96{
97 return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) &&
98 qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));
99}
100
101extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
102
103static void setAttribute_internal(Qt::WidgetAttribute attribute,
104 bool on, QWidgetData *data, QWidgetPrivate *d);
105
106QWidgetPrivate::QWidgetPrivate(decltype(QObjectPrivateVersion) version)
107 : QObjectPrivate(version)
108 , focus_next(nullptr)
109 , focus_prev(nullptr)
110 , focus_child(nullptr)
111 , layout(nullptr)
112 , needsFlush(nullptr)
113 , redirectDev(nullptr)
114 , widgetItem(nullptr)
115 , extraPaintEngine(nullptr)
116 , polished(nullptr)
117 , graphicsEffect(nullptr)
118#if !defined(QT_NO_IM)
119 , imHints(Qt::ImhNone)
120#endif
121#if QT_CONFIG(tooltip)
122 , toolTipDuration(-1)
123#endif
124 , directFontResolveMask(0)
125 , inheritedFontResolveMask(0)
126 , directPaletteResolveMask(0)
127 , inheritedPaletteResolveMask(0)
128 , leftmargin(0)
129 , topmargin(0)
130 , rightmargin(0)
131 , bottommargin(0)
132 , leftLayoutItemMargin(0)
133 , topLayoutItemMargin(0)
134 , rightLayoutItemMargin(0)
135 , bottomLayoutItemMargin(0)
136 , hd(nullptr)
137 , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
138 , fg_role(QPalette::NoRole)
139 , bg_role(QPalette::NoRole)
140 , dirtyOpaqueChildren(1)
141 , isOpaque(0)
142 , retainSizeWhenHiddenChanged(0)
143 , inDirtyList(0)
144 , isScrolled(0)
145 , isMoved(0)
146 , usesDoubleBufferedGLContext(0)
147 , mustHaveWindowHandle(0)
148 , renderToTexture(0)
149 , textureChildSeen(0)
150#ifndef QT_NO_IM
151 , inheritsInputMethodHints(0)
152#endif
153 , renderToTextureReallyDirty(1)
154 , usesRhiFlush(0)
155 , childrenHiddenByWState(0)
156 , childrenShownByExpose(0)
157 , dontSetExplicitShowHide(0)
158 , inheritStyleRecursionGuard(0)
159#if defined(Q_OS_WIN)
160 , noPaintOnScreen(0)
161#endif
162{
163 if (Q_UNLIKELY(!qApp)) {
164 qFatal("QWidget: Must construct a QApplication before a QWidget");
165 return;
166 }
167
168 willBeWidget = true; // used in QObject's ctor
169 memset(high_attributes, 0, sizeof(high_attributes));
170
171#ifdef QWIDGET_EXTRA_DEBUG
172 static int count = 0;
173 qDebug() << "widgets" << ++count;
174#endif
175}
176
177
178QWidgetPrivate::~QWidgetPrivate()
179{
180 if (widgetItem)
181 widgetItem->wid = nullptr;
182
183 if (extra)
184 deleteExtra();
185}
186
187/*!
188 \internal
189*/
190void QWidgetPrivate::scrollChildren(int dx, int dy)
191{
192 Q_Q(QWidget);
193 if (q->children().size() > 0) { // scroll children
194 QPoint pd(dx, dy);
195 QObjectList childObjects = q->children();
196 for (int i = 0; i < childObjects.size(); ++i) { // move all children
197 QWidget *w = qobject_cast<QWidget*>(childObjects.at(i));
198 if (w && !w->isWindow()) {
199 QPoint oldp = w->pos();
200 QRect r(w->pos() + pd, w->size());
201 w->data->crect = r;
202 if (w->testAttribute(Qt::WA_WState_Created))
203 w->d_func()->setWSGeometry();
204 w->d_func()->setDirtyOpaqueRegion();
205 QMoveEvent e(r.topLeft(), oldp);
206 QCoreApplication::sendEvent(w, &e);
207 }
208 }
209 }
210}
211
212void QWidgetPrivate::setWSGeometry()
213{
214 Q_Q(QWidget);
215 if (QWindow *window = q->windowHandle())
216 window->setGeometry(data.crect);
217}
218
219void QWidgetPrivate::updateWidgetTransform(QEvent *event)
220{
221 Q_Q(QWidget);
222 if (q == QGuiApplication::focusObject() || event->type() == QEvent::FocusIn) {
223 QTransform t;
224 QPoint p = q->mapTo(q->topLevelWidget(), QPoint(0,0));
225 t.translate(p.x(), p.y());
226 QGuiApplication::inputMethod()->setInputItemTransform(t);
227 QGuiApplication::inputMethod()->setInputItemRectangle(q->rect());
228 QGuiApplication::inputMethod()->update(Qt::ImInputItemClipRectangle);
229 }
230}
231
232/*!
233 \property QWidget::autoFillBackground
234 \brief whether the widget background is filled automatically
235 \since 4.1
236
237 If enabled, this property will cause Qt to fill the background of the
238 widget before invoking the paint event. The color used is defined by the
239 QPalette::Window color role from the widget's \l{QPalette}{palette}.
240
241 In addition, Windows are always filled with QPalette::Window, unless the
242 WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
243
244 This property cannot be turned off (i.e., set to false) if a widget's
245 parent has a static gradient for its background.
246
247 \warning Use this property with caution in conjunction with
248 \l{Qt Style Sheets}. When a widget has a style sheet with a valid
249 background or a border-image, this property is automatically disabled.
250
251 By default, this property is \c false.
252
253 \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
254 {QWidget#Transparency and Double Buffering}{Transparency and Double Buffering}
255*/
256bool QWidget::autoFillBackground() const
257{
258 Q_D(const QWidget);
259 return d->extra && d->extra->autoFillBackground;
260}
261
262void QWidget::setAutoFillBackground(bool enabled)
263{
264 Q_D(QWidget);
265 if (!d->extra)
266 d->createExtra();
267 if (d->extra->autoFillBackground == enabled)
268 return;
269
270 d->extra->autoFillBackground = enabled;
271 d->updateIsOpaque();
272 update();
273 d->updateIsOpaque();
274}
275
276/*!
277 \class QWidget
278 \brief The QWidget class is the base class of all user interface objects.
279
280 \ingroup basicwidgets
281 \inmodule QtWidgets
282
283 The widget is the atom of the user interface: it receives mouse, keyboard
284 and other events from the window system, and paints a representation of
285 itself on the screen. Every widget is rectangular, and they are sorted in a
286 Z-order. A widget is clipped by its parent and by the widgets in front of
287 it.
288
289 A widget that is not embedded in a parent widget is called a window.
290 Usually, windows have a frame and a title bar, although it is also possible
291 to create windows without such decoration using suitable
292 \l{Qt::WindowFlags}{window flags}. In Qt, QMainWindow and the various
293 subclasses of QDialog are the most common window types.
294
295 Every widget's constructor accepts one or two standard arguments:
296
297 \list 1
298 \li \c{QWidget *parent = nullptr} is the parent of the new widget.
299 If it is \nullptr (the default), the new widget will be a window.
300 If not, it will be a child of \e parent, and be constrained by
301 \e parent's geometry (unless you specify Qt::Window as window flag).
302 \li \c{Qt::WindowFlags f = { }} (where available) sets the window flags;
303 the default is suitable for most widgets, but to get, for
304 example, a window without a window system frame, you must use
305 special flags.
306 \endlist
307
308 QWidget has many member functions, but some of them have little direct
309 functionality; for example, QWidget has a font property, but never uses
310 this itself. There are many subclasses that provide real functionality,
311 such as QLabel, QPushButton, QListWidget, and QTabWidget.
312
313
314 \section1 Top-Level and Child Widgets
315
316 A widget without a parent widget is always an independent window (top-level
317 widget). For these widgets, setWindowTitle() and setWindowIcon() set the
318 title bar and icon, respectively.
319
320 Non-window widgets are child widgets, displayed within their parent
321 widgets. Most widgets in Qt are mainly useful as child widgets. For
322 example, it is possible to display a button as a top-level window, but most
323 people prefer to put their buttons inside other widgets, such as QDialog.
324
325 \image parent-child-widgets.png
326 {Appointment widget with labeled child widgets}
327 \caption A parent widget containing various child widgets.
328
329 The diagram above shows a QGroupBox widget being used to hold various child
330 widgets in a layout provided by QGridLayout. The QLabel child widgets have
331 been outlined to indicate their full sizes.
332
333 If you want to use a QWidget to hold child widgets, you will usually want to
334 add a layout to the parent QWidget. See \l{Layout Management} for more
335 information.
336
337
338 \section1 Composite Widgets
339
340 When a widget is used as a container to group a number of child widgets, it
341 is known as a composite widget. These can be created by constructing a
342 widget with the required visual properties - a QFrame, for example - and
343 adding child widgets to it, usually managed by a layout.
344
345 Composite widgets can also be created by subclassing a standard widget,
346 such as QWidget or QFrame, and adding the necessary layout and child
347 widgets in the constructor of the subclass. Many of the \l{Qt Widgets Examples}
348 {examples provided with Qt} use this approach, and it is also covered in
349 the Qt \l{Widgets Tutorial}.
350
351
352 \section1 Custom Widgets and Painting
353
354 Since QWidget is a subclass of QPaintDevice, subclasses can be used to
355 display custom content that is composed using a series of painting
356 operations with an instance of the QPainter class. This approach contrasts
357 with the canvas-style approach used by the \l{Graphics View}
358 {Graphics View Framework} where items are added to a scene by the
359 application and are rendered by the framework itself.
360
361 Each widget performs all painting operations from within its paintEvent()
362 function. This is called whenever the widget needs to be redrawn, either
363 because of some external change or when requested by the application.
364
365 The \l{widgets/analogclock}{Analog Clock example} shows how a simple widget
366 can handle paint events.
367
368
369 \section1 Size Hints and Size Policies
370
371 When implementing a new widget, it is almost always useful to reimplement
372 sizeHint() to provide a reasonable default size for the widget and to set
373 the correct size policy with setSizePolicy().
374
375 By default, composite widgets that do not provide a size hint will be
376 sized according to the space requirements of their child widgets.
377
378 The size policy lets you supply good default behavior for the layout
379 management system, so that other widgets can contain and manage yours
380 easily. The default size policy indicates that the size hint represents
381 the preferred size of the widget, and this is often good enough for many
382 widgets.
383
384 \note The size of top-level widgets are constrained to 2/3 of the desktop's
385 height and width. You can resize() the widget manually if these bounds are
386 inadequate.
387
388
389 \section1 Events
390
391 Widgets respond to events that are typically caused by user actions. Qt
392 delivers events to widgets by calling specific event handler functions with
393 instances of QEvent subclasses containing information about each event.
395 If your widget only contains child widgets, you probably don't need to
396 implement any event handlers. If you want to detect a mouse click in a
397 child widget, call the child's underMouse() function inside the widget's
398 mousePressEvent().
399
400 The \l{widgets/scribble}{Scribble example} implements a wider set of
401 events to handle mouse movement, button presses, and window resizing.
402
403 You will need to supply the behavior and content for your own widgets, but
404 here is a brief overview of the events that are relevant to QWidget,
405 starting with the most common ones:
406
407 \list
408 \li paintEvent() is called whenever the widget needs to be repainted.
409 Every widget displaying custom content must implement it. Painting
410 using a QPainter can only take place in a paintEvent() or a
411 function called by a paintEvent().
412 \li resizeEvent() is called when the widget has been resized.
413 \li mousePressEvent() is called when a mouse button is pressed while
414 the mouse cursor is inside the widget, or when the widget has
415 grabbed the mouse using grabMouse(). Pressing the mouse without
416 releasing it is effectively the same as calling grabMouse().
417 \li mouseReleaseEvent() is called when a mouse button is released. A
418 widget receives mouse release events when it has received the
419 corresponding mouse press event. This means that if the user
420 presses the mouse inside \e your widget, then drags the mouse
421 somewhere else before releasing the mouse button, \e your widget
422 receives the release event. There is one exception: if a popup menu
423 appears while the mouse button is held down, this popup immediately
424 steals the mouse events.
425 \li mouseDoubleClickEvent() is called when the user double-clicks in
426 the widget. If the user double-clicks, the widget receives a mouse
427 press event, a mouse release event, (a mouse click event,) a second
428 mouse press, this event and finally a second mouse release event.
429 (Some mouse move events may also be
430 received if the mouse is not held steady during this operation.) It
431 is \e{not possible} to distinguish a click from a double-click
432 until the second click arrives. (This is one reason why most GUI
433 books recommend that double-clicks be an extension of
434 single-clicks, rather than trigger a different action.)
435 \endlist
436
437 Widgets that accept keyboard input need to reimplement a few more event
438 handlers:
439
440 \list
441 \li keyPressEvent() is called whenever a key is pressed, and again when
442 a key has been held down long enough for it to auto-repeat. The
443 \uicontrol Tab and \uicontrol Shift+Tab keys are only passed to the widget if
444 they are not used by the focus-change mechanisms. To force those
445 keys to be processed by your widget, you must reimplement
446 QWidget::event().
447 \li focusInEvent() is called when the widget gains keyboard focus
448 (assuming you have called setFocusPolicy()). Well-behaved widgets
449 indicate that they own the keyboard focus in a clear but discreet
450 way.
451 \li focusOutEvent() is called when the widget loses keyboard focus.
452 \endlist
453
454 You may be required to also reimplement some of the less common event
455 handlers:
456
457 \list
458 \li mouseMoveEvent() is called whenever the mouse moves while a mouse
459 button is held down. This can be useful during drag and drop
460 operations. If you call \l{setMouseTracking()}{setMouseTracking}(true),
461 you get mouse move events even when no buttons are held down.
462 (See also the \l{Drag and Drop in Qt}{Drag and Drop} guide.)
463 \li keyReleaseEvent() is called whenever a key is released and while it
464 is held down (if the key is auto-repeating). In that case, the
465 widget will receive a pair of key release and key press event for
466 every repeat. The \uicontrol Tab and \uicontrol Shift+Tab keys are only passed
467 to the widget if they are not used by the focus-change mechanisms.
468 To force those keys to be processed by your widget, you must
469 reimplement QWidget::event().
470 \li wheelEvent() is called whenever the user turns the mouse wheel
471 while the widget has the focus.
472 \li enterEvent() is called when the mouse enters the widget's screen
473 space. (This excludes screen space owned by any of the widget's
474 children.)
475 \li leaveEvent() is called when the mouse leaves the widget's screen
476 space. If the mouse enters a child widget, it will not cause a
477 leaveEvent().
478 \li moveEvent() is called when the widget has been moved relative to
479 its parent.
480 \li closeEvent() is called when the user closes the widget (or when
481 close() is called).
482 \endlist
483
484 There are also some rather obscure events described in the documentation
485 for QEvent::Type. To handle these events, you need to reimplement event()
486 directly.
487
488 The default implementation of event() handles \uicontrol Tab and \uicontrol Shift+Tab
489 (to move the keyboard focus), and passes on most of the other events to
490 one of the more specialized handlers above.
491
492 Events and the mechanism used to deliver them are covered in
493 \l{The Event System}.
494
495 \section1 Groups of Functions and Properties
496
497 \table
498 \header \li Context \li Functions and Properties
499
500 \row \li Window functions \li
501 show(),
502 hide(),
503 raise(),
504 lower(),
505 close().
506
507 \row \li Top-level windows \li
508 \l windowModified, \l windowTitle, \l windowIcon,
509 \l isActiveWindow, activateWindow(), \l minimized, showMinimized(),
510 \l maximized, showMaximized(), \l fullScreen, showFullScreen(),
511 showNormal().
512
513 \row \li Window contents \li
514 update(),
515 repaint(),
516 scroll().
517
518 \row \li Geometry \li
519 \l pos, x(), y(), \l rect, \l size, width(), height(), move(), resize(),
520 \l sizePolicy, sizeHint(), minimumSizeHint(),
521 updateGeometry(), layout(),
522 \l frameGeometry, \l geometry, \l childrenRect, \l childrenRegion,
523 adjustSize(),
524 mapFromGlobal(), mapToGlobal(),
525 mapFromParent(), mapToParent(),
526 \l maximumSize, \l minimumSize, \l sizeIncrement,
527 \l baseSize, setFixedSize()
528
529 \row \li Mode \li
530 \l visible, isVisibleTo(),
531 \l enabled, isEnabledTo(),
532 \l modal,
533 isWindow(),
534 \l mouseTracking,
535 \l updatesEnabled,
536 visibleRegion().
537
538 \row \li Look and feel \li
539 style(),
540 setStyle(),
541 \l styleSheet,
542 \l cursor,
543 \l font,
544 \l palette,
545 backgroundRole(), setBackgroundRole(),
546 fontInfo(), fontMetrics().
547
548 \row \li Keyboard focus functions \li
549 \l focus, \l focusPolicy,
550 setFocus(), clearFocus(), setTabOrder(), setFocusProxy(),
551 focusNextChild(), focusPreviousChild().
552
553 \row \li Mouse and keyboard grabbing \li
554 grabMouse(), releaseMouse(),
555 grabKeyboard(), releaseKeyboard(),
556 mouseGrabber(), keyboardGrabber().
557
558 \row \li Event handlers \li
559 event(),
560 mousePressEvent(),
561 mouseReleaseEvent(),
562 mouseDoubleClickEvent(),
563 mouseMoveEvent(),
564 keyPressEvent(),
565 keyReleaseEvent(),
566 focusInEvent(),
567 focusOutEvent(),
568 wheelEvent(),
569 enterEvent(),
570 leaveEvent(),
571 paintEvent(),
572 moveEvent(),
573 resizeEvent(),
574 closeEvent(),
575 dragEnterEvent(),
576 dragMoveEvent(),
577 dragLeaveEvent(),
578 dropEvent(),
579 childEvent(),
580 showEvent(),
581 hideEvent(),
582 customEvent().
583 changeEvent(),
584
585 \row \li System functions \li
586 parentWidget(), window(), setParent(), winId(),
587 find(), metric().
588
589 \row \li Context menu \li
590 contextMenuPolicy, contextMenuEvent(),
591 customContextMenuRequested(), actions()
592
593 \row \li Interactive help \li
594 setToolTip(), setWhatsThis()
595
596 \endtable
597
598
599 \section1 Widget Style Sheets
600
601 In addition to the standard widget styles for each platform, widgets can
602 also be styled according to rules specified in a \l{styleSheet}
603 {style sheet}. This feature enables you to customize the appearance of
604 specific widgets to provide visual cues to users about their purpose. For
605 example, a button could be styled in a particular way to indicate that it
606 performs a destructive action.
607
608 The use of widget style sheets is described in more detail in the
609 \l{Qt Style Sheets} document.
610
611
612 \section1 Transparency and Double Buffering
613
614 QWidget automatically double-buffers its painting, so there
615 is no need to write double-buffering code in paintEvent() to avoid
616 flicker.
617
618 The contents of parent widgets are propagated by
619 default to each of their children as long as Qt::WA_PaintOnScreen is not
620 set. Custom widgets can be written to take advantage of this feature by
621 updating irregular regions (to create non-rectangular child widgets), or
622 painting with colors that have less than full alpha component. The
623 following diagram shows how attributes and properties of a custom widget
624 can be fine-tuned to achieve different effects.
625
626 \image propagation-custom.png
627 {Three pixmaps of a house with different background properties:
628 transparent, filled with white, and uninitialized}
629
630 In the above diagram, a semi-transparent rectangular child widget with an
631 area removed is constructed and added to a parent widget (a QLabel showing
632 a pixmap). Then, different properties and widget attributes are set to
633 achieve different effects:
634
635 \list
636 \li The left widget has no additional properties or widget attributes
637 set. This default state suits most custom widgets that have
638 transparency, are irregularly-shaped, or do not paint over their
639 entire area with an opaque brush.
640 \li The center widget has the \l autoFillBackground property set. This
641 property is used with custom widgets that rely on the widget to
642 supply a default background, and do not paint over their entire
643 area with an opaque brush.
644 \li The right widget has the Qt::WA_OpaquePaintEvent widget attribute
645 set. This indicates that the widget will paint over its entire area
646 with opaque colors. The widget's area will initially be
647 \e{uninitialized}, represented in the diagram with a red diagonal
648 grid pattern that shines through the overpainted area.
649 \endlist
650
651 To rapidly update custom widgets with simple background colors, such as
652 real-time plotting or graphing widgets, it is better to define a suitable
653 background color (using setBackgroundRole() with the
654 QPalette::Window role), set the \l autoFillBackground property, and only
655 implement the necessary drawing functionality in the widget's paintEvent().
656
657 To rapidly update custom widgets that constantly paint over their entire
658 areas with opaque content, for example, video streaming widgets, it is
659 better to set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary
660 overhead associated with repainting the widget's background.
661
662 If a widget has both the Qt::WA_OpaquePaintEvent widget attribute \e{and}
663 the \l autoFillBackground property set, the Qt::WA_OpaquePaintEvent
664 attribute takes precedence. Depending on your requirements, you should
665 choose either one of them.
666
667 The contents of parent widgets are also propagated to standard Qt widgets.
668 This can lead to some unexpected results if the parent widget is decorated
669 in a non-standard way, as shown in the diagram below.
670
671 \image propagation-standard.png
672 {One widget has a transparent background
673 and the other widget has a filled background}
674
675 The scope for customizing the painting behavior of standard Qt widgets,
676 without resorting to subclassing, is slightly less than that possible for
677 custom widgets. Usually, the desired appearance of a standard widget can be
678 achieved by setting its \l autoFillBackground property.
679
680
681 \section1 Creating Translucent Windows
682
683 You can create windows with translucent regions on window systems that
684 support compositing.
685
686 To enable this feature in a top-level widget, set its Qt::WA_TranslucentBackground
687 attribute with setAttribute() and ensure that its background is painted with
688 non-opaque colors in the regions you want to be partially transparent.
689
690 Platform notes:
691
692 \list
693 \li X11: This feature relies on the use of an X server that supports ARGB visuals
694 and a compositing window manager.
695 \li Windows: The widget needs to have the Qt::FramelessWindowHint window flag set
696 for the translucency to work.
697 \li \macos: The widget needs to have the Qt::FramelessWindowHint window flag set
698 for the translucency to work.
699 \endlist
700
701
702 \section1 Native Widgets vs Alien Widgets
703
704 Alien widgets are widgets unknown to the windowing system. They do not have
705 a native window handle associated with them. This feature significantly
706 speeds up widget painting, resizing, and removes flicker.
707
708 Should you require the old behavior with native windows, choose one of the
709 following options:
710
711 \list 1
712 \li Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
713 \li Set the Qt::AA_NativeWindows attribute on your application. All
714 widgets will be native widgets.
715 \li Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
716 and all its ancestors will become native (unless
717 Qt::WA_DontCreateNativeAncestors is set).
718 \li Call QWidget::winId to enforce a native window (this implies 3).
719 \li Set the Qt::WA_PaintOnScreen attribute to enforce a native window
720 (this implies 3).
721 \endlist
722
723 \sa QEvent, QPainter, QGridLayout, QBoxLayout
724
725*/
726
727QWidgetMapper *QWidgetPrivate::mapper = nullptr; // widget with wid
728QWidgetSet *QWidgetPrivate::allWidgets = nullptr; // widgets with no wid
729
730
731/*****************************************************************************
732 QWidget member functions
733 *****************************************************************************/
734
735/*
736 Widget state flags:
737 \list
738 \li Qt::WA_WState_Created The widget has a valid winId().
739 \li Qt::WA_WState_Visible The widget is currently visible.
740 \li Qt::WA_WState_Hidden The widget is hidden, i.e. it won't
741 become visible unless you call show() on it. Qt::WA_WState_Hidden
742 implies !Qt::WA_WState_Visible.
743 \li Qt::WA_WState_CompressKeys Compress keyboard events.
744 \li Qt::WA_WState_BlockUpdates Repaints and updates are disabled.
745 \li Qt::WA_WState_InPaintEvent Currently processing a paint event.
746 \li Qt::WA_WState_Reparented The widget has been reparented.
747 \li Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending.
748 \endlist
749*/
750
752{
753 /* this cleans up when the constructor throws an exception */
754 static inline void cleanup(QWidget *that, QWidgetPrivate *d)
755 {
756#ifdef QT_NO_EXCEPTIONS
757 Q_UNUSED(that);
758 Q_UNUSED(d);
759#else
760 QWidgetPrivate::allWidgets->remove(that);
761 d->removeFromFocusChain();
762#endif
763 }
764};
765
766/*!
767 Constructs a widget which is a child of \a parent, with widget
768 flags set to \a f.
769
770 If \a parent is \nullptr, the new widget becomes a window. If
771 \a parent is another widget, this widget becomes a child window
772 inside \a parent. The new widget is deleted when its \a parent is
773 deleted.
774
775 The widget flags argument, \a f, is normally 0, but it can be set
776 to customize the frame of a window (i.e. \a parent must be
777 \nullptr). To customize the frame, use a value composed
778 from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
779
780 If you add a child widget to an already visible widget you must
781 explicitly show the child to make it visible.
782
783 Note that the X11 version of Qt may not be able to deliver all
784 combinations of style flags on all systems. This is because on
785 X11, Qt can only ask the window manager, and the window manager
786 can override the application's settings. On Windows, Qt can set
787 whatever flags you want.
788
789 \sa windowFlags
790*/
791QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
792 : QWidget(*new QWidgetPrivate, parent, f)
793{
794}
795
796
797/*! \internal
798*/
799QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
800 : QObject(dd, nullptr), QPaintDevice()
801 , data(&dd.data)
802{
803 Q_D(QWidget);
804 QT_TRY {
805 d->init(parent, f);
806 } QT_CATCH(...) {
807 QWidgetExceptionCleaner::cleanup(this, d_func());
808 QT_RETHROW;
809 }
810}
811
812/*!
813 \internal
814*/
815int QWidget::devType() const
816{
817 return QInternal::Widget;
818}
819
820
821//### w is a "this" ptr, passed as a param because QWorkspace needs special logic
822void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
823{
824 bool customize = (flags & (Qt::CustomizeWindowHint
825 | Qt::FramelessWindowHint
826 | Qt::WindowTitleHint
827 | Qt::WindowSystemMenuHint
828 | Qt::WindowMinimizeButtonHint
829 | Qt::WindowMaximizeButtonHint
830 | Qt::WindowCloseButtonHint
831 | Qt::WindowContextHelpButtonHint));
832
833 uint type = (flags & Qt::WindowType_Mask);
834
835 if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) {
836 type = Qt::Window;
837 flags |= Qt::Window;
838 }
839
840 if (flags & Qt::CustomizeWindowHint) {
841 // modify window flags to make them consistent.
842 // Only enable this on non-Mac platforms. Since the old way of doing this would
843 // interpret WindowSystemMenuHint as a close button and we can't change that behavior
844 // we can't just add this in.
845 if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
846# ifdef Q_OS_WIN
847 && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
848# endif
849 ) {
850 flags |= Qt::WindowSystemMenuHint;
851 flags |= Qt::WindowTitleHint;
852 flags &= ~Qt::FramelessWindowHint;
853 }
854 } else if (customize && !(flags & Qt::FramelessWindowHint)) {
855 // if any of the window hints that affect the titlebar are set
856 // and the window is supposed to have frame, we add a titlebar
857 // and system menu by default.
858 flags |= Qt::WindowSystemMenuHint;
859 flags |= Qt::WindowTitleHint;
860 }
861 if (!customize) { // don't modify window flags if the user explicitly set them.
862 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
863 if (type != Qt::Dialog && type != Qt::Sheet && type != Qt::Tool)
864 flags |= Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowFullscreenButtonHint;
865 }
866 if (w->testAttribute(Qt::WA_TransparentForMouseEvents))
867 flags |= Qt::WindowTransparentForInput;
868}
869
870void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
871{
872 Q_Q(QWidget);
873 isWidget = true;
874 wasWidget = true;
875
876#if QT_DEPRECATED_SINCE(6, 11)
877 QT_IGNORE_DEPRECATIONS(
878 const bool isDesktopWindow = (f & Qt::WindowType_Mask) == Qt::WindowType::Desktop;
879 Q_ASSERT_X(!isDesktopWindow, Q_FUNC_INFO, "Qt::WindowType::Desktop is not allowed.");
880 if (isDesktopWindow)
881 f.setFlag(Qt::WindowType::Desktop, false);
882 )
883#endif
884
885 Q_ASSERT_X(q != parentWidget, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
886
887 if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
888 qFatal("QWidget: Cannot create a QWidget without QApplication");
889
890 Q_ASSERT(allWidgets);
891 if (allWidgets)
892 allWidgets->insert(q);
893
894#if QT_CONFIG(thread)
895 if (!parent) {
896 Q_ASSERT_X(QThread::isMainThread(), "QWidget",
897 "Widgets must be created in the GUI thread.");
898 }
899#endif
900
901 data.fstrut_dirty = true;
902
903 data.winid = 0;
904 data.widget_attributes = 0;
905 data.window_flags = f;
906 data.window_state = 0;
907 data.focus_policy = 0;
908 data.context_menu_policy = Qt::DefaultContextMenu;
909 data.window_modality = Qt::NonModal;
910
911 data.sizehint_forced = 0;
912 data.is_closing = false;
913 data.in_show = 0;
914 data.in_set_window_state = 0;
915 data.in_destructor = false;
916
917 // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
918 if (f & Qt::MSWindowsOwnDC) {
919 mustHaveWindowHandle = 1;
920 q->setAttribute(Qt::WA_NativeWindow);
921 }
922
923 q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
924 adjustQuitOnCloseAttribute();
925
926 q->setAttribute(Qt::WA_WState_Hidden);
927
928 //give potential windows a bigger "pre-initial" size; create() will give them a new size later
929 data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
930 initFocusChain();
931
932 if (parentWidget)
933 q->setParent(parentWidget, data.window_flags);
934 else {
935 adjustFlags(data.window_flags, q);
936 resolveLayoutDirection();
937 // opaque system background?
938 const QBrush &background = q->palette().brush(QPalette::Window);
939 setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
940 }
941 data.fnt = QFont(data.fnt, q);
942
943 q->setAttribute(Qt::WA_PendingMoveEvent);
944 q->setAttribute(Qt::WA_PendingResizeEvent);
945
946 if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
947 QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
948
949 QEvent e(QEvent::Create);
950 QCoreApplication::sendEvent(q, &e);
951 QCoreApplication::postEvent(q, new QEvent(QEvent::PolishRequest));
952
953 extraPaintEngine = nullptr;
954}
955
956void QWidgetPrivate::createRecursively()
957{
958 Q_Q(QWidget);
959 q->create(0, true, true);
960 for (int i = 0; i < children.size(); ++i) {
961 QWidget *child = qobject_cast<QWidget *>(children.at(i));
962 if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(Qt::WA_WState_Created))
963 child->d_func()->createRecursively();
964 }
965}
966
967QRhi *QWidgetPrivate::rhi() const
968{
969 Q_Q(const QWidget);
970 if (auto *backingStore = q->backingStore()) {
971 auto *window = windowHandle(WindowHandleMode::Closest);
972 return backingStore->handle()->rhi(window);
973 } else {
974 return nullptr;
975 }
976}
977
978/*!
979 \internal
980 Returns the closest parent widget that has a QWindow window handle
981
982 \note This behavior is different from nativeParentWidget(), which
983 returns the closest parent that has a QWindow window handle with
984 a created QPlatformWindow, and hence native window (winId).
985*/
986QWidget *QWidgetPrivate::closestParentWidgetWithWindowHandle() const
987{
988 Q_Q(const QWidget);
989 QWidget *parent = q->parentWidget();
990 while (parent && !parent->windowHandle())
991 parent = parent->parentWidget();
992 return parent;
993}
994
995QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
996{
997 if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) {
998 if (QTLWExtra *x = maybeTopData()) {
999 if (x->window != nullptr || mode == WindowHandleMode::Direct)
1000 return x->window;
1001 }
1002 }
1003 if (mode == WindowHandleMode::Closest) {
1004 // FIXME: Use closestParentWidgetWithWindowHandle instead
1005 if (auto nativeParent = q_func()->nativeParentWidget()) {
1006 if (auto window = nativeParent->windowHandle())
1007 return window;
1008 }
1009 }
1010 if (mode == WindowHandleMode::TopLevel || mode == WindowHandleMode::Closest) {
1011 if (auto topLevel = q_func()->topLevelWidget()) {
1012 if (auto window = topLevel ->windowHandle())
1013 return window;
1014 }
1015 }
1016 return nullptr;
1017}
1018
1019/*!
1020 \internal
1021
1022 Used by clients outside of widgets to get a handle to the
1023 closest QWindow without having to link to widgets.
1024*/
1025QWindow *QWidgetPrivate::_q_closestWindowHandle() const
1026{
1027 return windowHandle(QWidgetPrivate::WindowHandleMode::Closest);
1028}
1029
1030QScreen *QWidgetPrivate::associatedScreen() const
1031{
1032#if QT_CONFIG(graphicsview)
1033 // embedded widgets never have a screen associated, let QWidget::screen fall back to toplevel
1034 if (nearestGraphicsProxyWidget(q_func()))
1035 return nullptr;
1036#endif
1037 if (auto window = windowHandle(WindowHandleMode::Closest))
1038 return window->screen();
1039 return nullptr;
1040}
1041
1042// finds the first rhiconfig in the hierarchy that has enable==true
1043static bool q_evaluateRhiConfigRecursive(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
1044{
1045 QPlatformBackingStoreRhiConfig config = QWidgetPrivate::get(w)->rhiConfig();
1046 if (config.isEnabled()) {
1047 if (outConfig)
1048 *outConfig = config;
1049 if (outType)
1050 *outType = QBackingStoreRhiSupport::surfaceTypeForConfig(config);
1051 return true;
1052 }
1053 for (const QObject *child : w->children()) {
1054 if (const QWidget *childWidget = qobject_cast<const QWidget *>(child)) {
1055 if (q_evaluateRhiConfigRecursive(childWidget, outConfig, outType)) {
1056 static bool optOut = qEnvironmentVariableIsSet("QT_WIDGETS_NO_CHILD_RHI");
1057 // Native child widgets should not trigger RHI for its parent
1058 // hierarchy, but will still flush the native child using RHI.
1059 if (!optOut && childWidget->testAttribute(Qt::WA_NativeWindow))
1060 continue;
1061
1062 return true;
1063 }
1064 }
1065 }
1066 return false;
1067}
1068
1069bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
1070{
1071 // First, check env.vars. or other means that force the usage of rhi-based
1072 // flushing with a specific graphics API. This takes precedence over what
1073 // the widgets themselves declare. This is global, applying to all
1074 // top-levels.
1075 if (QBackingStoreRhiSupport::checkForceRhi(outConfig, outType)) {
1076 qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluated to forced flushing with QRhi";
1077 return true;
1078 }
1079
1080 // Otherwise, check the widget hierarchy to see if there is a child (or
1081 // ourselves) that declare the need for rhi-based composition.
1082 if (q_evaluateRhiConfigRecursive(w, outConfig, outType)) {
1083 qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluates to flushing with QRhi";
1084 return true;
1085 }
1086
1087 return false;
1088}
1089
1090// ### fixme: Qt 6: Remove parameter window from QWidget::create()
1091
1092/*!
1093 Creates a new widget window.
1094
1095 The parameters \a window, \a initializeWindow, and \a destroyOldWindow
1096 are ignored in Qt 5. Please use QWindow::fromWinId() to create a
1097 QWindow wrapping a foreign window and pass it to
1098 QWidget::createWindowContainer() instead.
1099
1100 \sa createWindowContainer(), QWindow::fromWinId()
1101*/
1102
1103void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
1104{
1105 Q_UNUSED(initializeWindow);
1106 Q_UNUSED(destroyOldWindow);
1107
1108 Q_D(QWidget);
1109 if (Q_UNLIKELY(window))
1110 qWarning("QWidget::create(): Parameter 'window' does not have any effect.");
1111 if (testAttribute(Qt::WA_WState_Created) && window == 0 && internalWinId())
1112 return;
1113
1114 if (d->data.in_destructor)
1115 return;
1116
1117 Qt::WindowType type = windowType();
1118 Qt::WindowFlags &flags = data->window_flags;
1119
1120 if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
1121 type = Qt::Window;
1122 flags |= Qt::Window;
1123 }
1124
1125 if (QWidget *parent = parentWidget()) {
1126 if (type & Qt::Window) {
1127 if (!parent->testAttribute(Qt::WA_WState_Created))
1128 parent->createWinId();
1129 } else if (testAttribute(Qt::WA_NativeWindow) && !parent->internalWinId()
1130 && !testAttribute(Qt::WA_DontCreateNativeAncestors)) {
1131 // We're about to create a native child widget that doesn't have a native parent;
1132 // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
1133 // attribute is set.
1134 d->createWinId();
1135 // Nothing more to do.
1136 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1137 Q_ASSERT(internalWinId());
1138 return;
1139 }
1140 }
1141
1142
1143 static const bool paintOnScreenEnv = qEnvironmentVariableIntValue("QT_ONSCREEN_PAINT") > 0;
1144 if (paintOnScreenEnv)
1145 setAttribute(Qt::WA_PaintOnScreen);
1146
1147 if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
1148 setAttribute(Qt::WA_NativeWindow);
1149
1150 if (isWindow()
1151#if QT_CONFIG(graphicsview)
1152 && !graphicsProxyWidget()
1153#endif
1154 ) {
1155 // Make top levels automatically respect safe areas by default
1156 auto *topExtra = d->maybeTopData();
1157 if (!topExtra || !topExtra->explicitContentsMarginsRespectsSafeArea) {
1158 setAttribute_internal(Qt::WA_ContentsMarginsRespectsSafeArea,
1159 true, data, d);
1160 }
1161 }
1162
1163 d->updateIsOpaque();
1164
1165 setAttribute(Qt::WA_WState_Created); // set created flag
1166 d->create();
1167
1168 // A real toplevel window needs a paint manager
1169 if (isWindow())
1170 d->topData()->repaintManager.reset(new QWidgetRepaintManager(this));
1171
1172 d->setModal_sys();
1173
1174 if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))
1175 setAttribute(Qt::WA_DropSiteRegistered, true);
1176
1177 // need to force the resting of the icon after changing parents
1178 if (testAttribute(Qt::WA_SetWindowIcon))
1179 d->setWindowIcon_sys();
1180
1181 if (isWindow() && !d->topData()->iconText.isEmpty())
1182 d->setWindowIconText_helper(d->topData()->iconText);
1183 if (isWindow() && !d->topData()->caption.isEmpty())
1184 d->setWindowTitle_helper(d->topData()->caption);
1185 if (isWindow() && !d->topData()->filePath.isEmpty())
1186 d->setWindowFilePath_helper(d->topData()->filePath);
1187 d->updateSystemBackground();
1188
1189 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon))
1190 d->setWindowIcon_sys();
1191
1192 // Frame strut update needed in cases where there are native widgets such as QGLWidget,
1193 // as those force native window creation on their ancestors before they are shown.
1194 // If the strut is not updated, any subsequent move of the top level window before show
1195 // will cause window frame to be ignored when positioning the window.
1196 // Note that this only helps on platforms that handle window creation synchronously.
1197 d->updateFrameStrut();
1198}
1199
1201{
1202 QObjectList children = parentWidget->children();
1203 for (int i = 0; i < children.size(); i++) {
1204 if (children.at(i)->isWidgetType()) {
1205 const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
1206 if (childWidget) { // should not be necessary
1207 if (childWidget->testAttribute(Qt::WA_NativeWindow)) {
1208 if (!childWidget->internalWinId())
1209 childWidget->winId();
1210 if (childWidget->windowHandle()) {
1211 if (childWidget->isWindow()) {
1212 childWidget->windowHandle()->setTransientParent(parentWidget->window()->windowHandle());
1213 } else {
1214 childWidget->windowHandle()->setParent(childWidget->nativeParentWidget()->windowHandle());
1215 }
1216 }
1217 } else {
1219 }
1220 }
1221 }
1222 }
1223
1224}
1225
1226void QWidgetPrivate::create()
1227{
1228 Q_Q(QWidget);
1229
1230 if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
1231 return; // we only care about real toplevels
1232
1233 QWidgetWindow *win = topData()->window;
1234 // topData() ensures the extra is created but does not ensure 'window' is non-null
1235 // in case the extra was already valid.
1236 if (!win) {
1237 createTLSysExtra();
1238 Q_ASSERT(topData()->window);
1239 win = topData()->window;
1240 }
1241
1242 const auto dynamicPropertyNames = q->dynamicPropertyNames();
1243 for (const QByteArray &propertyName : dynamicPropertyNames) {
1244 if (!qstrncmp(propertyName, "_q_platform_", 12))
1245 win->setProperty(propertyName, q->property(propertyName));
1246 }
1247
1248 Qt::WindowFlags &flags = data.window_flags;
1249
1250#if defined(QT_PLATFORM_UIKIT)
1251 if (q->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
1252 flags |= Qt::ExpandedClientAreaHint;
1253#endif
1254
1255 if (q->testAttribute(Qt::WA_ShowWithoutActivating))
1256 win->setProperty("_q_showWithoutActivating", QVariant(true));
1257 if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow))
1258 win->setProperty("_q_macAlwaysShowToolWindow", QVariant(true));
1259 win->setFlags(flags);
1260 fixPosIncludesFrame();
1261 if (q->testAttribute(Qt::WA_Moved)
1262 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
1263 win->setGeometry(q->geometry());
1264 else
1265 win->resize(q->size());
1266 if (win->isTopLevel()) {
1267 QScreen *targetScreen = topData()->initialScreen;
1268 topData()->initialScreen = nullptr;
1269 if (!targetScreen)
1270 targetScreen = q->screen();
1271 win->setScreen(targetScreen);
1272 }
1273
1274 QSurfaceFormat format = win->requestedFormat();
1275 if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
1276 && q->testAttribute(Qt::WA_TranslucentBackground)) {
1277 format.setAlphaBufferSize(8);
1278 }
1279 win->setFormat(format);
1280
1281 if (QWidget *nativeParent = q->nativeParentWidget()) {
1282 if (nativeParent->windowHandle()) {
1283 if (flags & Qt::Window) {
1284 // When setting the transient parent for a top-level window, skip
1285 // past any popup-based windows (Popup, Tool, ToolTip, SplashScreen)
1286 // in the native parent chain. These window types are typically short-
1287 // lived and dismissed as a side-effect of showing other top-level
1288 // windows. On some platforms (e.g., Wayland), closing a parent window
1289 // sends close events to all registered transient children; if a stable
1290 // dialog retained a popup-based parent, it could be unexpectedly closed
1291 // when that parent is dismissed.
1292 //
1293 // Popup-based windows that are themselves children of popup-based
1294 // parents intentionally retain the popup parent relationship so they
1295 // stay visually stacked and are dismissed together.
1296 const auto winType = Qt::WindowType((flags & Qt::WindowType_Mask).toInt());
1297 auto isPopupBased = [](Qt::WindowType type) {
1298 return type == Qt::Popup || type == Qt::Tool || type == Qt::ToolTip
1299 || type == Qt::SplashScreen;
1300 };
1301
1302 QWindow *transientParent = nativeParent->window()->windowHandle();
1303 if (!isPopupBased(winType)) {
1304 // Walk up past popup-based ancestors to find a stable parent.
1305 while (transientParent) {
1306 const Qt::WindowType tp = transientParent->type();
1307 if (!isPopupBased(tp))
1308 break;
1309 transientParent = transientParent->transientParent();
1310 }
1311 }
1312 win->setTransientParent(transientParent);
1313 win->setParent(nullptr);
1314 } else {
1315 win->setTransientParent(nullptr);
1316 win->setParent(nativeParent->windowHandle());
1317 }
1318 }
1319 }
1320
1321 qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
1322 QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
1323
1324 win->create();
1325 // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
1326 if (QPlatformWindow *platformWindow = win->handle())
1327 platformWindow->setFrameStrutEventsEnabled(true);
1328
1329 data.window_flags = win->flags();
1330
1331#if QT_CONFIG(xcb)
1332 if (!topData()->role.isNull()) {
1333 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(win->handle()))
1334 xcbWindow->setWindowRole(topData()->role);
1335 }
1336#endif
1337#if QT_CONFIG(wayland)
1338 if (!topData()->role.isNull()) {
1339 if (auto *waylandWindow = dynamic_cast<QWaylandWindow*>(win->handle()))
1340 waylandWindow->setSessionRestoreId(topData()->role);
1341 }
1342#endif
1343
1344 QBackingStore *store = q->backingStore();
1345 usesRhiFlush = false;
1346
1347 if (!store && q->isWindow())
1348 q->setBackingStore(new QBackingStore(win));
1349
1350 QPlatformBackingStoreRhiConfig rhiConfig;
1351 usesRhiFlush = q_evaluateRhiConfig(q, &rhiConfig, nullptr);
1352 if (usesRhiFlush && q->backingStore()) {
1353 // Trigger creation of support infrastructure up front,
1354 // now that we have a specific RHI configuration.
1355 q->backingStore()->handle()->createRhi(win, rhiConfig);
1356 }
1357
1358 setWindowModified_helper();
1359
1360 if (win->handle()) {
1361 WId id = win->winId();
1362 // See the QPlatformWindow::winId() documentation
1363 Q_ASSERT(id != WId(0));
1364 setWinId(id);
1365 }
1366 setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
1367
1368 // Check children and create windows for them if necessary
1369 q_createNativeChildrenAndSetParent(q);
1370
1371 if (extra && !extra->mask.isEmpty())
1372 setMask_sys(extra->mask);
1373
1374 if (data.crect.width() == 0 || data.crect.height() == 0) {
1375 q->setAttribute(Qt::WA_OutsideWSRange, true);
1376 } else {
1377 q->setAttribute(Qt::WA_OutsideWSRange, false);
1378 if (q->isVisible()) {
1379 // If widget is already shown, set window visible, too
1380 win->setNativeWindowVisibility(true);
1381 }
1382 }
1383}
1384
1385#ifdef Q_OS_WIN
1386static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1387#endif
1388
1389void QWidgetPrivate::createTLSysExtra()
1390{
1391 Q_Q(QWidget);
1392 if (!extra->topextra->window && (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())) {
1393 extra->topextra->window = new QWidgetWindow(q);
1394 if (extra->minw || extra->minh)
1395 extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
1396 if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
1397 extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
1398 if (extra->topextra->opacity != 255 && q->isWindow())
1399 extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
1400
1401#if QT_CONFIG(tooltip)
1402 const bool isTipLabel = qobject_cast<const QTipLabel *>(q) != nullptr;
1403#endif
1404 const bool isAlphaWidget = !isTipLabel && q->inherits("QAlphaWidget");
1405#ifdef Q_OS_WIN
1406 // Pass on native parent handle for Widget embedded into Active X.
1407 const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
1408 if (activeXNativeParentHandle.isValid())
1409 extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
1410 if (isTipLabel || isAlphaWidget)
1411 extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
1412#endif
1413 if (isTipLabel || isAlphaWidget || q->inherits("QRollEffect"))
1414 qt_window_private(extra->topextra->window)->setAutomaticPositionAndResizeEnabled(false);
1415
1416 updateIsTranslucent();
1417 }
1418
1419}
1420
1421/*!
1422 Destroys the widget.
1423
1424 All this widget's children are deleted first. The application
1425 exits if this widget is the main widget.
1426*/
1427
1428QWidget::~QWidget()
1429{
1430 Q_D(QWidget);
1431 d->data.in_destructor = true;
1432
1433#if QT_CONFIG(accessibility)
1434 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing && QAccessible::isActive())
1435 QAccessibleCache::instance()->sendObjectDestroyedEvent(this);
1436#endif
1437
1438#if defined (QT_CHECK_STATE)
1439 if (Q_UNLIKELY(paintingActive()))
1440 qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
1441#endif
1442
1443#ifndef QT_NO_GESTURES
1444 if (QGestureManager *manager = QGestureManager::instance(QGestureManager::DontForceCreation)) {
1445 // \forall Qt::GestureType type : ungrabGesture(type) (inlined)
1446 for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
1447 manager->cleanupCachedGestures(this, *it);
1448 }
1449 d->gestureContext.clear();
1450#endif
1451
1452#ifndef QT_NO_ACTION
1453 // remove all actions from this widget
1454 for (auto action : std::as_const(d->actions)) {
1455 QActionPrivate *apriv = action->d_func();
1456 apriv->associatedObjects.removeAll(this);
1457 }
1458 d->actions.clear();
1459#endif
1460
1461#ifndef QT_NO_SHORTCUT
1462 // Remove all shortcuts grabbed by this
1463 // widget, unless application is closing
1464 if (!QApplicationPrivate::is_app_closing && testAttribute(Qt::WA_GrabbedShortcut))
1465 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(0, this, QKeySequence());
1466#endif
1467
1468 // delete layout while we still are a valid widget
1469 delete d->layout;
1470 d->layout = nullptr;
1471
1472 // Remove this from focus list
1473 d->removeFromFocusChain(QWidgetPrivate::FocusChainRemovalRule::AssertConsistency);
1474
1475 QT_TRY {
1476#if QT_CONFIG(graphicsview)
1477 const QWidget* w = this;
1478 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1479 w = w->d_func()->extra->focus_proxy;
1480 QWidget *window = w->window();
1481 QWExtra *e = window ? window->d_func()->extra.get() : nullptr ;
1482 if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1483#endif
1484 clearFocus();
1485 } QT_CATCH(...) {
1486 // swallow this problem because we are in a destructor
1487 }
1488
1489 d->setDirtyOpaqueRegion();
1490
1491 if (isWindow() && isVisible() && internalWinId()) {
1492 QT_TRY {
1493 d->close();
1494 } QT_CATCH(...) {
1495 // if we're out of memory, at least hide the window.
1496 QT_TRY {
1497 hide();
1498 } QT_CATCH(...) {
1499 // and if that also doesn't work, then give up
1500 }
1501 }
1502 } else if (isVisible()) {
1503 qApp->d_func()->sendSyntheticEnterLeave(this);
1504 }
1505
1506 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
1507 repaintManager->removeDirtyWidget(this);
1508 if (testAttribute(Qt::WA_StaticContents))
1509 repaintManager->removeStaticWidget(this);
1510 }
1511
1512 delete d->needsFlush;
1513 d->needsFlush = nullptr;
1514
1515 // The next 20 lines are duplicated from QObject, but required here
1516 // since QWidget deletes is children itself
1517 bool blocked = d->blockSig;
1518 d->blockSig = 0; // unblock signals so we always emit destroyed()
1519
1520 if (d->isSignalConnected(0)) {
1521 QT_TRY {
1522 emit destroyed(this);
1523 } QT_CATCH(...) {
1524 // all the signal/slots connections are still in place - if we don't
1525 // quit now, we will crash pretty soon.
1526 qWarning("Detected an unexpected exception in ~QWidget while emitting destroyed().");
1527 QT_RETHROW;
1528 }
1529 }
1530
1531 if (d->declarativeData) {
1532 d->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1533 if (QAbstractDeclarativeData::destroyed)
1534 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1535 d->declarativeData = nullptr; // don't activate again in ~QObject
1536 d->wasDeleted = false;
1537 }
1538
1539 d->blockSig = blocked;
1540
1541 if (!d->children.isEmpty())
1542 d->deleteChildren();
1543
1544 QCoreApplication::removePostedEvents(this);
1545
1546 QT_TRY {
1547 destroy(); // platform-dependent cleanup
1548 } QT_CATCH(...) {
1549 // if this fails we can't do anything about it but at least we are not allowed to throw.
1550 }
1551 --QWidgetPrivate::instanceCounter;
1552
1553 if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1554 QWidgetPrivate::allWidgets->remove(this);
1555
1556 QT_TRY {
1557 QEvent e(QEvent::Destroy);
1558 QCoreApplication::sendEvent(this, &e);
1559 } QT_CATCH(const std::exception&) {
1560 // if this fails we can't do anything about it but at least we are not allowed to throw.
1561 }
1562
1563#if QT_CONFIG(graphicseffect)
1564 delete d->graphicsEffect;
1565#endif
1566 d->deleteExtra();
1567
1568 d->isWidget = false;
1569}
1570
1571int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1572int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1573
1574void QWidgetPrivate::setWinId(WId id) // set widget identifier
1575{
1576 Q_Q(QWidget);
1577 if (mapper && data.winid) {
1578 mapper->remove(data.winid);
1579 }
1580
1581 const WId oldWinId = data.winid;
1582
1583 data.winid = id;
1584 if (mapper && id) {
1585 mapper->insert(data.winid, q);
1586 }
1587
1588 if (oldWinId != id) {
1589 QEvent e(QEvent::WinIdChange);
1590 QCoreApplication::sendEvent(q, &e);
1591 }
1592}
1593
1594void QWidgetPrivate::createTLExtra()
1595{
1596 if (!extra)
1597 createExtra();
1598 if (!extra->topextra) {
1599 extra->topextra = std::make_unique<QTLWExtra>();
1600 QTLWExtra* x = extra->topextra.get();
1601 x->backingStore = nullptr;
1602 x->sharedPainter = nullptr;
1603 x->incw = x->inch = 0;
1604 x->basew = x->baseh = 0;
1605 x->frameStrut.setCoords(0, 0, 0, 0);
1606 x->normalGeometry = QRect(0,0,-1,-1);
1607 x->savedFlags = { };
1608 x->opacity = 255;
1609 x->posIncludesFrame = 0;
1610 x->sizeAdjusted = false;
1611 x->embedded = 0;
1612 x->explicitContentsMarginsRespectsSafeArea = 0;
1613 x->window = nullptr;
1614 x->initialScreen = nullptr;
1615
1616#ifdef QWIDGET_EXTRA_DEBUG
1617 static int count = 0;
1618 qDebug() << "tlextra" << ++count;
1619#endif
1620 }
1621}
1622
1623/*!
1624 \internal
1625 Creates the widget extra data.
1626*/
1627
1628void QWidgetPrivate::createExtra()
1629{
1630 if (!extra) { // if not exists
1631 extra = std::make_unique<QWExtra>();
1632 extra->glContext = nullptr;
1633#if QT_CONFIG(graphicsview)
1634 extra->proxyWidget = nullptr;
1635#endif
1636 extra->minw = 0;
1637 extra->minh = 0;
1638 extra->maxw = QWIDGETSIZE_MAX;
1639 extra->maxh = QWIDGETSIZE_MAX;
1640 extra->customDpiX = 0;
1641 extra->customDpiY = 0;
1642 extra->explicitMinSize = 0;
1643 extra->explicitMaxSize = 0;
1644 extra->autoFillBackground = 0;
1645 extra->nativeChildrenForced = 0;
1646 extra->inRenderWithPainter = 0;
1647 extra->hasWindowContainer = false;
1648 extra->hasMask = 0;
1649 createSysExtra();
1650#ifdef QWIDGET_EXTRA_DEBUG
1651 static int count = 0;
1652 qDebug() << "extra" << ++count;
1653#endif
1654 }
1655}
1656
1657void QWidgetPrivate::createSysExtra()
1658{
1659}
1660
1661/*!
1662 \internal
1663 Deletes the widget extra data.
1664*/
1665
1666void QWidgetPrivate::deleteExtra()
1667{
1668 if (extra) { // if exists
1669 deleteSysExtra();
1670#if QT_CONFIG(style_stylesheet)
1671 // dereference the stylesheet style
1672 if (QStyleSheetStyle *proxy = qt_styleSheet(extra->style))
1673 proxy->deref();
1674#endif
1675 if (extra->topextra)
1676 deleteTLSysExtra();
1677
1678 // extra->xic destroyed in QWidget::destroy()
1679 extra.reset();
1680 }
1681}
1682
1683void QWidgetPrivate::deleteSysExtra()
1684{
1685}
1686
1687void QWidgetPrivate::deleteTLSysExtra()
1688{
1689 Q_Q(QWidget);
1690 if (extra && extra->topextra) {
1691 if (extra->hasWindowContainer)
1692 QWindowContainer::toplevelAboutToBeDestroyed(q);
1693
1694 delete extra->topextra->window;
1695 extra->topextra->window = nullptr;
1696 }
1697}
1698
1699/*
1700 Returns \c region of widgets above this which overlap with
1701 \a rect, which is in parent's coordinate system (same as crect).
1702*/
1703
1704QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
1705{
1706 Q_Q(const QWidget);
1707
1708 const QWidget *w = q;
1709 QRect r = rect;
1710 QPoint p;
1711 QRegion region;
1712 while (w) {
1713 if (w->isWindow())
1714 break;
1715 QWidgetPrivate *pd = w->parentWidget()->d_func();
1716 bool above = false;
1717 for (int i = 0; i < pd->children.size(); ++i) {
1718 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
1719 if (!sibling || !sibling->isVisible() || sibling->isWindow())
1720 continue;
1721 if (!above) {
1722 above = (sibling == w);
1723 continue;
1724 }
1725
1726 const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect);
1727 if (qRectIntersects(siblingRect, r)) {
1728 const auto &siblingExtra = sibling->d_func()->extra;
1729 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1730 && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
1731 continue;
1732 }
1733 region += siblingRect.translated(-p);
1734 if (breakAfterFirst)
1735 break;
1736 }
1737 }
1738 w = w->parentWidget();
1739 r.translate(pd->data.crect.topLeft());
1740 p += pd->data.crect.topLeft();
1741 }
1742 return region;
1743}
1744
1745void QWidgetPrivate::syncBackingStore()
1746{
1747 if (shouldPaintOnScreen()) {
1748 paintOnScreen(dirty);
1749 dirty = QRegion();
1750 } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1751 repaintManager->sync();
1752 }
1753}
1754
1755void QWidgetPrivate::syncBackingStore(const QRegion &region)
1756{
1757 if (shouldPaintOnScreen())
1758 paintOnScreen(region);
1759 else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1760 repaintManager->sync(q_func(), region);
1761 }
1762}
1763
1764void QWidgetPrivate::paintOnScreen(const QRegion &rgn)
1765{
1766 if (data.in_destructor)
1767 return;
1768
1769 if (shouldDiscardSyncRequest())
1770 return;
1771
1772 Q_Q(QWidget);
1773 if (q->testAttribute(Qt::WA_StaticContents)) {
1774 if (!extra)
1775 createExtra();
1776 extra->staticContentsSize = data.crect.size();
1777 }
1778
1779 QPaintEngine *engine = q->paintEngine();
1780
1781 // QGLWidget does not support partial updates if:
1782 // 1) The context is double buffered
1783 // 2) The context is single buffered and auto-fill background is enabled.
1784 const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
1785 || engine->type() == QPaintEngine::OpenGL2))
1786 && (usesDoubleBufferedGLContext || q->autoFillBackground());
1787 QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
1788
1789 toBePainted &= clipRect();
1790 clipToEffectiveMask(toBePainted);
1791 if (toBePainted.isEmpty())
1792 return; // Nothing to repaint.
1793
1794 drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, nullptr);
1795
1796 if (Q_UNLIKELY(q->paintingActive()))
1797 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
1798}
1799
1800void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1801{
1802 Q_Q(QWidget);
1803
1804 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1805 return; // nothing we can do
1806
1807 if (enable != q->testAttribute(Qt::WA_UpdatesDisabled))
1808 return; // nothing to do
1809
1810 q->setAttribute(Qt::WA_UpdatesDisabled, !enable);
1811 if (enable)
1812 q->update();
1813
1814 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1815 for (int i = 0; i < children.size(); ++i) {
1816 QWidget *w = qobject_cast<QWidget *>(children.at(i));
1817 if (w && !w->isWindow() && !w->testAttribute(attribute))
1818 w->d_func()->setUpdatesEnabled_helper(enable);
1819 }
1820}
1821
1822/*!
1823 \internal
1824
1825 Propagate this widget's palette to all children, except style sheet
1826 widgets, and windows that don't enable window propagation (palettes don't
1827 normally propagate to windows).
1828*/
1829void QWidgetPrivate::propagatePaletteChange()
1830{
1831 Q_Q(QWidget);
1832 // Propagate a new inherited mask to all children.
1833#if QT_CONFIG(graphicsview)
1834 if (!q->parentWidget() && extra && extra->proxyWidget) {
1835 QGraphicsProxyWidget *p = extra->proxyWidget;
1836 inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolveMask();
1837 } else
1838#endif // QT_CONFIG(graphicsview)
1839 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
1840 inheritedPaletteResolveMask = 0;
1841 }
1842
1843 directPaletteResolveMask = data.pal.resolveMask();
1844 auto mask = directPaletteResolveMask | inheritedPaletteResolveMask;
1845
1846 const bool useStyleSheetPropagationInWidgetStyles =
1847 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
1848
1849 QEvent pc(QEvent::PaletteChange);
1850 QCoreApplication::sendEvent(q, &pc);
1851 for (int i = 0; i < children.size(); ++i) {
1852 QWidget *w = qobject_cast<QWidget*>(children.at(i));
1853 if (w && (!w->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
1854 && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
1855 QWidgetPrivate *wd = w->d_func();
1856 wd->inheritedPaletteResolveMask = mask;
1857 wd->resolvePalette();
1858 }
1859 }
1860}
1861
1862/*
1863 Returns the widget's clipping rectangle.
1864*/
1865QRect QWidgetPrivate::clipRect() const
1866{
1867 Q_Q(const QWidget);
1868 const QWidget * w = q;
1869 if (!w->isVisible())
1870 return QRect();
1871 QRect r = effectiveRectFor(q->rect());
1872 int ox = 0;
1873 int oy = 0;
1874 while (w
1875 && w->isVisible()
1876 && !w->isWindow()
1877 && w->parentWidget()) {
1878 ox -= w->x();
1879 oy -= w->y();
1880 w = w->parentWidget();
1881 r &= QRect(ox, oy, w->width(), w->height());
1882 }
1883 return r;
1884}
1885
1886/*
1887 Returns the widget's clipping region (without siblings).
1888*/
1889QRegion QWidgetPrivate::clipRegion() const
1890{
1891 Q_Q(const QWidget);
1892 if (!q->isVisible())
1893 return QRegion();
1894 QRegion r(q->rect());
1895 const QWidget * w = q;
1896 const QWidget *ignoreUpTo;
1897 int ox = 0;
1898 int oy = 0;
1899 while (w
1900 && w->isVisible()
1901 && !w->isWindow()
1902 && w->parentWidget()) {
1903 ox -= w->x();
1904 oy -= w->y();
1905 ignoreUpTo = w;
1906 w = w->parentWidget();
1907 r &= QRegion(ox, oy, w->width(), w->height());
1908
1909 int i = 0;
1910 while(w->d_func()->children.at(i++) != static_cast<const QObject *>(ignoreUpTo))
1911 ;
1912 for ( ; i < w->d_func()->children.size(); ++i) {
1913 if (QWidget *sibling = qobject_cast<QWidget *>(w->d_func()->children.at(i))) {
1914 if (sibling->isVisible() && !sibling->isWindow()) {
1915 QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
1916 sibling->width(), sibling->height());
1917 if (qRectIntersects(siblingRect, q->rect()))
1918 r -= QRegion(siblingRect);
1919 }
1920 }
1921 }
1922 }
1923 return r;
1924}
1925
1926void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
1927{
1928// Transform the system clip region from device-independent pixels to device pixels
1929 QTransform scaleTransform;
1930 scaleTransform.scale(devicePixelRatio, devicePixelRatio);
1931
1932 paintEngine->d_func()->baseSystemClip = region;
1933 paintEngine->d_func()->setSystemTransform(scaleTransform);
1934
1935}
1936
1937#if QT_CONFIG(graphicseffect)
1938void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
1939{
1940 Q_Q(QWidget);
1941 QWidget *w = q;
1942 do {
1943 if (w->graphicsEffect()) {
1944 QWidgetEffectSourcePrivate *sourced =
1945 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
1946 if (!sourced->updateDueToGraphicsEffect)
1947 w->graphicsEffect()->source()->d_func()->invalidateCache();
1948 }
1949 w = w->parentWidget();
1950 } while (w);
1951}
1952#endif // QT_CONFIG(graphicseffect)
1953
1954void QWidgetPrivate::setDirtyOpaqueRegion()
1955{
1956 Q_Q(QWidget);
1957
1958 dirtyOpaqueChildren = true;
1959
1960#if QT_CONFIG(graphicseffect)
1961 invalidateGraphicsEffectsRecursively();
1962#endif // QT_CONFIG(graphicseffect)
1963
1964 if (q->isWindow())
1965 return;
1966
1967 QWidget *parent = q->parentWidget();
1968 if (!parent)
1969 return;
1970
1971 // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
1972 QWidgetPrivate *pd = parent->d_func();
1973 if (!pd->dirtyOpaqueChildren)
1974 pd->setDirtyOpaqueRegion();
1975}
1976
1977const QRegion &QWidgetPrivate::getOpaqueChildren() const
1978{
1979 if (!dirtyOpaqueChildren)
1980 return opaqueChildren;
1981
1982 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
1983 that->opaqueChildren = QRegion();
1984
1985 for (int i = 0; i < children.size(); ++i) {
1986 QWidget *child = qobject_cast<QWidget *>(children.at(i));
1987 if (!child || !child->isVisible() || child->isWindow())
1988 continue;
1989
1990 const QPoint offset = child->geometry().topLeft();
1991 QWidgetPrivate *childd = child->d_func();
1992 QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
1993 if (childd->extra && childd->extra->hasMask)
1994 r &= childd->extra->mask;
1995 if (r.isEmpty())
1996 continue;
1997 r.translate(offset);
1998 that->opaqueChildren += r;
1999 }
2000
2001 that->opaqueChildren &= q_func()->rect();
2002 that->dirtyOpaqueChildren = false;
2003
2004 return that->opaqueChildren;
2005}
2006
2007void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2008{
2009 if (children.isEmpty() || clipRect.isEmpty())
2010 return;
2011
2012 const QRegion &r = getOpaqueChildren();
2013 if (!r.isEmpty())
2014 source -= (r & clipRect);
2015}
2016
2017//subtract any relatives that are higher up than me --- this is too expensive !!!
2018void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2019 bool alsoNonOpaque) const
2020{
2021 Q_Q(const QWidget);
2022 static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue("QT_NO_SUBTRACTOPAQUESIBLINGS");
2023 if (disableSubtractOpaqueSiblings || q->isWindow())
2024 return;
2025
2026 QRect clipBoundingRect;
2027 bool dirtyClipBoundingRect = true;
2028
2029 QRegion parentClip;
2030 bool dirtyParentClip = true;
2031
2032 QPoint parentOffset = data.crect.topLeft();
2033
2034 const QWidget *w = q;
2035
2036 while (w) {
2037 if (w->isWindow())
2038 break;
2039 QWidgetPrivate *pd = w->parentWidget()->d_func();
2040 const int myIndex = pd->children.indexOf(const_cast<QWidget *>(w));
2041 const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect);
2042 for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2043 QWidget *sibling = qobject_cast<QWidget *>(pd->children.at(i));
2044 if (!sibling || !sibling->isVisible() || sibling->isWindow())
2045 continue;
2046
2047 const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect);
2048 if (!qRectIntersects(siblingGeometry, widgetGeometry))
2049 continue;
2050
2051 if (dirtyClipBoundingRect) {
2052 clipBoundingRect = sourceRegion.boundingRect();
2053 dirtyClipBoundingRect = false;
2054 }
2055
2056 if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset)))
2057 continue;
2058
2059 if (dirtyParentClip) {
2060 parentClip = sourceRegion.translated(parentOffset);
2061 dirtyParentClip = false;
2062 }
2063
2064 const QPoint siblingPos(sibling->data->crect.topLeft());
2065 const QRect siblingClipRect(sibling->d_func()->clipRect());
2066 QRegion siblingDirty(parentClip);
2067 siblingDirty &= (siblingClipRect.translated(siblingPos));
2068 const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2069 && !sibling->d_func()->graphicsEffect;
2070 if (hasMask)
2071 siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos);
2072 if (siblingDirty.isEmpty())
2073 continue;
2074
2075 if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2076 if (hasMask) {
2077 siblingDirty.translate(-parentOffset);
2078 sourceRegion -= siblingDirty;
2079 } else {
2080 sourceRegion -= siblingGeometry.translated(-parentOffset);
2081 }
2082 } else {
2083 if (hasDirtySiblingsAbove)
2084 *hasDirtySiblingsAbove = true;
2085 if (sibling->d_func()->children.isEmpty())
2086 continue;
2087 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2088 opaqueSiblingChildren.translate(-parentOffset + siblingPos);
2089 sourceRegion -= opaqueSiblingChildren;
2090 }
2091 if (sourceRegion.isEmpty())
2092 return;
2093
2094 dirtyClipBoundingRect = true;
2095 dirtyParentClip = true;
2096 }
2097
2098 w = w->parentWidget();
2099 parentOffset += pd->data.crect.topLeft();
2100 dirtyParentClip = true;
2101 }
2102}
2103
2104void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2105{
2106 Q_Q(const QWidget);
2107
2108 const QWidget *w = q;
2109 QPoint offset;
2110
2111#if QT_CONFIG(graphicseffect)
2112 if (graphicsEffect && !w->isWindow()) {
2113 w = q->parentWidget();
2114 offset -= data.crect.topLeft();
2115 }
2116#endif // QT_CONFIG(graphicseffect)
2117
2118 while (w) {
2119 const QWidgetPrivate *wd = w->d_func();
2120 if (wd->extra && wd->extra->hasMask)
2121 region &= (w != q) ? wd->extra->mask.translated(offset) : wd->extra->mask;
2122 if (w->isWindow())
2123 return;
2124 offset -= wd->data.crect.topLeft();
2125 w = w->parentWidget();
2126 }
2127}
2128
2129bool QWidgetPrivate::shouldPaintOnScreen() const
2130{
2131#if defined(QT_NO_BACKINGSTORE)
2132 return true;
2133#else
2134 Q_Q(const QWidget);
2135 if (q->testAttribute(Qt::WA_PaintOnScreen)
2136 || (!q->isWindow() && q->window()->testAttribute(Qt::WA_PaintOnScreen))) {
2137 return true;
2138 }
2139
2140 return false;
2141#endif
2142}
2143
2144void QWidgetPrivate::updateIsOpaque()
2145{
2146 // hw: todo: only needed if opacity actually changed
2147 setDirtyOpaqueRegion();
2148
2149#if QT_CONFIG(graphicseffect)
2150 if (graphicsEffect) {
2151 // ### We should probably add QGraphicsEffect::isOpaque at some point.
2152 setOpaque(false);
2153 return;
2154 }
2155#endif // QT_CONFIG(graphicseffect)
2156
2157 Q_Q(QWidget);
2158 if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) {
2159 setOpaque(true);
2160 return;
2161 }
2162
2163 const QPalette &pal = q->palette();
2164
2165 if (q->autoFillBackground()) {
2166 const QBrush &autoFillBrush = pal.brush(q->backgroundRole());
2167 if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2168 setOpaque(true);
2169 return;
2170 }
2171 }
2172
2173 if (q->isWindow() && !q->testAttribute(Qt::WA_NoSystemBackground)) {
2174 const QBrush &windowBrush = q->palette().brush(QPalette::Window);
2175 if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2176 setOpaque(true);
2177 return;
2178 }
2179 }
2180 setOpaque(false);
2181}
2182
2183void QWidgetPrivate::setOpaque(bool opaque)
2184{
2185 if (isOpaque != opaque) {
2186 isOpaque = opaque;
2187 updateIsTranslucent();
2188 }
2189}
2190
2191void QWidgetPrivate::updateIsTranslucent()
2192{
2193 Q_Q(QWidget);
2194 if (QWindow *window = q->windowHandle()) {
2195 QSurfaceFormat format = window->format();
2196 const int oldAlpha = format.alphaBufferSize();
2197 const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground) ? 8 : -1;
2198 if (oldAlpha != newAlpha) {
2199 // QTBUG-85714: Do this only when the QWindow has not yet been create()'ed yet.
2200 //
2201 // If that is not the case, then the setFormat() is not just futile
2202 // but downright dangerous. Futile because the format matters only
2203 // when creating the native window, no point in changing it
2204 // afterwards. Dangerous because a QOpenGLContext or something else
2205 // may eventually query the QWindow's format(), in order to ensure
2206 // compatibility (in terms of native concepts such as pixel format,
2207 // EGLConfig, etc.), and if we change it here, then the returned
2208 // format does not describe reality anymore. (reality being the
2209 // settings with which the native resource was created).
2210 //
2211 // Whereas if one does a destroy()-create() then this all here
2212 // won't matter because the format is updated in
2213 // QWidgetPrivate::create() again.
2214 //
2215 if (!window->handle()) {
2216 format.setAlphaBufferSize(newAlpha);
2217 window->setFormat(format);
2218 }
2219 }
2220 }
2221}
2222
2223static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2224{
2225 Q_ASSERT(painter);
2226
2227 if (brush.style() == Qt::TexturePattern) {
2228 const QRect rect(rgn.boundingRect());
2229 painter->setClipRegion(rgn);
2230 painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
2231 } else if (brush.gradient()
2232 && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode
2233 || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) {
2234 painter->save();
2235 painter->setClipRegion(rgn);
2236 painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush);
2237 painter->restore();
2238 } else {
2239 for (const QRect &rect : rgn)
2240 painter->fillRect(rect, brush);
2241 }
2242}
2243
2244bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
2245{
2246#if QT_CONFIG(scrollarea)
2247 Q_Q(const QWidget);
2248 //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2249 if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
2250 return false;
2251 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
2252 if (scrollArea && scrollArea->viewport() == q) {
2253 QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2254 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2255 painter->setBrushOrigin(-priv->contentsOffset());
2256 }
2257#endif // QT_CONFIG(scrollarea)
2258 return true;
2259}
2260
2261void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, DrawWidgetFlags flags) const
2262{
2263 Q_Q(const QWidget);
2264
2265 bool brushOriginSet = false;
2266 const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
2267
2268 if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2269 const QBrush bg = q->palette().brush(QPalette::Window);
2270 if (!brushOriginSet)
2271 brushOriginSet = updateBrushOrigin(painter, bg);
2272 if (!(flags & DontSetCompositionMode)) {
2273 //copy alpha straight in
2274 QPainter::CompositionMode oldMode = painter->compositionMode();
2275 painter->setCompositionMode(QPainter::CompositionMode_Source);
2276 fillRegion(painter, rgn, bg);
2277 painter->setCompositionMode(oldMode);
2278 } else {
2279 fillRegion(painter, rgn, bg);
2280 }
2281 }
2282
2283 if (q->autoFillBackground()) {
2284 if (!brushOriginSet)
2285 brushOriginSet = updateBrushOrigin(painter, autoFillBrush);
2286 fillRegion(painter, rgn, autoFillBrush);
2287 }
2288
2289 if (q->testAttribute(Qt::WA_StyledBackground)) {
2290 painter->setClipRegion(rgn);
2291 QStyleOption opt;
2292 opt.initFrom(q);
2293 q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
2294 }
2295}
2296
2297/*
2298 \internal
2299 This function is called when a widget is hidden or destroyed.
2300 It resets some application global pointers that should only refer active,
2301 visible widgets.
2302*/
2303
2305
2306void QWidgetPrivate::deactivateWidgetCleanup()
2307{
2308 Q_Q(QWidget);
2309 // If this was the active application window, reset it
2310 if (QApplication::activeWindow() == q)
2311 QApplicationPrivate::setActiveWindow(nullptr);
2312 // If the is the active mouse press widget, reset it
2313 if (q == qt_button_down)
2314 qt_button_down = nullptr;
2315}
2316
2317
2318/*!
2319 Returns a pointer to the widget with window identifier/handle \a
2320 id.
2321
2322 The window identifier type depends on the underlying window
2323 system, see \c qwindowdefs.h for the actual definition. If there
2324 is no widget with this identifier, \nullptr is returned.
2325*/
2326
2327QWidget *QWidget::find(WId id)
2328{
2329 return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : nullptr;
2330}
2331
2332
2333
2334/*!
2335 \fn WId QWidget::internalWinId() const
2336 \internal
2337 Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2338
2339*/
2340
2341/*!
2342 \fn WId QWidget::winId() const
2343
2344 Returns the window system identifier of the widget.
2345
2346 Portable in principle, but if you use it you are probably about to
2347 do something non-portable. Be careful.
2348
2349 If a widget is non-native (alien) and winId() is invoked on it, that widget
2350 will be provided a native handle.
2351
2352 This value may change at run-time. An event with type QEvent::WinIdChange
2353 will be sent to the widget following a change in window system identifier.
2354
2355 \sa find()
2356*/
2357WId QWidget::winId() const
2358{
2359 if (!data->in_destructor
2360 && (!testAttribute(Qt::WA_WState_Created) || !internalWinId()))
2361 {
2362 QWidget *that = const_cast<QWidget*>(this);
2363 that->setAttribute(Qt::WA_NativeWindow);
2364 that->d_func()->createWinId();
2365 return that->data->winid;
2366 }
2367 return data->winid;
2368}
2369
2370void QWidgetPrivate::createWinId()
2371{
2372 Q_Q(QWidget);
2373
2374 const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
2375 if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2376 if (!q->isWindow()) {
2377 QWidget *parent = q->parentWidget();
2378 QWidgetPrivate *pd = parent->d_func();
2379 if (forceNativeWindow && !q->testAttribute(Qt::WA_DontCreateNativeAncestors))
2380 parent->setAttribute(Qt::WA_NativeWindow);
2381 if (!parent->internalWinId()) {
2382 pd->createWinId();
2383 }
2384
2385 for (int i = 0; i < pd->children.size(); ++i) {
2386 QWidget *w = qobject_cast<QWidget *>(pd->children.at(i));
2387 if (w && !w->isWindow() && (!w->testAttribute(Qt::WA_WState_Created)
2388 || (!w->internalWinId() && w->testAttribute(Qt::WA_NativeWindow)))) {
2389 w->create();
2390 }
2391 }
2392 } else {
2393 q->create();
2394 }
2395 }
2396}
2397
2398/*!
2399\internal
2400Ensures that the widget is set on the screen point is on. This is handy getting a correct
2401size hint before a resize in e.g QMenu and QToolTip.
2402Returns if the screen was changed.
2403*/
2404
2405bool QWidgetPrivate::setScreenForPoint(const QPoint &pos)
2406{
2407 Q_Q(QWidget);
2408 if (!q->isWindow())
2409 return false;
2410 // Find the screen for pos and make the widget understand it is on that screen.
2411 return setScreen(QGuiApplication::screenAt(pos));
2412}
2413
2414/*!
2415\internal
2416Ensures that the widget's QWindow is set to be on the given \a screen.
2417Returns true if the screen was changed.
2418*/
2419
2420bool QWidgetPrivate::setScreen(QScreen *screen)
2421{
2422 Q_Q(QWidget);
2423 if (!screen || !q->isWindow())
2424 return false;
2425 const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
2426 if (currentScreen != screen) {
2427 topData()->initialScreen = screen;
2428 if (windowHandle())
2429 windowHandle()->setScreen(screen);
2430 return true;
2431 }
2432 return false;
2433}
2434
2435/*!
2436\internal
2437Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2438
2439*/
2440
2441void QWidget::createWinId()
2442{
2443 Q_D(QWidget);
2444 d->createWinId();
2445}
2446
2447/*!
2448 \since 4.4
2449
2450 Returns the effective window system identifier of the widget, i.e. the
2451 native parent's window system identifier.
2452
2453 If the widget is native, this function returns the native widget ID.
2454 Otherwise, the window ID of the first native parent widget, i.e., the
2455 top-level widget that contains this widget, is returned.
2456
2457 \note We recommend that you do not store this value as it is likely to
2458 change at run-time.
2459
2460 \sa nativeParentWidget()
2461*/
2462WId QWidget::effectiveWinId() const
2463{
2464 const WId id = internalWinId();
2465 if (id || !testAttribute(Qt::WA_WState_Created))
2466 return id;
2467 if (const QWidget *realParent = nativeParentWidget())
2468 return realParent->internalWinId();
2469 return 0;
2470}
2471
2472/*!
2473 If this is a native widget, return the associated QWindow.
2474 Otherwise return null.
2475
2476 Native widgets include toplevel widgets, QGLWidget, and child widgets
2477 on which winId() was called.
2478
2479 \since 5.0
2480
2481 \sa winId(), screen()
2482*/
2483QWindow *QWidget::windowHandle() const
2484{
2485 Q_D(const QWidget);
2486 return d->windowHandle();
2487}
2488
2489/*!
2490 Returns the screen the widget is on.
2491
2492 \since 5.14
2493
2494 \sa windowHandle()
2495*/
2496QScreen *QWidget::screen() const
2497{
2498 Q_D(const QWidget);
2499 if (auto associatedScreen = d->associatedScreen())
2500 return associatedScreen;
2501 if (auto topLevel = window()) {
2502 if (auto topData = qt_widget_private(topLevel)->topData()) {
2503 if (topData->initialScreen)
2504 return topData->initialScreen;
2505 }
2506 if (auto screenByPos = QGuiApplication::screenAt(topLevel->geometry().center()))
2507 return screenByPos;
2508 }
2509 return QGuiApplication::primaryScreen();
2510}
2511
2512/*!
2513 Sets the screen on which the widget should be shown to \a screen.
2514
2515 Setting the screen only makes sense for windows. If necessary, the widget's
2516 window will get recreated on \a screen.
2517
2518 \note If the screen is part of a virtual desktop of multiple screens,
2519 the window will not move automatically to \a screen. To place the
2520 window relative to the screen, use the screen's topLeft() position.
2521
2522 \sa QWindow::setScreen()
2523*/
2524void QWidget::setScreen(QScreen *screen)
2525{
2526 Q_D(QWidget);
2527 d->setScreen(screen);
2528}
2529
2530#if QT_CONFIG(style_stylesheet)
2531
2532/*!
2533 \property QWidget::styleSheet
2534 \brief the widget's style sheet
2535 \since 4.2
2536
2537 The style sheet contains a textual description of customizations to the
2538 widget's style, as described in the \l{Qt Style Sheets} document.
2539
2540 Since Qt 4.5, Qt style sheets fully supports \macos.
2541
2542 \warning Qt style sheets are currently not supported for custom QStyle
2543 subclasses. We plan to address this in some future release.
2544
2545 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2546*/
2547QString QWidget::styleSheet() const
2548{
2549 Q_D(const QWidget);
2550 if (!d->extra)
2551 return QString();
2552 return d->extra->styleSheet;
2553}
2554
2555void QWidget::setStyleSheet(const QString& styleSheet)
2556{
2557 Q_D(QWidget);
2558 if (data->in_destructor)
2559 return;
2560 d->createExtra();
2561
2562 QStyleSheetStyle *proxy = qt_styleSheet(d->extra->style);
2563 d->extra->styleSheet = styleSheet;
2564 if (styleSheet.isEmpty()) { // stylesheet removed
2565 if (!proxy)
2566 return;
2567
2568 d->inheritStyle();
2569 return;
2570 }
2571
2572 if (proxy) { // style sheet update
2573 bool repolish = d->polished;
2574 if (!repolish) {
2575 const auto childWidgets = findChildren<QWidget*>();
2576 for (auto child : childWidgets) {
2577 repolish = child->d_func()->polished;
2578 if (repolish)
2579 break;
2580 }
2581 }
2582 if (repolish)
2583 proxy->repolish(this);
2584 return;
2585 }
2586
2587 if (testAttribute(Qt::WA_SetStyle)) {
2588 d->setStyle_helper(new QStyleSheetStyle(d->extra->style), true);
2589 } else {
2590 d->setStyle_helper(new QStyleSheetStyle(nullptr), true);
2591 }
2592}
2593
2594#endif // QT_NO_STYLE_STYLESHEET
2595
2596/*!
2597 \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2598*/
2599
2600QStyle *QWidget::style() const
2601{
2602 Q_D(const QWidget);
2603
2604 if (d->extra && d->extra->style)
2605 return d->extra->style;
2606 return QApplication::style();
2607}
2608
2609/*!
2610 Sets the widget's GUI style to \a style. The ownership of the style
2611 object is not transferred.
2612
2613 If no style is set, the widget uses the application's style,
2614 QApplication::style() instead.
2615
2616 Setting a widget's style has no effect on existing or future child
2617 widgets.
2618
2619 \warning This function is particularly useful for demonstration
2620 purposes, where you want to show Qt's styling capabilities. Real
2621 applications should avoid it and use one consistent GUI style
2622 instead.
2623
2624 \warning Qt style sheets are currently not supported for custom QStyle
2625 subclasses. We plan to address this in some future release.
2626
2627 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2628*/
2629
2630void QWidget::setStyle(QStyle *style)
2631{
2632 Q_D(QWidget);
2633 setAttribute(Qt::WA_SetStyle, style != nullptr);
2634 d->createExtra();
2635#if QT_CONFIG(style_stylesheet)
2636 if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2637 //if for some reason someone try to set a QStyleSheetStyle, ref it
2638 //(this may happen for example in QButtonDialogBox which propagates its style)
2639 styleSheetStyle->ref();
2640 d->setStyle_helper(style, false);
2641 } else if (qt_styleSheet(d->extra->style) || !qApp->styleSheet().isEmpty()) {
2642 // if we have an application stylesheet or have a proxy already, propagate
2643 d->setStyle_helper(new QStyleSheetStyle(style), true);
2644 } else
2645#endif
2646 d->setStyle_helper(style, false);
2647}
2648
2649void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2650{
2651 Q_Q(QWidget);
2652 QStyle *oldStyle = q->style();
2653
2654 createExtra();
2655
2656#if QT_CONFIG(style_stylesheet)
2657 QPointer<QStyle> origStyle = extra->style;
2658#endif
2659 extra->style = newStyle;
2660
2661 // repolish
2662 if (polished) {
2663 oldStyle->unpolish(q);
2664 q->style()->polish(q);
2665 }
2666
2667 if (propagate) {
2668 // We copy the list because the order may be modified
2669 const QObjectList childrenList = children;
2670 for (int i = 0; i < childrenList.size(); ++i) {
2671 QWidget *c = qobject_cast<QWidget*>(childrenList.at(i));
2672 if (c)
2673 c->d_func()->inheritStyle();
2674 }
2675 }
2676
2677#if QT_CONFIG(style_stylesheet)
2678 if (!qt_styleSheet(newStyle)) {
2679 if (const QStyleSheetStyle* cssStyle = qt_styleSheet(origStyle)) {
2680 cssStyle->clearWidgetFont(q);
2681 }
2682 }
2683#endif
2684
2685 QEvent e(QEvent::StyleChange);
2686 QCoreApplication::sendEvent(q, &e);
2687
2688#if QT_CONFIG(style_stylesheet)
2689 // dereference the old stylesheet style
2690 if (QStyleSheetStyle *proxy = qt_styleSheet(origStyle))
2691 proxy->deref();
2692#endif
2693}
2694
2695// Inherits style from the current parent and propagates it as necessary
2696void QWidgetPrivate::inheritStyle()
2697{
2698#if QT_CONFIG(style_stylesheet)
2699 Q_Q(QWidget);
2700
2701 QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2702
2703 QStyleSheetStyle *proxy = qt_styleSheet(extraStyle);
2704
2705 if (!q->styleSheet().isEmpty()) {
2706 Q_ASSERT(proxy);
2707 proxy->repolish(q);
2708 return;
2709 }
2710 if (inheritStyleRecursionGuard)
2711 return;
2712 inheritStyleRecursionGuard = true;
2713 const auto resetGuard = qScopeGuard([&]() {
2714 inheritStyleRecursionGuard = false;
2715 });
2716
2717 QStyle *origStyle = proxy ? proxy->base : extraStyle;
2718 QWidget *parent = q->parentWidget();
2719 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : nullptr;
2720 // If we have stylesheet on app or parent has stylesheet style, we need
2721 // to be running a proxy
2722 if (!qApp->styleSheet().isEmpty() || qt_styleSheet(parentStyle)) {
2723 QStyle *newStyle = parentStyle;
2724 if (q->testAttribute(Qt::WA_SetStyle) && qt_styleSheet(origStyle) == nullptr)
2725 newStyle = new QStyleSheetStyle(origStyle);
2726 else if (auto *styleSheetStyle = qt_styleSheet(origStyle))
2727 newStyle = styleSheetStyle;
2728 else if (QStyleSheetStyle *newProxy = qt_styleSheet(parentStyle))
2729 newProxy->ref();
2730
2731 setStyle_helper(newStyle, true);
2732 return;
2733 }
2734
2735 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2736 // we just need our original style back
2737 if (origStyle == extraStyle) // is it any different?
2738 return;
2739
2740 // We could have inherited the proxy from our parent (which has a custom style)
2741 // In such a case we need to start following the application style (i.e revert
2742 // the propagation behavior of QStyleSheetStyle)
2743 if (!q->testAttribute(Qt::WA_SetStyle))
2744 origStyle = nullptr;
2745
2746 setStyle_helper(origStyle, true);
2747#endif // QT_NO_STYLE_STYLESHEET
2748}
2749
2750
2751/*!
2752 \fn bool QWidget::isWindow() const
2753
2754 Returns \c true if the widget is an independent window, otherwise
2755 returns \c false.
2756
2757 A window is a widget that isn't visually the child of any other
2758 widget and that usually has a frame and a
2759 \l{QWidget::setWindowTitle()}{window title}.
2760
2761 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2762 It will then be grouped with its parent and deleted when the
2763 parent is deleted, minimized when the parent is minimized etc. If
2764 supported by the window manager, it will also have a common
2765 taskbar entry with its parent.
2766
2767 QDialog and QMainWindow widgets are by default windows, even if a
2768 parent widget is specified in the constructor. This behavior is
2769 specified by the Qt::Window flag.
2770
2771 \sa window(), isModal(), parentWidget()
2772*/
2773
2774/*!
2775 \property QWidget::modal
2776 \brief whether the widget is a modal widget
2777
2778 This property only makes sense for windows. A modal widget
2779 prevents widgets in all other windows from getting any input.
2780
2781 By default, this property is \c false.
2782
2783 \sa isWindow(), windowModality, QDialog
2784*/
2785
2786/*!
2787 \property QWidget::windowModality
2788 \brief which windows are blocked by the modal widget
2789 \since 4.1
2790
2791 This property only makes sense for windows. A modal widget
2792 prevents widgets in other windows from getting input. The value of
2793 this property controls which windows are blocked when the widget
2794 is visible. Changing this property while the window is visible has
2795 no effect; you must hide() the widget first, then show() it again.
2796
2797 By default, this property is Qt::NonModal.
2798
2799 \sa isWindow(), QWidget::modal, QDialog
2800*/
2801
2802Qt::WindowModality QWidget::windowModality() const
2803{
2804 return static_cast<Qt::WindowModality>(data->window_modality);
2805}
2806
2807void QWidget::setWindowModality(Qt::WindowModality windowModality)
2808{
2809 data->window_modality = windowModality;
2810 // setModal_sys() will be called by setAttribute()
2811 setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
2812 setAttribute(Qt::WA_SetWindowModality, true);
2813}
2814
2815void QWidgetPrivate::setModal_sys()
2816{
2817 Q_Q(QWidget);
2818 if (q->windowHandle())
2819 q->windowHandle()->setModality(q->windowModality());
2820}
2821
2822/*!
2823 \fn bool QWidget::underMouse() const
2824
2825 Returns \c true if the widget is under the mouse cursor; otherwise
2826 returns \c false.
2827
2828 This value is not updated properly during drag and drop
2829 operations.
2830
2831 \sa enterEvent(), leaveEvent()
2832*/
2833
2834/*!
2835 \property QWidget::minimized
2836 \brief whether this widget is minimized (iconified)
2837
2838 This property is only relevant for windows.
2839
2840 By default, this property is \c false.
2841
2842 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2843*/
2844bool QWidget::isMinimized() const
2845{ return data->window_state & Qt::WindowMinimized; }
2846
2847/*!
2848 Shows the widget minimized, as an icon.
2849
2850 Calling this function only affects \l{isWindow()}{windows}.
2851
2852 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2853 isMinimized()
2854*/
2855void QWidget::showMinimized()
2856{
2857 bool isMin = isMinimized();
2858 if (isMin && isVisible())
2859 return;
2860
2861 ensurePolished();
2862
2863 if (!isMin)
2864 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2865 setVisible(true);
2866}
2867
2868/*!
2869 \property QWidget::maximized
2870 \brief whether this widget is maximized
2871
2872 This property is only relevant for windows.
2873
2874 \note Due to limitations on some window systems, this does not always
2875 report the expected results (e.g., if the user on X11 maximizes the
2876 window via the window manager, Qt has no way of distinguishing this
2877 from any other resize). This is expected to improve as window manager
2878 protocols evolve.
2879
2880 By default, this property is \c false.
2881
2882 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2883*/
2884bool QWidget::isMaximized() const
2885{ return data->window_state & Qt::WindowMaximized; }
2886
2887
2888
2889/*!
2890 Returns the current window state. The window state is a OR'ed
2891 combination of Qt::WindowState: Qt::WindowMinimized,
2892 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2893
2894 \sa Qt::WindowState, setWindowState()
2895 */
2896Qt::WindowStates QWidget::windowState() const
2897{
2898 return Qt::WindowStates(data->window_state);
2899}
2900
2901/*!\internal
2902
2903 The function sets the window state on child widgets similar to
2904 setWindowState(). The difference is that the window state changed
2905 event has the isOverride() flag set. It exists mainly to keep
2906 QWorkspace working.
2907 */
2908void QWidget::overrideWindowState(Qt::WindowStates newstate)
2909{
2910 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
2911 data->window_state = newstate;
2912 QCoreApplication::sendEvent(this, &e);
2913}
2914
2915/*!
2916 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
2917
2918 Sets the window state to \a windowState. The window state is a OR'ed
2919 combination of Qt::WindowState: Qt::WindowMinimized,
2920 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2921
2922 If the window is not visible (i.e. isVisible() returns \c false), the
2923 window state will take effect when show() is called. For visible
2924 windows, the change is immediate. For example, to toggle between
2925 full-screen and normal mode, use the following code:
2926
2927 \snippet code/src_gui_kernel_qwidget.cpp 0
2928
2929 To restore and activate a minimized window (while
2930 preserving its maximized and/or full-screen state), use the following:
2931
2932 \snippet code/src_gui_kernel_qwidget.cpp 1
2933
2934 Calling this function will hide the widget. You must call show() to make
2935 the widget visible again.
2936
2937 \note On some window systems Qt::WindowActive is not immediate, and may be
2938 ignored in certain cases.
2939
2940 When the window state changes, the widget receives a changeEvent()
2941 of type QEvent::WindowStateChange.
2942
2943 \sa Qt::WindowState, windowState()
2944*/
2945void QWidget::setWindowState(Qt::WindowStates newstate)
2946{
2947 Q_D(QWidget);
2948 Qt::WindowStates oldstate = windowState();
2949 if (newstate.testFlag(Qt::WindowMinimized)) // QTBUG-46763
2950 newstate.setFlag(Qt::WindowActive, false);
2951 if (oldstate == newstate)
2952 return;
2953 if (isWindow() && !testAttribute(Qt::WA_WState_Created))
2954 create();
2955
2956 data->window_state = newstate;
2957 data->in_set_window_state = 1;
2958 if (isWindow()) {
2959 // Ensure the initial size is valid, since we store it as normalGeometry below.
2960 if (!testAttribute(Qt::WA_Resized) && !isVisible())
2961 adjustSize();
2962
2963 d->createTLExtra();
2964 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
2965 d->topData()->normalGeometry = geometry();
2966
2967 Q_ASSERT(windowHandle());
2968 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
2969 }
2970 data->in_set_window_state = 0;
2971
2972 if (newstate & Qt::WindowActive)
2973 activateWindow();
2974
2975 QWindowStateChangeEvent e(oldstate);
2976 QCoreApplication::sendEvent(this, &e);
2977}
2978
2979/*!
2980 \property QWidget::fullScreen
2981 \brief whether the widget is shown in full screen mode
2982
2983 A widget in full screen mode occupies the whole screen area and does not
2984 display window decorations, such as a title bar.
2985
2986 By default, this property is \c false.
2987
2988 \sa windowState(), minimized, maximized
2989*/
2990bool QWidget::isFullScreen() const
2991{ return data->window_state & Qt::WindowFullScreen; }
2992
2993/*!
2994 Shows the widget in full-screen mode.
2995
2996 Calling this function only affects \l{isWindow()}{windows}.
2997
2998 To return from full-screen mode, call showNormal() or close().
2999
3000 \note Full-screen mode works fine under Windows, but has certain
3001 problems under X. These problems are due to limitations of the
3002 ICCCM protocol that specifies the communication between X11
3003 clients and the window manager. ICCCM simply does not understand
3004 the concept of non-decorated full-screen windows. Therefore, the
3005 best you can do is to request a borderless window and place and
3006 resize it to fill the entire screen. Depending on the window
3007 manager, this may or may not work. The borderless window is
3008 requested using MOTIF hints, which are at least partially
3009 supported by virtually all modern window managers.
3010
3011 An alternative would be to bypass the window manager entirely and
3012 create a window with the Qt::X11BypassWindowManagerHint flag. This
3013 has other severe problems though, like broken keyboard focus
3014 and very strange effects on desktop changes or when the user raises
3015 other windows.
3016
3017 X11 window managers that follow modern post-ICCCM specifications
3018 support full-screen mode properly.
3019
3020 On macOS, showing a window full screen puts the entire application in
3021 full-screen mode, providing it with a dedicated desktop. Showing another
3022 window while the application runs in full-screen mode might automatically
3023 make that window full screen as well. To prevent that, exit full-screen
3024 mode by calling showNormal() or by close() on the full screen window
3025 before showing another window.
3026
3027 \sa showNormal(), showMaximized(), show(), isVisible(), close()
3028*/
3029void QWidget::showFullScreen()
3030{
3031 ensurePolished();
3032
3033 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
3034 | Qt::WindowFullScreen);
3035 setVisible(true);
3036#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
3037 // activating it here before libscreen activates it causes problems
3038 activateWindow();
3039#endif
3040}
3041
3042/*!
3043 Shows the widget maximized.
3044
3045 Calling this function only affects \l{isWindow()}{windows}.
3046
3047 On X11, this function may not work properly with certain window
3048 managers. See the \l{Window Geometry} documentation for an explanation.
3049
3050 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3051*/
3052void QWidget::showMaximized()
3053{
3054 ensurePolished();
3055
3056 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3057 | Qt::WindowMaximized);
3058 setVisible(true);
3059}
3060
3061/*!
3062 Restores the widget after it has been maximized or minimized.
3063
3064 Calling this function only affects \l{isWindow()}{windows}.
3065
3066 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3067*/
3068void QWidget::showNormal()
3069{
3070 ensurePolished();
3071
3072 setWindowState(windowState() & ~(Qt::WindowMinimized
3073 | Qt::WindowMaximized
3074 | Qt::WindowFullScreen));
3075 setVisible(true);
3076}
3077
3078/*!
3079 Returns \c true if this widget would become enabled if \a ancestor is
3080 enabled; otherwise returns \c false.
3081
3082
3083
3084 This is the case if neither the widget itself nor every parent up
3085 to but excluding \a ancestor has been explicitly disabled.
3086
3087 isEnabledTo(0) returns false if this widget or any if its ancestors
3088 was explicitly disabled.
3089
3090 The word ancestor here means a parent widget within the same window.
3091
3092 Therefore isEnabledTo(0) stops at this widget's window, unlike
3093 isEnabled() which also takes parent windows into considerations.
3094
3095 \sa setEnabled(), enabled
3096*/
3097
3098bool QWidget::isEnabledTo(const QWidget *ancestor) const
3099{
3100 const QWidget * w = this;
3101 while (!w->testAttribute(Qt::WA_ForceDisabled)
3102 && !w->isWindow()
3103 && w->parentWidget()
3104 && w->parentWidget() != ancestor)
3105 w = w->parentWidget();
3106 return !w->testAttribute(Qt::WA_ForceDisabled);
3107}
3108
3109#ifndef QT_NO_ACTION
3110/*!
3111 Appends the action \a action to this widget's list of actions.
3112
3113 All QWidgets have a list of \l{QAction}s. However, they can be
3114 represented graphically in many different ways. The default use of
3115 the QAction list (as returned by actions()) is to create a context
3116 QMenu.
3117
3118 A QWidget should only have one of each action and adding an action
3119 it already has will not cause the same action to be in the widget twice.
3120
3121 The ownership of \a action is not transferred to this QWidget.
3122
3123 \sa removeAction(), insertAction(), actions(), QMenu
3124*/
3125void QWidget::addAction(QAction *action)
3126{
3127 insertAction(nullptr, action);
3128}
3129
3130/*!
3131 Appends the actions \a actions to this widget's list of actions.
3132
3133 \sa removeAction(), QMenu, addAction()
3134*/
3135void QWidget::addActions(const QList<QAction *> &actions)
3136{
3137 for(int i = 0; i < actions.size(); i++)
3138 insertAction(nullptr, actions.at(i));
3139}
3140
3141/*!
3142 Inserts the action \a action to this widget's list of actions,
3143 before the action \a before. It appends the action if \a before is \nullptr or
3144 \a before is not a valid action for this widget.
3145
3146 A QWidget should only have one of each action.
3147
3148 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3149*/
3150void QWidget::insertAction(QAction *before, QAction *action)
3151{
3152 if (Q_UNLIKELY(!action)) {
3153 qWarning("QWidget::insertAction: Attempt to insert null action");
3154 return;
3155 }
3156
3157 Q_D(QWidget);
3158 if (d->actions.contains(action))
3159 removeAction(action);
3160
3161 int pos = d->actions.indexOf(before);
3162 if (pos < 0) {
3163 before = nullptr;
3164 pos = d->actions.size();
3165 }
3166 d->actions.insert(pos, action);
3167
3168 QActionPrivate *apriv = action->d_func();
3169 apriv->associatedObjects.append(this);
3170
3171 QActionEvent e(QEvent::ActionAdded, action, before);
3172 QCoreApplication::sendEvent(this, &e);
3173}
3174
3175/*!
3176 Inserts the actions \a actions to this widget's list of actions,
3177 before the action \a before. It appends the action if \a before is \nullptr or
3178 \a before is not a valid action for this widget.
3179
3180 A QWidget can have at most one of each action.
3181
3182 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3183*/
3184void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3185{
3186 for(int i = 0; i < actions.size(); ++i)
3187 insertAction(before, actions.at(i));
3188}
3189
3190/*!
3191 Removes the action \a action from this widget's list of actions.
3192 \sa insertAction(), actions(), insertAction()
3193*/
3194void QWidget::removeAction(QAction *action)
3195{
3196 if (!action)
3197 return;
3198
3199 Q_D(QWidget);
3200
3201 QActionPrivate *apriv = action->d_func();
3202 apriv->associatedObjects.removeAll(this);
3203
3204 if (d->actions.removeAll(action)) {
3205 QActionEvent e(QEvent::ActionRemoved, action);
3206 QCoreApplication::sendEvent(this, &e);
3207 }
3208}
3209
3210/*!
3211 Returns the (possibly empty) list of this widget's actions.
3212
3213 \sa contextMenuPolicy, insertAction(), removeAction()
3214*/
3215QList<QAction*> QWidget::actions() const
3216{
3217 Q_D(const QWidget);
3218 return d->actions;
3219}
3220
3221/*!
3222 \fn QAction *QWidget::addAction(const QString &text);
3223 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut);
3224 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text);
3225 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut);
3226
3227 \since 6.3
3228
3229 These convenience functions create a new action with text \a text,
3230 icon \a icon and shortcut \a shortcut, if any.
3231
3232 The functions add the newly created action to the widget's
3233 list of actions, and return it.
3234
3235 QWidget takes ownership of the returned QAction.
3236*/
3237QAction *QWidget::addAction(const QString &text)
3238{
3239 QAction *ret = new QAction(text, this);
3240 addAction(ret);
3241 return ret;
3242}
3243
3244QAction *QWidget::addAction(const QIcon &icon, const QString &text)
3245{
3246 QAction *ret = new QAction(icon, text, this);
3247 addAction(ret);
3248 return ret;
3249}
3250
3251#if QT_CONFIG(shortcut)
3252QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut)
3253{
3254 QAction *ret = addAction(text);
3255 ret->setShortcut(shortcut);
3256 return ret;
3257}
3258
3259QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut)
3260{
3261 QAction *ret = addAction(icon, text);
3262 ret->setShortcut(shortcut);
3263 return ret;
3264}
3265#endif
3266
3267/*!
3268 \fn QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3269 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3270 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3271 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3272
3273 \overload
3274 \since 6.3
3275
3276 This convenience function creates a new action with the text \a
3277 text, icon \a icon, and shortcut \a shortcut, if any.
3278
3279 The action's \l{QAction::triggered()}{triggered()} signal is connected
3280 to the \a receiver's \a member slot. The function adds the newly created
3281 action to the widget's list of actions and returns it.
3282
3283 QWidget takes ownership of the returned QAction.
3284*/
3285QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member,
3286 Qt::ConnectionType type)
3287{
3288 QAction *action = addAction(text);
3289 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member, type);
3290 return action;
3291}
3292
3293QAction *QWidget::addAction(const QIcon &icon, const QString &text,
3294 const QObject *receiver, const char* member,
3295 Qt::ConnectionType type)
3296{
3297 QAction *action = addAction(icon, text);
3298 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member, type);
3299 return action;
3300}
3301
3302#if QT_CONFIG(shortcut)
3303QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut,
3304 const QObject *receiver, const char* member,
3305 Qt::ConnectionType type)
3306{
3307 QAction *action = addAction(text, receiver, member, type);
3308 action->setShortcut(shortcut);
3309 return action;
3310}
3311
3312QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut,
3313 const QObject *receiver, const char* member,
3314 Qt::ConnectionType type)
3315{
3316 QAction *action = addAction(icon, text, receiver, member, type);
3317 action->setShortcut(shortcut);
3318 return action;
3319}
3320#endif // QT_CONFIG(shortcut)
3321
3322/*!
3323 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, Args&&...args)
3324 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, Args&&...args)
3325 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, Args&&...args)
3326 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, Args&&...args)
3327
3328 \since 6.3
3329 \overload
3330
3331 These convenience functions create a new action with the text \a text,
3332 icon \a icon, and shortcut \a shortcut, if any.
3333
3334 The action's \l{QAction::triggered()}{triggered()} signal is connected
3335 as if by a call to QObject::connect(action, &QAction::triggered, args...),
3336 perfectly forwarding \a args, including a possible Qt::ConnectionType.
3337
3338 The function adds the newly created action to the widget's list of
3339 actions and returns it.
3340
3341 QWidget takes ownership of the returned QAction.
3342*/
3343#endif // QT_NO_ACTION
3344
3345/*!
3346 \property QWidget::enabled
3347 \brief whether the widget is enabled
3348
3349 In general an enabled widget handles keyboard and mouse events; a disabled
3350 widget does not. An exception is made with \l{QAbstractButton}.
3351
3352 Some widgets display themselves differently when they are
3353 disabled. For example a button might draw its label grayed out. If
3354 your widget needs to know when it becomes enabled or disabled, you
3355 can use the changeEvent() with type QEvent::EnabledChange.
3356
3357 Disabling a widget implicitly disables all its children. Enabling
3358 respectively enables all child widgets unless they have been
3359 explicitly disabled. It it not possible to explicitly enable a child
3360 widget which is not a window while its parent widget remains disabled.
3361
3362 By default, this property is \c true.
3363
3364 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3365*/
3366void QWidget::setEnabled(bool enable)
3367{
3368 Q_D(QWidget);
3369
3370#if QT_CONFIG(accessibility)
3371 const bool wasEnabled = !testAttribute(Qt::WA_ForceDisabled);
3372#endif
3373
3374 setAttribute(Qt::WA_ForceDisabled, !enable);
3375 d->setEnabled_helper(enable);
3376
3377#if QT_CONFIG(accessibility)
3378 // A widget is enabled if it's parent and itself is enabled.
3379 // We do not send state changed events recursively. It is up
3380 // to the receiver of the events to check children if required.
3381 if (QAccessible::isActive() && wasEnabled != enable) {
3382 QAccessible::State states;
3383 states.disabled = 1;
3384 QAccessibleStateChangeEvent scEvent(this, states);
3385 QAccessible::updateAccessibility(&scEvent);
3386 }
3387#endif
3388}
3389
3390void QWidgetPrivate::setEnabled_helper(bool enable)
3391{
3392 Q_Q(QWidget);
3393
3394 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3395 return; // nothing we can do
3396
3397 if (enable != q->testAttribute(Qt::WA_Disabled))
3398 return; // nothing to do
3399
3400 q->setAttribute(Qt::WA_Disabled, !enable);
3401 updateSystemBackground();
3402
3403 if (!enable && q->window()->focusWidget() == q) {
3404 bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3405 if (!parentIsEnabled || !q->focusNextChild())
3406 q->clearFocus();
3407 }
3408
3409 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3410 for (int i = 0; i < children.size(); ++i) {
3411 QWidget *w = qobject_cast<QWidget *>(children.at(i));
3412 if (w && !w->testAttribute(attribute))
3413 w->d_func()->setEnabled_helper(enable);
3414 }
3415#ifndef QT_NO_CURSOR
3416 if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3417 // enforce the windows behavior of clearing the cursor on
3418 // disabled widgets
3419 qt_qpa_set_cursor(q, false);
3420 }
3421#endif
3422#ifndef QT_NO_IM
3423 if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3424 QWidget *focusWidget = effectiveFocusWidget();
3425
3426 if (enable) {
3427 if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
3428 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3429 } else {
3430 QGuiApplication::inputMethod()->commit();
3431 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3432 }
3433 }
3434#endif //QT_NO_IM
3435 QEvent e(QEvent::EnabledChange);
3436 QCoreApplication::sendEvent(q, &e);
3437}
3438
3439/*!
3440 \property QWidget::acceptDrops
3441 \brief whether drop events are enabled for this widget
3442
3443 Setting this property to true announces to the system that this
3444 widget \e may be able to accept drop events.
3445
3446 \warning Do not modify this property in a drag and drop event handler.
3447
3448 By default, this property is \c false.
3449
3450 \sa {Drag and Drop in Qt}{Drag and Drop}
3451*/
3452bool QWidget::acceptDrops() const
3453{
3454 return testAttribute(Qt::WA_AcceptDrops);
3455}
3456
3457void QWidget::setAcceptDrops(bool on)
3458{
3459 setAttribute(Qt::WA_AcceptDrops, on);
3460
3461}
3462
3463/*!
3464 Disables widget input events if \a disable is true; otherwise
3465 enables input events.
3466
3467 See the \l enabled documentation for more information.
3468
3469 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3470*/
3471void QWidget::setDisabled(bool disable)
3472{
3473 setEnabled(!disable);
3474}
3475
3476/*!
3477 \property QWidget::frameGeometry
3478 \brief geometry of the widget relative to its parent including any
3479 window frame
3480
3481 See the \l{Window Geometry} documentation for an overview of geometry
3482 issues with windows.
3483
3484 By default, this property contains a value that depends on the user's
3485 platform and screen geometry.
3486
3487 \sa geometry(), x(), y(), pos()
3488*/
3489QRect QWidget::frameGeometry() const
3490{
3491 Q_D(const QWidget);
3492 if (isWindow() && ! (windowType() == Qt::Popup)) {
3493 QRect fs = d->frameStrut();
3494 return QRect(data->crect.x() - fs.left(),
3495 data->crect.y() - fs.top(),
3496 data->crect.width() + fs.left() + fs.right(),
3497 data->crect.height() + fs.top() + fs.bottom());
3498 }
3499 return data->crect;
3500}
3501
3502/*!
3503 \property QWidget::x
3504
3505 \brief the x coordinate of the widget relative to its parent including
3506 any window frame
3507
3508 See the \l{Window Geometry} documentation for an overview of geometry
3509 issues with windows.
3510
3511 By default, this property has a value of 0.
3512
3513 \sa frameGeometry, y, pos
3514*/
3515int QWidget::x() const
3516{
3517 Q_D(const QWidget);
3518 if (isWindow() && ! (windowType() == Qt::Popup))
3519 return data->crect.x() - d->frameStrut().left();
3520 return data->crect.x();
3521}
3522
3523/*!
3524 \property QWidget::y
3525 \brief the y coordinate of the widget relative to its parent and
3526 including any window frame
3527
3528 See the \l{Window Geometry} documentation for an overview of geometry
3529 issues with windows.
3530
3531 By default, this property has a value of 0.
3532
3533 \sa frameGeometry, x, pos
3534*/
3535int QWidget::y() const
3536{
3537 Q_D(const QWidget);
3538 if (isWindow() && ! (windowType() == Qt::Popup))
3539 return data->crect.y() - d->frameStrut().top();
3540 return data->crect.y();
3541}
3542
3543/*!
3544 \property QWidget::pos
3545 \brief the position of the widget within its parent widget
3546
3547 If the widget is a window, the position is that of the widget on
3548 the desktop, including its frame.
3549
3550 When changing the position, the widget, if visible, receives a
3551 move event (moveEvent()) immediately. If the widget is not
3552 currently visible, it is guaranteed to receive an event before it
3553 is shown.
3554
3555 By default, this property contains a position that refers to the
3556 origin.
3557
3558 \warning Calling move() or setGeometry() inside moveEvent() can
3559 lead to infinite recursion.
3560
3561 See the \l{Window Geometry} documentation for an overview of geometry
3562 issues with windows.
3563
3564 \note Not all windowing systems support setting or querying top level window positions.
3565 On such a system, programmatically moving windows may not have any effect, and artificial
3566 values may be returned for the current positions, such as \c QPoint(0, 0).
3567
3568 \sa frameGeometry, size, x(), y()
3569*/
3570QPoint QWidget::pos() const
3571{
3572 Q_D(const QWidget);
3573 QPoint result = data->crect.topLeft();
3574 if (isWindow() && ! (windowType() == Qt::Popup))
3575 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3576 result -= d->frameStrut().topLeft();
3577 return result;
3578}
3579
3580/*!
3581 \property QWidget::geometry
3582 \brief the geometry of the widget relative to its parent and
3583 excluding the window frame
3584
3585 If the widget is a top-level widget (a window) its geometry is
3586 given in global screen coordinates.
3587
3588 When changing the geometry, the widget, if visible, receives a
3589 move event (moveEvent()) and/or a resize event (resizeEvent())
3590 immediately. If the widget is not currently visible, it is
3591 guaranteed to receive appropriate events before it is shown.
3592
3593 The size component is adjusted if it lies outside the range
3594 defined by minimumSize() and maximumSize().
3595
3596 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3597 can lead to infinite recursion.
3598
3599 See the \l{Window Geometry} documentation for an overview of geometry
3600 issues with windows.
3601
3602 By default, this property contains a value that depends on the user's
3603 platform and screen geometry.
3604
3605 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3606 resizeEvent(), minimumSize(), maximumSize()
3607*/
3608
3609/*!
3610 \property QWidget::size
3611 \brief the size of the widget excluding any window frame
3612
3613 If the widget is visible when it is being resized, it receives a resize event
3614 (resizeEvent()) immediately. If the widget is not currently
3615 visible, it is guaranteed to receive an event before it is shown.
3616
3617 The size is adjusted if it lies outside the range defined by
3618 minimumSize() and maximumSize().
3619
3620 By default, this property contains a value that depends on the user's
3621 platform and screen geometry.
3622
3623 \warning Calling resize() or setGeometry() inside resizeEvent() can
3624 lead to infinite recursion.
3625
3626 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3627 appear on screen. This also applies to windows.
3628
3629 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3630*/
3631
3632/*!
3633 \property QWidget::width
3634 \brief the width of the widget excluding any window frame
3635
3636 See the \l{Window Geometry} documentation for an overview of geometry
3637 issues with windows.
3638
3639 \note Do not use this function to find the width of a screen on
3640 a multi-screen desktop. See QScreen for details.
3641
3642 By default, this property contains a value that depends on the user's
3643 platform and screen geometry.
3644
3645 \sa geometry, height, size
3646*/
3647
3648/*!
3649 \property QWidget::height
3650 \brief the height of the widget excluding any window frame
3651
3652 See the \l{Window Geometry} documentation for an overview of geometry
3653 issues with windows.
3654
3655 By default, this property contains a value that depends on the user's
3656 platform and \l{QScreen::geometry}{screen geometry}.
3657
3658 \sa geometry, width, size
3659*/
3660
3661/*!
3662 \property QWidget::rect
3663 \brief the internal geometry of the widget excluding any window
3664 frame
3665
3666 The rect property equals QRect(0, 0, width(), height()).
3667
3668 See the \l{Window Geometry} documentation for an overview of geometry
3669 issues with windows.
3670
3671 By default, this property contains a value that depends on the user's
3672 platform and screen geometry.
3673
3674 \sa size
3675*/
3676
3677/*!
3678 \property QWidget::normalGeometry
3679
3680 \brief the geometry of the widget as it will appear when shown as
3681 a normal (not maximized or full screen) top-level widget
3682
3683 If the widget is already in this state the normal geometry will
3684 reflect the widget's current geometry().
3685
3686 For child widgets this property always holds an empty rectangle.
3687
3688 By default, this property contains an empty rectangle.
3689
3690 \sa QWidget::windowState(), QWidget::geometry
3691*/
3692QRect QWidget::normalGeometry() const
3693{
3694 Q_D(const QWidget);
3695 if (!isWindow())
3696 return QRect();
3697
3698 if (!isMaximized() && !isFullScreen())
3699 return geometry();
3700
3701 return d->topData()->normalGeometry;
3702}
3703
3704
3705/*!
3706 \property QWidget::childrenRect
3707 \brief the bounding rectangle of the widget's children
3708
3709 Hidden children are excluded.
3710
3711 By default, for a widget with no children, this property contains a
3712 rectangle with zero width and height located at the origin.
3713
3714 \sa childrenRegion(), geometry()
3715*/
3716
3717QRect QWidget::childrenRect() const
3718{
3719 Q_D(const QWidget);
3720 QRect r(0, 0, 0, 0);
3721 for (int i = 0; i < d->children.size(); ++i) {
3722 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3723 if (w && !w->isWindow() && !w->isHidden())
3724 r |= w->geometry();
3725 }
3726 return r;
3727}
3728
3729/*!
3730 \property QWidget::childrenRegion
3731 \brief the combined region occupied by the widget's children
3732
3733 Hidden children are excluded.
3734
3735 By default, for a widget with no children, this property contains an
3736 empty region.
3737
3738 \sa childrenRect(), geometry(), mask()
3739*/
3740
3741QRegion QWidget::childrenRegion() const
3742{
3743 Q_D(const QWidget);
3744 QRegion r;
3745 for (int i = 0; i < d->children.size(); ++i) {
3746 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3747 if (w && !w->isWindow() && !w->isHidden()) {
3748 QRegion mask = w->mask();
3749 if (mask.isEmpty())
3750 r |= w->geometry();
3751 else
3752 r |= mask.translated(w->pos());
3753 }
3754 }
3755 return r;
3756}
3757
3758
3759/*!
3760 \property QWidget::minimumSize
3761 \brief the widget's minimum size
3762
3763 The widget cannot be resized to a smaller size than the minimum
3764 widget size. The widget's size is forced to the minimum size if
3765 the current size is smaller.
3766
3767 The minimum size set by this function will override the minimum size
3768 defined by QLayout. To unset the minimum size, use a
3769 value of \c{QSize(0, 0)}.
3770
3771 By default, this property contains a size with zero width and height.
3772
3773 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3774*/
3775
3776QSize QWidget::minimumSize() const
3777{
3778 Q_D(const QWidget);
3779 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3780}
3781
3782/*!
3783 \property QWidget::maximumSize
3784 \brief the widget's maximum size in pixels
3785
3786 The widget cannot be resized to a larger size than the maximum
3787 widget size.
3788
3789 By default, this property contains a size in which both width and height
3790 have values of 16777215.
3791
3792 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3793 of widgets.
3794
3795 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3796*/
3797
3798QSize QWidget::maximumSize() const
3799{
3800 Q_D(const QWidget);
3801 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3803}
3804
3805
3806/*!
3807 \property QWidget::minimumWidth
3808 \brief the widget's minimum width in pixels
3809
3810 This property corresponds to the width held by the \l minimumSize property.
3811
3812 By default, this property has a value of 0.
3813
3814 \sa minimumSize, minimumHeight
3815*/
3816
3817/*!
3818 \property QWidget::minimumHeight
3819 \brief the widget's minimum height in pixels
3820
3821 This property corresponds to the height held by the \l minimumSize property.
3822
3823 By default, this property has a value of 0.
3824
3825 \sa minimumSize, minimumWidth
3826*/
3827
3828/*!
3829 \property QWidget::maximumWidth
3830 \brief the widget's maximum width in pixels
3831
3832 This property corresponds to the width held by the \l maximumSize property.
3833
3834 By default, this property contains a value of 16777215.
3835
3836 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3837 of widgets.
3838
3839 \sa maximumSize, maximumHeight
3840*/
3841
3842/*!
3843 \property QWidget::maximumHeight
3844 \brief the widget's maximum height in pixels
3845
3846 This property corresponds to the height held by the \l maximumSize property.
3847
3848 By default, this property contains a value of 16777215.
3849
3850 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3851 of widgets.
3852
3853 \sa maximumSize, maximumWidth
3854*/
3855
3856/*!
3857 \property QWidget::sizeIncrement
3858 \brief the size increment of the widget
3859
3860 When the user resizes the window, the size will move in steps of
3861 sizeIncrement().width() pixels horizontally and
3862 sizeIncrement.height() pixels vertically, with baseSize() as the
3863 basis. Preferred widget sizes are for non-negative integers \e i
3864 and \e j:
3865 \snippet code/src_gui_kernel_qwidget.cpp 2
3866
3867 Note that while you can set the size increment for all widgets, it
3868 only affects windows.
3869
3870 By default, this property contains a size with zero width and height.
3871
3872 \warning The size increment has no effect under Windows, and may
3873 be disregarded by the window manager on X11.
3874
3875 \sa size, minimumSize, maximumSize
3876*/
3877QSize QWidget::sizeIncrement() const
3878{
3879 Q_D(const QWidget);
3880 return (d->extra && d->extra->topextra)
3881 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3882 : QSize(0, 0);
3883}
3884
3885/*!
3886 \property QWidget::baseSize
3887 \brief the base size of the widget
3888
3889 The base size is used to calculate a proper widget size if the
3890 widget defines sizeIncrement().
3891
3892 By default, for a newly-created widget, this property contains a size with
3893 zero width and height.
3894
3895 \sa setSizeIncrement()
3896*/
3897
3898QSize QWidget::baseSize() const
3899{
3900 Q_D(const QWidget);
3901 return (d->extra && d->extra->topextra)
3902 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3903 : QSize(0, 0);
3904}
3905
3906bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3907{
3908 Q_Q(QWidget);
3909
3910 int mw = minw, mh = minh;
3911 if (mw == QWIDGETSIZE_MAX)
3912 mw = 0;
3913 if (mh == QWIDGETSIZE_MAX)
3914 mh = 0;
3915 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3916 qWarning("QWidget::setMinimumSize: (%s/%s) "
3917 "The largest allowed size is (%d,%d)",
3918 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3920 minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX);
3921 minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX);
3922 }
3923 if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3924 qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3925 "are not possible",
3926 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3927 minw = mw = qMax(minw, 0);
3928 minh = mh = qMax(minh, 0);
3929 }
3930 createExtra();
3931 if (extra->minw == mw && extra->minh == mh)
3932 return false;
3933 extra->minw = mw;
3934 extra->minh = mh;
3935 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3936 return true;
3937}
3938
3939void QWidgetPrivate::setConstraints_sys()
3940{
3941 Q_Q(QWidget);
3942 if (extra && q->windowHandle()) {
3943 QWindow *win = q->windowHandle();
3944 QWindowPrivate *winp = qt_window_private(win);
3945
3946 winp->minimumSize = QSize(extra->minw, extra->minh);
3947 winp->maximumSize = QSize(extra->maxw, extra->maxh);
3948
3949 if (extra->topextra) {
3950 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3951 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3952 }
3953
3954 if (winp->platformWindow) {
3955 fixPosIncludesFrame();
3956 winp->platformWindow->propagateSizeHints();
3957 }
3958 }
3959}
3960
3961/*!
3962 \overload
3963
3964 This function corresponds to setMinimumSize(QSize(minw, minh)).
3965 Sets the minimum width to \a minw and the minimum height to \a
3966 minh.
3967*/
3968
3969void QWidget::setMinimumSize(int minw, int minh)
3970{
3971 Q_D(QWidget);
3972 if (!d->setMinimumSize_helper(minw, minh))
3973 return;
3974
3975 if (isWindow())
3976 d->setConstraints_sys();
3977 if (minw > width() || minh > height()) {
3978 bool resized = testAttribute(Qt::WA_Resized);
3979 bool maximized = isMaximized();
3980 resize(qMax(minw,width()), qMax(minh,height()));
3981 setAttribute(Qt::WA_Resized, resized); //not a user resize
3982 if (maximized)
3983 data->window_state = data->window_state | Qt::WindowMaximized;
3984 }
3985#if QT_CONFIG(graphicsview)
3986 if (d->extra) {
3987 if (d->extra->proxyWidget)
3988 d->extra->proxyWidget->setMinimumSize(minw, minh);
3989 }
3990#endif
3991 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
3992}
3993
3994bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
3995{
3996 Q_Q(QWidget);
3997 if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
3998 qWarning("QWidget::setMaximumSize: (%s/%s) "
3999 "The largest allowed size is (%d,%d)",
4000 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
4002 maxw = qMin<int>(maxw, QWIDGETSIZE_MAX);
4003 maxh = qMin<int>(maxh, QWIDGETSIZE_MAX);
4004 }
4005 if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
4006 qWarning("QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
4007 "are not possible",
4008 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
4009 maxw = qMax(maxw, 0);
4010 maxh = qMax(maxh, 0);
4011 }
4012 createExtra();
4013 if (extra->maxw == maxw && extra->maxh == maxh)
4014 return false;
4015 extra->maxw = maxw;
4016 extra->maxh = maxh;
4017 extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
4018 (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
4019 return true;
4020}
4021
4022/*!
4023 \overload
4024
4025 This function corresponds to setMaximumSize(QSize(\a maxw, \a
4026 maxh)). Sets the maximum width to \a maxw and the maximum height
4027 to \a maxh.
4028*/
4029void QWidget::setMaximumSize(int maxw, int maxh)
4030{
4031 Q_D(QWidget);
4032 if (!d->setMaximumSize_helper(maxw, maxh))
4033 return;
4034
4035 if (isWindow())
4036 d->setConstraints_sys();
4037 if (maxw < width() || maxh < height()) {
4038 bool resized = testAttribute(Qt::WA_Resized);
4039 resize(qMin(maxw,width()), qMin(maxh,height()));
4040 setAttribute(Qt::WA_Resized, resized); //not a user resize
4041 }
4042
4043#if QT_CONFIG(graphicsview)
4044 if (d->extra) {
4045 if (d->extra->proxyWidget)
4046 d->extra->proxyWidget->setMaximumSize(maxw, maxh);
4047 }
4048#endif
4049
4050 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4051}
4052
4053/*!
4054 \overload
4055
4056 Sets the x (width) size increment to \a w and the y (height) size
4057 increment to \a h.
4058*/
4059void QWidget::setSizeIncrement(int w, int h)
4060{
4061 Q_D(QWidget);
4062 d->createTLExtra();
4063 QTLWExtra* x = d->topData();
4064 if (x->incw == w && x->inch == h)
4065 return;
4066 x->incw = w;
4067 x->inch = h;
4068 if (isWindow())
4069 d->setConstraints_sys();
4070}
4071
4072/*!
4073 \overload
4074
4075 This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
4076 the widgets base size to width \a basew and height \a baseh.
4077*/
4078void QWidget::setBaseSize(int basew, int baseh)
4079{
4080 Q_D(QWidget);
4081 d->createTLExtra();
4082 QTLWExtra* x = d->topData();
4083 if (x->basew == basew && x->baseh == baseh)
4084 return;
4085 x->basew = basew;
4086 x->baseh = baseh;
4087 if (isWindow())
4088 d->setConstraints_sys();
4089}
4090
4091/*!
4092 Sets both the minimum and maximum sizes of the widget to \a s,
4093 thereby preventing it from ever growing or shrinking.
4094
4095 This will override the default size constraints set by QLayout.
4096
4097 To remove constraints, set the size to QWIDGETSIZE_MAX.
4098
4099 Alternatively, if you want the widget to have a
4100 fixed size based on its contents, you can call
4101 QLayout::setSizeConstraint(QLayout::SetFixedSize);
4102
4103 \sa maximumSize, minimumSize
4104*/
4105
4106void QWidget::setFixedSize(const QSize & s)
4107{
4108 setFixedSize(s.width(), s.height());
4109}
4110
4111
4112/*!
4113 \fn void QWidget::setFixedSize(int w, int h)
4114 \overload
4115
4116 Sets the width of the widget to \a w and the height to \a h.
4117*/
4118
4119void QWidget::setFixedSize(int w, int h)
4120{
4121 Q_D(QWidget);
4122 bool minSizeSet = d->setMinimumSize_helper(w, h);
4123 bool maxSizeSet = d->setMaximumSize_helper(w, h);
4124 if (!minSizeSet && !maxSizeSet)
4125 return;
4126
4127 if (isWindow())
4128 d->setConstraints_sys();
4129 else
4130 d->updateGeometry_helper(true);
4131
4132 if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
4133 resize(w, h);
4134}
4135
4136void QWidget::setMinimumWidth(int w)
4137{
4138 Q_D(QWidget);
4139 d->createExtra();
4140 uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
4141 setMinimumSize(w, minimumSize().height());
4142 d->extra->explicitMinSize = expl;
4143}
4144
4145void QWidget::setMinimumHeight(int h)
4146{
4147 Q_D(QWidget);
4148 d->createExtra();
4149 uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
4150 setMinimumSize(minimumSize().width(), h);
4151 d->extra->explicitMinSize = expl;
4152}
4153
4154void QWidget::setMaximumWidth(int w)
4155{
4156 Q_D(QWidget);
4157 d->createExtra();
4158 uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
4159 setMaximumSize(w, maximumSize().height());
4160 d->extra->explicitMaxSize = expl;
4161}
4162
4163void QWidget::setMaximumHeight(int h)
4164{
4165 Q_D(QWidget);
4166 d->createExtra();
4167 uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
4168 setMaximumSize(maximumSize().width(), h);
4169 d->extra->explicitMaxSize = expl;
4170}
4171
4172/*!
4173 Sets both the minimum and maximum width of the widget to \a w
4174 without changing the heights. Provided for convenience.
4175
4176 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4177*/
4178
4179void QWidget::setFixedWidth(int w)
4180{
4181 Q_D(QWidget);
4182 d->createExtra();
4183 uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4184 uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4185 setMinimumSize(w, minimumSize().height());
4186 setMaximumSize(w, maximumSize().height());
4187 d->extra->explicitMinSize = explMin;
4188 d->extra->explicitMaxSize = explMax;
4189}
4190
4191
4192/*!
4193 Sets both the minimum and maximum heights of the widget to \a h
4194 without changing the widths. Provided for convenience.
4195
4196 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4197*/
4198
4199void QWidget::setFixedHeight(int h)
4200{
4201 Q_D(QWidget);
4202 d->createExtra();
4203 uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4204 uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4205 setMinimumSize(minimumSize().width(), h);
4206 setMaximumSize(maximumSize().width(), h);
4207 d->extra->explicitMinSize = explMin;
4208 d->extra->explicitMaxSize = explMax;
4209}
4210
4211
4212/*!
4213 Translates the widget coordinate \a pos to the coordinate system
4214 of \a parent. The \a parent must not be \nullptr and must be a parent
4215 of the calling widget.
4216
4217 \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4218 \since 6.0
4219*/
4220
4221QPointF QWidget::mapTo(const QWidget *parent, const QPointF &pos) const
4222{
4223 QPointF p = pos;
4224 if (parent) {
4225 const QWidget * w = this;
4226 while (w != parent) {
4227 p = w->mapToParent(p);
4228 w = w->parentWidget();
4229 if (!w) {
4230 qWarning("QWidget::mapTo(): parent must be in parent hierarchy");
4231 break;
4232 }
4233 }
4234 }
4235 return p;
4236}
4237
4238/*!
4239 \overload
4240*/
4241QPoint QWidget::mapTo(const QWidget *parent, const QPoint &pos) const
4242{
4243 return mapTo(parent, QPointF(pos)).toPoint();
4244}
4245
4246/*!
4247 Translates the widget coordinate \a pos from the coordinate system
4248 of \a parent to this widget's coordinate system. The \a parent
4249 must not be \nullptr and must be a parent of the calling widget.
4250
4251 \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4252 \since 6.0
4253*/
4254
4255QPointF QWidget::mapFrom(const QWidget *parent, const QPointF &pos) const
4256{
4257 QPointF p(pos);
4258 if (parent) {
4259 const QWidget * w = this;
4260 while (w != parent) {
4261 p = w->mapFromParent(p);
4262 w = w->parentWidget();
4263 if (!w) {
4264 qWarning("QWidget::mapFrom(): parent must be in parent hierarchy");
4265 break;
4266 }
4267 }
4268 }
4269 return p;
4270}
4271
4272/*!
4273 \overload
4274*/
4275QPoint QWidget::mapFrom(const QWidget *parent, const QPoint &pos) const
4276{
4277 return mapFrom(parent, QPointF(pos)).toPoint();
4278}
4279
4280/*!
4281 Translates the widget coordinate \a pos to a coordinate in the
4282 parent widget.
4283
4284 Same as mapToGlobal() if the widget has no parent.
4285
4286 \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4287 \since 6.0
4288*/
4289
4290QPointF QWidget::mapToParent(const QPointF &pos) const
4291{
4292 return pos + QPointF(data->crect.topLeft());
4293}
4294
4295/*!
4296 \overload
4297*/
4298QPoint QWidget::mapToParent(const QPoint &pos) const
4299{
4300 return pos + data->crect.topLeft();
4301}
4302
4303/*!
4304 Translates the parent widget coordinate \a pos to widget
4305 coordinates.
4306
4307 Same as mapFromGlobal() if the widget has no parent.
4308
4309 \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4310 \since 6.0
4311*/
4312
4313QPointF QWidget::mapFromParent(const QPointF &pos) const
4314{
4315 return pos - QPointF(data->crect.topLeft());
4316}
4317
4318/*!
4319 \overload
4320*/
4321QPoint QWidget::mapFromParent(const QPoint &pos) const
4322{
4323 return pos - data->crect.topLeft();
4324}
4325
4326
4327/*!
4328 Returns the window for this widget, i.e. the next ancestor widget
4329 that has (or could have) a window-system frame.
4330
4331 If the widget is a window, the widget itself is returned.
4332
4333 Typical usage is changing the window title:
4334
4335 \snippet code/src_gui_kernel_qwidget.cpp 3
4336
4337 \sa isWindow()
4338*/
4339
4340QWidget *QWidget::window() const
4341{
4342 QWidget *w = const_cast<QWidget *>(this);
4343 QWidget *p = w->parentWidget();
4344 while (!w->isWindow() && p) {
4345 w = p;
4346 p = p->parentWidget();
4347 }
4348 return w;
4349}
4350
4351/*!
4352 \since 4.4
4353
4354 Returns the native parent for this widget, i.e. the next ancestor widget
4355 that has a system identifier, or \nullptr if it does not have any native
4356 parent.
4357
4358 \sa effectiveWinId()
4359*/
4360QWidget *QWidget::nativeParentWidget() const
4361{
4362 QWidget *parent = parentWidget();
4363 while (parent && !parent->internalWinId())
4364 parent = parent->parentWidget();
4365 return parent;
4366}
4367
4368/*! \fn QWidget *QWidget::topLevelWidget() const
4369 \deprecated
4370
4371 Use window() instead.
4372*/
4373
4374
4375
4376/*!
4377 Returns the background role of the widget.
4378
4379 The background role defines the brush from the widget's \l palette that
4380 is used to render the background.
4381
4382 If no explicit background role is set, the widget inherits its parent
4383 widget's background role.
4384
4385 \sa setBackgroundRole(), foregroundRole()
4386 */
4387QPalette::ColorRole QWidget::backgroundRole() const
4388{
4389
4390 const QWidget *w = this;
4391 do {
4392 QPalette::ColorRole role = w->d_func()->bg_role;
4393 if (role != QPalette::NoRole)
4394 return role;
4395 if (w->isWindow() || w->windowType() == Qt::SubWindow)
4396 break;
4397 w = w->parentWidget();
4398 } while (w);
4399 return QPalette::Window;
4400}
4401
4402/*!
4403 Sets the background role of the widget to \a role.
4404
4405 The background role defines the brush from the widget's \l palette that
4406 is used to render the background.
4407
4408 If \a role is QPalette::NoRole, then the widget inherits its
4409 parent's background role.
4410
4411 Note that styles are free to choose any color from the palette.
4412 You can modify the palette or set a style sheet if you don't
4413 achieve the result you want with setBackgroundRole().
4414
4415 \sa backgroundRole(), foregroundRole()
4416 */
4417
4418void QWidget::setBackgroundRole(QPalette::ColorRole role)
4419{
4420 Q_D(QWidget);
4421 d->bg_role = role;
4422 d->updateSystemBackground();
4423 d->propagatePaletteChange();
4424 d->updateIsOpaque();
4425}
4426
4427/*!
4428 Returns the foreground role.
4429
4430 The foreground role defines the color from the widget's \l palette that
4431 is used to draw the foreground.
4432
4433 If no explicit foreground role is set, the function returns a role
4434 that contrasts with the background role.
4435
4436 \sa setForegroundRole(), backgroundRole()
4437 */
4438QPalette::ColorRole QWidget::foregroundRole() const
4439{
4440 Q_D(const QWidget);
4441 QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4442 if (rl != QPalette::NoRole)
4443 return rl;
4444 QPalette::ColorRole role = QPalette::WindowText;
4445 switch (backgroundRole()) {
4446 case QPalette::Button:
4447 role = QPalette::ButtonText;
4448 break;
4449 case QPalette::Base:
4450 role = QPalette::Text;
4451 break;
4452 case QPalette::Dark:
4453 case QPalette::Shadow:
4454 role = QPalette::Light;
4455 break;
4456 case QPalette::Highlight:
4457 role = QPalette::HighlightedText;
4458 break;
4459 case QPalette::ToolTipBase:
4460 role = QPalette::ToolTipText;
4461 break;
4462 default:
4463 ;
4464 }
4465 return role;
4466}
4467
4468/*!
4469 Sets the foreground role of the widget to \a role.
4470
4471 The foreground role defines the color from the widget's \l palette that
4472 is used to draw the foreground.
4473
4474 If \a role is QPalette::NoRole, the widget uses a foreground role
4475 that contrasts with the background role.
4476
4477 Note that styles are free to choose any color from the palette.
4478 You can modify the palette or set a style sheet if you don't
4479 achieve the result you want with setForegroundRole().
4480
4481 \sa foregroundRole(), backgroundRole()
4482 */
4483void QWidget::setForegroundRole(QPalette::ColorRole role)
4484{
4485 Q_D(QWidget);
4486 d->fg_role = role;
4487 d->updateSystemBackground();
4488 d->propagatePaletteChange();
4489}
4490
4491/*!
4492 \property QWidget::palette
4493 \brief the widget's palette
4494
4495 This property describes the widget's palette. The palette is used by the
4496 widget's style when rendering standard components, and is available as a
4497 means to ensure that custom widgets can maintain consistency with the
4498 native platform's look and feel. It's common that different platforms, or
4499 different styles, have different palettes.
4500
4501 When you assign a new palette to a widget, the color roles from this
4502 palette are combined with the widget's default palette to form the
4503 widget's final palette. The palette entry for the widget's background role
4504 is used to fill the widget's background (see QWidget::autoFillBackground),
4505 and the foreground role initializes QPainter's pen.
4506
4507 The default depends on the system environment. QApplication maintains a
4508 system/theme palette which serves as a default for all widgets. There may
4509 also be special palette defaults for certain types of widgets (e.g., on
4510 Windows Vista, all classes that derive from QMenuBar have a special
4511 default palette). You can also define default palettes for widgets
4512 yourself by passing a custom palette and the name of a widget to
4513 QApplication::setPalette(). Finally, the style always has the option of
4514 polishing the palette as it's assigned (see QStyle::polish()).
4515
4516 QWidget propagates explicit palette roles from parent to child. If you
4517 assign a brush or color to a specific role on a palette and assign that
4518 palette to a widget, that role will propagate to all the widget's
4519 children, overriding any system defaults for that role. Note that palettes
4520 by default don't propagate to windows (see isWindow()) unless the
4521 Qt::WA_WindowPropagation attribute is enabled.
4522
4523 QWidget's palette propagation is similar to its font propagation.
4524
4525 The current style, which is used to render the content of all standard Qt
4526 widgets, is free to choose colors and brushes from the widget palette, or,
4527 in some cases, to ignore the palette (partially, or completely). In
4528 particular, certain styles like GTK style, Mac style, and Windows Vista
4529 style, depend on third party APIs to render the content of widgets,
4530 and these styles typically do not follow the palette. Because of this,
4531 assigning roles to a widget's palette is not guaranteed to change the
4532 appearance of the widget. Instead, you may choose to apply a \l {styleSheet}.
4533
4534 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4535 When using style sheets, the palette of a widget can be customized using
4536 the "color", "background-color", "selection-color",
4537 "selection-background-color" and "alternate-background-color".
4538
4539 \sa QGuiApplication::palette(), QWidget::font(), {Qt Style Sheets}
4540*/
4541const QPalette &QWidget::palette() const
4542{
4543 if (!isEnabled()) {
4544 data->pal.setCurrentColorGroup(QPalette::Disabled);
4545 } else if ((!isVisible() || isActiveWindow())
4546#if defined(Q_OS_WIN)
4547 && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4548#endif
4549 ) {
4550 data->pal.setCurrentColorGroup(QPalette::Active);
4551 } else {
4552 data->pal.setCurrentColorGroup(QPalette::Inactive);
4553 }
4554 return data->pal;
4555}
4556
4557void QWidget::setPalette(const QPalette &palette)
4558{
4559 Q_D(QWidget);
4560 setAttribute(Qt::WA_SetPalette, palette.resolveMask() != 0);
4561
4562 // Determine which palette is inherited from this widget's ancestors and
4563 // QApplication::palette, resolve this against \a palette (attributes from
4564 // the inherited palette are copied over this widget's palette). Then
4565 // propagate this palette to this widget's children.
4566 QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
4567 QPalette resolvedPalette = palette.resolve(naturalPalette);
4568 d->setPalette_helper(resolvedPalette);
4569}
4570
4571/*!
4572 \internal
4573
4574 Returns the palette that the widget \a w inherits from its ancestors and
4575 QApplication::palette. \a inheritedMask is the combination of the widget's
4576 ancestors palette request masks (i.e., which attributes from the parent
4577 widget's palette are implicitly imposed on this widget by the user). Note
4578 that this font does not take into account the palette set on \a w itself.
4579*/
4580QPalette QWidgetPrivate::naturalWidgetPalette(QPalette::ResolveMask inheritedMask) const
4581{
4582 Q_Q(const QWidget);
4583
4584 const bool useStyleSheetPropagationInWidgetStyles =
4585 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4586
4587 QPalette naturalPalette = QApplication::palette(q);
4588 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4589 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4590#if QT_CONFIG(graphicsview)
4591 || (extra && extra->proxyWidget)
4592#endif // QT_CONFIG(graphicsview)
4593 )) {
4594 if (QWidget *p = q->parentWidget()) {
4595 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4596 if (!naturalPalette.isCopyOf(QGuiApplication::palette())) {
4597 QPalette inheritedPalette = p->palette();
4598 inheritedPalette.setResolveMask(inheritedMask);
4599 naturalPalette = inheritedPalette.resolve(naturalPalette);
4600 } else {
4601 naturalPalette = p->palette();
4602 }
4603 }
4604 }
4605#if QT_CONFIG(graphicsview)
4606 else if (extra && extra->proxyWidget) {
4607 QPalette inheritedPalette = extra->proxyWidget->palette();
4608 inheritedPalette.setResolveMask(inheritedMask);
4609 naturalPalette = inheritedPalette.resolve(naturalPalette);
4610 }
4611#endif // QT_CONFIG(graphicsview)
4612 }
4613 naturalPalette.setResolveMask(0);
4614 return naturalPalette;
4615}
4616/*!
4617 \internal
4618
4619 Determine which palette is inherited from this widget's ancestors and
4620 QApplication::palette, resolve this against this widget's palette
4621 (attributes from the inherited palette are copied over this widget's
4622 palette). Then propagate this palette to this widget's children.
4623*/
4624void QWidgetPrivate::resolvePalette()
4625{
4626 QPalette naturalPalette = naturalWidgetPalette(inheritedPaletteResolveMask);
4627 QPalette resolvedPalette = data.pal.resolve(naturalPalette);
4628 setPalette_helper(resolvedPalette);
4629}
4630
4631void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4632{
4633 Q_Q(QWidget);
4634 if (data.pal == palette && data.pal.resolveMask() == palette.resolveMask())
4635 return;
4636 data.pal = palette;
4637 updateSystemBackground();
4638 propagatePaletteChange();
4639 updateIsOpaque();
4640 q->update();
4641 updateIsOpaque();
4642}
4643
4644void QWidgetPrivate::updateSystemBackground()
4645{
4646}
4647
4648/*!
4649 \property QWidget::font
4650 \brief the font currently set for the widget
4651
4652 This property describes the widget's requested font. The font is used by
4653 the widget's style when rendering standard components, and is available as
4654 a means to ensure that custom widgets can maintain consistency with the
4655 native platform's look and feel. It's common that different platforms, or
4656 different styles, define different fonts for an application.
4657
4658 When you assign a new font to a widget, the properties from this font are
4659 combined with the widget's default font to form the widget's final
4660 font. You can call fontInfo() to get a copy of the widget's final
4661 font. The final font is also used to initialize QPainter's font.
4662
4663 The default depends on the system environment. QApplication maintains a
4664 system/theme font which serves as a default for all widgets. There may
4665 also be special font defaults for certain types of widgets. You can also
4666 define default fonts for widgets yourself by passing a custom font and the
4667 name of a widget to QApplication::setFont(). Finally, the font is matched
4668 against Qt's font database to find the best match.
4669
4670 QWidget propagates explicit font properties from parent to child. If you
4671 change a specific property on a font and assign that font to a widget,
4672 that property will propagate to all the widget's children, overriding any
4673 system defaults for that property. Note that fonts by default don't
4674 propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4675 attribute is enabled.
4676
4677 QWidget's font propagation is similar to its palette propagation.
4678
4679 The current style, which is used to render the content of all standard Qt
4680 widgets, is free to choose to use the widget font, or in some cases, to
4681 ignore it (partially, or completely). In particular, certain styles like
4682 GTK style, Mac style, and Windows Vista style, apply special
4683 modifications to the widget font to match the platform's native look and
4684 feel. Because of this, assigning properties to a widget's font is not
4685 guaranteed to change the appearance of the widget. Instead, you may choose
4686 to apply a \l styleSheet.
4687
4688 \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4689 style sheets will take precedence if the settings conflict.
4690
4691 \sa fontInfo(), fontMetrics()
4692*/
4693
4694void QWidget::setFont(const QFont &font)
4695{
4696 Q_D(QWidget);
4697
4698#if QT_CONFIG(style_stylesheet)
4699 const QStyleSheetStyle* style;
4700 if (d->extra && (style = qt_styleSheet(d->extra->style)))
4701 style->saveWidgetFont(this, font);
4702#endif
4703
4704 setAttribute(Qt::WA_SetFont, font.resolveMask() != 0);
4705
4706 // Determine which font is inherited from this widget's ancestors and
4707 // QApplication::font, resolve this against \a font (attributes from the
4708 // inherited font are copied over). Then propagate this font to this
4709 // widget's children.
4710 QFont naturalFont = d->naturalWidgetFont(d->inheritedFontResolveMask);
4711 QFont resolvedFont = font.resolve(naturalFont);
4712 d->setFont_helper(resolvedFont);
4713}
4714
4715/*
4716 \internal
4717
4718 Returns the font that the widget \a w inherits from its ancestors and
4719 QApplication::font. \a inheritedMask is the combination of the widget's
4720 ancestors font request masks (i.e., which attributes from the parent
4721 widget's font are implicitly imposed on this widget by the user). Note
4722 that this font does not take into account the font set on \a w itself.
4723
4724 ### Stylesheet has a different font propagation mechanism. When a stylesheet
4725 is applied, fonts are not propagated anymore
4726*/
4727QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4728{
4729 Q_Q(const QWidget);
4730
4731 const bool useStyleSheetPropagationInWidgetStyles =
4732 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4733
4734 QFont naturalFont = QApplication::font(q);
4735 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4736 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4737#if QT_CONFIG(graphicsview)
4738 || (extra && extra->proxyWidget)
4739#endif // QT_CONFIG(graphicsview)
4740 )) {
4741 if (QWidget *p = q->parentWidget()) {
4742 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4743 if (!naturalFont.isCopyOf(QApplication::font())) {
4744 if (inheritedMask != 0) {
4745 QFont inheritedFont = p->font();
4746 inheritedFont.setResolveMask(inheritedMask);
4747 naturalFont = inheritedFont.resolve(naturalFont);
4748 } // else nothing to do (naturalFont = naturalFont)
4749 } else {
4750 naturalFont = p->font();
4751 }
4752 }
4753 }
4754#if QT_CONFIG(graphicsview)
4755 else if (extra && extra->proxyWidget) {
4756 if (inheritedMask != 0) {
4757 QFont inheritedFont = extra->proxyWidget->font();
4758 inheritedFont.setResolveMask(inheritedMask);
4759 naturalFont = inheritedFont.resolve(naturalFont);
4760 } // else nothing to do (naturalFont = naturalFont)
4761 }
4762#endif // QT_CONFIG(graphicsview)
4763 }
4764 naturalFont.setResolveMask(0);
4765 return naturalFont;
4766}
4767
4768/*!
4769 \internal
4770
4771 Returns a font suitable for inheritance, where only locally set attributes are considered resolved.
4772*/
4773QFont QWidgetPrivate::localFont() const
4774{
4775 QFont localfont = data.fnt;
4776 localfont.setResolveMask(directFontResolveMask);
4777 return localfont;
4778}
4779
4780/*!
4781 \internal
4782
4783 Determine which font is implicitly imposed on this widget by its ancestors
4784 and QApplication::font, resolve this against its own font (attributes from
4785 the implicit font are copied over). Then propagate this font to this
4786 widget's children.
4787*/
4788void QWidgetPrivate::resolveFont()
4789{
4790 QFont naturalFont = naturalWidgetFont(inheritedFontResolveMask);
4791 QFont resolvedFont = localFont().resolve(naturalFont);
4792 setFont_helper(resolvedFont);
4793}
4794
4795/*!
4796 \internal
4797
4798 Assign \a font to this widget, and propagate it to all children, except
4799 style sheet widgets (handled differently) and windows that don't enable
4800 window propagation. \a implicitMask is the union of all ancestor widgets'
4801 font request masks, and determines which attributes from this widget's
4802 font should propagate.
4803*/
4804void QWidgetPrivate::updateFont(const QFont &font)
4805{
4806 Q_Q(QWidget);
4807#if QT_CONFIG(style_stylesheet)
4808 const QStyleSheetStyle* cssStyle;
4809 cssStyle = extra ? qt_styleSheet(extra->style) : nullptr;
4810 const bool useStyleSheetPropagationInWidgetStyles =
4811 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4812#endif
4813
4814 data.fnt = QFont(font, q);
4815
4816 // Combine new mask with natural mask and propagate to children.
4817#if QT_CONFIG(graphicsview)
4818 if (!q->parentWidget() && extra && extra->proxyWidget) {
4819 QGraphicsProxyWidget *p = extra->proxyWidget;
4820 inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolveMask();
4821 } else
4822#endif // QT_CONFIG(graphicsview)
4823 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
4824 inheritedFontResolveMask = 0;
4825 }
4826 uint newMask = data.fnt.resolveMask() | inheritedFontResolveMask;
4827 // Set the font as also having resolved inherited traits, so the result of reading QWidget::font()
4828 // isn't all weak information, but save the original mask to be able to let new changes on the
4829 // parent widget font propagate correctly.
4830 directFontResolveMask = data.fnt.resolveMask();
4831 data.fnt.setResolveMask(newMask);
4832
4833 for (int i = 0; i < children.size(); ++i) {
4834 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4835 if (w) {
4836 if (0) {
4837#if QT_CONFIG(style_stylesheet)
4838 } else if (!useStyleSheetPropagationInWidgetStyles && w->testAttribute(Qt::WA_StyleSheet)) {
4839 // Style sheets follow a different font propagation scheme.
4840 if (cssStyle)
4841 cssStyle->updateStyleSheetFont(w);
4842#endif
4843 } else if ((!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
4844 // Propagate font changes.
4845 QWidgetPrivate *wd = w->d_func();
4846 wd->inheritedFontResolveMask = newMask;
4847 wd->resolveFont();
4848 }
4849 }
4850 }
4851
4852#if QT_CONFIG(style_stylesheet)
4853 if (!useStyleSheetPropagationInWidgetStyles && cssStyle) {
4854 cssStyle->updateStyleSheetFont(q);
4855 }
4856#endif
4857
4858 QEvent e(QEvent::FontChange);
4859 QCoreApplication::sendEvent(q, &e);
4860}
4861
4862void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
4863{
4864 Q_Q(QWidget);
4865
4866 if ( (direction == Qt::RightToLeft) == q->testAttribute(Qt::WA_RightToLeft))
4867 return;
4868 q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));
4869 if (!children.isEmpty()) {
4870 for (int i = 0; i < children.size(); ++i) {
4871 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4872 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_SetLayoutDirection))
4873 w->d_func()->setLayoutDirection_helper(direction);
4874 }
4875 }
4876 QEvent e(QEvent::LayoutDirectionChange);
4877 QCoreApplication::sendEvent(q, &e);
4878}
4879
4880void QWidgetPrivate::resolveLayoutDirection()
4881{
4882 Q_Q(const QWidget);
4883 if (!q->testAttribute(Qt::WA_SetLayoutDirection))
4884 setLayoutDirection_helper(q->isWindow() ? QGuiApplication::layoutDirection() : q->parentWidget()->layoutDirection());
4885}
4886
4887/*!
4888 \property QWidget::layoutDirection
4889
4890 \brief the layout direction for this widget.
4891
4892 \note This method no longer affects text layout direction since Qt 4.7.
4893
4894 By default, this property is set to Qt::LeftToRight.
4895
4896 When the layout direction is set on a widget, it will propagate to
4897 the widget's children, but not to a child that is a window and not
4898 to a child for which setLayoutDirection() has been explicitly
4899 called. Also, child widgets added \e after setLayoutDirection()
4900 has been called for the parent do not inherit the parent's layout
4901 direction.
4902
4903
4904 \sa QApplication::layoutDirection
4905*/
4906void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
4907{
4908 Q_D(QWidget);
4909
4910 if (direction == Qt::LayoutDirectionAuto) {
4911 unsetLayoutDirection();
4912 return;
4913 }
4914
4915 setAttribute(Qt::WA_SetLayoutDirection);
4916 d->setLayoutDirection_helper(direction);
4917}
4918
4919Qt::LayoutDirection QWidget::layoutDirection() const
4920{
4921 return testAttribute(Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
4922}
4923
4924void QWidget::unsetLayoutDirection()
4925{
4926 Q_D(QWidget);
4927 setAttribute(Qt::WA_SetLayoutDirection, false);
4928 d->resolveLayoutDirection();
4929}
4930
4931/*!
4932 \fn QFontMetrics QWidget::fontMetrics() const
4933
4934 Returns the font metrics for the widget's current font.
4935 Equivalent to \c QFontMetrics(widget->font()).
4936
4937 \sa font(), fontInfo(), setFont()
4938*/
4939
4940/*!
4941 \fn QFontInfo QWidget::fontInfo() const
4942
4943 Returns the font info for the widget's current font.
4944 Equivalent to \c QFontInfo(widget->font()).
4945
4946 \sa font(), fontMetrics(), setFont()
4947*/
4948
4949
4950/*!
4951 \property QWidget::cursor
4952 \brief the cursor shape for this widget
4953
4954 The mouse cursor will assume this shape when it's over this
4955 widget. See the \l{Qt::CursorShape}{list of predefined cursor objects} for a range of useful shapes.
4956
4957 An editor widget might use an I-beam cursor:
4958 \snippet code/src_gui_kernel_qwidget.cpp 6
4959
4960 If no cursor has been set, or after a call to unsetCursor(), the
4961 parent's cursor is used.
4962
4963 By default, this property contains a cursor with the Qt::ArrowCursor
4964 shape.
4965
4966 Some underlying window implementations will reset the cursor if it
4967 leaves a widget even if the mouse is grabbed. If you want to have
4968 a cursor set for all widgets, even when outside the window, consider
4969 QGuiApplication::setOverrideCursor().
4970
4971 \sa QGuiApplication::setOverrideCursor()
4972*/
4973
4974#ifndef QT_NO_CURSOR
4975QCursor QWidget::cursor() const
4976{
4977 Q_D(const QWidget);
4978 if (testAttribute(Qt::WA_SetCursor))
4979 return (d->extra && d->extra->curs)
4980 ? *d->extra->curs
4981 : QCursor(Qt::ArrowCursor);
4982 if (isWindow() || !parentWidget())
4983 return QCursor(Qt::ArrowCursor);
4984 return parentWidget()->cursor();
4985}
4986
4987void QWidget::setCursor(const QCursor &cursor)
4988{
4989 Q_D(QWidget);
4990 if (cursor.shape() != Qt::ArrowCursor
4991 || (d->extra && d->extra->curs))
4992 {
4993 d->createExtra();
4994 d->extra->curs = std::make_unique<QCursor>(cursor);
4995 }
4996 setAttribute(Qt::WA_SetCursor);
4997 d->setCursor_sys(cursor);
4998
4999 QEvent event(QEvent::CursorChange);
5000 QCoreApplication::sendEvent(this, &event);
5001}
5002
5003void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
5004{
5005 Q_UNUSED(cursor);
5006 Q_Q(QWidget);
5007 qt_qpa_set_cursor(q, false);
5008}
5009
5010void QWidget::unsetCursor()
5011{
5012 Q_D(QWidget);
5013 if (d->extra)
5014 d->extra->curs.reset();
5015 if (!isWindow())
5016 setAttribute(Qt::WA_SetCursor, false);
5017 d->unsetCursor_sys();
5018
5019 QEvent event(QEvent::CursorChange);
5020 QCoreApplication::sendEvent(this, &event);
5021}
5022
5023void QWidgetPrivate::unsetCursor_sys()
5024{
5025 Q_Q(QWidget);
5026 qt_qpa_set_cursor(q, false);
5027}
5028
5029static inline void applyCursor(QWidget *w, const QCursor &c)
5030{
5031 if (QWindow *window = w->windowHandle())
5032 window->setCursor(c);
5033}
5034
5035static inline void unsetCursor(QWidget *w)
5036{
5037 if (QWindow *window = w->windowHandle())
5038 window->unsetCursor();
5039}
5040
5041void qt_qpa_set_cursor(QWidget *w, bool force)
5042{
5043 if (!w->testAttribute(Qt::WA_WState_Created))
5044 return;
5045
5046 static QPointer<QWidget> lastUnderMouse = nullptr;
5047 if (force) {
5048 lastUnderMouse = w;
5049 } else if (lastUnderMouse) {
5050 const WId lastWinId = lastUnderMouse->effectiveWinId();
5051 const WId winId = w->effectiveWinId();
5052 if (lastWinId && lastWinId == winId)
5053 w = lastUnderMouse;
5054 } else if (!w->internalWinId()) {
5055 return; // The mouse is not under this widget, and it's not native, so don't change it.
5056 }
5057
5058 while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
5059 && !w->testAttribute(Qt::WA_SetCursor))
5060 w = w->parentWidget();
5061
5062 QWidget *nativeParent = w;
5063 if (!w->internalWinId())
5064 nativeParent = w->nativeParentWidget();
5065 if (!nativeParent || !nativeParent->internalWinId())
5066 return;
5067
5068 if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
5069 if (w->isEnabled())
5070 applyCursor(nativeParent, w->cursor());
5071 else
5072 // Enforce the windows behavior of clearing the cursor on
5073 // disabled widgets.
5074 unsetCursor(nativeParent);
5075 } else {
5076 unsetCursor(nativeParent);
5077 }
5078}
5079#endif
5080
5081/*!
5082 \enum QWidget::RenderFlag
5083
5084 This enum describes how to render the widget when calling QWidget::render().
5085
5086 \value DrawWindowBackground If you enable this option, the widget's background
5087 is rendered into the target even if autoFillBackground is not set. By default,
5088 this option is enabled.
5089
5090 \value DrawChildren If you enable this option, the widget's children
5091 are rendered recursively into the target. By default, this option is enabled.
5092
5093 \value IgnoreMask If you enable this option, the widget's QWidget::mask()
5094 is ignored when rendering into the target. By default, this option is disabled.
5095
5096 \since 4.3
5097*/
5098
5099/*!
5100 \since 4.3
5101
5102 Renders the \a sourceRegion of this widget into the \a target
5103 using \a renderFlags to determine how to render. Rendering
5104 starts at \a targetOffset in the \a target. For example:
5105
5106 \snippet code/src_gui_kernel_qwidget.cpp 7
5107
5108 If \a sourceRegion is a null region, this function will use QWidget::rect() as
5109 the region, i.e. the entire widget.
5110
5111 Ensure that you call QPainter::end() for the \a target device's
5112 active painter (if any) before rendering. For example:
5113
5114 \snippet code/src_gui_kernel_qwidget.cpp 8
5115
5116 \note To obtain the contents of a QOpenGLWidget, use QOpenGLWidget::grabFramebuffer()
5117 instead.
5118*/
5119void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
5120 const QRegion &sourceRegion, RenderFlags renderFlags)
5121{
5122 QPainter p(target);
5123 render(&p, targetOffset, sourceRegion, renderFlags);
5124}
5125
5126/*!
5127 \overload
5128
5129 Renders the widget into the \a painter's QPainter::device().
5130
5131 Transformations and settings applied to the \a painter will be used
5132 when rendering.
5133
5134 \note The \a painter must be active. On \macos the widget will be
5135 rendered into a QPixmap and then drawn by the \a painter.
5136
5137 \sa QPainter::device()
5138*/
5139void QWidget::render(QPainter *painter, const QPoint &targetOffset,
5140 const QRegion &sourceRegion, RenderFlags renderFlags)
5141{
5142 if (Q_UNLIKELY(!painter)) {
5143 qWarning("QWidget::render: Null pointer to painter");
5144 return;
5145 }
5146
5147 if (Q_UNLIKELY(!painter->isActive())) {
5148 qWarning("QWidget::render: Cannot render with an inactive painter");
5149 return;
5150 }
5151
5152 const qreal opacity = painter->opacity();
5153 if (qFuzzyIsNull(opacity))
5154 return; // Fully transparent.
5155
5156 Q_D(QWidget);
5157 const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
5158 const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
5159 : sourceRegion;
5160 if (toBePainted.isEmpty())
5161 return;
5162
5163 if (!d->extra)
5164 d->createExtra();
5165 d->extra->inRenderWithPainter = true;
5166
5167 QPaintEngine *engine = painter->paintEngine();
5168 Q_ASSERT(engine);
5169 QPaintEnginePrivate *enginePriv = engine->d_func();
5170 Q_ASSERT(enginePriv);
5171 QPaintDevice *target = engine->paintDevice();
5172 Q_ASSERT(target);
5173
5174 // Render via a pixmap when dealing with non-opaque painters or printers.
5175 if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
5176 d->render_helper(painter, targetOffset, toBePainted, renderFlags);
5177 d->extra->inRenderWithPainter = inRenderWithPainter;
5178 return;
5179 }
5180
5181 // Set new shared painter.
5182 QPainter *oldPainter = d->sharedPainter();
5183 d->setSharedPainter(painter);
5184
5185 // Save current system clip, viewport and transform,
5186 const QTransform oldTransform = enginePriv->systemTransform;
5187 const QRegion oldSystemClip = enginePriv->systemClip;
5188 const QRegion oldBaseClip = enginePriv->baseSystemClip;
5189 const QRegion oldSystemViewport = enginePriv->systemViewport;
5190 const Qt::LayoutDirection oldLayoutDirection = painter->layoutDirection();
5191
5192 // This ensures that all painting triggered by render() is clipped to the current engine clip.
5193 if (painter->hasClipping()) {
5194 const QRegion painterClip = painter->deviceTransform().map(painter->clipRegion());
5195 enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip);
5196 } else {
5197 enginePriv->setSystemViewport(oldSystemClip);
5198 }
5199 painter->setLayoutDirection(layoutDirection());
5200
5201 d->render(target, targetOffset, toBePainted, renderFlags);
5202
5203 // Restore system clip, viewport and transform.
5204 enginePriv->baseSystemClip = oldBaseClip;
5205 enginePriv->setSystemTransformAndViewport(oldTransform, oldSystemViewport);
5206 enginePriv->systemStateChanged();
5207 painter->setLayoutDirection(oldLayoutDirection);
5208
5209 // Restore shared painter.
5210 d->setSharedPainter(oldPainter);
5211
5212 d->extra->inRenderWithPainter = inRenderWithPainter;
5213}
5214
5215static void sendResizeEvents(QWidget *target)
5216{
5217 QResizeEvent e(target->size(), QSize());
5218 QCoreApplication::sendEvent(target, &e);
5219
5220 const QObjectList children = target->children();
5221 for (int i = 0; i < children.size(); ++i) {
5222 if (!children.at(i)->isWidgetType())
5223 continue;
5224 QWidget *child = static_cast<QWidget*>(children.at(i));
5225 if (!child->isWindow() && child->testAttribute(Qt::WA_PendingResizeEvent))
5226 sendResizeEvents(child);
5227 }
5228}
5229
5230/*!
5231 \since 5.0
5232
5233 Renders the widget into a pixmap restricted by the
5234 given \a rectangle. If the widget has any children, then
5235 they are also painted in the appropriate positions.
5236
5237 If a rectangle with an invalid size is specified (the default),
5238 the entire widget is painted.
5239
5240 \sa render(), QPixmap
5241*/
5242QPixmap QWidget::grab(const QRect &rectangle)
5243{
5244 Q_D(QWidget);
5245 if (testAttribute(Qt::WA_PendingResizeEvent) || !testAttribute(Qt::WA_WState_Created))
5246 sendResizeEvents(this);
5247
5248 const QWidget::RenderFlags renderFlags = QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask;
5249
5250 const bool oldDirtyOpaqueChildren = d->dirtyOpaqueChildren;
5251 QRect r(rectangle);
5252 if (r.width() < 0 || r.height() < 0) {
5253 // For grabbing widgets that haven't been shown yet,
5254 // we trigger the layouting mechanism to determine the widget's size.
5255 r = d->prepareToRender(QRegion(), renderFlags).boundingRect();
5256 r.setTopLeft(rectangle.topLeft());
5257 }
5258
5259 if (!r.intersects(rect()))
5260 return QPixmap();
5261
5262 const qreal dpr = devicePixelRatio();
5263 QPixmap res((QSizeF(r.size()) * dpr).toSize());
5264 res.setDevicePixelRatio(dpr);
5265 if (!d->isOpaque || res.hasAlphaChannel())
5266 res.fill(Qt::transparent);
5267 d->render(&res, QPoint(), QRegion(r), renderFlags);
5268
5269 d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
5270 return res;
5271}
5272
5273/*!
5274 \brief The graphicsEffect function returns a pointer to the
5275 widget's graphics effect.
5276
5277 If the widget has no graphics effect, \nullptr is returned.
5278
5279 \since 4.6
5280
5281 \sa setGraphicsEffect()
5282*/
5283#if QT_CONFIG(graphicseffect)
5284QGraphicsEffect *QWidget::graphicsEffect() const
5285{
5286 Q_D(const QWidget);
5287 return d->graphicsEffect;
5288}
5289#endif // QT_CONFIG(graphicseffect)
5290
5291/*!
5292
5293 \brief The setGraphicsEffect function is for setting the widget's graphics effect.
5294
5295 Sets \a effect as the widget's effect. If there already is an effect installed
5296 on this widget, QWidget will delete the existing effect before installing
5297 the new \a effect.
5298
5299 If \a effect is the installed effect on a different widget, setGraphicsEffect() will remove
5300 the effect from the widget and install it on this widget.
5301
5302 QWidget takes ownership of \a effect.
5303
5304 \note This function will apply the effect on itself and all its children.
5305
5306 \note Graphics effects are not supported for OpenGL-based widgets, such as QGLWidget,
5307 QOpenGLWidget and QQuickWidget.
5308
5309 \since 4.6
5310
5311 \sa graphicsEffect()
5312*/
5313#if QT_CONFIG(graphicseffect)
5314void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
5315{
5316 Q_D(QWidget);
5317 if (d->graphicsEffect == effect)
5318 return;
5319
5320 if (d->graphicsEffect) {
5321 d->invalidateBackingStore(rect());
5322 delete d->graphicsEffect;
5323 d->graphicsEffect = nullptr;
5324 }
5325
5326 if (effect) {
5327 // Set new effect.
5328 QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
5329 QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
5330 d->graphicsEffect = effect;
5331 effect->d_func()->setGraphicsEffectSource(source);
5332 update();
5333 }
5334
5335 d->updateIsOpaque();
5336}
5337#endif // QT_CONFIG(graphicseffect)
5338
5339bool QWidgetPrivate::isAboutToShow() const
5340{
5341 if (data.in_show)
5342 return true;
5343
5344 Q_Q(const QWidget);
5345 if (q->isHidden())
5346 return false;
5347
5348 // The widget will be shown if any of its ancestors are about to show.
5349 QWidget *parent = q->parentWidget();
5350 return parent ? parent->d_func()->isAboutToShow() : false;
5351}
5352
5353QRegion QWidgetPrivate::prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags)
5354{
5355 Q_Q(QWidget);
5356 const bool isVisible = q->isVisible();
5357
5358 // Make sure the widget is laid out correctly.
5359 if (!isVisible && !isAboutToShow()) {
5360 QWidget *topLevel = q->window();
5361 (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
5362 topLevel->ensurePolished();
5363
5364 // Invalidate the layout of hidden ancestors (incl. myself) and pretend
5365 // they're not explicitly hidden.
5366 QWidget *widget = q;
5367 QWidgetList hiddenWidgets;
5368 while (widget) {
5369 if (widget->isHidden()) {
5370 widget->setAttribute(Qt::WA_WState_Hidden, false);
5371 hiddenWidgets.append(widget);
5372 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5373 widget->d_func()->updateGeometry_helper(true);
5374 }
5375 widget = widget->parentWidget();
5376 }
5377
5378 // Activate top-level layout.
5379 if (topLevel->d_func()->layout)
5380 topLevel->d_func()->layout->activate();
5381
5382 // Adjust size if necessary.
5383 QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
5384 if (topLevelExtra && !topLevelExtra->sizeAdjusted
5385 && !topLevel->testAttribute(Qt::WA_Resized)) {
5386 topLevel->adjustSize();
5387 topLevel->setAttribute(Qt::WA_Resized, false);
5388 }
5389
5390 // Activate child layouts.
5391 topLevel->d_func()->activateChildLayoutsRecursively();
5392
5393 // We're not cheating with WA_WState_Hidden anymore.
5394 for (int i = 0; i < hiddenWidgets.size(); ++i) {
5395 QWidget *widget = hiddenWidgets.at(i);
5396 widget->setAttribute(Qt::WA_WState_Hidden);
5397 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5398 widget->parentWidget()->d_func()->layout->invalidate();
5399 }
5400 } else if (isVisible) {
5401 q->window()->d_func()->sendPendingMoveAndResizeEvents(true, true);
5402 }
5403
5404 // Calculate the region to be painted.
5405 QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
5406 if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
5407 toBePainted &= extra->mask;
5408 return toBePainted;
5409}
5410
5411void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
5412 QWidget::RenderFlags renderFlags)
5413{
5414 Q_ASSERT(painter);
5415 Q_ASSERT(!toBePainted.isEmpty());
5416
5417 Q_Q(QWidget);
5418 const QTransform originalTransform = painter->worldTransform();
5419 const bool useDeviceCoordinates = originalTransform.isScaling();
5420 if (!useDeviceCoordinates) {
5421 // Render via a pixmap.
5422 const QRect rect = toBePainted.boundingRect();
5423 const QSize size = rect.size();
5424 if (size.isNull())
5425 return;
5426
5427 const qreal pixmapDevicePixelRatio = painter->device()->devicePixelRatio();
5428 QPixmap pixmap(size * pixmapDevicePixelRatio);
5429 pixmap.setDevicePixelRatio(pixmapDevicePixelRatio);
5430
5431 if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque)
5432 pixmap.fill(Qt::transparent);
5433 q->render(&pixmap, QPoint(), toBePainted, renderFlags);
5434
5435 const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
5436 painter->setRenderHints(QPainter::SmoothPixmapTransform, true);
5437
5438 painter->drawPixmap(targetOffset, pixmap);
5439
5440 if (restore)
5441 painter->setRenderHints(QPainter::SmoothPixmapTransform, false);
5442
5443 } else {
5444 // Render via a pixmap in device coordinates (to avoid pixmap scaling).
5445 QTransform transform = originalTransform;
5446 transform.translate(targetOffset.x(), targetOffset.y());
5447
5448 QPaintDevice *device = painter->device();
5449 Q_ASSERT(device);
5450
5451 // Calculate device rect.
5452 const QRectF rect(toBePainted.boundingRect());
5453 QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
5454 deviceRect &= QRect(0, 0, device->width(), device->height());
5455
5456 QPixmap pixmap(deviceRect.size());
5457 pixmap.fill(Qt::transparent);
5458
5459 // Create a pixmap device coordinate painter.
5460 QPainter pixmapPainter(&pixmap);
5461 pixmapPainter.setRenderHints(painter->renderHints());
5462 transform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
5463 pixmapPainter.setTransform(transform);
5464
5465 q->render(&pixmapPainter, QPoint(), toBePainted, renderFlags);
5466 pixmapPainter.end();
5467
5468 // And then draw the pixmap.
5469 painter->setTransform(QTransform());
5470 painter->drawPixmap(deviceRect.topLeft(), pixmap);
5471 painter->setTransform(originalTransform);
5472 }
5473}
5474
5475void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
5476 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5477{
5478 if (rgn.isEmpty())
5479 return;
5480
5481 Q_Q(QWidget);
5482
5483 qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset
5484 << "into paint device" << pdev << "with" << flags;
5485
5486 const bool asRoot = flags & DrawAsRoot;
5487 bool onScreen = shouldPaintOnScreen();
5488
5489#if QT_CONFIG(graphicseffect)
5490 if (graphicsEffect && graphicsEffect->isEnabled()) {
5491 QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
5492 QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
5493 (source->d_func());
5494 if (!sourced->context) {
5495 const QRegion effectRgn((flags & UseEffectRegionBounds) ? rgn.boundingRect() : rgn);
5496 QWidgetPaintContext context(pdev, effectRgn, offset, flags, sharedPainter, repaintManager);
5497 sourced->context = &context;
5498 if (!sharedPainter) {
5499 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), effectRgn.translated(offset));
5500 QPainter p(pdev);
5501 p.translate(offset);
5502 context.painter = &p;
5503 graphicsEffect->draw(&p);
5504 setSystemClip(pdev->paintEngine(), 1, QRegion());
5505 } else {
5506 context.painter = sharedPainter;
5507 if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
5508 sourced->invalidateCache();
5509 sourced->lastEffectTransform = sharedPainter->worldTransform();
5510 }
5511 sharedPainter->save();
5512 sharedPainter->translate(offset);
5513 setSystemClip(sharedPainter->paintEngine(), sharedPainter->device()->devicePixelRatio(), effectRgn.translated(offset));
5514 graphicsEffect->draw(sharedPainter);
5515 setSystemClip(sharedPainter->paintEngine(), 1, QRegion());
5516 sharedPainter->restore();
5517 }
5518 sourced->context = nullptr;
5519
5520 if (repaintManager)
5521 repaintManager->markNeedsFlush(q, effectRgn, offset);
5522
5523 return;
5524 }
5525 }
5526#endif // QT_CONFIG(graphicseffect)
5527 flags = flags & ~UseEffectRegionBounds;
5528
5529 const bool alsoOnScreen = flags & DrawPaintOnScreen;
5530 const bool recursive = flags & DrawRecursive;
5531 const bool alsoInvisible = flags & DrawInvisible;
5532
5533 Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
5534
5535 QRegion toBePainted(rgn);
5536 if (asRoot && !alsoInvisible)
5537 toBePainted &= clipRect(); //(rgn & visibleRegion());
5538 if (!(flags & DontSubtractOpaqueChildren))
5539 subtractOpaqueChildren(toBePainted, q->rect());
5540
5541 if (!toBePainted.isEmpty()) {
5542 if (!onScreen || alsoOnScreen) {
5543 //update the "in paint event" flag
5544 if (Q_UNLIKELY(q->testAttribute(Qt::WA_WState_InPaintEvent)))
5545 qWarning("QWidget::repaint: Recursive repaint detected");
5546 q->setAttribute(Qt::WA_WState_InPaintEvent);
5547
5548 //clip away the new area
5549 QPaintEngine *paintEngine = pdev->paintEngine();
5550 if (paintEngine) {
5551 setRedirected(pdev, -offset);
5552
5553 if (sharedPainter)
5554 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted);
5555 else
5556 paintEngine->d_func()->systemRect = q->data->crect;
5557
5558 //paint the background
5559 if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
5560 && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
5561 beginBackingStorePainting();
5562 QPainter p(q);
5563 p.setRenderHint(QPainter::SmoothPixmapTransform);
5564 paintBackground(&p, toBePainted, (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags());
5565 endBackingStorePainting();
5566 }
5567
5568 if (!sharedPainter)
5569 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted.translated(offset));
5570
5571 if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
5572 beginBackingStorePainting();
5573 QPainter p(q);
5574 QColor tint = q->palette().window().color();
5575 tint.setAlphaF(.6f);
5576 p.fillRect(toBePainted.boundingRect(), tint);
5577 endBackingStorePainting();
5578 }
5579 }
5580
5581#if 0
5582 qDebug() << "painting" << q << "opaque ==" << isOpaque();
5583 qDebug() << "clipping to" << toBePainted << "location == " << offset
5584 << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
5585#endif
5586
5587 bool skipPaintEvent = false;
5588 if (renderToTexture) {
5589 // This widget renders into a texture which is composed later. We just need to
5590 // punch a hole in the backingstore, so the texture will be visible.
5591 beginBackingStorePainting();
5592 if (!q->testAttribute(Qt::WA_AlwaysStackOnTop) && repaintManager) {
5593 QPainter p(q);
5594 p.setCompositionMode(QPainter::CompositionMode_Source);
5595 p.fillRect(q->rect(), Qt::transparent);
5596 } else if (!repaintManager) {
5597 // We are not drawing to a backingstore: fall back to QImage
5598 QImage img = grabFramebuffer();
5599 // grabFramebuffer() always sets the format to RGB32
5600 // regardless of whether it is transparent or not.
5601 if (img.format() == QImage::Format_RGB32)
5602 img.reinterpretAsFormat(QImage::Format_ARGB32_Premultiplied);
5603 QPainter p(q);
5604 p.drawImage(q->rect(), img);
5605 skipPaintEvent = true;
5606 }
5607 endBackingStorePainting();
5608 if (renderToTextureReallyDirty)
5609 renderToTextureReallyDirty = 0;
5610 else
5611 skipPaintEvent = true;
5612 }
5613
5614 if (!skipPaintEvent) {
5615 //actually send the paint event
5616 sendPaintEvent(toBePainted);
5617 }
5618
5619 if (repaintManager)
5620 repaintManager->markNeedsFlush(q, toBePainted, offset);
5621
5622 //restore
5623 if (paintEngine) {
5624 restoreRedirected();
5625 if (!sharedPainter)
5626 paintEngine->d_func()->systemRect = QRect();
5627 else
5628 paintEngine->d_func()->currentClipDevice = nullptr;
5629
5630 setSystemClip(pdev->paintEngine(), 1, QRegion());
5631 }
5632 q->setAttribute(Qt::WA_WState_InPaintEvent, false);
5633 if (Q_UNLIKELY(q->paintingActive()))
5634 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
5635
5636 if (paintEngine && paintEngine->autoDestruct()) {
5637 delete paintEngine;
5638 }
5639 } else if (q->isWindow()) {
5640 QPaintEngine *engine = pdev->paintEngine();
5641 if (engine) {
5642 QPainter p(pdev);
5643 p.setClipRegion(toBePainted);
5644 const QBrush bg = q->palette().brush(QPalette::Window);
5645 if (bg.style() == Qt::TexturePattern)
5646 p.drawTiledPixmap(q->rect(), bg.texture());
5647 else
5648 p.fillRect(q->rect(), bg);
5649
5650 if (engine->autoDestruct())
5651 delete engine;
5652 }
5653 }
5654 }
5655
5656 if (recursive && !children.isEmpty()) {
5657 paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot,
5658 sharedPainter, repaintManager);
5659 }
5660}
5661
5662void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
5663{
5664 Q_Q(QWidget);
5665 QPaintEvent e(toBePainted);
5666 QCoreApplication::sendSpontaneousEvent(q, &e);
5667
5668 if (renderToTexture)
5669 resolveSamples();
5670}
5671
5672void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
5673 const QRegion &sourceRegion, QWidget::RenderFlags renderFlags)
5674{
5675 if (Q_UNLIKELY(!target)) {
5676 qWarning("QWidget::render: null pointer to paint device");
5677 return;
5678 }
5679
5680 const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
5681 QRegion paintRegion = !inRenderWithPainter
5682 ? prepareToRender(sourceRegion, renderFlags)
5683 : sourceRegion;
5684 if (paintRegion.isEmpty())
5685 return;
5686
5687 QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : nullptr;
5688
5689 // Use the target's shared painter if set (typically set when doing
5690 // "other->render(widget);" in the widget's paintEvent.
5691 if (target->devType() == QInternal::Widget) {
5692 QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
5693 if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
5694 QPainter *targetPainter = targetPrivate->sharedPainter();
5695 if (targetPainter && targetPainter->isActive())
5696 setSharedPainter(targetPainter);
5697 }
5698 }
5699
5700 // Use the target's redirected device if set and adjust offset and paint
5701 // region accordingly. This is typically the case when people call render
5702 // from the paintEvent.
5703 QPoint offset = targetOffset;
5704 offset -= paintRegion.boundingRect().topLeft();
5705 QPoint redirectionOffset;
5706 QPaintDevice *redirected = nullptr;
5707
5708 if (target->devType() == QInternal::Widget)
5709 redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
5710
5711 if (redirected) {
5712 target = redirected;
5713 offset -= redirectionOffset;
5714 }
5715
5716 if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
5717 if (QPaintEngine *targetEngine = target->paintEngine()) {
5718 const QRegion targetSystemClip = targetEngine->systemClip();
5719 if (!targetSystemClip.isEmpty())
5720 paintRegion &= targetSystemClip.translated(-offset);
5721 }
5722 }
5723
5724 // Set backingstore flags.
5725 DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible;
5726 if (renderFlags & QWidget::DrawWindowBackground)
5727 flags |= DrawAsRoot;
5728
5729 if (renderFlags & QWidget::DrawChildren)
5730 flags |= DrawRecursive;
5731 else
5732 flags |= DontSubtractOpaqueChildren;
5733
5734 flags |= DontSetCompositionMode;
5735
5736 // Render via backingstore.
5737 drawWidget(target, paintRegion, offset, flags, sharedPainter());
5738
5739 // Restore shared painter.
5740 if (oldSharedPainter)
5741 setSharedPainter(oldSharedPainter);
5742}
5743
5744void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
5745 const QPoint &offset, DrawWidgetFlags flags
5746 , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5747{
5748 QWidget *w = nullptr;
5749 QRect boundingRect;
5750 bool dirtyBoundingRect = true;
5751 const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
5752 const bool excludeNativeChildren = (flags & DontDrawNativeChildren);
5753
5754 do {
5755 QWidget *x = qobject_cast<QWidget*>(siblings.at(index));
5756 if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()
5757 && !(excludeNativeChildren && x->internalWinId())) {
5758 if (dirtyBoundingRect) {
5759 boundingRect = rgn.boundingRect();
5760 dirtyBoundingRect = false;
5761 }
5762
5763 if (qRectIntersects(boundingRect, x->d_func()->effectiveRectFor(x->data->crect))) {
5764 w = x;
5765 break;
5766 }
5767 }
5768 --index;
5769 } while (index >= 0);
5770
5771 if (!w)
5772 return;
5773
5774 QWidgetPrivate *wd = w->d_func();
5775 const QPoint widgetPos(w->data->crect.topLeft());
5776 const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
5777 if (index > 0) {
5778 QRegion wr(rgn);
5779 if (wd->isOpaque)
5780 wr -= hasMask ? wd->extra->mask.translated(widgetPos) : w->data->crect;
5781 paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags,
5782 sharedPainter, repaintManager);
5783 }
5784
5785 if (w->updatesEnabled()
5786#if QT_CONFIG(graphicsview)
5787 && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)
5788#endif // QT_CONFIG(graphicsview)
5789 ) {
5790 QRegion wRegion(rgn);
5791 wRegion &= wd->effectiveRectFor(w->data->crect);
5792 wRegion.translate(-widgetPos);
5793 if (hasMask)
5794 wRegion &= wd->extra->mask;
5795 wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, repaintManager);
5796 }
5797}
5798
5799#if QT_CONFIG(graphicseffect)
5800QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
5801{
5802 if (system != Qt::DeviceCoordinates)
5803 return m_widget->rect();
5804
5805 if (Q_UNLIKELY(!context)) {
5806 // Device coordinates without context not yet supported.
5807 qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
5808 return QRectF();
5809 }
5810
5811 return context->painter->worldTransform().mapRect(m_widget->rect());
5812}
5813
5814void QWidgetEffectSourcePrivate::draw(QPainter *painter)
5815{
5816 if (!context || context->painter != painter) {
5817 m_widget->render(painter);
5818 return;
5819 }
5820
5821 // The region saved in the context is neither clipped to the rect
5822 // nor the mask, so we have to clip it here before calling drawWidget.
5823 QRegion toBePainted = context->rgn;
5824 toBePainted &= m_widget->rect();
5825 QWidgetPrivate *wd = qt_widget_private(m_widget);
5826 if (wd->extra && wd->extra->hasMask)
5827 toBePainted &= wd->extra->mask;
5828
5829 wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags,
5830 context->sharedPainter, context->repaintManager);
5831}
5832
5833QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
5834 QGraphicsEffect::PixmapPadMode mode) const
5835{
5836 const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
5837 if (Q_UNLIKELY(!context && deviceCoordinates)) {
5838 // Device coordinates without context not yet supported.
5839 qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
5840 return QPixmap();
5841 }
5842
5843 QPoint pixmapOffset;
5844 QRectF sourceRect = m_widget->rect();
5845
5846 if (deviceCoordinates) {
5847 const QTransform &painterTransform = context->painter->worldTransform();
5848 sourceRect = painterTransform.mapRect(sourceRect);
5849 pixmapOffset = painterTransform.map(pixmapOffset);
5850 }
5851
5852 QRect effectRect;
5853
5854 if (mode == QGraphicsEffect::PadToEffectiveBoundingRect)
5855 effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
5856 else if (mode == QGraphicsEffect::PadToTransparentBorder)
5857 effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect();
5858 else
5859 effectRect = sourceRect.toAlignedRect();
5860
5861 if (offset)
5862 *offset = effectRect.topLeft();
5863
5864 pixmapOffset -= effectRect.topLeft();
5865
5866 qreal dpr(1.0);
5867 if (const auto *paintDevice = context->painter->device())
5868 dpr = paintDevice->devicePixelRatio();
5869 else
5870 qWarning("QWidgetEffectSourcePrivate::pixmap: Painter not active");
5871 QPixmap pixmap(effectRect.size() * dpr);
5872 pixmap.setDevicePixelRatio(dpr);
5873
5874 pixmap.fill(Qt::transparent);
5875 m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren);
5876 return pixmap;
5877}
5878#endif // QT_CONFIG(graphicseffect)
5879
5880#if QT_CONFIG(graphicsview)
5881/*!
5882 \internal
5883
5884 Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
5885 widget and its ancestors. The search starts at \a origin (inclusive).
5886 If successful, the function returns the proxy that embeds the widget, or \nullptr if no
5887 embedded widget was found.
5888*/
5889QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
5890{
5891 if (origin) {
5892 const auto &extra = origin->d_func()->extra;
5893 if (extra && extra->proxyWidget)
5894 return extra->proxyWidget;
5895 return nearestGraphicsProxyWidget(origin->parentWidget());
5896 }
5897 return nullptr;
5898}
5899#endif
5900
5901/*!
5902 \property QWidget::locale
5903 \brief the widget's locale
5904 \since 4.3
5905
5906 As long as no special locale has been set, this is either
5907 the parent's locale or (if this widget is a top level widget),
5908 the default locale.
5909
5910 If the widget displays dates or numbers, these should be formatted
5911 using the widget's locale.
5912
5913 \sa QLocale, QLocale::setDefault()
5914*/
5915
5916void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
5917{
5918 Q_Q(QWidget);
5919 if (locale == loc && !forceUpdate)
5920 return;
5921
5922 locale = loc;
5923
5924 if (!children.isEmpty()) {
5925 for (int i = 0; i < children.size(); ++i) {
5926 QWidget *w = qobject_cast<QWidget*>(children.at(i));
5927 if (!w)
5928 continue;
5929 if (w->testAttribute(Qt::WA_SetLocale))
5930 continue;
5931 if (w->isWindow() && !w->testAttribute(Qt::WA_WindowPropagation))
5932 continue;
5933 w->d_func()->setLocale_helper(loc, forceUpdate);
5934 }
5935 }
5936 QEvent e(QEvent::LocaleChange);
5937 QCoreApplication::sendEvent(q, &e);
5938}
5939
5940void QWidget::setLocale(const QLocale &locale)
5941{
5942 Q_D(QWidget);
5943
5944 setAttribute(Qt::WA_SetLocale);
5945 d->setLocale_helper(locale);
5946}
5947
5948QLocale QWidget::locale() const
5949{
5950 Q_D(const QWidget);
5951
5952 return d->locale;
5953}
5954
5955void QWidgetPrivate::resolveLocale()
5956{
5957 Q_Q(const QWidget);
5958
5959 if (!q->testAttribute(Qt::WA_SetLocale)) {
5960 QWidget *parent = q->parentWidget();
5961 setLocale_helper(!parent || (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
5962 ? QLocale() : parent->locale());
5963 }
5964}
5965
5966void QWidget::unsetLocale()
5967{
5968 Q_D(QWidget);
5969 setAttribute(Qt::WA_SetLocale, false);
5970 d->resolveLocale();
5971}
5972
5973/*!
5974 \property QWidget::windowTitle
5975 \brief the window title (caption)
5976
5977 This property only makes sense for top-level widgets, such as
5978 windows and dialogs. If no caption has been set, the title is based of the
5979 \l windowFilePath. If neither of these is set, then the title is
5980 an empty string.
5981
5982 If you use the \l windowModified mechanism, the window title must
5983 contain a "[*]" placeholder, which indicates where the '*' should
5984 appear. Normally, it should appear right after the file name
5985 (e.g., "document1.txt[*] - Text Editor"). If the \l
5986 windowModified property is \c false (the default), the placeholder
5987 is simply removed.
5988
5989 On some desktop platforms (including Windows and Unix), the application name
5990 (from QGuiApplication::applicationDisplayName) is added at the end of the
5991 window title, if set. This is done by the QPA plugin, so it is shown to the
5992 user, but isn't part of the windowTitle string.
5993
5994 \sa windowIcon, windowModified, windowFilePath
5995*/
5996QString QWidget::windowTitle() const
5997{
5998 Q_D(const QWidget);
5999 if (d->extra && d->extra->topextra) {
6000 if (!d->extra->topextra->caption.isEmpty())
6001 return d->extra->topextra->caption;
6002 if (!d->extra->topextra->filePath.isEmpty())
6003 return QFileInfo(d->extra->topextra->filePath).fileName() + "[*]"_L1;
6004 }
6005 return QString();
6006}
6007
6008/*!
6009 Returns a modified window title with the [*] place holder
6010 replaced according to the rules described in QWidget::setWindowTitle
6011
6012 This function assumes that "[*]" can be quoted by another
6013 "[*]", so it will replace two place holders by one and
6014 a single last one by either "*" or nothing depending on
6015 the modified flag.
6016
6017 \internal
6018*/
6019QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
6020{
6021 Q_ASSERT(widget);
6022
6023 QString cap = title;
6024 if (cap.isEmpty())
6025 return cap;
6026
6027 const auto placeHolder = "[*]"_L1;
6028 int index = cap.indexOf(placeHolder);
6029
6030 // here the magic begins
6031 while (index != -1) {
6032 index += placeHolder.size();
6033 int count = 1;
6034 while (cap.indexOf(placeHolder, index) == index) {
6035 ++count;
6036 index += placeHolder.size();
6037 }
6038
6039 if (count%2) { // odd number of [*] -> replace last one
6040 int lastIndex = cap.lastIndexOf(placeHolder, index - 1);
6041 if (widget->isWindowModified()
6042 && widget->style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, nullptr, widget))
6043 cap.replace(lastIndex, 3, QWidget::tr("*"));
6044 else
6045 cap.remove(lastIndex, 3);
6046 }
6047
6048 index = cap.indexOf(placeHolder, index);
6049 }
6050
6051 cap.replace("[*][*]"_L1, placeHolder);
6052
6053 return cap;
6054}
6055
6056void QWidgetPrivate::setWindowTitle_helper(const QString &title)
6057{
6058 Q_Q(QWidget);
6059 if (q->testAttribute(Qt::WA_WState_Created))
6060 setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, q));
6061}
6062
6063void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
6064{
6065 Q_Q(QWidget);
6066 if (!q->isWindow())
6067 return;
6068
6069 if (QWindow *window = q->windowHandle())
6070 {
6071#if QT_CONFIG(accessibility)
6072 QString oldAccessibleName;
6073 const QAccessibleInterface *accessible = QAccessible::isActive()
6074 ? QAccessible::queryAccessibleInterface(q)
6075 : nullptr;
6076 if (accessible)
6077 oldAccessibleName = accessible->text(QAccessible::Name);
6078#endif
6079
6080 window->setTitle(caption);
6081
6082#if QT_CONFIG(accessibility)
6083 if (accessible && accessible->text(QAccessible::Name) != oldAccessibleName) {
6084 QAccessibleEvent event(q, QAccessible::NameChanged);
6085 QAccessible::updateAccessibility(&event);
6086 }
6087#endif
6088 }
6089}
6090
6091void QWidgetPrivate::setWindowIconText_helper(const QString &title)
6092{
6093 Q_Q(QWidget);
6094 if (q->testAttribute(Qt::WA_WState_Created))
6095 setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, q));
6096}
6097
6098void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
6099{
6100#if QT_CONFIG(xcb)
6101 Q_Q(QWidget);
6102 // ### The QWidget property is deprecated, but the XCB window function is not.
6103 // It should remain available for the rare application that needs it.
6104 if (QWindow *window = q->windowHandle()) {
6105 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(window->handle()))
6106 xcbWindow->setWindowIconText(iconText);
6107 }
6108#else
6109 Q_UNUSED(iconText);
6110#endif
6111}
6112
6113/*!
6114 \fn void QWidget::windowIconTextChanged(const QString &iconText)
6115
6116 This signal is emitted when the window's icon text has changed, with the
6117 new \a iconText as an argument.
6118
6119 \since 5.2
6120 \deprecated
6121
6122 This signal is deprecated.
6123*/
6124
6125void QWidget::setWindowIconText(const QString &iconText)
6126{
6127 if (QWidget::windowIconText() == iconText)
6128 return;
6129
6130 Q_D(QWidget);
6131 d->topData()->iconText = iconText;
6132 d->setWindowIconText_helper(iconText);
6133
6134 QEvent e(QEvent::IconTextChange);
6135 QCoreApplication::sendEvent(this, &e);
6136
6137 emit windowIconTextChanged(iconText);
6138}
6139
6140/*!
6141 \fn void QWidget::windowTitleChanged(const QString &title)
6142
6143 This signal is emitted when the window's title has changed, with the
6144 new \a title as an argument.
6145
6146 \since 5.2
6147*/
6148
6149void QWidget::setWindowTitle(const QString &title)
6150{
6151 if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
6152 return;
6153
6154 Q_D(QWidget);
6155 d->topData()->caption = title;
6156 d->setWindowTitle_helper(title);
6157
6158 QEvent e(QEvent::WindowTitleChange);
6159 QCoreApplication::sendEvent(this, &e);
6160
6161 emit windowTitleChanged(title);
6162}
6163
6164
6165/*!
6166 \property QWidget::windowIcon
6167 \brief the widget's icon
6168
6169 This property only makes sense for windows. If no icon
6170 has been set, windowIcon() returns the application icon
6171 (QApplication::windowIcon()).
6172
6173 \note On \macos, window icons represent the active document,
6174 and will not be displayed unless a file path has also been
6175 set using setWindowFilePath.
6176
6177 \sa windowTitle, setWindowFilePath
6178*/
6179QIcon QWidget::windowIcon() const
6180{
6181 const QWidget *w = this;
6182 while (w) {
6183 const QWidgetPrivate *d = w->d_func();
6184 if (d->extra && d->extra->topextra && d->extra->topextra->icon)
6185 return *d->extra->topextra->icon;
6186 w = w->parentWidget();
6187 }
6188 return QApplication::windowIcon();
6189}
6190
6191void QWidgetPrivate::setWindowIcon_helper()
6192{
6193 Q_Q(QWidget);
6194 QEvent e(QEvent::WindowIconChange);
6195
6196 // Do not send the event if the widget is a top level.
6197 // In that case, setWindowIcon_sys does it, and event propagation from
6198 // QWidgetWindow to the top level QWidget ensures that the event reaches
6199 // the top level anyhow
6200 if (!q->windowHandle())
6201 QCoreApplication::sendEvent(q, &e);
6202 for (int i = 0; i < children.size(); ++i) {
6203 QWidget *w = qobject_cast<QWidget *>(children.at(i));
6204 if (w && !w->isWindow())
6205 QCoreApplication::sendEvent(w, &e);
6206 }
6207}
6208
6209/*!
6210 \fn void QWidget::windowIconChanged(const QIcon &icon)
6211
6212 This signal is emitted when the window's icon has changed, with the
6213 new \a icon as an argument.
6214
6215 \since 5.2
6216*/
6217
6218void QWidget::setWindowIcon(const QIcon &icon)
6219{
6220 Q_D(QWidget);
6221
6222 setAttribute(Qt::WA_SetWindowIcon, !icon.isNull());
6223 d->createTLExtra();
6224
6225 if (!d->extra->topextra->icon)
6226 d->extra->topextra->icon = std::make_unique<QIcon>(icon);
6227 else
6228 *d->extra->topextra->icon = icon;
6229
6230 d->setWindowIcon_sys();
6231 d->setWindowIcon_helper();
6232
6233 emit windowIconChanged(icon);
6234}
6235
6236void QWidgetPrivate::setWindowIcon_sys()
6237{
6238 Q_Q(QWidget);
6239 if (QWindow *window = q->windowHandle())
6240 window->setIcon(q->windowIcon());
6241}
6242
6243/*!
6244 \property QWidget::windowIconText
6245 \brief the text to be displayed on the icon of a minimized window
6246
6247 This property only makes sense for windows. If no icon
6248 text has been set, this accessor returns an empty string.
6249 It is only implemented on the X11 platform, and only certain
6250 window managers use this window property.
6251
6252 \deprecated
6253 This property is deprecated.
6254
6255 \sa windowIcon, windowTitle
6256*/
6257
6258QString QWidget::windowIconText() const
6259{
6260 Q_D(const QWidget);
6261 return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
6262}
6263
6264/*!
6265 \property QWidget::windowFilePath
6266 \since 4.4
6267 \brief the file path associated with a widget
6268
6269 This property only makes sense for windows. It associates a file path with
6270 a window. If you set the file path, but have not set the window title, Qt
6271 sets the window title to the file name of the specified path, obtained using
6272 QFileInfo::fileName().
6273
6274 If the window title is set at any point, then the window title takes precedence and
6275 will be shown instead of the file path string.
6276
6277 Additionally, on \macos, this has an added benefit that it sets the
6278 \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
6279 for the window, assuming that the file path exists.
6280
6281 If no file path is set, this property contains an empty string.
6282
6283 By default, this property contains an empty string.
6284
6285 \sa windowTitle, windowIcon
6286*/
6287
6288QString QWidget::windowFilePath() const
6289{
6290 Q_D(const QWidget);
6291 return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
6292}
6293
6294void QWidget::setWindowFilePath(const QString &filePath)
6295{
6296 if (filePath == windowFilePath())
6297 return;
6298
6299 Q_D(QWidget);
6300
6301 d->createTLExtra();
6302 d->extra->topextra->filePath = filePath;
6303 d->setWindowFilePath_helper(filePath);
6304}
6305
6306void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
6307{
6308 if (extra->topextra && extra->topextra->caption.isEmpty()) {
6309#ifdef Q_OS_MACOS
6310 setWindowTitle_helper(QFileInfo(filePath).fileName());
6311#else
6312 Q_Q(QWidget);
6313 Q_UNUSED(filePath);
6314 setWindowTitle_helper(q->windowTitle());
6315#endif
6316 }
6317#ifdef Q_OS_MACOS
6318 setWindowFilePath_sys(filePath);
6319#endif
6320}
6321
6322void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
6323{
6324 Q_Q(QWidget);
6325 if (!q->isWindow())
6326 return;
6327
6328 if (QWindow *window = q->windowHandle())
6329 window->setFilePath(filePath);
6330}
6331
6332/*!
6333 Returns the window's role, or an empty string.
6334
6335 \sa windowIcon, windowTitle
6336*/
6337
6338QString QWidget::windowRole() const
6339{
6340 Q_D(const QWidget);
6341 return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
6342}
6343
6344/*!
6345 Sets the window's role to \a role. This only makes sense for
6346 windows on X11.
6347*/
6348void QWidget::setWindowRole(const QString &role)
6349{
6350#if QT_CONFIG(xcb) || QT_CONFIG(wayland)
6351 Q_D(QWidget);
6352 d->createTLExtra();
6353 d->topData()->role = role;
6354#else
6355 Q_UNUSED(role);
6356#endif
6357
6358 if (windowHandle()) {
6359#if QT_CONFIG(xcb)
6360 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(windowHandle()->handle()))
6361 xcbWindow->setWindowRole(role);
6362#endif
6363#if QT_CONFIG(wayland)
6364 if (auto *waylandWindow = dynamic_cast<QWaylandWindow*>(windowHandle()->handle()))
6365 waylandWindow->setSessionRestoreId(role);
6366#endif
6367 }
6368}
6369
6370/*!
6371 \property QWidget::mouseTracking
6372 \brief whether mouse tracking is enabled for the widget
6373
6374 If mouse tracking is disabled (the default), the widget only
6375 receives mouse move events when at least one mouse button is
6376 pressed while the mouse is being moved.
6377
6378 If mouse tracking is enabled, the widget receives mouse move
6379 events even if no buttons are pressed.
6380
6381 \sa mouseMoveEvent()
6382*/
6383
6384/*!
6385 \property QWidget::tabletTracking
6386 \brief whether tablet tracking is enabled for the widget
6387 \since 5.9
6388
6389 If tablet tracking is disabled (the default), the widget only
6390 receives tablet move events when the stylus is in contact with
6391 the tablet, or at least one stylus button is pressed,
6392 while the stylus is being moved.
6393
6394 If tablet tracking is enabled, the widget receives tablet move
6395 events even while hovering in proximity. This is useful for
6396 monitoring position as well as the auxiliary properties such
6397 as rotation and tilt, and providing feedback in the UI.
6398
6399 \sa tabletEvent()
6400*/
6401
6402
6403/*!
6404 Sets the widget's focus proxy to widget \a w. If \a w is \nullptr, the
6405 function resets this widget to have no focus proxy.
6406
6407 Some widgets can "have focus", but create a child widget, such as
6408 QLineEdit, to actually handle the focus. In this case, the widget
6409 can set the line edit to be its focus proxy.
6410
6411 setFocusProxy() sets the widget which will actually get focus when
6412 "this widget" gets it. If there is a focus proxy, setFocus() and
6413 hasFocus() operate on the focus proxy. If "this widget" is the focus
6414 widget, then setFocusProxy() moves focus to the new focus proxy.
6415
6416 \sa focusProxy()
6417*/
6418
6419void QWidget::setFocusProxy(QWidget * w)
6420{
6421 Q_D(QWidget);
6422 if (!w && !d->extra)
6423 return;
6424
6425 for (QWidget* fp = w; fp; fp = fp->focusProxy()) {
6426 if (Q_UNLIKELY(fp == this)) {
6427 qWarning("QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
6428 return;
6429 }
6430 }
6431
6432 const bool moveFocusToProxy = (QApplicationPrivate::focus_widget == this);
6433
6434 d->createExtra();
6435 d->extra->focus_proxy = w;
6436
6437 if (w && isAncestorOf(w)) {
6438 // If the focus proxy is a child of this (so this is a compound widget), then
6439 // we need to make sure that this widget is immediately in front of its own children
6440 // in the focus chain. Otherwise focusNextPrev_helper might jump over unrelated
6441 // widgets that are positioned between this compound widget, and its proxy in
6442 // the focus chain.
6443 const QWidget *parentOfW = w->parentWidget();
6444 Q_ASSERT(parentOfW); // can't be nullptr since we are an ancestor of w
6445 QWidget *firstChild = nullptr;
6446 const auto childList = children();
6447 for (QObject *child : childList) {
6448 if ((firstChild = qobject_cast<QWidget *>(child)))
6449 break;
6450 }
6451 Q_ASSERT(firstChild); // can't be nullptr since w is a child
6452 d->insertIntoFocusChainBefore(firstChild);
6453 } else if (w && w->isAncestorOf(this)) {
6454 // If the focus proxy is a parent, 'this' has to be inserted directly after its parent in the focus chain
6455 // remove it from the chain and insert this into the focus chain after its parent
6456
6457 // is this the case already?
6458 QWidget *parentsNext = w->nextInFocusChain();
6459 if (parentsNext == this) {
6460 // nothing to do.
6461 Q_ASSERT(previousInFocusChain() == w);
6462 } else {
6463 d->QWidgetPrivate::insertIntoFocusChainAfter(w);
6464 }
6465 }
6466
6467 if (moveFocusToProxy)
6468 setFocus(Qt::OtherFocusReason);
6469}
6470
6471
6472/*!
6473 Returns the focus proxy, or \nullptr if there is no focus proxy.
6474
6475 \sa setFocusProxy()
6476*/
6477
6478QWidget *QWidget::focusProxy() const
6479{
6480 Q_D(const QWidget);
6481 return d->extra ? d->extra->focus_proxy.data() : nullptr;
6482}
6483
6484
6485/*!
6486 \property QWidget::focus
6487 \brief whether this widget (or its focus proxy) has the keyboard
6488 input focus
6489
6490 By default, this property is \c false.
6491
6492 \note Obtaining the value of this property for a widget is effectively equivalent
6493 to checking whether QApplication::focusWidget() refers to the widget.
6494
6495 \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
6496*/
6497bool QWidget::hasFocus() const
6498{
6499 const QWidget* w = this;
6500 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
6501 w = w->d_func()->extra->focus_proxy;
6502#if QT_CONFIG(graphicsview)
6503 if (QWidget *window = w->window()) {
6504 const auto &e = window->d_func()->extra;
6505 if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
6506 return true;
6507 }
6508#endif // QT_CONFIG(graphicsview)
6509 return (QApplication::focusWidget() == w);
6510}
6511
6512/*!
6513 Gives the keyboard input focus to this widget (or its focus
6514 proxy) if this widget or one of its parents is the \l{isActiveWindow()}{active window}. The \a reason argument will
6515 be passed into any focus event sent from this function, it is used
6516 to give an explanation of what caused the widget to get focus.
6517 If the window is not active, the widget will be given the focus when
6518 the window becomes active.
6519
6520 First, a focus about to change event is sent to the focus widget (if any) to
6521 tell it that it is about to lose the focus. Then focus is changed, a
6522 focus out event is sent to the previous focus item and a focus in event is sent
6523 to the new item to tell it that it just received the focus.
6524 (Nothing happens if the focus in and focus out widgets are the
6525 same.)
6526
6527 \note On embedded platforms, setFocus() will not cause an input panel
6528 to be opened by the input method. If you want this to happen, you
6529 have to send a QEvent::RequestSoftwareInputPanel event to the
6530 widget yourself.
6531
6532 setFocus() gives focus to a widget regardless of its focus policy,
6533 but does not clear any keyboard grab (see grabKeyboard()).
6534
6535 Be aware that if the widget is hidden, it will not accept focus
6536 until it is shown.
6537
6538 \warning If you call setFocus() in a function which may itself be
6539 called from focusOutEvent() or focusInEvent(), you may get an
6540 infinite recursion.
6541
6542 \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
6543 setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
6544 grabMouse(), {Keyboard Focus in Widgets}, QEvent::RequestSoftwareInputPanel
6545*/
6546
6547void QWidget::setFocus(Qt::FocusReason reason)
6548{
6549 if (!isEnabled())
6550 return;
6551
6552 QWidget *f = d_func()->deepestFocusProxy();
6553 if (!f)
6554 f = this;
6555
6556 if (QApplication::focusWidget() == f)
6557 return;
6558
6559#if QT_CONFIG(graphicsview)
6560 QWidget *previousProxyFocus = nullptr;
6561 if (const auto &topData = window()->d_func()->extra) {
6562 if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
6563 previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
6564 if (previousProxyFocus && previousProxyFocus->focusProxy())
6565 previousProxyFocus = previousProxyFocus->focusProxy();
6566 if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
6567 return;
6568 }
6569 }
6570#endif
6571
6572#if QT_CONFIG(graphicsview)
6573 // Update proxy state
6574 if (const auto &topData = window()->d_func()->extra) {
6575 if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
6576 f->d_func()->updateFocusChild();
6577 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
6578 topData->proxyWidget->setFocus(reason);
6579 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
6580 }
6581 }
6582#endif
6583
6584 if (f->isActiveWindow()) {
6585 QWidget *prev = QApplicationPrivate::focus_widget;
6586 if (prev) {
6587 if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
6588 && prev->testAttribute(Qt::WA_InputMethodEnabled)) {
6589 QGuiApplication::inputMethod()->commit();
6590 }
6591
6592 if (reason != Qt::NoFocusReason) {
6593 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
6594 QCoreApplication::sendEvent(prev, &focusAboutToChange);
6595 }
6596 }
6597
6598 f->d_func()->updateFocusChild();
6599
6600 QApplicationPrivate::setFocusWidget(f, reason);
6601#if QT_CONFIG(accessibility)
6602 // menus update the focus manually and this would create bogus events
6603 if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem")))
6604 {
6605 QAccessibleEvent event(f, QAccessible::Focus);
6606 QAccessible::updateAccessibility(&event);
6607 }
6608#endif
6609#if QT_CONFIG(graphicsview)
6610 if (const auto &topData = window()->d_func()->extra) {
6611 if (topData->proxyWidget) {
6612 if (previousProxyFocus && previousProxyFocus != f) {
6613 // Send event to self
6614 QFocusEvent event(QEvent::FocusOut, reason);
6615 QPointer<QWidget> that = previousProxyFocus;
6616 QCoreApplication::sendEvent(previousProxyFocus, &event);
6617 if (that)
6618 QCoreApplication::sendEvent(that->style(), &event);
6619 }
6620 if (!isHidden()) {
6621#if QT_CONFIG(graphicsview)
6622 // Update proxy state
6623 if (const auto &topData = window()->d_func()->extra)
6624 if (topData->proxyWidget && topData->proxyWidget->hasFocus())
6625 topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget();
6626#endif
6627 // Send event to self
6628 QFocusEvent event(QEvent::FocusIn, reason);
6629 QPointer<QWidget> that = f;
6630 QCoreApplication::sendEvent(f, &event);
6631 if (that)
6632 QCoreApplication::sendEvent(that->style(), &event);
6633 }
6634 }
6635 }
6636#endif
6637 } else {
6638 f->d_func()->updateFocusChild();
6639 }
6640}
6641
6642
6643/*!\internal
6644 * A focus proxy can have its own focus proxy, which can have its own
6645 * proxy, and so on. This helper function returns the widget that sits
6646 * at the bottom of the proxy chain, and therefore the one that should
6647 * normally get focus if this widget receives a focus request.
6648 */
6649QWidget *QWidgetPrivate::deepestFocusProxy() const
6650{
6651 Q_Q(const QWidget);
6652
6653 QWidget *focusProxy = q->focusProxy();
6654 if (!focusProxy)
6655 return nullptr;
6656
6657 while (QWidget *nextFocusProxy = focusProxy->focusProxy())
6658 focusProxy = nextFocusProxy;
6659
6660 return focusProxy;
6661}
6662
6663static inline bool isEmbedded(const QWindow *w)
6664{
6665 const auto platformWindow = w->handle();
6666 return platformWindow && platformWindow->isEmbedded();
6667}
6668
6669void QWidgetPrivate::setFocus_sys()
6670{
6671 Q_Q(QWidget);
6672 // Embedded native widget may have taken the focus; get it back to toplevel
6673 // if that is the case (QTBUG-25852), unless widget is a window container.
6674 if (extra && extra->hasWindowContainer)
6675 return;
6676 // Do not activate in case the popup menu opens another application (QTBUG-70810)
6677 // unless the application is embedded (QTBUG-71991).
6678 if (QWindow *nativeWindow = q->testAttribute(Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) {
6679 if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow()
6680 && (QGuiApplication::applicationState() == Qt::ApplicationActive
6681 || QCoreApplication::testAttribute(Qt::AA_PluginApplication)
6682 || isEmbedded(nativeWindow))) {
6683 nativeWindow->requestActivate();
6684 }
6685 }
6686}
6687
6688// updates focus_child on parent widgets to point into this widget
6689void QWidgetPrivate::updateFocusChild()
6690{
6691 Q_Q(QWidget);
6692
6693 QWidget *w = q;
6694 if (q->isHidden()) {
6695 while (w && w->isHidden()) {
6696 w->d_func()->focus_child = q;
6697 w = w->isWindow() ? nullptr : w->parentWidget();
6698 }
6699 } else {
6700 while (w) {
6701 w->d_func()->focus_child = q;
6702 w = w->isWindow() ? nullptr : w->parentWidget();
6703 }
6704 }
6705
6706 if (QTLWExtra *extra = q->window()->d_func()->maybeTopData()) {
6707 if (extra->window)
6708 emit extra->window->focusObjectChanged(q);
6709 }
6710}
6711
6712/*!
6713 \fn void QWidget::setFocus()
6714 \overload
6715
6716 Gives the keyboard input focus to this widget (or its focus
6717 proxy) if this widget or one of its parents is the
6718 \l{isActiveWindow()}{active window}.
6719*/
6720
6721/*!
6722 Takes keyboard input focus from the widget.
6723
6724 If the widget has active focus, a \l{focusOutEvent()}{focus out event} is sent to this widget to tell it that it has
6725 lost the focus.
6726
6727 This widget must enable focus setting to get the keyboard
6728 input focus; that is, it must call setFocusPolicy().
6729
6730 \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
6731 setFocusPolicy(), QApplication::focusWidget()
6732*/
6733
6734void QWidget::clearFocus()
6735{
6736 if (hasFocus()) {
6737 if (testAttribute(Qt::WA_InputMethodEnabled))
6738 QGuiApplication::inputMethod()->commit();
6739
6740 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
6741 QCoreApplication::sendEvent(this, &focusAboutToChange);
6742 }
6743
6744 QTLWExtra *extra = window()->d_func()->maybeTopData();
6745 QObject *originalFocusObject = nullptr;
6746 if (extra && extra->window) {
6747 originalFocusObject = extra->window->focusObject();
6748 // the window's focus object might already be nullptr if we are in the destructor, but we still
6749 // need to update QGuiApplication and input context if we have a focus widget.
6750 if (!originalFocusObject)
6751 originalFocusObject = focusWidget();
6752 }
6753
6754 QWidget *w = this;
6755 while (w) {
6756 // Just like setFocus(), we update (clear) the focus_child of our parents
6757 if (w->d_func()->focus_child == this)
6758 w->d_func()->focus_child = nullptr;
6759 w = w->parentWidget();
6760 }
6761
6762 // We've potentially cleared the focus_child of our parents, so we need
6763 // to report this to the rest of Qt. Note that the focus_child is not the same
6764 // thing as the application's focusWidget, which is why this piece of code is
6765 // not inside a hasFocus() block.
6766 if (originalFocusObject && originalFocusObject != extra->window->focusObject())
6767 emit extra->window->focusObjectChanged(extra->window->focusObject());
6768
6769#if QT_CONFIG(graphicsview)
6770 const auto &topData = d_func()->extra;
6771 if (topData && topData->proxyWidget)
6772 topData->proxyWidget->clearFocus();
6773#endif
6774
6775 if (hasFocus()) {
6776 // Update proxy state
6777 QApplicationPrivate::setFocusWidget(nullptr, Qt::OtherFocusReason);
6778#if QT_CONFIG(accessibility)
6779 QAccessibleEvent event(this, QAccessible::Focus);
6780 QAccessible::updateAccessibility(&event);
6781#endif
6782 }
6783}
6784
6785
6786/*!
6787 \fn bool QWidget::focusNextChild()
6788
6789 Finds a new widget to give the keyboard focus to, as appropriate
6790 for \uicontrol Tab, and returns \c true if it can find a new widget, or
6791 false if it can't.
6792
6793 \sa focusPreviousChild()
6794*/
6795
6796/*!
6797 \fn bool QWidget::focusPreviousChild()
6798
6799 Finds a new widget to give the keyboard focus to, as appropriate
6800 for \uicontrol Shift+Tab, and returns \c true if it can find a new widget,
6801 or false if it can't.
6802
6803 \sa focusNextChild()
6804*/
6805
6806/*!
6807 Finds a new widget to give the keyboard focus to, as appropriate
6808 for Tab and Shift+Tab, and returns \c true if it can find a new
6809 widget, or false if it can't.
6810
6811 If \a next is true, this function searches forward, if \a next
6812 is false, it searches backward.
6813
6814 Sometimes, you will want to reimplement this function. For
6815 example, a web browser might reimplement it to move its "current
6816 active link" forward or backward, and call
6817 focusNextPrevChild() only when it reaches the last or
6818 first link on the "page".
6819
6820 Child widgets call focusNextPrevChild() on their parent widgets,
6821 but only the window that contains the child widgets decides where
6822 to redirect focus. By reimplementing this function for an object,
6823 you thus gain control of focus traversal for all child widgets.
6824
6825 \sa focusNextChild(), focusPreviousChild()
6826*/
6827
6828bool QWidget::focusNextPrevChild(bool next)
6829{
6830 QWidget* p = parentWidget();
6831 bool isSubWindow = (windowType() == Qt::SubWindow);
6832 if (!isWindow() && !isSubWindow && p)
6833 return p->focusNextPrevChild(next);
6834#if QT_CONFIG(graphicsview)
6835 Q_D(QWidget);
6836 if (d->extra && d->extra->proxyWidget)
6837 return d->extra->proxyWidget->focusNextPrevChild(next);
6838#endif
6839
6840 bool wrappingOccurred = false;
6841 QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(this, next,
6842 &wrappingOccurred);
6843 if (!w) return false;
6844
6845 Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
6846
6847 /* If we are about to wrap the focus chain, give the platform
6848 * implementation a chance to alter the wrapping behavior. This is
6849 * especially needed when the window is embedded in a window created by
6850 * another process.
6851 */
6852 if (wrappingOccurred) {
6853 QWindow *window = windowHandle();
6854 if (window != nullptr) {
6855 QWindowPrivate *winp = qt_window_private(window);
6856
6857 if (winp->platformWindow != nullptr) {
6858 QFocusEvent event(QEvent::FocusIn, reason);
6859 event.ignore();
6860 winp->platformWindow->windowEvent(&event);
6861 if (event.isAccepted()) return true;
6862 }
6863 }
6864 }
6865
6866 w->setFocus(reason);
6867 return true;
6868}
6869
6870/*!
6871 Returns the last child of this widget that setFocus had been
6872 called on. For top level widgets this is the widget that will get
6873 focus in case this window gets activated
6874
6875 This is not the same as QApplication::focusWidget(), which returns
6876 the focus widget in the currently active window.
6877*/
6878
6879QWidget *QWidget::focusWidget() const
6880{
6881 return const_cast<QWidget *>(d_func()->focus_child);
6882}
6883
6884QObject *QWidgetPrivate::focusObject()
6885{
6886 Q_Q(QWidget);
6887 QWidget *proxy = deepestFocusProxy();
6888 return proxy ? proxy : q;
6889}
6890
6891/*!
6892 Returns the next widget in this widget's focus chain.
6893
6894 \sa previousInFocusChain()
6895*/
6896QWidget *QWidget::nextInFocusChain() const
6897{
6898 Q_D(const QWidget);
6899 return d->nextPrevElementInFocusChain(QWidgetPrivate::FocusDirection::Next);
6900}
6901
6902/*!
6903 \brief The previousInFocusChain function returns the previous
6904 widget in this widget's focus chain.
6905
6906 \sa nextInFocusChain()
6907
6908 \since 4.6
6909*/
6910QWidget *QWidget::previousInFocusChain() const
6911{
6912 Q_D(const QWidget);
6913 return d->nextPrevElementInFocusChain(QWidgetPrivate::FocusDirection::Previous);
6914}
6915
6916/*!
6917 \property QWidget::isActiveWindow
6918 \brief whether this widget's window is the active window
6919
6920 The active window is the window that contains the widget that has
6921 keyboard focus (The window may still have focus if it has no
6922 widgets or none of its widgets accepts keyboard focus).
6923
6924 When popup windows are visible, this property is \c true for both the
6925 active window \e and for the popup.
6926
6927 By default, this property is \c false.
6928
6929 \sa activateWindow(), QApplication::activeWindow()
6930*/
6931bool QWidget::isActiveWindow() const
6932{
6933 QWidget *tlw = window();
6934 if (tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
6935 return true;
6936
6937#if QT_CONFIG(graphicsview)
6938 if (const auto &tlwExtra = tlw->d_func()->extra) {
6939 if (isVisible() && tlwExtra->proxyWidget)
6940 return tlwExtra->proxyWidget->isActiveWindow();
6941 }
6942#endif
6943
6944 if (style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, this)) {
6945 if (tlw->windowType() == Qt::Tool &&
6946 !tlw->isModal() &&
6947 (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
6948 return true;
6949 QWidget *w = QApplication::activeWindow();
6950 while(w && tlw->windowType() == Qt::Tool &&
6951 !w->isModal() && w->parentWidget()) {
6952 w = w->parentWidget()->window();
6953 if (w == tlw)
6954 return true;
6955 }
6956 }
6957
6958 // Check for an active window container
6959 if (QWindow *ww = QGuiApplication::focusWindow()) {
6960 while (ww) {
6961 QWidgetWindow *qww = qobject_cast<QWidgetWindow *>(ww);
6962 QWindowContainer *qwc = qww ? qobject_cast<QWindowContainer *>(qww->widget()) : 0;
6963 if (qwc && qwc->topLevelWidget() == tlw)
6964 return true;
6965 ww = ww->parent();
6966 }
6967 }
6968
6969 // Check if platform adaptation thinks the window is active. This is necessary for
6970 // example in case of ActiveQt servers that are embedded into another application.
6971 // Those are separate processes that are not part of the parent application Qt window/widget
6972 // hierarchy, so they need to rely on native methods to determine if they are part of the
6973 // active window.
6974 if (const QWindow *w = tlw->windowHandle()) {
6975 if (w->handle())
6976 return w->handle()->isActive();
6977 }
6978
6979 return false;
6980}
6981
6982/*!
6983 \fn void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
6984 \overload
6985 \since 6.6
6986
6987 Sets the tab order for the widgets in the \a widgets list by calling
6988 \l{QWidget::setTabOrder(QWidget *, QWidget *)} for each consecutive
6989 pair of widgets.
6990
6991 Instead of setting up each pair manually like this:
6992
6993 \snippet code/src_gui_kernel_qwidget.cpp 9
6994
6995 you can call:
6996
6997 \snippet code/src_gui_kernel_qwidget.cpp 9.list
6998
6999 The call does not create a closed tab focus loop. If there are more widgets
7000 with \l{Qt::TabFocus} focus policy, tabbing on \c{d} will move focus to one
7001 of those widgets, not back to \c{a}.
7002
7003 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7004*/
7005
7006/*!
7007 Puts the \a second widget after the \a first widget in the focus order.
7008
7009 It effectively removes the \a second widget from its focus chain and
7010 inserts it after the \a first widget.
7011
7012 Note that since the tab order of the \a second widget is changed, you
7013 should order a chain like this:
7014
7015 \snippet code/src_gui_kernel_qwidget.cpp 9
7016
7017 \e not like this:
7018
7019 \snippet code/src_gui_kernel_qwidget.cpp 10
7020
7021 If \a first or \a second has a focus proxy, setTabOrder()
7022 correctly substitutes the proxy.
7023
7024 \note Since Qt 5.10: A widget that has a child as focus proxy is understood as
7025 a compound widget. When setting a tab order between one or two compound widgets, the
7026 local tab order inside each will be preserved. This means that if both widgets are
7027 compound widgets, the resulting tab order will be from the last child inside
7028 \a first, to the first child inside \a second.
7029
7030 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7031*/
7032void QWidget::setTabOrder(QWidget* first, QWidget *second)
7033{
7034 if (!first || !second || first == second
7035 || first->focusPolicy() == Qt::NoFocus
7036 || second->focusPolicy() == Qt::NoFocus)
7037 return;
7038
7039 if (Q_UNLIKELY(first->window() != second->window())) {
7040 qWarning("QWidget::setTabOrder: 'first' and 'second' must be in the same window");
7041 return;
7042 }
7043
7044 const auto determineLastFocusChild = [](QWidget *target, QWidget *noFurtherThan)
7045 {
7046 // Since we need to repeat the same logic for both 'first' and 'second', we add a function that
7047 // determines the last focus child for a widget, taking proxies and compound widgets into account.
7048 // If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
7049 // 'lastFocusChild' will be set to the target itself.
7050 QWidget *lastFocusChild = target;
7051
7052 QWidget *focusProxy = target->d_func()->deepestFocusProxy();
7053 if (!focusProxy) {
7054 // QTBUG-81097: Another case is possible here. We can have a child
7055 // widget, that sets its focusProxy() to the parent (target).
7056 // An example of such widget is a QLineEdit, nested into
7057 // a QAbstractSpinBox. In this case such widget should be considered
7058 // the last focus child.
7059 for (auto *object : target->children()) {
7060 QWidget *w = qobject_cast<QWidget*>(object);
7061 if (w && w->focusProxy() == target) {
7062 lastFocusChild = w;
7063 break;
7064 }
7065 }
7066 } else if (target->isAncestorOf(focusProxy)) {
7067 lastFocusChild = focusProxy;
7068 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
7069 focusNext != focusProxy && target->isAncestorOf(focusNext) && focusNext->window() == focusProxy->window();
7070 focusNext = focusNext->nextInFocusChain()) {
7071 if (focusNext == noFurtherThan)
7072 break;
7073 if (focusNext->focusPolicy() != Qt::NoFocus)
7074 lastFocusChild = focusNext;
7075 }
7076 }
7077 return lastFocusChild;
7078 };
7079 // detect inflection in case we have compound widgets
7080 QWidget *lastFocusChildOfFirst = determineLastFocusChild(first, second);
7081 if (lastFocusChildOfFirst == second)
7082 lastFocusChildOfFirst = first;
7083 QWidget *lastFocusChildOfSecond = determineLastFocusChild(second, first);
7084 if (lastFocusChildOfSecond == first)
7085 lastFocusChildOfSecond = second;
7086
7087 // Return if only NoFocus widgets are between first and second
7088 QWidget *oldPrev = second->previousInFocusChain();
7089 QWidget *prevWithFocus = oldPrev;
7090 while (prevWithFocus->focusPolicy() == Qt::NoFocus)
7091 prevWithFocus = prevWithFocus->previousInFocusChain();
7092 if (prevWithFocus == first)
7093 return;
7094 const QWidgetList chain = QWidgetPrivate::takeFromFocusChain(second, lastFocusChildOfSecond);
7095 QWidgetPrivate::insertIntoFocusChain(chain, QWidgetPrivate::FocusDirection::Next, lastFocusChildOfFirst);
7096}
7097
7098void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
7099{
7100 QWidget *prev = nullptr;
7101 for (const auto &widget : widgets) {
7102 if (!prev) {
7103 prev = widget;
7104 } else {
7105 QWidget::setTabOrder(prev, widget);
7106 prev = widget;
7107 }
7108 }
7109}
7110
7111
7112/*!\internal
7113
7114 Moves the relevant subwidgets of this widget from the \a oldtlw's
7115 tab chain to that of the new parent, if there's anything to move and
7116 we're really moving
7117
7118 This function is called from QWidget::reparent() *after* the widget
7119 has been reparented.
7120
7121 \sa reparent()
7122*/
7123
7124void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
7125{
7126 Q_Q(QWidget);
7127 if (oldtlw == q->window())
7128 return; // nothing to do
7129
7130 if (focus_child)
7131 focus_child->clearFocus();
7132
7133 reparentFocusChildren(QWidgetPrivate::FocusDirection::Next);
7134}
7135
7136/*!
7137 \property QWidget::frameSize
7138 \brief the size of the widget including any window frame
7139
7140 By default, this property contains a value that depends on the user's
7141 platform and screen geometry.
7142*/
7143QSize QWidget::frameSize() const
7144{
7145 Q_D(const QWidget);
7146 if (isWindow() && !(windowType() == Qt::Popup)) {
7147 QRect fs = d->frameStrut();
7148 return QSize(data->crect.width() + fs.left() + fs.right(),
7149 data->crect.height() + fs.top() + fs.bottom());
7150 }
7151 return data->crect.size();
7152}
7153
7154/*! \fn void QWidget::move(int x, int y)
7155
7156 \overload
7157
7158 This corresponds to move(QPoint(\a x, \a y)).
7159*/
7160
7161void QWidget::move(const QPoint &p)
7162{
7163 Q_D(QWidget);
7164 setAttribute(Qt::WA_Moved);
7165 if (testAttribute(Qt::WA_WState_Created)) {
7166 if (isWindow())
7167 d->topData()->posIncludesFrame = false;
7168 d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
7169 p.y() + geometry().y() - QWidget::y(),
7170 width(), height(), true);
7171 d->setDirtyOpaqueRegion();
7172 } else {
7173 // no frame yet: see also QWidgetPrivate::fixPosIncludesFrame(), QWindowPrivate::PositionPolicy.
7174 if (isWindow())
7175 d->topData()->posIncludesFrame = true;
7176 data->crect.moveTopLeft(p); // no frame yet
7177 setAttribute(Qt::WA_PendingMoveEvent);
7178 }
7179
7180 if (d->extra && d->extra->hasWindowContainer)
7181 QWindowContainer::parentWasMoved(this);
7182}
7183
7184// move() was invoked with Qt::WA_WState_Created not set (frame geometry
7185// unknown), that is, crect has a position including the frame.
7186// If we can determine the frame strut, fix that and clear the flag.
7187// FIXME: This does not play well with window states other than
7188// Qt::WindowNoState, as we depend on calling setGeometry() on the
7189// platform window after fixing up the position so that the new
7190// geometry is reflected in the platform window, but when the frame
7191// comes in after the window has been shown (e.g. maximized), we're
7192// not in a position to do that kind of fixup.
7193void QWidgetPrivate::fixPosIncludesFrame()
7194{
7195 Q_Q(QWidget);
7196 if (QTLWExtra *te = maybeTopData()) {
7197 if (te->posIncludesFrame) {
7198 // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
7199 // example, in QGraphicsProxyWidget).
7200 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
7201 te->posIncludesFrame = 0;
7202 } else {
7203 if (q->windowHandle() && q->windowHandle()->handle()) {
7204 updateFrameStrut();
7205 if (!q->data->fstrut_dirty) {
7206 data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
7207 te->posIncludesFrame = 0;
7208 }
7209 } // windowHandle()
7210 } // !WA_DontShowOnScreen
7211 } // posIncludesFrame
7212 } // QTLWExtra
7213}
7214
7215/*! \fn void QWidget::resize(int w, int h)
7216 \overload
7217
7218 This corresponds to resize(QSize(\a w, \a h)).
7219*/
7220
7221void QWidget::resize(const QSize &s)
7222{
7223 Q_D(QWidget);
7224 setAttribute(Qt::WA_Resized);
7225 if (testAttribute(Qt::WA_WState_Created)) {
7226 d->fixPosIncludesFrame();
7227 d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
7228 d->setDirtyOpaqueRegion();
7229 } else {
7230 const auto oldRect = data->crect;
7231 data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize()));
7232 if (oldRect != data->crect)
7233 setAttribute(Qt::WA_PendingResizeEvent);
7234 }
7235}
7236
7237void QWidget::setGeometry(const QRect &r)
7238{
7239 Q_D(QWidget);
7240 setAttribute(Qt::WA_Resized);
7241 setAttribute(Qt::WA_Moved);
7242 if (isWindow())
7243 d->topData()->posIncludesFrame = 0;
7244 if (testAttribute(Qt::WA_WState_Created)) {
7245 d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
7246 d->setDirtyOpaqueRegion();
7247 } else {
7248 const auto oldRect = data->crect;
7249 data->crect.setTopLeft(r.topLeft());
7250 data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
7251 if (oldRect != data->crect) {
7252 setAttribute(Qt::WA_PendingMoveEvent);
7253 setAttribute(Qt::WA_PendingResizeEvent);
7254 }
7255 }
7256
7257 if (d->extra && d->extra->hasWindowContainer)
7258 QWindowContainer::parentWasMoved(this);
7259}
7260
7261void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
7262{
7263 Q_Q(QWidget);
7264 if (extra) { // any size restrictions?
7265 w = qMin(w,extra->maxw);
7266 h = qMin(h,extra->maxh);
7267 w = qMax(w,extra->minw);
7268 h = qMax(h,extra->minh);
7269 }
7270
7271 if (q->isWindow() && q->windowHandle()) {
7272 QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
7273 if (!integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)) {
7274 x = 0;
7275 y = 0;
7276 w = q->windowHandle()->width();
7277 h = q->windowHandle()->height();
7278 }
7279 }
7280
7281 QPoint oldp = q->geometry().topLeft();
7282 QSize olds = q->size();
7283 QRect r(x, y, w, h);
7284
7285 bool isResize = olds != r.size();
7286 if (!isMove)
7287 isMove = oldp != r.topLeft();
7288
7289
7290 // We only care about stuff that changes the geometry, or may
7291 // cause the window manager to change its state
7292 if (r.size() == olds && oldp == r.topLeft())
7293 return;
7294
7295 if (!data.in_set_window_state) {
7296 q->data->window_state &= ~Qt::WindowMaximized;
7297 q->data->window_state &= ~Qt::WindowFullScreen;
7298 if (q->isWindow())
7299 topData()->normalGeometry = QRect(0, 0, -1, -1);
7300 }
7301
7302 QPoint oldPos = q->pos();
7303 data.crect = r;
7304
7305 bool needsShow = false;
7306
7307 if (q->isWindow() || q->windowHandle()) {
7308 if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
7309 q->setAttribute(Qt::WA_OutsideWSRange, true);
7310 if (q->isVisible())
7311 hide_sys();
7312 data.crect = QRect(x, y, w, h);
7313 } else if (q->testAttribute(Qt::WA_OutsideWSRange)) {
7314 q->setAttribute(Qt::WA_OutsideWSRange, false);
7315 needsShow = true;
7316 }
7317 }
7318
7319 if (q->isVisible()) {
7320 if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
7321 if (QWindow *win = q->windowHandle()) {
7322 if (q->isWindow()) {
7323 if (isResize && !isMove)
7324 win->resize(w, h);
7325 else if (isMove && !isResize)
7326 win->setPosition(x, y);
7327 else
7328 win->setGeometry(q->geometry());
7329 } else {
7330 QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint());
7331 win->setGeometry(QRect(posInNativeParent,r.size()));
7332 }
7333
7334 if (needsShow)
7335 show_sys();
7336 }
7337
7338 if (!q->isWindow()) {
7339 if (renderToTexture) {
7340 QRegion updateRegion(q->geometry());
7341 updateRegion += QRect(oldPos, olds);
7342 q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
7343 } else if (isMove && !isResize) {
7344 moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
7345 } else {
7346 invalidateBackingStore_resizeHelper(oldPos, olds);
7347 }
7348 }
7349 }
7350
7351 if (isMove) {
7352 QMoveEvent e(q->pos(), oldPos);
7353 QCoreApplication::sendEvent(q, &e);
7354 }
7355 if (isResize) {
7356 QResizeEvent e(r.size(), olds);
7357 QCoreApplication::sendEvent(q, &e);
7358 if (q->windowHandle())
7359 q->update();
7360 }
7361 } else { // not visible
7362 if (isMove && q->pos() != oldPos)
7363 q->setAttribute(Qt::WA_PendingMoveEvent, true);
7364 if (isResize)
7365 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7366 }
7367
7368#if QT_CONFIG(accessibility)
7369 if (QAccessible::isActive() && q->isVisible()) {
7370 QAccessibleEvent event(q, QAccessible::LocationChanged);
7371 QAccessible::updateAccessibility(&event);
7372 }
7373#endif
7374}
7375
7376/*!
7377 \since 4.2
7378 Saves the current geometry and state for top-level widgets.
7379
7380 To save the geometry when the window closes, you can
7381 implement a close event like this:
7382
7383 \snippet code/src_gui_kernel_qwidget.cpp 11
7384
7385 See the \l{Window Geometry} documentation for an overview of geometry
7386 issues with windows.
7387
7388 Use QMainWindow::saveState() to save the geometry and the state of
7389 toolbars and dock widgets.
7390
7391 \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
7392*/
7393QByteArray QWidget::saveGeometry() const
7394{
7395 QByteArray array;
7396 QDataStream stream(&array, QIODevice::WriteOnly);
7397 stream.setVersion(QDataStream::Qt_4_0);
7398 const quint32 magicNumber = 0x1D9D0CB;
7399 // Version history:
7400 // - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0
7401 // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
7402 // - Qt 5.12 - today : Version 3.0, save QWidget::geometry()
7403 quint16 majorVersion = 3;
7404 quint16 minorVersion = 0;
7405 const int screenNumber = QGuiApplication::screens().indexOf(screen());
7406 stream << magicNumber
7407 << majorVersion
7408 << minorVersion
7409 << frameGeometry()
7410 << normalGeometry()
7411 << qint32(screenNumber)
7412 << quint8(windowState() & Qt::WindowMaximized)
7413 << quint8(windowState() & Qt::WindowFullScreen)
7414 << qint32(screen()->geometry().width()) // added in 2.0
7415 << geometry(); // added in 3.0
7416 return array;
7417}
7418
7419/*!
7420 \internal
7421
7422 Check a if \a restoredGeometry fits into \a availableGeometry
7423 This method is used to verify that a widget is restored to a geometry, which
7424 fits into the target screen.
7425
7426 \param frameHeight represents the height of the widget's title bar, which is expected
7427 to be on its top.
7428
7429 If the size of \a restoredGeometry exceeds \a availableGeometry, its height and width
7430 will be resized to be two pixels smaller than \a availableGeometry. An exact match would
7431 be full screen.
7432
7433 If at least one edge of \a restoredGeometry is outside \a availableGeometry,
7434 \a restoredGeometry will be moved
7435 \list
7436 \li down if its top is off screen
7437 \li up if its bottom is off screen
7438 \li right if its left edge is off screen
7439 \li left if its right edge is off screen
7440 \endlist
7441 */
7442void QWidgetPrivate::checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
7443 int frameHeight)
7444{
7445 // compare with restored geometry's height increased by frameHeight
7446 const int height = restoredGeometry->height() + frameHeight;
7447
7448 // Step 1: Resize if necessary:
7449 // make height / width 2px smaller than screen, because an exact match would be fullscreen
7450 if (availableGeometry.height() <= height)
7451 restoredGeometry->setHeight(availableGeometry.height() - 2 - frameHeight);
7452 if (availableGeometry.width() <= restoredGeometry->width())
7453 restoredGeometry->setWidth(availableGeometry.width() - 2);
7454
7455 // Step 2: Move if necessary:
7456 // Construct a rectangle from restored Geometry adjusted by frameHeight
7457 const QRect restored = restoredGeometry->adjusted(0, -frameHeight, 0, 0);
7458
7459 // Return if restoredGeometry (including frame) fits into screen
7460 if (availableGeometry.contains(restored))
7461 return;
7462
7463 // (size is correct, but at least one edge is off screen)
7464
7465 // Top out of bounds => move down
7466 if (restored.top() <= availableGeometry.top()) {
7467 restoredGeometry->moveTop(availableGeometry.top() + 1 + frameHeight);
7468 } else if (restored.bottom() >= availableGeometry.bottom()) {
7469 // Bottom out of bounds => move up
7470 restoredGeometry->moveBottom(availableGeometry.bottom() - 1);
7471 }
7472
7473 // Left edge out of bounds => move right
7474 if (restored.left() <= availableGeometry.left()) {
7475 restoredGeometry->moveLeft(availableGeometry.left() + 1);
7476 } else if (restored.right() >= availableGeometry.right()) {
7477 // Right edge out of bounds => move left
7478 restoredGeometry->moveRight(availableGeometry.right() - 1);
7479 }
7480}
7481
7482/*!
7483 \since 4.2
7484
7485 Restores the geometry and state of top-level widgets stored in the
7486 byte array \a geometry. Returns \c true on success; otherwise
7487 returns \c false.
7488
7489 If the restored geometry is off-screen, it will be modified to be
7490 inside the available screen geometry.
7491
7492 To restore geometry saved using QSettings, you can use code like
7493 this:
7494
7495 \snippet code/src_gui_kernel_qwidget.cpp 12
7496
7497 See the \l{Window Geometry} documentation for an overview of geometry
7498 issues with windows.
7499
7500 Use QMainWindow::restoreState() to restore the geometry and the
7501 state of toolbars and dock widgets.
7502
7503 \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
7504*/
7505bool QWidget::restoreGeometry(const QByteArray &geometry)
7506{
7507 if (geometry.size() < 4)
7508 return false;
7509 QDataStream stream(geometry);
7510 stream.setVersion(QDataStream::Qt_4_0);
7511
7512 const quint32 magicNumber = 0x1D9D0CB;
7513 quint32 storedMagicNumber;
7514 stream >> storedMagicNumber;
7515 if (storedMagicNumber != magicNumber)
7516 return false;
7517
7518 const quint16 currentMajorVersion = 3;
7519 quint16 majorVersion = 0;
7520 quint16 minorVersion = 0;
7521
7522 stream >> majorVersion >> minorVersion;
7523
7524 if (majorVersion > currentMajorVersion)
7525 return false;
7526 // (Allow all minor versions.)
7527
7528 QRect restoredFrameGeometry;
7529 QRect restoredGeometry;
7530 QRect restoredNormalGeometry;
7531 qint32 restoredScreenNumber;
7532 quint8 maximized;
7533 quint8 fullScreen;
7534 qint32 restoredScreenWidth = 0;
7535
7536 stream >> restoredFrameGeometry // Only used for sanity checks in version 0
7537 >> restoredNormalGeometry
7538 >> restoredScreenNumber
7539 >> maximized
7540 >> fullScreen;
7541
7542 if (majorVersion > 1)
7543 stream >> restoredScreenWidth;
7544 if (majorVersion > 2)
7545 stream >> restoredGeometry;
7546
7547 // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
7548
7549 if (restoredScreenNumber >= qMax(QGuiApplication::screens().size(), 1))
7550 restoredScreenNumber = 0;
7551 const QScreen *restoredScreen = QGuiApplication::screens().value(restoredScreenNumber, nullptr);
7552 const qreal screenWidthF = restoredScreen ? qreal(restoredScreen->geometry().width()) : 0;
7553 // Sanity check bailing out when large variations of screen sizes occur due to
7554 // high DPI scaling or different levels of DPI awareness.
7555 if (restoredScreenWidth) {
7556 const qreal factor = qreal(restoredScreenWidth) / screenWidthF;
7557 if (factor < 0.8 || factor > 1.25)
7558 return false;
7559 } else {
7560 // Saved by Qt 5.3 and earlier, try to prevent too large windows
7561 // unless the size will be adapted by maximized or fullscreen.
7562 if (!maximized && !fullScreen && qreal(restoredFrameGeometry.width()) / screenWidthF > 1.5)
7563 return false;
7564 }
7565
7566 const int frameHeight = QApplication::style()
7567 ? QApplication::style()->pixelMetric(QStyle::PM_TitleBarHeight, nullptr, this)
7568 : 20;
7569
7570 if (!restoredNormalGeometry.isValid())
7571 restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
7572 if (!restoredNormalGeometry.isValid()) {
7573 // use the widget's adjustedSize if the sizeHint() doesn't help
7574 restoredNormalGeometry.setSize(restoredNormalGeometry
7575 .size()
7576 .expandedTo(d_func()->adjustedSize()));
7577 }
7578
7579 const QRect availableGeometry = restoredScreen ? restoredScreen->availableGeometry()
7580 : QRect();
7581
7582 // Modify the restored geometry if we are about to restore to coordinates
7583 // that would make the window "lost". This happens if:
7584 // - The restored geometry is completely or partly oustside the available geometry
7585 // - The title bar is outside the available geometry.
7586
7587 QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight);
7588 QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight);
7589
7590 if (maximized || fullScreen) {
7591 // set geometry before setting the window state to make
7592 // sure the window is maximized to the right screen.
7593 Qt::WindowStates ws = windowState();
7594#ifndef Q_OS_WIN
7595 setGeometry(restoredNormalGeometry);
7596#else
7597 if (ws & Qt::WindowFullScreen) {
7598 // Full screen is not a real window state on Windows.
7599 move(availableGeometry.topLeft());
7600 } else if (ws & Qt::WindowMaximized) {
7601 // Setting a geometry on an already maximized window causes this to be
7602 // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
7603 // Move the window in normal state if needed.
7604 if (restoredScreen != screen()) {
7605 setWindowState(Qt::WindowNoState);
7606 setGeometry(restoredNormalGeometry);
7607 }
7608 } else {
7609 setGeometry(restoredNormalGeometry);
7610 }
7611#endif // Q_OS_WIN
7612 if (maximized)
7613 ws |= Qt::WindowMaximized;
7614 if (fullScreen)
7615 ws |= Qt::WindowFullScreen;
7616 setWindowState(ws);
7617 d_func()->topData()->normalGeometry = restoredNormalGeometry;
7618 } else {
7619 setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
7620
7621 // FIXME: Why fall back to restoredNormalGeometry if majorVersion <= 2?
7622 if (majorVersion > 2)
7623 setGeometry(restoredGeometry);
7624 else
7625 setGeometry(restoredNormalGeometry);
7626 }
7627 return true;
7628}
7629
7630/*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
7631 \overload
7632
7633 This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
7634*/
7635
7636/*!
7637 Sets the margins around the contents of the widget to have the sizes
7638 \a left, \a top, \a right, and \a bottom. The margins are used by
7639 the layout system, and may be used by subclasses to specify the area
7640 to draw in (e.g. excluding the frame).
7641
7642 Changing the margins will trigger a resizeEvent().
7643
7644 \sa contentsRect(), contentsMargins()
7645*/
7646void QWidget::setContentsMargins(int left, int top, int right, int bottom)
7647{
7648 Q_D(QWidget);
7649 if (left == d->leftmargin && top == d->topmargin
7650 && right == d->rightmargin && bottom == d->bottommargin)
7651 return;
7652 d->leftmargin = left;
7653 d->topmargin = top;
7654 d->rightmargin = right;
7655 d->bottommargin = bottom;
7656
7657 d->updateContentsRect();
7658}
7659
7660/*!
7661 \overload
7662 \since 4.6
7663
7664 \brief The setContentsMargins function sets the margins around the
7665 widget's contents.
7666
7667 Sets the margins around the contents of the widget to have the
7668 sizes determined by \a margins. The margins are
7669 used by the layout system, and may be used by subclasses to
7670 specify the area to draw in (e.g. excluding the frame).
7671
7672 Changing the margins will trigger a resizeEvent().
7673
7674 \sa contentsRect(), contentsMargins()
7675*/
7676void QWidget::setContentsMargins(const QMargins &margins)
7677{
7678 setContentsMargins(margins.left(), margins.top(),
7679 margins.right(), margins.bottom());
7680}
7681
7682void QWidgetPrivate::updateContentsRect()
7683{
7684 Q_Q(QWidget);
7685
7686 if (layout)
7687 layout->update(); //force activate; will do updateGeometry
7688 else
7689 q->updateGeometry();
7690
7691 if (q->isVisible()) {
7692 q->update();
7693 QResizeEvent e(q->data->crect.size(), q->data->crect.size());
7694 QCoreApplication::sendEvent(q, &e);
7695 } else {
7696 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7697 }
7698
7699 QEvent e(QEvent::ContentsRectChange);
7700 QCoreApplication::sendEvent(q, &e);
7701}
7702
7703/*!
7704 \since 4.6
7705
7706 \brief The contentsMargins function returns the widget's contents margins.
7707
7708 \sa setContentsMargins(), contentsRect()
7709 */
7710QMargins QWidget::contentsMargins() const
7711{
7712 Q_D(const QWidget);
7713 QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
7714 return testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea) ?
7715 userMargins | d->safeAreaMargins() : userMargins;
7716}
7717
7718/*!
7719 Returns the area inside the widget's margins.
7720
7721 \sa setContentsMargins(), contentsMargins()
7722*/
7723QRect QWidget::contentsRect() const
7724{
7725 return rect() - contentsMargins();
7726}
7727
7728QMargins QWidgetPrivate::safeAreaMargins() const
7729{
7730 Q_Q(const QWidget);
7731
7732#if QT_CONFIG(graphicsview)
7733 // Don't report margins for proxied widgets, as the logic
7734 // below doesn't handle that case (yet).
7735 if (nearestGraphicsProxyWidget(q))
7736 return QMargins();
7737#endif
7738
7739 QWidget *nativeWidget = q->window();
7740 if (!nativeWidget->windowHandle())
7741 return QMargins();
7742
7743 QMargins safeAreaMargins = nativeWidget->windowHandle()->safeAreaMargins();
7744
7745 if (!q->isWindow()) {
7746 // In theory the native parent widget already has a contents rect reflecting
7747 // the safe area of that widget, but we can't be sure that the widget or child
7748 // widgets of that widget have respected the contents rect when setting their
7749 // geometry, so we need to manually compute the safe area.
7750
7751 // Unless the native widget doesn't have any margins, in which case there's
7752 // nothing for us to compute.
7753 if (safeAreaMargins.isNull())
7754 return QMargins();
7755
7756 // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
7757 // set, and the widget respects the safe area, then we know that the layout has already
7758 // taken care of placing us inside the safe area, by taking the contents rect of its
7759 // parent widget into account.
7760 const QWidget *assumedSafeWidget = nullptr;
7761 for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
7762 QWidget *parentWidget = w->parentWidget();
7763 if (!parentWidget->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
7764 continue; // Layout can't help us
7765
7766 if (parentWidget->testAttribute(Qt::WA_LayoutOnEntireRect))
7767 continue; // Layout not going to help us
7768
7769 QLayout *layout = parentWidget->layout();
7770 if (!layout)
7771 continue;
7772
7773 if (layout->geometry().isNull())
7774 continue; // Layout hasn't been activated yet
7775
7776 if (layout->indexOf(w) < 0)
7777 continue; // Widget is not in layout
7778
7779 assumedSafeWidget = w;
7780 break;
7781 }
7782
7783#if !defined(QT_DEBUG)
7784 if (assumedSafeWidget) {
7785 // We found a layout that we assume will take care of keeping us within the safe area
7786 // For debug builds we still map the safe area using the fallback logic, so that we
7787 // can detect any misbehaving layouts.
7788 return QMargins();
7789 }
7790#endif
7791
7792 // In all other cases we need to map the safe area of the native parent to the widget.
7793 // This depends on the widget being positioned and sized already, which means the initial
7794 // layout will be wrong, but the layout will then adjust itself.
7795 QPoint topLeftMargins = q->mapFrom(nativeWidget, QPoint(safeAreaMargins.left(), safeAreaMargins.top()));
7796 QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect();
7797 QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(nativeWidget,
7798 nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom()));
7799
7800 // Margins should never be negative
7801 safeAreaMargins = QMargins(qMax(0, topLeftMargins.x()), qMax(0, topLeftMargins.y()),
7802 qMax(0, bottomRightMargins.x()), qMax(0, bottomRightMargins.y()));
7803
7804 if (!safeAreaMargins.isNull() && assumedSafeWidget) {
7805 QLayout *layout = assumedSafeWidget->parentWidget()->layout();
7806 qWarning() << layout << "is laying out" << assumedSafeWidget
7807 << "outside of the contents rect of" << layout->parentWidget();
7808 return QMargins(); // Return empty margin to visually highlight the error
7809 }
7810 }
7811
7812 return safeAreaMargins;
7813}
7814
7815/*!
7816 \fn void QWidget::customContextMenuRequested(const QPoint &pos)
7817
7818 This signal is emitted when the widget's \l contextMenuPolicy is
7819 Qt::CustomContextMenu, and the user has requested a context menu on
7820 the widget. The position \a pos is the position of the context menu
7821 event that the widget receives. Normally this is in widget
7822 coordinates. The exception to this rule is QAbstractScrollArea and
7823 its subclasses that map the context menu event to coordinates of the
7824 \l{QAbstractScrollArea::viewport()}{viewport()}.
7825
7826
7827 \sa mapToGlobal(), QMenu, contextMenuPolicy
7828*/
7829
7830
7831/*!
7832 \property QWidget::contextMenuPolicy
7833 \brief how the widget shows a context menu
7834
7835 The default value of this property is Qt::DefaultContextMenu,
7836 which means the contextMenuEvent() handler is called. Other values
7837 are Qt::NoContextMenu, Qt::PreventContextMenu,
7838 Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
7839 Qt::CustomContextMenu, the signal customContextMenuRequested() is
7840 emitted.
7841
7842 \sa contextMenuEvent(), customContextMenuRequested(), actions()
7843*/
7844
7845Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
7846{
7847 return (Qt::ContextMenuPolicy)data->context_menu_policy;
7848}
7849
7850void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
7851{
7852 data->context_menu_policy = (uint) policy;
7853}
7854
7855/*!
7856 \property QWidget::focusPolicy
7857 \brief the way the widget accepts keyboard focus
7858
7859 The policy is Qt::TabFocus if the widget accepts keyboard
7860 focus by tabbing, Qt::ClickFocus if the widget accepts
7861 focus by clicking, Qt::StrongFocus if it accepts both, and
7862 Qt::NoFocus (the default) if it does not accept focus at
7863 all.
7864
7865 You must enable keyboard focus for a widget if it processes
7866 keyboard events. This is normally done from the widget's
7867 constructor. For instance, the QLineEdit constructor calls
7868 setFocusPolicy(Qt::StrongFocus).
7869
7870 If the widget has a focus proxy, then the focus policy will
7871 be propagated to it.
7872
7873 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
7874*/
7875
7876
7877Qt::FocusPolicy QWidget::focusPolicy() const
7878{
7879 return (Qt::FocusPolicy)data->focus_policy;
7880}
7881
7882void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
7883{
7884 data->focus_policy = (uint) policy;
7885 Q_D(QWidget);
7886 if (d->extra && d->extra->focus_proxy)
7887 d->extra->focus_proxy->setFocusPolicy(policy);
7888}
7889
7890/*!
7891 \property QWidget::updatesEnabled
7892 \brief whether updates are enabled
7893
7894 An updates enabled widget receives paint events and has a system
7895 background; a disabled widget does not. This also implies that
7896 calling update() and repaint() has no effect if updates are
7897 disabled.
7898
7899 By default, this property is \c true.
7900
7901 setUpdatesEnabled() is normally used to disable updates for a
7902 short period of time, for instance to avoid screen flicker during
7903 large changes. In Qt, widgets normally do not generate screen
7904 flicker, but on X11 the server might erase regions on the screen
7905 when widgets get hidden before they can be replaced by other
7906 widgets. Disabling updates solves this.
7907
7908 Example:
7909 \snippet code/src_gui_kernel_qwidget.cpp 13
7910
7911 Disabling a widget implicitly disables all its children. Enabling a widget
7912 enables all child widgets \e except top-level widgets or those that
7913 have been explicitly disabled. Re-enabling updates implicitly calls
7914 update() on the widget.
7915
7916 \sa paintEvent()
7917*/
7918void QWidget::setUpdatesEnabled(bool enable)
7919{
7920 Q_D(QWidget);
7921 setAttribute(Qt::WA_ForceUpdatesDisabled, !enable);
7922 d->setUpdatesEnabled_helper(enable);
7923}
7924
7925/*!
7926 Shows the widget and its child widgets.
7927
7928 For child windows, this is equivalent to calling setVisible(true).
7929 Otherwise, it is equivalent to calling showFullScreen(), showMaximized(),
7930 or setVisible(true), depending on the platform's default behavior for the window flags.
7931
7932 \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
7933 showNormal(), isVisible(), windowFlags()
7934*/
7935void QWidget::show()
7936{
7937 // Note: We don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
7938
7939 if (!isWindow()) {
7940 setVisible(true);
7941 } else {
7942 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
7943 Qt::WindowState defaultState = platformIntegration->defaultWindowState(data->window_flags);
7944 if (defaultState == Qt::WindowFullScreen)
7945 showFullScreen();
7946 else if (defaultState == Qt::WindowMaximized)
7947 showMaximized();
7948 else
7949 setVisible(true);
7950 }
7951}
7952
7953/*! \internal
7954
7955 Makes the widget visible in the isVisible() meaning of the word.
7956 It is only called for toplevels or widgets with visible parents.
7957 */
7958void QWidgetPrivate::show_recursive()
7959{
7960 Q_Q(QWidget);
7961 // polish if necessary
7962
7963 if (!q->testAttribute(Qt::WA_WState_Created))
7964 createRecursively();
7965 q->ensurePolished();
7966
7967 if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
7968 q->parentWidget()->d_func()->layout->activate();
7969 // activate our layout before we and our children become visible
7970 if (layout)
7971 layout->activate();
7972
7973 show_helper();
7974}
7975
7976void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
7977{
7978 Q_Q(QWidget);
7979
7980 disableUpdates = disableUpdates && q->updatesEnabled();
7981 if (disableUpdates)
7982 q->setAttribute(Qt::WA_UpdatesDisabled);
7983
7984 if (q->testAttribute(Qt::WA_PendingMoveEvent)) {
7985 QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
7986 QCoreApplication::sendEvent(q, &e);
7987 q->setAttribute(Qt::WA_PendingMoveEvent, false);
7988 }
7989
7990 if (q->testAttribute(Qt::WA_PendingResizeEvent)) {
7991 QResizeEvent e(data.crect.size(), QSize());
7992 QCoreApplication::sendEvent(q, &e);
7993 q->setAttribute(Qt::WA_PendingResizeEvent, false);
7994 }
7995
7996 if (disableUpdates)
7997 q->setAttribute(Qt::WA_UpdatesDisabled, false);
7998
7999 if (!recursive)
8000 return;
8001
8002 for (int i = 0; i < children.size(); ++i) {
8003 if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
8004 child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
8005 }
8006}
8007
8008void QWidgetPrivate::activateChildLayoutsRecursively()
8009{
8010 sendPendingMoveAndResizeEvents(false, true);
8011
8012 for (int i = 0; i < children.size(); ++i) {
8013 QWidget *child = qobject_cast<QWidget *>(children.at(i));
8014 if (!child || child->isHidden() || child->isWindow())
8015 continue;
8016
8017 child->ensurePolished();
8018
8019 // Activate child's layout
8020 QWidgetPrivate *childPrivate = child->d_func();
8021 if (childPrivate->layout)
8022 childPrivate->layout->activate();
8023
8024 // Pretend we're visible.
8025 const bool wasVisible = child->isVisible();
8026 if (!wasVisible)
8027 child->setAttribute(Qt::WA_WState_Visible);
8028
8029 // Do the same for all my children.
8030 childPrivate->activateChildLayoutsRecursively();
8031
8032 // We're not cheating anymore.
8033 if (!wasVisible)
8034 child->setAttribute(Qt::WA_WState_Visible, false);
8035 }
8036}
8037
8038void QWidgetPrivate::show_helper()
8039{
8040 Q_Q(QWidget);
8041 data.in_show = true; // qws optimization
8042 // make sure we receive pending move and resize events
8043 sendPendingMoveAndResizeEvents();
8044
8045 // become visible before showing all children
8046 q->setAttribute(Qt::WA_WState_Visible);
8047
8048 // finally show all children recursively
8049 showChildren(false);
8050
8051
8052
8053 const bool isWindow = q->isWindow();
8054#if QT_CONFIG(graphicsview)
8055 bool isEmbedded = isWindow && q->graphicsProxyWidget() != nullptr;
8056#else
8057 bool isEmbedded = false;
8058#endif
8059
8060 // popup handling: new popups and tools need to be raised, and
8061 // existing popups must be closed. Also propagate the current
8062 // windows's KeyboardFocusChange status.
8063 if (isWindow && !isEmbedded) {
8064 if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
8065 q->raise();
8066 if (q->parentWidget() && q->parentWidget()->window()->testAttribute(Qt::WA_KeyboardFocusChange))
8067 q->setAttribute(Qt::WA_KeyboardFocusChange);
8068 } else {
8069 while (QApplication::activePopupWidget()) {
8070 if (!QApplication::activePopupWidget()->close())
8071 break;
8072 }
8073 }
8074 }
8075
8076 // Automatic embedding of child windows of widgets already embedded into
8077 // QGraphicsProxyWidget when they are shown the first time.
8078#if QT_CONFIG(graphicsview)
8079 if (isWindow) {
8080 if (!isEmbedded && !bypassGraphicsProxyWidget(q)) {
8081 QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(q->parentWidget());
8082 if (ancestorProxy) {
8083 isEmbedded = true;
8084 ancestorProxy->d_func()->embedSubWindow(q);
8085 }
8086 }
8087 }
8088#else
8089 Q_UNUSED(isEmbedded);
8090#endif
8091
8092 // send the show event before showing the window
8093 QShowEvent showEvent;
8094 QCoreApplication::sendEvent(q, &showEvent);
8095
8096 show_sys();
8097
8098 if (!isEmbedded && q->windowType() == Qt::Popup)
8099 qApp->d_func()->openPopup(q);
8100
8101#if QT_CONFIG(accessibility)
8102 if (q->windowType() != Qt::ToolTip) { // Tooltips are read aloud twice in MS narrator.
8103 QAccessibleEvent event(q, QAccessible::ObjectShow);
8104 QAccessible::updateAccessibility(&event);
8105 }
8106#endif
8107
8108 if (QApplicationPrivate::hidden_focus_widget == q) {
8109 QApplicationPrivate::hidden_focus_widget = nullptr;
8110 q->setFocus(Qt::OtherFocusReason);
8111 }
8112
8113 // Process events when showing a Qt::SplashScreen widget before the event loop
8114 // is spinnning; otherwise it might not show up on particular platforms.
8115 // This makes QSplashScreen behave the same on all platforms.
8116 if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
8117 QCoreApplication::processEvents();
8118
8119 data.in_show = false; // reset qws optimization
8120}
8121
8122void QWidgetPrivate::show_sys()
8123{
8124 Q_Q(QWidget);
8125
8126 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
8127
8128 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
8129 invalidateBackingStore(q->rect());
8130 q->setAttribute(Qt::WA_Mapped);
8131 // add our window the modal window list (native dialogs)
8132 if (window && q->isWindow()
8133#if QT_CONFIG(graphicsview)
8134 && (!extra || !extra->proxyWidget)
8135#endif
8136 && q->windowModality() != Qt::NonModal) {
8137 QGuiApplicationPrivate::showModalWindow(window);
8138 }
8139 return;
8140 }
8141
8142 if (renderToTexture && !q->isWindow())
8143 QCoreApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry()));
8144 else
8145 QCoreApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
8146
8147 if ((!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
8148 || q->testAttribute(Qt::WA_OutsideWSRange)) {
8149 return;
8150 }
8151
8152 if (window) {
8153 if (q->isWindow())
8154 fixPosIncludesFrame();
8155 QRect geomRect = q->geometry();
8156 if (!q->isWindow()) {
8157 QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint());
8158 geomRect.moveTopLeft(topLeftOfWindow);
8159 }
8160 const QRect windowRect = window->geometry();
8161 if (windowRect != geomRect) {
8162 if (q->testAttribute(Qt::WA_Moved)
8163 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
8164 window->setGeometry(geomRect);
8165 else
8166 window->resize(geomRect.size());
8167 }
8168
8169#ifndef QT_NO_CURSOR
8170 qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
8171#endif
8172 invalidateBackingStore(q->rect());
8173 window->setNativeWindowVisibility(true);
8174 // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
8175 if (window->isTopLevel()) {
8176 const QPoint crectTopLeft = q->data->crect.topLeft();
8177 const QPoint windowTopLeft = window->geometry().topLeft();
8178 if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
8179 q->data->crect.moveTopLeft(windowTopLeft);
8180 }
8181 }
8182}
8183
8184/*!
8185 Hides the widget. This function is equivalent to
8186 setVisible(false).
8187
8188
8189 \note If you are working with QDialog or its subclasses and you invoke
8190 the show() function after this function, the dialog will be displayed in
8191 its original position.
8192
8193 \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
8194*/
8195void QWidget::hide()
8196{
8197 setVisible(false);
8198}
8199
8200/*!\internal
8201 */
8202void QWidgetPrivate::hide_helper()
8203{
8204 Q_Q(QWidget);
8205
8206 bool isEmbedded = false;
8207#if QT_CONFIG(graphicsview)
8208 isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(q) && nearestGraphicsProxyWidget(q->parentWidget()) != nullptr;
8209#else
8210 Q_UNUSED(isEmbedded);
8211#endif
8212
8213 if (!isEmbedded && (q->windowType() == Qt::Popup))
8214 qApp->d_func()->closePopup(q);
8215
8216 q->setAttribute(Qt::WA_Mapped, false);
8217 hide_sys();
8218
8219 bool wasVisible = q->testAttribute(Qt::WA_WState_Visible);
8220
8221 if (wasVisible) {
8222 q->setAttribute(Qt::WA_WState_Visible, false);
8223
8224 }
8225
8226 QHideEvent hideEvent;
8227 QCoreApplication::sendEvent(q, &hideEvent);
8228 hideChildren(false);
8229
8230 // next bit tries to move the focus if the focus widget is now
8231 // hidden.
8232 if (wasVisible) {
8233 qApp->d_func()->sendSyntheticEnterLeave(q);
8234 QWidget *fw = QApplication::focusWidget();
8235 while (fw && !fw->isWindow()) {
8236 if (fw == q) {
8237 q->focusNextPrevChild(true);
8238 break;
8239 }
8240 fw = fw->parentWidget();
8241 }
8242 }
8243
8244 if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
8245 repaintManager->removeDirtyWidget(q);
8246
8247#if QT_CONFIG(accessibility)
8248 if (wasVisible) {
8249 QAccessibleEvent event(q, QAccessible::ObjectHide);
8250 QAccessible::updateAccessibility(&event);
8251 }
8252#endif
8253}
8254
8255void QWidgetPrivate::hide_sys()
8256{
8257 Q_Q(QWidget);
8258
8259 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
8260
8261 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
8262 q->setAttribute(Qt::WA_Mapped, false);
8263 // remove our window from the modal window list (native dialogs)
8264 if (window && q->isWindow()
8265#if QT_CONFIG(graphicsview)
8266 && (!extra || !extra->proxyWidget)
8267#endif
8268 && q->windowModality() != Qt::NonModal) {
8269 QGuiApplicationPrivate::hideModalWindow(window);
8270 }
8271 // do not return here, if window non-zero, we must hide it
8272 }
8273
8274 deactivateWidgetCleanup();
8275
8276 if (!q->isWindow()) {
8277 QWidget *p = q->parentWidget();
8278 if (p &&p->isVisible()) {
8279 if (renderToTexture)
8280 p->d_func()->invalidateBackingStore(q->geometry());
8281 else
8282 invalidateBackingStore(q->rect());
8283 }
8284 } else {
8285 invalidateBackingStore(q->rect());
8286 }
8287
8288 if (window)
8289 window->setNativeWindowVisibility(false);
8290}
8291
8292/*!
8293 \fn bool QWidget::isHidden() const
8294
8295 Returns \c true if the widget is hidden, otherwise returns \c false.
8296
8297 A hidden widget will only become visible when show() is called on
8298 it. It will not be automatically shown when the parent is shown.
8299
8300 To check visibility, use !isVisible() instead (notice the exclamation mark).
8301
8302 isHidden() implies !isVisible(), but a widget can be not visible
8303 and not hidden at the same time. This is the case for widgets that are children of
8304 widgets that are not visible.
8305
8306
8307 Widgets are hidden if:
8308 \list
8309 \li they were created as independent windows,
8310 \li they were created as children of visible widgets,
8311 \li hide() or setVisible(false) was called.
8312 \endlist
8313*/
8314
8315void QWidget::setVisible(bool visible)
8316{
8317 Q_D(QWidget);
8318 qCDebug(lcWidgetShowHide) << "Setting visibility of" << this
8319 << "with attributes" << WidgetAttributes{this}
8320 << "to" << visible << "via QWidget";
8321
8322 if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) == !visible)
8323 return;
8324
8325 if (d->dontSetExplicitShowHide) {
8326 d->dontSetExplicitShowHide = false;
8327 } else {
8328 // Remember that setVisible was called explicitly
8329 setAttribute(Qt::WA_WState_ExplicitShowHide);
8330 }
8331
8332 d->setVisible(visible);
8333}
8334
8335// This method is called from QWidgetWindow in response to QWindow::setVisible,
8336// and should match the semantics of QWindow::setVisible. QWidget::setVisible on
8337// the other hand keeps track of WA_WState_ExplicitShowHide in addition.
8338void QWidgetPrivate::setVisible(bool visible)
8339{
8340 Q_Q(QWidget);
8341 qCDebug(lcWidgetShowHide) << "Setting visibility of" << q
8342 << "with attributes" << WidgetAttributes{q}
8343 << "to" << visible << "via QWidgetPrivate";
8344
8345 if (visible) { // show
8346 // Designer uses a trick to make grabWidget work without showing
8347 if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
8348 && !q->parentWidget()->testAttribute(Qt::WA_WState_Created))
8349 q->parentWidget()->window()->d_func()->createRecursively();
8350
8351 //create toplevels but not children of non-visible parents
8352 QWidget *pw = q->parentWidget();
8353 if (!q->testAttribute(Qt::WA_WState_Created)
8354 && (q->isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
8355 q->create();
8356 }
8357
8358 bool wasResized = q->testAttribute(Qt::WA_Resized);
8359 Qt::WindowStates initialWindowState = q->windowState();
8360
8361 // polish if necessary
8362 q->ensurePolished();
8363
8364 // whether we need to inform the parent widget immediately
8365 bool needUpdateGeometry = !q->isWindow() && q->testAttribute(Qt::WA_WState_Hidden);
8366 // we are no longer hidden
8367 q->setAttribute(Qt::WA_WState_Hidden, false);
8368
8369 if (needUpdateGeometry)
8370 updateGeometry_helper(true);
8371
8372 // activate our layout before we and our children become visible
8373 if (layout)
8374 layout->activate();
8375
8376 if (!q->isWindow()) {
8377 QWidget *parent = q->parentWidget();
8378 while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
8379 parent->d_func()->layout->activate();
8380 if (parent->isWindow())
8381 break;
8382 parent = parent->parentWidget();
8383 }
8384 if (parent)
8385 parent->d_func()->setDirtyOpaqueRegion();
8386 }
8387
8388 // adjust size if necessary
8389 if (!wasResized
8390 && (q->isWindow() || !q->parentWidget()->d_func()->layout)) {
8391 if (q->isWindow()) {
8392 q->adjustSize();
8393 if (q->windowState() != initialWindowState)
8394 q->setWindowState(initialWindowState);
8395 } else {
8396 q->adjustSize();
8397 }
8398 q->setAttribute(Qt::WA_Resized, false);
8399 }
8400
8401 q->setAttribute(Qt::WA_KeyboardFocusChange, false);
8402
8403 if (q->isWindow() || q->parentWidget()->isVisible()) {
8404 show_helper();
8405
8406 qApp->d_func()->sendSyntheticEnterLeave(q);
8407 }
8408
8409 QEvent showToParentEvent(QEvent::ShowToParent);
8410 QCoreApplication::sendEvent(q, &showToParentEvent);
8411 } else { // hide
8412 if (QApplicationPrivate::hidden_focus_widget == q)
8413 QApplicationPrivate::hidden_focus_widget = nullptr;
8414
8415 // hw: The test on getOpaqueRegion() needs to be more intelligent
8416 // currently it doesn't work if the widget is hidden (the region will
8417 // be clipped). The real check should be testing the cached region
8418 // (and dirty flag) directly.
8419 if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty())
8420 q->parentWidget()->d_func()->setDirtyOpaqueRegion();
8421
8422 if (!q->testAttribute(Qt::WA_WState_Hidden)) {
8423 q->setAttribute(Qt::WA_WState_Hidden);
8424 hide_helper();
8425 }
8426
8427 // invalidate layout similar to updateGeometry()
8428 if (!q->isWindow() && q->parentWidget()) {
8429 if (q->parentWidget()->d_func()->layout)
8430 q->parentWidget()->d_func()->layout->invalidate();
8431 else if (q->parentWidget()->isVisible())
8432 QCoreApplication::postEvent(q->parentWidget(), new QEvent(QEvent::LayoutRequest));
8433 }
8434
8435 QEvent hideToParentEvent(QEvent::HideToParent);
8436 QCoreApplication::sendEvent(q, &hideToParentEvent);
8437 }
8438}
8439
8440/*!
8441 Convenience function, equivalent to setVisible(!\a hidden).
8442*/
8443void QWidget::setHidden(bool hidden)
8444{
8445 setVisible(!hidden);
8446}
8447
8448bool QWidgetPrivate::isExplicitlyHidden() const
8449{
8450 Q_Q(const QWidget);
8451 return q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
8452}
8453
8454void QWidgetPrivate::_q_showIfNotHidden()
8455{
8456 Q_Q(QWidget);
8457 if (!isExplicitlyHidden())
8458 q->setVisible(true);
8459}
8460
8461void QWidgetPrivate::showChildren(bool spontaneous)
8462{
8463 Q_Q(QWidget);
8464 qCDebug(lcWidgetShowHide) << "Showing children of" << q
8465 << "spontaneously" << spontaneous;
8466
8467 QList<QObject*> childList = children;
8468 for (int i = 0; i < childList.size(); ++i) {
8469 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8470 if (!widget)
8471 continue;
8472 qCDebug(lcWidgetShowHide) << "Considering" << widget
8473 << "with attributes" << WidgetAttributes{widget};
8474 if (widget->windowHandle() && !widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
8475 widget->setAttribute(Qt::WA_WState_Hidden, false);
8476 if (widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
8477 continue;
8478 if (spontaneous) {
8479 widget->setAttribute(Qt::WA_Mapped);
8480 widget->d_func()->showChildren(true);
8481 QShowEvent e;
8482 QApplication::sendSpontaneousEvent(widget, &e);
8483 } else {
8484 if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide)) {
8485 widget->d_func()->show_recursive();
8486 } else {
8487 // Call QWidget::setVisible() here, so that subclasses
8488 // that (wrongly) override setVisible to do initialization
8489 // will still be notified that they are made visible, but
8490 // do so without triggering ExplicitShowHide.
8491 widget->d_func()->dontSetExplicitShowHide = true;
8492 widget->setVisible(true);
8493 widget->d_func()->dontSetExplicitShowHide = false;
8494 }
8495 }
8496 }
8497}
8498
8499void QWidgetPrivate::hideChildren(bool spontaneous)
8500{
8501 Q_Q(QWidget);
8502 qCDebug(lcWidgetShowHide) << "Hiding children of" << q
8503 << "spontaneously" << spontaneous;
8504
8505 QList<QObject*> childList = children;
8506 for (int i = 0; i < childList.size(); ++i) {
8507 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8508 if (!widget)
8509 continue;
8510 qCDebug(lcWidgetShowHide) << "Considering" << widget
8511 << "with attributes" << WidgetAttributes{widget};
8512 if (widget->isWindow() || !widget->isVisible())
8513 continue;
8514
8515 if (spontaneous)
8516 widget->setAttribute(Qt::WA_Mapped, false);
8517 else
8518 widget->setAttribute(Qt::WA_WState_Visible, false);
8519 widget->d_func()->hideChildren(spontaneous);
8520 QHideEvent e;
8521 if (spontaneous) {
8522 QApplication::sendSpontaneousEvent(widget, &e);
8523 } else {
8524 QCoreApplication::sendEvent(widget, &e);
8525 if (widget->internalWinId()
8526 && widget->testAttribute(Qt::WA_DontCreateNativeAncestors)) {
8527 // hide_sys() on an ancestor won't have any affect on this
8528 // widget, so it needs an explicit hide_sys() of its own
8529 widget->d_func()->hide_sys();
8530 }
8531 }
8532 qApp->d_func()->sendSyntheticEnterLeave(widget);
8533#if QT_CONFIG(accessibility)
8534 if (!spontaneous) {
8535 QAccessibleEvent event(widget, QAccessible::ObjectHide);
8536 QAccessible::updateAccessibility(&event);
8537 }
8538#endif
8539 }
8540
8541 // If the window of this widget is not closed, then the leave event
8542 // will eventually handle the widget under mouse use case.
8543 // Otherwise, we need to explicitly handle it here.
8544 if (QWidget* widgetWindow = q->window();
8545 widgetWindow && widgetWindow->data->is_closing) {
8546 q->setAttribute(Qt::WA_UnderMouse, false);
8547 }
8548}
8549
8550/*!
8551 \internal
8552
8553 For windows, this is called from the QWidgetWindow::handleCloseEvent implementation,
8554 which QWidget::close indirectly calls by closing the QWindow. \a mode will be
8555 CloseWithEvent if QWidgetWindow::handleCloseEvent is called indirectly by
8556 QWindow::close, and CloseWithSpontaneousEvent if the close event originates from the
8557 system (i.e. the user clicked the close button in the title bar).
8558
8559 QDialog calls this method directly in its hide() implementation, which might be
8560 called from the QDialog::closeEvent override. \a mode will be set to CloseNoEvent
8561 to prevent recursion.
8562
8563 For non-windows, this is called directly by QWidget::close, and \a mode will be
8564 CloseWithEvent.
8565
8566 The function is also called by the QWidget destructor, with \a mode set to CloseNoEvent.
8567*/
8568bool QWidgetPrivate::handleClose(CloseMode mode)
8569{
8570 Q_Q(QWidget);
8571 qCDebug(lcWidgetShowHide) << "Handling close event for" << q;
8572
8573 if (data.is_closing)
8574 return true;
8575
8576 // We might not have initiated the close, so update the state now that we know
8577 data.is_closing = true;
8578
8579 QPointer<QWidget> that = q;
8580
8581 if (data.in_destructor)
8582 mode = CloseNoEvent;
8583
8584 if (mode != CloseNoEvent) {
8585 QCloseEvent e;
8586 if (mode == CloseWithSpontaneousEvent)
8587 QApplication::sendSpontaneousEvent(q, &e);
8588 else
8589 QCoreApplication::sendEvent(q, &e);
8590 if (!that.isNull() && !e.isAccepted()) {
8591 data.is_closing = false;
8592 return false;
8593 }
8594 }
8595
8596 // even for windows, make sure we deliver a hide event and that all children get hidden
8597 if (!that.isNull() && !q->isHidden())
8598 q->hide();
8599
8600 if (!that.isNull()) {
8601 data.is_closing = false;
8602 if (q->testAttribute(Qt::WA_DeleteOnClose)) {
8603 q->setAttribute(Qt::WA_DeleteOnClose, false);
8604 q->deleteLater();
8605 }
8606 }
8607 return true;
8608}
8609
8610
8611/*!
8612 Closes this widget. Returns \c true if the widget was closed;
8613 otherwise returns \c false.
8614
8615 First it sends the widget a QCloseEvent. The widget is
8616 \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
8617 the close event. If it \l{QEvent::ignore()}{ignores}
8618 the event, nothing happens. The default
8619 implementation of QWidget::closeEvent() accepts the close event.
8620
8621 If the widget has the Qt::WA_DeleteOnClose flag, the widget
8622 is also deleted. A close events is delivered to the widget no
8623 matter if the widget is visible or not.
8624
8625 The \l QGuiApplication::lastWindowClosed() signal is emitted when the
8626 last visible primary window (i.e. window with no parent) with the
8627 Qt::WA_QuitOnClose attribute set is closed. By default this
8628 attribute is set for all widgets except transient windows such as
8629 splash screens, tool windows, and popup menus.
8630
8631*/
8632
8633bool QWidget::close()
8634{
8635 return d_func()->close();
8636}
8637
8638bool QWidgetPrivate::close()
8639{
8640 // FIXME: We're not setting is_closing here, even though that would
8641 // make sense, as the code below will not end up in handleClose to
8642 // reset is_closing when there's a QWindow, but no QPlatformWindow,
8643 // and we can't assume close is synchronous so we can't reset it here.
8644
8645 // Close native widgets via QWindow::close() in order to run QWindow
8646 // close code. The QWidget-specific close code in handleClose() will
8647 // in this case be called from the Close event handler in QWidgetWindow.
8648 if (QWindow *widgetWindow = windowHandle()) {
8649 if (widgetWindow->isTopLevel())
8650 return widgetWindow->close();
8651 }
8652
8653 return handleClose(QWidgetPrivate::CloseWithEvent);
8654}
8655
8656/*!
8657 \property QWidget::visible
8658 \brief whether the widget is visible
8659
8660 Calling setVisible(true) or show() sets the widget to visible
8661 status if all its parent widgets up to the window are visible. If
8662 an ancestor is not visible, the widget won't become visible until
8663 all its ancestors are shown. If its size or position has changed,
8664 Qt guarantees that a widget gets move and resize events just
8665 before it is shown. If the widget has not been resized yet, Qt
8666 will adjust the widget's size to a useful default using
8667 adjustSize().
8668
8669 Calling setVisible(false) or hide() hides a widget explicitly. An
8670 explicitly hidden widget will never become visible, even if all
8671 its ancestors become visible, unless you show it.
8672
8673 A widget receives show and hide events when its visibility status
8674 changes. Between a hide and a show event, there is no need to
8675 waste CPU cycles preparing or displaying information to the user.
8676 A video application, for example, might simply stop generating new
8677 frames.
8678
8679 A widget that happens to be obscured by other windows on the
8680 screen is considered to be visible. The same applies to iconified
8681 windows and windows that exist on another virtual
8682 desktop (on platforms that support this concept). A widget
8683 receives spontaneous show and hide events when its mapping status
8684 is changed by the window system, e.g. a spontaneous hide event
8685 when the user minimizes the window, and a spontaneous show event
8686 when the window is restored again.
8687
8688 You seldom have to reimplement the setVisible() function. If
8689 you need to change some settings before a widget is shown, use
8690 showEvent() instead. If you need to do some delayed initialization
8691 use the Polish event delivered to the event() function.
8692
8693 \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
8694 showEvent(), hideEvent()
8695*/
8696
8697
8698/*!
8699 Returns \c true if this widget would become visible if \a ancestor is
8700 shown; otherwise returns \c false.
8701
8702 The true case occurs if neither the widget itself nor any parent
8703 up to but excluding \a ancestor has been explicitly hidden.
8704
8705 This function will still return true if the widget is obscured by
8706 other windows on the screen, but could be physically visible if it
8707 or they were to be moved.
8708
8709 isVisibleTo(0) is identical to isVisible().
8710
8711 \sa show(), hide(), isVisible()
8712*/
8713
8714bool QWidget::isVisibleTo(const QWidget *ancestor) const
8715{
8716 if (!ancestor)
8717 return isVisible();
8718 const QWidget * w = this;
8719 while (!w->isHidden()
8720 && !w->isWindow()
8721 && w->parentWidget()
8722 && w->parentWidget() != ancestor)
8723 w = w->parentWidget();
8724 return !w->isHidden();
8725}
8726
8727
8728/*!
8729 Returns the unobscured region where paint events can occur.
8730
8731 For visible widgets, this is an approximation of the area not
8732 covered by other widgets; otherwise, this is an empty region.
8733
8734 The repaint() function calls this function if necessary, so in
8735 general you do not need to call it.
8736
8737*/
8738QRegion QWidget::visibleRegion() const
8739{
8740 Q_D(const QWidget);
8741
8742 QRect clipRect = d->clipRect();
8743 if (clipRect.isEmpty())
8744 return QRegion();
8745 QRegion r(clipRect);
8746 d->subtractOpaqueChildren(r, clipRect);
8747 d->subtractOpaqueSiblings(r);
8748 return r;
8749}
8750
8751
8752QSize QWidgetPrivate::adjustedSize() const
8753{
8754 Q_Q(const QWidget);
8755
8756 QSize s = q->sizeHint();
8757
8758 if (q->isWindow()) {
8759 Qt::Orientations exp;
8760 if (layout) {
8761 if (layout->hasHeightForWidth())
8762 s.setHeight(layout->totalHeightForWidth(s.width()));
8763 exp = layout->expandingDirections();
8764 } else
8765 {
8766 if (q->sizePolicy().hasHeightForWidth())
8767 s.setHeight(q->heightForWidth(s.width()));
8768 exp = q->sizePolicy().expandingDirections();
8769 }
8770 if (exp & Qt::Horizontal)
8771 s.setWidth(qMax(s.width(), 200));
8772 if (exp & Qt::Vertical)
8773 s.setHeight(qMax(s.height(), 100));
8774
8775 QRect screen;
8776 if (const QScreen *screenAtPoint = QGuiApplication::screenAt(q->pos()))
8777 screen = screenAtPoint->geometry();
8778 else
8779 screen = QGuiApplication::primaryScreen()->geometry();
8780
8781 s.setWidth(qMin(s.width(), screen.width()*2/3));
8782 s.setHeight(qMin(s.height(), screen.height()*2/3));
8783
8784 if (QTLWExtra *extra = maybeTopData())
8785 extra->sizeAdjusted = true;
8786 }
8787
8788 if (!s.isValid()) {
8789 QRect r = q->childrenRect(); // get children rectangle
8790 if (r.isNull())
8791 return s;
8792 s = r.size() + QSize(2 * r.x(), 2 * r.y());
8793 }
8794
8795 return s;
8796}
8797
8798/*!
8799 Adjusts the size of the widget to fit its contents.
8800
8801 This function uses sizeHint() if it is valid, i.e., the size hint's width
8802 and height are >= 0. Otherwise, it sets the size to the children
8803 rectangle that covers all child widgets (the union of all child widget
8804 rectangles).
8805
8806 For windows, the screen size is also taken into account. If the sizeHint()
8807 is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
8808 {expanding}, the window will be at least (200, 100). The maximum size of
8809 a window is 2/3 of the screen's width and height.
8810
8811 \sa sizeHint(), childrenRect()
8812*/
8813
8814void QWidget::adjustSize()
8815{
8816 Q_D(QWidget);
8817 ensurePolished();
8818 QSize s = d->adjustedSize();
8819
8820 if (d->layout)
8821 d->layout->activate();
8822
8823 if (s.isValid())
8824 resize(s);
8825}
8826
8827
8828/*!
8829 \property QWidget::sizeHint
8830 \brief the recommended size for the widget
8831
8832 If the value of this property is an invalid size, no size is
8833 recommended.
8834
8835 The default implementation of sizeHint() returns an invalid size
8836 if there is no layout for this widget, and returns the layout's
8837 preferred size otherwise.
8838
8839 \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
8840 setMinimumSize(), updateGeometry()
8841*/
8842
8843QSize QWidget::sizeHint() const
8844{
8845 Q_D(const QWidget);
8846 if (d->layout)
8847 return d->layout->totalSizeHint();
8848 return QSize(-1, -1);
8849}
8850
8851/*!
8852 \property QWidget::minimumSizeHint
8853 \brief the recommended minimum size for the widget
8854
8855 If the value of this property is an invalid size, no minimum size
8856 is recommended.
8857
8858 The default implementation of minimumSizeHint() returns an invalid
8859 size if there is no layout for this widget, and returns the
8860 layout's minimum size otherwise. Most built-in widgets reimplement
8861 minimumSizeHint().
8862
8863 \l QLayout will never resize a widget to a size smaller than the
8864 minimum size hint unless minimumSize() is set or the size policy is
8865 set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
8866 size hint will be ignored.
8867
8868 \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
8869*/
8870QSize QWidget::minimumSizeHint() const
8871{
8872 Q_D(const QWidget);
8873 if (d->layout)
8874 return d->layout->totalMinimumSize();
8875 return QSize(-1, -1);
8876}
8877
8878
8879/*!
8880 \fn QWidget *QWidget::parentWidget() const
8881
8882 Returns the parent of this widget, or \nullptr if it does not have any
8883 parent widget.
8884*/
8885
8886
8887/*!
8888 Returns \c true if this widget is a parent, (or grandparent and so on
8889 to any level), of the given \a child, and both widgets are within
8890 the same window; otherwise returns \c false.
8891*/
8892
8893bool QWidget::isAncestorOf(const QWidget *child) const
8894{
8895 while (child) {
8896 if (child == this)
8897 return true;
8898 if (child->isWindow())
8899 return false;
8900 child = child->parentWidget();
8901 }
8902 return false;
8903}
8904
8905/*****************************************************************************
8906 QWidget event handling
8907 *****************************************************************************/
8908
8909/*!
8910 This is the main event handler; it handles event \a event. You can
8911 reimplement this function in a subclass, but we recommend using
8912 one of the specialized event handlers instead.
8913
8914 Key press and release events are treated differently from other
8915 events. event() checks for Tab and Shift+Tab and tries to move the
8916 focus appropriately. If there is no widget to move the focus to
8917 (or the key press is not Tab or Shift+Tab), event() calls
8918 keyPressEvent().
8919
8920 Mouse and tablet event handling is also slightly special: only
8921 when the widget is \l enabled, event() will call the specialized
8922 handlers such as mousePressEvent(); otherwise it will discard the
8923 event.
8924
8925 This function returns \c true if the event was recognized, otherwise
8926 it returns \c false. If the recognized event was accepted (see \l
8927 QEvent::accepted), any further processing such as event
8928 propagation to the parent widget stops.
8929
8930 \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
8931 keyPressEvent(), keyReleaseEvent(), leaveEvent(),
8932 mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
8933 mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
8934 QObject::event(), QObject::timerEvent()
8935*/
8936
8937bool QWidget::event(QEvent *event)
8938{
8939 Q_D(QWidget);
8940
8941 // ignore mouse and key events when disabled
8942 if (!isEnabled()) {
8943 switch(event->type()) {
8944 case QEvent::TabletPress:
8945 case QEvent::TabletRelease:
8946 case QEvent::TabletMove:
8947 case QEvent::MouseButtonPress:
8948 case QEvent::MouseButtonRelease:
8949 case QEvent::MouseButtonDblClick:
8950 case QEvent::MouseMove:
8951 case QEvent::TouchBegin:
8952 case QEvent::TouchUpdate:
8953 case QEvent::TouchEnd:
8954 case QEvent::TouchCancel:
8955 case QEvent::ContextMenu:
8956 case QEvent::KeyPress:
8957 case QEvent::KeyRelease:
8958#if QT_CONFIG(wheelevent)
8959 case QEvent::Wheel:
8960#endif
8961 return false;
8962 default:
8963 break;
8964 }
8965 }
8966 switch (event->type()) {
8967 case QEvent::PlatformSurface: {
8968 // Sync up QWidget's view of whether or not the widget has been created
8969 switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
8970 case QPlatformSurfaceEvent::SurfaceCreated:
8971 if (!testAttribute(Qt::WA_WState_Created))
8972 create();
8973 break;
8974 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
8975 if (testAttribute(Qt::WA_WState_Created)) {
8976 // Child windows have already been destroyed by QWindow,
8977 // so we skip them here.
8978 destroy(false, false);
8979 }
8980 break;
8981 }
8982 break;
8983 }
8984 case QEvent::MouseMove:
8985 mouseMoveEvent((QMouseEvent*)event);
8986 break;
8987
8988 case QEvent::MouseButtonPress:
8989 mousePressEvent((QMouseEvent*)event);
8990 break;
8991
8992 case QEvent::MouseButtonRelease:
8993 mouseReleaseEvent((QMouseEvent*)event);
8994 break;
8995
8996 case QEvent::MouseButtonDblClick:
8997 mouseDoubleClickEvent((QMouseEvent*)event);
8998 break;
8999#if QT_CONFIG(wheelevent)
9000 case QEvent::Wheel:
9001 wheelEvent((QWheelEvent*)event);
9002 break;
9003#endif
9004#if QT_CONFIG(tabletevent)
9005 case QEvent::TabletMove:
9006 if (static_cast<QTabletEvent *>(event)->buttons() == Qt::NoButton && !testAttribute(Qt::WA_TabletTracking))
9007 break;
9008 Q_FALLTHROUGH();
9009 case QEvent::TabletPress:
9010 case QEvent::TabletRelease:
9011 tabletEvent((QTabletEvent*)event);
9012 break;
9013#endif
9014 case QEvent::KeyPress: {
9015 QKeyEvent *k = static_cast<QKeyEvent *>(event);
9016 bool res = false;
9017 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
9018 if (k->key() == Qt::Key_Backtab
9019 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
9020 res = focusNextPrevChild(false);
9021 else if (k->key() == Qt::Key_Tab)
9022 res = focusNextPrevChild(true);
9023 if (res)
9024 break;
9025 }
9026 keyPressEvent(k);
9027#if QT_CONFIG(whatsthis)
9028 if (!k->isAccepted()
9029 && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
9030 && d->whatsThis.size()) {
9031 QWhatsThis::showText(mapToGlobal(inputMethodQuery(Qt::ImCursorRectangle).toRect().center()), d->whatsThis, this);
9032 k->accept();
9033 }
9034#endif
9035 }
9036 break;
9037
9038 case QEvent::KeyRelease:
9039 keyReleaseEvent((QKeyEvent*)event);
9040 Q_FALLTHROUGH();
9041 case QEvent::ShortcutOverride:
9042 break;
9043
9044 case QEvent::InputMethod:
9045 inputMethodEvent((QInputMethodEvent *) event);
9046 break;
9047
9048 case QEvent::InputMethodQuery: {
9049 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
9050 Qt::InputMethodQueries queries = query->queries();
9051 for (uint i = 0; i < 32; ++i) {
9052 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
9053 if (q) {
9054 QVariant v = inputMethodQuery(q);
9055 if (q == Qt::ImEnabled && !v.isValid() && isEnabled()) {
9056 // Qt:ImEnabled was added in Qt 5.3. So not all widgets support it, even
9057 // if they implement IM otherwise (by overriding inputMethodQuery()). Instead
9058 // they set the widget attribute Qt::WA_InputMethodEnabled. But this attribute
9059 // will only be set if the widget supports IM _and_ is not read-only. So for
9060 // read-only widgets, not all IM features will be supported when ImEnabled is
9061 // not implemented explicitly (e.g selection handles for read-only widgets on iOS).
9062 v = QVariant(testAttribute(Qt::WA_InputMethodEnabled));
9063 }
9064 query->setValue(q, v);
9065 }
9066 }
9067 query->accept();
9068 }
9069 break;
9070
9071 case QEvent::PolishRequest:
9072 ensurePolished();
9073 break;
9074
9075 case QEvent::Polish: {
9076 style()->polish(this);
9077 setAttribute(Qt::WA_WState_Polished);
9078 if (!QApplication::font(this).isCopyOf(QApplication::font()))
9079 d->resolveFont();
9080 if (!QApplication::palette(this).isCopyOf(QGuiApplication::palette()))
9081 d->resolvePalette();
9082 }
9083 break;
9084
9085 case QEvent::ApplicationWindowIconChange:
9086 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon)) {
9087 d->setWindowIcon_sys();
9088 d->setWindowIcon_helper();
9089 }
9090 break;
9091 case QEvent::FocusIn:
9092 focusInEvent((QFocusEvent*)event);
9093 d->updateWidgetTransform(event);
9094 break;
9095
9096 case QEvent::FocusOut:
9097 focusOutEvent((QFocusEvent*)event);
9098 break;
9099
9100 case QEvent::Enter:
9101#if QT_CONFIG(statustip)
9102 if (d->statusTip.size()) {
9103 QStatusTipEvent tip(d->statusTip);
9104 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
9105 }
9106#endif
9107 enterEvent(static_cast<QEnterEvent*>(event));
9108 break;
9109
9110 case QEvent::Leave:
9111#if QT_CONFIG(statustip)
9112 if (d->statusTip.size()) {
9113 QString empty;
9114 QStatusTipEvent tip(empty);
9115 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
9116 }
9117#endif
9118 leaveEvent(event);
9119 break;
9120
9121 case QEvent::HoverEnter:
9122 case QEvent::HoverLeave:
9123 update();
9124 break;
9125
9126 case QEvent::Paint:
9127 // At this point the event has to be delivered, regardless
9128 // whether the widget isVisible() or not because it
9129 // already went through the filters
9130 paintEvent((QPaintEvent*)event);
9131 break;
9132
9133 case QEvent::Move:
9134 moveEvent((QMoveEvent*)event);
9135 d->updateWidgetTransform(event);
9136 break;
9137
9138 case QEvent::Resize:
9139 resizeEvent((QResizeEvent*)event);
9140 d->updateWidgetTransform(event);
9141 break;
9142
9143 case QEvent::Close:
9144 closeEvent((QCloseEvent *)event);
9145 break;
9146
9147#ifndef QT_NO_CONTEXTMENU
9148 case QEvent::ContextMenu:
9149 switch (data->context_menu_policy) {
9150 case Qt::PreventContextMenu:
9151 break;
9152 case Qt::DefaultContextMenu:
9153 contextMenuEvent(static_cast<QContextMenuEvent *>(event));
9154 break;
9155 case Qt::CustomContextMenu:
9156 emit customContextMenuRequested(static_cast<QContextMenuEvent *>(event)->pos());
9157 break;
9158#if QT_CONFIG(menu)
9159 case Qt::ActionsContextMenu:
9160 if (d->actions.size()) {
9161 QMenu::exec(d->actions, static_cast<QContextMenuEvent *>(event)->globalPos(),
9162 nullptr, this);
9163 break;
9164 }
9165 Q_FALLTHROUGH();
9166#endif
9167 default:
9168 event->ignore();
9169 break;
9170 }
9171 break;
9172#endif // QT_NO_CONTEXTMENU
9173
9174#if QT_CONFIG(draganddrop)
9175 case QEvent::Drop:
9176 dropEvent((QDropEvent*) event);
9177 break;
9178
9179 case QEvent::DragEnter:
9180 dragEnterEvent((QDragEnterEvent*) event);
9181 break;
9182
9183 case QEvent::DragMove:
9184 dragMoveEvent((QDragMoveEvent*) event);
9185 break;
9186
9187 case QEvent::DragLeave:
9188 dragLeaveEvent((QDragLeaveEvent*) event);
9189 break;
9190#endif
9191
9192 case QEvent::Show:
9193 showEvent((QShowEvent*) event);
9194 break;
9195
9196 case QEvent::Hide:
9197 hideEvent((QHideEvent*) event);
9198 break;
9199
9200 case QEvent::ShowWindowRequest:
9201 if (!isHidden())
9202 d->show_sys();
9203 break;
9204
9205 case QEvent::ApplicationFontChange:
9206 d->resolveFont();
9207 break;
9208 case QEvent::ApplicationPaletteChange:
9209 d->resolvePalette();
9210 break;
9211
9212 case QEvent::ToolBarChange:
9213 case QEvent::ActivationChange:
9214 case QEvent::EnabledChange:
9215 case QEvent::FontChange:
9216 case QEvent::StyleChange:
9217 case QEvent::PaletteChange:
9218 case QEvent::WindowTitleChange:
9219 case QEvent::IconTextChange:
9220 case QEvent::ModifiedChange:
9221 case QEvent::MouseTrackingChange:
9222 case QEvent::TabletTrackingChange:
9223 case QEvent::ParentChange:
9224 case QEvent::LocaleChange:
9225 case QEvent::MacSizeChange:
9226 case QEvent::ContentsRectChange:
9227 case QEvent::ThemeChange:
9228 case QEvent::ReadOnlyChange:
9229 changeEvent(event);
9230 break;
9231
9232 case QEvent::WindowStateChange: {
9233 const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
9234 if (wasMinimized != isMinimized()) {
9235 QWidget *widget = const_cast<QWidget *>(this);
9236 if (wasMinimized) {
9237 // Always send the spontaneous events here, otherwise it can break the application!
9238 if (!d->childrenShownByExpose) {
9239 // Show widgets only when they are not yet shown by the expose event
9240 d->showChildren(true);
9241 QShowEvent showEvent;
9242 QCoreApplication::sendSpontaneousEvent(widget, &showEvent);
9243 }
9244 d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
9245 } else {
9246 QHideEvent hideEvent;
9247 QCoreApplication::sendSpontaneousEvent(widget, &hideEvent);
9248 d->hideChildren(true);
9249 d->childrenHiddenByWState = true;
9250 }
9251 d->childrenShownByExpose = false; // Set it always to "false" when window state changes
9252 }
9253 changeEvent(event);
9254 }
9255 break;
9256
9257 case QEvent::WindowActivate:
9258 case QEvent::WindowDeactivate: {
9259 if (isVisible() && !palette().isEqual(QPalette::Active, QPalette::Inactive))
9260 update();
9261 QList<QObject*> childList = d->children;
9262 for (int i = 0; i < childList.size(); ++i) {
9263 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9264 if (w && w->isVisible() && !w->isWindow())
9265 QCoreApplication::sendEvent(w, event);
9266 }
9267 break; }
9268
9269 case QEvent::LanguageChange:
9270 changeEvent(event);
9271 {
9272 QList<QObject*> childList = d->children;
9273 for (int i = 0; i < childList.size(); ++i) {
9274 QObject *o = childList.at(i);
9275 if (o)
9276 QCoreApplication::sendEvent(o, event);
9277 }
9278 }
9279 update();
9280 break;
9281
9282 case QEvent::ApplicationLayoutDirectionChange:
9283 d->resolveLayoutDirection();
9284 break;
9285
9286 case QEvent::LayoutDirectionChange:
9287 if (d->layout)
9288 d->layout->invalidate();
9289 update();
9290 changeEvent(event);
9291 break;
9292 case QEvent::UpdateRequest:
9293 d->syncBackingStore();
9294 break;
9295 case QEvent::UpdateLater:
9296 update(static_cast<QUpdateLaterEvent*>(event)->region());
9297 break;
9298 case QEvent::StyleAnimationUpdate:
9299 if (isVisible() && !window()->isMinimized()) {
9300 event->accept();
9301 update();
9302 }
9303 break;
9304
9305 case QEvent::WindowBlocked:
9306 case QEvent::WindowUnblocked:
9307 if (!d->children.isEmpty()) {
9308 QWidget *modalWidget = QApplication::activeModalWidget();
9309 for (int i = 0; i < d->children.size(); ++i) {
9310 QObject *o = d->children.at(i);
9311 if (o && o != modalWidget && o->isWidgetType()) {
9312 QWidget *w = static_cast<QWidget *>(o);
9313 // do not forward the event to child windows; QApplication does this for us
9314 if (!w->isWindow())
9315 QCoreApplication::sendEvent(w, event);
9316 }
9317 }
9318 }
9319 break;
9320#if QT_CONFIG(tooltip)
9321 case QEvent::ToolTip:
9322 if (!d->toolTip.isEmpty())
9323 QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), d->toolTip, this, QRect(), d->toolTipDuration);
9324 else
9325 event->ignore();
9326 break;
9327#endif
9328#if QT_CONFIG(whatsthis)
9329 case QEvent::WhatsThis:
9330 if (d->whatsThis.size())
9331 QWhatsThis::showText(static_cast<QHelpEvent *>(event)->globalPos(), d->whatsThis, this);
9332 else
9333 event->ignore();
9334 break;
9335 case QEvent::QueryWhatsThis:
9336 if (d->whatsThis.isEmpty())
9337 event->ignore();
9338 break;
9339#endif
9340 case QEvent::EmbeddingControl:
9341 d->topData()->frameStrut.setCoords(0 ,0, 0, 0);
9342 data->fstrut_dirty = false;
9343 break;
9344#ifndef QT_NO_ACTION
9345 case QEvent::ActionAdded:
9346 case QEvent::ActionRemoved:
9347 case QEvent::ActionChanged:
9348 actionEvent((QActionEvent*)event);
9349 break;
9350#endif
9351
9352 case QEvent::KeyboardLayoutChange:
9353 {
9354 changeEvent(event);
9355
9356 // inform children of the change
9357 QList<QObject*> childList = d->children;
9358 for (int i = 0; i < childList.size(); ++i) {
9359 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9360 if (w && w->isVisible() && !w->isWindow())
9361 QCoreApplication::sendEvent(w, event);
9362 }
9363 break;
9364 }
9365 case QEvent::TouchBegin:
9366 case QEvent::TouchUpdate:
9367 case QEvent::TouchEnd:
9368 case QEvent::TouchCancel:
9369 {
9370 event->ignore();
9371 break;
9372 }
9373#ifndef QT_NO_GESTURES
9374 case QEvent::Gesture:
9375 event->ignore();
9376 break;
9377#endif
9378 case QEvent::ScreenChangeInternal:
9379 if (const QTLWExtra *te = d->maybeTopData()) {
9380 const QWindow *win = te->window;
9381 d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
9382 }
9383 break;
9384 case QEvent::DevicePixelRatioChange:
9385 if (d->data.fnt.d->dpi != logicalDpiY())
9386 d->updateFont(d->data.fnt);
9387 d->renderToTextureReallyDirty = 1;
9388 break;
9389 case QEvent::DynamicPropertyChange: {
9390 const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
9391 if (propName.size() == 13 && !qstrncmp(propName, "_q_customDpi", 12)) {
9392 uint value = property(propName.constData()).toUInt();
9393 if (!d->extra)
9394 d->createExtra();
9395 const char axis = propName.at(12);
9396 if (axis == 'X')
9397 d->extra->customDpiX = value;
9398 else if (axis == 'Y')
9399 d->extra->customDpiY = value;
9400 d->updateFont(d->data.fnt);
9401 }
9402 if (windowHandle() && !qstrncmp(propName, "_q_platform_", 12))
9403 windowHandle()->setProperty(propName, property(propName));
9404 Q_FALLTHROUGH();
9405 }
9406 default:
9407 return QObject::event(event);
9408 }
9409 return true;
9410}
9411
9412/*!
9413 This event handler can be reimplemented to handle state changes.
9414
9415 The state being changed in this event can be retrieved through the \a event
9416 supplied.
9417
9418 Change events include: QEvent::ToolBarChange,
9419 QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
9420 QEvent::StyleChange, QEvent::PaletteChange,
9421 QEvent::WindowTitleChange, QEvent::IconTextChange,
9422 QEvent::ModifiedChange, QEvent::MouseTrackingChange,
9423 QEvent::ParentChange, QEvent::WindowStateChange,
9424 QEvent::LanguageChange, QEvent::LocaleChange,
9425 QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
9426
9427*/
9428void QWidget::changeEvent(QEvent * event)
9429{
9430 switch(event->type()) {
9431 case QEvent::EnabledChange: {
9432 update();
9433#if QT_CONFIG(accessibility)
9434 QAccessible::State s;
9435 s.disabled = true;
9436 QAccessibleStateChangeEvent event(this, s);
9437 QAccessible::updateAccessibility(&event);
9438#endif
9439 break;
9440 }
9441
9442 case QEvent::FontChange:
9443 case QEvent::StyleChange: {
9444 Q_D(QWidget);
9445 update();
9446 updateGeometry();
9447 if (d->layout)
9448 d->layout->invalidate();
9449 break;
9450 }
9451
9452 case QEvent::PaletteChange:
9453 update();
9454 break;
9455
9456 case QEvent::ThemeChange:
9457 if (QGuiApplication::desktopSettingsAware()
9458 && qApp && !QCoreApplication::closingDown()) {
9459 if (testAttribute(Qt::WA_WState_Polished))
9460 QApplication::style()->unpolish(this);
9461 if (testAttribute(Qt::WA_WState_Polished))
9462 QApplication::style()->polish(this);
9463 QEvent styleChangedEvent(QEvent::StyleChange);
9464 QCoreApplication::sendEvent(this, &styleChangedEvent);
9465 if (isVisible())
9466 update();
9467 }
9468 break;
9469
9470#ifdef Q_OS_MACOS
9471 case QEvent::MacSizeChange:
9472 updateGeometry();
9473 break;
9474#endif
9475
9476 default:
9477 break;
9478 }
9479}
9480
9481/*!
9482 This event handler, for event \a event, can be reimplemented in a
9483 subclass to receive mouse move events for the widget.
9484
9485 If mouse tracking is switched off, mouse move events only occur if
9486 a mouse button is pressed while the mouse is being moved. If mouse
9487 tracking is switched on, mouse move events occur even if no mouse
9488 button is pressed.
9489
9490 QMouseEvent::position() reports the position of the mouse cursor,
9491 relative to this widget. For press and release events, the
9492 position is usually the same as the position of the last mouse
9493 move event, but it might be different if the user's hand shakes.
9494 This is a feature of the underlying window system, not Qt.
9495
9496 If you want to show a tooltip immediately, while the mouse is
9497 moving (e.g., to get the mouse coordinates with QMouseEvent::position()
9498 and show them as a tooltip), you must first enable mouse tracking
9499 as described above. Then, to ensure that the tooltip is updated
9500 immediately, you must call QToolTip::showText() instead of
9501 setToolTip() in your implementation of mouseMoveEvent().
9502
9503 \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
9504 mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
9505*/
9506
9507void QWidget::mouseMoveEvent(QMouseEvent *event)
9508{
9509 event->ignore();
9510}
9511
9512/*!
9513 This event handler, for event \a event, can be reimplemented in a
9514 subclass to receive mouse press events for the widget.
9515
9516 If you create new widgets in the mousePressEvent() the
9517 mouseReleaseEvent() may not end up where you expect, depending on
9518 the underlying window system (or X11 window manager), the widgets'
9519 location and maybe more.
9520
9521 The default implementation implements the closing of popup widgets
9522 when you click outside the window. For other widget types it does
9523 nothing.
9524
9525 \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
9526 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9527*/
9528
9529void QWidget::mousePressEvent(QMouseEvent *event)
9530{
9531 event->ignore();
9532 if ((windowType() == Qt::Popup)) {
9533 event->accept();
9534 QWidget* w;
9535 while ((w = QApplication::activePopupWidget()) && w != this){
9536 w->close();
9537 if (QApplication::activePopupWidget() == w) // widget does not want to disappear
9538 w->hide(); // hide at least
9539 }
9540 if (!rect().contains(event->position().toPoint())){
9541 close();
9542 }
9543 }
9544}
9545
9546/*!
9547 This event handler, for event \a event, can be reimplemented in a
9548 subclass to receive mouse release events for the widget.
9549
9550 \sa mousePressEvent(), mouseDoubleClickEvent(),
9551 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9552*/
9553
9554void QWidget::mouseReleaseEvent(QMouseEvent *event)
9555{
9556 event->ignore();
9557}
9558
9559/*!
9560 This event handler, for event \a event, can be reimplemented in a
9561 subclass to receive mouse double click events for the widget.
9562
9563 The default implementation calls mousePressEvent().
9564
9565 \note The widget will also receive mouse press and mouse release
9566 events in addition to the double click event. And if another widget
9567 that overlaps this widget disappears in response to press or
9568 release events, then this widget will only receive the double click
9569 event. It is up to the developer to ensure that the application
9570 interprets these events correctly.
9571
9572 \sa mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(),
9573 event(), QMouseEvent
9574*/
9575
9576void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
9577{
9578 mousePressEvent(event);
9579}
9580
9581#if QT_CONFIG(wheelevent)
9582/*!
9583 This event handler, for event \a event, can be reimplemented in a
9584 subclass to receive wheel events for the widget.
9585
9586 If you reimplement this handler, it is very important that you
9587 \l{QEvent}{ignore()} the event if you do not handle
9588 it, so that the widget's parent can interpret it.
9589
9590 The default implementation ignores the event.
9591
9592 \sa QEvent::ignore(), QEvent::accept(), event(),
9593 QWheelEvent
9594*/
9595
9596void QWidget::wheelEvent(QWheelEvent *event)
9597{
9598 event->ignore();
9599}
9600#endif // QT_CONFIG(wheelevent)
9601
9602#if QT_CONFIG(tabletevent)
9603/*!
9604 This event handler, for event \a event, can be reimplemented in a
9605 subclass to receive tablet events for the widget.
9606
9607 If you reimplement this handler, it is very important that you
9608 \l{QEvent}{ignore()} the event if you do not handle
9609 it, so that the widget's parent can interpret it.
9610
9611 The default implementation ignores the event.
9612
9613 If tablet tracking is switched off, tablet move events only occur if the
9614 stylus is in contact with the tablet, or at least one stylus button is
9615 pressed, while the stylus is being moved. If tablet tracking is switched on,
9616 tablet move events occur even while the stylus is hovering in proximity of
9617 the tablet, with no buttons pressed.
9618
9619 \sa QEvent::ignore(), QEvent::accept(), event(), setTabletTracking(),
9620 QTabletEvent
9621*/
9622
9623void QWidget::tabletEvent(QTabletEvent *event)
9624{
9625 event->ignore();
9626}
9627#endif // QT_CONFIG(tabletevent)
9628
9629/*!
9630 This event handler, for event \a event, can be reimplemented in a
9631 subclass to receive key press events for the widget.
9632
9633 A widget must call setFocusPolicy() to accept focus initially and
9634 have focus in order to receive a key press event.
9635
9636 If you reimplement this handler, it is very important that you
9637 call the base class implementation if you do not act upon the key.
9638
9639 The default implementation closes popup widgets if the user
9640 presses the key sequence for QKeySequence::Cancel (typically the
9641 Escape key). Otherwise the event is ignored, so that the widget's
9642 parent can interpret it.
9643
9644 Note that QKeyEvent starts with isAccepted() == true, so you do not
9645 need to call QKeyEvent::accept() - just do not call the base class
9646 implementation if you act upon the key.
9647
9648 \sa keyReleaseEvent(), setFocusPolicy(),
9649 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9650*/
9651
9652void QWidget::keyPressEvent(QKeyEvent *event)
9653{
9654#ifndef QT_NO_SHORTCUT
9655 if ((windowType() == Qt::Popup) && event->matches(QKeySequence::Cancel)) {
9656 event->accept();
9657 close();
9658 } else
9659#endif
9660 {
9661 event->ignore();
9662 }
9663}
9664
9665/*!
9666 This event handler, for event \a event, can be reimplemented in a
9667 subclass to receive key release events for the widget.
9668
9669 A widget must \l{setFocusPolicy()}{accept focus}
9670 initially and \l{hasFocus()}{have focus} in order to
9671 receive a key release event.
9672
9673 If you reimplement this handler, it is very important that you
9674 call the base class implementation if you do not act upon the key.
9675
9676 The default implementation ignores the event, so that the widget's
9677 parent can interpret it.
9678
9679 Note that QKeyEvent starts with isAccepted() == true, so you do not
9680 need to call QKeyEvent::accept() - just do not call the base class
9681 implementation if you act upon the key.
9682
9683 \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(),
9684 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9685*/
9686
9687void QWidget::keyReleaseEvent(QKeyEvent *event)
9688{
9689 event->ignore();
9690}
9691
9692/*!
9693 \fn void QWidget::focusInEvent(QFocusEvent *event)
9694
9695 This event handler can be reimplemented in a subclass to receive
9696 keyboard focus events (focus received) for the widget. The event
9697 is passed in the \a event parameter
9698
9699 A widget normally must setFocusPolicy() to something other than
9700 Qt::NoFocus to receive focus events. (Note that the
9701 application programmer can call setFocus() on any widget, even
9702 those that do not normally accept focus.)
9703
9704 The default implementation updates the widget (except for windows
9705 that do not specify a focusPolicy()).
9706
9707 \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
9708 keyReleaseEvent(), event(), QFocusEvent
9709*/
9710
9711void QWidget::focusInEvent(QFocusEvent *)
9712{
9713 if (focusPolicy() != Qt::NoFocus || !isWindow()) {
9714 update();
9715 }
9716}
9717
9718/*!
9719 \fn void QWidget::focusOutEvent(QFocusEvent *event)
9720
9721 This event handler can be reimplemented in a subclass to receive
9722 keyboard focus events (focus lost) for the widget. The events is
9723 passed in the \a event parameter.
9724
9725 A widget normally must setFocusPolicy() to something other than
9726 Qt::NoFocus to receive focus events. (Note that the
9727 application programmer can call setFocus() on any widget, even
9728 those that do not normally accept focus.)
9729
9730 The default implementation updates the widget (except for windows
9731 that do not specify a focusPolicy()).
9732
9733 \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
9734 keyReleaseEvent(), event(), QFocusEvent
9735*/
9736
9737void QWidget::focusOutEvent(QFocusEvent *)
9738{
9739 if (focusPolicy() != Qt::NoFocus || !isWindow())
9740 update();
9741
9742#if !defined(QT_PLATFORM_UIKIT)
9743 // FIXME: revisit autoSIP logic, QTBUG-42906
9744 if (qApp->autoSipEnabled() && testAttribute(Qt::WA_InputMethodEnabled))
9745 QGuiApplication::inputMethod()->hide();
9746#endif
9747}
9748
9749/*!
9750 \fn void QWidget::enterEvent(QEnterEvent *event)
9751
9752 This event handler can be reimplemented in a subclass to receive
9753 widget enter events which are passed in the \a event parameter.
9754
9755 An event is sent to the widget when the mouse cursor enters the
9756 widget.
9757
9758 \sa leaveEvent(), mouseMoveEvent(), event()
9759*/
9760
9761void QWidget::enterEvent(QEnterEvent *)
9762{
9763}
9764
9765/*!
9766 \fn void QWidget::leaveEvent(QEvent *event)
9767
9768 This event handler can be reimplemented in a subclass to receive
9769 widget leave events which are passed in the \a event parameter.
9770
9771 A leave event is sent to the widget when the mouse cursor leaves
9772 the widget.
9773
9774 \sa enterEvent(), mouseMoveEvent(), event()
9775*/
9776
9777void QWidget::leaveEvent(QEvent *)
9778{
9779}
9780
9781/*!
9782 \fn void QWidget::paintEvent(QPaintEvent *event)
9783
9784 This event handler can be reimplemented in a subclass to receive paint
9785 events passed in \a event.
9786
9787 A paint event is a request to repaint all or part of a widget. It can
9788 happen for one of the following reasons:
9789
9790 \list
9791 \li repaint() or update() was invoked,
9792 \li the widget was obscured and has now been uncovered, or
9793 \li many other reasons.
9794 \endlist
9795
9796 Many widgets can simply repaint their entire surface when asked to, but
9797 some slow widgets need to optimize by painting only the requested region:
9798 QPaintEvent::region(). This speed optimization does not change the result,
9799 as painting is clipped to that region during event processing. QListView
9800 and QTableView do this, for example.
9801
9802 Qt also tries to speed up painting by merging multiple paint events into
9803 one. When update() is called several times or the window system sends
9804 several paint events, Qt merges these events into one event with a larger
9805 region (see QRegion::united()). The repaint() function does not permit this
9806 optimization, so we suggest using update() whenever possible.
9807
9808 When the paint event occurs, the update region has normally been erased, so
9809 you are painting on the widget's background.
9810
9811 The background can be set using setBackgroundRole() and setPalette().
9812
9813 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
9814 is no need to write double-buffering code in paintEvent() to avoid flicker.
9815
9816 \note Generally, you should refrain from calling update() or repaint()
9817 \b{inside} a paintEvent(). For example, calling update() or repaint() on
9818 children inside a paintEvent() results in undefined behavior; the child may
9819 or may not get a paint event.
9820
9821 \warning If you are using a custom paint engine without Qt's backingstore,
9822 Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
9823 never be called; the backingstore will be used instead.
9824
9825 \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
9826 {Analog Clock}
9827*/
9828
9829void QWidget::paintEvent(QPaintEvent *)
9830{
9831}
9832
9833
9834/*!
9835 \fn void QWidget::moveEvent(QMoveEvent *event)
9836
9837 This event handler can be reimplemented in a subclass to receive
9838 widget move events which are passed in the \a event parameter.
9839 When the widget receives this event, it is already at the new
9840 position.
9841
9842 The old position is accessible through QMoveEvent::oldPos().
9843
9844 \sa resizeEvent(), event(), move(), QMoveEvent
9845*/
9846
9847void QWidget::moveEvent(QMoveEvent *)
9848{
9849}
9850
9851
9852/*!
9853 This event handler can be reimplemented in a subclass to receive
9854 widget resize events which are passed in the \a event parameter.
9855 When resizeEvent() is called, the widget already has its new
9856 geometry. The old size is accessible through
9857 QResizeEvent::oldSize().
9858
9859 The widget will be erased and receive a paint event immediately
9860 after processing the resize event. No drawing need be (or should
9861 be) done inside this handler.
9862
9863
9864 \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
9865 {Scribble Example}
9866*/
9867
9868void QWidget::resizeEvent(QResizeEvent * /* event */)
9869{
9870}
9871
9872#ifndef QT_NO_ACTION
9873/*!
9874 \fn void QWidget::actionEvent(QActionEvent *event)
9875
9876 This event handler is called with the given \a event whenever the
9877 widget's actions are changed.
9878
9879 \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
9880*/
9881void QWidget::actionEvent(QActionEvent *)
9882{
9883
9884}
9885#endif
9886
9887/*!
9888 This event handler is called with the given \a event when Qt receives a window
9889 close request for a top-level widget from the window system.
9890
9891 By default, the event is accepted and the widget is closed. You can reimplement
9892 this function to change the way the widget responds to window close requests.
9893 For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
9894 on all events.
9895
9896 Main window applications typically use reimplementations of this function to check
9897 whether the user's work has been saved and ask for permission before closing.
9898
9899 \sa event(), hide(), close(), QCloseEvent
9900*/
9901
9902void QWidget::closeEvent(QCloseEvent *event)
9903{
9904 event->accept();
9905}
9906
9907#ifndef QT_NO_CONTEXTMENU
9908/*!
9909 This event handler, for event \a event, can be reimplemented in a
9910 subclass to receive widget context menu events.
9911
9912 The handler is called when the widget's \l contextMenuPolicy is
9913 Qt::DefaultContextMenu.
9914
9915 The default implementation ignores the context event.
9916 See the \l QContextMenuEvent documentation for more details.
9917
9918 \sa event(), QContextMenuEvent, customContextMenuRequested()
9919*/
9920
9921void QWidget::contextMenuEvent(QContextMenuEvent *event)
9922{
9923 event->ignore();
9924}
9925#endif // QT_NO_CONTEXTMENU
9926
9927
9928/*!
9929 This event handler, for event \a event, can be reimplemented in a
9930 subclass to receive Input Method composition events. This handler
9931 is called when the state of the input method changes.
9932
9933 Note that when creating custom text editing widgets, the
9934 Qt::WA_InputMethodEnabled window attribute must be set explicitly
9935 (using the setAttribute() function) in order to receive input
9936 method events.
9937
9938 The default implementation calls event->ignore(), which rejects the
9939 Input Method event. See the \l QInputMethodEvent documentation for more
9940 details.
9941
9942 \sa event(), QInputMethodEvent
9943*/
9944void QWidget::inputMethodEvent(QInputMethodEvent *event)
9945{
9946 event->ignore();
9947}
9948
9949/*!
9950 This method is only relevant for input widgets. It is used by the
9951 input method to query a set of properties of the widget to be
9952 able to support complex input method operations as support for
9953 surrounding text and reconversions.
9954
9955 \a query specifies which property is queried.
9956
9957 \sa inputMethodEvent(), QInputMethodEvent, QInputMethodQueryEvent, inputMethodHints
9958*/
9959QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
9960{
9961 switch(query) {
9962 case Qt::ImCursorRectangle:
9963 return QRect(width()/2, 0, 1, height());
9964 case Qt::ImFont:
9965 return font();
9966 case Qt::ImAnchorPosition:
9967 // Fallback.
9968 return inputMethodQuery(Qt::ImCursorPosition);
9969 case Qt::ImHints:
9970 return (int)inputMethodHints();
9971 case Qt::ImInputItemClipRectangle:
9972 return d_func()->clipRect();
9973 default:
9974 return QVariant();
9975 }
9976}
9977
9978/*!
9979 \property QWidget::inputMethodHints
9980 \brief What input method specific hints the widget has.
9981
9982 This is only relevant for input widgets. It is used by
9983 the input method to retrieve hints as to how the input method
9984 should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
9985 is set, the input method may change its visual components to reflect
9986 that only numbers can be entered.
9987
9988 \warning Some widgets require certain flags to work as
9989 intended. To set a flag, do \c{w->setInputMethodHints(w->inputMethodHints()|f)}
9990 instead of \c{w->setInputMethodHints(f)}.
9991
9992 \note The flags are only hints, so the particular input method
9993 implementation is free to ignore them. If you want to be
9994 sure that a certain type of characters are entered,
9995 you should also set a QValidator on the widget.
9996
9997 The default value is Qt::ImhNone.
9998
9999 \since 4.6
10000
10001 \sa inputMethodQuery()
10002*/
10003Qt::InputMethodHints QWidget::inputMethodHints() const
10004{
10005#if QT_CONFIG(im)
10006 const QWidgetPrivate *priv = d_func();
10007 while (priv->inheritsInputMethodHints) {
10008 priv = priv->q_func()->parentWidget()->d_func();
10009 Q_ASSERT(priv);
10010 }
10011 return priv->imHints;
10012#else
10013 return Qt::ImhNone;
10014#endif
10015}
10016
10017void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
10018{
10019#ifndef QT_NO_IM
10020 Q_D(QWidget);
10021 if (d->imHints == hints)
10022 return;
10023 d->imHints = hints;
10024 if (this == QGuiApplication::focusObject())
10025 QGuiApplication::inputMethod()->update(Qt::ImHints);
10026#else
10027 Q_UNUSED(hints);
10028#endif //QT_NO_IM
10029}
10030
10031
10032#if QT_CONFIG(draganddrop)
10033
10034/*!
10035 \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
10036
10037 This event handler is called when a drag is in progress and the
10038 mouse enters this widget. The event is passed in the \a event parameter.
10039
10040 If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
10041 move events}.
10042
10043 See the \l{dnd.html}{Drag-and-drop documentation} for an
10044 overview of how to provide drag-and-drop in your application.
10045
10046 \sa QDrag, QDragEnterEvent
10047*/
10048void QWidget::dragEnterEvent(QDragEnterEvent *)
10049{
10050}
10051
10052/*!
10053 \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
10054
10055 This event handler is called if a drag is in progress, and when
10056 any of the following conditions occur: the cursor enters this widget,
10057 the cursor moves within this widget, or a modifier key is pressed on
10058 the keyboard while this widget has the focus. The event is passed
10059 in the \a event parameter.
10060
10061 See the \l{dnd.html}{Drag-and-drop documentation} for an
10062 overview of how to provide drag-and-drop in your application.
10063
10064 \sa QDrag, QDragMoveEvent
10065*/
10066void QWidget::dragMoveEvent(QDragMoveEvent *)
10067{
10068}
10069
10070/*!
10071 \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
10072
10073 This event handler is called when a drag is in progress and the
10074 mouse leaves this widget. The event is passed in the \a event
10075 parameter.
10076
10077 See the \l{dnd.html}{Drag-and-drop documentation} for an
10078 overview of how to provide drag-and-drop in your application.
10079
10080 \sa QDrag, QDragLeaveEvent
10081*/
10082void QWidget::dragLeaveEvent(QDragLeaveEvent *)
10083{
10084}
10085
10086/*!
10087 \fn void QWidget::dropEvent(QDropEvent *event)
10088
10089 This event handler is called when the drag is dropped on this
10090 widget. The event is passed in the \a event parameter.
10091
10092 See the \l{dnd.html}{Drag-and-drop documentation} for an
10093 overview of how to provide drag-and-drop in your application.
10094
10095 \sa QDrag, QDropEvent
10096*/
10097void QWidget::dropEvent(QDropEvent *)
10098{
10099}
10100
10101#endif // QT_CONFIG(draganddrop)
10102
10103/*!
10104 \fn void QWidget::showEvent(QShowEvent *event)
10105
10106 This event handler can be reimplemented in a subclass to receive
10107 widget show events which are passed in the \a event parameter.
10108
10109 Non-spontaneous show events are sent to widgets immediately
10110 before they are shown. The spontaneous show events of windows are
10111 delivered afterwards.
10112
10113 Note: A widget receives spontaneous show and hide events when its
10114 mapping status is changed by the window system, e.g. a spontaneous
10115 hide event when the user minimizes the window, and a spontaneous
10116 show event when the window is restored again. After receiving a
10117 spontaneous hide event, a widget is still considered visible in
10118 the sense of isVisible().
10119
10120 \sa visible, event(), QShowEvent
10121*/
10122void QWidget::showEvent(QShowEvent *)
10123{
10124}
10125
10126/*!
10127 \fn void QWidget::hideEvent(QHideEvent *event)
10128
10129 This event handler can be reimplemented in a subclass to receive
10130 widget hide events. The event is passed in the \a event parameter.
10131
10132 Hide events are sent to widgets immediately after they have been
10133 hidden.
10134
10135 Note: A widget receives spontaneous show and hide events when its
10136 mapping status is changed by the window system, e.g. a spontaneous
10137 hide event when the user minimizes the window, and a spontaneous
10138 show event when the window is restored again. After receiving a
10139 spontaneous hide event, a widget is still considered visible in
10140 the sense of isVisible().
10141
10142 \sa visible, event(), QHideEvent
10143*/
10144void QWidget::hideEvent(QHideEvent *)
10145{
10146}
10147
10148/*!
10149 This special event handler can be reimplemented in a subclass to
10150 receive native platform events identified by \a eventType
10151 which are passed in the \a message parameter.
10152
10153 In your reimplementation of this function, if you want to stop the
10154 event being handled by Qt, return true and set \a result. The \a result
10155 parameter has meaning only on Windows. If you return false, this native
10156 event is passed back to Qt, which translates the event into a Qt event
10157 and sends it to the widget.
10158
10159 \note Events are only delivered to this event handler if the widget
10160 has a native window handle.
10161
10162 \note This function superseedes the event filter functions
10163 x11Event(), winEvent() and macEvent() of Qt 4.
10164
10165 \sa QAbstractNativeEventFilter
10166
10167 \table
10168 \header \li Platform \li Event Type Identifier \li Message Type \li Result Type
10169 \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
10170 \row \li macOS \li "NSEvent" \li NSEvent * \li
10171 \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li
10172 \endtable
10173*/
10174
10175bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
10176{
10177 Q_UNUSED(eventType);
10178 Q_UNUSED(message);
10179 Q_UNUSED(result);
10180 return false;
10181}
10182
10183/*!
10184 Ensures that the widget and its children have been polished by
10185 QStyle (i.e., have a proper font and palette).
10186
10187 QWidget calls this function after it has been fully constructed
10188 but before it is shown the very first time. You can call this
10189 function if you want to ensure that the widget is polished before
10190 doing an operation, e.g., the correct font size might be needed in
10191 the widget's sizeHint() reimplementation. Note that this function
10192 \e is called from the default implementation of sizeHint().
10193
10194 Polishing is useful for final initialization that must happen after
10195 all constructors (from base classes as well as from subclasses)
10196 have been called.
10197
10198 If you need to change some settings when a widget is polished,
10199 reimplement event() and handle the QEvent::Polish event type.
10200
10201 \b{Note:} The function is declared const so that it can be called from
10202 other const functions (e.g., sizeHint()).
10203
10204 \sa event()
10205*/
10206void QWidget::ensurePolished() const
10207{
10208 Q_D(const QWidget);
10209
10210 const QMetaObject *m = metaObject();
10211 if (m == d->polished)
10212 return;
10213 d->polished = m;
10214
10215 QEvent e(QEvent::Polish);
10216 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &e);
10217
10218 // polish children after 'this'
10219 QList<QObject*> children = d->children;
10220 for (int i = 0; i < children.size(); ++i) {
10221 QObject *o = children.at(i);
10222 if (!o->isWidgetType())
10223 continue;
10224 if (QWidget *w = qobject_cast<QWidget *>(o))
10225 w->ensurePolished();
10226 }
10227
10228 if (d->parent && d->sendChildEvents) {
10229 QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
10230 QCoreApplication::sendEvent(d->parent, &e);
10231 }
10232}
10233
10234/*!
10235 Returns the mask currently set on a widget. If no mask is set the
10236 return value will be an empty region.
10237
10238 \sa setMask(), clearMask(), QRegion::isEmpty()
10239*/
10240QRegion QWidget::mask() const
10241{
10242 Q_D(const QWidget);
10243 return d->extra ? d->extra->mask : QRegion();
10244}
10245
10246/*!
10247 Returns the layout manager that is installed on this widget, or \nullptr
10248 if no layout manager is installed.
10249
10250 The layout manager sets the geometry of the widget's children
10251 that have been added to the layout.
10252
10253 \sa setLayout(), sizePolicy(), {Layout Management}
10254*/
10255QLayout *QWidget::layout() const
10256{
10257 return d_func()->layout;
10258}
10259
10260
10261/*!
10262 \fn void QWidget::setLayout(QLayout *layout)
10263
10264 Sets the layout manager for this widget to \a layout.
10265
10266 If there already is a layout manager installed on this widget,
10267 QWidget won't let you install another. You must first delete the
10268 existing layout manager (returned by layout()) before you can
10269 call setLayout() with the new layout.
10270
10271 If \a layout is the layout manager on a different widget, setLayout()
10272 will reparent the layout and make it the layout manager for this widget.
10273
10274 Example:
10275
10276 \snippet layouts/layouts.cpp 24
10277
10278 An alternative to calling this function is to pass this widget to
10279 the layout's constructor.
10280
10281 The QWidget will take ownership of \a layout.
10282
10283 \sa layout(), {Layout Management}
10284*/
10285
10286void QWidget::setLayout(QLayout *l)
10287{
10288 if (Q_UNLIKELY(!l)) {
10289 qWarning("QWidget::setLayout: Cannot set layout to 0");
10290 return;
10291 }
10292 if (layout()) {
10293 if (Q_UNLIKELY(layout() != l))
10294 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
10295 " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
10296 objectName().toLocal8Bit().data());
10297 return;
10298 }
10299
10300 QObject *oldParent = l->parent();
10301 if (oldParent && oldParent != this) {
10302 if (oldParent->isWidgetType()) {
10303 // Steal the layout off a widget parent. Takes effect when
10304 // morphing laid-out container widgets in Designer.
10305 QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
10306 oldParentWidget->takeLayout();
10307 } else {
10308 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
10309 l->objectName().toLocal8Bit().data(), metaObject()->className(),
10310 objectName().toLocal8Bit().data());
10311 return;
10312 }
10313 }
10314
10315 Q_D(QWidget);
10316 l->d_func()->topLevel = true;
10317 d->layout = l;
10318 if (oldParent != this) {
10319 l->setParent(this);
10320 l->d_func()->reparentChildWidgets(this);
10321 l->invalidate();
10322 }
10323
10324 if (isWindow() && d->maybeTopData())
10325 d->topData()->sizeAdjusted = false;
10326}
10327
10328/*!
10329 \fn QLayout *QWidget::takeLayout()
10330
10331 Remove the layout from the widget.
10332 \since 4.5
10333*/
10334
10335QLayout *QWidget::takeLayout()
10336{
10337 Q_D(QWidget);
10338 QLayout *l = layout();
10339 if (!l)
10340 return nullptr;
10341 d->layout = nullptr;
10342 l->setParent(nullptr);
10343 return l;
10344}
10345
10346/*!
10347 \property QWidget::sizePolicy
10348 \brief the default layout behavior of the widget
10349
10350 If there is a QLayout that manages this widget's children, the
10351 size policy specified by that layout is used. If there is no such
10352 QLayout, the result of this function is used.
10353
10354 The default policy is Preferred/Preferred, which means that the
10355 widget can be freely resized, but prefers to be the size
10356 sizeHint() returns. Button-like widgets set the size policy to
10357 specify that they may stretch horizontally, but are fixed
10358 vertically. The same applies to lineedit controls (such as
10359 QLineEdit, QSpinBox or an editable QComboBox) and other
10360 horizontally orientated widgets (such as QProgressBar).
10361 QToolButton's are normally square, so they allow growth in both
10362 directions. Widgets that support different directions (such as
10363 QSlider, QScrollBar or QHeader) specify stretching in the
10364 respective direction only. Widgets that can provide scroll bars
10365 (usually subclasses of QScrollArea) tend to specify that they can
10366 use additional space, and that they can make do with less than
10367 sizeHint().
10368
10369 \sa sizeHint(), QLayout, QSizePolicy, updateGeometry()
10370*/
10371QSizePolicy QWidget::sizePolicy() const
10372{
10373 Q_D(const QWidget);
10374 return d->size_policy;
10375}
10376
10377void QWidget::setSizePolicy(QSizePolicy policy)
10378{
10379 Q_D(QWidget);
10380 setAttribute(Qt::WA_WState_OwnSizePolicy);
10381 if (policy == d->size_policy)
10382 return;
10383
10384 if (d->size_policy.retainSizeWhenHidden() != policy.retainSizeWhenHidden())
10385 d->retainSizeWhenHiddenChanged = 1;
10386
10387 d->size_policy = policy;
10388
10389#if QT_CONFIG(graphicsview)
10390 if (const auto &extra = d->extra) {
10391 if (extra->proxyWidget)
10392 extra->proxyWidget->setSizePolicy(policy);
10393 }
10394#endif
10395
10396 updateGeometry();
10397 d->retainSizeWhenHiddenChanged = 0;
10398
10399 if (isWindow() && d->maybeTopData())
10400 d->topData()->sizeAdjusted = false;
10401}
10402
10403/*!
10404 \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
10405 \overload
10406
10407 Sets the size policy of the widget to \a horizontal and \a
10408 vertical, with standard stretch and no height-for-width.
10409
10410 \sa QSizePolicy::QSizePolicy()
10411*/
10412
10413/*!
10414 Returns the preferred height for this widget, given the width \a w.
10415
10416 If this widget has a layout, the default implementation returns
10417 the layout's preferred height. if there is no layout, the default
10418 implementation returns -1 indicating that the preferred height
10419 does not depend on the width.
10420*/
10421
10422int QWidget::heightForWidth(int w) const
10423{
10424 if (layout() && layout()->hasHeightForWidth())
10425 return layout()->totalHeightForWidth(w);
10426 return -1;
10427}
10428
10429
10430/*!
10431 \since 5.0
10432
10433 Returns \c true if the widget's preferred height depends on its width; otherwise returns \c false.
10434*/
10435bool QWidget::hasHeightForWidth() const
10436{
10437 Q_D(const QWidget);
10438 return d->layout ? d->layout->hasHeightForWidth() : d->size_policy.hasHeightForWidth();
10439}
10440
10441/*!
10442 \fn QWidget *QWidget::childAt(int x, int y) const
10443
10444 Returns the visible child widget at the position (\a{x}, \a{y})
10445 in the widget's coordinate system. If there is no visible child
10446 widget at the specified position, the function returns \nullptr.
10447*/
10448
10449/*!
10450 \overload
10451
10452 Returns the visible child widget at point \a p in the widget's own
10453 coordinate system.
10454*/
10455
10456QWidget *QWidget::childAt(const QPoint &p) const
10457{
10458 return d_func()->childAt_helper(QPointF(p), false);
10459}
10460
10461/*!
10462 \overload
10463 \since 6.8
10464
10465 Returns the visible child widget at point \a p in the widget's own
10466 coordinate system.
10467*/
10468
10469QWidget *QWidget::childAt(const QPointF &p) const
10470{
10471 return d_func()->childAt_helper(p, false);
10472}
10473
10474QWidget *QWidgetPrivate::childAt_helper(const QPointF &p, bool ignoreChildrenInDestructor) const
10475{
10476 if (children.isEmpty())
10477 return nullptr;
10478
10479 if (!pointInsideRectAndMask(p))
10480 return nullptr;
10481 return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
10482}
10483
10484QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPointF &p, bool ignoreChildrenInDestructor) const
10485{
10486 for (int i = children.size() - 1; i >= 0; --i) {
10487 QWidget *child = qobject_cast<QWidget *>(children.at(i));
10488 if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents)
10489 || (ignoreChildrenInDestructor && child->data->in_destructor)) {
10490 continue;
10491 }
10492
10493 // Map the point 'p' from parent coordinates to child coordinates.
10494 QPointF childPoint = p;
10495 childPoint -= child->data->crect.topLeft();
10496
10497 // Check if the point hits the child.
10498 if (!child->d_func()->pointInsideRectAndMask(childPoint))
10499 continue;
10500
10501 // Do the same for the child's descendants.
10502 if (QWidget *w = child->d_func()->childAtRecursiveHelper(childPoint, ignoreChildrenInDestructor))
10503 return w;
10504
10505 // We have found our target; namely the child at position 'p'.
10506 return child;
10507 }
10508 return nullptr;
10509}
10510
10511void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
10512{
10513 Q_Q(QWidget);
10514 if (widgetItem)
10515 widgetItem->invalidateSizeCache();
10516 QWidget *parent;
10517 if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
10518 const int isHidden = q->isHidden() && !size_policy.retainSizeWhenHidden() && !retainSizeWhenHiddenChanged;
10519
10520 if (!q->isWindow() && !isHidden && (parent = q->parentWidget())) {
10521 if (parent->d_func()->layout)
10522 parent->d_func()->layout->invalidate();
10523 else if (parent->isVisible())
10524 QCoreApplication::postEvent(parent, new QEvent(QEvent::LayoutRequest));
10525 }
10526 }
10527}
10528
10529/*!
10530 Notifies the layout system that this widget has changed and may
10531 need to change geometry.
10532
10533 Call this function if the sizeHint() or sizePolicy() have changed.
10534
10535 For explicitly hidden widgets, updateGeometry() is a no-op. The
10536 layout system will be notified as soon as the widget is shown.
10537*/
10538
10539void QWidget::updateGeometry()
10540{
10541 Q_D(QWidget);
10542 d->updateGeometry_helper(false);
10543}
10544
10545/*! \property QWidget::windowFlags
10546
10547 Window flags are a combination of a type (e.g. Qt::Dialog) and
10548 zero or more hints to the window system (e.g.
10549 Qt::FramelessWindowHint).
10550
10551 If the widget had type Qt::Widget or Qt::SubWindow and becomes a
10552 window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
10553 0) on the desktop. If the widget is a window and becomes a
10554 Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
10555 relative to its parent widget.
10556
10557 \note This function calls setParent() when changing the flags for
10558 a window, causing the widget to be hidden. You must call show() to make
10559 the widget visible again..
10560
10561 \sa windowType(), setWindowFlag(), {Window Flags Example}
10562*/
10563void QWidget::setWindowFlags(Qt::WindowFlags flags)
10564{
10565 Q_D(QWidget);
10566 d->setWindowFlags(flags);
10567}
10568
10569/*!
10570 \since 5.9
10571
10572 Sets the window flag \a flag on this widget if \a on is true;
10573 otherwise clears the flag.
10574
10575 \note This function calls setParent() when changing the flags for
10576 a window, causing the widget to be hidden. You must call show() to make
10577 the widget visible again.
10578
10579 \sa setWindowFlags(), windowFlags(), windowType()
10580*/
10581void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
10582{
10583 Q_D(QWidget);
10584 if (on)
10585 d->setWindowFlags(data->window_flags | flag);
10586 else
10587 d->setWindowFlags(data->window_flags & ~flag);
10588}
10589
10590/*! \internal
10591
10592 Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
10593*/
10594void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
10595{
10596 Q_Q(QWidget);
10597#if QT_DEPRECATED_SINCE(6, 11)
10598 QT_IGNORE_DEPRECATIONS(
10599 if ((flags & Qt::WindowType_Mask) == Qt::WindowType::Desktop) {
10600 qWarning() << "Qt::WindowType::Desktop has been deprecated in Qt 6. Ignoring.";
10601 flags.setFlag(Qt::WindowType::Desktop, false);
10602 }
10603 )
10604#endif
10605
10606 if (q->data->window_flags == flags)
10607 return;
10608
10609 if ((q->data->window_flags | flags) & Qt::Window) {
10610 // the old type was a window and/or the new type is a window
10611 QPoint oldPos = q->pos();
10612 bool visible = q->isVisible();
10613 const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
10614 q->setParent(q->parentWidget(), flags);
10615
10616 // if both types are windows or neither of them are, we restore
10617 // the old position
10618 if (!windowFlagChanged && (visible || q->testAttribute(Qt::WA_Moved)))
10619 q->move(oldPos);
10620 // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
10621 adjustQuitOnCloseAttribute();
10622 } else {
10623 q->data->window_flags = flags;
10624 }
10625}
10626
10627/*!
10628 Sets the window flags for the widget to \a flags,
10629 \e without telling the window system.
10630
10631 \warning Do not call this function unless you really know what
10632 you're doing.
10633
10634 \sa setWindowFlags()
10635*/
10636void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
10637{
10638 data->window_flags = flags;
10639}
10640
10641/*!
10642 \fn Qt::WindowType QWidget::windowType() const
10643
10644 Returns the window type of this widget. This is identical to
10645 windowFlags() & Qt::WindowType_Mask.
10646
10647 \sa windowFlags
10648*/
10649
10650/*!
10651 Sets the parent of the widget to \a parent, and resets the window
10652 flags. The widget is moved to position (0, 0) in its new parent.
10653
10654 If the new parent widget is in a different window, the
10655 reparented widget and its children are appended to the end of the
10656 \l{setFocusPolicy()}{tab chain} of the new parent
10657 widget, in the same internal order as before. If one of the moved
10658 widgets had keyboard focus, setParent() calls clearFocus() for that
10659 widget.
10660
10661 If the new parent widget is in the same window as the
10662 old parent, setting the parent doesn't change the tab order or
10663 keyboard focus.
10664
10665 If the "new" parent widget is the old parent widget, this function
10666 does nothing.
10667
10668 \note The widget becomes invisible as part of changing its parent,
10669 even if it was previously visible. You must call show() to make the
10670 widget visible again.
10671
10672 \warning It is very unlikely that you will ever need this
10673 function. If you have a widget that changes its content
10674 dynamically, it is far easier to use \l QStackedWidget.
10675
10676 \sa setWindowFlags()
10677*/
10678void QWidget::setParent(QWidget *parent)
10679{
10680 if (parent == parentWidget())
10681 return;
10682 setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask);
10683}
10684
10685void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType)
10686{
10687 QWidgetPrivate *d = QWidgetPrivate::get(widget);
10688 if (d->renderToTexture) {
10689 QEvent e(eventType);
10690 QCoreApplication::sendEvent(widget, &e);
10691 }
10692
10693 for (int i = 0; i < d->children.size(); ++i) {
10694 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
10695 if (w && !w->isWindow())
10696 qSendWindowChangeToTextureChildrenRecursively(w, eventType);
10697 }
10698
10699 // Notify QWidgetWindow after we've notified all child QWidgets
10700 if (auto *window = d->windowHandle(QWidgetPrivate::WindowHandleMode::Direct)) {
10701 QEvent e(eventType);
10702 QCoreApplication::sendEvent(window, &e);
10703 }
10704}
10705
10706/*!
10707 \overload
10708
10709 This function also takes widget flags, \a f as an argument.
10710*/
10711
10712void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
10713{
10714 Q_D(QWidget);
10715 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
10716#ifdef QT_DEBUG
10717 const auto checkForParentChildLoops = qScopeGuard([&](){
10718 int depth = 0;
10719 auto p = parentWidget();
10720 while (p) {
10721 if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
10722 qWarning("QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
10723 "this is undefined behavior",
10724 this, metaObject()->className(), qPrintable(objectName()));
10725 }
10726 p = p->parentWidget();
10727 }
10728 });
10729#endif
10730
10731 const bool resized = testAttribute(Qt::WA_Resized);
10732 const bool wasCreated = testAttribute(Qt::WA_WState_Created);
10733 QWidget *oldtlw = window();
10734 Q_ASSERT(oldtlw);
10735 QWidget *oldParentWithWindow = d->closestParentWidgetWithWindowHandle();
10736
10737 if (f & Qt::Window) // Frame geometry likely changes, refresh.
10738 d->data.fstrut_dirty = true;
10739
10740 bool newParent = (parent != parentWidget());
10741
10742 if (newParent && parent) {
10743 if (testAttribute(Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
10744 parent->d_func()->enforceNativeChildren();
10745 else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(Qt::WA_PaintOnScreen))
10746 setAttribute(Qt::WA_NativeWindow);
10747 }
10748
10749 if (wasCreated) {
10750 if (!testAttribute(Qt::WA_WState_Hidden)) {
10751 // Hiding the widget will set WA_WState_Hidden as well, which would
10752 // normally require the widget to be explicitly shown again to become
10753 // visible, even as a child widget. But we refine this value later in
10754 // setParent_sys(), applying WA_WState_Hidden based on whether the
10755 // widget is a top level or not.
10756 hide();
10757
10758 // We reset WA_WState_ExplicitShowHide here, likely as a remnant of
10759 // when we only had QWidget::setVisible(), which is treated as an
10760 // explicit show/hide. Nowadays we have QWidgetPrivate::setVisible(),
10761 // that allows us to hide a widget without affecting ExplicitShowHide.
10762 // Though it can be argued that ExplicitShowHide should reflect the
10763 // last update of the widget's state, so if we hide the widget as a
10764 // side effect of changing parent, perhaps we _should_ reset it?
10765 setAttribute(Qt::WA_WState_ExplicitShowHide, false);
10766 }
10767 if (newParent) {
10768 QEvent e(QEvent::ParentAboutToChange);
10769 QCoreApplication::sendEvent(this, &e);
10770 }
10771 }
10772
10773 // texture-based widgets need a pre-notification when their associated top-level window changes
10774 // This is not under the wasCreated/newParent conditions above in order to also play nice with QDockWidget.
10775 const bool oldWidgetUsesRhiFlush = oldParentWithWindow ? oldParentWithWindow->d_func()->usesRhiFlush
10776 : oldtlw->d_func()->usesRhiFlush;
10777 if (oldWidgetUsesRhiFlush && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw)))
10778 qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowAboutToChangeInternal);
10779
10780 // If we get parented into another window, children will be folded
10781 // into the new parent's focus chain, so clear focus now.
10782 if (newParent && isAncestorOf(focusWidget()) && !(f & Qt::Window))
10783 focusWidget()->clearFocus();
10784
10785 d->setParent_sys(parent, f);
10786
10787 if (d->textureChildSeen && parent) {
10788 // set the textureChildSeen flag up the whole parent chain
10789 QWidgetPrivate::get(parent)->setTextureChildSeen();
10790 }
10791
10792 if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
10793 if (newParent)
10794 oldPaintManager->removeDirtyWidget(this);
10795 // Move the widget and all its static children from
10796 // the old backing store to the new one.
10797 oldPaintManager->moveStaticWidgets(this);
10798 }
10799
10800 d->reparentFocusWidgets(oldtlw);
10801 setAttribute(Qt::WA_Resized, resized);
10802
10803 const bool useStyleSheetPropagationInWidgetStyles =
10804 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
10805
10806 if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(Qt::WA_StyleSheet)
10807 && (!parent || !parent->testAttribute(Qt::WA_StyleSheet))) {
10808 // if the parent has a font set or inherited, then propagate the mask to the new child
10809 if (parent) {
10810 const auto pd = parent->d_func();
10811 d->inheritedFontResolveMask = pd->directFontResolveMask | pd->inheritedFontResolveMask;
10812 d->inheritedPaletteResolveMask = pd->directPaletteResolveMask | pd->inheritedPaletteResolveMask;
10813 }
10814 d->resolveFont();
10815 d->resolvePalette();
10816 }
10817 d->resolveLayoutDirection();
10818 d->resolveLocale();
10819
10820 // Note: GL widgets under WGL or EGL will always need a ParentChange
10821 // event to handle recreation/rebinding of the GL context, hence the
10822 // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
10823 // platforms).
10824 if (newParent || !wasCreated
10825#if QT_CONFIG(opengles2)
10826 || (f & Qt::MSWindowsOwnDC)
10827#endif
10828 ) {
10829 // propagate enabled updates enabled state to non-windows
10830 if (!isWindow()) {
10831 if (!testAttribute(Qt::WA_ForceDisabled))
10832 d->setEnabled_helper(parent ? parent->isEnabled() : true);
10833 if (!testAttribute(Qt::WA_ForceUpdatesDisabled))
10834 d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
10835 }
10836 d->inheritStyle();
10837
10838 // send and post remaining QObject events
10839 if (parent && d->sendChildEvents) {
10840 QChildEvent e(QEvent::ChildAdded, this);
10841 QCoreApplication::sendEvent(parent, &e);
10842 }
10843
10844 if (parent && d->sendChildEvents && d->polished) {
10845 QChildEvent e(QEvent::ChildPolished, this);
10846 QCoreApplication::sendEvent(parent, &e);
10847 }
10848
10849 QEvent e(QEvent::ParentChange);
10850 QCoreApplication::sendEvent(this, &e);
10851 }
10852
10853 // texture-based widgets need another event when their top-level window
10854 // changes (more precisely, has already changed at this point)
10855 if (oldWidgetUsesRhiFlush && oldtlw != window())
10856 qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowChangeInternal);
10857
10858 if (!wasCreated) {
10859 if (isWindow() || parentWidget()->isVisible())
10860 setAttribute(Qt::WA_WState_Hidden, true);
10861 else if (!testAttribute(Qt::WA_WState_ExplicitShowHide))
10862 setAttribute(Qt::WA_WState_Hidden, false);
10863 }
10864
10865 d->updateIsOpaque();
10866
10867#if QT_CONFIG(graphicsview)
10868 // Embed the widget into a proxy if the parent is embedded.
10869 // ### Doesn't handle reparenting out of an embedded widget.
10870 if (oldtlw->graphicsProxyWidget()) {
10871 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(oldtlw))
10872 ancestorProxy->d_func()->unembedSubWindow(this);
10873 }
10874 if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(this)) {
10875 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(parent))
10876 ancestorProxy->d_func()->embedSubWindow(this);
10877 }
10878#endif
10879
10880 if (d->extra && d->extra->hasWindowContainer)
10881 QWindowContainer::parentWasChanged(this);
10882
10883 QWidget *newParentWithWindow = d->closestParentWidgetWithWindowHandle();
10884 if (newParentWithWindow && newParentWithWindow != oldParentWithWindow) {
10885 // Check if the native parent now needs to switch to RHI
10886 qCDebug(lcWidgetPainting) << "Evaluating whether reparenting of" << this
10887 << "into" << parent << "requires RHI enablement for" << newParentWithWindow;
10888
10889 QPlatformBackingStoreRhiConfig rhiConfig;
10890 QSurface::SurfaceType surfaceType = QSurface::RasterSurface;
10891
10892 // First evaluate whether the reparented widget uses RHI.
10893 // We do this as a separate step because the performance
10894 // implications of always checking the native parent are
10895 // problematic when it comes to large widget trees.
10896 if (q_evaluateRhiConfig(this, &rhiConfig, &surfaceType)) {
10897 // Then check whether the native parent requires RHI
10898 // as a result. It may not, if this widget is a native
10899 // window, and can handle its own RHI flushing.
10900 if (q_evaluateRhiConfig(newParentWithWindow, nullptr, nullptr)) {
10901 // Finally, check whether we need to recreate the
10902 // native parent to enable RHI flushing.
10903 auto *existingWindow = newParentWithWindow->windowHandle();
10904 auto existingSurfaceType = existingWindow->surfaceType();
10905 if (existingSurfaceType != surfaceType) {
10906 qCDebug(lcWidgetPainting)
10907 << "Recreating" << existingWindow
10908 << "with current type" << existingSurfaceType
10909 << "to support" << surfaceType;
10910 const auto windowStateBeforeDestroy = newParentWithWindow->windowState();
10911 const auto visibilityBeforeDestroy = newParentWithWindow->isVisible();
10912 const auto positionBeforeDestroy = newParentWithWindow->pos();
10913 newParentWithWindow->d_func()->recreate();
10914 Q_ASSERT(newParentWithWindow->windowHandle());
10915 newParentWithWindow->windowHandle()->setWindowStates(windowStateBeforeDestroy);
10916 newParentWithWindow->move(positionBeforeDestroy);
10917 QWidgetPrivate::get(newParentWithWindow)->setVisible(visibilityBeforeDestroy);
10918 } else if (auto *backingStore = newParentWithWindow->backingStore()) {
10919 // If we don't recreate we still need to make sure the native parent
10920 // widget has a RHI config that the reparented widget can use.
10921 backingStore->handle()->createRhi(existingWindow, rhiConfig);
10922 // And that it knows it's now flushing with RHI
10923 QWidgetPrivate::get(newParentWithWindow)->usesRhiFlush = true;
10924 }
10925 }
10926 }
10927 }
10928
10929#if QT_CONFIG(accessibility)
10930 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing) {
10931 QAccessibleEvent qaEvent(this, QAccessible::ParentChanged);
10932 QAccessible::updateAccessibility(&qaEvent);
10933 }
10934#endif
10935
10936}
10937
10938void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
10939{
10940 Q_Q(QWidget);
10941
10942 Qt::WindowFlags oldFlags = data.window_flags;
10943 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
10944
10945 QScreen *targetScreen = nullptr;
10946 setWinId(0);
10947
10948 if (!newparent) {
10949 f |= Qt::Window;
10950 if (parent)
10951 targetScreen = q->parentWidget()->window()->screen();
10952 }
10953
10954 const bool destroyWindow = (
10955 // Reparenting top level to child
10956 (oldFlags & Qt::Window) && !(f & Qt::Window)
10957 // And we can dispose of the window
10958 && wasCreated && !q->testAttribute(Qt::WA_NativeWindow)
10959 );
10960
10961 if (parent != newparent) {
10962 // Update object parent now, so we can resolve new parent window below
10963 QObjectPrivate::setParent_helper(newparent);
10964
10965 if (q->windowHandle())
10966 q->windowHandle()->setFlags(f);
10967
10968 // If the widget itself or any of its children have been created,
10969 // we need to reparent their QWindows as well.
10970 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
10971 // But if the widget is about to be destroyed we must skip the
10972 // widget itself, and only reparent children.
10973 if (destroyWindow) {
10974 reparentWidgetWindowChildren(parentWithWindow);
10975 } else {
10976 // During reparentWidgetWindows() we need to know whether the reparented
10977 // QWindow should be a top level (with a transient parent) or not. This
10978 // widget has not updated its window flags yet, so we can't ask the widget
10979 // directly at that point. Nor can we use the QWindow flags, as unlike QWidgets
10980 // the QWindow flags always reflect Qt::Window, even for child windows. And
10981 // we can't use QWindow::isTopLevel() either, as that depends on the parent,
10982 // which we are in the process of updating. So we propagate the
10983 // new flags of the reparented window here.
10984 reparentWidgetWindows(parentWithWindow, f);
10985 }
10986 }
10987
10988 bool explicitlyHidden = isExplicitlyHidden();
10989
10990 if (destroyWindow) {
10991 if (extra && extra->hasWindowContainer)
10992 QWindowContainer::toplevelAboutToBeDestroyed(q);
10993
10994 // There shouldn't be any QWindow children left, but if there
10995 // are, re-parent them now, before we destroy.
10996 if (!q->windowHandle()->children().isEmpty()) {
10997 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
10998 QWindow *newParentWindow = parentWithWindow ? parentWithWindow->windowHandle() : nullptr;
10999 for (QObject *child : q->windowHandle()->children()) {
11000 if (QWindow *childWindow = qobject_cast<QWindow *>(child)) {
11001 qCWarning(lcWidgetWindow) << "Reparenting" << childWindow
11002 << "before destroying" << this;
11003 childWindow->setParent(newParentWindow);
11004 }
11005 }
11006 }
11007
11008 // We have reparented any child windows of the widget we are
11009 // about to destroy to the new parent window handle, so we can
11010 // safely destroy this widget without destroying sub windows.
11011 q->destroy(true, false);
11012 }
11013
11014 adjustFlags(f, q);
11015 data.window_flags = f;
11016 q->setAttribute(Qt::WA_WState_Created, false);
11017 q->setAttribute(Qt::WA_WState_Visible, false);
11018 q->setAttribute(Qt::WA_WState_Hidden, false);
11019
11020 if (newparent && wasCreated && (q->testAttribute(Qt::WA_NativeWindow) || (f & Qt::Window)))
11021 q->createWinId();
11022
11023 if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
11024 q->setAttribute(Qt::WA_WState_Hidden);
11025 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
11026
11027 // move the window to the selected screen
11028 if (!newparent && targetScreen) {
11029 // only if it is already created
11030 if (q->testAttribute(Qt::WA_WState_Created))
11031 q->windowHandle()->setScreen(targetScreen);
11032 else
11033 topData()->initialScreen = targetScreen;
11034 }
11035}
11036
11037void QWidgetPrivate::reparentWidgetWindows(QWidget *parentWithWindow, Qt::WindowFlags windowFlags)
11038{
11039 if (QWindow *window = windowHandle()) {
11040 // Reparent this QWindow, and all QWindow children will follow
11041 if (parentWithWindow) {
11042 if (windowFlags & Qt::Window) {
11043 // Top level windows can only have transient parents,
11044 // and the transient parent must be another top level.
11045 QWidget *topLevel = parentWithWindow->window();
11046 auto *transientParent = topLevel->windowHandle();
11047 Q_ASSERT(transientParent);
11048 qCDebug(lcWidgetWindow) << "Setting" << window << "transient parent to" << transientParent;
11049 window->setTransientParent(transientParent);
11050 window->setParent(nullptr);
11051 } else {
11052 auto *parentWindow = parentWithWindow->windowHandle();
11053 qCDebug(lcWidgetWindow) << "Reparenting" << window << "into" << parentWindow;
11054 window->setTransientParent(nullptr);
11055 window->setParent(parentWindow);
11056 }
11057 } else {
11058 qCDebug(lcWidgetWindow) << "Making" << window << "top level window";
11059 window->setTransientParent(nullptr);
11060 window->setParent(nullptr);
11061 }
11062 } else {
11063 reparentWidgetWindowChildren(parentWithWindow);
11064 }
11065}
11066
11067void QWidgetPrivate::reparentWidgetWindowChildren(QWidget *parentWithWindow)
11068{
11069 for (auto *child : std::as_const(children)) {
11070 if (auto *childWidget = qobject_cast<QWidget*>(child)) {
11071 auto *childPrivate = QWidgetPrivate::get(childWidget);
11072 // Child widgets with QWindows should always continue to be child
11073 // windows, so we pass on the child's current window flags here.
11074 childPrivate->reparentWidgetWindows(parentWithWindow, childWidget->windowFlags());
11075 }
11076 }
11077}
11078
11079/*!
11080 Scrolls the widget including its children \a dx pixels to the
11081 right and \a dy downward. Both \a dx and \a dy may be negative.
11082
11083 After scrolling, the widgets will receive paint events for
11084 the areas that need to be repainted. For widgets that Qt knows to
11085 be opaque, this is only the newly exposed parts.
11086 For example, if an opaque widget is scrolled 8 pixels to the left,
11087 only an 8-pixel wide stripe at the right edge needs updating.
11088
11089 Since widgets propagate the contents of their parents by default,
11090 you need to set the \l autoFillBackground property, or use
11091 setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
11092 a widget opaque.
11093
11094 For widgets that use contents propagation, a scroll will cause an
11095 update of the entire scroll area.
11096
11097 \sa {Transparency and Double Buffering}
11098*/
11099
11100void QWidget::scroll(int dx, int dy)
11101{
11102 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11103 return;
11104 if (dx == 0 && dy == 0)
11105 return;
11106 Q_D(QWidget);
11107#if QT_CONFIG(graphicsview)
11108 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
11109 // Graphics View maintains its own dirty region as a list of rects;
11110 // until we can connect item updates directly to the view, we must
11111 // separately add a translated dirty region.
11112 for (const QRect &rect : d->dirty)
11113 proxy->update(rect.translated(dx, dy));
11114 proxy->scroll(dx, dy, proxy->subWidgetRect(this));
11115 d->scrollChildren(dx, dy); // QTBUG-138381: scroll item view cell widgets
11116 return;
11117 }
11118#endif
11119 d->setDirtyOpaqueRegion();
11120 d->scroll_sys(dx, dy);
11121}
11122
11123void QWidgetPrivate::scroll_sys(int dx, int dy)
11124{
11125 Q_Q(QWidget);
11126 scrollChildren(dx, dy);
11127 scrollRect(q->rect(), dx, dy);
11128}
11129
11130/*!
11131 \overload
11132
11133 This version only scrolls \a r and does not move the children of
11134 the widget.
11135
11136 If \a r is empty or invalid, the result is undefined.
11137
11138 \sa QScrollArea
11139*/
11140void QWidget::scroll(int dx, int dy, const QRect &r)
11141{
11142
11143 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11144 return;
11145 if (dx == 0 && dy == 0)
11146 return;
11147 Q_D(QWidget);
11148#if QT_CONFIG(graphicsview)
11149 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
11150 // Graphics View maintains its own dirty region as a list of rects;
11151 // until we can connect item updates directly to the view, we must
11152 // separately add a translated dirty region.
11153 if (!d->dirty.isEmpty()) {
11154 for (const QRect &rect : d->dirty.translated(dx, dy) & r)
11155 proxy->update(rect);
11156 }
11157 proxy->scroll(dx, dy, r.translated(proxy->subWidgetRect(this).topLeft().toPoint()));
11158 return;
11159 }
11160#endif
11161 d->scroll_sys(dx, dy, r);
11162}
11163
11164void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
11165{
11166 scrollRect(r, dx, dy);
11167}
11168
11169/*!
11170 Repaints the widget directly by calling paintEvent() immediately,
11171 unless updates are disabled or the widget is hidden.
11172
11173 We suggest only using repaint() if you need an immediate repaint,
11174 for example during animation. In most circumstances update()
11175 is better, as it permits Qt to optimize for speed and minimize
11176 flicker.
11177
11178 \warning If you call repaint() in a function which may itself be
11179 called from paintEvent(), you may get infinite recursion. The
11180 update() function never causes recursion.
11181
11182 \sa update(), paintEvent(), setUpdatesEnabled()
11183*/
11184
11185void QWidget::repaint()
11186{
11187 repaint(rect());
11188}
11189
11190/*! \overload
11191
11192 This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
11193 the widget.
11194
11195 If \a w is negative, it is replaced with \c{width() - x}, and if
11196 \a h is negative, it is replaced width \c{height() - y}.
11197*/
11198void QWidget::repaint(int x, int y, int w, int h)
11199{
11200 if (x > data->crect.width() || y > data->crect.height())
11201 return;
11202
11203 if (w < 0)
11204 w = data->crect.width() - x;
11205 if (h < 0)
11206 h = data->crect.height() - y;
11207
11208 repaint(QRect(x, y, w, h));
11209}
11210
11211/*! \overload
11212
11213 This version repaints a rectangle \a rect inside the widget.
11214*/
11215void QWidget::repaint(const QRect &rect)
11216{
11217 Q_D(QWidget);
11218 d->repaint(rect);
11219}
11220
11221/*!
11222 \overload
11223
11224 This version repaints a region \a rgn inside the widget.
11225*/
11226void QWidget::repaint(const QRegion &rgn)
11227{
11228 Q_D(QWidget);
11229 d->repaint(rgn);
11230}
11231
11232template <typename T>
11233void QWidgetPrivate::repaint(T r)
11234{
11235 Q_Q(QWidget);
11236
11237 if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
11238 return;
11239
11240 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11241 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11242 tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
11243}
11244
11245/*!
11246 Updates the widget unless updates are disabled or the widget is
11247 hidden.
11248
11249 This function does not cause an immediate repaint; instead it
11250 schedules a paint event for processing when Qt returns to the main
11251 event loop. This permits Qt to optimize for more speed and less
11252 flicker than a call to repaint() does.
11253
11254 Calling update() several times normally results in just one
11255 paintEvent() call.
11256
11257 Qt normally erases the widget's area before the paintEvent() call.
11258 If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
11259 responsible for painting all its pixels with an opaque color.
11260
11261 \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock}
11262*/
11263void QWidget::update()
11264{
11265 update(rect());
11266}
11267
11268/*! \fn void QWidget::update(int x, int y, int w, int h)
11269 \overload
11270
11271 This version updates a rectangle (\a x, \a y, \a w, \a h) inside
11272 the widget.
11273*/
11274
11275/*!
11276 \overload
11277
11278 This version updates a rectangle \a rect inside the widget.
11279*/
11280void QWidget::update(const QRect &rect)
11281{
11282 Q_D(QWidget);
11283 d->update(rect);
11284}
11285
11286/*!
11287 \overload
11288
11289 This version repaints a region \a rgn inside the widget.
11290*/
11291void QWidget::update(const QRegion &rgn)
11292{
11293 Q_D(QWidget);
11294 d->update(rgn);
11295}
11296
11297template <typename T>
11298void QWidgetPrivate::update(T r)
11299{
11300 Q_Q(QWidget);
11301
11302 if (renderToTexture && !q->isVisible()) {
11303 renderToTextureReallyDirty = 1;
11304 return;
11305 }
11306
11307 if (!q->isVisible() || !q->updatesEnabled())
11308 return;
11309
11310 T clipped = r & q->rect();
11311
11312 if (clipped.isEmpty())
11313 return;
11314
11315 if (q->testAttribute(Qt::WA_WState_InPaintEvent)) {
11316 QCoreApplication::postEvent(q, new QUpdateLaterEvent(clipped));
11317 return;
11318 }
11319
11320 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11321 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11322 tlwExtra->repaintManager->markDirty(clipped, q);
11323}
11324
11325 /*!
11326 \internal
11327
11328 This just sets the corresponding attribute bit to 1 or 0
11329 */
11330static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
11331 QWidgetPrivate *d)
11332{
11333 if (attribute < int(8*sizeof(uint))) {
11334 if (on)
11335 data->widget_attributes |= (1<<attribute);
11336 else
11337 data->widget_attributes &= ~(1<<attribute);
11338 } else {
11339 const int x = attribute - 8*sizeof(uint);
11340 const int int_off = x / (8*sizeof(uint));
11341 if (on)
11342 d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
11343 else
11344 d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
11345 }
11346}
11347
11348#ifdef Q_OS_MACOS
11349void QWidgetPrivate::macUpdateSizeAttribute()
11350{
11351 Q_Q(QWidget);
11352 QEvent event(QEvent::MacSizeChange);
11353 QCoreApplication::sendEvent(q, &event);
11354 for (int i = 0; i < children.size(); ++i) {
11355 QWidget *w = qobject_cast<QWidget *>(children.at(i));
11356 if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
11357 && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
11358 && !w->testAttribute(Qt::WA_MacSmallSize)
11359 && !w->testAttribute(Qt::WA_MacNormalSize))
11360 w->d_func()->macUpdateSizeAttribute();
11361 }
11362 resolveFont();
11363}
11364#endif
11365
11366/*!
11367 Sets the attribute \a attribute on this widget if \a on is true;
11368 otherwise clears the attribute.
11369
11370 \sa testAttribute()
11371*/
11372void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
11373{
11374 Q_D(QWidget);
11375
11376 if (attribute == Qt::WA_ContentsMarginsRespectsSafeArea) {
11377 if (isWindow()) {
11378 auto *topExtra = d->topData();
11379 topExtra->explicitContentsMarginsRespectsSafeArea = true;
11380 }
11381 }
11382
11383 if (testAttribute(attribute) == on)
11384 return;
11385
11386 static_assert(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
11387 "QWidget::setAttribute(WidgetAttribute, bool): "
11388 "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
11389#ifdef Q_OS_WIN
11390 // ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
11391 if (attribute == Qt::WA_PaintOnScreen && on && !inherits("QGLWidget")) {
11392 // see ::paintEngine for details
11393 paintEngine();
11394 if (d->noPaintOnScreen)
11395 return;
11396 }
11397#endif
11398
11399 // Don't set WA_NativeWindow on platforms that don't support it -- except for QGLWidget, which depends on it
11400 if (attribute == Qt::WA_NativeWindow && !d->mustHaveWindowHandle) {
11401 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
11402 if (!platformIntegration->hasCapability(QPlatformIntegration::NativeWidgets))
11403 return;
11404 }
11405
11406 setAttribute_internal(attribute, on, data, d);
11407
11408 switch (attribute) {
11409
11410#if QT_CONFIG(draganddrop)
11411 case Qt::WA_AcceptDrops: {
11412 if (on && !testAttribute(Qt::WA_DropSiteRegistered))
11413 setAttribute(Qt::WA_DropSiteRegistered, true);
11414 else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
11415 setAttribute(Qt::WA_DropSiteRegistered, false);
11416 QEvent e(QEvent::AcceptDropsChange);
11417 QCoreApplication::sendEvent(this, &e);
11418 break;
11419 }
11420 case Qt::WA_DropSiteRegistered: {
11421 for (int i = 0; i < d->children.size(); ++i) {
11422 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
11423 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_AcceptDrops) && w->testAttribute(Qt::WA_DropSiteRegistered) != on)
11424 w->setAttribute(Qt::WA_DropSiteRegistered, on);
11425 }
11426 break;
11427 }
11428#endif
11429
11430 case Qt::WA_NoChildEventsForParent:
11431 d->sendChildEvents = !on;
11432 break;
11433 case Qt::WA_NoChildEventsFromChildren:
11434 d->receiveChildEvents = !on;
11435 break;
11436 case Qt::WA_MacNormalSize:
11437 case Qt::WA_MacSmallSize:
11438 case Qt::WA_MacMiniSize:
11439#ifdef Q_OS_MACOS
11440 {
11441 // We can only have one of these set at a time
11442 const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
11443 Qt::WA_MacMiniSize };
11444 for (int i = 0; i < 3; ++i) {
11445 if (MacSizes[i] != attribute)
11446 setAttribute_internal(MacSizes[i], false, data, d);
11447 }
11448 d->macUpdateSizeAttribute();
11449 }
11450#endif
11451 break;
11452 case Qt::WA_ShowModal:
11453 if (!on) {
11454 // reset modality type to NonModal when clearing WA_ShowModal
11455 data->window_modality = Qt::NonModal;
11456 } else if (data->window_modality == Qt::NonModal) {
11457 // If modality hasn't been set prior to setting WA_ShowModal, use
11458 // ApplicationModal.
11459 data->window_modality = Qt::ApplicationModal;
11460 // Some window managers do not allow us to enter modality after the
11461 // window is visible.The window must be hidden before changing the
11462 // windowModality property and then reshown.
11463 }
11464 if (testAttribute(Qt::WA_WState_Created)) {
11465 // don't call setModal_sys() before create()
11466 d->setModal_sys();
11467 }
11468 break;
11469 case Qt::WA_MouseTracking: {
11470 QEvent e(QEvent::MouseTrackingChange);
11471 QCoreApplication::sendEvent(this, &e);
11472 break; }
11473 case Qt::WA_TabletTracking: {
11474 QEvent e(QEvent::TabletTrackingChange);
11475 QCoreApplication::sendEvent(this, &e);
11476 break; }
11477 case Qt::WA_NativeWindow: {
11478 d->createTLExtra();
11479 if (on)
11480 d->createTLSysExtra();
11481#ifndef QT_NO_IM
11482 QWidget *focusWidget = d->effectiveFocusWidget();
11483 if (on && !internalWinId() && this == QGuiApplication::focusObject()
11484 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11485 QGuiApplication::inputMethod()->commit();
11486 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11487 }
11488 if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
11489 parentWidget()->d_func()->enforceNativeChildren();
11490 if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
11491 d->createWinId();
11492 if (isEnabled() && focusWidget->isEnabled() && this == QGuiApplication::focusObject()
11493 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11494 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11495 }
11496#endif //QT_NO_IM
11497 break;
11498 }
11499 case Qt::WA_PaintOnScreen:
11500 d->updateIsOpaque();
11501 Q_FALLTHROUGH();
11502 case Qt::WA_OpaquePaintEvent:
11503 d->updateIsOpaque();
11504 break;
11505 case Qt::WA_NoSystemBackground:
11506 d->updateIsOpaque();
11507 Q_FALLTHROUGH();
11508 case Qt::WA_UpdatesDisabled:
11509 d->updateSystemBackground();
11510 break;
11511 case Qt::WA_TransparentForMouseEvents:
11512 break;
11513 case Qt::WA_InputMethodEnabled: {
11514#ifndef QT_NO_IM
11515 if (QGuiApplication::focusObject() == this) {
11516 if (!on)
11517 QGuiApplication::inputMethod()->commit();
11518 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11519 }
11520#endif //QT_NO_IM
11521 break;
11522 }
11523 case Qt::WA_WindowPropagation:
11524 d->resolvePalette();
11525 d->resolveFont();
11526 d->resolveLocale();
11527 break;
11528 case Qt::WA_DontShowOnScreen: {
11529 if (on && isVisible()) {
11530 // Make sure we keep the current state and only hide the widget
11531 // from the desktop. show_sys will only update platform specific
11532 // attributes at this point.
11533 d->hide_sys();
11534 d->show_sys();
11535 }
11536 break;
11537 }
11538
11539 case Qt::WA_X11NetWmWindowTypeDesktop:
11540 case Qt::WA_X11NetWmWindowTypeDock:
11541 case Qt::WA_X11NetWmWindowTypeToolBar:
11542 case Qt::WA_X11NetWmWindowTypeMenu:
11543 case Qt::WA_X11NetWmWindowTypeUtility:
11544 case Qt::WA_X11NetWmWindowTypeSplash:
11545 case Qt::WA_X11NetWmWindowTypeDialog:
11546 case Qt::WA_X11NetWmWindowTypeDropDownMenu:
11547 case Qt::WA_X11NetWmWindowTypePopupMenu:
11548 case Qt::WA_X11NetWmWindowTypeToolTip:
11549 case Qt::WA_X11NetWmWindowTypeNotification:
11550 case Qt::WA_X11NetWmWindowTypeCombo:
11551 case Qt::WA_X11NetWmWindowTypeDND:
11552 d->setNetWmWindowTypes();
11553 break;
11554
11555 case Qt::WA_StaticContents:
11556 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
11557 if (on)
11558 repaintManager->addStaticWidget(this);
11559 else
11560 repaintManager->removeStaticWidget(this);
11561 }
11562 break;
11563 case Qt::WA_TranslucentBackground:
11564 if (on)
11565 setAttribute(Qt::WA_NoSystemBackground);
11566 d->updateIsTranslucent();
11567
11568 break;
11569 case Qt::WA_AcceptTouchEvents:
11570 break;
11571 default:
11572 break;
11573 }
11574}
11575
11576/*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
11577
11578 Returns \c true if attribute \a attribute is set on this widget;
11579 otherwise returns \c false.
11580
11581 \sa setAttribute()
11582 */
11583bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
11584{
11585 Q_D(const QWidget);
11586 const int x = attribute - 8*sizeof(uint);
11587 const int int_off = x / (8*sizeof(uint));
11588 return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
11589}
11590
11591/*!
11592 \property QWidget::windowOpacity
11593
11594 \brief The level of opacity for the window.
11595
11596 The valid range of opacity is from 1.0 (completely opaque) to
11597 0.0 (completely transparent).
11598
11599 By default the value of this property is 1.0.
11600
11601 This feature is available on Embedded Linux, \macos, Windows,
11602 and X11 platforms that support the Composite extension.
11603
11604 \note On X11 you need to have a composite manager running,
11605 and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
11606 supported by the window manager you are using.
11607
11608 \warning Changing this property from opaque to transparent might issue a
11609 paint event that needs to be processed before the window is displayed
11610 correctly. This affects mainly the use of QScreen::grabWindow(). Also note
11611 that semi-transparent windows update and resize significantly slower than
11612 opaque windows.
11613
11614 \sa setMask()
11615*/
11616qreal QWidget::windowOpacity() const
11617{
11618 Q_D(const QWidget);
11619 return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
11620}
11621
11622void QWidget::setWindowOpacity(qreal opacity)
11623{
11624 Q_D(QWidget);
11625 if (!isWindow())
11626 return;
11627
11628 opacity = qBound(qreal(0.0), opacity, qreal(1.0));
11629 QTLWExtra *extra = d->topData();
11630 extra->opacity = uint(opacity * 255);
11631 setAttribute(Qt::WA_WState_WindowOpacitySet);
11632 d->setWindowOpacity_sys(opacity);
11633
11634 if (!testAttribute(Qt::WA_WState_Created))
11635 return;
11636
11637#if QT_CONFIG(graphicsview)
11638 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
11639 // Avoid invalidating the cache if set.
11640 if (proxy->cacheMode() == QGraphicsItem::NoCache)
11641 proxy->update();
11642 else if (QGraphicsScene *scene = proxy->scene())
11643 scene->update(proxy->sceneBoundingRect());
11644 return;
11645 }
11646#endif
11647}
11648
11649void QWidgetPrivate::setWindowOpacity_sys(qreal level)
11650{
11651 Q_Q(QWidget);
11652 if (q->windowHandle())
11653 q->windowHandle()->setOpacity(level);
11654}
11655
11656/*!
11657 \property QWidget::windowModified
11658 \brief whether the document shown in the window has unsaved changes
11659
11660 A modified window is a window whose content has changed but has
11661 not been saved to disk. This flag will have different effects
11662 varied by the platform. On \macos the close button will have a
11663 modified look; on other platforms, the window title will have an
11664 '*' (asterisk).
11665
11666 The window title must contain a "[*]" placeholder, which
11667 indicates where the '*' should appear. Normally, it should appear
11668 right after the file name (e.g., "document1.txt[*] - Text
11669 Editor"). If the window isn't modified, the placeholder is simply
11670 removed.
11671
11672 Note that if a widget is set as modified, all its ancestors will
11673 also be set as modified. However, if you call \c
11674 {setWindowModified(false)} on a widget, this will not propagate to
11675 its parent because other children of the parent might have been
11676 modified.
11677
11678 \sa windowTitle
11679*/
11680bool QWidget::isWindowModified() const
11681{
11682 return testAttribute(Qt::WA_WindowModified);
11683}
11684
11685void QWidget::setWindowModified(bool mod)
11686{
11687 Q_D(QWidget);
11688 setAttribute(Qt::WA_WindowModified, mod);
11689
11690 d->setWindowModified_helper();
11691
11692 QEvent e(QEvent::ModifiedChange);
11693 QCoreApplication::sendEvent(this, &e);
11694}
11695
11696void QWidgetPrivate::setWindowModified_helper()
11697{
11698 Q_Q(QWidget);
11699 QWindow *window = q->windowHandle();
11700 if (!window)
11701 return;
11702 QPlatformWindow *platformWindow = window->handle();
11703 if (!platformWindow)
11704 return;
11705 bool on = q->testAttribute(Qt::WA_WindowModified);
11706 if (!platformWindow->setWindowModified(on)) {
11707 if (Q_UNLIKELY(on && !q->windowTitle().contains("[*]"_L1)))
11708 qWarning("QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
11709 setWindowTitle_helper(q->windowTitle());
11710 setWindowIconText_helper(q->windowIconText());
11711 }
11712}
11713
11714#if QT_CONFIG(tooltip)
11715/*!
11716 \property QWidget::toolTip
11717
11718 \brief the widget's tooltip
11719
11720 Note that by default tooltips are only shown for widgets that are
11721 children of the active window. You can change this behavior by
11722 setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
11723 not on the widget with the tooltip.
11724
11725 If you want to control a tooltip's behavior, you can intercept the
11726 event() function and catch the QEvent::ToolTip event (e.g., if you
11727 want to customize the area for which the tooltip should be shown).
11728
11729 By default, this property contains an empty string.
11730
11731 \sa QToolTip, statusTip, whatsThis
11732*/
11733void QWidget::setToolTip(const QString &s)
11734{
11735 Q_D(QWidget);
11736 d->toolTip = s;
11737
11738 QEvent event(QEvent::ToolTipChange);
11739 QCoreApplication::sendEvent(this, &event);
11740}
11741
11742QString QWidget::toolTip() const
11743{
11744 Q_D(const QWidget);
11745 return d->toolTip;
11746}
11747
11748/*!
11749 \property QWidget::toolTipDuration
11750 \brief the widget's tooltip duration
11751 \since 5.2
11752
11753 Specifies how long time the tooltip will be displayed, in milliseconds.
11754 If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
11755
11756 \sa toolTip
11757*/
11758
11759void QWidget::setToolTipDuration(int msec)
11760{
11761 Q_D(QWidget);
11762 d->toolTipDuration = msec;
11763}
11764
11765int QWidget::toolTipDuration() const
11766{
11767 Q_D(const QWidget);
11768 return d->toolTipDuration;
11769}
11770
11771#endif // QT_CONFIG(tooltip)
11772
11773
11774#if QT_CONFIG(statustip)
11775/*!
11776 \property QWidget::statusTip
11777 \brief the widget's status tip
11778
11779 By default, this property contains an empty string.
11780
11781 \sa toolTip, whatsThis
11782*/
11783void QWidget::setStatusTip(const QString &s)
11784{
11785 Q_D(QWidget);
11786 d->statusTip = s;
11787}
11788
11789QString QWidget::statusTip() const
11790{
11791 Q_D(const QWidget);
11792 return d->statusTip;
11793}
11794#endif // QT_CONFIG(statustip)
11795
11796#if QT_CONFIG(whatsthis)
11797/*!
11798 \property QWidget::whatsThis
11799
11800 \brief the widget's What's This help text.
11801
11802 By default, this property contains an empty string.
11803
11804 \sa QWhatsThis, QWidget::toolTip, QWidget::statusTip
11805*/
11806void QWidget::setWhatsThis(const QString &s)
11807{
11808 Q_D(QWidget);
11809 d->whatsThis = s;
11810}
11811
11812QString QWidget::whatsThis() const
11813{
11814 Q_D(const QWidget);
11815 return d->whatsThis;
11816}
11817#endif // QT_CONFIG(whatsthis)
11818
11819#if QT_CONFIG(accessibility)
11820/*!
11821 \property QWidget::accessibleName
11822
11823 \brief the widget's name as seen by assistive technologies
11824
11825 This is the primary name by which assistive technology such as screen readers
11826 announce this widget. For most widgets setting this property is not required.
11827 For example for QPushButton the button's text will be used.
11828
11829 It is important to set this property when the widget does not provide any
11830 text. For example a button that only contains an icon needs to set this
11831 property to work with screen readers.
11832 The name should be short and equivalent to the visual information conveyed
11833 by the widget.
11834
11835 This property has to be \l{Internationalization with Qt}{localized}.
11836
11837 By default, this property contains an empty string.
11838
11839 \sa QWidget::accessibleDescription, QAccessibleInterface::text()
11840*/
11841void QWidget::setAccessibleName(const QString &name)
11842{
11843 Q_D(QWidget);
11844 if (d->accessibleName == name)
11845 return;
11846
11847 d->accessibleName = name;
11848 QAccessibleEvent event(this, QAccessible::NameChanged);
11849 QAccessible::updateAccessibility(&event);
11850}
11851
11852QString QWidget::accessibleName() const
11853{
11854 Q_D(const QWidget);
11855 return d->accessibleName;
11856}
11857
11858/*!
11859 \property QWidget::accessibleDescription
11860
11861 \brief the widget's description as seen by assistive technologies
11862
11863 The accessible description of a widget should convey what a widget does.
11864 While the \l accessibleName should be a short and concise string (e.g. \gui{Save}),
11865 the description should give more context, such as \gui{Saves the current document}.
11866
11867 This property has to be \l{Internationalization with Qt}{localized}.
11868
11869 By default, this property contains an empty string and Qt falls back
11870 to using the tool tip to provide this information.
11871
11872 \sa QWidget::accessibleName, QAccessibleInterface::text()
11873*/
11874void QWidget::setAccessibleDescription(const QString &description)
11875{
11876 Q_D(QWidget);
11877 if (d->accessibleDescription == description)
11878 return;
11879
11880 d->accessibleDescription = description;
11881 QAccessibleEvent event(this, QAccessible::DescriptionChanged);
11882 QAccessible::updateAccessibility(&event);
11883}
11884
11885QString QWidget::accessibleDescription() const
11886{
11887 Q_D(const QWidget);
11888 return d->accessibleDescription;
11889}
11890
11891/*!
11892 \property QWidget::accessibleIdentifier
11893
11894 \brief the widget's identifier as seen by assistive technologies
11895
11896 If set, the accessible identifier of a widget can be used by assistive
11897 technologies in order to identify a specific widget, e.g. in automated
11898 tests.
11899
11900 \since 6.9
11901*/
11902void QWidget::setAccessibleIdentifier(const QString &identifier)
11903{
11904 Q_D(QWidget);
11905 if (d->accessibleIdentifier == identifier)
11906 return;
11907
11908 d->accessibleIdentifier = identifier;
11909 QAccessibleEvent event(this, QAccessible::IdentifierChanged);
11910 QAccessible::updateAccessibility(&event);
11911}
11912
11913QString QWidget::accessibleIdentifier() const
11914{
11915 Q_D(const QWidget);
11916 return d->accessibleIdentifier;
11917}
11918
11919#endif // QT_CONFIG(accessibility)
11920
11921#ifndef QT_NO_SHORTCUT
11922/*!
11923 Adds a shortcut to Qt's shortcut system that watches for the given
11924 \a key sequence in the given \a context. If the \a context is
11925 Qt::ApplicationShortcut, the shortcut applies to the application as a
11926 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
11927 or to the window itself, Qt::WindowShortcut.
11928
11929 If the same \a key sequence has been grabbed by several widgets,
11930 when the \a key sequence occurs a QEvent::Shortcut event is sent
11931 to all the widgets to which it applies in a non-deterministic
11932 order, but with the ``ambiguous'' flag set to true.
11933
11934 \warning You should not normally need to use this function;
11935 instead create \l{QAction}s with the shortcut key sequences you
11936 require (if you also want equivalent menu options and toolbar
11937 buttons), or create \l{QShortcut}s if you just need key sequences.
11938 Both QAction and QShortcut handle all the event filtering for you,
11939 and provide signals which are triggered when the user triggers the
11940 key sequence, so are much easier to use than this low-level
11941 function.
11942
11943 \sa releaseShortcut(), setShortcutEnabled()
11944*/
11945int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
11946{
11947 Q_ASSERT(qApp);
11948 if (key.isEmpty())
11949 return 0;
11950 setAttribute(Qt::WA_GrabbedShortcut);
11951 return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, key, context, qWidgetShortcutContextMatcher);
11952}
11953
11954/*!
11955 Removes the shortcut with the given \a id from Qt's shortcut
11956 system. The widget will no longer receive QEvent::Shortcut events
11957 for the shortcut's key sequence (unless it has other shortcuts
11958 with the same key sequence).
11959
11960 \warning You should not normally need to use this function since
11961 Qt's shortcut system removes shortcuts automatically when their
11962 parent widget is destroyed. It is best to use QAction or
11963 QShortcut to handle shortcuts, since they are easier to use than
11964 this low-level function. Note also that this is an expensive
11965 operation.
11966
11967 \sa grabShortcut(), setShortcutEnabled()
11968*/
11969void QWidget::releaseShortcut(int id)
11970{
11971 Q_ASSERT(qApp);
11972 if (id)
11973 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this, 0);
11974}
11975
11976/*!
11977 If \a enable is true, the shortcut with the given \a id is
11978 enabled; otherwise the shortcut is disabled.
11979
11980 \warning You should not normally need to use this function since
11981 Qt's shortcut system enables/disables shortcuts automatically as
11982 widgets become hidden/visible and gain or lose focus. It is best
11983 to use QAction or QShortcut to handle shortcuts, since they are
11984 easier to use than this low-level function.
11985
11986 \sa grabShortcut(), releaseShortcut()
11987*/
11988void QWidget::setShortcutEnabled(int id, bool enable)
11989{
11990 Q_ASSERT(qApp);
11991 if (id)
11992 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, this, 0);
11993}
11994
11995/*!
11996 \since 4.2
11997
11998 If \a enable is true, auto repeat of the shortcut with the
11999 given \a id is enabled; otherwise it is disabled.
12000
12001 \sa grabShortcut(), releaseShortcut()
12002*/
12003void QWidget::setShortcutAutoRepeat(int id, bool enable)
12004{
12005 Q_ASSERT(qApp);
12006 if (id)
12007 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(enable, id, this, 0);
12008}
12009#endif // QT_NO_SHORTCUT
12010
12011/*!
12012 Updates the widget's micro focus and informs input methods
12013 that the state specified by \a query has changed.
12014*/
12015void QWidget::updateMicroFocus(Qt::InputMethodQuery query)
12016{
12017 if (this == QGuiApplication::focusObject())
12018 QGuiApplication::inputMethod()->update(query);
12019}
12020
12021/*!
12022 Raises this widget to the top of the parent widget's stack.
12023
12024 After this call the widget will be visually in front of any
12025 overlapping sibling widgets.
12026
12027 \note When using activateWindow(), you can call this function to
12028 ensure that the window is stacked on top.
12029
12030 \sa lower(), stackUnder()
12031*/
12032
12033void QWidget::raise()
12034{
12035 Q_D(QWidget);
12036 if (!isWindow()) {
12037 QWidget *p = parentWidget();
12038 const int parentChildCount = p->d_func()->children.size();
12039 if (parentChildCount < 2)
12040 return;
12041 const int from = p->d_func()->children.indexOf(this);
12042 Q_ASSERT(from >= 0);
12043 // Do nothing if the widget is already in correct stacking order _and_ created.
12044 if (from != parentChildCount -1)
12045 p->d_func()->children.move(from, parentChildCount - 1);
12046 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12047 create();
12048 else if (from == parentChildCount - 1)
12049 return;
12050
12051 QRegion region(rect());
12052 d->subtractOpaqueSiblings(region);
12053 d->invalidateBackingStore(region);
12054 }
12055 if (testAttribute(Qt::WA_WState_Created))
12056 d->raise_sys();
12057
12058 if (d->extra && d->extra->hasWindowContainer)
12059 QWindowContainer::parentWasRaised(this);
12060
12061 QEvent e(QEvent::ZOrderChange);
12062 QCoreApplication::sendEvent(this, &e);
12063}
12064
12065void QWidgetPrivate::raise_sys()
12066{
12067 Q_Q(QWidget);
12068 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
12069 q->windowHandle()->raise();
12070 } else if (renderToTexture) {
12071 if (QWidget *p = q->parentWidget()) {
12072 setDirtyOpaqueRegion();
12073 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12074 }
12075 }
12076}
12077
12078/*!
12079 Lowers the widget to the bottom of the parent widget's stack.
12080
12081 After this call the widget will be visually behind (and therefore
12082 obscured by) any overlapping sibling widgets.
12083
12084 \sa raise(), stackUnder()
12085*/
12086
12087void QWidget::lower()
12088{
12089 Q_D(QWidget);
12090 if (!isWindow()) {
12091 QWidget *p = parentWidget();
12092 const int parentChildCount = p->d_func()->children.size();
12093 if (parentChildCount < 2)
12094 return;
12095 const int from = p->d_func()->children.indexOf(this);
12096 Q_ASSERT(from >= 0);
12097 // Do nothing if the widget is already in correct stacking order _and_ created.
12098 if (from != 0)
12099 p->d_func()->children.move(from, 0);
12100 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12101 create();
12102 else if (from == 0)
12103 return;
12104 }
12105 if (testAttribute(Qt::WA_WState_Created))
12106 d->lower_sys();
12107
12108 if (d->extra && d->extra->hasWindowContainer)
12109 QWindowContainer::parentWasLowered(this);
12110
12111 QEvent e(QEvent::ZOrderChange);
12112 QCoreApplication::sendEvent(this, &e);
12113}
12114
12115void QWidgetPrivate::lower_sys()
12116{
12117 Q_Q(QWidget);
12118 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
12119 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
12120 q->windowHandle()->lower();
12121 } else if (QWidget *p = q->parentWidget()) {
12122 setDirtyOpaqueRegion();
12123 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12124 }
12125}
12126
12127/*!
12128 Places the widget under \a w in the parent widget's stack.
12129
12130 To make this work, the widget itself and \a w must be siblings.
12131
12132 \sa raise(), lower()
12133*/
12134void QWidget::stackUnder(QWidget* w)
12135{
12136 Q_D(QWidget);
12137 QWidget *p = parentWidget();
12138 if (!w || isWindow() || p != w->parentWidget() || this == w)
12139 return;
12140 if (p) {
12141 int from = p->d_func()->children.indexOf(this);
12142 int to = p->d_func()->children.indexOf(w);
12143 Q_ASSERT(from >= 0);
12144 Q_ASSERT(to >= 0);
12145 if (from < to)
12146 --to;
12147 // Do nothing if the widget is already in correct stacking order _and_ created.
12148 if (from != to)
12149 p->d_func()->children.move(from, to);
12150 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12151 create();
12152 else if (from == to)
12153 return;
12154 }
12155 if (testAttribute(Qt::WA_WState_Created))
12156 d->stackUnder_sys(w);
12157
12158 QEvent e(QEvent::ZOrderChange);
12159 QCoreApplication::sendEvent(this, &e);
12160}
12161
12162void QWidgetPrivate::stackUnder_sys(QWidget*)
12163{
12164 Q_Q(QWidget);
12165 if (QWidget *p = q->parentWidget()) {
12166 setDirtyOpaqueRegion();
12167 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12168 }
12169}
12170
12171/*!
12172 \fn bool QWidget::isTopLevel() const
12173 \deprecated
12174
12175 Use isWindow() instead.
12176*/
12177
12178/*!
12179 \fn bool QWidget::isRightToLeft() const
12180 \internal
12181*/
12182
12183/*!
12184 \fn bool QWidget::isLeftToRight() const
12185 \internal
12186*/
12187
12188/*!
12189 \macro QWIDGETSIZE_MAX
12190 \relates QWidget
12191
12192 Defines the maximum size for a QWidget object.
12193
12194 The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
12195 QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
12196
12197 \sa QWidget::setMaximumSize()
12198*/
12199
12200/*!
12201 \fn QWidget::setupUi(QWidget *widget)
12202
12203 Sets up the user interface for the specified \a widget.
12204
12205 \note This function is available with widgets that derive from user
12206 interface descriptions created using \l{uic}.
12207
12208 \sa {Using a Designer UI File in Your Application}
12209*/
12210
12211QRect QWidgetPrivate::frameStrut() const
12212{
12213 Q_Q(const QWidget);
12214 if (!q->isWindow() || q->testAttribute(Qt::WA_DontShowOnScreen)) {
12215 // x2 = x1 + w - 1, so w/h = 1
12216 return QRect(0, 0, 1, 1);
12217 }
12218
12219 if (data.fstrut_dirty
12220 // ### Fix properly for 4.3
12221 && q->isVisible()
12222 && q->testAttribute(Qt::WA_WState_Created))
12223 const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
12224
12225 return maybeTopData() ? maybeTopData()->frameStrut : QRect();
12226}
12227
12228void QWidgetPrivate::updateFrameStrut()
12229{
12230 Q_Q(QWidget);
12231 if (q->data->fstrut_dirty) {
12232 if (QTLWExtra *te = maybeTopData()) {
12233 if (te->window && te->window->handle()) {
12234 const QMargins margins = te->window->frameMargins();
12235 if (!margins.isNull()) {
12236 te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
12237 q->data->fstrut_dirty = false;
12238 }
12239 }
12240 }
12241 }
12242}
12243
12244/*!
12245 \since 5.0
12246 \internal
12247
12248 Sets the backing store to be the \a store specified.
12249 The QWidget will take ownership of the \a store.
12250*/
12251void QWidget::setBackingStore(QBackingStore *store)
12252{
12253 // ### createWinId() ??
12254
12255 if (!isWindow())
12256 return;
12257
12258 Q_D(QWidget);
12259
12260 QTLWExtra *topData = d->topData();
12261 if (topData->backingStore == store)
12262 return;
12263
12264 QBackingStore *oldStore = topData->backingStore;
12265 delete topData->backingStore;
12266 topData->backingStore = store;
12267
12268 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
12269 if (!repaintManager)
12270 return;
12271
12272 if (isWindow()) {
12273 if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store)
12274 delete repaintManager->backingStore();
12275 repaintManager->setBackingStore(store);
12276 }
12277}
12278
12279/*!
12280 \since 5.0
12281
12282 Returns the QBackingStore this widget will be drawn into.
12283*/
12284QBackingStore *QWidget::backingStore() const
12285{
12286 Q_D(const QWidget);
12287 QTLWExtra *extra = d->maybeTopData();
12288 if (extra && extra->backingStore)
12289 return extra->backingStore;
12290
12291 if (!isWindow())
12292 return window()->backingStore();
12293
12294 return nullptr;
12295}
12296
12297void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
12298{
12299 if (left)
12300 *left = (int)leftLayoutItemMargin;
12301 if (top)
12302 *top = (int)topLayoutItemMargin;
12303 if (right)
12304 *right = (int)rightLayoutItemMargin;
12305 if (bottom)
12306 *bottom = (int)bottomLayoutItemMargin;
12307}
12308
12309void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
12310{
12311 if (leftLayoutItemMargin == left
12312 && topLayoutItemMargin == top
12313 && rightLayoutItemMargin == right
12314 && bottomLayoutItemMargin == bottom)
12315 return;
12316
12317 Q_Q(QWidget);
12318 leftLayoutItemMargin = (signed char)left;
12319 topLayoutItemMargin = (signed char)top;
12320 rightLayoutItemMargin = (signed char)right;
12321 bottomLayoutItemMargin = (signed char)bottom;
12322 q->updateGeometry();
12323}
12324
12325void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
12326{
12327 Q_Q(QWidget);
12328 QStyleOption myOpt;
12329 if (!opt) {
12330 myOpt.initFrom(q);
12331 myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary
12332 opt = &myOpt;
12333 }
12334
12335 QRect liRect = q->style()->subElementRect(element, opt, q);
12336 if (liRect.isValid()) {
12337 leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
12338 topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
12339 rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
12340 bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
12341 } else {
12342 leftLayoutItemMargin = 0;
12343 topLayoutItemMargin = 0;
12344 rightLayoutItemMargin = 0;
12345 bottomLayoutItemMargin = 0;
12346 }
12347}
12348// resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
12349void QWidgetPrivate::adjustQuitOnCloseAttribute()
12350{
12351 Q_Q(QWidget);
12352
12353 if (!q->parentWidget()) {
12354 Qt::WindowType type = q->windowType();
12355 if (type == Qt::Widget || type == Qt::SubWindow)
12356 type = Qt::Window;
12357 if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
12358 q->setAttribute(Qt::WA_QuitOnClose, false);
12359 }
12360}
12361
12362void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
12363{
12364 QWidgetPrivate *wd = QWidgetPrivate::get(w);
12365 if (!wd->textureChildSeen)
12366 return;
12367 if (end)
12368 wd->endCompose();
12369 else
12370 wd->beginCompose();
12371 for (int i = 0; i < wd->children.size(); ++i) {
12372 w = qobject_cast<QWidget *>(wd->children.at(i));
12373 if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
12374 sendComposeStatus(w, end);
12375 }
12376}
12377
12378Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
12379{
12380 return widget->data;
12381}
12382
12383Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
12384{
12385 return widget->d_func();
12386}
12387
12388
12389#if QT_CONFIG(graphicsview)
12390/*!
12391 \since 4.5
12392
12393 Returns the proxy widget for the corresponding embedded widget in a graphics
12394 view; otherwise returns \nullptr.
12395
12396 \sa QGraphicsProxyWidget::createProxyForChildWidget(),
12397 QGraphicsScene::addWidget()
12398 */
12399QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
12400{
12401 Q_D(const QWidget);
12402 if (d->extra) {
12403 return d->extra->proxyWidget;
12404 }
12405 return nullptr;
12406}
12407#endif
12408
12409#ifndef QT_NO_GESTURES
12410/*!
12411 Subscribes the widget to a given \a gesture with specific \a flags.
12412
12413 \sa ungrabGesture(), QGestureEvent
12414 \since 4.6
12415*/
12416void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
12417{
12418 Q_D(QWidget);
12419 d->gestureContext.insert(gesture, flags);
12420 (void)QGestureManager::instance(); // create a gesture manager
12421}
12422
12423/*!
12424 Unsubscribes the widget from a given \a gesture type
12425
12426 \sa grabGesture(), QGestureEvent
12427 \since 4.6
12428*/
12429void QWidget::ungrabGesture(Qt::GestureType gesture)
12430{
12431 // if you modify this function, check the inlined version in ~QWidget, too
12432 Q_D(QWidget);
12433 if (d->gestureContext.remove(gesture)) {
12434 if (QGestureManager *manager = QGestureManager::instance())
12435 manager->cleanupCachedGestures(this, gesture);
12436 }
12437}
12438#endif // QT_NO_GESTURES
12439
12440/*!
12441 \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12442
12443 Frees up window system resources. Destroys the widget window if \a
12444 destroyWindow is true.
12445
12446 destroy() calls itself recursively for all the child widgets,
12447 passing \a destroySubWindows for the \a destroyWindow parameter.
12448 To have more control over destruction of subwidgets, destroy
12449 subwidgets selectively first.
12450
12451 This function is usually called from the QWidget destructor.
12452*/
12453void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12454{
12455 Q_D(QWidget);
12456
12457 d->aboutToDestroy();
12458 if (!isWindow() && parentWidget())
12459 parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(geometry()));
12460 d->deactivateWidgetCleanup();
12461
12462 if ((windowType() == Qt::Popup) && qApp)
12463 qApp->d_func()->closePopup(this);
12464
12465 if (this == qApp->activeWindow())
12466 QApplicationPrivate::setActiveWindow(nullptr);
12467 if (QWidget::mouseGrabber() == this)
12468 releaseMouse();
12469 if (QWidget::keyboardGrabber() == this)
12470 releaseKeyboard();
12471
12472 setAttribute(Qt::WA_WState_Created, false);
12473
12474 if (destroySubWindows) {
12475 QObjectList childList(children());
12476 for (int i = 0; i < childList.size(); i++) {
12477 QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
12478 if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
12479 if (widget->windowHandle()) {
12480 widget->destroy();
12481 }
12482 }
12483 }
12484 }
12485 if (destroyWindow) {
12486 d->deleteTLSysExtra();
12487 } else {
12488 if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
12489 d->hide_sys();
12490 }
12491 }
12492
12493 d->setWinId(0);
12494}
12495
12496/*!
12497 \fn QPaintEngine *QWidget::paintEngine() const
12498
12499 Returns the widget's paint engine.
12500
12501 Note that this function should not be called explicitly by the
12502 user, since it's meant for reimplementation purposes only. The
12503 function is called by Qt internally, and the default
12504 implementation may not always return a valid pointer.
12505*/
12506QPaintEngine *QWidget::paintEngine() const
12507{
12508 qWarning("QWidget::paintEngine: Should no longer be called");
12509
12510#ifdef Q_OS_WIN
12511 // We set this bit which is checked in setAttribute for
12512 // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
12513 //
12514 // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
12515 // Windows which would mean suddenly their widgets stop working.
12516 //
12517 // 2. Users set paint on screen and subclass paintEngine() to
12518 // return 0, in which case we have a "hole" in the backingstore
12519 // allowing use of GDI or DirectX directly.
12520 //
12521 // 1 is WRONG, but to minimize silent failures, we have set this
12522 // bit to ignore the setAttribute call. 2. needs to be
12523 // supported because its our only means of embedding native
12524 // graphics stuff.
12525 const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
12526#endif
12527
12528 return nullptr; //##### @@@
12529}
12530
12531// Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing.
12532static inline bool canMapPosition(QWindow *window)
12533{
12534 return window->handle() && !qt_window_private(window)->resizeEventPending;
12535}
12536
12537#if QT_CONFIG(graphicsview)
12538static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w)
12539{
12540 QGraphicsProxyWidget *result = nullptr;
12541 const QWidgetPrivate *d = qt_widget_private(const_cast<QWidget *>(w));
12542 if (d->extra)
12543 result = d->extra->proxyWidget;
12544 return result;
12545}
12546#endif // QT_CONFIG(graphicsview)
12547
12549 QTransform transform;
12550 QWindow *window;
12551};
12552
12554{
12556 result.window = nullptr;
12557 for ( ; w ; w = w->parentWidget()) {
12558#if QT_CONFIG(graphicsview)
12559 if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) {
12560 if (const QGraphicsScene *scene = qgpw->scene()) {
12561 const QList <QGraphicsView *> views = scene->views();
12562 if (!views.isEmpty()) {
12563 auto *viewP = static_cast<QGraphicsViewPrivate *>(qt_widget_private(views.constFirst()));
12564 result.transform *= viewP->mapToViewTransform(qgpw);
12565 w = views.first()->viewport();
12566 }
12567 }
12568 }
12569#endif // QT_CONFIG(graphicsview)
12570 QWindow *window = w->windowHandle();
12571 if (window && canMapPosition(window)) {
12572 result.window = window;
12573 break;
12574 }
12575
12576 const auto &geometry = w->geometry();
12577 result.transform *= QTransform::fromTranslate(geometry.x(), geometry.y());
12578 if (w->isWindow())
12579 break;
12580 }
12581 return result;
12582}
12583
12584/*!
12585 \fn QPointF QWidget::mapToGlobal(const QPointF &pos) const
12586
12587 Translates the widget coordinate \a pos to global screen
12588 coordinates. For example, \c{mapToGlobal(QPointF(0,0))} would give
12589 the global coordinates of the top-left pixel of the widget.
12590
12591 \sa mapFromGlobal(), mapTo(), mapToParent()
12592 \since 6.0
12593*/
12594QPointF QWidget::mapToGlobal(const QPointF &pos) const
12595{
12596 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12597 const QPointF g = t.transform.map(pos);
12598 return t.window ? t.window->mapToGlobal(g) : g;
12599}
12600
12601/*!
12602 \overload
12603*/
12604QPoint QWidget::mapToGlobal(const QPoint &pos) const
12605{
12606 return mapToGlobal(QPointF(pos)).toPoint();
12607}
12608
12609/*!
12610 \fn QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12611
12612 Translates the global screen coordinate \a pos to widget
12613 coordinates.
12614
12615 \sa mapToGlobal(), mapFrom(), mapFromParent()
12616 \since 6.0
12617*/
12618QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12619{
12620 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12621 const QPointF windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos;
12622 return t.transform.inverted().map(windowLocal);
12623}
12624
12625/*!
12626 \overload
12627*/
12628QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12629{
12630 return mapFromGlobal(QPointF(pos)).toPoint();
12631}
12632
12634static bool mouseGrabWithCursor = false;
12635static QWidget *keyboardGrb = nullptr;
12636
12637static inline QWindow *grabberWindow(const QWidget *w)
12638{
12639 QWindow *window = w->windowHandle();
12640 if (!window)
12641 if (const QWidget *nativeParent = w->nativeParentWidget())
12642 window = nativeParent->windowHandle();
12643 return window;
12644}
12645
12646#ifndef QT_NO_CURSOR
12647static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = nullptr)
12648#else
12649static void grabMouseForWidget(QWidget *widget)
12650#endif
12651{
12652 if (qt_mouseGrb)
12653 qt_mouseGrb->releaseMouse();
12654
12655 mouseGrabWithCursor = false;
12656 if (QWindow *window = grabberWindow(widget)) {
12657#ifndef QT_NO_CURSOR
12658 if (cursor) {
12659 mouseGrabWithCursor = true;
12660 QGuiApplication::setOverrideCursor(*cursor);
12661 }
12662#endif // !QT_NO_CURSOR
12663 window->setMouseGrabEnabled(true);
12664 }
12665
12666 qt_mouseGrb = widget;
12667}
12668
12670{
12671 if (qt_mouseGrb == widget) {
12672 if (QWindow *window = grabberWindow(widget)) {
12673#ifndef QT_NO_CURSOR
12674 if (mouseGrabWithCursor) {
12675 QGuiApplication::restoreOverrideCursor();
12676 mouseGrabWithCursor = false;
12677 }
12678#endif // !QT_NO_CURSOR
12679 window->setMouseGrabEnabled(false);
12680 }
12681 }
12682 qt_mouseGrb = nullptr;
12683}
12684
12685/*!
12686 \fn void QWidget::grabMouse()
12687
12688 Grabs the mouse input.
12689
12690 This widget receives all mouse events until releaseMouse() is
12691 called; other widgets get no mouse events at all. Keyboard
12692 events are not affected. Use grabKeyboard() if you want to grab
12693 that.
12694
12695 \warning Bugs in mouse-grabbing applications very often lock the
12696 terminal. Use this function with extreme caution, and consider
12697 using the \c -nograb command line option while debugging.
12698
12699 It is seldom necessary to grab the mouse when using Qt, as
12700 Qt grabs and releases it sensibly. In particular, Qt grabs the
12701 mouse when a mouse button is pressed and keeps it until the last
12702 button is released.
12703
12704 \note Only visible widgets can grab mouse input. If isVisible()
12705 returns \c false for a widget, that widget cannot call grabMouse().
12706
12707 \note On Windows, grabMouse() only works when the mouse is inside a window
12708 owned by the process.
12709 On \macos, grabMouse() only works when the mouse is inside the frame of that widget.
12710
12711 \sa releaseMouse(), grabKeyboard(), releaseKeyboard()
12712*/
12713void QWidget::grabMouse()
12714{
12715 grabMouseForWidget(this);
12716}
12717
12718/*!
12719 \fn void QWidget::grabMouse(const QCursor &cursor)
12720 \overload grabMouse()
12721
12722 Grabs the mouse input and changes the cursor shape.
12723
12724 The cursor will assume shape \a cursor (for as long as the mouse
12725 focus is grabbed) and this widget will be the only one to receive
12726 mouse events until releaseMouse() is called().
12727
12728 \warning Grabbing the mouse might lock the terminal.
12729
12730 \note See the note in QWidget::grabMouse().
12731
12732 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
12733*/
12734#ifndef QT_NO_CURSOR
12735void QWidget::grabMouse(const QCursor &cursor)
12736{
12737 grabMouseForWidget(this, &cursor);
12738}
12739#endif
12740
12741bool QWidgetPrivate::stealMouseGrab(bool grab)
12742{
12743 // This is like a combination of grab/releaseMouse() but with error checking
12744 // and it has no effect on the result of mouseGrabber().
12745 Q_Q(QWidget);
12746 QWindow *window = grabberWindow(q);
12747 return window ? window->setMouseGrabEnabled(grab) : false;
12748}
12749
12750/*!
12751 \fn void QWidget::releaseMouse()
12752
12753 Releases the mouse grab.
12754
12755 \sa grabMouse(), grabKeyboard(), releaseKeyboard()
12756*/
12757void QWidget::releaseMouse()
12758{
12759 releaseMouseGrabOfWidget(this);
12760}
12761
12762/*!
12763 \fn void QWidget::grabKeyboard()
12764
12765 Grabs the keyboard input.
12766
12767 This widget receives all keyboard events until releaseKeyboard()
12768 is called; other widgets get no keyboard events at all. Mouse
12769 events are not affected. Use grabMouse() if you want to grab that.
12770
12771 The focus widget is not affected, except that it doesn't receive
12772 any keyboard events. setFocus() moves the focus as usual, but the
12773 new focus widget receives keyboard events only after
12774 releaseKeyboard() is called.
12775
12776 If a different widget is currently grabbing keyboard input, that
12777 widget's grab is released first.
12778
12779 \sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
12780*/
12781void QWidget::grabKeyboard()
12782{
12783 if (keyboardGrb)
12784 keyboardGrb->releaseKeyboard();
12785 if (QWindow *window = grabberWindow(this))
12786 window->setKeyboardGrabEnabled(true);
12787 keyboardGrb = this;
12788}
12789
12790bool QWidgetPrivate::stealKeyboardGrab(bool grab)
12791{
12792 // This is like a combination of grab/releaseKeyboard() but with error
12793 // checking and it has no effect on the result of keyboardGrabber().
12794 Q_Q(QWidget);
12795 QWindow *window = grabberWindow(q);
12796 return window ? window->setKeyboardGrabEnabled(grab) : false;
12797}
12798
12799/*!
12800 \fn void QWidget::releaseKeyboard()
12801
12802 Releases the keyboard grab.
12803
12804 \sa grabKeyboard(), grabMouse(), releaseMouse()
12805*/
12806void QWidget::releaseKeyboard()
12807{
12808 if (keyboardGrb == this) {
12809 if (QWindow *window = grabberWindow(this))
12810 window->setKeyboardGrabEnabled(false);
12811 keyboardGrb = nullptr;
12812 }
12813}
12814
12815/*!
12816 \fn QWidget *QWidget::mouseGrabber()
12817
12818 Returns the widget that is currently grabbing the mouse input.
12819
12820 If no widget in this application is currently grabbing the mouse,
12821 \nullptr is returned.
12822
12823 \sa grabMouse(), keyboardGrabber()
12824*/
12825QWidget *QWidget::mouseGrabber()
12826{
12827 return qt_mouseGrb;
12828}
12829
12830/*!
12831 \fn QWidget *QWidget::keyboardGrabber()
12832
12833 Returns the widget that is currently grabbing the keyboard input.
12834
12835 If no widget in this application is currently grabbing the
12836 keyboard, \nullptr is returned.
12837
12838 \sa grabMouse(), mouseGrabber()
12839*/
12840QWidget *QWidget::keyboardGrabber()
12841{
12842 return keyboardGrb;
12843}
12844
12845/*!
12846 \fn void QWidget::activateWindow()
12847
12848 Sets the top-level widget containing this widget to be the active
12849 window.
12850
12851 An active window is a visible top-level window that has the
12852 keyboard input focus.
12853
12854 This function performs the same operation as clicking the mouse on
12855 the title bar of a top-level window. On X11, the result depends on
12856 the Window Manager. If you want to ensure that the window is
12857 stacked on top as well you should also call raise(). Note that the
12858 window must be visible, otherwise activateWindow() has no effect.
12859
12860 On Windows, if you are calling this when the application is not
12861 currently the active one then it will not make it the active
12862 window. It will change the color of the taskbar entry to indicate
12863 that the window has changed in some way. This is because Microsoft
12864 does not allow an application to interrupt what the user is currently
12865 doing in another application.
12866
12867 \sa isActiveWindow(), window(), show()
12868*/
12869void QWidget::activateWindow()
12870{
12871 QWindow *const wnd = window()->windowHandle();
12872
12873 if (wnd)
12874 wnd->requestActivate();
12875}
12876
12877/*!
12878
12879 Internal implementation of the virtual QPaintDevice::metric()
12880 function.
12881
12882 \a m is the metric to get.
12883*/
12884int QWidget::metric(PaintDeviceMetric m) const
12885{
12886 QScreen *screen = this->screen();
12887
12888 if (!screen) {
12889 if (m == PdmDpiX || m == PdmDpiY)
12890 return 72;
12891 return QPaintDevice::metric(m);
12892 }
12893
12894 auto resolveDevicePixelRatio = [this, screen]() -> qreal {
12895
12896 // Note: keep in sync with QBackingStorePrivate::backingStoreDevicePixelRatio()!
12897 static bool downscale = qEnvironmentVariableIntValue("QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
12898 QWindow *window = this->window()->windowHandle();
12899 if (window)
12900 return downscale ? std::ceil(window->devicePixelRatio()) : window->devicePixelRatio();
12901 return screen->devicePixelRatio();
12902 };
12903
12904 switch (m) {
12905 case PdmWidth:
12906 return data->crect.width();
12907 case PdmWidthMM:
12908 return data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
12909 case PdmHeight:
12910 return data->crect.height();
12911 case PdmHeightMM:
12912 return data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
12913 case PdmDepth:
12914 return screen->depth();
12915 case PdmDpiX:
12916 for (const QWidget *p = this; p; p = p->parentWidget()) {
12917 if (p->d_func()->extra && p->d_func()->extra->customDpiX)
12918 return p->d_func()->extra->customDpiX;
12919 }
12920 return qRound(screen->logicalDotsPerInchX());
12921 case PdmDpiY:
12922 for (const QWidget *p = this; p; p = p->parentWidget()) {
12923 if (p->d_func()->extra && p->d_func()->extra->customDpiY)
12924 return p->d_func()->extra->customDpiY;
12925 }
12926 return qRound(screen->logicalDotsPerInchY());
12927 case PdmPhysicalDpiX:
12928 return qRound(screen->physicalDotsPerInchX());
12929 case PdmPhysicalDpiY:
12930 return qRound(screen->physicalDotsPerInchY());
12931 case PdmDevicePixelRatio:
12932 return resolveDevicePixelRatio();
12933 case PdmDevicePixelRatioScaled:
12934 return QPaintDevice::devicePixelRatioFScale() * resolveDevicePixelRatio();
12935 case PdmDevicePixelRatioF_EncodedA:
12936 Q_FALLTHROUGH();
12937 case PdmDevicePixelRatioF_EncodedB:
12938 return QPaintDevice::encodeMetricF(m, resolveDevicePixelRatio());
12939 default:
12940 break;
12941 }
12942 return QPaintDevice::metric(m);
12943}
12944
12945/*!
12946 Initializes the \a painter pen, background and font to the same as
12947 the given widget's. This function is called automatically when the
12948 painter is opened on a QWidget.
12949*/
12950void QWidget::initPainter(QPainter *painter) const
12951{
12952 const QPalette &pal = palette();
12953 QPainterPrivate *painterPrivate = QPainterPrivate::get(painter);
12954
12955 painterPrivate->state->pen = QPen(pal.brush(foregroundRole()), 1);
12956 painterPrivate->state->bgBrush = pal.brush(backgroundRole());
12957 QFont f(font(), this);
12958 painterPrivate->state->deviceFont = f;
12959 painterPrivate->state->font = f;
12960
12961 painterPrivate->setEngineDirtyFlags({
12962 QPaintEngine::DirtyPen,
12963 QPaintEngine::DirtyBrush,
12964 QPaintEngine::DirtyFont,
12965 });
12966
12967 if (painterPrivate->extended)
12968 painterPrivate->extended->penChanged();
12969}
12970
12971/*!
12972 \internal
12973
12974 Do PaintDevice rendering with the specified \a offset.
12975*/
12976QPaintDevice *QWidget::redirected(QPoint *offset) const
12977{
12978 return d_func()->redirected(offset);
12979}
12980
12981/*!
12982 \internal
12983
12984 A painter that is shared among other instances of QPainter.
12985*/
12986QPainter *QWidget::sharedPainter() const
12987{
12988 // Someone sent a paint event directly to the widget
12989 if (!d_func()->redirectDev)
12990 return nullptr;
12991
12992 QPainter *sp = d_func()->sharedPainter();
12993 if (!sp || !sp->isActive())
12994 return nullptr;
12995
12996 if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
12997 return nullptr;
12998
12999 return sp;
13000}
13001
13002/*!
13003 \fn void QWidget::setMask(const QRegion &region)
13004 \overload
13005
13006 Causes only the parts of the widget which overlap \a region to be
13007 visible. If the region includes pixels outside the rect() of the
13008 widget, window system controls in that area may or may not be
13009 visible, depending on the platform.
13010
13011 Since QRegion allows arbitrarily complex regions to be created, widget
13012 masks can be made to suit the most unconventionally-shaped windows, and
13013 even allow widgets to be displayed with holes in them. Note that this
13014 effect can be slow if the region is particularly complex.
13015
13016 Widget masks are used to hint to the window system that the application
13017 does not want mouse events for areas outside the mask. On most systems,
13018 they also result in coarse visual clipping. To get smooth window edges, use
13019 translucent background and anti-aliased painting instead, as shown in the
13020 \l{Translucent Background} example.
13021
13022 \sa windowOpacity
13023*/
13024void QWidget::setMask(const QRegion &newMask)
13025{
13026 Q_D(QWidget);
13027
13028 d->createExtra();
13029 if (newMask == d->extra->mask)
13030 return;
13031
13032#ifndef QT_NO_BACKINGSTORE
13033 const QRegion oldMask(d->extra->mask);
13034#endif
13035
13036 d->extra->mask = newMask;
13037 d->extra->hasMask = !newMask.isEmpty();
13038
13039 if (!testAttribute(Qt::WA_WState_Created))
13040 return;
13041
13042 d->setMask_sys(newMask);
13043
13044#ifndef QT_NO_BACKINGSTORE
13045 if (!isVisible())
13046 return;
13047
13048 if (!d->extra->hasMask) {
13049 // Mask was cleared; update newly exposed area.
13050 QRegion expose(rect());
13051 expose -= oldMask;
13052 if (!expose.isEmpty()) {
13053 d->setDirtyOpaqueRegion();
13054 update(expose);
13055 }
13056 return;
13057 }
13058
13059 if (!isWindow()) {
13060 // Update newly exposed area on the parent widget.
13061 QRegion parentExpose(rect());
13062 parentExpose -= newMask;
13063 if (!parentExpose.isEmpty()) {
13064 d->setDirtyOpaqueRegion();
13065 parentExpose.translate(data->crect.topLeft());
13066 parentWidget()->update(parentExpose);
13067 }
13068
13069 // Update newly exposed area on this widget
13070 if (!oldMask.isEmpty())
13071 update(newMask - oldMask);
13072 }
13073#endif
13074}
13075
13076void QWidgetPrivate::setMask_sys(const QRegion &region)
13077{
13078 Q_Q(QWidget);
13079 if (QWindow *window = q->windowHandle())
13080 window->setMask(region);
13081}
13082
13083/*!
13084 \fn void QWidget::setMask(const QBitmap &bitmap)
13085
13086 Causes only the pixels of the widget for which \a bitmap has a
13087 corresponding 1 bit to be visible. If the region includes pixels
13088 outside the rect() of the widget, window system controls in that
13089 area may or may not be visible, depending on the platform.
13090
13091 Note that this effect can be slow if the region is particularly
13092 complex.
13093
13094 The following code shows how an image with an alpha channel can be
13095 used to generate a mask for a widget:
13096
13097 \snippet widget-mask/main.cpp 0
13098
13099 The label shown by this code is masked using the image it contains,
13100 giving the appearance that an irregularly-shaped image is being drawn
13101 directly onto the screen.
13102
13103 Masked widgets receive mouse events only on their visible
13104 portions.
13105
13106 \sa clearMask(), windowOpacity()
13107*/
13108void QWidget::setMask(const QBitmap &bitmap)
13109{
13110 setMask(QRegion(bitmap));
13111}
13112
13113/*!
13114 \fn void QWidget::clearMask()
13115
13116 Removes any mask set by setMask().
13117
13118 \sa setMask()
13119*/
13120void QWidget::clearMask()
13121{
13122 Q_D(QWidget);
13123 if (!d->extra || !d->extra->hasMask)
13124 return;
13125 setMask(QRegion());
13126}
13127
13128void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent)
13129{
13130 Q_ASSERT(widgetAsObject->isWidgetType());
13131 Q_ASSERT(!newParent || newParent->isWidgetType());
13132 QWidget *widget = static_cast<QWidget*>(widgetAsObject);
13133 widget->setParent(static_cast<QWidget*>(newParent));
13134}
13135
13136std::string QWidgetPrivate::flagsForDumping() const
13137{
13138 Q_Q(const QWidget);
13139 std::string flags = QObjectPrivate::flagsForDumping();
13140 if (QApplication::focusWidget() == q)
13141 flags += 'F';
13142 if (q->isVisible()) {
13143 std::stringstream s;
13144 s << '<'
13145 << q->width() << 'x' << q->height()
13146 << std::showpos << q->x() << q->y()
13147 << '>';
13148 flags += s.str();
13149 } else {
13150 flags += 'I';
13151 }
13152 return flags;
13153}
13154
13155void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
13156{
13157#if QT_CONFIG(xcb)
13158 Q_Q(QWidget);
13159
13160 if (!q->windowHandle())
13161 return;
13162
13163 QXcbWindow::WindowTypes wmWindowType = QXcbWindow::None;
13164 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
13165 wmWindowType |= QXcbWindow::Desktop;
13166 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
13167 wmWindowType |= QXcbWindow::Dock;
13168 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
13169 wmWindowType |= QXcbWindow::Toolbar;
13170 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
13171 wmWindowType |= QXcbWindow::Menu;
13172 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
13173 wmWindowType |= QXcbWindow::Utility;
13174 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
13175 wmWindowType |= QXcbWindow::Splash;
13176 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
13177 wmWindowType |= QXcbWindow::Dialog;
13178 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
13179 wmWindowType |= QXcbWindow::DropDownMenu;
13180 if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
13181 wmWindowType |= QXcbWindow::PopupMenu;
13182 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
13183 wmWindowType |= QXcbWindow::Tooltip;
13184 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
13185 wmWindowType |= QXcbWindow::Notification;
13186 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
13187 wmWindowType |= QXcbWindow::Combo;
13188 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
13189 wmWindowType |= QXcbWindow::Dnd;
13190
13191 if (wmWindowType == QXcbWindow::None && skipIfMissing)
13192 return;
13193
13194 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(q->windowHandle()->handle()))
13195 xcbWindow->setWindowType(wmWindowType);
13196#else
13197 Q_UNUSED(skipIfMissing);
13198#endif
13199}
13200
13201/*!
13202 \internal
13203 \return \c true, if a child with \param policy exists and isn't a child of \param excludeChildrenOf.
13204 Return false otherwise.
13205 */
13206bool QWidgetPrivate::hasChildWithFocusPolicy(Qt::FocusPolicy policy, const QWidget *excludeChildrenOf) const
13207{
13208 Q_Q(const QWidget);
13209 const QWidgetList &children = q->findChildren<QWidget *>(Qt::FindChildrenRecursively);
13210 for (const auto *child : children) {
13211 if (child->focusPolicy() == policy && child->isEnabled()
13212 && (!excludeChildrenOf || !excludeChildrenOf->isAncestorOf(child))) {
13213 return true;
13214 }
13215 }
13216 return false;
13217}
13218
13219#ifndef QT_NO_DEBUG_STREAM
13220
13221namespace {
13222QDebug operator<<(QDebug debug, const WidgetAttributes &attributes)
13223{
13224 const QDebugStateSaver saver(debug);
13225 debug.nospace();
13226 debug << '[';
13227 if (const QWidget *widget = attributes.widget) {
13228 const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
13229 const QMetaEnum me = qtMo->enumerator(qtMo->indexOfEnumerator("WidgetAttribute"));
13230 int count = 0;
13231 for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
13232 if (widget->testAttribute(static_cast<Qt::WidgetAttribute>(a))) {
13233 if (count++)
13234 debug << ',';
13235 debug << me.valueToKey(a);
13236 }
13237 }
13238 }
13239 debug << ']';
13240 return debug;
13241}
13242}
13243
13244QDebug operator<<(QDebug debug, const QWidget *widget)
13245{
13246 const QDebugStateSaver saver(debug);
13247 debug.nospace();
13248 if (widget) {
13249 debug << widget->metaObject()->className() << '(' << (const void *)widget;
13250 if (!widget->objectName().isEmpty())
13251 debug << ", name=" << widget->objectName();
13252 if (debug.verbosity() > 2) {
13253 const QRect geometry = widget->geometry();
13254 const QRect frameGeometry = widget->frameGeometry();
13255 if (widget->isVisible())
13256 debug << ", visible";
13257 if (!widget->isEnabled())
13258 debug << ", disabled";
13259 debug << ", states=" << widget->windowState()
13260 << ", type=" << widget->windowType() << ", flags=" << widget->windowFlags();
13261 debug << ", attributes=" << WidgetAttributes{widget};
13262 if (widget->isWindow())
13263 debug << ", window";
13264 debug << ", " << geometry.width() << 'x' << geometry.height()
13265 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
13266 if (frameGeometry != geometry) {
13267 const QMargins margins(geometry.x() - frameGeometry.x(),
13268 geometry.y() - frameGeometry.y(),
13269 frameGeometry.right() - geometry.right(),
13270 frameGeometry.bottom() - geometry.bottom());
13271 debug << ", margins=" << margins;
13272 }
13273 debug << ", devicePixelRatio=" << widget->devicePixelRatio();
13274 if (const WId wid = widget->internalWinId())
13275 debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
13276 }
13277 debug << ')';
13278 } else {
13279 debug << "QWidget(0x0)";
13280 }
13281 return debug;
13282}
13283#endif // !QT_NO_DEBUG_STREAM
13284
13285
13286// *************************** Focus abstraction ************************************
13287
13288#define FOCUS_NEXT(w) w->d_func()->focus_next
13289#define FOCUS_PREV(w) w->d_func()->focus_prev
13290
13291/*!
13292 \internal
13293 \return next or previous element in the focus chain, depending on
13294 \param direction, irrespective of focus proxies or widgets with Qt::NoFocus.
13295 */
13296QWidget *QWidgetPrivate::nextPrevElementInFocusChain(FocusDirection direction) const
13297{
13298 Q_Q(const QWidget);
13299 return direction == FocusDirection::Next ? FOCUS_NEXT(q) : FOCUS_PREV(q);
13300}
13301
13302/*!
13303 \internal
13304 Removes a widget from the focus chain, respecting the flags set in \param rules.
13305 \list
13306 \li EnsureFocusOut: If the widget has input focus, transfer focus to the next or previous widget
13307 in the focus chain, depending on \param direction.
13308 \li RemoveInconsistent: Remove the widget, even if its focus chain is inconsistent.
13309 \li AssertConsistency: qFatal, if the focus chain is inconsistent. This is used in the QWidget destructor.
13310 \endlist
13311 \return \c true if the widget has been removed, otherwise \c false.
13312 */
13313bool QWidgetPrivate::removeFromFocusChain(FocusChainRemovalRules rules, FocusDirection direction)
13314{
13315 Q_Q(QWidget);
13316 if (!isFocusChainConsistent()) {
13317#ifdef QT_DEBUG
13318 if (rules.testFlag(FocusChainRemovalRule::AssertConsistency))
13319 qFatal() << q << "has inconsistent focus chain.";
13320#endif
13321 qCDebug(lcWidgetFocus) << q << "wasn't removed, because of inconsistent focus chain.";
13322 return false;
13323 }
13324
13325 if (!isInFocusChain()) {
13326 qCDebug(lcWidgetFocus) << q << "wasn't removed, because it is not part of a focus chain.";
13327 return false;
13328 }
13329
13330 if (rules.testFlag(FocusChainRemovalRule::EnsureFocusOut))
13331 q->focusNextPrevChild(direction == FocusDirection::Next);
13332
13335 initFocusChain();
13336 qCDebug(lcWidgetFocus) << q << "removed from focus chain.";
13337 return true;
13338}
13339
13340/*!
13341 \internal
13342 Initialises the focus chain by making the widget point to itself.
13343 */
13344void QWidgetPrivate::initFocusChain()
13345{
13346 Q_Q(QWidget);
13347 qCDebug(lcWidgetFocus) << "Initializing focus chain of" << q;
13348 FOCUS_PREV(q) = q;
13349 FOCUS_NEXT(q) = q;
13350}
13351
13352/*!
13353 \internal
13354 Reads QWidget children, which are not part of a focus chain yet.
13355 Inserts them into the focus chain before or after the widget,
13356 depending on \param direction and in the order of their creation.
13357 This is used, when QWidget::setParent() causes a widget to change toplevel windows.
13358 */
13359void QWidgetPrivate::reparentFocusChildren(FocusDirection direction)
13360{
13361 Q_Q(QWidget);
13362
13363 // separate the focus chain into new (children of myself) and old (the rest)
13364 QWidget *firstOld = nullptr;
13365 QWidget *lastOld = nullptr; // last in the old list
13366 QWidget *lastNew = q; // last in the new list
13367 bool prevWasNew = true;
13368 QWidget *widget = nextPrevElementInFocusChain(direction);
13369
13370 // For efficiency, do not maintain the list invariant inside the loop.
13371 // Append items to the relevant list, and we optimize by not changing pointers,
13372 // when subsequent items are going into the same list.
13373 while (widget != q) {
13374 bool currentIsNew = q->isAncestorOf(widget);
13375 if (currentIsNew) {
13376 if (!prevWasNew) {
13377 // previous was old => append to new list
13378 FOCUS_NEXT(lastNew) = widget;
13379 FOCUS_PREV(widget) = lastNew;
13380 }
13381 lastNew = widget;
13382 } else {
13383 if (prevWasNew) {
13384 // prev was new => append to old list, if it exists
13385 if (lastOld) {
13386 FOCUS_NEXT(lastOld) = widget;
13387 FOCUS_PREV(widget) = lastOld;
13388 } else {
13389 // start the old list
13390 firstOld = widget;
13391 }
13392 }
13393 lastOld = widget;
13394 }
13395 widget = widget->d_func()->nextPrevElementInFocusChain(direction);
13396 prevWasNew = currentIsNew;
13397 }
13398
13399 // repair old list:
13400 if (firstOld) {
13401 FOCUS_NEXT(lastOld) = firstOld;
13402 FOCUS_PREV(firstOld) = lastOld;
13403 }
13404
13405 if (!q->isWindow()) {
13406 QWidget *topLevel = q->window();
13407 // insert new chain into toplevel's chain
13408 QWidget *prev = FOCUS_PREV(topLevel);
13409 FOCUS_PREV(topLevel) = lastNew;
13410 FOCUS_NEXT(prev) = q;
13411 FOCUS_PREV(q) = prev;
13412 FOCUS_NEXT(lastNew) = topLevel;
13413 } else {
13414 // repair new list
13415 FOCUS_NEXT(lastNew) = q;
13416 FOCUS_PREV(q) = lastNew;
13417 }
13418}
13419
13420/*!
13421 \internal
13422 Inserts a widget into the focus chain before or after \param position, depending on
13423 \param direction.
13424 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13425 */
13426bool QWidgetPrivate::insertIntoFocusChain(FocusDirection direction, QWidget *position)
13427{
13428 Q_Q(QWidget);
13429 Q_ASSERT(position);
13430 QWidget *next = FOCUS_NEXT(q);
13431 QWidget *previous = FOCUS_PREV(q);
13432
13433 switch (direction) {
13434 case FocusDirection::Next:
13435 if (previous == position) {
13436 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already before" << position;
13437 return false;
13438 }
13439
13440 removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
13441
13442 FOCUS_NEXT(q) = FOCUS_NEXT(position);
13443 FOCUS_PREV(FOCUS_NEXT(position)) = q;
13444 FOCUS_NEXT(position) = q;
13445 FOCUS_PREV(q) = position;
13446 qCDebug(lcWidgetFocus) << q << "inserted after" << position;
13447 break;
13448
13449 case FocusDirection::Previous:
13450 if (next == position) {
13451 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already after" << position;
13452 return false;
13453 }
13454
13455 removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
13456
13457 FOCUS_PREV(q) = FOCUS_PREV(position);
13458 FOCUS_NEXT(FOCUS_PREV(position)) = q;
13459 FOCUS_PREV(position) = q;
13460 FOCUS_NEXT(q) = position;
13461 qCDebug(lcWidgetFocus) << q << "inserted before" << position;
13462 break;
13463 }
13464
13465 Q_ASSERT(isFocusChainConsistent());
13466 return true;
13467}
13468
13469/*!
13470 \internal
13471 Convenience override to insert a QWidgetList \param toBeInserted into the focus chain
13472 before or after \param position, depending on \param direction.
13473 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13474 \note
13475 \param toBeInserted must be a consistent focus chain.
13476 */
13477bool QWidgetPrivate::insertIntoFocusChain(const QWidgetList &toBeInserted,
13478 FocusDirection direction, QWidget *position)
13479{
13480 if (toBeInserted.isEmpty()) {
13481 qCDebug(lcWidgetFocus) << "No-op insertion of an empty list";
13482 return false;
13483 }
13484
13485 Q_ASSERT_X(!toBeInserted.contains(position),
13486 Q_FUNC_INFO,
13487 "Coding error: toBeInserted contains position");
13488
13489 QWidget *first = toBeInserted.constFirst();
13490 QWidget *last = toBeInserted.constLast();
13491
13492 // Call QWidget override to log accordingly
13493 if (toBeInserted.count() == 1)
13494 return first->d_func()->insertIntoFocusChain(direction, position);
13495
13496 Q_ASSERT(first != last);
13497 switch (direction) {
13498 case FocusDirection::Previous:
13499 if (FOCUS_PREV(position) == last) {
13500 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already before"
13501 << position;
13502 return false;
13503 }
13504 FOCUS_NEXT(FOCUS_PREV(position)) = first;
13505 FOCUS_PREV(first) = FOCUS_PREV(position);
13506 FOCUS_NEXT(last) = position;
13507 FOCUS_PREV(position) = last;
13508 qCDebug(lcWidgetFocus) << toBeInserted << "inserted before" << position;
13509 break;
13510 case FocusDirection::Next:
13511 if (FOCUS_PREV(position) == last) {
13512 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already after"
13513 << position;
13514 return false;
13515 }
13516 FOCUS_PREV(FOCUS_NEXT(position)) = last;
13517 FOCUS_NEXT(last) = FOCUS_NEXT(position);
13518 FOCUS_PREV(first) = position;
13519 FOCUS_NEXT(position) = first;
13520 qCDebug(lcWidgetFocus) << toBeInserted << "inserted after" << position;
13521 break;
13522 }
13523
13524 Q_ASSERT(position->d_func()->isFocusChainConsistent());
13525 return true;
13526}
13527
13528/*!
13529 \internal
13530 \return a QWidgetList, representing the part of the focus chain,
13531 starting with \param from and ending with \param to, in \param direction.
13532 */
13533QWidgetList focusPath(QWidget *from, QWidget *to, QWidgetPrivate::FocusDirection direction)
13534{
13535 QWidgetList path({from});
13536 if (from == to)
13537 return path;
13538
13539 QWidget *current = from;
13540 do {
13541 switch (direction) {
13542 case QWidgetPrivate::FocusDirection::Previous:
13543 current = current->previousInFocusChain();
13544 break;
13545 case QWidgetPrivate::FocusDirection::Next:
13546 current = current->nextInFocusChain();
13547 break;
13548 }
13549 if (path.contains(current))
13550 return QWidgetList();
13551 path << current;
13552 } while (current != to);
13553
13554 return path;
13555}
13556
13557/*!
13558 \internal
13559 Removes the part from the focus chain starting with \param from and ending with \param to,
13560 in \param direction.
13561 \return removed part as a QWidgetList.
13562 */
13563QWidgetList QWidgetPrivate::takeFromFocusChain(QWidget *from,
13564 QWidget *to,
13565 FocusDirection direction)
13566{
13567 // Check if there is a path from->to in direction
13568 const QWidgetList path = focusPath(from, to , direction);
13569 if (path.isEmpty()) {
13570 qCDebug(lcWidgetFocus) << "No-op removal. Focus chain from" << from << "doesn't lead to " << to;
13571 return QWidgetList();
13572 }
13573
13574 QWidget *first = path.constFirst();
13575 QWidget *last = path.constLast();
13576 if (first == last) {
13577 first->d_func()->removeFromFocusChain();
13578 return QWidgetList({first});
13579 }
13580
13581 FOCUS_NEXT(FOCUS_PREV(first)) = FOCUS_NEXT(last);
13582 FOCUS_PREV(FOCUS_NEXT(last)) = FOCUS_PREV(first);
13583 FOCUS_PREV(first) = last;
13584 FOCUS_NEXT(last) = first;
13585 qCDebug(lcWidgetFocus) << path << "removed from focus chain";
13586 return path;
13587}
13588
13589/*!
13590 \internal
13591 \return The last focus child of the widget, traversing the focus chain no further than
13592 \param noFurtherThan.
13593 */
13594QWidget *QWidgetPrivate::determineLastFocusChild(QWidget *noFurtherThan)
13595{
13596 Q_Q(QWidget);
13597 // Since we need to repeat the same logic for both 'first' and 'second', we add a function
13598 // that determines the last focus child for a widget, taking proxies and compound widgets into
13599 // account. If the target is not a compound widget (it doesn't have a focus proxy that points
13600 // to a child), 'lastFocusChild' will be set to the target itself.
13601 QWidget *lastFocusChild = q;
13602
13603 QWidget *focusProxy = deepestFocusProxy();
13604 if (!focusProxy) {
13605 // QTBUG-81097: Another case is possible here. We can have a child
13606 // widget, that sets its focusProxy() to the parent (target).
13607 // An example of such widget is a QLineEdit, nested into
13608 // a QAbstractSpinBox. In this case such widget should be considered
13609 // the last focus child.
13610 for (auto *object : std::as_const(q->children())) {
13611 QWidget *w = qobject_cast<QWidget *>(object);
13612 if (w && w->focusProxy() == q) {
13613 lastFocusChild = w;
13614 break;
13615 }
13616 }
13617 } else if (q->isAncestorOf(focusProxy)) {
13618 lastFocusChild = focusProxy;
13619 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
13620 focusNext != focusProxy && q->isAncestorOf(focusNext)
13621 && focusNext->window() == focusProxy->window();
13622 focusNext = focusNext->nextInFocusChain()) {
13623 if (focusNext == noFurtherThan)
13624 break;
13625 if (focusNext->focusPolicy() != Qt::NoFocus)
13626 lastFocusChild = focusNext;
13627 }
13628 }
13629 return lastFocusChild;
13630};
13631
13632/*!
13633 \internal
13634 \return \c true, if the widget is part of a focus chain and \c false otherwise.
13635 A widget is considered to be part of a focus chain, neither FOCUS_NEXT, nor FOCUS_PREV
13636 are pointing to the widget itself.
13637
13638 \note
13639 This method doesn't check the consistency of the focus chain.
13640 If multiple widgets have been removed from the focus chain by takeFromFocusChain(),
13641 isInFocusChain() will return \c true for all of those widgets, even if they represent
13642 an inconsistent focus chain.
13643 */
13644bool QWidgetPrivate::isInFocusChain() const
13645{
13646 Q_Q(const QWidget);
13647 return !(FOCUS_NEXT(q) == q && FOCUS_PREV(q) == q);
13648}
13649
13650/*!
13651 \internal
13652 A focus chain is consistent, when it is circular: Following the chain in either direction
13653 has to return to the beginning. This is why a newly constructed widget points to itself,
13654 when the focus chain has been initialized. A newly constructed widget is considered to have
13655 a consistent focus chain, while not being part of a focus chain.
13656
13657 The method always returns \c true, when the logging category "qt.widgets.focus" is disabled.
13658 When it is enabled, the method returns \c true early, if a widget is pointing to itself.
13659 It returns \c false, if one of the following is detected:
13660 \list
13661 \li nullptr found in a previous/next pointer.
13662 \li broken chain: widget A is B's previous, but B isn't A's next.
13663 \li chain isn't closed: starting at A doesn't lead back to A.
13664 \endlist
13665 It return \c true, if none of the above is observed.
13666
13667 \note
13668 The focus chain is checked only in forward direction.
13669 This is sufficient, because the check for a broken chain asserts consistent paths
13670 in both directions.
13671 */
13672bool QWidgetPrivate::isFocusChainConsistent() const
13673{
13674 Q_Q(const QWidget);
13675 const bool skip = !lcWidgetFocus().isDebugEnabled();
13676 if (skip)
13677 return true;
13678
13679 if (!isInFocusChain())
13680 return true;
13681
13682 const QWidget *position = q;
13683
13684 for (int i = 0; i < QApplication::allWidgets().count(); ++i) {
13685 if (!FOCUS_PREV(position) || !FOCUS_NEXT(position)) {
13686 qCDebug(lcWidgetFocus) << "Nullptr found at:" << position
13687 << "Previous pointing to" << FOCUS_PREV(position)
13688 << "Next pointing to" << FOCUS_NEXT(position);
13689 return false;
13690 }
13691 if (!(FOCUS_PREV(FOCUS_NEXT(position)) == position
13692 && FOCUS_NEXT(FOCUS_PREV(position)) == position)) {
13693 qCDebug(lcWidgetFocus) << "Inconsistent focus chain at:" << position
13694 << "Previous pointing to" << FOCUS_PREV(FOCUS_NEXT(position))
13695 << "Next pointing to" << FOCUS_NEXT(FOCUS_PREV(position));
13696 return false;
13697 }
13698 position = FOCUS_NEXT(position);
13699 if (position == q)
13700 return true;
13701
13702 }
13703
13704 qCDebug(lcWidgetFocus) << "Focus chain leading from" << q << "to" << position << "is not closed.";
13705 return false;
13706}
13707
13708#undef FOCUS_NEXT
13709#undef FOCUS_PREV
13710
13711
13712QT_END_NAMESPACE
13713
13714#include "moc_qwidget.cpp"
13715#include "moc_qwidget_p.cpp"
friend class QWidgetPrivate
friend class QWidget
Definition qpainter.h:432
\inmodule QtWidgets
Definition qwidget_p.h:184
void qt_qpa_set_cursor(QWidget *w, bool force)
Definition qwidget.cpp:5041
#define qApp
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
static bool canMapPosition(QWindow *window)
static void unsetCursor(QWidget *w)
Definition qwidget.cpp:5035
void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
Definition qwidget.cpp:1200
QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
Returns a modified window title with the [*] place holder replaced according to the rules described i...
Definition qwidget.cpp:6019
static void sendResizeEvents(QWidget *target)
Definition qwidget.cpp:5215
static void applyCursor(QWidget *w, const QCursor &c)
Definition qwidget.cpp:5029
#define FOCUS_PREV(w)
static bool isEmbedded(const QWindow *w)
Definition qwidget.cpp:6663
static void releaseMouseGrabOfWidget(QWidget *widget)
#define FOCUS_NEXT(w)
static void grabMouseForWidget(QWidget *widget, const QCursor *cursor=nullptr)
QWidget * qt_button_down
Definition qwidget.cpp:2304
static MapToGlobalTransformResult mapToGlobalTransform(const QWidget *w)
static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data, QWidgetPrivate *d)
void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType)
static bool qRectIntersects(const QRect &r1, const QRect &r2)
Definition qwidget.cpp:95
bool qt_sendSpontaneousEvent(QObject *, QEvent *)
QWidgetList focusPath(QWidget *from, QWidget *to, QWidgetPrivate::FocusDirection direction)
bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
Definition qwidget.cpp:1069
static QWidget * keyboardGrb
QWidget * qt_mouseGrb
static bool mouseGrabWithCursor
static QWindow * grabberWindow(const QWidget *w)
static void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
Definition qwidget.cpp:2223
static bool q_evaluateRhiConfigRecursive(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
Definition qwidget.cpp:1043
#define QWIDGETSIZE_MAX
Definition qwidget.h:917
static void cleanup(QWidget *that, QWidgetPrivate *d)
Definition qwidget.cpp:754