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 Setting a style sheet on a widget makes the widget and its children use a
2541 style sheet style that wraps the current \l{style()}{style}. For when to
2542 use style sheets, see \l{Styling Approaches for Qt Widgets}.
2543
2544 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets},
2545 {Styling Approaches for Qt Widgets}
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 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2625*/
2626
2627void QWidget::setStyle(QStyle *style)
2628{
2629 Q_D(QWidget);
2630 setAttribute(Qt::WA_SetStyle, style != nullptr);
2631 d->createExtra();
2632#if QT_CONFIG(style_stylesheet)
2633 if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2634 //if for some reason someone try to set a QStyleSheetStyle, ref it
2635 //(this may happen for example in QButtonDialogBox which propagates its style)
2636 styleSheetStyle->ref();
2637 d->setStyle_helper(style, false);
2638 } else if (qt_styleSheet(d->extra->style) || !qApp->styleSheet().isEmpty()) {
2639 // if we have an application stylesheet or have a proxy already, propagate
2640 d->setStyle_helper(new QStyleSheetStyle(style), true);
2641 } else
2642#endif
2643 d->setStyle_helper(style, false);
2644}
2645
2646void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2647{
2648 Q_Q(QWidget);
2649 QStyle *oldStyle = q->style();
2650
2651 createExtra();
2652
2653#if QT_CONFIG(style_stylesheet)
2654 QPointer<QStyle> origStyle = extra->style;
2655#endif
2656 extra->style = newStyle;
2657
2658 // repolish
2659 if (polished) {
2660 oldStyle->unpolish(q);
2661 q->style()->polish(q);
2662 }
2663
2664 if (propagate) {
2665 // We copy the list because the order may be modified
2666 const QObjectList childrenList = children;
2667 for (int i = 0; i < childrenList.size(); ++i) {
2668 QWidget *c = qobject_cast<QWidget*>(childrenList.at(i));
2669 if (c)
2670 c->d_func()->inheritStyle();
2671 }
2672 }
2673
2674#if QT_CONFIG(style_stylesheet)
2675 if (!qt_styleSheet(newStyle)) {
2676 if (const QStyleSheetStyle* cssStyle = qt_styleSheet(origStyle)) {
2677 cssStyle->clearWidgetFont(q);
2678 }
2679 }
2680#endif
2681
2682 QEvent e(QEvent::StyleChange);
2683 QCoreApplication::sendEvent(q, &e);
2684
2685#if QT_CONFIG(style_stylesheet)
2686 // dereference the old stylesheet style
2687 if (QStyleSheetStyle *proxy = qt_styleSheet(origStyle))
2688 proxy->deref();
2689#endif
2690}
2691
2692// Inherits style from the current parent and propagates it as necessary
2693void QWidgetPrivate::inheritStyle()
2694{
2695#if QT_CONFIG(style_stylesheet)
2696 Q_Q(QWidget);
2697
2698 QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2699
2700 QStyleSheetStyle *proxy = qt_styleSheet(extraStyle);
2701
2702 if (!q->styleSheet().isEmpty()) {
2703 Q_ASSERT(proxy);
2704 proxy->repolish(q);
2705 return;
2706 }
2707 if (inheritStyleRecursionGuard)
2708 return;
2709 inheritStyleRecursionGuard = true;
2710 const auto resetGuard = qScopeGuard([&]() {
2711 inheritStyleRecursionGuard = false;
2712 });
2713
2714 QStyle *origStyle = proxy ? proxy->base : extraStyle;
2715 QWidget *parent = q->parentWidget();
2716 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : nullptr;
2717 // If we have stylesheet on app or parent has stylesheet style, we need
2718 // to be running a proxy
2719 if (!qApp->styleSheet().isEmpty() || qt_styleSheet(parentStyle)) {
2720 QStyle *newStyle = parentStyle;
2721 if (q->testAttribute(Qt::WA_SetStyle) && qt_styleSheet(origStyle) == nullptr)
2722 newStyle = new QStyleSheetStyle(origStyle);
2723 else if (auto *styleSheetStyle = qt_styleSheet(origStyle))
2724 newStyle = styleSheetStyle;
2725 else if (QStyleSheetStyle *newProxy = qt_styleSheet(parentStyle))
2726 newProxy->ref();
2727
2728 setStyle_helper(newStyle, true);
2729 return;
2730 }
2731
2732 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2733 // we just need our original style back
2734 if (origStyle == extraStyle) // is it any different?
2735 return;
2736
2737 // We could have inherited the proxy from our parent (which has a custom style)
2738 // In such a case we need to start following the application style (i.e revert
2739 // the propagation behavior of QStyleSheetStyle)
2740 if (!q->testAttribute(Qt::WA_SetStyle))
2741 origStyle = nullptr;
2742
2743 setStyle_helper(origStyle, true);
2744#endif // QT_NO_STYLE_STYLESHEET
2745}
2746
2747
2748/*!
2749 \fn bool QWidget::isWindow() const
2750
2751 Returns \c true if the widget is an independent window, otherwise
2752 returns \c false.
2753
2754 A window is a widget that isn't visually the child of any other
2755 widget and that usually has a frame and a
2756 \l{QWidget::setWindowTitle()}{window title}.
2757
2758 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2759 It will then be grouped with its parent and deleted when the
2760 parent is deleted, minimized when the parent is minimized etc. If
2761 supported by the window manager, it will also have a common
2762 taskbar entry with its parent.
2763
2764 QDialog and QMainWindow widgets are by default windows, even if a
2765 parent widget is specified in the constructor. This behavior is
2766 specified by the Qt::Window flag.
2767
2768 \sa window(), isModal(), parentWidget()
2769*/
2770
2771/*!
2772 \property QWidget::modal
2773 \brief whether the widget is a modal widget
2774
2775 This property only makes sense for windows. A modal widget
2776 prevents widgets in all other windows from getting any input.
2777
2778 By default, this property is \c false.
2779
2780 \sa isWindow(), windowModality, QDialog
2781*/
2782
2783/*!
2784 \property QWidget::windowModality
2785 \brief which windows are blocked by the modal widget
2786 \since 4.1
2787
2788 This property only makes sense for windows. A modal widget
2789 prevents widgets in other windows from getting input. The value of
2790 this property controls which windows are blocked when the widget
2791 is visible. Changing this property while the window is visible has
2792 no effect; you must hide() the widget first, then show() it again.
2793
2794 By default, this property is Qt::NonModal.
2795
2796 \sa isWindow(), QWidget::modal, QDialog
2797*/
2798
2799Qt::WindowModality QWidget::windowModality() const
2800{
2801 return static_cast<Qt::WindowModality>(data->window_modality);
2802}
2803
2804void QWidget::setWindowModality(Qt::WindowModality windowModality)
2805{
2806 data->window_modality = windowModality;
2807 // setModal_sys() will be called by setAttribute()
2808 setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
2809 setAttribute(Qt::WA_SetWindowModality, true);
2810}
2811
2812void QWidgetPrivate::setModal_sys()
2813{
2814 Q_Q(QWidget);
2815 if (q->windowHandle())
2816 q->windowHandle()->setModality(q->windowModality());
2817}
2818
2819/*!
2820 \fn bool QWidget::underMouse() const
2821
2822 Returns \c true if the widget is under the mouse cursor; otherwise
2823 returns \c false.
2824
2825 This value is not updated properly during drag and drop
2826 operations.
2827
2828 \sa enterEvent(), leaveEvent()
2829*/
2830
2831/*!
2832 \property QWidget::minimized
2833 \brief whether this widget is minimized (iconified)
2834
2835 This property is only relevant for windows.
2836
2837 By default, this property is \c false.
2838
2839 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2840*/
2841bool QWidget::isMinimized() const
2842{ return data->window_state & Qt::WindowMinimized; }
2843
2844/*!
2845 Shows the widget minimized, as an icon.
2846
2847 Calling this function only affects \l{isWindow()}{windows}.
2848
2849 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2850 isMinimized()
2851*/
2852void QWidget::showMinimized()
2853{
2854 bool isMin = isMinimized();
2855 if (isMin && isVisible())
2856 return;
2857
2858 ensurePolished();
2859
2860 if (!isMin)
2861 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2862 setVisible(true);
2863}
2864
2865/*!
2866 \property QWidget::maximized
2867 \brief whether this widget is maximized
2868
2869 This property is only relevant for windows.
2870
2871 \note Due to limitations on some window systems, this does not always
2872 report the expected results (e.g., if the user on X11 maximizes the
2873 window via the window manager, Qt has no way of distinguishing this
2874 from any other resize). This is expected to improve as window manager
2875 protocols evolve.
2876
2877 By default, this property is \c false.
2878
2879 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2880*/
2881bool QWidget::isMaximized() const
2882{ return data->window_state & Qt::WindowMaximized; }
2883
2884
2885
2886/*!
2887 Returns the current window state. The window state is a OR'ed
2888 combination of Qt::WindowState: Qt::WindowMinimized,
2889 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2890
2891 \sa Qt::WindowState, setWindowState()
2892 */
2893Qt::WindowStates QWidget::windowState() const
2894{
2895 return Qt::WindowStates(data->window_state);
2896}
2897
2898/*!\internal
2899
2900 The function sets the window state on child widgets similar to
2901 setWindowState(). The difference is that the window state changed
2902 event has the isOverride() flag set. It exists mainly to keep
2903 QWorkspace working.
2904 */
2905void QWidget::overrideWindowState(Qt::WindowStates newstate)
2906{
2907 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
2908 data->window_state = newstate;
2909 QCoreApplication::sendEvent(this, &e);
2910}
2911
2912/*!
2913 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
2914
2915 Sets the window state to \a windowState. The window state is a OR'ed
2916 combination of Qt::WindowState: Qt::WindowMinimized,
2917 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2918
2919 If the window is not visible (i.e. isVisible() returns \c false), the
2920 window state will take effect when show() is called. For visible
2921 windows, the change is immediate. For example, to toggle between
2922 full-screen and normal mode, use the following code:
2923
2924 \snippet code/src_gui_kernel_qwidget.cpp 0
2925
2926 To restore and activate a minimized window (while
2927 preserving its maximized and/or full-screen state), use the following:
2928
2929 \snippet code/src_gui_kernel_qwidget.cpp 1
2930
2931 Calling this function will hide the widget. You must call show() to make
2932 the widget visible again.
2933
2934 \note On some window systems Qt::WindowActive is not immediate, and may be
2935 ignored in certain cases.
2936
2937 When the window state changes, the widget receives a changeEvent()
2938 of type QEvent::WindowStateChange.
2939
2940 \sa Qt::WindowState, windowState()
2941*/
2942void QWidget::setWindowState(Qt::WindowStates newstate)
2943{
2944 Q_D(QWidget);
2945 Qt::WindowStates oldstate = windowState();
2946 if (newstate.testFlag(Qt::WindowMinimized)) // QTBUG-46763
2947 newstate.setFlag(Qt::WindowActive, false);
2948 if (oldstate == newstate)
2949 return;
2950 if (isWindow() && !testAttribute(Qt::WA_WState_Created))
2951 create();
2952
2953 data->window_state = newstate;
2954 data->in_set_window_state = 1;
2955 if (isWindow()) {
2956 // Ensure the initial size is valid, since we store it as normalGeometry below.
2957 if (!testAttribute(Qt::WA_Resized) && !isVisible())
2958 adjustSize();
2959
2960 d->createTLExtra();
2961 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
2962 d->topData()->normalGeometry = geometry();
2963
2964 Q_ASSERT(windowHandle());
2965 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
2966 }
2967 data->in_set_window_state = 0;
2968
2969 if (newstate & Qt::WindowActive)
2970 activateWindow();
2971
2972 QWindowStateChangeEvent e(oldstate);
2973 QCoreApplication::sendEvent(this, &e);
2974}
2975
2976/*!
2977 \property QWidget::fullScreen
2978 \brief whether the widget is shown in full screen mode
2979
2980 A widget in full screen mode occupies the whole screen area and does not
2981 display window decorations, such as a title bar.
2982
2983 By default, this property is \c false.
2984
2985 \sa windowState(), minimized, maximized
2986*/
2987bool QWidget::isFullScreen() const
2988{ return data->window_state & Qt::WindowFullScreen; }
2989
2990/*!
2991 Shows the widget in full-screen mode.
2992
2993 Calling this function only affects \l{isWindow()}{windows}.
2994
2995 To return from full-screen mode, call showNormal() or close().
2996
2997 \note Full-screen mode works fine under Windows, but has certain
2998 problems under X. These problems are due to limitations of the
2999 ICCCM protocol that specifies the communication between X11
3000 clients and the window manager. ICCCM simply does not understand
3001 the concept of non-decorated full-screen windows. Therefore, the
3002 best you can do is to request a borderless window and place and
3003 resize it to fill the entire screen. Depending on the window
3004 manager, this may or may not work. The borderless window is
3005 requested using MOTIF hints, which are at least partially
3006 supported by virtually all modern window managers.
3007
3008 An alternative would be to bypass the window manager entirely and
3009 create a window with the Qt::X11BypassWindowManagerHint flag. This
3010 has other severe problems though, like broken keyboard focus
3011 and very strange effects on desktop changes or when the user raises
3012 other windows.
3013
3014 X11 window managers that follow modern post-ICCCM specifications
3015 support full-screen mode properly.
3016
3017 On macOS, showing a window full screen puts the entire application in
3018 full-screen mode, providing it with a dedicated desktop. Showing another
3019 window while the application runs in full-screen mode might automatically
3020 make that window full screen as well. To prevent that, exit full-screen
3021 mode by calling showNormal() or by close() on the full screen window
3022 before showing another window.
3023
3024 \sa showNormal(), showMaximized(), show(), isVisible(), close()
3025*/
3026void QWidget::showFullScreen()
3027{
3028 ensurePolished();
3029
3030 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
3031 | Qt::WindowFullScreen);
3032 setVisible(true);
3033#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
3034 // activating it here before libscreen activates it causes problems
3035 activateWindow();
3036#endif
3037}
3038
3039/*!
3040 Shows the widget maximized.
3041
3042 Calling this function only affects \l{isWindow()}{windows}.
3043
3044 On X11, this function may not work properly with certain window
3045 managers. See the \l{Window Geometry} documentation for an explanation.
3046
3047 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3048*/
3049void QWidget::showMaximized()
3050{
3051 ensurePolished();
3052
3053 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3054 | Qt::WindowMaximized);
3055 setVisible(true);
3056}
3057
3058/*!
3059 Restores the widget after it has been maximized or minimized.
3060
3061 Calling this function only affects \l{isWindow()}{windows}.
3062
3063 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3064*/
3065void QWidget::showNormal()
3066{
3067 ensurePolished();
3068
3069 setWindowState(windowState() & ~(Qt::WindowMinimized
3070 | Qt::WindowMaximized
3071 | Qt::WindowFullScreen));
3072 setVisible(true);
3073}
3074
3075/*!
3076 Returns \c true if this widget would become enabled if \a ancestor is
3077 enabled; otherwise returns \c false.
3078
3079
3080
3081 This is the case if neither the widget itself nor every parent up
3082 to but excluding \a ancestor has been explicitly disabled.
3083
3084 isEnabledTo(0) returns false if this widget or any if its ancestors
3085 was explicitly disabled.
3086
3087 The word ancestor here means a parent widget within the same window.
3088
3089 Therefore isEnabledTo(0) stops at this widget's window, unlike
3090 isEnabled() which also takes parent windows into considerations.
3091
3092 \sa setEnabled(), enabled
3093*/
3094
3095bool QWidget::isEnabledTo(const QWidget *ancestor) const
3096{
3097 const QWidget * w = this;
3098 while (!w->testAttribute(Qt::WA_ForceDisabled)
3099 && !w->isWindow()
3100 && w->parentWidget()
3101 && w->parentWidget() != ancestor)
3102 w = w->parentWidget();
3103 return !w->testAttribute(Qt::WA_ForceDisabled);
3104}
3105
3106#ifndef QT_NO_ACTION
3107/*!
3108 Appends the action \a action to this widget's list of actions.
3109
3110 All QWidgets have a list of \l{QAction}s. However, they can be
3111 represented graphically in many different ways. The default use of
3112 the QAction list (as returned by actions()) is to create a context
3113 QMenu.
3114
3115 A QWidget should only have one of each action and adding an action
3116 it already has will not cause the same action to be in the widget twice.
3117
3118 The ownership of \a action is not transferred to this QWidget.
3119
3120 \sa removeAction(), insertAction(), actions(), QMenu
3121*/
3122void QWidget::addAction(QAction *action)
3123{
3124 insertAction(nullptr, action);
3125}
3126
3127/*!
3128 Appends the actions \a actions to this widget's list of actions.
3129
3130 \sa removeAction(), QMenu, addAction()
3131*/
3132void QWidget::addActions(const QList<QAction *> &actions)
3133{
3134 for(int i = 0; i < actions.size(); i++)
3135 insertAction(nullptr, actions.at(i));
3136}
3137
3138/*!
3139 Inserts the action \a action to this widget's list of actions,
3140 before the action \a before. It appends the action if \a before is \nullptr or
3141 \a before is not a valid action for this widget.
3142
3143 A QWidget should only have one of each action.
3144
3145 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3146*/
3147void QWidget::insertAction(QAction *before, QAction *action)
3148{
3149 if (Q_UNLIKELY(!action)) {
3150 qWarning("QWidget::insertAction: Attempt to insert null action");
3151 return;
3152 }
3153
3154 Q_D(QWidget);
3155 if (d->actions.contains(action))
3156 removeAction(action);
3157
3158 int pos = d->actions.indexOf(before);
3159 if (pos < 0) {
3160 before = nullptr;
3161 pos = d->actions.size();
3162 }
3163 d->actions.insert(pos, action);
3164
3165 QActionPrivate *apriv = action->d_func();
3166 apriv->associatedObjects.append(this);
3167
3168 QActionEvent e(QEvent::ActionAdded, action, before);
3169 QCoreApplication::sendEvent(this, &e);
3170}
3171
3172/*!
3173 Inserts the actions \a actions to this widget's list of actions,
3174 before the action \a before. It appends the action if \a before is \nullptr or
3175 \a before is not a valid action for this widget.
3176
3177 A QWidget can have at most one of each action.
3178
3179 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3180*/
3181void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3182{
3183 for(int i = 0; i < actions.size(); ++i)
3184 insertAction(before, actions.at(i));
3185}
3186
3187/*!
3188 Removes the action \a action from this widget's list of actions.
3189 \sa insertAction(), actions()
3190*/
3191void QWidget::removeAction(QAction *action)
3192{
3193 if (!action)
3194 return;
3195
3196 Q_D(QWidget);
3197
3198 QActionPrivate *apriv = action->d_func();
3199 apriv->associatedObjects.removeAll(this);
3200
3201 if (d->actions.removeAll(action)) {
3202 QActionEvent e(QEvent::ActionRemoved, action);
3203 QCoreApplication::sendEvent(this, &e);
3204 }
3205}
3206
3207/*!
3208 Returns the (possibly empty) list of this widget's actions.
3209
3210 \sa contextMenuPolicy, insertAction(), removeAction()
3211*/
3212QList<QAction*> QWidget::actions() const
3213{
3214 Q_D(const QWidget);
3215 return d->actions;
3216}
3217
3218/*!
3219 \fn QAction *QWidget::addAction(const QString &text);
3220 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut);
3221 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text);
3222 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut);
3223
3224 \since 6.3
3225
3226 These convenience functions create a new action with text \a text,
3227 icon \a icon and shortcut \a shortcut, if any.
3228
3229 The functions add the newly created action to the widget's
3230 list of actions, and return it.
3231
3232 QWidget takes ownership of the returned QAction.
3233*/
3234QAction *QWidget::addAction(const QString &text)
3235{
3236 QAction *ret = new QAction(text, this);
3237 addAction(ret);
3238 return ret;
3239}
3240
3241QAction *QWidget::addAction(const QIcon &icon, const QString &text)
3242{
3243 QAction *ret = new QAction(icon, text, this);
3244 addAction(ret);
3245 return ret;
3246}
3247
3248#if QT_CONFIG(shortcut)
3249QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut)
3250{
3251 QAction *ret = addAction(text);
3252 ret->setShortcut(shortcut);
3253 return ret;
3254}
3255
3256QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut)
3257{
3258 QAction *ret = addAction(icon, text);
3259 ret->setShortcut(shortcut);
3260 return ret;
3261}
3262#endif
3263
3264/*!
3265 \fn QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3266 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3267 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3268 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3269
3270 \overload
3271 \since 6.3
3272
3273 This convenience function creates a new action with the text \a
3274 text, icon \a icon, and shortcut \a shortcut, if any.
3275
3276 The action's \l{QAction::triggered()}{triggered()} signal is connected
3277 to the \a receiver's \a member slot. The function adds the newly created
3278 action to the widget's list of actions and returns it.
3279
3280 QWidget takes ownership of the returned QAction.
3281*/
3282QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member,
3283 Qt::ConnectionType type)
3284{
3285 QAction *action = addAction(text);
3286 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member, type);
3287 return action;
3288}
3289
3290QAction *QWidget::addAction(const QIcon &icon, const QString &text,
3291 const QObject *receiver, const char* member,
3292 Qt::ConnectionType type)
3293{
3294 QAction *action = addAction(icon, text);
3295 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member, type);
3296 return action;
3297}
3298
3299#if QT_CONFIG(shortcut)
3300QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut,
3301 const QObject *receiver, const char* member,
3302 Qt::ConnectionType type)
3303{
3304 QAction *action = addAction(text, receiver, member, type);
3305 action->setShortcut(shortcut);
3306 return action;
3307}
3308
3309QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut,
3310 const QObject *receiver, const char* member,
3311 Qt::ConnectionType type)
3312{
3313 QAction *action = addAction(icon, text, receiver, member, type);
3314 action->setShortcut(shortcut);
3315 return action;
3316}
3317#endif // QT_CONFIG(shortcut)
3318
3319/*!
3320 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, Args&&...args)
3321 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, Args&&...args)
3322 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, Args&&...args)
3323 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, Args&&...args)
3324
3325 \since 6.3
3326 \overload
3327
3328 These convenience functions create a new action with the text \a text,
3329 icon \a icon, and shortcut \a shortcut, if any.
3330
3331 The action's \l{QAction::triggered()}{triggered()} signal is connected
3332 as if by a call to QObject::connect(action, &QAction::triggered, args...),
3333 perfectly forwarding \a args, including a possible Qt::ConnectionType.
3334
3335 The function adds the newly created action to the widget's list of
3336 actions and returns it.
3337
3338 QWidget takes ownership of the returned QAction.
3339*/
3340#endif // QT_NO_ACTION
3341
3342/*!
3343 \property QWidget::enabled
3344 \brief whether the widget is enabled
3345
3346 In general an enabled widget handles keyboard and mouse events; a disabled
3347 widget does not. An exception is made with \l{QAbstractButton}.
3348
3349 Some widgets display themselves differently when they are
3350 disabled. For example a button might draw its label grayed out. If
3351 your widget needs to know when it becomes enabled or disabled, you
3352 can use the changeEvent() with type QEvent::EnabledChange.
3353
3354 Disabling a widget implicitly disables all its children. Enabling
3355 respectively enables all child widgets unless they have been
3356 explicitly disabled. It it not possible to explicitly enable a child
3357 widget which is not a window while its parent widget remains disabled.
3358
3359 By default, this property is \c true.
3360
3361 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3362*/
3363void QWidget::setEnabled(bool enable)
3364{
3365 Q_D(QWidget);
3366
3367#if QT_CONFIG(accessibility)
3368 const bool wasEnabled = !testAttribute(Qt::WA_ForceDisabled);
3369#endif
3370
3371 setAttribute(Qt::WA_ForceDisabled, !enable);
3372 d->setEnabled_helper(enable);
3373
3374#if QT_CONFIG(accessibility)
3375 // A widget is enabled if it's parent and itself is enabled.
3376 // We do not send state changed events recursively. It is up
3377 // to the receiver of the events to check children if required.
3378 if (QAccessible::isActive() && wasEnabled != enable) {
3379 QAccessible::State states;
3380 states.disabled = 1;
3381 QAccessibleStateChangeEvent scEvent(this, states);
3382 QAccessible::updateAccessibility(&scEvent);
3383 }
3384#endif
3385}
3386
3387void QWidgetPrivate::setEnabled_helper(bool enable)
3388{
3389 Q_Q(QWidget);
3390
3391 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->isEnabled())
3392 return; // nothing we can do
3393
3394 if (enable != q->testAttribute(Qt::WA_Disabled))
3395 return; // nothing to do
3396
3397 q->setAttribute(Qt::WA_Disabled, !enable);
3398 updateSystemBackground();
3399
3400 if (!enable && q->window()->focusWidget() == q) {
3401 bool parentIsEnabled = (!q->parentWidget() || q->parentWidget()->isEnabled());
3402 if (!parentIsEnabled || !q->focusNextChild())
3403 q->clearFocus();
3404 }
3405
3406 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceDisabled : Qt::WA_Disabled;
3407 for (int i = 0; i < children.size(); ++i) {
3408 QWidget *w = qobject_cast<QWidget *>(children.at(i));
3409 if (w && !w->testAttribute(attribute))
3410 w->d_func()->setEnabled_helper(enable);
3411 }
3412#ifndef QT_NO_CURSOR
3413 if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) {
3414 // enforce the windows behavior of clearing the cursor on
3415 // disabled widgets
3416 qt_qpa_set_cursor(q, false);
3417 }
3418#endif
3419#ifndef QT_NO_IM
3420 if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3421 QWidget *focusWidget = effectiveFocusWidget();
3422
3423 if (enable) {
3424 if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
3425 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3426 } else {
3427 QGuiApplication::inputMethod()->commit();
3428 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
3429 }
3430 }
3431#endif //QT_NO_IM
3432 QEvent e(QEvent::EnabledChange);
3433 QCoreApplication::sendEvent(q, &e);
3434}
3435
3436/*!
3437 \property QWidget::acceptDrops
3438 \brief whether drop events are enabled for this widget
3439
3440 Setting this property to true announces to the system that this
3441 widget \e may be able to accept drop events.
3442
3443 \warning Do not modify this property in a drag and drop event handler.
3444
3445 By default, this property is \c false.
3446
3447 \sa {Drag and Drop in Qt}{Drag and Drop}
3448*/
3449bool QWidget::acceptDrops() const
3450{
3451 return testAttribute(Qt::WA_AcceptDrops);
3452}
3453
3454void QWidget::setAcceptDrops(bool on)
3455{
3456 setAttribute(Qt::WA_AcceptDrops, on);
3457
3458}
3459
3460/*!
3461 Disables widget input events if \a disable is true; otherwise
3462 enables input events.
3463
3464 See the \l enabled documentation for more information.
3465
3466 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3467*/
3468void QWidget::setDisabled(bool disable)
3469{
3470 setEnabled(!disable);
3471}
3472
3473/*!
3474 \property QWidget::frameGeometry
3475 \brief geometry of the widget relative to its parent including any
3476 window frame
3477
3478 See the \l{Window Geometry} documentation for an overview of geometry
3479 issues with windows.
3480
3481 By default, this property contains a value that depends on the user's
3482 platform and screen geometry.
3483
3484 \sa geometry(), x(), y(), pos()
3485*/
3486QRect QWidget::frameGeometry() const
3487{
3488 Q_D(const QWidget);
3489 if (isWindow() && ! (windowType() == Qt::Popup)) {
3490 QRect fs = d->frameStrut();
3491 return QRect(data->crect.x() - fs.left(),
3492 data->crect.y() - fs.top(),
3493 data->crect.width() + fs.left() + fs.right(),
3494 data->crect.height() + fs.top() + fs.bottom());
3495 }
3496 return data->crect;
3497}
3498
3499/*!
3500 \property QWidget::x
3501
3502 \brief the x coordinate of the widget relative to its parent including
3503 any window frame
3504
3505 See the \l{Window Geometry} documentation for an overview of geometry
3506 issues with windows.
3507
3508 By default, this property has a value of 0.
3509
3510 \sa frameGeometry, y, pos
3511*/
3512int QWidget::x() const
3513{
3514 Q_D(const QWidget);
3515 if (isWindow() && ! (windowType() == Qt::Popup))
3516 return data->crect.x() - d->frameStrut().left();
3517 return data->crect.x();
3518}
3519
3520/*!
3521 \property QWidget::y
3522 \brief the y coordinate of the widget relative to its parent and
3523 including any window frame
3524
3525 See the \l{Window Geometry} documentation for an overview of geometry
3526 issues with windows.
3527
3528 By default, this property has a value of 0.
3529
3530 \sa frameGeometry, x, pos
3531*/
3532int QWidget::y() const
3533{
3534 Q_D(const QWidget);
3535 if (isWindow() && ! (windowType() == Qt::Popup))
3536 return data->crect.y() - d->frameStrut().top();
3537 return data->crect.y();
3538}
3539
3540/*!
3541 \property QWidget::pos
3542 \brief the position of the widget within its parent widget
3543
3544 If the widget is a window, the position is that of the widget on
3545 the desktop, including its frame.
3546
3547 When changing the position, the widget, if visible, receives a
3548 move event (moveEvent()) immediately. If the widget is not
3549 currently visible, it is guaranteed to receive an event before it
3550 is shown.
3551
3552 By default, this property contains a position that refers to the
3553 origin.
3554
3555 \warning Calling move() or setGeometry() inside moveEvent() can
3556 lead to infinite recursion.
3557
3558 See the \l{Window Geometry} documentation for an overview of geometry
3559 issues with windows.
3560
3561 \note Not all windowing systems support setting or querying top level window positions.
3562 On such a system, programmatically moving windows may not have any effect, and artificial
3563 values may be returned for the current positions, such as \c QPoint(0, 0).
3564
3565 \sa frameGeometry, size, x(), y()
3566*/
3567QPoint QWidget::pos() const
3568{
3569 Q_D(const QWidget);
3570 QPoint result = data->crect.topLeft();
3571 if (isWindow() && ! (windowType() == Qt::Popup))
3572 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3573 result -= d->frameStrut().topLeft();
3574 return result;
3575}
3576
3577/*!
3578 \property QWidget::geometry
3579 \brief the geometry of the widget relative to its parent and
3580 excluding the window frame
3581
3582 If the widget is a top-level widget (a window) its geometry is
3583 given in global screen coordinates.
3584
3585 When changing the geometry, the widget, if visible, receives a
3586 move event (moveEvent()) and/or a resize event (resizeEvent())
3587 immediately. If the widget is not currently visible, it is
3588 guaranteed to receive appropriate events before it is shown.
3589
3590 The size component is adjusted if it lies outside the range
3591 defined by minimumSize() and maximumSize().
3592
3593 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3594 can lead to infinite recursion.
3595
3596 See the \l{Window Geometry} documentation for an overview of geometry
3597 issues with windows.
3598
3599 By default, this property contains a value that depends on the user's
3600 platform and screen geometry.
3601
3602 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3603 resizeEvent(), minimumSize(), maximumSize()
3604*/
3605
3606/*!
3607 \property QWidget::size
3608 \brief the size of the widget excluding any window frame
3609
3610 If the widget is visible when it is being resized, it receives a resize event
3611 (resizeEvent()) immediately. If the widget is not currently
3612 visible, it is guaranteed to receive an event before it is shown.
3613
3614 The size is adjusted if it lies outside the range defined by
3615 minimumSize() and maximumSize().
3616
3617 By default, this property contains a value that depends on the user's
3618 platform and screen geometry.
3619
3620 \warning Calling resize() or setGeometry() inside resizeEvent() can
3621 lead to infinite recursion.
3622
3623 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3624 appear on screen. This also applies to windows.
3625
3626 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3627*/
3628
3629/*!
3630 \property QWidget::width
3631 \brief the width of the widget excluding any window frame
3632
3633 See the \l{Window Geometry} documentation for an overview of geometry
3634 issues with windows.
3635
3636 \note Do not use this function to find the width of a screen on
3637 a multi-screen desktop. See QScreen for details.
3638
3639 By default, this property contains a value that depends on the user's
3640 platform and screen geometry.
3641
3642 \sa geometry, height, size
3643*/
3644
3645/*!
3646 \property QWidget::height
3647 \brief the height of the widget excluding any window frame
3648
3649 See the \l{Window Geometry} documentation for an overview of geometry
3650 issues with windows.
3651
3652 By default, this property contains a value that depends on the user's
3653 platform and \l{QScreen::geometry}{screen geometry}.
3654
3655 \sa geometry, width, size
3656*/
3657
3658/*!
3659 \property QWidget::rect
3660 \brief the internal geometry of the widget excluding any window
3661 frame
3662
3663 The rect property equals QRect(0, 0, width(), height()).
3664
3665 See the \l{Window Geometry} documentation for an overview of geometry
3666 issues with windows.
3667
3668 By default, this property contains a value that depends on the user's
3669 platform and screen geometry.
3670
3671 \sa size
3672*/
3673
3674/*!
3675 \property QWidget::normalGeometry
3676
3677 \brief the geometry of the widget as it will appear when shown as
3678 a normal (not maximized or full screen) top-level widget
3679
3680 If the widget is already in this state the normal geometry will
3681 reflect the widget's current geometry().
3682
3683 For child widgets this property always holds an empty rectangle.
3684
3685 By default, this property contains an empty rectangle.
3686
3687 \sa QWidget::windowState(), QWidget::geometry
3688*/
3689QRect QWidget::normalGeometry() const
3690{
3691 Q_D(const QWidget);
3692 if (!isWindow())
3693 return QRect();
3694
3695 if (!isMaximized() && !isFullScreen())
3696 return geometry();
3697
3698 return d->topData()->normalGeometry;
3699}
3700
3701
3702/*!
3703 \property QWidget::childrenRect
3704 \brief the bounding rectangle of the widget's children
3705
3706 Hidden children are excluded.
3707
3708 By default, for a widget with no children, this property contains a
3709 rectangle with zero width and height located at the origin.
3710
3711 \sa childrenRegion(), geometry()
3712*/
3713
3714QRect QWidget::childrenRect() const
3715{
3716 Q_D(const QWidget);
3717 QRect r(0, 0, 0, 0);
3718 for (int i = 0; i < d->children.size(); ++i) {
3719 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3720 if (w && !w->isWindow() && !w->isHidden())
3721 r |= w->geometry();
3722 }
3723 return r;
3724}
3725
3726/*!
3727 \property QWidget::childrenRegion
3728 \brief the combined region occupied by the widget's children
3729
3730 Hidden children are excluded.
3731
3732 By default, for a widget with no children, this property contains an
3733 empty region.
3734
3735 \sa childrenRect(), geometry(), mask()
3736*/
3737
3738QRegion QWidget::childrenRegion() const
3739{
3740 Q_D(const QWidget);
3741 QRegion r;
3742 for (int i = 0; i < d->children.size(); ++i) {
3743 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
3744 if (w && !w->isWindow() && !w->isHidden()) {
3745 QRegion mask = w->mask();
3746 if (mask.isEmpty())
3747 r |= w->geometry();
3748 else
3749 r |= mask.translated(w->pos());
3750 }
3751 }
3752 return r;
3753}
3754
3755
3756/*!
3757 \property QWidget::minimumSize
3758 \brief the widget's minimum size
3759
3760 The widget cannot be resized to a smaller size than the minimum
3761 widget size. The widget's size is forced to the minimum size if
3762 the current size is smaller.
3763
3764 The minimum size set by this function will override the minimum size
3765 defined by QLayout. To unset the minimum size, use a
3766 value of \c{QSize(0, 0)}.
3767
3768 By default, this property contains a size with zero width and height.
3769
3770 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3771*/
3772
3773QSize QWidget::minimumSize() const
3774{
3775 Q_D(const QWidget);
3776 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3777}
3778
3779/*!
3780 \property QWidget::maximumSize
3781 \brief the widget's maximum size in pixels
3782
3783 The widget cannot be resized to a larger size than the maximum
3784 widget size.
3785
3786 By default, this property contains a size in which both width and height
3787 have values of 16777215.
3788
3789 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3790 of widgets.
3791
3792 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3793*/
3794
3795QSize QWidget::maximumSize() const
3796{
3797 Q_D(const QWidget);
3798 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3800}
3801
3802
3803/*!
3804 \property QWidget::minimumWidth
3805 \brief the widget's minimum width in pixels
3806
3807 This property corresponds to the width held by the \l minimumSize property.
3808
3809 By default, this property has a value of 0.
3810
3811 \sa minimumSize, minimumHeight
3812*/
3813
3814/*!
3815 \property QWidget::minimumHeight
3816 \brief the widget's minimum height in pixels
3817
3818 This property corresponds to the height held by the \l minimumSize property.
3819
3820 By default, this property has a value of 0.
3821
3822 \sa minimumSize, minimumWidth
3823*/
3824
3825/*!
3826 \property QWidget::maximumWidth
3827 \brief the widget's maximum width in pixels
3828
3829 This property corresponds to the width held by the \l maximumSize property.
3830
3831 By default, this property contains a value of 16777215.
3832
3833 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3834 of widgets.
3835
3836 \sa maximumSize, maximumHeight
3837*/
3838
3839/*!
3840 \property QWidget::maximumHeight
3841 \brief the widget's maximum height in pixels
3842
3843 This property corresponds to the height held by the \l maximumSize property.
3844
3845 By default, this property contains a value of 16777215.
3846
3847 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3848 of widgets.
3849
3850 \sa maximumSize, maximumWidth
3851*/
3852
3853/*!
3854 \property QWidget::sizeIncrement
3855 \brief the size increment of the widget
3856
3857 When the user resizes the window, the size will move in steps of
3858 sizeIncrement().width() pixels horizontally and
3859 sizeIncrement.height() pixels vertically, with baseSize() as the
3860 basis. Preferred widget sizes are for non-negative integers \e i
3861 and \e j:
3862 \snippet code/src_gui_kernel_qwidget.cpp 2
3863
3864 Note that while you can set the size increment for all widgets, it
3865 only affects windows.
3866
3867 By default, this property contains a size with zero width and height.
3868
3869 \warning The size increment has no effect under Windows, and may
3870 be disregarded by the window manager on X11.
3871
3872 \sa size, minimumSize, maximumSize
3873*/
3874QSize QWidget::sizeIncrement() const
3875{
3876 Q_D(const QWidget);
3877 return (d->extra && d->extra->topextra)
3878 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3879 : QSize(0, 0);
3880}
3881
3882/*!
3883 \property QWidget::baseSize
3884 \brief the base size of the widget
3885
3886 The base size is used to calculate a proper widget size if the
3887 widget defines sizeIncrement().
3888
3889 By default, for a newly-created widget, this property contains a size with
3890 zero width and height.
3891
3892 \sa setSizeIncrement()
3893*/
3894
3895QSize QWidget::baseSize() const
3896{
3897 Q_D(const QWidget);
3898 return (d->extra && d->extra->topextra)
3899 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3900 : QSize(0, 0);
3901}
3902
3903bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3904{
3905 Q_Q(QWidget);
3906
3907 int mw = minw, mh = minh;
3908 if (mw == QWIDGETSIZE_MAX)
3909 mw = 0;
3910 if (mh == QWIDGETSIZE_MAX)
3911 mh = 0;
3912 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3913 qWarning("QWidget::setMinimumSize: (%s/%s) "
3914 "The largest allowed size is (%d,%d)",
3915 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3917 minw = mw = qMin<int>(minw, QWIDGETSIZE_MAX);
3918 minh = mh = qMin<int>(minh, QWIDGETSIZE_MAX);
3919 }
3920 if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3921 qWarning("QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3922 "are not possible",
3923 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3924 minw = mw = qMax(minw, 0);
3925 minh = mh = qMax(minh, 0);
3926 }
3927 createExtra();
3928 if (extra->minw == mw && extra->minh == mh)
3929 return false;
3930 extra->minw = mw;
3931 extra->minh = mh;
3932 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3933 return true;
3934}
3935
3936void QWidgetPrivate::setConstraints_sys()
3937{
3938 Q_Q(QWidget);
3939 if (extra && q->windowHandle()) {
3940 QWindow *win = q->windowHandle();
3941 QWindowPrivate *winp = qt_window_private(win);
3942
3943 winp->minimumSize = QSize(extra->minw, extra->minh);
3944 winp->maximumSize = QSize(extra->maxw, extra->maxh);
3945
3946 if (extra->topextra) {
3947 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3948 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3949 }
3950
3951 if (winp->platformWindow) {
3952 fixPosIncludesFrame();
3953 winp->platformWindow->propagateSizeHints();
3954 }
3955 }
3956}
3957
3958/*!
3959 \overload
3960
3961 This function corresponds to setMinimumSize(QSize(minw, minh)).
3962 Sets the minimum width to \a minw and the minimum height to \a
3963 minh.
3964*/
3965
3966void QWidget::setMinimumSize(int minw, int minh)
3967{
3968 Q_D(QWidget);
3969 if (!d->setMinimumSize_helper(minw, minh))
3970 return;
3971
3972 if (isWindow())
3973 d->setConstraints_sys();
3974 if (minw > width() || minh > height()) {
3975 bool resized = testAttribute(Qt::WA_Resized);
3976 bool maximized = isMaximized();
3977 resize(qMax(minw,width()), qMax(minh,height()));
3978 setAttribute(Qt::WA_Resized, resized); //not a user resize
3979 if (maximized)
3980 data->window_state = data->window_state | Qt::WindowMaximized;
3981 }
3982#if QT_CONFIG(graphicsview)
3983 if (d->extra) {
3984 if (d->extra->proxyWidget)
3985 d->extra->proxyWidget->setMinimumSize(minw, minh);
3986 }
3987#endif
3988 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
3989}
3990
3991bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
3992{
3993 Q_Q(QWidget);
3994 if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
3995 qWarning("QWidget::setMaximumSize: (%s/%s) "
3996 "The largest allowed size is (%d,%d)",
3997 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3999 maxw = qMin<int>(maxw, QWIDGETSIZE_MAX);
4000 maxh = qMin<int>(maxh, QWIDGETSIZE_MAX);
4001 }
4002 if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
4003 qWarning("QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
4004 "are not possible",
4005 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
4006 maxw = qMax(maxw, 0);
4007 maxh = qMax(maxh, 0);
4008 }
4009 createExtra();
4010 if (extra->maxw == maxw && extra->maxh == maxh)
4011 return false;
4012 extra->maxw = maxw;
4013 extra->maxh = maxh;
4014 extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
4015 (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
4016 return true;
4017}
4018
4019/*!
4020 \overload
4021
4022 This function corresponds to setMaximumSize(QSize(\a maxw, \a
4023 maxh)). Sets the maximum width to \a maxw and the maximum height
4024 to \a maxh.
4025*/
4026void QWidget::setMaximumSize(int maxw, int maxh)
4027{
4028 Q_D(QWidget);
4029 if (!d->setMaximumSize_helper(maxw, maxh))
4030 return;
4031
4032 if (isWindow())
4033 d->setConstraints_sys();
4034 if (maxw < width() || maxh < height()) {
4035 bool resized = testAttribute(Qt::WA_Resized);
4036 resize(qMin(maxw,width()), qMin(maxh,height()));
4037 setAttribute(Qt::WA_Resized, resized); //not a user resize
4038 }
4039
4040#if QT_CONFIG(graphicsview)
4041 if (d->extra) {
4042 if (d->extra->proxyWidget)
4043 d->extra->proxyWidget->setMaximumSize(maxw, maxh);
4044 }
4045#endif
4046
4047 d->updateGeometry_helper(d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4048}
4049
4050/*!
4051 \overload
4052
4053 Sets the x (width) size increment to \a w and the y (height) size
4054 increment to \a h.
4055*/
4056void QWidget::setSizeIncrement(int w, int h)
4057{
4058 Q_D(QWidget);
4059 d->createTLExtra();
4060 QTLWExtra* x = d->topData();
4061 if (x->incw == w && x->inch == h)
4062 return;
4063 x->incw = w;
4064 x->inch = h;
4065 if (isWindow())
4066 d->setConstraints_sys();
4067}
4068
4069/*!
4070 \overload
4071
4072 This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
4073 the widgets base size to width \a basew and height \a baseh.
4074*/
4075void QWidget::setBaseSize(int basew, int baseh)
4076{
4077 Q_D(QWidget);
4078 d->createTLExtra();
4079 QTLWExtra* x = d->topData();
4080 if (x->basew == basew && x->baseh == baseh)
4081 return;
4082 x->basew = basew;
4083 x->baseh = baseh;
4084 if (isWindow())
4085 d->setConstraints_sys();
4086}
4087
4088/*!
4089 Sets both the minimum and maximum sizes of the widget to \a s,
4090 thereby preventing it from ever growing or shrinking.
4091
4092 This will override the default size constraints set by QLayout.
4093
4094 To remove constraints, set the size to QWIDGETSIZE_MAX.
4095
4096 Alternatively, if you want the widget to have a
4097 fixed size based on its contents, you can call
4098 QLayout::setSizeConstraint(QLayout::SetFixedSize);
4099
4100 \sa maximumSize, minimumSize
4101*/
4102
4103void QWidget::setFixedSize(const QSize & s)
4104{
4105 setFixedSize(s.width(), s.height());
4106}
4107
4108
4109/*!
4110 \fn void QWidget::setFixedSize(int w, int h)
4111 \overload
4112
4113 Sets the width of the widget to \a w and the height to \a h.
4114*/
4115
4116void QWidget::setFixedSize(int w, int h)
4117{
4118 Q_D(QWidget);
4119 bool minSizeSet = d->setMinimumSize_helper(w, h);
4120 bool maxSizeSet = d->setMaximumSize_helper(w, h);
4121 if (!minSizeSet && !maxSizeSet)
4122 return;
4123
4124 if (isWindow())
4125 d->setConstraints_sys();
4126 else
4127 d->updateGeometry_helper(true);
4128
4129 if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
4130 resize(w, h);
4131}
4132
4133void QWidget::setMinimumWidth(int w)
4134{
4135 Q_D(QWidget);
4136 d->createExtra();
4137 uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
4138 setMinimumSize(w, minimumSize().height());
4139 d->extra->explicitMinSize = expl;
4140}
4141
4142void QWidget::setMinimumHeight(int h)
4143{
4144 Q_D(QWidget);
4145 d->createExtra();
4146 uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
4147 setMinimumSize(minimumSize().width(), h);
4148 d->extra->explicitMinSize = expl;
4149}
4150
4151void QWidget::setMaximumWidth(int w)
4152{
4153 Q_D(QWidget);
4154 d->createExtra();
4155 uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
4156 setMaximumSize(w, maximumSize().height());
4157 d->extra->explicitMaxSize = expl;
4158}
4159
4160void QWidget::setMaximumHeight(int h)
4161{
4162 Q_D(QWidget);
4163 d->createExtra();
4164 uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
4165 setMaximumSize(maximumSize().width(), h);
4166 d->extra->explicitMaxSize = expl;
4167}
4168
4169/*!
4170 Sets both the minimum and maximum width of the widget to \a w
4171 without changing the heights. Provided for convenience.
4172
4173 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4174*/
4175
4176void QWidget::setFixedWidth(int w)
4177{
4178 Q_D(QWidget);
4179 d->createExtra();
4180 uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4181 uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4182 setMinimumSize(w, minimumSize().height());
4183 setMaximumSize(w, maximumSize().height());
4184 d->extra->explicitMinSize = explMin;
4185 d->extra->explicitMaxSize = explMax;
4186}
4187
4188
4189/*!
4190 Sets both the minimum and maximum heights of the widget to \a h
4191 without changing the widths. Provided for convenience.
4192
4193 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4194*/
4195
4196void QWidget::setFixedHeight(int h)
4197{
4198 Q_D(QWidget);
4199 d->createExtra();
4200 uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4201 uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4202 setMinimumSize(minimumSize().width(), h);
4203 setMaximumSize(maximumSize().width(), h);
4204 d->extra->explicitMinSize = explMin;
4205 d->extra->explicitMaxSize = explMax;
4206}
4207
4208
4209/*!
4210 Translates the widget coordinate \a pos to the coordinate system
4211 of \a parent. The \a parent must not be \nullptr and must be a parent
4212 of the calling widget.
4213
4214 \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4215 \since 6.0
4216*/
4217
4218QPointF QWidget::mapTo(const QWidget *parent, const QPointF &pos) const
4219{
4220 QPointF p = pos;
4221 if (parent) {
4222 const QWidget * w = this;
4223 while (w != parent) {
4224 p = w->mapToParent(p);
4225 w = w->parentWidget();
4226 if (!w) {
4227 qWarning("QWidget::mapTo(): parent must be in parent hierarchy");
4228 break;
4229 }
4230 }
4231 }
4232 return p;
4233}
4234
4235/*!
4236 \overload
4237*/
4238QPoint QWidget::mapTo(const QWidget *parent, const QPoint &pos) const
4239{
4240 return mapTo(parent, QPointF(pos)).toPoint();
4241}
4242
4243/*!
4244 Translates the widget coordinate \a pos from the coordinate system
4245 of \a parent to this widget's coordinate system. The \a parent
4246 must not be \nullptr and must be a parent of the calling widget.
4247
4248 \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4249 \since 6.0
4250*/
4251
4252QPointF QWidget::mapFrom(const QWidget *parent, const QPointF &pos) const
4253{
4254 QPointF p(pos);
4255 if (parent) {
4256 const QWidget * w = this;
4257 while (w != parent) {
4258 p = w->mapFromParent(p);
4259 w = w->parentWidget();
4260 if (!w) {
4261 qWarning("QWidget::mapFrom(): parent must be in parent hierarchy");
4262 break;
4263 }
4264 }
4265 }
4266 return p;
4267}
4268
4269/*!
4270 \overload
4271*/
4272QPoint QWidget::mapFrom(const QWidget *parent, const QPoint &pos) const
4273{
4274 return mapFrom(parent, QPointF(pos)).toPoint();
4275}
4276
4277/*!
4278 Translates the widget coordinate \a pos to a coordinate in the
4279 parent widget.
4280
4281 Same as mapToGlobal() if the widget has no parent.
4282
4283 \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4284 \since 6.0
4285*/
4286
4287QPointF QWidget::mapToParent(const QPointF &pos) const
4288{
4289 return pos + QPointF(data->crect.topLeft());
4290}
4291
4292/*!
4293 \overload
4294*/
4295QPoint QWidget::mapToParent(const QPoint &pos) const
4296{
4297 return pos + data->crect.topLeft();
4298}
4299
4300/*!
4301 Translates the parent widget coordinate \a pos to widget
4302 coordinates.
4303
4304 Same as mapFromGlobal() if the widget has no parent.
4305
4306 \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4307 \since 6.0
4308*/
4309
4310QPointF QWidget::mapFromParent(const QPointF &pos) const
4311{
4312 return pos - QPointF(data->crect.topLeft());
4313}
4314
4315/*!
4316 \overload
4317*/
4318QPoint QWidget::mapFromParent(const QPoint &pos) const
4319{
4320 return pos - data->crect.topLeft();
4321}
4322
4323
4324/*!
4325 Returns the window for this widget, i.e. the next ancestor widget
4326 that has (or could have) a window-system frame.
4327
4328 If the widget is a window, the widget itself is returned.
4329
4330 Typical usage is changing the window title:
4331
4332 \snippet code/src_gui_kernel_qwidget.cpp 3
4333
4334 \sa isWindow()
4335*/
4336
4337QWidget *QWidget::window() const
4338{
4339 QWidget *w = const_cast<QWidget *>(this);
4340 QWidget *p = w->parentWidget();
4341 while (!w->isWindow() && p) {
4342 w = p;
4343 p = p->parentWidget();
4344 }
4345 return w;
4346}
4347
4348/*!
4349 \since 4.4
4350
4351 Returns the native parent for this widget, i.e. the next ancestor widget
4352 that has a system identifier, or \nullptr if it does not have any native
4353 parent.
4354
4355 \sa effectiveWinId()
4356*/
4357QWidget *QWidget::nativeParentWidget() const
4358{
4359 QWidget *parent = parentWidget();
4360 while (parent && !parent->internalWinId())
4361 parent = parent->parentWidget();
4362 return parent;
4363}
4364
4365/*! \fn QWidget *QWidget::topLevelWidget() const
4366 \deprecated
4367
4368 Use window() instead.
4369*/
4370
4371
4372
4373/*!
4374 Returns the background role of the widget.
4375
4376 The background role defines the brush from the widget's \l palette that
4377 is used to render the background.
4378
4379 If no explicit background role is set, the widget inherits its parent
4380 widget's background role.
4381
4382 \sa setBackgroundRole(), foregroundRole()
4383 */
4384QPalette::ColorRole QWidget::backgroundRole() const
4385{
4386
4387 const QWidget *w = this;
4388 do {
4389 QPalette::ColorRole role = w->d_func()->bg_role;
4390 if (role != QPalette::NoRole)
4391 return role;
4392 if (w->isWindow() || w->windowType() == Qt::SubWindow)
4393 break;
4394 w = w->parentWidget();
4395 } while (w);
4396 return QPalette::Window;
4397}
4398
4399/*!
4400 Sets the background role of the widget to \a role.
4401
4402 The background role defines the brush from the widget's \l palette that
4403 is used to render the background.
4404
4405 If \a role is QPalette::NoRole, then the widget inherits its
4406 parent's background role.
4407
4408 Note that styles are free to choose any color from the palette.
4409 You can modify the palette or set a style sheet if you don't
4410 achieve the result you want with setBackgroundRole().
4411
4412 \sa backgroundRole(), foregroundRole()
4413 */
4414
4415void QWidget::setBackgroundRole(QPalette::ColorRole role)
4416{
4417 Q_D(QWidget);
4418 d->bg_role = role;
4419 d->updateSystemBackground();
4420 d->propagatePaletteChange();
4421 d->updateIsOpaque();
4422}
4423
4424/*!
4425 Returns the foreground role.
4426
4427 The foreground role defines the color from the widget's \l palette that
4428 is used to draw the foreground.
4429
4430 If no explicit foreground role is set, the function returns a role
4431 that contrasts with the background role.
4432
4433 \sa setForegroundRole(), backgroundRole()
4434 */
4435QPalette::ColorRole QWidget::foregroundRole() const
4436{
4437 Q_D(const QWidget);
4438 QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4439 if (rl != QPalette::NoRole)
4440 return rl;
4441 QPalette::ColorRole role = QPalette::WindowText;
4442 switch (backgroundRole()) {
4443 case QPalette::Button:
4444 role = QPalette::ButtonText;
4445 break;
4446 case QPalette::Base:
4447 role = QPalette::Text;
4448 break;
4449 case QPalette::Dark:
4450 case QPalette::Shadow:
4451 role = QPalette::Light;
4452 break;
4453 case QPalette::Highlight:
4454 role = QPalette::HighlightedText;
4455 break;
4456 case QPalette::ToolTipBase:
4457 role = QPalette::ToolTipText;
4458 break;
4459 default:
4460 ;
4461 }
4462 return role;
4463}
4464
4465/*!
4466 Sets the foreground role of the widget to \a role.
4467
4468 The foreground role defines the color from the widget's \l palette that
4469 is used to draw the foreground.
4470
4471 If \a role is QPalette::NoRole, the widget uses a foreground role
4472 that contrasts with the background role.
4473
4474 Note that styles are free to choose any color from the palette.
4475 You can modify the palette or set a style sheet if you don't
4476 achieve the result you want with setForegroundRole().
4477
4478 \sa foregroundRole(), backgroundRole()
4479 */
4480void QWidget::setForegroundRole(QPalette::ColorRole role)
4481{
4482 Q_D(QWidget);
4483 d->fg_role = role;
4484 d->updateSystemBackground();
4485 d->propagatePaletteChange();
4486}
4487
4488/*!
4489 \property QWidget::palette
4490 \brief the widget's palette
4491
4492 This property describes the widget's palette. The palette is used by the
4493 widget's style when rendering standard components, and is available as a
4494 means to ensure that custom widgets can maintain consistency with the
4495 native platform's look and feel. It's common that different platforms, or
4496 different styles, have different palettes.
4497
4498 When you assign a new palette to a widget, the color roles from this
4499 palette are combined with the widget's default palette to form the
4500 widget's final palette. The palette entry for the widget's background role
4501 is used to fill the widget's background (see QWidget::autoFillBackground),
4502 and the foreground role initializes QPainter's pen.
4503
4504 The default depends on the system environment. QApplication maintains a
4505 system/theme palette which serves as a default for all widgets. There may
4506 also be special palette defaults for certain types of widgets (e.g., on
4507 Windows Vista, all classes that derive from QMenuBar have a special
4508 default palette). You can also define default palettes for widgets
4509 yourself by passing a custom palette and the name of a widget to
4510 QApplication::setPalette(). Finally, the style always has the option of
4511 polishing the palette as it's assigned (see QStyle::polish()).
4512
4513 QWidget propagates explicit palette roles from parent to child. If you
4514 assign a brush or color to a specific role on a palette and assign that
4515 palette to a widget, that role will propagate to all the widget's
4516 children, overriding any system defaults for that role. Note that palettes
4517 by default don't propagate to windows (see isWindow()) unless the
4518 Qt::WA_WindowPropagation attribute is enabled.
4519
4520 QWidget's palette propagation is similar to its font propagation.
4521
4522 The current style, which is used to render the content of all standard Qt
4523 widgets, is free to choose colors and brushes from the widget palette, or,
4524 in some cases, to ignore the palette (partially, or completely). In
4525 particular, certain styles like GTK style, Mac style, and Windows Vista
4526 style, depend on third party APIs to render the content of widgets,
4527 and these styles typically do not follow the palette. Because of this,
4528 assigning roles to a widget's palette is not guaranteed to change the
4529 appearance of the widget. Instead, you may choose to apply a \l {styleSheet}.
4530
4531 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4532 When using style sheets, the palette of a widget can be customized using
4533 the "color", "background-color", "selection-color",
4534 "selection-background-color" and "alternate-background-color".
4535
4536 \sa QGuiApplication::palette(), QWidget::font(), {Qt Style Sheets}
4537*/
4538const QPalette &QWidget::palette() const
4539{
4540 if (!isEnabled()) {
4541 data->pal.setCurrentColorGroup(QPalette::Disabled);
4542 } else if ((!isVisible() || isActiveWindow())
4543#if defined(Q_OS_WIN)
4544 && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4545#endif
4546 ) {
4547 data->pal.setCurrentColorGroup(QPalette::Active);
4548 } else {
4549 data->pal.setCurrentColorGroup(QPalette::Inactive);
4550 }
4551 return data->pal;
4552}
4553
4554void QWidget::setPalette(const QPalette &palette)
4555{
4556 Q_D(QWidget);
4557 setAttribute(Qt::WA_SetPalette, palette.resolveMask() != 0);
4558
4559 // Determine which palette is inherited from this widget's ancestors and
4560 // QApplication::palette, resolve this against \a palette (attributes from
4561 // the inherited palette are copied over this widget's palette). Then
4562 // propagate this palette to this widget's children.
4563 QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
4564 QPalette resolvedPalette = palette.resolve(naturalPalette);
4565 d->setPalette_helper(resolvedPalette);
4566}
4567
4568/*!
4569 \internal
4570
4571 Returns the palette that the widget \a w inherits from its ancestors and
4572 QApplication::palette. \a inheritedMask is the combination of the widget's
4573 ancestors palette request masks (i.e., which attributes from the parent
4574 widget's palette are implicitly imposed on this widget by the user). Note
4575 that this font does not take into account the palette set on \a w itself.
4576*/
4577QPalette QWidgetPrivate::naturalWidgetPalette(QPalette::ResolveMask inheritedMask) const
4578{
4579 Q_Q(const QWidget);
4580
4581 const bool useStyleSheetPropagationInWidgetStyles =
4582 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4583
4584 QPalette naturalPalette = QApplication::palette(q);
4585 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4586 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4587#if QT_CONFIG(graphicsview)
4588 || (extra && extra->proxyWidget)
4589#endif // QT_CONFIG(graphicsview)
4590 )) {
4591 if (QWidget *p = q->parentWidget()) {
4592 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4593 if (!naturalPalette.isCopyOf(QGuiApplication::palette())) {
4594 QPalette inheritedPalette = p->palette();
4595 inheritedPalette.setResolveMask(inheritedMask);
4596 naturalPalette = inheritedPalette.resolve(naturalPalette);
4597 } else {
4598 naturalPalette = p->palette();
4599 }
4600 }
4601 }
4602#if QT_CONFIG(graphicsview)
4603 else if (extra && extra->proxyWidget) {
4604 QPalette inheritedPalette = extra->proxyWidget->palette();
4605 inheritedPalette.setResolveMask(inheritedMask);
4606 naturalPalette = inheritedPalette.resolve(naturalPalette);
4607 }
4608#endif // QT_CONFIG(graphicsview)
4609 }
4610 naturalPalette.setResolveMask(0);
4611 return naturalPalette;
4612}
4613/*!
4614 \internal
4615
4616 Determine which palette is inherited from this widget's ancestors and
4617 QApplication::palette, resolve this against this widget's palette
4618 (attributes from the inherited palette are copied over this widget's
4619 palette). Then propagate this palette to this widget's children.
4620*/
4621void QWidgetPrivate::resolvePalette()
4622{
4623 QPalette naturalPalette = naturalWidgetPalette(inheritedPaletteResolveMask);
4624 QPalette resolvedPalette = data.pal.resolve(naturalPalette);
4625 setPalette_helper(resolvedPalette);
4626}
4627
4628void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4629{
4630 Q_Q(QWidget);
4631 if (data.pal == palette && data.pal.resolveMask() == palette.resolveMask())
4632 return;
4633 data.pal = palette;
4634 updateSystemBackground();
4635 propagatePaletteChange();
4636 updateIsOpaque();
4637 q->update();
4638 updateIsOpaque();
4639}
4640
4641void QWidgetPrivate::updateSystemBackground()
4642{
4643}
4644
4645/*!
4646 \property QWidget::font
4647 \brief the font currently set for the widget
4648
4649 This property describes the widget's requested font. The font is used by
4650 the widget's style when rendering standard components, and is available as
4651 a means to ensure that custom widgets can maintain consistency with the
4652 native platform's look and feel. It's common that different platforms, or
4653 different styles, define different fonts for an application.
4654
4655 When you assign a new font to a widget, the properties from this font are
4656 combined with the widget's default font to form the widget's final
4657 font. You can call fontInfo() to get a copy of the widget's final
4658 font. The final font is also used to initialize QPainter's font.
4659
4660 The default depends on the system environment. QApplication maintains a
4661 system/theme font which serves as a default for all widgets. There may
4662 also be special font defaults for certain types of widgets. You can also
4663 define default fonts for widgets yourself by passing a custom font and the
4664 name of a widget to QApplication::setFont(). Finally, the font is matched
4665 against Qt's font database to find the best match.
4666
4667 QWidget propagates explicit font properties from parent to child. If you
4668 change a specific property on a font and assign that font to a widget,
4669 that property will propagate to all the widget's children, overriding any
4670 system defaults for that property. Note that fonts by default don't
4671 propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4672 attribute is enabled.
4673
4674 QWidget's font propagation is similar to its palette propagation.
4675
4676 The current style, which is used to render the content of all standard Qt
4677 widgets, is free to choose to use the widget font, or in some cases, to
4678 ignore it (partially, or completely). In particular, certain styles like
4679 GTK style, Mac style, and Windows Vista style, apply special
4680 modifications to the widget font to match the platform's native look and
4681 feel. Because of this, assigning properties to a widget's font is not
4682 guaranteed to change the appearance of the widget. Instead, you may choose
4683 to apply a \l styleSheet.
4684
4685 \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4686 style sheets will take precedence if the settings conflict.
4687
4688 \sa fontInfo(), fontMetrics()
4689*/
4690
4691void QWidget::setFont(const QFont &font)
4692{
4693 Q_D(QWidget);
4694
4695#if QT_CONFIG(style_stylesheet)
4696 const QStyleSheetStyle* style;
4697 if (d->extra && (style = qt_styleSheet(d->extra->style)))
4698 style->saveWidgetFont(this, font);
4699#endif
4700
4701 setAttribute(Qt::WA_SetFont, font.resolveMask() != 0);
4702
4703 // Determine which font is inherited from this widget's ancestors and
4704 // QApplication::font, resolve this against \a font (attributes from the
4705 // inherited font are copied over). Then propagate this font to this
4706 // widget's children.
4707 QFont naturalFont = d->naturalWidgetFont(d->inheritedFontResolveMask);
4708 QFont resolvedFont = font.resolve(naturalFont);
4709 d->setFont_helper(resolvedFont);
4710}
4711
4712/*
4713 \internal
4714
4715 Returns the font that the widget \a w inherits from its ancestors and
4716 QApplication::font. \a inheritedMask is the combination of the widget's
4717 ancestors font request masks (i.e., which attributes from the parent
4718 widget's font are implicitly imposed on this widget by the user). Note
4719 that this font does not take into account the font set on \a w itself.
4720
4721 ### Stylesheet has a different font propagation mechanism. When a stylesheet
4722 is applied, fonts are not propagated anymore
4723*/
4724QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4725{
4726 Q_Q(const QWidget);
4727
4728 const bool useStyleSheetPropagationInWidgetStyles =
4729 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4730
4731 QFont naturalFont = QApplication::font(q);
4732 if ((!q->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4733 && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation)
4734#if QT_CONFIG(graphicsview)
4735 || (extra && extra->proxyWidget)
4736#endif // QT_CONFIG(graphicsview)
4737 )) {
4738 if (QWidget *p = q->parentWidget()) {
4739 if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4740 if (!naturalFont.isCopyOf(QApplication::font())) {
4741 if (inheritedMask != 0) {
4742 QFont inheritedFont = p->font();
4743 inheritedFont.setResolveMask(inheritedMask);
4744 naturalFont = inheritedFont.resolve(naturalFont);
4745 } // else nothing to do (naturalFont = naturalFont)
4746 } else {
4747 naturalFont = p->font();
4748 }
4749 }
4750 }
4751#if QT_CONFIG(graphicsview)
4752 else if (extra && extra->proxyWidget) {
4753 if (inheritedMask != 0) {
4754 QFont inheritedFont = extra->proxyWidget->font();
4755 inheritedFont.setResolveMask(inheritedMask);
4756 naturalFont = inheritedFont.resolve(naturalFont);
4757 } // else nothing to do (naturalFont = naturalFont)
4758 }
4759#endif // QT_CONFIG(graphicsview)
4760 }
4761 naturalFont.setResolveMask(0);
4762 return naturalFont;
4763}
4764
4765/*!
4766 \internal
4767
4768 Returns a font suitable for inheritance, where only locally set attributes are considered resolved.
4769*/
4770QFont QWidgetPrivate::localFont() const
4771{
4772 QFont localfont = data.fnt;
4773 localfont.setResolveMask(directFontResolveMask);
4774 return localfont;
4775}
4776
4777/*!
4778 \internal
4779
4780 Determine which font is implicitly imposed on this widget by its ancestors
4781 and QApplication::font, resolve this against its own font (attributes from
4782 the implicit font are copied over). Then propagate this font to this
4783 widget's children.
4784*/
4785void QWidgetPrivate::resolveFont()
4786{
4787 QFont naturalFont = naturalWidgetFont(inheritedFontResolveMask);
4788 QFont resolvedFont = localFont().resolve(naturalFont);
4789 setFont_helper(resolvedFont);
4790}
4791
4792/*!
4793 \internal
4794
4795 Assign \a font to this widget, and propagate it to all children, except
4796 style sheet widgets (handled differently) and windows that don't enable
4797 window propagation. \a implicitMask is the union of all ancestor widgets'
4798 font request masks, and determines which attributes from this widget's
4799 font should propagate.
4800*/
4801void QWidgetPrivate::updateFont(const QFont &font)
4802{
4803 Q_Q(QWidget);
4804#if QT_CONFIG(style_stylesheet)
4805 const QStyleSheetStyle* cssStyle;
4806 cssStyle = extra ? qt_styleSheet(extra->style) : nullptr;
4807 const bool useStyleSheetPropagationInWidgetStyles =
4808 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4809#endif
4810
4811 data.fnt = QFont(font, q);
4812
4813 // Combine new mask with natural mask and propagate to children.
4814#if QT_CONFIG(graphicsview)
4815 if (!q->parentWidget() && extra && extra->proxyWidget) {
4816 QGraphicsProxyWidget *p = extra->proxyWidget;
4817 inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolveMask();
4818 } else
4819#endif // QT_CONFIG(graphicsview)
4820 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) {
4821 inheritedFontResolveMask = 0;
4822 }
4823 uint newMask = data.fnt.resolveMask() | inheritedFontResolveMask;
4824 // Set the font as also having resolved inherited traits, so the result of reading QWidget::font()
4825 // isn't all weak information, but save the original mask to be able to let new changes on the
4826 // parent widget font propagate correctly.
4827 directFontResolveMask = data.fnt.resolveMask();
4828 data.fnt.setResolveMask(newMask);
4829
4830 for (int i = 0; i < children.size(); ++i) {
4831 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4832 if (w) {
4833 if (0) {
4834#if QT_CONFIG(style_stylesheet)
4835 } else if (!useStyleSheetPropagationInWidgetStyles && w->testAttribute(Qt::WA_StyleSheet)) {
4836 // Style sheets follow a different font propagation scheme.
4837 if (cssStyle)
4838 cssStyle->updateStyleSheetFont(w);
4839#endif
4840 } else if ((!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))) {
4841 // Propagate font changes.
4842 QWidgetPrivate *wd = w->d_func();
4843 wd->inheritedFontResolveMask = newMask;
4844 wd->resolveFont();
4845 }
4846 }
4847 }
4848
4849#if QT_CONFIG(style_stylesheet)
4850 if (!useStyleSheetPropagationInWidgetStyles && cssStyle) {
4851 cssStyle->updateStyleSheetFont(q);
4852 }
4853#endif
4854
4855 QEvent e(QEvent::FontChange);
4856 QCoreApplication::sendEvent(q, &e);
4857}
4858
4859void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
4860{
4861 Q_Q(QWidget);
4862
4863 if ( (direction == Qt::RightToLeft) == q->testAttribute(Qt::WA_RightToLeft))
4864 return;
4865 q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));
4866 if (!children.isEmpty()) {
4867 for (int i = 0; i < children.size(); ++i) {
4868 QWidget *w = qobject_cast<QWidget*>(children.at(i));
4869 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_SetLayoutDirection))
4870 w->d_func()->setLayoutDirection_helper(direction);
4871 }
4872 }
4873 QEvent e(QEvent::LayoutDirectionChange);
4874 QCoreApplication::sendEvent(q, &e);
4875}
4876
4877void QWidgetPrivate::resolveLayoutDirection()
4878{
4879 Q_Q(const QWidget);
4880 if (!q->testAttribute(Qt::WA_SetLayoutDirection))
4881 setLayoutDirection_helper(q->isWindow() ? QGuiApplication::layoutDirection() : q->parentWidget()->layoutDirection());
4882}
4883
4884/*!
4885 \property QWidget::layoutDirection
4886
4887 \brief the layout direction for this widget.
4888
4889 \note This method no longer affects text layout direction since Qt 4.7.
4890
4891 By default, this property is set to Qt::LeftToRight.
4892
4893 When the layout direction is set on a widget, it will propagate to
4894 the widget's children, but not to a child that is a window and not
4895 to a child for which setLayoutDirection() has been explicitly
4896 called. Also, child widgets added \e after setLayoutDirection()
4897 has been called for the parent do not inherit the parent's layout
4898 direction.
4899
4900
4901 \sa QApplication::layoutDirection
4902*/
4903void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
4904{
4905 Q_D(QWidget);
4906
4907 if (direction == Qt::LayoutDirectionAuto) {
4908 unsetLayoutDirection();
4909 return;
4910 }
4911
4912 setAttribute(Qt::WA_SetLayoutDirection);
4913 d->setLayoutDirection_helper(direction);
4914}
4915
4916Qt::LayoutDirection QWidget::layoutDirection() const
4917{
4918 return testAttribute(Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
4919}
4920
4921void QWidget::unsetLayoutDirection()
4922{
4923 Q_D(QWidget);
4924 setAttribute(Qt::WA_SetLayoutDirection, false);
4925 d->resolveLayoutDirection();
4926}
4927
4928/*!
4929 \fn QFontMetrics QWidget::fontMetrics() const
4930
4931 Returns the font metrics for the widget's current font.
4932 Equivalent to \c QFontMetrics(widget->font()).
4933
4934 \sa font(), fontInfo(), setFont()
4935*/
4936
4937/*!
4938 \fn QFontInfo QWidget::fontInfo() const
4939
4940 Returns the font info for the widget's current font.
4941 Equivalent to \c QFontInfo(widget->font()).
4942
4943 \sa font(), fontMetrics(), setFont()
4944*/
4945
4946
4947/*!
4948 \property QWidget::cursor
4949 \brief the cursor shape for this widget
4950
4951 The mouse cursor will assume this shape when it's over this
4952 widget. See the \l{Qt::CursorShape}{list of predefined cursor objects} for a range of useful shapes.
4953
4954 An editor widget might use an I-beam cursor:
4955 \snippet code/src_gui_kernel_qwidget.cpp 6
4956
4957 If no cursor has been set, or after a call to unsetCursor(), the
4958 parent's cursor is used.
4959
4960 By default, this property contains a cursor with the Qt::ArrowCursor
4961 shape.
4962
4963 Some underlying window implementations will reset the cursor if it
4964 leaves a widget even if the mouse is grabbed. If you want to have
4965 a cursor set for all widgets, even when outside the window, consider
4966 QGuiApplication::setOverrideCursor().
4967
4968 \sa QGuiApplication::setOverrideCursor()
4969*/
4970
4971#ifndef QT_NO_CURSOR
4972QCursor QWidget::cursor() const
4973{
4974 Q_D(const QWidget);
4975 if (testAttribute(Qt::WA_SetCursor))
4976 return (d->extra && d->extra->curs)
4977 ? *d->extra->curs
4978 : QCursor(Qt::ArrowCursor);
4979 if (isWindow() || !parentWidget())
4980 return QCursor(Qt::ArrowCursor);
4981 return parentWidget()->cursor();
4982}
4983
4984void QWidget::setCursor(const QCursor &cursor)
4985{
4986 Q_D(QWidget);
4987 if (cursor.shape() != Qt::ArrowCursor
4988 || (d->extra && d->extra->curs))
4989 {
4990 d->createExtra();
4991 d->extra->curs = std::make_unique<QCursor>(cursor);
4992 }
4993 setAttribute(Qt::WA_SetCursor);
4994 d->setCursor_sys(cursor);
4995
4996 QEvent event(QEvent::CursorChange);
4997 QCoreApplication::sendEvent(this, &event);
4998}
4999
5000void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
5001{
5002 Q_UNUSED(cursor);
5003 Q_Q(QWidget);
5004 qt_qpa_set_cursor(q, false);
5005}
5006
5007void QWidget::unsetCursor()
5008{
5009 Q_D(QWidget);
5010 if (d->extra)
5011 d->extra->curs.reset();
5012 if (!isWindow())
5013 setAttribute(Qt::WA_SetCursor, false);
5014 d->unsetCursor_sys();
5015
5016 QEvent event(QEvent::CursorChange);
5017 QCoreApplication::sendEvent(this, &event);
5018}
5019
5020void QWidgetPrivate::unsetCursor_sys()
5021{
5022 Q_Q(QWidget);
5023 qt_qpa_set_cursor(q, false);
5024}
5025
5026static inline void applyCursor(QWidget *w, const QCursor &c)
5027{
5028 if (QWindow *window = w->windowHandle())
5029 window->setCursor(c);
5030}
5031
5032static inline void unsetCursor(QWidget *w)
5033{
5034 if (QWindow *window = w->windowHandle())
5035 window->unsetCursor();
5036}
5037
5038void qt_qpa_set_cursor(QWidget *w, bool force)
5039{
5040 if (!w->testAttribute(Qt::WA_WState_Created))
5041 return;
5042
5043 static QPointer<QWidget> lastUnderMouse = nullptr;
5044 if (force) {
5045 lastUnderMouse = w;
5046 } else if (lastUnderMouse) {
5047 const WId lastWinId = lastUnderMouse->effectiveWinId();
5048 const WId winId = w->effectiveWinId();
5049 if (lastWinId && lastWinId == winId)
5050 w = lastUnderMouse;
5051 } else if (!w->internalWinId()) {
5052 return; // The mouse is not under this widget, and it's not native, so don't change it.
5053 }
5054
5055 while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
5056 && !w->testAttribute(Qt::WA_SetCursor))
5057 w = w->parentWidget();
5058
5059 QWidget *nativeParent = w;
5060 if (!w->internalWinId())
5061 nativeParent = w->nativeParentWidget();
5062 if (!nativeParent || !nativeParent->internalWinId())
5063 return;
5064
5065 if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
5066 if (w->isEnabled())
5067 applyCursor(nativeParent, w->cursor());
5068 else
5069 // Enforce the windows behavior of clearing the cursor on
5070 // disabled widgets.
5071 unsetCursor(nativeParent);
5072 } else {
5073 unsetCursor(nativeParent);
5074 }
5075}
5076#endif
5077
5078/*!
5079 \enum QWidget::RenderFlag
5080
5081 This enum describes how to render the widget when calling QWidget::render().
5082
5083 \value DrawWindowBackground If you enable this option, the widget's background
5084 is rendered into the target even if autoFillBackground is not set. By default,
5085 this option is enabled.
5086
5087 \value DrawChildren If you enable this option, the widget's children
5088 are rendered recursively into the target. By default, this option is enabled.
5089
5090 \value IgnoreMask If you enable this option, the widget's QWidget::mask()
5091 is ignored when rendering into the target. By default, this option is disabled.
5092
5093 \since 4.3
5094*/
5095
5096/*!
5097 \since 4.3
5098
5099 Renders the \a sourceRegion of this widget into the \a target
5100 using \a renderFlags to determine how to render. Rendering
5101 starts at \a targetOffset in the \a target. For example:
5102
5103 \snippet code/src_gui_kernel_qwidget.cpp 7
5104
5105 If \a sourceRegion is a null region, this function will use QWidget::rect() as
5106 the region, i.e. the entire widget.
5107
5108 Ensure that you call QPainter::end() for the \a target device's
5109 active painter (if any) before rendering. For example:
5110
5111 \snippet code/src_gui_kernel_qwidget.cpp 8
5112
5113 \note To obtain the contents of a QOpenGLWidget, use QOpenGLWidget::grabFramebuffer()
5114 instead.
5115*/
5116void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
5117 const QRegion &sourceRegion, RenderFlags renderFlags)
5118{
5119 QPainter p(target);
5120 render(&p, targetOffset, sourceRegion, renderFlags);
5121}
5122
5123/*!
5124 \overload
5125
5126 Renders the widget into the \a painter's QPainter::device().
5127
5128 Transformations and settings applied to the \a painter will be used
5129 when rendering.
5130
5131 \note The \a painter must be active. On \macos the widget will be
5132 rendered into a QPixmap and then drawn by the \a painter.
5133
5134 \sa QPainter::device()
5135*/
5136void QWidget::render(QPainter *painter, const QPoint &targetOffset,
5137 const QRegion &sourceRegion, RenderFlags renderFlags)
5138{
5139 if (Q_UNLIKELY(!painter)) {
5140 qWarning("QWidget::render: Null pointer to painter");
5141 return;
5142 }
5143
5144 if (Q_UNLIKELY(!painter->isActive())) {
5145 qWarning("QWidget::render: Cannot render with an inactive painter");
5146 return;
5147 }
5148
5149 const qreal opacity = painter->opacity();
5150 if (qFuzzyIsNull(opacity))
5151 return; // Fully transparent.
5152
5153 Q_D(QWidget);
5154 const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
5155 const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
5156 : sourceRegion;
5157 if (toBePainted.isEmpty())
5158 return;
5159
5160 if (!d->extra)
5161 d->createExtra();
5162 d->extra->inRenderWithPainter = true;
5163
5164 QPaintEngine *engine = painter->paintEngine();
5165 Q_ASSERT(engine);
5166 QPaintEnginePrivate *enginePriv = engine->d_func();
5167 Q_ASSERT(enginePriv);
5168 QPaintDevice *target = engine->paintDevice();
5169 Q_ASSERT(target);
5170
5171 // Render via a pixmap when dealing with non-opaque painters or printers.
5172 if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
5173 d->render_helper(painter, targetOffset, toBePainted, renderFlags);
5174 d->extra->inRenderWithPainter = inRenderWithPainter;
5175 return;
5176 }
5177
5178 // Set new shared painter.
5179 QPainter *oldPainter = d->sharedPainter();
5180 d->setSharedPainter(painter);
5181
5182 // Save current system clip, viewport and transform,
5183 const QTransform oldTransform = enginePriv->systemTransform;
5184 const QRegion oldSystemClip = enginePriv->systemClip;
5185 const QRegion oldBaseClip = enginePriv->baseSystemClip;
5186 const QRegion oldSystemViewport = enginePriv->systemViewport;
5187 const Qt::LayoutDirection oldLayoutDirection = painter->layoutDirection();
5188
5189 // This ensures that all painting triggered by render() is clipped to the current engine clip.
5190 if (painter->hasClipping()) {
5191 const QRegion painterClip = painter->deviceTransform().map(painter->clipRegion());
5192 enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip);
5193 } else {
5194 enginePriv->setSystemViewport(oldSystemClip);
5195 }
5196 painter->setLayoutDirection(layoutDirection());
5197
5198 d->render(target, targetOffset, toBePainted, renderFlags);
5199
5200 // Restore system clip, viewport and transform.
5201 enginePriv->baseSystemClip = oldBaseClip;
5202 enginePriv->setSystemTransformAndViewport(oldTransform, oldSystemViewport);
5203 enginePriv->systemStateChanged();
5204 painter->setLayoutDirection(oldLayoutDirection);
5205
5206 // Restore shared painter.
5207 d->setSharedPainter(oldPainter);
5208
5209 d->extra->inRenderWithPainter = inRenderWithPainter;
5210}
5211
5212static void sendResizeEvents(QWidget *target)
5213{
5214 QResizeEvent e(target->size(), QSize());
5215 QCoreApplication::sendEvent(target, &e);
5216
5217 const QObjectList children = target->children();
5218 for (int i = 0; i < children.size(); ++i) {
5219 if (!children.at(i)->isWidgetType())
5220 continue;
5221 QWidget *child = static_cast<QWidget*>(children.at(i));
5222 if (!child->isWindow() && child->testAttribute(Qt::WA_PendingResizeEvent))
5223 sendResizeEvents(child);
5224 }
5225}
5226
5227/*!
5228 \since 5.0
5229
5230 Renders the widget into a pixmap restricted by the
5231 given \a rectangle. If the widget has any children, then
5232 they are also painted in the appropriate positions.
5233
5234 If a rectangle with an invalid size is specified (the default),
5235 the entire widget is painted.
5236
5237 \sa render(), QPixmap
5238*/
5239QPixmap QWidget::grab(const QRect &rectangle)
5240{
5241 Q_D(QWidget);
5242 if (testAttribute(Qt::WA_PendingResizeEvent) || !testAttribute(Qt::WA_WState_Created))
5243 sendResizeEvents(this);
5244
5245 const QWidget::RenderFlags renderFlags = QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask;
5246
5247 const bool oldDirtyOpaqueChildren = d->dirtyOpaqueChildren;
5248 QRect r(rectangle);
5249 if (r.width() < 0 || r.height() < 0) {
5250 // For grabbing widgets that haven't been shown yet,
5251 // we trigger the layouting mechanism to determine the widget's size.
5252 r = d->prepareToRender(QRegion(), renderFlags).boundingRect();
5253 r.setTopLeft(rectangle.topLeft());
5254 }
5255
5256 if (!r.intersects(rect()))
5257 return QPixmap();
5258
5259 const qreal dpr = devicePixelRatio();
5260 QPixmap res((QSizeF(r.size()) * dpr).toSize());
5261 res.setDevicePixelRatio(dpr);
5262 if (!d->isOpaque || res.hasAlphaChannel())
5263 res.fill(Qt::transparent);
5264 d->render(&res, QPoint(), QRegion(r), renderFlags);
5265
5266 d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
5267 return res;
5268}
5269
5270/*!
5271 \brief The graphicsEffect function returns a pointer to the
5272 widget's graphics effect.
5273
5274 If the widget has no graphics effect, \nullptr is returned.
5275
5276 \since 4.6
5277
5278 \sa setGraphicsEffect()
5279*/
5280#if QT_CONFIG(graphicseffect)
5281QGraphicsEffect *QWidget::graphicsEffect() const
5282{
5283 Q_D(const QWidget);
5284 return d->graphicsEffect;
5285}
5286#endif // QT_CONFIG(graphicseffect)
5287
5288/*!
5289
5290 \brief The setGraphicsEffect function is for setting the widget's graphics effect.
5291
5292 Sets \a effect as the widget's effect. If there already is an effect installed
5293 on this widget, QWidget will delete the existing effect before installing
5294 the new \a effect.
5295
5296 If \a effect is the installed effect on a different widget, setGraphicsEffect() will remove
5297 the effect from the widget and install it on this widget.
5298
5299 QWidget takes ownership of \a effect.
5300
5301 \note This function will apply the effect on itself and all its children.
5302
5303 \note Graphics effects are not supported for OpenGL-based widgets, such as QGLWidget,
5304 QOpenGLWidget and QQuickWidget.
5305
5306 \since 4.6
5307
5308 \sa graphicsEffect()
5309*/
5310#if QT_CONFIG(graphicseffect)
5311void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
5312{
5313 Q_D(QWidget);
5314 if (d->graphicsEffect == effect)
5315 return;
5316
5317 if (d->graphicsEffect) {
5318 d->invalidateBackingStore(rect());
5319 delete d->graphicsEffect;
5320 d->graphicsEffect = nullptr;
5321 }
5322
5323 if (effect) {
5324 // Set new effect.
5325 QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
5326 QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
5327 d->graphicsEffect = effect;
5328 effect->d_func()->setGraphicsEffectSource(source);
5329 update();
5330 }
5331
5332 d->updateIsOpaque();
5333}
5334#endif // QT_CONFIG(graphicseffect)
5335
5336bool QWidgetPrivate::isAboutToShow() const
5337{
5338 if (data.in_show)
5339 return true;
5340
5341 Q_Q(const QWidget);
5342 if (q->isHidden())
5343 return false;
5344
5345 // The widget will be shown if any of its ancestors are about to show.
5346 QWidget *parent = q->parentWidget();
5347 return parent ? parent->d_func()->isAboutToShow() : false;
5348}
5349
5350QRegion QWidgetPrivate::prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags)
5351{
5352 Q_Q(QWidget);
5353 const bool isVisible = q->isVisible();
5354
5355 // Make sure the widget is laid out correctly.
5356 if (!isVisible && !isAboutToShow()) {
5357 QWidget *topLevel = q->window();
5358 (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
5359 topLevel->ensurePolished();
5360
5361 // Invalidate the layout of hidden ancestors (incl. myself) and pretend
5362 // they're not explicitly hidden.
5363 QWidget *widget = q;
5364 QWidgetList hiddenWidgets;
5365 while (widget) {
5366 if (widget->isHidden()) {
5367 widget->setAttribute(Qt::WA_WState_Hidden, false);
5368 hiddenWidgets.append(widget);
5369 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5370 widget->d_func()->updateGeometry_helper(true);
5371 }
5372 widget = widget->parentWidget();
5373 }
5374
5375 // Activate top-level layout.
5376 if (topLevel->d_func()->layout)
5377 topLevel->d_func()->layout->activate();
5378
5379 // Adjust size if necessary.
5380 QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
5381 if (topLevelExtra && !topLevelExtra->sizeAdjusted
5382 && !topLevel->testAttribute(Qt::WA_Resized)) {
5383 topLevel->adjustSize();
5384 topLevel->setAttribute(Qt::WA_Resized, false);
5385 }
5386
5387 // Activate child layouts.
5388 topLevel->d_func()->activateChildLayoutsRecursively();
5389
5390 // We're not cheating with WA_WState_Hidden anymore.
5391 for (int i = 0; i < hiddenWidgets.size(); ++i) {
5392 QWidget *widget = hiddenWidgets.at(i);
5393 widget->setAttribute(Qt::WA_WState_Hidden);
5394 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5395 widget->parentWidget()->d_func()->layout->invalidate();
5396 }
5397 } else if (isVisible) {
5398 q->window()->d_func()->sendPendingMoveAndResizeEvents(true, true);
5399 }
5400
5401 // Calculate the region to be painted.
5402 QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
5403 if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
5404 toBePainted &= extra->mask;
5405 return toBePainted;
5406}
5407
5408void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
5409 QWidget::RenderFlags renderFlags)
5410{
5411 Q_ASSERT(painter);
5412 Q_ASSERT(!toBePainted.isEmpty());
5413
5414 Q_Q(QWidget);
5415 const QTransform originalTransform = painter->worldTransform();
5416 const bool useDeviceCoordinates = originalTransform.isScaling();
5417 if (!useDeviceCoordinates) {
5418 // Render via a pixmap.
5419 const QRect rect = toBePainted.boundingRect();
5420 const QSize size = rect.size();
5421 if (size.isNull())
5422 return;
5423
5424 const qreal pixmapDevicePixelRatio = painter->device()->devicePixelRatio();
5425 QPixmap pixmap(size * pixmapDevicePixelRatio);
5426 pixmap.setDevicePixelRatio(pixmapDevicePixelRatio);
5427
5428 if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque)
5429 pixmap.fill(Qt::transparent);
5430 q->render(&pixmap, QPoint(), toBePainted, renderFlags);
5431
5432 const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
5433 painter->setRenderHints(QPainter::SmoothPixmapTransform, true);
5434
5435 painter->drawPixmap(targetOffset, pixmap);
5436
5437 if (restore)
5438 painter->setRenderHints(QPainter::SmoothPixmapTransform, false);
5439
5440 } else {
5441 // Render via a pixmap in device coordinates (to avoid pixmap scaling).
5442 QTransform transform = originalTransform;
5443 transform.translate(targetOffset.x(), targetOffset.y());
5444
5445 QPaintDevice *device = painter->device();
5446 Q_ASSERT(device);
5447
5448 // Calculate device rect.
5449 const QRectF rect(toBePainted.boundingRect());
5450 QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
5451 deviceRect &= QRect(0, 0, device->width(), device->height());
5452
5453 QPixmap pixmap(deviceRect.size());
5454 pixmap.fill(Qt::transparent);
5455
5456 // Create a pixmap device coordinate painter.
5457 QPainter pixmapPainter(&pixmap);
5458 pixmapPainter.setRenderHints(painter->renderHints());
5459 transform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
5460 pixmapPainter.setTransform(transform);
5461
5462 q->render(&pixmapPainter, QPoint(), toBePainted, renderFlags);
5463 pixmapPainter.end();
5464
5465 // And then draw the pixmap.
5466 painter->setTransform(QTransform());
5467 painter->drawPixmap(deviceRect.topLeft(), pixmap);
5468 painter->setTransform(originalTransform);
5469 }
5470}
5471
5472void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
5473 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5474{
5475 if (rgn.isEmpty())
5476 return;
5477
5478 Q_Q(QWidget);
5479
5480 qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset
5481 << "into paint device" << pdev << "with" << flags;
5482
5483 const bool asRoot = flags & DrawAsRoot;
5484 bool onScreen = shouldPaintOnScreen();
5485
5486#if QT_CONFIG(graphicseffect)
5487 if (graphicsEffect && graphicsEffect->isEnabled()) {
5488 QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
5489 QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
5490 (source->d_func());
5491 if (!sourced->context) {
5492 const QRegion effectRgn((flags & UseEffectRegionBounds) ? rgn.boundingRect() : rgn);
5493 QWidgetPaintContext context(pdev, effectRgn, offset, flags, sharedPainter, repaintManager);
5494 sourced->context = &context;
5495 if (!sharedPainter) {
5496 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), effectRgn.translated(offset));
5497 QPainter p(pdev);
5498 p.translate(offset);
5499 context.painter = &p;
5500 graphicsEffect->draw(&p);
5501 setSystemClip(pdev->paintEngine(), 1, QRegion());
5502 } else {
5503 context.painter = sharedPainter;
5504 if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
5505 sourced->invalidateCache();
5506 sourced->lastEffectTransform = sharedPainter->worldTransform();
5507 }
5508 sharedPainter->save();
5509 sharedPainter->translate(offset);
5510 setSystemClip(sharedPainter->paintEngine(), sharedPainter->device()->devicePixelRatio(), effectRgn.translated(offset));
5511 graphicsEffect->draw(sharedPainter);
5512 setSystemClip(sharedPainter->paintEngine(), 1, QRegion());
5513 sharedPainter->restore();
5514 }
5515 sourced->context = nullptr;
5516
5517 if (repaintManager)
5518 repaintManager->markNeedsFlush(q, effectRgn, offset);
5519
5520 return;
5521 }
5522 }
5523#endif // QT_CONFIG(graphicseffect)
5524 flags = flags & ~UseEffectRegionBounds;
5525
5526 const bool alsoOnScreen = flags & DrawPaintOnScreen;
5527 const bool recursive = flags & DrawRecursive;
5528 const bool alsoInvisible = flags & DrawInvisible;
5529
5530 Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
5531
5532 QRegion toBePainted(rgn);
5533 if (asRoot && !alsoInvisible)
5534 toBePainted &= clipRect(); //(rgn & visibleRegion());
5535 if (!(flags & DontSubtractOpaqueChildren))
5536 subtractOpaqueChildren(toBePainted, q->rect());
5537
5538 if (!toBePainted.isEmpty()) {
5539 if (!onScreen || alsoOnScreen) {
5540 //update the "in paint event" flag
5541 if (Q_UNLIKELY(q->testAttribute(Qt::WA_WState_InPaintEvent)))
5542 qWarning("QWidget::repaint: Recursive repaint detected");
5543 q->setAttribute(Qt::WA_WState_InPaintEvent);
5544
5545 //clip away the new area
5546 QPaintEngine *paintEngine = pdev->paintEngine();
5547 if (paintEngine) {
5548 setRedirected(pdev, -offset);
5549
5550 if (sharedPainter)
5551 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted);
5552 else
5553 paintEngine->d_func()->systemRect = q->data->crect;
5554
5555 //paint the background
5556 if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
5557 && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
5558 beginBackingStorePainting();
5559 QPainter p(q);
5560 p.setRenderHint(QPainter::SmoothPixmapTransform);
5561 paintBackground(&p, toBePainted, (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags());
5562 endBackingStorePainting();
5563 }
5564
5565 if (!sharedPainter)
5566 setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted.translated(offset));
5567
5568 if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
5569 beginBackingStorePainting();
5570 QPainter p(q);
5571 QColor tint = q->palette().window().color();
5572 tint.setAlphaF(.6f);
5573 p.fillRect(toBePainted.boundingRect(), tint);
5574 endBackingStorePainting();
5575 }
5576 }
5577
5578#if 0
5579 qDebug() << "painting" << q << "opaque ==" << isOpaque();
5580 qDebug() << "clipping to" << toBePainted << "location == " << offset
5581 << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
5582#endif
5583
5584 bool skipPaintEvent = false;
5585 if (renderToTexture) {
5586 // This widget renders into a texture which is composed later. We just need to
5587 // punch a hole in the backingstore, so the texture will be visible.
5588 beginBackingStorePainting();
5589 if (!q->testAttribute(Qt::WA_AlwaysStackOnTop) && repaintManager) {
5590 QPainter p(q);
5591 p.setCompositionMode(QPainter::CompositionMode_Source);
5592 p.fillRect(q->rect(), Qt::transparent);
5593 } else if (!repaintManager) {
5594 // We are not drawing to a backingstore: fall back to QImage
5595 QImage img = grabFramebuffer();
5596 // grabFramebuffer() always sets the format to RGB32
5597 // regardless of whether it is transparent or not.
5598 if (img.format() == QImage::Format_RGB32)
5599 img.reinterpretAsFormat(QImage::Format_ARGB32_Premultiplied);
5600 QPainter p(q);
5601 p.drawImage(q->rect(), img);
5602 skipPaintEvent = true;
5603 }
5604 endBackingStorePainting();
5605 if (renderToTextureReallyDirty)
5606 renderToTextureReallyDirty = 0;
5607 else
5608 skipPaintEvent = true;
5609 }
5610
5611 if (!skipPaintEvent) {
5612 //actually send the paint event
5613 sendPaintEvent(toBePainted);
5614 }
5615
5616 if (repaintManager)
5617 repaintManager->markNeedsFlush(q, toBePainted, offset);
5618
5619 //restore
5620 if (paintEngine) {
5621 restoreRedirected();
5622 if (!sharedPainter)
5623 paintEngine->d_func()->systemRect = QRect();
5624 else
5625 paintEngine->d_func()->currentClipDevice = nullptr;
5626
5627 setSystemClip(pdev->paintEngine(), 1, QRegion());
5628 }
5629 q->setAttribute(Qt::WA_WState_InPaintEvent, false);
5630 if (Q_UNLIKELY(q->paintingActive()))
5631 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
5632
5633 if (paintEngine && paintEngine->autoDestruct()) {
5634 delete paintEngine;
5635 }
5636 } else if (q->isWindow()) {
5637 QPaintEngine *engine = pdev->paintEngine();
5638 if (engine) {
5639 QPainter p(pdev);
5640 p.setClipRegion(toBePainted);
5641 const QBrush bg = q->palette().brush(QPalette::Window);
5642 if (bg.style() == Qt::TexturePattern)
5643 p.drawTiledPixmap(q->rect(), bg.texture());
5644 else
5645 p.fillRect(q->rect(), bg);
5646
5647 if (engine->autoDestruct())
5648 delete engine;
5649 }
5650 }
5651 }
5652
5653 if (recursive && !children.isEmpty()) {
5654 paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot,
5655 sharedPainter, repaintManager);
5656 }
5657}
5658
5659void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
5660{
5661 Q_Q(QWidget);
5662 QPaintEvent e(toBePainted);
5663 QCoreApplication::sendSpontaneousEvent(q, &e);
5664
5665 if (renderToTexture)
5666 resolveSamples();
5667}
5668
5669void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
5670 const QRegion &sourceRegion, QWidget::RenderFlags renderFlags)
5671{
5672 if (Q_UNLIKELY(!target)) {
5673 qWarning("QWidget::render: null pointer to paint device");
5674 return;
5675 }
5676
5677 const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
5678 QRegion paintRegion = !inRenderWithPainter
5679 ? prepareToRender(sourceRegion, renderFlags)
5680 : sourceRegion;
5681 if (paintRegion.isEmpty())
5682 return;
5683
5684 QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : nullptr;
5685
5686 // Use the target's shared painter if set (typically set when doing
5687 // "other->render(widget);" in the widget's paintEvent.
5688 if (target->devType() == QInternal::Widget) {
5689 QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
5690 if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
5691 QPainter *targetPainter = targetPrivate->sharedPainter();
5692 if (targetPainter && targetPainter->isActive())
5693 setSharedPainter(targetPainter);
5694 }
5695 }
5696
5697 // Use the target's redirected device if set and adjust offset and paint
5698 // region accordingly. This is typically the case when people call render
5699 // from the paintEvent.
5700 QPoint offset = targetOffset;
5701 offset -= paintRegion.boundingRect().topLeft();
5702 QPoint redirectionOffset;
5703 QPaintDevice *redirected = nullptr;
5704
5705 if (target->devType() == QInternal::Widget)
5706 redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
5707
5708 if (redirected) {
5709 target = redirected;
5710 offset -= redirectionOffset;
5711 }
5712
5713 if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
5714 if (QPaintEngine *targetEngine = target->paintEngine()) {
5715 const QRegion targetSystemClip = targetEngine->systemClip();
5716 if (!targetSystemClip.isEmpty())
5717 paintRegion &= targetSystemClip.translated(-offset);
5718 }
5719 }
5720
5721 // Set backingstore flags.
5722 DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible;
5723 if (renderFlags & QWidget::DrawWindowBackground)
5724 flags |= DrawAsRoot;
5725
5726 if (renderFlags & QWidget::DrawChildren)
5727 flags |= DrawRecursive;
5728 else
5729 flags |= DontSubtractOpaqueChildren;
5730
5731 flags |= DontSetCompositionMode;
5732
5733 // Render via backingstore.
5734 drawWidget(target, paintRegion, offset, flags, sharedPainter());
5735
5736 // Restore shared painter.
5737 if (oldSharedPainter)
5738 setSharedPainter(oldSharedPainter);
5739}
5740
5741void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
5742 const QPoint &offset, DrawWidgetFlags flags
5743 , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5744{
5745 QWidget *w = nullptr;
5746 QRect boundingRect;
5747 bool dirtyBoundingRect = true;
5748 const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
5749 const bool excludeNativeChildren = (flags & DontDrawNativeChildren);
5750
5751 do {
5752 QWidget *x = qobject_cast<QWidget*>(siblings.at(index));
5753 if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()
5754 && !(excludeNativeChildren && x->internalWinId())) {
5755 if (dirtyBoundingRect) {
5756 boundingRect = rgn.boundingRect();
5757 dirtyBoundingRect = false;
5758 }
5759
5760 if (qRectIntersects(boundingRect, x->d_func()->effectiveRectFor(x->data->crect))) {
5761 w = x;
5762 break;
5763 }
5764 }
5765 --index;
5766 } while (index >= 0);
5767
5768 if (!w)
5769 return;
5770
5771 QWidgetPrivate *wd = w->d_func();
5772 const QPoint widgetPos(w->data->crect.topLeft());
5773 const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
5774 if (index > 0) {
5775 QRegion wr(rgn);
5776 if (wd->isOpaque)
5777 wr -= hasMask ? wd->extra->mask.translated(widgetPos) : w->data->crect;
5778 paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags,
5779 sharedPainter, repaintManager);
5780 }
5781
5782 if (w->updatesEnabled()
5783#if QT_CONFIG(graphicsview)
5784 && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)
5785#endif // QT_CONFIG(graphicsview)
5786 ) {
5787 QRegion wRegion(rgn);
5788 wRegion &= wd->effectiveRectFor(w->data->crect);
5789 wRegion.translate(-widgetPos);
5790 if (hasMask)
5791 wRegion &= wd->extra->mask;
5792 wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, repaintManager);
5793 }
5794}
5795
5796#if QT_CONFIG(graphicseffect)
5797QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
5798{
5799 if (system != Qt::DeviceCoordinates)
5800 return m_widget->rect();
5801
5802 if (Q_UNLIKELY(!context)) {
5803 // Device coordinates without context not yet supported.
5804 qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
5805 return QRectF();
5806 }
5807
5808 return context->painter->worldTransform().mapRect(m_widget->rect());
5809}
5810
5811void QWidgetEffectSourcePrivate::draw(QPainter *painter)
5812{
5813 if (!context || context->painter != painter) {
5814 m_widget->render(painter);
5815 return;
5816 }
5817
5818 // The region saved in the context is neither clipped to the rect
5819 // nor the mask, so we have to clip it here before calling drawWidget.
5820 QRegion toBePainted = context->rgn;
5821 toBePainted &= m_widget->rect();
5822 QWidgetPrivate *wd = qt_widget_private(m_widget);
5823 if (wd->extra && wd->extra->hasMask)
5824 toBePainted &= wd->extra->mask;
5825
5826 wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags,
5827 context->sharedPainter, context->repaintManager);
5828}
5829
5830QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
5831 QGraphicsEffect::PixmapPadMode mode) const
5832{
5833 const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
5834 if (Q_UNLIKELY(!context && deviceCoordinates)) {
5835 // Device coordinates without context not yet supported.
5836 qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
5837 return QPixmap();
5838 }
5839
5840 QPoint pixmapOffset;
5841 QRectF sourceRect = m_widget->rect();
5842
5843 if (deviceCoordinates) {
5844 const QTransform &painterTransform = context->painter->worldTransform();
5845 sourceRect = painterTransform.mapRect(sourceRect);
5846 pixmapOffset = painterTransform.map(pixmapOffset);
5847 }
5848
5849 QRect effectRect;
5850
5851 if (mode == QGraphicsEffect::PadToEffectiveBoundingRect)
5852 effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
5853 else if (mode == QGraphicsEffect::PadToTransparentBorder)
5854 effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect();
5855 else
5856 effectRect = sourceRect.toAlignedRect();
5857
5858 if (offset)
5859 *offset = effectRect.topLeft();
5860
5861 pixmapOffset -= effectRect.topLeft();
5862
5863 qreal dpr(1.0);
5864 if (const auto *paintDevice = context->painter->device())
5865 dpr = paintDevice->devicePixelRatio();
5866 else
5867 qWarning("QWidgetEffectSourcePrivate::pixmap: Painter not active");
5868 QPixmap pixmap(effectRect.size() * dpr);
5869 pixmap.setDevicePixelRatio(dpr);
5870
5871 pixmap.fill(Qt::transparent);
5872 m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren);
5873 return pixmap;
5874}
5875#endif // QT_CONFIG(graphicseffect)
5876
5877#if QT_CONFIG(graphicsview)
5878/*!
5879 \internal
5880
5881 Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
5882 widget and its ancestors. The search starts at \a origin (inclusive).
5883 If successful, the function returns the proxy that embeds the widget, or \nullptr if no
5884 embedded widget was found.
5885*/
5886QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
5887{
5888 if (origin) {
5889 const auto &extra = origin->d_func()->extra;
5890 if (extra && extra->proxyWidget)
5891 return extra->proxyWidget;
5892 return nearestGraphicsProxyWidget(origin->parentWidget());
5893 }
5894 return nullptr;
5895}
5896#endif
5897
5898/*!
5899 \property QWidget::locale
5900 \brief the widget's locale
5901 \since 4.3
5902
5903 As long as no special locale has been set, this is either
5904 the parent's locale or (if this widget is a top level widget),
5905 the default locale.
5906
5907 If the widget displays dates or numbers, these should be formatted
5908 using the widget's locale.
5909
5910 \sa QLocale, QLocale::setDefault()
5911*/
5912
5913void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
5914{
5915 Q_Q(QWidget);
5916 if (locale == loc && !forceUpdate)
5917 return;
5918
5919 locale = loc;
5920
5921 if (!children.isEmpty()) {
5922 for (int i = 0; i < children.size(); ++i) {
5923 QWidget *w = qobject_cast<QWidget*>(children.at(i));
5924 if (!w)
5925 continue;
5926 if (w->testAttribute(Qt::WA_SetLocale))
5927 continue;
5928 if (w->isWindow() && !w->testAttribute(Qt::WA_WindowPropagation))
5929 continue;
5930 w->d_func()->setLocale_helper(loc, forceUpdate);
5931 }
5932 }
5933 QEvent e(QEvent::LocaleChange);
5934 QCoreApplication::sendEvent(q, &e);
5935}
5936
5937void QWidget::setLocale(const QLocale &locale)
5938{
5939 Q_D(QWidget);
5940
5941 setAttribute(Qt::WA_SetLocale);
5942 d->setLocale_helper(locale);
5943}
5944
5945QLocale QWidget::locale() const
5946{
5947 Q_D(const QWidget);
5948
5949 return d->locale;
5950}
5951
5952void QWidgetPrivate::resolveLocale()
5953{
5954 Q_Q(const QWidget);
5955
5956 if (!q->testAttribute(Qt::WA_SetLocale)) {
5957 QWidget *parent = q->parentWidget();
5958 setLocale_helper(!parent || (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
5959 ? QLocale() : parent->locale());
5960 }
5961}
5962
5963void QWidget::unsetLocale()
5964{
5965 Q_D(QWidget);
5966 setAttribute(Qt::WA_SetLocale, false);
5967 d->resolveLocale();
5968}
5969
5970/*!
5971 \property QWidget::windowTitle
5972 \brief the window title (caption)
5973
5974 This property only makes sense for top-level widgets, such as
5975 windows and dialogs. If no caption has been set, the title is based of the
5976 \l windowFilePath. If neither of these is set, then the title is
5977 an empty string.
5978
5979 If you use the \l windowModified mechanism, the window title must
5980 contain a "[*]" placeholder, which indicates where the '*' should
5981 appear. Normally, it should appear right after the file name
5982 (e.g., "document1.txt[*] - Text Editor"). If the \l
5983 windowModified property is \c false (the default), the placeholder
5984 is simply removed.
5985
5986 On some desktop platforms (including Windows and Unix), the application name
5987 (from QGuiApplication::applicationDisplayName) is added at the end of the
5988 window title, if set. This is done by the QPA plugin, so it is shown to the
5989 user, but isn't part of the windowTitle string.
5990
5991 \sa windowIcon, windowModified, windowFilePath
5992*/
5993QString QWidget::windowTitle() const
5994{
5995 Q_D(const QWidget);
5996 if (d->extra && d->extra->topextra) {
5997 if (!d->extra->topextra->caption.isEmpty())
5998 return d->extra->topextra->caption;
5999 if (!d->extra->topextra->filePath.isEmpty())
6000 return QFileInfo(d->extra->topextra->filePath).fileName() + "[*]"_L1;
6001 }
6002 return QString();
6003}
6004
6005/*!
6006 Returns a modified window title with the [*] place holder
6007 replaced according to the rules described in QWidget::setWindowTitle
6008
6009 This function assumes that "[*]" can be quoted by another
6010 "[*]", so it will replace two place holders by one and
6011 a single last one by either "*" or nothing depending on
6012 the modified flag.
6013
6014 \internal
6015*/
6016QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
6017{
6018 Q_ASSERT(widget);
6019
6020 QString cap = title;
6021 if (cap.isEmpty())
6022 return cap;
6023
6024 const auto placeHolder = "[*]"_L1;
6025 int index = cap.indexOf(placeHolder);
6026
6027 // here the magic begins
6028 while (index != -1) {
6029 index += placeHolder.size();
6030 int count = 1;
6031 while (cap.indexOf(placeHolder, index) == index) {
6032 ++count;
6033 index += placeHolder.size();
6034 }
6035
6036 if (count%2) { // odd number of [*] -> replace last one
6037 int lastIndex = cap.lastIndexOf(placeHolder, index - 1);
6038 if (widget->isWindowModified()
6039 && widget->style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, nullptr, widget))
6040 cap.replace(lastIndex, 3, QWidget::tr("*"));
6041 else
6042 cap.remove(lastIndex, 3);
6043 }
6044
6045 index = cap.indexOf(placeHolder, index);
6046 }
6047
6048 cap.replace("[*][*]"_L1, placeHolder);
6049
6050 return cap;
6051}
6052
6053void QWidgetPrivate::setWindowTitle_helper(const QString &title)
6054{
6055 Q_Q(QWidget);
6056 if (q->testAttribute(Qt::WA_WState_Created))
6057 setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, q));
6058}
6059
6060void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
6061{
6062 Q_Q(QWidget);
6063 if (!q->isWindow())
6064 return;
6065
6066 if (QWindow *window = q->windowHandle())
6067 {
6068#if QT_CONFIG(accessibility)
6069 QString oldAccessibleName;
6070 const QAccessibleInterface *accessible = QAccessible::isActive()
6071 ? QAccessible::queryAccessibleInterface(q)
6072 : nullptr;
6073 if (accessible)
6074 oldAccessibleName = accessible->text(QAccessible::Name);
6075#endif
6076
6077 window->setTitle(caption);
6078
6079#if QT_CONFIG(accessibility)
6080 if (accessible && accessible->text(QAccessible::Name) != oldAccessibleName) {
6081 QAccessibleEvent event(q, QAccessible::NameChanged);
6082 QAccessible::updateAccessibility(&event);
6083 }
6084#endif
6085 }
6086}
6087
6088void QWidgetPrivate::setWindowIconText_helper(const QString &title)
6089{
6090 Q_Q(QWidget);
6091 if (q->testAttribute(Qt::WA_WState_Created))
6092 setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, q));
6093}
6094
6095void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
6096{
6097#if QT_CONFIG(xcb)
6098 Q_Q(QWidget);
6099 // ### The QWidget property is deprecated, but the XCB window function is not.
6100 // It should remain available for the rare application that needs it.
6101 if (QWindow *window = q->windowHandle()) {
6102 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(window->handle()))
6103 xcbWindow->setWindowIconText(iconText);
6104 }
6105#else
6106 Q_UNUSED(iconText);
6107#endif
6108}
6109
6110/*!
6111 \fn void QWidget::windowIconTextChanged(const QString &iconText)
6112
6113 This signal is emitted when the window's icon text has changed, with the
6114 new \a iconText as an argument.
6115
6116 \since 5.2
6117 \deprecated
6118
6119 This signal is deprecated.
6120*/
6121
6122void QWidget::setWindowIconText(const QString &iconText)
6123{
6124 if (QWidget::windowIconText() == iconText)
6125 return;
6126
6127 Q_D(QWidget);
6128 d->topData()->iconText = iconText;
6129 d->setWindowIconText_helper(iconText);
6130
6131 QEvent e(QEvent::IconTextChange);
6132 QCoreApplication::sendEvent(this, &e);
6133
6134 emit windowIconTextChanged(iconText);
6135}
6136
6137/*!
6138 \fn void QWidget::windowTitleChanged(const QString &title)
6139
6140 This signal is emitted when the window's title has changed, with the
6141 new \a title as an argument.
6142
6143 \since 5.2
6144*/
6145
6146void QWidget::setWindowTitle(const QString &title)
6147{
6148 if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
6149 return;
6150
6151 Q_D(QWidget);
6152 d->topData()->caption = title;
6153 d->setWindowTitle_helper(title);
6154
6155 QEvent e(QEvent::WindowTitleChange);
6156 QCoreApplication::sendEvent(this, &e);
6157
6158 emit windowTitleChanged(title);
6159}
6160
6161
6162/*!
6163 \property QWidget::windowIcon
6164 \brief the widget's icon
6165
6166 This property only makes sense for windows. If no icon
6167 has been set, windowIcon() returns the application icon
6168 (QApplication::windowIcon()).
6169
6170 \note On \macos, window icons represent the active document,
6171 and will not be displayed unless a file path has also been
6172 set using setWindowFilePath.
6173
6174 \sa windowTitle, setWindowFilePath
6175*/
6176QIcon QWidget::windowIcon() const
6177{
6178 const QWidget *w = this;
6179 while (w) {
6180 const QWidgetPrivate *d = w->d_func();
6181 if (d->extra && d->extra->topextra && d->extra->topextra->icon)
6182 return *d->extra->topextra->icon;
6183 w = w->parentWidget();
6184 }
6185 return QApplication::windowIcon();
6186}
6187
6188void QWidgetPrivate::setWindowIcon_helper()
6189{
6190 Q_Q(QWidget);
6191 QEvent e(QEvent::WindowIconChange);
6192
6193 // Do not send the event if the widget is a top level.
6194 // In that case, setWindowIcon_sys does it, and event propagation from
6195 // QWidgetWindow to the top level QWidget ensures that the event reaches
6196 // the top level anyhow
6197 if (!q->windowHandle())
6198 QCoreApplication::sendEvent(q, &e);
6199 for (int i = 0; i < children.size(); ++i) {
6200 QWidget *w = qobject_cast<QWidget *>(children.at(i));
6201 if (w && !w->isWindow())
6202 QCoreApplication::sendEvent(w, &e);
6203 }
6204}
6205
6206/*!
6207 \fn void QWidget::windowIconChanged(const QIcon &icon)
6208
6209 This signal is emitted when the window's icon has changed, with the
6210 new \a icon as an argument.
6211
6212 \since 5.2
6213*/
6214
6215void QWidget::setWindowIcon(const QIcon &icon)
6216{
6217 Q_D(QWidget);
6218
6219 setAttribute(Qt::WA_SetWindowIcon, !icon.isNull());
6220 d->createTLExtra();
6221
6222 if (!d->extra->topextra->icon)
6223 d->extra->topextra->icon = std::make_unique<QIcon>(icon);
6224 else
6225 *d->extra->topextra->icon = icon;
6226
6227 d->setWindowIcon_sys();
6228 d->setWindowIcon_helper();
6229
6230 emit windowIconChanged(icon);
6231}
6232
6233void QWidgetPrivate::setWindowIcon_sys()
6234{
6235 Q_Q(QWidget);
6236 if (QWindow *window = q->windowHandle())
6237 window->setIcon(q->windowIcon());
6238}
6239
6240/*!
6241 \property QWidget::windowIconText
6242 \brief the text to be displayed on the icon of a minimized window
6243
6244 This property only makes sense for windows. If no icon
6245 text has been set, this accessor returns an empty string.
6246 It is only implemented on the X11 platform, and only certain
6247 window managers use this window property.
6248
6249 \deprecated
6250 This property is deprecated.
6251
6252 \sa windowIcon, windowTitle
6253*/
6254
6255QString QWidget::windowIconText() const
6256{
6257 Q_D(const QWidget);
6258 return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
6259}
6260
6261/*!
6262 \property QWidget::windowFilePath
6263 \since 4.4
6264 \brief the file path associated with a widget
6265
6266 This property only makes sense for windows. It associates a file path with
6267 a window. If you set the file path, but have not set the window title, Qt
6268 sets the window title to the file name of the specified path, obtained using
6269 QFileInfo::fileName().
6270
6271 If the window title is set at any point, then the window title takes precedence and
6272 will be shown instead of the file path string.
6273
6274 Additionally, on \macos, this has an added benefit that it sets the
6275 \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
6276 for the window, assuming that the file path exists.
6277
6278 If no file path is set, this property contains an empty string.
6279
6280 By default, this property contains an empty string.
6281
6282 \sa windowTitle, windowIcon
6283*/
6284
6285QString QWidget::windowFilePath() const
6286{
6287 Q_D(const QWidget);
6288 return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
6289}
6290
6291void QWidget::setWindowFilePath(const QString &filePath)
6292{
6293 if (filePath == windowFilePath())
6294 return;
6295
6296 Q_D(QWidget);
6297
6298 d->createTLExtra();
6299 d->extra->topextra->filePath = filePath;
6300 d->setWindowFilePath_helper(filePath);
6301}
6302
6303void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
6304{
6305 if (extra->topextra && extra->topextra->caption.isEmpty()) {
6306#ifdef Q_OS_MACOS
6307 setWindowTitle_helper(QFileInfo(filePath).fileName());
6308#else
6309 Q_Q(QWidget);
6310 Q_UNUSED(filePath);
6311 setWindowTitle_helper(q->windowTitle());
6312#endif
6313 }
6314#ifdef Q_OS_MACOS
6315 setWindowFilePath_sys(filePath);
6316#endif
6317}
6318
6319void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
6320{
6321 Q_Q(QWidget);
6322 if (!q->isWindow())
6323 return;
6324
6325 if (QWindow *window = q->windowHandle())
6326 window->setFilePath(filePath);
6327}
6328
6329/*!
6330 Returns the window's role, or an empty string.
6331
6332 \sa windowIcon, windowTitle
6333*/
6334
6335QString QWidget::windowRole() const
6336{
6337 Q_D(const QWidget);
6338 return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
6339}
6340
6341/*!
6342 Sets the window's role to \a role. This only makes sense for
6343 windows on X11.
6344*/
6345void QWidget::setWindowRole(const QString &role)
6346{
6347#if QT_CONFIG(xcb) || QT_CONFIG(wayland)
6348 Q_D(QWidget);
6349 d->createTLExtra();
6350 d->topData()->role = role;
6351#else
6352 Q_UNUSED(role);
6353#endif
6354
6355 if (windowHandle()) {
6356#if QT_CONFIG(xcb)
6357 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(windowHandle()->handle()))
6358 xcbWindow->setWindowRole(role);
6359#endif
6360#if QT_CONFIG(wayland)
6361 if (auto *waylandWindow = dynamic_cast<QWaylandWindow*>(windowHandle()->handle()))
6362 waylandWindow->setSessionRestoreId(role);
6363#endif
6364 }
6365}
6366
6367/*!
6368 \property QWidget::mouseTracking
6369 \brief whether mouse tracking is enabled for the widget
6370
6371 If mouse tracking is disabled (the default), the widget only
6372 receives mouse move events when at least one mouse button is
6373 pressed while the mouse is being moved.
6374
6375 If mouse tracking is enabled, the widget receives mouse move
6376 events even if no buttons are pressed.
6377
6378 \sa mouseMoveEvent()
6379*/
6380
6381/*!
6382 \property QWidget::tabletTracking
6383 \brief whether tablet tracking is enabled for the widget
6384 \since 5.9
6385
6386 If tablet tracking is disabled (the default), the widget only
6387 receives tablet move events when the stylus is in contact with
6388 the tablet, or at least one stylus button is pressed,
6389 while the stylus is being moved.
6390
6391 If tablet tracking is enabled, the widget receives tablet move
6392 events even while hovering in proximity. This is useful for
6393 monitoring position as well as the auxiliary properties such
6394 as rotation and tilt, and providing feedback in the UI.
6395
6396 \sa tabletEvent()
6397*/
6398
6399
6400/*!
6401 Sets the widget's focus proxy to widget \a w. If \a w is \nullptr, the
6402 function resets this widget to have no focus proxy.
6403
6404 Some widgets can "have focus", but create a child widget, such as
6405 QLineEdit, to actually handle the focus. In this case, the widget
6406 can set the line edit to be its focus proxy.
6407
6408 setFocusProxy() sets the widget which will actually get focus when
6409 "this widget" gets it. If there is a focus proxy, setFocus() and
6410 hasFocus() operate on the focus proxy. If "this widget" is the focus
6411 widget, then setFocusProxy() moves focus to the new focus proxy.
6412
6413 \sa focusProxy()
6414*/
6415
6416void QWidget::setFocusProxy(QWidget * w)
6417{
6418 Q_D(QWidget);
6419 if (!w && !d->extra)
6420 return;
6421
6422 for (QWidget* fp = w; fp; fp = fp->focusProxy()) {
6423 if (Q_UNLIKELY(fp == this)) {
6424 qWarning("QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
6425 return;
6426 }
6427 }
6428
6429 const bool moveFocusToProxy = (QApplicationPrivate::focus_widget == this);
6430
6431 d->createExtra();
6432 d->extra->focus_proxy = w;
6433
6434 if (w && isAncestorOf(w)) {
6435 // If the focus proxy is a child of this (so this is a compound widget), then
6436 // we need to make sure that this widget is immediately in front of its own children
6437 // in the focus chain. Otherwise focusNextPrev_helper might jump over unrelated
6438 // widgets that are positioned between this compound widget, and its proxy in
6439 // the focus chain.
6440 const QWidget *parentOfW = w->parentWidget();
6441 Q_ASSERT(parentOfW); // can't be nullptr since we are an ancestor of w
6442 QWidget *firstChild = nullptr;
6443 const auto childList = children();
6444 for (QObject *child : childList) {
6445 if ((firstChild = qobject_cast<QWidget *>(child)))
6446 break;
6447 }
6448 Q_ASSERT(firstChild); // can't be nullptr since w is a child
6449 d->insertIntoFocusChainBefore(firstChild);
6450 } else if (w && w->isAncestorOf(this)) {
6451 // If the focus proxy is a parent, 'this' has to be inserted directly after its parent in the focus chain
6452 // remove it from the chain and insert this into the focus chain after its parent
6453
6454 // is this the case already?
6455 QWidget *parentsNext = w->nextInFocusChain();
6456 if (parentsNext == this) {
6457 // nothing to do.
6458 Q_ASSERT(previousInFocusChain() == w);
6459 } else {
6460 d->QWidgetPrivate::insertIntoFocusChainAfter(w);
6461 }
6462 }
6463
6464 if (moveFocusToProxy)
6465 setFocus(Qt::OtherFocusReason);
6466}
6467
6468
6469/*!
6470 Returns the focus proxy, or \nullptr if there is no focus proxy.
6471
6472 \sa setFocusProxy()
6473*/
6474
6475QWidget *QWidget::focusProxy() const
6476{
6477 Q_D(const QWidget);
6478 return d->extra ? d->extra->focus_proxy.data() : nullptr;
6479}
6480
6481
6482/*!
6483 \property QWidget::focus
6484 \brief whether this widget (or its focus proxy) has the keyboard
6485 input focus
6486
6487 By default, this property is \c false.
6488
6489 \note Obtaining the value of this property for a widget is effectively equivalent
6490 to checking whether QApplication::focusWidget() refers to the widget.
6491
6492 \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
6493*/
6494bool QWidget::hasFocus() const
6495{
6496 const QWidget* w = this;
6497 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
6498 w = w->d_func()->extra->focus_proxy;
6499#if QT_CONFIG(graphicsview)
6500 if (QWidget *window = w->window()) {
6501 const auto &e = window->d_func()->extra;
6502 if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
6503 return true;
6504 }
6505#endif // QT_CONFIG(graphicsview)
6506 return (QApplication::focusWidget() == w);
6507}
6508
6509/*!
6510 Gives the keyboard input focus to this widget (or its focus
6511 proxy) if this widget or one of its parents is the \l{isActiveWindow()}{active window}. The \a reason argument will
6512 be passed into any focus event sent from this function, it is used
6513 to give an explanation of what caused the widget to get focus.
6514 If the window is not active, the widget will be given the focus when
6515 the window becomes active.
6516
6517 First, a focus about to change event is sent to the focus widget (if any) to
6518 tell it that it is about to lose the focus. Then focus is changed, a
6519 focus out event is sent to the previous focus item and a focus in event is sent
6520 to the new item to tell it that it just received the focus.
6521 (Nothing happens if the focus in and focus out widgets are the
6522 same.)
6523
6524 \note On embedded platforms, setFocus() will not cause an input panel
6525 to be opened by the input method. If you want this to happen, you
6526 have to send a QEvent::RequestSoftwareInputPanel event to the
6527 widget yourself.
6528
6529 setFocus() gives focus to a widget regardless of its focus policy,
6530 but does not clear any keyboard grab (see grabKeyboard()).
6531
6532 Be aware that if the widget is hidden, it will not accept focus
6533 until it is shown.
6534
6535 \warning If you call setFocus() in a function which may itself be
6536 called from focusOutEvent() or focusInEvent(), you may get an
6537 infinite recursion.
6538
6539 \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
6540 setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
6541 grabMouse(), {Keyboard Focus in Widgets}, QEvent::RequestSoftwareInputPanel
6542*/
6543
6544void QWidget::setFocus(Qt::FocusReason reason)
6545{
6546 if (!isEnabled())
6547 return;
6548
6549 QWidget *f = d_func()->deepestFocusProxy();
6550 if (!f)
6551 f = this;
6552
6553 if (QApplication::focusWidget() == f)
6554 return;
6555
6556#if QT_CONFIG(graphicsview)
6557 QWidget *previousProxyFocus = nullptr;
6558 if (const auto &topData = window()->d_func()->extra) {
6559 if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
6560 previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
6561 if (previousProxyFocus && previousProxyFocus->focusProxy())
6562 previousProxyFocus = previousProxyFocus->focusProxy();
6563 if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
6564 return;
6565 }
6566 }
6567#endif
6568
6569#if QT_CONFIG(graphicsview)
6570 // Update proxy state
6571 if (const auto &topData = window()->d_func()->extra) {
6572 if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
6573 f->d_func()->updateFocusChild();
6574 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
6575 topData->proxyWidget->setFocus(reason);
6576 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
6577 }
6578 }
6579#endif
6580
6581 if (f->isActiveWindow()) {
6582 QWidget *prev = QApplicationPrivate::focus_widget;
6583 if (prev) {
6584 if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
6585 && prev->testAttribute(Qt::WA_InputMethodEnabled)) {
6586 QGuiApplication::inputMethod()->commit();
6587 }
6588
6589 if (reason != Qt::NoFocusReason) {
6590 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
6591 QCoreApplication::sendEvent(prev, &focusAboutToChange);
6592 }
6593 }
6594
6595 f->d_func()->updateFocusChild();
6596
6597 QApplicationPrivate::setFocusWidget(f, reason);
6598#if QT_CONFIG(accessibility)
6599 // menus update the focus manually and this would create bogus events
6600 if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem")))
6601 {
6602 QAccessibleEvent event(f, QAccessible::Focus);
6603 QAccessible::updateAccessibility(&event);
6604 }
6605#endif
6606#if QT_CONFIG(graphicsview)
6607 if (const auto &topData = window()->d_func()->extra) {
6608 if (topData->proxyWidget) {
6609 if (previousProxyFocus && previousProxyFocus != f) {
6610 // Send event to self
6611 QFocusEvent event(QEvent::FocusOut, reason);
6612 QPointer<QWidget> that = previousProxyFocus;
6613 QCoreApplication::sendEvent(previousProxyFocus, &event);
6614 if (that)
6615 QCoreApplication::sendEvent(that->style(), &event);
6616 }
6617 if (!isHidden()) {
6618#if QT_CONFIG(graphicsview)
6619 // Update proxy state
6620 if (const auto &topData = window()->d_func()->extra)
6621 if (topData->proxyWidget && topData->proxyWidget->hasFocus())
6622 topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget();
6623#endif
6624 // Send event to self
6625 QFocusEvent event(QEvent::FocusIn, reason);
6626 QPointer<QWidget> that = f;
6627 QCoreApplication::sendEvent(f, &event);
6628 if (that)
6629 QCoreApplication::sendEvent(that->style(), &event);
6630 }
6631 }
6632 }
6633#endif
6634 } else {
6635 f->d_func()->updateFocusChild();
6636 }
6637}
6638
6639
6640/*!\internal
6641 * A focus proxy can have its own focus proxy, which can have its own
6642 * proxy, and so on. This helper function returns the widget that sits
6643 * at the bottom of the proxy chain, and therefore the one that should
6644 * normally get focus if this widget receives a focus request.
6645 */
6646QWidget *QWidgetPrivate::deepestFocusProxy() const
6647{
6648 Q_Q(const QWidget);
6649
6650 QWidget *focusProxy = q->focusProxy();
6651 if (!focusProxy)
6652 return nullptr;
6653
6654 while (QWidget *nextFocusProxy = focusProxy->focusProxy())
6655 focusProxy = nextFocusProxy;
6656
6657 return focusProxy;
6658}
6659
6660static inline bool isEmbedded(const QWindow *w)
6661{
6662 const auto platformWindow = w->handle();
6663 return platformWindow && platformWindow->isEmbedded();
6664}
6665
6666void QWidgetPrivate::setFocus_sys()
6667{
6668 Q_Q(QWidget);
6669 // Embedded native widget may have taken the focus; get it back to toplevel
6670 // if that is the case (QTBUG-25852), unless widget is a window container.
6671 if (extra && extra->hasWindowContainer)
6672 return;
6673 // Do not activate in case the popup menu opens another application (QTBUG-70810)
6674 // unless the application is embedded (QTBUG-71991).
6675 if (QWindow *nativeWindow = q->testAttribute(Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) {
6676 if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow()
6677 && (QGuiApplication::applicationState() == Qt::ApplicationActive
6678 || QCoreApplication::testAttribute(Qt::AA_PluginApplication)
6679 || isEmbedded(nativeWindow))) {
6680 nativeWindow->requestActivate();
6681 }
6682 }
6683}
6684
6685// updates focus_child on parent widgets to point into this widget
6686void QWidgetPrivate::updateFocusChild()
6687{
6688 Q_Q(QWidget);
6689
6690 QWidget *w = q;
6691 if (q->isHidden()) {
6692 while (w && w->isHidden()) {
6693 w->d_func()->focus_child = q;
6694 w = w->isWindow() ? nullptr : w->parentWidget();
6695 }
6696 } else {
6697 while (w) {
6698 w->d_func()->focus_child = q;
6699 w = w->isWindow() ? nullptr : w->parentWidget();
6700 }
6701 }
6702
6703 if (QTLWExtra *extra = q->window()->d_func()->maybeTopData()) {
6704 if (extra->window)
6705 emit extra->window->focusObjectChanged(q);
6706 }
6707}
6708
6709/*!
6710 \fn void QWidget::setFocus()
6711 \overload
6712
6713 Gives the keyboard input focus to this widget (or its focus
6714 proxy) if this widget or one of its parents is the
6715 \l{isActiveWindow()}{active window}.
6716*/
6717
6718/*!
6719 Takes keyboard input focus from the widget.
6720
6721 If the widget has active focus, a \l{focusOutEvent()}{focus out event} is sent to this widget to tell it that it has
6722 lost the focus.
6723
6724 This widget must enable focus setting to get the keyboard
6725 input focus; that is, it must call setFocusPolicy().
6726
6727 \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
6728 setFocusPolicy(), QApplication::focusWidget()
6729*/
6730
6731void QWidget::clearFocus()
6732{
6733 if (hasFocus()) {
6734 if (testAttribute(Qt::WA_InputMethodEnabled))
6735 QGuiApplication::inputMethod()->commit();
6736
6737 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
6738 QCoreApplication::sendEvent(this, &focusAboutToChange);
6739 }
6740
6741 QTLWExtra *extra = window()->d_func()->maybeTopData();
6742 QObject *originalFocusObject = nullptr;
6743 if (extra && extra->window) {
6744 originalFocusObject = extra->window->focusObject();
6745 // the window's focus object might already be nullptr if we are in the destructor, but we still
6746 // need to update QGuiApplication and input context if we have a focus widget.
6747 if (!originalFocusObject)
6748 originalFocusObject = focusWidget();
6749 }
6750
6751 QWidget *w = this;
6752 while (w) {
6753 // Just like setFocus(), we update (clear) the focus_child of our parents
6754 if (w->d_func()->focus_child == this)
6755 w->d_func()->focus_child = nullptr;
6756 w = w->parentWidget();
6757 }
6758
6759 // We've potentially cleared the focus_child of our parents, so we need
6760 // to report this to the rest of Qt. Note that the focus_child is not the same
6761 // thing as the application's focusWidget, which is why this piece of code is
6762 // not inside a hasFocus() block.
6763 if (originalFocusObject && originalFocusObject != extra->window->focusObject())
6764 emit extra->window->focusObjectChanged(extra->window->focusObject());
6765
6766#if QT_CONFIG(graphicsview)
6767 const auto &topData = d_func()->extra;
6768 if (topData && topData->proxyWidget)
6769 topData->proxyWidget->clearFocus();
6770#endif
6771
6772 if (hasFocus()) {
6773 // Update proxy state
6774 QApplicationPrivate::setFocusWidget(nullptr, Qt::OtherFocusReason);
6775#if QT_CONFIG(accessibility)
6776 QAccessibleEvent event(this, QAccessible::Focus);
6777 QAccessible::updateAccessibility(&event);
6778#endif
6779 }
6780}
6781
6782
6783/*!
6784 \fn bool QWidget::focusNextChild()
6785
6786 Finds a new widget to give the keyboard focus to, as appropriate
6787 for \uicontrol Tab, and returns \c true if it can find a new widget, or
6788 false if it can't.
6789
6790 \sa focusPreviousChild()
6791*/
6792
6793/*!
6794 \fn bool QWidget::focusPreviousChild()
6795
6796 Finds a new widget to give the keyboard focus to, as appropriate
6797 for \uicontrol Shift+Tab, and returns \c true if it can find a new widget,
6798 or false if it can't.
6799
6800 \sa focusNextChild()
6801*/
6802
6803/*!
6804 Finds a new widget to give the keyboard focus to, as appropriate
6805 for Tab and Shift+Tab, and returns \c true if it can find a new
6806 widget, or false if it can't.
6807
6808 If \a next is true, this function searches forward, if \a next
6809 is false, it searches backward.
6810
6811 Sometimes, you will want to reimplement this function. For
6812 example, a web browser might reimplement it to move its "current
6813 active link" forward or backward, and call
6814 focusNextPrevChild() only when it reaches the last or
6815 first link on the "page".
6816
6817 Child widgets call focusNextPrevChild() on their parent widgets,
6818 but only the window that contains the child widgets decides where
6819 to redirect focus. By reimplementing this function for an object,
6820 you thus gain control of focus traversal for all child widgets.
6821
6822 \sa focusNextChild(), focusPreviousChild()
6823*/
6824
6825bool QWidget::focusNextPrevChild(bool next)
6826{
6827 QWidget* p = parentWidget();
6828 bool isSubWindow = (windowType() == Qt::SubWindow);
6829 if (!isWindow() && !isSubWindow && p)
6830 return p->focusNextPrevChild(next);
6831#if QT_CONFIG(graphicsview)
6832 Q_D(QWidget);
6833 if (d->extra && d->extra->proxyWidget)
6834 return d->extra->proxyWidget->focusNextPrevChild(next);
6835#endif
6836
6837 bool wrappingOccurred = false;
6838 QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(this, next,
6839 &wrappingOccurred);
6840 if (!w) return false;
6841
6842 Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
6843
6844 /* If we are about to wrap the focus chain, give the platform
6845 * implementation a chance to alter the wrapping behavior. This is
6846 * especially needed when the window is embedded in a window created by
6847 * another process.
6848 */
6849 if (wrappingOccurred) {
6850 QWindow *window = windowHandle();
6851 if (window != nullptr) {
6852 QWindowPrivate *winp = qt_window_private(window);
6853
6854 if (winp->platformWindow != nullptr) {
6855 QFocusEvent event(QEvent::FocusIn, reason);
6856 event.ignore();
6857 winp->platformWindow->windowEvent(&event);
6858 if (event.isAccepted()) return true;
6859 }
6860 }
6861 }
6862
6863 w->setFocus(reason);
6864 return true;
6865}
6866
6867/*!
6868 Returns the last child of this widget that setFocus had been
6869 called on. For top level widgets this is the widget that will get
6870 focus in case this window gets activated
6871
6872 This is not the same as QApplication::focusWidget(), which returns
6873 the focus widget in the currently active window.
6874*/
6875
6876QWidget *QWidget::focusWidget() const
6877{
6878 return const_cast<QWidget *>(d_func()->focus_child);
6879}
6880
6881QObject *QWidgetPrivate::focusObject()
6882{
6883 Q_Q(QWidget);
6884 QWidget *proxy = deepestFocusProxy();
6885 return proxy ? proxy : q;
6886}
6887
6888/*!
6889 Returns the next widget in this widget's focus chain.
6890
6891 \sa previousInFocusChain()
6892*/
6893QWidget *QWidget::nextInFocusChain() const
6894{
6895 Q_D(const QWidget);
6896 return d->nextPrevElementInFocusChain(QWidgetPrivate::FocusDirection::Next);
6897}
6898
6899/*!
6900 \brief The previousInFocusChain function returns the previous
6901 widget in this widget's focus chain.
6902
6903 \sa nextInFocusChain()
6904
6905 \since 4.6
6906*/
6907QWidget *QWidget::previousInFocusChain() const
6908{
6909 Q_D(const QWidget);
6910 return d->nextPrevElementInFocusChain(QWidgetPrivate::FocusDirection::Previous);
6911}
6912
6913/*!
6914 \property QWidget::isActiveWindow
6915 \brief whether this widget's window is the active window
6916
6917 The active window is the window that contains the widget that has
6918 keyboard focus (The window may still have focus if it has no
6919 widgets or none of its widgets accepts keyboard focus).
6920
6921 When popup windows are visible, this property is \c true for both the
6922 active window \e and for the popup.
6923
6924 By default, this property is \c false.
6925
6926 \sa activateWindow(), QApplication::activeWindow()
6927*/
6928bool QWidget::isActiveWindow() const
6929{
6930 QWidget *tlw = window();
6931 if (tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
6932 return true;
6933
6934#if QT_CONFIG(graphicsview)
6935 if (const auto &tlwExtra = tlw->d_func()->extra) {
6936 if (isVisible() && tlwExtra->proxyWidget)
6937 return tlwExtra->proxyWidget->isActiveWindow();
6938 }
6939#endif
6940
6941 if (style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, this)) {
6942 if (tlw->windowType() == Qt::Tool &&
6943 !tlw->isModal() &&
6944 (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
6945 return true;
6946 QWidget *w = QApplication::activeWindow();
6947 while(w && tlw->windowType() == Qt::Tool &&
6948 !w->isModal() && w->parentWidget()) {
6949 w = w->parentWidget()->window();
6950 if (w == tlw)
6951 return true;
6952 }
6953 }
6954
6955 // Check for an active window container
6956 if (QWindow *ww = QGuiApplication::focusWindow()) {
6957 while (ww) {
6958 QWidgetWindow *qww = qobject_cast<QWidgetWindow *>(ww);
6959 QWindowContainer *qwc = qww ? qobject_cast<QWindowContainer *>(qww->widget()) : 0;
6960 if (qwc && qwc->topLevelWidget() == tlw)
6961 return true;
6962 ww = ww->parent();
6963 }
6964 }
6965
6966 // Check if platform adaptation thinks the window is active. This is necessary for
6967 // example in case of ActiveQt servers that are embedded into another application.
6968 // Those are separate processes that are not part of the parent application Qt window/widget
6969 // hierarchy, so they need to rely on native methods to determine if they are part of the
6970 // active window.
6971 if (const QWindow *w = tlw->windowHandle()) {
6972 if (w->handle())
6973 return w->handle()->isActive();
6974 }
6975
6976 return false;
6977}
6978
6979/*!
6980 \fn void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
6981 \overload
6982 \since 6.6
6983
6984 Sets the tab order for the widgets in the \a widgets list by calling
6985 \l{QWidget::setTabOrder(QWidget *, QWidget *)} for each consecutive
6986 pair of widgets.
6987
6988 Instead of setting up each pair manually like this:
6989
6990 \snippet code/src_gui_kernel_qwidget.cpp 9
6991
6992 you can call:
6993
6994 \snippet code/src_gui_kernel_qwidget.cpp 9.list
6995
6996 The call does not create a closed tab focus loop. If there are more widgets
6997 with \l{Qt::TabFocus} focus policy, tabbing on \c{d} will move focus to one
6998 of those widgets, not back to \c{a}.
6999
7000 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7001*/
7002
7003/*!
7004 Puts the \a second widget after the \a first widget in the focus order.
7005
7006 It effectively removes the \a second widget from its focus chain and
7007 inserts it after the \a first widget.
7008
7009 Note that since the tab order of the \a second widget is changed, you
7010 should order a chain like this:
7011
7012 \snippet code/src_gui_kernel_qwidget.cpp 9
7013
7014 \e not like this:
7015
7016 \snippet code/src_gui_kernel_qwidget.cpp 10
7017
7018 If \a first or \a second has a focus proxy, setTabOrder()
7019 correctly substitutes the proxy.
7020
7021 \note Since Qt 5.10: A widget that has a child as focus proxy is understood as
7022 a compound widget. When setting a tab order between one or two compound widgets, the
7023 local tab order inside each will be preserved. This means that if both widgets are
7024 compound widgets, the resulting tab order will be from the last child inside
7025 \a first, to the first child inside \a second.
7026
7027 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7028*/
7029void QWidget::setTabOrder(QWidget* first, QWidget *second)
7030{
7031 if (!first || !second || first == second
7032 || first->focusPolicy() == Qt::NoFocus
7033 || second->focusPolicy() == Qt::NoFocus)
7034 return;
7035
7036 if (Q_UNLIKELY(first->window() != second->window())) {
7037 qWarning("QWidget::setTabOrder: 'first' and 'second' must be in the same window");
7038 return;
7039 }
7040
7041 const auto determineLastFocusChild = [](QWidget *target, QWidget *noFurtherThan)
7042 {
7043 // Since we need to repeat the same logic for both 'first' and 'second', we add a function that
7044 // determines the last focus child for a widget, taking proxies and compound widgets into account.
7045 // If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
7046 // 'lastFocusChild' will be set to the target itself.
7047 QWidget *lastFocusChild = target;
7048
7049 QWidget *focusProxy = target->d_func()->deepestFocusProxy();
7050 if (!focusProxy) {
7051 // QTBUG-81097: Another case is possible here. We can have a child
7052 // widget, that sets its focusProxy() to the parent (target).
7053 // An example of such widget is a QLineEdit, nested into
7054 // a QAbstractSpinBox. In this case such widget should be considered
7055 // the last focus child.
7056 for (auto *object : target->children()) {
7057 QWidget *w = qobject_cast<QWidget*>(object);
7058 if (w && w->focusProxy() == target) {
7059 lastFocusChild = w;
7060 break;
7061 }
7062 }
7063 } else if (target->isAncestorOf(focusProxy)) {
7064 lastFocusChild = focusProxy;
7065 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
7066 focusNext != focusProxy && target->isAncestorOf(focusNext) && focusNext->window() == focusProxy->window();
7067 focusNext = focusNext->nextInFocusChain()) {
7068 if (focusNext == noFurtherThan)
7069 break;
7070 if (focusNext->focusPolicy() != Qt::NoFocus)
7071 lastFocusChild = focusNext;
7072 }
7073 }
7074 return lastFocusChild;
7075 };
7076 // detect inflection in case we have compound widgets
7077 QWidget *lastFocusChildOfFirst = determineLastFocusChild(first, second);
7078 if (lastFocusChildOfFirst == second)
7079 lastFocusChildOfFirst = first;
7080 QWidget *lastFocusChildOfSecond = determineLastFocusChild(second, first);
7081 if (lastFocusChildOfSecond == first)
7082 lastFocusChildOfSecond = second;
7083
7084 // Return if only NoFocus widgets are between first and second
7085 QWidget *oldPrev = second->previousInFocusChain();
7086 QWidget *prevWithFocus = oldPrev;
7087 while (prevWithFocus->focusPolicy() == Qt::NoFocus)
7088 prevWithFocus = prevWithFocus->previousInFocusChain();
7089 if (prevWithFocus == first)
7090 return;
7091 const QWidgetList chain = QWidgetPrivate::takeFromFocusChain(second, lastFocusChildOfSecond);
7092 QWidgetPrivate::insertIntoFocusChain(chain, QWidgetPrivate::FocusDirection::Next, lastFocusChildOfFirst);
7093}
7094
7095void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
7096{
7097 QWidget *prev = nullptr;
7098 for (const auto &widget : widgets) {
7099 if (!prev) {
7100 prev = widget;
7101 } else {
7102 QWidget::setTabOrder(prev, widget);
7103 prev = widget;
7104 }
7105 }
7106}
7107
7108
7109/*!\internal
7110
7111 Moves the relevant subwidgets of this widget from the \a oldtlw's
7112 tab chain to that of the new parent, if there's anything to move and
7113 we're really moving
7114
7115 This function is called from QWidget::reparent() *after* the widget
7116 has been reparented.
7117
7118 \sa reparent()
7119*/
7120
7121void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
7122{
7123 Q_Q(QWidget);
7124 if (oldtlw == q->window())
7125 return; // nothing to do
7126
7127 if (focus_child)
7128 focus_child->clearFocus();
7129
7130 reparentFocusChildren(QWidgetPrivate::FocusDirection::Next);
7131}
7132
7133/*!
7134 \property QWidget::frameSize
7135 \brief the size of the widget including any window frame
7136
7137 By default, this property contains a value that depends on the user's
7138 platform and screen geometry.
7139*/
7140QSize QWidget::frameSize() const
7141{
7142 Q_D(const QWidget);
7143 if (isWindow() && !(windowType() == Qt::Popup)) {
7144 QRect fs = d->frameStrut();
7145 return QSize(data->crect.width() + fs.left() + fs.right(),
7146 data->crect.height() + fs.top() + fs.bottom());
7147 }
7148 return data->crect.size();
7149}
7150
7151/*! \fn void QWidget::move(int x, int y)
7152
7153 \overload
7154
7155 This corresponds to move(QPoint(\a x, \a y)).
7156*/
7157
7158void QWidget::move(const QPoint &p)
7159{
7160 Q_D(QWidget);
7161 setAttribute(Qt::WA_Moved);
7162 if (testAttribute(Qt::WA_WState_Created)) {
7163 if (isWindow())
7164 d->topData()->posIncludesFrame = false;
7165 d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
7166 p.y() + geometry().y() - QWidget::y(),
7167 width(), height(), true);
7168 d->setDirtyOpaqueRegion();
7169 } else {
7170 // no frame yet: see also QWidgetPrivate::fixPosIncludesFrame(), QWindowPrivate::PositionPolicy.
7171 if (isWindow())
7172 d->topData()->posIncludesFrame = true;
7173 data->crect.moveTopLeft(p); // no frame yet
7174 setAttribute(Qt::WA_PendingMoveEvent);
7175 }
7176
7177 if (d->extra && d->extra->hasWindowContainer)
7178 QWindowContainer::parentWasMoved(this);
7179}
7180
7181// move() was invoked with Qt::WA_WState_Created not set (frame geometry
7182// unknown), that is, crect has a position including the frame.
7183// If we can determine the frame strut, fix that and clear the flag.
7184// FIXME: This does not play well with window states other than
7185// Qt::WindowNoState, as we depend on calling setGeometry() on the
7186// platform window after fixing up the position so that the new
7187// geometry is reflected in the platform window, but when the frame
7188// comes in after the window has been shown (e.g. maximized), we're
7189// not in a position to do that kind of fixup.
7190void QWidgetPrivate::fixPosIncludesFrame()
7191{
7192 Q_Q(QWidget);
7193 if (QTLWExtra *te = maybeTopData()) {
7194 if (te->posIncludesFrame) {
7195 // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
7196 // example, in QGraphicsProxyWidget).
7197 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
7198 te->posIncludesFrame = 0;
7199 } else {
7200 if (q->windowHandle() && q->windowHandle()->handle()) {
7201 updateFrameStrut();
7202 if (!q->data->fstrut_dirty) {
7203 data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
7204 te->posIncludesFrame = 0;
7205 }
7206 } // windowHandle()
7207 } // !WA_DontShowOnScreen
7208 } // posIncludesFrame
7209 } // QTLWExtra
7210}
7211
7212/*! \fn void QWidget::resize(int w, int h)
7213 \overload
7214
7215 This corresponds to resize(QSize(\a w, \a h)).
7216*/
7217
7218void QWidget::resize(const QSize &s)
7219{
7220 Q_D(QWidget);
7221 setAttribute(Qt::WA_Resized);
7222 if (testAttribute(Qt::WA_WState_Created)) {
7223 d->fixPosIncludesFrame();
7224 d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
7225 d->setDirtyOpaqueRegion();
7226 } else {
7227 const auto oldRect = data->crect;
7228 data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize()));
7229 if (oldRect != data->crect)
7230 setAttribute(Qt::WA_PendingResizeEvent);
7231 }
7232}
7233
7234void QWidget::setGeometry(const QRect &r)
7235{
7236 Q_D(QWidget);
7237 setAttribute(Qt::WA_Resized);
7238 setAttribute(Qt::WA_Moved);
7239 if (isWindow())
7240 d->topData()->posIncludesFrame = 0;
7241 if (testAttribute(Qt::WA_WState_Created)) {
7242 d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
7243 d->setDirtyOpaqueRegion();
7244 } else {
7245 const auto oldRect = data->crect;
7246 data->crect.setTopLeft(r.topLeft());
7247 data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize()));
7248 if (oldRect != data->crect) {
7249 setAttribute(Qt::WA_PendingMoveEvent);
7250 setAttribute(Qt::WA_PendingResizeEvent);
7251 }
7252 }
7253
7254 if (d->extra && d->extra->hasWindowContainer)
7255 QWindowContainer::parentWasMoved(this);
7256}
7257
7258void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
7259{
7260 Q_Q(QWidget);
7261 if (extra) { // any size restrictions?
7262 w = qMin(w,extra->maxw);
7263 h = qMin(h,extra->maxh);
7264 w = qMax(w,extra->minw);
7265 h = qMax(h,extra->minh);
7266 }
7267
7268 if (q->isWindow() && q->windowHandle()) {
7269 QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
7270 if (!integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)) {
7271 x = 0;
7272 y = 0;
7273 w = q->windowHandle()->width();
7274 h = q->windowHandle()->height();
7275 }
7276 }
7277
7278 QPoint oldp = q->geometry().topLeft();
7279 QSize olds = q->size();
7280 QRect r(x, y, w, h);
7281
7282 bool isResize = olds != r.size();
7283 if (!isMove)
7284 isMove = oldp != r.topLeft();
7285
7286
7287 // We only care about stuff that changes the geometry, or may
7288 // cause the window manager to change its state
7289 if (r.size() == olds && oldp == r.topLeft())
7290 return;
7291
7292 if (!data.in_set_window_state) {
7293 q->data->window_state &= ~Qt::WindowMaximized;
7294 q->data->window_state &= ~Qt::WindowFullScreen;
7295 if (q->isWindow())
7296 topData()->normalGeometry = QRect(0, 0, -1, -1);
7297 }
7298
7299 QPoint oldPos = q->pos();
7300 data.crect = r;
7301
7302 bool needsShow = false;
7303
7304 if (q->isWindow() || q->windowHandle()) {
7305 if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
7306 q->setAttribute(Qt::WA_OutsideWSRange, true);
7307 if (q->isVisible())
7308 hide_sys();
7309 data.crect = QRect(x, y, w, h);
7310 } else if (q->testAttribute(Qt::WA_OutsideWSRange)) {
7311 q->setAttribute(Qt::WA_OutsideWSRange, false);
7312 needsShow = true;
7313 }
7314 }
7315
7316 if (q->isVisible()) {
7317 if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
7318 if (QWindow *win = q->windowHandle()) {
7319 if (q->isWindow()) {
7320 if (isResize && !isMove)
7321 win->resize(w, h);
7322 else if (isMove && !isResize)
7323 win->setPosition(x, y);
7324 else
7325 win->setGeometry(q->geometry());
7326 } else {
7327 QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint());
7328 win->setGeometry(QRect(posInNativeParent,r.size()));
7329 }
7330
7331 if (needsShow)
7332 show_sys();
7333 }
7334
7335 if (!q->isWindow()) {
7336 if (renderToTexture) {
7337 QRegion updateRegion(q->geometry());
7338 updateRegion += QRect(oldPos, olds);
7339 q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
7340 } else if (isMove && !isResize) {
7341 moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
7342 } else {
7343 invalidateBackingStore_resizeHelper(oldPos, olds);
7344 }
7345 }
7346 }
7347
7348 if (isMove) {
7349 QMoveEvent e(q->pos(), oldPos);
7350 QCoreApplication::sendEvent(q, &e);
7351 }
7352 if (isResize) {
7353 QResizeEvent e(r.size(), olds);
7354 QCoreApplication::sendEvent(q, &e);
7355 if (q->windowHandle())
7356 q->update();
7357 }
7358 } else { // not visible
7359 if (isMove && q->pos() != oldPos)
7360 q->setAttribute(Qt::WA_PendingMoveEvent, true);
7361 if (isResize)
7362 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7363 }
7364
7365#if QT_CONFIG(accessibility)
7366 if (QAccessible::isActive() && q->isVisible()) {
7367 QAccessibleEvent event(q, QAccessible::LocationChanged);
7368 QAccessible::updateAccessibility(&event);
7369 }
7370#endif
7371}
7372
7373/*!
7374 \since 4.2
7375 Saves the current geometry and state for top-level widgets.
7376
7377 To save the geometry when the window closes, you can
7378 implement a close event like this:
7379
7380 \snippet code/src_gui_kernel_qwidget.cpp 11
7381
7382 See the \l{Window Geometry} documentation for an overview of geometry
7383 issues with windows.
7384
7385 Use QMainWindow::saveState() to save the geometry and the state of
7386 toolbars and dock widgets.
7387
7388 \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
7389*/
7390QByteArray QWidget::saveGeometry() const
7391{
7392 QByteArray array;
7393 QDataStream stream(&array, QIODevice::WriteOnly);
7394 stream.setVersion(QDataStream::Qt_4_0);
7395 const quint32 magicNumber = 0x1D9D0CB;
7396 // Version history:
7397 // - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0
7398 // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
7399 // - Qt 5.12 - today : Version 3.0, save QWidget::geometry()
7400 quint16 majorVersion = 3;
7401 quint16 minorVersion = 0;
7402 const int screenNumber = QGuiApplication::screens().indexOf(screen());
7403 stream << magicNumber
7404 << majorVersion
7405 << minorVersion
7406 << frameGeometry()
7407 << normalGeometry()
7408 << qint32(screenNumber)
7409 << quint8(windowState() & Qt::WindowMaximized)
7410 << quint8(windowState() & Qt::WindowFullScreen)
7411 << qint32(screen()->geometry().width()) // added in 2.0
7412 << geometry(); // added in 3.0
7413 return array;
7414}
7415
7416/*!
7417 \internal
7418
7419 Check a if \a restoredGeometry fits into \a availableGeometry
7420 This method is used to verify that a widget is restored to a geometry, which
7421 fits into the target screen.
7422
7423 \param frameHeight represents the height of the widget's title bar, which is expected
7424 to be on its top.
7425
7426 If the size of \a restoredGeometry exceeds \a availableGeometry, its height and width
7427 will be resized to be two pixels smaller than \a availableGeometry. An exact match would
7428 be full screen.
7429
7430 If at least one edge of \a restoredGeometry is outside \a availableGeometry,
7431 \a restoredGeometry will be moved
7432 \list
7433 \li down if its top is off screen
7434 \li up if its bottom is off screen
7435 \li right if its left edge is off screen
7436 \li left if its right edge is off screen
7437 \endlist
7438 */
7439void QWidgetPrivate::checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
7440 int frameHeight)
7441{
7442 // compare with restored geometry's height increased by frameHeight
7443 const int height = restoredGeometry->height() + frameHeight;
7444
7445 // Step 1: Resize if necessary:
7446 // make height / width 2px smaller than screen, because an exact match would be fullscreen
7447 if (availableGeometry.height() <= height)
7448 restoredGeometry->setHeight(availableGeometry.height() - 2 - frameHeight);
7449 if (availableGeometry.width() <= restoredGeometry->width())
7450 restoredGeometry->setWidth(availableGeometry.width() - 2);
7451
7452 // Step 2: Move if necessary:
7453 // Construct a rectangle from restored Geometry adjusted by frameHeight
7454 const QRect restored = restoredGeometry->adjusted(0, -frameHeight, 0, 0);
7455
7456 // Return if restoredGeometry (including frame) fits into screen
7457 if (availableGeometry.contains(restored))
7458 return;
7459
7460 // (size is correct, but at least one edge is off screen)
7461
7462 // Top out of bounds => move down
7463 if (restored.top() <= availableGeometry.top()) {
7464 restoredGeometry->moveTop(availableGeometry.top() + 1 + frameHeight);
7465 } else if (restored.bottom() >= availableGeometry.bottom()) {
7466 // Bottom out of bounds => move up
7467 restoredGeometry->moveBottom(availableGeometry.bottom() - 1);
7468 }
7469
7470 // Left edge out of bounds => move right
7471 if (restored.left() <= availableGeometry.left()) {
7472 restoredGeometry->moveLeft(availableGeometry.left() + 1);
7473 } else if (restored.right() >= availableGeometry.right()) {
7474 // Right edge out of bounds => move left
7475 restoredGeometry->moveRight(availableGeometry.right() - 1);
7476 }
7477}
7478
7479/*!
7480 \since 4.2
7481
7482 Restores the geometry and state of top-level widgets stored in the
7483 byte array \a geometry. Returns \c true on success; otherwise
7484 returns \c false.
7485
7486 If the restored geometry is off-screen, it will be modified to be
7487 inside the available screen geometry.
7488
7489 To restore geometry saved using QSettings, you can use code like
7490 this:
7491
7492 \snippet code/src_gui_kernel_qwidget.cpp 12
7493
7494 See the \l{Window Geometry} documentation for an overview of geometry
7495 issues with windows.
7496
7497 Use QMainWindow::restoreState() to restore the geometry and the
7498 state of toolbars and dock widgets.
7499
7500 \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
7501*/
7502bool QWidget::restoreGeometry(const QByteArray &geometry)
7503{
7504 if (geometry.size() < 4)
7505 return false;
7506 QDataStream stream(geometry);
7507 stream.setVersion(QDataStream::Qt_4_0);
7508
7509 const quint32 magicNumber = 0x1D9D0CB;
7510 quint32 storedMagicNumber;
7511 stream >> storedMagicNumber;
7512 if (storedMagicNumber != magicNumber)
7513 return false;
7514
7515 const quint16 currentMajorVersion = 3;
7516 quint16 majorVersion = 0;
7517 quint16 minorVersion = 0;
7518
7519 stream >> majorVersion >> minorVersion;
7520
7521 if (majorVersion > currentMajorVersion)
7522 return false;
7523 // (Allow all minor versions.)
7524
7525 QRect restoredFrameGeometry;
7526 QRect restoredGeometry;
7527 QRect restoredNormalGeometry;
7528 qint32 restoredScreenNumber;
7529 quint8 maximized;
7530 quint8 fullScreen;
7531 qint32 restoredScreenWidth = 0;
7532
7533 stream >> restoredFrameGeometry // Only used for sanity checks in version 0
7534 >> restoredNormalGeometry
7535 >> restoredScreenNumber
7536 >> maximized
7537 >> fullScreen;
7538
7539 if (majorVersion > 1)
7540 stream >> restoredScreenWidth;
7541 if (majorVersion > 2)
7542 stream >> restoredGeometry;
7543
7544 // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
7545
7546 if (restoredScreenNumber >= qMax(QGuiApplication::screens().size(), 1))
7547 restoredScreenNumber = 0;
7548 const QScreen *restoredScreen = QGuiApplication::screens().value(restoredScreenNumber, nullptr);
7549 const qreal screenWidthF = restoredScreen ? qreal(restoredScreen->geometry().width()) : 0;
7550 // Sanity check bailing out when large variations of screen sizes occur due to
7551 // high DPI scaling or different levels of DPI awareness.
7552 if (restoredScreenWidth) {
7553 const qreal factor = qreal(restoredScreenWidth) / screenWidthF;
7554 if (factor < 0.8 || factor > 1.25)
7555 return false;
7556 } else {
7557 // Saved by Qt 5.3 and earlier, try to prevent too large windows
7558 // unless the size will be adapted by maximized or fullscreen.
7559 if (!maximized && !fullScreen && qreal(restoredFrameGeometry.width()) / screenWidthF > 1.5)
7560 return false;
7561 }
7562
7563 const int frameHeight = QApplication::style()
7564 ? QApplication::style()->pixelMetric(QStyle::PM_TitleBarHeight, nullptr, this)
7565 : 20;
7566
7567 if (!restoredNormalGeometry.isValid())
7568 restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
7569 if (!restoredNormalGeometry.isValid()) {
7570 // use the widget's adjustedSize if the sizeHint() doesn't help
7571 restoredNormalGeometry.setSize(restoredNormalGeometry
7572 .size()
7573 .expandedTo(d_func()->adjustedSize()));
7574 }
7575
7576 const QRect availableGeometry = restoredScreen ? restoredScreen->availableGeometry()
7577 : QRect();
7578
7579 // Modify the restored geometry if we are about to restore to coordinates
7580 // that would make the window "lost". This happens if:
7581 // - The restored geometry is completely or partly oustside the available geometry
7582 // - The title bar is outside the available geometry.
7583
7584 QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight);
7585 QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight);
7586
7587 if (maximized || fullScreen) {
7588 // set geometry before setting the window state to make
7589 // sure the window is maximized to the right screen.
7590 Qt::WindowStates ws = windowState();
7591#ifndef Q_OS_WIN
7592 setGeometry(restoredNormalGeometry);
7593#else
7594 if (ws & Qt::WindowFullScreen) {
7595 // Full screen is not a real window state on Windows.
7596 move(availableGeometry.topLeft());
7597 } else if (ws & Qt::WindowMaximized) {
7598 // Setting a geometry on an already maximized window causes this to be
7599 // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
7600 // Move the window in normal state if needed.
7601 if (restoredScreen != screen()) {
7602 setWindowState(Qt::WindowNoState);
7603 setGeometry(restoredNormalGeometry);
7604 }
7605 } else {
7606 setGeometry(restoredNormalGeometry);
7607 }
7608#endif // Q_OS_WIN
7609 if (maximized)
7610 ws |= Qt::WindowMaximized;
7611 if (fullScreen)
7612 ws |= Qt::WindowFullScreen;
7613 setWindowState(ws);
7614 d_func()->topData()->normalGeometry = restoredNormalGeometry;
7615 } else {
7616 setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
7617
7618 // FIXME: Why fall back to restoredNormalGeometry if majorVersion <= 2?
7619 if (majorVersion > 2)
7620 setGeometry(restoredGeometry);
7621 else
7622 setGeometry(restoredNormalGeometry);
7623 }
7624 return true;
7625}
7626
7627/*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
7628 \overload
7629
7630 This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
7631*/
7632
7633/*!
7634 Sets the margins around the contents of the widget to have the sizes
7635 \a left, \a top, \a right, and \a bottom. The margins are used by
7636 the layout system, and may be used by subclasses to specify the area
7637 to draw in (e.g. excluding the frame).
7638
7639 Changing the margins will trigger a resizeEvent().
7640
7641 \sa contentsRect(), contentsMargins()
7642*/
7643void QWidget::setContentsMargins(int left, int top, int right, int bottom)
7644{
7645 Q_D(QWidget);
7646 if (left == d->leftmargin && top == d->topmargin
7647 && right == d->rightmargin && bottom == d->bottommargin)
7648 return;
7649 d->leftmargin = left;
7650 d->topmargin = top;
7651 d->rightmargin = right;
7652 d->bottommargin = bottom;
7653
7654 d->updateContentsRect();
7655}
7656
7657/*!
7658 \overload
7659 \since 4.6
7660
7661 \brief The setContentsMargins function sets the margins around the
7662 widget's contents.
7663
7664 Sets the margins around the contents of the widget to have the
7665 sizes determined by \a margins. The margins are
7666 used by the layout system, and may be used by subclasses to
7667 specify the area to draw in (e.g. excluding the frame).
7668
7669 Changing the margins will trigger a resizeEvent().
7670
7671 \sa contentsRect(), contentsMargins()
7672*/
7673void QWidget::setContentsMargins(const QMargins &margins)
7674{
7675 setContentsMargins(margins.left(), margins.top(),
7676 margins.right(), margins.bottom());
7677}
7678
7679void QWidgetPrivate::updateContentsRect()
7680{
7681 Q_Q(QWidget);
7682
7683 if (layout)
7684 layout->update(); //force activate; will do updateGeometry
7685 else
7686 q->updateGeometry();
7687
7688 if (q->isVisible()) {
7689 q->update();
7690 QResizeEvent e(q->data->crect.size(), q->data->crect.size());
7691 QCoreApplication::sendEvent(q, &e);
7692 } else {
7693 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7694 }
7695
7696 QEvent e(QEvent::ContentsRectChange);
7697 QCoreApplication::sendEvent(q, &e);
7698}
7699
7700/*!
7701 \since 4.6
7702
7703 \brief The contentsMargins function returns the widget's contents margins.
7704
7705 \sa setContentsMargins(), contentsRect()
7706 */
7707QMargins QWidget::contentsMargins() const
7708{
7709 Q_D(const QWidget);
7710 QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
7711 return testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea) ?
7712 userMargins | d->safeAreaMargins() : userMargins;
7713}
7714
7715/*!
7716 Returns the area inside the widget's margins.
7717
7718 \sa setContentsMargins(), contentsMargins()
7719*/
7720QRect QWidget::contentsRect() const
7721{
7722 return rect() - contentsMargins();
7723}
7724
7725QMargins QWidgetPrivate::safeAreaMargins() const
7726{
7727 Q_Q(const QWidget);
7728
7729#if QT_CONFIG(graphicsview)
7730 // Don't report margins for proxied widgets, as the logic
7731 // below doesn't handle that case (yet).
7732 if (nearestGraphicsProxyWidget(q))
7733 return QMargins();
7734#endif
7735
7736 QWidget *nativeWidget = q->window();
7737 if (!nativeWidget->windowHandle())
7738 return QMargins();
7739
7740 QMargins safeAreaMargins = nativeWidget->windowHandle()->safeAreaMargins();
7741
7742 if (!q->isWindow()) {
7743 // In theory the native parent widget already has a contents rect reflecting
7744 // the safe area of that widget, but we can't be sure that the widget or child
7745 // widgets of that widget have respected the contents rect when setting their
7746 // geometry, so we need to manually compute the safe area.
7747
7748 // Unless the native widget doesn't have any margins, in which case there's
7749 // nothing for us to compute.
7750 if (safeAreaMargins.isNull())
7751 return QMargins();
7752
7753 // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
7754 // set, and the widget respects the safe area, then we know that the layout has already
7755 // taken care of placing us inside the safe area, by taking the contents rect of its
7756 // parent widget into account.
7757 const QWidget *assumedSafeWidget = nullptr;
7758 for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
7759 QWidget *parentWidget = w->parentWidget();
7760 if (!parentWidget->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
7761 continue; // Layout can't help us
7762
7763 if (parentWidget->testAttribute(Qt::WA_LayoutOnEntireRect))
7764 continue; // Layout not going to help us
7765
7766 QLayout *layout = parentWidget->layout();
7767 if (!layout)
7768 continue;
7769
7770 if (layout->geometry().isNull())
7771 continue; // Layout hasn't been activated yet
7772
7773 if (layout->indexOf(w) < 0)
7774 continue; // Widget is not in layout
7775
7776 assumedSafeWidget = w;
7777 break;
7778 }
7779
7780#if !defined(QT_DEBUG)
7781 if (assumedSafeWidget) {
7782 // We found a layout that we assume will take care of keeping us within the safe area
7783 // For debug builds we still map the safe area using the fallback logic, so that we
7784 // can detect any misbehaving layouts.
7785 return QMargins();
7786 }
7787#endif
7788
7789 // In all other cases we need to map the safe area of the native parent to the widget.
7790 // This depends on the widget being positioned and sized already, which means the initial
7791 // layout will be wrong, but the layout will then adjust itself.
7792 QPoint topLeftMargins = q->mapFrom(nativeWidget, QPoint(safeAreaMargins.left(), safeAreaMargins.top()));
7793 QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect();
7794 QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(nativeWidget,
7795 nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom()));
7796
7797 // Margins should never be negative
7798 safeAreaMargins = QMargins(qMax(0, topLeftMargins.x()), qMax(0, topLeftMargins.y()),
7799 qMax(0, bottomRightMargins.x()), qMax(0, bottomRightMargins.y()));
7800
7801 if (!safeAreaMargins.isNull() && assumedSafeWidget) {
7802 QLayout *layout = assumedSafeWidget->parentWidget()->layout();
7803 qWarning() << layout << "is laying out" << assumedSafeWidget
7804 << "outside of the contents rect of" << layout->parentWidget();
7805 return QMargins(); // Return empty margin to visually highlight the error
7806 }
7807 }
7808
7809 return safeAreaMargins;
7810}
7811
7812/*!
7813 \fn void QWidget::customContextMenuRequested(const QPoint &pos)
7814
7815 This signal is emitted when the widget's \l contextMenuPolicy is
7816 Qt::CustomContextMenu, and the user has requested a context menu on
7817 the widget. The position \a pos is the position of the context menu
7818 event that the widget receives. Normally this is in widget
7819 coordinates. The exception to this rule is QAbstractScrollArea and
7820 its subclasses that map the context menu event to coordinates of the
7821 \l{QAbstractScrollArea::viewport()}{viewport()}.
7822
7823
7824 \sa mapToGlobal(), QMenu, contextMenuPolicy
7825*/
7826
7827
7828/*!
7829 \property QWidget::contextMenuPolicy
7830 \brief how the widget shows a context menu
7831
7832 The default value of this property is Qt::DefaultContextMenu,
7833 which means the contextMenuEvent() handler is called. Other values
7834 are Qt::NoContextMenu, Qt::PreventContextMenu,
7835 Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
7836 Qt::CustomContextMenu, the signal customContextMenuRequested() is
7837 emitted.
7838
7839 \sa contextMenuEvent(), customContextMenuRequested(), actions()
7840*/
7841
7842Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
7843{
7844 return (Qt::ContextMenuPolicy)data->context_menu_policy;
7845}
7846
7847void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
7848{
7849 data->context_menu_policy = (uint) policy;
7850}
7851
7852/*!
7853 \property QWidget::focusPolicy
7854 \brief the way the widget accepts keyboard focus
7855
7856 The policy is Qt::TabFocus if the widget accepts keyboard
7857 focus by tabbing, Qt::ClickFocus if the widget accepts
7858 focus by clicking, Qt::StrongFocus if it accepts both, and
7859 Qt::NoFocus (the default) if it does not accept focus at
7860 all.
7861
7862 You must enable keyboard focus for a widget if it processes
7863 keyboard events. This is normally done from the widget's
7864 constructor. For instance, the QLineEdit constructor calls
7865 setFocusPolicy(Qt::StrongFocus).
7866
7867 If the widget has a focus proxy, then the focus policy will
7868 be propagated to it.
7869
7870 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
7871*/
7872
7873
7874Qt::FocusPolicy QWidget::focusPolicy() const
7875{
7876 return (Qt::FocusPolicy)data->focus_policy;
7877}
7878
7879void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
7880{
7881 data->focus_policy = (uint) policy;
7882 Q_D(QWidget);
7883 if (d->extra && d->extra->focus_proxy)
7884 d->extra->focus_proxy->setFocusPolicy(policy);
7885}
7886
7887/*!
7888 \property QWidget::updatesEnabled
7889 \brief whether updates are enabled
7890
7891 An updates enabled widget receives paint events and has a system
7892 background; a disabled widget does not. This also implies that
7893 calling update() and repaint() has no effect if updates are
7894 disabled.
7895
7896 By default, this property is \c true.
7897
7898 setUpdatesEnabled() is normally used to disable updates for a
7899 short period of time, for instance to avoid screen flicker during
7900 large changes. In Qt, widgets normally do not generate screen
7901 flicker, but on X11 the server might erase regions on the screen
7902 when widgets get hidden before they can be replaced by other
7903 widgets. Disabling updates solves this.
7904
7905 Example:
7906 \snippet code/src_gui_kernel_qwidget.cpp 13
7907
7908 Disabling a widget implicitly disables all its children. Enabling a widget
7909 enables all child widgets \e except top-level widgets or those that
7910 have been explicitly disabled. Re-enabling updates implicitly calls
7911 update() on the widget.
7912
7913 \sa paintEvent()
7914*/
7915void QWidget::setUpdatesEnabled(bool enable)
7916{
7917 Q_D(QWidget);
7918 setAttribute(Qt::WA_ForceUpdatesDisabled, !enable);
7919 d->setUpdatesEnabled_helper(enable);
7920}
7921
7922/*!
7923 Shows the widget and its child widgets.
7924
7925 For child windows, this is equivalent to calling setVisible(true).
7926 Otherwise, it is equivalent to calling showFullScreen(), showMaximized(),
7927 or setVisible(true), depending on the platform's default behavior for the window flags.
7928
7929 \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
7930 showNormal(), isVisible(), windowFlags()
7931*/
7932void QWidget::show()
7933{
7934 // Note: We don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
7935
7936 if (!isWindow()) {
7937 setVisible(true);
7938 } else {
7939 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
7940 Qt::WindowState defaultState = platformIntegration->defaultWindowState(data->window_flags);
7941 if (defaultState == Qt::WindowFullScreen)
7942 showFullScreen();
7943 else if (defaultState == Qt::WindowMaximized)
7944 showMaximized();
7945 else
7946 setVisible(true);
7947 }
7948}
7949
7950/*! \internal
7951
7952 Makes the widget visible in the isVisible() meaning of the word.
7953 It is only called for toplevels or widgets with visible parents.
7954 */
7955void QWidgetPrivate::show_recursive()
7956{
7957 Q_Q(QWidget);
7958 // polish if necessary
7959
7960 if (!q->testAttribute(Qt::WA_WState_Created))
7961 createRecursively();
7962 q->ensurePolished();
7963
7964 if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
7965 q->parentWidget()->d_func()->layout->activate();
7966 // activate our layout before we and our children become visible
7967 if (layout)
7968 layout->activate();
7969
7970 show_helper();
7971}
7972
7973void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
7974{
7975 Q_Q(QWidget);
7976
7977 disableUpdates = disableUpdates && q->updatesEnabled();
7978 if (disableUpdates)
7979 q->setAttribute(Qt::WA_UpdatesDisabled);
7980
7981 if (q->testAttribute(Qt::WA_PendingMoveEvent)) {
7982 QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
7983 QCoreApplication::sendEvent(q, &e);
7984 q->setAttribute(Qt::WA_PendingMoveEvent, false);
7985 }
7986
7987 if (q->testAttribute(Qt::WA_PendingResizeEvent)) {
7988 QResizeEvent e(data.crect.size(), QSize());
7989 QCoreApplication::sendEvent(q, &e);
7990 q->setAttribute(Qt::WA_PendingResizeEvent, false);
7991 }
7992
7993 if (disableUpdates)
7994 q->setAttribute(Qt::WA_UpdatesDisabled, false);
7995
7996 if (!recursive)
7997 return;
7998
7999 for (int i = 0; i < children.size(); ++i) {
8000 if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
8001 child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
8002 }
8003}
8004
8005void QWidgetPrivate::activateChildLayoutsRecursively()
8006{
8007 sendPendingMoveAndResizeEvents(false, true);
8008
8009 for (int i = 0; i < children.size(); ++i) {
8010 QWidget *child = qobject_cast<QWidget *>(children.at(i));
8011 if (!child || child->isHidden() || child->isWindow())
8012 continue;
8013
8014 child->ensurePolished();
8015
8016 // Activate child's layout
8017 QWidgetPrivate *childPrivate = child->d_func();
8018 if (childPrivate->layout)
8019 childPrivate->layout->activate();
8020
8021 // Pretend we're visible.
8022 const bool wasVisible = child->isVisible();
8023 if (!wasVisible)
8024 child->setAttribute(Qt::WA_WState_Visible);
8025
8026 // Do the same for all my children.
8027 childPrivate->activateChildLayoutsRecursively();
8028
8029 // We're not cheating anymore.
8030 if (!wasVisible)
8031 child->setAttribute(Qt::WA_WState_Visible, false);
8032 }
8033}
8034
8035void QWidgetPrivate::show_helper()
8036{
8037 Q_Q(QWidget);
8038 data.in_show = true; // qws optimization
8039 // make sure we receive pending move and resize events
8040 sendPendingMoveAndResizeEvents();
8041
8042 // become visible before showing all children
8043 q->setAttribute(Qt::WA_WState_Visible);
8044
8045 // finally show all children recursively
8046 showChildren(false);
8047
8048
8049
8050 const bool isWindow = q->isWindow();
8051#if QT_CONFIG(graphicsview)
8052 bool isEmbedded = isWindow && q->graphicsProxyWidget() != nullptr;
8053#else
8054 bool isEmbedded = false;
8055#endif
8056
8057 // popup handling: new popups and tools need to be raised, and
8058 // existing popups must be closed. Also propagate the current
8059 // windows's KeyboardFocusChange status.
8060 if (isWindow && !isEmbedded) {
8061 if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
8062 q->raise();
8063 if (q->parentWidget() && q->parentWidget()->window()->testAttribute(Qt::WA_KeyboardFocusChange))
8064 q->setAttribute(Qt::WA_KeyboardFocusChange);
8065 } else {
8066 while (QApplication::activePopupWidget()) {
8067 if (!QApplication::activePopupWidget()->close())
8068 break;
8069 }
8070 }
8071 }
8072
8073 // Automatic embedding of child windows of widgets already embedded into
8074 // QGraphicsProxyWidget when they are shown the first time.
8075#if QT_CONFIG(graphicsview)
8076 if (isWindow) {
8077 if (!isEmbedded && !bypassGraphicsProxyWidget(q)) {
8078 QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(q->parentWidget());
8079 if (ancestorProxy) {
8080 isEmbedded = true;
8081 ancestorProxy->d_func()->embedSubWindow(q);
8082 }
8083 }
8084 }
8085#else
8086 Q_UNUSED(isEmbedded);
8087#endif
8088
8089 // send the show event before showing the window
8090 QShowEvent showEvent;
8091 QCoreApplication::sendEvent(q, &showEvent);
8092
8093 show_sys();
8094
8095 if (!isEmbedded && q->windowType() == Qt::Popup)
8096 qApp->d_func()->openPopup(q);
8097
8098#if QT_CONFIG(accessibility)
8099 if (q->windowType() != Qt::ToolTip) { // Tooltips are read aloud twice in MS narrator.
8100 QAccessibleEvent event(q, QAccessible::ObjectShow);
8101 QAccessible::updateAccessibility(&event);
8102 }
8103#endif
8104
8105 if (QApplicationPrivate::hidden_focus_widget == q) {
8106 QApplicationPrivate::hidden_focus_widget = nullptr;
8107 q->setFocus(Qt::OtherFocusReason);
8108 }
8109
8110 // Process events when showing a Qt::SplashScreen widget before the event loop
8111 // is spinnning; otherwise it might not show up on particular platforms.
8112 // This makes QSplashScreen behave the same on all platforms.
8113 if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
8114 QCoreApplication::processEvents();
8115
8116 data.in_show = false; // reset qws optimization
8117}
8118
8119void QWidgetPrivate::show_sys()
8120{
8121 Q_Q(QWidget);
8122
8123 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
8124
8125 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
8126 invalidateBackingStore(q->rect());
8127 q->setAttribute(Qt::WA_Mapped);
8128 // add our window the modal window list (native dialogs)
8129 if (window && q->isWindow()
8130#if QT_CONFIG(graphicsview)
8131 && (!extra || !extra->proxyWidget)
8132#endif
8133 && q->windowModality() != Qt::NonModal) {
8134 QGuiApplicationPrivate::showModalWindow(window);
8135 }
8136 return;
8137 }
8138
8139 if (renderToTexture && !q->isWindow())
8140 QCoreApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry()));
8141 else
8142 QCoreApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
8143
8144 if ((!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
8145 || q->testAttribute(Qt::WA_OutsideWSRange)) {
8146 return;
8147 }
8148
8149 if (window) {
8150 if (q->isWindow())
8151 fixPosIncludesFrame();
8152 QRect geomRect = q->geometry();
8153 if (!q->isWindow()) {
8154 QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint());
8155 geomRect.moveTopLeft(topLeftOfWindow);
8156 }
8157 const QRect windowRect = window->geometry();
8158 if (windowRect != geomRect) {
8159 if (q->testAttribute(Qt::WA_Moved)
8160 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
8161 window->setGeometry(geomRect);
8162 else
8163 window->resize(geomRect.size());
8164 }
8165
8166#ifndef QT_NO_CURSOR
8167 qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
8168#endif
8169 invalidateBackingStore(q->rect());
8170 window->setNativeWindowVisibility(true);
8171 // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
8172 if (window->isTopLevel()) {
8173 const QPoint crectTopLeft = q->data->crect.topLeft();
8174 const QPoint windowTopLeft = window->geometry().topLeft();
8175 if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
8176 q->data->crect.moveTopLeft(windowTopLeft);
8177 }
8178 }
8179}
8180
8181/*!
8182 Hides the widget. This function is equivalent to
8183 setVisible(false).
8184
8185
8186 \note If you are working with QDialog or its subclasses and you invoke
8187 the show() function after this function, the dialog will be displayed in
8188 its original position.
8189
8190 \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
8191*/
8192void QWidget::hide()
8193{
8194 setVisible(false);
8195}
8196
8197/*!\internal
8198 */
8199void QWidgetPrivate::hide_helper()
8200{
8201 Q_Q(QWidget);
8202
8203 bool isEmbedded = false;
8204#if QT_CONFIG(graphicsview)
8205 isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(q) && nearestGraphicsProxyWidget(q->parentWidget()) != nullptr;
8206#else
8207 Q_UNUSED(isEmbedded);
8208#endif
8209
8210 if (!isEmbedded && (q->windowType() == Qt::Popup))
8211 qApp->d_func()->closePopup(q);
8212
8213 q->setAttribute(Qt::WA_Mapped, false);
8214 hide_sys();
8215
8216 bool wasVisible = q->testAttribute(Qt::WA_WState_Visible);
8217
8218 if (wasVisible) {
8219 q->setAttribute(Qt::WA_WState_Visible, false);
8220
8221 }
8222
8223 QHideEvent hideEvent;
8224 QCoreApplication::sendEvent(q, &hideEvent);
8225 hideChildren(false);
8226
8227 // next bit tries to move the focus if the focus widget is now
8228 // hidden.
8229 if (wasVisible) {
8230 qApp->d_func()->sendSyntheticEnterLeave(q);
8231 QWidget *fw = QApplication::focusWidget();
8232 while (fw && !fw->isWindow()) {
8233 if (fw == q) {
8234 q->focusNextPrevChild(true);
8235 break;
8236 }
8237 fw = fw->parentWidget();
8238 }
8239 }
8240
8241 if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
8242 repaintManager->removeDirtyWidget(q);
8243
8244#if QT_CONFIG(accessibility)
8245 if (wasVisible) {
8246 QAccessibleEvent event(q, QAccessible::ObjectHide);
8247 QAccessible::updateAccessibility(&event);
8248 }
8249#endif
8250}
8251
8252void QWidgetPrivate::hide_sys()
8253{
8254 Q_Q(QWidget);
8255
8256 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
8257
8258 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
8259 q->setAttribute(Qt::WA_Mapped, false);
8260 // remove our window from the modal window list (native dialogs)
8261 if (window && q->isWindow()
8262#if QT_CONFIG(graphicsview)
8263 && (!extra || !extra->proxyWidget)
8264#endif
8265 && q->windowModality() != Qt::NonModal) {
8266 QGuiApplicationPrivate::hideModalWindow(window);
8267 }
8268 // do not return here, if window non-zero, we must hide it
8269 }
8270
8271 deactivateWidgetCleanup();
8272
8273 if (!q->isWindow()) {
8274 QWidget *p = q->parentWidget();
8275 if (p &&p->isVisible()) {
8276 if (renderToTexture)
8277 p->d_func()->invalidateBackingStore(q->geometry());
8278 else
8279 invalidateBackingStore(q->rect());
8280 }
8281 } else {
8282 invalidateBackingStore(q->rect());
8283 }
8284
8285 if (window)
8286 window->setNativeWindowVisibility(false);
8287}
8288
8289/*!
8290 \fn bool QWidget::isHidden() const
8291
8292 Returns \c true if the widget is hidden, otherwise returns \c false.
8293
8294 A hidden widget will only become visible when show() is called on
8295 it. It will not be automatically shown when the parent is shown.
8296
8297 To check visibility, use !isVisible() instead (notice the exclamation mark).
8298
8299 isHidden() implies !isVisible(), but a widget can be not visible
8300 and not hidden at the same time. This is the case for widgets that are children of
8301 widgets that are not visible.
8302
8303
8304 Widgets are hidden if:
8305 \list
8306 \li they were created as independent windows,
8307 \li they were created as children of visible widgets,
8308 \li hide() or setVisible(false) was called.
8309 \endlist
8310*/
8311
8312void QWidget::setVisible(bool visible)
8313{
8314 Q_D(QWidget);
8315 qCDebug(lcWidgetShowHide) << "Setting visibility of" << this
8316 << "with attributes" << WidgetAttributes{this}
8317 << "to" << visible << "via QWidget";
8318
8319 if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) == !visible)
8320 return;
8321
8322 if (d->dontSetExplicitShowHide) {
8323 d->dontSetExplicitShowHide = false;
8324 } else {
8325 // Remember that setVisible was called explicitly
8326 setAttribute(Qt::WA_WState_ExplicitShowHide);
8327 }
8328
8329 d->setVisible(visible);
8330}
8331
8332// This method is called from QWidgetWindow in response to QWindow::setVisible,
8333// and should match the semantics of QWindow::setVisible. QWidget::setVisible on
8334// the other hand keeps track of WA_WState_ExplicitShowHide in addition.
8335void QWidgetPrivate::setVisible(bool visible)
8336{
8337 Q_Q(QWidget);
8338 qCDebug(lcWidgetShowHide) << "Setting visibility of" << q
8339 << "with attributes" << WidgetAttributes{q}
8340 << "to" << visible << "via QWidgetPrivate";
8341
8342 if (visible) { // show
8343 // Designer uses a trick to make grabWidget work without showing
8344 if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
8345 && !q->parentWidget()->testAttribute(Qt::WA_WState_Created))
8346 q->parentWidget()->window()->d_func()->createRecursively();
8347
8348 //create toplevels but not children of non-visible parents
8349 QWidget *pw = q->parentWidget();
8350 if (!q->testAttribute(Qt::WA_WState_Created)
8351 && (q->isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
8352 q->create();
8353 }
8354
8355 bool wasResized = q->testAttribute(Qt::WA_Resized);
8356 Qt::WindowStates initialWindowState = q->windowState();
8357
8358 // polish if necessary
8359 q->ensurePolished();
8360
8361 // whether we need to inform the parent widget immediately
8362 bool needUpdateGeometry = !q->isWindow() && q->testAttribute(Qt::WA_WState_Hidden);
8363 // we are no longer hidden
8364 q->setAttribute(Qt::WA_WState_Hidden, false);
8365
8366 if (needUpdateGeometry)
8367 updateGeometry_helper(true);
8368
8369 // activate our layout before we and our children become visible
8370 if (layout)
8371 layout->activate();
8372
8373 if (!q->isWindow()) {
8374 QWidget *parent = q->parentWidget();
8375 while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
8376 parent->d_func()->layout->activate();
8377 if (parent->isWindow())
8378 break;
8379 parent = parent->parentWidget();
8380 }
8381 if (parent)
8382 parent->d_func()->setDirtyOpaqueRegion();
8383 }
8384
8385 // adjust size if necessary
8386 if (!wasResized
8387 && (q->isWindow() || !q->parentWidget()->d_func()->layout)) {
8388 if (q->isWindow()) {
8389 q->adjustSize();
8390 if (q->windowState() != initialWindowState)
8391 q->setWindowState(initialWindowState);
8392 } else {
8393 q->adjustSize();
8394 }
8395 q->setAttribute(Qt::WA_Resized, false);
8396 }
8397
8398 q->setAttribute(Qt::WA_KeyboardFocusChange, false);
8399
8400 if (q->isWindow() || q->parentWidget()->isVisible()) {
8401 show_helper();
8402
8403 qApp->d_func()->sendSyntheticEnterLeave(q);
8404 }
8405
8406 QEvent showToParentEvent(QEvent::ShowToParent);
8407 QCoreApplication::sendEvent(q, &showToParentEvent);
8408 } else { // hide
8409 if (QApplicationPrivate::hidden_focus_widget == q)
8410 QApplicationPrivate::hidden_focus_widget = nullptr;
8411
8412 // hw: The test on getOpaqueRegion() needs to be more intelligent
8413 // currently it doesn't work if the widget is hidden (the region will
8414 // be clipped). The real check should be testing the cached region
8415 // (and dirty flag) directly.
8416 if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty())
8417 q->parentWidget()->d_func()->setDirtyOpaqueRegion();
8418
8419 if (!q->testAttribute(Qt::WA_WState_Hidden)) {
8420 q->setAttribute(Qt::WA_WState_Hidden);
8421 hide_helper();
8422 }
8423
8424 // invalidate layout similar to updateGeometry()
8425 if (!q->isWindow() && q->parentWidget()) {
8426 if (q->parentWidget()->d_func()->layout)
8427 q->parentWidget()->d_func()->layout->invalidate();
8428 else if (q->parentWidget()->isVisible())
8429 QCoreApplication::postEvent(q->parentWidget(), new QEvent(QEvent::LayoutRequest));
8430 }
8431
8432 QEvent hideToParentEvent(QEvent::HideToParent);
8433 QCoreApplication::sendEvent(q, &hideToParentEvent);
8434 }
8435}
8436
8437/*!
8438 Convenience function, equivalent to setVisible(!\a hidden).
8439*/
8440void QWidget::setHidden(bool hidden)
8441{
8442 setVisible(!hidden);
8443}
8444
8445bool QWidgetPrivate::isExplicitlyHidden() const
8446{
8447 Q_Q(const QWidget);
8448 return q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
8449}
8450
8451void QWidgetPrivate::_q_showIfNotHidden()
8452{
8453 Q_Q(QWidget);
8454 if (!isExplicitlyHidden())
8455 q->setVisible(true);
8456}
8457
8458void QWidgetPrivate::showChildren(bool spontaneous)
8459{
8460 Q_Q(QWidget);
8461 qCDebug(lcWidgetShowHide) << "Showing children of" << q
8462 << "spontaneously" << spontaneous;
8463
8464 QList<QObject*> childList = children;
8465 for (int i = 0; i < childList.size(); ++i) {
8466 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8467 if (!widget)
8468 continue;
8469 qCDebug(lcWidgetShowHide) << "Considering" << widget
8470 << "with attributes" << WidgetAttributes{widget};
8471 if (widget->windowHandle() && !widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
8472 widget->setAttribute(Qt::WA_WState_Hidden, false);
8473 if (widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
8474 continue;
8475 if (spontaneous) {
8476 widget->setAttribute(Qt::WA_Mapped);
8477 widget->d_func()->showChildren(true);
8478 QShowEvent e;
8479 QApplication::sendSpontaneousEvent(widget, &e);
8480 } else {
8481 if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide)) {
8482 widget->d_func()->show_recursive();
8483 } else {
8484 // Call QWidget::setVisible() here, so that subclasses
8485 // that (wrongly) override setVisible to do initialization
8486 // will still be notified that they are made visible, but
8487 // do so without triggering ExplicitShowHide.
8488 widget->d_func()->dontSetExplicitShowHide = true;
8489 widget->setVisible(true);
8490 widget->d_func()->dontSetExplicitShowHide = false;
8491 }
8492 }
8493 }
8494}
8495
8496void QWidgetPrivate::hideChildren(bool spontaneous)
8497{
8498 Q_Q(QWidget);
8499 qCDebug(lcWidgetShowHide) << "Hiding children of" << q
8500 << "spontaneously" << spontaneous;
8501
8502 QList<QObject*> childList = children;
8503 for (int i = 0; i < childList.size(); ++i) {
8504 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8505 if (!widget)
8506 continue;
8507 qCDebug(lcWidgetShowHide) << "Considering" << widget
8508 << "with attributes" << WidgetAttributes{widget};
8509 if (widget->isWindow() || !widget->isVisible())
8510 continue;
8511
8512 if (spontaneous)
8513 widget->setAttribute(Qt::WA_Mapped, false);
8514 else
8515 widget->setAttribute(Qt::WA_WState_Visible, false);
8516 widget->d_func()->hideChildren(spontaneous);
8517 QHideEvent e;
8518 if (spontaneous) {
8519 QApplication::sendSpontaneousEvent(widget, &e);
8520 } else {
8521 QCoreApplication::sendEvent(widget, &e);
8522 if (widget->internalWinId()
8523 && widget->testAttribute(Qt::WA_DontCreateNativeAncestors)) {
8524 // hide_sys() on an ancestor won't have any affect on this
8525 // widget, so it needs an explicit hide_sys() of its own
8526 widget->d_func()->hide_sys();
8527 }
8528 }
8529 qApp->d_func()->sendSyntheticEnterLeave(widget);
8530#if QT_CONFIG(accessibility)
8531 if (!spontaneous) {
8532 QAccessibleEvent event(widget, QAccessible::ObjectHide);
8533 QAccessible::updateAccessibility(&event);
8534 }
8535#endif
8536 }
8537
8538 // If the window of this widget is not closed, then the leave event
8539 // will eventually handle the widget under mouse use case.
8540 // Otherwise, we need to explicitly handle it here.
8541 if (QWidget* widgetWindow = q->window();
8542 widgetWindow && widgetWindow->data->is_closing) {
8543 q->setAttribute(Qt::WA_UnderMouse, false);
8544 }
8545}
8546
8547/*!
8548 \internal
8549
8550 For windows, this is called from the QWidgetWindow::handleCloseEvent implementation,
8551 which QWidget::close indirectly calls by closing the QWindow. \a mode will be
8552 CloseWithEvent if QWidgetWindow::handleCloseEvent is called indirectly by
8553 QWindow::close, and CloseWithSpontaneousEvent if the close event originates from the
8554 system (i.e. the user clicked the close button in the title bar).
8555
8556 QDialog calls this method directly in its hide() implementation, which might be
8557 called from the QDialog::closeEvent override. \a mode will be set to CloseNoEvent
8558 to prevent recursion.
8559
8560 For non-windows, this is called directly by QWidget::close, and \a mode will be
8561 CloseWithEvent.
8562
8563 The function is also called by the QWidget destructor, with \a mode set to CloseNoEvent.
8564*/
8565bool QWidgetPrivate::handleClose(CloseMode mode)
8566{
8567 Q_Q(QWidget);
8568 qCDebug(lcWidgetShowHide) << "Handling close event for" << q;
8569
8570 if (data.is_closing)
8571 return true;
8572
8573 // We might not have initiated the close, so update the state now that we know
8574 data.is_closing = true;
8575
8576 QPointer<QWidget> that = q;
8577
8578 if (data.in_destructor)
8579 mode = CloseNoEvent;
8580
8581 if (mode != CloseNoEvent) {
8582 QCloseEvent e;
8583 if (mode == CloseWithSpontaneousEvent)
8584 QApplication::sendSpontaneousEvent(q, &e);
8585 else
8586 QCoreApplication::sendEvent(q, &e);
8587 if (!that.isNull() && !e.isAccepted()) {
8588 data.is_closing = false;
8589 return false;
8590 }
8591 }
8592
8593 // even for windows, make sure we deliver a hide event and that all children get hidden
8594 if (!that.isNull() && !q->isHidden())
8595 q->hide();
8596
8597 if (!that.isNull()) {
8598 data.is_closing = false;
8599 if (q->testAttribute(Qt::WA_DeleteOnClose)) {
8600 q->setAttribute(Qt::WA_DeleteOnClose, false);
8601 q->deleteLater();
8602 }
8603 }
8604 return true;
8605}
8606
8607
8608/*!
8609 Closes this widget. Returns \c true if the widget was closed;
8610 otherwise returns \c false.
8611
8612 First it sends the widget a QCloseEvent. The widget is
8613 \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
8614 the close event. If it \l{QEvent::ignore()}{ignores}
8615 the event, nothing happens. The default
8616 implementation of QWidget::closeEvent() accepts the close event.
8617
8618 If the widget has the Qt::WA_DeleteOnClose flag, the widget
8619 is also deleted. A close events is delivered to the widget no
8620 matter if the widget is visible or not.
8621
8622 The \l QGuiApplication::lastWindowClosed() signal is emitted when the
8623 last visible primary window (i.e. window with no parent) with the
8624 Qt::WA_QuitOnClose attribute set is closed. By default this
8625 attribute is set for all widgets except transient windows such as
8626 splash screens, tool windows, and popup menus.
8627
8628*/
8629
8630bool QWidget::close()
8631{
8632 return d_func()->close();
8633}
8634
8635bool QWidgetPrivate::close()
8636{
8637 // FIXME: We're not setting is_closing here, even though that would
8638 // make sense, as the code below will not end up in handleClose to
8639 // reset is_closing when there's a QWindow, but no QPlatformWindow,
8640 // and we can't assume close is synchronous so we can't reset it here.
8641
8642 // Close native widgets via QWindow::close() in order to run QWindow
8643 // close code. The QWidget-specific close code in handleClose() will
8644 // in this case be called from the Close event handler in QWidgetWindow.
8645 if (QWindow *widgetWindow = windowHandle()) {
8646 if (widgetWindow->isTopLevel())
8647 return widgetWindow->close();
8648 }
8649
8650 return handleClose(QWidgetPrivate::CloseWithEvent);
8651}
8652
8653/*!
8654 \property QWidget::visible
8655 \brief whether the widget is visible
8656
8657 Calling setVisible(true) or show() sets the widget to visible
8658 status if all its parent widgets up to the window are visible. If
8659 an ancestor is not visible, the widget won't become visible until
8660 all its ancestors are shown. If its size or position has changed,
8661 Qt guarantees that a widget gets move and resize events just
8662 before it is shown. If the widget has not been resized yet, Qt
8663 will adjust the widget's size to a useful default using
8664 adjustSize().
8665
8666 Calling setVisible(false) or hide() hides a widget explicitly. An
8667 explicitly hidden widget will never become visible, even if all
8668 its ancestors become visible, unless you show it.
8669
8670 A widget receives show and hide events when its visibility status
8671 changes. Between a hide and a show event, there is no need to
8672 waste CPU cycles preparing or displaying information to the user.
8673 A video application, for example, might simply stop generating new
8674 frames.
8675
8676 A widget that happens to be obscured by other windows on the
8677 screen is considered to be visible. The same applies to iconified
8678 windows and windows that exist on another virtual
8679 desktop (on platforms that support this concept). A widget
8680 receives spontaneous show and hide events when its mapping status
8681 is changed by the window system, e.g. a spontaneous hide event
8682 when the user minimizes the window, and a spontaneous show event
8683 when the window is restored again.
8684
8685 You seldom have to reimplement the setVisible() function. If
8686 you need to change some settings before a widget is shown, use
8687 showEvent() instead. If you need to do some delayed initialization
8688 use the Polish event delivered to the event() function.
8689
8690 \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
8691 showEvent(), hideEvent()
8692*/
8693
8694
8695/*!
8696 Returns \c true if this widget would become visible if \a ancestor is
8697 shown; otherwise returns \c false.
8698
8699 The true case occurs if neither the widget itself nor any parent
8700 up to but excluding \a ancestor has been explicitly hidden.
8701
8702 This function will still return true if the widget is obscured by
8703 other windows on the screen, but could be physically visible if it
8704 or they were to be moved.
8705
8706 isVisibleTo(0) is identical to isVisible().
8707
8708 \sa show(), hide(), isVisible()
8709*/
8710
8711bool QWidget::isVisibleTo(const QWidget *ancestor) const
8712{
8713 if (!ancestor)
8714 return isVisible();
8715 const QWidget * w = this;
8716 while (!w->isHidden()
8717 && !w->isWindow()
8718 && w->parentWidget()
8719 && w->parentWidget() != ancestor)
8720 w = w->parentWidget();
8721 return !w->isHidden();
8722}
8723
8724
8725/*!
8726 Returns the unobscured region where paint events can occur.
8727
8728 For visible widgets, this is an approximation of the area not
8729 covered by other widgets; otherwise, this is an empty region.
8730
8731 The repaint() function calls this function if necessary, so in
8732 general you do not need to call it.
8733
8734*/
8735QRegion QWidget::visibleRegion() const
8736{
8737 Q_D(const QWidget);
8738
8739 QRect clipRect = d->clipRect();
8740 if (clipRect.isEmpty())
8741 return QRegion();
8742 QRegion r(clipRect);
8743 d->subtractOpaqueChildren(r, clipRect);
8744 d->subtractOpaqueSiblings(r);
8745 return r;
8746}
8747
8748
8749QSize QWidgetPrivate::adjustedSize() const
8750{
8751 Q_Q(const QWidget);
8752
8753 QSize s = q->sizeHint();
8754
8755 if (q->isWindow()) {
8756 Qt::Orientations exp;
8757 if (layout) {
8758 if (layout->hasHeightForWidth())
8759 s.setHeight(layout->totalHeightForWidth(s.width()));
8760 exp = layout->expandingDirections();
8761 } else
8762 {
8763 if (q->sizePolicy().hasHeightForWidth())
8764 s.setHeight(q->heightForWidth(s.width()));
8765 exp = q->sizePolicy().expandingDirections();
8766 }
8767 if (exp & Qt::Horizontal)
8768 s.setWidth(qMax(s.width(), 200));
8769 if (exp & Qt::Vertical)
8770 s.setHeight(qMax(s.height(), 100));
8771
8772 QRect screen;
8773 if (const QScreen *screenAtPoint = QGuiApplication::screenAt(q->pos()))
8774 screen = screenAtPoint->geometry();
8775 else
8776 screen = QGuiApplication::primaryScreen()->geometry();
8777
8778 s.setWidth(qMin(s.width(), screen.width()*2/3));
8779 s.setHeight(qMin(s.height(), screen.height()*2/3));
8780
8781 if (QTLWExtra *extra = maybeTopData())
8782 extra->sizeAdjusted = true;
8783 }
8784
8785 if (!s.isValid()) {
8786 QRect r = q->childrenRect(); // get children rectangle
8787 if (r.isNull())
8788 return s;
8789 s = r.size() + QSize(2 * r.x(), 2 * r.y());
8790 }
8791
8792 return s;
8793}
8794
8795/*!
8796 Adjusts the size of the widget to fit its contents.
8797
8798 This function uses sizeHint() if it is valid, i.e., the size hint's width
8799 and height are >= 0. Otherwise, it sets the size to the children
8800 rectangle that covers all child widgets (the union of all child widget
8801 rectangles).
8802
8803 For windows, the screen size is also taken into account. If the sizeHint()
8804 is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
8805 {expanding}, the window will be at least (200, 100). The maximum size of
8806 a window is 2/3 of the screen's width and height.
8807
8808 \sa sizeHint(), childrenRect()
8809*/
8810
8811void QWidget::adjustSize()
8812{
8813 Q_D(QWidget);
8814 ensurePolished();
8815 QSize s = d->adjustedSize();
8816
8817 if (d->layout)
8818 d->layout->activate();
8819
8820 if (s.isValid())
8821 resize(s);
8822}
8823
8824
8825/*!
8826 \property QWidget::sizeHint
8827 \brief the recommended size for the widget
8828
8829 If the value of this property is an invalid size, no size is
8830 recommended.
8831
8832 The default implementation of sizeHint() returns an invalid size
8833 if there is no layout for this widget, and returns the layout's
8834 preferred size otherwise.
8835
8836 \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
8837 setMinimumSize(), updateGeometry()
8838*/
8839
8840QSize QWidget::sizeHint() const
8841{
8842 Q_D(const QWidget);
8843 if (d->layout)
8844 return d->layout->totalSizeHint();
8845 return QSize(-1, -1);
8846}
8847
8848/*!
8849 \property QWidget::minimumSizeHint
8850 \brief the recommended minimum size for the widget
8851
8852 If the value of this property is an invalid size, no minimum size
8853 is recommended.
8854
8855 The default implementation of minimumSizeHint() returns an invalid
8856 size if there is no layout for this widget, and returns the
8857 layout's minimum size otherwise. Most built-in widgets reimplement
8858 minimumSizeHint().
8859
8860 \l QLayout will never resize a widget to a size smaller than the
8861 minimum size hint unless minimumSize() is set or the size policy is
8862 set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
8863 size hint will be ignored.
8864
8865 \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
8866*/
8867QSize QWidget::minimumSizeHint() const
8868{
8869 Q_D(const QWidget);
8870 if (d->layout)
8871 return d->layout->totalMinimumSize();
8872 return QSize(-1, -1);
8873}
8874
8875
8876/*!
8877 \fn QWidget *QWidget::parentWidget() const
8878
8879 Returns the parent of this widget, or \nullptr if it does not have any
8880 parent widget.
8881*/
8882
8883
8884/*!
8885 Returns \c true if this widget is a parent, (or grandparent and so on
8886 to any level), of the given \a child, and both widgets are within
8887 the same window; otherwise returns \c false.
8888*/
8889
8890bool QWidget::isAncestorOf(const QWidget *child) const
8891{
8892 while (child) {
8893 if (child == this)
8894 return true;
8895 if (child->isWindow())
8896 return false;
8897 child = child->parentWidget();
8898 }
8899 return false;
8900}
8901
8902/*****************************************************************************
8903 QWidget event handling
8904 *****************************************************************************/
8905
8906/*!
8907 This is the main event handler; it handles event \a event. You can
8908 reimplement this function in a subclass, but we recommend using
8909 one of the specialized event handlers instead.
8910
8911 Key press and release events are treated differently from other
8912 events. event() checks for Tab and Shift+Tab and tries to move the
8913 focus appropriately. If there is no widget to move the focus to
8914 (or the key press is not Tab or Shift+Tab), event() calls
8915 keyPressEvent().
8916
8917 Mouse and tablet event handling is also slightly special: only
8918 when the widget is \l enabled, event() will call the specialized
8919 handlers such as mousePressEvent(); otherwise it will discard the
8920 event.
8921
8922 This function returns \c true if the event was recognized, otherwise
8923 it returns \c false. If the recognized event was accepted (see \l
8924 QEvent::accepted), any further processing such as event
8925 propagation to the parent widget stops.
8926
8927 \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
8928 keyPressEvent(), keyReleaseEvent(), leaveEvent(),
8929 mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
8930 mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
8931 QObject::event(), QObject::timerEvent()
8932*/
8933
8934bool QWidget::event(QEvent *event)
8935{
8936 Q_D(QWidget);
8937
8938 // ignore mouse and key events when disabled
8939 if (!isEnabled()) {
8940 switch(event->type()) {
8941 case QEvent::TabletPress:
8942 case QEvent::TabletRelease:
8943 case QEvent::TabletMove:
8944 case QEvent::MouseButtonPress:
8945 case QEvent::MouseButtonRelease:
8946 case QEvent::MouseButtonDblClick:
8947 case QEvent::MouseMove:
8948 case QEvent::TouchBegin:
8949 case QEvent::TouchUpdate:
8950 case QEvent::TouchEnd:
8951 case QEvent::TouchCancel:
8952 case QEvent::ContextMenu:
8953 case QEvent::KeyPress:
8954 case QEvent::KeyRelease:
8955#if QT_CONFIG(wheelevent)
8956 case QEvent::Wheel:
8957#endif
8958 return false;
8959 default:
8960 break;
8961 }
8962 }
8963 switch (event->type()) {
8964 case QEvent::PlatformSurface: {
8965 // Sync up QWidget's view of whether or not the widget has been created
8966 switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
8967 case QPlatformSurfaceEvent::SurfaceCreated:
8968 if (!testAttribute(Qt::WA_WState_Created))
8969 create();
8970 break;
8971 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
8972 if (testAttribute(Qt::WA_WState_Created)) {
8973 // Child windows have already been destroyed by QWindow,
8974 // so we skip them here.
8975 destroy(false, false);
8976 }
8977 break;
8978 }
8979 break;
8980 }
8981 case QEvent::MouseMove:
8982 mouseMoveEvent((QMouseEvent*)event);
8983 break;
8984
8985 case QEvent::MouseButtonPress:
8986 mousePressEvent((QMouseEvent*)event);
8987 break;
8988
8989 case QEvent::MouseButtonRelease:
8990 mouseReleaseEvent((QMouseEvent*)event);
8991 break;
8992
8993 case QEvent::MouseButtonDblClick:
8994 mouseDoubleClickEvent((QMouseEvent*)event);
8995 break;
8996#if QT_CONFIG(wheelevent)
8997 case QEvent::Wheel:
8998 wheelEvent((QWheelEvent*)event);
8999 break;
9000#endif
9001#if QT_CONFIG(tabletevent)
9002 case QEvent::TabletMove:
9003 if (static_cast<QTabletEvent *>(event)->buttons() == Qt::NoButton && !testAttribute(Qt::WA_TabletTracking))
9004 break;
9005 Q_FALLTHROUGH();
9006 case QEvent::TabletPress:
9007 case QEvent::TabletRelease:
9008 tabletEvent((QTabletEvent*)event);
9009 break;
9010#endif
9011 case QEvent::KeyPress: {
9012 QKeyEvent *k = static_cast<QKeyEvent *>(event);
9013 bool res = false;
9014 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
9015 if (k->key() == Qt::Key_Backtab
9016 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
9017 res = focusNextPrevChild(false);
9018 else if (k->key() == Qt::Key_Tab)
9019 res = focusNextPrevChild(true);
9020 if (res)
9021 break;
9022 }
9023 keyPressEvent(k);
9024#if QT_CONFIG(whatsthis)
9025 if (!k->isAccepted()
9026 && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
9027 && d->whatsThis.size()) {
9028 QWhatsThis::showText(mapToGlobal(inputMethodQuery(Qt::ImCursorRectangle).toRect().center()), d->whatsThis, this);
9029 k->accept();
9030 }
9031#endif
9032 }
9033 break;
9034
9035 case QEvent::KeyRelease:
9036 keyReleaseEvent((QKeyEvent*)event);
9037 Q_FALLTHROUGH();
9038 case QEvent::ShortcutOverride:
9039 break;
9040
9041 case QEvent::InputMethod:
9042 inputMethodEvent((QInputMethodEvent *) event);
9043 break;
9044
9045 case QEvent::InputMethodQuery: {
9046 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
9047 Qt::InputMethodQueries queries = query->queries();
9048 for (uint i = 0; i < 32; ++i) {
9049 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
9050 if (q) {
9051 QVariant v = inputMethodQuery(q);
9052 if (q == Qt::ImEnabled && !v.isValid() && isEnabled()) {
9053 // Qt:ImEnabled was added in Qt 5.3. So not all widgets support it, even
9054 // if they implement IM otherwise (by overriding inputMethodQuery()). Instead
9055 // they set the widget attribute Qt::WA_InputMethodEnabled. But this attribute
9056 // will only be set if the widget supports IM _and_ is not read-only. So for
9057 // read-only widgets, not all IM features will be supported when ImEnabled is
9058 // not implemented explicitly (e.g selection handles for read-only widgets on iOS).
9059 v = QVariant(testAttribute(Qt::WA_InputMethodEnabled));
9060 }
9061 query->setValue(q, v);
9062 }
9063 }
9064 query->accept();
9065 }
9066 break;
9067
9068 case QEvent::PolishRequest:
9069 ensurePolished();
9070 break;
9071
9072 case QEvent::Polish: {
9073 style()->polish(this);
9074 setAttribute(Qt::WA_WState_Polished);
9075 if (!QApplication::font(this).isCopyOf(QApplication::font()))
9076 d->resolveFont();
9077 if (!QApplication::palette(this).isCopyOf(QGuiApplication::palette()))
9078 d->resolvePalette();
9079 }
9080 break;
9081
9082 case QEvent::ApplicationWindowIconChange:
9083 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon)) {
9084 d->setWindowIcon_sys();
9085 d->setWindowIcon_helper();
9086 }
9087 break;
9088 case QEvent::FocusIn:
9089 focusInEvent((QFocusEvent*)event);
9090 d->updateWidgetTransform(event);
9091 break;
9092
9093 case QEvent::FocusOut:
9094 focusOutEvent((QFocusEvent*)event);
9095 break;
9096
9097 case QEvent::Enter:
9098#if QT_CONFIG(statustip)
9099 if (d->statusTip.size()) {
9100 QStatusTipEvent tip(d->statusTip);
9101 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
9102 }
9103#endif
9104 enterEvent(static_cast<QEnterEvent*>(event));
9105 break;
9106
9107 case QEvent::Leave:
9108#if QT_CONFIG(statustip)
9109 if (d->statusTip.size()) {
9110 QString empty;
9111 QStatusTipEvent tip(empty);
9112 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
9113 }
9114#endif
9115 leaveEvent(event);
9116 break;
9117
9118 case QEvent::HoverEnter:
9119 case QEvent::HoverLeave:
9120 update();
9121 break;
9122
9123 case QEvent::Paint:
9124 // At this point the event has to be delivered, regardless
9125 // whether the widget isVisible() or not because it
9126 // already went through the filters
9127 paintEvent((QPaintEvent*)event);
9128 break;
9129
9130 case QEvent::Move:
9131 moveEvent((QMoveEvent*)event);
9132 d->updateWidgetTransform(event);
9133 break;
9134
9135 case QEvent::Resize:
9136 resizeEvent((QResizeEvent*)event);
9137 d->updateWidgetTransform(event);
9138 break;
9139
9140 case QEvent::Close:
9141 closeEvent((QCloseEvent *)event);
9142 break;
9143
9144#ifndef QT_NO_CONTEXTMENU
9145 case QEvent::ContextMenu:
9146 switch (data->context_menu_policy) {
9147 case Qt::PreventContextMenu:
9148 break;
9149 case Qt::DefaultContextMenu:
9150 contextMenuEvent(static_cast<QContextMenuEvent *>(event));
9151 break;
9152 case Qt::CustomContextMenu:
9153 emit customContextMenuRequested(static_cast<QContextMenuEvent *>(event)->pos());
9154 break;
9155#if QT_CONFIG(menu)
9156 case Qt::ActionsContextMenu:
9157 if (d->actions.size()) {
9158 QMenu::exec(d->actions, static_cast<QContextMenuEvent *>(event)->globalPos(),
9159 nullptr, this);
9160 break;
9161 }
9162 Q_FALLTHROUGH();
9163#endif
9164 default:
9165 event->ignore();
9166 break;
9167 }
9168 break;
9169#endif // QT_NO_CONTEXTMENU
9170
9171#if QT_CONFIG(draganddrop)
9172 case QEvent::Drop:
9173 dropEvent((QDropEvent*) event);
9174 break;
9175
9176 case QEvent::DragEnter:
9177 dragEnterEvent((QDragEnterEvent*) event);
9178 break;
9179
9180 case QEvent::DragMove:
9181 dragMoveEvent((QDragMoveEvent*) event);
9182 break;
9183
9184 case QEvent::DragLeave:
9185 dragLeaveEvent((QDragLeaveEvent*) event);
9186 break;
9187#endif
9188
9189 case QEvent::Show:
9190 showEvent((QShowEvent*) event);
9191 break;
9192
9193 case QEvent::Hide:
9194 hideEvent((QHideEvent*) event);
9195 break;
9196
9197 case QEvent::ShowWindowRequest:
9198 if (!isHidden())
9199 d->show_sys();
9200 break;
9201
9202 case QEvent::ApplicationFontChange:
9203 d->resolveFont();
9204 break;
9205 case QEvent::ApplicationPaletteChange:
9206 d->resolvePalette();
9207 break;
9208
9209 case QEvent::ToolBarChange:
9210 case QEvent::ActivationChange:
9211 case QEvent::EnabledChange:
9212 case QEvent::FontChange:
9213 case QEvent::StyleChange:
9214 case QEvent::PaletteChange:
9215 case QEvent::WindowTitleChange:
9216 case QEvent::IconTextChange:
9217 case QEvent::ModifiedChange:
9218 case QEvent::MouseTrackingChange:
9219 case QEvent::TabletTrackingChange:
9220 case QEvent::ParentChange:
9221 case QEvent::LocaleChange:
9222 case QEvent::MacSizeChange:
9223 case QEvent::ContentsRectChange:
9224 case QEvent::ThemeChange:
9225 case QEvent::ReadOnlyChange:
9226 changeEvent(event);
9227 break;
9228
9229 case QEvent::WindowStateChange: {
9230 const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
9231 if (wasMinimized != isMinimized()) {
9232 QWidget *widget = const_cast<QWidget *>(this);
9233 if (wasMinimized) {
9234 // Always send the spontaneous events here, otherwise it can break the application!
9235 if (!d->childrenShownByExpose) {
9236 // Show widgets only when they are not yet shown by the expose event
9237 d->showChildren(true);
9238 QShowEvent showEvent;
9239 QCoreApplication::sendSpontaneousEvent(widget, &showEvent);
9240 }
9241 d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
9242 } else {
9243 QHideEvent hideEvent;
9244 QCoreApplication::sendSpontaneousEvent(widget, &hideEvent);
9245 d->hideChildren(true);
9246 d->childrenHiddenByWState = true;
9247 }
9248 d->childrenShownByExpose = false; // Set it always to "false" when window state changes
9249 }
9250 changeEvent(event);
9251 }
9252 break;
9253
9254 case QEvent::WindowActivate:
9255 case QEvent::WindowDeactivate: {
9256 if (isVisible() && !palette().isEqual(QPalette::Active, QPalette::Inactive))
9257 update();
9258 QList<QObject*> childList = d->children;
9259 for (int i = 0; i < childList.size(); ++i) {
9260 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9261 if (w && w->isVisible() && !w->isWindow())
9262 QCoreApplication::sendEvent(w, event);
9263 }
9264 break; }
9265
9266 case QEvent::LanguageChange:
9267 changeEvent(event);
9268 {
9269 QList<QObject*> childList = d->children;
9270 for (int i = 0; i < childList.size(); ++i) {
9271 QObject *o = childList.at(i);
9272 if (o)
9273 QCoreApplication::sendEvent(o, event);
9274 }
9275 }
9276 update();
9277 break;
9278
9279 case QEvent::ApplicationLayoutDirectionChange:
9280 d->resolveLayoutDirection();
9281 break;
9282
9283 case QEvent::LayoutDirectionChange:
9284 if (d->layout)
9285 d->layout->invalidate();
9286 update();
9287 changeEvent(event);
9288 break;
9289 case QEvent::UpdateRequest:
9290 d->syncBackingStore();
9291 break;
9292 case QEvent::UpdateLater:
9293 update(static_cast<QUpdateLaterEvent*>(event)->region());
9294 break;
9295 case QEvent::StyleAnimationUpdate:
9296 if (isVisible() && !window()->isMinimized()) {
9297 event->accept();
9298 update();
9299 }
9300 break;
9301
9302 case QEvent::WindowBlocked:
9303 case QEvent::WindowUnblocked:
9304 if (!d->children.isEmpty()) {
9305 QWidget *modalWidget = QApplication::activeModalWidget();
9306 for (int i = 0; i < d->children.size(); ++i) {
9307 QObject *o = d->children.at(i);
9308 if (o && o != modalWidget && o->isWidgetType()) {
9309 QWidget *w = static_cast<QWidget *>(o);
9310 // do not forward the event to child windows; QApplication does this for us
9311 if (!w->isWindow())
9312 QCoreApplication::sendEvent(w, event);
9313 }
9314 }
9315 }
9316 break;
9317#if QT_CONFIG(tooltip)
9318 case QEvent::ToolTip:
9319 if (!d->toolTip.isEmpty())
9320 QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), d->toolTip, this, QRect(), d->toolTipDuration);
9321 else
9322 event->ignore();
9323 break;
9324#endif
9325#if QT_CONFIG(whatsthis)
9326 case QEvent::WhatsThis:
9327 if (d->whatsThis.size())
9328 QWhatsThis::showText(static_cast<QHelpEvent *>(event)->globalPos(), d->whatsThis, this);
9329 else
9330 event->ignore();
9331 break;
9332 case QEvent::QueryWhatsThis:
9333 if (d->whatsThis.isEmpty())
9334 event->ignore();
9335 break;
9336#endif
9337 case QEvent::EmbeddingControl:
9338 d->topData()->frameStrut.setCoords(0 ,0, 0, 0);
9339 data->fstrut_dirty = false;
9340 break;
9341#ifndef QT_NO_ACTION
9342 case QEvent::ActionAdded:
9343 case QEvent::ActionRemoved:
9344 case QEvent::ActionChanged:
9345 actionEvent((QActionEvent*)event);
9346 break;
9347#endif
9348
9349 case QEvent::KeyboardLayoutChange:
9350 {
9351 changeEvent(event);
9352
9353 // inform children of the change
9354 QList<QObject*> childList = d->children;
9355 for (int i = 0; i < childList.size(); ++i) {
9356 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9357 if (w && w->isVisible() && !w->isWindow())
9358 QCoreApplication::sendEvent(w, event);
9359 }
9360 break;
9361 }
9362 case QEvent::TouchBegin:
9363 case QEvent::TouchUpdate:
9364 case QEvent::TouchEnd:
9365 case QEvent::TouchCancel:
9366 {
9367 event->ignore();
9368 break;
9369 }
9370#ifndef QT_NO_GESTURES
9371 case QEvent::Gesture:
9372 event->ignore();
9373 break;
9374#endif
9375 case QEvent::ScreenChangeInternal:
9376 if (const QTLWExtra *te = d->maybeTopData()) {
9377 const QWindow *win = te->window;
9378 d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
9379 }
9380 break;
9381 case QEvent::DevicePixelRatioChange:
9382 if (d->data.fnt.d->dpi != logicalDpiY())
9383 d->updateFont(d->data.fnt);
9384 d->renderToTextureReallyDirty = 1;
9385 break;
9386 case QEvent::DynamicPropertyChange: {
9387 const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
9388 if (propName.size() == 13 && !qstrncmp(propName, "_q_customDpi", 12)) {
9389 uint value = property(propName.constData()).toUInt();
9390 if (!d->extra)
9391 d->createExtra();
9392 const char axis = propName.at(12);
9393 if (axis == 'X')
9394 d->extra->customDpiX = value;
9395 else if (axis == 'Y')
9396 d->extra->customDpiY = value;
9397 d->updateFont(d->data.fnt);
9398 }
9399 if (windowHandle() && !qstrncmp(propName, "_q_platform_", 12))
9400 windowHandle()->setProperty(propName, property(propName));
9401 Q_FALLTHROUGH();
9402 }
9403 default:
9404 return QObject::event(event);
9405 }
9406 return true;
9407}
9408
9409/*!
9410 This event handler can be reimplemented to handle state changes.
9411
9412 The state being changed in this event can be retrieved through the \a event
9413 supplied.
9414
9415 Change events include: QEvent::ToolBarChange,
9416 QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
9417 QEvent::StyleChange, QEvent::PaletteChange,
9418 QEvent::WindowTitleChange, QEvent::IconTextChange,
9419 QEvent::ModifiedChange, QEvent::MouseTrackingChange,
9420 QEvent::ParentChange, QEvent::WindowStateChange,
9421 QEvent::LanguageChange, QEvent::LocaleChange,
9422 QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
9423
9424*/
9425void QWidget::changeEvent(QEvent * event)
9426{
9427 switch(event->type()) {
9428 case QEvent::EnabledChange: {
9429 update();
9430#if QT_CONFIG(accessibility)
9431 QAccessible::State s;
9432 s.disabled = true;
9433 QAccessibleStateChangeEvent event(this, s);
9434 QAccessible::updateAccessibility(&event);
9435#endif
9436 break;
9437 }
9438
9439 case QEvent::FontChange:
9440 case QEvent::StyleChange: {
9441 Q_D(QWidget);
9442 update();
9443 updateGeometry();
9444 if (d->layout)
9445 d->layout->invalidate();
9446 break;
9447 }
9448
9449 case QEvent::PaletteChange:
9450 update();
9451 break;
9452
9453 case QEvent::ThemeChange:
9454 if (QGuiApplication::desktopSettingsAware()
9455 && qApp && !QCoreApplication::closingDown()) {
9456 if (testAttribute(Qt::WA_WState_Polished))
9457 QApplication::style()->unpolish(this);
9458 if (testAttribute(Qt::WA_WState_Polished))
9459 QApplication::style()->polish(this);
9460 QEvent styleChangedEvent(QEvent::StyleChange);
9461 QCoreApplication::sendEvent(this, &styleChangedEvent);
9462 if (isVisible())
9463 update();
9464 }
9465 break;
9466
9467#ifdef Q_OS_MACOS
9468 case QEvent::MacSizeChange:
9469 updateGeometry();
9470 break;
9471#endif
9472
9473 default:
9474 break;
9475 }
9476}
9477
9478/*!
9479 This event handler, for event \a event, can be reimplemented in a
9480 subclass to receive mouse move events for the widget.
9481
9482 If mouse tracking is switched off, mouse move events only occur if
9483 a mouse button is pressed while the mouse is being moved. If mouse
9484 tracking is switched on, mouse move events occur even if no mouse
9485 button is pressed.
9486
9487 QMouseEvent::position() reports the position of the mouse cursor,
9488 relative to this widget. For press and release events, the
9489 position is usually the same as the position of the last mouse
9490 move event, but it might be different if the user's hand shakes.
9491 This is a feature of the underlying window system, not Qt.
9492
9493 If you want to show a tooltip immediately, while the mouse is
9494 moving (e.g., to get the mouse coordinates with QMouseEvent::position()
9495 and show them as a tooltip), you must first enable mouse tracking
9496 as described above. Then, to ensure that the tooltip is updated
9497 immediately, you must call QToolTip::showText() instead of
9498 setToolTip() in your implementation of mouseMoveEvent().
9499
9500 \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
9501 mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
9502*/
9503
9504void QWidget::mouseMoveEvent(QMouseEvent *event)
9505{
9506 event->ignore();
9507}
9508
9509/*!
9510 This event handler, for event \a event, can be reimplemented in a
9511 subclass to receive mouse press events for the widget.
9512
9513 If you create new widgets in the mousePressEvent() the
9514 mouseReleaseEvent() may not end up where you expect, depending on
9515 the underlying window system (or X11 window manager), the widgets'
9516 location and maybe more.
9517
9518 The default implementation implements the closing of popup widgets
9519 when you click outside the window. For other widget types it does
9520 nothing.
9521
9522 \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
9523 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9524*/
9525
9526void QWidget::mousePressEvent(QMouseEvent *event)
9527{
9528 event->ignore();
9529 if ((windowType() == Qt::Popup)) {
9530 event->accept();
9531 QWidget* w;
9532 while ((w = QApplication::activePopupWidget()) && w != this){
9533 w->close();
9534 if (QApplication::activePopupWidget() == w) // widget does not want to disappear
9535 w->hide(); // hide at least
9536 }
9537 if (!rect().contains(event->position().toPoint())){
9538 close();
9539 }
9540 }
9541}
9542
9543/*!
9544 This event handler, for event \a event, can be reimplemented in a
9545 subclass to receive mouse release events for the widget.
9546
9547 \sa mousePressEvent(), mouseDoubleClickEvent(),
9548 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9549*/
9550
9551void QWidget::mouseReleaseEvent(QMouseEvent *event)
9552{
9553 event->ignore();
9554}
9555
9556/*!
9557 This event handler, for event \a event, can be reimplemented in a
9558 subclass to receive mouse double click events for the widget.
9559
9560 The default implementation calls mousePressEvent().
9561
9562 \note The widget will also receive mouse press and mouse release
9563 events in addition to the double click event. And if another widget
9564 that overlaps this widget disappears in response to press or
9565 release events, then this widget will only receive the double click
9566 event. It is up to the developer to ensure that the application
9567 interprets these events correctly.
9568
9569 \sa mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(),
9570 event(), QMouseEvent
9571*/
9572
9573void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
9574{
9575 mousePressEvent(event);
9576}
9577
9578#if QT_CONFIG(wheelevent)
9579/*!
9580 This event handler, for event \a event, can be reimplemented in a
9581 subclass to receive wheel events for the widget.
9582
9583 If you reimplement this handler, it is very important that you
9584 \l{QEvent}{ignore()} the event if you do not handle
9585 it, so that the widget's parent can interpret it.
9586
9587 The default implementation ignores the event.
9588
9589 \sa QEvent::ignore(), QEvent::accept(), event(),
9590 QWheelEvent
9591*/
9592
9593void QWidget::wheelEvent(QWheelEvent *event)
9594{
9595 event->ignore();
9596}
9597#endif // QT_CONFIG(wheelevent)
9598
9599#if QT_CONFIG(tabletevent)
9600/*!
9601 This event handler, for event \a event, can be reimplemented in a
9602 subclass to receive tablet events for the widget.
9603
9604 If you reimplement this handler, it is very important that you
9605 \l{QEvent}{ignore()} the event if you do not handle
9606 it, so that the widget's parent can interpret it.
9607
9608 The default implementation ignores the event.
9609
9610 If tablet tracking is switched off, tablet move events only occur if the
9611 stylus is in contact with the tablet, or at least one stylus button is
9612 pressed, while the stylus is being moved. If tablet tracking is switched on,
9613 tablet move events occur even while the stylus is hovering in proximity of
9614 the tablet, with no buttons pressed.
9615
9616 \sa QEvent::ignore(), QEvent::accept(), event(), setTabletTracking(),
9617 QTabletEvent
9618*/
9619
9620void QWidget::tabletEvent(QTabletEvent *event)
9621{
9622 event->ignore();
9623}
9624#endif // QT_CONFIG(tabletevent)
9625
9626/*!
9627 This event handler, for event \a event, can be reimplemented in a
9628 subclass to receive key press events for the widget.
9629
9630 A widget must call setFocusPolicy() to accept focus initially and
9631 have focus in order to receive a key press event.
9632
9633 If you reimplement this handler, it is very important that you
9634 call the base class implementation if you do not act upon the key.
9635
9636 The default implementation closes popup widgets if the user
9637 presses the key sequence for QKeySequence::Cancel (typically the
9638 Escape key). Otherwise the event is ignored, so that the widget's
9639 parent can interpret it.
9640
9641 Note that QKeyEvent starts with isAccepted() == true, so you do not
9642 need to call QKeyEvent::accept() - just do not call the base class
9643 implementation if you act upon the key.
9644
9645 \sa keyReleaseEvent(), setFocusPolicy(),
9646 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9647*/
9648
9649void QWidget::keyPressEvent(QKeyEvent *event)
9650{
9651#ifndef QT_NO_SHORTCUT
9652 if ((windowType() == Qt::Popup) && event->matches(QKeySequence::Cancel)) {
9653 event->accept();
9654 close();
9655 } else
9656#endif
9657 {
9658 event->ignore();
9659 }
9660}
9661
9662/*!
9663 This event handler, for event \a event, can be reimplemented in a
9664 subclass to receive key release events for the widget.
9665
9666 A widget must \l{setFocusPolicy()}{accept focus}
9667 initially and \l{hasFocus()}{have focus} in order to
9668 receive a key release event.
9669
9670 If you reimplement this handler, it is very important that you
9671 call the base class implementation if you do not act upon the key.
9672
9673 The default implementation ignores the event, so that the widget's
9674 parent can interpret it.
9675
9676 Note that QKeyEvent starts with isAccepted() == true, so you do not
9677 need to call QKeyEvent::accept() - just do not call the base class
9678 implementation if you act upon the key.
9679
9680 \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(),
9681 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9682*/
9683
9684void QWidget::keyReleaseEvent(QKeyEvent *event)
9685{
9686 event->ignore();
9687}
9688
9689/*!
9690 \fn void QWidget::focusInEvent(QFocusEvent *event)
9691
9692 This event handler can be reimplemented in a subclass to receive
9693 keyboard focus events (focus received) for the widget. The event
9694 is passed in the \a event parameter
9695
9696 A widget normally must setFocusPolicy() to something other than
9697 Qt::NoFocus to receive focus events. (Note that the
9698 application programmer can call setFocus() on any widget, even
9699 those that do not normally accept focus.)
9700
9701 The default implementation updates the widget (except for windows
9702 that do not specify a focusPolicy()).
9703
9704 \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
9705 keyReleaseEvent(), event(), QFocusEvent
9706*/
9707
9708void QWidget::focusInEvent(QFocusEvent *)
9709{
9710 if (focusPolicy() != Qt::NoFocus || !isWindow()) {
9711 update();
9712 }
9713}
9714
9715/*!
9716 \fn void QWidget::focusOutEvent(QFocusEvent *event)
9717
9718 This event handler can be reimplemented in a subclass to receive
9719 keyboard focus events (focus lost) for the widget. The event is
9720 passed in the \a event parameter.
9721
9722 A widget normally must setFocusPolicy() to something other than
9723 Qt::NoFocus to receive focus events. (Note that the
9724 application programmer can call setFocus() on any widget, even
9725 those that do not normally accept focus.)
9726
9727 The default implementation updates the widget (except for windows
9728 that do not specify a focusPolicy()).
9729
9730 \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
9731 keyReleaseEvent(), event(), QFocusEvent
9732*/
9733
9734void QWidget::focusOutEvent(QFocusEvent *)
9735{
9736 if (focusPolicy() != Qt::NoFocus || !isWindow())
9737 update();
9738
9739#if !defined(QT_PLATFORM_UIKIT)
9740 // FIXME: revisit autoSIP logic, QTBUG-42906
9741 if (qApp->autoSipEnabled() && testAttribute(Qt::WA_InputMethodEnabled))
9742 QGuiApplication::inputMethod()->hide();
9743#endif
9744}
9745
9746/*!
9747 \fn void QWidget::enterEvent(QEnterEvent *event)
9748
9749 This event handler can be reimplemented in a subclass to receive
9750 widget enter events which are passed in the \a event parameter.
9751
9752 An event is sent to the widget when the mouse cursor enters the
9753 widget.
9754
9755 \sa leaveEvent(), mouseMoveEvent(), event()
9756*/
9757
9758void QWidget::enterEvent(QEnterEvent *)
9759{
9760}
9761
9762/*!
9763 \fn void QWidget::leaveEvent(QEvent *event)
9764
9765 This event handler can be reimplemented in a subclass to receive
9766 widget leave events which are passed in the \a event parameter.
9767
9768 A leave event is sent to the widget when the mouse cursor leaves
9769 the widget.
9770
9771 \sa enterEvent(), mouseMoveEvent(), event()
9772*/
9773
9774void QWidget::leaveEvent(QEvent *)
9775{
9776}
9777
9778/*!
9779 \fn void QWidget::paintEvent(QPaintEvent *event)
9780
9781 This event handler can be reimplemented in a subclass to receive paint
9782 events passed in \a event.
9783
9784 A paint event is a request to repaint all or part of a widget. It can
9785 happen for one of the following reasons:
9786
9787 \list
9788 \li repaint() or update() was invoked,
9789 \li the widget was obscured and has now been uncovered, or
9790 \li many other reasons.
9791 \endlist
9792
9793 Many widgets can simply repaint their entire surface when asked to, but
9794 some slow widgets need to optimize by painting only the requested region:
9795 QPaintEvent::region(). This speed optimization does not change the result,
9796 as painting is clipped to that region during event processing. QListView
9797 and QTableView do this, for example.
9798
9799 Qt also tries to speed up painting by merging multiple paint events into
9800 one. When update() is called several times or the window system sends
9801 several paint events, Qt merges these events into one event with a larger
9802 region (see QRegion::united()). The repaint() function does not permit this
9803 optimization, so we suggest using update() whenever possible.
9804
9805 When the paint event occurs, the update region has normally been erased, so
9806 you are painting on the widget's background.
9807
9808 The background can be set using setBackgroundRole() and setPalette().
9809
9810 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
9811 is no need to write double-buffering code in paintEvent() to avoid flicker.
9812
9813 \note Generally, you should refrain from calling update() or repaint()
9814 \b{inside} a paintEvent(). For example, calling update() or repaint() on
9815 children inside a paintEvent() results in undefined behavior; the child may
9816 or may not get a paint event.
9817
9818 \warning If you are using a custom paint engine without Qt's backingstore,
9819 Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
9820 never be called; the backingstore will be used instead.
9821
9822 \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
9823 {Analog Clock}
9824*/
9825
9826void QWidget::paintEvent(QPaintEvent *)
9827{
9828}
9829
9830
9831/*!
9832 \fn void QWidget::moveEvent(QMoveEvent *event)
9833
9834 This event handler can be reimplemented in a subclass to receive
9835 widget move events which are passed in the \a event parameter.
9836 When the widget receives this event, it is already at the new
9837 position.
9838
9839 The old position is accessible through QMoveEvent::oldPos().
9840
9841 \sa resizeEvent(), event(), move(), QMoveEvent
9842*/
9843
9844void QWidget::moveEvent(QMoveEvent *)
9845{
9846}
9847
9848
9849/*!
9850 This event handler can be reimplemented in a subclass to receive
9851 widget resize events which are passed in the \a event parameter.
9852 When resizeEvent() is called, the widget already has its new
9853 geometry. The old size is accessible through
9854 QResizeEvent::oldSize().
9855
9856 The widget will be erased and receive a paint event immediately
9857 after processing the resize event. No drawing need be (or should
9858 be) done inside this handler.
9859
9860
9861 \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
9862 {Scribble Example}
9863*/
9864
9865void QWidget::resizeEvent(QResizeEvent * /* event */)
9866{
9867}
9868
9869#ifndef QT_NO_ACTION
9870/*!
9871 \fn void QWidget::actionEvent(QActionEvent *event)
9872
9873 This event handler is called with the given \a event whenever the
9874 widget's actions are changed.
9875
9876 \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
9877*/
9878void QWidget::actionEvent(QActionEvent *)
9879{
9880
9881}
9882#endif
9883
9884/*!
9885 This event handler is called with the given \a event when Qt receives a window
9886 close request for a top-level widget from the window system.
9887
9888 By default, the event is accepted and the widget is closed. You can reimplement
9889 this function to change the way the widget responds to window close requests.
9890 For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
9891 on all events.
9892
9893 Main window applications typically use reimplementations of this function to check
9894 whether the user's work has been saved and ask for permission before closing.
9895
9896 \sa event(), hide(), close(), QCloseEvent
9897*/
9898
9899void QWidget::closeEvent(QCloseEvent *event)
9900{
9901 event->accept();
9902}
9903
9904#ifndef QT_NO_CONTEXTMENU
9905/*!
9906 This event handler, for event \a event, can be reimplemented in a
9907 subclass to receive widget context menu events.
9908
9909 The handler is called when the widget's \l contextMenuPolicy is
9910 Qt::DefaultContextMenu.
9911
9912 The default implementation ignores the context event.
9913 See the \l QContextMenuEvent documentation for more details.
9914
9915 \sa event(), QContextMenuEvent, customContextMenuRequested()
9916*/
9917
9918void QWidget::contextMenuEvent(QContextMenuEvent *event)
9919{
9920 event->ignore();
9921}
9922#endif // QT_NO_CONTEXTMENU
9923
9924
9925/*!
9926 This event handler, for event \a event, can be reimplemented in a
9927 subclass to receive Input Method composition events. This handler
9928 is called when the state of the input method changes.
9929
9930 Note that when creating custom text editing widgets, the
9931 Qt::WA_InputMethodEnabled window attribute must be set explicitly
9932 (using the setAttribute() function) in order to receive input
9933 method events.
9934
9935 The default implementation calls event->ignore(), which rejects the
9936 Input Method event. See the \l QInputMethodEvent documentation for more
9937 details.
9938
9939 \sa event(), QInputMethodEvent
9940*/
9941void QWidget::inputMethodEvent(QInputMethodEvent *event)
9942{
9943 event->ignore();
9944}
9945
9946/*!
9947 This method is only relevant for input widgets. It is used by the
9948 input method to query a set of properties of the widget to be
9949 able to support complex input method operations as support for
9950 surrounding text and reconversions.
9951
9952 \a query specifies which property is queried.
9953
9954 \sa inputMethodEvent(), QInputMethodEvent, QInputMethodQueryEvent, inputMethodHints
9955*/
9956QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
9957{
9958 switch(query) {
9959 case Qt::ImCursorRectangle:
9960 return QRect(width()/2, 0, 1, height());
9961 case Qt::ImFont:
9962 return font();
9963 case Qt::ImAnchorPosition:
9964 // Fallback.
9965 return inputMethodQuery(Qt::ImCursorPosition);
9966 case Qt::ImHints:
9967 return (int)inputMethodHints();
9968 case Qt::ImInputItemClipRectangle:
9969 return d_func()->clipRect();
9970 default:
9971 return QVariant();
9972 }
9973}
9974
9975/*!
9976 \property QWidget::inputMethodHints
9977 \brief What input method specific hints the widget has.
9978
9979 This is only relevant for input widgets. It is used by
9980 the input method to retrieve hints as to how the input method
9981 should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
9982 is set, the input method may change its visual components to reflect
9983 that only numbers can be entered.
9984
9985 \warning Some widgets require certain flags to work as
9986 intended. To set a flag, do \c{w->setInputMethodHints(w->inputMethodHints()|f)}
9987 instead of \c{w->setInputMethodHints(f)}.
9988
9989 \note The flags are only hints, so the particular input method
9990 implementation is free to ignore them. If you want to be
9991 sure that a certain type of characters are entered,
9992 you should also set a QValidator on the widget.
9993
9994 The default value is Qt::ImhNone.
9995
9996 \since 4.6
9997
9998 \sa inputMethodQuery()
9999*/
10000Qt::InputMethodHints QWidget::inputMethodHints() const
10001{
10002#if QT_CONFIG(im)
10003 const QWidgetPrivate *priv = d_func();
10004 while (priv->inheritsInputMethodHints) {
10005 priv = priv->q_func()->parentWidget()->d_func();
10006 Q_ASSERT(priv);
10007 }
10008 return priv->imHints;
10009#else
10010 return Qt::ImhNone;
10011#endif
10012}
10013
10014void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
10015{
10016#ifndef QT_NO_IM
10017 Q_D(QWidget);
10018 if (d->imHints == hints)
10019 return;
10020 d->imHints = hints;
10021 if (this == QGuiApplication::focusObject())
10022 QGuiApplication::inputMethod()->update(Qt::ImHints);
10023#else
10024 Q_UNUSED(hints);
10025#endif //QT_NO_IM
10026}
10027
10028
10029#if QT_CONFIG(draganddrop)
10030
10031/*!
10032 \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
10033
10034 This event handler is called when a drag is in progress and the
10035 mouse enters this widget. The event is passed in the \a event parameter.
10036
10037 If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
10038 move events}.
10039
10040 See the \l{dnd.html}{Drag-and-drop documentation} for an
10041 overview of how to provide drag-and-drop in your application.
10042
10043 \sa QDrag, QDragEnterEvent
10044*/
10045void QWidget::dragEnterEvent(QDragEnterEvent *)
10046{
10047}
10048
10049/*!
10050 \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
10051
10052 This event handler is called if a drag is in progress, and when
10053 any of the following conditions occur: the cursor enters this widget,
10054 the cursor moves within this widget, or a modifier key is pressed on
10055 the keyboard while this widget has the focus. The event is passed
10056 in the \a event parameter.
10057
10058 See the \l{dnd.html}{Drag-and-drop documentation} for an
10059 overview of how to provide drag-and-drop in your application.
10060
10061 \sa QDrag, QDragMoveEvent
10062*/
10063void QWidget::dragMoveEvent(QDragMoveEvent *)
10064{
10065}
10066
10067/*!
10068 \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
10069
10070 This event handler is called when a drag is in progress and the
10071 mouse leaves this widget. The event is passed in the \a event
10072 parameter.
10073
10074 See the \l{dnd.html}{Drag-and-drop documentation} for an
10075 overview of how to provide drag-and-drop in your application.
10076
10077 \sa QDrag, QDragLeaveEvent
10078*/
10079void QWidget::dragLeaveEvent(QDragLeaveEvent *)
10080{
10081}
10082
10083/*!
10084 \fn void QWidget::dropEvent(QDropEvent *event)
10085
10086 This event handler is called when the drag is dropped on this
10087 widget. The event is passed in the \a event parameter.
10088
10089 See the \l{dnd.html}{Drag-and-drop documentation} for an
10090 overview of how to provide drag-and-drop in your application.
10091
10092 \sa QDrag, QDropEvent
10093*/
10094void QWidget::dropEvent(QDropEvent *)
10095{
10096}
10097
10098#endif // QT_CONFIG(draganddrop)
10099
10100/*!
10101 \fn void QWidget::showEvent(QShowEvent *event)
10102
10103 This event handler can be reimplemented in a subclass to receive
10104 widget show events which are passed in the \a event parameter.
10105
10106 Non-spontaneous show events are sent to widgets immediately
10107 before they are shown. The spontaneous show events of windows are
10108 delivered afterwards.
10109
10110 Note: A widget receives spontaneous show and hide events when its
10111 mapping status is changed by the window system, e.g. a spontaneous
10112 hide event when the user minimizes the window, and a spontaneous
10113 show event when the window is restored again. After receiving a
10114 spontaneous hide event, a widget is still considered visible in
10115 the sense of isVisible().
10116
10117 \sa visible, event(), QShowEvent
10118*/
10119void QWidget::showEvent(QShowEvent *)
10120{
10121}
10122
10123/*!
10124 \fn void QWidget::hideEvent(QHideEvent *event)
10125
10126 This event handler can be reimplemented in a subclass to receive
10127 widget hide events. The event is passed in the \a event parameter.
10128
10129 Hide events are sent to widgets immediately after they have been
10130 hidden.
10131
10132 Note: A widget receives spontaneous show and hide events when its
10133 mapping status is changed by the window system, e.g. a spontaneous
10134 hide event when the user minimizes the window, and a spontaneous
10135 show event when the window is restored again. After receiving a
10136 spontaneous hide event, a widget is still considered visible in
10137 the sense of isVisible().
10138
10139 \sa visible, event(), QHideEvent
10140*/
10141void QWidget::hideEvent(QHideEvent *)
10142{
10143}
10144
10145/*!
10146 This special event handler can be reimplemented in a subclass to
10147 receive native platform events identified by \a eventType
10148 which are passed in the \a message parameter.
10149
10150 In your reimplementation of this function, if you want to stop the
10151 event being handled by Qt, return true and set \a result. The \a result
10152 parameter has meaning only on Windows. If you return false, this native
10153 event is passed back to Qt, which translates the event into a Qt event
10154 and sends it to the widget.
10155
10156 \note Events are only delivered to this event handler if the widget
10157 has a native window handle.
10158
10159 \note This function superseedes the event filter functions
10160 x11Event(), winEvent() and macEvent() of Qt 4.
10161
10162 \sa QAbstractNativeEventFilter
10163
10164 \table
10165 \header \li Platform \li Event Type Identifier \li Message Type \li Result Type
10166 \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
10167 \row \li macOS \li "NSEvent" \li NSEvent * \li
10168 \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li
10169 \endtable
10170*/
10171
10172bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
10173{
10174 Q_UNUSED(eventType);
10175 Q_UNUSED(message);
10176 Q_UNUSED(result);
10177 return false;
10178}
10179
10180/*!
10181 Ensures that the widget and its children have been polished by
10182 QStyle (i.e., have a proper font and palette).
10183
10184 QWidget calls this function after it has been fully constructed
10185 but before it is shown the very first time. You can call this
10186 function if you want to ensure that the widget is polished before
10187 doing an operation, e.g., the correct font size might be needed in
10188 the widget's sizeHint() reimplementation. Note that this function
10189 \e is called from the default implementation of sizeHint().
10190
10191 Polishing is useful for final initialization that must happen after
10192 all constructors (from base classes as well as from subclasses)
10193 have been called.
10194
10195 If you need to change some settings when a widget is polished,
10196 reimplement event() and handle the QEvent::Polish event type.
10197
10198 \b{Note:} The function is declared const so that it can be called from
10199 other const functions (e.g., sizeHint()).
10200
10201 \sa event()
10202*/
10203void QWidget::ensurePolished() const
10204{
10205 Q_D(const QWidget);
10206
10207 const QMetaObject *m = metaObject();
10208 if (m == d->polished)
10209 return;
10210 d->polished = m;
10211
10212 QEvent e(QEvent::Polish);
10213 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &e);
10214
10215 // polish children after 'this'
10216 QList<QObject*> children = d->children;
10217 for (int i = 0; i < children.size(); ++i) {
10218 QObject *o = children.at(i);
10219 if (!o->isWidgetType())
10220 continue;
10221 if (QWidget *w = qobject_cast<QWidget *>(o))
10222 w->ensurePolished();
10223 }
10224
10225 if (d->parent && d->sendChildEvents) {
10226 QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
10227 QCoreApplication::sendEvent(d->parent, &e);
10228 }
10229}
10230
10231/*!
10232 Returns the mask currently set on a widget. If no mask is set the
10233 return value will be an empty region.
10234
10235 \sa setMask(), clearMask(), QRegion::isEmpty()
10236*/
10237QRegion QWidget::mask() const
10238{
10239 Q_D(const QWidget);
10240 return d->extra ? d->extra->mask : QRegion();
10241}
10242
10243/*!
10244 Returns the layout manager that is installed on this widget, or \nullptr
10245 if no layout manager is installed.
10246
10247 The layout manager sets the geometry of the widget's children
10248 that have been added to the layout.
10249
10250 \sa setLayout(), sizePolicy(), {Layout Management}
10251*/
10252QLayout *QWidget::layout() const
10253{
10254 return d_func()->layout;
10255}
10256
10257
10258/*!
10259 \fn void QWidget::setLayout(QLayout *layout)
10260
10261 Sets the layout manager for this widget to \a layout.
10262
10263 If there already is a layout manager installed on this widget,
10264 QWidget won't let you install another. You must first delete the
10265 existing layout manager (returned by layout()) before you can
10266 call setLayout() with the new layout.
10267
10268 If \a layout is the layout manager on a different widget, setLayout()
10269 will reparent the layout and make it the layout manager for this widget.
10270
10271 Example:
10272
10273 \snippet layouts/layouts.cpp 24
10274
10275 An alternative to calling this function is to pass this widget to
10276 the layout's constructor.
10277
10278 The QWidget will take ownership of \a layout.
10279
10280 \sa layout(), {Layout Management}
10281*/
10282
10283void QWidget::setLayout(QLayout *l)
10284{
10285 if (Q_UNLIKELY(!l)) {
10286 qWarning("QWidget::setLayout: Cannot set layout to 0");
10287 return;
10288 }
10289 if (layout()) {
10290 if (Q_UNLIKELY(layout() != l))
10291 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
10292 " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
10293 objectName().toLocal8Bit().data());
10294 return;
10295 }
10296
10297 QObject *oldParent = l->parent();
10298 if (oldParent && oldParent != this) {
10299 if (oldParent->isWidgetType()) {
10300 // Steal the layout off a widget parent. Takes effect when
10301 // morphing laid-out container widgets in Designer.
10302 QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
10303 oldParentWidget->takeLayout();
10304 } else {
10305 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
10306 l->objectName().toLocal8Bit().data(), metaObject()->className(),
10307 objectName().toLocal8Bit().data());
10308 return;
10309 }
10310 }
10311
10312 Q_D(QWidget);
10313 l->d_func()->topLevel = true;
10314 d->layout = l;
10315 if (oldParent != this) {
10316 l->setParent(this);
10317 l->d_func()->reparentChildWidgets(this);
10318 l->invalidate();
10319 }
10320
10321 if (isWindow() && d->maybeTopData())
10322 d->topData()->sizeAdjusted = false;
10323}
10324
10325/*!
10326 \fn QLayout *QWidget::takeLayout()
10327
10328 Remove the layout from the widget.
10329 \since 4.5
10330*/
10331
10332QLayout *QWidget::takeLayout()
10333{
10334 Q_D(QWidget);
10335 QLayout *l = layout();
10336 if (!l)
10337 return nullptr;
10338 d->layout = nullptr;
10339 l->setParent(nullptr);
10340 return l;
10341}
10342
10343/*!
10344 \property QWidget::sizePolicy
10345 \brief the default layout behavior of the widget
10346
10347 If there is a QLayout that manages this widget's children, the
10348 size policy specified by that layout is used. If there is no such
10349 QLayout, the result of this function is used.
10350
10351 The default policy is Preferred/Preferred, which means that the
10352 widget can be freely resized, but prefers to be the size
10353 sizeHint() returns. Button-like widgets set the size policy to
10354 specify that they may stretch horizontally, but are fixed
10355 vertically. The same applies to lineedit controls (such as
10356 QLineEdit, QSpinBox or an editable QComboBox) and other
10357 horizontally orientated widgets (such as QProgressBar).
10358 QToolButton's are normally square, so they allow growth in both
10359 directions. Widgets that support different directions (such as
10360 QSlider, QScrollBar or QHeader) specify stretching in the
10361 respective direction only. Widgets that can provide scroll bars
10362 (usually subclasses of QScrollArea) tend to specify that they can
10363 use additional space, and that they can make do with less than
10364 sizeHint().
10365
10366 \sa sizeHint(), QLayout, QSizePolicy, updateGeometry()
10367*/
10368QSizePolicy QWidget::sizePolicy() const
10369{
10370 Q_D(const QWidget);
10371 return d->size_policy;
10372}
10373
10374void QWidget::setSizePolicy(QSizePolicy policy)
10375{
10376 Q_D(QWidget);
10377 setAttribute(Qt::WA_WState_OwnSizePolicy);
10378 if (policy == d->size_policy)
10379 return;
10380
10381 if (d->size_policy.retainSizeWhenHidden() != policy.retainSizeWhenHidden())
10382 d->retainSizeWhenHiddenChanged = 1;
10383
10384 d->size_policy = policy;
10385
10386#if QT_CONFIG(graphicsview)
10387 if (const auto &extra = d->extra) {
10388 if (extra->proxyWidget)
10389 extra->proxyWidget->setSizePolicy(policy);
10390 }
10391#endif
10392
10393 updateGeometry();
10394 d->retainSizeWhenHiddenChanged = 0;
10395
10396 if (isWindow() && d->maybeTopData())
10397 d->topData()->sizeAdjusted = false;
10398}
10399
10400/*!
10401 \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
10402 \overload
10403
10404 Sets the size policy of the widget to \a horizontal and \a
10405 vertical, with standard stretch and no height-for-width.
10406
10407 \sa QSizePolicy::QSizePolicy()
10408*/
10409
10410/*!
10411 Returns the preferred height for this widget, given the width \a w.
10412
10413 If this widget has a layout, the default implementation returns
10414 the layout's preferred height. if there is no layout, the default
10415 implementation returns -1 indicating that the preferred height
10416 does not depend on the width.
10417*/
10418
10419int QWidget::heightForWidth(int w) const
10420{
10421 if (layout() && layout()->hasHeightForWidth())
10422 return layout()->totalHeightForWidth(w);
10423 return -1;
10424}
10425
10426
10427/*!
10428 \since 5.0
10429
10430 Returns \c true if the widget's preferred height depends on its width; otherwise returns \c false.
10431*/
10432bool QWidget::hasHeightForWidth() const
10433{
10434 Q_D(const QWidget);
10435 return d->layout ? d->layout->hasHeightForWidth() : d->size_policy.hasHeightForWidth();
10436}
10437
10438/*!
10439 \fn QWidget *QWidget::childAt(int x, int y) const
10440
10441 Returns the visible child widget at the position (\a{x}, \a{y})
10442 in the widget's coordinate system. If there is no visible child
10443 widget at the specified position, the function returns \nullptr.
10444*/
10445
10446/*!
10447 \overload
10448
10449 Returns the visible child widget at point \a p in the widget's own
10450 coordinate system.
10451*/
10452
10453QWidget *QWidget::childAt(const QPoint &p) const
10454{
10455 return d_func()->childAt_helper(QPointF(p), false);
10456}
10457
10458/*!
10459 \overload
10460 \since 6.8
10461
10462 Returns the visible child widget at point \a p in the widget's own
10463 coordinate system.
10464*/
10465
10466QWidget *QWidget::childAt(const QPointF &p) const
10467{
10468 return d_func()->childAt_helper(p, false);
10469}
10470
10471QWidget *QWidgetPrivate::childAt_helper(const QPointF &p, bool ignoreChildrenInDestructor) const
10472{
10473 if (children.isEmpty())
10474 return nullptr;
10475
10476 if (!pointInsideRectAndMask(p))
10477 return nullptr;
10478 return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
10479}
10480
10481QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPointF &p, bool ignoreChildrenInDestructor) const
10482{
10483 for (int i = children.size() - 1; i >= 0; --i) {
10484 QWidget *child = qobject_cast<QWidget *>(children.at(i));
10485 if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents)
10486 || (ignoreChildrenInDestructor && child->data->in_destructor)) {
10487 continue;
10488 }
10489
10490 // Map the point 'p' from parent coordinates to child coordinates.
10491 QPointF childPoint = p;
10492 childPoint -= child->data->crect.topLeft();
10493
10494 // Check if the point hits the child.
10495 if (!child->d_func()->pointInsideRectAndMask(childPoint))
10496 continue;
10497
10498 // Do the same for the child's descendants.
10499 if (QWidget *w = child->d_func()->childAtRecursiveHelper(childPoint, ignoreChildrenInDestructor))
10500 return w;
10501
10502 // We have found our target; namely the child at position 'p'.
10503 return child;
10504 }
10505 return nullptr;
10506}
10507
10508void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
10509{
10510 Q_Q(QWidget);
10511 if (widgetItem)
10512 widgetItem->invalidateSizeCache();
10513 QWidget *parent;
10514 if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
10515 const int isHidden = q->isHidden() && !size_policy.retainSizeWhenHidden() && !retainSizeWhenHiddenChanged;
10516
10517 if (!q->isWindow() && !isHidden && (parent = q->parentWidget())) {
10518 if (parent->d_func()->layout)
10519 parent->d_func()->layout->invalidate();
10520 else if (parent->isVisible())
10521 QCoreApplication::postEvent(parent, new QEvent(QEvent::LayoutRequest));
10522 }
10523 }
10524}
10525
10526/*!
10527 Notifies the layout system that this widget has changed and may
10528 need to change geometry.
10529
10530 Call this function if the sizeHint() or sizePolicy() have changed.
10531
10532 For explicitly hidden widgets, updateGeometry() is a no-op. The
10533 layout system will be notified as soon as the widget is shown.
10534*/
10535
10536void QWidget::updateGeometry()
10537{
10538 Q_D(QWidget);
10539 d->updateGeometry_helper(false);
10540}
10541
10542/*! \property QWidget::windowFlags
10543
10544 Window flags are a combination of a type (e.g. Qt::Dialog) and
10545 zero or more hints to the window system (e.g.
10546 Qt::FramelessWindowHint).
10547
10548 If the widget had type Qt::Widget or Qt::SubWindow and becomes a
10549 window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
10550 0) on the desktop. If the widget is a window and becomes a
10551 Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
10552 relative to its parent widget.
10553
10554 \note This function calls setParent() when changing the flags for
10555 a window, causing the widget to be hidden. You must call show() to make
10556 the widget visible again..
10557
10558 \sa windowType(), setWindowFlag(), {Window Flags Example}
10559*/
10560void QWidget::setWindowFlags(Qt::WindowFlags flags)
10561{
10562 Q_D(QWidget);
10563 d->setWindowFlags(flags);
10564}
10565
10566/*!
10567 \since 5.9
10568
10569 Sets the window flag \a flag on this widget if \a on is true;
10570 otherwise clears the flag.
10571
10572 \note This function calls setParent() when changing the flags for
10573 a window, causing the widget to be hidden. You must call show() to make
10574 the widget visible again.
10575
10576 \sa setWindowFlags(), windowFlags(), windowType()
10577*/
10578void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
10579{
10580 Q_D(QWidget);
10581 if (on)
10582 d->setWindowFlags(data->window_flags | flag);
10583 else
10584 d->setWindowFlags(data->window_flags & ~flag);
10585}
10586
10587/*! \internal
10588
10589 Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
10590*/
10591void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
10592{
10593 Q_Q(QWidget);
10594#if QT_DEPRECATED_SINCE(6, 11)
10595 QT_IGNORE_DEPRECATIONS(
10596 if ((flags & Qt::WindowType_Mask) == Qt::WindowType::Desktop) {
10597 qWarning() << "Qt::WindowType::Desktop has been deprecated in Qt 6. Ignoring.";
10598 flags.setFlag(Qt::WindowType::Desktop, false);
10599 }
10600 )
10601#endif
10602
10603 if (q->data->window_flags == flags)
10604 return;
10605
10606 if ((q->data->window_flags | flags) & Qt::Window) {
10607 // the old type was a window and/or the new type is a window
10608 QPoint oldPos = q->pos();
10609 bool visible = q->isVisible();
10610 const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
10611 q->setParent(q->parentWidget(), flags);
10612
10613 // if both types are windows or neither of them are, we restore
10614 // the old position
10615 if (!windowFlagChanged && (visible || q->testAttribute(Qt::WA_Moved)))
10616 q->move(oldPos);
10617 // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
10618 adjustQuitOnCloseAttribute();
10619 } else {
10620 q->data->window_flags = flags;
10621 }
10622}
10623
10624/*!
10625 Sets the window flags for the widget to \a flags,
10626 \e without telling the window system.
10627
10628 \warning Do not call this function unless you really know what
10629 you're doing.
10630
10631 \sa setWindowFlags()
10632*/
10633void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
10634{
10635 data->window_flags = flags;
10636}
10637
10638/*!
10639 \fn Qt::WindowType QWidget::windowType() const
10640
10641 Returns the window type of this widget. This is identical to
10642 windowFlags() & Qt::WindowType_Mask.
10643
10644 \sa windowFlags
10645*/
10646
10647/*!
10648 Sets the parent of the widget to \a parent, and resets the window
10649 flags. The widget is moved to position (0, 0) in its new parent.
10650
10651 If the new parent widget is in a different window, the
10652 reparented widget and its children are appended to the end of the
10653 \l{setFocusPolicy()}{tab chain} of the new parent
10654 widget, in the same internal order as before. If one of the moved
10655 widgets had keyboard focus, setParent() calls clearFocus() for that
10656 widget.
10657
10658 If the new parent widget is in the same window as the
10659 old parent, setting the parent doesn't change the tab order or
10660 keyboard focus.
10661
10662 If the "new" parent widget is the old parent widget, this function
10663 does nothing.
10664
10665 \note The widget becomes invisible as part of changing its parent,
10666 even if it was previously visible. You must call show() to make the
10667 widget visible again.
10668
10669 \warning It is very unlikely that you will ever need this
10670 function. If you have a widget that changes its content
10671 dynamically, it is far easier to use \l QStackedWidget.
10672
10673 \sa setWindowFlags()
10674*/
10675void QWidget::setParent(QWidget *parent)
10676{
10677 if (parent == parentWidget())
10678 return;
10679 setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask);
10680}
10681
10682void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType)
10683{
10684 QWidgetPrivate *d = QWidgetPrivate::get(widget);
10685 if (d->renderToTexture) {
10686 QEvent e(eventType);
10687 QCoreApplication::sendEvent(widget, &e);
10688 }
10689
10690 for (int i = 0; i < d->children.size(); ++i) {
10691 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
10692 if (w && !w->isWindow())
10693 qSendWindowChangeToTextureChildrenRecursively(w, eventType);
10694 }
10695
10696 // Notify QWidgetWindow after we've notified all child QWidgets
10697 if (auto *window = d->windowHandle(QWidgetPrivate::WindowHandleMode::Direct)) {
10698 QEvent e(eventType);
10699 QCoreApplication::sendEvent(window, &e);
10700 }
10701}
10702
10703/*!
10704 \overload
10705
10706 This function also takes widget flags, \a f as an argument.
10707*/
10708
10709void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
10710{
10711 Q_D(QWidget);
10712 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
10713#ifdef QT_DEBUG
10714 const auto checkForParentChildLoops = qScopeGuard([&](){
10715 int depth = 0;
10716 auto p = parentWidget();
10717 while (p) {
10718 if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
10719 qWarning("QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
10720 "this is undefined behavior",
10721 this, metaObject()->className(), qPrintable(objectName()));
10722 }
10723 p = p->parentWidget();
10724 }
10725 });
10726#endif
10727
10728 const bool resized = testAttribute(Qt::WA_Resized);
10729 const bool wasCreated = testAttribute(Qt::WA_WState_Created);
10730 QWidget *oldtlw = window();
10731 Q_ASSERT(oldtlw);
10732 QWidget *oldParentWithWindow = d->closestParentWidgetWithWindowHandle();
10733
10734 if (f & Qt::Window) // Frame geometry likely changes, refresh.
10735 d->data.fstrut_dirty = true;
10736
10737 bool newParent = (parent != parentWidget());
10738
10739 if (newParent && parent) {
10740 if (testAttribute(Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
10741 parent->d_func()->enforceNativeChildren();
10742 else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(Qt::WA_PaintOnScreen))
10743 setAttribute(Qt::WA_NativeWindow);
10744 }
10745
10746 if (wasCreated) {
10747 if (!testAttribute(Qt::WA_WState_Hidden)) {
10748 // Hiding the widget will set WA_WState_Hidden as well, which would
10749 // normally require the widget to be explicitly shown again to become
10750 // visible, even as a child widget. But we refine this value later in
10751 // setParent_sys(), applying WA_WState_Hidden based on whether the
10752 // widget is a top level or not.
10753 hide();
10754
10755 // We reset WA_WState_ExplicitShowHide here, likely as a remnant of
10756 // when we only had QWidget::setVisible(), which is treated as an
10757 // explicit show/hide. Nowadays we have QWidgetPrivate::setVisible(),
10758 // that allows us to hide a widget without affecting ExplicitShowHide.
10759 // Though it can be argued that ExplicitShowHide should reflect the
10760 // last update of the widget's state, so if we hide the widget as a
10761 // side effect of changing parent, perhaps we _should_ reset it?
10762 setAttribute(Qt::WA_WState_ExplicitShowHide, false);
10763 }
10764 if (newParent) {
10765 QEvent e(QEvent::ParentAboutToChange);
10766 QCoreApplication::sendEvent(this, &e);
10767 }
10768 }
10769
10770 // texture-based widgets need a pre-notification when their associated top-level window changes
10771 // This is not under the wasCreated/newParent conditions above in order to also play nice with QDockWidget.
10772 const bool oldWidgetUsesRhiFlush = oldParentWithWindow ? oldParentWithWindow->d_func()->usesRhiFlush
10773 : oldtlw->d_func()->usesRhiFlush;
10774 if (oldWidgetUsesRhiFlush && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw)))
10775 qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowAboutToChangeInternal);
10776
10777 // If we get parented into another window, children will be folded
10778 // into the new parent's focus chain, so clear focus now.
10779 if (newParent && isAncestorOf(focusWidget()) && !(f & Qt::Window))
10780 focusWidget()->clearFocus();
10781
10782 d->setParent_sys(parent, f);
10783
10784 if (d->textureChildSeen && parent) {
10785 // set the textureChildSeen flag up the whole parent chain
10786 QWidgetPrivate::get(parent)->setTextureChildSeen();
10787 }
10788
10789 if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
10790 if (newParent)
10791 oldPaintManager->removeDirtyWidget(this);
10792 // Move the widget and all its static children from
10793 // the old backing store to the new one.
10794 oldPaintManager->moveStaticWidgets(this);
10795 }
10796
10797 d->reparentFocusWidgets(oldtlw);
10798 setAttribute(Qt::WA_Resized, resized);
10799
10800 const bool useStyleSheetPropagationInWidgetStyles =
10801 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
10802
10803 if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(Qt::WA_StyleSheet)
10804 && (!parent || !parent->testAttribute(Qt::WA_StyleSheet))) {
10805 // if the parent has a font set or inherited, then propagate the mask to the new child
10806 if (parent) {
10807 const auto pd = parent->d_func();
10808 d->inheritedFontResolveMask = pd->directFontResolveMask | pd->inheritedFontResolveMask;
10809 d->inheritedPaletteResolveMask = pd->directPaletteResolveMask | pd->inheritedPaletteResolveMask;
10810 }
10811 d->resolveFont();
10812 d->resolvePalette();
10813 }
10814 d->resolveLayoutDirection();
10815 d->resolveLocale();
10816
10817 // Note: GL widgets under WGL or EGL will always need a ParentChange
10818 // event to handle recreation/rebinding of the GL context, hence the
10819 // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
10820 // platforms).
10821 if (newParent || !wasCreated
10822#if QT_CONFIG(opengles2)
10823 || (f & Qt::MSWindowsOwnDC)
10824#endif
10825 ) {
10826 // propagate enabled updates enabled state to non-windows
10827 if (!isWindow()) {
10828 if (!testAttribute(Qt::WA_ForceDisabled))
10829 d->setEnabled_helper(parent ? parent->isEnabled() : true);
10830 if (!testAttribute(Qt::WA_ForceUpdatesDisabled))
10831 d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
10832 }
10833 d->inheritStyle();
10834
10835 // send and post remaining QObject events
10836 if (parent && d->sendChildEvents) {
10837 QChildEvent e(QEvent::ChildAdded, this);
10838 QCoreApplication::sendEvent(parent, &e);
10839 }
10840
10841 if (parent && d->sendChildEvents && d->polished) {
10842 QChildEvent e(QEvent::ChildPolished, this);
10843 QCoreApplication::sendEvent(parent, &e);
10844 }
10845
10846 QEvent e(QEvent::ParentChange);
10847 QCoreApplication::sendEvent(this, &e);
10848 }
10849
10850 // texture-based widgets need another event when their top-level window
10851 // changes (more precisely, has already changed at this point)
10852 if (oldWidgetUsesRhiFlush && oldtlw != window())
10853 qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowChangeInternal);
10854
10855 if (!wasCreated) {
10856 if (isWindow() || parentWidget()->isVisible())
10857 setAttribute(Qt::WA_WState_Hidden, true);
10858 else if (!testAttribute(Qt::WA_WState_ExplicitShowHide))
10859 setAttribute(Qt::WA_WState_Hidden, false);
10860 }
10861
10862 d->updateIsOpaque();
10863
10864#if QT_CONFIG(graphicsview)
10865 // Embed the widget into a proxy if the parent is embedded.
10866 // ### Doesn't handle reparenting out of an embedded widget.
10867 if (oldtlw->graphicsProxyWidget()) {
10868 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(oldtlw))
10869 ancestorProxy->d_func()->unembedSubWindow(this);
10870 }
10871 if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(this)) {
10872 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(parent))
10873 ancestorProxy->d_func()->embedSubWindow(this);
10874 }
10875#endif
10876
10877 if (d->extra && d->extra->hasWindowContainer)
10878 QWindowContainer::parentWasChanged(this);
10879
10880 QWidget *newParentWithWindow = d->closestParentWidgetWithWindowHandle();
10881 if (newParentWithWindow && newParentWithWindow != oldParentWithWindow) {
10882 // Check if the native parent now needs to switch to RHI
10883 qCDebug(lcWidgetPainting) << "Evaluating whether reparenting of" << this
10884 << "into" << parent << "requires RHI enablement for" << newParentWithWindow;
10885
10886 QPlatformBackingStoreRhiConfig rhiConfig;
10887 QSurface::SurfaceType surfaceType = QSurface::RasterSurface;
10888
10889 // First evaluate whether the reparented widget uses RHI.
10890 // We do this as a separate step because the performance
10891 // implications of always checking the native parent are
10892 // problematic when it comes to large widget trees.
10893 if (q_evaluateRhiConfig(this, &rhiConfig, &surfaceType)) {
10894 // Then check whether the native parent requires RHI
10895 // as a result. It may not, if this widget is a native
10896 // window, and can handle its own RHI flushing.
10897 if (q_evaluateRhiConfig(newParentWithWindow, nullptr, nullptr)) {
10898 // Finally, check whether we need to recreate the
10899 // native parent to enable RHI flushing.
10900 auto *existingWindow = newParentWithWindow->windowHandle();
10901 auto existingSurfaceType = existingWindow->surfaceType();
10902 if (existingSurfaceType != surfaceType) {
10903 qCDebug(lcWidgetPainting)
10904 << "Recreating" << existingWindow
10905 << "with current type" << existingSurfaceType
10906 << "to support" << surfaceType;
10907 const auto windowStateBeforeDestroy = newParentWithWindow->windowState();
10908 const auto visibilityBeforeDestroy = newParentWithWindow->isVisible();
10909 const auto positionBeforeDestroy = newParentWithWindow->pos();
10910 newParentWithWindow->d_func()->recreate();
10911 Q_ASSERT(newParentWithWindow->windowHandle());
10912 newParentWithWindow->windowHandle()->setWindowStates(windowStateBeforeDestroy);
10913 newParentWithWindow->move(positionBeforeDestroy);
10914 QWidgetPrivate::get(newParentWithWindow)->setVisible(visibilityBeforeDestroy);
10915 } else if (auto *backingStore = newParentWithWindow->backingStore()) {
10916 // If we don't recreate we still need to make sure the native parent
10917 // widget has a RHI config that the reparented widget can use.
10918 backingStore->handle()->createRhi(existingWindow, rhiConfig);
10919 // And that it knows it's now flushing with RHI
10920 QWidgetPrivate::get(newParentWithWindow)->usesRhiFlush = true;
10921 }
10922 }
10923 }
10924 }
10925
10926#if QT_CONFIG(accessibility)
10927 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing) {
10928 QAccessibleEvent qaEvent(this, QAccessible::ParentChanged);
10929 QAccessible::updateAccessibility(&qaEvent);
10930 }
10931#endif
10932
10933}
10934
10935void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
10936{
10937 Q_Q(QWidget);
10938
10939 Qt::WindowFlags oldFlags = data.window_flags;
10940 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
10941
10942 QScreen *targetScreen = nullptr;
10943 setWinId(0);
10944
10945 if (!newparent) {
10946 f |= Qt::Window;
10947 if (parent)
10948 targetScreen = q->parentWidget()->window()->screen();
10949 }
10950
10951 const bool destroyWindow = (
10952 // Reparenting top level to child
10953 (oldFlags & Qt::Window) && !(f & Qt::Window)
10954 // And we can dispose of the window
10955 && wasCreated && !q->testAttribute(Qt::WA_NativeWindow)
10956 );
10957
10958 if (parent != newparent) {
10959 // Update object parent now, so we can resolve new parent window below
10960 QObjectPrivate::setParent_helper(newparent);
10961
10962 if (q->windowHandle())
10963 q->windowHandle()->setFlags(f);
10964
10965 // If the widget itself or any of its children have been created,
10966 // we need to reparent their QWindows as well.
10967 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
10968 // But if the widget is about to be destroyed we must skip the
10969 // widget itself, and only reparent children.
10970 if (destroyWindow) {
10971 reparentWidgetWindowChildren(parentWithWindow);
10972 } else {
10973 // During reparentWidgetWindows() we need to know whether the reparented
10974 // QWindow should be a top level (with a transient parent) or not. This
10975 // widget has not updated its window flags yet, so we can't ask the widget
10976 // directly at that point. Nor can we use the QWindow flags, as unlike QWidgets
10977 // the QWindow flags always reflect Qt::Window, even for child windows. And
10978 // we can't use QWindow::isTopLevel() either, as that depends on the parent,
10979 // which we are in the process of updating. So we propagate the
10980 // new flags of the reparented window here.
10981 reparentWidgetWindows(parentWithWindow, f);
10982 }
10983 }
10984
10985 bool explicitlyHidden = isExplicitlyHidden();
10986
10987 if (destroyWindow) {
10988 if (extra && extra->hasWindowContainer)
10989 QWindowContainer::toplevelAboutToBeDestroyed(q);
10990
10991 // There shouldn't be any QWindow children left, but if there
10992 // are, re-parent them now, before we destroy.
10993 if (!q->windowHandle()->children().isEmpty()) {
10994 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
10995 QWindow *newParentWindow = parentWithWindow ? parentWithWindow->windowHandle() : nullptr;
10996 for (QObject *child : q->windowHandle()->children()) {
10997 if (QWindow *childWindow = qobject_cast<QWindow *>(child)) {
10998 qCWarning(lcWidgetWindow) << "Reparenting" << childWindow
10999 << "before destroying" << this;
11000 childWindow->setParent(newParentWindow);
11001 }
11002 }
11003 }
11004
11005 // We have reparented any child windows of the widget we are
11006 // about to destroy to the new parent window handle, so we can
11007 // safely destroy this widget without destroying sub windows.
11008 q->destroy(true, false);
11009 }
11010
11011 adjustFlags(f, q);
11012 data.window_flags = f;
11013 q->setAttribute(Qt::WA_WState_Created, false);
11014 q->setAttribute(Qt::WA_WState_Visible, false);
11015 q->setAttribute(Qt::WA_WState_Hidden, false);
11016
11017 if (newparent && wasCreated && (q->testAttribute(Qt::WA_NativeWindow) || (f & Qt::Window)))
11018 q->createWinId();
11019
11020 if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
11021 q->setAttribute(Qt::WA_WState_Hidden);
11022 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
11023
11024 // move the window to the selected screen
11025 if (!newparent && targetScreen) {
11026 // only if it is already created
11027 if (q->testAttribute(Qt::WA_WState_Created))
11028 q->windowHandle()->setScreen(targetScreen);
11029 else
11030 topData()->initialScreen = targetScreen;
11031 }
11032}
11033
11034void QWidgetPrivate::reparentWidgetWindows(QWidget *parentWithWindow, Qt::WindowFlags windowFlags)
11035{
11036 if (QWindow *window = windowHandle()) {
11037 // Reparent this QWindow, and all QWindow children will follow
11038 if (parentWithWindow) {
11039 if (windowFlags & Qt::Window) {
11040 // Top level windows can only have transient parents,
11041 // and the transient parent must be another top level.
11042 QWidget *topLevel = parentWithWindow->window();
11043 auto *transientParent = topLevel->windowHandle();
11044 Q_ASSERT(transientParent);
11045 qCDebug(lcWidgetWindow) << "Setting" << window << "transient parent to" << transientParent;
11046 window->setTransientParent(transientParent);
11047 window->setParent(nullptr);
11048 } else {
11049 auto *parentWindow = parentWithWindow->windowHandle();
11050 qCDebug(lcWidgetWindow) << "Reparenting" << window << "into" << parentWindow;
11051 window->setTransientParent(nullptr);
11052 window->setParent(parentWindow);
11053 }
11054 } else {
11055 qCDebug(lcWidgetWindow) << "Making" << window << "top level window";
11056 window->setTransientParent(nullptr);
11057 window->setParent(nullptr);
11058 }
11059 } else {
11060 reparentWidgetWindowChildren(parentWithWindow);
11061 }
11062}
11063
11064void QWidgetPrivate::reparentWidgetWindowChildren(QWidget *parentWithWindow)
11065{
11066 for (auto *child : std::as_const(children)) {
11067 if (auto *childWidget = qobject_cast<QWidget*>(child)) {
11068 auto *childPrivate = QWidgetPrivate::get(childWidget);
11069 // Child widgets with QWindows should always continue to be child
11070 // windows, so we pass on the child's current window flags here.
11071 childPrivate->reparentWidgetWindows(parentWithWindow, childWidget->windowFlags());
11072 }
11073 }
11074}
11075
11076/*!
11077 Scrolls the widget including its children \a dx pixels to the
11078 right and \a dy downward. Both \a dx and \a dy may be negative.
11079
11080 After scrolling, the widgets will receive paint events for
11081 the areas that need to be repainted. For widgets that Qt knows to
11082 be opaque, this is only the newly exposed parts.
11083 For example, if an opaque widget is scrolled 8 pixels to the left,
11084 only an 8-pixel wide stripe at the right edge needs updating.
11085
11086 Since widgets propagate the contents of their parents by default,
11087 you need to set the \l autoFillBackground property, or use
11088 setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
11089 a widget opaque.
11090
11091 For widgets that use contents propagation, a scroll will cause an
11092 update of the entire scroll area.
11093
11094 \sa {Transparency and Double Buffering}
11095*/
11096
11097void QWidget::scroll(int dx, int dy)
11098{
11099 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11100 return;
11101 if (dx == 0 && dy == 0)
11102 return;
11103 Q_D(QWidget);
11104#if QT_CONFIG(graphicsview)
11105 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
11106 // Graphics View maintains its own dirty region as a list of rects;
11107 // until we can connect item updates directly to the view, we must
11108 // separately add a translated dirty region.
11109 for (const QRect &rect : d->dirty)
11110 proxy->update(rect.translated(dx, dy));
11111 proxy->scroll(dx, dy, proxy->subWidgetRect(this));
11112 d->scrollChildren(dx, dy); // QTBUG-138381: scroll item view cell widgets
11113 return;
11114 }
11115#endif
11116 d->setDirtyOpaqueRegion();
11117 d->scroll_sys(dx, dy);
11118}
11119
11120void QWidgetPrivate::scroll_sys(int dx, int dy)
11121{
11122 Q_Q(QWidget);
11123 scrollChildren(dx, dy);
11124 scrollRect(q->rect(), dx, dy);
11125}
11126
11127/*!
11128 \overload
11129
11130 This version only scrolls \a r and does not move the children of
11131 the widget.
11132
11133 If \a r is empty or invalid, the result is undefined.
11134
11135 \sa QScrollArea
11136*/
11137void QWidget::scroll(int dx, int dy, const QRect &r)
11138{
11139
11140 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11141 return;
11142 if (dx == 0 && dy == 0)
11143 return;
11144 Q_D(QWidget);
11145#if QT_CONFIG(graphicsview)
11146 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
11147 // Graphics View maintains its own dirty region as a list of rects;
11148 // until we can connect item updates directly to the view, we must
11149 // separately add a translated dirty region.
11150 if (!d->dirty.isEmpty()) {
11151 for (const QRect &rect : d->dirty.translated(dx, dy) & r)
11152 proxy->update(rect);
11153 }
11154 proxy->scroll(dx, dy, r.translated(proxy->subWidgetRect(this).topLeft().toPoint()));
11155 return;
11156 }
11157#endif
11158 d->scroll_sys(dx, dy, r);
11159}
11160
11161void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
11162{
11163 scrollRect(r, dx, dy);
11164}
11165
11166/*!
11167 Repaints the widget directly by calling paintEvent() immediately,
11168 unless updates are disabled or the widget is hidden.
11169
11170 We suggest only using repaint() if you need an immediate repaint,
11171 for example during animation. In most circumstances update()
11172 is better, as it permits Qt to optimize for speed and minimize
11173 flicker.
11174
11175 \warning If you call repaint() in a function which may itself be
11176 called from paintEvent(), you may get infinite recursion. The
11177 update() function never causes recursion.
11178
11179 \sa update(), paintEvent(), setUpdatesEnabled()
11180*/
11181
11182void QWidget::repaint()
11183{
11184 repaint(rect());
11185}
11186
11187/*! \overload
11188
11189 This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
11190 the widget.
11191
11192 If \a w is negative, it is replaced with \c{width() - x}, and if
11193 \a h is negative, it is replaced width \c{height() - y}.
11194*/
11195void QWidget::repaint(int x, int y, int w, int h)
11196{
11197 if (x > data->crect.width() || y > data->crect.height())
11198 return;
11199
11200 if (w < 0)
11201 w = data->crect.width() - x;
11202 if (h < 0)
11203 h = data->crect.height() - y;
11204
11205 repaint(QRect(x, y, w, h));
11206}
11207
11208/*! \overload
11209
11210 This version repaints a rectangle \a rect inside the widget.
11211*/
11212void QWidget::repaint(const QRect &rect)
11213{
11214 Q_D(QWidget);
11215 d->repaint(rect);
11216}
11217
11218/*!
11219 \overload
11220
11221 This version repaints a region \a rgn inside the widget.
11222*/
11223void QWidget::repaint(const QRegion &rgn)
11224{
11225 Q_D(QWidget);
11226 d->repaint(rgn);
11227}
11228
11229template <typename T>
11230void QWidgetPrivate::repaint(T r)
11231{
11232 Q_Q(QWidget);
11233
11234 if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
11235 return;
11236
11237 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11238 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11239 tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
11240}
11241
11242/*!
11243 Updates the widget unless updates are disabled or the widget is
11244 hidden.
11245
11246 This function does not cause an immediate repaint; instead it
11247 schedules a paint event for processing when Qt returns to the main
11248 event loop. This permits Qt to optimize for more speed and less
11249 flicker than a call to repaint() does.
11250
11251 Calling update() several times normally results in just one
11252 paintEvent() call.
11253
11254 Qt normally erases the widget's area before the paintEvent() call.
11255 If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
11256 responsible for painting all its pixels with an opaque color.
11257
11258 \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock}
11259*/
11260void QWidget::update()
11261{
11262 update(rect());
11263}
11264
11265/*! \fn void QWidget::update(int x, int y, int w, int h)
11266 \overload
11267
11268 This version updates a rectangle (\a x, \a y, \a w, \a h) inside
11269 the widget.
11270*/
11271
11272/*!
11273 \overload
11274
11275 This version updates a rectangle \a rect inside the widget.
11276*/
11277void QWidget::update(const QRect &rect)
11278{
11279 Q_D(QWidget);
11280 d->update(rect);
11281}
11282
11283/*!
11284 \overload
11285
11286 This version repaints a region \a rgn inside the widget.
11287*/
11288void QWidget::update(const QRegion &rgn)
11289{
11290 Q_D(QWidget);
11291 d->update(rgn);
11292}
11293
11294template <typename T>
11295void QWidgetPrivate::update(T r)
11296{
11297 Q_Q(QWidget);
11298
11299 if (renderToTexture && !q->isVisible()) {
11300 renderToTextureReallyDirty = 1;
11301 return;
11302 }
11303
11304 if (!q->isVisible() || !q->updatesEnabled())
11305 return;
11306
11307 T clipped = r & q->rect();
11308
11309 if (clipped.isEmpty())
11310 return;
11311
11312 if (q->testAttribute(Qt::WA_WState_InPaintEvent)) {
11313 QCoreApplication::postEvent(q, new QUpdateLaterEvent(clipped));
11314 return;
11315 }
11316
11317 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11318 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11319 tlwExtra->repaintManager->markDirty(clipped, q);
11320}
11321
11322 /*!
11323 \internal
11324
11325 This just sets the corresponding attribute bit to 1 or 0
11326 */
11327static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
11328 QWidgetPrivate *d)
11329{
11330 if (attribute < int(8*sizeof(uint))) {
11331 if (on)
11332 data->widget_attributes |= (1<<attribute);
11333 else
11334 data->widget_attributes &= ~(1<<attribute);
11335 } else {
11336 const int x = attribute - 8*sizeof(uint);
11337 const int int_off = x / (8*sizeof(uint));
11338 if (on)
11339 d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
11340 else
11341 d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
11342 }
11343}
11344
11345#ifdef Q_OS_MACOS
11346void QWidgetPrivate::macUpdateSizeAttribute()
11347{
11348 Q_Q(QWidget);
11349 QEvent event(QEvent::MacSizeChange);
11350 QCoreApplication::sendEvent(q, &event);
11351 for (int i = 0; i < children.size(); ++i) {
11352 QWidget *w = qobject_cast<QWidget *>(children.at(i));
11353 if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
11354 && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
11355 && !w->testAttribute(Qt::WA_MacSmallSize)
11356 && !w->testAttribute(Qt::WA_MacNormalSize))
11357 w->d_func()->macUpdateSizeAttribute();
11358 }
11359 resolveFont();
11360}
11361#endif
11362
11363/*!
11364 Sets the attribute \a attribute on this widget if \a on is true;
11365 otherwise clears the attribute.
11366
11367 \sa testAttribute()
11368*/
11369void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
11370{
11371 Q_D(QWidget);
11372
11373 if (attribute == Qt::WA_ContentsMarginsRespectsSafeArea) {
11374 if (isWindow()) {
11375 auto *topExtra = d->topData();
11376 topExtra->explicitContentsMarginsRespectsSafeArea = true;
11377 }
11378 }
11379
11380 if (testAttribute(attribute) == on)
11381 return;
11382
11383 static_assert(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
11384 "QWidget::setAttribute(WidgetAttribute, bool): "
11385 "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
11386#ifdef Q_OS_WIN
11387 // ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
11388 if (attribute == Qt::WA_PaintOnScreen && on && !inherits("QGLWidget")) {
11389 // see ::paintEngine for details
11390 paintEngine();
11391 if (d->noPaintOnScreen)
11392 return;
11393 }
11394#endif
11395
11396 // Don't set WA_NativeWindow on platforms that don't support it -- except for QGLWidget, which depends on it
11397 if (attribute == Qt::WA_NativeWindow && !d->mustHaveWindowHandle) {
11398 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
11399 if (!platformIntegration->hasCapability(QPlatformIntegration::NativeWidgets))
11400 return;
11401 }
11402
11403 setAttribute_internal(attribute, on, data, d);
11404
11405 switch (attribute) {
11406
11407#if QT_CONFIG(draganddrop)
11408 case Qt::WA_AcceptDrops: {
11409 if (on && !testAttribute(Qt::WA_DropSiteRegistered))
11410 setAttribute(Qt::WA_DropSiteRegistered, true);
11411 else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
11412 setAttribute(Qt::WA_DropSiteRegistered, false);
11413 QEvent e(QEvent::AcceptDropsChange);
11414 QCoreApplication::sendEvent(this, &e);
11415 break;
11416 }
11417 case Qt::WA_DropSiteRegistered: {
11418 for (int i = 0; i < d->children.size(); ++i) {
11419 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
11420 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_AcceptDrops) && w->testAttribute(Qt::WA_DropSiteRegistered) != on)
11421 w->setAttribute(Qt::WA_DropSiteRegistered, on);
11422 }
11423 break;
11424 }
11425#endif
11426
11427 case Qt::WA_NoChildEventsForParent:
11428 d->sendChildEvents = !on;
11429 break;
11430 case Qt::WA_NoChildEventsFromChildren:
11431 d->receiveChildEvents = !on;
11432 break;
11433 case Qt::WA_MacNormalSize:
11434 case Qt::WA_MacSmallSize:
11435 case Qt::WA_MacMiniSize:
11436#ifdef Q_OS_MACOS
11437 {
11438 // We can only have one of these set at a time
11439 const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
11440 Qt::WA_MacMiniSize };
11441 for (int i = 0; i < 3; ++i) {
11442 if (MacSizes[i] != attribute)
11443 setAttribute_internal(MacSizes[i], false, data, d);
11444 }
11445 d->macUpdateSizeAttribute();
11446 }
11447#endif
11448 break;
11449 case Qt::WA_ShowModal:
11450 if (!on) {
11451 // reset modality type to NonModal when clearing WA_ShowModal
11452 data->window_modality = Qt::NonModal;
11453 } else if (data->window_modality == Qt::NonModal) {
11454 // If modality hasn't been set prior to setting WA_ShowModal, use
11455 // ApplicationModal.
11456 data->window_modality = Qt::ApplicationModal;
11457 // Some window managers do not allow us to enter modality after the
11458 // window is visible.The window must be hidden before changing the
11459 // windowModality property and then reshown.
11460 }
11461 if (testAttribute(Qt::WA_WState_Created)) {
11462 // don't call setModal_sys() before create()
11463 d->setModal_sys();
11464 }
11465 break;
11466 case Qt::WA_MouseTracking: {
11467 QEvent e(QEvent::MouseTrackingChange);
11468 QCoreApplication::sendEvent(this, &e);
11469 break; }
11470 case Qt::WA_TabletTracking: {
11471 QEvent e(QEvent::TabletTrackingChange);
11472 QCoreApplication::sendEvent(this, &e);
11473 break; }
11474 case Qt::WA_NativeWindow: {
11475 d->createTLExtra();
11476 if (on)
11477 d->createTLSysExtra();
11478#ifndef QT_NO_IM
11479 QWidget *focusWidget = d->effectiveFocusWidget();
11480 if (on && !internalWinId() && this == QGuiApplication::focusObject()
11481 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11482 QGuiApplication::inputMethod()->commit();
11483 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11484 }
11485 if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
11486 parentWidget()->d_func()->enforceNativeChildren();
11487 if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
11488 d->createWinId();
11489 if (isEnabled() && focusWidget->isEnabled() && this == QGuiApplication::focusObject()
11490 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11491 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11492 }
11493#endif //QT_NO_IM
11494 break;
11495 }
11496 case Qt::WA_PaintOnScreen:
11497 d->updateIsOpaque();
11498 Q_FALLTHROUGH();
11499 case Qt::WA_OpaquePaintEvent:
11500 d->updateIsOpaque();
11501 break;
11502 case Qt::WA_NoSystemBackground:
11503 d->updateIsOpaque();
11504 Q_FALLTHROUGH();
11505 case Qt::WA_UpdatesDisabled:
11506 d->updateSystemBackground();
11507 break;
11508 case Qt::WA_TransparentForMouseEvents:
11509 break;
11510 case Qt::WA_InputMethodEnabled: {
11511#ifndef QT_NO_IM
11512 if (QGuiApplication::focusObject() == this) {
11513 if (!on)
11514 QGuiApplication::inputMethod()->commit();
11515 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11516 }
11517#endif //QT_NO_IM
11518 break;
11519 }
11520 case Qt::WA_WindowPropagation:
11521 d->resolvePalette();
11522 d->resolveFont();
11523 d->resolveLocale();
11524 break;
11525 case Qt::WA_DontShowOnScreen: {
11526 if (on && isVisible()) {
11527 // Make sure we keep the current state and only hide the widget
11528 // from the desktop. show_sys will only update platform specific
11529 // attributes at this point.
11530 d->hide_sys();
11531 d->show_sys();
11532 }
11533 break;
11534 }
11535
11536 case Qt::WA_X11NetWmWindowTypeDesktop:
11537 case Qt::WA_X11NetWmWindowTypeDock:
11538 case Qt::WA_X11NetWmWindowTypeToolBar:
11539 case Qt::WA_X11NetWmWindowTypeMenu:
11540 case Qt::WA_X11NetWmWindowTypeUtility:
11541 case Qt::WA_X11NetWmWindowTypeSplash:
11542 case Qt::WA_X11NetWmWindowTypeDialog:
11543 case Qt::WA_X11NetWmWindowTypeDropDownMenu:
11544 case Qt::WA_X11NetWmWindowTypePopupMenu:
11545 case Qt::WA_X11NetWmWindowTypeToolTip:
11546 case Qt::WA_X11NetWmWindowTypeNotification:
11547 case Qt::WA_X11NetWmWindowTypeCombo:
11548 case Qt::WA_X11NetWmWindowTypeDND:
11549 d->setNetWmWindowTypes();
11550 break;
11551
11552 case Qt::WA_StaticContents:
11553 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
11554 if (on)
11555 repaintManager->addStaticWidget(this);
11556 else
11557 repaintManager->removeStaticWidget(this);
11558 }
11559 break;
11560 case Qt::WA_TranslucentBackground:
11561 if (on)
11562 setAttribute(Qt::WA_NoSystemBackground);
11563 d->updateIsTranslucent();
11564
11565 break;
11566 case Qt::WA_AcceptTouchEvents:
11567 break;
11568 default:
11569 break;
11570 }
11571}
11572
11573/*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
11574
11575 Returns \c true if attribute \a attribute is set on this widget;
11576 otherwise returns \c false.
11577
11578 \sa setAttribute()
11579 */
11580bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
11581{
11582 Q_D(const QWidget);
11583 const int x = attribute - 8*sizeof(uint);
11584 const int int_off = x / (8*sizeof(uint));
11585 return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
11586}
11587
11588/*!
11589 \property QWidget::windowOpacity
11590
11591 \brief The level of opacity for the window.
11592
11593 The valid range of opacity is from 1.0 (completely opaque) to
11594 0.0 (completely transparent).
11595
11596 By default the value of this property is 1.0.
11597
11598 This feature is available on Embedded Linux, \macos, Windows,
11599 and X11 platforms that support the Composite extension.
11600
11601 \note On X11 you need to have a composite manager running,
11602 and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
11603 supported by the window manager you are using.
11604
11605 \warning Changing this property from opaque to transparent might issue a
11606 paint event that needs to be processed before the window is displayed
11607 correctly. This affects mainly the use of QScreen::grabWindow(). Also note
11608 that semi-transparent windows update and resize significantly slower than
11609 opaque windows.
11610
11611 \sa setMask()
11612*/
11613qreal QWidget::windowOpacity() const
11614{
11615 Q_D(const QWidget);
11616 return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
11617}
11618
11619void QWidget::setWindowOpacity(qreal opacity)
11620{
11621 Q_D(QWidget);
11622 if (!isWindow())
11623 return;
11624
11625 opacity = qBound(qreal(0.0), opacity, qreal(1.0));
11626 QTLWExtra *extra = d->topData();
11627 extra->opacity = uint(opacity * 255);
11628 setAttribute(Qt::WA_WState_WindowOpacitySet);
11629 d->setWindowOpacity_sys(opacity);
11630
11631 if (!testAttribute(Qt::WA_WState_Created))
11632 return;
11633
11634#if QT_CONFIG(graphicsview)
11635 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
11636 // Avoid invalidating the cache if set.
11637 if (proxy->cacheMode() == QGraphicsItem::NoCache)
11638 proxy->update();
11639 else if (QGraphicsScene *scene = proxy->scene())
11640 scene->update(proxy->sceneBoundingRect());
11641 return;
11642 }
11643#endif
11644}
11645
11646void QWidgetPrivate::setWindowOpacity_sys(qreal level)
11647{
11648 Q_Q(QWidget);
11649 if (q->windowHandle())
11650 q->windowHandle()->setOpacity(level);
11651}
11652
11653/*!
11654 \property QWidget::windowModified
11655 \brief whether the document shown in the window has unsaved changes
11656
11657 A modified window is a window whose content has changed but has
11658 not been saved to disk. This flag will have different effects
11659 varied by the platform. On \macos the close button will have a
11660 modified look; on other platforms, the window title will have an
11661 '*' (asterisk).
11662
11663 The window title must contain a "[*]" placeholder, which
11664 indicates where the '*' should appear. Normally, it should appear
11665 right after the file name (e.g., "document1.txt[*] - Text
11666 Editor"). If the window isn't modified, the placeholder is simply
11667 removed.
11668
11669 Note that if a widget is set as modified, all its ancestors will
11670 also be set as modified. However, if you call \c
11671 {setWindowModified(false)} on a widget, this will not propagate to
11672 its parent because other children of the parent might have been
11673 modified.
11674
11675 \sa windowTitle
11676*/
11677bool QWidget::isWindowModified() const
11678{
11679 return testAttribute(Qt::WA_WindowModified);
11680}
11681
11682void QWidget::setWindowModified(bool mod)
11683{
11684 Q_D(QWidget);
11685 setAttribute(Qt::WA_WindowModified, mod);
11686
11687 d->setWindowModified_helper();
11688
11689 QEvent e(QEvent::ModifiedChange);
11690 QCoreApplication::sendEvent(this, &e);
11691}
11692
11693void QWidgetPrivate::setWindowModified_helper()
11694{
11695 Q_Q(QWidget);
11696 QWindow *window = q->windowHandle();
11697 if (!window)
11698 return;
11699 QPlatformWindow *platformWindow = window->handle();
11700 if (!platformWindow)
11701 return;
11702 bool on = q->testAttribute(Qt::WA_WindowModified);
11703 if (!platformWindow->setWindowModified(on)) {
11704 if (Q_UNLIKELY(on && !q->windowTitle().contains("[*]"_L1)))
11705 qWarning("QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
11706 setWindowTitle_helper(q->windowTitle());
11707 setWindowIconText_helper(q->windowIconText());
11708 }
11709}
11710
11711#if QT_CONFIG(tooltip)
11712/*!
11713 \property QWidget::toolTip
11714
11715 \brief the widget's tooltip
11716
11717 Note that by default tooltips are only shown for widgets that are
11718 children of the active window. You can change this behavior by
11719 setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
11720 not on the widget with the tooltip.
11721
11722 If you want to control a tooltip's behavior, you can intercept the
11723 event() function and catch the QEvent::ToolTip event (e.g., if you
11724 want to customize the area for which the tooltip should be shown).
11725
11726 By default, this property contains an empty string.
11727
11728 \sa QToolTip, statusTip, whatsThis
11729*/
11730void QWidget::setToolTip(const QString &s)
11731{
11732 Q_D(QWidget);
11733 d->toolTip = s;
11734
11735 QEvent event(QEvent::ToolTipChange);
11736 QCoreApplication::sendEvent(this, &event);
11737}
11738
11739QString QWidget::toolTip() const
11740{
11741 Q_D(const QWidget);
11742 return d->toolTip;
11743}
11744
11745/*!
11746 \property QWidget::toolTipDuration
11747 \brief the widget's tooltip duration
11748 \since 5.2
11749
11750 Specifies how long time the tooltip will be displayed, in milliseconds.
11751 If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
11752
11753 \sa toolTip
11754*/
11755
11756void QWidget::setToolTipDuration(int msec)
11757{
11758 Q_D(QWidget);
11759 d->toolTipDuration = msec;
11760}
11761
11762int QWidget::toolTipDuration() const
11763{
11764 Q_D(const QWidget);
11765 return d->toolTipDuration;
11766}
11767
11768#endif // QT_CONFIG(tooltip)
11769
11770
11771#if QT_CONFIG(statustip)
11772/*!
11773 \property QWidget::statusTip
11774 \brief the widget's status tip
11775
11776 By default, this property contains an empty string.
11777
11778 \sa toolTip, whatsThis
11779*/
11780void QWidget::setStatusTip(const QString &s)
11781{
11782 Q_D(QWidget);
11783 d->statusTip = s;
11784}
11785
11786QString QWidget::statusTip() const
11787{
11788 Q_D(const QWidget);
11789 return d->statusTip;
11790}
11791#endif // QT_CONFIG(statustip)
11792
11793#if QT_CONFIG(whatsthis)
11794/*!
11795 \property QWidget::whatsThis
11796
11797 \brief the widget's What's This help text.
11798
11799 By default, this property contains an empty string.
11800
11801 \sa QWhatsThis, QWidget::toolTip, QWidget::statusTip
11802*/
11803void QWidget::setWhatsThis(const QString &s)
11804{
11805 Q_D(QWidget);
11806 d->whatsThis = s;
11807}
11808
11809QString QWidget::whatsThis() const
11810{
11811 Q_D(const QWidget);
11812 return d->whatsThis;
11813}
11814#endif // QT_CONFIG(whatsthis)
11815
11816#if QT_CONFIG(accessibility)
11817/*!
11818 \property QWidget::accessibleName
11819
11820 \brief the widget's name as seen by assistive technologies
11821
11822 This is the primary name by which assistive technology such as screen readers
11823 announce this widget. For most widgets setting this property is not required.
11824 For example for QPushButton the button's text will be used.
11825
11826 It is important to set this property when the widget does not provide any
11827 text. For example a button that only contains an icon needs to set this
11828 property to work with screen readers.
11829 The name should be short and equivalent to the visual information conveyed
11830 by the widget.
11831
11832 This property has to be \l{Internationalization with Qt}{localized}.
11833
11834 By default, this property contains an empty string.
11835
11836 \sa QWidget::accessibleDescription, QAccessibleInterface::text()
11837*/
11838void QWidget::setAccessibleName(const QString &name)
11839{
11840 Q_D(QWidget);
11841 if (d->accessibleName == name)
11842 return;
11843
11844 d->accessibleName = name;
11845 QAccessibleEvent event(this, QAccessible::NameChanged);
11846 QAccessible::updateAccessibility(&event);
11847}
11848
11849QString QWidget::accessibleName() const
11850{
11851 Q_D(const QWidget);
11852 return d->accessibleName;
11853}
11854
11855/*!
11856 \property QWidget::accessibleDescription
11857
11858 \brief the widget's description as seen by assistive technologies
11859
11860 The accessible description of a widget should convey what a widget does.
11861 While the \l accessibleName should be a short and concise string (e.g. \gui{Save}),
11862 the description should give more context, such as \gui{Saves the current document}.
11863
11864 This property has to be \l{Internationalization with Qt}{localized}.
11865
11866 By default, this property contains an empty string and Qt falls back
11867 to using the tool tip to provide this information.
11868
11869 \sa QWidget::accessibleName, QAccessibleInterface::text()
11870*/
11871void QWidget::setAccessibleDescription(const QString &description)
11872{
11873 Q_D(QWidget);
11874 if (d->accessibleDescription == description)
11875 return;
11876
11877 d->accessibleDescription = description;
11878 QAccessibleEvent event(this, QAccessible::DescriptionChanged);
11879 QAccessible::updateAccessibility(&event);
11880}
11881
11882QString QWidget::accessibleDescription() const
11883{
11884 Q_D(const QWidget);
11885 return d->accessibleDescription;
11886}
11887
11888/*!
11889 \property QWidget::accessibleIdentifier
11890
11891 \brief the widget's identifier as seen by assistive technologies
11892
11893 If set, the accessible identifier of a widget can be used by assistive
11894 technologies in order to identify a specific widget, e.g. in automated
11895 tests.
11896
11897 \since 6.9
11898*/
11899void QWidget::setAccessibleIdentifier(const QString &identifier)
11900{
11901 Q_D(QWidget);
11902 if (d->accessibleIdentifier == identifier)
11903 return;
11904
11905 d->accessibleIdentifier = identifier;
11906 QAccessibleEvent event(this, QAccessible::IdentifierChanged);
11907 QAccessible::updateAccessibility(&event);
11908}
11909
11910QString QWidget::accessibleIdentifier() const
11911{
11912 Q_D(const QWidget);
11913 return d->accessibleIdentifier;
11914}
11915
11916#endif // QT_CONFIG(accessibility)
11917
11918#ifndef QT_NO_SHORTCUT
11919/*!
11920 Adds a shortcut to Qt's shortcut system that watches for the given
11921 \a key sequence in the given \a context. If the \a context is
11922 Qt::ApplicationShortcut, the shortcut applies to the application as a
11923 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
11924 or to the window itself, Qt::WindowShortcut.
11925
11926 If the same \a key sequence has been grabbed by several widgets,
11927 when the \a key sequence occurs a QEvent::Shortcut event is sent
11928 to all the widgets to which it applies in a non-deterministic
11929 order, but with the ``ambiguous'' flag set to true.
11930
11931 \warning You should not normally need to use this function;
11932 instead create \l{QAction}s with the shortcut key sequences you
11933 require (if you also want equivalent menu options and toolbar
11934 buttons), or create \l{QShortcut}s if you just need key sequences.
11935 Both QAction and QShortcut handle all the event filtering for you,
11936 and provide signals which are triggered when the user triggers the
11937 key sequence, so are much easier to use than this low-level
11938 function.
11939
11940 \sa releaseShortcut(), setShortcutEnabled()
11941*/
11942int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
11943{
11944 Q_ASSERT(qApp);
11945 if (key.isEmpty())
11946 return 0;
11947 setAttribute(Qt::WA_GrabbedShortcut);
11948 return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, key, context, qWidgetShortcutContextMatcher);
11949}
11950
11951/*!
11952 Removes the shortcut with the given \a id from Qt's shortcut
11953 system. The widget will no longer receive QEvent::Shortcut events
11954 for the shortcut's key sequence (unless it has other shortcuts
11955 with the same key sequence).
11956
11957 \warning You should not normally need to use this function since
11958 Qt's shortcut system removes shortcuts automatically when their
11959 parent widget is destroyed. It is best to use QAction or
11960 QShortcut to handle shortcuts, since they are easier to use than
11961 this low-level function. Note also that this is an expensive
11962 operation.
11963
11964 \sa grabShortcut(), setShortcutEnabled()
11965*/
11966void QWidget::releaseShortcut(int id)
11967{
11968 Q_ASSERT(qApp);
11969 if (id)
11970 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this, 0);
11971}
11972
11973/*!
11974 If \a enable is true, the shortcut with the given \a id is
11975 enabled; otherwise the shortcut is disabled.
11976
11977 \warning You should not normally need to use this function since
11978 Qt's shortcut system enables/disables shortcuts automatically as
11979 widgets become hidden/visible and gain or lose focus. It is best
11980 to use QAction or QShortcut to handle shortcuts, since they are
11981 easier to use than this low-level function.
11982
11983 \sa grabShortcut(), releaseShortcut()
11984*/
11985void QWidget::setShortcutEnabled(int id, bool enable)
11986{
11987 Q_ASSERT(qApp);
11988 if (id)
11989 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, this, 0);
11990}
11991
11992/*!
11993 \since 4.2
11994
11995 If \a enable is true, auto repeat of the shortcut with the
11996 given \a id is enabled; otherwise it is disabled.
11997
11998 \sa grabShortcut(), releaseShortcut()
11999*/
12000void QWidget::setShortcutAutoRepeat(int id, bool enable)
12001{
12002 Q_ASSERT(qApp);
12003 if (id)
12004 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(enable, id, this, 0);
12005}
12006#endif // QT_NO_SHORTCUT
12007
12008/*!
12009 Updates the widget's micro focus and informs input methods
12010 that the state specified by \a query has changed.
12011*/
12012void QWidget::updateMicroFocus(Qt::InputMethodQuery query)
12013{
12014 if (this == QGuiApplication::focusObject())
12015 QGuiApplication::inputMethod()->update(query);
12016}
12017
12018/*!
12019 Raises this widget to the top of the parent widget's stack.
12020
12021 After this call the widget will be visually in front of any
12022 overlapping sibling widgets.
12023
12024 \note When using activateWindow(), you can call this function to
12025 ensure that the window is stacked on top.
12026
12027 \sa lower(), stackUnder()
12028*/
12029
12030void QWidget::raise()
12031{
12032 Q_D(QWidget);
12033 if (!isWindow()) {
12034 QWidget *p = parentWidget();
12035 const int parentChildCount = p->d_func()->children.size();
12036 if (parentChildCount < 2)
12037 return;
12038 const int from = p->d_func()->children.indexOf(this);
12039 Q_ASSERT(from >= 0);
12040 // Do nothing if the widget is already in correct stacking order _and_ created.
12041 if (from != parentChildCount -1)
12042 p->d_func()->children.move(from, parentChildCount - 1);
12043 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12044 create();
12045 else if (from == parentChildCount - 1)
12046 return;
12047
12048 QRegion region(rect());
12049 d->subtractOpaqueSiblings(region);
12050 d->invalidateBackingStore(region);
12051 }
12052 if (testAttribute(Qt::WA_WState_Created))
12053 d->raise_sys();
12054
12055 if (d->extra && d->extra->hasWindowContainer)
12056 QWindowContainer::parentWasRaised(this);
12057
12058 QEvent e(QEvent::ZOrderChange);
12059 QCoreApplication::sendEvent(this, &e);
12060}
12061
12062void QWidgetPrivate::raise_sys()
12063{
12064 Q_Q(QWidget);
12065 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
12066 q->windowHandle()->raise();
12067 } else if (renderToTexture) {
12068 if (QWidget *p = q->parentWidget()) {
12069 setDirtyOpaqueRegion();
12070 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12071 }
12072 }
12073}
12074
12075/*!
12076 Lowers the widget to the bottom of the parent widget's stack.
12077
12078 After this call the widget will be visually behind (and therefore
12079 obscured by) any overlapping sibling widgets.
12080
12081 \sa raise(), stackUnder()
12082*/
12083
12084void QWidget::lower()
12085{
12086 Q_D(QWidget);
12087 if (!isWindow()) {
12088 QWidget *p = parentWidget();
12089 const int parentChildCount = p->d_func()->children.size();
12090 if (parentChildCount < 2)
12091 return;
12092 const int from = p->d_func()->children.indexOf(this);
12093 Q_ASSERT(from >= 0);
12094 // Do nothing if the widget is already in correct stacking order _and_ created.
12095 if (from != 0)
12096 p->d_func()->children.move(from, 0);
12097 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12098 create();
12099 else if (from == 0)
12100 return;
12101 }
12102 if (testAttribute(Qt::WA_WState_Created))
12103 d->lower_sys();
12104
12105 if (d->extra && d->extra->hasWindowContainer)
12106 QWindowContainer::parentWasLowered(this);
12107
12108 QEvent e(QEvent::ZOrderChange);
12109 QCoreApplication::sendEvent(this, &e);
12110}
12111
12112void QWidgetPrivate::lower_sys()
12113{
12114 Q_Q(QWidget);
12115 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
12116 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
12117 q->windowHandle()->lower();
12118 } else if (QWidget *p = q->parentWidget()) {
12119 setDirtyOpaqueRegion();
12120 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12121 }
12122}
12123
12124/*!
12125 Places the widget under \a w in the parent widget's stack.
12126
12127 To make this work, the widget itself and \a w must be siblings.
12128
12129 \sa raise(), lower()
12130*/
12131void QWidget::stackUnder(QWidget* w)
12132{
12133 Q_D(QWidget);
12134 QWidget *p = parentWidget();
12135 if (!w || isWindow() || p != w->parentWidget() || this == w)
12136 return;
12137 if (p) {
12138 int from = p->d_func()->children.indexOf(this);
12139 int to = p->d_func()->children.indexOf(w);
12140 Q_ASSERT(from >= 0);
12141 Q_ASSERT(to >= 0);
12142 if (from < to)
12143 --to;
12144 // Do nothing if the widget is already in correct stacking order _and_ created.
12145 if (from != to)
12146 p->d_func()->children.move(from, to);
12147 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12148 create();
12149 else if (from == to)
12150 return;
12151 }
12152 if (testAttribute(Qt::WA_WState_Created))
12153 d->stackUnder_sys(w);
12154
12155 QEvent e(QEvent::ZOrderChange);
12156 QCoreApplication::sendEvent(this, &e);
12157}
12158
12159void QWidgetPrivate::stackUnder_sys(QWidget*)
12160{
12161 Q_Q(QWidget);
12162 if (QWidget *p = q->parentWidget()) {
12163 setDirtyOpaqueRegion();
12164 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12165 }
12166}
12167
12168/*!
12169 \fn bool QWidget::isTopLevel() const
12170 \deprecated
12171
12172 Use isWindow() instead.
12173*/
12174
12175/*!
12176 \fn bool QWidget::isRightToLeft() const
12177 \internal
12178*/
12179
12180/*!
12181 \fn bool QWidget::isLeftToRight() const
12182 \internal
12183*/
12184
12185/*!
12186 \macro QWIDGETSIZE_MAX
12187 \relates QWidget
12188
12189 Defines the maximum size for a QWidget object.
12190
12191 The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
12192 QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
12193
12194 \sa QWidget::setMaximumSize()
12195*/
12196
12197/*!
12198 \fn QWidget::setupUi(QWidget *widget)
12199
12200 Sets up the user interface for the specified \a widget.
12201
12202 \note This function is available with widgets that derive from user
12203 interface descriptions created using \l{uic}.
12204
12205 \sa {Using a Qt Widgets Designer UI File in Your Application}
12206*/
12207
12208QRect QWidgetPrivate::frameStrut() const
12209{
12210 Q_Q(const QWidget);
12211 if (!q->isWindow() || q->testAttribute(Qt::WA_DontShowOnScreen)) {
12212 // x2 = x1 + w - 1, so w/h = 1
12213 return QRect(0, 0, 1, 1);
12214 }
12215
12216 if (data.fstrut_dirty
12217 // ### Fix properly for 4.3
12218 && q->isVisible()
12219 && q->testAttribute(Qt::WA_WState_Created))
12220 const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
12221
12222 return maybeTopData() ? maybeTopData()->frameStrut : QRect();
12223}
12224
12225void QWidgetPrivate::updateFrameStrut()
12226{
12227 Q_Q(QWidget);
12228 if (q->data->fstrut_dirty) {
12229 if (QTLWExtra *te = maybeTopData()) {
12230 if (te->window && te->window->handle()) {
12231 const QMargins margins = te->window->frameMargins();
12232 if (!margins.isNull()) {
12233 te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
12234 q->data->fstrut_dirty = false;
12235 }
12236 }
12237 }
12238 }
12239}
12240
12241/*!
12242 \since 5.0
12243 \internal
12244
12245 Sets the backing store to be the \a store specified.
12246 The QWidget will take ownership of the \a store.
12247*/
12248void QWidget::setBackingStore(QBackingStore *store)
12249{
12250 // ### createWinId() ??
12251
12252 if (!isWindow())
12253 return;
12254
12255 Q_D(QWidget);
12256
12257 QTLWExtra *topData = d->topData();
12258 if (topData->backingStore == store)
12259 return;
12260
12261 QBackingStore *oldStore = topData->backingStore;
12262 delete topData->backingStore;
12263 topData->backingStore = store;
12264
12265 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
12266 if (!repaintManager)
12267 return;
12268
12269 if (isWindow()) {
12270 if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store)
12271 delete repaintManager->backingStore();
12272 repaintManager->setBackingStore(store);
12273 }
12274}
12275
12276/*!
12277 \since 5.0
12278
12279 Returns the QBackingStore this widget will be drawn into.
12280*/
12281QBackingStore *QWidget::backingStore() const
12282{
12283 Q_D(const QWidget);
12284 QTLWExtra *extra = d->maybeTopData();
12285 if (extra && extra->backingStore)
12286 return extra->backingStore;
12287
12288 if (!isWindow())
12289 return window()->backingStore();
12290
12291 return nullptr;
12292}
12293
12294void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
12295{
12296 if (left)
12297 *left = (int)leftLayoutItemMargin;
12298 if (top)
12299 *top = (int)topLayoutItemMargin;
12300 if (right)
12301 *right = (int)rightLayoutItemMargin;
12302 if (bottom)
12303 *bottom = (int)bottomLayoutItemMargin;
12304}
12305
12306void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
12307{
12308 if (leftLayoutItemMargin == left
12309 && topLayoutItemMargin == top
12310 && rightLayoutItemMargin == right
12311 && bottomLayoutItemMargin == bottom)
12312 return;
12313
12314 Q_Q(QWidget);
12315 leftLayoutItemMargin = (signed char)left;
12316 topLayoutItemMargin = (signed char)top;
12317 rightLayoutItemMargin = (signed char)right;
12318 bottomLayoutItemMargin = (signed char)bottom;
12319 q->updateGeometry();
12320}
12321
12322void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
12323{
12324 Q_Q(QWidget);
12325 QStyleOption myOpt;
12326 if (!opt) {
12327 myOpt.initFrom(q);
12328 myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary
12329 opt = &myOpt;
12330 }
12331
12332 QRect liRect = q->style()->subElementRect(element, opt, q);
12333 if (liRect.isValid()) {
12334 leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
12335 topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
12336 rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
12337 bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
12338 } else {
12339 leftLayoutItemMargin = 0;
12340 topLayoutItemMargin = 0;
12341 rightLayoutItemMargin = 0;
12342 bottomLayoutItemMargin = 0;
12343 }
12344}
12345// resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
12346void QWidgetPrivate::adjustQuitOnCloseAttribute()
12347{
12348 Q_Q(QWidget);
12349
12350 if (!q->parentWidget()) {
12351 Qt::WindowType type = q->windowType();
12352 if (type == Qt::Widget || type == Qt::SubWindow)
12353 type = Qt::Window;
12354 if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
12355 q->setAttribute(Qt::WA_QuitOnClose, false);
12356 }
12357}
12358
12359void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
12360{
12361 QWidgetPrivate *wd = QWidgetPrivate::get(w);
12362 if (!wd->textureChildSeen)
12363 return;
12364 if (end)
12365 wd->endCompose();
12366 else
12367 wd->beginCompose();
12368 for (int i = 0; i < wd->children.size(); ++i) {
12369 w = qobject_cast<QWidget *>(wd->children.at(i));
12370 if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
12371 sendComposeStatus(w, end);
12372 }
12373}
12374
12375Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
12376{
12377 return widget->data;
12378}
12379
12380Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
12381{
12382 return widget->d_func();
12383}
12384
12385
12386#if QT_CONFIG(graphicsview)
12387/*!
12388 \since 4.5
12389
12390 Returns the proxy widget for the corresponding embedded widget in a graphics
12391 view; otherwise returns \nullptr.
12392
12393 \sa QGraphicsProxyWidget::createProxyForChildWidget(),
12394 QGraphicsScene::addWidget()
12395 */
12396QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
12397{
12398 Q_D(const QWidget);
12399 if (d->extra) {
12400 return d->extra->proxyWidget;
12401 }
12402 return nullptr;
12403}
12404#endif
12405
12406#ifndef QT_NO_GESTURES
12407/*!
12408 Subscribes the widget to a given \a gesture with specific \a flags.
12409
12410 \sa ungrabGesture(), QGestureEvent
12411 \since 4.6
12412*/
12413void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
12414{
12415 Q_D(QWidget);
12416 d->gestureContext.insert(gesture, flags);
12417 (void)QGestureManager::instance(); // create a gesture manager
12418}
12419
12420/*!
12421 Unsubscribes the widget from a given \a gesture type
12422
12423 \sa grabGesture(), QGestureEvent
12424 \since 4.6
12425*/
12426void QWidget::ungrabGesture(Qt::GestureType gesture)
12427{
12428 // if you modify this function, check the inlined version in ~QWidget, too
12429 Q_D(QWidget);
12430 if (d->gestureContext.remove(gesture)) {
12431 if (QGestureManager *manager = QGestureManager::instance())
12432 manager->cleanupCachedGestures(this, gesture);
12433 }
12434}
12435#endif // QT_NO_GESTURES
12436
12437/*!
12438 \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12439
12440 Frees up window system resources. Destroys the widget window if \a
12441 destroyWindow is true.
12442
12443 destroy() calls itself recursively for all the child widgets,
12444 passing \a destroySubWindows for the \a destroyWindow parameter.
12445 To have more control over destruction of subwidgets, destroy
12446 subwidgets selectively first.
12447
12448 This function is usually called from the QWidget destructor.
12449*/
12450void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12451{
12452 Q_D(QWidget);
12453
12454 d->aboutToDestroy();
12455 if (!isWindow() && parentWidget())
12456 parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(geometry()));
12457 d->deactivateWidgetCleanup();
12458
12459 if ((windowType() == Qt::Popup) && qApp)
12460 qApp->d_func()->closePopup(this);
12461
12462 if (this == qApp->activeWindow())
12463 QApplicationPrivate::setActiveWindow(nullptr);
12464 if (QWidget::mouseGrabber() == this)
12465 releaseMouse();
12466 if (QWidget::keyboardGrabber() == this)
12467 releaseKeyboard();
12468
12469 setAttribute(Qt::WA_WState_Created, false);
12470
12471 if (destroySubWindows) {
12472 QObjectList childList(children());
12473 for (int i = 0; i < childList.size(); i++) {
12474 QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
12475 if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
12476 if (widget->windowHandle()) {
12477 widget->destroy();
12478 }
12479 }
12480 }
12481 }
12482 if (destroyWindow) {
12483 d->deleteTLSysExtra();
12484 } else {
12485 if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
12486 d->hide_sys();
12487 }
12488 }
12489
12490 d->setWinId(0);
12491}
12492
12493/*!
12494 \fn QPaintEngine *QWidget::paintEngine() const
12495
12496 Returns the widget's paint engine.
12497
12498 Note that this function should not be called explicitly by the
12499 user, since it's meant for reimplementation purposes only. The
12500 function is called by Qt internally, and the default
12501 implementation may not always return a valid pointer.
12502*/
12503QPaintEngine *QWidget::paintEngine() const
12504{
12505 qWarning("QWidget::paintEngine: Should no longer be called");
12506
12507#ifdef Q_OS_WIN
12508 // We set this bit which is checked in setAttribute for
12509 // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
12510 //
12511 // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
12512 // Windows which would mean suddenly their widgets stop working.
12513 //
12514 // 2. Users set paint on screen and subclass paintEngine() to
12515 // return 0, in which case we have a "hole" in the backingstore
12516 // allowing use of GDI or DirectX directly.
12517 //
12518 // 1 is WRONG, but to minimize silent failures, we have set this
12519 // bit to ignore the setAttribute call. 2. needs to be
12520 // supported because its our only means of embedding native
12521 // graphics stuff.
12522 const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
12523#endif
12524
12525 return nullptr; //##### @@@
12526}
12527
12528// Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing.
12529static inline bool canMapPosition(QWindow *window)
12530{
12531 return window->handle() && !qt_window_private(window)->resizeEventPending;
12532}
12533
12534#if QT_CONFIG(graphicsview)
12535static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w)
12536{
12537 QGraphicsProxyWidget *result = nullptr;
12538 const QWidgetPrivate *d = qt_widget_private(const_cast<QWidget *>(w));
12539 if (d->extra)
12540 result = d->extra->proxyWidget;
12541 return result;
12542}
12543#endif // QT_CONFIG(graphicsview)
12544
12546 QTransform transform;
12547 QWindow *window;
12548};
12549
12551{
12553 result.window = nullptr;
12554 for ( ; w ; w = w->parentWidget()) {
12555#if QT_CONFIG(graphicsview)
12556 if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) {
12557 if (const QGraphicsScene *scene = qgpw->scene()) {
12558 const QList <QGraphicsView *> views = scene->views();
12559 if (!views.isEmpty()) {
12560 auto *viewP = static_cast<QGraphicsViewPrivate *>(qt_widget_private(views.constFirst()));
12561 result.transform *= viewP->mapToViewTransform(qgpw);
12562 w = views.first()->viewport();
12563 }
12564 }
12565 }
12566#endif // QT_CONFIG(graphicsview)
12567 QWindow *window = w->windowHandle();
12568 if (window && canMapPosition(window)) {
12569 result.window = window;
12570 break;
12571 }
12572
12573 const auto &geometry = w->geometry();
12574 result.transform *= QTransform::fromTranslate(geometry.x(), geometry.y());
12575 if (w->isWindow())
12576 break;
12577 }
12578 return result;
12579}
12580
12581/*!
12582 \fn QPointF QWidget::mapToGlobal(const QPointF &pos) const
12583
12584 Translates the widget coordinate \a pos to global screen
12585 coordinates. For example, \c{mapToGlobal(QPointF(0,0))} would give
12586 the global coordinates of the top-left pixel of the widget.
12587
12588 \sa mapFromGlobal(), mapTo(), mapToParent()
12589 \since 6.0
12590*/
12591QPointF QWidget::mapToGlobal(const QPointF &pos) const
12592{
12593 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12594 const QPointF g = t.transform.map(pos);
12595 return t.window ? t.window->mapToGlobal(g) : g;
12596}
12597
12598/*!
12599 \overload
12600*/
12601QPoint QWidget::mapToGlobal(const QPoint &pos) const
12602{
12603 return mapToGlobal(QPointF(pos)).toPoint();
12604}
12605
12606/*!
12607 \fn QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12608
12609 Translates the global screen coordinate \a pos to widget
12610 coordinates.
12611
12612 \sa mapToGlobal(), mapFrom(), mapFromParent()
12613 \since 6.0
12614*/
12615QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12616{
12617 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12618 const QPointF windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos;
12619 return t.transform.inverted().map(windowLocal);
12620}
12621
12622/*!
12623 \overload
12624*/
12625QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12626{
12627 return mapFromGlobal(QPointF(pos)).toPoint();
12628}
12629
12631static bool mouseGrabWithCursor = false;
12632static QWidget *keyboardGrb = nullptr;
12633
12634static inline QWindow *grabberWindow(const QWidget *w)
12635{
12636 QWindow *window = w->windowHandle();
12637 if (!window)
12638 if (const QWidget *nativeParent = w->nativeParentWidget())
12639 window = nativeParent->windowHandle();
12640 return window;
12641}
12642
12643#ifndef QT_NO_CURSOR
12644static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = nullptr)
12645#else
12646static void grabMouseForWidget(QWidget *widget)
12647#endif
12648{
12649 if (qt_mouseGrb)
12650 qt_mouseGrb->releaseMouse();
12651
12652 mouseGrabWithCursor = false;
12653 if (QWindow *window = grabberWindow(widget)) {
12654#ifndef QT_NO_CURSOR
12655 if (cursor) {
12656 mouseGrabWithCursor = true;
12657 QGuiApplication::setOverrideCursor(*cursor);
12658 }
12659#endif // !QT_NO_CURSOR
12660 window->setMouseGrabEnabled(true);
12661 }
12662
12663 qt_mouseGrb = widget;
12664}
12665
12667{
12668 if (qt_mouseGrb == widget) {
12669 if (QWindow *window = grabberWindow(widget)) {
12670#ifndef QT_NO_CURSOR
12671 if (mouseGrabWithCursor) {
12672 QGuiApplication::restoreOverrideCursor();
12673 mouseGrabWithCursor = false;
12674 }
12675#endif // !QT_NO_CURSOR
12676 window->setMouseGrabEnabled(false);
12677 }
12678 }
12679 qt_mouseGrb = nullptr;
12680}
12681
12682/*!
12683 \fn void QWidget::grabMouse()
12684
12685 Grabs the mouse input.
12686
12687 This widget receives all mouse events until releaseMouse() is
12688 called; other widgets get no mouse events at all. Keyboard
12689 events are not affected. Use grabKeyboard() if you want to grab
12690 that.
12691
12692 \warning Bugs in mouse-grabbing applications very often lock the
12693 terminal. Use this function with extreme caution, and consider
12694 using the \c -nograb command line option while debugging.
12695
12696 It is seldom necessary to grab the mouse when using Qt, as
12697 Qt grabs and releases it sensibly. In particular, Qt grabs the
12698 mouse when a mouse button is pressed and keeps it until the last
12699 button is released.
12700
12701 \note Only visible widgets can grab mouse input. If isVisible()
12702 returns \c false for a widget, that widget cannot call grabMouse().
12703
12704 \note On Windows, grabMouse() only works when the mouse is inside a window
12705 owned by the process.
12706 On \macos, grabMouse() only works when the mouse is inside the frame of that widget.
12707
12708 \sa releaseMouse(), grabKeyboard(), releaseKeyboard()
12709*/
12710void QWidget::grabMouse()
12711{
12712 grabMouseForWidget(this);
12713}
12714
12715/*!
12716 \fn void QWidget::grabMouse(const QCursor &cursor)
12717 \overload grabMouse()
12718
12719 Grabs the mouse input and changes the cursor shape.
12720
12721 The cursor will assume shape \a cursor (for as long as the mouse
12722 focus is grabbed) and this widget will be the only one to receive
12723 mouse events until releaseMouse() is called().
12724
12725 \warning Grabbing the mouse might lock the terminal.
12726
12727 \note See the note in QWidget::grabMouse().
12728
12729 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
12730*/
12731#ifndef QT_NO_CURSOR
12732void QWidget::grabMouse(const QCursor &cursor)
12733{
12734 grabMouseForWidget(this, &cursor);
12735}
12736#endif
12737
12738bool QWidgetPrivate::stealMouseGrab(bool grab)
12739{
12740 // This is like a combination of grab/releaseMouse() but with error checking
12741 // and it has no effect on the result of mouseGrabber().
12742 Q_Q(QWidget);
12743 QWindow *window = grabberWindow(q);
12744 return window ? window->setMouseGrabEnabled(grab) : false;
12745}
12746
12747/*!
12748 \fn void QWidget::releaseMouse()
12749
12750 Releases the mouse grab.
12751
12752 \sa grabMouse(), grabKeyboard(), releaseKeyboard()
12753*/
12754void QWidget::releaseMouse()
12755{
12756 releaseMouseGrabOfWidget(this);
12757}
12758
12759/*!
12760 \fn void QWidget::grabKeyboard()
12761
12762 Grabs the keyboard input.
12763
12764 This widget receives all keyboard events until releaseKeyboard()
12765 is called; other widgets get no keyboard events at all. Mouse
12766 events are not affected. Use grabMouse() if you want to grab that.
12767
12768 The focus widget is not affected, except that it doesn't receive
12769 any keyboard events. setFocus() moves the focus as usual, but the
12770 new focus widget receives keyboard events only after
12771 releaseKeyboard() is called.
12772
12773 If a different widget is currently grabbing keyboard input, that
12774 widget's grab is released first.
12775
12776 \sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
12777*/
12778void QWidget::grabKeyboard()
12779{
12780 if (keyboardGrb)
12781 keyboardGrb->releaseKeyboard();
12782 if (QWindow *window = grabberWindow(this))
12783 window->setKeyboardGrabEnabled(true);
12784 keyboardGrb = this;
12785}
12786
12787bool QWidgetPrivate::stealKeyboardGrab(bool grab)
12788{
12789 // This is like a combination of grab/releaseKeyboard() but with error
12790 // checking and it has no effect on the result of keyboardGrabber().
12791 Q_Q(QWidget);
12792 QWindow *window = grabberWindow(q);
12793 return window ? window->setKeyboardGrabEnabled(grab) : false;
12794}
12795
12796/*!
12797 \fn void QWidget::releaseKeyboard()
12798
12799 Releases the keyboard grab.
12800
12801 \sa grabKeyboard(), grabMouse(), releaseMouse()
12802*/
12803void QWidget::releaseKeyboard()
12804{
12805 if (keyboardGrb == this) {
12806 if (QWindow *window = grabberWindow(this))
12807 window->setKeyboardGrabEnabled(false);
12808 keyboardGrb = nullptr;
12809 }
12810}
12811
12812/*!
12813 \fn QWidget *QWidget::mouseGrabber()
12814
12815 Returns the widget that is currently grabbing the mouse input.
12816
12817 If no widget in this application is currently grabbing the mouse,
12818 \nullptr is returned.
12819
12820 \sa grabMouse(), keyboardGrabber()
12821*/
12822QWidget *QWidget::mouseGrabber()
12823{
12824 return qt_mouseGrb;
12825}
12826
12827/*!
12828 \fn QWidget *QWidget::keyboardGrabber()
12829
12830 Returns the widget that is currently grabbing the keyboard input.
12831
12832 If no widget in this application is currently grabbing the
12833 keyboard, \nullptr is returned.
12834
12835 \sa grabMouse(), mouseGrabber()
12836*/
12837QWidget *QWidget::keyboardGrabber()
12838{
12839 return keyboardGrb;
12840}
12841
12842/*!
12843 \fn void QWidget::activateWindow()
12844
12845 Sets the top-level widget containing this widget to be the active
12846 window.
12847
12848 An active window is a visible top-level window that has the
12849 keyboard input focus.
12850
12851 This function performs the same operation as clicking the mouse on
12852 the title bar of a top-level window. On X11, the result depends on
12853 the Window Manager. If you want to ensure that the window is
12854 stacked on top as well you should also call raise(). Note that the
12855 window must be visible, otherwise activateWindow() has no effect.
12856
12857 On Windows, if you are calling this when the application is not
12858 currently the active one then it will not make it the active
12859 window. It will change the color of the taskbar entry to indicate
12860 that the window has changed in some way. This is because Microsoft
12861 does not allow an application to interrupt what the user is currently
12862 doing in another application.
12863
12864 \sa isActiveWindow(), window(), show()
12865*/
12866void QWidget::activateWindow()
12867{
12868 QWindow *const wnd = window()->windowHandle();
12869
12870 if (wnd)
12871 wnd->requestActivate();
12872}
12873
12874/*!
12875
12876 Internal implementation of the virtual QPaintDevice::metric()
12877 function.
12878
12879 \a m is the metric to get.
12880*/
12881int QWidget::metric(PaintDeviceMetric m) const
12882{
12883 QScreen *screen = this->screen();
12884
12885 if (!screen) {
12886 if (m == PdmDpiX || m == PdmDpiY)
12887 return 72;
12888 return QPaintDevice::metric(m);
12889 }
12890
12891 auto resolveDevicePixelRatio = [this, screen]() -> qreal {
12892
12893 // Note: keep in sync with QBackingStorePrivate::backingStoreDevicePixelRatio()!
12894 static bool downscale = qEnvironmentVariableIntValue("QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
12895 QWindow *window = this->window()->windowHandle();
12896 if (window)
12897 return downscale ? std::ceil(window->devicePixelRatio()) : window->devicePixelRatio();
12898 return screen->devicePixelRatio();
12899 };
12900
12901 switch (m) {
12902 case PdmWidth:
12903 return data->crect.width();
12904 case PdmWidthMM:
12905 return data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
12906 case PdmHeight:
12907 return data->crect.height();
12908 case PdmHeightMM:
12909 return data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
12910 case PdmDepth:
12911 return screen->depth();
12912 case PdmDpiX:
12913 for (const QWidget *p = this; p; p = p->parentWidget()) {
12914 if (p->d_func()->extra && p->d_func()->extra->customDpiX)
12915 return p->d_func()->extra->customDpiX;
12916 }
12917 return qRound(screen->logicalDotsPerInchX());
12918 case PdmDpiY:
12919 for (const QWidget *p = this; p; p = p->parentWidget()) {
12920 if (p->d_func()->extra && p->d_func()->extra->customDpiY)
12921 return p->d_func()->extra->customDpiY;
12922 }
12923 return qRound(screen->logicalDotsPerInchY());
12924 case PdmPhysicalDpiX:
12925 return qRound(screen->physicalDotsPerInchX());
12926 case PdmPhysicalDpiY:
12927 return qRound(screen->physicalDotsPerInchY());
12928 case PdmDevicePixelRatio:
12929 return resolveDevicePixelRatio();
12930 case PdmDevicePixelRatioScaled:
12931 return QPaintDevice::devicePixelRatioFScale() * resolveDevicePixelRatio();
12932 case PdmDevicePixelRatioF_EncodedA:
12933 Q_FALLTHROUGH();
12934 case PdmDevicePixelRatioF_EncodedB:
12935 return QPaintDevice::encodeMetricF(m, resolveDevicePixelRatio());
12936 default:
12937 break;
12938 }
12939 return QPaintDevice::metric(m);
12940}
12941
12942/*!
12943 Initializes the \a painter pen, background and font to the same as
12944 the given widget's. This function is called automatically when the
12945 painter is opened on a QWidget.
12946*/
12947void QWidget::initPainter(QPainter *painter) const
12948{
12949 const QPalette &pal = palette();
12950 QPainterPrivate *painterPrivate = QPainterPrivate::get(painter);
12951
12952 painterPrivate->state->pen = QPen(pal.brush(foregroundRole()), 1);
12953 painterPrivate->state->bgBrush = pal.brush(backgroundRole());
12954 QFont f(font(), this);
12955 painterPrivate->state->deviceFont = f;
12956 painterPrivate->state->font = f;
12957
12958 painterPrivate->setEngineDirtyFlags({
12959 QPaintEngine::DirtyPen,
12960 QPaintEngine::DirtyBrush,
12961 QPaintEngine::DirtyFont,
12962 });
12963
12964 if (painterPrivate->extended)
12965 painterPrivate->extended->penChanged();
12966}
12967
12968/*!
12969 \internal
12970
12971 Do PaintDevice rendering with the specified \a offset.
12972*/
12973QPaintDevice *QWidget::redirected(QPoint *offset) const
12974{
12975 return d_func()->redirected(offset);
12976}
12977
12978/*!
12979 \internal
12980
12981 A painter that is shared among other instances of QPainter.
12982*/
12983QPainter *QWidget::sharedPainter() const
12984{
12985 // Someone sent a paint event directly to the widget
12986 if (!d_func()->redirectDev)
12987 return nullptr;
12988
12989 QPainter *sp = d_func()->sharedPainter();
12990 if (!sp || !sp->isActive())
12991 return nullptr;
12992
12993 if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
12994 return nullptr;
12995
12996 return sp;
12997}
12998
12999/*!
13000 \fn void QWidget::setMask(const QRegion &region)
13001 \overload
13002
13003 Causes only the parts of the widget which overlap \a region to be
13004 visible. If the region includes pixels outside the rect() of the
13005 widget, window system controls in that area may or may not be
13006 visible, depending on the platform.
13007
13008 Since QRegion allows arbitrarily complex regions to be created, widget
13009 masks can be made to suit the most unconventionally-shaped windows, and
13010 even allow widgets to be displayed with holes in them. Note that this
13011 effect can be slow if the region is particularly complex.
13012
13013 Widget masks are used to hint to the window system that the application
13014 does not want mouse events for areas outside the mask. On most systems,
13015 they also result in coarse visual clipping. To get smooth window edges, use
13016 translucent background and anti-aliased painting instead, as shown in the
13017 \l{Translucent Background} example.
13018
13019 \sa windowOpacity
13020*/
13021void QWidget::setMask(const QRegion &newMask)
13022{
13023 Q_D(QWidget);
13024
13025 d->createExtra();
13026 if (newMask == d->extra->mask)
13027 return;
13028
13029#ifndef QT_NO_BACKINGSTORE
13030 const QRegion oldMask(d->extra->mask);
13031#endif
13032
13033 d->extra->mask = newMask;
13034 d->extra->hasMask = !newMask.isEmpty();
13035
13036 if (!testAttribute(Qt::WA_WState_Created))
13037 return;
13038
13039 d->setMask_sys(newMask);
13040
13041#ifndef QT_NO_BACKINGSTORE
13042 if (!isVisible())
13043 return;
13044
13045 if (!d->extra->hasMask) {
13046 // Mask was cleared; update newly exposed area.
13047 QRegion expose(rect());
13048 expose -= oldMask;
13049 if (!expose.isEmpty()) {
13050 d->setDirtyOpaqueRegion();
13051 update(expose);
13052 }
13053 return;
13054 }
13055
13056 if (!isWindow()) {
13057 // Update newly exposed area on the parent widget.
13058 QRegion parentExpose(rect());
13059 parentExpose -= newMask;
13060 if (!parentExpose.isEmpty()) {
13061 d->setDirtyOpaqueRegion();
13062 parentExpose.translate(data->crect.topLeft());
13063 parentWidget()->update(parentExpose);
13064 }
13065
13066 // Update newly exposed area on this widget
13067 if (!oldMask.isEmpty())
13068 update(newMask - oldMask);
13069 }
13070#endif
13071}
13072
13073void QWidgetPrivate::setMask_sys(const QRegion &region)
13074{
13075 Q_Q(QWidget);
13076 if (QWindow *window = q->windowHandle())
13077 window->setMask(region);
13078}
13079
13080/*!
13081 \fn void QWidget::setMask(const QBitmap &bitmap)
13082
13083 Causes only the pixels of the widget for which \a bitmap has a
13084 corresponding 1 bit to be visible. If the region includes pixels
13085 outside the rect() of the widget, window system controls in that
13086 area may or may not be visible, depending on the platform.
13087
13088 Note that this effect can be slow if the region is particularly
13089 complex.
13090
13091 The following code shows how an image with an alpha channel can be
13092 used to generate a mask for a widget:
13093
13094 \snippet widget-mask/main.cpp 0
13095
13096 The label shown by this code is masked using the image it contains,
13097 giving the appearance that an irregularly-shaped image is being drawn
13098 directly onto the screen.
13099
13100 Masked widgets receive mouse events only on their visible
13101 portions.
13102
13103 \sa clearMask(), windowOpacity()
13104*/
13105void QWidget::setMask(const QBitmap &bitmap)
13106{
13107 setMask(QRegion(bitmap));
13108}
13109
13110/*!
13111 \fn void QWidget::clearMask()
13112
13113 Removes any mask set by setMask().
13114
13115 \sa setMask()
13116*/
13117void QWidget::clearMask()
13118{
13119 Q_D(QWidget);
13120 if (!d->extra || !d->extra->hasMask)
13121 return;
13122 setMask(QRegion());
13123}
13124
13125void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent)
13126{
13127 Q_ASSERT(widgetAsObject->isWidgetType());
13128 Q_ASSERT(!newParent || newParent->isWidgetType());
13129 QWidget *widget = static_cast<QWidget*>(widgetAsObject);
13130 widget->setParent(static_cast<QWidget*>(newParent));
13131}
13132
13133std::string QWidgetPrivate::flagsForDumping() const
13134{
13135 Q_Q(const QWidget);
13136 std::string flags = QObjectPrivate::flagsForDumping();
13137 if (QApplication::focusWidget() == q)
13138 flags += 'F';
13139 if (q->isVisible()) {
13140 std::stringstream s;
13141 s << '<'
13142 << q->width() << 'x' << q->height()
13143 << std::showpos << q->x() << q->y()
13144 << '>';
13145 flags += s.str();
13146 } else {
13147 flags += 'I';
13148 }
13149 return flags;
13150}
13151
13152void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
13153{
13154#if QT_CONFIG(xcb)
13155 Q_Q(QWidget);
13156
13157 if (!q->windowHandle())
13158 return;
13159
13160 QXcbWindow::WindowTypes wmWindowType = QXcbWindow::None;
13161 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
13162 wmWindowType |= QXcbWindow::Desktop;
13163 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
13164 wmWindowType |= QXcbWindow::Dock;
13165 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
13166 wmWindowType |= QXcbWindow::Toolbar;
13167 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
13168 wmWindowType |= QXcbWindow::Menu;
13169 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
13170 wmWindowType |= QXcbWindow::Utility;
13171 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
13172 wmWindowType |= QXcbWindow::Splash;
13173 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
13174 wmWindowType |= QXcbWindow::Dialog;
13175 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
13176 wmWindowType |= QXcbWindow::DropDownMenu;
13177 if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
13178 wmWindowType |= QXcbWindow::PopupMenu;
13179 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
13180 wmWindowType |= QXcbWindow::Tooltip;
13181 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
13182 wmWindowType |= QXcbWindow::Notification;
13183 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
13184 wmWindowType |= QXcbWindow::Combo;
13185 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
13186 wmWindowType |= QXcbWindow::Dnd;
13187
13188 if (wmWindowType == QXcbWindow::None && skipIfMissing)
13189 return;
13190
13191 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(q->windowHandle()->handle()))
13192 xcbWindow->setWindowType(wmWindowType);
13193#else
13194 Q_UNUSED(skipIfMissing);
13195#endif
13196}
13197
13198/*!
13199 \internal
13200 \return \c true, if a child with \param policy exists and isn't a child of \param excludeChildrenOf.
13201 Return false otherwise.
13202 */
13203bool QWidgetPrivate::hasChildWithFocusPolicy(Qt::FocusPolicy policy, const QWidget *excludeChildrenOf) const
13204{
13205 Q_Q(const QWidget);
13206 const QWidgetList &children = q->findChildren<QWidget *>(Qt::FindChildrenRecursively);
13207 for (const auto *child : children) {
13208 if (child->focusPolicy() == policy && child->isEnabled()
13209 && (!excludeChildrenOf || !excludeChildrenOf->isAncestorOf(child))) {
13210 return true;
13211 }
13212 }
13213 return false;
13214}
13215
13216#ifndef QT_NO_DEBUG_STREAM
13217
13218namespace {
13219QDebug operator<<(QDebug debug, const WidgetAttributes &attributes)
13220{
13221 const QDebugStateSaver saver(debug);
13222 debug.nospace();
13223 debug << '[';
13224 if (const QWidget *widget = attributes.widget) {
13225 const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
13226 const QMetaEnum me = qtMo->enumerator(qtMo->indexOfEnumerator("WidgetAttribute"));
13227 int count = 0;
13228 for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
13229 if (widget->testAttribute(static_cast<Qt::WidgetAttribute>(a))) {
13230 if (count++)
13231 debug << ',';
13232 debug << me.valueToKey(a);
13233 }
13234 }
13235 }
13236 debug << ']';
13237 return debug;
13238}
13239}
13240
13241QDebug operator<<(QDebug debug, const QWidget *widget)
13242{
13243 const QDebugStateSaver saver(debug);
13244 debug.nospace();
13245 if (widget) {
13246 debug << widget->metaObject()->className() << '(' << (const void *)widget;
13247 if (!widget->objectName().isEmpty())
13248 debug << ", name=" << widget->objectName();
13249 if (debug.verbosity() > 2) {
13250 const QRect geometry = widget->geometry();
13251 const QRect frameGeometry = widget->frameGeometry();
13252 if (widget->isVisible())
13253 debug << ", visible";
13254 if (!widget->isEnabled())
13255 debug << ", disabled";
13256 debug << ", states=" << widget->windowState()
13257 << ", type=" << widget->windowType() << ", flags=" << widget->windowFlags();
13258 debug << ", attributes=" << WidgetAttributes{widget};
13259 if (widget->isWindow())
13260 debug << ", window";
13261 debug << ", " << geometry.width() << 'x' << geometry.height()
13262 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
13263 if (frameGeometry != geometry) {
13264 const QMargins margins(geometry.x() - frameGeometry.x(),
13265 geometry.y() - frameGeometry.y(),
13266 frameGeometry.right() - geometry.right(),
13267 frameGeometry.bottom() - geometry.bottom());
13268 debug << ", margins=" << margins;
13269 }
13270 debug << ", devicePixelRatio=" << widget->devicePixelRatio();
13271 if (const WId wid = widget->internalWinId())
13272 debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
13273 }
13274 debug << ')';
13275 } else {
13276 debug << "QWidget(0x0)";
13277 }
13278 return debug;
13279}
13280#endif // !QT_NO_DEBUG_STREAM
13281
13282
13283// *************************** Focus abstraction ************************************
13284
13285#define FOCUS_NEXT(w) w->d_func()->focus_next
13286#define FOCUS_PREV(w) w->d_func()->focus_prev
13287
13288/*!
13289 \internal
13290 \return next or previous element in the focus chain, depending on
13291 \param direction, irrespective of focus proxies or widgets with Qt::NoFocus.
13292 */
13293QWidget *QWidgetPrivate::nextPrevElementInFocusChain(FocusDirection direction) const
13294{
13295 Q_Q(const QWidget);
13296 return direction == FocusDirection::Next ? FOCUS_NEXT(q) : FOCUS_PREV(q);
13297}
13298
13299/*!
13300 \internal
13301 Removes a widget from the focus chain, respecting the flags set in \param rules.
13302 \list
13303 \li EnsureFocusOut: If the widget has input focus, transfer focus to the next or previous widget
13304 in the focus chain, depending on \param direction.
13305 \li RemoveInconsistent: Remove the widget, even if its focus chain is inconsistent.
13306 \li AssertConsistency: qFatal, if the focus chain is inconsistent. This is used in the QWidget destructor.
13307 \endlist
13308 \return \c true if the widget has been removed, otherwise \c false.
13309 */
13310bool QWidgetPrivate::removeFromFocusChain(FocusChainRemovalRules rules, FocusDirection direction)
13311{
13312 Q_Q(QWidget);
13313 if (!isFocusChainConsistent()) {
13314#ifdef QT_DEBUG
13315 if (rules.testFlag(FocusChainRemovalRule::AssertConsistency))
13316 qFatal() << q << "has inconsistent focus chain.";
13317#endif
13318 qCDebug(lcWidgetFocus) << q << "wasn't removed, because of inconsistent focus chain.";
13319 return false;
13320 }
13321
13322 if (!isInFocusChain()) {
13323 qCDebug(lcWidgetFocus) << q << "wasn't removed, because it is not part of a focus chain.";
13324 return false;
13325 }
13326
13327 if (rules.testFlag(FocusChainRemovalRule::EnsureFocusOut))
13328 q->focusNextPrevChild(direction == FocusDirection::Next);
13329
13332 initFocusChain();
13333 qCDebug(lcWidgetFocus) << q << "removed from focus chain.";
13334 return true;
13335}
13336
13337/*!
13338 \internal
13339 Initialises the focus chain by making the widget point to itself.
13340 */
13341void QWidgetPrivate::initFocusChain()
13342{
13343 Q_Q(QWidget);
13344 qCDebug(lcWidgetFocus) << "Initializing focus chain of" << q;
13345 FOCUS_PREV(q) = q;
13346 FOCUS_NEXT(q) = q;
13347}
13348
13349/*!
13350 \internal
13351 Reads QWidget children, which are not part of a focus chain yet.
13352 Inserts them into the focus chain before or after the widget,
13353 depending on \param direction and in the order of their creation.
13354 This is used, when QWidget::setParent() causes a widget to change toplevel windows.
13355 */
13356void QWidgetPrivate::reparentFocusChildren(FocusDirection direction)
13357{
13358 Q_Q(QWidget);
13359
13360 // separate the focus chain into new (children of myself) and old (the rest)
13361 QWidget *firstOld = nullptr;
13362 QWidget *lastOld = nullptr; // last in the old list
13363 QWidget *lastNew = q; // last in the new list
13364 bool prevWasNew = true;
13365 QWidget *widget = nextPrevElementInFocusChain(direction);
13366
13367 // For efficiency, do not maintain the list invariant inside the loop.
13368 // Append items to the relevant list, and we optimize by not changing pointers,
13369 // when subsequent items are going into the same list.
13370 while (widget != q) {
13371 bool currentIsNew = q->isAncestorOf(widget);
13372 if (currentIsNew) {
13373 if (!prevWasNew) {
13374 // previous was old => append to new list
13375 FOCUS_NEXT(lastNew) = widget;
13376 FOCUS_PREV(widget) = lastNew;
13377 }
13378 lastNew = widget;
13379 } else {
13380 if (prevWasNew) {
13381 // prev was new => append to old list, if it exists
13382 if (lastOld) {
13383 FOCUS_NEXT(lastOld) = widget;
13384 FOCUS_PREV(widget) = lastOld;
13385 } else {
13386 // start the old list
13387 firstOld = widget;
13388 }
13389 }
13390 lastOld = widget;
13391 }
13392 widget = widget->d_func()->nextPrevElementInFocusChain(direction);
13393 prevWasNew = currentIsNew;
13394 }
13395
13396 // repair old list:
13397 if (firstOld) {
13398 FOCUS_NEXT(lastOld) = firstOld;
13399 FOCUS_PREV(firstOld) = lastOld;
13400 }
13401
13402 if (!q->isWindow()) {
13403 QWidget *topLevel = q->window();
13404 // insert new chain into toplevel's chain
13405 QWidget *prev = FOCUS_PREV(topLevel);
13406 FOCUS_PREV(topLevel) = lastNew;
13407 FOCUS_NEXT(prev) = q;
13408 FOCUS_PREV(q) = prev;
13409 FOCUS_NEXT(lastNew) = topLevel;
13410 } else {
13411 // repair new list
13412 FOCUS_NEXT(lastNew) = q;
13413 FOCUS_PREV(q) = lastNew;
13414 }
13415}
13416
13417/*!
13418 \internal
13419 Inserts a widget into the focus chain before or after \param position, depending on
13420 \param direction.
13421 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13422 */
13423bool QWidgetPrivate::insertIntoFocusChain(FocusDirection direction, QWidget *position)
13424{
13425 Q_Q(QWidget);
13426 Q_ASSERT(position);
13427 QWidget *next = FOCUS_NEXT(q);
13428 QWidget *previous = FOCUS_PREV(q);
13429
13430 switch (direction) {
13431 case FocusDirection::Next:
13432 if (previous == position) {
13433 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already before" << position;
13434 return false;
13435 }
13436
13437 removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
13438
13439 FOCUS_NEXT(q) = FOCUS_NEXT(position);
13440 FOCUS_PREV(FOCUS_NEXT(position)) = q;
13441 FOCUS_NEXT(position) = q;
13442 FOCUS_PREV(q) = position;
13443 qCDebug(lcWidgetFocus) << q << "inserted after" << position;
13444 break;
13445
13446 case FocusDirection::Previous:
13447 if (next == position) {
13448 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already after" << position;
13449 return false;
13450 }
13451
13452 removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
13453
13454 FOCUS_PREV(q) = FOCUS_PREV(position);
13455 FOCUS_NEXT(FOCUS_PREV(position)) = q;
13456 FOCUS_PREV(position) = q;
13457 FOCUS_NEXT(q) = position;
13458 qCDebug(lcWidgetFocus) << q << "inserted before" << position;
13459 break;
13460 }
13461
13462 Q_ASSERT(isFocusChainConsistent());
13463 return true;
13464}
13465
13466/*!
13467 \internal
13468 Convenience override to insert a QWidgetList \param toBeInserted into the focus chain
13469 before or after \param position, depending on \param direction.
13470 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13471 \note
13472 \param toBeInserted must be a consistent focus chain.
13473 */
13474bool QWidgetPrivate::insertIntoFocusChain(const QWidgetList &toBeInserted,
13475 FocusDirection direction, QWidget *position)
13476{
13477 if (toBeInserted.isEmpty()) {
13478 qCDebug(lcWidgetFocus) << "No-op insertion of an empty list";
13479 return false;
13480 }
13481
13482 Q_ASSERT_X(!toBeInserted.contains(position),
13483 Q_FUNC_INFO,
13484 "Coding error: toBeInserted contains position");
13485
13486 QWidget *first = toBeInserted.constFirst();
13487 QWidget *last = toBeInserted.constLast();
13488
13489 // Call QWidget override to log accordingly
13490 if (toBeInserted.count() == 1)
13491 return first->d_func()->insertIntoFocusChain(direction, position);
13492
13493 Q_ASSERT(first != last);
13494 switch (direction) {
13495 case FocusDirection::Previous:
13496 if (FOCUS_PREV(position) == last) {
13497 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already before"
13498 << position;
13499 return false;
13500 }
13501 FOCUS_NEXT(FOCUS_PREV(position)) = first;
13502 FOCUS_PREV(first) = FOCUS_PREV(position);
13503 FOCUS_NEXT(last) = position;
13504 FOCUS_PREV(position) = last;
13505 qCDebug(lcWidgetFocus) << toBeInserted << "inserted before" << position;
13506 break;
13507 case FocusDirection::Next:
13508 if (FOCUS_PREV(position) == last) {
13509 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already after"
13510 << position;
13511 return false;
13512 }
13513 FOCUS_PREV(FOCUS_NEXT(position)) = last;
13514 FOCUS_NEXT(last) = FOCUS_NEXT(position);
13515 FOCUS_PREV(first) = position;
13516 FOCUS_NEXT(position) = first;
13517 qCDebug(lcWidgetFocus) << toBeInserted << "inserted after" << position;
13518 break;
13519 }
13520
13521 Q_ASSERT(position->d_func()->isFocusChainConsistent());
13522 return true;
13523}
13524
13525/*!
13526 \internal
13527 \return a QWidgetList, representing the part of the focus chain,
13528 starting with \param from and ending with \param to, in \param direction.
13529 */
13530QWidgetList focusPath(QWidget *from, QWidget *to, QWidgetPrivate::FocusDirection direction)
13531{
13532 QWidgetList path({from});
13533 if (from == to)
13534 return path;
13535
13536 QWidget *current = from;
13537 do {
13538 switch (direction) {
13539 case QWidgetPrivate::FocusDirection::Previous:
13540 current = current->previousInFocusChain();
13541 break;
13542 case QWidgetPrivate::FocusDirection::Next:
13543 current = current->nextInFocusChain();
13544 break;
13545 }
13546 if (path.contains(current))
13547 return QWidgetList();
13548 path << current;
13549 } while (current != to);
13550
13551 return path;
13552}
13553
13554/*!
13555 \internal
13556 Removes the part from the focus chain starting with \param from and ending with \param to,
13557 in \param direction.
13558 \return removed part as a QWidgetList.
13559 */
13560QWidgetList QWidgetPrivate::takeFromFocusChain(QWidget *from,
13561 QWidget *to,
13562 FocusDirection direction)
13563{
13564 // Check if there is a path from->to in direction
13565 const QWidgetList path = focusPath(from, to , direction);
13566 if (path.isEmpty()) {
13567 qCDebug(lcWidgetFocus) << "No-op removal. Focus chain from" << from << "doesn't lead to " << to;
13568 return QWidgetList();
13569 }
13570
13571 QWidget *first = path.constFirst();
13572 QWidget *last = path.constLast();
13573 if (first == last) {
13574 first->d_func()->removeFromFocusChain();
13575 return QWidgetList({first});
13576 }
13577
13578 FOCUS_NEXT(FOCUS_PREV(first)) = FOCUS_NEXT(last);
13579 FOCUS_PREV(FOCUS_NEXT(last)) = FOCUS_PREV(first);
13580 FOCUS_PREV(first) = last;
13581 FOCUS_NEXT(last) = first;
13582 qCDebug(lcWidgetFocus) << path << "removed from focus chain";
13583 return path;
13584}
13585
13586/*!
13587 \internal
13588 \return The last focus child of the widget, traversing the focus chain no further than
13589 \param noFurtherThan.
13590 */
13591QWidget *QWidgetPrivate::determineLastFocusChild(QWidget *noFurtherThan)
13592{
13593 Q_Q(QWidget);
13594 // Since we need to repeat the same logic for both 'first' and 'second', we add a function
13595 // that determines the last focus child for a widget, taking proxies and compound widgets into
13596 // account. If the target is not a compound widget (it doesn't have a focus proxy that points
13597 // to a child), 'lastFocusChild' will be set to the target itself.
13598 QWidget *lastFocusChild = q;
13599
13600 QWidget *focusProxy = deepestFocusProxy();
13601 if (!focusProxy) {
13602 // QTBUG-81097: Another case is possible here. We can have a child
13603 // widget, that sets its focusProxy() to the parent (target).
13604 // An example of such widget is a QLineEdit, nested into
13605 // a QAbstractSpinBox. In this case such widget should be considered
13606 // the last focus child.
13607 for (auto *object : std::as_const(q->children())) {
13608 QWidget *w = qobject_cast<QWidget *>(object);
13609 if (w && w->focusProxy() == q) {
13610 lastFocusChild = w;
13611 break;
13612 }
13613 }
13614 } else if (q->isAncestorOf(focusProxy)) {
13615 lastFocusChild = focusProxy;
13616 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
13617 focusNext != focusProxy && q->isAncestorOf(focusNext)
13618 && focusNext->window() == focusProxy->window();
13619 focusNext = focusNext->nextInFocusChain()) {
13620 if (focusNext == noFurtherThan)
13621 break;
13622 if (focusNext->focusPolicy() != Qt::NoFocus)
13623 lastFocusChild = focusNext;
13624 }
13625 }
13626 return lastFocusChild;
13627};
13628
13629/*!
13630 \internal
13631 \return \c true, if the widget is part of a focus chain and \c false otherwise.
13632 A widget is considered to be part of a focus chain, neither FOCUS_NEXT, nor FOCUS_PREV
13633 are pointing to the widget itself.
13634
13635 \note
13636 This method doesn't check the consistency of the focus chain.
13637 If multiple widgets have been removed from the focus chain by takeFromFocusChain(),
13638 isInFocusChain() will return \c true for all of those widgets, even if they represent
13639 an inconsistent focus chain.
13640 */
13641bool QWidgetPrivate::isInFocusChain() const
13642{
13643 Q_Q(const QWidget);
13644 return !(FOCUS_NEXT(q) == q && FOCUS_PREV(q) == q);
13645}
13646
13647/*!
13648 \internal
13649 A focus chain is consistent, when it is circular: Following the chain in either direction
13650 has to return to the beginning. This is why a newly constructed widget points to itself,
13651 when the focus chain has been initialized. A newly constructed widget is considered to have
13652 a consistent focus chain, while not being part of a focus chain.
13653
13654 The method always returns \c true, when the logging category "qt.widgets.focus" is disabled.
13655 When it is enabled, the method returns \c true early, if a widget is pointing to itself.
13656 It returns \c false, if one of the following is detected:
13657 \list
13658 \li nullptr found in a previous/next pointer.
13659 \li broken chain: widget A is B's previous, but B isn't A's next.
13660 \li chain isn't closed: starting at A doesn't lead back to A.
13661 \endlist
13662 It return \c true, if none of the above is observed.
13663
13664 \note
13665 The focus chain is checked only in forward direction.
13666 This is sufficient, because the check for a broken chain asserts consistent paths
13667 in both directions.
13668 */
13669bool QWidgetPrivate::isFocusChainConsistent() const
13670{
13671 Q_Q(const QWidget);
13672 const bool skip = !lcWidgetFocus().isDebugEnabled();
13673 if (skip)
13674 return true;
13675
13676 if (!isInFocusChain())
13677 return true;
13678
13679 const QWidget *position = q;
13680
13681 for (int i = 0; i < QApplication::allWidgets().count(); ++i) {
13682 if (!FOCUS_PREV(position) || !FOCUS_NEXT(position)) {
13683 qCDebug(lcWidgetFocus) << "Nullptr found at:" << position
13684 << "Previous pointing to" << FOCUS_PREV(position)
13685 << "Next pointing to" << FOCUS_NEXT(position);
13686 return false;
13687 }
13688 if (!(FOCUS_PREV(FOCUS_NEXT(position)) == position
13689 && FOCUS_NEXT(FOCUS_PREV(position)) == position)) {
13690 qCDebug(lcWidgetFocus) << "Inconsistent focus chain at:" << position
13691 << "Previous pointing to" << FOCUS_PREV(FOCUS_NEXT(position))
13692 << "Next pointing to" << FOCUS_NEXT(FOCUS_PREV(position));
13693 return false;
13694 }
13695 position = FOCUS_NEXT(position);
13696 if (position == q)
13697 return true;
13698
13699 }
13700
13701 qCDebug(lcWidgetFocus) << "Focus chain leading from" << q << "to" << position << "is not closed.";
13702 return false;
13703}
13704
13705#undef FOCUS_NEXT
13706#undef FOCUS_PREV
13707
13708
13709QT_END_NAMESPACE
13710
13711#include "moc_qwidget.cpp"
13712#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:5038
#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:5032
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:6016
static void sendResizeEvents(QWidget *target)
Definition qwidget.cpp:5212
static void applyCursor(QWidget *w, const QCursor &c)
Definition qwidget.cpp:5026
#define FOCUS_PREV(w)
static bool isEmbedded(const QWindow *w)
Definition qwidget.cpp:6660
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