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, this event instead of a second
428 mouse press 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 fit into \a availableGeometry, with the height reduced by
7428 \a frameHeight.
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, corrected for frame height
7446 if (availableGeometry.height() <= height)
7447 restoredGeometry->setHeight(availableGeometry.height() - frameHeight);
7448 if (availableGeometry.width() <= restoredGeometry->width())
7449 restoredGeometry->setWidth(availableGeometry.width());
7450
7451 // Step 2: Move if necessary:
7452 // Construct a rectangle from restored Geometry adjusted by frameHeight
7453 const QRect restored = restoredGeometry->adjusted(0, -frameHeight, 0, 0);
7454
7455 // Return if restoredGeometry (including frame) fits into screen
7456 if (availableGeometry.contains(restored))
7457 return;
7458
7459 // (size is correct, but at least one edge is off screen)
7460
7461 // Top out of bounds => move down
7462 if (restored.top() < availableGeometry.top()) {
7463 restoredGeometry->moveTop(availableGeometry.top() + frameHeight);
7464 } else if (restored.bottom() > availableGeometry.bottom()) {
7465 // Bottom out of bounds => move up
7466 restoredGeometry->moveBottom(availableGeometry.bottom());
7467 }
7468
7469 // Left edge out of bounds => move right
7470 if (restored.left() < availableGeometry.left()) {
7471 restoredGeometry->moveLeft(availableGeometry.left());
7472 } else if (restored.right() > availableGeometry.right()) {
7473 // Right edge out of bounds => move left
7474 restoredGeometry->moveRight(availableGeometry.right());
7475 }
7476}
7477
7478/*!
7479 \since 4.2
7480
7481 Restores the geometry and state of top-level widgets stored in the
7482 byte array \a geometry. Returns \c true on success; otherwise
7483 returns \c false.
7484
7485 If the restored geometry is off-screen, it will be modified to be
7486 inside the available screen geometry.
7487
7488 To restore geometry saved using QSettings, you can use code like
7489 this:
7490
7491 \snippet code/src_gui_kernel_qwidget.cpp 12
7492
7493 See the \l{Window Geometry} documentation for an overview of geometry
7494 issues with windows.
7495
7496 Use QMainWindow::restoreState() to restore the geometry and the
7497 state of toolbars and dock widgets.
7498
7499 \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
7500*/
7501bool QWidget::restoreGeometry(const QByteArray &geometry)
7502{
7503 if (geometry.size() < 4)
7504 return false;
7505 QDataStream stream(geometry);
7506 stream.setVersion(QDataStream::Qt_4_0);
7507
7508 const quint32 magicNumber = 0x1D9D0CB;
7509 quint32 storedMagicNumber;
7510 stream >> storedMagicNumber;
7511 if (storedMagicNumber != magicNumber)
7512 return false;
7513
7514 const quint16 currentMajorVersion = 3;
7515 quint16 majorVersion = 0;
7516 quint16 minorVersion = 0;
7517
7518 stream >> majorVersion >> minorVersion;
7519
7520 if (majorVersion > currentMajorVersion)
7521 return false;
7522 // (Allow all minor versions.)
7523
7524 QRect restoredFrameGeometry;
7525 QRect restoredGeometry;
7526 QRect restoredNormalGeometry;
7527 qint32 restoredScreenNumber;
7528 quint8 maximized;
7529 quint8 fullScreen;
7530 qint32 restoredScreenWidth = 0;
7531
7532 stream >> restoredFrameGeometry // Only used for sanity checks in version 0
7533 >> restoredNormalGeometry
7534 >> restoredScreenNumber
7535 >> maximized
7536 >> fullScreen;
7537
7538 if (majorVersion > 1)
7539 stream >> restoredScreenWidth;
7540 if (majorVersion > 2)
7541 stream >> restoredGeometry;
7542
7543 // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
7544
7545 if (restoredScreenNumber >= qMax(QGuiApplication::screens().size(), 1))
7546 restoredScreenNumber = 0;
7547 const QScreen *restoredScreen = QGuiApplication::screens().value(restoredScreenNumber, nullptr);
7548 const qreal screenWidthF = restoredScreen ? qreal(restoredScreen->geometry().width()) : 0;
7549 // Sanity check bailing out when large variations of screen sizes occur due to
7550 // high DPI scaling or different levels of DPI awareness.
7551 if (restoredScreenWidth) {
7552 const qreal factor = qreal(restoredScreenWidth) / screenWidthF;
7553 if (factor < 0.8 || factor > 1.25)
7554 return false;
7555 } else {
7556 // Saved by Qt 5.3 and earlier, try to prevent too large windows
7557 // unless the size will be adapted by maximized or fullscreen.
7558 if (!maximized && !fullScreen && qreal(restoredFrameGeometry.width()) / screenWidthF > 1.5)
7559 return false;
7560 }
7561
7562 const int frameHeight = QApplication::style()
7563 ? QApplication::style()->pixelMetric(QStyle::PM_TitleBarHeight, nullptr, this)
7564 : 20;
7565
7566 if (!restoredNormalGeometry.isValid())
7567 restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
7568 if (!restoredNormalGeometry.isValid()) {
7569 // use the widget's adjustedSize if the sizeHint() doesn't help
7570 restoredNormalGeometry.setSize(restoredNormalGeometry
7571 .size()
7572 .expandedTo(d_func()->adjustedSize()));
7573 }
7574
7575 const QRect availableGeometry = restoredScreen ? restoredScreen->availableGeometry()
7576 : QRect();
7577
7578 // Modify the restored geometry if we are about to restore to coordinates
7579 // that would make the window "lost". This happens if:
7580 // - The restored geometry is completely or partly oustside the available geometry
7581 // - The title bar is outside the available geometry.
7582
7583 QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight);
7584 QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight);
7585
7586 if (maximized || fullScreen) {
7587 // set geometry before setting the window state to make
7588 // sure the window is maximized to the right screen.
7589 Qt::WindowStates ws = windowState();
7590#ifndef Q_OS_WIN
7591 setGeometry(restoredNormalGeometry);
7592#else
7593 if (ws & Qt::WindowFullScreen) {
7594 // Full screen is not a real window state on Windows.
7595 move(availableGeometry.topLeft());
7596 } else if (ws & Qt::WindowMaximized) {
7597 // Setting a geometry on an already maximized window causes this to be
7598 // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
7599 // Move the window in normal state if needed.
7600 if (restoredScreen != screen()) {
7601 setWindowState(Qt::WindowNoState);
7602 setGeometry(restoredNormalGeometry);
7603 }
7604 } else {
7605 setGeometry(restoredNormalGeometry);
7606 }
7607#endif // Q_OS_WIN
7608 if (maximized)
7609 ws |= Qt::WindowMaximized;
7610 if (fullScreen)
7611 ws |= Qt::WindowFullScreen;
7612 setWindowState(ws);
7613 d_func()->topData()->normalGeometry = restoredNormalGeometry;
7614 } else {
7615 setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
7616
7617 // FIXME: Why fall back to restoredNormalGeometry if majorVersion <= 2?
7618 if (majorVersion > 2)
7619 setGeometry(restoredGeometry);
7620 else
7621 setGeometry(restoredNormalGeometry);
7622 }
7623 return true;
7624}
7625
7626/*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
7627 \overload
7628
7629 This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
7630*/
7631
7632/*!
7633 Sets the margins around the contents of the widget to have the sizes
7634 \a left, \a top, \a right, and \a bottom. The margins are used by
7635 the layout system, and may be used by subclasses to specify the area
7636 to draw in (e.g. excluding the frame).
7637
7638 Changing the margins will trigger a resizeEvent().
7639
7640 \sa contentsRect(), contentsMargins()
7641*/
7642void QWidget::setContentsMargins(int left, int top, int right, int bottom)
7643{
7644 Q_D(QWidget);
7645 if (left == d->leftmargin && top == d->topmargin
7646 && right == d->rightmargin && bottom == d->bottommargin)
7647 return;
7648 d->leftmargin = left;
7649 d->topmargin = top;
7650 d->rightmargin = right;
7651 d->bottommargin = bottom;
7652
7653 d->updateContentsRect();
7654}
7655
7656/*!
7657 \overload
7658 \since 4.6
7659
7660 \brief The setContentsMargins function sets the margins around the
7661 widget's contents.
7662
7663 Sets the margins around the contents of the widget to have the
7664 sizes determined by \a margins. The margins are
7665 used by the layout system, and may be used by subclasses to
7666 specify the area to draw in (e.g. excluding the frame).
7667
7668 Changing the margins will trigger a resizeEvent().
7669
7670 \sa contentsRect(), contentsMargins()
7671*/
7672void QWidget::setContentsMargins(const QMargins &margins)
7673{
7674 setContentsMargins(margins.left(), margins.top(),
7675 margins.right(), margins.bottom());
7676}
7677
7678void QWidgetPrivate::updateContentsRect()
7679{
7680 Q_Q(QWidget);
7681
7682 if (layout)
7683 layout->update(); //force activate; will do updateGeometry
7684 else
7685 q->updateGeometry();
7686
7687 if (q->isVisible()) {
7688 q->update();
7689 QResizeEvent e(q->data->crect.size(), q->data->crect.size());
7690 QCoreApplication::sendEvent(q, &e);
7691 } else {
7692 q->setAttribute(Qt::WA_PendingResizeEvent, true);
7693 }
7694
7695 QEvent e(QEvent::ContentsRectChange);
7696 QCoreApplication::sendEvent(q, &e);
7697}
7698
7699/*!
7700 \since 4.6
7701
7702 \brief The contentsMargins function returns the widget's contents margins.
7703
7704 \sa setContentsMargins(), contentsRect()
7705 */
7706QMargins QWidget::contentsMargins() const
7707{
7708 Q_D(const QWidget);
7709 QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
7710 return testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea) ?
7711 userMargins | d->safeAreaMargins() : userMargins;
7712}
7713
7714/*!
7715 Returns the area inside the widget's margins.
7716
7717 \sa setContentsMargins(), contentsMargins()
7718*/
7719QRect QWidget::contentsRect() const
7720{
7721 return rect() - contentsMargins();
7722}
7723
7724QMargins QWidgetPrivate::safeAreaMargins() const
7725{
7726 Q_Q(const QWidget);
7727
7728#if QT_CONFIG(graphicsview)
7729 // Don't report margins for proxied widgets, as the logic
7730 // below doesn't handle that case (yet).
7731 if (nearestGraphicsProxyWidget(q))
7732 return QMargins();
7733#endif
7734
7735 QWidget *nativeWidget = q->window();
7736 if (!nativeWidget->windowHandle())
7737 return QMargins();
7738
7739 QMargins safeAreaMargins = nativeWidget->windowHandle()->safeAreaMargins();
7740
7741 if (!q->isWindow()) {
7742 // In theory the native parent widget already has a contents rect reflecting
7743 // the safe area of that widget, but we can't be sure that the widget or child
7744 // widgets of that widget have respected the contents rect when setting their
7745 // geometry, so we need to manually compute the safe area.
7746
7747 // Unless the native widget doesn't have any margins, in which case there's
7748 // nothing for us to compute.
7749 if (safeAreaMargins.isNull())
7750 return QMargins();
7751
7752 // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
7753 // set, and the widget respects the safe area, then we know that the layout has already
7754 // taken care of placing us inside the safe area, by taking the contents rect of its
7755 // parent widget into account.
7756 const QWidget *assumedSafeWidget = nullptr;
7757 for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
7758 QWidget *parentWidget = w->parentWidget();
7759 if (!parentWidget->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
7760 continue; // Layout can't help us
7761
7762 if (parentWidget->testAttribute(Qt::WA_LayoutOnEntireRect))
7763 continue; // Layout not going to help us
7764
7765 QLayout *layout = parentWidget->layout();
7766 if (!layout)
7767 continue;
7768
7769 if (layout->geometry().isNull())
7770 continue; // Layout hasn't been activated yet
7771
7772 if (layout->indexOf(w) < 0)
7773 continue; // Widget is not in layout
7774
7775 assumedSafeWidget = w;
7776 break;
7777 }
7778
7779#if !defined(QT_DEBUG)
7780 if (assumedSafeWidget) {
7781 // We found a layout that we assume will take care of keeping us within the safe area
7782 // For debug builds we still map the safe area using the fallback logic, so that we
7783 // can detect any misbehaving layouts.
7784 return QMargins();
7785 }
7786#endif
7787
7788 // In all other cases we need to map the safe area of the native parent to the widget.
7789 // This depends on the widget being positioned and sized already, which means the initial
7790 // layout will be wrong, but the layout will then adjust itself.
7791 QPoint topLeftMargins = q->mapFrom(nativeWidget, QPoint(safeAreaMargins.left(), safeAreaMargins.top()));
7792 QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect();
7793 QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(nativeWidget,
7794 nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom()));
7795
7796 // Margins should never be negative
7797 safeAreaMargins = QMargins(qMax(0, topLeftMargins.x()), qMax(0, topLeftMargins.y()),
7798 qMax(0, bottomRightMargins.x()), qMax(0, bottomRightMargins.y()));
7799
7800 if (!safeAreaMargins.isNull() && assumedSafeWidget) {
7801 QLayout *layout = assumedSafeWidget->parentWidget()->layout();
7802 qWarning() << layout << "is laying out" << assumedSafeWidget
7803 << "outside of the contents rect of" << layout->parentWidget();
7804 return QMargins(); // Return empty margin to visually highlight the error
7805 }
7806 }
7807
7808 return safeAreaMargins;
7809}
7810
7811/*!
7812 \fn void QWidget::customContextMenuRequested(const QPoint &pos)
7813
7814 This signal is emitted when the widget's \l contextMenuPolicy is
7815 Qt::CustomContextMenu, and the user has requested a context menu on
7816 the widget. The position \a pos is the position of the context menu
7817 event that the widget receives. Normally this is in widget
7818 coordinates. The exception to this rule is QAbstractScrollArea and
7819 its subclasses that map the context menu event to coordinates of the
7820 \l{QAbstractScrollArea::viewport()}{viewport()}.
7821
7822
7823 \sa mapToGlobal(), QMenu, contextMenuPolicy
7824*/
7825
7826
7827/*!
7828 \property QWidget::contextMenuPolicy
7829 \brief how the widget shows a context menu
7830
7831 The default value of this property is Qt::DefaultContextMenu,
7832 which means the contextMenuEvent() handler is called. Other values
7833 are Qt::NoContextMenu, Qt::PreventContextMenu,
7834 Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
7835 Qt::CustomContextMenu, the signal customContextMenuRequested() is
7836 emitted.
7837
7838 \sa contextMenuEvent(), customContextMenuRequested(), actions()
7839*/
7840
7841Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
7842{
7843 return (Qt::ContextMenuPolicy)data->context_menu_policy;
7844}
7845
7846void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
7847{
7848 data->context_menu_policy = (uint) policy;
7849}
7850
7851/*!
7852 \property QWidget::focusPolicy
7853 \brief the way the widget accepts keyboard focus
7854
7855 The policy is Qt::TabFocus if the widget accepts keyboard
7856 focus by tabbing, Qt::ClickFocus if the widget accepts
7857 focus by clicking, Qt::StrongFocus if it accepts both, and
7858 Qt::NoFocus (the default) if it does not accept focus at
7859 all.
7860
7861 You must enable keyboard focus for a widget if it processes
7862 keyboard events. This is normally done from the widget's
7863 constructor. For instance, the QLineEdit constructor calls
7864 setFocusPolicy(Qt::StrongFocus).
7865
7866 If the widget has a focus proxy, then the focus policy will
7867 be propagated to it.
7868
7869 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
7870*/
7871
7872
7873Qt::FocusPolicy QWidget::focusPolicy() const
7874{
7875 return (Qt::FocusPolicy)data->focus_policy;
7876}
7877
7878void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
7879{
7880 data->focus_policy = (uint) policy;
7881 Q_D(QWidget);
7882 if (d->extra && d->extra->focus_proxy)
7883 d->extra->focus_proxy->setFocusPolicy(policy);
7884}
7885
7886/*!
7887 \property QWidget::updatesEnabled
7888 \brief whether updates are enabled
7889
7890 An updates enabled widget receives paint events and has a system
7891 background; a disabled widget does not. This also implies that
7892 calling update() and repaint() has no effect if updates are
7893 disabled.
7894
7895 By default, this property is \c true.
7896
7897 setUpdatesEnabled() is normally used to disable updates for a
7898 short period of time, for instance to avoid screen flicker during
7899 large changes. In Qt, widgets normally do not generate screen
7900 flicker, but on X11 the server might erase regions on the screen
7901 when widgets get hidden before they can be replaced by other
7902 widgets. Disabling updates solves this.
7903
7904 Example:
7905 \snippet code/src_gui_kernel_qwidget.cpp 13
7906
7907 Disabling a widget implicitly disables all its children. Enabling a widget
7908 enables all child widgets \e except top-level widgets or those that
7909 have been explicitly disabled. Re-enabling updates implicitly calls
7910 update() on the widget.
7911
7912 \sa paintEvent()
7913*/
7914void QWidget::setUpdatesEnabled(bool enable)
7915{
7916 Q_D(QWidget);
7917 setAttribute(Qt::WA_ForceUpdatesDisabled, !enable);
7918 d->setUpdatesEnabled_helper(enable);
7919}
7920
7921/*!
7922 Shows the widget and its child widgets.
7923
7924 For child windows, this is equivalent to calling setVisible(true).
7925 Otherwise, it is equivalent to calling showFullScreen(), showMaximized(),
7926 or setVisible(true), depending on the platform's default behavior for the window flags.
7927
7928 \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
7929 showNormal(), isVisible(), windowFlags()
7930*/
7931void QWidget::show()
7932{
7933 // Note: We don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
7934
7935 if (!isWindow()) {
7936 setVisible(true);
7937 } else {
7938 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
7939 Qt::WindowState defaultState = platformIntegration->defaultWindowState(data->window_flags);
7940 if (defaultState == Qt::WindowFullScreen)
7941 showFullScreen();
7942 else if (defaultState == Qt::WindowMaximized)
7943 showMaximized();
7944 else
7945 setVisible(true);
7946 }
7947}
7948
7949/*! \internal
7950
7951 Makes the widget visible in the isVisible() meaning of the word.
7952 It is only called for toplevels or widgets with visible parents.
7953 */
7954void QWidgetPrivate::show_recursive()
7955{
7956 Q_Q(QWidget);
7957 // polish if necessary
7958
7959 if (!q->testAttribute(Qt::WA_WState_Created))
7960 createRecursively();
7961 q->ensurePolished();
7962
7963 if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
7964 q->parentWidget()->d_func()->layout->activate();
7965 // activate our layout before we and our children become visible
7966 if (layout)
7967 layout->activate();
7968
7969 show_helper();
7970}
7971
7972void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
7973{
7974 Q_Q(QWidget);
7975
7976 disableUpdates = disableUpdates && q->updatesEnabled();
7977 if (disableUpdates)
7978 q->setAttribute(Qt::WA_UpdatesDisabled);
7979
7980 if (q->testAttribute(Qt::WA_PendingMoveEvent)) {
7981 QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
7982 QCoreApplication::sendEvent(q, &e);
7983 q->setAttribute(Qt::WA_PendingMoveEvent, false);
7984 }
7985
7986 if (q->testAttribute(Qt::WA_PendingResizeEvent)) {
7987 QResizeEvent e(data.crect.size(), QSize());
7988 QCoreApplication::sendEvent(q, &e);
7989 q->setAttribute(Qt::WA_PendingResizeEvent, false);
7990 }
7991
7992 if (disableUpdates)
7993 q->setAttribute(Qt::WA_UpdatesDisabled, false);
7994
7995 if (!recursive)
7996 return;
7997
7998 for (int i = 0; i < children.size(); ++i) {
7999 if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
8000 child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
8001 }
8002}
8003
8004void QWidgetPrivate::activateChildLayoutsRecursively()
8005{
8006 sendPendingMoveAndResizeEvents(false, true);
8007
8008 for (int i = 0; i < children.size(); ++i) {
8009 QWidget *child = qobject_cast<QWidget *>(children.at(i));
8010 if (!child || child->isHidden() || child->isWindow())
8011 continue;
8012
8013 child->ensurePolished();
8014
8015 // Activate child's layout
8016 QWidgetPrivate *childPrivate = child->d_func();
8017 if (childPrivate->layout)
8018 childPrivate->layout->activate();
8019
8020 // Pretend we're visible.
8021 const bool wasVisible = child->isVisible();
8022 if (!wasVisible)
8023 child->setAttribute(Qt::WA_WState_Visible);
8024
8025 // Do the same for all my children.
8026 childPrivate->activateChildLayoutsRecursively();
8027
8028 // We're not cheating anymore.
8029 if (!wasVisible)
8030 child->setAttribute(Qt::WA_WState_Visible, false);
8031 }
8032}
8033
8034void QWidgetPrivate::show_helper()
8035{
8036 Q_Q(QWidget);
8037 data.in_show = true; // qws optimization
8038 // make sure we receive pending move and resize events
8039 sendPendingMoveAndResizeEvents();
8040
8041 // become visible before showing all children
8042 q->setAttribute(Qt::WA_WState_Visible);
8043
8044 // finally show all children recursively
8045 showChildren(false);
8046
8047
8048
8049 const bool isWindow = q->isWindow();
8050#if QT_CONFIG(graphicsview)
8051 bool isEmbedded = isWindow && q->graphicsProxyWidget() != nullptr;
8052#else
8053 bool isEmbedded = false;
8054#endif
8055
8056 // popup handling: new popups and tools need to be raised, and
8057 // existing popups must be closed. Also propagate the current
8058 // windows's KeyboardFocusChange status.
8059 if (isWindow && !isEmbedded) {
8060 if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
8061 q->raise();
8062 if (q->parentWidget() && q->parentWidget()->window()->testAttribute(Qt::WA_KeyboardFocusChange))
8063 q->setAttribute(Qt::WA_KeyboardFocusChange);
8064 } else {
8065 while (QApplication::activePopupWidget()) {
8066 if (!QApplication::activePopupWidget()->close())
8067 break;
8068 }
8069 }
8070 }
8071
8072 // Automatic embedding of child windows of widgets already embedded into
8073 // QGraphicsProxyWidget when they are shown the first time.
8074#if QT_CONFIG(graphicsview)
8075 if (isWindow) {
8076 if (!isEmbedded && !bypassGraphicsProxyWidget(q)) {
8077 QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(q->parentWidget());
8078 if (ancestorProxy) {
8079 isEmbedded = true;
8080 ancestorProxy->d_func()->embedSubWindow(q);
8081 }
8082 }
8083 }
8084#else
8085 Q_UNUSED(isEmbedded);
8086#endif
8087
8088 // send the show event before showing the window
8089 QShowEvent showEvent;
8090 QCoreApplication::sendEvent(q, &showEvent);
8091
8092 show_sys();
8093
8094 if (!isEmbedded && q->windowType() == Qt::Popup)
8095 qApp->d_func()->openPopup(q);
8096
8097#if QT_CONFIG(accessibility)
8098 if (q->windowType() != Qt::ToolTip) { // Tooltips are read aloud twice in MS narrator.
8099 QAccessibleEvent event(q, QAccessible::ObjectShow);
8100 QAccessible::updateAccessibility(&event);
8101 }
8102#endif
8103
8104 if (QApplicationPrivate::hidden_focus_widget == q) {
8105 QApplicationPrivate::hidden_focus_widget = nullptr;
8106 q->setFocus(Qt::OtherFocusReason);
8107 }
8108
8109 // Process events when showing a Qt::SplashScreen widget before the event loop
8110 // is spinnning; otherwise it might not show up on particular platforms.
8111 // This makes QSplashScreen behave the same on all platforms.
8112 if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
8113 QCoreApplication::processEvents();
8114
8115 data.in_show = false; // reset qws optimization
8116}
8117
8118void QWidgetPrivate::show_sys()
8119{
8120 Q_Q(QWidget);
8121
8122 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
8123
8124 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
8125 invalidateBackingStore(q->rect());
8126 q->setAttribute(Qt::WA_Mapped);
8127 // add our window the modal window list (native dialogs)
8128 if (window && q->isWindow()
8129#if QT_CONFIG(graphicsview)
8130 && (!extra || !extra->proxyWidget)
8131#endif
8132 && q->windowModality() != Qt::NonModal) {
8133 QGuiApplicationPrivate::showModalWindow(window);
8134 }
8135 return;
8136 }
8137
8138 if (renderToTexture && !q->isWindow())
8139 QCoreApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry()));
8140 else
8141 QCoreApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
8142
8143 if ((!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
8144 || q->testAttribute(Qt::WA_OutsideWSRange)) {
8145 return;
8146 }
8147
8148 if (window) {
8149 if (q->isWindow())
8150 fixPosIncludesFrame();
8151 QRect geomRect = q->geometry();
8152 if (!q->isWindow()) {
8153 QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint());
8154 geomRect.moveTopLeft(topLeftOfWindow);
8155 }
8156 const QRect windowRect = window->geometry();
8157 if (windowRect != geomRect) {
8158 if (q->testAttribute(Qt::WA_Moved)
8159 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowManagement))
8160 window->setGeometry(geomRect);
8161 else
8162 window->resize(geomRect.size());
8163 }
8164
8165#ifndef QT_NO_CURSOR
8166 qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
8167#endif
8168 invalidateBackingStore(q->rect());
8169 window->setNativeWindowVisibility(true);
8170 // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
8171 if (window->isTopLevel()) {
8172 const QPoint crectTopLeft = q->data->crect.topLeft();
8173 const QPoint windowTopLeft = window->geometry().topLeft();
8174 if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
8175 q->data->crect.moveTopLeft(windowTopLeft);
8176 }
8177 }
8178}
8179
8180/*!
8181 Hides the widget. This function is equivalent to
8182 setVisible(false).
8183
8184
8185 \note If you are working with QDialog or its subclasses and you invoke
8186 the show() function after this function, the dialog will be displayed in
8187 its original position.
8188
8189 \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
8190*/
8191void QWidget::hide()
8192{
8193 setVisible(false);
8194}
8195
8196/*!\internal
8197 */
8198void QWidgetPrivate::hide_helper()
8199{
8200 Q_Q(QWidget);
8201
8202 bool isEmbedded = false;
8203#if QT_CONFIG(graphicsview)
8204 isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(q) && nearestGraphicsProxyWidget(q->parentWidget()) != nullptr;
8205#else
8206 Q_UNUSED(isEmbedded);
8207#endif
8208
8209 if (!isEmbedded && (q->windowType() == Qt::Popup))
8210 qApp->d_func()->closePopup(q);
8211
8212 q->setAttribute(Qt::WA_Mapped, false);
8213 hide_sys();
8214
8215 bool wasVisible = q->testAttribute(Qt::WA_WState_Visible);
8216
8217 if (wasVisible) {
8218 q->setAttribute(Qt::WA_WState_Visible, false);
8219
8220 }
8221
8222 QHideEvent hideEvent;
8223 QCoreApplication::sendEvent(q, &hideEvent);
8224 hideChildren(false);
8225
8226 // next bit tries to move the focus if the focus widget is now
8227 // hidden.
8228 if (wasVisible) {
8229 qApp->d_func()->sendSyntheticEnterLeave(q);
8230 QWidget *fw = QApplication::focusWidget();
8231 while (fw && !fw->isWindow()) {
8232 if (fw == q) {
8233 q->focusNextPrevChild(true);
8234 break;
8235 }
8236 fw = fw->parentWidget();
8237 }
8238 }
8239
8240 if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
8241 repaintManager->removeDirtyWidget(q);
8242
8243#if QT_CONFIG(accessibility)
8244 if (wasVisible) {
8245 QAccessibleEvent event(q, QAccessible::ObjectHide);
8246 QAccessible::updateAccessibility(&event);
8247 }
8248#endif
8249}
8250
8251void QWidgetPrivate::hide_sys()
8252{
8253 Q_Q(QWidget);
8254
8255 auto window = qobject_cast<QWidgetWindow *>(windowHandle());
8256
8257 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
8258 q->setAttribute(Qt::WA_Mapped, false);
8259 // remove our window from the modal window list (native dialogs)
8260 if (window && q->isWindow()
8261#if QT_CONFIG(graphicsview)
8262 && (!extra || !extra->proxyWidget)
8263#endif
8264 && q->windowModality() != Qt::NonModal) {
8265 QGuiApplicationPrivate::hideModalWindow(window);
8266 }
8267 // do not return here, if window non-zero, we must hide it
8268 }
8269
8270 deactivateWidgetCleanup();
8271
8272 if (!q->isWindow()) {
8273 QWidget *p = q->parentWidget();
8274 if (p &&p->isVisible()) {
8275 if (renderToTexture)
8276 p->d_func()->invalidateBackingStore(q->geometry());
8277 else
8278 invalidateBackingStore(q->rect());
8279 }
8280 } else {
8281 invalidateBackingStore(q->rect());
8282 }
8283
8284 if (window)
8285 window->setNativeWindowVisibility(false);
8286}
8287
8288/*!
8289 \fn bool QWidget::isHidden() const
8290
8291 Returns \c true if the widget is hidden, otherwise returns \c false.
8292
8293 A hidden widget will only become visible when show() is called on
8294 it. It will not be automatically shown when the parent is shown.
8295
8296 To check visibility, use !isVisible() instead (notice the exclamation mark).
8297
8298 isHidden() implies !isVisible(), but a widget can be not visible
8299 and not hidden at the same time. This is the case for widgets that are children of
8300 widgets that are not visible.
8301
8302
8303 Widgets are hidden if:
8304 \list
8305 \li they were created as independent windows,
8306 \li they were created as children of visible widgets,
8307 \li hide() or setVisible(false) was called.
8308 \endlist
8309*/
8310
8311void QWidget::setVisible(bool visible)
8312{
8313 Q_D(QWidget);
8314 qCDebug(lcWidgetShowHide) << "Setting visibility of" << this
8315 << "with attributes" << WidgetAttributes{this}
8316 << "to" << visible << "via QWidget";
8317
8318 if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) == !visible)
8319 return;
8320
8321 if (d->dontSetExplicitShowHide) {
8322 d->dontSetExplicitShowHide = false;
8323 } else {
8324 // Remember that setVisible was called explicitly
8325 setAttribute(Qt::WA_WState_ExplicitShowHide);
8326 }
8327
8328 d->setVisible(visible);
8329}
8330
8331// This method is called from QWidgetWindow in response to QWindow::setVisible,
8332// and should match the semantics of QWindow::setVisible. QWidget::setVisible on
8333// the other hand keeps track of WA_WState_ExplicitShowHide in addition.
8334void QWidgetPrivate::setVisible(bool visible)
8335{
8336 Q_Q(QWidget);
8337 qCDebug(lcWidgetShowHide) << "Setting visibility of" << q
8338 << "with attributes" << WidgetAttributes{q}
8339 << "to" << visible << "via QWidgetPrivate";
8340
8341 if (visible) { // show
8342 // Designer uses a trick to make grabWidget work without showing
8343 if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
8344 && !q->parentWidget()->testAttribute(Qt::WA_WState_Created))
8345 q->parentWidget()->window()->d_func()->createRecursively();
8346
8347 //create toplevels but not children of non-visible parents
8348 QWidget *pw = q->parentWidget();
8349 if (!q->testAttribute(Qt::WA_WState_Created)
8350 && (q->isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
8351 q->create();
8352 }
8353
8354 bool wasResized = q->testAttribute(Qt::WA_Resized);
8355 Qt::WindowStates initialWindowState = q->windowState();
8356
8357 // polish if necessary
8358 q->ensurePolished();
8359
8360 // whether we need to inform the parent widget immediately
8361 bool needUpdateGeometry = !q->isWindow() && q->testAttribute(Qt::WA_WState_Hidden);
8362 // we are no longer hidden
8363 q->setAttribute(Qt::WA_WState_Hidden, false);
8364
8365 if (needUpdateGeometry)
8366 updateGeometry_helper(true);
8367
8368 // activate our layout before we and our children become visible
8369 if (layout)
8370 layout->activate();
8371
8372 if (!q->isWindow()) {
8373 QWidget *parent = q->parentWidget();
8374 while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
8375 parent->d_func()->layout->activate();
8376 if (parent->isWindow())
8377 break;
8378 parent = parent->parentWidget();
8379 }
8380 if (parent)
8381 parent->d_func()->setDirtyOpaqueRegion();
8382 }
8383
8384 // adjust size if necessary
8385 if (!wasResized
8386 && (q->isWindow() || !q->parentWidget()->d_func()->layout)) {
8387 if (q->isWindow()) {
8388 q->adjustSize();
8389 if (q->windowState() != initialWindowState)
8390 q->setWindowState(initialWindowState);
8391 } else {
8392 q->adjustSize();
8393 }
8394 q->setAttribute(Qt::WA_Resized, false);
8395 }
8396
8397 q->setAttribute(Qt::WA_KeyboardFocusChange, false);
8398
8399 if (q->isWindow() || q->parentWidget()->isVisible()) {
8400 show_helper();
8401
8402 qApp->d_func()->sendSyntheticEnterLeave(q);
8403 }
8404
8405 QEvent showToParentEvent(QEvent::ShowToParent);
8406 QCoreApplication::sendEvent(q, &showToParentEvent);
8407 } else { // hide
8408 if (QApplicationPrivate::hidden_focus_widget == q)
8409 QApplicationPrivate::hidden_focus_widget = nullptr;
8410
8411 // hw: The test on getOpaqueRegion() needs to be more intelligent
8412 // currently it doesn't work if the widget is hidden (the region will
8413 // be clipped). The real check should be testing the cached region
8414 // (and dirty flag) directly.
8415 if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty())
8416 q->parentWidget()->d_func()->setDirtyOpaqueRegion();
8417
8418 if (!q->testAttribute(Qt::WA_WState_Hidden)) {
8419 q->setAttribute(Qt::WA_WState_Hidden);
8420 hide_helper();
8421 }
8422
8423 // invalidate layout similar to updateGeometry()
8424 if (!q->isWindow() && q->parentWidget()) {
8425 if (q->parentWidget()->d_func()->layout)
8426 q->parentWidget()->d_func()->layout->invalidate();
8427 else if (q->parentWidget()->isVisible())
8428 QCoreApplication::postEvent(q->parentWidget(), new QEvent(QEvent::LayoutRequest));
8429 }
8430
8431 QEvent hideToParentEvent(QEvent::HideToParent);
8432 QCoreApplication::sendEvent(q, &hideToParentEvent);
8433 }
8434}
8435
8436/*!
8437 Convenience function, equivalent to setVisible(!\a hidden).
8438*/
8439void QWidget::setHidden(bool hidden)
8440{
8441 setVisible(!hidden);
8442}
8443
8444bool QWidgetPrivate::isExplicitlyHidden() const
8445{
8446 Q_Q(const QWidget);
8447 return q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
8448}
8449
8450void QWidgetPrivate::_q_showIfNotHidden()
8451{
8452 Q_Q(QWidget);
8453 if (!isExplicitlyHidden())
8454 q->setVisible(true);
8455}
8456
8457void QWidgetPrivate::showChildren(bool spontaneous)
8458{
8459 Q_Q(QWidget);
8460 qCDebug(lcWidgetShowHide) << "Showing children of" << q
8461 << "spontaneously" << spontaneous;
8462
8463 QList<QObject*> childList = children;
8464 for (int i = 0; i < childList.size(); ++i) {
8465 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8466 if (!widget)
8467 continue;
8468 qCDebug(lcWidgetShowHide) << "Considering" << widget
8469 << "with attributes" << WidgetAttributes{widget};
8470 if (widget->windowHandle() && !widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
8471 widget->setAttribute(Qt::WA_WState_Hidden, false);
8472 if (widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
8473 continue;
8474 if (spontaneous) {
8475 widget->setAttribute(Qt::WA_Mapped);
8476 widget->d_func()->showChildren(true);
8477 QShowEvent e;
8478 QApplication::sendSpontaneousEvent(widget, &e);
8479 } else {
8480 if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide)) {
8481 widget->d_func()->show_recursive();
8482 } else {
8483 // Call QWidget::setVisible() here, so that subclasses
8484 // that (wrongly) override setVisible to do initialization
8485 // will still be notified that they are made visible, but
8486 // do so without triggering ExplicitShowHide.
8487 widget->d_func()->dontSetExplicitShowHide = true;
8488 widget->setVisible(true);
8489 widget->d_func()->dontSetExplicitShowHide = false;
8490 }
8491 }
8492 }
8493}
8494
8495void QWidgetPrivate::hideChildren(bool spontaneous)
8496{
8497 Q_Q(QWidget);
8498 qCDebug(lcWidgetShowHide) << "Hiding children of" << q
8499 << "spontaneously" << spontaneous;
8500
8501 QList<QObject*> childList = children;
8502 for (int i = 0; i < childList.size(); ++i) {
8503 QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
8504 if (!widget)
8505 continue;
8506 qCDebug(lcWidgetShowHide) << "Considering" << widget
8507 << "with attributes" << WidgetAttributes{widget};
8508 if (widget->isWindow() || !widget->isVisible())
8509 continue;
8510
8511 if (spontaneous)
8512 widget->setAttribute(Qt::WA_Mapped, false);
8513 else
8514 widget->setAttribute(Qt::WA_WState_Visible, false);
8515 widget->d_func()->hideChildren(spontaneous);
8516 QHideEvent e;
8517 if (spontaneous) {
8518 QApplication::sendSpontaneousEvent(widget, &e);
8519 } else {
8520 QCoreApplication::sendEvent(widget, &e);
8521 if (widget->internalWinId()
8522 && widget->testAttribute(Qt::WA_DontCreateNativeAncestors)) {
8523 // hide_sys() on an ancestor won't have any affect on this
8524 // widget, so it needs an explicit hide_sys() of its own
8525 widget->d_func()->hide_sys();
8526 }
8527 }
8528 qApp->d_func()->sendSyntheticEnterLeave(widget);
8529#if QT_CONFIG(accessibility)
8530 if (!spontaneous) {
8531 QAccessibleEvent event(widget, QAccessible::ObjectHide);
8532 QAccessible::updateAccessibility(&event);
8533 }
8534#endif
8535 }
8536
8537 // If the window of this widget is not closed, then the leave event
8538 // will eventually handle the widget under mouse use case.
8539 // Otherwise, we need to explicitly handle it here.
8540 if (QWidget* widgetWindow = q->window();
8541 widgetWindow && widgetWindow->data->is_closing) {
8542 q->setAttribute(Qt::WA_UnderMouse, false);
8543 }
8544}
8545
8546/*!
8547 \internal
8548
8549 For windows, this is called from the QWidgetWindow::handleCloseEvent implementation,
8550 which QWidget::close indirectly calls by closing the QWindow. \a mode will be
8551 CloseWithEvent if QWidgetWindow::handleCloseEvent is called indirectly by
8552 QWindow::close, and CloseWithSpontaneousEvent if the close event originates from the
8553 system (i.e. the user clicked the close button in the title bar).
8554
8555 QDialog calls this method directly in its hide() implementation, which might be
8556 called from the QDialog::closeEvent override. \a mode will be set to CloseNoEvent
8557 to prevent recursion.
8558
8559 For non-windows, this is called directly by QWidget::close, and \a mode will be
8560 CloseWithEvent.
8561
8562 The function is also called by the QWidget destructor, with \a mode set to CloseNoEvent.
8563*/
8564bool QWidgetPrivate::handleClose(CloseMode mode)
8565{
8566 Q_Q(QWidget);
8567 qCDebug(lcWidgetShowHide) << "Handling close event for" << q;
8568
8569 if (data.is_closing)
8570 return true;
8571
8572 // We might not have initiated the close, so update the state now that we know
8573 data.is_closing = true;
8574
8575 QPointer<QWidget> that = q;
8576
8577 if (data.in_destructor)
8578 mode = CloseNoEvent;
8579
8580 if (mode != CloseNoEvent) {
8581 QCloseEvent e;
8582 if (mode == CloseWithSpontaneousEvent)
8583 QApplication::sendSpontaneousEvent(q, &e);
8584 else
8585 QCoreApplication::sendEvent(q, &e);
8586 if (!that.isNull() && !e.isAccepted()) {
8587 data.is_closing = false;
8588 return false;
8589 }
8590 }
8591
8592 // even for windows, make sure we deliver a hide event and that all children get hidden
8593 if (!that.isNull() && !q->isHidden())
8594 q->hide();
8595
8596 if (!that.isNull()) {
8597 data.is_closing = false;
8598 if (q->testAttribute(Qt::WA_DeleteOnClose)) {
8599 q->setAttribute(Qt::WA_DeleteOnClose, false);
8600 q->deleteLater();
8601 }
8602 }
8603 return true;
8604}
8605
8606
8607/*!
8608 Closes this widget. Returns \c true if the widget was closed;
8609 otherwise returns \c false.
8610
8611 First it sends the widget a QCloseEvent. The widget is
8612 \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
8613 the close event. If it \l{QEvent::ignore()}{ignores}
8614 the event, nothing happens. The default
8615 implementation of QWidget::closeEvent() accepts the close event.
8616
8617 If the widget has the Qt::WA_DeleteOnClose flag, the widget
8618 is also deleted. A close events is delivered to the widget no
8619 matter if the widget is visible or not.
8620
8621 The \l QGuiApplication::lastWindowClosed() signal is emitted when the
8622 last visible primary window (i.e. window with no parent) with the
8623 Qt::WA_QuitOnClose attribute set is closed. By default this
8624 attribute is set for all widgets except transient windows such as
8625 splash screens, tool windows, and popup menus.
8626
8627*/
8628
8629bool QWidget::close()
8630{
8631 return d_func()->close();
8632}
8633
8634bool QWidgetPrivate::close()
8635{
8636 // FIXME: We're not setting is_closing here, even though that would
8637 // make sense, as the code below will not end up in handleClose to
8638 // reset is_closing when there's a QWindow, but no QPlatformWindow,
8639 // and we can't assume close is synchronous so we can't reset it here.
8640
8641 // Close native widgets via QWindow::close() in order to run QWindow
8642 // close code. The QWidget-specific close code in handleClose() will
8643 // in this case be called from the Close event handler in QWidgetWindow.
8644 if (QWindow *widgetWindow = windowHandle()) {
8645 if (widgetWindow->isTopLevel())
8646 return widgetWindow->close();
8647 }
8648
8649 return handleClose(QWidgetPrivate::CloseWithEvent);
8650}
8651
8652/*!
8653 \property QWidget::visible
8654 \brief whether the widget is visible
8655
8656 Calling setVisible(true) or show() sets the widget to visible
8657 status if all its parent widgets up to the window are visible. If
8658 an ancestor is not visible, the widget won't become visible until
8659 all its ancestors are shown. If its size or position has changed,
8660 Qt guarantees that a widget gets move and resize events just
8661 before it is shown. If the widget has not been resized yet, Qt
8662 will adjust the widget's size to a useful default using
8663 adjustSize().
8664
8665 Calling setVisible(false) or hide() hides a widget explicitly. An
8666 explicitly hidden widget will never become visible, even if all
8667 its ancestors become visible, unless you show it.
8668
8669 A widget receives show and hide events when its visibility status
8670 changes. Between a hide and a show event, there is no need to
8671 waste CPU cycles preparing or displaying information to the user.
8672 A video application, for example, might simply stop generating new
8673 frames.
8674
8675 A widget that happens to be obscured by other windows on the
8676 screen is considered to be visible. The same applies to iconified
8677 windows and windows that exist on another virtual
8678 desktop (on platforms that support this concept). A widget
8679 receives spontaneous show and hide events when its mapping status
8680 is changed by the window system, e.g. a spontaneous hide event
8681 when the user minimizes the window, and a spontaneous show event
8682 when the window is restored again.
8683
8684 You seldom have to reimplement the setVisible() function. If
8685 you need to change some settings before a widget is shown, use
8686 showEvent() instead. If you need to do some delayed initialization
8687 use the Polish event delivered to the event() function.
8688
8689 \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
8690 showEvent(), hideEvent()
8691*/
8692
8693
8694/*!
8695 Returns \c true if this widget would become visible if \a ancestor is
8696 shown; otherwise returns \c false.
8697
8698 The true case occurs if neither the widget itself nor any parent
8699 up to but excluding \a ancestor has been explicitly hidden.
8700
8701 This function will still return true if the widget is obscured by
8702 other windows on the screen, but could be physically visible if it
8703 or they were to be moved.
8704
8705 isVisibleTo(0) is identical to isVisible().
8706
8707 \sa show(), hide(), isVisible()
8708*/
8709
8710bool QWidget::isVisibleTo(const QWidget *ancestor) const
8711{
8712 if (!ancestor)
8713 return isVisible();
8714 const QWidget * w = this;
8715 while (!w->isHidden()
8716 && !w->isWindow()
8717 && w->parentWidget()
8718 && w->parentWidget() != ancestor)
8719 w = w->parentWidget();
8720 return !w->isHidden();
8721}
8722
8723
8724/*!
8725 Returns the unobscured region where paint events can occur.
8726
8727 For visible widgets, this is an approximation of the area not
8728 covered by other widgets; otherwise, this is an empty region.
8729
8730 The repaint() function calls this function if necessary, so in
8731 general you do not need to call it.
8732
8733*/
8734QRegion QWidget::visibleRegion() const
8735{
8736 Q_D(const QWidget);
8737
8738 QRect clipRect = d->clipRect();
8739 if (clipRect.isEmpty())
8740 return QRegion();
8741 QRegion r(clipRect);
8742 d->subtractOpaqueChildren(r, clipRect);
8743 d->subtractOpaqueSiblings(r);
8744 return r;
8745}
8746
8747
8748QSize QWidgetPrivate::adjustedSize() const
8749{
8750 Q_Q(const QWidget);
8751
8752 QSize s = q->sizeHint();
8753
8754 if (q->isWindow()) {
8755 Qt::Orientations exp;
8756 if (layout) {
8757 if (layout->hasHeightForWidth())
8758 s.setHeight(layout->totalHeightForWidth(s.width()));
8759 exp = layout->expandingDirections();
8760 } else
8761 {
8762 if (q->sizePolicy().hasHeightForWidth())
8763 s.setHeight(q->heightForWidth(s.width()));
8764 exp = q->sizePolicy().expandingDirections();
8765 }
8766 if (exp & Qt::Horizontal)
8767 s.setWidth(qMax(s.width(), 200));
8768 if (exp & Qt::Vertical)
8769 s.setHeight(qMax(s.height(), 100));
8770
8771 QRect screen;
8772 if (const QScreen *screenAtPoint = QGuiApplication::screenAt(q->pos()))
8773 screen = screenAtPoint->geometry();
8774 else
8775 screen = QGuiApplication::primaryScreen()->geometry();
8776
8777 s.setWidth(qMin(s.width(), screen.width()*2/3));
8778 s.setHeight(qMin(s.height(), screen.height()*2/3));
8779
8780 if (QTLWExtra *extra = maybeTopData())
8781 extra->sizeAdjusted = true;
8782 }
8783
8784 if (!s.isValid()) {
8785 QRect r = q->childrenRect(); // get children rectangle
8786 if (r.isNull())
8787 return s;
8788 s = r.size() + QSize(2 * r.x(), 2 * r.y());
8789 }
8790
8791 return s;
8792}
8793
8794/*!
8795 Adjusts the size of the widget to fit its contents.
8796
8797 This function uses sizeHint() if it is valid, i.e., the size hint's width
8798 and height are >= 0. Otherwise, it sets the size to the children
8799 rectangle that covers all child widgets (the union of all child widget
8800 rectangles).
8801
8802 For windows, the screen size is also taken into account. If the sizeHint()
8803 is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
8804 {expanding}, the window will be at least (200, 100). The maximum size of
8805 a window is 2/3 of the screen's width and height.
8806
8807 \sa sizeHint(), childrenRect()
8808*/
8809
8810void QWidget::adjustSize()
8811{
8812 Q_D(QWidget);
8813 ensurePolished();
8814 QSize s = d->adjustedSize();
8815
8816 if (d->layout)
8817 d->layout->activate();
8818
8819 if (s.isValid())
8820 resize(s);
8821}
8822
8823
8824/*!
8825 \property QWidget::sizeHint
8826 \brief the recommended size for the widget
8827
8828 If the value of this property is an invalid size, no size is
8829 recommended.
8830
8831 The default implementation of sizeHint() returns an invalid size
8832 if there is no layout for this widget, and returns the layout's
8833 preferred size otherwise.
8834
8835 \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
8836 setMinimumSize(), updateGeometry()
8837*/
8838
8839QSize QWidget::sizeHint() const
8840{
8841 Q_D(const QWidget);
8842 if (d->layout)
8843 return d->layout->totalSizeHint();
8844 return QSize(-1, -1);
8845}
8846
8847/*!
8848 \property QWidget::minimumSizeHint
8849 \brief the recommended minimum size for the widget
8850
8851 If the value of this property is an invalid size, no minimum size
8852 is recommended.
8853
8854 The default implementation of minimumSizeHint() returns an invalid
8855 size if there is no layout for this widget, and returns the
8856 layout's minimum size otherwise. Most built-in widgets reimplement
8857 minimumSizeHint().
8858
8859 \l QLayout will never resize a widget to a size smaller than the
8860 minimum size hint unless minimumSize() is set or the size policy is
8861 set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
8862 size hint will be ignored.
8863
8864 \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
8865*/
8866QSize QWidget::minimumSizeHint() const
8867{
8868 Q_D(const QWidget);
8869 if (d->layout)
8870 return d->layout->totalMinimumSize();
8871 return QSize(-1, -1);
8872}
8873
8874
8875/*!
8876 \fn QWidget *QWidget::parentWidget() const
8877
8878 Returns the parent of this widget, or \nullptr if it does not have any
8879 parent widget.
8880*/
8881
8882
8883/*!
8884 Returns \c true if this widget is a parent, (or grandparent and so on
8885 to any level), of the given \a child, and both widgets are within
8886 the same window; otherwise returns \c false.
8887*/
8888
8889bool QWidget::isAncestorOf(const QWidget *child) const
8890{
8891 while (child) {
8892 if (child == this)
8893 return true;
8894 if (child->isWindow())
8895 return false;
8896 child = child->parentWidget();
8897 }
8898 return false;
8899}
8900
8901/*****************************************************************************
8902 QWidget event handling
8903 *****************************************************************************/
8904
8905/*!
8906 This is the main event handler; it handles event \a event. You can
8907 reimplement this function in a subclass, but we recommend using
8908 one of the specialized event handlers instead.
8909
8910 Key press and release events are treated differently from other
8911 events. event() checks for Tab and Shift+Tab and tries to move the
8912 focus appropriately. If there is no widget to move the focus to
8913 (or the key press is not Tab or Shift+Tab), event() calls
8914 keyPressEvent().
8915
8916 Mouse and tablet event handling is also slightly special: only
8917 when the widget is \l enabled, event() will call the specialized
8918 handlers such as mousePressEvent(); otherwise it will discard the
8919 event.
8920
8921 This function returns \c true if the event was recognized, otherwise
8922 it returns \c false. If the recognized event was accepted (see \l
8923 QEvent::accepted), any further processing such as event
8924 propagation to the parent widget stops.
8925
8926 \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
8927 keyPressEvent(), keyReleaseEvent(), leaveEvent(),
8928 mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
8929 mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
8930 QObject::event(), QObject::timerEvent()
8931*/
8932
8933bool QWidget::event(QEvent *event)
8934{
8935 Q_D(QWidget);
8936
8937 // ignore mouse and key events when disabled
8938 if (!isEnabled()) {
8939 switch(event->type()) {
8940 case QEvent::TabletPress:
8941 case QEvent::TabletRelease:
8942 case QEvent::TabletMove:
8943 case QEvent::MouseButtonPress:
8944 case QEvent::MouseButtonRelease:
8945 case QEvent::MouseButtonDblClick:
8946 case QEvent::MouseMove:
8947 case QEvent::TouchBegin:
8948 case QEvent::TouchUpdate:
8949 case QEvent::TouchEnd:
8950 case QEvent::TouchCancel:
8951 case QEvent::ContextMenu:
8952 case QEvent::KeyPress:
8953 case QEvent::KeyRelease:
8954#if QT_CONFIG(wheelevent)
8955 case QEvent::Wheel:
8956#endif
8957 return false;
8958 default:
8959 break;
8960 }
8961 }
8962 switch (event->type()) {
8963 case QEvent::PlatformSurface: {
8964 // Sync up QWidget's view of whether or not the widget has been created
8965 switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
8966 case QPlatformSurfaceEvent::SurfaceCreated:
8967 if (!testAttribute(Qt::WA_WState_Created))
8968 create();
8969 break;
8970 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
8971 if (testAttribute(Qt::WA_WState_Created)) {
8972 // Child windows have already been destroyed by QWindow,
8973 // so we skip them here.
8974 destroy(false, false);
8975 }
8976 break;
8977 }
8978 break;
8979 }
8980 case QEvent::MouseMove:
8981 mouseMoveEvent((QMouseEvent*)event);
8982 break;
8983
8984 case QEvent::MouseButtonPress:
8985 mousePressEvent((QMouseEvent*)event);
8986 break;
8987
8988 case QEvent::MouseButtonRelease:
8989 mouseReleaseEvent((QMouseEvent*)event);
8990 break;
8991
8992 case QEvent::MouseButtonDblClick:
8993 mouseDoubleClickEvent((QMouseEvent*)event);
8994 break;
8995#if QT_CONFIG(wheelevent)
8996 case QEvent::Wheel:
8997 wheelEvent((QWheelEvent*)event);
8998 break;
8999#endif
9000#if QT_CONFIG(tabletevent)
9001 case QEvent::TabletMove:
9002 if (static_cast<QTabletEvent *>(event)->buttons() == Qt::NoButton && !testAttribute(Qt::WA_TabletTracking))
9003 break;
9004 Q_FALLTHROUGH();
9005 case QEvent::TabletPress:
9006 case QEvent::TabletRelease:
9007 tabletEvent((QTabletEvent*)event);
9008 break;
9009#endif
9010 case QEvent::KeyPress: {
9011 QKeyEvent *k = static_cast<QKeyEvent *>(event);
9012 bool res = false;
9013 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
9014 if (k->key() == Qt::Key_Backtab
9015 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
9016 res = focusNextPrevChild(false);
9017 else if (k->key() == Qt::Key_Tab)
9018 res = focusNextPrevChild(true);
9019 if (res)
9020 break;
9021 }
9022 keyPressEvent(k);
9023#if QT_CONFIG(whatsthis)
9024 if (!k->isAccepted()
9025 && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
9026 && d->whatsThis.size()) {
9027 QWhatsThis::showText(mapToGlobal(inputMethodQuery(Qt::ImCursorRectangle).toRect().center()), d->whatsThis, this);
9028 k->accept();
9029 }
9030#endif
9031 }
9032 break;
9033
9034 case QEvent::KeyRelease:
9035 keyReleaseEvent((QKeyEvent*)event);
9036 Q_FALLTHROUGH();
9037 case QEvent::ShortcutOverride:
9038 break;
9039
9040 case QEvent::InputMethod:
9041 inputMethodEvent((QInputMethodEvent *) event);
9042 break;
9043
9044 case QEvent::InputMethodQuery: {
9045 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
9046 Qt::InputMethodQueries queries = query->queries();
9047 for (uint i = 0; i < 32; ++i) {
9048 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
9049 if (q) {
9050 QVariant v = inputMethodQuery(q);
9051 if (q == Qt::ImEnabled && !v.isValid() && isEnabled()) {
9052 // Qt:ImEnabled was added in Qt 5.3. So not all widgets support it, even
9053 // if they implement IM otherwise (by overriding inputMethodQuery()). Instead
9054 // they set the widget attribute Qt::WA_InputMethodEnabled. But this attribute
9055 // will only be set if the widget supports IM _and_ is not read-only. So for
9056 // read-only widgets, not all IM features will be supported when ImEnabled is
9057 // not implemented explicitly (e.g selection handles for read-only widgets on iOS).
9058 v = QVariant(testAttribute(Qt::WA_InputMethodEnabled));
9059 }
9060 query->setValue(q, v);
9061 }
9062 }
9063 query->accept();
9064 }
9065 break;
9066
9067 case QEvent::PolishRequest:
9068 ensurePolished();
9069 break;
9070
9071 case QEvent::Polish: {
9072 style()->polish(this);
9073 setAttribute(Qt::WA_WState_Polished);
9074 if (!QApplication::font(this).isCopyOf(QApplication::font()))
9075 d->resolveFont();
9076 if (!QApplication::palette(this).isCopyOf(QGuiApplication::palette()))
9077 d->resolvePalette();
9078 }
9079 break;
9080
9081 case QEvent::ApplicationWindowIconChange:
9082 if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon)) {
9083 d->setWindowIcon_sys();
9084 d->setWindowIcon_helper();
9085 }
9086 break;
9087 case QEvent::FocusIn:
9088 focusInEvent((QFocusEvent*)event);
9089 d->updateWidgetTransform(event);
9090 break;
9091
9092 case QEvent::FocusOut:
9093 focusOutEvent((QFocusEvent*)event);
9094 break;
9095
9096 case QEvent::Enter:
9097#if QT_CONFIG(statustip)
9098 if (d->statusTip.size()) {
9099 QStatusTipEvent tip(d->statusTip);
9100 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
9101 }
9102#endif
9103 enterEvent(static_cast<QEnterEvent*>(event));
9104 break;
9105
9106 case QEvent::Leave:
9107#if QT_CONFIG(statustip)
9108 if (d->statusTip.size()) {
9109 QString empty;
9110 QStatusTipEvent tip(empty);
9111 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip);
9112 }
9113#endif
9114 leaveEvent(event);
9115 break;
9116
9117 case QEvent::HoverEnter:
9118 case QEvent::HoverLeave:
9119 update();
9120 break;
9121
9122 case QEvent::Paint:
9123 // At this point the event has to be delivered, regardless
9124 // whether the widget isVisible() or not because it
9125 // already went through the filters
9126 paintEvent((QPaintEvent*)event);
9127 break;
9128
9129 case QEvent::Move:
9130 moveEvent((QMoveEvent*)event);
9131 d->updateWidgetTransform(event);
9132 break;
9133
9134 case QEvent::Resize:
9135 resizeEvent((QResizeEvent*)event);
9136 d->updateWidgetTransform(event);
9137 break;
9138
9139 case QEvent::Close:
9140 closeEvent((QCloseEvent *)event);
9141 break;
9142
9143#ifndef QT_NO_CONTEXTMENU
9144 case QEvent::ContextMenu:
9145 switch (data->context_menu_policy) {
9146 case Qt::PreventContextMenu:
9147 break;
9148 case Qt::DefaultContextMenu:
9149 contextMenuEvent(static_cast<QContextMenuEvent *>(event));
9150 break;
9151 case Qt::CustomContextMenu:
9152 emit customContextMenuRequested(static_cast<QContextMenuEvent *>(event)->pos());
9153 break;
9154#if QT_CONFIG(menu)
9155 case Qt::ActionsContextMenu:
9156 if (d->actions.size()) {
9157 QMenu::exec(d->actions, static_cast<QContextMenuEvent *>(event)->globalPos(),
9158 nullptr, this);
9159 break;
9160 }
9161 Q_FALLTHROUGH();
9162#endif
9163 default:
9164 event->ignore();
9165 break;
9166 }
9167 break;
9168#endif // QT_NO_CONTEXTMENU
9169
9170#if QT_CONFIG(draganddrop)
9171 case QEvent::Drop:
9172 dropEvent((QDropEvent*) event);
9173 break;
9174
9175 case QEvent::DragEnter:
9176 dragEnterEvent((QDragEnterEvent*) event);
9177 break;
9178
9179 case QEvent::DragMove:
9180 dragMoveEvent((QDragMoveEvent*) event);
9181 break;
9182
9183 case QEvent::DragLeave:
9184 dragLeaveEvent((QDragLeaveEvent*) event);
9185 break;
9186#endif
9187
9188 case QEvent::Show:
9189 showEvent((QShowEvent*) event);
9190 break;
9191
9192 case QEvent::Hide:
9193 hideEvent((QHideEvent*) event);
9194 break;
9195
9196 case QEvent::ShowWindowRequest:
9197 if (!isHidden())
9198 d->show_sys();
9199 break;
9200
9201 case QEvent::ApplicationFontChange:
9202 d->resolveFont();
9203 break;
9204 case QEvent::ApplicationPaletteChange:
9205 d->resolvePalette();
9206 break;
9207
9208 case QEvent::ToolBarChange:
9209 case QEvent::ActivationChange:
9210 case QEvent::EnabledChange:
9211 case QEvent::FontChange:
9212 case QEvent::StyleChange:
9213 case QEvent::PaletteChange:
9214 case QEvent::WindowTitleChange:
9215 case QEvent::IconTextChange:
9216 case QEvent::ModifiedChange:
9217 case QEvent::MouseTrackingChange:
9218 case QEvent::TabletTrackingChange:
9219 case QEvent::ParentChange:
9220 case QEvent::LocaleChange:
9221 case QEvent::MacSizeChange:
9222 case QEvent::ContentsRectChange:
9223 case QEvent::ThemeChange:
9224 case QEvent::ReadOnlyChange:
9225 changeEvent(event);
9226 break;
9227
9228 case QEvent::WindowStateChange: {
9229 const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
9230 if (wasMinimized != isMinimized()) {
9231 QWidget *widget = const_cast<QWidget *>(this);
9232 if (wasMinimized) {
9233 // Always send the spontaneous events here, otherwise it can break the application!
9234 if (!d->childrenShownByExpose) {
9235 // Show widgets only when they are not yet shown by the expose event
9236 d->showChildren(true);
9237 QShowEvent showEvent;
9238 QCoreApplication::sendSpontaneousEvent(widget, &showEvent);
9239 }
9240 d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
9241 } else {
9242 QHideEvent hideEvent;
9243 QCoreApplication::sendSpontaneousEvent(widget, &hideEvent);
9244 d->hideChildren(true);
9245 d->childrenHiddenByWState = true;
9246 }
9247 d->childrenShownByExpose = false; // Set it always to "false" when window state changes
9248 }
9249 changeEvent(event);
9250 }
9251 break;
9252
9253 case QEvent::WindowActivate:
9254 case QEvent::WindowDeactivate: {
9255 if (isVisible() && !palette().isEqual(QPalette::Active, QPalette::Inactive))
9256 update();
9257 QList<QObject*> childList = d->children;
9258 for (int i = 0; i < childList.size(); ++i) {
9259 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9260 if (w && w->isVisible() && !w->isWindow())
9261 QCoreApplication::sendEvent(w, event);
9262 }
9263 break; }
9264
9265 case QEvent::LanguageChange:
9266 changeEvent(event);
9267 {
9268 QList<QObject*> childList = d->children;
9269 for (int i = 0; i < childList.size(); ++i) {
9270 QObject *o = childList.at(i);
9271 if (o)
9272 QCoreApplication::sendEvent(o, event);
9273 }
9274 }
9275 update();
9276 break;
9277
9278 case QEvent::ApplicationLayoutDirectionChange:
9279 d->resolveLayoutDirection();
9280 break;
9281
9282 case QEvent::LayoutDirectionChange:
9283 if (d->layout)
9284 d->layout->invalidate();
9285 update();
9286 changeEvent(event);
9287 break;
9288 case QEvent::UpdateRequest:
9289 d->syncBackingStore();
9290 break;
9291 case QEvent::UpdateLater:
9292 update(static_cast<QUpdateLaterEvent*>(event)->region());
9293 break;
9294 case QEvent::StyleAnimationUpdate:
9295 if (isVisible() && !window()->isMinimized()) {
9296 event->accept();
9297 update();
9298 }
9299 break;
9300
9301 case QEvent::WindowBlocked:
9302 case QEvent::WindowUnblocked:
9303 if (!d->children.isEmpty()) {
9304 QWidget *modalWidget = QApplication::activeModalWidget();
9305 for (int i = 0; i < d->children.size(); ++i) {
9306 QObject *o = d->children.at(i);
9307 if (o && o != modalWidget && o->isWidgetType()) {
9308 QWidget *w = static_cast<QWidget *>(o);
9309 // do not forward the event to child windows; QApplication does this for us
9310 if (!w->isWindow())
9311 QCoreApplication::sendEvent(w, event);
9312 }
9313 }
9314 }
9315 break;
9316#if QT_CONFIG(tooltip)
9317 case QEvent::ToolTip:
9318 if (!d->toolTip.isEmpty())
9319 QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), d->toolTip, this, QRect(), d->toolTipDuration);
9320 else
9321 event->ignore();
9322 break;
9323#endif
9324#if QT_CONFIG(whatsthis)
9325 case QEvent::WhatsThis:
9326 if (d->whatsThis.size())
9327 QWhatsThis::showText(static_cast<QHelpEvent *>(event)->globalPos(), d->whatsThis, this);
9328 else
9329 event->ignore();
9330 break;
9331 case QEvent::QueryWhatsThis:
9332 if (d->whatsThis.isEmpty())
9333 event->ignore();
9334 break;
9335#endif
9336 case QEvent::EmbeddingControl:
9337 d->topData()->frameStrut.setCoords(0 ,0, 0, 0);
9338 data->fstrut_dirty = false;
9339 break;
9340#ifndef QT_NO_ACTION
9341 case QEvent::ActionAdded:
9342 case QEvent::ActionRemoved:
9343 case QEvent::ActionChanged:
9344 actionEvent((QActionEvent*)event);
9345 break;
9346#endif
9347
9348 case QEvent::KeyboardLayoutChange:
9349 {
9350 changeEvent(event);
9351
9352 // inform children of the change
9353 QList<QObject*> childList = d->children;
9354 for (int i = 0; i < childList.size(); ++i) {
9355 QWidget *w = qobject_cast<QWidget *>(childList.at(i));
9356 if (w && w->isVisible() && !w->isWindow())
9357 QCoreApplication::sendEvent(w, event);
9358 }
9359 break;
9360 }
9361 case QEvent::TouchBegin:
9362 case QEvent::TouchUpdate:
9363 case QEvent::TouchEnd:
9364 case QEvent::TouchCancel:
9365 {
9366 event->ignore();
9367 break;
9368 }
9369#ifndef QT_NO_GESTURES
9370 case QEvent::Gesture:
9371 event->ignore();
9372 break;
9373#endif
9374 case QEvent::ScreenChangeInternal:
9375 if (const QTLWExtra *te = d->maybeTopData()) {
9376 const QWindow *win = te->window;
9377 d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
9378 }
9379 break;
9380 case QEvent::DevicePixelRatioChange:
9381 if (d->data.fnt.d->dpi != logicalDpiY())
9382 d->updateFont(d->data.fnt);
9383 d->renderToTextureReallyDirty = 1;
9384 break;
9385 case QEvent::DynamicPropertyChange: {
9386 const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
9387 if (propName.size() == 13 && !qstrncmp(propName, "_q_customDpi", 12)) {
9388 uint value = property(propName.constData()).toUInt();
9389 if (!d->extra)
9390 d->createExtra();
9391 const char axis = propName.at(12);
9392 if (axis == 'X')
9393 d->extra->customDpiX = value;
9394 else if (axis == 'Y')
9395 d->extra->customDpiY = value;
9396 d->updateFont(d->data.fnt);
9397 }
9398 if (windowHandle() && !qstrncmp(propName, "_q_platform_", 12))
9399 windowHandle()->setProperty(propName, property(propName));
9400 Q_FALLTHROUGH();
9401 }
9402 default:
9403 return QObject::event(event);
9404 }
9405 return true;
9406}
9407
9408/*!
9409 This event handler can be reimplemented to handle state changes.
9410
9411 The state being changed in this event can be retrieved through the \a event
9412 supplied.
9413
9414 Change events include: QEvent::ToolBarChange,
9415 QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
9416 QEvent::StyleChange, QEvent::PaletteChange,
9417 QEvent::WindowTitleChange, QEvent::IconTextChange,
9418 QEvent::ModifiedChange, QEvent::MouseTrackingChange,
9419 QEvent::ParentChange, QEvent::WindowStateChange,
9420 QEvent::LanguageChange, QEvent::LocaleChange,
9421 QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
9422
9423*/
9424void QWidget::changeEvent(QEvent * event)
9425{
9426 switch(event->type()) {
9427 case QEvent::EnabledChange: {
9428 update();
9429#if QT_CONFIG(accessibility)
9430 QAccessible::State s;
9431 s.disabled = true;
9432 QAccessibleStateChangeEvent event(this, s);
9433 QAccessible::updateAccessibility(&event);
9434#endif
9435 break;
9436 }
9437
9438 case QEvent::FontChange:
9439 case QEvent::StyleChange: {
9440 Q_D(QWidget);
9441 update();
9442 updateGeometry();
9443 if (d->layout)
9444 d->layout->invalidate();
9445 break;
9446 }
9447
9448 case QEvent::PaletteChange:
9449 update();
9450 break;
9451
9452 case QEvent::ThemeChange:
9453 if (QGuiApplication::desktopSettingsAware()
9454 && qApp && !QCoreApplication::closingDown()) {
9455 if (testAttribute(Qt::WA_WState_Polished))
9456 QApplication::style()->unpolish(this);
9457 if (testAttribute(Qt::WA_WState_Polished))
9458 QApplication::style()->polish(this);
9459 QEvent styleChangedEvent(QEvent::StyleChange);
9460 QCoreApplication::sendEvent(this, &styleChangedEvent);
9461 if (isVisible())
9462 update();
9463 }
9464 break;
9465
9466#ifdef Q_OS_MACOS
9467 case QEvent::MacSizeChange:
9468 updateGeometry();
9469 break;
9470#endif
9471
9472 default:
9473 break;
9474 }
9475}
9476
9477/*!
9478 This event handler, for event \a event, can be reimplemented in a
9479 subclass to receive mouse move events for the widget.
9480
9481 If mouse tracking is switched off, mouse move events only occur if
9482 a mouse button is pressed while the mouse is being moved. If mouse
9483 tracking is switched on, mouse move events occur even if no mouse
9484 button is pressed.
9485
9486 QMouseEvent::position() reports the position of the mouse cursor,
9487 relative to this widget. For press and release events, the
9488 position is usually the same as the position of the last mouse
9489 move event, but it might be different if the user's hand shakes.
9490 This is a feature of the underlying window system, not Qt.
9491
9492 If you want to show a tooltip immediately, while the mouse is
9493 moving (e.g., to get the mouse coordinates with QMouseEvent::position()
9494 and show them as a tooltip), you must first enable mouse tracking
9495 as described above. Then, to ensure that the tooltip is updated
9496 immediately, you must call QToolTip::showText() instead of
9497 setToolTip() in your implementation of mouseMoveEvent().
9498
9499 \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
9500 mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
9501*/
9502
9503void QWidget::mouseMoveEvent(QMouseEvent *event)
9504{
9505 event->ignore();
9506}
9507
9508/*!
9509 This event handler, for event \a event, can be reimplemented in a
9510 subclass to receive mouse press events for the widget.
9511
9512 If you create new widgets in the mousePressEvent() the
9513 mouseReleaseEvent() may not end up where you expect, depending on
9514 the underlying window system (or X11 window manager), the widgets'
9515 location and maybe more.
9516
9517 The default implementation implements the closing of popup widgets
9518 when you click outside the window. For other widget types it does
9519 nothing.
9520
9521 \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
9522 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9523*/
9524
9525void QWidget::mousePressEvent(QMouseEvent *event)
9526{
9527 event->ignore();
9528 if ((windowType() == Qt::Popup)) {
9529 event->accept();
9530 QWidget* w;
9531 while ((w = QApplication::activePopupWidget()) && w != this){
9532 w->close();
9533 if (QApplication::activePopupWidget() == w) // widget does not want to disappear
9534 w->hide(); // hide at least
9535 }
9536 if (!rect().contains(event->position().toPoint())){
9537 close();
9538 }
9539 }
9540}
9541
9542/*!
9543 This event handler, for event \a event, can be reimplemented in a
9544 subclass to receive mouse release events for the widget.
9545
9546 \sa mousePressEvent(), mouseDoubleClickEvent(),
9547 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9548*/
9549
9550void QWidget::mouseReleaseEvent(QMouseEvent *event)
9551{
9552 event->ignore();
9553}
9554
9555/*!
9556 This event handler, for event \a event, can be reimplemented in a
9557 subclass to receive mouse double click events for the widget.
9558
9559 The double click event replaces the second mouse press event of a
9560 double click. The widget receives a mouse press event, a mouse
9561 release event, the double click event, and a second mouse release
9562 event.
9563
9564 The default implementation calls mousePressEvent(), so a widget that
9565 doesn't reimplement this function handles the second click as an
9566 ordinary press. If you reimplement this function and also need to
9567 react to every press, either call the base implementation or handle
9568 the event as a press yourself.
9569
9570 \note If another widget that overlaps this widget disappears in
9571 response to press or release events, then this widget will only
9572 receive the double click event. It is up to the developer to ensure
9573 that the application interprets these events correctly.
9574
9575 \sa mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(),
9576 event(), QMouseEvent
9577*/
9578
9579void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
9580{
9581 mousePressEvent(event);
9582}
9583
9584#if QT_CONFIG(wheelevent)
9585/*!
9586 This event handler, for event \a event, can be reimplemented in a
9587 subclass to receive wheel events for the widget.
9588
9589 If you reimplement this handler, it is very important that you
9590 \l{QEvent}{ignore()} the event if you do not handle
9591 it, so that the widget's parent can interpret it.
9592
9593 The default implementation ignores the event.
9594
9595 \sa QEvent::ignore(), QEvent::accept(), event(),
9596 QWheelEvent
9597*/
9598
9599void QWidget::wheelEvent(QWheelEvent *event)
9600{
9601 event->ignore();
9602}
9603#endif // QT_CONFIG(wheelevent)
9604
9605#if QT_CONFIG(tabletevent)
9606/*!
9607 This event handler, for event \a event, can be reimplemented in a
9608 subclass to receive tablet events for the widget.
9609
9610 If you reimplement this handler, it is very important that you
9611 \l{QEvent}{ignore()} the event if you do not handle
9612 it, so that the widget's parent can interpret it.
9613
9614 The default implementation ignores the event.
9615
9616 If tablet tracking is switched off, tablet move events only occur if the
9617 stylus is in contact with the tablet, or at least one stylus button is
9618 pressed, while the stylus is being moved. If tablet tracking is switched on,
9619 tablet move events occur even while the stylus is hovering in proximity of
9620 the tablet, with no buttons pressed.
9621
9622 \sa QEvent::ignore(), QEvent::accept(), event(), setTabletTracking(),
9623 QTabletEvent
9624*/
9625
9626void QWidget::tabletEvent(QTabletEvent *event)
9627{
9628 event->ignore();
9629}
9630#endif // QT_CONFIG(tabletevent)
9631
9632/*!
9633 This event handler, for event \a event, can be reimplemented in a
9634 subclass to receive key press events for the widget.
9635
9636 A widget must call setFocusPolicy() to accept focus initially and
9637 have focus in order to receive a key press event.
9638
9639 If you reimplement this handler, it is very important that you
9640 call the base class implementation if you do not act upon the key.
9641
9642 The default implementation closes popup widgets if the user
9643 presses the key sequence for QKeySequence::Cancel (typically the
9644 Escape key). Otherwise the event is ignored, so that the widget's
9645 parent can interpret it.
9646
9647 Note that QKeyEvent starts with isAccepted() == true, so you do not
9648 need to call QKeyEvent::accept() - just do not call the base class
9649 implementation if you act upon the key.
9650
9651 \sa keyReleaseEvent(), setFocusPolicy(),
9652 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9653*/
9654
9655void QWidget::keyPressEvent(QKeyEvent *event)
9656{
9657#ifndef QT_NO_SHORTCUT
9658 if ((windowType() == Qt::Popup) && event->matches(QKeySequence::Cancel)) {
9659 event->accept();
9660 close();
9661 } else
9662#endif
9663 {
9664 event->ignore();
9665 }
9666}
9667
9668/*!
9669 This event handler, for event \a event, can be reimplemented in a
9670 subclass to receive key release events for the widget.
9671
9672 A widget must \l{setFocusPolicy()}{accept focus}
9673 initially and \l{hasFocus()}{have focus} in order to
9674 receive a key release event.
9675
9676 If you reimplement this handler, it is very important that you
9677 call the base class implementation if you do not act upon the key.
9678
9679 The default implementation ignores the event, so that the widget's
9680 parent can interpret it.
9681
9682 Note that QKeyEvent starts with isAccepted() == true, so you do not
9683 need to call QKeyEvent::accept() - just do not call the base class
9684 implementation if you act upon the key.
9685
9686 \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(),
9687 focusInEvent(), focusOutEvent(), event(), QKeyEvent
9688*/
9689
9690void QWidget::keyReleaseEvent(QKeyEvent *event)
9691{
9692 event->ignore();
9693}
9694
9695/*!
9696 \fn void QWidget::focusInEvent(QFocusEvent *event)
9697
9698 This event handler can be reimplemented in a subclass to receive
9699 keyboard focus events (focus received) for the widget. The event
9700 is passed in the \a event parameter
9701
9702 A widget normally must setFocusPolicy() to something other than
9703 Qt::NoFocus to receive focus events. (Note that the
9704 application programmer can call setFocus() on any widget, even
9705 those that do not normally accept focus.)
9706
9707 The default implementation updates the widget (except for windows
9708 that do not specify a focusPolicy()).
9709
9710 \sa focusOutEvent(), setFocusPolicy(), keyPressEvent(),
9711 keyReleaseEvent(), event(), QFocusEvent
9712*/
9713
9714void QWidget::focusInEvent(QFocusEvent *)
9715{
9716 if (focusPolicy() != Qt::NoFocus || !isWindow()) {
9717 update();
9718 }
9719}
9720
9721/*!
9722 \fn void QWidget::focusOutEvent(QFocusEvent *event)
9723
9724 This event handler can be reimplemented in a subclass to receive
9725 keyboard focus events (focus lost) for the widget. The event is
9726 passed in the \a event parameter.
9727
9728 A widget normally must setFocusPolicy() to something other than
9729 Qt::NoFocus to receive focus events. (Note that the
9730 application programmer can call setFocus() on any widget, even
9731 those that do not normally accept focus.)
9732
9733 The default implementation updates the widget (except for windows
9734 that do not specify a focusPolicy()).
9735
9736 \sa focusInEvent(), setFocusPolicy(), keyPressEvent(),
9737 keyReleaseEvent(), event(), QFocusEvent
9738*/
9739
9740void QWidget::focusOutEvent(QFocusEvent *)
9741{
9742 if (focusPolicy() != Qt::NoFocus || !isWindow())
9743 update();
9744
9745#if !defined(QT_PLATFORM_UIKIT)
9746 // FIXME: revisit autoSIP logic, QTBUG-42906
9747 if (qApp->autoSipEnabled() && testAttribute(Qt::WA_InputMethodEnabled))
9748 QGuiApplication::inputMethod()->hide();
9749#endif
9750}
9751
9752/*!
9753 \fn void QWidget::enterEvent(QEnterEvent *event)
9754
9755 This event handler can be reimplemented in a subclass to receive
9756 widget enter events which are passed in the \a event parameter.
9757
9758 An event is sent to the widget when the mouse cursor enters the
9759 widget.
9760
9761 \sa leaveEvent(), mouseMoveEvent(), event()
9762*/
9763
9764void QWidget::enterEvent(QEnterEvent *)
9765{
9766}
9767
9768/*!
9769 \fn void QWidget::leaveEvent(QEvent *event)
9770
9771 This event handler can be reimplemented in a subclass to receive
9772 widget leave events which are passed in the \a event parameter.
9773
9774 A leave event is sent to the widget when the mouse cursor leaves
9775 the widget.
9776
9777 \sa enterEvent(), mouseMoveEvent(), event()
9778*/
9779
9780void QWidget::leaveEvent(QEvent *)
9781{
9782}
9783
9784/*!
9785 \fn void QWidget::paintEvent(QPaintEvent *event)
9786
9787 This event handler can be reimplemented in a subclass to receive paint
9788 events passed in \a event.
9789
9790 A paint event is a request to repaint all or part of a widget. It can
9791 happen for one of the following reasons:
9792
9793 \list
9794 \li repaint() or update() was invoked,
9795 \li the widget was obscured and has now been uncovered, or
9796 \li many other reasons.
9797 \endlist
9798
9799 Many widgets can simply repaint their entire surface when asked to, but
9800 some slow widgets need to optimize by painting only the requested region:
9801 QPaintEvent::region(). This speed optimization does not change the result,
9802 as painting is clipped to that region during event processing. QListView
9803 and QTableView do this, for example.
9804
9805 Qt also tries to speed up painting by merging multiple paint events into
9806 one. When update() is called several times or the window system sends
9807 several paint events, Qt merges these events into one event with a larger
9808 region (see QRegion::united()). The repaint() function does not permit this
9809 optimization, so we suggest using update() whenever possible.
9810
9811 When the paint event occurs, the update region has normally been erased, so
9812 you are painting on the widget's background.
9813
9814 The background can be set using setBackgroundRole() and setPalette().
9815
9816 Since Qt 4.0, QWidget automatically double-buffers its painting, so there
9817 is no need to write double-buffering code in paintEvent() to avoid flicker.
9818
9819 \note Generally, you should refrain from calling update() or repaint()
9820 \b{inside} a paintEvent(). For example, calling update() or repaint() on
9821 children inside a paintEvent() results in undefined behavior; the child may
9822 or may not get a paint event.
9823
9824 \warning If you are using a custom paint engine without Qt's backingstore,
9825 Qt::WA_PaintOnScreen must be set. Otherwise, QWidget::paintEngine() will
9826 never be called; the backingstore will be used instead.
9827
9828 \sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
9829 {Analog Clock}
9830*/
9831
9832void QWidget::paintEvent(QPaintEvent *)
9833{
9834}
9835
9836
9837/*!
9838 \fn void QWidget::moveEvent(QMoveEvent *event)
9839
9840 This event handler can be reimplemented in a subclass to receive
9841 widget move events which are passed in the \a event parameter.
9842 When the widget receives this event, it is already at the new
9843 position.
9844
9845 The old position is accessible through QMoveEvent::oldPos().
9846
9847 \sa resizeEvent(), event(), move(), QMoveEvent
9848*/
9849
9850void QWidget::moveEvent(QMoveEvent *)
9851{
9852}
9853
9854
9855/*!
9856 This event handler can be reimplemented in a subclass to receive
9857 widget resize events which are passed in the \a event parameter.
9858 When resizeEvent() is called, the widget already has its new
9859 geometry. The old size is accessible through
9860 QResizeEvent::oldSize().
9861
9862 The widget will be erased and receive a paint event immediately
9863 after processing the resize event. No drawing need be (or should
9864 be) done inside this handler.
9865
9866
9867 \sa moveEvent(), event(), resize(), QResizeEvent, paintEvent(),
9868 {Scribble Example}
9869*/
9870
9871void QWidget::resizeEvent(QResizeEvent * /* event */)
9872{
9873}
9874
9875#ifndef QT_NO_ACTION
9876/*!
9877 \fn void QWidget::actionEvent(QActionEvent *event)
9878
9879 This event handler is called with the given \a event whenever the
9880 widget's actions are changed.
9881
9882 \sa addAction(), insertAction(), removeAction(), actions(), QActionEvent
9883*/
9884void QWidget::actionEvent(QActionEvent *)
9885{
9886
9887}
9888#endif
9889
9890/*!
9891 This event handler is called with the given \a event when Qt receives a window
9892 close request for a top-level widget from the window system.
9893
9894 By default, the event is accepted and the widget is closed. You can reimplement
9895 this function to change the way the widget responds to window close requests.
9896 For example, you can prevent the window from closing by calling \l{QEvent::}{ignore()}
9897 on all events.
9898
9899 Main window applications typically use reimplementations of this function to check
9900 whether the user's work has been saved and ask for permission before closing.
9901
9902 \sa event(), hide(), close(), QCloseEvent
9903*/
9904
9905void QWidget::closeEvent(QCloseEvent *event)
9906{
9907 event->accept();
9908}
9909
9910#ifndef QT_NO_CONTEXTMENU
9911/*!
9912 This event handler, for event \a event, can be reimplemented in a
9913 subclass to receive widget context menu events.
9914
9915 The handler is called when the widget's \l contextMenuPolicy is
9916 Qt::DefaultContextMenu.
9917
9918 The default implementation ignores the context event.
9919 See the \l QContextMenuEvent documentation for more details.
9920
9921 \sa event(), QContextMenuEvent, customContextMenuRequested()
9922*/
9923
9924void QWidget::contextMenuEvent(QContextMenuEvent *event)
9925{
9926 event->ignore();
9927}
9928#endif // QT_NO_CONTEXTMENU
9929
9930
9931/*!
9932 This event handler, for event \a event, can be reimplemented in a
9933 subclass to receive Input Method composition events. This handler
9934 is called when the state of the input method changes.
9935
9936 Note that when creating custom text editing widgets, the
9937 Qt::WA_InputMethodEnabled window attribute must be set explicitly
9938 (using the setAttribute() function) in order to receive input
9939 method events.
9940
9941 The default implementation calls event->ignore(), which rejects the
9942 Input Method event. See the \l QInputMethodEvent documentation for more
9943 details.
9944
9945 \sa event(), QInputMethodEvent
9946*/
9947void QWidget::inputMethodEvent(QInputMethodEvent *event)
9948{
9949 event->ignore();
9950}
9951
9952/*!
9953 This method is only relevant for input widgets. It is used by the
9954 input method to query a set of properties of the widget to be
9955 able to support complex input method operations as support for
9956 surrounding text and reconversions.
9957
9958 \a query specifies which property is queried.
9959
9960 \sa inputMethodEvent(), QInputMethodEvent, QInputMethodQueryEvent, inputMethodHints
9961*/
9962QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
9963{
9964 switch(query) {
9965 case Qt::ImCursorRectangle:
9966 return QRect(width()/2, 0, 1, height());
9967 case Qt::ImFont:
9968 return font();
9969 case Qt::ImAnchorPosition:
9970 // Fallback.
9971 return inputMethodQuery(Qt::ImCursorPosition);
9972 case Qt::ImHints:
9973 return (int)inputMethodHints();
9974 case Qt::ImInputItemClipRectangle:
9975 return d_func()->clipRect();
9976 default:
9977 return QVariant();
9978 }
9979}
9980
9981/*!
9982 \property QWidget::inputMethodHints
9983 \brief What input method specific hints the widget has.
9984
9985 This is only relevant for input widgets. It is used by
9986 the input method to retrieve hints as to how the input method
9987 should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
9988 is set, the input method may change its visual components to reflect
9989 that only numbers can be entered.
9990
9991 \warning Some widgets require certain flags to work as
9992 intended. To set a flag, do \c{w->setInputMethodHints(w->inputMethodHints()|f)}
9993 instead of \c{w->setInputMethodHints(f)}.
9994
9995 \note The flags are only hints, so the particular input method
9996 implementation is free to ignore them. If you want to be
9997 sure that a certain type of characters are entered,
9998 you should also set a QValidator on the widget.
9999
10000 The default value is Qt::ImhNone.
10001
10002 \since 4.6
10003
10004 \sa inputMethodQuery()
10005*/
10006Qt::InputMethodHints QWidget::inputMethodHints() const
10007{
10008#if QT_CONFIG(im)
10009 const QWidgetPrivate *priv = d_func();
10010 while (priv->inheritsInputMethodHints) {
10011 priv = priv->q_func()->parentWidget()->d_func();
10012 Q_ASSERT(priv);
10013 }
10014 return priv->imHints;
10015#else
10016 return Qt::ImhNone;
10017#endif
10018}
10019
10020void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
10021{
10022#ifndef QT_NO_IM
10023 Q_D(QWidget);
10024 if (d->imHints == hints)
10025 return;
10026 d->imHints = hints;
10027 if (this == QGuiApplication::focusObject())
10028 QGuiApplication::inputMethod()->update(Qt::ImHints);
10029#else
10030 Q_UNUSED(hints);
10031#endif //QT_NO_IM
10032}
10033
10034
10035#if QT_CONFIG(draganddrop)
10036
10037/*!
10038 \fn void QWidget::dragEnterEvent(QDragEnterEvent *event)
10039
10040 This event handler is called when a drag is in progress and the
10041 mouse enters this widget. The event is passed in the \a event parameter.
10042
10043 If the event is ignored, the widget won't receive any \l{dragMoveEvent()}{drag
10044 move events}.
10045
10046 See the \l{dnd.html}{Drag-and-drop documentation} for an
10047 overview of how to provide drag-and-drop in your application.
10048
10049 \sa QDrag, QDragEnterEvent
10050*/
10051void QWidget::dragEnterEvent(QDragEnterEvent *)
10052{
10053}
10054
10055/*!
10056 \fn void QWidget::dragMoveEvent(QDragMoveEvent *event)
10057
10058 This event handler is called if a drag is in progress, and when
10059 any of the following conditions occur: the cursor enters this widget,
10060 the cursor moves within this widget, or a modifier key is pressed on
10061 the keyboard while this widget has the focus. The event is passed
10062 in the \a event parameter.
10063
10064 See the \l{dnd.html}{Drag-and-drop documentation} for an
10065 overview of how to provide drag-and-drop in your application.
10066
10067 \sa QDrag, QDragMoveEvent
10068*/
10069void QWidget::dragMoveEvent(QDragMoveEvent *)
10070{
10071}
10072
10073/*!
10074 \fn void QWidget::dragLeaveEvent(QDragLeaveEvent *event)
10075
10076 This event handler is called when a drag is in progress and the
10077 mouse leaves this widget. The event is passed in the \a event
10078 parameter.
10079
10080 See the \l{dnd.html}{Drag-and-drop documentation} for an
10081 overview of how to provide drag-and-drop in your application.
10082
10083 \sa QDrag, QDragLeaveEvent
10084*/
10085void QWidget::dragLeaveEvent(QDragLeaveEvent *)
10086{
10087}
10088
10089/*!
10090 \fn void QWidget::dropEvent(QDropEvent *event)
10091
10092 This event handler is called when the drag is dropped on this
10093 widget. The event is passed in the \a event parameter.
10094
10095 See the \l{dnd.html}{Drag-and-drop documentation} for an
10096 overview of how to provide drag-and-drop in your application.
10097
10098 \sa QDrag, QDropEvent
10099*/
10100void QWidget::dropEvent(QDropEvent *)
10101{
10102}
10103
10104#endif // QT_CONFIG(draganddrop)
10105
10106/*!
10107 \fn void QWidget::showEvent(QShowEvent *event)
10108
10109 This event handler can be reimplemented in a subclass to receive
10110 widget show events which are passed in the \a event parameter.
10111
10112 Non-spontaneous show events are sent to widgets immediately
10113 before they are shown. The spontaneous show events of windows are
10114 delivered afterwards.
10115
10116 Note: A widget receives spontaneous show and hide events when its
10117 mapping status is changed by the window system, e.g. a spontaneous
10118 hide event when the user minimizes the window, and a spontaneous
10119 show event when the window is restored again. After receiving a
10120 spontaneous hide event, a widget is still considered visible in
10121 the sense of isVisible().
10122
10123 \sa visible, event(), QShowEvent
10124*/
10125void QWidget::showEvent(QShowEvent *)
10126{
10127}
10128
10129/*!
10130 \fn void QWidget::hideEvent(QHideEvent *event)
10131
10132 This event handler can be reimplemented in a subclass to receive
10133 widget hide events. The event is passed in the \a event parameter.
10134
10135 Hide events are sent to widgets immediately after they have been
10136 hidden.
10137
10138 Note: A widget receives spontaneous show and hide events when its
10139 mapping status is changed by the window system, e.g. a spontaneous
10140 hide event when the user minimizes the window, and a spontaneous
10141 show event when the window is restored again. After receiving a
10142 spontaneous hide event, a widget is still considered visible in
10143 the sense of isVisible().
10144
10145 \sa visible, event(), QHideEvent
10146*/
10147void QWidget::hideEvent(QHideEvent *)
10148{
10149}
10150
10151/*!
10152 This special event handler can be reimplemented in a subclass to
10153 receive native platform events identified by \a eventType
10154 which are passed in the \a message parameter.
10155
10156 In your reimplementation of this function, if you want to stop the
10157 event being handled by Qt, return true and set \a result. The \a result
10158 parameter has meaning only on Windows. If you return false, this native
10159 event is passed back to Qt, which translates the event into a Qt event
10160 and sends it to the widget.
10161
10162 \note Events are only delivered to this event handler if the widget
10163 has a native window handle.
10164
10165 \note This function superseedes the event filter functions
10166 x11Event(), winEvent() and macEvent() of Qt 4.
10167
10168 \sa QAbstractNativeEventFilter
10169
10170 \table
10171 \header \li Platform \li Event Type Identifier \li Message Type \li Result Type
10172 \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
10173 \row \li macOS \li "NSEvent" \li NSEvent * \li
10174 \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li
10175 \endtable
10176*/
10177
10178bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
10179{
10180 Q_UNUSED(eventType);
10181 Q_UNUSED(message);
10182 Q_UNUSED(result);
10183 return false;
10184}
10185
10186/*!
10187 Ensures that the widget and its children have been polished by
10188 QStyle (i.e., have a proper font and palette).
10189
10190 QWidget calls this function after it has been fully constructed
10191 but before it is shown the very first time. You can call this
10192 function if you want to ensure that the widget is polished before
10193 doing an operation, e.g., the correct font size might be needed in
10194 the widget's sizeHint() reimplementation. Note that this function
10195 \e is called from the default implementation of sizeHint().
10196
10197 Polishing is useful for final initialization that must happen after
10198 all constructors (from base classes as well as from subclasses)
10199 have been called.
10200
10201 If you need to change some settings when a widget is polished,
10202 reimplement event() and handle the QEvent::Polish event type.
10203
10204 \b{Note:} The function is declared const so that it can be called from
10205 other const functions (e.g., sizeHint()).
10206
10207 \sa event()
10208*/
10209void QWidget::ensurePolished() const
10210{
10211 Q_D(const QWidget);
10212
10213 const QMetaObject *m = metaObject();
10214 if (m == d->polished)
10215 return;
10216 d->polished = m;
10217
10218 QEvent e(QEvent::Polish);
10219 QCoreApplication::sendEvent(const_cast<QWidget *>(this), &e);
10220
10221 // polish children after 'this'
10222 QList<QObject*> children = d->children;
10223 for (int i = 0; i < children.size(); ++i) {
10224 QObject *o = children.at(i);
10225 if (!o->isWidgetType())
10226 continue;
10227 if (QWidget *w = qobject_cast<QWidget *>(o))
10228 w->ensurePolished();
10229 }
10230
10231 if (d->parent && d->sendChildEvents) {
10232 QChildEvent e(QEvent::ChildPolished, const_cast<QWidget *>(this));
10233 QCoreApplication::sendEvent(d->parent, &e);
10234 }
10235}
10236
10237/*!
10238 Returns the mask currently set on a widget. If no mask is set the
10239 return value will be an empty region.
10240
10241 \sa setMask(), clearMask(), QRegion::isEmpty()
10242*/
10243QRegion QWidget::mask() const
10244{
10245 Q_D(const QWidget);
10246 return d->extra ? d->extra->mask : QRegion();
10247}
10248
10249/*!
10250 Returns the layout manager that is installed on this widget, or \nullptr
10251 if no layout manager is installed.
10252
10253 The layout manager sets the geometry of the widget's children
10254 that have been added to the layout.
10255
10256 \sa setLayout(), sizePolicy(), {Layout Management}
10257*/
10258QLayout *QWidget::layout() const
10259{
10260 return d_func()->layout;
10261}
10262
10263
10264/*!
10265 \fn void QWidget::setLayout(QLayout *layout)
10266
10267 Sets the layout manager for this widget to \a layout.
10268
10269 If there already is a layout manager installed on this widget,
10270 QWidget won't let you install another. You must first delete the
10271 existing layout manager (returned by layout()) before you can
10272 call setLayout() with the new layout.
10273
10274 If \a layout is the layout manager on a different widget, setLayout()
10275 will reparent the layout and make it the layout manager for this widget.
10276
10277 Example:
10278
10279 \snippet layouts/layouts.cpp 24
10280
10281 An alternative to calling this function is to pass this widget to
10282 the layout's constructor.
10283
10284 The QWidget will take ownership of \a layout.
10285
10286 \sa layout(), {Layout Management}
10287*/
10288
10289void QWidget::setLayout(QLayout *l)
10290{
10291 if (Q_UNLIKELY(!l)) {
10292 qWarning("QWidget::setLayout: Cannot set layout to 0");
10293 return;
10294 }
10295 if (layout()) {
10296 if (Q_UNLIKELY(layout() != l))
10297 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", which already has a"
10298 " layout", l->objectName().toLocal8Bit().data(), metaObject()->className(),
10299 objectName().toLocal8Bit().data());
10300 return;
10301 }
10302
10303 QObject *oldParent = l->parent();
10304 if (oldParent && oldParent != this) {
10305 if (oldParent->isWidgetType()) {
10306 // Steal the layout off a widget parent. Takes effect when
10307 // morphing laid-out container widgets in Designer.
10308 QWidget *oldParentWidget = static_cast<QWidget *>(oldParent);
10309 oldParentWidget->takeLayout();
10310 } else {
10311 qWarning("QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
10312 l->objectName().toLocal8Bit().data(), metaObject()->className(),
10313 objectName().toLocal8Bit().data());
10314 return;
10315 }
10316 }
10317
10318 Q_D(QWidget);
10319 l->d_func()->topLevel = true;
10320 d->layout = l;
10321 if (oldParent != this) {
10322 l->setParent(this);
10323 l->d_func()->reparentChildWidgets(this);
10324 l->invalidate();
10325 }
10326
10327 if (isWindow() && d->maybeTopData())
10328 d->topData()->sizeAdjusted = false;
10329}
10330
10331/*!
10332 \fn QLayout *QWidget::takeLayout()
10333
10334 Remove the layout from the widget.
10335 \since 4.5
10336*/
10337
10338QLayout *QWidget::takeLayout()
10339{
10340 Q_D(QWidget);
10341 QLayout *l = layout();
10342 if (!l)
10343 return nullptr;
10344 d->layout = nullptr;
10345 l->setParent(nullptr);
10346 return l;
10347}
10348
10349/*!
10350 \property QWidget::sizePolicy
10351 \brief the default layout behavior of the widget
10352
10353 If there is a QLayout that manages this widget's children, the
10354 size policy specified by that layout is used. If there is no such
10355 QLayout, the result of this function is used.
10356
10357 The default policy is Preferred/Preferred, which means that the
10358 widget can be freely resized, but prefers to be the size
10359 sizeHint() returns. Button-like widgets set the size policy to
10360 specify that they may stretch horizontally, but are fixed
10361 vertically. The same applies to lineedit controls (such as
10362 QLineEdit, QSpinBox or an editable QComboBox) and other
10363 horizontally orientated widgets (such as QProgressBar).
10364 QToolButton's are normally square, so they allow growth in both
10365 directions. Widgets that support different directions (such as
10366 QSlider, QScrollBar or QHeader) specify stretching in the
10367 respective direction only. Widgets that can provide scroll bars
10368 (usually subclasses of QScrollArea) tend to specify that they can
10369 use additional space, and that they can make do with less than
10370 sizeHint().
10371
10372 \sa sizeHint(), QLayout, QSizePolicy, updateGeometry()
10373*/
10374QSizePolicy QWidget::sizePolicy() const
10375{
10376 Q_D(const QWidget);
10377 return d->size_policy;
10378}
10379
10380void QWidget::setSizePolicy(QSizePolicy policy)
10381{
10382 Q_D(QWidget);
10383 setAttribute(Qt::WA_WState_OwnSizePolicy);
10384 if (policy == d->size_policy)
10385 return;
10386
10387 if (d->size_policy.retainSizeWhenHidden() != policy.retainSizeWhenHidden())
10388 d->retainSizeWhenHiddenChanged = 1;
10389
10390 d->size_policy = policy;
10391
10392#if QT_CONFIG(graphicsview)
10393 if (const auto &extra = d->extra) {
10394 if (extra->proxyWidget)
10395 extra->proxyWidget->setSizePolicy(policy);
10396 }
10397#endif
10398
10399 updateGeometry();
10400 d->retainSizeWhenHiddenChanged = 0;
10401
10402 if (isWindow() && d->maybeTopData())
10403 d->topData()->sizeAdjusted = false;
10404}
10405
10406/*!
10407 \fn void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
10408 \overload
10409
10410 Sets the size policy of the widget to \a horizontal and \a
10411 vertical, with standard stretch and no height-for-width.
10412
10413 \sa QSizePolicy::QSizePolicy()
10414*/
10415
10416/*!
10417 Returns the preferred height for this widget, given the width \a w.
10418
10419 If this widget has a layout, the default implementation returns
10420 the layout's preferred height. if there is no layout, the default
10421 implementation returns -1 indicating that the preferred height
10422 does not depend on the width.
10423*/
10424
10425int QWidget::heightForWidth(int w) const
10426{
10427 if (layout() && layout()->hasHeightForWidth())
10428 return layout()->totalHeightForWidth(w);
10429 return -1;
10430}
10431
10432
10433/*!
10434 \since 5.0
10435
10436 Returns \c true if the widget's preferred height depends on its width; otherwise returns \c false.
10437*/
10438bool QWidget::hasHeightForWidth() const
10439{
10440 Q_D(const QWidget);
10441 return d->layout ? d->layout->hasHeightForWidth() : d->size_policy.hasHeightForWidth();
10442}
10443
10444/*!
10445 \fn QWidget *QWidget::childAt(int x, int y) const
10446
10447 Returns the visible child widget at the position (\a{x}, \a{y})
10448 in the widget's coordinate system. If there is no visible child
10449 widget at the specified position, the function returns \nullptr.
10450*/
10451
10452/*!
10453 \overload
10454
10455 Returns the visible child widget at point \a p in the widget's own
10456 coordinate system.
10457*/
10458
10459QWidget *QWidget::childAt(const QPoint &p) const
10460{
10461 return d_func()->childAt_helper(QPointF(p), false);
10462}
10463
10464/*!
10465 \overload
10466 \since 6.8
10467
10468 Returns the visible child widget at point \a p in the widget's own
10469 coordinate system.
10470*/
10471
10472QWidget *QWidget::childAt(const QPointF &p) const
10473{
10474 return d_func()->childAt_helper(p, false);
10475}
10476
10477QWidget *QWidgetPrivate::childAt_helper(const QPointF &p, bool ignoreChildrenInDestructor) const
10478{
10479 if (children.isEmpty())
10480 return nullptr;
10481
10482 if (!pointInsideRectAndMask(p))
10483 return nullptr;
10484 return childAtRecursiveHelper(p, ignoreChildrenInDestructor);
10485}
10486
10487QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPointF &p, bool ignoreChildrenInDestructor) const
10488{
10489 for (int i = children.size() - 1; i >= 0; --i) {
10490 QWidget *child = qobject_cast<QWidget *>(children.at(i));
10491 if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents)
10492 || (ignoreChildrenInDestructor && child->data->in_destructor)) {
10493 continue;
10494 }
10495
10496 // Map the point 'p' from parent coordinates to child coordinates.
10497 QPointF childPoint = p;
10498 childPoint -= child->data->crect.topLeft();
10499
10500 // Check if the point hits the child.
10501 if (!child->d_func()->pointInsideRectAndMask(childPoint))
10502 continue;
10503
10504 // Do the same for the child's descendants.
10505 if (QWidget *w = child->d_func()->childAtRecursiveHelper(childPoint, ignoreChildrenInDestructor))
10506 return w;
10507
10508 // We have found our target; namely the child at position 'p'.
10509 return child;
10510 }
10511 return nullptr;
10512}
10513
10514void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
10515{
10516 Q_Q(QWidget);
10517 if (widgetItem)
10518 widgetItem->invalidateSizeCache();
10519 QWidget *parent;
10520 if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
10521 const int isHidden = q->isHidden() && !size_policy.retainSizeWhenHidden() && !retainSizeWhenHiddenChanged;
10522
10523 if (!q->isWindow() && !isHidden && (parent = q->parentWidget())) {
10524 if (parent->d_func()->layout)
10525 parent->d_func()->layout->invalidate();
10526 else if (parent->isVisible())
10527 QCoreApplication::postEvent(parent, new QEvent(QEvent::LayoutRequest));
10528 }
10529 }
10530}
10531
10532/*!
10533 Notifies the layout system that this widget has changed and may
10534 need to change geometry.
10535
10536 Call this function if the sizeHint() or sizePolicy() have changed.
10537
10538 For explicitly hidden widgets, updateGeometry() is a no-op. The
10539 layout system will be notified as soon as the widget is shown.
10540*/
10541
10542void QWidget::updateGeometry()
10543{
10544 Q_D(QWidget);
10545 d->updateGeometry_helper(false);
10546}
10547
10548/*! \property QWidget::windowFlags
10549
10550 Window flags are a combination of a type (e.g. Qt::Dialog) and
10551 zero or more hints to the window system (e.g.
10552 Qt::FramelessWindowHint).
10553
10554 If the widget had type Qt::Widget or Qt::SubWindow and becomes a
10555 window (Qt::Window, Qt::Dialog, etc.), it is put at position (0,
10556 0) on the desktop. If the widget is a window and becomes a
10557 Qt::Widget or Qt::SubWindow, it is put at position (0, 0)
10558 relative to its parent widget.
10559
10560 \note This function calls setParent() when changing the flags for
10561 a window, causing the widget to be hidden. You must call show() to make
10562 the widget visible again..
10563
10564 \sa windowType(), setWindowFlag(), {Window Flags Example}
10565*/
10566void QWidget::setWindowFlags(Qt::WindowFlags flags)
10567{
10568 Q_D(QWidget);
10569 d->setWindowFlags(flags);
10570}
10571
10572/*!
10573 \since 5.9
10574
10575 Sets the window flag \a flag on this widget if \a on is true;
10576 otherwise clears the flag.
10577
10578 \note This function calls setParent() when changing the flags for
10579 a window, causing the widget to be hidden. You must call show() to make
10580 the widget visible again.
10581
10582 \sa setWindowFlags(), windowFlags(), windowType()
10583*/
10584void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
10585{
10586 Q_D(QWidget);
10587 if (on)
10588 d->setWindowFlags(data->window_flags | flag);
10589 else
10590 d->setWindowFlags(data->window_flags & ~flag);
10591}
10592
10593/*! \internal
10594
10595 Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
10596*/
10597void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
10598{
10599 Q_Q(QWidget);
10600#if QT_DEPRECATED_SINCE(6, 11)
10601 QT_IGNORE_DEPRECATIONS(
10602 if ((flags & Qt::WindowType_Mask) == Qt::WindowType::Desktop) {
10603 qWarning() << "Qt::WindowType::Desktop has been deprecated in Qt 6. Ignoring.";
10604 flags.setFlag(Qt::WindowType::Desktop, false);
10605 }
10606 )
10607#endif
10608
10609 if (q->data->window_flags == flags)
10610 return;
10611
10612 if ((q->data->window_flags | flags) & Qt::Window) {
10613 // the old type was a window and/or the new type is a window
10614 QPoint oldPos = q->pos();
10615 bool visible = q->isVisible();
10616 const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
10617 q->setParent(q->parentWidget(), flags);
10618
10619 // if both types are windows or neither of them are, we restore
10620 // the old position
10621 if (!windowFlagChanged && (visible || q->testAttribute(Qt::WA_Moved)))
10622 q->move(oldPos);
10623 // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
10624 adjustQuitOnCloseAttribute();
10625 } else {
10626 q->data->window_flags = flags;
10627 }
10628}
10629
10630/*!
10631 Sets the window flags for the widget to \a flags,
10632 \e without telling the window system.
10633
10634 \warning Do not call this function unless you really know what
10635 you're doing.
10636
10637 \sa setWindowFlags()
10638*/
10639void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
10640{
10641 data->window_flags = flags;
10642}
10643
10644/*!
10645 \fn Qt::WindowType QWidget::windowType() const
10646
10647 Returns the window type of this widget. This is identical to
10648 windowFlags() & Qt::WindowType_Mask.
10649
10650 \sa windowFlags
10651*/
10652
10653/*!
10654 Sets the parent of the widget to \a parent, and resets the window
10655 flags. The widget is moved to position (0, 0) in its new parent.
10656
10657 If the new parent widget is in a different window, the
10658 reparented widget and its children are appended to the end of the
10659 \l{setFocusPolicy()}{tab chain} of the new parent
10660 widget, in the same internal order as before. If one of the moved
10661 widgets had keyboard focus, setParent() calls clearFocus() for that
10662 widget.
10663
10664 If the new parent widget is in the same window as the
10665 old parent, setting the parent doesn't change the tab order or
10666 keyboard focus.
10667
10668 If the "new" parent widget is the old parent widget, this function
10669 does nothing.
10670
10671 \note The widget becomes invisible as part of changing its parent,
10672 even if it was previously visible. You must call show() to make the
10673 widget visible again.
10674
10675 \warning It is very unlikely that you will ever need this
10676 function. If you have a widget that changes its content
10677 dynamically, it is far easier to use \l QStackedWidget.
10678
10679 \sa setWindowFlags()
10680*/
10681void QWidget::setParent(QWidget *parent)
10682{
10683 if (parent == parentWidget())
10684 return;
10685 setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask);
10686}
10687
10688void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType)
10689{
10690 QWidgetPrivate *d = QWidgetPrivate::get(widget);
10691 if (d->renderToTexture) {
10692 QEvent e(eventType);
10693 QCoreApplication::sendEvent(widget, &e);
10694 }
10695
10696 for (int i = 0; i < d->children.size(); ++i) {
10697 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
10698 if (w && !w->isWindow())
10699 qSendWindowChangeToTextureChildrenRecursively(w, eventType);
10700 }
10701
10702 // Notify QWidgetWindow after we've notified all child QWidgets
10703 if (auto *window = d->windowHandle(QWidgetPrivate::WindowHandleMode::Direct)) {
10704 QEvent e(eventType);
10705 QCoreApplication::sendEvent(window, &e);
10706 }
10707}
10708
10709/*!
10710 \overload
10711
10712 This function also takes widget flags, \a f as an argument.
10713*/
10714
10715void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
10716{
10717 Q_D(QWidget);
10718 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
10719#ifdef QT_DEBUG
10720 const auto checkForParentChildLoops = qScopeGuard([&](){
10721 int depth = 0;
10722 auto p = parentWidget();
10723 while (p) {
10724 if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
10725 qWarning("QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
10726 "this is undefined behavior",
10727 this, metaObject()->className(), qPrintable(objectName()));
10728 }
10729 p = p->parentWidget();
10730 }
10731 });
10732#endif
10733
10734 const bool resized = testAttribute(Qt::WA_Resized);
10735 const bool wasCreated = testAttribute(Qt::WA_WState_Created);
10736 QWidget *oldtlw = window();
10737 Q_ASSERT(oldtlw);
10738 QWidget *oldParentWithWindow = d->closestParentWidgetWithWindowHandle();
10739
10740 if (f & Qt::Window) // Frame geometry likely changes, refresh.
10741 d->data.fstrut_dirty = true;
10742
10743 bool newParent = (parent != parentWidget());
10744
10745 if (newParent && parent) {
10746 if (testAttribute(Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
10747 parent->d_func()->enforceNativeChildren();
10748 else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(Qt::WA_PaintOnScreen))
10749 setAttribute(Qt::WA_NativeWindow);
10750 }
10751
10752 if (wasCreated) {
10753 if (!testAttribute(Qt::WA_WState_Hidden)) {
10754 // Hiding the widget will set WA_WState_Hidden as well, which would
10755 // normally require the widget to be explicitly shown again to become
10756 // visible, even as a child widget. But we refine this value later in
10757 // setParent_sys(), applying WA_WState_Hidden based on whether the
10758 // widget is a top level or not.
10759 hide();
10760
10761 // We reset WA_WState_ExplicitShowHide here, likely as a remnant of
10762 // when we only had QWidget::setVisible(), which is treated as an
10763 // explicit show/hide. Nowadays we have QWidgetPrivate::setVisible(),
10764 // that allows us to hide a widget without affecting ExplicitShowHide.
10765 // Though it can be argued that ExplicitShowHide should reflect the
10766 // last update of the widget's state, so if we hide the widget as a
10767 // side effect of changing parent, perhaps we _should_ reset it?
10768 setAttribute(Qt::WA_WState_ExplicitShowHide, false);
10769 }
10770 if (newParent) {
10771 QEvent e(QEvent::ParentAboutToChange);
10772 QCoreApplication::sendEvent(this, &e);
10773 }
10774 }
10775
10776 // texture-based widgets need a pre-notification when their associated top-level window changes
10777 // This is not under the wasCreated/newParent conditions above in order to also play nice with QDockWidget.
10778 const bool oldWidgetUsesRhiFlush = oldParentWithWindow ? oldParentWithWindow->d_func()->usesRhiFlush
10779 : oldtlw->d_func()->usesRhiFlush;
10780 if (oldWidgetUsesRhiFlush && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw)))
10781 qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowAboutToChangeInternal);
10782
10783 // If we get parented into another window, children will be folded
10784 // into the new parent's focus chain, so clear focus now.
10785 if (newParent && isAncestorOf(focusWidget()) && !(f & Qt::Window))
10786 focusWidget()->clearFocus();
10787
10788 d->setParent_sys(parent, f);
10789
10790 if (d->textureChildSeen && parent) {
10791 // set the textureChildSeen flag up the whole parent chain
10792 QWidgetPrivate::get(parent)->setTextureChildSeen();
10793 }
10794
10795 if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
10796 if (newParent)
10797 oldPaintManager->removeDirtyWidget(this);
10798 // Move the widget and all its static children from
10799 // the old backing store to the new one.
10800 oldPaintManager->moveStaticWidgets(this);
10801 }
10802
10803 d->reparentFocusWidgets(oldtlw);
10804 setAttribute(Qt::WA_Resized, resized);
10805
10806 const bool useStyleSheetPropagationInWidgetStyles =
10807 QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
10808
10809 if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(Qt::WA_StyleSheet)
10810 && (!parent || !parent->testAttribute(Qt::WA_StyleSheet))) {
10811 // if the parent has a font set or inherited, then propagate the mask to the new child
10812 if (parent) {
10813 const auto pd = parent->d_func();
10814 d->inheritedFontResolveMask = pd->directFontResolveMask | pd->inheritedFontResolveMask;
10815 d->inheritedPaletteResolveMask = pd->directPaletteResolveMask | pd->inheritedPaletteResolveMask;
10816 }
10817 d->resolveFont();
10818 d->resolvePalette();
10819 }
10820 d->resolveLayoutDirection();
10821 d->resolveLocale();
10822
10823 // Note: GL widgets under WGL or EGL will always need a ParentChange
10824 // event to handle recreation/rebinding of the GL context, hence the
10825 // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
10826 // platforms).
10827 if (newParent || !wasCreated
10828#if QT_CONFIG(opengles2)
10829 || (f & Qt::MSWindowsOwnDC)
10830#endif
10831 ) {
10832 // propagate enabled updates enabled state to non-windows
10833 if (!isWindow()) {
10834 if (!testAttribute(Qt::WA_ForceDisabled))
10835 d->setEnabled_helper(parent ? parent->isEnabled() : true);
10836 if (!testAttribute(Qt::WA_ForceUpdatesDisabled))
10837 d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
10838 }
10839 d->inheritStyle();
10840
10841 // send and post remaining QObject events
10842 if (parent && d->sendChildEvents) {
10843 QChildEvent e(QEvent::ChildAdded, this);
10844 QCoreApplication::sendEvent(parent, &e);
10845 }
10846
10847 if (parent && d->sendChildEvents && d->polished) {
10848 QChildEvent e(QEvent::ChildPolished, this);
10849 QCoreApplication::sendEvent(parent, &e);
10850 }
10851
10852 QEvent e(QEvent::ParentChange);
10853 QCoreApplication::sendEvent(this, &e);
10854 }
10855
10856 // texture-based widgets need another event when their top-level window
10857 // changes (more precisely, has already changed at this point)
10858 if (oldWidgetUsesRhiFlush && oldtlw != window())
10859 qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowChangeInternal);
10860
10861 if (!wasCreated) {
10862 if (isWindow() || parentWidget()->isVisible())
10863 setAttribute(Qt::WA_WState_Hidden, true);
10864 else if (!testAttribute(Qt::WA_WState_ExplicitShowHide))
10865 setAttribute(Qt::WA_WState_Hidden, false);
10866 }
10867
10868 d->updateIsOpaque();
10869
10870#if QT_CONFIG(graphicsview)
10871 // Embed the widget into a proxy if the parent is embedded.
10872 // ### Doesn't handle reparenting out of an embedded widget.
10873 if (oldtlw->graphicsProxyWidget()) {
10874 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(oldtlw))
10875 ancestorProxy->d_func()->unembedSubWindow(this);
10876 }
10877 if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(this)) {
10878 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(parent))
10879 ancestorProxy->d_func()->embedSubWindow(this);
10880 }
10881#endif
10882
10883 if (d->extra && d->extra->hasWindowContainer)
10884 QWindowContainer::parentWasChanged(this);
10885
10886 QWidget *newParentWithWindow = d->closestParentWidgetWithWindowHandle();
10887 if (newParentWithWindow && newParentWithWindow != oldParentWithWindow) {
10888 // Check if the native parent now needs to switch to RHI
10889 qCDebug(lcWidgetPainting) << "Evaluating whether reparenting of" << this
10890 << "into" << parent << "requires RHI enablement for" << newParentWithWindow;
10891
10892 QPlatformBackingStoreRhiConfig rhiConfig;
10893 QSurface::SurfaceType surfaceType = QSurface::RasterSurface;
10894
10895 // First evaluate whether the reparented widget uses RHI.
10896 // We do this as a separate step because the performance
10897 // implications of always checking the native parent are
10898 // problematic when it comes to large widget trees.
10899 if (q_evaluateRhiConfig(this, &rhiConfig, &surfaceType)) {
10900 // Then check whether the native parent requires RHI
10901 // as a result. It may not, if this widget is a native
10902 // window, and can handle its own RHI flushing.
10903 if (q_evaluateRhiConfig(newParentWithWindow, nullptr, nullptr)) {
10904 // Finally, check whether we need to recreate the
10905 // native parent to enable RHI flushing.
10906 auto *existingWindow = newParentWithWindow->windowHandle();
10907 auto existingSurfaceType = existingWindow->surfaceType();
10908 if (existingSurfaceType != surfaceType) {
10909 qCDebug(lcWidgetPainting)
10910 << "Recreating" << existingWindow
10911 << "with current type" << existingSurfaceType
10912 << "to support" << surfaceType;
10913 const auto windowStateBeforeDestroy = newParentWithWindow->windowState();
10914 const auto visibilityBeforeDestroy = newParentWithWindow->isVisible();
10915 const auto positionBeforeDestroy = newParentWithWindow->pos();
10916 newParentWithWindow->d_func()->recreate();
10917 Q_ASSERT(newParentWithWindow->windowHandle());
10918 newParentWithWindow->windowHandle()->setWindowStates(windowStateBeforeDestroy);
10919 newParentWithWindow->move(positionBeforeDestroy);
10920 QWidgetPrivate::get(newParentWithWindow)->setVisible(visibilityBeforeDestroy);
10921 } else if (auto *backingStore = newParentWithWindow->backingStore()) {
10922 // If we don't recreate we still need to make sure the native parent
10923 // widget has a RHI config that the reparented widget can use.
10924 backingStore->handle()->createRhi(existingWindow, rhiConfig);
10925 // And that it knows it's now flushing with RHI
10926 QWidgetPrivate::get(newParentWithWindow)->usesRhiFlush = true;
10927 }
10928 }
10929 }
10930 }
10931
10932#if QT_CONFIG(accessibility)
10933 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing) {
10934 QAccessibleEvent qaEvent(this, QAccessible::ParentChanged);
10935 QAccessible::updateAccessibility(&qaEvent);
10936 }
10937#endif
10938
10939}
10940
10941void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
10942{
10943 Q_Q(QWidget);
10944
10945 Qt::WindowFlags oldFlags = data.window_flags;
10946 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
10947
10948 QScreen *targetScreen = nullptr;
10949 setWinId(0);
10950
10951 if (!newparent) {
10952 f |= Qt::Window;
10953 if (parent)
10954 targetScreen = q->parentWidget()->window()->screen();
10955 }
10956
10957 const bool destroyWindow = (
10958 // Reparenting top level to child
10959 (oldFlags & Qt::Window) && !(f & Qt::Window)
10960 // And we can dispose of the window
10961 && wasCreated && !q->testAttribute(Qt::WA_NativeWindow)
10962 );
10963
10964 if (parent != newparent) {
10965 // Update object parent now, so we can resolve new parent window below
10966 QObjectPrivate::setParent_helper(newparent);
10967
10968 if (q->windowHandle())
10969 q->windowHandle()->setFlags(f);
10970
10971 // If the widget itself or any of its children have been created,
10972 // we need to reparent their QWindows as well.
10973 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
10974 // But if the widget is about to be destroyed we must skip the
10975 // widget itself, and only reparent children.
10976 if (destroyWindow) {
10977 reparentWidgetWindowChildren(parentWithWindow);
10978 } else {
10979 // During reparentWidgetWindows() we need to know whether the reparented
10980 // QWindow should be a top level (with a transient parent) or not. This
10981 // widget has not updated its window flags yet, so we can't ask the widget
10982 // directly at that point. Nor can we use the QWindow flags, as unlike QWidgets
10983 // the QWindow flags always reflect Qt::Window, even for child windows. And
10984 // we can't use QWindow::isTopLevel() either, as that depends on the parent,
10985 // which we are in the process of updating. So we propagate the
10986 // new flags of the reparented window here.
10987 reparentWidgetWindows(parentWithWindow, f);
10988 }
10989 }
10990
10991 bool explicitlyHidden = isExplicitlyHidden();
10992
10993 if (destroyWindow) {
10994 if (extra && extra->hasWindowContainer)
10995 QWindowContainer::toplevelAboutToBeDestroyed(q);
10996
10997 // There shouldn't be any QWindow children left, but if there
10998 // are, re-parent them now, before we destroy.
10999 if (!q->windowHandle()->children().isEmpty()) {
11000 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
11001 QWindow *newParentWindow = parentWithWindow ? parentWithWindow->windowHandle() : nullptr;
11002 for (QObject *child : q->windowHandle()->children()) {
11003 if (QWindow *childWindow = qobject_cast<QWindow *>(child)) {
11004 qCWarning(lcWidgetWindow) << "Reparenting" << childWindow
11005 << "before destroying" << this;
11006 childWindow->setParent(newParentWindow);
11007 }
11008 }
11009 }
11010
11011 // We have reparented any child windows of the widget we are
11012 // about to destroy to the new parent window handle, so we can
11013 // safely destroy this widget without destroying sub windows.
11014 q->destroy(true, false);
11015 }
11016
11017 adjustFlags(f, q);
11018 data.window_flags = f;
11019 q->setAttribute(Qt::WA_WState_Created, false);
11020 q->setAttribute(Qt::WA_WState_Visible, false);
11021 q->setAttribute(Qt::WA_WState_Hidden, false);
11022
11023 if (newparent && wasCreated && (q->testAttribute(Qt::WA_NativeWindow) || (f & Qt::Window)))
11024 q->createWinId();
11025
11026 if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
11027 q->setAttribute(Qt::WA_WState_Hidden);
11028 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
11029
11030 // move the window to the selected screen
11031 if (!newparent && targetScreen) {
11032 // only if it is already created
11033 if (q->testAttribute(Qt::WA_WState_Created))
11034 q->windowHandle()->setScreen(targetScreen);
11035 else
11036 topData()->initialScreen = targetScreen;
11037 }
11038}
11039
11040void QWidgetPrivate::reparentWidgetWindows(QWidget *parentWithWindow, Qt::WindowFlags windowFlags)
11041{
11042 if (QWindow *window = windowHandle()) {
11043 // Reparent this QWindow, and all QWindow children will follow
11044 if (parentWithWindow) {
11045 if (windowFlags & Qt::Window) {
11046 // Top level windows can only have transient parents,
11047 // and the transient parent must be another top level.
11048 QWidget *topLevel = parentWithWindow->window();
11049 auto *transientParent = topLevel->windowHandle();
11050 Q_ASSERT(transientParent);
11051 qCDebug(lcWidgetWindow) << "Setting" << window << "transient parent to" << transientParent;
11052 window->setTransientParent(transientParent);
11053 window->setParent(nullptr);
11054 } else {
11055 auto *parentWindow = parentWithWindow->windowHandle();
11056 qCDebug(lcWidgetWindow) << "Reparenting" << window << "into" << parentWindow;
11057 window->setTransientParent(nullptr);
11058 window->setParent(parentWindow);
11059 }
11060 } else {
11061 qCDebug(lcWidgetWindow) << "Making" << window << "top level window";
11062 window->setTransientParent(nullptr);
11063 window->setParent(nullptr);
11064 }
11065 } else {
11066 reparentWidgetWindowChildren(parentWithWindow);
11067 }
11068}
11069
11070void QWidgetPrivate::reparentWidgetWindowChildren(QWidget *parentWithWindow)
11071{
11072 for (auto *child : std::as_const(children)) {
11073 if (auto *childWidget = qobject_cast<QWidget*>(child)) {
11074 auto *childPrivate = QWidgetPrivate::get(childWidget);
11075 // Child widgets with QWindows should always continue to be child
11076 // windows, so we pass on the child's current window flags here.
11077 childPrivate->reparentWidgetWindows(parentWithWindow, childWidget->windowFlags());
11078 }
11079 }
11080}
11081
11082/*!
11083 Scrolls the widget including its children \a dx pixels to the
11084 right and \a dy downward. Both \a dx and \a dy may be negative.
11085
11086 After scrolling, the widgets will receive paint events for
11087 the areas that need to be repainted. For widgets that Qt knows to
11088 be opaque, this is only the newly exposed parts.
11089 For example, if an opaque widget is scrolled 8 pixels to the left,
11090 only an 8-pixel wide stripe at the right edge needs updating.
11091
11092 Since widgets propagate the contents of their parents by default,
11093 you need to set the \l autoFillBackground property, or use
11094 setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
11095 a widget opaque.
11096
11097 For widgets that use contents propagation, a scroll will cause an
11098 update of the entire scroll area.
11099
11100 \sa {Transparency and Double Buffering}
11101*/
11102
11103void QWidget::scroll(int dx, int dy)
11104{
11105 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11106 return;
11107 if (dx == 0 && dy == 0)
11108 return;
11109 Q_D(QWidget);
11110#if QT_CONFIG(graphicsview)
11111 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
11112 // Graphics View maintains its own dirty region as a list of rects;
11113 // until we can connect item updates directly to the view, we must
11114 // separately add a translated dirty region.
11115 for (const QRect &rect : d->dirty)
11116 proxy->update(rect.translated(dx, dy));
11117 proxy->scroll(dx, dy, proxy->subWidgetRect(this));
11118 d->scrollChildren(dx, dy); // QTBUG-138381: scroll item view cell widgets
11119 return;
11120 }
11121#endif
11122 d->setDirtyOpaqueRegion();
11123 d->scroll_sys(dx, dy);
11124}
11125
11126void QWidgetPrivate::scroll_sys(int dx, int dy)
11127{
11128 Q_Q(QWidget);
11129 scrollChildren(dx, dy);
11130 scrollRect(q->rect(), dx, dy);
11131}
11132
11133/*!
11134 \overload
11135
11136 This version only scrolls \a r and does not move the children of
11137 the widget.
11138
11139 If \a r is empty or invalid, the result is undefined.
11140
11141 \sa QScrollArea
11142*/
11143void QWidget::scroll(int dx, int dy, const QRect &r)
11144{
11145
11146 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11147 return;
11148 if (dx == 0 && dy == 0)
11149 return;
11150 Q_D(QWidget);
11151#if QT_CONFIG(graphicsview)
11152 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(this)) {
11153 // Graphics View maintains its own dirty region as a list of rects;
11154 // until we can connect item updates directly to the view, we must
11155 // separately add a translated dirty region.
11156 if (!d->dirty.isEmpty()) {
11157 for (const QRect &rect : d->dirty.translated(dx, dy) & r)
11158 proxy->update(rect);
11159 }
11160 proxy->scroll(dx, dy, r.translated(proxy->subWidgetRect(this).topLeft().toPoint()));
11161 return;
11162 }
11163#endif
11164 d->scroll_sys(dx, dy, r);
11165}
11166
11167void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
11168{
11169 scrollRect(r, dx, dy);
11170}
11171
11172/*!
11173 Repaints the widget directly by calling paintEvent() immediately,
11174 unless updates are disabled or the widget is hidden.
11175
11176 We suggest only using repaint() if you need an immediate repaint,
11177 for example during animation. In most circumstances update()
11178 is better, as it permits Qt to optimize for speed and minimize
11179 flicker.
11180
11181 \warning If you call repaint() in a function which may itself be
11182 called from paintEvent(), you may get infinite recursion. The
11183 update() function never causes recursion.
11184
11185 \sa update(), paintEvent(), setUpdatesEnabled()
11186*/
11187
11188void QWidget::repaint()
11189{
11190 repaint(rect());
11191}
11192
11193/*! \overload
11194
11195 This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
11196 the widget.
11197
11198 If \a w is negative, it is replaced with \c{width() - x}, and if
11199 \a h is negative, it is replaced width \c{height() - y}.
11200*/
11201void QWidget::repaint(int x, int y, int w, int h)
11202{
11203 if (x > data->crect.width() || y > data->crect.height())
11204 return;
11205
11206 if (w < 0)
11207 w = data->crect.width() - x;
11208 if (h < 0)
11209 h = data->crect.height() - y;
11210
11211 repaint(QRect(x, y, w, h));
11212}
11213
11214/*! \overload
11215
11216 This version repaints a rectangle \a rect inside the widget.
11217*/
11218void QWidget::repaint(const QRect &rect)
11219{
11220 Q_D(QWidget);
11221 d->repaint(rect);
11222}
11223
11224/*!
11225 \overload
11226
11227 This version repaints a region \a rgn inside the widget.
11228*/
11229void QWidget::repaint(const QRegion &rgn)
11230{
11231 Q_D(QWidget);
11232 d->repaint(rgn);
11233}
11234
11235template <typename T>
11236void QWidgetPrivate::repaint(T r)
11237{
11238 Q_Q(QWidget);
11239
11240 if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
11241 return;
11242
11243 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11244 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11245 tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
11246}
11247
11248/*!
11249 Updates the widget unless updates are disabled or the widget is
11250 hidden.
11251
11252 This function does not cause an immediate repaint; instead it
11253 schedules a paint event for processing when Qt returns to the main
11254 event loop. This permits Qt to optimize for more speed and less
11255 flicker than a call to repaint() does.
11256
11257 Calling update() several times normally results in just one
11258 paintEvent() call.
11259
11260 Qt normally erases the widget's area before the paintEvent() call.
11261 If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
11262 responsible for painting all its pixels with an opaque color.
11263
11264 \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock}
11265*/
11266void QWidget::update()
11267{
11268 update(rect());
11269}
11270
11271/*! \fn void QWidget::update(int x, int y, int w, int h)
11272 \overload
11273
11274 This version updates a rectangle (\a x, \a y, \a w, \a h) inside
11275 the widget.
11276*/
11277
11278/*!
11279 \overload
11280
11281 This version updates a rectangle \a rect inside the widget.
11282*/
11283void QWidget::update(const QRect &rect)
11284{
11285 Q_D(QWidget);
11286 d->update(rect);
11287}
11288
11289/*!
11290 \overload
11291
11292 This version repaints a region \a rgn inside the widget.
11293*/
11294void QWidget::update(const QRegion &rgn)
11295{
11296 Q_D(QWidget);
11297 d->update(rgn);
11298}
11299
11300template <typename T>
11301void QWidgetPrivate::update(T r)
11302{
11303 Q_Q(QWidget);
11304
11305 if (renderToTexture && !q->isVisible()) {
11306 renderToTextureReallyDirty = 1;
11307 return;
11308 }
11309
11310 if (!q->isVisible() || !q->updatesEnabled())
11311 return;
11312
11313 T clipped = r & q->rect();
11314
11315 if (clipped.isEmpty())
11316 return;
11317
11318 if (q->testAttribute(Qt::WA_WState_InPaintEvent)) {
11319 QCoreApplication::postEvent(q, new QUpdateLaterEvent(clipped));
11320 return;
11321 }
11322
11323 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11324 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11325 tlwExtra->repaintManager->markDirty(clipped, q);
11326}
11327
11328 /*!
11329 \internal
11330
11331 This just sets the corresponding attribute bit to 1 or 0
11332 */
11333static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
11334 QWidgetPrivate *d)
11335{
11336 if (attribute < int(8*sizeof(uint))) {
11337 if (on)
11338 data->widget_attributes |= (1<<attribute);
11339 else
11340 data->widget_attributes &= ~(1<<attribute);
11341 } else {
11342 const int x = attribute - 8*sizeof(uint);
11343 const int int_off = x / (8*sizeof(uint));
11344 if (on)
11345 d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
11346 else
11347 d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
11348 }
11349}
11350
11351#ifdef Q_OS_MACOS
11352void QWidgetPrivate::macUpdateSizeAttribute()
11353{
11354 Q_Q(QWidget);
11355 QEvent event(QEvent::MacSizeChange);
11356 QCoreApplication::sendEvent(q, &event);
11357 for (int i = 0; i < children.size(); ++i) {
11358 QWidget *w = qobject_cast<QWidget *>(children.at(i));
11359 if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
11360 && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
11361 && !w->testAttribute(Qt::WA_MacSmallSize)
11362 && !w->testAttribute(Qt::WA_MacNormalSize))
11363 w->d_func()->macUpdateSizeAttribute();
11364 }
11365 resolveFont();
11366}
11367#endif
11368
11369/*!
11370 Sets the attribute \a attribute on this widget if \a on is true;
11371 otherwise clears the attribute.
11372
11373 \sa testAttribute()
11374*/
11375void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
11376{
11377 Q_D(QWidget);
11378
11379 if (attribute == Qt::WA_ContentsMarginsRespectsSafeArea) {
11380 if (isWindow()) {
11381 auto *topExtra = d->topData();
11382 topExtra->explicitContentsMarginsRespectsSafeArea = true;
11383 }
11384 }
11385
11386 if (testAttribute(attribute) == on)
11387 return;
11388
11389 static_assert(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
11390 "QWidget::setAttribute(WidgetAttribute, bool): "
11391 "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
11392#ifdef Q_OS_WIN
11393 // ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
11394 if (attribute == Qt::WA_PaintOnScreen && on && !inherits("QGLWidget")) {
11395 // see ::paintEngine for details
11396 paintEngine();
11397 if (d->noPaintOnScreen)
11398 return;
11399 }
11400#endif
11401
11402 // Don't set WA_NativeWindow on platforms that don't support it -- except for QGLWidget, which depends on it
11403 if (attribute == Qt::WA_NativeWindow && !d->mustHaveWindowHandle) {
11404 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
11405 if (!platformIntegration->hasCapability(QPlatformIntegration::NativeWidgets))
11406 return;
11407 }
11408
11409 setAttribute_internal(attribute, on, data, d);
11410
11411 switch (attribute) {
11412
11413#if QT_CONFIG(draganddrop)
11414 case Qt::WA_AcceptDrops: {
11415 if (on && !testAttribute(Qt::WA_DropSiteRegistered))
11416 setAttribute(Qt::WA_DropSiteRegistered, true);
11417 else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
11418 setAttribute(Qt::WA_DropSiteRegistered, false);
11419 QEvent e(QEvent::AcceptDropsChange);
11420 QCoreApplication::sendEvent(this, &e);
11421 break;
11422 }
11423 case Qt::WA_DropSiteRegistered: {
11424 for (int i = 0; i < d->children.size(); ++i) {
11425 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
11426 if (w && !w->isWindow() && !w->testAttribute(Qt::WA_AcceptDrops) && w->testAttribute(Qt::WA_DropSiteRegistered) != on)
11427 w->setAttribute(Qt::WA_DropSiteRegistered, on);
11428 }
11429 break;
11430 }
11431#endif
11432
11433 case Qt::WA_NoChildEventsForParent:
11434 d->sendChildEvents = !on;
11435 break;
11436 case Qt::WA_NoChildEventsFromChildren:
11437 d->receiveChildEvents = !on;
11438 break;
11439 case Qt::WA_MacNormalSize:
11440 case Qt::WA_MacSmallSize:
11441 case Qt::WA_MacMiniSize:
11442#ifdef Q_OS_MACOS
11443 {
11444 // We can only have one of these set at a time
11445 const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
11446 Qt::WA_MacMiniSize };
11447 for (int i = 0; i < 3; ++i) {
11448 if (MacSizes[i] != attribute)
11449 setAttribute_internal(MacSizes[i], false, data, d);
11450 }
11451 d->macUpdateSizeAttribute();
11452 }
11453#endif
11454 break;
11455 case Qt::WA_ShowModal:
11456 if (!on) {
11457 // reset modality type to NonModal when clearing WA_ShowModal
11458 data->window_modality = Qt::NonModal;
11459 } else if (data->window_modality == Qt::NonModal) {
11460 // If modality hasn't been set prior to setting WA_ShowModal, use
11461 // ApplicationModal.
11462 data->window_modality = Qt::ApplicationModal;
11463 // Some window managers do not allow us to enter modality after the
11464 // window is visible.The window must be hidden before changing the
11465 // windowModality property and then reshown.
11466 }
11467 if (testAttribute(Qt::WA_WState_Created)) {
11468 // don't call setModal_sys() before create()
11469 d->setModal_sys();
11470 }
11471 break;
11472 case Qt::WA_MouseTracking: {
11473 QEvent e(QEvent::MouseTrackingChange);
11474 QCoreApplication::sendEvent(this, &e);
11475 break; }
11476 case Qt::WA_TabletTracking: {
11477 QEvent e(QEvent::TabletTrackingChange);
11478 QCoreApplication::sendEvent(this, &e);
11479 break; }
11480 case Qt::WA_NativeWindow: {
11481 d->createTLExtra();
11482 if (on)
11483 d->createTLSysExtra();
11484#ifndef QT_NO_IM
11485 QWidget *focusWidget = d->effectiveFocusWidget();
11486 if (on && !internalWinId() && this == QGuiApplication::focusObject()
11487 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11488 QGuiApplication::inputMethod()->commit();
11489 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11490 }
11491 if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
11492 parentWidget()->d_func()->enforceNativeChildren();
11493 if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
11494 d->createWinId();
11495 if (isEnabled() && focusWidget->isEnabled() && this == QGuiApplication::focusObject()
11496 && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
11497 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11498 }
11499#endif //QT_NO_IM
11500 break;
11501 }
11502 case Qt::WA_PaintOnScreen:
11503 d->updateIsOpaque();
11504 Q_FALLTHROUGH();
11505 case Qt::WA_OpaquePaintEvent:
11506 d->updateIsOpaque();
11507 break;
11508 case Qt::WA_NoSystemBackground:
11509 d->updateIsOpaque();
11510 Q_FALLTHROUGH();
11511 case Qt::WA_UpdatesDisabled:
11512 d->updateSystemBackground();
11513 break;
11514 case Qt::WA_TransparentForMouseEvents:
11515 break;
11516 case Qt::WA_InputMethodEnabled: {
11517#ifndef QT_NO_IM
11518 if (QGuiApplication::focusObject() == this) {
11519 if (!on)
11520 QGuiApplication::inputMethod()->commit();
11521 QGuiApplication::inputMethod()->update(Qt::ImEnabled);
11522 }
11523#endif //QT_NO_IM
11524 break;
11525 }
11526 case Qt::WA_WindowPropagation:
11527 d->resolvePalette();
11528 d->resolveFont();
11529 d->resolveLocale();
11530 break;
11531 case Qt::WA_DontShowOnScreen: {
11532 if (on && isVisible()) {
11533 // Make sure we keep the current state and only hide the widget
11534 // from the desktop. show_sys will only update platform specific
11535 // attributes at this point.
11536 d->hide_sys();
11537 d->show_sys();
11538 }
11539 break;
11540 }
11541
11542 case Qt::WA_X11NetWmWindowTypeDesktop:
11543 case Qt::WA_X11NetWmWindowTypeDock:
11544 case Qt::WA_X11NetWmWindowTypeToolBar:
11545 case Qt::WA_X11NetWmWindowTypeMenu:
11546 case Qt::WA_X11NetWmWindowTypeUtility:
11547 case Qt::WA_X11NetWmWindowTypeSplash:
11548 case Qt::WA_X11NetWmWindowTypeDialog:
11549 case Qt::WA_X11NetWmWindowTypeDropDownMenu:
11550 case Qt::WA_X11NetWmWindowTypePopupMenu:
11551 case Qt::WA_X11NetWmWindowTypeToolTip:
11552 case Qt::WA_X11NetWmWindowTypeNotification:
11553 case Qt::WA_X11NetWmWindowTypeCombo:
11554 case Qt::WA_X11NetWmWindowTypeDND:
11555 d->setNetWmWindowTypes();
11556 break;
11557
11558 case Qt::WA_StaticContents:
11559 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
11560 if (on)
11561 repaintManager->addStaticWidget(this);
11562 else
11563 repaintManager->removeStaticWidget(this);
11564 }
11565 break;
11566 case Qt::WA_TranslucentBackground:
11567 if (on)
11568 setAttribute(Qt::WA_NoSystemBackground);
11569 d->updateIsTranslucent();
11570
11571 break;
11572 case Qt::WA_AcceptTouchEvents:
11573 break;
11574 default:
11575 break;
11576 }
11577}
11578
11579/*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
11580
11581 Returns \c true if attribute \a attribute is set on this widget;
11582 otherwise returns \c false.
11583
11584 \sa setAttribute()
11585 */
11586bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
11587{
11588 Q_D(const QWidget);
11589 const int x = attribute - 8*sizeof(uint);
11590 const int int_off = x / (8*sizeof(uint));
11591 return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
11592}
11593
11594/*!
11595 \property QWidget::windowOpacity
11596
11597 \brief The level of opacity for the window.
11598
11599 The valid range of opacity is from 1.0 (completely opaque) to
11600 0.0 (completely transparent).
11601
11602 By default the value of this property is 1.0.
11603
11604 This feature is available on Embedded Linux, \macos, Windows,
11605 and X11 platforms that support the Composite extension.
11606
11607 \note On X11 you need to have a composite manager running,
11608 and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
11609 supported by the window manager you are using.
11610
11611 \warning Changing this property from opaque to transparent might issue a
11612 paint event that needs to be processed before the window is displayed
11613 correctly. This affects mainly the use of QScreen::grabWindow(). Also note
11614 that semi-transparent windows update and resize significantly slower than
11615 opaque windows.
11616
11617 \sa setMask()
11618*/
11619qreal QWidget::windowOpacity() const
11620{
11621 Q_D(const QWidget);
11622 return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
11623}
11624
11625void QWidget::setWindowOpacity(qreal opacity)
11626{
11627 Q_D(QWidget);
11628 if (!isWindow())
11629 return;
11630
11631 opacity = qBound(qreal(0.0), opacity, qreal(1.0));
11632 QTLWExtra *extra = d->topData();
11633 extra->opacity = uint(opacity * 255);
11634 setAttribute(Qt::WA_WState_WindowOpacitySet);
11635 d->setWindowOpacity_sys(opacity);
11636
11637 if (!testAttribute(Qt::WA_WState_Created))
11638 return;
11639
11640#if QT_CONFIG(graphicsview)
11641 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
11642 // Avoid invalidating the cache if set.
11643 if (proxy->cacheMode() == QGraphicsItem::NoCache)
11644 proxy->update();
11645 else if (QGraphicsScene *scene = proxy->scene())
11646 scene->update(proxy->sceneBoundingRect());
11647 return;
11648 }
11649#endif
11650}
11651
11652void QWidgetPrivate::setWindowOpacity_sys(qreal level)
11653{
11654 Q_Q(QWidget);
11655 if (q->windowHandle())
11656 q->windowHandle()->setOpacity(level);
11657}
11658
11659/*!
11660 \property QWidget::windowModified
11661 \brief whether the document shown in the window has unsaved changes
11662
11663 A modified window is a window whose content has changed but has
11664 not been saved to disk. This flag will have different effects
11665 varied by the platform. On \macos the close button will have a
11666 modified look; on other platforms, the window title will have an
11667 '*' (asterisk).
11668
11669 The window title must contain a "[*]" placeholder, which
11670 indicates where the '*' should appear. Normally, it should appear
11671 right after the file name (e.g., "document1.txt[*] - Text
11672 Editor"). If the window isn't modified, the placeholder is simply
11673 removed.
11674
11675 Note that if a widget is set as modified, all its ancestors will
11676 also be set as modified. However, if you call \c
11677 {setWindowModified(false)} on a widget, this will not propagate to
11678 its parent because other children of the parent might have been
11679 modified.
11680
11681 \sa windowTitle
11682*/
11683bool QWidget::isWindowModified() const
11684{
11685 return testAttribute(Qt::WA_WindowModified);
11686}
11687
11688void QWidget::setWindowModified(bool mod)
11689{
11690 Q_D(QWidget);
11691 setAttribute(Qt::WA_WindowModified, mod);
11692
11693 d->setWindowModified_helper();
11694
11695 QEvent e(QEvent::ModifiedChange);
11696 QCoreApplication::sendEvent(this, &e);
11697}
11698
11699void QWidgetPrivate::setWindowModified_helper()
11700{
11701 Q_Q(QWidget);
11702 QWindow *window = q->windowHandle();
11703 if (!window)
11704 return;
11705 QPlatformWindow *platformWindow = window->handle();
11706 if (!platformWindow)
11707 return;
11708 bool on = q->testAttribute(Qt::WA_WindowModified);
11709 if (!platformWindow->setWindowModified(on)) {
11710 if (Q_UNLIKELY(on && !q->windowTitle().contains("[*]"_L1)))
11711 qWarning("QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
11712 setWindowTitle_helper(q->windowTitle());
11713 setWindowIconText_helper(q->windowIconText());
11714 }
11715}
11716
11717#if QT_CONFIG(tooltip)
11718/*!
11719 \property QWidget::toolTip
11720
11721 \brief the widget's tooltip
11722
11723 Note that by default tooltips are only shown for widgets that are
11724 children of the active window. You can change this behavior by
11725 setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
11726 not on the widget with the tooltip.
11727
11728 If you want to control a tooltip's behavior, you can intercept the
11729 event() function and catch the QEvent::ToolTip event (e.g., if you
11730 want to customize the area for which the tooltip should be shown).
11731
11732 By default, this property contains an empty string.
11733
11734 \sa QToolTip, statusTip, whatsThis
11735*/
11736void QWidget::setToolTip(const QString &s)
11737{
11738 Q_D(QWidget);
11739 d->toolTip = s;
11740
11741 QEvent event(QEvent::ToolTipChange);
11742 QCoreApplication::sendEvent(this, &event);
11743}
11744
11745QString QWidget::toolTip() const
11746{
11747 Q_D(const QWidget);
11748 return d->toolTip;
11749}
11750
11751/*!
11752 \property QWidget::toolTipDuration
11753 \brief the widget's tooltip duration
11754 \since 5.2
11755
11756 Specifies how long time the tooltip will be displayed, in milliseconds.
11757 If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
11758
11759 \sa toolTip
11760*/
11761
11762void QWidget::setToolTipDuration(int msec)
11763{
11764 Q_D(QWidget);
11765 d->toolTipDuration = msec;
11766}
11767
11768int QWidget::toolTipDuration() const
11769{
11770 Q_D(const QWidget);
11771 return d->toolTipDuration;
11772}
11773
11774#endif // QT_CONFIG(tooltip)
11775
11776
11777#if QT_CONFIG(statustip)
11778/*!
11779 \property QWidget::statusTip
11780 \brief the widget's status tip
11781
11782 By default, this property contains an empty string.
11783
11784 \sa toolTip, whatsThis
11785*/
11786void QWidget::setStatusTip(const QString &s)
11787{
11788 Q_D(QWidget);
11789 d->statusTip = s;
11790}
11791
11792QString QWidget::statusTip() const
11793{
11794 Q_D(const QWidget);
11795 return d->statusTip;
11796}
11797#endif // QT_CONFIG(statustip)
11798
11799#if QT_CONFIG(whatsthis)
11800/*!
11801 \property QWidget::whatsThis
11802
11803 \brief the widget's What's This help text.
11804
11805 By default, this property contains an empty string.
11806
11807 \sa QWhatsThis, QWidget::toolTip, QWidget::statusTip
11808*/
11809void QWidget::setWhatsThis(const QString &s)
11810{
11811 Q_D(QWidget);
11812 d->whatsThis = s;
11813}
11814
11815QString QWidget::whatsThis() const
11816{
11817 Q_D(const QWidget);
11818 return d->whatsThis;
11819}
11820#endif // QT_CONFIG(whatsthis)
11821
11822#if QT_CONFIG(accessibility)
11823/*!
11824 \property QWidget::accessibleName
11825
11826 \brief the widget's name as seen by assistive technologies
11827
11828 This is the primary name by which assistive technology such as screen readers
11829 announce this widget. For most widgets setting this property is not required.
11830 For example for QPushButton the button's text will be used.
11831
11832 It is important to set this property when the widget does not provide any
11833 text. For example a button that only contains an icon needs to set this
11834 property to work with screen readers.
11835 The name should be short and equivalent to the visual information conveyed
11836 by the widget.
11837
11838 This property has to be \l{Internationalization with Qt}{localized}.
11839
11840 By default, this property contains an empty string.
11841
11842 \sa QWidget::accessibleDescription, QAccessibleInterface::text()
11843*/
11844void QWidget::setAccessibleName(const QString &name)
11845{
11846 Q_D(QWidget);
11847 if (d->accessibleName == name)
11848 return;
11849
11850 d->accessibleName = name;
11851 QAccessibleEvent event(this, QAccessible::NameChanged);
11852 QAccessible::updateAccessibility(&event);
11853}
11854
11855QString QWidget::accessibleName() const
11856{
11857 Q_D(const QWidget);
11858 return d->accessibleName;
11859}
11860
11861/*!
11862 \property QWidget::accessibleDescription
11863
11864 \brief the widget's description as seen by assistive technologies
11865
11866 The accessible description of a widget should convey what a widget does.
11867 While the \l accessibleName should be a short and concise string (e.g. \gui{Save}),
11868 the description should give more context, such as \gui{Saves the current document}.
11869
11870 This property has to be \l{Internationalization with Qt}{localized}.
11871
11872 By default, this property contains an empty string and Qt falls back
11873 to using the tool tip to provide this information.
11874
11875 \sa QWidget::accessibleName, QAccessibleInterface::text()
11876*/
11877void QWidget::setAccessibleDescription(const QString &description)
11878{
11879 Q_D(QWidget);
11880 if (d->accessibleDescription == description)
11881 return;
11882
11883 d->accessibleDescription = description;
11884 QAccessibleEvent event(this, QAccessible::DescriptionChanged);
11885 QAccessible::updateAccessibility(&event);
11886}
11887
11888QString QWidget::accessibleDescription() const
11889{
11890 Q_D(const QWidget);
11891 return d->accessibleDescription;
11892}
11893
11894/*!
11895 \property QWidget::accessibleIdentifier
11896
11897 \brief the widget's identifier as seen by assistive technologies
11898
11899 If set, the accessible identifier of a widget can be used by assistive
11900 technologies in order to identify a specific widget, e.g. in automated
11901 tests.
11902
11903 \since 6.9
11904*/
11905void QWidget::setAccessibleIdentifier(const QString &identifier)
11906{
11907 Q_D(QWidget);
11908 if (d->accessibleIdentifier == identifier)
11909 return;
11910
11911 d->accessibleIdentifier = identifier;
11912 QAccessibleEvent event(this, QAccessible::IdentifierChanged);
11913 QAccessible::updateAccessibility(&event);
11914}
11915
11916QString QWidget::accessibleIdentifier() const
11917{
11918 Q_D(const QWidget);
11919 return d->accessibleIdentifier;
11920}
11921
11922#endif // QT_CONFIG(accessibility)
11923
11924#ifndef QT_NO_SHORTCUT
11925/*!
11926 Adds a shortcut to Qt's shortcut system that watches for the given
11927 \a key sequence in the given \a context. If the \a context is
11928 Qt::ApplicationShortcut, the shortcut applies to the application as a
11929 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
11930 or to the window itself, Qt::WindowShortcut.
11931
11932 If the same \a key sequence has been grabbed by several widgets,
11933 when the \a key sequence occurs a QEvent::Shortcut event is sent
11934 to all the widgets to which it applies in a non-deterministic
11935 order, but with the ``ambiguous'' flag set to true.
11936
11937 \warning You should not normally need to use this function;
11938 instead create \l{QAction}s with the shortcut key sequences you
11939 require (if you also want equivalent menu options and toolbar
11940 buttons), or create \l{QShortcut}s if you just need key sequences.
11941 Both QAction and QShortcut handle all the event filtering for you,
11942 and provide signals which are triggered when the user triggers the
11943 key sequence, so are much easier to use than this low-level
11944 function.
11945
11946 \sa releaseShortcut(), setShortcutEnabled()
11947*/
11948int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
11949{
11950 Q_ASSERT(qApp);
11951 if (key.isEmpty())
11952 return 0;
11953 setAttribute(Qt::WA_GrabbedShortcut);
11954 return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, key, context, qWidgetShortcutContextMatcher);
11955}
11956
11957/*!
11958 Removes the shortcut with the given \a id from Qt's shortcut
11959 system. The widget will no longer receive QEvent::Shortcut events
11960 for the shortcut's key sequence (unless it has other shortcuts
11961 with the same key sequence).
11962
11963 \warning You should not normally need to use this function since
11964 Qt's shortcut system removes shortcuts automatically when their
11965 parent widget is destroyed. It is best to use QAction or
11966 QShortcut to handle shortcuts, since they are easier to use than
11967 this low-level function. Note also that this is an expensive
11968 operation.
11969
11970 \sa grabShortcut(), setShortcutEnabled()
11971*/
11972void QWidget::releaseShortcut(int id)
11973{
11974 Q_ASSERT(qApp);
11975 if (id)
11976 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this, 0);
11977}
11978
11979/*!
11980 If \a enable is true, the shortcut with the given \a id is
11981 enabled; otherwise the shortcut is disabled.
11982
11983 \warning You should not normally need to use this function since
11984 Qt's shortcut system enables/disables shortcuts automatically as
11985 widgets become hidden/visible and gain or lose focus. It is best
11986 to use QAction or QShortcut to handle shortcuts, since they are
11987 easier to use than this low-level function.
11988
11989 \sa grabShortcut(), releaseShortcut()
11990*/
11991void QWidget::setShortcutEnabled(int id, bool enable)
11992{
11993 Q_ASSERT(qApp);
11994 if (id)
11995 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, this, 0);
11996}
11997
11998/*!
11999 \since 4.2
12000
12001 If \a enable is true, auto repeat of the shortcut with the
12002 given \a id is enabled; otherwise it is disabled.
12003
12004 \sa grabShortcut(), releaseShortcut()
12005*/
12006void QWidget::setShortcutAutoRepeat(int id, bool enable)
12007{
12008 Q_ASSERT(qApp);
12009 if (id)
12010 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(enable, id, this, 0);
12011}
12012#endif // QT_NO_SHORTCUT
12013
12014/*!
12015 Updates the widget's micro focus and informs input methods
12016 that the state specified by \a query has changed.
12017*/
12018void QWidget::updateMicroFocus(Qt::InputMethodQuery query)
12019{
12020 if (this == QGuiApplication::focusObject())
12021 QGuiApplication::inputMethod()->update(query);
12022}
12023
12024/*!
12025 Raises this widget to the top of the parent widget's stack.
12026
12027 After this call the widget will be visually in front of any
12028 overlapping sibling widgets.
12029
12030 \note When using activateWindow(), you can call this function to
12031 ensure that the window is stacked on top.
12032
12033 \sa lower(), stackUnder()
12034*/
12035
12036void QWidget::raise()
12037{
12038 Q_D(QWidget);
12039 if (!isWindow()) {
12040 QWidget *p = parentWidget();
12041 const int parentChildCount = p->d_func()->children.size();
12042 if (parentChildCount < 2)
12043 return;
12044 const int from = p->d_func()->children.indexOf(this);
12045 Q_ASSERT(from >= 0);
12046 // Do nothing if the widget is already in correct stacking order _and_ created.
12047 if (from != parentChildCount -1)
12048 p->d_func()->children.move(from, parentChildCount - 1);
12049 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12050 create();
12051 else if (from == parentChildCount - 1)
12052 return;
12053
12054 QRegion region(rect());
12055 d->subtractOpaqueSiblings(region);
12056 d->invalidateBackingStore(region);
12057 }
12058 if (testAttribute(Qt::WA_WState_Created))
12059 d->raise_sys();
12060
12061 if (d->extra && d->extra->hasWindowContainer)
12062 QWindowContainer::parentWasRaised(this);
12063
12064 QEvent e(QEvent::ZOrderChange);
12065 QCoreApplication::sendEvent(this, &e);
12066}
12067
12068void QWidgetPrivate::raise_sys()
12069{
12070 Q_Q(QWidget);
12071 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
12072 q->windowHandle()->raise();
12073 } else if (renderToTexture) {
12074 if (QWidget *p = q->parentWidget()) {
12075 setDirtyOpaqueRegion();
12076 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12077 }
12078 }
12079}
12080
12081/*!
12082 Lowers the widget to the bottom of the parent widget's stack.
12083
12084 After this call the widget will be visually behind (and therefore
12085 obscured by) any overlapping sibling widgets.
12086
12087 \sa raise(), stackUnder()
12088*/
12089
12090void QWidget::lower()
12091{
12092 Q_D(QWidget);
12093 if (!isWindow()) {
12094 QWidget *p = parentWidget();
12095 const int parentChildCount = p->d_func()->children.size();
12096 if (parentChildCount < 2)
12097 return;
12098 const int from = p->d_func()->children.indexOf(this);
12099 Q_ASSERT(from >= 0);
12100 // Do nothing if the widget is already in correct stacking order _and_ created.
12101 if (from != 0)
12102 p->d_func()->children.move(from, 0);
12103 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12104 create();
12105 else if (from == 0)
12106 return;
12107 }
12108 if (testAttribute(Qt::WA_WState_Created))
12109 d->lower_sys();
12110
12111 if (d->extra && d->extra->hasWindowContainer)
12112 QWindowContainer::parentWasLowered(this);
12113
12114 QEvent e(QEvent::ZOrderChange);
12115 QCoreApplication::sendEvent(this, &e);
12116}
12117
12118void QWidgetPrivate::lower_sys()
12119{
12120 Q_Q(QWidget);
12121 if (q->isWindow() || q->testAttribute(Qt::WA_NativeWindow)) {
12122 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
12123 q->windowHandle()->lower();
12124 } else if (QWidget *p = q->parentWidget()) {
12125 setDirtyOpaqueRegion();
12126 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12127 }
12128}
12129
12130/*!
12131 Places the widget under \a w in the parent widget's stack.
12132
12133 To make this work, the widget itself and \a w must be siblings.
12134
12135 \sa raise(), lower()
12136*/
12137void QWidget::stackUnder(QWidget* w)
12138{
12139 Q_D(QWidget);
12140 QWidget *p = parentWidget();
12141 if (!w || isWindow() || p != w->parentWidget() || this == w)
12142 return;
12143 if (p) {
12144 int from = p->d_func()->children.indexOf(this);
12145 int to = p->d_func()->children.indexOf(w);
12146 Q_ASSERT(from >= 0);
12147 Q_ASSERT(to >= 0);
12148 if (from < to)
12149 --to;
12150 // Do nothing if the widget is already in correct stacking order _and_ created.
12151 if (from != to)
12152 p->d_func()->children.move(from, to);
12153 if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
12154 create();
12155 else if (from == to)
12156 return;
12157 }
12158 if (testAttribute(Qt::WA_WState_Created))
12159 d->stackUnder_sys(w);
12160
12161 QEvent e(QEvent::ZOrderChange);
12162 QCoreApplication::sendEvent(this, &e);
12163}
12164
12165void QWidgetPrivate::stackUnder_sys(QWidget*)
12166{
12167 Q_Q(QWidget);
12168 if (QWidget *p = q->parentWidget()) {
12169 setDirtyOpaqueRegion();
12170 p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
12171 }
12172}
12173
12174/*!
12175 \fn bool QWidget::isTopLevel() const
12176 \deprecated
12177
12178 Use isWindow() instead.
12179*/
12180
12181/*!
12182 \fn bool QWidget::isRightToLeft() const
12183 \internal
12184*/
12185
12186/*!
12187 \fn bool QWidget::isLeftToRight() const
12188 \internal
12189*/
12190
12191/*!
12192 \macro QWIDGETSIZE_MAX
12193 \relates QWidget
12194
12195 Defines the maximum size for a QWidget object.
12196
12197 The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
12198 QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
12199
12200 \sa QWidget::setMaximumSize()
12201*/
12202
12203/*!
12204 \fn QWidget::setupUi(QWidget *widget)
12205
12206 Sets up the user interface for the specified \a widget.
12207
12208 \note This function is available with widgets that derive from user
12209 interface descriptions created using \l{uic}.
12210
12211 \sa {Using a Qt Widgets Designer UI File in Your Application}
12212*/
12213
12214QRect QWidgetPrivate::frameStrut() const
12215{
12216 Q_Q(const QWidget);
12217 if (!q->isWindow() || q->testAttribute(Qt::WA_DontShowOnScreen)) {
12218 // x2 = x1 + w - 1, so w/h = 1
12219 return QRect(0, 0, 1, 1);
12220 }
12221
12222 if (data.fstrut_dirty
12223 // ### Fix properly for 4.3
12224 && q->isVisible()
12225 && q->testAttribute(Qt::WA_WState_Created))
12226 const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
12227
12228 return maybeTopData() ? maybeTopData()->frameStrut : QRect();
12229}
12230
12231void QWidgetPrivate::updateFrameStrut()
12232{
12233 Q_Q(QWidget);
12234 if (q->data->fstrut_dirty) {
12235 if (QTLWExtra *te = maybeTopData()) {
12236 if (te->window && te->window->handle()) {
12237 const QMargins margins = te->window->frameMargins();
12238 if (!margins.isNull()) {
12239 te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
12240 q->data->fstrut_dirty = false;
12241 }
12242 }
12243 }
12244 }
12245}
12246
12247/*!
12248 \since 5.0
12249 \internal
12250
12251 Sets the backing store to be the \a store specified.
12252 The QWidget will take ownership of the \a store.
12253*/
12254void QWidget::setBackingStore(QBackingStore *store)
12255{
12256 // ### createWinId() ??
12257
12258 if (!isWindow())
12259 return;
12260
12261 Q_D(QWidget);
12262
12263 QTLWExtra *topData = d->topData();
12264 if (topData->backingStore == store)
12265 return;
12266
12267 QBackingStore *oldStore = topData->backingStore;
12268 delete topData->backingStore;
12269 topData->backingStore = store;
12270
12271 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
12272 if (!repaintManager)
12273 return;
12274
12275 if (isWindow()) {
12276 if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store)
12277 delete repaintManager->backingStore();
12278 repaintManager->setBackingStore(store);
12279 }
12280}
12281
12282/*!
12283 \since 5.0
12284
12285 Returns the QBackingStore this widget will be drawn into.
12286*/
12287QBackingStore *QWidget::backingStore() const
12288{
12289 Q_D(const QWidget);
12290 QTLWExtra *extra = d->maybeTopData();
12291 if (extra && extra->backingStore)
12292 return extra->backingStore;
12293
12294 if (!isWindow())
12295 return window()->backingStore();
12296
12297 return nullptr;
12298}
12299
12300void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
12301{
12302 if (left)
12303 *left = (int)leftLayoutItemMargin;
12304 if (top)
12305 *top = (int)topLayoutItemMargin;
12306 if (right)
12307 *right = (int)rightLayoutItemMargin;
12308 if (bottom)
12309 *bottom = (int)bottomLayoutItemMargin;
12310}
12311
12312void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
12313{
12314 if (leftLayoutItemMargin == left
12315 && topLayoutItemMargin == top
12316 && rightLayoutItemMargin == right
12317 && bottomLayoutItemMargin == bottom)
12318 return;
12319
12320 Q_Q(QWidget);
12321 leftLayoutItemMargin = (signed char)left;
12322 topLayoutItemMargin = (signed char)top;
12323 rightLayoutItemMargin = (signed char)right;
12324 bottomLayoutItemMargin = (signed char)bottom;
12325 q->updateGeometry();
12326}
12327
12328void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
12329{
12330 Q_Q(QWidget);
12331 QStyleOption myOpt;
12332 if (!opt) {
12333 myOpt.initFrom(q);
12334 myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary
12335 opt = &myOpt;
12336 }
12337
12338 QRect liRect = q->style()->subElementRect(element, opt, q);
12339 if (liRect.isValid()) {
12340 leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
12341 topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
12342 rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
12343 bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
12344 } else {
12345 leftLayoutItemMargin = 0;
12346 topLayoutItemMargin = 0;
12347 rightLayoutItemMargin = 0;
12348 bottomLayoutItemMargin = 0;
12349 }
12350}
12351// resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
12352void QWidgetPrivate::adjustQuitOnCloseAttribute()
12353{
12354 Q_Q(QWidget);
12355
12356 if (!q->parentWidget()) {
12357 Qt::WindowType type = q->windowType();
12358 if (type == Qt::Widget || type == Qt::SubWindow)
12359 type = Qt::Window;
12360 if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
12361 q->setAttribute(Qt::WA_QuitOnClose, false);
12362 }
12363}
12364
12365void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
12366{
12367 QWidgetPrivate *wd = QWidgetPrivate::get(w);
12368 if (!wd->textureChildSeen)
12369 return;
12370 if (end)
12371 wd->endCompose();
12372 else
12373 wd->beginCompose();
12374 for (int i = 0; i < wd->children.size(); ++i) {
12375 w = qobject_cast<QWidget *>(wd->children.at(i));
12376 if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
12377 sendComposeStatus(w, end);
12378 }
12379}
12380
12381Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
12382{
12383 return widget->data;
12384}
12385
12386Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
12387{
12388 return widget->d_func();
12389}
12390
12391
12392#if QT_CONFIG(graphicsview)
12393/*!
12394 \since 4.5
12395
12396 Returns the proxy widget for the corresponding embedded widget in a graphics
12397 view; otherwise returns \nullptr.
12398
12399 \sa QGraphicsProxyWidget::createProxyForChildWidget(),
12400 QGraphicsScene::addWidget()
12401 */
12402QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
12403{
12404 Q_D(const QWidget);
12405 if (d->extra) {
12406 return d->extra->proxyWidget;
12407 }
12408 return nullptr;
12409}
12410#endif
12411
12412#ifndef QT_NO_GESTURES
12413/*!
12414 Subscribes the widget to a given \a gesture with specific \a flags.
12415
12416 \sa ungrabGesture(), QGestureEvent
12417 \since 4.6
12418*/
12419void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
12420{
12421 Q_D(QWidget);
12422 d->gestureContext.insert(gesture, flags);
12423 (void)QGestureManager::instance(); // create a gesture manager
12424}
12425
12426/*!
12427 Unsubscribes the widget from a given \a gesture type
12428
12429 \sa grabGesture(), QGestureEvent
12430 \since 4.6
12431*/
12432void QWidget::ungrabGesture(Qt::GestureType gesture)
12433{
12434 // if you modify this function, check the inlined version in ~QWidget, too
12435 Q_D(QWidget);
12436 if (d->gestureContext.remove(gesture)) {
12437 if (QGestureManager *manager = QGestureManager::instance())
12438 manager->cleanupCachedGestures(this, gesture);
12439 }
12440}
12441#endif // QT_NO_GESTURES
12442
12443/*!
12444 \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12445
12446 Frees up window system resources. Destroys the widget window if \a
12447 destroyWindow is true.
12448
12449 destroy() calls itself recursively for all the child widgets,
12450 passing \a destroySubWindows for the \a destroyWindow parameter.
12451 To have more control over destruction of subwidgets, destroy
12452 subwidgets selectively first.
12453
12454 This function is usually called from the QWidget destructor.
12455*/
12456void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12457{
12458 Q_D(QWidget);
12459
12460 d->aboutToDestroy();
12461 if (!isWindow() && parentWidget())
12462 parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(geometry()));
12463 d->deactivateWidgetCleanup();
12464
12465 if ((windowType() == Qt::Popup) && qApp)
12466 qApp->d_func()->closePopup(this);
12467
12468 if (this == qApp->activeWindow())
12469 QApplicationPrivate::setActiveWindow(nullptr);
12470 if (QWidget::mouseGrabber() == this)
12471 releaseMouse();
12472 if (QWidget::keyboardGrabber() == this)
12473 releaseKeyboard();
12474
12475 setAttribute(Qt::WA_WState_Created, false);
12476
12477 if (destroySubWindows) {
12478 QObjectList childList(children());
12479 for (int i = 0; i < childList.size(); i++) {
12480 QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
12481 if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
12482 if (widget->windowHandle()) {
12483 widget->destroy();
12484 }
12485 }
12486 }
12487 }
12488 if (destroyWindow) {
12489 d->deleteTLSysExtra();
12490 } else {
12491 if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
12492 d->hide_sys();
12493 }
12494 }
12495
12496 d->setWinId(0);
12497}
12498
12499/*!
12500 \fn QPaintEngine *QWidget::paintEngine() const
12501
12502 Returns the widget's paint engine.
12503
12504 Note that this function should not be called explicitly by the
12505 user, since it's meant for reimplementation purposes only. The
12506 function is called by Qt internally, and the default
12507 implementation may not always return a valid pointer.
12508*/
12509QPaintEngine *QWidget::paintEngine() const
12510{
12511 qWarning("QWidget::paintEngine: Should no longer be called");
12512
12513#ifdef Q_OS_WIN
12514 // We set this bit which is checked in setAttribute for
12515 // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
12516 //
12517 // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
12518 // Windows which would mean suddenly their widgets stop working.
12519 //
12520 // 2. Users set paint on screen and subclass paintEngine() to
12521 // return 0, in which case we have a "hole" in the backingstore
12522 // allowing use of GDI or DirectX directly.
12523 //
12524 // 1 is WRONG, but to minimize silent failures, we have set this
12525 // bit to ignore the setAttribute call. 2. needs to be
12526 // supported because its our only means of embedding native
12527 // graphics stuff.
12528 const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
12529#endif
12530
12531 return nullptr; //##### @@@
12532}
12533
12534// Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing.
12535static inline bool canMapPosition(QWindow *window)
12536{
12537 return window->handle() && !qt_window_private(window)->resizeEventPending;
12538}
12539
12540#if QT_CONFIG(graphicsview)
12541static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w)
12542{
12543 QGraphicsProxyWidget *result = nullptr;
12544 const QWidgetPrivate *d = qt_widget_private(const_cast<QWidget *>(w));
12545 if (d->extra)
12546 result = d->extra->proxyWidget;
12547 return result;
12548}
12549#endif // QT_CONFIG(graphicsview)
12550
12552 QTransform transform;
12553 QWindow *window;
12554};
12555
12557{
12559 result.window = nullptr;
12560 for ( ; w ; w = w->parentWidget()) {
12561#if QT_CONFIG(graphicsview)
12562 if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) {
12563 if (const QGraphicsScene *scene = qgpw->scene()) {
12564 const QList <QGraphicsView *> views = scene->views();
12565 if (!views.isEmpty()) {
12566 auto *viewP = static_cast<QGraphicsViewPrivate *>(qt_widget_private(views.constFirst()));
12567 result.transform *= viewP->mapToViewTransform(qgpw);
12568 w = views.first()->viewport();
12569 }
12570 }
12571 }
12572#endif // QT_CONFIG(graphicsview)
12573 QWindow *window = w->windowHandle();
12574 if (window && canMapPosition(window)) {
12575 result.window = window;
12576 break;
12577 }
12578
12579 const auto &geometry = w->geometry();
12580 result.transform *= QTransform::fromTranslate(geometry.x(), geometry.y());
12581 if (w->isWindow())
12582 break;
12583 }
12584 return result;
12585}
12586
12587/*!
12588 \fn QPointF QWidget::mapToGlobal(const QPointF &pos) const
12589
12590 Translates the widget coordinate \a pos to global screen
12591 coordinates. For example, \c{mapToGlobal(QPointF(0,0))} would give
12592 the global coordinates of the top-left pixel of the widget.
12593
12594 \sa mapFromGlobal(), mapTo(), mapToParent()
12595 \since 6.0
12596*/
12597QPointF QWidget::mapToGlobal(const QPointF &pos) const
12598{
12599 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12600 const QPointF g = t.transform.map(pos);
12601 return t.window ? t.window->mapToGlobal(g) : g;
12602}
12603
12604/*!
12605 \overload
12606*/
12607QPoint QWidget::mapToGlobal(const QPoint &pos) const
12608{
12609 return mapToGlobal(QPointF(pos)).toPoint();
12610}
12611
12612/*!
12613 \fn QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12614
12615 Translates the global screen coordinate \a pos to widget
12616 coordinates.
12617
12618 \sa mapToGlobal(), mapFrom(), mapFromParent()
12619 \since 6.0
12620*/
12621QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12622{
12623 const MapToGlobalTransformResult t = mapToGlobalTransform(this);
12624 const QPointF windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos;
12625 return t.transform.inverted().map(windowLocal);
12626}
12627
12628/*!
12629 \overload
12630*/
12631QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12632{
12633 return mapFromGlobal(QPointF(pos)).toPoint();
12634}
12635
12637static bool mouseGrabWithCursor = false;
12638static QWidget *keyboardGrb = nullptr;
12639
12640static inline QWindow *grabberWindow(const QWidget *w)
12641{
12642 QWindow *window = w->windowHandle();
12643 if (!window)
12644 if (const QWidget *nativeParent = w->nativeParentWidget())
12645 window = nativeParent->windowHandle();
12646 return window;
12647}
12648
12649#ifndef QT_NO_CURSOR
12650static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = nullptr)
12651#else
12652static void grabMouseForWidget(QWidget *widget)
12653#endif
12654{
12655 if (qt_mouseGrb)
12656 qt_mouseGrb->releaseMouse();
12657
12658 mouseGrabWithCursor = false;
12659 if (QWindow *window = grabberWindow(widget)) {
12660#ifndef QT_NO_CURSOR
12661 if (cursor) {
12662 mouseGrabWithCursor = true;
12663 QGuiApplication::setOverrideCursor(*cursor);
12664 }
12665#endif // !QT_NO_CURSOR
12666 window->setMouseGrabEnabled(true);
12667 }
12668
12669 qt_mouseGrb = widget;
12670}
12671
12673{
12674 if (qt_mouseGrb == widget) {
12675 if (QWindow *window = grabberWindow(widget)) {
12676#ifndef QT_NO_CURSOR
12677 if (mouseGrabWithCursor) {
12678 QGuiApplication::restoreOverrideCursor();
12679 mouseGrabWithCursor = false;
12680 }
12681#endif // !QT_NO_CURSOR
12682 window->setMouseGrabEnabled(false);
12683 }
12684 }
12685 qt_mouseGrb = nullptr;
12686}
12687
12688/*!
12689 \fn void QWidget::grabMouse()
12690
12691 Grabs the mouse input.
12692
12693 This widget receives all mouse events until releaseMouse() is
12694 called; other widgets get no mouse events at all. Keyboard
12695 events are not affected. Use grabKeyboard() if you want to grab
12696 that.
12697
12698 \warning Bugs in mouse-grabbing applications very often lock the
12699 terminal. Use this function with extreme caution, and consider
12700 using the \c -nograb command line option while debugging.
12701
12702 It is seldom necessary to grab the mouse when using Qt, as
12703 Qt grabs and releases it sensibly. In particular, Qt grabs the
12704 mouse when a mouse button is pressed and keeps it until the last
12705 button is released.
12706
12707 \note Only visible widgets can grab mouse input. If isVisible()
12708 returns \c false for a widget, that widget cannot call grabMouse().
12709
12710 \note On Windows, grabMouse() only works when the mouse is inside a window
12711 owned by the process.
12712 On \macos, grabMouse() only works when the mouse is inside the frame of that widget.
12713
12714 \sa releaseMouse(), grabKeyboard(), releaseKeyboard()
12715*/
12716void QWidget::grabMouse()
12717{
12718 grabMouseForWidget(this);
12719}
12720
12721/*!
12722 \fn void QWidget::grabMouse(const QCursor &cursor)
12723 \overload grabMouse()
12724
12725 Grabs the mouse input and changes the cursor shape.
12726
12727 The cursor will assume shape \a cursor (for as long as the mouse
12728 focus is grabbed) and this widget will be the only one to receive
12729 mouse events until releaseMouse() is called().
12730
12731 \warning Grabbing the mouse might lock the terminal.
12732
12733 \note See the note in QWidget::grabMouse().
12734
12735 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
12736*/
12737#ifndef QT_NO_CURSOR
12738void QWidget::grabMouse(const QCursor &cursor)
12739{
12740 grabMouseForWidget(this, &cursor);
12741}
12742#endif
12743
12744bool QWidgetPrivate::stealMouseGrab(bool grab)
12745{
12746 // This is like a combination of grab/releaseMouse() but with error checking
12747 // and it has no effect on the result of mouseGrabber().
12748 Q_Q(QWidget);
12749 QWindow *window = grabberWindow(q);
12750 return window ? window->setMouseGrabEnabled(grab) : false;
12751}
12752
12753/*!
12754 \fn void QWidget::releaseMouse()
12755
12756 Releases the mouse grab.
12757
12758 \sa grabMouse(), grabKeyboard(), releaseKeyboard()
12759*/
12760void QWidget::releaseMouse()
12761{
12762 releaseMouseGrabOfWidget(this);
12763}
12764
12765/*!
12766 \fn void QWidget::grabKeyboard()
12767
12768 Grabs the keyboard input.
12769
12770 This widget receives all keyboard events until releaseKeyboard()
12771 is called; other widgets get no keyboard events at all. Mouse
12772 events are not affected. Use grabMouse() if you want to grab that.
12773
12774 The focus widget is not affected, except that it doesn't receive
12775 any keyboard events. setFocus() moves the focus as usual, but the
12776 new focus widget receives keyboard events only after
12777 releaseKeyboard() is called.
12778
12779 If a different widget is currently grabbing keyboard input, that
12780 widget's grab is released first.
12781
12782 \sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
12783*/
12784void QWidget::grabKeyboard()
12785{
12786 if (keyboardGrb)
12787 keyboardGrb->releaseKeyboard();
12788 if (QWindow *window = grabberWindow(this))
12789 window->setKeyboardGrabEnabled(true);
12790 keyboardGrb = this;
12791}
12792
12793bool QWidgetPrivate::stealKeyboardGrab(bool grab)
12794{
12795 // This is like a combination of grab/releaseKeyboard() but with error
12796 // checking and it has no effect on the result of keyboardGrabber().
12797 Q_Q(QWidget);
12798 QWindow *window = grabberWindow(q);
12799 return window ? window->setKeyboardGrabEnabled(grab) : false;
12800}
12801
12802/*!
12803 \fn void QWidget::releaseKeyboard()
12804
12805 Releases the keyboard grab.
12806
12807 \sa grabKeyboard(), grabMouse(), releaseMouse()
12808*/
12809void QWidget::releaseKeyboard()
12810{
12811 if (keyboardGrb == this) {
12812 if (QWindow *window = grabberWindow(this))
12813 window->setKeyboardGrabEnabled(false);
12814 keyboardGrb = nullptr;
12815 }
12816}
12817
12818/*!
12819 \fn QWidget *QWidget::mouseGrabber()
12820
12821 Returns the widget that is currently grabbing the mouse input.
12822
12823 If no widget in this application is currently grabbing the mouse,
12824 \nullptr is returned.
12825
12826 \sa grabMouse(), keyboardGrabber()
12827*/
12828QWidget *QWidget::mouseGrabber()
12829{
12830 return qt_mouseGrb;
12831}
12832
12833/*!
12834 \fn QWidget *QWidget::keyboardGrabber()
12835
12836 Returns the widget that is currently grabbing the keyboard input.
12837
12838 If no widget in this application is currently grabbing the
12839 keyboard, \nullptr is returned.
12840
12841 \sa grabMouse(), mouseGrabber()
12842*/
12843QWidget *QWidget::keyboardGrabber()
12844{
12845 return keyboardGrb;
12846}
12847
12848/*!
12849 \fn void QWidget::activateWindow()
12850
12851 Sets the top-level widget containing this widget to be the active
12852 window.
12853
12854 An active window is a visible top-level window that has the
12855 keyboard input focus.
12856
12857 This function performs the same operation as clicking the mouse on
12858 the title bar of a top-level window. On X11, the result depends on
12859 the Window Manager. If you want to ensure that the window is
12860 stacked on top as well you should also call raise(). Note that the
12861 window must be visible, otherwise activateWindow() has no effect.
12862
12863 On Windows, if you are calling this when the application is not
12864 currently the active one then it will not make it the active
12865 window. It will change the color of the taskbar entry to indicate
12866 that the window has changed in some way. This is because Microsoft
12867 does not allow an application to interrupt what the user is currently
12868 doing in another application.
12869
12870 \sa isActiveWindow(), window(), show()
12871*/
12872void QWidget::activateWindow()
12873{
12874 QWindow *const wnd = window()->windowHandle();
12875
12876 if (wnd)
12877 wnd->requestActivate();
12878}
12879
12880/*!
12881
12882 Internal implementation of the virtual QPaintDevice::metric()
12883 function.
12884
12885 \a m is the metric to get.
12886*/
12887int QWidget::metric(PaintDeviceMetric m) const
12888{
12889 QScreen *screen = this->screen();
12890
12891 if (!screen) {
12892 if (m == PdmDpiX || m == PdmDpiY)
12893 return 72;
12894 return QPaintDevice::metric(m);
12895 }
12896
12897 auto resolveDevicePixelRatio = [this, screen]() -> qreal {
12898
12899 // Note: keep in sync with QBackingStorePrivate::backingStoreDevicePixelRatio()!
12900 static bool downscale = qEnvironmentVariableIntValue("QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
12901 QWindow *window = this->window()->windowHandle();
12902 if (window)
12903 return downscale ? std::ceil(window->devicePixelRatio()) : window->devicePixelRatio();
12904 return screen->devicePixelRatio();
12905 };
12906
12907 switch (m) {
12908 case PdmWidth:
12909 return data->crect.width();
12910 case PdmWidthMM:
12911 return data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
12912 case PdmHeight:
12913 return data->crect.height();
12914 case PdmHeightMM:
12915 return data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
12916 case PdmDepth:
12917 return screen->depth();
12918 case PdmDpiX:
12919 for (const QWidget *p = this; p; p = p->parentWidget()) {
12920 if (p->d_func()->extra && p->d_func()->extra->customDpiX)
12921 return p->d_func()->extra->customDpiX;
12922 }
12923 return qRound(screen->logicalDotsPerInchX());
12924 case PdmDpiY:
12925 for (const QWidget *p = this; p; p = p->parentWidget()) {
12926 if (p->d_func()->extra && p->d_func()->extra->customDpiY)
12927 return p->d_func()->extra->customDpiY;
12928 }
12929 return qRound(screen->logicalDotsPerInchY());
12930 case PdmPhysicalDpiX:
12931 return qRound(screen->physicalDotsPerInchX());
12932 case PdmPhysicalDpiY:
12933 return qRound(screen->physicalDotsPerInchY());
12934 case PdmDevicePixelRatio:
12935 return resolveDevicePixelRatio();
12936 case PdmDevicePixelRatioScaled:
12937 return QPaintDevice::devicePixelRatioFScale() * resolveDevicePixelRatio();
12938 case PdmDevicePixelRatioF_EncodedA:
12939 Q_FALLTHROUGH();
12940 case PdmDevicePixelRatioF_EncodedB:
12941 return QPaintDevice::encodeMetricF(m, resolveDevicePixelRatio());
12942 default:
12943 break;
12944 }
12945 return QPaintDevice::metric(m);
12946}
12947
12948/*!
12949 Initializes the \a painter pen, background and font to the same as
12950 the given widget's. This function is called automatically when the
12951 painter is opened on a QWidget.
12952*/
12953void QWidget::initPainter(QPainter *painter) const
12954{
12955 const QPalette &pal = palette();
12956 QPainterPrivate *painterPrivate = QPainterPrivate::get(painter);
12957
12958 painterPrivate->state->pen = QPen(pal.brush(foregroundRole()), 1);
12959 painterPrivate->state->bgBrush = pal.brush(backgroundRole());
12960 QFont f(font(), this);
12961 painterPrivate->state->deviceFont = f;
12962 painterPrivate->state->font = f;
12963
12964 painterPrivate->setEngineDirtyFlags({
12965 QPaintEngine::DirtyPen,
12966 QPaintEngine::DirtyBrush,
12967 QPaintEngine::DirtyFont,
12968 });
12969
12970 if (painterPrivate->extended)
12971 painterPrivate->extended->penChanged();
12972}
12973
12974/*!
12975 \internal
12976
12977 Do PaintDevice rendering with the specified \a offset.
12978*/
12979QPaintDevice *QWidget::redirected(QPoint *offset) const
12980{
12981 return d_func()->redirected(offset);
12982}
12983
12984/*!
12985 \internal
12986
12987 A painter that is shared among other instances of QPainter.
12988*/
12989QPainter *QWidget::sharedPainter() const
12990{
12991 // Someone sent a paint event directly to the widget
12992 if (!d_func()->redirectDev)
12993 return nullptr;
12994
12995 QPainter *sp = d_func()->sharedPainter();
12996 if (!sp || !sp->isActive())
12997 return nullptr;
12998
12999 if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
13000 return nullptr;
13001
13002 return sp;
13003}
13004
13005/*!
13006 \fn void QWidget::setMask(const QRegion &region)
13007 \overload
13008
13009 Causes only the parts of the widget which overlap \a region to be
13010 visible. If the region includes pixels outside the rect() of the
13011 widget, window system controls in that area may or may not be
13012 visible, depending on the platform.
13013
13014 Since QRegion allows arbitrarily complex regions to be created, widget
13015 masks can be made to suit the most unconventionally-shaped windows, and
13016 even allow widgets to be displayed with holes in them. Note that this
13017 effect can be slow if the region is particularly complex.
13018
13019 Widget masks are used to hint to the window system that the application
13020 does not want mouse events for areas outside the mask. On most systems,
13021 they also result in coarse visual clipping. To get smooth window edges, use
13022 translucent background and anti-aliased painting instead, as shown in the
13023 \l{Translucent Background} example.
13024
13025 \sa windowOpacity
13026*/
13027void QWidget::setMask(const QRegion &newMask)
13028{
13029 Q_D(QWidget);
13030
13031 d->createExtra();
13032 if (newMask == d->extra->mask)
13033 return;
13034
13035#ifndef QT_NO_BACKINGSTORE
13036 const QRegion oldMask(d->extra->mask);
13037#endif
13038
13039 d->extra->mask = newMask;
13040 d->extra->hasMask = !newMask.isEmpty();
13041
13042 if (!testAttribute(Qt::WA_WState_Created))
13043 return;
13044
13045 d->setMask_sys(newMask);
13046
13047#ifndef QT_NO_BACKINGSTORE
13048 if (!isVisible())
13049 return;
13050
13051 if (!d->extra->hasMask) {
13052 // Mask was cleared; update newly exposed area.
13053 QRegion expose(rect());
13054 expose -= oldMask;
13055 if (!expose.isEmpty()) {
13056 d->setDirtyOpaqueRegion();
13057 update(expose);
13058 }
13059 return;
13060 }
13061
13062 if (!isWindow()) {
13063 // Update newly exposed area on the parent widget.
13064 QRegion parentExpose(rect());
13065 parentExpose -= newMask;
13066 if (!parentExpose.isEmpty()) {
13067 d->setDirtyOpaqueRegion();
13068 parentExpose.translate(data->crect.topLeft());
13069 parentWidget()->update(parentExpose);
13070 }
13071
13072 // Update newly exposed area on this widget
13073 if (!oldMask.isEmpty())
13074 update(newMask - oldMask);
13075 }
13076#endif
13077}
13078
13079void QWidgetPrivate::setMask_sys(const QRegion &region)
13080{
13081 Q_Q(QWidget);
13082 if (QWindow *window = q->windowHandle())
13083 window->setMask(region);
13084}
13085
13086/*!
13087 \fn void QWidget::setMask(const QBitmap &bitmap)
13088
13089 Causes only the pixels of the widget for which \a bitmap has a
13090 corresponding 1 bit to be visible. If the region includes pixels
13091 outside the rect() of the widget, window system controls in that
13092 area may or may not be visible, depending on the platform.
13093
13094 Note that this effect can be slow if the region is particularly
13095 complex.
13096
13097 The following code shows how an image with an alpha channel can be
13098 used to generate a mask for a widget:
13099
13100 \snippet widget-mask/main.cpp 0
13101
13102 The label shown by this code is masked using the image it contains,
13103 giving the appearance that an irregularly-shaped image is being drawn
13104 directly onto the screen.
13105
13106 Masked widgets receive mouse events only on their visible
13107 portions.
13108
13109 \sa clearMask(), windowOpacity()
13110*/
13111void QWidget::setMask(const QBitmap &bitmap)
13112{
13113 setMask(QRegion(bitmap));
13114}
13115
13116/*!
13117 \fn void QWidget::clearMask()
13118
13119 Removes any mask set by setMask().
13120
13121 \sa setMask()
13122*/
13123void QWidget::clearMask()
13124{
13125 Q_D(QWidget);
13126 if (!d->extra || !d->extra->hasMask)
13127 return;
13128 setMask(QRegion());
13129}
13130
13131void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent)
13132{
13133 Q_ASSERT(widgetAsObject->isWidgetType());
13134 Q_ASSERT(!newParent || newParent->isWidgetType());
13135 QWidget *widget = static_cast<QWidget*>(widgetAsObject);
13136 widget->setParent(static_cast<QWidget*>(newParent));
13137}
13138
13139std::string QWidgetPrivate::flagsForDumping() const
13140{
13141 Q_Q(const QWidget);
13142 std::string flags = QObjectPrivate::flagsForDumping();
13143 if (QApplication::focusWidget() == q)
13144 flags += 'F';
13145 if (q->isVisible()) {
13146 std::stringstream s;
13147 s << '<'
13148 << q->width() << 'x' << q->height()
13149 << std::showpos << q->x() << q->y()
13150 << '>';
13151 flags += s.str();
13152 } else {
13153 flags += 'I';
13154 }
13155 return flags;
13156}
13157
13158void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
13159{
13160#if QT_CONFIG(xcb)
13161 Q_Q(QWidget);
13162
13163 if (!q->windowHandle())
13164 return;
13165
13166 QXcbWindow::WindowTypes wmWindowType = QXcbWindow::None;
13167 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
13168 wmWindowType |= QXcbWindow::Desktop;
13169 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
13170 wmWindowType |= QXcbWindow::Dock;
13171 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
13172 wmWindowType |= QXcbWindow::Toolbar;
13173 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
13174 wmWindowType |= QXcbWindow::Menu;
13175 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
13176 wmWindowType |= QXcbWindow::Utility;
13177 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
13178 wmWindowType |= QXcbWindow::Splash;
13179 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
13180 wmWindowType |= QXcbWindow::Dialog;
13181 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
13182 wmWindowType |= QXcbWindow::DropDownMenu;
13183 if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
13184 wmWindowType |= QXcbWindow::PopupMenu;
13185 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
13186 wmWindowType |= QXcbWindow::Tooltip;
13187 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
13188 wmWindowType |= QXcbWindow::Notification;
13189 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
13190 wmWindowType |= QXcbWindow::Combo;
13191 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
13192 wmWindowType |= QXcbWindow::Dnd;
13193
13194 if (wmWindowType == QXcbWindow::None && skipIfMissing)
13195 return;
13196
13197 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(q->windowHandle()->handle()))
13198 xcbWindow->setWindowType(wmWindowType);
13199#else
13200 Q_UNUSED(skipIfMissing);
13201#endif
13202}
13203
13204/*!
13205 \internal
13206 \return \c true, if a child with \param policy exists and isn't a child of \param excludeChildrenOf.
13207 Return false otherwise.
13208 */
13209bool QWidgetPrivate::hasChildWithFocusPolicy(Qt::FocusPolicy policy, const QWidget *excludeChildrenOf) const
13210{
13211 Q_Q(const QWidget);
13212 const QWidgetList &children = q->findChildren<QWidget *>(Qt::FindChildrenRecursively);
13213 for (const auto *child : children) {
13214 if (child->focusPolicy() == policy && child->isEnabled()
13215 && (!excludeChildrenOf || !excludeChildrenOf->isAncestorOf(child))) {
13216 return true;
13217 }
13218 }
13219 return false;
13220}
13221
13222#ifndef QT_NO_DEBUG_STREAM
13223
13224namespace {
13225QDebug operator<<(QDebug debug, const WidgetAttributes &attributes)
13226{
13227 const QDebugStateSaver saver(debug);
13228 debug.nospace();
13229 debug << '[';
13230 if (const QWidget *widget = attributes.widget) {
13231 const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
13232 const QMetaEnum me = qtMo->enumerator(qtMo->indexOfEnumerator("WidgetAttribute"));
13233 int count = 0;
13234 for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
13235 if (widget->testAttribute(static_cast<Qt::WidgetAttribute>(a))) {
13236 if (count++)
13237 debug << ',';
13238 debug << me.valueToKey(a);
13239 }
13240 }
13241 }
13242 debug << ']';
13243 return debug;
13244}
13245}
13246
13247QDebug operator<<(QDebug debug, const QWidget *widget)
13248{
13249 const QDebugStateSaver saver(debug);
13250 debug.nospace();
13251 if (widget) {
13252 debug << widget->metaObject()->className() << '(' << (const void *)widget;
13253 if (!widget->objectName().isEmpty())
13254 debug << ", name=" << widget->objectName();
13255 if (debug.verbosity() > 2) {
13256 const QRect geometry = widget->geometry();
13257 const QRect frameGeometry = widget->frameGeometry();
13258 if (widget->isVisible())
13259 debug << ", visible";
13260 if (!widget->isEnabled())
13261 debug << ", disabled";
13262 debug << ", states=" << widget->windowState()
13263 << ", type=" << widget->windowType() << ", flags=" << widget->windowFlags();
13264 debug << ", attributes=" << WidgetAttributes{widget};
13265 if (widget->isWindow())
13266 debug << ", window";
13267 debug << ", " << geometry.width() << 'x' << geometry.height()
13268 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
13269 if (frameGeometry != geometry) {
13270 const QMargins margins(geometry.x() - frameGeometry.x(),
13271 geometry.y() - frameGeometry.y(),
13272 frameGeometry.right() - geometry.right(),
13273 frameGeometry.bottom() - geometry.bottom());
13274 debug << ", margins=" << margins;
13275 }
13276 debug << ", devicePixelRatio=" << widget->devicePixelRatio();
13277 if (const WId wid = widget->internalWinId())
13278 debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
13279 }
13280 debug << ')';
13281 } else {
13282 debug << "QWidget(0x0)";
13283 }
13284 return debug;
13285}
13286#endif // !QT_NO_DEBUG_STREAM
13287
13288
13289// *************************** Focus abstraction ************************************
13290
13291#define FOCUS_NEXT(w) w->d_func()->focus_next
13292#define FOCUS_PREV(w) w->d_func()->focus_prev
13293
13294/*!
13295 \internal
13296 \return next or previous element in the focus chain, depending on
13297 \param direction, irrespective of focus proxies or widgets with Qt::NoFocus.
13298 */
13299QWidget *QWidgetPrivate::nextPrevElementInFocusChain(FocusDirection direction) const
13300{
13301 Q_Q(const QWidget);
13302 return direction == FocusDirection::Next ? FOCUS_NEXT(q) : FOCUS_PREV(q);
13303}
13304
13305/*!
13306 \internal
13307 Removes a widget from the focus chain, respecting the flags set in \param rules.
13308 \list
13309 \li EnsureFocusOut: If the widget has input focus, transfer focus to the next or previous widget
13310 in the focus chain, depending on \param direction.
13311 \li RemoveInconsistent: Remove the widget, even if its focus chain is inconsistent.
13312 \li AssertConsistency: qFatal, if the focus chain is inconsistent. This is used in the QWidget destructor.
13313 \endlist
13314 \return \c true if the widget has been removed, otherwise \c false.
13315 */
13316bool QWidgetPrivate::removeFromFocusChain(FocusChainRemovalRules rules, FocusDirection direction)
13317{
13318 Q_Q(QWidget);
13319 if (!isFocusChainConsistent()) {
13320#ifdef QT_DEBUG
13321 if (rules.testFlag(FocusChainRemovalRule::AssertConsistency))
13322 qFatal() << q << "has inconsistent focus chain.";
13323#endif
13324 qCDebug(lcWidgetFocus) << q << "wasn't removed, because of inconsistent focus chain.";
13325 return false;
13326 }
13327
13328 if (!isInFocusChain()) {
13329 qCDebug(lcWidgetFocus) << q << "wasn't removed, because it is not part of a focus chain.";
13330 return false;
13331 }
13332
13333 if (rules.testFlag(FocusChainRemovalRule::EnsureFocusOut))
13334 q->focusNextPrevChild(direction == FocusDirection::Next);
13335
13338 initFocusChain();
13339 qCDebug(lcWidgetFocus) << q << "removed from focus chain.";
13340 return true;
13341}
13342
13343/*!
13344 \internal
13345 Initialises the focus chain by making the widget point to itself.
13346 */
13347void QWidgetPrivate::initFocusChain()
13348{
13349 Q_Q(QWidget);
13350 qCDebug(lcWidgetFocus) << "Initializing focus chain of" << q;
13351 FOCUS_PREV(q) = q;
13352 FOCUS_NEXT(q) = q;
13353}
13354
13355/*!
13356 \internal
13357 Reads QWidget children, which are not part of a focus chain yet.
13358 Inserts them into the focus chain before or after the widget,
13359 depending on \param direction and in the order of their creation.
13360 This is used, when QWidget::setParent() causes a widget to change toplevel windows.
13361 */
13362void QWidgetPrivate::reparentFocusChildren(FocusDirection direction)
13363{
13364 Q_Q(QWidget);
13365
13366 // separate the focus chain into new (children of myself) and old (the rest)
13367 QWidget *firstOld = nullptr;
13368 QWidget *lastOld = nullptr; // last in the old list
13369 QWidget *lastNew = q; // last in the new list
13370 bool prevWasNew = true;
13371 QWidget *widget = nextPrevElementInFocusChain(direction);
13372
13373 // For efficiency, do not maintain the list invariant inside the loop.
13374 // Append items to the relevant list, and we optimize by not changing pointers,
13375 // when subsequent items are going into the same list.
13376 while (widget != q) {
13377 bool currentIsNew = q->isAncestorOf(widget);
13378 if (currentIsNew) {
13379 if (!prevWasNew) {
13380 // previous was old => append to new list
13381 FOCUS_NEXT(lastNew) = widget;
13382 FOCUS_PREV(widget) = lastNew;
13383 }
13384 lastNew = widget;
13385 } else {
13386 if (prevWasNew) {
13387 // prev was new => append to old list, if it exists
13388 if (lastOld) {
13389 FOCUS_NEXT(lastOld) = widget;
13390 FOCUS_PREV(widget) = lastOld;
13391 } else {
13392 // start the old list
13393 firstOld = widget;
13394 }
13395 }
13396 lastOld = widget;
13397 }
13398 widget = widget->d_func()->nextPrevElementInFocusChain(direction);
13399 prevWasNew = currentIsNew;
13400 }
13401
13402 // repair old list:
13403 if (firstOld) {
13404 FOCUS_NEXT(lastOld) = firstOld;
13405 FOCUS_PREV(firstOld) = lastOld;
13406 }
13407
13408 if (!q->isWindow()) {
13409 QWidget *topLevel = q->window();
13410 // insert new chain into toplevel's chain
13411 QWidget *prev = FOCUS_PREV(topLevel);
13412 FOCUS_PREV(topLevel) = lastNew;
13413 FOCUS_NEXT(prev) = q;
13414 FOCUS_PREV(q) = prev;
13415 FOCUS_NEXT(lastNew) = topLevel;
13416 } else {
13417 // repair new list
13418 FOCUS_NEXT(lastNew) = q;
13419 FOCUS_PREV(q) = lastNew;
13420 }
13421}
13422
13423/*!
13424 \internal
13425 Inserts a widget into the focus chain before or after \param position, depending on
13426 \param direction.
13427 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13428 */
13429bool QWidgetPrivate::insertIntoFocusChain(FocusDirection direction, QWidget *position)
13430{
13431 Q_Q(QWidget);
13432 Q_ASSERT(position);
13433 QWidget *next = FOCUS_NEXT(q);
13434 QWidget *previous = FOCUS_PREV(q);
13435
13436 switch (direction) {
13437 case FocusDirection::Next:
13438 if (previous == position) {
13439 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already before" << position;
13440 return false;
13441 }
13442
13443 removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
13444
13445 FOCUS_NEXT(q) = FOCUS_NEXT(position);
13446 FOCUS_PREV(FOCUS_NEXT(position)) = q;
13447 FOCUS_NEXT(position) = q;
13448 FOCUS_PREV(q) = position;
13449 qCDebug(lcWidgetFocus) << q << "inserted after" << position;
13450 break;
13451
13452 case FocusDirection::Previous:
13453 if (next == position) {
13454 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already after" << position;
13455 return false;
13456 }
13457
13458 removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
13459
13460 FOCUS_PREV(q) = FOCUS_PREV(position);
13461 FOCUS_NEXT(FOCUS_PREV(position)) = q;
13462 FOCUS_PREV(position) = q;
13463 FOCUS_NEXT(q) = position;
13464 qCDebug(lcWidgetFocus) << q << "inserted before" << position;
13465 break;
13466 }
13467
13468 Q_ASSERT(isFocusChainConsistent());
13469 return true;
13470}
13471
13472/*!
13473 \internal
13474 Convenience override to insert a QWidgetList \param toBeInserted into the focus chain
13475 before or after \param position, depending on \param direction.
13476 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13477 \note
13478 \param toBeInserted must be a consistent focus chain.
13479 */
13480bool QWidgetPrivate::insertIntoFocusChain(const QWidgetList &toBeInserted,
13481 FocusDirection direction, QWidget *position)
13482{
13483 if (toBeInserted.isEmpty()) {
13484 qCDebug(lcWidgetFocus) << "No-op insertion of an empty list";
13485 return false;
13486 }
13487
13488 Q_ASSERT_X(!toBeInserted.contains(position),
13489 Q_FUNC_INFO,
13490 "Coding error: toBeInserted contains position");
13491
13492 QWidget *first = toBeInserted.constFirst();
13493 QWidget *last = toBeInserted.constLast();
13494
13495 // Call QWidget override to log accordingly
13496 if (toBeInserted.count() == 1)
13497 return first->d_func()->insertIntoFocusChain(direction, position);
13498
13499 Q_ASSERT(first != last);
13500 switch (direction) {
13501 case FocusDirection::Previous:
13502 if (FOCUS_PREV(position) == last) {
13503 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already before"
13504 << position;
13505 return false;
13506 }
13507 FOCUS_NEXT(FOCUS_PREV(position)) = first;
13508 FOCUS_PREV(first) = FOCUS_PREV(position);
13509 FOCUS_NEXT(last) = position;
13510 FOCUS_PREV(position) = last;
13511 qCDebug(lcWidgetFocus) << toBeInserted << "inserted before" << position;
13512 break;
13513 case FocusDirection::Next:
13514 if (FOCUS_PREV(position) == last) {
13515 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already after"
13516 << position;
13517 return false;
13518 }
13519 FOCUS_PREV(FOCUS_NEXT(position)) = last;
13520 FOCUS_NEXT(last) = FOCUS_NEXT(position);
13521 FOCUS_PREV(first) = position;
13522 FOCUS_NEXT(position) = first;
13523 qCDebug(lcWidgetFocus) << toBeInserted << "inserted after" << position;
13524 break;
13525 }
13526
13527 Q_ASSERT(position->d_func()->isFocusChainConsistent());
13528 return true;
13529}
13530
13531/*!
13532 \internal
13533 \return a QWidgetList, representing the part of the focus chain,
13534 starting with \param from and ending with \param to, in \param direction.
13535 */
13536QWidgetList focusPath(QWidget *from, QWidget *to, QWidgetPrivate::FocusDirection direction)
13537{
13538 QWidgetList path({from});
13539 if (from == to)
13540 return path;
13541
13542 QWidget *current = from;
13543 do {
13544 switch (direction) {
13545 case QWidgetPrivate::FocusDirection::Previous:
13546 current = current->previousInFocusChain();
13547 break;
13548 case QWidgetPrivate::FocusDirection::Next:
13549 current = current->nextInFocusChain();
13550 break;
13551 }
13552 if (path.contains(current))
13553 return QWidgetList();
13554 path << current;
13555 } while (current != to);
13556
13557 return path;
13558}
13559
13560/*!
13561 \internal
13562 Removes the part from the focus chain starting with \param from and ending with \param to,
13563 in \param direction.
13564 \return removed part as a QWidgetList.
13565 */
13566QWidgetList QWidgetPrivate::takeFromFocusChain(QWidget *from,
13567 QWidget *to,
13568 FocusDirection direction)
13569{
13570 // Check if there is a path from->to in direction
13571 const QWidgetList path = focusPath(from, to , direction);
13572 if (path.isEmpty()) {
13573 qCDebug(lcWidgetFocus) << "No-op removal. Focus chain from" << from << "doesn't lead to " << to;
13574 return QWidgetList();
13575 }
13576
13577 QWidget *first = path.constFirst();
13578 QWidget *last = path.constLast();
13579 if (first == last) {
13580 first->d_func()->removeFromFocusChain();
13581 return QWidgetList({first});
13582 }
13583
13584 FOCUS_NEXT(FOCUS_PREV(first)) = FOCUS_NEXT(last);
13585 FOCUS_PREV(FOCUS_NEXT(last)) = FOCUS_PREV(first);
13586 FOCUS_PREV(first) = last;
13587 FOCUS_NEXT(last) = first;
13588 qCDebug(lcWidgetFocus) << path << "removed from focus chain";
13589 return path;
13590}
13591
13592/*!
13593 \internal
13594 \return The last focus child of the widget, traversing the focus chain no further than
13595 \param noFurtherThan.
13596 */
13597QWidget *QWidgetPrivate::determineLastFocusChild(QWidget *noFurtherThan)
13598{
13599 Q_Q(QWidget);
13600 // Since we need to repeat the same logic for both 'first' and 'second', we add a function
13601 // that determines the last focus child for a widget, taking proxies and compound widgets into
13602 // account. If the target is not a compound widget (it doesn't have a focus proxy that points
13603 // to a child), 'lastFocusChild' will be set to the target itself.
13604 QWidget *lastFocusChild = q;
13605
13606 QWidget *focusProxy = deepestFocusProxy();
13607 if (!focusProxy) {
13608 // QTBUG-81097: Another case is possible here. We can have a child
13609 // widget, that sets its focusProxy() to the parent (target).
13610 // An example of such widget is a QLineEdit, nested into
13611 // a QAbstractSpinBox. In this case such widget should be considered
13612 // the last focus child.
13613 for (auto *object : std::as_const(q->children())) {
13614 QWidget *w = qobject_cast<QWidget *>(object);
13615 if (w && w->focusProxy() == q) {
13616 lastFocusChild = w;
13617 break;
13618 }
13619 }
13620 } else if (q->isAncestorOf(focusProxy)) {
13621 lastFocusChild = focusProxy;
13622 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
13623 focusNext != focusProxy && q->isAncestorOf(focusNext)
13624 && focusNext->window() == focusProxy->window();
13625 focusNext = focusNext->nextInFocusChain()) {
13626 if (focusNext == noFurtherThan)
13627 break;
13628 if (focusNext->focusPolicy() != Qt::NoFocus)
13629 lastFocusChild = focusNext;
13630 }
13631 }
13632 return lastFocusChild;
13633};
13634
13635/*!
13636 \internal
13637 \return \c true, if the widget is part of a focus chain and \c false otherwise.
13638 A widget is considered to be part of a focus chain, neither FOCUS_NEXT, nor FOCUS_PREV
13639 are pointing to the widget itself.
13640
13641 \note
13642 This method doesn't check the consistency of the focus chain.
13643 If multiple widgets have been removed from the focus chain by takeFromFocusChain(),
13644 isInFocusChain() will return \c true for all of those widgets, even if they represent
13645 an inconsistent focus chain.
13646 */
13647bool QWidgetPrivate::isInFocusChain() const
13648{
13649 Q_Q(const QWidget);
13650 return !(FOCUS_NEXT(q) == q && FOCUS_PREV(q) == q);
13651}
13652
13653/*!
13654 \internal
13655 A focus chain is consistent, when it is circular: Following the chain in either direction
13656 has to return to the beginning. This is why a newly constructed widget points to itself,
13657 when the focus chain has been initialized. A newly constructed widget is considered to have
13658 a consistent focus chain, while not being part of a focus chain.
13659
13660 The method always returns \c true, when the logging category "qt.widgets.focus" is disabled.
13661 When it is enabled, the method returns \c true early, if a widget is pointing to itself.
13662 It returns \c false, if one of the following is detected:
13663 \list
13664 \li nullptr found in a previous/next pointer.
13665 \li broken chain: widget A is B's previous, but B isn't A's next.
13666 \li chain isn't closed: starting at A doesn't lead back to A.
13667 \endlist
13668 It return \c true, if none of the above is observed.
13669
13670 \note
13671 The focus chain is checked only in forward direction.
13672 This is sufficient, because the check for a broken chain asserts consistent paths
13673 in both directions.
13674 */
13675bool QWidgetPrivate::isFocusChainConsistent() const
13676{
13677 Q_Q(const QWidget);
13678 const bool skip = !lcWidgetFocus().isDebugEnabled();
13679 if (skip)
13680 return true;
13681
13682 if (!isInFocusChain())
13683 return true;
13684
13685 const QWidget *position = q;
13686
13687 for (int i = 0; i < QApplication::allWidgets().count(); ++i) {
13688 if (!FOCUS_PREV(position) || !FOCUS_NEXT(position)) {
13689 qCDebug(lcWidgetFocus) << "Nullptr found at:" << position
13690 << "Previous pointing to" << FOCUS_PREV(position)
13691 << "Next pointing to" << FOCUS_NEXT(position);
13692 return false;
13693 }
13694 if (!(FOCUS_PREV(FOCUS_NEXT(position)) == position
13695 && FOCUS_NEXT(FOCUS_PREV(position)) == position)) {
13696 qCDebug(lcWidgetFocus) << "Inconsistent focus chain at:" << position
13697 << "Previous pointing to" << FOCUS_PREV(FOCUS_NEXT(position))
13698 << "Next pointing to" << FOCUS_NEXT(FOCUS_PREV(position));
13699 return false;
13700 }
13701 position = FOCUS_NEXT(position);
13702 if (position == q)
13703 return true;
13704
13705 }
13706
13707 qCDebug(lcWidgetFocus) << "Focus chain leading from" << q << "to" << position << "is not closed.";
13708 return false;
13709}
13710
13711#undef FOCUS_NEXT
13712#undef FOCUS_PREV
13713
13714
13715QT_END_NAMESPACE
13716
13717#include "moc_qwidget.cpp"
13718#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