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
5#include "qapplication.h"
6#include "qapplication_p.h"
7#include "qbrush.h"
8#include "qcursor.h"
9#include "private/qduplicatetracker_p.h"
10#include "qevent.h"
11#include "qlayout.h"
12#if QT_CONFIG(menu)
13#include "qmenu.h"
14#endif
15#include "qmetaobject.h"
16#include "qpixmap.h"
17#include "qpointer.h"
18#include "qstack.h"
19#include "qstyle.h"
20#include "qstylefactory.h"
21#include "qvariant.h"
22#include "qwidget.h"
23#include "qstyleoption.h"
24#include "qstylehints.h"
25#if QT_CONFIG(accessibility)
26# include "qaccessible.h"
27#endif
28#include <qpa/qplatformwindow.h>
29#include <qpa/qplatformwindow_p.h>
30#include "private/qwidgetwindow_p.h"
31#include "qpainter.h"
32#if QT_CONFIG(tooltip)
33#include "qtooltip.h"
34#endif
35#if QT_CONFIG(whatsthis)
36#include "qwhatsthis.h"
37#endif
38#include "qdebug.h"
39#include "private/qstylesheetstyle_p.h"
40#include "private/qstyle_p.h"
41#include "qfileinfo.h"
42#include "qscopeguard.h"
43#include <QtGui/private/qhighdpiscaling_p.h>
44#include <QtGui/qinputmethod.h>
45
46#if QT_CONFIG(graphicseffect)
47#include <private/qgraphicseffect_p.h>
48#endif
49#include <qbackingstore.h>
50#include <private/qwidgetrepaintmanager_p.h>
51#include <private/qpaintengine_raster_p.h>
52
53#include "qwidget_p.h"
54#include <QtGui/private/qwindow_p.h>
55#if QT_CONFIG(action)
56# include "QtGui/private/qaction_p.h"
57#endif
58#include "qlayout_p.h"
59#if QT_CONFIG(graphicsview)
60#include "QtWidgets/qgraphicsproxywidget.h"
61#include "QtWidgets/qgraphicsscene.h"
62#include "private/qgraphicsproxywidget_p.h"
63#include "private/qgraphicsview_p.h"
64#endif
65#include "QtWidgets/qabstractscrollarea.h"
66#include "private/qabstractscrollarea_p.h"
67#include "private/qevent_p.h"
68
69#include "private/qgesturemanager_p.h"
70
71#ifdef QT_KEYPAD_NAVIGATION
72#if QT_CONFIG(tabwidget)
73#include "qtabwidget.h" // Needed in inTabWidget()
74#endif
75#endif // QT_KEYPAD_NAVIGATION
76
77#include "qwindowcontainer_p.h"
78
79#include <sstream>
80
81QT_BEGIN_NAMESPACE
82
83using namespace QNativeInterface::Private;
84using namespace Qt::StringLiterals;
85
86Q_LOGGING_CATEGORY(lcWidgetPainting, "qt.widgets.painting", QtWarningMsg);
87Q_LOGGING_CATEGORY(lcWidgetShowHide, "qt.widgets.showhide", QtWarningMsg);
88Q_LOGGING_CATEGORY(lcWidgetWindow, "qt.widgets.window", QtWarningMsg);
89Q_LOGGING_CATEGORY(lcWidgetFocus, "qt.widgets.focus")
90
91#ifndef QT_NO_DEBUG_STREAM
92namespace {
93 struct WidgetAttributes { const QWidget *widget; };
94 QDebug operator<<(QDebug debug, const WidgetAttributes &attributes);
95}
96#endif
97
98static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
99{
100 return (qMax(a: r1.left(), b: r2.left()) <= qMin(a: r1.right(), b: r2.right()) &&
101 qMax(a: r1.top(), b: r2.top()) <= qMin(a: r1.bottom(), b: r2.bottom()));
102}
103
104extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
105
106QWidgetPrivate::QWidgetPrivate(int 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#if defined(Q_OS_WIN)
159 , noPaintOnScreen(0)
160#endif
161{
162 if (Q_UNLIKELY(!qApp)) {
163 qFatal(msg: "QWidget: Must construct a QApplication before a QWidget");
164 return;
165 }
166
167#ifdef QT_BUILD_INTERNAL
168 // Don't check the version parameter in internal builds.
169 // This allows incompatible versions to be loaded, possibly for testing.
170 Q_UNUSED(version);
171#else
172 if (Q_UNLIKELY(version != QObjectPrivateVersion))
173 qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)",
174 version, QObjectPrivateVersion);
175#endif
176
177 willBeWidget = true; // used in QObject's ctor
178 memset(s: high_attributes, c: 0, n: sizeof(high_attributes));
179
180#ifdef QWIDGET_EXTRA_DEBUG
181 static int count = 0;
182 qDebug() << "widgets" << ++count;
183#endif
184}
185
186
187QWidgetPrivate::~QWidgetPrivate()
188{
189 if (widgetItem)
190 widgetItem->wid = nullptr;
191
192 if (extra)
193 deleteExtra();
194}
195
196/*!
197 \internal
198*/
199void QWidgetPrivate::scrollChildren(int dx, int dy)
200{
201 Q_Q(QWidget);
202 if (q->children().size() > 0) { // scroll children
203 QPoint pd(dx, dy);
204 QObjectList childObjects = q->children();
205 for (int i = 0; i < childObjects.size(); ++i) { // move all children
206 QWidget *w = qobject_cast<QWidget*>(o: childObjects.at(i));
207 if (w && !w->isWindow()) {
208 QPoint oldp = w->pos();
209 QRect r(w->pos() + pd, w->size());
210 w->data->crect = r;
211 if (w->testAttribute(attribute: Qt::WA_WState_Created))
212 w->d_func()->setWSGeometry();
213 w->d_func()->setDirtyOpaqueRegion();
214 QMoveEvent e(r.topLeft(), oldp);
215 QCoreApplication::sendEvent(receiver: w, event: &e);
216 }
217 }
218 }
219}
220
221void QWidgetPrivate::setWSGeometry()
222{
223 Q_Q(QWidget);
224 if (QWindow *window = q->windowHandle())
225 window->setGeometry(data.crect);
226}
227
228void QWidgetPrivate::updateWidgetTransform(QEvent *event)
229{
230 Q_Q(QWidget);
231 if (q == QGuiApplication::focusObject() || event->type() == QEvent::FocusIn) {
232 QTransform t;
233 QPoint p = q->mapTo(q->topLevelWidget(), QPoint(0,0));
234 t.translate(dx: p.x(), dy: p.y());
235 QGuiApplication::inputMethod()->setInputItemTransform(t);
236 QGuiApplication::inputMethod()->setInputItemRectangle(q->rect());
237 QGuiApplication::inputMethod()->update(queries: Qt::ImInputItemClipRectangle);
238 }
239}
240
241#ifdef QT_KEYPAD_NAVIGATION
242QPointer<QWidget> QWidgetPrivate::editingWidget;
243
244/*!
245 Returns \c true if this widget currently has edit focus; otherwise false.
246
247 This feature is only available in Qt for Embedded Linux.
248
249 \sa setEditFocus(), QApplication::navigationMode()
250*/
251bool QWidget::hasEditFocus() const
252{
253 const QWidget* w = this;
254 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
255 w = w->d_func()->extra->focus_proxy;
256 return QWidgetPrivate::editingWidget == w;
257}
258
259/*!
260 \fn void QWidget::setEditFocus(bool enable)
261
262 If \a enable is true, make this widget have edit focus, in which
263 case Qt::Key_Up and Qt::Key_Down will be delivered to the widget
264 normally; otherwise, Qt::Key_Up and Qt::Key_Down are used to
265 change focus.
266
267 This feature is only available in Qt for Embedded Linux.
268
269 \sa hasEditFocus(), QApplication::navigationMode()
270*/
271void QWidget::setEditFocus(bool on)
272{
273 QWidget *f = this;
274 while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
275 f = f->d_func()->extra->focus_proxy;
276
277 if (QWidgetPrivate::editingWidget && QWidgetPrivate::editingWidget != f)
278 QWidgetPrivate::editingWidget->setEditFocus(false);
279
280 if (on && !f->hasFocus())
281 f->setFocus();
282
283 if ((!on && !QWidgetPrivate::editingWidget)
284 || (on && QWidgetPrivate::editingWidget == f)) {
285 return;
286 }
287
288 if (!on && QWidgetPrivate::editingWidget == f) {
289 QWidgetPrivate::editingWidget = 0;
290 QEvent event(QEvent::LeaveEditFocus);
291 QCoreApplication::sendEvent(f, &event);
292 QCoreApplication::sendEvent(f->style(), &event);
293 } else if (on) {
294 QWidgetPrivate::editingWidget = f;
295 QEvent event(QEvent::EnterEditFocus);
296 QCoreApplication::sendEvent(f, &event);
297 QCoreApplication::sendEvent(f->style(), &event);
298 }
299}
300#endif
301
302/*!
303 \property QWidget::autoFillBackground
304 \brief whether the widget background is filled automatically
305 \since 4.1
306
307 If enabled, this property will cause Qt to fill the background of the
308 widget before invoking the paint event. The color used is defined by the
309 QPalette::Window color role from the widget's \l{QPalette}{palette}.
310
311 In addition, Windows are always filled with QPalette::Window, unless the
312 WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
313
314 This property cannot be turned off (i.e., set to false) if a widget's
315 parent has a static gradient for its background.
316
317 \warning Use this property with caution in conjunction with
318 \l{Qt Style Sheets}. When a widget has a style sheet with a valid
319 background or a border-image, this property is automatically disabled.
320
321 By default, this property is \c false.
322
323 \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
324 {QWidget#Transparency and Double Buffering}{Transparency and Double Buffering}
325*/
326bool QWidget::autoFillBackground() const
327{
328 Q_D(const QWidget);
329 return d->extra && d->extra->autoFillBackground;
330}
331
332void QWidget::setAutoFillBackground(bool enabled)
333{
334 Q_D(QWidget);
335 if (!d->extra)
336 d->createExtra();
337 if (d->extra->autoFillBackground == enabled)
338 return;
339
340 d->extra->autoFillBackground = enabled;
341 d->updateIsOpaque();
342 update();
343 d->updateIsOpaque();
344}
345
346/*!
347 \class QWidget
348 \brief The QWidget class is the base class of all user interface objects.
349
350 \ingroup basicwidgets
351 \inmodule QtWidgets
352
353 The widget is the atom of the user interface: it receives mouse, keyboard
354 and other events from the window system, and paints a representation of
355 itself on the screen. Every widget is rectangular, and they are sorted in a
356 Z-order. A widget is clipped by its parent and by the widgets in front of
357 it.
358
359 A widget that is not embedded in a parent widget is called a window.
360 Usually, windows have a frame and a title bar, although it is also possible
361 to create windows without such decoration using suitable
362 \l{Qt::WindowFlags}{window flags}. In Qt, QMainWindow and the various
363 subclasses of QDialog are the most common window types.
364
365 Every widget's constructor accepts one or two standard arguments:
366
367 \list 1
368 \li \c{QWidget *parent = nullptr} is the parent of the new widget.
369 If it is \nullptr (the default), the new widget will be a window.
370 If not, it will be a child of \e parent, and be constrained by
371 \e parent's geometry (unless you specify Qt::Window as window flag).
372 \li \c{Qt::WindowFlags f = { }} (where available) sets the window flags;
373 the default is suitable for most widgets, but to get, for
374 example, a window without a window system frame, you must use
375 special flags.
376 \endlist
377
378 QWidget has many member functions, but some of them have little direct
379 functionality; for example, QWidget has a font property, but never uses
380 this itself. There are many subclasses that provide real functionality,
381 such as QLabel, QPushButton, QListWidget, and QTabWidget.
382
383
384 \section1 Top-Level and Child Widgets
385
386 A widget without a parent widget is always an independent window (top-level
387 widget). For these widgets, setWindowTitle() and setWindowIcon() set the
388 title bar and icon, respectively.
389
390 Non-window widgets are child widgets, displayed within their parent
391 widgets. Most widgets in Qt are mainly useful as child widgets. For
392 example, it is possible to display a button as a top-level window, but most
393 people prefer to put their buttons inside other widgets, such as QDialog.
394
395 \image parent-child-widgets.png A parent widget containing various child widgets.
396
397 The diagram above shows a QGroupBox widget being used to hold various child
398 widgets in a layout provided by QGridLayout. The QLabel child widgets have
399 been outlined to indicate their full sizes.
400
401 If you want to use a QWidget to hold child widgets, you will usually want to
402 add a layout to the parent QWidget. See \l{Layout Management} for more
403 information.
404
405
406 \section1 Composite Widgets
407
408 When a widget is used as a container to group a number of child widgets, it
409 is known as a composite widget. These can be created by constructing a
410 widget with the required visual properties - a QFrame, for example - and
411 adding child widgets to it, usually managed by a layout.
412
413 Composite widgets can also be created by subclassing a standard widget,
414 such as QWidget or QFrame, and adding the necessary layout and child
415 widgets in the constructor of the subclass. Many of the \l{Qt Widgets Examples}
416 {examples provided with Qt} use this approach, and it is also covered in
417 the Qt \l{Widgets Tutorial}.
418
419
420 \section1 Custom Widgets and Painting
421
422 Since QWidget is a subclass of QPaintDevice, subclasses can be used to
423 display custom content that is composed using a series of painting
424 operations with an instance of the QPainter class. This approach contrasts
425 with the canvas-style approach used by the \l{Graphics View}
426 {Graphics View Framework} where items are added to a scene by the
427 application and are rendered by the framework itself.
428
429 Each widget performs all painting operations from within its paintEvent()
430 function. This is called whenever the widget needs to be redrawn, either
431 because of some external change or when requested by the application.
432
433 The \l{widgets/analogclock}{Analog Clock example} shows how a simple widget
434 can handle paint events.
435
436
437 \section1 Size Hints and Size Policies
438
439 When implementing a new widget, it is almost always useful to reimplement
440 sizeHint() to provide a reasonable default size for the widget and to set
441 the correct size policy with setSizePolicy().
442
443 By default, composite widgets that do not provide a size hint will be
444 sized according to the space requirements of their child widgets.
445
446 The size policy lets you supply good default behavior for the layout
447 management system, so that other widgets can contain and manage yours
448 easily. The default size policy indicates that the size hint represents
449 the preferred size of the widget, and this is often good enough for many
450 widgets.
451
452 \note The size of top-level widgets are constrained to 2/3 of the desktop's
453 height and width. You can resize() the widget manually if these bounds are
454 inadequate.
455
456
457 \section1 Events
458
459 Widgets respond to events that are typically caused by user actions. Qt
460 delivers events to widgets by calling specific event handler functions with
461 instances of QEvent subclasses containing information about each event.
462
463 If your widget only contains child widgets, you probably don't need to
464 implement any event handlers. If you want to detect a mouse click in a
465 child widget, call the child's underMouse() function inside the widget's
466 mousePressEvent().
467
468 The \l{widgets/scribble}{Scribble example} implements a wider set of
469 events to handle mouse movement, button presses, and window resizing.
470
471 You will need to supply the behavior and content for your own widgets, but
472 here is a brief overview of the events that are relevant to QWidget,
473 starting with the most common ones:
474
475 \list
476 \li paintEvent() is called whenever the widget needs to be repainted.
477 Every widget displaying custom content must implement it. Painting
478 using a QPainter can only take place in a paintEvent() or a
479 function called by a paintEvent().
480 \li resizeEvent() is called when the widget has been resized.
481 \li mousePressEvent() is called when a mouse button is pressed while
482 the mouse cursor is inside the widget, or when the widget has
483 grabbed the mouse using grabMouse(). Pressing the mouse without
484 releasing it is effectively the same as calling grabMouse().
485 \li mouseReleaseEvent() is called when a mouse button is released. A
486 widget receives mouse release events when it has received the
487 corresponding mouse press event. This means that if the user
488 presses the mouse inside \e your widget, then drags the mouse
489 somewhere else before releasing the mouse button, \e your widget
490 receives the release event. There is one exception: if a popup menu
491 appears while the mouse button is held down, this popup immediately
492 steals the mouse events.
493 \li mouseDoubleClickEvent() is called when the user double-clicks in
494 the widget. If the user double-clicks, the widget receives a mouse
495 press event, a mouse release event, (a mouse click event,) a second
496 mouse press, this event and finally a second mouse release event.
497 (Some mouse move events may also be
498 received if the mouse is not held steady during this operation.) It
499 is \e{not possible} to distinguish a click from a double-click
500 until the second click arrives. (This is one reason why most GUI
501 books recommend that double-clicks be an extension of
502 single-clicks, rather than trigger a different action.)
503 \endlist
504
505 Widgets that accept keyboard input need to reimplement a few more event
506 handlers:
507
508 \list
509 \li keyPressEvent() is called whenever a key is pressed, and again when
510 a key has been held down long enough for it to auto-repeat. The
511 \uicontrol Tab and \uicontrol Shift+Tab keys are only passed to the widget if
512 they are not used by the focus-change mechanisms. To force those
513 keys to be processed by your widget, you must reimplement
514 QWidget::event().
515 \li focusInEvent() is called when the widget gains keyboard focus
516 (assuming you have called setFocusPolicy()). Well-behaved widgets
517 indicate that they own the keyboard focus in a clear but discreet
518 way.
519 \li focusOutEvent() is called when the widget loses keyboard focus.
520 \endlist
521
522 You may be required to also reimplement some of the less common event
523 handlers:
524
525 \list
526 \li mouseMoveEvent() is called whenever the mouse moves while a mouse
527 button is held down. This can be useful during drag and drop
528 operations. If you call \l{setMouseTracking()}{setMouseTracking}(true),
529 you get mouse move events even when no buttons are held down.
530 (See also the \l{Drag and Drop in Qt}{Drag and Drop} guide.)
531 \li keyReleaseEvent() is called whenever a key is released and while it
532 is held down (if the key is auto-repeating). In that case, the
533 widget will receive a pair of key release and key press event for
534 every repeat. The \uicontrol Tab and \uicontrol Shift+Tab keys are only passed
535 to the widget if they are not used by the focus-change mechanisms.
536 To force those keys to be processed by your widget, you must
537 reimplement QWidget::event().
538 \li wheelEvent() is called whenever the user turns the mouse wheel
539 while the widget has the focus.
540 \li enterEvent() is called when the mouse enters the widget's screen
541 space. (This excludes screen space owned by any of the widget's
542 children.)
543 \li leaveEvent() is called when the mouse leaves the widget's screen
544 space. If the mouse enters a child widget, it will not cause a
545 leaveEvent().
546 \li moveEvent() is called when the widget has been moved relative to
547 its parent.
548 \li closeEvent() is called when the user closes the widget (or when
549 close() is called).
550 \endlist
551
552 There are also some rather obscure events described in the documentation
553 for QEvent::Type. To handle these events, you need to reimplement event()
554 directly.
555
556 The default implementation of event() handles \uicontrol Tab and \uicontrol Shift+Tab
557 (to move the keyboard focus), and passes on most of the other events to
558 one of the more specialized handlers above.
559
560 Events and the mechanism used to deliver them are covered in
561 \l{The Event System}.
562
563 \section1 Groups of Functions and Properties
564
565 \table
566 \header \li Context \li Functions and Properties
567
568 \row \li Window functions \li
569 show(),
570 hide(),
571 raise(),
572 lower(),
573 close().
574
575 \row \li Top-level windows \li
576 \l windowModified, \l windowTitle, \l windowIcon,
577 \l isActiveWindow, activateWindow(), \l minimized, showMinimized(),
578 \l maximized, showMaximized(), \l fullScreen, showFullScreen(),
579 showNormal().
580
581 \row \li Window contents \li
582 update(),
583 repaint(),
584 scroll().
585
586 \row \li Geometry \li
587 \l pos, x(), y(), \l rect, \l size, width(), height(), move(), resize(),
588 \l sizePolicy, sizeHint(), minimumSizeHint(),
589 updateGeometry(), layout(),
590 \l frameGeometry, \l geometry, \l childrenRect, \l childrenRegion,
591 adjustSize(),
592 mapFromGlobal(), mapToGlobal(),
593 mapFromParent(), mapToParent(),
594 \l maximumSize, \l minimumSize, \l sizeIncrement,
595 \l baseSize, setFixedSize()
596
597 \row \li Mode \li
598 \l visible, isVisibleTo(),
599 \l enabled, isEnabledTo(),
600 \l modal,
601 isWindow(),
602 \l mouseTracking,
603 \l updatesEnabled,
604 visibleRegion().
605
606 \row \li Look and feel \li
607 style(),
608 setStyle(),
609 \l styleSheet,
610 \l cursor,
611 \l font,
612 \l palette,
613 backgroundRole(), setBackgroundRole(),
614 fontInfo(), fontMetrics().
615
616 \row \li Keyboard focus functions \li
617 \l focus, \l focusPolicy,
618 setFocus(), clearFocus(), setTabOrder(), setFocusProxy(),
619 focusNextChild(), focusPreviousChild().
620
621 \row \li Mouse and keyboard grabbing \li
622 grabMouse(), releaseMouse(),
623 grabKeyboard(), releaseKeyboard(),
624 mouseGrabber(), keyboardGrabber().
625
626 \row \li Event handlers \li
627 event(),
628 mousePressEvent(),
629 mouseReleaseEvent(),
630 mouseDoubleClickEvent(),
631 mouseMoveEvent(),
632 keyPressEvent(),
633 keyReleaseEvent(),
634 focusInEvent(),
635 focusOutEvent(),
636 wheelEvent(),
637 enterEvent(),
638 leaveEvent(),
639 paintEvent(),
640 moveEvent(),
641 resizeEvent(),
642 closeEvent(),
643 dragEnterEvent(),
644 dragMoveEvent(),
645 dragLeaveEvent(),
646 dropEvent(),
647 childEvent(),
648 showEvent(),
649 hideEvent(),
650 customEvent().
651 changeEvent(),
652
653 \row \li System functions \li
654 parentWidget(), window(), setParent(), winId(),
655 find(), metric().
656
657 \row \li Context menu \li
658 contextMenuPolicy, contextMenuEvent(),
659 customContextMenuRequested(), actions()
660
661 \row \li Interactive help \li
662 setToolTip(), setWhatsThis()
663
664 \endtable
665
666
667 \section1 Widget Style Sheets
668
669 In addition to the standard widget styles for each platform, widgets can
670 also be styled according to rules specified in a \l{styleSheet}
671 {style sheet}. This feature enables you to customize the appearance of
672 specific widgets to provide visual cues to users about their purpose. For
673 example, a button could be styled in a particular way to indicate that it
674 performs a destructive action.
675
676 The use of widget style sheets is described in more detail in the
677 \l{Qt Style Sheets} document.
678
679
680 \section1 Transparency and Double Buffering
681
682 QWidget automatically double-buffers its painting, so there
683 is no need to write double-buffering code in paintEvent() to avoid
684 flicker.
685
686 The contents of parent widgets are propagated by
687 default to each of their children as long as Qt::WA_PaintOnScreen is not
688 set. Custom widgets can be written to take advantage of this feature by
689 updating irregular regions (to create non-rectangular child widgets), or
690 painting with colors that have less than full alpha component. The
691 following diagram shows how attributes and properties of a custom widget
692 can be fine-tuned to achieve different effects.
693
694 \image propagation-custom.png
695
696 In the above diagram, a semi-transparent rectangular child widget with an
697 area removed is constructed and added to a parent widget (a QLabel showing
698 a pixmap). Then, different properties and widget attributes are set to
699 achieve different effects:
700
701 \list
702 \li The left widget has no additional properties or widget attributes
703 set. This default state suits most custom widgets that have
704 transparency, are irregularly-shaped, or do not paint over their
705 entire area with an opaque brush.
706 \li The center widget has the \l autoFillBackground property set. This
707 property is used with custom widgets that rely on the widget to
708 supply a default background, and do not paint over their entire
709 area with an opaque brush.
710 \li The right widget has the Qt::WA_OpaquePaintEvent widget attribute
711 set. This indicates that the widget will paint over its entire area
712 with opaque colors. The widget's area will initially be
713 \e{uninitialized}, represented in the diagram with a red diagonal
714 grid pattern that shines through the overpainted area.
715 \endlist
716
717 To rapidly update custom widgets with simple background colors, such as
718 real-time plotting or graphing widgets, it is better to define a suitable
719 background color (using setBackgroundRole() with the
720 QPalette::Window role), set the \l autoFillBackground property, and only
721 implement the necessary drawing functionality in the widget's paintEvent().
722
723 To rapidly update custom widgets that constantly paint over their entire
724 areas with opaque content, for example, video streaming widgets, it is
725 better to set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary
726 overhead associated with repainting the widget's background.
727
728 If a widget has both the Qt::WA_OpaquePaintEvent widget attribute \e{and}
729 the \l autoFillBackground property set, the Qt::WA_OpaquePaintEvent
730 attribute takes precedence. Depending on your requirements, you should
731 choose either one of them.
732
733 The contents of parent widgets are also propagated to standard Qt widgets.
734 This can lead to some unexpected results if the parent widget is decorated
735 in a non-standard way, as shown in the diagram below.
736
737 \image propagation-standard.png
738
739 The scope for customizing the painting behavior of standard Qt widgets,
740 without resorting to subclassing, is slightly less than that possible for
741 custom widgets. Usually, the desired appearance of a standard widget can be
742 achieved by setting its \l autoFillBackground property.
743
744
745 \section1 Creating Translucent Windows
746
747 You can create windows with translucent regions on window systems that
748 support compositing.
749
750 To enable this feature in a top-level widget, set its Qt::WA_TranslucentBackground
751 attribute with setAttribute() and ensure that its background is painted with
752 non-opaque colors in the regions you want to be partially transparent.
753
754 Platform notes:
755
756 \list
757 \li X11: This feature relies on the use of an X server that supports ARGB visuals
758 and a compositing window manager.
759 \li Windows: The widget needs to have the Qt::FramelessWindowHint window flag set
760 for the translucency to work.
761 \li \macos: The widget needs to have the Qt::FramelessWindowHint window flag set
762 for the translucency to work.
763 \endlist
764
765
766 \section1 Native Widgets vs Alien Widgets
767
768 Alien widgets are widgets unknown to the windowing system. They do not have
769 a native window handle associated with them. This feature significantly
770 speeds up widget painting, resizing, and removes flicker.
771
772 Should you require the old behavior with native windows, choose one of the
773 following options:
774
775 \list 1
776 \li Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
777 \li Set the Qt::AA_NativeWindows attribute on your application. All
778 widgets will be native widgets.
779 \li Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
780 and all its ancestors will become native (unless
781 Qt::WA_DontCreateNativeAncestors is set).
782 \li Call QWidget::winId to enforce a native window (this implies 3).
783 \li Set the Qt::WA_PaintOnScreen attribute to enforce a native window
784 (this implies 3).
785 \endlist
786
787 \sa QEvent, QPainter, QGridLayout, QBoxLayout
788
789*/
790
791QWidgetMapper *QWidgetPrivate::mapper = nullptr; // widget with wid
792QWidgetSet *QWidgetPrivate::allWidgets = nullptr; // widgets with no wid
793
794
795/*****************************************************************************
796 QWidget member functions
797 *****************************************************************************/
798
799/*
800 Widget state flags:
801 \list
802 \li Qt::WA_WState_Created The widget has a valid winId().
803 \li Qt::WA_WState_Visible The widget is currently visible.
804 \li Qt::WA_WState_Hidden The widget is hidden, i.e. it won't
805 become visible unless you call show() on it. Qt::WA_WState_Hidden
806 implies !Qt::WA_WState_Visible.
807 \li Qt::WA_WState_CompressKeys Compress keyboard events.
808 \li Qt::WA_WState_BlockUpdates Repaints and updates are disabled.
809 \li Qt::WA_WState_InPaintEvent Currently processing a paint event.
810 \li Qt::WA_WState_Reparented The widget has been reparented.
811 \li Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending.
812 \endlist
813*/
814
815struct QWidgetExceptionCleaner
816{
817 /* this cleans up when the constructor throws an exception */
818 static inline void cleanup(QWidget *that, QWidgetPrivate *d)
819 {
820#ifdef QT_NO_EXCEPTIONS
821 Q_UNUSED(that);
822 Q_UNUSED(d);
823#else
824 QWidgetPrivate::allWidgets->remove(that);
825 d->removeFromFocusChain();
826#endif
827 }
828};
829
830/*!
831 Constructs a widget which is a child of \a parent, with widget
832 flags set to \a f.
833
834 If \a parent is \nullptr, the new widget becomes a window. If
835 \a parent is another widget, this widget becomes a child window
836 inside \a parent. The new widget is deleted when its \a parent is
837 deleted.
838
839 The widget flags argument, \a f, is normally 0, but it can be set
840 to customize the frame of a window (i.e. \a parent must be
841 \nullptr). To customize the frame, use a value composed
842 from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
843
844 If you add a child widget to an already visible widget you must
845 explicitly show the child to make it visible.
846
847 Note that the X11 version of Qt may not be able to deliver all
848 combinations of style flags on all systems. This is because on
849 X11, Qt can only ask the window manager, and the window manager
850 can override the application's settings. On Windows, Qt can set
851 whatever flags you want.
852
853 \sa windowFlags
854*/
855QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
856 : QObject(*new QWidgetPrivate, nullptr), QPaintDevice()
857{
858 QT_TRY {
859 d_func()->init(desktopWidget: parent, f);
860 } QT_CATCH(...) {
861 QWidgetExceptionCleaner::cleanup(that: this, d: d_func());
862 QT_RETHROW;
863 }
864}
865
866
867/*! \internal
868*/
869QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
870 : QObject(dd, nullptr), QPaintDevice()
871{
872 Q_D(QWidget);
873 QT_TRY {
874 d->init(desktopWidget: parent, f);
875 } QT_CATCH(...) {
876 QWidgetExceptionCleaner::cleanup(that: this, d: d_func());
877 QT_RETHROW;
878 }
879}
880
881/*!
882 \internal
883*/
884int QWidget::devType() const
885{
886 return QInternal::Widget;
887}
888
889
890//### w is a "this" ptr, passed as a param because QWorkspace needs special logic
891void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
892{
893 bool customize = (flags & (Qt::CustomizeWindowHint
894 | Qt::FramelessWindowHint
895 | Qt::WindowTitleHint
896 | Qt::WindowSystemMenuHint
897 | Qt::WindowMinimizeButtonHint
898 | Qt::WindowMaximizeButtonHint
899 | Qt::WindowCloseButtonHint
900 | Qt::WindowContextHelpButtonHint));
901
902 uint type = (flags & Qt::WindowType_Mask);
903
904 if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) {
905 type = Qt::Window;
906 flags |= Qt::Window;
907 }
908
909 if (flags & Qt::CustomizeWindowHint) {
910 // modify window flags to make them consistent.
911 // Only enable this on non-Mac platforms. Since the old way of doing this would
912 // interpret WindowSystemMenuHint as a close button and we can't change that behavior
913 // we can't just add this in.
914 if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint))
915# ifdef Q_OS_WIN
916 && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs.
917# endif
918 ) {
919 flags |= Qt::WindowSystemMenuHint;
920 flags |= Qt::WindowTitleHint;
921 flags &= ~Qt::FramelessWindowHint;
922 }
923 } else if (customize && !(flags & Qt::FramelessWindowHint)) {
924 // if any of the window hints that affect the titlebar are set
925 // and the window is supposed to have frame, we add a titlebar
926 // and system menu by default.
927 flags |= Qt::WindowSystemMenuHint;
928 flags |= Qt::WindowTitleHint;
929 }
930 if (!customize) { // don't modify window flags if the user explicitly set them.
931 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
932 if (type != Qt::Dialog && type != Qt::Sheet && type != Qt::Tool)
933 flags |= Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowFullscreenButtonHint;
934 }
935 if (w->testAttribute(attribute: Qt::WA_TransparentForMouseEvents))
936 flags |= Qt::WindowTransparentForInput;
937}
938
939void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
940{
941 Q_Q(QWidget);
942 isWidget = true;
943 wasWidget = true;
944
945 Q_ASSERT_X(q != parentWidget, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
946
947 if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
948 qFatal(msg: "QWidget: Cannot create a QWidget without QApplication");
949
950 Q_ASSERT(allWidgets);
951 if (allWidgets)
952 allWidgets->insert(value: q);
953
954 q->data = &data;
955
956#if QT_CONFIG(thread)
957 if (!parent) {
958 Q_ASSERT_X(QThread::isMainThread(), "QWidget",
959 "Widgets must be created in the GUI thread.");
960 }
961#endif
962
963 data.fstrut_dirty = true;
964
965 data.winid = 0;
966 data.widget_attributes = 0;
967 data.window_flags = f;
968 data.window_state = 0;
969 data.focus_policy = 0;
970 data.context_menu_policy = Qt::DefaultContextMenu;
971 data.window_modality = Qt::NonModal;
972
973 data.sizehint_forced = 0;
974 data.is_closing = false;
975 data.in_show = 0;
976 data.in_set_window_state = 0;
977 data.in_destructor = false;
978
979 // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
980 if (f & Qt::MSWindowsOwnDC) {
981 mustHaveWindowHandle = 1;
982 q->setAttribute(Qt::WA_NativeWindow);
983 }
984
985 q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
986 adjustQuitOnCloseAttribute();
987
988 q->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea);
989 q->setAttribute(Qt::WA_WState_Hidden);
990
991 //give potential windows a bigger "pre-initial" size; create() will give them a new size later
992 data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
993 initFocusChain();
994
995 if ((f & Qt::WindowType_Mask) == Qt::Desktop)
996 q->create();
997 else if (parentWidget)
998 q->setParent(parent: parentWidget, f: data.window_flags);
999 else {
1000 adjustFlags(flags&: data.window_flags, w: q);
1001 resolveLayoutDirection();
1002 // opaque system background?
1003 const QBrush &background = q->palette().brush(cr: QPalette::Window);
1004 setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
1005 }
1006 data.fnt = QFont(data.fnt, q);
1007
1008 q->setAttribute(Qt::WA_PendingMoveEvent);
1009 q->setAttribute(Qt::WA_PendingResizeEvent);
1010
1011 if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
1012 QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
1013
1014 QEvent e(QEvent::Create);
1015 QCoreApplication::sendEvent(receiver: q, event: &e);
1016 QCoreApplication::postEvent(receiver: q, event: new QEvent(QEvent::PolishRequest));
1017
1018 extraPaintEngine = nullptr;
1019}
1020
1021void QWidgetPrivate::createRecursively()
1022{
1023 Q_Q(QWidget);
1024 q->create(0, initializeWindow: true, destroyOldWindow: true);
1025 for (int i = 0; i < children.size(); ++i) {
1026 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
1027 if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(attribute: Qt::WA_WState_Created))
1028 child->d_func()->createRecursively();
1029 }
1030}
1031
1032QRhi *QWidgetPrivate::rhi() const
1033{
1034 Q_Q(const QWidget);
1035 if (auto *backingStore = q->backingStore()) {
1036 auto *window = windowHandle(mode: WindowHandleMode::Closest);
1037 return backingStore->handle()->rhi(window);
1038 } else {
1039 return nullptr;
1040 }
1041}
1042
1043/*!
1044 \internal
1045 Returns the closest parent widget that has a QWindow window handle
1046
1047 \note This behavior is different from nativeParentWidget(), which
1048 returns the closest parent that has a QWindow window handle with
1049 a created QPlatformWindow, and hence native window (winId).
1050*/
1051QWidget *QWidgetPrivate::closestParentWidgetWithWindowHandle() const
1052{
1053 Q_Q(const QWidget);
1054 QWidget *parent = q->parentWidget();
1055 while (parent && !parent->windowHandle())
1056 parent = parent->parentWidget();
1057 return parent;
1058}
1059
1060QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
1061{
1062 if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) {
1063 if (QTLWExtra *x = maybeTopData()) {
1064 if (x->window != nullptr || mode == WindowHandleMode::Direct)
1065 return x->window;
1066 }
1067 }
1068 if (mode == WindowHandleMode::Closest) {
1069 // FIXME: Use closestParentWidgetWithWindowHandle instead
1070 if (auto nativeParent = q_func()->nativeParentWidget()) {
1071 if (auto window = nativeParent->windowHandle())
1072 return window;
1073 }
1074 }
1075 if (mode == WindowHandleMode::TopLevel || mode == WindowHandleMode::Closest) {
1076 if (auto topLevel = q_func()->topLevelWidget()) {
1077 if (auto window = topLevel ->windowHandle())
1078 return window;
1079 }
1080 }
1081 return nullptr;
1082}
1083
1084/*!
1085 \internal
1086
1087 Used by clients outside of widgets to get a handle to the
1088 closest QWindow without having to link to widgets.
1089*/
1090QWindow *QWidgetPrivate::_q_closestWindowHandle() const
1091{
1092 return windowHandle(mode: QWidgetPrivate::WindowHandleMode::Closest);
1093}
1094
1095QScreen *QWidgetPrivate::associatedScreen() const
1096{
1097#if QT_CONFIG(graphicsview)
1098 // embedded widgets never have a screen associated, let QWidget::screen fall back to toplevel
1099 if (nearestGraphicsProxyWidget(origin: q_func()))
1100 return nullptr;
1101#endif
1102 if (auto window = windowHandle(mode: WindowHandleMode::Closest))
1103 return window->screen();
1104 return nullptr;
1105}
1106
1107// finds the first rhiconfig in the hierarchy that has enable==true
1108static bool q_evaluateRhiConfigRecursive(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
1109{
1110 QPlatformBackingStoreRhiConfig config = QWidgetPrivate::get(w)->rhiConfig();
1111 if (config.isEnabled()) {
1112 if (outConfig)
1113 *outConfig = config;
1114 if (outType)
1115 *outType = QBackingStoreRhiSupport::surfaceTypeForConfig(config);
1116 return true;
1117 }
1118 for (const QObject *child : w->children()) {
1119 if (const QWidget *childWidget = qobject_cast<const QWidget *>(o: child)) {
1120 if (q_evaluateRhiConfigRecursive(w: childWidget, outConfig, outType)) {
1121 static bool optOut = qEnvironmentVariableIsSet(varName: "QT_WIDGETS_NO_CHILD_RHI");
1122 // Native child widgets should not trigger RHI for its parent
1123 // hierarchy, but will still flush the native child using RHI.
1124 if (!optOut && childWidget->testAttribute(attribute: Qt::WA_NativeWindow))
1125 continue;
1126
1127 return true;
1128 }
1129 }
1130 }
1131 return false;
1132}
1133
1134bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
1135{
1136 // First, check env.vars. or other means that force the usage of rhi-based
1137 // flushing with a specific graphics API. This takes precedence over what
1138 // the widgets themselves declare. This is global, applying to all
1139 // top-levels.
1140 if (QBackingStoreRhiSupport::checkForceRhi(outConfig, outType)) {
1141 qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluated to forced flushing with QRhi";
1142 return true;
1143 }
1144
1145 // Otherwise, check the widget hierarchy to see if there is a child (or
1146 // ourselves) that declare the need for rhi-based composition.
1147 if (q_evaluateRhiConfigRecursive(w, outConfig, outType)) {
1148 qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluates to flushing with QRhi";
1149 return true;
1150 }
1151
1152 return false;
1153}
1154
1155// ### fixme: Qt 6: Remove parameter window from QWidget::create()
1156
1157/*!
1158 Creates a new widget window.
1159
1160 The parameters \a window, \a initializeWindow, and \a destroyOldWindow
1161 are ignored in Qt 5. Please use QWindow::fromWinId() to create a
1162 QWindow wrapping a foreign window and pass it to
1163 QWidget::createWindowContainer() instead.
1164
1165 \sa createWindowContainer(), QWindow::fromWinId()
1166*/
1167
1168void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
1169{
1170 Q_UNUSED(initializeWindow);
1171 Q_UNUSED(destroyOldWindow);
1172
1173 Q_D(QWidget);
1174 if (Q_UNLIKELY(window))
1175 qWarning(msg: "QWidget::create(): Parameter 'window' does not have any effect.");
1176 if (testAttribute(attribute: Qt::WA_WState_Created) && window == 0 && internalWinId())
1177 return;
1178
1179 if (d->data.in_destructor)
1180 return;
1181
1182 Qt::WindowType type = windowType();
1183 Qt::WindowFlags &flags = data->window_flags;
1184
1185 if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
1186 type = Qt::Window;
1187 flags |= Qt::Window;
1188 }
1189
1190 if (QWidget *parent = parentWidget()) {
1191 if (type & Qt::Window) {
1192 if (!parent->testAttribute(attribute: Qt::WA_WState_Created))
1193 parent->createWinId();
1194 } else if (testAttribute(attribute: Qt::WA_NativeWindow) && !parent->internalWinId()
1195 && !testAttribute(attribute: Qt::WA_DontCreateNativeAncestors)) {
1196 // We're about to create a native child widget that doesn't have a native parent;
1197 // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
1198 // attribute is set.
1199 d->createWinId();
1200 // Nothing more to do.
1201 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1202 Q_ASSERT(internalWinId());
1203 return;
1204 }
1205 }
1206
1207
1208 static const bool paintOnScreenEnv = qEnvironmentVariableIntValue(varName: "QT_ONSCREEN_PAINT") > 0;
1209 if (paintOnScreenEnv)
1210 setAttribute(Qt::WA_PaintOnScreen);
1211
1212 if (QApplicationPrivate::testAttribute(flag: Qt::AA_NativeWindows))
1213 setAttribute(Qt::WA_NativeWindow);
1214
1215 d->updateIsOpaque();
1216
1217 setAttribute(Qt::WA_WState_Created); // set created flag
1218 d->create();
1219
1220 // A real toplevel window needs a paint manager
1221 if (isWindow() && windowType() != Qt::Desktop)
1222 d->topData()->repaintManager.reset(p: new QWidgetRepaintManager(this));
1223
1224 d->setModal_sys();
1225
1226 if (!isWindow() && parentWidget() && parentWidget()->testAttribute(attribute: Qt::WA_DropSiteRegistered))
1227 setAttribute(Qt::WA_DropSiteRegistered, on: true);
1228
1229 // need to force the resting of the icon after changing parents
1230 if (testAttribute(attribute: Qt::WA_SetWindowIcon))
1231 d->setWindowIcon_sys();
1232
1233 if (isWindow() && !d->topData()->iconText.isEmpty())
1234 d->setWindowIconText_helper(d->topData()->iconText);
1235 if (isWindow() && !d->topData()->caption.isEmpty())
1236 d->setWindowTitle_helper(d->topData()->caption);
1237 if (isWindow() && !d->topData()->filePath.isEmpty())
1238 d->setWindowFilePath_helper(d->topData()->filePath);
1239 if (windowType() != Qt::Desktop) {
1240 d->updateSystemBackground();
1241
1242 if (isWindow() && !testAttribute(attribute: Qt::WA_SetWindowIcon))
1243 d->setWindowIcon_sys();
1244 }
1245
1246 // Frame strut update needed in cases where there are native widgets such as QGLWidget,
1247 // as those force native window creation on their ancestors before they are shown.
1248 // If the strut is not updated, any subsequent move of the top level window before show
1249 // will cause window frame to be ignored when positioning the window.
1250 // Note that this only helps on platforms that handle window creation synchronously.
1251 d->updateFrameStrut();
1252}
1253
1254void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
1255{
1256 QObjectList children = parentWidget->children();
1257 for (int i = 0; i < children.size(); i++) {
1258 if (children.at(i)->isWidgetType()) {
1259 const QWidget *childWidget = qobject_cast<const QWidget *>(object: children.at(i));
1260 if (childWidget) { // should not be necessary
1261 if (childWidget->testAttribute(attribute: Qt::WA_NativeWindow)) {
1262 if (!childWidget->internalWinId())
1263 childWidget->winId();
1264 if (childWidget->windowHandle()) {
1265 if (childWidget->isWindow()) {
1266 childWidget->windowHandle()->setTransientParent(parentWidget->window()->windowHandle());
1267 } else {
1268 childWidget->windowHandle()->setParent(childWidget->nativeParentWidget()->windowHandle());
1269 }
1270 }
1271 } else {
1272 q_createNativeChildrenAndSetParent(parentWidget: childWidget);
1273 }
1274 }
1275 }
1276 }
1277
1278}
1279
1280void QWidgetPrivate::create()
1281{
1282 Q_Q(QWidget);
1283
1284 if (!q->testAttribute(attribute: Qt::WA_NativeWindow) && !q->isWindow())
1285 return; // we only care about real toplevels
1286
1287 QWidgetWindow *win = topData()->window;
1288 // topData() ensures the extra is created but does not ensure 'window' is non-null
1289 // in case the extra was already valid.
1290 if (!win) {
1291 createTLSysExtra();
1292 Q_ASSERT(topData()->window);
1293 win = topData()->window;
1294 }
1295
1296 const auto dynamicPropertyNames = q->dynamicPropertyNames();
1297 for (const QByteArray &propertyName : dynamicPropertyNames) {
1298 if (!qstrncmp(str1: propertyName, str2: "_q_platform_", len: 12))
1299 win->setProperty(name: propertyName, value: q->property(name: propertyName));
1300 }
1301
1302 Qt::WindowFlags &flags = data.window_flags;
1303
1304#if defined(QT_PLATFORM_UIKIT)
1305 if (q->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
1306 flags |= Qt::MaximizeUsingFullscreenGeometryHint;
1307#endif
1308
1309 if (q->testAttribute(attribute: Qt::WA_ShowWithoutActivating))
1310 win->setProperty(name: "_q_showWithoutActivating", value: QVariant(true));
1311 if (q->testAttribute(attribute: Qt::WA_MacAlwaysShowToolWindow))
1312 win->setProperty(name: "_q_macAlwaysShowToolWindow", value: QVariant(true));
1313 win->setFlags(flags);
1314 fixPosIncludesFrame();
1315 if (q->testAttribute(attribute: Qt::WA_Moved)
1316 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowManagement))
1317 win->setGeometry(q->geometry());
1318 else
1319 win->resize(newSize: q->size());
1320 if (win->isTopLevel()) {
1321 QScreen *targetScreen = topData()->initialScreen;
1322 topData()->initialScreen = nullptr;
1323 if (!targetScreen) {
1324 targetScreen = q->windowType() != Qt::Desktop
1325 ? q->screen() : nullptr;
1326 }
1327 win->setScreen(targetScreen);
1328 }
1329
1330 QSurfaceFormat format = win->requestedFormat();
1331 if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
1332 && q->testAttribute(attribute: Qt::WA_TranslucentBackground)) {
1333 format.setAlphaBufferSize(8);
1334 }
1335 win->setFormat(format);
1336
1337 if (QWidget *nativeParent = q->nativeParentWidget()) {
1338 if (nativeParent->windowHandle()) {
1339 if (flags & Qt::Window) {
1340 win->setTransientParent(nativeParent->window()->windowHandle());
1341 win->setParent(nullptr);
1342 } else {
1343 win->setTransientParent(nullptr);
1344 win->setParent(nativeParent->windowHandle());
1345 }
1346 }
1347 }
1348
1349 qt_window_private(window: win)->positionPolicy = topData()->posIncludesFrame ?
1350 QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
1351
1352 if (q->windowType() != Qt::Desktop || q->testAttribute(attribute: Qt::WA_NativeWindow)) {
1353 win->create();
1354 // Enable nonclient-area events for QDockWidget and other NonClientArea-mouse event processing.
1355 if (QPlatformWindow *platformWindow = win->handle())
1356 platformWindow->setFrameStrutEventsEnabled(true);
1357 }
1358
1359 data.window_flags = win->flags();
1360
1361#if QT_CONFIG(xcb)
1362 if (!topData()->role.isNull()) {
1363 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(win->handle()))
1364 xcbWindow->setWindowRole(topData()->role);
1365 }
1366#endif
1367
1368 QBackingStore *store = q->backingStore();
1369 usesRhiFlush = false;
1370
1371 if (q->windowType() == Qt::Desktop) {
1372 q->setAttribute(Qt::WA_PaintOnScreen, on: true);
1373 } else {
1374 if (!store && q->isWindow())
1375 q->setBackingStore(new QBackingStore(win));
1376
1377 QPlatformBackingStoreRhiConfig rhiConfig;
1378 usesRhiFlush = q_evaluateRhiConfig(w: q, outConfig: &rhiConfig, outType: nullptr);
1379 if (usesRhiFlush && q->backingStore()) {
1380 // Trigger creation of support infrastructure up front,
1381 // now that we have a specific RHI configuration.
1382 q->backingStore()->handle()->createRhi(window: win, config: rhiConfig);
1383 }
1384 }
1385
1386 setWindowModified_helper();
1387
1388 if (win->handle()) {
1389 WId id = win->winId();
1390 // See the QPlatformWindow::winId() documentation
1391 Q_ASSERT(id != WId(0));
1392 setWinId(id);
1393 }
1394 setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
1395
1396 // Check children and create windows for them if necessary
1397 q_createNativeChildrenAndSetParent(parentWidget: q);
1398
1399 if (extra && !extra->mask.isEmpty())
1400 setMask_sys(extra->mask);
1401
1402 if (data.crect.width() == 0 || data.crect.height() == 0) {
1403 q->setAttribute(Qt::WA_OutsideWSRange, on: true);
1404 } else {
1405 q->setAttribute(Qt::WA_OutsideWSRange, on: false);
1406 if (q->isVisible()) {
1407 // If widget is already shown, set window visible, too
1408 win->setNativeWindowVisibility(true);
1409 }
1410 }
1411}
1412
1413#ifdef Q_OS_WIN
1414static const char activeXNativeParentHandleProperty[] = "_q_embedded_native_parent_handle";
1415#endif
1416
1417void QWidgetPrivate::createTLSysExtra()
1418{
1419 Q_Q(QWidget);
1420 if (!extra->topextra->window && (q->testAttribute(attribute: Qt::WA_NativeWindow) || q->isWindow())) {
1421 extra->topextra->window = new QWidgetWindow(q);
1422 if (extra->minw || extra->minh)
1423 extra->topextra->window->setMinimumSize(QSize(extra->minw, extra->minh));
1424 if (extra->maxw != QWIDGETSIZE_MAX || extra->maxh != QWIDGETSIZE_MAX)
1425 extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
1426 if (extra->topextra->opacity != 255 && q->isWindow())
1427 extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
1428
1429 const bool isTipLabel = q->inherits(classname: "QTipLabel");
1430 const bool isAlphaWidget = !isTipLabel && q->inherits(classname: "QAlphaWidget");
1431#ifdef Q_OS_WIN
1432 // Pass on native parent handle for Widget embedded into Active X.
1433 const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
1434 if (activeXNativeParentHandle.isValid())
1435 extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
1436 if (isTipLabel || isAlphaWidget)
1437 extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
1438#endif
1439 if (isTipLabel || isAlphaWidget || q->inherits(classname: "QRollEffect"))
1440 qt_window_private(window: extra->topextra->window)->setAutomaticPositionAndResizeEnabled(false);
1441
1442 updateIsTranslucent();
1443 }
1444
1445}
1446
1447/*!
1448 Destroys the widget.
1449
1450 All this widget's children are deleted first. The application
1451 exits if this widget is the main widget.
1452*/
1453
1454QWidget::~QWidget()
1455{
1456 Q_D(QWidget);
1457 d->data.in_destructor = true;
1458
1459#if defined (QT_CHECK_STATE)
1460 if (Q_UNLIKELY(paintingActive()))
1461 qWarning("QWidget: %s (%s) deleted while being painted", className(), name());
1462#endif
1463
1464#ifndef QT_NO_GESTURES
1465 if (QGestureManager *manager = QGestureManager::instance(ic: QGestureManager::DontForceCreation)) {
1466 // \forall Qt::GestureType type : ungrabGesture(type) (inlined)
1467 for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
1468 manager->cleanupCachedGestures(target: this, type: *it);
1469 }
1470 d->gestureContext.clear();
1471#endif
1472
1473#ifndef QT_NO_ACTION
1474 // remove all actions from this widget
1475 for (auto action : std::as_const(t&: d->actions)) {
1476 QActionPrivate *apriv = action->d_func();
1477 apriv->associatedObjects.removeAll(t: this);
1478 }
1479 d->actions.clear();
1480#endif
1481
1482#ifndef QT_NO_SHORTCUT
1483 // Remove all shortcuts grabbed by this
1484 // widget, unless application is closing
1485 if (!QApplicationPrivate::is_app_closing && testAttribute(attribute: Qt::WA_GrabbedShortcut))
1486 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id: 0, owner: this, key: QKeySequence());
1487#endif
1488
1489 // delete layout while we still are a valid widget
1490 delete d->layout;
1491 d->layout = nullptr;
1492
1493 // Remove this from focus list
1494 d->removeFromFocusChain(rules: QWidgetPrivate::FocusChainRemovalRule::AssertConsistency);
1495
1496 QT_TRY {
1497#if QT_CONFIG(graphicsview)
1498 const QWidget* w = this;
1499 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
1500 w = w->d_func()->extra->focus_proxy;
1501 QWidget *window = w->window();
1502 QWExtra *e = window ? window->d_func()->extra.get() : nullptr ;
1503 if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this))
1504#endif
1505 clearFocus();
1506 } QT_CATCH(...) {
1507 // swallow this problem because we are in a destructor
1508 }
1509
1510 d->setDirtyOpaqueRegion();
1511
1512 if (isWindow() && isVisible() && internalWinId()) {
1513 QT_TRY {
1514 d->close();
1515 } QT_CATCH(...) {
1516 // if we're out of memory, at least hide the window.
1517 QT_TRY {
1518 hide();
1519 } QT_CATCH(...) {
1520 // and if that also doesn't work, then give up
1521 }
1522 }
1523 } else if (isVisible()) {
1524 qApp->d_func()->sendSyntheticEnterLeave(widget: this);
1525 }
1526
1527 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
1528 repaintManager->removeDirtyWidget(w: this);
1529 if (testAttribute(attribute: Qt::WA_StaticContents))
1530 repaintManager->removeStaticWidget(widget: this);
1531 }
1532
1533 delete d->needsFlush;
1534 d->needsFlush = nullptr;
1535
1536 // The next 20 lines are duplicated from QObject, but required here
1537 // since QWidget deletes is children itself
1538 bool blocked = d->blockSig;
1539 d->blockSig = 0; // unblock signals so we always emit destroyed()
1540
1541 if (d->isSignalConnected(signalIdx: 0)) {
1542 QT_TRY {
1543 emit destroyed(this);
1544 } QT_CATCH(...) {
1545 // all the signal/slots connections are still in place - if we don't
1546 // quit now, we will crash pretty soon.
1547 qWarning(msg: "Detected an unexpected exception in ~QWidget while emitting destroyed().");
1548 QT_RETHROW;
1549 }
1550 }
1551
1552 if (d->declarativeData) {
1553 d->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1554 if (QAbstractDeclarativeData::destroyed)
1555 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1556 d->declarativeData = nullptr; // don't activate again in ~QObject
1557 d->wasDeleted = false;
1558 }
1559
1560 d->blockSig = blocked;
1561
1562 if (!d->children.isEmpty())
1563 d->deleteChildren();
1564
1565 QCoreApplication::removePostedEvents(receiver: this);
1566
1567 QT_TRY {
1568 destroy(); // platform-dependent cleanup
1569 } QT_CATCH(...) {
1570 // if this fails we can't do anything about it but at least we are not allowed to throw.
1571 }
1572 --QWidgetPrivate::instanceCounter;
1573
1574 if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
1575 QWidgetPrivate::allWidgets->remove(value: this);
1576
1577 QT_TRY {
1578 QEvent e(QEvent::Destroy);
1579 QCoreApplication::sendEvent(receiver: this, event: &e);
1580 } QT_CATCH(const std::exception&) {
1581 // if this fails we can't do anything about it but at least we are not allowed to throw.
1582 }
1583
1584#if QT_CONFIG(graphicseffect)
1585 delete d->graphicsEffect;
1586#endif
1587 d->deleteExtra();
1588
1589 d->isWidget = false;
1590}
1591
1592int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
1593int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances
1594
1595void QWidgetPrivate::setWinId(WId id) // set widget identifier
1596{
1597 Q_Q(QWidget);
1598 if (mapper && data.winid) {
1599 mapper->remove(key: data.winid);
1600 }
1601
1602 const WId oldWinId = data.winid;
1603
1604 data.winid = id;
1605 if (mapper && id) {
1606 mapper->insert(key: data.winid, value: q);
1607 }
1608
1609 if (oldWinId != id) {
1610 QEvent e(QEvent::WinIdChange);
1611 QCoreApplication::sendEvent(receiver: q, event: &e);
1612 }
1613}
1614
1615void QWidgetPrivate::createTLExtra()
1616{
1617 if (!extra)
1618 createExtra();
1619 if (!extra->topextra) {
1620 extra->topextra = std::make_unique<QTLWExtra>();
1621 QTLWExtra* x = extra->topextra.get();
1622 x->backingStore = nullptr;
1623 x->sharedPainter = nullptr;
1624 x->incw = x->inch = 0;
1625 x->basew = x->baseh = 0;
1626 x->frameStrut.setCoords(xp1: 0, yp1: 0, xp2: 0, yp2: 0);
1627 x->normalGeometry = QRect(0,0,-1,-1);
1628 x->savedFlags = { };
1629 x->opacity = 255;
1630 x->posIncludesFrame = 0;
1631 x->sizeAdjusted = false;
1632 x->embedded = 0;
1633 x->window = nullptr;
1634 x->initialScreen = nullptr;
1635
1636#ifdef QWIDGET_EXTRA_DEBUG
1637 static int count = 0;
1638 qDebug() << "tlextra" << ++count;
1639#endif
1640 }
1641}
1642
1643/*!
1644 \internal
1645 Creates the widget extra data.
1646*/
1647
1648void QWidgetPrivate::createExtra()
1649{
1650 if (!extra) { // if not exists
1651 extra = std::make_unique<QWExtra>();
1652 extra->glContext = nullptr;
1653#if QT_CONFIG(graphicsview)
1654 extra->proxyWidget = nullptr;
1655#endif
1656 extra->minw = 0;
1657 extra->minh = 0;
1658 extra->maxw = QWIDGETSIZE_MAX;
1659 extra->maxh = QWIDGETSIZE_MAX;
1660 extra->customDpiX = 0;
1661 extra->customDpiY = 0;
1662 extra->explicitMinSize = 0;
1663 extra->explicitMaxSize = 0;
1664 extra->autoFillBackground = 0;
1665 extra->nativeChildrenForced = 0;
1666 extra->inRenderWithPainter = 0;
1667 extra->hasWindowContainer = false;
1668 extra->hasMask = 0;
1669 createSysExtra();
1670#ifdef QWIDGET_EXTRA_DEBUG
1671 static int count = 0;
1672 qDebug() << "extra" << ++count;
1673#endif
1674 }
1675}
1676
1677void QWidgetPrivate::createSysExtra()
1678{
1679}
1680
1681/*!
1682 \internal
1683 Deletes the widget extra data.
1684*/
1685
1686void QWidgetPrivate::deleteExtra()
1687{
1688 if (extra) { // if exists
1689 deleteSysExtra();
1690#ifndef QT_NO_STYLE_STYLESHEET
1691 // dereference the stylesheet style
1692 if (QStyleSheetStyle *proxy = qt_styleSheet(style: extra->style))
1693 proxy->deref();
1694#endif
1695 if (extra->topextra)
1696 deleteTLSysExtra();
1697
1698 // extra->xic destroyed in QWidget::destroy()
1699 extra.reset();
1700 }
1701}
1702
1703void QWidgetPrivate::deleteSysExtra()
1704{
1705}
1706
1707void QWidgetPrivate::deleteTLSysExtra()
1708{
1709 Q_Q(QWidget);
1710 if (extra && extra->topextra) {
1711 if (extra->hasWindowContainer)
1712 QWindowContainer::toplevelAboutToBeDestroyed(parent: q);
1713
1714 delete extra->topextra->window;
1715 extra->topextra->window = nullptr;
1716 }
1717}
1718
1719/*
1720 Returns \c region of widgets above this which overlap with
1721 \a rect, which is in parent's coordinate system (same as crect).
1722*/
1723
1724QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
1725{
1726 Q_Q(const QWidget);
1727
1728 const QWidget *w = q;
1729 QRect r = rect;
1730 QPoint p;
1731 QRegion region;
1732 while (w) {
1733 if (w->isWindow())
1734 break;
1735 QWidgetPrivate *pd = w->parentWidget()->d_func();
1736 bool above = false;
1737 for (int i = 0; i < pd->children.size(); ++i) {
1738 QWidget *sibling = qobject_cast<QWidget *>(o: pd->children.at(i));
1739 if (!sibling || !sibling->isVisible() || sibling->isWindow())
1740 continue;
1741 if (!above) {
1742 above = (sibling == w);
1743 continue;
1744 }
1745
1746 const QRect siblingRect = sibling->d_func()->effectiveRectFor(rect: sibling->data->crect);
1747 if (qRectIntersects(r1: siblingRect, r2: r)) {
1748 const auto &siblingExtra = sibling->d_func()->extra;
1749 if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
1750 && !siblingExtra->mask.translated(p: sibling->data->crect.topLeft()).intersects(r)) {
1751 continue;
1752 }
1753 region += siblingRect.translated(p: -p);
1754 if (breakAfterFirst)
1755 break;
1756 }
1757 }
1758 w = w->parentWidget();
1759 r.translate(p: pd->data.crect.topLeft());
1760 p += pd->data.crect.topLeft();
1761 }
1762 return region;
1763}
1764
1765void QWidgetPrivate::syncBackingStore()
1766{
1767 if (shouldPaintOnScreen()) {
1768 paintOnScreen(rgn: dirty);
1769 dirty = QRegion();
1770 } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1771 repaintManager->sync();
1772 }
1773}
1774
1775void QWidgetPrivate::syncBackingStore(const QRegion &region)
1776{
1777 if (shouldPaintOnScreen())
1778 paintOnScreen(rgn: region);
1779 else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
1780 repaintManager->sync(exposedWidget: q_func(), exposedRegion: region);
1781 }
1782}
1783
1784void QWidgetPrivate::paintOnScreen(const QRegion &rgn)
1785{
1786 if (data.in_destructor)
1787 return;
1788
1789 if (shouldDiscardSyncRequest())
1790 return;
1791
1792 Q_Q(QWidget);
1793 if (q->testAttribute(attribute: Qt::WA_StaticContents)) {
1794 if (!extra)
1795 createExtra();
1796 extra->staticContentsSize = data.crect.size();
1797 }
1798
1799 QPaintEngine *engine = q->paintEngine();
1800
1801 // QGLWidget does not support partial updates if:
1802 // 1) The context is double buffered
1803 // 2) The context is single buffered and auto-fill background is enabled.
1804 const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
1805 || engine->type() == QPaintEngine::OpenGL2))
1806 && (usesDoubleBufferedGLContext || q->autoFillBackground());
1807 QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
1808
1809 toBePainted &= clipRect();
1810 clipToEffectiveMask(region&: toBePainted);
1811 if (toBePainted.isEmpty())
1812 return; // Nothing to repaint.
1813
1814 drawWidget(pdev: q, rgn: toBePainted, offset: QPoint(), flags: QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, sharedPainter: nullptr);
1815
1816 if (Q_UNLIKELY(q->paintingActive()))
1817 qWarning(msg: "QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
1818}
1819
1820void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
1821{
1822 Q_Q(QWidget);
1823
1824 if (enable && !q->isWindow() && q->parentWidget() && !q->parentWidget()->updatesEnabled())
1825 return; // nothing we can do
1826
1827 if (enable != q->testAttribute(attribute: Qt::WA_UpdatesDisabled))
1828 return; // nothing to do
1829
1830 q->setAttribute(Qt::WA_UpdatesDisabled, on: !enable);
1831 if (enable)
1832 q->update();
1833
1834 Qt::WidgetAttribute attribute = enable ? Qt::WA_ForceUpdatesDisabled : Qt::WA_UpdatesDisabled;
1835 for (int i = 0; i < children.size(); ++i) {
1836 QWidget *w = qobject_cast<QWidget *>(o: children.at(i));
1837 if (w && !w->isWindow() && !w->testAttribute(attribute))
1838 w->d_func()->setUpdatesEnabled_helper(enable);
1839 }
1840}
1841
1842/*!
1843 \internal
1844
1845 Propagate this widget's palette to all children, except style sheet
1846 widgets, and windows that don't enable window propagation (palettes don't
1847 normally propagate to windows).
1848*/
1849void QWidgetPrivate::propagatePaletteChange()
1850{
1851 Q_Q(QWidget);
1852 // Propagate a new inherited mask to all children.
1853#if QT_CONFIG(graphicsview)
1854 if (!q->parentWidget() && extra && extra->proxyWidget) {
1855 QGraphicsProxyWidget *p = extra->proxyWidget;
1856 inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolveMask();
1857 } else
1858#endif // QT_CONFIG(graphicsview)
1859 if (q->isWindow() && !q->testAttribute(attribute: Qt::WA_WindowPropagation)) {
1860 inheritedPaletteResolveMask = 0;
1861 }
1862
1863 directPaletteResolveMask = data.pal.resolveMask();
1864 auto mask = directPaletteResolveMask | inheritedPaletteResolveMask;
1865
1866 const bool useStyleSheetPropagationInWidgetStyles =
1867 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
1868
1869 QEvent pc(QEvent::PaletteChange);
1870 QCoreApplication::sendEvent(receiver: q, event: &pc);
1871 for (int i = 0; i < children.size(); ++i) {
1872 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
1873 if (w && (!w->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
1874 && (!w->isWindow() || w->testAttribute(attribute: Qt::WA_WindowPropagation))) {
1875 QWidgetPrivate *wd = w->d_func();
1876 wd->inheritedPaletteResolveMask = mask;
1877 wd->resolvePalette();
1878 }
1879 }
1880}
1881
1882/*
1883 Returns the widget's clipping rectangle.
1884*/
1885QRect QWidgetPrivate::clipRect() const
1886{
1887 Q_Q(const QWidget);
1888 const QWidget * w = q;
1889 if (!w->isVisible())
1890 return QRect();
1891 QRect r = effectiveRectFor(rect: q->rect());
1892 int ox = 0;
1893 int oy = 0;
1894 while (w
1895 && w->isVisible()
1896 && !w->isWindow()
1897 && w->parentWidget()) {
1898 ox -= w->x();
1899 oy -= w->y();
1900 w = w->parentWidget();
1901 r &= QRect(ox, oy, w->width(), w->height());
1902 }
1903 return r;
1904}
1905
1906/*
1907 Returns the widget's clipping region (without siblings).
1908*/
1909QRegion QWidgetPrivate::clipRegion() const
1910{
1911 Q_Q(const QWidget);
1912 if (!q->isVisible())
1913 return QRegion();
1914 QRegion r(q->rect());
1915 const QWidget * w = q;
1916 const QWidget *ignoreUpTo;
1917 int ox = 0;
1918 int oy = 0;
1919 while (w
1920 && w->isVisible()
1921 && !w->isWindow()
1922 && w->parentWidget()) {
1923 ox -= w->x();
1924 oy -= w->y();
1925 ignoreUpTo = w;
1926 w = w->parentWidget();
1927 r &= QRegion(ox, oy, w->width(), w->height());
1928
1929 int i = 0;
1930 while(w->d_func()->children.at(i: i++) != static_cast<const QObject *>(ignoreUpTo))
1931 ;
1932 for ( ; i < w->d_func()->children.size(); ++i) {
1933 if (QWidget *sibling = qobject_cast<QWidget *>(o: w->d_func()->children.at(i))) {
1934 if (sibling->isVisible() && !sibling->isWindow()) {
1935 QRect siblingRect(ox+sibling->x(), oy+sibling->y(),
1936 sibling->width(), sibling->height());
1937 if (qRectIntersects(r1: siblingRect, r2: q->rect()))
1938 r -= QRegion(siblingRect);
1939 }
1940 }
1941 }
1942 }
1943 return r;
1944}
1945
1946void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
1947{
1948// Transform the system clip region from device-independent pixels to device pixels
1949 QTransform scaleTransform;
1950 scaleTransform.scale(sx: devicePixelRatio, sy: devicePixelRatio);
1951
1952 paintEngine->d_func()->baseSystemClip = region;
1953 paintEngine->d_func()->setSystemTransform(scaleTransform);
1954
1955}
1956
1957#if QT_CONFIG(graphicseffect)
1958void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
1959{
1960 Q_Q(QWidget);
1961 QWidget *w = q;
1962 do {
1963 if (w->graphicsEffect()) {
1964 QWidgetEffectSourcePrivate *sourced =
1965 static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func());
1966 if (!sourced->updateDueToGraphicsEffect)
1967 w->graphicsEffect()->source()->d_func()->invalidateCache();
1968 }
1969 w = w->parentWidget();
1970 } while (w);
1971}
1972#endif // QT_CONFIG(graphicseffect)
1973
1974void QWidgetPrivate::setDirtyOpaqueRegion()
1975{
1976 Q_Q(QWidget);
1977
1978 dirtyOpaqueChildren = true;
1979
1980#if QT_CONFIG(graphicseffect)
1981 invalidateGraphicsEffectsRecursively();
1982#endif // QT_CONFIG(graphicseffect)
1983
1984 if (q->isWindow())
1985 return;
1986
1987 QWidget *parent = q->parentWidget();
1988 if (!parent)
1989 return;
1990
1991 // TODO: instead of setting dirtyflag, manipulate the dirtyregion directly?
1992 QWidgetPrivate *pd = parent->d_func();
1993 if (!pd->dirtyOpaqueChildren)
1994 pd->setDirtyOpaqueRegion();
1995}
1996
1997const QRegion &QWidgetPrivate::getOpaqueChildren() const
1998{
1999 if (!dirtyOpaqueChildren)
2000 return opaqueChildren;
2001
2002 QWidgetPrivate *that = const_cast<QWidgetPrivate*>(this);
2003 that->opaqueChildren = QRegion();
2004
2005 for (int i = 0; i < children.size(); ++i) {
2006 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
2007 if (!child || !child->isVisible() || child->isWindow())
2008 continue;
2009
2010 const QPoint offset = child->geometry().topLeft();
2011 QWidgetPrivate *childd = child->d_func();
2012 QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren();
2013 if (childd->extra && childd->extra->hasMask)
2014 r &= childd->extra->mask;
2015 if (r.isEmpty())
2016 continue;
2017 r.translate(p: offset);
2018 that->opaqueChildren += r;
2019 }
2020
2021 that->opaqueChildren &= q_func()->rect();
2022 that->dirtyOpaqueChildren = false;
2023
2024 return that->opaqueChildren;
2025}
2026
2027void QWidgetPrivate::subtractOpaqueChildren(QRegion &source, const QRect &clipRect) const
2028{
2029 if (children.isEmpty() || clipRect.isEmpty())
2030 return;
2031
2032 const QRegion &r = getOpaqueChildren();
2033 if (!r.isEmpty())
2034 source -= (r & clipRect);
2035}
2036
2037//subtract any relatives that are higher up than me --- this is too expensive !!!
2038void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirtySiblingsAbove,
2039 bool alsoNonOpaque) const
2040{
2041 Q_Q(const QWidget);
2042 static int disableSubtractOpaqueSiblings = qEnvironmentVariableIntValue(varName: "QT_NO_SUBTRACTOPAQUESIBLINGS");
2043 if (disableSubtractOpaqueSiblings || q->isWindow())
2044 return;
2045
2046 QRect clipBoundingRect;
2047 bool dirtyClipBoundingRect = true;
2048
2049 QRegion parentClip;
2050 bool dirtyParentClip = true;
2051
2052 QPoint parentOffset = data.crect.topLeft();
2053
2054 const QWidget *w = q;
2055
2056 while (w) {
2057 if (w->isWindow())
2058 break;
2059 QWidgetPrivate *pd = w->parentWidget()->d_func();
2060 const int myIndex = pd->children.indexOf(t: const_cast<QWidget *>(w));
2061 const QRect widgetGeometry = w->d_func()->effectiveRectFor(rect: w->data->crect);
2062 for (int i = myIndex + 1; i < pd->children.size(); ++i) {
2063 QWidget *sibling = qobject_cast<QWidget *>(o: pd->children.at(i));
2064 if (!sibling || !sibling->isVisible() || sibling->isWindow())
2065 continue;
2066
2067 const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(rect: sibling->data->crect);
2068 if (!qRectIntersects(r1: siblingGeometry, r2: widgetGeometry))
2069 continue;
2070
2071 if (dirtyClipBoundingRect) {
2072 clipBoundingRect = sourceRegion.boundingRect();
2073 dirtyClipBoundingRect = false;
2074 }
2075
2076 if (!qRectIntersects(r1: siblingGeometry, r2: clipBoundingRect.translated(p: parentOffset)))
2077 continue;
2078
2079 if (dirtyParentClip) {
2080 parentClip = sourceRegion.translated(p: parentOffset);
2081 dirtyParentClip = false;
2082 }
2083
2084 const QPoint siblingPos(sibling->data->crect.topLeft());
2085 const QRect siblingClipRect(sibling->d_func()->clipRect());
2086 QRegion siblingDirty(parentClip);
2087 siblingDirty &= (siblingClipRect.translated(p: siblingPos));
2088 const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask
2089 && !sibling->d_func()->graphicsEffect;
2090 if (hasMask)
2091 siblingDirty &= sibling->d_func()->extra->mask.translated(p: siblingPos);
2092 if (siblingDirty.isEmpty())
2093 continue;
2094
2095 if (sibling->d_func()->isOpaque || alsoNonOpaque) {
2096 if (hasMask) {
2097 siblingDirty.translate(p: -parentOffset);
2098 sourceRegion -= siblingDirty;
2099 } else {
2100 sourceRegion -= siblingGeometry.translated(p: -parentOffset);
2101 }
2102 } else {
2103 if (hasDirtySiblingsAbove)
2104 *hasDirtySiblingsAbove = true;
2105 if (sibling->d_func()->children.isEmpty())
2106 continue;
2107 QRegion opaqueSiblingChildren(sibling->d_func()->getOpaqueChildren());
2108 opaqueSiblingChildren.translate(p: -parentOffset + siblingPos);
2109 sourceRegion -= opaqueSiblingChildren;
2110 }
2111 if (sourceRegion.isEmpty())
2112 return;
2113
2114 dirtyClipBoundingRect = true;
2115 dirtyParentClip = true;
2116 }
2117
2118 w = w->parentWidget();
2119 parentOffset += pd->data.crect.topLeft();
2120 dirtyParentClip = true;
2121 }
2122}
2123
2124void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
2125{
2126 Q_Q(const QWidget);
2127
2128 const QWidget *w = q;
2129 QPoint offset;
2130
2131#if QT_CONFIG(graphicseffect)
2132 if (graphicsEffect && !w->isWindow()) {
2133 w = q->parentWidget();
2134 offset -= data.crect.topLeft();
2135 }
2136#endif // QT_CONFIG(graphicseffect)
2137
2138 while (w) {
2139 const QWidgetPrivate *wd = w->d_func();
2140 if (wd->extra && wd->extra->hasMask)
2141 region &= (w != q) ? wd->extra->mask.translated(p: offset) : wd->extra->mask;
2142 if (w->isWindow())
2143 return;
2144 offset -= wd->data.crect.topLeft();
2145 w = w->parentWidget();
2146 }
2147}
2148
2149bool QWidgetPrivate::shouldPaintOnScreen() const
2150{
2151#if defined(QT_NO_BACKINGSTORE)
2152 return true;
2153#else
2154 Q_Q(const QWidget);
2155 if (q->testAttribute(attribute: Qt::WA_PaintOnScreen)
2156 || (!q->isWindow() && q->window()->testAttribute(attribute: Qt::WA_PaintOnScreen))) {
2157 return true;
2158 }
2159
2160 return false;
2161#endif
2162}
2163
2164void QWidgetPrivate::updateIsOpaque()
2165{
2166 // hw: todo: only needed if opacity actually changed
2167 setDirtyOpaqueRegion();
2168
2169#if QT_CONFIG(graphicseffect)
2170 if (graphicsEffect) {
2171 // ### We should probably add QGraphicsEffect::isOpaque at some point.
2172 setOpaque(false);
2173 return;
2174 }
2175#endif // QT_CONFIG(graphicseffect)
2176
2177 Q_Q(QWidget);
2178 if (q->testAttribute(attribute: Qt::WA_OpaquePaintEvent) || q->testAttribute(attribute: Qt::WA_PaintOnScreen)) {
2179 setOpaque(true);
2180 return;
2181 }
2182
2183 const QPalette &pal = q->palette();
2184
2185 if (q->autoFillBackground()) {
2186 const QBrush &autoFillBrush = pal.brush(cr: q->backgroundRole());
2187 if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
2188 setOpaque(true);
2189 return;
2190 }
2191 }
2192
2193 if (q->isWindow() && !q->testAttribute(attribute: Qt::WA_NoSystemBackground)) {
2194 const QBrush &windowBrush = q->palette().brush(cr: QPalette::Window);
2195 if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
2196 setOpaque(true);
2197 return;
2198 }
2199 }
2200 setOpaque(false);
2201}
2202
2203void QWidgetPrivate::setOpaque(bool opaque)
2204{
2205 if (isOpaque != opaque) {
2206 isOpaque = opaque;
2207 updateIsTranslucent();
2208 }
2209}
2210
2211void QWidgetPrivate::updateIsTranslucent()
2212{
2213 Q_Q(QWidget);
2214 if (QWindow *window = q->windowHandle()) {
2215 QSurfaceFormat format = window->format();
2216 const int oldAlpha = format.alphaBufferSize();
2217 const int newAlpha = q->testAttribute(attribute: Qt::WA_TranslucentBackground) ? 8 : -1;
2218 if (oldAlpha != newAlpha) {
2219 // QTBUG-85714: Do this only when the QWindow has not yet been create()'ed yet.
2220 //
2221 // If that is not the case, then the setFormat() is not just futile
2222 // but downright dangerous. Futile because the format matters only
2223 // when creating the native window, no point in changing it
2224 // afterwards. Dangerous because a QOpenGLContext or something else
2225 // may eventually query the QWindow's format(), in order to ensure
2226 // compatibility (in terms of native concepts such as pixel format,
2227 // EGLConfig, etc.), and if we change it here, then the returned
2228 // format does not describe reality anymore. (reality being the
2229 // settings with which the native resource was created).
2230 //
2231 // Whereas if one does a destroy()-create() then this all here
2232 // won't matter because the format is updated in
2233 // QWidgetPrivate::create() again.
2234 //
2235 if (!window->handle()) {
2236 format.setAlphaBufferSize(newAlpha);
2237 window->setFormat(format);
2238 }
2239 }
2240 }
2241}
2242
2243static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrush &brush)
2244{
2245 Q_ASSERT(painter);
2246
2247 if (brush.style() == Qt::TexturePattern) {
2248 const QRect rect(rgn.boundingRect());
2249 painter->setClipRegion(rgn);
2250 painter->drawTiledPixmap(rect, pm: brush.texture(), offset: rect.topLeft());
2251 } else if (brush.gradient()
2252 && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode
2253 || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) {
2254 painter->save();
2255 painter->setClipRegion(rgn);
2256 painter->fillRect(x: 0, y: 0, w: painter->device()->width(), h: painter->device()->height(), b: brush);
2257 painter->restore();
2258 } else {
2259 for (const QRect &rect : rgn)
2260 painter->fillRect(rect, brush);
2261 }
2262}
2263
2264bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
2265{
2266#if QT_CONFIG(scrollarea)
2267 Q_Q(const QWidget);
2268 //If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
2269 if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
2270 return false;
2271 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(object: parent);
2272 if (scrollArea && scrollArea->viewport() == q) {
2273 QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
2274 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
2275 painter->setBrushOrigin(-priv->contentsOffset());
2276 }
2277#endif // QT_CONFIG(scrollarea)
2278 return true;
2279}
2280
2281void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, DrawWidgetFlags flags) const
2282{
2283 Q_Q(const QWidget);
2284
2285 bool brushOriginSet = false;
2286 const QBrush autoFillBrush = q->palette().brush(cr: q->backgroundRole());
2287
2288 if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
2289 const QBrush bg = q->palette().brush(cr: QPalette::Window);
2290 if (!brushOriginSet)
2291 brushOriginSet = updateBrushOrigin(painter, brush: bg);
2292 if (!(flags & DontSetCompositionMode)) {
2293 //copy alpha straight in
2294 QPainter::CompositionMode oldMode = painter->compositionMode();
2295 painter->setCompositionMode(QPainter::CompositionMode_Source);
2296 fillRegion(painter, rgn, brush: bg);
2297 painter->setCompositionMode(oldMode);
2298 } else {
2299 fillRegion(painter, rgn, brush: bg);
2300 }
2301 }
2302
2303 if (q->autoFillBackground()) {
2304 if (!brushOriginSet)
2305 brushOriginSet = updateBrushOrigin(painter, brush: autoFillBrush);
2306 fillRegion(painter, rgn, brush: autoFillBrush);
2307 }
2308
2309 if (q->testAttribute(attribute: Qt::WA_StyledBackground)) {
2310 painter->setClipRegion(rgn);
2311 QStyleOption opt;
2312 opt.initFrom(w: q);
2313 q->style()->drawPrimitive(pe: QStyle::PE_Widget, opt: &opt, p: painter, w: q);
2314 }
2315}
2316
2317/*
2318 \internal
2319 This function is called when a widget is hidden or destroyed.
2320 It resets some application global pointers that should only refer active,
2321 visible widgets.
2322*/
2323
2324extern QWidget *qt_button_down;
2325
2326void QWidgetPrivate::deactivateWidgetCleanup()
2327{
2328 Q_Q(QWidget);
2329 // If this was the active application window, reset it
2330 if (QApplication::activeWindow() == q)
2331 QApplicationPrivate::setActiveWindow(nullptr);
2332 // If the is the active mouse press widget, reset it
2333 if (q == qt_button_down)
2334 qt_button_down = nullptr;
2335}
2336
2337
2338/*!
2339 Returns a pointer to the widget with window identifier/handle \a
2340 id.
2341
2342 The window identifier type depends on the underlying window
2343 system, see \c qwindowdefs.h for the actual definition. If there
2344 is no widget with this identifier, \nullptr is returned.
2345*/
2346
2347QWidget *QWidget::find(WId id)
2348{
2349 return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(key: id, defaultValue: 0) : nullptr;
2350}
2351
2352
2353
2354/*!
2355 \fn WId QWidget::internalWinId() const
2356 \internal
2357 Returns the window system identifier of the widget, or 0 if the widget is not created yet.
2358
2359*/
2360
2361/*!
2362 \fn WId QWidget::winId() const
2363
2364 Returns the window system identifier of the widget.
2365
2366 Portable in principle, but if you use it you are probably about to
2367 do something non-portable. Be careful.
2368
2369 If a widget is non-native (alien) and winId() is invoked on it, that widget
2370 will be provided a native handle.
2371
2372 This value may change at run-time. An event with type QEvent::WinIdChange
2373 will be sent to the widget following a change in window system identifier.
2374
2375 \sa find()
2376*/
2377WId QWidget::winId() const
2378{
2379 if (!data->in_destructor
2380 && (!testAttribute(attribute: Qt::WA_WState_Created) || !internalWinId()))
2381 {
2382 QWidget *that = const_cast<QWidget*>(this);
2383 that->setAttribute(Qt::WA_NativeWindow);
2384 that->d_func()->createWinId();
2385 return that->data->winid;
2386 }
2387 return data->winid;
2388}
2389
2390void QWidgetPrivate::createWinId()
2391{
2392 Q_Q(QWidget);
2393
2394 const bool forceNativeWindow = q->testAttribute(attribute: Qt::WA_NativeWindow);
2395 if (!q->testAttribute(attribute: Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
2396 if (!q->isWindow()) {
2397 QWidget *parent = q->parentWidget();
2398 QWidgetPrivate *pd = parent->d_func();
2399 if (forceNativeWindow && !q->testAttribute(attribute: Qt::WA_DontCreateNativeAncestors))
2400 parent->setAttribute(Qt::WA_NativeWindow);
2401 if (!parent->internalWinId()) {
2402 pd->createWinId();
2403 }
2404
2405 for (int i = 0; i < pd->children.size(); ++i) {
2406 QWidget *w = qobject_cast<QWidget *>(o: pd->children.at(i));
2407 if (w && !w->isWindow() && (!w->testAttribute(attribute: Qt::WA_WState_Created)
2408 || (!w->internalWinId() && w->testAttribute(attribute: Qt::WA_NativeWindow)))) {
2409 w->create();
2410 }
2411 }
2412 } else {
2413 q->create();
2414 }
2415 }
2416}
2417
2418/*!
2419\internal
2420Ensures that the widget is set on the screen point is on. This is handy getting a correct
2421size hint before a resize in e.g QMenu and QToolTip.
2422Returns if the screen was changed.
2423*/
2424
2425bool QWidgetPrivate::setScreenForPoint(const QPoint &pos)
2426{
2427 Q_Q(QWidget);
2428 if (!q->isWindow())
2429 return false;
2430 // Find the screen for pos and make the widget understand it is on that screen.
2431 return setScreen(QGuiApplication::screenAt(point: pos));
2432}
2433
2434/*!
2435\internal
2436Ensures that the widget's QWindow is set to be on the given \a screen.
2437Returns true if the screen was changed.
2438*/
2439
2440bool QWidgetPrivate::setScreen(QScreen *screen)
2441{
2442 Q_Q(QWidget);
2443 if (!screen || !q->isWindow())
2444 return false;
2445 const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
2446 if (currentScreen != screen) {
2447 topData()->initialScreen = screen;
2448 if (windowHandle())
2449 windowHandle()->setScreen(screen);
2450 return true;
2451 }
2452 return false;
2453}
2454
2455/*!
2456\internal
2457Ensures that the widget has a window system identifier, i.e. that it is known to the windowing system.
2458
2459*/
2460
2461void QWidget::createWinId()
2462{
2463 Q_D(QWidget);
2464 d->createWinId();
2465}
2466
2467/*!
2468 \since 4.4
2469
2470 Returns the effective window system identifier of the widget, i.e. the
2471 native parent's window system identifier.
2472
2473 If the widget is native, this function returns the native widget ID.
2474 Otherwise, the window ID of the first native parent widget, i.e., the
2475 top-level widget that contains this widget, is returned.
2476
2477 \note We recommend that you do not store this value as it is likely to
2478 change at run-time.
2479
2480 \sa nativeParentWidget()
2481*/
2482WId QWidget::effectiveWinId() const
2483{
2484 const WId id = internalWinId();
2485 if (id || !testAttribute(attribute: Qt::WA_WState_Created))
2486 return id;
2487 if (const QWidget *realParent = nativeParentWidget())
2488 return realParent->internalWinId();
2489 return 0;
2490}
2491
2492/*!
2493 If this is a native widget, return the associated QWindow.
2494 Otherwise return null.
2495
2496 Native widgets include toplevel widgets, QGLWidget, and child widgets
2497 on which winId() was called.
2498
2499 \since 5.0
2500
2501 \sa winId(), screen()
2502*/
2503QWindow *QWidget::windowHandle() const
2504{
2505 Q_D(const QWidget);
2506 return d->windowHandle();
2507}
2508
2509/*!
2510 Returns the screen the widget is on.
2511
2512 \since 5.14
2513
2514 \sa windowHandle()
2515*/
2516QScreen *QWidget::screen() const
2517{
2518 Q_D(const QWidget);
2519 if (auto associatedScreen = d->associatedScreen())
2520 return associatedScreen;
2521 if (auto topLevel = window()) {
2522 if (auto topData = qt_widget_private(widget: topLevel)->topData()) {
2523 if (topData->initialScreen)
2524 return topData->initialScreen;
2525 }
2526 if (auto screenByPos = QGuiApplication::screenAt(point: topLevel->geometry().center()))
2527 return screenByPos;
2528 }
2529 return QGuiApplication::primaryScreen();
2530}
2531
2532/*!
2533 Sets the screen on which the widget should be shown to \a screen.
2534
2535 Setting the screen only makes sense for windows. If necessary, the widget's
2536 window will get recreated on \a screen.
2537
2538 \note If the screen is part of a virtual desktop of multiple screens,
2539 the window will not move automatically to \a screen. To place the
2540 window relative to the screen, use the screen's topLeft() position.
2541
2542 \sa QWindow::setScreen()
2543*/
2544void QWidget::setScreen(QScreen *screen)
2545{
2546 Q_D(QWidget);
2547 d->setScreen(screen);
2548}
2549
2550#ifndef QT_NO_STYLE_STYLESHEET
2551
2552/*!
2553 \property QWidget::styleSheet
2554 \brief the widget's style sheet
2555 \since 4.2
2556
2557 The style sheet contains a textual description of customizations to the
2558 widget's style, as described in the \l{Qt Style Sheets} document.
2559
2560 Since Qt 4.5, Qt style sheets fully supports \macos.
2561
2562 \warning Qt style sheets are currently not supported for custom QStyle
2563 subclasses. We plan to address this in some future release.
2564
2565 \sa setStyle(), QApplication::styleSheet, {Qt Style Sheets}
2566*/
2567QString QWidget::styleSheet() const
2568{
2569 Q_D(const QWidget);
2570 if (!d->extra)
2571 return QString();
2572 return d->extra->styleSheet;
2573}
2574
2575void QWidget::setStyleSheet(const QString& styleSheet)
2576{
2577 Q_D(QWidget);
2578 if (data->in_destructor)
2579 return;
2580 d->createExtra();
2581
2582 QStyleSheetStyle *proxy = qt_styleSheet(style: d->extra->style);
2583 d->extra->styleSheet = styleSheet;
2584 if (styleSheet.isEmpty()) { // stylesheet removed
2585 if (!proxy)
2586 return;
2587
2588 d->inheritStyle();
2589 return;
2590 }
2591
2592 if (proxy) { // style sheet update
2593 bool repolish = d->polished;
2594 if (!repolish) {
2595 const auto childWidgets = findChildren<QWidget*>();
2596 for (auto child : childWidgets) {
2597 repolish = child->d_func()->polished;
2598 if (repolish)
2599 break;
2600 }
2601 }
2602 if (repolish)
2603 proxy->repolish(widget: this);
2604 return;
2605 }
2606
2607 if (testAttribute(attribute: Qt::WA_SetStyle)) {
2608 d->setStyle_helper(newStyle: new QStyleSheetStyle(d->extra->style), propagate: true);
2609 } else {
2610 d->setStyle_helper(newStyle: new QStyleSheetStyle(nullptr), propagate: true);
2611 }
2612}
2613
2614#endif // QT_NO_STYLE_STYLESHEET
2615
2616/*!
2617 \sa QWidget::setStyle(), QApplication::setStyle(), QApplication::style()
2618*/
2619
2620QStyle *QWidget::style() const
2621{
2622 Q_D(const QWidget);
2623
2624 if (d->extra && d->extra->style)
2625 return d->extra->style;
2626 return QApplication::style();
2627}
2628
2629/*!
2630 Sets the widget's GUI style to \a style. The ownership of the style
2631 object is not transferred.
2632
2633 If no style is set, the widget uses the application's style,
2634 QApplication::style() instead.
2635
2636 Setting a widget's style has no effect on existing or future child
2637 widgets.
2638
2639 \warning This function is particularly useful for demonstration
2640 purposes, where you want to show Qt's styling capabilities. Real
2641 applications should avoid it and use one consistent GUI style
2642 instead.
2643
2644 \warning Qt style sheets are currently not supported for custom QStyle
2645 subclasses. We plan to address this in some future release.
2646
2647 \sa style(), QStyle, QApplication::style(), QApplication::setStyle()
2648*/
2649
2650void QWidget::setStyle(QStyle *style)
2651{
2652 Q_D(QWidget);
2653 setAttribute(Qt::WA_SetStyle, on: style != nullptr);
2654 d->createExtra();
2655#ifndef QT_NO_STYLE_STYLESHEET
2656 if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
2657 //if for some reason someone try to set a QStyleSheetStyle, ref it
2658 //(this may happen for example in QButtonDialogBox which propagates its style)
2659 styleSheetStyle->ref();
2660 d->setStyle_helper(newStyle: style, propagate: false);
2661 } else if (qt_styleSheet(style: d->extra->style) || !qApp->styleSheet().isEmpty()) {
2662 // if we have an application stylesheet or have a proxy already, propagate
2663 d->setStyle_helper(newStyle: new QStyleSheetStyle(style), propagate: true);
2664 } else
2665#endif
2666 d->setStyle_helper(newStyle: style, propagate: false);
2667}
2668
2669void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
2670{
2671 Q_Q(QWidget);
2672 QStyle *oldStyle = q->style();
2673
2674 createExtra();
2675
2676#ifndef QT_NO_STYLE_STYLESHEET
2677 QPointer<QStyle> origStyle = extra->style;
2678#endif
2679 extra->style = newStyle;
2680
2681 // repolish
2682 if (polished && q->windowType() != Qt::Desktop) {
2683 oldStyle->unpolish(widget: q);
2684 q->style()->polish(widget: q);
2685 }
2686
2687 if (propagate) {
2688 // We copy the list because the order may be modified
2689 const QObjectList childrenList = children;
2690 for (int i = 0; i < childrenList.size(); ++i) {
2691 QWidget *c = qobject_cast<QWidget*>(o: childrenList.at(i));
2692 if (c)
2693 c->d_func()->inheritStyle();
2694 }
2695 }
2696
2697#ifndef QT_NO_STYLE_STYLESHEET
2698 if (!qt_styleSheet(style: newStyle)) {
2699 if (const QStyleSheetStyle* cssStyle = qt_styleSheet(style: origStyle)) {
2700 cssStyle->clearWidgetFont(w: q);
2701 }
2702 }
2703#endif
2704
2705 QEvent e(QEvent::StyleChange);
2706 QCoreApplication::sendEvent(receiver: q, event: &e);
2707
2708#ifndef QT_NO_STYLE_STYLESHEET
2709 // dereference the old stylesheet style
2710 if (QStyleSheetStyle *proxy = qt_styleSheet(style: origStyle))
2711 proxy->deref();
2712#endif
2713}
2714
2715// Inherits style from the current parent and propagates it as necessary
2716void QWidgetPrivate::inheritStyle()
2717{
2718#ifndef QT_NO_STYLE_STYLESHEET
2719 Q_Q(QWidget);
2720
2721 QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
2722
2723 QStyleSheetStyle *proxy = qt_styleSheet(style: extraStyle);
2724
2725 if (!q->styleSheet().isEmpty()) {
2726 Q_ASSERT(proxy);
2727 proxy->repolish(widget: q);
2728 return;
2729 }
2730
2731 QStyle *origStyle = proxy ? proxy->base : extraStyle;
2732 QWidget *parent = q->parentWidget();
2733 QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : nullptr;
2734 // If we have stylesheet on app or parent has stylesheet style, we need
2735 // to be running a proxy
2736 if (!qApp->styleSheet().isEmpty() || qt_styleSheet(style: parentStyle)) {
2737 QStyle *newStyle = parentStyle;
2738 if (q->testAttribute(attribute: Qt::WA_SetStyle) && qt_styleSheet(style: origStyle) == nullptr)
2739 newStyle = new QStyleSheetStyle(origStyle);
2740 else if (auto *styleSheetStyle = qt_styleSheet(style: origStyle))
2741 newStyle = styleSheetStyle;
2742 else if (QStyleSheetStyle *newProxy = qt_styleSheet(style: parentStyle))
2743 newProxy->ref();
2744
2745 setStyle_helper(newStyle, propagate: true);
2746 return;
2747 }
2748
2749 // So, we have no stylesheet on parent/app and we have an empty stylesheet
2750 // we just need our original style back
2751 if (origStyle == extraStyle) // is it any different?
2752 return;
2753
2754 // We could have inherited the proxy from our parent (which has a custom style)
2755 // In such a case we need to start following the application style (i.e revert
2756 // the propagation behavior of QStyleSheetStyle)
2757 if (!q->testAttribute(attribute: Qt::WA_SetStyle))
2758 origStyle = nullptr;
2759
2760 setStyle_helper(newStyle: origStyle, propagate: true);
2761#endif // QT_NO_STYLE_STYLESHEET
2762}
2763
2764
2765/*!
2766 \fn bool QWidget::isWindow() const
2767
2768 Returns \c true if the widget is an independent window, otherwise
2769 returns \c false.
2770
2771 A window is a widget that isn't visually the child of any other
2772 widget and that usually has a frame and a
2773 \l{QWidget::setWindowTitle()}{window title}.
2774
2775 A window can have a \l{QWidget::parentWidget()}{parent widget}.
2776 It will then be grouped with its parent and deleted when the
2777 parent is deleted, minimized when the parent is minimized etc. If
2778 supported by the window manager, it will also have a common
2779 taskbar entry with its parent.
2780
2781 QDialog and QMainWindow widgets are by default windows, even if a
2782 parent widget is specified in the constructor. This behavior is
2783 specified by the Qt::Window flag.
2784
2785 \sa window(), isModal(), parentWidget()
2786*/
2787
2788/*!
2789 \property QWidget::modal
2790 \brief whether the widget is a modal widget
2791
2792 This property only makes sense for windows. A modal widget
2793 prevents widgets in all other windows from getting any input.
2794
2795 By default, this property is \c false.
2796
2797 \sa isWindow(), windowModality, QDialog
2798*/
2799
2800/*!
2801 \property QWidget::windowModality
2802 \brief which windows are blocked by the modal widget
2803 \since 4.1
2804
2805 This property only makes sense for windows. A modal widget
2806 prevents widgets in other windows from getting input. The value of
2807 this property controls which windows are blocked when the widget
2808 is visible. Changing this property while the window is visible has
2809 no effect; you must hide() the widget first, then show() it again.
2810
2811 By default, this property is Qt::NonModal.
2812
2813 \sa isWindow(), QWidget::modal, QDialog
2814*/
2815
2816Qt::WindowModality QWidget::windowModality() const
2817{
2818 return static_cast<Qt::WindowModality>(data->window_modality);
2819}
2820
2821void QWidget::setWindowModality(Qt::WindowModality windowModality)
2822{
2823 data->window_modality = windowModality;
2824 // setModal_sys() will be called by setAttribute()
2825 setAttribute(Qt::WA_ShowModal, on: (data->window_modality != Qt::NonModal));
2826 setAttribute(Qt::WA_SetWindowModality, on: true);
2827}
2828
2829void QWidgetPrivate::setModal_sys()
2830{
2831 Q_Q(QWidget);
2832 if (q->windowHandle())
2833 q->windowHandle()->setModality(q->windowModality());
2834}
2835
2836/*!
2837 \fn bool QWidget::underMouse() const
2838
2839 Returns \c true if the widget is under the mouse cursor; otherwise
2840 returns \c false.
2841
2842 This value is not updated properly during drag and drop
2843 operations.
2844
2845 \sa enterEvent(), leaveEvent()
2846*/
2847
2848/*!
2849 \property QWidget::minimized
2850 \brief whether this widget is minimized (iconified)
2851
2852 This property is only relevant for windows.
2853
2854 By default, this property is \c false.
2855
2856 \sa showMinimized(), visible, show(), hide(), showNormal(), maximized
2857*/
2858bool QWidget::isMinimized() const
2859{ return data->window_state & Qt::WindowMinimized; }
2860
2861/*!
2862 Shows the widget minimized, as an icon.
2863
2864 Calling this function only affects \l{isWindow()}{windows}.
2865
2866 \sa showNormal(), showMaximized(), show(), hide(), isVisible(),
2867 isMinimized()
2868*/
2869void QWidget::showMinimized()
2870{
2871 bool isMin = isMinimized();
2872 if (isMin && isVisible())
2873 return;
2874
2875 ensurePolished();
2876
2877 if (!isMin)
2878 setWindowState((windowState() & ~Qt::WindowActive) | Qt::WindowMinimized);
2879 setVisible(true);
2880}
2881
2882/*!
2883 \property QWidget::maximized
2884 \brief whether this widget is maximized
2885
2886 This property is only relevant for windows.
2887
2888 \note Due to limitations on some window systems, this does not always
2889 report the expected results (e.g., if the user on X11 maximizes the
2890 window via the window manager, Qt has no way of distinguishing this
2891 from any other resize). This is expected to improve as window manager
2892 protocols evolve.
2893
2894 By default, this property is \c false.
2895
2896 \sa windowState(), showMaximized(), visible, show(), hide(), showNormal(), minimized
2897*/
2898bool QWidget::isMaximized() const
2899{ return data->window_state & Qt::WindowMaximized; }
2900
2901
2902
2903/*!
2904 Returns the current window state. The window state is a OR'ed
2905 combination of Qt::WindowState: Qt::WindowMinimized,
2906 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2907
2908 \sa Qt::WindowState, setWindowState()
2909 */
2910Qt::WindowStates QWidget::windowState() const
2911{
2912 return Qt::WindowStates(data->window_state);
2913}
2914
2915/*!\internal
2916
2917 The function sets the window state on child widgets similar to
2918 setWindowState(). The difference is that the window state changed
2919 event has the isOverride() flag set. It exists mainly to keep
2920 QWorkspace working.
2921 */
2922void QWidget::overrideWindowState(Qt::WindowStates newstate)
2923{
2924 QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
2925 data->window_state = newstate;
2926 QCoreApplication::sendEvent(receiver: this, event: &e);
2927}
2928
2929/*!
2930 \fn void QWidget::setWindowState(Qt::WindowStates windowState)
2931
2932 Sets the window state to \a windowState. The window state is a OR'ed
2933 combination of Qt::WindowState: Qt::WindowMinimized,
2934 Qt::WindowMaximized, Qt::WindowFullScreen, and Qt::WindowActive.
2935
2936 If the window is not visible (i.e. isVisible() returns \c false), the
2937 window state will take effect when show() is called. For visible
2938 windows, the change is immediate. For example, to toggle between
2939 full-screen and normal mode, use the following code:
2940
2941 \snippet code/src_gui_kernel_qwidget.cpp 0
2942
2943 To restore and activate a minimized window (while
2944 preserving its maximized and/or full-screen state), use the following:
2945
2946 \snippet code/src_gui_kernel_qwidget.cpp 1
2947
2948 Calling this function will hide the widget. You must call show() to make
2949 the widget visible again.
2950
2951 \note On some window systems Qt::WindowActive is not immediate, and may be
2952 ignored in certain cases.
2953
2954 When the window state changes, the widget receives a changeEvent()
2955 of type QEvent::WindowStateChange.
2956
2957 \sa Qt::WindowState, windowState()
2958*/
2959void QWidget::setWindowState(Qt::WindowStates newstate)
2960{
2961 Q_D(QWidget);
2962 Qt::WindowStates oldstate = windowState();
2963 if (newstate.testFlag(flag: Qt::WindowMinimized)) // QTBUG-46763
2964 newstate.setFlag(flag: Qt::WindowActive, on: false);
2965 if (oldstate == newstate)
2966 return;
2967 if (isWindow() && !testAttribute(attribute: Qt::WA_WState_Created))
2968 create();
2969
2970 data->window_state = newstate;
2971 data->in_set_window_state = 1;
2972 if (isWindow()) {
2973 // Ensure the initial size is valid, since we store it as normalGeometry below.
2974 if (!testAttribute(attribute: Qt::WA_Resized) && !isVisible())
2975 adjustSize();
2976
2977 d->createTLExtra();
2978 if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
2979 d->topData()->normalGeometry = geometry();
2980
2981 Q_ASSERT(windowHandle());
2982 windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
2983 }
2984 data->in_set_window_state = 0;
2985
2986 if (newstate & Qt::WindowActive)
2987 activateWindow();
2988
2989 QWindowStateChangeEvent e(oldstate);
2990 QCoreApplication::sendEvent(receiver: this, event: &e);
2991}
2992
2993/*!
2994 \property QWidget::fullScreen
2995 \brief whether the widget is shown in full screen mode
2996
2997 A widget in full screen mode occupies the whole screen area and does not
2998 display window decorations, such as a title bar.
2999
3000 By default, this property is \c false.
3001
3002 \sa windowState(), minimized, maximized
3003*/
3004bool QWidget::isFullScreen() const
3005{ return data->window_state & Qt::WindowFullScreen; }
3006
3007/*!
3008 Shows the widget in full-screen mode.
3009
3010 Calling this function only affects \l{isWindow()}{windows}.
3011
3012 To return from full-screen mode, call showNormal() or close().
3013
3014 \note Full-screen mode works fine under Windows, but has certain
3015 problems under X. These problems are due to limitations of the
3016 ICCCM protocol that specifies the communication between X11
3017 clients and the window manager. ICCCM simply does not understand
3018 the concept of non-decorated full-screen windows. Therefore, the
3019 best you can do is to request a borderless window and place and
3020 resize it to fill the entire screen. Depending on the window
3021 manager, this may or may not work. The borderless window is
3022 requested using MOTIF hints, which are at least partially
3023 supported by virtually all modern window managers.
3024
3025 An alternative would be to bypass the window manager entirely and
3026 create a window with the Qt::X11BypassWindowManagerHint flag. This
3027 has other severe problems though, like broken keyboard focus
3028 and very strange effects on desktop changes or when the user raises
3029 other windows.
3030
3031 X11 window managers that follow modern post-ICCCM specifications
3032 support full-screen mode properly.
3033
3034 On macOS, showing a window full screen puts the entire application in
3035 full-screen mode, providing it with a dedicated desktop. Showing another
3036 window while the application runs in full-screen mode might automatically
3037 make that window full screen as well. To prevent that, exit full-screen
3038 mode by calling showNormal() or by close() on the full screen window
3039 before showing another window.
3040
3041 \sa showNormal(), showMaximized(), show(), isVisible(), close()
3042*/
3043void QWidget::showFullScreen()
3044{
3045 ensurePolished();
3046
3047 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized))
3048 | Qt::WindowFullScreen);
3049 setVisible(true);
3050#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
3051 // activating it here before libscreen activates it causes problems
3052 activateWindow();
3053#endif
3054}
3055
3056/*!
3057 Shows the widget maximized.
3058
3059 Calling this function only affects \l{isWindow()}{windows}.
3060
3061 On X11, this function may not work properly with certain window
3062 managers. See the \l{Window Geometry} documentation for an explanation.
3063
3064 \sa setWindowState(), showNormal(), showMinimized(), show(), hide(), isVisible()
3065*/
3066void QWidget::showMaximized()
3067{
3068 ensurePolished();
3069
3070 setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen))
3071 | Qt::WindowMaximized);
3072 setVisible(true);
3073}
3074
3075/*!
3076 Restores the widget after it has been maximized or minimized.
3077
3078 Calling this function only affects \l{isWindow()}{windows}.
3079
3080 \sa setWindowState(), showMinimized(), showMaximized(), show(), hide(), isVisible()
3081*/
3082void QWidget::showNormal()
3083{
3084 ensurePolished();
3085
3086 setWindowState(windowState() & ~(Qt::WindowMinimized
3087 | Qt::WindowMaximized
3088 | Qt::WindowFullScreen));
3089 setVisible(true);
3090}
3091
3092/*!
3093 Returns \c true if this widget would become enabled if \a ancestor is
3094 enabled; otherwise returns \c false.
3095
3096
3097
3098 This is the case if neither the widget itself nor every parent up
3099 to but excluding \a ancestor has been explicitly disabled.
3100
3101 isEnabledTo(0) returns false if this widget or any if its ancestors
3102 was explicitly disabled.
3103
3104 The word ancestor here means a parent widget within the same window.
3105
3106 Therefore isEnabledTo(0) stops at this widget's window, unlike
3107 isEnabled() which also takes parent windows into considerations.
3108
3109 \sa setEnabled(), enabled
3110*/
3111
3112bool QWidget::isEnabledTo(const QWidget *ancestor) const
3113{
3114 const QWidget * w = this;
3115 while (!w->testAttribute(attribute: Qt::WA_ForceDisabled)
3116 && !w->isWindow()
3117 && w->parentWidget()
3118 && w->parentWidget() != ancestor)
3119 w = w->parentWidget();
3120 return !w->testAttribute(attribute: Qt::WA_ForceDisabled);
3121}
3122
3123#ifndef QT_NO_ACTION
3124/*!
3125 Appends the action \a action to this widget's list of actions.
3126
3127 All QWidgets have a list of \l{QAction}s. However, they can be
3128 represented graphically in many different ways. The default use of
3129 the QAction list (as returned by actions()) is to create a context
3130 QMenu.
3131
3132 A QWidget should only have one of each action and adding an action
3133 it already has will not cause the same action to be in the widget twice.
3134
3135 The ownership of \a action is not transferred to this QWidget.
3136
3137 \sa removeAction(), insertAction(), actions(), QMenu
3138*/
3139void QWidget::addAction(QAction *action)
3140{
3141 insertAction(before: nullptr, action);
3142}
3143
3144/*!
3145 Appends the actions \a actions to this widget's list of actions.
3146
3147 \sa removeAction(), QMenu, addAction()
3148*/
3149void QWidget::addActions(const QList<QAction *> &actions)
3150{
3151 for(int i = 0; i < actions.size(); i++)
3152 insertAction(before: nullptr, action: actions.at(i));
3153}
3154
3155/*!
3156 Inserts the action \a action to this widget's list of actions,
3157 before the action \a before. It appends the action if \a before is \nullptr or
3158 \a before is not a valid action for this widget.
3159
3160 A QWidget should only have one of each action.
3161
3162 \sa removeAction(), addAction(), QMenu, contextMenuPolicy, actions()
3163*/
3164void QWidget::insertAction(QAction *before, QAction *action)
3165{
3166 if (Q_UNLIKELY(!action)) {
3167 qWarning(msg: "QWidget::insertAction: Attempt to insert null action");
3168 return;
3169 }
3170
3171 Q_D(QWidget);
3172 if (d->actions.contains(t: action))
3173 removeAction(action);
3174
3175 int pos = d->actions.indexOf(t: before);
3176 if (pos < 0) {
3177 before = nullptr;
3178 pos = d->actions.size();
3179 }
3180 d->actions.insert(i: pos, t: action);
3181
3182 QActionPrivate *apriv = action->d_func();
3183 apriv->associatedObjects.append(t: this);
3184
3185 QActionEvent e(QEvent::ActionAdded, action, before);
3186 QCoreApplication::sendEvent(receiver: this, event: &e);
3187}
3188
3189/*!
3190 Inserts the actions \a actions to this widget's list of actions,
3191 before the action \a before. It appends the action if \a before is \nullptr or
3192 \a before is not a valid action for this widget.
3193
3194 A QWidget can have at most one of each action.
3195
3196 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
3197*/
3198void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
3199{
3200 for(int i = 0; i < actions.size(); ++i)
3201 insertAction(before, action: actions.at(i));
3202}
3203
3204/*!
3205 Removes the action \a action from this widget's list of actions.
3206 \sa insertAction(), actions(), insertAction()
3207*/
3208void QWidget::removeAction(QAction *action)
3209{
3210 if (!action)
3211 return;
3212
3213 Q_D(QWidget);
3214
3215 QActionPrivate *apriv = action->d_func();
3216 apriv->associatedObjects.removeAll(t: this);
3217
3218 if (d->actions.removeAll(t: action)) {
3219 QActionEvent e(QEvent::ActionRemoved, action);
3220 QCoreApplication::sendEvent(receiver: this, event: &e);
3221 }
3222}
3223
3224/*!
3225 Returns the (possibly empty) list of this widget's actions.
3226
3227 \sa contextMenuPolicy, insertAction(), removeAction()
3228*/
3229QList<QAction*> QWidget::actions() const
3230{
3231 Q_D(const QWidget);
3232 return d->actions;
3233}
3234
3235/*!
3236 \fn QAction *QWidget::addAction(const QString &text);
3237 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut);
3238 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text);
3239 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut);
3240
3241 \since 6.3
3242
3243 These convenience functions create a new action with text \a text,
3244 icon \a icon and shortcut \a shortcut, if any.
3245
3246 The functions add the newly created action to the widget's
3247 list of actions, and return it.
3248
3249 QWidget takes ownership of the returned QAction.
3250*/
3251QAction *QWidget::addAction(const QString &text)
3252{
3253 QAction *ret = new QAction(text, this);
3254 addAction(action: ret);
3255 return ret;
3256}
3257
3258QAction *QWidget::addAction(const QIcon &icon, const QString &text)
3259{
3260 QAction *ret = new QAction(icon, text, this);
3261 addAction(action: ret);
3262 return ret;
3263}
3264
3265#if QT_CONFIG(shortcut)
3266QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut)
3267{
3268 QAction *ret = addAction(text);
3269 ret->setShortcut(shortcut);
3270 return ret;
3271}
3272
3273QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut)
3274{
3275 QAction *ret = addAction(icon, text);
3276 ret->setShortcut(shortcut);
3277 return ret;
3278}
3279#endif
3280
3281/*!
3282 \fn QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3283 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
3284 \fn QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3285 \fn QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, const QObject *receiver, const char* member, Qt::ConnectionType type)
3286
3287 \overload
3288 \since 6.3
3289
3290 This convenience function creates a new action with the text \a
3291 text, icon \a icon, and shortcut \a shortcut, if any.
3292
3293 The action's \l{QAction::triggered()}{triggered()} signal is connected
3294 to the \a receiver's \a member slot. The function adds the newly created
3295 action to the widget's list of actions and returns it.
3296
3297 QWidget takes ownership of the returned QAction.
3298*/
3299QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member,
3300 Qt::ConnectionType type)
3301{
3302 QAction *action = addAction(text);
3303 QObject::connect(sender: action, SIGNAL(triggered(bool)), receiver, member, type);
3304 return action;
3305}
3306
3307QAction *QWidget::addAction(const QIcon &icon, const QString &text,
3308 const QObject *receiver, const char* member,
3309 Qt::ConnectionType type)
3310{
3311 QAction *action = addAction(icon, text);
3312 QObject::connect(sender: action, SIGNAL(triggered(bool)), receiver, member, type);
3313 return action;
3314}
3315
3316#if QT_CONFIG(shortcut)
3317QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut,
3318 const QObject *receiver, const char* member,
3319 Qt::ConnectionType type)
3320{
3321 QAction *action = addAction(text, receiver, member, type);
3322 action->setShortcut(shortcut);
3323 return action;
3324}
3325
3326QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut,
3327 const QObject *receiver, const char* member,
3328 Qt::ConnectionType type)
3329{
3330 QAction *action = addAction(icon, text, receiver, member, type);
3331 action->setShortcut(shortcut);
3332 return action;
3333}
3334#endif // QT_CONFIG(shortcut)
3335
3336/*!
3337 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, Args&&...args)
3338 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, Args&&...args)
3339 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, Args&&...args)
3340 \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, Args&&...args)
3341
3342 \since 6.3
3343 \overload
3344
3345 These convenience functions create a new action with the text \a text,
3346 icon \a icon, and shortcut \a shortcut, if any.
3347
3348 The action's \l{QAction::triggered()}{triggered()} signal is connected
3349 as if by a call to QObject::connect(action, &QAction::triggered, args...),
3350 perfectly forwarding \a args, including a possible Qt::ConnectionType.
3351
3352 The function adds the newly created action to the widget's list of
3353 actions and returns it.
3354
3355 QWidget takes ownership of the returned QAction.
3356*/
3357#endif // QT_NO_ACTION
3358
3359/*!
3360 \property QWidget::enabled
3361 \brief whether the widget is enabled
3362
3363 In general an enabled widget handles keyboard and mouse events; a disabled
3364 widget does not. An exception is made with \l{QAbstractButton}.
3365
3366 Some widgets display themselves differently when they are
3367 disabled. For example a button might draw its label grayed out. If
3368 your widget needs to know when it becomes enabled or disabled, you
3369 can use the changeEvent() with type QEvent::EnabledChange.
3370
3371 Disabling a widget implicitly disables all its children. Enabling
3372 respectively enables all child widgets unless they have been
3373 explicitly disabled. It it not possible to explicitly enable a child
3374 widget which is not a window while its parent widget remains disabled.
3375
3376 By default, this property is \c true.
3377
3378 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3379*/
3380void QWidget::setEnabled(bool enable)
3381{
3382 Q_D(QWidget);
3383 setAttribute(Qt::WA_ForceDisabled, on: !enable);
3384 d->setEnabled_helper(enable);
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(attribute: Qt::WA_Disabled))
3395 return; // nothing to do
3396
3397 q->setAttribute(Qt::WA_Disabled, on: !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 *>(o: 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(attribute: Qt::WA_SetCursor) || q->isWindow()) {
3414 // enforce the windows behavior of clearing the cursor on
3415 // disabled widgets
3416 qt_qpa_set_cursor(w: q, force: false);
3417 }
3418#endif
3419#ifndef QT_NO_IM
3420 if (q->testAttribute(attribute: Qt::WA_InputMethodEnabled) && q->hasFocus()) {
3421 QWidget *focusWidget = effectiveFocusWidget();
3422
3423 if (enable) {
3424 if (focusWidget->testAttribute(attribute: Qt::WA_InputMethodEnabled))
3425 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
3426 } else {
3427 QGuiApplication::inputMethod()->commit();
3428 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
3429 }
3430 }
3431#endif //QT_NO_IM
3432 QEvent e(QEvent::EnabledChange);
3433 QCoreApplication::sendEvent(receiver: q, event: &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 If the widget is the desktop (windowType() == Qt::Desktop), this may
3444 fail if another application is using the desktop; you can call
3445 acceptDrops() to test if this occurs.
3446
3447 \warning Do not modify this property in a drag and drop event handler.
3448
3449 By default, this property is \c false.
3450
3451 \sa {Drag and Drop in Qt}{Drag and Drop}
3452*/
3453bool QWidget::acceptDrops() const
3454{
3455 return testAttribute(attribute: Qt::WA_AcceptDrops);
3456}
3457
3458void QWidget::setAcceptDrops(bool on)
3459{
3460 setAttribute(Qt::WA_AcceptDrops, on);
3461
3462}
3463
3464/*!
3465 Disables widget input events if \a disable is true; otherwise
3466 enables input events.
3467
3468 See the \l enabled documentation for more information.
3469
3470 \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()
3471*/
3472void QWidget::setDisabled(bool disable)
3473{
3474 setEnabled(!disable);
3475}
3476
3477/*!
3478 \property QWidget::frameGeometry
3479 \brief geometry of the widget relative to its parent including any
3480 window frame
3481
3482 See the \l{Window Geometry} documentation for an overview of geometry
3483 issues with windows.
3484
3485 By default, this property contains a value that depends on the user's
3486 platform and screen geometry.
3487
3488 \sa geometry(), x(), y(), pos()
3489*/
3490QRect QWidget::frameGeometry() const
3491{
3492 Q_D(const QWidget);
3493 if (isWindow() && ! (windowType() == Qt::Popup)) {
3494 QRect fs = d->frameStrut();
3495 return QRect(data->crect.x() - fs.left(),
3496 data->crect.y() - fs.top(),
3497 data->crect.width() + fs.left() + fs.right(),
3498 data->crect.height() + fs.top() + fs.bottom());
3499 }
3500 return data->crect;
3501}
3502
3503/*!
3504 \property QWidget::x
3505
3506 \brief the x coordinate of the widget relative to its parent including
3507 any window frame
3508
3509 See the \l{Window Geometry} documentation for an overview of geometry
3510 issues with windows.
3511
3512 By default, this property has a value of 0.
3513
3514 \sa frameGeometry, y, pos
3515*/
3516int QWidget::x() const
3517{
3518 Q_D(const QWidget);
3519 if (isWindow() && ! (windowType() == Qt::Popup))
3520 return data->crect.x() - d->frameStrut().left();
3521 return data->crect.x();
3522}
3523
3524/*!
3525 \property QWidget::y
3526 \brief the y coordinate of the widget relative to its parent and
3527 including any window frame
3528
3529 See the \l{Window Geometry} documentation for an overview of geometry
3530 issues with windows.
3531
3532 By default, this property has a value of 0.
3533
3534 \sa frameGeometry, x, pos
3535*/
3536int QWidget::y() const
3537{
3538 Q_D(const QWidget);
3539 if (isWindow() && ! (windowType() == Qt::Popup))
3540 return data->crect.y() - d->frameStrut().top();
3541 return data->crect.y();
3542}
3543
3544/*!
3545 \property QWidget::pos
3546 \brief the position of the widget within its parent widget
3547
3548 If the widget is a window, the position is that of the widget on
3549 the desktop, including its frame.
3550
3551 When changing the position, the widget, if visible, receives a
3552 move event (moveEvent()) immediately. If the widget is not
3553 currently visible, it is guaranteed to receive an event before it
3554 is shown.
3555
3556 By default, this property contains a position that refers to the
3557 origin.
3558
3559 \warning Calling move() or setGeometry() inside moveEvent() can
3560 lead to infinite recursion.
3561
3562 See the \l{Window Geometry} documentation for an overview of geometry
3563 issues with windows.
3564
3565 \note Not all windowing systems support setting or querying top level window positions.
3566 On such a system, programmatically moving windows may not have any effect, and artificial
3567 values may be returned for the current positions, such as \c QPoint(0, 0).
3568
3569 \sa frameGeometry, size, x(), y()
3570*/
3571QPoint QWidget::pos() const
3572{
3573 Q_D(const QWidget);
3574 QPoint result = data->crect.topLeft();
3575 if (isWindow() && ! (windowType() == Qt::Popup))
3576 if (!d->maybeTopData() || !d->maybeTopData()->posIncludesFrame)
3577 result -= d->frameStrut().topLeft();
3578 return result;
3579}
3580
3581/*!
3582 \property QWidget::geometry
3583 \brief the geometry of the widget relative to its parent and
3584 excluding the window frame
3585
3586 When changing the geometry, the widget, if visible, receives a
3587 move event (moveEvent()) and/or a resize event (resizeEvent())
3588 immediately. If the widget is not currently visible, it is
3589 guaranteed to receive appropriate events before it is shown.
3590
3591 The size component is adjusted if it lies outside the range
3592 defined by minimumSize() and maximumSize().
3593
3594 \warning Calling setGeometry() inside resizeEvent() or moveEvent()
3595 can lead to infinite recursion.
3596
3597 See the \l{Window Geometry} documentation for an overview of geometry
3598 issues with windows.
3599
3600 By default, this property contains a value that depends on the user's
3601 platform and screen geometry.
3602
3603 \sa frameGeometry(), rect(), move(), resize(), moveEvent(),
3604 resizeEvent(), minimumSize(), maximumSize()
3605*/
3606
3607/*!
3608 \property QWidget::size
3609 \brief the size of the widget excluding any window frame
3610
3611 If the widget is visible when it is being resized, it receives a resize event
3612 (resizeEvent()) immediately. If the widget is not currently
3613 visible, it is guaranteed to receive an event before it is shown.
3614
3615 The size is adjusted if it lies outside the range defined by
3616 minimumSize() and maximumSize().
3617
3618 By default, this property contains a value that depends on the user's
3619 platform and screen geometry.
3620
3621 \warning Calling resize() or setGeometry() inside resizeEvent() can
3622 lead to infinite recursion.
3623
3624 \note Setting the size to \c{QSize(0, 0)} will cause the widget to not
3625 appear on screen. This also applies to windows.
3626
3627 \sa pos, geometry, minimumSize, maximumSize, resizeEvent(), adjustSize()
3628*/
3629
3630/*!
3631 \property QWidget::width
3632 \brief the width of the widget excluding any window frame
3633
3634 See the \l{Window Geometry} documentation for an overview of geometry
3635 issues with windows.
3636
3637 \note Do not use this function to find the width of a screen on
3638 a multi-screen desktop. See QScreen for details.
3639
3640 By default, this property contains a value that depends on the user's
3641 platform and screen geometry.
3642
3643 \sa geometry, height, size
3644*/
3645
3646/*!
3647 \property QWidget::height
3648 \brief the height of the widget excluding any window frame
3649
3650 See the \l{Window Geometry} documentation for an overview of geometry
3651 issues with windows.
3652
3653 By default, this property contains a value that depends on the user's
3654 platform and \l{QScreen::geometry}{screen geometry}.
3655
3656 \sa geometry, width, size
3657*/
3658
3659/*!
3660 \property QWidget::rect
3661 \brief the internal geometry of the widget excluding any window
3662 frame
3663
3664 The rect property equals QRect(0, 0, width(), height()).
3665
3666 See the \l{Window Geometry} documentation for an overview of geometry
3667 issues with windows.
3668
3669 By default, this property contains a value that depends on the user's
3670 platform and screen geometry.
3671
3672 \sa size
3673*/
3674
3675/*!
3676 \property QWidget::normalGeometry
3677
3678 \brief the geometry of the widget as it will appear when shown as
3679 a normal (not maximized or full screen) top-level widget
3680
3681 If the widget is already in this state the normal geometry will
3682 reflect the widget's current geometry().
3683
3684 For child widgets this property always holds an empty rectangle.
3685
3686 By default, this property contains an empty rectangle.
3687
3688 \sa QWidget::windowState(), QWidget::geometry
3689*/
3690QRect QWidget::normalGeometry() const
3691{
3692 Q_D(const QWidget);
3693 if (!isWindow())
3694 return QRect();
3695
3696 if (!isMaximized() && !isFullScreen())
3697 return geometry();
3698
3699 return d->topData()->normalGeometry;
3700}
3701
3702
3703/*!
3704 \property QWidget::childrenRect
3705 \brief the bounding rectangle of the widget's children
3706
3707 Hidden children are excluded.
3708
3709 By default, for a widget with no children, this property contains a
3710 rectangle with zero width and height located at the origin.
3711
3712 \sa childrenRegion(), geometry()
3713*/
3714
3715QRect QWidget::childrenRect() const
3716{
3717 Q_D(const QWidget);
3718 QRect r(0, 0, 0, 0);
3719 for (int i = 0; i < d->children.size(); ++i) {
3720 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
3721 if (w && !w->isWindow() && !w->isHidden())
3722 r |= w->geometry();
3723 }
3724 return r;
3725}
3726
3727/*!
3728 \property QWidget::childrenRegion
3729 \brief the combined region occupied by the widget's children
3730
3731 Hidden children are excluded.
3732
3733 By default, for a widget with no children, this property contains an
3734 empty region.
3735
3736 \sa childrenRect(), geometry(), mask()
3737*/
3738
3739QRegion QWidget::childrenRegion() const
3740{
3741 Q_D(const QWidget);
3742 QRegion r;
3743 for (int i = 0; i < d->children.size(); ++i) {
3744 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
3745 if (w && !w->isWindow() && !w->isHidden()) {
3746 QRegion mask = w->mask();
3747 if (mask.isEmpty())
3748 r |= w->geometry();
3749 else
3750 r |= mask.translated(p: w->pos());
3751 }
3752 }
3753 return r;
3754}
3755
3756
3757/*!
3758 \property QWidget::minimumSize
3759 \brief the widget's minimum size
3760
3761 The widget cannot be resized to a smaller size than the minimum
3762 widget size. The widget's size is forced to the minimum size if
3763 the current size is smaller.
3764
3765 The minimum size set by this function will override the minimum size
3766 defined by QLayout. To unset the minimum size, use a
3767 value of \c{QSize(0, 0)}.
3768
3769 By default, this property contains a size with zero width and height.
3770
3771 \sa minimumWidth, minimumHeight, maximumSize, sizeIncrement
3772*/
3773
3774QSize QWidget::minimumSize() const
3775{
3776 Q_D(const QWidget);
3777 return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
3778}
3779
3780/*!
3781 \property QWidget::maximumSize
3782 \brief the widget's maximum size in pixels
3783
3784 The widget cannot be resized to a larger size than the maximum
3785 widget size.
3786
3787 By default, this property contains a size in which both width and height
3788 have values of 16777215.
3789
3790 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3791 of widgets.
3792
3793 \sa maximumWidth, maximumHeight, minimumSize, sizeIncrement
3794*/
3795
3796QSize QWidget::maximumSize() const
3797{
3798 Q_D(const QWidget);
3799 return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
3800 : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
3801}
3802
3803
3804/*!
3805 \property QWidget::minimumWidth
3806 \brief the widget's minimum width in pixels
3807
3808 This property corresponds to the width held by the \l minimumSize property.
3809
3810 By default, this property has a value of 0.
3811
3812 \sa minimumSize, minimumHeight
3813*/
3814
3815/*!
3816 \property QWidget::minimumHeight
3817 \brief the widget's minimum height in pixels
3818
3819 This property corresponds to the height held by the \l minimumSize property.
3820
3821 By default, this property has a value of 0.
3822
3823 \sa minimumSize, minimumWidth
3824*/
3825
3826/*!
3827 \property QWidget::maximumWidth
3828 \brief the widget's maximum width in pixels
3829
3830 This property corresponds to the width held by the \l maximumSize property.
3831
3832 By default, this property contains a value of 16777215.
3833
3834 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3835 of widgets.
3836
3837 \sa maximumSize, maximumHeight
3838*/
3839
3840/*!
3841 \property QWidget::maximumHeight
3842 \brief the widget's maximum height in pixels
3843
3844 This property corresponds to the height held by the \l maximumSize property.
3845
3846 By default, this property contains a value of 16777215.
3847
3848 \note The definition of the \c QWIDGETSIZE_MAX macro limits the maximum size
3849 of widgets.
3850
3851 \sa maximumSize, maximumWidth
3852*/
3853
3854/*!
3855 \property QWidget::sizeIncrement
3856 \brief the size increment of the widget
3857
3858 When the user resizes the window, the size will move in steps of
3859 sizeIncrement().width() pixels horizontally and
3860 sizeIncrement.height() pixels vertically, with baseSize() as the
3861 basis. Preferred widget sizes are for non-negative integers \e i
3862 and \e j:
3863 \snippet code/src_gui_kernel_qwidget.cpp 2
3864
3865 Note that while you can set the size increment for all widgets, it
3866 only affects windows.
3867
3868 By default, this property contains a size with zero width and height.
3869
3870 \warning The size increment has no effect under Windows, and may
3871 be disregarded by the window manager on X11.
3872
3873 \sa size, minimumSize, maximumSize
3874*/
3875QSize QWidget::sizeIncrement() const
3876{
3877 Q_D(const QWidget);
3878 return (d->extra && d->extra->topextra)
3879 ? QSize(d->extra->topextra->incw, d->extra->topextra->inch)
3880 : QSize(0, 0);
3881}
3882
3883/*!
3884 \property QWidget::baseSize
3885 \brief the base size of the widget
3886
3887 The base size is used to calculate a proper widget size if the
3888 widget defines sizeIncrement().
3889
3890 By default, for a newly-created widget, this property contains a size with
3891 zero width and height.
3892
3893 \sa setSizeIncrement()
3894*/
3895
3896QSize QWidget::baseSize() const
3897{
3898 Q_D(const QWidget);
3899 return (d->extra && d->extra->topextra)
3900 ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh)
3901 : QSize(0, 0);
3902}
3903
3904bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh)
3905{
3906 Q_Q(QWidget);
3907
3908 int mw = minw, mh = minh;
3909 if (mw == QWIDGETSIZE_MAX)
3910 mw = 0;
3911 if (mh == QWIDGETSIZE_MAX)
3912 mh = 0;
3913 if (Q_UNLIKELY(minw > QWIDGETSIZE_MAX || minh > QWIDGETSIZE_MAX)) {
3914 qWarning(msg: "QWidget::setMinimumSize: (%s/%s) "
3915 "The largest allowed size is (%d,%d)",
3916 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3917 QWIDGETSIZE_MAX);
3918 minw = mw = qMin<int>(a: minw, QWIDGETSIZE_MAX);
3919 minh = mh = qMin<int>(a: minh, QWIDGETSIZE_MAX);
3920 }
3921 if (Q_UNLIKELY(minw < 0 || minh < 0)) {
3922 qWarning(msg: "QWidget::setMinimumSize: (%s/%s) Negative sizes (%d,%d) "
3923 "are not possible",
3924 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), minw, minh);
3925 minw = mw = qMax(a: minw, b: 0);
3926 minh = mh = qMax(a: minh, b: 0);
3927 }
3928 createExtra();
3929 if (extra->minw == mw && extra->minh == mh)
3930 return false;
3931 extra->minw = mw;
3932 extra->minh = mh;
3933 extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0);
3934 return true;
3935}
3936
3937void QWidgetPrivate::setConstraints_sys()
3938{
3939 Q_Q(QWidget);
3940 if (extra && q->windowHandle()) {
3941 QWindow *win = q->windowHandle();
3942 QWindowPrivate *winp = qt_window_private(window: win);
3943
3944 winp->minimumSize = QSize(extra->minw, extra->minh);
3945 winp->maximumSize = QSize(extra->maxw, extra->maxh);
3946
3947 if (extra->topextra) {
3948 winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
3949 winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
3950 }
3951
3952 if (winp->platformWindow) {
3953 fixPosIncludesFrame();
3954 winp->platformWindow->propagateSizeHints();
3955 }
3956 }
3957}
3958
3959/*!
3960 \overload
3961
3962 This function corresponds to setMinimumSize(QSize(minw, minh)).
3963 Sets the minimum width to \a minw and the minimum height to \a
3964 minh.
3965*/
3966
3967void QWidget::setMinimumSize(int minw, int minh)
3968{
3969 Q_D(QWidget);
3970 if (!d->setMinimumSize_helper(minw, minh))
3971 return;
3972
3973 if (isWindow())
3974 d->setConstraints_sys();
3975 if (minw > width() || minh > height()) {
3976 bool resized = testAttribute(attribute: Qt::WA_Resized);
3977 bool maximized = isMaximized();
3978 resize(w: qMax(a: minw,b: width()), h: qMax(a: minh,b: height()));
3979 setAttribute(Qt::WA_Resized, on: resized); //not a user resize
3980 if (maximized)
3981 data->window_state = data->window_state | Qt::WindowMaximized;
3982 }
3983#if QT_CONFIG(graphicsview)
3984 if (d->extra) {
3985 if (d->extra->proxyWidget)
3986 d->extra->proxyWidget->setMinimumSize(aw: minw, ah: minh);
3987 }
3988#endif
3989 d->updateGeometry_helper(forceUpdate: d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
3990}
3991
3992bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh)
3993{
3994 Q_Q(QWidget);
3995 if (Q_UNLIKELY(maxw > QWIDGETSIZE_MAX || maxh > QWIDGETSIZE_MAX)) {
3996 qWarning(msg: "QWidget::setMaximumSize: (%s/%s) "
3997 "The largest allowed size is (%d,%d)",
3998 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), QWIDGETSIZE_MAX,
3999 QWIDGETSIZE_MAX);
4000 maxw = qMin<int>(a: maxw, QWIDGETSIZE_MAX);
4001 maxh = qMin<int>(a: maxh, QWIDGETSIZE_MAX);
4002 }
4003 if (Q_UNLIKELY(maxw < 0 || maxh < 0)) {
4004 qWarning(msg: "QWidget::setMaximumSize: (%s/%s) Negative sizes (%d,%d) "
4005 "are not possible",
4006 q->objectName().toLocal8Bit().data(), q->metaObject()->className(), maxw, maxh);
4007 maxw = qMax(a: maxw, b: 0);
4008 maxh = qMax(a: maxh, b: 0);
4009 }
4010 createExtra();
4011 if (extra->maxw == maxw && extra->maxh == maxh)
4012 return false;
4013 extra->maxw = maxw;
4014 extra->maxh = maxh;
4015 extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) |
4016 (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0);
4017 return true;
4018}
4019
4020/*!
4021 \overload
4022
4023 This function corresponds to setMaximumSize(QSize(\a maxw, \a
4024 maxh)). Sets the maximum width to \a maxw and the maximum height
4025 to \a maxh.
4026*/
4027void QWidget::setMaximumSize(int maxw, int maxh)
4028{
4029 Q_D(QWidget);
4030 if (!d->setMaximumSize_helper(maxw, maxh))
4031 return;
4032
4033 if (isWindow())
4034 d->setConstraints_sys();
4035 if (maxw < width() || maxh < height()) {
4036 bool resized = testAttribute(attribute: Qt::WA_Resized);
4037 resize(w: qMin(a: maxw,b: width()), h: qMin(a: maxh,b: height()));
4038 setAttribute(Qt::WA_Resized, on: resized); //not a user resize
4039 }
4040
4041#if QT_CONFIG(graphicsview)
4042 if (d->extra) {
4043 if (d->extra->proxyWidget)
4044 d->extra->proxyWidget->setMaximumSize(aw: maxw, ah: maxh);
4045 }
4046#endif
4047
4048 d->updateGeometry_helper(forceUpdate: d->extra->minw == d->extra->maxw && d->extra->minh == d->extra->maxh);
4049}
4050
4051/*!
4052 \overload
4053
4054 Sets the x (width) size increment to \a w and the y (height) size
4055 increment to \a h.
4056*/
4057void QWidget::setSizeIncrement(int w, int h)
4058{
4059 Q_D(QWidget);
4060 d->createTLExtra();
4061 QTLWExtra* x = d->topData();
4062 if (x->incw == w && x->inch == h)
4063 return;
4064 x->incw = w;
4065 x->inch = h;
4066 if (isWindow())
4067 d->setConstraints_sys();
4068}
4069
4070/*!
4071 \overload
4072
4073 This corresponds to setBaseSize(QSize(\a basew, \a baseh)). Sets
4074 the widgets base size to width \a basew and height \a baseh.
4075*/
4076void QWidget::setBaseSize(int basew, int baseh)
4077{
4078 Q_D(QWidget);
4079 d->createTLExtra();
4080 QTLWExtra* x = d->topData();
4081 if (x->basew == basew && x->baseh == baseh)
4082 return;
4083 x->basew = basew;
4084 x->baseh = baseh;
4085 if (isWindow())
4086 d->setConstraints_sys();
4087}
4088
4089/*!
4090 Sets both the minimum and maximum sizes of the widget to \a s,
4091 thereby preventing it from ever growing or shrinking.
4092
4093 This will override the default size constraints set by QLayout.
4094
4095 To remove constraints, set the size to QWIDGETSIZE_MAX.
4096
4097 Alternatively, if you want the widget to have a
4098 fixed size based on its contents, you can call
4099 QLayout::setSizeConstraint(QLayout::SetFixedSize);
4100
4101 \sa maximumSize, minimumSize
4102*/
4103
4104void QWidget::setFixedSize(const QSize & s)
4105{
4106 setFixedSize(w: s.width(), h: s.height());
4107}
4108
4109
4110/*!
4111 \fn void QWidget::setFixedSize(int w, int h)
4112 \overload
4113
4114 Sets the width of the widget to \a w and the height to \a h.
4115*/
4116
4117void QWidget::setFixedSize(int w, int h)
4118{
4119 Q_D(QWidget);
4120 bool minSizeSet = d->setMinimumSize_helper(minw&: w, minh&: h);
4121 bool maxSizeSet = d->setMaximumSize_helper(maxw&: w, maxh&: h);
4122 if (!minSizeSet && !maxSizeSet)
4123 return;
4124
4125 if (isWindow())
4126 d->setConstraints_sys();
4127 else
4128 d->updateGeometry_helper(forceUpdate: true);
4129
4130 if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
4131 resize(w, h);
4132}
4133
4134void QWidget::setMinimumWidth(int w)
4135{
4136 Q_D(QWidget);
4137 d->createExtra();
4138 uint expl = d->extra->explicitMinSize | (w ? Qt::Horizontal : 0);
4139 setMinimumSize(minw: w, minh: minimumSize().height());
4140 d->extra->explicitMinSize = expl;
4141}
4142
4143void QWidget::setMinimumHeight(int h)
4144{
4145 Q_D(QWidget);
4146 d->createExtra();
4147 uint expl = d->extra->explicitMinSize | (h ? Qt::Vertical : 0);
4148 setMinimumSize(minw: minimumSize().width(), minh: h);
4149 d->extra->explicitMinSize = expl;
4150}
4151
4152void QWidget::setMaximumWidth(int w)
4153{
4154 Q_D(QWidget);
4155 d->createExtra();
4156 uint expl = d->extra->explicitMaxSize | (w == QWIDGETSIZE_MAX ? 0 : Qt::Horizontal);
4157 setMaximumSize(maxw: w, maxh: maximumSize().height());
4158 d->extra->explicitMaxSize = expl;
4159}
4160
4161void QWidget::setMaximumHeight(int h)
4162{
4163 Q_D(QWidget);
4164 d->createExtra();
4165 uint expl = d->extra->explicitMaxSize | (h == QWIDGETSIZE_MAX ? 0 : Qt::Vertical);
4166 setMaximumSize(maxw: maximumSize().width(), maxh: h);
4167 d->extra->explicitMaxSize = expl;
4168}
4169
4170/*!
4171 Sets both the minimum and maximum width of the widget to \a w
4172 without changing the heights. Provided for convenience.
4173
4174 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4175*/
4176
4177void QWidget::setFixedWidth(int w)
4178{
4179 Q_D(QWidget);
4180 d->createExtra();
4181 uint explMin = d->extra->explicitMinSize | Qt::Horizontal;
4182 uint explMax = d->extra->explicitMaxSize | Qt::Horizontal;
4183 setMinimumSize(minw: w, minh: minimumSize().height());
4184 setMaximumSize(maxw: w, maxh: maximumSize().height());
4185 d->extra->explicitMinSize = explMin;
4186 d->extra->explicitMaxSize = explMax;
4187}
4188
4189
4190/*!
4191 Sets both the minimum and maximum heights of the widget to \a h
4192 without changing the widths. Provided for convenience.
4193
4194 \sa sizeHint(), minimumSize(), maximumSize(), setFixedSize()
4195*/
4196
4197void QWidget::setFixedHeight(int h)
4198{
4199 Q_D(QWidget);
4200 d->createExtra();
4201 uint explMin = d->extra->explicitMinSize | Qt::Vertical;
4202 uint explMax = d->extra->explicitMaxSize | Qt::Vertical;
4203 setMinimumSize(minw: minimumSize().width(), minh: h);
4204 setMaximumSize(maxw: maximumSize().width(), maxh: h);
4205 d->extra->explicitMinSize = explMin;
4206 d->extra->explicitMaxSize = explMax;
4207}
4208
4209
4210/*!
4211 Translates the widget coordinate \a pos to the coordinate system
4212 of \a parent. The \a parent must not be \nullptr and must be a parent
4213 of the calling widget.
4214
4215 \sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
4216 \since 6.0
4217*/
4218
4219QPointF QWidget::mapTo(const QWidget *parent, const QPointF &pos) const
4220{
4221 QPointF p = pos;
4222 if (parent) {
4223 const QWidget * w = this;
4224 while (w != parent) {
4225 p = w->mapToParent(p);
4226 w = w->parentWidget();
4227 if (!w) {
4228 qWarning(msg: "QWidget::mapTo(): parent must be in parent hierarchy");
4229 break;
4230 }
4231 }
4232 }
4233 return p;
4234}
4235
4236/*!
4237 \overload
4238*/
4239QPoint QWidget::mapTo(const QWidget *parent, const QPoint &pos) const
4240{
4241 return mapTo(parent, pos: QPointF(pos)).toPoint();
4242}
4243
4244/*!
4245 Translates the widget coordinate \a pos from the coordinate system
4246 of \a parent to this widget's coordinate system. The \a parent
4247 must not be \nullptr and must be a parent of the calling widget.
4248
4249 \sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
4250 \since 6.0
4251*/
4252
4253QPointF QWidget::mapFrom(const QWidget *parent, const QPointF &pos) const
4254{
4255 QPointF p(pos);
4256 if (parent) {
4257 const QWidget * w = this;
4258 while (w != parent) {
4259 p = w->mapFromParent(p);
4260 w = w->parentWidget();
4261 if (!w) {
4262 qWarning(msg: "QWidget::mapFrom(): parent must be in parent hierarchy");
4263 break;
4264 }
4265 }
4266 }
4267 return p;
4268}
4269
4270/*!
4271 \overload
4272*/
4273QPoint QWidget::mapFrom(const QWidget *parent, const QPoint &pos) const
4274{
4275 return mapFrom(parent, pos: QPointF(pos)).toPoint();
4276}
4277
4278/*!
4279 Translates the widget coordinate \a pos to a coordinate in the
4280 parent widget.
4281
4282 Same as mapToGlobal() if the widget has no parent.
4283
4284 \sa mapFromParent(), mapTo(), mapToGlobal(), underMouse()
4285 \since 6.0
4286*/
4287
4288QPointF QWidget::mapToParent(const QPointF &pos) const
4289{
4290 return pos + QPointF(data->crect.topLeft());
4291}
4292
4293/*!
4294 \overload
4295*/
4296QPoint QWidget::mapToParent(const QPoint &pos) const
4297{
4298 return pos + data->crect.topLeft();
4299}
4300
4301/*!
4302 Translates the parent widget coordinate \a pos to widget
4303 coordinates.
4304
4305 Same as mapFromGlobal() if the widget has no parent.
4306
4307 \sa mapToParent(), mapFrom(), mapFromGlobal(), underMouse()
4308 \since 6.0
4309*/
4310
4311QPointF QWidget::mapFromParent(const QPointF &pos) const
4312{
4313 return pos - QPointF(data->crect.topLeft());
4314}
4315
4316/*!
4317 \overload
4318*/
4319QPoint QWidget::mapFromParent(const QPoint &pos) const
4320{
4321 return pos - data->crect.topLeft();
4322}
4323
4324
4325/*!
4326 Returns the window for this widget, i.e. the next ancestor widget
4327 that has (or could have) a window-system frame.
4328
4329 If the widget is a window, the widget itself is returned.
4330
4331 Typical usage is changing the window title:
4332
4333 \snippet code/src_gui_kernel_qwidget.cpp 3
4334
4335 \sa isWindow()
4336*/
4337
4338QWidget *QWidget::window() const
4339{
4340 QWidget *w = const_cast<QWidget *>(this);
4341 QWidget *p = w->parentWidget();
4342 while (!w->isWindow() && p) {
4343 w = p;
4344 p = p->parentWidget();
4345 }
4346 return w;
4347}
4348
4349/*!
4350 \since 4.4
4351
4352 Returns the native parent for this widget, i.e. the next ancestor widget
4353 that has a system identifier, or \nullptr if it does not have any native
4354 parent.
4355
4356 \sa effectiveWinId()
4357*/
4358QWidget *QWidget::nativeParentWidget() const
4359{
4360 QWidget *parent = parentWidget();
4361 while (parent && !parent->internalWinId())
4362 parent = parent->parentWidget();
4363 return parent;
4364}
4365
4366/*! \fn QWidget *QWidget::topLevelWidget() const
4367 \deprecated
4368
4369 Use window() instead.
4370*/
4371
4372
4373
4374/*!
4375 Returns the background role of the widget.
4376
4377 The background role defines the brush from the widget's \l palette that
4378 is used to render the background.
4379
4380 If no explicit background role is set, the widget inherits its parent
4381 widget's background role.
4382
4383 \sa setBackgroundRole(), foregroundRole()
4384 */
4385QPalette::ColorRole QWidget::backgroundRole() const
4386{
4387
4388 const QWidget *w = this;
4389 do {
4390 QPalette::ColorRole role = w->d_func()->bg_role;
4391 if (role != QPalette::NoRole)
4392 return role;
4393 if (w->isWindow() || w->windowType() == Qt::SubWindow)
4394 break;
4395 w = w->parentWidget();
4396 } while (w);
4397 return QPalette::Window;
4398}
4399
4400/*!
4401 Sets the background role of the widget to \a role.
4402
4403 The background role defines the brush from the widget's \l palette that
4404 is used to render the background.
4405
4406 If \a role is QPalette::NoRole, then the widget inherits its
4407 parent's background role.
4408
4409 Note that styles are free to choose any color from the palette.
4410 You can modify the palette or set a style sheet if you don't
4411 achieve the result you want with setBackgroundRole().
4412
4413 \sa backgroundRole(), foregroundRole()
4414 */
4415
4416void QWidget::setBackgroundRole(QPalette::ColorRole role)
4417{
4418 Q_D(QWidget);
4419 d->bg_role = role;
4420 d->updateSystemBackground();
4421 d->propagatePaletteChange();
4422 d->updateIsOpaque();
4423}
4424
4425/*!
4426 Returns the foreground role.
4427
4428 The foreground role defines the color from the widget's \l palette that
4429 is used to draw the foreground.
4430
4431 If no explicit foreground role is set, the function returns a role
4432 that contrasts with the background role.
4433
4434 \sa setForegroundRole(), backgroundRole()
4435 */
4436QPalette::ColorRole QWidget::foregroundRole() const
4437{
4438 Q_D(const QWidget);
4439 QPalette::ColorRole rl = QPalette::ColorRole(d->fg_role);
4440 if (rl != QPalette::NoRole)
4441 return rl;
4442 QPalette::ColorRole role = QPalette::WindowText;
4443 switch (backgroundRole()) {
4444 case QPalette::Button:
4445 role = QPalette::ButtonText;
4446 break;
4447 case QPalette::Base:
4448 role = QPalette::Text;
4449 break;
4450 case QPalette::Dark:
4451 case QPalette::Shadow:
4452 role = QPalette::Light;
4453 break;
4454 case QPalette::Highlight:
4455 role = QPalette::HighlightedText;
4456 break;
4457 case QPalette::ToolTipBase:
4458 role = QPalette::ToolTipText;
4459 break;
4460 default:
4461 ;
4462 }
4463 return role;
4464}
4465
4466/*!
4467 Sets the foreground role of the widget to \a role.
4468
4469 The foreground role defines the color from the widget's \l palette that
4470 is used to draw the foreground.
4471
4472 If \a role is QPalette::NoRole, the widget uses a foreground role
4473 that contrasts with the background role.
4474
4475 Note that styles are free to choose any color from the palette.
4476 You can modify the palette or set a style sheet if you don't
4477 achieve the result you want with setForegroundRole().
4478
4479 \sa foregroundRole(), backgroundRole()
4480 */
4481void QWidget::setForegroundRole(QPalette::ColorRole role)
4482{
4483 Q_D(QWidget);
4484 d->fg_role = role;
4485 d->updateSystemBackground();
4486 d->propagatePaletteChange();
4487}
4488
4489/*!
4490 \property QWidget::palette
4491 \brief the widget's palette
4492
4493 This property describes the widget's palette. The palette is used by the
4494 widget's style when rendering standard components, and is available as a
4495 means to ensure that custom widgets can maintain consistency with the
4496 native platform's look and feel. It's common that different platforms, or
4497 different styles, have different palettes.
4498
4499 When you assign a new palette to a widget, the color roles from this
4500 palette are combined with the widget's default palette to form the
4501 widget's final palette. The palette entry for the widget's background role
4502 is used to fill the widget's background (see QWidget::autoFillBackground),
4503 and the foreground role initializes QPainter's pen.
4504
4505 The default depends on the system environment. QApplication maintains a
4506 system/theme palette which serves as a default for all widgets. There may
4507 also be special palette defaults for certain types of widgets (e.g., on
4508 Windows Vista, all classes that derive from QMenuBar have a special
4509 default palette). You can also define default palettes for widgets
4510 yourself by passing a custom palette and the name of a widget to
4511 QApplication::setPalette(). Finally, the style always has the option of
4512 polishing the palette as it's assigned (see QStyle::polish()).
4513
4514 QWidget propagates explicit palette roles from parent to child. If you
4515 assign a brush or color to a specific role on a palette and assign that
4516 palette to a widget, that role will propagate to all the widget's
4517 children, overriding any system defaults for that role. Note that palettes
4518 by default don't propagate to windows (see isWindow()) unless the
4519 Qt::WA_WindowPropagation attribute is enabled.
4520
4521 QWidget's palette propagation is similar to its font propagation.
4522
4523 The current style, which is used to render the content of all standard Qt
4524 widgets, is free to choose colors and brushes from the widget palette, or,
4525 in some cases, to ignore the palette (partially, or completely). In
4526 particular, certain styles like GTK style, Mac style, and Windows Vista
4527 style, depend on third party APIs to render the content of widgets,
4528 and these styles typically do not follow the palette. Because of this,
4529 assigning roles to a widget's palette is not guaranteed to change the
4530 appearance of the widget. Instead, you may choose to apply a \l {styleSheet}.
4531
4532 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
4533 When using style sheets, the palette of a widget can be customized using
4534 the "color", "background-color", "selection-color",
4535 "selection-background-color" and "alternate-background-color".
4536
4537 \sa QGuiApplication::palette(), QWidget::font(), {Qt Style Sheets}
4538*/
4539const QPalette &QWidget::palette() const
4540{
4541 if (!isEnabled()) {
4542 data->pal.setCurrentColorGroup(QPalette::Disabled);
4543 } else if ((!isVisible() || isActiveWindow())
4544#if defined(Q_OS_WIN)
4545 && !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
4546#endif
4547 ) {
4548 data->pal.setCurrentColorGroup(QPalette::Active);
4549 } else {
4550 data->pal.setCurrentColorGroup(QPalette::Inactive);
4551 }
4552 return data->pal;
4553}
4554
4555void QWidget::setPalette(const QPalette &palette)
4556{
4557 Q_D(QWidget);
4558 setAttribute(Qt::WA_SetPalette, on: palette.resolveMask() != 0);
4559
4560 // Determine which palette is inherited from this widget's ancestors and
4561 // QApplication::palette, resolve this against \a palette (attributes from
4562 // the inherited palette are copied over this widget's palette). Then
4563 // propagate this palette to this widget's children.
4564 QPalette naturalPalette = d->naturalWidgetPalette(inheritedMask: d->inheritedPaletteResolveMask);
4565 QPalette resolvedPalette = palette.resolve(other: naturalPalette);
4566 d->setPalette_helper(resolvedPalette);
4567}
4568
4569/*!
4570 \internal
4571
4572 Returns the palette that the widget \a w inherits from its ancestors and
4573 QApplication::palette. \a inheritedMask is the combination of the widget's
4574 ancestors palette request masks (i.e., which attributes from the parent
4575 widget's palette are implicitly imposed on this widget by the user). Note
4576 that this font does not take into account the palette set on \a w itself.
4577*/
4578QPalette QWidgetPrivate::naturalWidgetPalette(QPalette::ResolveMask inheritedMask) const
4579{
4580 Q_Q(const QWidget);
4581
4582 const bool useStyleSheetPropagationInWidgetStyles =
4583 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4584
4585 QPalette naturalPalette = QApplication::palette(q);
4586 if ((!q->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4587 && (!q->isWindow() || q->testAttribute(attribute: Qt::WA_WindowPropagation)
4588#if QT_CONFIG(graphicsview)
4589 || (extra && extra->proxyWidget)
4590#endif // QT_CONFIG(graphicsview)
4591 )) {
4592 if (QWidget *p = q->parentWidget()) {
4593 if (!p->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4594 if (!naturalPalette.isCopyOf(p: QGuiApplication::palette())) {
4595 QPalette inheritedPalette = p->palette();
4596 inheritedPalette.setResolveMask(inheritedMask);
4597 naturalPalette = inheritedPalette.resolve(other: naturalPalette);
4598 } else {
4599 naturalPalette = p->palette();
4600 }
4601 }
4602 }
4603#if QT_CONFIG(graphicsview)
4604 else if (extra && extra->proxyWidget) {
4605 QPalette inheritedPalette = extra->proxyWidget->palette();
4606 inheritedPalette.setResolveMask(inheritedMask);
4607 naturalPalette = inheritedPalette.resolve(other: naturalPalette);
4608 }
4609#endif // QT_CONFIG(graphicsview)
4610 }
4611 naturalPalette.setResolveMask(0);
4612 return naturalPalette;
4613}
4614/*!
4615 \internal
4616
4617 Determine which palette is inherited from this widget's ancestors and
4618 QApplication::palette, resolve this against this widget's palette
4619 (attributes from the inherited palette are copied over this widget's
4620 palette). Then propagate this palette to this widget's children.
4621*/
4622void QWidgetPrivate::resolvePalette()
4623{
4624 QPalette naturalPalette = naturalWidgetPalette(inheritedMask: inheritedPaletteResolveMask);
4625 QPalette resolvedPalette = data.pal.resolve(other: naturalPalette);
4626 setPalette_helper(resolvedPalette);
4627}
4628
4629void QWidgetPrivate::setPalette_helper(const QPalette &palette)
4630{
4631 Q_Q(QWidget);
4632 if (data.pal == palette && data.pal.resolveMask() == palette.resolveMask())
4633 return;
4634 data.pal = palette;
4635 updateSystemBackground();
4636 propagatePaletteChange();
4637 updateIsOpaque();
4638 q->update();
4639 updateIsOpaque();
4640}
4641
4642void QWidgetPrivate::updateSystemBackground()
4643{
4644}
4645
4646/*!
4647 \property QWidget::font
4648 \brief the font currently set for the widget
4649
4650 This property describes the widget's requested font. The font is used by
4651 the widget's style when rendering standard components, and is available as
4652 a means to ensure that custom widgets can maintain consistency with the
4653 native platform's look and feel. It's common that different platforms, or
4654 different styles, define different fonts for an application.
4655
4656 When you assign a new font to a widget, the properties from this font are
4657 combined with the widget's default font to form the widget's final
4658 font. You can call fontInfo() to get a copy of the widget's final
4659 font. The final font is also used to initialize QPainter's font.
4660
4661 The default depends on the system environment. QApplication maintains a
4662 system/theme font which serves as a default for all widgets. There may
4663 also be special font defaults for certain types of widgets. You can also
4664 define default fonts for widgets yourself by passing a custom font and the
4665 name of a widget to QApplication::setFont(). Finally, the font is matched
4666 against Qt's font database to find the best match.
4667
4668 QWidget propagates explicit font properties from parent to child. If you
4669 change a specific property on a font and assign that font to a widget,
4670 that property will propagate to all the widget's children, overriding any
4671 system defaults for that property. Note that fonts by default don't
4672 propagate to windows (see isWindow()) unless the Qt::WA_WindowPropagation
4673 attribute is enabled.
4674
4675 QWidget's font propagation is similar to its palette propagation.
4676
4677 The current style, which is used to render the content of all standard Qt
4678 widgets, is free to choose to use the widget font, or in some cases, to
4679 ignore it (partially, or completely). In particular, certain styles like
4680 GTK style, Mac style, and Windows Vista style, apply special
4681 modifications to the widget font to match the platform's native look and
4682 feel. Because of this, assigning properties to a widget's font is not
4683 guaranteed to change the appearance of the widget. Instead, you may choose
4684 to apply a \l styleSheet.
4685
4686 \note If \l{Qt Style Sheets} are used on the same widget as setFont(),
4687 style sheets will take precedence if the settings conflict.
4688
4689 \sa fontInfo(), fontMetrics()
4690*/
4691
4692void QWidget::setFont(const QFont &font)
4693{
4694 Q_D(QWidget);
4695
4696#ifndef QT_NO_STYLE_STYLESHEET
4697 const QStyleSheetStyle* style;
4698 if (d->extra && (style = qt_styleSheet(style: d->extra->style)))
4699 style->saveWidgetFont(w: this, font);
4700#endif
4701
4702 setAttribute(Qt::WA_SetFont, on: font.resolveMask() != 0);
4703
4704 // Determine which font is inherited from this widget's ancestors and
4705 // QApplication::font, resolve this against \a font (attributes from the
4706 // inherited font are copied over). Then propagate this font to this
4707 // widget's children.
4708 QFont naturalFont = d->naturalWidgetFont(inheritedMask: d->inheritedFontResolveMask);
4709 QFont resolvedFont = font.resolve(naturalFont);
4710 d->setFont_helper(resolvedFont);
4711}
4712
4713/*
4714 \internal
4715
4716 Returns the font that the widget \a w inherits from its ancestors and
4717 QApplication::font. \a inheritedMask is the combination of the widget's
4718 ancestors font request masks (i.e., which attributes from the parent
4719 widget's font are implicitly imposed on this widget by the user). Note
4720 that this font does not take into account the font set on \a w itself.
4721
4722 ### Stylesheet has a different font propagation mechanism. When a stylesheet
4723 is applied, fonts are not propagated anymore
4724*/
4725QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
4726{
4727 Q_Q(const QWidget);
4728
4729 const bool useStyleSheetPropagationInWidgetStyles =
4730 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4731
4732 QFont naturalFont = QApplication::font(q);
4733 if ((!q->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles)
4734 && (!q->isWindow() || q->testAttribute(attribute: Qt::WA_WindowPropagation)
4735#if QT_CONFIG(graphicsview)
4736 || (extra && extra->proxyWidget)
4737#endif // QT_CONFIG(graphicsview)
4738 )) {
4739 if (QWidget *p = q->parentWidget()) {
4740 if (!p->testAttribute(attribute: Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) {
4741 if (!naturalFont.isCopyOf(QApplication::font())) {
4742 if (inheritedMask != 0) {
4743 QFont inheritedFont = p->font();
4744 inheritedFont.setResolveMask(inheritedMask);
4745 naturalFont = inheritedFont.resolve(naturalFont);
4746 } // else nothing to do (naturalFont = naturalFont)
4747 } else {
4748 naturalFont = p->font();
4749 }
4750 }
4751 }
4752#if QT_CONFIG(graphicsview)
4753 else if (extra && extra->proxyWidget) {
4754 if (inheritedMask != 0) {
4755 QFont inheritedFont = extra->proxyWidget->font();
4756 inheritedFont.setResolveMask(inheritedMask);
4757 naturalFont = inheritedFont.resolve(naturalFont);
4758 } // else nothing to do (naturalFont = naturalFont)
4759 }
4760#endif // QT_CONFIG(graphicsview)
4761 }
4762 naturalFont.setResolveMask(0);
4763 return naturalFont;
4764}
4765
4766/*!
4767 \internal
4768
4769 Returns a font suitable for inheritance, where only locally set attributes are considered resolved.
4770*/
4771QFont QWidgetPrivate::localFont() const
4772{
4773 QFont localfont = data.fnt;
4774 localfont.setResolveMask(directFontResolveMask);
4775 return localfont;
4776}
4777
4778/*!
4779 \internal
4780
4781 Determine which font is implicitly imposed on this widget by its ancestors
4782 and QApplication::font, resolve this against its own font (attributes from
4783 the implicit font are copied over). Then propagate this font to this
4784 widget's children.
4785*/
4786void QWidgetPrivate::resolveFont()
4787{
4788 QFont naturalFont = naturalWidgetFont(inheritedMask: inheritedFontResolveMask);
4789 QFont resolvedFont = localFont().resolve(naturalFont);
4790 setFont_helper(resolvedFont);
4791}
4792
4793/*!
4794 \internal
4795
4796 Assign \a font to this widget, and propagate it to all children, except
4797 style sheet widgets (handled differently) and windows that don't enable
4798 window propagation. \a implicitMask is the union of all ancestor widgets'
4799 font request masks, and determines which attributes from this widget's
4800 font should propagate.
4801*/
4802void QWidgetPrivate::updateFont(const QFont &font)
4803{
4804 Q_Q(QWidget);
4805#ifndef QT_NO_STYLE_STYLESHEET
4806 const QStyleSheetStyle* cssStyle;
4807 cssStyle = extra ? qt_styleSheet(style: extra->style) : nullptr;
4808 const bool useStyleSheetPropagationInWidgetStyles =
4809 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
4810#endif
4811
4812 data.fnt = QFont(font, q);
4813
4814 // Combine new mask with natural mask and propagate to children.
4815#if QT_CONFIG(graphicsview)
4816 if (!q->parentWidget() && extra && extra->proxyWidget) {
4817 QGraphicsProxyWidget *p = extra->proxyWidget;
4818 inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolveMask();
4819 } else
4820#endif // QT_CONFIG(graphicsview)
4821 if (q->isWindow() && !q->testAttribute(attribute: Qt::WA_WindowPropagation)) {
4822 inheritedFontResolveMask = 0;
4823 }
4824 uint newMask = data.fnt.resolveMask() | inheritedFontResolveMask;
4825 // Set the font as also having resolved inherited traits, so the result of reading QWidget::font()
4826 // isn't all weak information, but save the original mask to be able to let new changes on the
4827 // parent widget font propagate correctly.
4828 directFontResolveMask = data.fnt.resolveMask();
4829 data.fnt.setResolveMask(newMask);
4830
4831 for (int i = 0; i < children.size(); ++i) {
4832 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
4833 if (w) {
4834 if (0) {
4835#ifndef QT_NO_STYLE_STYLESHEET
4836 } else if (!useStyleSheetPropagationInWidgetStyles && w->testAttribute(attribute: Qt::WA_StyleSheet)) {
4837 // Style sheets follow a different font propagation scheme.
4838 if (cssStyle)
4839 cssStyle->updateStyleSheetFont(w);
4840#endif
4841 } else if ((!w->isWindow() || w->testAttribute(attribute: Qt::WA_WindowPropagation))) {
4842 // Propagate font changes.
4843 QWidgetPrivate *wd = w->d_func();
4844 wd->inheritedFontResolveMask = newMask;
4845 wd->resolveFont();
4846 }
4847 }
4848 }
4849
4850#ifndef QT_NO_STYLE_STYLESHEET
4851 if (!useStyleSheetPropagationInWidgetStyles && cssStyle) {
4852 cssStyle->updateStyleSheetFont(w: q);
4853 }
4854#endif
4855
4856 QEvent e(QEvent::FontChange);
4857 QCoreApplication::sendEvent(receiver: q, event: &e);
4858}
4859
4860void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
4861{
4862 Q_Q(QWidget);
4863
4864 if ( (direction == Qt::RightToLeft) == q->testAttribute(attribute: Qt::WA_RightToLeft))
4865 return;
4866 q->setAttribute(Qt::WA_RightToLeft, on: (direction == Qt::RightToLeft));
4867 if (!children.isEmpty()) {
4868 for (int i = 0; i < children.size(); ++i) {
4869 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
4870 if (w && !w->isWindow() && !w->testAttribute(attribute: Qt::WA_SetLayoutDirection))
4871 w->d_func()->setLayoutDirection_helper(direction);
4872 }
4873 }
4874 QEvent e(QEvent::LayoutDirectionChange);
4875 QCoreApplication::sendEvent(receiver: q, event: &e);
4876}
4877
4878void QWidgetPrivate::resolveLayoutDirection()
4879{
4880 Q_Q(const QWidget);
4881 if (!q->testAttribute(attribute: Qt::WA_SetLayoutDirection))
4882 setLayoutDirection_helper(q->isWindow() ? QGuiApplication::layoutDirection() : q->parentWidget()->layoutDirection());
4883}
4884
4885/*!
4886 \property QWidget::layoutDirection
4887
4888 \brief the layout direction for this widget.
4889
4890 \note This method no longer affects text layout direction since Qt 4.7.
4891
4892 By default, this property is set to Qt::LeftToRight.
4893
4894 When the layout direction is set on a widget, it will propagate to
4895 the widget's children, but not to a child that is a window and not
4896 to a child for which setLayoutDirection() has been explicitly
4897 called. Also, child widgets added \e after setLayoutDirection()
4898 has been called for the parent do not inherit the parent's layout
4899 direction.
4900
4901
4902 \sa QApplication::layoutDirection
4903*/
4904void QWidget::setLayoutDirection(Qt::LayoutDirection direction)
4905{
4906 Q_D(QWidget);
4907
4908 if (direction == Qt::LayoutDirectionAuto) {
4909 unsetLayoutDirection();
4910 return;
4911 }
4912
4913 setAttribute(Qt::WA_SetLayoutDirection);
4914 d->setLayoutDirection_helper(direction);
4915}
4916
4917Qt::LayoutDirection QWidget::layoutDirection() const
4918{
4919 return testAttribute(attribute: Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
4920}
4921
4922void QWidget::unsetLayoutDirection()
4923{
4924 Q_D(QWidget);
4925 setAttribute(Qt::WA_SetLayoutDirection, on: false);
4926 d->resolveLayoutDirection();
4927}
4928
4929/*!
4930 \fn QFontMetrics QWidget::fontMetrics() const
4931
4932 Returns the font metrics for the widget's current font.
4933 Equivalent to \c QFontMetrics(widget->font()).
4934
4935 \sa font(), fontInfo(), setFont()
4936*/
4937
4938/*!
4939 \fn QFontInfo QWidget::fontInfo() const
4940
4941 Returns the font info for the widget's current font.
4942 Equivalent to \c QFontInfo(widget->font()).
4943
4944 \sa font(), fontMetrics(), setFont()
4945*/
4946
4947
4948/*!
4949 \property QWidget::cursor
4950 \brief the cursor shape for this widget
4951
4952 The mouse cursor will assume this shape when it's over this
4953 widget. See the \l{Qt::CursorShape}{list of predefined cursor objects} for a range of useful shapes.
4954
4955 An editor widget might use an I-beam cursor:
4956 \snippet code/src_gui_kernel_qwidget.cpp 6
4957
4958 If no cursor has been set, or after a call to unsetCursor(), the
4959 parent's cursor is used.
4960
4961 By default, this property contains a cursor with the Qt::ArrowCursor
4962 shape.
4963
4964 Some underlying window implementations will reset the cursor if it
4965 leaves a widget even if the mouse is grabbed. If you want to have
4966 a cursor set for all widgets, even when outside the window, consider
4967 QGuiApplication::setOverrideCursor().
4968
4969 \sa QGuiApplication::setOverrideCursor()
4970*/
4971
4972#ifndef QT_NO_CURSOR
4973QCursor QWidget::cursor() const
4974{
4975 Q_D(const QWidget);
4976 if (testAttribute(attribute: Qt::WA_SetCursor))
4977 return (d->extra && d->extra->curs)
4978 ? *d->extra->curs
4979 : QCursor(Qt::ArrowCursor);
4980 if (isWindow() || !parentWidget())
4981 return QCursor(Qt::ArrowCursor);
4982 return parentWidget()->cursor();
4983}
4984
4985void QWidget::setCursor(const QCursor &cursor)
4986{
4987 Q_D(QWidget);
4988 if (cursor.shape() != Qt::ArrowCursor
4989 || (d->extra && d->extra->curs))
4990 {
4991 d->createExtra();
4992 d->extra->curs = std::make_unique<QCursor>(args: cursor);
4993 }
4994 setAttribute(Qt::WA_SetCursor);
4995 d->setCursor_sys(cursor);
4996
4997 QEvent event(QEvent::CursorChange);
4998 QCoreApplication::sendEvent(receiver: this, event: &event);
4999}
5000
5001void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
5002{
5003 Q_UNUSED(cursor);
5004 Q_Q(QWidget);
5005 qt_qpa_set_cursor(w: q, force: false);
5006}
5007
5008void QWidget::unsetCursor()
5009{
5010 Q_D(QWidget);
5011 if (d->extra)
5012 d->extra->curs.reset();
5013 if (!isWindow())
5014 setAttribute(Qt::WA_SetCursor, on: false);
5015 d->unsetCursor_sys();
5016
5017 QEvent event(QEvent::CursorChange);
5018 QCoreApplication::sendEvent(receiver: this, event: &event);
5019}
5020
5021void QWidgetPrivate::unsetCursor_sys()
5022{
5023 Q_Q(QWidget);
5024 qt_qpa_set_cursor(w: q, force: false);
5025}
5026
5027static inline void applyCursor(QWidget *w, const QCursor &c)
5028{
5029 if (QWindow *window = w->windowHandle())
5030 window->setCursor(c);
5031}
5032
5033static inline void unsetCursor(QWidget *w)
5034{
5035 if (QWindow *window = w->windowHandle())
5036 window->unsetCursor();
5037}
5038
5039void qt_qpa_set_cursor(QWidget *w, bool force)
5040{
5041 if (!w->testAttribute(attribute: Qt::WA_WState_Created))
5042 return;
5043
5044 static QPointer<QWidget> lastUnderMouse = nullptr;
5045 if (force) {
5046 lastUnderMouse = w;
5047 } else if (lastUnderMouse) {
5048 const WId lastWinId = lastUnderMouse->effectiveWinId();
5049 const WId winId = w->effectiveWinId();
5050 if (lastWinId && lastWinId == winId)
5051 w = lastUnderMouse;
5052 } else if (!w->internalWinId()) {
5053 return; // The mouse is not under this widget, and it's not native, so don't change it.
5054 }
5055
5056 while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
5057 && !w->testAttribute(attribute: Qt::WA_SetCursor))
5058 w = w->parentWidget();
5059
5060 QWidget *nativeParent = w;
5061 if (!w->internalWinId())
5062 nativeParent = w->nativeParentWidget();
5063 if (!nativeParent || !nativeParent->internalWinId())
5064 return;
5065
5066 if (w->isWindow() || w->testAttribute(attribute: Qt::WA_SetCursor)) {
5067 if (w->isEnabled())
5068 applyCursor(w: nativeParent, c: w->cursor());
5069 else
5070 // Enforce the windows behavior of clearing the cursor on
5071 // disabled widgets.
5072 unsetCursor(w: nativeParent);
5073 } else {
5074 unsetCursor(w: nativeParent);
5075 }
5076}
5077#endif
5078
5079/*!
5080 \enum QWidget::RenderFlag
5081
5082 This enum describes how to render the widget when calling QWidget::render().
5083
5084 \value DrawWindowBackground If you enable this option, the widget's background
5085 is rendered into the target even if autoFillBackground is not set. By default,
5086 this option is enabled.
5087
5088 \value DrawChildren If you enable this option, the widget's children
5089 are rendered recursively into the target. By default, this option is enabled.
5090
5091 \value IgnoreMask If you enable this option, the widget's QWidget::mask()
5092 is ignored when rendering into the target. By default, this option is disabled.
5093
5094 \since 4.3
5095*/
5096
5097/*!
5098 \since 4.3
5099
5100 Renders the \a sourceRegion of this widget into the \a target
5101 using \a renderFlags to determine how to render. Rendering
5102 starts at \a targetOffset in the \a target. For example:
5103
5104 \snippet code/src_gui_kernel_qwidget.cpp 7
5105
5106 If \a sourceRegion is a null region, this function will use QWidget::rect() as
5107 the region, i.e. the entire widget.
5108
5109 Ensure that you call QPainter::end() for the \a target device's
5110 active painter (if any) before rendering. For example:
5111
5112 \snippet code/src_gui_kernel_qwidget.cpp 8
5113
5114 \note To obtain the contents of a QOpenGLWidget, use QOpenGLWidget::grabFramebuffer()
5115 instead.
5116*/
5117void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
5118 const QRegion &sourceRegion, RenderFlags renderFlags)
5119{
5120 QPainter p(target);
5121 render(painter: &p, targetOffset, sourceRegion, renderFlags);
5122}
5123
5124/*!
5125 \overload
5126
5127 Renders the widget into the \a painter's QPainter::device().
5128
5129 Transformations and settings applied to the \a painter will be used
5130 when rendering.
5131
5132 \note The \a painter must be active. On \macos the widget will be
5133 rendered into a QPixmap and then drawn by the \a painter.
5134
5135 \sa QPainter::device()
5136*/
5137void QWidget::render(QPainter *painter, const QPoint &targetOffset,
5138 const QRegion &sourceRegion, RenderFlags renderFlags)
5139{
5140 if (Q_UNLIKELY(!painter)) {
5141 qWarning(msg: "QWidget::render: Null pointer to painter");
5142 return;
5143 }
5144
5145 if (Q_UNLIKELY(!painter->isActive())) {
5146 qWarning(msg: "QWidget::render: Cannot render with an inactive painter");
5147 return;
5148 }
5149
5150 const qreal opacity = painter->opacity();
5151 if (qFuzzyIsNull(d: opacity))
5152 return; // Fully transparent.
5153
5154 Q_D(QWidget);
5155 const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
5156 const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(region: sourceRegion, renderFlags)
5157 : sourceRegion;
5158 if (toBePainted.isEmpty())
5159 return;
5160
5161 if (!d->extra)
5162 d->createExtra();
5163 d->extra->inRenderWithPainter = true;
5164
5165 QPaintEngine *engine = painter->paintEngine();
5166 Q_ASSERT(engine);
5167 QPaintEnginePrivate *enginePriv = engine->d_func();
5168 Q_ASSERT(enginePriv);
5169 QPaintDevice *target = engine->paintDevice();
5170 Q_ASSERT(target);
5171
5172 // Render via a pixmap when dealing with non-opaque painters or printers.
5173 if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
5174 d->render_helper(painter, targetOffset, sourceRegion: toBePainted, renderFlags);
5175 d->extra->inRenderWithPainter = inRenderWithPainter;
5176 return;
5177 }
5178
5179 // Set new shared painter.
5180 QPainter *oldPainter = d->sharedPainter();
5181 d->setSharedPainter(painter);
5182
5183 // Save current system clip, viewport and transform,
5184 const QTransform oldTransform = enginePriv->systemTransform;
5185 const QRegion oldSystemClip = enginePriv->systemClip;
5186 const QRegion oldBaseClip = enginePriv->baseSystemClip;
5187 const QRegion oldSystemViewport = enginePriv->systemViewport;
5188 const Qt::LayoutDirection oldLayoutDirection = painter->layoutDirection();
5189
5190 // This ensures that all painting triggered by render() is clipped to the current engine clip.
5191 if (painter->hasClipping()) {
5192 const QRegion painterClip = painter->deviceTransform().map(r: painter->clipRegion());
5193 enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip);
5194 } else {
5195 enginePriv->setSystemViewport(oldSystemClip);
5196 }
5197 painter->setLayoutDirection(layoutDirection());
5198
5199 d->render(target, targetOffset, sourceRegion: toBePainted, renderFlags);
5200
5201 // Restore system clip, viewport and transform.
5202 enginePriv->baseSystemClip = oldBaseClip;
5203 enginePriv->setSystemTransformAndViewport(xform: oldTransform, region: oldSystemViewport);
5204 enginePriv->systemStateChanged();
5205 painter->setLayoutDirection(oldLayoutDirection);
5206
5207 // Restore shared painter.
5208 d->setSharedPainter(oldPainter);
5209
5210 d->extra->inRenderWithPainter = inRenderWithPainter;
5211}
5212
5213static void sendResizeEvents(QWidget *target)
5214{
5215 QResizeEvent e(target->size(), QSize());
5216 QCoreApplication::sendEvent(receiver: target, event: &e);
5217
5218 const QObjectList children = target->children();
5219 for (int i = 0; i < children.size(); ++i) {
5220 if (!children.at(i)->isWidgetType())
5221 continue;
5222 QWidget *child = static_cast<QWidget*>(children.at(i));
5223 if (!child->isWindow() && child->testAttribute(attribute: Qt::WA_PendingResizeEvent))
5224 sendResizeEvents(target: child);
5225 }
5226}
5227
5228/*!
5229 \since 5.0
5230
5231 Renders the widget into a pixmap restricted by the
5232 given \a rectangle. If the widget has any children, then
5233 they are also painted in the appropriate positions.
5234
5235 If a rectangle with an invalid size is specified (the default),
5236 the entire widget is painted.
5237
5238 \sa render(), QPixmap
5239*/
5240QPixmap QWidget::grab(const QRect &rectangle)
5241{
5242 Q_D(QWidget);
5243 if (testAttribute(attribute: Qt::WA_PendingResizeEvent) || !testAttribute(attribute: Qt::WA_WState_Created))
5244 sendResizeEvents(target: this);
5245
5246 const QWidget::RenderFlags renderFlags = QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask;
5247
5248 const bool oldDirtyOpaqueChildren = d->dirtyOpaqueChildren;
5249 QRect r(rectangle);
5250 if (r.width() < 0 || r.height() < 0) {
5251 // For grabbing widgets that haven't been shown yet,
5252 // we trigger the layouting mechanism to determine the widget's size.
5253 r = d->prepareToRender(region: QRegion(), renderFlags).boundingRect();
5254 r.setTopLeft(rectangle.topLeft());
5255 }
5256
5257 if (!r.intersects(r: rect()))
5258 return QPixmap();
5259
5260 const qreal dpr = devicePixelRatio();
5261 QPixmap res((QSizeF(r.size()) * dpr).toSize());
5262 res.setDevicePixelRatio(dpr);
5263 if (!d->isOpaque)
5264 res.fill(fillColor: Qt::transparent);
5265 d->render(target: &res, targetOffset: QPoint(), sourceRegion: QRegion(r), renderFlags);
5266
5267 d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
5268 return res;
5269}
5270
5271/*!
5272 \brief The graphicsEffect function returns a pointer to the
5273 widget's graphics effect.
5274
5275 If the widget has no graphics effect, \nullptr is returned.
5276
5277 \since 4.6
5278
5279 \sa setGraphicsEffect()
5280*/
5281#if QT_CONFIG(graphicseffect)
5282QGraphicsEffect *QWidget::graphicsEffect() const
5283{
5284 Q_D(const QWidget);
5285 return d->graphicsEffect;
5286}
5287#endif // QT_CONFIG(graphicseffect)
5288
5289/*!
5290
5291 \brief The setGraphicsEffect function is for setting the widget's graphics effect.
5292
5293 Sets \a effect as the widget's effect. If there already is an effect installed
5294 on this widget, QWidget will delete the existing effect before installing
5295 the new \a effect.
5296
5297 If \a effect is the installed effect on a different widget, setGraphicsEffect() will remove
5298 the effect from the widget and install it on this widget.
5299
5300 QWidget takes ownership of \a effect.
5301
5302 \note This function will apply the effect on itself and all its children.
5303
5304 \note Graphics effects are not supported for OpenGL-based widgets, such as QGLWidget,
5305 QOpenGLWidget and QQuickWidget.
5306
5307 \since 4.6
5308
5309 \sa graphicsEffect()
5310*/
5311#if QT_CONFIG(graphicseffect)
5312void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
5313{
5314 Q_D(QWidget);
5315 if (d->graphicsEffect == effect)
5316 return;
5317
5318 if (d->graphicsEffect) {
5319 d->invalidateBackingStore(rect());
5320 delete d->graphicsEffect;
5321 d->graphicsEffect = nullptr;
5322 }
5323
5324 if (effect) {
5325 // Set new effect.
5326 QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
5327 QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
5328 d->graphicsEffect = effect;
5329 effect->d_func()->setGraphicsEffectSource(source);
5330 update();
5331 }
5332
5333 d->updateIsOpaque();
5334}
5335#endif // QT_CONFIG(graphicseffect)
5336
5337bool QWidgetPrivate::isAboutToShow() const
5338{
5339 if (data.in_show)
5340 return true;
5341
5342 Q_Q(const QWidget);
5343 if (q->isHidden())
5344 return false;
5345
5346 // The widget will be shown if any of its ancestors are about to show.
5347 QWidget *parent = q->parentWidget();
5348 return parent ? parent->d_func()->isAboutToShow() : false;
5349}
5350
5351QRegion QWidgetPrivate::prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags)
5352{
5353 Q_Q(QWidget);
5354 const bool isVisible = q->isVisible();
5355
5356 // Make sure the widget is laid out correctly.
5357 if (!isVisible && !isAboutToShow()) {
5358 QWidget *topLevel = q->window();
5359 (void)topLevel->d_func()->topData(); // Make sure we at least have top-data.
5360 topLevel->ensurePolished();
5361
5362 // Invalidate the layout of hidden ancestors (incl. myself) and pretend
5363 // they're not explicitly hidden.
5364 QWidget *widget = q;
5365 QWidgetList hiddenWidgets;
5366 while (widget) {
5367 if (widget->isHidden()) {
5368 widget->setAttribute(Qt::WA_WState_Hidden, on: false);
5369 hiddenWidgets.append(t: widget);
5370 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5371 widget->d_func()->updateGeometry_helper(forceUpdate: true);
5372 }
5373 widget = widget->parentWidget();
5374 }
5375
5376 // Activate top-level layout.
5377 if (topLevel->d_func()->layout)
5378 topLevel->d_func()->layout->activate();
5379
5380 // Adjust size if necessary.
5381 QTLWExtra *topLevelExtra = topLevel->d_func()->maybeTopData();
5382 if (topLevelExtra && !topLevelExtra->sizeAdjusted
5383 && !topLevel->testAttribute(attribute: Qt::WA_Resized)) {
5384 topLevel->adjustSize();
5385 topLevel->setAttribute(Qt::WA_Resized, on: false);
5386 }
5387
5388 // Activate child layouts.
5389 topLevel->d_func()->activateChildLayoutsRecursively();
5390
5391 // We're not cheating with WA_WState_Hidden anymore.
5392 for (int i = 0; i < hiddenWidgets.size(); ++i) {
5393 QWidget *widget = hiddenWidgets.at(i);
5394 widget->setAttribute(Qt::WA_WState_Hidden);
5395 if (!widget->isWindow() && widget->parentWidget()->d_func()->layout)
5396 widget->parentWidget()->d_func()->layout->invalidate();
5397 }
5398 } else if (isVisible) {
5399 q->window()->d_func()->sendPendingMoveAndResizeEvents(recursive: true, disableUpdates: true);
5400 }
5401
5402 // Calculate the region to be painted.
5403 QRegion toBePainted = !region.isEmpty() ? region : QRegion(q->rect());
5404 if (!(renderFlags & QWidget::IgnoreMask) && extra && extra->hasMask)
5405 toBePainted &= extra->mask;
5406 return toBePainted;
5407}
5408
5409void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &toBePainted,
5410 QWidget::RenderFlags renderFlags)
5411{
5412 Q_ASSERT(painter);
5413 Q_ASSERT(!toBePainted.isEmpty());
5414
5415 Q_Q(QWidget);
5416 const QTransform originalTransform = painter->worldTransform();
5417 const bool useDeviceCoordinates = originalTransform.isScaling();
5418 if (!useDeviceCoordinates) {
5419 // Render via a pixmap.
5420 const QRect rect = toBePainted.boundingRect();
5421 const QSize size = rect.size();
5422 if (size.isNull())
5423 return;
5424
5425 const qreal pixmapDevicePixelRatio = painter->device()->devicePixelRatio();
5426 QPixmap pixmap(size * pixmapDevicePixelRatio);
5427 pixmap.setDevicePixelRatio(pixmapDevicePixelRatio);
5428
5429 if (!(renderFlags & QWidget::DrawWindowBackground) || !isOpaque)
5430 pixmap.fill(fillColor: Qt::transparent);
5431 q->render(target: &pixmap, targetOffset: QPoint(), sourceRegion: toBePainted, renderFlags);
5432
5433 const bool restore = !(painter->renderHints() & QPainter::SmoothPixmapTransform);
5434 painter->setRenderHints(hints: QPainter::SmoothPixmapTransform, on: true);
5435
5436 painter->drawPixmap(p: targetOffset, pm: pixmap);
5437
5438 if (restore)
5439 painter->setRenderHints(hints: QPainter::SmoothPixmapTransform, on: false);
5440
5441 } else {
5442 // Render via a pixmap in device coordinates (to avoid pixmap scaling).
5443 QTransform transform = originalTransform;
5444 transform.translate(dx: targetOffset.x(), dy: targetOffset.y());
5445
5446 QPaintDevice *device = painter->device();
5447 Q_ASSERT(device);
5448
5449 // Calculate device rect.
5450 const QRectF rect(toBePainted.boundingRect());
5451 QRect deviceRect = transform.mapRect(QRectF(0, 0, rect.width(), rect.height())).toAlignedRect();
5452 deviceRect &= QRect(0, 0, device->width(), device->height());
5453
5454 QPixmap pixmap(deviceRect.size());
5455 pixmap.fill(fillColor: Qt::transparent);
5456
5457 // Create a pixmap device coordinate painter.
5458 QPainter pixmapPainter(&pixmap);
5459 pixmapPainter.setRenderHints(hints: painter->renderHints());
5460 transform *= QTransform::fromTranslate(dx: -deviceRect.x(), dy: -deviceRect.y());
5461 pixmapPainter.setTransform(transform);
5462
5463 q->render(painter: &pixmapPainter, targetOffset: QPoint(), sourceRegion: toBePainted, renderFlags);
5464 pixmapPainter.end();
5465
5466 // And then draw the pixmap.
5467 painter->setTransform(transform: QTransform());
5468 painter->drawPixmap(p: deviceRect.topLeft(), pm: pixmap);
5469 painter->setTransform(transform: originalTransform);
5470 }
5471}
5472
5473void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
5474 QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5475{
5476 if (rgn.isEmpty())
5477 return;
5478
5479 Q_Q(QWidget);
5480
5481 qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset
5482 << "into paint device" << pdev << "with" << flags;
5483
5484 const bool asRoot = flags & DrawAsRoot;
5485 bool onScreen = shouldPaintOnScreen();
5486
5487#if QT_CONFIG(graphicseffect)
5488 if (graphicsEffect && graphicsEffect->isEnabled()) {
5489 QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
5490 QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
5491 (source->d_func());
5492 if (!sourced->context) {
5493 const QRegion effectRgn((flags & UseEffectRegionBounds) ? rgn.boundingRect() : rgn);
5494 QWidgetPaintContext context(pdev, effectRgn, offset, flags, sharedPainter, repaintManager);
5495 sourced->context = &context;
5496 if (!sharedPainter) {
5497 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: pdev->devicePixelRatio(), region: effectRgn.translated(p: offset));
5498 QPainter p(pdev);
5499 p.translate(offset);
5500 context.painter = &p;
5501 graphicsEffect->draw(painter: &p);
5502 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: 1, region: QRegion());
5503 } else {
5504 context.painter = sharedPainter;
5505 if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
5506 sourced->invalidateCache();
5507 sourced->lastEffectTransform = sharedPainter->worldTransform();
5508 }
5509 sharedPainter->save();
5510 sharedPainter->translate(offset);
5511 setSystemClip(paintEngine: sharedPainter->paintEngine(), devicePixelRatio: sharedPainter->device()->devicePixelRatio(), region: effectRgn.translated(p: offset));
5512 graphicsEffect->draw(painter: sharedPainter);
5513 setSystemClip(paintEngine: sharedPainter->paintEngine(), devicePixelRatio: 1, region: QRegion());
5514 sharedPainter->restore();
5515 }
5516 sourced->context = nullptr;
5517
5518 if (repaintManager)
5519 repaintManager->markNeedsFlush(widget: q, region: effectRgn, topLevelOffset: offset);
5520
5521 return;
5522 }
5523 }
5524#endif // QT_CONFIG(graphicseffect)
5525 flags = flags & ~UseEffectRegionBounds;
5526
5527 const bool alsoOnScreen = flags & DrawPaintOnScreen;
5528 const bool recursive = flags & DrawRecursive;
5529 const bool alsoInvisible = flags & DrawInvisible;
5530
5531 Q_ASSERT(sharedPainter ? sharedPainter->isActive() : true);
5532
5533 QRegion toBePainted(rgn);
5534 if (asRoot && !alsoInvisible)
5535 toBePainted &= clipRect(); //(rgn & visibleRegion());
5536 if (!(flags & DontSubtractOpaqueChildren))
5537 subtractOpaqueChildren(source&: toBePainted, clipRect: q->rect());
5538
5539 if (!toBePainted.isEmpty()) {
5540 if (!onScreen || alsoOnScreen) {
5541 //update the "in paint event" flag
5542 if (Q_UNLIKELY(q->testAttribute(Qt::WA_WState_InPaintEvent)))
5543 qWarning(msg: "QWidget::repaint: Recursive repaint detected");
5544 q->setAttribute(Qt::WA_WState_InPaintEvent);
5545
5546 //clip away the new area
5547 QPaintEngine *paintEngine = pdev->paintEngine();
5548 if (paintEngine) {
5549 setRedirected(replacement: pdev, offset: -offset);
5550
5551 if (sharedPainter)
5552 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: pdev->devicePixelRatio(), region: toBePainted);
5553 else
5554 paintEngine->d_func()->systemRect = q->data->crect;
5555
5556 //paint the background
5557 if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(attribute: Qt::WA_StyledBackground))
5558 && !q->testAttribute(attribute: Qt::WA_OpaquePaintEvent) && !q->testAttribute(attribute: Qt::WA_NoSystemBackground)) {
5559 beginBackingStorePainting();
5560 QPainter p(q);
5561 p.setRenderHint(hint: QPainter::SmoothPixmapTransform);
5562 paintBackground(painter: &p, rgn: toBePainted, flags: (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags());
5563 endBackingStorePainting();
5564 }
5565
5566 if (!sharedPainter)
5567 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: pdev->devicePixelRatio(), region: toBePainted.translated(p: offset));
5568
5569 if (!onScreen && !asRoot && !isOpaque && q->testAttribute(attribute: Qt::WA_TintedBackground)) {
5570 beginBackingStorePainting();
5571 QPainter p(q);
5572 QColor tint = q->palette().window().color();
5573 tint.setAlphaF(.6f);
5574 p.fillRect(toBePainted.boundingRect(), color: tint);
5575 endBackingStorePainting();
5576 }
5577 }
5578
5579#if 0
5580 qDebug() << "painting" << q << "opaque ==" << isOpaque();
5581 qDebug() << "clipping to" << toBePainted << "location == " << offset
5582 << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
5583#endif
5584
5585 bool skipPaintEvent = false;
5586 if (renderToTexture) {
5587 // This widget renders into a texture which is composed later. We just need to
5588 // punch a hole in the backingstore, so the texture will be visible.
5589 beginBackingStorePainting();
5590 if (!q->testAttribute(attribute: Qt::WA_AlwaysStackOnTop) && repaintManager) {
5591 QPainter p(q);
5592 p.setCompositionMode(QPainter::CompositionMode_Source);
5593 p.fillRect(r: q->rect(), c: Qt::transparent);
5594 } else if (!repaintManager) {
5595 // We are not drawing to a backingstore: fall back to QImage
5596 QImage img = grabFramebuffer();
5597 // grabFramebuffer() always sets the format to RGB32
5598 // regardless of whether it is transparent or not.
5599 if (img.format() == QImage::Format_RGB32)
5600 img.reinterpretAsFormat(f: QImage::Format_ARGB32_Premultiplied);
5601 QPainter p(q);
5602 p.drawImage(r: q->rect(), image: img);
5603 skipPaintEvent = true;
5604 }
5605 endBackingStorePainting();
5606 if (renderToTextureReallyDirty)
5607 renderToTextureReallyDirty = 0;
5608 else
5609 skipPaintEvent = true;
5610 }
5611
5612 if (!skipPaintEvent) {
5613 //actually send the paint event
5614 sendPaintEvent(toBePainted);
5615 }
5616
5617 if (repaintManager)
5618 repaintManager->markNeedsFlush(widget: q, region: toBePainted, topLevelOffset: offset);
5619
5620 //restore
5621 if (paintEngine) {
5622 restoreRedirected();
5623 if (!sharedPainter)
5624 paintEngine->d_func()->systemRect = QRect();
5625 else
5626 paintEngine->d_func()->currentClipDevice = nullptr;
5627
5628 setSystemClip(paintEngine: pdev->paintEngine(), devicePixelRatio: 1, region: QRegion());
5629 }
5630 q->setAttribute(Qt::WA_WState_InPaintEvent, on: false);
5631 if (Q_UNLIKELY(q->paintingActive()))
5632 qWarning(msg: "QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
5633
5634 if (paintEngine && paintEngine->autoDestruct()) {
5635 delete paintEngine;
5636 }
5637 } else if (q->isWindow()) {
5638 QPaintEngine *engine = pdev->paintEngine();
5639 if (engine) {
5640 QPainter p(pdev);
5641 p.setClipRegion(toBePainted);
5642 const QBrush bg = q->palette().brush(cr: QPalette::Window);
5643 if (bg.style() == Qt::TexturePattern)
5644 p.drawTiledPixmap(rect: q->rect(), pm: bg.texture());
5645 else
5646 p.fillRect(q->rect(), bg);
5647
5648 if (engine->autoDestruct())
5649 delete engine;
5650 }
5651 }
5652 }
5653
5654 if (recursive && !children.isEmpty()) {
5655 paintSiblingsRecursive(pdev, children, index: children.size() - 1, rgn, offset, flags: flags & ~DrawAsRoot,
5656 sharedPainter, repaintManager);
5657 }
5658}
5659
5660void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
5661{
5662 Q_Q(QWidget);
5663 QPaintEvent e(toBePainted);
5664 QCoreApplication::sendSpontaneousEvent(receiver: q, event: &e);
5665
5666 if (renderToTexture)
5667 resolveSamples();
5668}
5669
5670void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
5671 const QRegion &sourceRegion, QWidget::RenderFlags renderFlags)
5672{
5673 if (Q_UNLIKELY(!target)) {
5674 qWarning(msg: "QWidget::render: null pointer to paint device");
5675 return;
5676 }
5677
5678 const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
5679 QRegion paintRegion = !inRenderWithPainter
5680 ? prepareToRender(region: sourceRegion, renderFlags)
5681 : sourceRegion;
5682 if (paintRegion.isEmpty())
5683 return;
5684
5685 QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : nullptr;
5686
5687 // Use the target's shared painter if set (typically set when doing
5688 // "other->render(widget);" in the widget's paintEvent.
5689 if (target->devType() == QInternal::Widget) {
5690 QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
5691 if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
5692 QPainter *targetPainter = targetPrivate->sharedPainter();
5693 if (targetPainter && targetPainter->isActive())
5694 setSharedPainter(targetPainter);
5695 }
5696 }
5697
5698 // Use the target's redirected device if set and adjust offset and paint
5699 // region accordingly. This is typically the case when people call render
5700 // from the paintEvent.
5701 QPoint offset = targetOffset;
5702 offset -= paintRegion.boundingRect().topLeft();
5703 QPoint redirectionOffset;
5704 QPaintDevice *redirected = nullptr;
5705
5706 if (target->devType() == QInternal::Widget)
5707 redirected = static_cast<QWidget *>(target)->d_func()->redirected(offset: &redirectionOffset);
5708
5709 if (redirected) {
5710 target = redirected;
5711 offset -= redirectionOffset;
5712 }
5713
5714 if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
5715 if (QPaintEngine *targetEngine = target->paintEngine()) {
5716 const QRegion targetSystemClip = targetEngine->systemClip();
5717 if (!targetSystemClip.isEmpty())
5718 paintRegion &= targetSystemClip.translated(p: -offset);
5719 }
5720 }
5721
5722 // Set backingstore flags.
5723 DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible;
5724 if (renderFlags & QWidget::DrawWindowBackground)
5725 flags |= DrawAsRoot;
5726
5727 if (renderFlags & QWidget::DrawChildren)
5728 flags |= DrawRecursive;
5729 else
5730 flags |= DontSubtractOpaqueChildren;
5731
5732 flags |= DontSetCompositionMode;
5733
5734 // Render via backingstore.
5735 drawWidget(pdev: target, rgn: paintRegion, offset, flags, sharedPainter: sharedPainter());
5736
5737 // Restore shared painter.
5738 if (oldSharedPainter)
5739 setSharedPainter(oldSharedPainter);
5740}
5741
5742void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
5743 const QPoint &offset, DrawWidgetFlags flags
5744 , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
5745{
5746 QWidget *w = nullptr;
5747 QRect boundingRect;
5748 bool dirtyBoundingRect = true;
5749 const bool exludeOpaqueChildren = (flags & DontDrawOpaqueChildren);
5750 const bool excludeNativeChildren = (flags & DontDrawNativeChildren);
5751
5752 do {
5753 QWidget *x = qobject_cast<QWidget*>(o: siblings.at(i: index));
5754 if (x && !(exludeOpaqueChildren && x->d_func()->isOpaque) && !x->isHidden() && !x->isWindow()
5755 && !(excludeNativeChildren && x->internalWinId())) {
5756 if (dirtyBoundingRect) {
5757 boundingRect = rgn.boundingRect();
5758 dirtyBoundingRect = false;
5759 }
5760
5761 if (qRectIntersects(r1: boundingRect, r2: x->d_func()->effectiveRectFor(rect: x->data->crect))) {
5762 w = x;
5763 break;
5764 }
5765 }
5766 --index;
5767 } while (index >= 0);
5768
5769 if (!w)
5770 return;
5771
5772 QWidgetPrivate *wd = w->d_func();
5773 const QPoint widgetPos(w->data->crect.topLeft());
5774 const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect;
5775 if (index > 0) {
5776 QRegion wr(rgn);
5777 if (wd->isOpaque)
5778 wr -= hasMask ? wd->extra->mask.translated(p: widgetPos) : w->data->crect;
5779 paintSiblingsRecursive(pdev, siblings, index: --index, rgn: wr, offset, flags,
5780 sharedPainter, repaintManager);
5781 }
5782
5783 if (w->updatesEnabled()
5784#if QT_CONFIG(graphicsview)
5785 && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)
5786#endif // QT_CONFIG(graphicsview)
5787 ) {
5788 QRegion wRegion(rgn);
5789 wRegion &= wd->effectiveRectFor(rect: w->data->crect);
5790 wRegion.translate(p: -widgetPos);
5791 if (hasMask)
5792 wRegion &= wd->extra->mask;
5793 wd->drawWidget(pdev, rgn: wRegion, offset: offset + widgetPos, flags, sharedPainter, repaintManager);
5794 }
5795}
5796
5797#if QT_CONFIG(graphicseffect)
5798QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
5799{
5800 if (system != Qt::DeviceCoordinates)
5801 return m_widget->rect();
5802
5803 if (Q_UNLIKELY(!context)) {
5804 // Device coordinates without context not yet supported.
5805 qWarning(msg: "QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
5806 return QRectF();
5807 }
5808
5809 return context->painter->worldTransform().mapRect(m_widget->rect());
5810}
5811
5812void QWidgetEffectSourcePrivate::draw(QPainter *painter)
5813{
5814 if (!context || context->painter != painter) {
5815 m_widget->render(painter);
5816 return;
5817 }
5818
5819 // The region saved in the context is neither clipped to the rect
5820 // nor the mask, so we have to clip it here before calling drawWidget.
5821 QRegion toBePainted = context->rgn;
5822 toBePainted &= m_widget->rect();
5823 QWidgetPrivate *wd = qt_widget_private(widget: m_widget);
5824 if (wd->extra && wd->extra->hasMask)
5825 toBePainted &= wd->extra->mask;
5826
5827 wd->drawWidget(pdev: context->pdev, rgn: toBePainted, offset: context->offset, flags: context->flags,
5828 sharedPainter: context->sharedPainter, repaintManager: context->repaintManager);
5829}
5830
5831QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
5832 QGraphicsEffect::PixmapPadMode mode) const
5833{
5834 const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
5835 if (Q_UNLIKELY(!context && deviceCoordinates)) {
5836 // Device coordinates without context not yet supported.
5837 qWarning(msg: "QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
5838 return QPixmap();
5839 }
5840
5841 QPoint pixmapOffset;
5842 QRectF sourceRect = m_widget->rect();
5843
5844 if (deviceCoordinates) {
5845 const QTransform &painterTransform = context->painter->worldTransform();
5846 sourceRect = painterTransform.mapRect(sourceRect);
5847 pixmapOffset = painterTransform.map(p: pixmapOffset);
5848 }
5849
5850 QRect effectRect;
5851
5852 if (mode == QGraphicsEffect::PadToEffectiveBoundingRect)
5853 effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
5854 else if (mode == QGraphicsEffect::PadToTransparentBorder)
5855 effectRect = sourceRect.adjusted(xp1: -1, yp1: -1, xp2: 1, yp2: 1).toAlignedRect();
5856 else
5857 effectRect = sourceRect.toAlignedRect();
5858
5859 if (offset)
5860 *offset = effectRect.topLeft();
5861
5862 pixmapOffset -= effectRect.topLeft();
5863
5864 qreal dpr(1.0);
5865 if (const auto *paintDevice = context->painter->device())
5866 dpr = paintDevice->devicePixelRatio();
5867 else
5868 qWarning(msg: "QWidgetEffectSourcePrivate::pixmap: Painter not active");
5869 QPixmap pixmap(effectRect.size() * dpr);
5870 pixmap.setDevicePixelRatio(dpr);
5871
5872 pixmap.fill(fillColor: Qt::transparent);
5873 m_widget->render(target: &pixmap, targetOffset: pixmapOffset, sourceRegion: QRegion(), renderFlags: QWidget::DrawChildren);
5874 return pixmap;
5875}
5876#endif // QT_CONFIG(graphicseffect)
5877
5878#if QT_CONFIG(graphicsview)
5879/*!
5880 \internal
5881
5882 Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
5883 widget and its ancestors. The search starts at \a origin (inclusive).
5884 If successful, the function returns the proxy that embeds the widget, or \nullptr if no
5885 embedded widget was found.
5886*/
5887QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
5888{
5889 if (origin) {
5890 const auto &extra = origin->d_func()->extra;
5891 if (extra && extra->proxyWidget)
5892 return extra->proxyWidget;
5893 return nearestGraphicsProxyWidget(origin: origin->parentWidget());
5894 }
5895 return nullptr;
5896}
5897#endif
5898
5899/*!
5900 \property QWidget::locale
5901 \brief the widget's locale
5902 \since 4.3
5903
5904 As long as no special locale has been set, this is either
5905 the parent's locale or (if this widget is a top level widget),
5906 the default locale.
5907
5908 If the widget displays dates or numbers, these should be formatted
5909 using the widget's locale.
5910
5911 \sa QLocale, QLocale::setDefault()
5912*/
5913
5914void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate)
5915{
5916 Q_Q(QWidget);
5917 if (locale == loc && !forceUpdate)
5918 return;
5919
5920 locale = loc;
5921
5922 if (!children.isEmpty()) {
5923 for (int i = 0; i < children.size(); ++i) {
5924 QWidget *w = qobject_cast<QWidget*>(o: children.at(i));
5925 if (!w)
5926 continue;
5927 if (w->testAttribute(attribute: Qt::WA_SetLocale))
5928 continue;
5929 if (w->isWindow() && !w->testAttribute(attribute: Qt::WA_WindowPropagation))
5930 continue;
5931 w->d_func()->setLocale_helper(loc, forceUpdate);
5932 }
5933 }
5934 QEvent e(QEvent::LocaleChange);
5935 QCoreApplication::sendEvent(receiver: q, event: &e);
5936}
5937
5938void QWidget::setLocale(const QLocale &locale)
5939{
5940 Q_D(QWidget);
5941
5942 setAttribute(Qt::WA_SetLocale);
5943 d->setLocale_helper(loc: locale);
5944}
5945
5946QLocale QWidget::locale() const
5947{
5948 Q_D(const QWidget);
5949
5950 return d->locale;
5951}
5952
5953void QWidgetPrivate::resolveLocale()
5954{
5955 Q_Q(const QWidget);
5956
5957 if (!q->testAttribute(attribute: Qt::WA_SetLocale)) {
5958 QWidget *parent = q->parentWidget();
5959 setLocale_helper(loc: !parent || (q->isWindow() && !q->testAttribute(attribute: Qt::WA_WindowPropagation))
5960 ? QLocale() : parent->locale());
5961 }
5962}
5963
5964void QWidget::unsetLocale()
5965{
5966 Q_D(QWidget);
5967 setAttribute(Qt::WA_SetLocale, on: false);
5968 d->resolveLocale();
5969}
5970
5971/*!
5972 \property QWidget::windowTitle
5973 \brief the window title (caption)
5974
5975 This property only makes sense for top-level widgets, such as
5976 windows and dialogs. If no caption has been set, the title is based of the
5977 \l windowFilePath. If neither of these is set, then the title is
5978 an empty string.
5979
5980 If you use the \l windowModified mechanism, the window title must
5981 contain a "[*]" placeholder, which indicates where the '*' should
5982 appear. Normally, it should appear right after the file name
5983 (e.g., "document1.txt[*] - Text Editor"). If the \l
5984 windowModified property is \c false (the default), the placeholder
5985 is simply removed.
5986
5987 On some desktop platforms (including Windows and Unix), the application name
5988 (from QGuiApplication::applicationDisplayName) is added at the end of the
5989 window title, if set. This is done by the QPA plugin, so it is shown to the
5990 user, but isn't part of the windowTitle string.
5991
5992 \sa windowIcon, windowModified, windowFilePath
5993*/
5994QString QWidget::windowTitle() const
5995{
5996 Q_D(const QWidget);
5997 if (d->extra && d->extra->topextra) {
5998 if (!d->extra->topextra->caption.isEmpty())
5999 return d->extra->topextra->caption;
6000 if (!d->extra->topextra->filePath.isEmpty())
6001 return QFileInfo(d->extra->topextra->filePath).fileName() + "[*]"_L1;
6002 }
6003 return QString();
6004}
6005
6006/*!
6007 Returns a modified window title with the [*] place holder
6008 replaced according to the rules described in QWidget::setWindowTitle
6009
6010 This function assumes that "[*]" can be quoted by another
6011 "[*]", so it will replace two place holders by one and
6012 a single last one by either "*" or nothing depending on
6013 the modified flag.
6014
6015 \internal
6016*/
6017QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widget)
6018{
6019 Q_ASSERT(widget);
6020
6021 QString cap = title;
6022 if (cap.isEmpty())
6023 return cap;
6024
6025 const auto placeHolder = "[*]"_L1;
6026 int index = cap.indexOf(s: placeHolder);
6027
6028 // here the magic begins
6029 while (index != -1) {
6030 index += placeHolder.size();
6031 int count = 1;
6032 while (cap.indexOf(s: placeHolder, from: index) == index) {
6033 ++count;
6034 index += placeHolder.size();
6035 }
6036
6037 if (count%2) { // odd number of [*] -> replace last one
6038 int lastIndex = cap.lastIndexOf(s: placeHolder, from: index - 1);
6039 if (widget->isWindowModified()
6040 && widget->style()->styleHint(stylehint: QStyle::SH_TitleBar_ModifyNotification, opt: nullptr, widget))
6041 cap.replace(i: lastIndex, len: 3, after: QWidget::tr(s: "*"));
6042 else
6043 cap.remove(i: lastIndex, len: 3);
6044 }
6045
6046 index = cap.indexOf(s: placeHolder, from: index);
6047 }
6048
6049 cap.replace(before: "[*][*]"_L1, after: placeHolder);
6050
6051 return cap;
6052}
6053
6054void QWidgetPrivate::setWindowTitle_helper(const QString &title)
6055{
6056 Q_Q(QWidget);
6057 if (q->testAttribute(attribute: Qt::WA_WState_Created))
6058 setWindowTitle_sys(qt_setWindowTitle_helperHelper(title, widget: q));
6059}
6060
6061void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
6062{
6063 Q_Q(QWidget);
6064 if (!q->isWindow())
6065 return;
6066
6067 if (QWindow *window = q->windowHandle())
6068 window->setTitle(caption);
6069
6070}
6071
6072void QWidgetPrivate::setWindowIconText_helper(const QString &title)
6073{
6074 Q_Q(QWidget);
6075 if (q->testAttribute(attribute: Qt::WA_WState_Created))
6076 setWindowIconText_sys(qt_setWindowTitle_helperHelper(title, widget: q));
6077}
6078
6079void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
6080{
6081#if QT_CONFIG(xcb)
6082 Q_Q(QWidget);
6083 // ### The QWidget property is deprecated, but the XCB window function is not.
6084 // It should remain available for the rare application that needs it.
6085 if (QWindow *window = q->windowHandle()) {
6086 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(window->handle()))
6087 xcbWindow->setWindowIconText(iconText);
6088 }
6089#else
6090 Q_UNUSED(iconText);
6091#endif
6092}
6093
6094/*!
6095 \fn void QWidget::windowIconTextChanged(const QString &iconText)
6096
6097 This signal is emitted when the window's icon text has changed, with the
6098 new \a iconText as an argument.
6099
6100 \since 5.2
6101 \deprecated
6102
6103 This signal is deprecated.
6104*/
6105
6106void QWidget::setWindowIconText(const QString &iconText)
6107{
6108 if (QWidget::windowIconText() == iconText)
6109 return;
6110
6111 Q_D(QWidget);
6112 d->topData()->iconText = iconText;
6113 d->setWindowIconText_helper(iconText);
6114
6115 QEvent e(QEvent::IconTextChange);
6116 QCoreApplication::sendEvent(receiver: this, event: &e);
6117
6118 emit windowIconTextChanged(iconText);
6119}
6120
6121/*!
6122 \fn void QWidget::windowTitleChanged(const QString &title)
6123
6124 This signal is emitted when the window's title has changed, with the
6125 new \a title as an argument.
6126
6127 \since 5.2
6128*/
6129
6130void QWidget::setWindowTitle(const QString &title)
6131{
6132 if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull())
6133 return;
6134
6135#if QT_CONFIG(accessibility)
6136 QString oldAccessibleName;
6137 const QAccessibleInterface *accessible = QAccessible::queryAccessibleInterface(this);
6138 if (accessible)
6139 oldAccessibleName = accessible->text(t: QAccessible::Name);
6140#endif
6141
6142 Q_D(QWidget);
6143 d->topData()->caption = title;
6144 d->setWindowTitle_helper(title);
6145
6146 QEvent e(QEvent::WindowTitleChange);
6147 QCoreApplication::sendEvent(receiver: this, event: &e);
6148
6149 emit windowTitleChanged(title);
6150
6151#if QT_CONFIG(accessibility)
6152 if (accessible && accessible->text(t: QAccessible::Name) != oldAccessibleName) {
6153 QAccessibleEvent event(this, QAccessible::NameChanged);
6154 QAccessible::updateAccessibility(event: &event);
6155 }
6156#endif
6157}
6158
6159
6160/*!
6161 \property QWidget::windowIcon
6162 \brief the widget's icon
6163
6164 This property only makes sense for windows. If no icon
6165 has been set, windowIcon() returns the application icon
6166 (QApplication::windowIcon()).
6167
6168 \note On \macos, window icons represent the active document,
6169 and will not be displayed unless a file path has also been
6170 set using setWindowFilePath.
6171
6172 \sa windowTitle, setWindowFilePath
6173*/
6174QIcon QWidget::windowIcon() const
6175{
6176 const QWidget *w = this;
6177 while (w) {
6178 const QWidgetPrivate *d = w->d_func();
6179 if (d->extra && d->extra->topextra && d->extra->topextra->icon)
6180 return *d->extra->topextra->icon;
6181 w = w->parentWidget();
6182 }
6183 return QApplication::windowIcon();
6184}
6185
6186void QWidgetPrivate::setWindowIcon_helper()
6187{
6188 Q_Q(QWidget);
6189 QEvent e(QEvent::WindowIconChange);
6190
6191 // Do not send the event if the widget is a top level.
6192 // In that case, setWindowIcon_sys does it, and event propagation from
6193 // QWidgetWindow to the top level QWidget ensures that the event reaches
6194 // the top level anyhow
6195 if (!q->windowHandle())
6196 QCoreApplication::sendEvent(receiver: q, event: &e);
6197 for (int i = 0; i < children.size(); ++i) {
6198 QWidget *w = qobject_cast<QWidget *>(o: children.at(i));
6199 if (w && !w->isWindow())
6200 QCoreApplication::sendEvent(receiver: w, event: &e);
6201 }
6202}
6203
6204/*!
6205 \fn void QWidget::windowIconChanged(const QIcon &icon)
6206
6207 This signal is emitted when the window's icon has changed, with the
6208 new \a icon as an argument.
6209
6210 \since 5.2
6211*/
6212
6213void QWidget::setWindowIcon(const QIcon &icon)
6214{
6215 Q_D(QWidget);
6216
6217 setAttribute(Qt::WA_SetWindowIcon, on: !icon.isNull());
6218 d->createTLExtra();
6219
6220 if (!d->extra->topextra->icon)
6221 d->extra->topextra->icon = std::make_unique<QIcon>(args: icon);
6222 else
6223 *d->extra->topextra->icon = icon;
6224
6225 d->setWindowIcon_sys();
6226 d->setWindowIcon_helper();
6227
6228 emit windowIconChanged(icon);
6229}
6230
6231void QWidgetPrivate::setWindowIcon_sys()
6232{
6233 Q_Q(QWidget);
6234 if (QWindow *window = q->windowHandle())
6235 window->setIcon(q->windowIcon());
6236}
6237
6238/*!
6239 \property QWidget::windowIconText
6240 \brief the text to be displayed on the icon of a minimized window
6241
6242 This property only makes sense for windows. If no icon
6243 text has been set, this accessor returns an empty string.
6244 It is only implemented on the X11 platform, and only certain
6245 window managers use this window property.
6246
6247 \deprecated
6248 This property is deprecated.
6249
6250 \sa windowIcon, windowTitle
6251*/
6252
6253QString QWidget::windowIconText() const
6254{
6255 Q_D(const QWidget);
6256 return (d->extra && d->extra->topextra) ? d->extra->topextra->iconText : QString();
6257}
6258
6259/*!
6260 \property QWidget::windowFilePath
6261 \since 4.4
6262 \brief the file path associated with a widget
6263
6264 This property only makes sense for windows. It associates a file path with
6265 a window. If you set the file path, but have not set the window title, Qt
6266 sets the window title to the file name of the specified path, obtained using
6267 QFileInfo::fileName().
6268
6269 If the window title is set at any point, then the window title takes precedence and
6270 will be shown instead of the file path string.
6271
6272 Additionally, on \macos, this has an added benefit that it sets the
6273 \l{http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGWindows/chapter_17_section_3.html}{proxy icon}
6274 for the window, assuming that the file path exists.
6275
6276 If no file path is set, this property contains an empty string.
6277
6278 By default, this property contains an empty string.
6279
6280 \sa windowTitle, windowIcon
6281*/
6282
6283QString QWidget::windowFilePath() const
6284{
6285 Q_D(const QWidget);
6286 return (d->extra && d->extra->topextra) ? d->extra->topextra->filePath : QString();
6287}
6288
6289void QWidget::setWindowFilePath(const QString &filePath)
6290{
6291 if (filePath == windowFilePath())
6292 return;
6293
6294 Q_D(QWidget);
6295
6296 d->createTLExtra();
6297 d->extra->topextra->filePath = filePath;
6298 d->setWindowFilePath_helper(filePath);
6299}
6300
6301void QWidgetPrivate::setWindowFilePath_helper(const QString &filePath)
6302{
6303 if (extra->topextra && extra->topextra->caption.isEmpty()) {
6304#ifdef Q_OS_MAC
6305 setWindowTitle_helper(QFileInfo(filePath).fileName());
6306#else
6307 Q_Q(QWidget);
6308 Q_UNUSED(filePath);
6309 setWindowTitle_helper(q->windowTitle());
6310#endif
6311 }
6312#ifdef Q_OS_MAC
6313 setWindowFilePath_sys(filePath);
6314#endif
6315}
6316
6317void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath)
6318{
6319 Q_Q(QWidget);
6320 if (!q->isWindow())
6321 return;
6322
6323 if (QWindow *window = q->windowHandle())
6324 window->setFilePath(filePath);
6325}
6326
6327/*!
6328 Returns the window's role, or an empty string.
6329
6330 \sa windowIcon, windowTitle
6331*/
6332
6333QString QWidget::windowRole() const
6334{
6335 Q_D(const QWidget);
6336 return (d->extra && d->extra->topextra) ? d->extra->topextra->role : QString();
6337}
6338
6339/*!
6340 Sets the window's role to \a role. This only makes sense for
6341 windows on X11.
6342*/
6343void QWidget::setWindowRole(const QString &role)
6344{
6345#if QT_CONFIG(xcb)
6346 Q_D(QWidget);
6347 d->createTLExtra();
6348 d->topData()->role = role;
6349 if (windowHandle()) {
6350 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(windowHandle()->handle()))
6351 xcbWindow->setWindowRole(role);
6352 }
6353#else
6354 Q_UNUSED(role);
6355#endif
6356}
6357
6358/*!
6359 \property QWidget::mouseTracking
6360 \brief whether mouse tracking is enabled for the widget
6361
6362 If mouse tracking is disabled (the default), the widget only
6363 receives mouse move events when at least one mouse button is
6364 pressed while the mouse is being moved.
6365
6366 If mouse tracking is enabled, the widget receives mouse move
6367 events even if no buttons are pressed.
6368
6369 \sa mouseMoveEvent()
6370*/
6371
6372/*!
6373 \property QWidget::tabletTracking
6374 \brief whether tablet tracking is enabled for the widget
6375 \since 5.9
6376
6377 If tablet tracking is disabled (the default), the widget only
6378 receives tablet move events when the stylus is in contact with
6379 the tablet, or at least one stylus button is pressed,
6380 while the stylus is being moved.
6381
6382 If tablet tracking is enabled, the widget receives tablet move
6383 events even while hovering in proximity. This is useful for
6384 monitoring position as well as the auxiliary properties such
6385 as rotation and tilt, and providing feedback in the UI.
6386
6387 \sa tabletEvent()
6388*/
6389
6390
6391/*!
6392 Sets the widget's focus proxy to widget \a w. If \a w is \nullptr, the
6393 function resets this widget to have no focus proxy.
6394
6395 Some widgets can "have focus", but create a child widget, such as
6396 QLineEdit, to actually handle the focus. In this case, the widget
6397 can set the line edit to be its focus proxy.
6398
6399 setFocusProxy() sets the widget which will actually get focus when
6400 "this widget" gets it. If there is a focus proxy, setFocus() and
6401 hasFocus() operate on the focus proxy. If "this widget" is the focus
6402 widget, then setFocusProxy() moves focus to the new focus proxy.
6403
6404 \sa focusProxy()
6405*/
6406
6407void QWidget::setFocusProxy(QWidget * w)
6408{
6409 Q_D(QWidget);
6410 if (!w && !d->extra)
6411 return;
6412
6413 for (QWidget* fp = w; fp; fp = fp->focusProxy()) {
6414 if (Q_UNLIKELY(fp == this)) {
6415 qWarning(msg: "QWidget: %s (%s) already in focus proxy chain", metaObject()->className(), objectName().toLocal8Bit().constData());
6416 return;
6417 }
6418 }
6419
6420 const bool moveFocusToProxy = (QApplicationPrivate::focus_widget == this);
6421
6422 d->createExtra();
6423 d->extra->focus_proxy = w;
6424
6425 if (w && isAncestorOf(child: w)) {
6426 // If the focus proxy is a child of this (so this is a compound widget), then
6427 // we need to make sure that this widget is immediately in front of its own children
6428 // in the focus chain. Otherwise focusNextPrev_helper might jump over unrelated
6429 // widgets that are positioned between this compound widget, and its proxy in
6430 // the focus chain.
6431 const QWidget *parentOfW = w->parentWidget();
6432 Q_ASSERT(parentOfW); // can't be nullptr since we are an ancestor of w
6433 QWidget *firstChild = nullptr;
6434 const auto childList = children();
6435 for (QObject *child : childList) {
6436 if ((firstChild = qobject_cast<QWidget *>(o: child)))
6437 break;
6438 }
6439 Q_ASSERT(firstChild); // can't be nullptr since w is a child
6440 d->insertIntoFocusChainBefore(position: firstChild);
6441 } else if (w && w->isAncestorOf(child: this)) {
6442 // If the focus proxy is a parent, 'this' has to be inserted directly after its parent in the focus chain
6443 // remove it from the chain and insert this into the focus chain after its parent
6444
6445 // is this the case already?
6446 QWidget *parentsNext = w->nextInFocusChain();
6447 if (parentsNext == this) {
6448 // nothing to do.
6449 Q_ASSERT(previousInFocusChain() == w);
6450 } else {
6451 d->QWidgetPrivate::insertIntoFocusChainAfter(position: w);
6452 }
6453 }
6454
6455 if (moveFocusToProxy)
6456 setFocus(Qt::OtherFocusReason);
6457}
6458
6459
6460/*!
6461 Returns the focus proxy, or \nullptr if there is no focus proxy.
6462
6463 \sa setFocusProxy()
6464*/
6465
6466QWidget *QWidget::focusProxy() const
6467{
6468 Q_D(const QWidget);
6469 return d->extra ? d->extra->focus_proxy.data() : nullptr;
6470}
6471
6472
6473/*!
6474 \property QWidget::focus
6475 \brief whether this widget (or its focus proxy) has the keyboard
6476 input focus
6477
6478 By default, this property is \c false.
6479
6480 \note Obtaining the value of this property for a widget is effectively equivalent
6481 to checking whether QApplication::focusWidget() refers to the widget.
6482
6483 \sa setFocus(), clearFocus(), setFocusPolicy(), QApplication::focusWidget()
6484*/
6485bool QWidget::hasFocus() const
6486{
6487 const QWidget* w = this;
6488 while (w->d_func()->extra && w->d_func()->extra->focus_proxy)
6489 w = w->d_func()->extra->focus_proxy;
6490#if QT_CONFIG(graphicsview)
6491 if (QWidget *window = w->window()) {
6492 const auto &e = window->d_func()->extra;
6493 if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w)
6494 return true;
6495 }
6496#endif // QT_CONFIG(graphicsview)
6497 return (QApplication::focusWidget() == w);
6498}
6499
6500/*!
6501 Gives the keyboard input focus to this widget (or its focus
6502 proxy) if this widget or one of its parents is the \l{isActiveWindow()}{active window}. The \a reason argument will
6503 be passed into any focus event sent from this function, it is used
6504 to give an explanation of what caused the widget to get focus.
6505 If the window is not active, the widget will be given the focus when
6506 the window becomes active.
6507
6508 First, a focus about to change event is sent to the focus widget (if any) to
6509 tell it that it is about to lose the focus. Then focus is changed, a
6510 focus out event is sent to the previous focus item and a focus in event is sent
6511 to the new item to tell it that it just received the focus.
6512 (Nothing happens if the focus in and focus out widgets are the
6513 same.)
6514
6515 \note On embedded platforms, setFocus() will not cause an input panel
6516 to be opened by the input method. If you want this to happen, you
6517 have to send a QEvent::RequestSoftwareInputPanel event to the
6518 widget yourself.
6519
6520 setFocus() gives focus to a widget regardless of its focus policy,
6521 but does not clear any keyboard grab (see grabKeyboard()).
6522
6523 Be aware that if the widget is hidden, it will not accept focus
6524 until it is shown.
6525
6526 \warning If you call setFocus() in a function which may itself be
6527 called from focusOutEvent() or focusInEvent(), you may get an
6528 infinite recursion.
6529
6530 \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
6531 setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
6532 grabMouse(), {Keyboard Focus in Widgets}, QEvent::RequestSoftwareInputPanel
6533*/
6534
6535void QWidget::setFocus(Qt::FocusReason reason)
6536{
6537 if (!isEnabled())
6538 return;
6539
6540 QWidget *f = d_func()->deepestFocusProxy();
6541 if (!f)
6542 f = this;
6543
6544 if (QApplication::focusWidget() == f)
6545 return;
6546
6547#if QT_CONFIG(graphicsview)
6548 QWidget *previousProxyFocus = nullptr;
6549 if (const auto &topData = window()->d_func()->extra) {
6550 if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
6551 previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
6552 if (previousProxyFocus && previousProxyFocus->focusProxy())
6553 previousProxyFocus = previousProxyFocus->focusProxy();
6554 if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
6555 return;
6556 }
6557 }
6558#endif
6559
6560#if QT_CONFIG(graphicsview)
6561 // Update proxy state
6562 if (const auto &topData = window()->d_func()->extra) {
6563 if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
6564 f->d_func()->updateFocusChild();
6565 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
6566 topData->proxyWidget->setFocus(reason);
6567 topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
6568 }
6569 }
6570#endif
6571
6572 if (f->isActiveWindow()) {
6573 QWidget *prev = QApplicationPrivate::focus_widget;
6574 if (prev) {
6575 if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
6576 && prev->testAttribute(attribute: Qt::WA_InputMethodEnabled)) {
6577 QGuiApplication::inputMethod()->commit();
6578 }
6579
6580 if (reason != Qt::NoFocusReason) {
6581 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
6582 QCoreApplication::sendEvent(receiver: prev, event: &focusAboutToChange);
6583 }
6584 }
6585
6586 f->d_func()->updateFocusChild();
6587
6588 QApplicationPrivate::setFocusWidget(focus: f, reason);
6589#if QT_CONFIG(accessibility)
6590 // menus update the focus manually and this would create bogus events
6591 if (!(f->inherits(classname: "QMenuBar") || f->inherits(classname: "QMenu") || f->inherits(classname: "QMenuItem")))
6592 {
6593 QAccessibleEvent event(f, QAccessible::Focus);
6594 QAccessible::updateAccessibility(event: &event);
6595 }
6596#endif
6597#if QT_CONFIG(graphicsview)
6598 if (const auto &topData = window()->d_func()->extra) {
6599 if (topData->proxyWidget) {
6600 if (previousProxyFocus && previousProxyFocus != f) {
6601 // Send event to self
6602 QFocusEvent event(QEvent::FocusOut, reason);
6603 QPointer<QWidget> that = previousProxyFocus;
6604 QCoreApplication::sendEvent(receiver: previousProxyFocus, event: &event);
6605 if (that)
6606 QCoreApplication::sendEvent(receiver: that->style(), event: &event);
6607 }
6608 if (!isHidden()) {
6609#if QT_CONFIG(graphicsview)
6610 // Update proxy state
6611 if (const auto &topData = window()->d_func()->extra)
6612 if (topData->proxyWidget && topData->proxyWidget->hasFocus())
6613 topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget();
6614#endif
6615 // Send event to self
6616 QFocusEvent event(QEvent::FocusIn, reason);
6617 QPointer<QWidget> that = f;
6618 QCoreApplication::sendEvent(receiver: f, event: &event);
6619 if (that)
6620 QCoreApplication::sendEvent(receiver: that->style(), event: &event);
6621 }
6622 }
6623 }
6624#endif
6625 } else {
6626 f->d_func()->updateFocusChild();
6627 }
6628}
6629
6630
6631/*!\internal
6632 * A focus proxy can have its own focus proxy, which can have its own
6633 * proxy, and so on. This helper function returns the widget that sits
6634 * at the bottom of the proxy chain, and therefore the one that should
6635 * normally get focus if this widget receives a focus request.
6636 */
6637QWidget *QWidgetPrivate::deepestFocusProxy() const
6638{
6639 Q_Q(const QWidget);
6640
6641 QWidget *focusProxy = q->focusProxy();
6642 if (!focusProxy)
6643 return nullptr;
6644
6645 while (QWidget *nextFocusProxy = focusProxy->focusProxy())
6646 focusProxy = nextFocusProxy;
6647
6648 return focusProxy;
6649}
6650
6651static inline bool isEmbedded(const QWindow *w)
6652{
6653 const auto platformWindow = w->handle();
6654 return platformWindow && platformWindow->isEmbedded();
6655}
6656
6657void QWidgetPrivate::setFocus_sys()
6658{
6659 Q_Q(QWidget);
6660 // Embedded native widget may have taken the focus; get it back to toplevel
6661 // if that is the case (QTBUG-25852), unless widget is a window container.
6662 if (extra && extra->hasWindowContainer)
6663 return;
6664 // Do not activate in case the popup menu opens another application (QTBUG-70810)
6665 // unless the application is embedded (QTBUG-71991).
6666 if (QWindow *nativeWindow = q->testAttribute(attribute: Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) {
6667 if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow()
6668 && (QGuiApplication::applicationState() == Qt::ApplicationActive
6669 || QCoreApplication::testAttribute(attribute: Qt::AA_PluginApplication)
6670 || isEmbedded(w: nativeWindow))) {
6671 nativeWindow->requestActivate();
6672 }
6673 }
6674}
6675
6676// updates focus_child on parent widgets to point into this widget
6677void QWidgetPrivate::updateFocusChild()
6678{
6679 Q_Q(QWidget);
6680
6681 QWidget *w = q;
6682 if (q->isHidden()) {
6683 while (w && w->isHidden()) {
6684 w->d_func()->focus_child = q;
6685 w = w->isWindow() ? nullptr : w->parentWidget();
6686 }
6687 } else {
6688 while (w) {
6689 w->d_func()->focus_child = q;
6690 w = w->isWindow() ? nullptr : w->parentWidget();
6691 }
6692 }
6693
6694 if (QTLWExtra *extra = q->window()->d_func()->maybeTopData()) {
6695 if (extra->window)
6696 emit extra->window->focusObjectChanged(object: q);
6697 }
6698}
6699
6700/*!
6701 \fn void QWidget::setFocus()
6702 \overload
6703
6704 Gives the keyboard input focus to this widget (or its focus
6705 proxy) if this widget or one of its parents is the
6706 \l{isActiveWindow()}{active window}.
6707*/
6708
6709/*!
6710 Takes keyboard input focus from the widget.
6711
6712 If the widget has active focus, a \l{focusOutEvent()}{focus out event} is sent to this widget to tell it that it has
6713 lost the focus.
6714
6715 This widget must enable focus setting to get the keyboard
6716 input focus; that is, it must call setFocusPolicy().
6717
6718 \sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
6719 setFocusPolicy(), QApplication::focusWidget()
6720*/
6721
6722void QWidget::clearFocus()
6723{
6724 if (hasFocus()) {
6725 if (testAttribute(attribute: Qt::WA_InputMethodEnabled))
6726 QGuiApplication::inputMethod()->commit();
6727
6728 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
6729 QCoreApplication::sendEvent(receiver: this, event: &focusAboutToChange);
6730 }
6731
6732 QTLWExtra *extra = window()->d_func()->maybeTopData();
6733 QObject *originalFocusObject = nullptr;
6734 if (extra && extra->window) {
6735 originalFocusObject = extra->window->focusObject();
6736 // the window's focus object might already be nullptr if we are in the destructor, but we still
6737 // need to update QGuiApplication and input context if we have a focus widget.
6738 if (!originalFocusObject)
6739 originalFocusObject = focusWidget();
6740 }
6741
6742 QWidget *w = this;
6743 while (w) {
6744 // Just like setFocus(), we update (clear) the focus_child of our parents
6745 if (w->d_func()->focus_child == this)
6746 w->d_func()->focus_child = nullptr;
6747 w = w->parentWidget();
6748 }
6749
6750 // We've potentially cleared the focus_child of our parents, so we need
6751 // to report this to the rest of Qt. Note that the focus_child is not the same
6752 // thing as the application's focusWidget, which is why this piece of code is
6753 // not inside a hasFocus() block.
6754 if (originalFocusObject && originalFocusObject != extra->window->focusObject())
6755 emit extra->window->focusObjectChanged(object: extra->window->focusObject());
6756
6757#if QT_CONFIG(graphicsview)
6758 const auto &topData = d_func()->extra;
6759 if (topData && topData->proxyWidget)
6760 topData->proxyWidget->clearFocus();
6761#endif
6762
6763 if (hasFocus()) {
6764 // Update proxy state
6765 QApplicationPrivate::setFocusWidget(focus: nullptr, reason: Qt::OtherFocusReason);
6766#if QT_CONFIG(accessibility)
6767 QAccessibleEvent event(this, QAccessible::Focus);
6768 QAccessible::updateAccessibility(event: &event);
6769#endif
6770 }
6771}
6772
6773
6774/*!
6775 \fn bool QWidget::focusNextChild()
6776
6777 Finds a new widget to give the keyboard focus to, as appropriate
6778 for \uicontrol Tab, and returns \c true if it can find a new widget, or
6779 false if it can't.
6780
6781 \sa focusPreviousChild()
6782*/
6783
6784/*!
6785 \fn bool QWidget::focusPreviousChild()
6786
6787 Finds a new widget to give the keyboard focus to, as appropriate
6788 for \uicontrol Shift+Tab, and returns \c true if it can find a new widget,
6789 or false if it can't.
6790
6791 \sa focusNextChild()
6792*/
6793
6794/*!
6795 Finds a new widget to give the keyboard focus to, as appropriate
6796 for Tab and Shift+Tab, and returns \c true if it can find a new
6797 widget, or false if it can't.
6798
6799 If \a next is true, this function searches forward, if \a next
6800 is false, it searches backward.
6801
6802 Sometimes, you will want to reimplement this function. For
6803 example, a web browser might reimplement it to move its "current
6804 active link" forward or backward, and call
6805 focusNextPrevChild() only when it reaches the last or
6806 first link on the "page".
6807
6808 Child widgets call focusNextPrevChild() on their parent widgets,
6809 but only the window that contains the child widgets decides where
6810 to redirect focus. By reimplementing this function for an object,
6811 you thus gain control of focus traversal for all child widgets.
6812
6813 \sa focusNextChild(), focusPreviousChild()
6814*/
6815
6816bool QWidget::focusNextPrevChild(bool next)
6817{
6818 QWidget* p = parentWidget();
6819 bool isSubWindow = (windowType() == Qt::SubWindow);
6820 if (!isWindow() && !isSubWindow && p)
6821 return p->focusNextPrevChild(next);
6822#if QT_CONFIG(graphicsview)
6823 Q_D(QWidget);
6824 if (d->extra && d->extra->proxyWidget)
6825 return d->extra->proxyWidget->focusNextPrevChild(next);
6826#endif
6827
6828 bool wrappingOccurred = false;
6829 QWidget *w = QApplicationPrivate::focusNextPrevChild_helper(toplevel: this, next,
6830 wrappingOccurred: &wrappingOccurred);
6831 if (!w) return false;
6832
6833 Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
6834
6835 /* If we are about to wrap the focus chain, give the platform
6836 * implementation a chance to alter the wrapping behavior. This is
6837 * especially needed when the window is embedded in a window created by
6838 * another process.
6839 */
6840 if (wrappingOccurred) {
6841 QWindow *window = windowHandle();
6842 if (window != nullptr) {
6843 QWindowPrivate *winp = qt_window_private(window);
6844
6845 if (winp->platformWindow != nullptr) {
6846 QFocusEvent event(QEvent::FocusIn, reason);
6847 event.ignore();
6848 winp->platformWindow->windowEvent(event: &event);
6849 if (event.isAccepted()) return true;
6850 }
6851 }
6852 }
6853
6854 w->setFocus(reason);
6855 return true;
6856}
6857
6858/*!
6859 Returns the last child of this widget that setFocus had been
6860 called on. For top level widgets this is the widget that will get
6861 focus in case this window gets activated
6862
6863 This is not the same as QApplication::focusWidget(), which returns
6864 the focus widget in the currently active window.
6865*/
6866
6867QWidget *QWidget::focusWidget() const
6868{
6869 return const_cast<QWidget *>(d_func()->focus_child);
6870}
6871
6872QObject *QWidgetPrivate::focusObject()
6873{
6874 Q_Q(QWidget);
6875 QWidget *proxy = deepestFocusProxy();
6876 return proxy ? proxy : q;
6877}
6878
6879/*!
6880 Returns the next widget in this widget's focus chain.
6881
6882 \sa previousInFocusChain()
6883*/
6884QWidget *QWidget::nextInFocusChain() const
6885{
6886 Q_D(const QWidget);
6887 return d->nextPrevElementInFocusChain(direction: QWidgetPrivate::FocusDirection::Next);
6888}
6889
6890/*!
6891 \brief The previousInFocusChain function returns the previous
6892 widget in this widget's focus chain.
6893
6894 \sa nextInFocusChain()
6895
6896 \since 4.6
6897*/
6898QWidget *QWidget::previousInFocusChain() const
6899{
6900 Q_D(const QWidget);
6901 return d->nextPrevElementInFocusChain(direction: QWidgetPrivate::FocusDirection::Previous);
6902}
6903
6904/*!
6905 \property QWidget::isActiveWindow
6906 \brief whether this widget's window is the active window
6907
6908 The active window is the window that contains the widget that has
6909 keyboard focus (The window may still have focus if it has no
6910 widgets or none of its widgets accepts keyboard focus).
6911
6912 When popup windows are visible, this property is \c true for both the
6913 active window \e and for the popup.
6914
6915 By default, this property is \c false.
6916
6917 \sa activateWindow(), QApplication::activeWindow()
6918*/
6919bool QWidget::isActiveWindow() const
6920{
6921 QWidget *tlw = window();
6922 if (tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
6923 return true;
6924
6925#if QT_CONFIG(graphicsview)
6926 if (const auto &tlwExtra = tlw->d_func()->extra) {
6927 if (isVisible() && tlwExtra->proxyWidget)
6928 return tlwExtra->proxyWidget->isActiveWindow();
6929 }
6930#endif
6931
6932 if (style()->styleHint(stylehint: QStyle::SH_Widget_ShareActivation, opt: nullptr, widget: this)) {
6933 if (tlw->windowType() == Qt::Tool &&
6934 !tlw->isModal() &&
6935 (!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
6936 return true;
6937 QWidget *w = QApplication::activeWindow();
6938 while(w && tlw->windowType() == Qt::Tool &&
6939 !w->isModal() && w->parentWidget()) {
6940 w = w->parentWidget()->window();
6941 if (w == tlw)
6942 return true;
6943 }
6944 }
6945
6946 // Check for an active window container
6947 if (QWindow *ww = QGuiApplication::focusWindow()) {
6948 while (ww) {
6949 QWidgetWindow *qww = qobject_cast<QWidgetWindow *>(object: ww);
6950 QWindowContainer *qwc = qww ? qobject_cast<QWindowContainer *>(object: qww->widget()) : 0;
6951 if (qwc && qwc->topLevelWidget() == tlw)
6952 return true;
6953 ww = ww->parent();
6954 }
6955 }
6956
6957 // Check if platform adaptation thinks the window is active. This is necessary for
6958 // example in case of ActiveQt servers that are embedded into another application.
6959 // Those are separate processes that are not part of the parent application Qt window/widget
6960 // hierarchy, so they need to rely on native methods to determine if they are part of the
6961 // active window.
6962 if (const QWindow *w = tlw->windowHandle()) {
6963 if (w->handle())
6964 return w->handle()->isActive();
6965 }
6966
6967 return false;
6968}
6969
6970/*!
6971 \fn void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
6972 \overload
6973 \since 6.6
6974
6975 Sets the tab order for the widgets in the \a widgets list by calling
6976 \l{QWidget::setTabOrder(QWidget *, QWidget *)} for each consecutive
6977 pair of widgets.
6978
6979 Instead of setting up each pair manually like this:
6980
6981 \snippet code/src_gui_kernel_qwidget.cpp 9
6982
6983 you can call:
6984
6985 \snippet code/src_gui_kernel_qwidget.cpp 9.list
6986
6987 The call does not create a closed tab focus loop. If there are more widgets
6988 with \l{Qt::TabFocus} focus policy, tabbing on \c{d} will move focus to one
6989 of those widgets, not back to \c{a}.
6990
6991 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
6992*/
6993
6994/*!
6995 Puts the \a second widget after the \a first widget in the focus order.
6996
6997 It effectively removes the \a second widget from its focus chain and
6998 inserts it after the \a first widget.
6999
7000 Note that since the tab order of the \a second widget is changed, you
7001 should order a chain like this:
7002
7003 \snippet code/src_gui_kernel_qwidget.cpp 9
7004
7005 \e not like this:
7006
7007 \snippet code/src_gui_kernel_qwidget.cpp 10
7008
7009 If \a first or \a second has a focus proxy, setTabOrder()
7010 correctly substitutes the proxy.
7011
7012 \note Since Qt 5.10: A widget that has a child as focus proxy is understood as
7013 a compound widget. When setting a tab order between one or two compound widgets, the
7014 local tab order inside each will be preserved. This means that if both widgets are
7015 compound widgets, the resulting tab order will be from the last child inside
7016 \a first, to the first child inside \a second.
7017
7018 \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
7019*/
7020void QWidget::setTabOrder(QWidget* first, QWidget *second)
7021{
7022 if (!first || !second || first == second
7023 || first->focusPolicy() == Qt::NoFocus
7024 || second->focusPolicy() == Qt::NoFocus)
7025 return;
7026
7027 if (Q_UNLIKELY(first->window() != second->window())) {
7028 qWarning(msg: "QWidget::setTabOrder: 'first' and 'second' must be in the same window");
7029 return;
7030 }
7031
7032 const auto determineLastFocusChild = [](QWidget *target, QWidget *noFurtherThan)
7033 {
7034 // Since we need to repeat the same logic for both 'first' and 'second', we add a function that
7035 // determines the last focus child for a widget, taking proxies and compound widgets into account.
7036 // If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
7037 // 'lastFocusChild' will be set to the target itself.
7038 QWidget *lastFocusChild = target;
7039
7040 QWidget *focusProxy = target->d_func()->deepestFocusProxy();
7041 if (!focusProxy) {
7042 // QTBUG-81097: Another case is possible here. We can have a child
7043 // widget, that sets its focusProxy() to the parent (target).
7044 // An example of such widget is a QLineEdit, nested into
7045 // a QAbstractSpinBox. In this case such widget should be considered
7046 // the last focus child.
7047 for (auto *object : target->children()) {
7048 QWidget *w = qobject_cast<QWidget*>(o: object);
7049 if (w && w->focusProxy() == target) {
7050 lastFocusChild = w;
7051 break;
7052 }
7053 }
7054 } else if (target->isAncestorOf(child: focusProxy)) {
7055 lastFocusChild = focusProxy;
7056 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
7057 focusNext != focusProxy && target->isAncestorOf(child: focusNext) && focusNext->window() == focusProxy->window();
7058 focusNext = focusNext->nextInFocusChain()) {
7059 if (focusNext == noFurtherThan)
7060 break;
7061 if (focusNext->focusPolicy() != Qt::NoFocus)
7062 lastFocusChild = focusNext;
7063 }
7064 }
7065 return lastFocusChild;
7066 };
7067 // detect inflection in case we have compound widgets
7068 QWidget *lastFocusChildOfFirst = determineLastFocusChild(first, second);
7069 if (lastFocusChildOfFirst == second)
7070 lastFocusChildOfFirst = first;
7071 QWidget *lastFocusChildOfSecond = determineLastFocusChild(second, first);
7072 if (lastFocusChildOfSecond == first)
7073 lastFocusChildOfSecond = second;
7074
7075 // Return if only NoFocus widgets are between first and second
7076 QWidget *oldPrev = second->previousInFocusChain();
7077 QWidget *prevWithFocus = oldPrev;
7078 while (prevWithFocus->focusPolicy() == Qt::NoFocus)
7079 prevWithFocus = prevWithFocus->previousInFocusChain();
7080 if (prevWithFocus == first)
7081 return;
7082 const QWidgetList chain = QWidgetPrivate::takeFromFocusChain(from: second, to: lastFocusChildOfSecond);
7083 QWidgetPrivate::insertIntoFocusChain(toBeInserted: chain, direction: QWidgetPrivate::FocusDirection::Next, position: lastFocusChildOfFirst);
7084}
7085
7086void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
7087{
7088 QWidget *prev = nullptr;
7089 for (const auto &widget : widgets) {
7090 if (!prev) {
7091 prev = widget;
7092 } else {
7093 QWidget::setTabOrder(first: prev, second: widget);
7094 prev = widget;
7095 }
7096 }
7097}
7098
7099
7100/*!\internal
7101
7102 Moves the relevant subwidgets of this widget from the \a oldtlw's
7103 tab chain to that of the new parent, if there's anything to move and
7104 we're really moving
7105
7106 This function is called from QWidget::reparent() *after* the widget
7107 has been reparented.
7108
7109 \sa reparent()
7110*/
7111
7112void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
7113{
7114 Q_Q(QWidget);
7115 if (oldtlw == q->window())
7116 return; // nothing to do
7117
7118 if (focus_child)
7119 focus_child->clearFocus();
7120
7121 reparentFocusChildren(direction: QWidgetPrivate::FocusDirection::Next);
7122}
7123
7124/*!
7125 \property QWidget::frameSize
7126 \brief the size of the widget including any window frame
7127
7128 By default, this property contains a value that depends on the user's
7129 platform and screen geometry.
7130*/
7131QSize QWidget::frameSize() const
7132{
7133 Q_D(const QWidget);
7134 if (isWindow() && !(windowType() == Qt::Popup)) {
7135 QRect fs = d->frameStrut();
7136 return QSize(data->crect.width() + fs.left() + fs.right(),
7137 data->crect.height() + fs.top() + fs.bottom());
7138 }
7139 return data->crect.size();
7140}
7141
7142/*! \fn void QWidget::move(int x, int y)
7143
7144 \overload
7145
7146 This corresponds to move(QPoint(\a x, \a y)).
7147*/
7148
7149void QWidget::move(const QPoint &p)
7150{
7151 Q_D(QWidget);
7152 setAttribute(Qt::WA_Moved);
7153 if (testAttribute(attribute: Qt::WA_WState_Created)) {
7154 if (isWindow())
7155 d->topData()->posIncludesFrame = false;
7156 d->setGeometry_sys(p.x() + geometry().x() - QWidget::x(),
7157 p.y() + geometry().y() - QWidget::y(),
7158 width(), height(), true);
7159 d->setDirtyOpaqueRegion();
7160 } else {
7161 // no frame yet: see also QWidgetPrivate::fixPosIncludesFrame(), QWindowPrivate::PositionPolicy.
7162 if (isWindow())
7163 d->topData()->posIncludesFrame = true;
7164 data->crect.moveTopLeft(p); // no frame yet
7165 setAttribute(Qt::WA_PendingMoveEvent);
7166 }
7167
7168 if (d->extra && d->extra->hasWindowContainer)
7169 QWindowContainer::parentWasMoved(parent: this);
7170}
7171
7172// move() was invoked with Qt::WA_WState_Created not set (frame geometry
7173// unknown), that is, crect has a position including the frame.
7174// If we can determine the frame strut, fix that and clear the flag.
7175// FIXME: This does not play well with window states other than
7176// Qt::WindowNoState, as we depend on calling setGeometry() on the
7177// platform window after fixing up the position so that the new
7178// geometry is reflected in the platform window, but when the frame
7179// comes in after the window has been shown (e.g. maximized), we're
7180// not in a position to do that kind of fixup.
7181void QWidgetPrivate::fixPosIncludesFrame()
7182{
7183 Q_Q(QWidget);
7184 if (QTLWExtra *te = maybeTopData()) {
7185 if (te->posIncludesFrame) {
7186 // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
7187 // example, in QGraphicsProxyWidget).
7188 if (q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
7189 te->posIncludesFrame = 0;
7190 } else {
7191 if (q->windowHandle() && q->windowHandle()->handle()) {
7192 updateFrameStrut();
7193 if (!q->data->fstrut_dirty) {
7194 data.crect.translate(dx: te->frameStrut.x(), dy: te->frameStrut.y());
7195 te->posIncludesFrame = 0;
7196 }
7197 } // windowHandle()
7198 } // !WA_DontShowOnScreen
7199 } // posIncludesFrame
7200 } // QTLWExtra
7201}
7202
7203/*! \fn void QWidget::resize(int w, int h)
7204 \overload
7205
7206 This corresponds to resize(QSize(\a w, \a h)).
7207*/
7208
7209void QWidget::resize(const QSize &s)
7210{
7211 Q_D(QWidget);
7212 setAttribute(Qt::WA_Resized);
7213 if (testAttribute(attribute: Qt::WA_WState_Created)) {
7214 d->fixPosIncludesFrame();
7215 d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false);
7216 d->setDirtyOpaqueRegion();
7217 } else {
7218 const auto oldRect = data->crect;
7219 data->crect.setSize(s.boundedTo(otherSize: maximumSize()).expandedTo(otherSize: minimumSize()));
7220 if (oldRect != data->crect)
7221 setAttribute(Qt::WA_PendingResizeEvent);
7222 }
7223}
7224
7225void QWidget::setGeometry(const QRect &r)
7226{
7227 Q_D(QWidget);
7228 setAttribute(Qt::WA_Resized);
7229 setAttribute(Qt::WA_Moved);
7230 if (isWindow())
7231 d->topData()->posIncludesFrame = 0;
7232 if (testAttribute(attribute: Qt::WA_WState_Created)) {
7233 d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true);
7234 d->setDirtyOpaqueRegion();
7235 } else {
7236 const auto oldRect = data->crect;
7237 data->crect.setTopLeft(r.topLeft());
7238 data->crect.setSize(r.size().boundedTo(otherSize: maximumSize()).expandedTo(otherSize: minimumSize()));
7239 if (oldRect != data->crect) {
7240 setAttribute(Qt::WA_PendingMoveEvent);
7241 setAttribute(Qt::WA_PendingResizeEvent);
7242 }
7243 }
7244
7245 if (d->extra && d->extra->hasWindowContainer)
7246 QWindowContainer::parentWasMoved(parent: this);
7247}
7248
7249void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
7250{
7251 Q_Q(QWidget);
7252 if (extra) { // any size restrictions?
7253 w = qMin(a: w,b: extra->maxw);
7254 h = qMin(a: h,b: extra->maxh);
7255 w = qMax(a: w,b: extra->minw);
7256 h = qMax(a: h,b: extra->minh);
7257 }
7258
7259 if (q->isWindow() && q->windowHandle()) {
7260 QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
7261 if (!integration->hasCapability(cap: QPlatformIntegration::NonFullScreenWindows)) {
7262 x = 0;
7263 y = 0;
7264 w = q->windowHandle()->width();
7265 h = q->windowHandle()->height();
7266 }
7267 }
7268
7269 QPoint oldp = q->geometry().topLeft();
7270 QSize olds = q->size();
7271 QRect r(x, y, w, h);
7272
7273 bool isResize = olds != r.size();
7274 if (!isMove)
7275 isMove = oldp != r.topLeft();
7276
7277
7278 // We only care about stuff that changes the geometry, or may
7279 // cause the window manager to change its state
7280 if (r.size() == olds && oldp == r.topLeft())
7281 return;
7282
7283 if (!data.in_set_window_state) {
7284 q->data->window_state &= ~Qt::WindowMaximized;
7285 q->data->window_state &= ~Qt::WindowFullScreen;
7286 if (q->isWindow())
7287 topData()->normalGeometry = QRect(0, 0, -1, -1);
7288 }
7289
7290 QPoint oldPos = q->pos();
7291 data.crect = r;
7292
7293 bool needsShow = false;
7294
7295 if (q->isWindow() || q->windowHandle()) {
7296 if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) {
7297 q->setAttribute(Qt::WA_OutsideWSRange, on: true);
7298 if (q->isVisible())
7299 hide_sys();
7300 data.crect = QRect(x, y, w, h);
7301 } else if (q->testAttribute(attribute: Qt::WA_OutsideWSRange)) {
7302 q->setAttribute(Qt::WA_OutsideWSRange, on: false);
7303 needsShow = true;
7304 }
7305 }
7306
7307 if (q->isVisible()) {
7308 if (!q->testAttribute(attribute: Qt::WA_DontShowOnScreen) && !q->testAttribute(attribute: Qt::WA_OutsideWSRange)) {
7309 if (QWindow *win = q->windowHandle()) {
7310 if (q->isWindow()) {
7311 if (isResize && !isMove)
7312 win->resize(w, h);
7313 else if (isMove && !isResize)
7314 win->setPosition(posx: x, posy: y);
7315 else
7316 win->setGeometry(q->geometry());
7317 } else {
7318 QPoint posInNativeParent = q->mapTo(parent: q->nativeParentWidget(),pos: QPoint());
7319 win->setGeometry(QRect(posInNativeParent,r.size()));
7320 }
7321
7322 if (needsShow)
7323 show_sys();
7324 }
7325
7326 if (!q->isWindow()) {
7327 if (renderToTexture) {
7328 QRegion updateRegion(q->geometry());
7329 updateRegion += QRect(oldPos, olds);
7330 q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
7331 } else if (isMove && !isResize) {
7332 moveRect(QRect(oldPos, olds), dx: x - oldPos.x(), dy: y - oldPos.y());
7333 } else {
7334 invalidateBackingStore_resizeHelper(oldPos, oldSize: olds);
7335 }
7336 }
7337 }
7338
7339 if (isMove) {
7340 QMoveEvent e(q->pos(), oldPos);
7341 QCoreApplication::sendEvent(receiver: q, event: &e);
7342 }
7343 if (isResize) {
7344 QResizeEvent e(r.size(), olds);
7345 QCoreApplication::sendEvent(receiver: q, event: &e);
7346 if (q->windowHandle())
7347 q->update();
7348 }
7349 } else { // not visible
7350 if (isMove && q->pos() != oldPos)
7351 q->setAttribute(Qt::WA_PendingMoveEvent, on: true);
7352 if (isResize)
7353 q->setAttribute(Qt::WA_PendingResizeEvent, on: true);
7354 }
7355
7356}
7357
7358/*!
7359 \since 4.2
7360 Saves the current geometry and state for top-level widgets.
7361
7362 To save the geometry when the window closes, you can
7363 implement a close event like this:
7364
7365 \snippet code/src_gui_kernel_qwidget.cpp 11
7366
7367 See the \l{Window Geometry} documentation for an overview of geometry
7368 issues with windows.
7369
7370 Use QMainWindow::saveState() to save the geometry and the state of
7371 toolbars and dock widgets.
7372
7373 \sa restoreGeometry(), QMainWindow::saveState(), QMainWindow::restoreState()
7374*/
7375QByteArray QWidget::saveGeometry() const
7376{
7377 QByteArray array;
7378 QDataStream stream(&array, QIODevice::WriteOnly);
7379 stream.setVersion(QDataStream::Qt_4_0);
7380 const quint32 magicNumber = 0x1D9D0CB;
7381 // Version history:
7382 // - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0
7383 // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
7384 // - Qt 5.12 - today : Version 3.0, save QWidget::geometry()
7385 quint16 majorVersion = 3;
7386 quint16 minorVersion = 0;
7387 const int screenNumber = QGuiApplication::screens().indexOf(t: screen());
7388 stream << magicNumber
7389 << majorVersion
7390 << minorVersion
7391 << frameGeometry()
7392 << normalGeometry()
7393 << qint32(screenNumber)
7394 << quint8(windowState() & Qt::WindowMaximized)
7395 << quint8(windowState() & Qt::WindowFullScreen)
7396 << qint32(screen()->geometry().width()) // added in 2.0
7397 << geometry(); // added in 3.0
7398 return array;
7399}
7400
7401/*!
7402 \internal
7403
7404 Check a if \a restoredGeometry fits into \a availableGeometry
7405 This method is used to verify that a widget is restored to a geometry, which
7406 fits into the target screen.
7407
7408 \param frameHeight represents the height of the widget's title bar, which is expected
7409 to be on its top.
7410
7411 If the size of \a restoredGeometry exceeds \a availableGeometry, its height and width
7412 will be resized to be two pixels smaller than \a availableGeometry. An exact match would
7413 be full screen.
7414
7415 If at least one edge of \a restoredGeometry is outside \a availableGeometry,
7416 \a restoredGeometry will be moved
7417 \list
7418 \li down if its top is off screen
7419 \li up if its bottom is off screen
7420 \li right if its left edge is off screen
7421 \li left if its right edge is off screen
7422 \endlist
7423 */
7424void QWidgetPrivate::checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
7425 int frameHeight)
7426{
7427 // compare with restored geometry's height increased by frameHeight
7428 const int height = restoredGeometry->height() + frameHeight;
7429
7430 // Step 1: Resize if necessary:
7431 // make height / width 2px smaller than screen, because an exact match would be fullscreen
7432 if (availableGeometry.height() <= height)
7433 restoredGeometry->setHeight(availableGeometry.height() - 2 - frameHeight);
7434 if (availableGeometry.width() <= restoredGeometry->width())
7435 restoredGeometry->setWidth(availableGeometry.width() - 2);
7436
7437 // Step 2: Move if necessary:
7438 // Construct a rectangle from restored Geometry adjusted by frameHeight
7439 const QRect restored = restoredGeometry->adjusted(xp1: 0, yp1: -frameHeight, xp2: 0, yp2: 0);
7440
7441 // Return if restoredGeometry (including frame) fits into screen
7442 if (availableGeometry.contains(r: restored))
7443 return;
7444
7445 // (size is correct, but at least one edge is off screen)
7446
7447 // Top out of bounds => move down
7448 if (restored.top() <= availableGeometry.top()) {
7449 restoredGeometry->moveTop(pos: availableGeometry.top() + 1 + frameHeight);
7450 } else if (restored.bottom() >= availableGeometry.bottom()) {
7451 // Bottom out of bounds => move up
7452 restoredGeometry->moveBottom(pos: availableGeometry.bottom() - 1);
7453 }
7454
7455 // Left edge out of bounds => move right
7456 if (restored.left() <= availableGeometry.left()) {
7457 restoredGeometry->moveLeft(pos: availableGeometry.left() + 1);
7458 } else if (restored.right() >= availableGeometry.right()) {
7459 // Right edge out of bounds => move left
7460 restoredGeometry->moveRight(pos: availableGeometry.right() - 1);
7461 }
7462}
7463
7464/*!
7465 \since 4.2
7466
7467 Restores the geometry and state of top-level widgets stored in the
7468 byte array \a geometry. Returns \c true on success; otherwise
7469 returns \c false.
7470
7471 If the restored geometry is off-screen, it will be modified to be
7472 inside the available screen geometry.
7473
7474 To restore geometry saved using QSettings, you can use code like
7475 this:
7476
7477 \snippet code/src_gui_kernel_qwidget.cpp 12
7478
7479 See the \l{Window Geometry} documentation for an overview of geometry
7480 issues with windows.
7481
7482 Use QMainWindow::restoreState() to restore the geometry and the
7483 state of toolbars and dock widgets.
7484
7485 \sa saveGeometry(), QSettings, QMainWindow::saveState(), QMainWindow::restoreState()
7486*/
7487bool QWidget::restoreGeometry(const QByteArray &geometry)
7488{
7489 if (geometry.size() < 4)
7490 return false;
7491 QDataStream stream(geometry);
7492 stream.setVersion(QDataStream::Qt_4_0);
7493
7494 const quint32 magicNumber = 0x1D9D0CB;
7495 quint32 storedMagicNumber;
7496 stream >> storedMagicNumber;
7497 if (storedMagicNumber != magicNumber)
7498 return false;
7499
7500 const quint16 currentMajorVersion = 3;
7501 quint16 majorVersion = 0;
7502 quint16 minorVersion = 0;
7503
7504 stream >> majorVersion >> minorVersion;
7505
7506 if (majorVersion > currentMajorVersion)
7507 return false;
7508 // (Allow all minor versions.)
7509
7510 QRect restoredFrameGeometry;
7511 QRect restoredGeometry;
7512 QRect restoredNormalGeometry;
7513 qint32 restoredScreenNumber;
7514 quint8 maximized;
7515 quint8 fullScreen;
7516 qint32 restoredScreenWidth = 0;
7517
7518 stream >> restoredFrameGeometry // Only used for sanity checks in version 0
7519 >> restoredNormalGeometry
7520 >> restoredScreenNumber
7521 >> maximized
7522 >> fullScreen;
7523
7524 if (majorVersion > 1)
7525 stream >> restoredScreenWidth;
7526 if (majorVersion > 2)
7527 stream >> restoredGeometry;
7528
7529 // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
7530
7531 if (restoredScreenNumber >= qMax(a: QGuiApplication::screens().size(), b: 1))
7532 restoredScreenNumber = 0;
7533 const QScreen *restoredScreen = QGuiApplication::screens().value(i: restoredScreenNumber, defaultValue: nullptr);
7534 const qreal screenWidthF = restoredScreen ? qreal(restoredScreen->geometry().width()) : 0;
7535 // Sanity check bailing out when large variations of screen sizes occur due to
7536 // high DPI scaling or different levels of DPI awareness.
7537 if (restoredScreenWidth) {
7538 const qreal factor = qreal(restoredScreenWidth) / screenWidthF;
7539 if (factor < 0.8 || factor > 1.25)
7540 return false;
7541 } else {
7542 // Saved by Qt 5.3 and earlier, try to prevent too large windows
7543 // unless the size will be adapted by maximized or fullscreen.
7544 if (!maximized && !fullScreen && qreal(restoredFrameGeometry.width()) / screenWidthF > 1.5)
7545 return false;
7546 }
7547
7548 const int frameHeight = QApplication::style()
7549 ? QApplication::style()->pixelMetric(metric: QStyle::PM_TitleBarHeight, option: nullptr, widget: this)
7550 : 20;
7551
7552 if (!restoredNormalGeometry.isValid())
7553 restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
7554 if (!restoredNormalGeometry.isValid()) {
7555 // use the widget's adjustedSize if the sizeHint() doesn't help
7556 restoredNormalGeometry.setSize(restoredNormalGeometry
7557 .size()
7558 .expandedTo(otherSize: d_func()->adjustedSize()));
7559 }
7560
7561 const QRect availableGeometry = restoredScreen ? restoredScreen->availableGeometry()
7562 : QRect();
7563
7564 // Modify the restored geometry if we are about to restore to coordinates
7565 // that would make the window "lost". This happens if:
7566 // - The restored geometry is completely or partly oustside the available geometry
7567 // - The title bar is outside the available geometry.
7568
7569 QWidgetPrivate::checkRestoredGeometry(availableGeometry, restoredGeometry: &restoredGeometry, frameHeight);
7570 QWidgetPrivate::checkRestoredGeometry(availableGeometry, restoredGeometry: &restoredNormalGeometry, frameHeight);
7571
7572 if (maximized || fullScreen) {
7573 // set geometry before setting the window state to make
7574 // sure the window is maximized to the right screen.
7575 Qt::WindowStates ws = windowState();
7576#ifndef Q_OS_WIN
7577 setGeometry(restoredNormalGeometry);
7578#else
7579 if (ws & Qt::WindowFullScreen) {
7580 // Full screen is not a real window state on Windows.
7581 move(availableGeometry.topLeft());
7582 } else if (ws & Qt::WindowMaximized) {
7583 // Setting a geometry on an already maximized window causes this to be
7584 // restored into a broken, half-maximized state, non-resizable state (QTBUG-4397).
7585 // Move the window in normal state if needed.
7586 if (restoredScreen != screen()) {
7587 setWindowState(Qt::WindowNoState);
7588 setGeometry(restoredNormalGeometry);
7589 }
7590 } else {
7591 setGeometry(restoredNormalGeometry);
7592 }
7593#endif // Q_OS_WIN
7594 if (maximized)
7595 ws |= Qt::WindowMaximized;
7596 if (fullScreen)
7597 ws |= Qt::WindowFullScreen;
7598 setWindowState(ws);
7599 d_func()->topData()->normalGeometry = restoredNormalGeometry;
7600 } else {
7601 setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
7602
7603 // FIXME: Why fall back to restoredNormalGeometry if majorVersion <= 2?
7604 if (majorVersion > 2)
7605 setGeometry(restoredGeometry);
7606 else
7607 setGeometry(restoredNormalGeometry);
7608 }
7609 return true;
7610}
7611
7612/*!\fn void QWidget::setGeometry(int x, int y, int w, int h)
7613 \overload
7614
7615 This corresponds to setGeometry(QRect(\a x, \a y, \a w, \a h)).
7616*/
7617
7618/*!
7619 Sets the margins around the contents of the widget to have the sizes
7620 \a left, \a top, \a right, and \a bottom. The margins are used by
7621 the layout system, and may be used by subclasses to specify the area
7622 to draw in (e.g. excluding the frame).
7623
7624 Changing the margins will trigger a resizeEvent().
7625
7626 \sa contentsRect(), contentsMargins()
7627*/
7628void QWidget::setContentsMargins(int left, int top, int right, int bottom)
7629{
7630 Q_D(QWidget);
7631 if (left == d->leftmargin && top == d->topmargin
7632 && right == d->rightmargin && bottom == d->bottommargin)
7633 return;
7634 d->leftmargin = left;
7635 d->topmargin = top;
7636 d->rightmargin = right;
7637 d->bottommargin = bottom;
7638
7639 d->updateContentsRect();
7640}
7641
7642/*!
7643 \overload
7644 \since 4.6
7645
7646 \brief The setContentsMargins function sets the margins around the
7647 widget's contents.
7648
7649 Sets the margins around the contents of the widget to have the
7650 sizes determined by \a margins. The margins are
7651 used by the layout system, and may be used by subclasses to
7652 specify the area to draw in (e.g. excluding the frame).
7653
7654 Changing the margins will trigger a resizeEvent().
7655
7656 \sa contentsRect(), contentsMargins()
7657*/
7658void QWidget::setContentsMargins(const QMargins &margins)
7659{
7660 setContentsMargins(left: margins.left(), top: margins.top(),
7661 right: margins.right(), bottom: margins.bottom());
7662}
7663
7664void QWidgetPrivate::updateContentsRect()
7665{
7666 Q_Q(QWidget);
7667
7668 if (layout)
7669 layout->update(); //force activate; will do updateGeometry
7670 else
7671 q->updateGeometry();
7672
7673 if (q->isVisible()) {
7674 q->update();
7675 QResizeEvent e(q->data->crect.size(), q->data->crect.size());
7676 QCoreApplication::sendEvent(receiver: q, event: &e);
7677 } else {
7678 q->setAttribute(Qt::WA_PendingResizeEvent, on: true);
7679 }
7680
7681 QEvent e(QEvent::ContentsRectChange);
7682 QCoreApplication::sendEvent(receiver: q, event: &e);
7683}
7684
7685/*!
7686 \since 4.6
7687
7688 \brief The contentsMargins function returns the widget's contents margins.
7689
7690 \sa setContentsMargins(), contentsRect()
7691 */
7692QMargins QWidget::contentsMargins() const
7693{
7694 Q_D(const QWidget);
7695 QMargins userMargins(d->leftmargin, d->topmargin, d->rightmargin, d->bottommargin);
7696 return testAttribute(attribute: Qt::WA_ContentsMarginsRespectsSafeArea) ?
7697 userMargins | d->safeAreaMargins() : userMargins;
7698}
7699
7700/*!
7701 Returns the area inside the widget's margins.
7702
7703 \sa setContentsMargins(), contentsMargins()
7704*/
7705QRect QWidget::contentsRect() const
7706{
7707 return rect() - contentsMargins();
7708}
7709
7710QMargins QWidgetPrivate::safeAreaMargins() const
7711{
7712 Q_Q(const QWidget);
7713 QWidget *nativeWidget = q->window();
7714 if (!nativeWidget->windowHandle())
7715 return QMargins();
7716
7717 QPlatformWindow *platformWindow = nativeWidget->windowHandle()->handle();
7718 if (!platformWindow)
7719 return QMargins();
7720
7721 QMargins safeAreaMargins = platformWindow->safeAreaMargins();
7722
7723 if (!q->isWindow()) {
7724 // In theory the native parent widget already has a contents rect reflecting
7725 // the safe area of that widget, but we can't be sure that the widget or child
7726 // widgets of that widget have respected the contents rect when setting their
7727 // geometry, so we need to manually compute the safe area.
7728
7729 // Unless the native widget doesn't have any margins, in which case there's
7730 // nothing for us to compute.
7731 if (safeAreaMargins.isNull())
7732 return QMargins();
7733
7734 // Or, if one of our ancestors are in a layout that does not have WA_LayoutOnEntireRect
7735 // set, and the widget respects the safe area, then we know that the layout has already
7736 // taken care of placing us inside the safe area, by taking the contents rect of its
7737 // parent widget into account.
7738 const QWidget *assumedSafeWidget = nullptr;
7739 for (const QWidget *w = q; w != nativeWidget; w = w->parentWidget()) {
7740 QWidget *parentWidget = w->parentWidget();
7741 if (!parentWidget->testAttribute(attribute: Qt::WA_ContentsMarginsRespectsSafeArea))
7742 continue; // Layout can't help us
7743
7744 if (parentWidget->testAttribute(attribute: Qt::WA_LayoutOnEntireRect))
7745 continue; // Layout not going to help us
7746
7747 QLayout *layout = parentWidget->layout();
7748 if (!layout)
7749 continue;
7750
7751 if (layout->geometry().isNull())
7752 continue; // Layout hasn't been activated yet
7753
7754 if (layout->indexOf(w) < 0)
7755 continue; // Widget is not in layout
7756
7757 assumedSafeWidget = w;
7758 break;
7759 }
7760
7761#if !defined(QT_DEBUG)
7762 if (assumedSafeWidget) {
7763 // We found a layout that we assume will take care of keeping us within the safe area
7764 // For debug builds we still map the safe area using the fallback logic, so that we
7765 // can detect any misbehaving layouts.
7766 return QMargins();
7767 }
7768#endif
7769
7770 // In all other cases we need to map the safe area of the native parent to the widget.
7771 // This depends on the widget being positioned and sized already, which means the initial
7772 // layout will be wrong, but the layout will then adjust itself.
7773 QPoint topLeftMargins = q->mapFrom(parent: nativeWidget, pos: QPoint(safeAreaMargins.left(), safeAreaMargins.top()));
7774 QRect widgetRect = q->isVisible() ? q->visibleRegion().boundingRect() : q->rect();
7775 QPoint bottomRightMargins = widgetRect.bottomRight() - q->mapFrom(parent: nativeWidget,
7776 pos: nativeWidget->rect().bottomRight() - QPoint(safeAreaMargins.right(), safeAreaMargins.bottom()));
7777
7778 // Margins should never be negative
7779 safeAreaMargins = QMargins(qMax(a: 0, b: topLeftMargins.x()), qMax(a: 0, b: topLeftMargins.y()),
7780 qMax(a: 0, b: bottomRightMargins.x()), qMax(a: 0, b: bottomRightMargins.y()));
7781
7782 if (!safeAreaMargins.isNull() && assumedSafeWidget) {
7783 QLayout *layout = assumedSafeWidget->parentWidget()->layout();
7784 qWarning() << layout << "is laying out" << assumedSafeWidget
7785 << "outside of the contents rect of" << layout->parentWidget();
7786 return QMargins(); // Return empty margin to visually highlight the error
7787 }
7788 }
7789
7790 return safeAreaMargins;
7791}
7792
7793/*!
7794 \fn void QWidget::customContextMenuRequested(const QPoint &pos)
7795
7796 This signal is emitted when the widget's \l contextMenuPolicy is
7797 Qt::CustomContextMenu, and the user has requested a context menu on
7798 the widget. The position \a pos is the position of the context menu
7799 event that the widget receives. Normally this is in widget
7800 coordinates. The exception to this rule is QAbstractScrollArea and
7801 its subclasses that map the context menu event to coordinates of the
7802 \l{QAbstractScrollArea::viewport()}{viewport()}.
7803
7804
7805 \sa mapToGlobal(), QMenu, contextMenuPolicy
7806*/
7807
7808
7809/*!
7810 \property QWidget::contextMenuPolicy
7811 \brief how the widget shows a context menu
7812
7813 The default value of this property is Qt::DefaultContextMenu,
7814 which means the contextMenuEvent() handler is called. Other values
7815 are Qt::NoContextMenu, Qt::PreventContextMenu,
7816 Qt::ActionsContextMenu, and Qt::CustomContextMenu. With
7817 Qt::CustomContextMenu, the signal customContextMenuRequested() is
7818 emitted.
7819
7820 \sa contextMenuEvent(), customContextMenuRequested(), actions()
7821*/
7822
7823Qt::ContextMenuPolicy QWidget::contextMenuPolicy() const
7824{
7825 return (Qt::ContextMenuPolicy)data->context_menu_policy;
7826}
7827
7828void QWidget::setContextMenuPolicy(Qt::ContextMenuPolicy policy)
7829{
7830 data->context_menu_policy = (uint) policy;
7831}
7832
7833/*!
7834 \property QWidget::focusPolicy
7835 \brief the way the widget accepts keyboard focus
7836
7837 The policy is Qt::TabFocus if the widget accepts keyboard
7838 focus by tabbing, Qt::ClickFocus if the widget accepts
7839 focus by clicking, Qt::StrongFocus if it accepts both, and
7840 Qt::NoFocus (the default) if it does not accept focus at
7841 all.
7842
7843 You must enable keyboard focus for a widget if it processes
7844 keyboard events. This is normally done from the widget's
7845 constructor. For instance, the QLineEdit constructor calls
7846 setFocusPolicy(Qt::StrongFocus).
7847
7848 If the widget has a focus proxy, then the focus policy will
7849 be propagated to it.
7850
7851 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
7852*/
7853
7854
7855Qt::FocusPolicy QWidget::focusPolicy() const
7856{
7857 return (Qt::FocusPolicy)data->focus_policy;
7858}
7859
7860void QWidget::setFocusPolicy(Qt::FocusPolicy policy)
7861{
7862 data->focus_policy = (uint) policy;
7863 Q_D(QWidget);
7864 if (d->extra && d->extra->focus_proxy)
7865 d->extra->focus_proxy->setFocusPolicy(policy);
7866}
7867
7868/*!
7869 \property QWidget::updatesEnabled
7870 \brief whether updates are enabled
7871
7872 An updates enabled widget receives paint events and has a system
7873 background; a disabled widget does not. This also implies that
7874 calling update() and repaint() has no effect if updates are
7875 disabled.
7876
7877 By default, this property is \c true.
7878
7879 setUpdatesEnabled() is normally used to disable updates for a
7880 short period of time, for instance to avoid screen flicker during
7881 large changes. In Qt, widgets normally do not generate screen
7882 flicker, but on X11 the server might erase regions on the screen
7883 when widgets get hidden before they can be replaced by other
7884 widgets. Disabling updates solves this.
7885
7886 Example:
7887 \snippet code/src_gui_kernel_qwidget.cpp 13
7888
7889 Disabling a widget implicitly disables all its children. Enabling a widget
7890 enables all child widgets \e except top-level widgets or those that
7891 have been explicitly disabled. Re-enabling updates implicitly calls
7892 update() on the widget.
7893
7894 \sa paintEvent()
7895*/
7896void QWidget::setUpdatesEnabled(bool enable)
7897{
7898 Q_D(QWidget);
7899 setAttribute(Qt::WA_ForceUpdatesDisabled, on: !enable);
7900 d->setUpdatesEnabled_helper(enable);
7901}
7902
7903/*!
7904 Shows the widget and its child widgets.
7905
7906 For child windows, this is equivalent to calling setVisible(true).
7907 Otherwise, it is equivalent to calling showFullScreen(), showMaximized(),
7908 or setVisible(true), depending on the platform's default behavior for the window flags.
7909
7910 \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
7911 showNormal(), isVisible(), windowFlags()
7912*/
7913void QWidget::show()
7914{
7915 // Note: We don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
7916
7917 if (!isWindow()) {
7918 setVisible(true);
7919 } else {
7920 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
7921 Qt::WindowState defaultState = platformIntegration->defaultWindowState(data->window_flags);
7922 if (defaultState == Qt::WindowFullScreen)
7923 showFullScreen();
7924 else if (defaultState == Qt::WindowMaximized)
7925 showMaximized();
7926 else
7927 setVisible(true);
7928 }
7929}
7930
7931/*! \internal
7932
7933 Makes the widget visible in the isVisible() meaning of the word.
7934 It is only called for toplevels or widgets with visible parents.
7935 */
7936void QWidgetPrivate::show_recursive()
7937{
7938 Q_Q(QWidget);
7939 // polish if necessary
7940
7941 if (!q->testAttribute(attribute: Qt::WA_WState_Created))
7942 createRecursively();
7943 q->ensurePolished();
7944
7945 if (!q->isWindow() && q->parentWidget()->d_func()->layout && !q->parentWidget()->data->in_show)
7946 q->parentWidget()->d_func()->layout->activate();
7947 // activate our layout before we and our children become visible
7948 if (layout)
7949 layout->activate();
7950
7951 show_helper();
7952}
7953
7954void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disableUpdates)
7955{
7956 Q_Q(QWidget);
7957
7958 disableUpdates = disableUpdates && q->updatesEnabled();
7959 if (disableUpdates)
7960 q->setAttribute(Qt::WA_UpdatesDisabled);
7961
7962 if (q->testAttribute(attribute: Qt::WA_PendingMoveEvent)) {
7963 QMoveEvent e(data.crect.topLeft(), data.crect.topLeft());
7964 QCoreApplication::sendEvent(receiver: q, event: &e);
7965 q->setAttribute(Qt::WA_PendingMoveEvent, on: false);
7966 }
7967
7968 if (q->testAttribute(attribute: Qt::WA_PendingResizeEvent)) {
7969 QResizeEvent e(data.crect.size(), QSize());
7970 QCoreApplication::sendEvent(receiver: q, event: &e);
7971 q->setAttribute(Qt::WA_PendingResizeEvent, on: false);
7972 }
7973
7974 if (disableUpdates)
7975 q->setAttribute(Qt::WA_UpdatesDisabled, on: false);
7976
7977 if (!recursive)
7978 return;
7979
7980 for (int i = 0; i < children.size(); ++i) {
7981 if (QWidget *child = qobject_cast<QWidget *>(o: children.at(i)))
7982 child->d_func()->sendPendingMoveAndResizeEvents(recursive, disableUpdates);
7983 }
7984}
7985
7986void QWidgetPrivate::activateChildLayoutsRecursively()
7987{
7988 sendPendingMoveAndResizeEvents(recursive: false, disableUpdates: true);
7989
7990 for (int i = 0; i < children.size(); ++i) {
7991 QWidget *child = qobject_cast<QWidget *>(o: children.at(i));
7992 if (!child || child->isHidden() || child->isWindow())
7993 continue;
7994
7995 child->ensurePolished();
7996
7997 // Activate child's layout
7998 QWidgetPrivate *childPrivate = child->d_func();
7999 if (childPrivate->layout)
8000 childPrivate->layout->activate();
8001
8002 // Pretend we're visible.
8003 const bool wasVisible = child->isVisible();
8004 if (!wasVisible)
8005 child->setAttribute(Qt::WA_WState_Visible);
8006
8007 // Do the same for all my children.
8008 childPrivate->activateChildLayoutsRecursively();
8009
8010 // We're not cheating anymore.
8011 if (!wasVisible)
8012 child->setAttribute(Qt::WA_WState_Visible, on: false);
8013 }
8014}
8015
8016void QWidgetPrivate::show_helper()
8017{
8018 Q_Q(QWidget);
8019 data.in_show = true; // qws optimization
8020 // make sure we receive pending move and resize events
8021 sendPendingMoveAndResizeEvents();
8022
8023 // become visible before showing all children
8024 q->setAttribute(Qt::WA_WState_Visible);
8025
8026 // finally show all children recursively
8027 showChildren(spontaneous: false);
8028
8029
8030
8031 const bool isWindow = q->isWindow();
8032#if QT_CONFIG(graphicsview)
8033 bool isEmbedded = isWindow && q->graphicsProxyWidget() != nullptr;
8034#else
8035 bool isEmbedded = false;
8036#endif
8037
8038 // popup handling: new popups and tools need to be raised, and
8039 // existing popups must be closed. Also propagate the current
8040 // windows's KeyboardFocusChange status.
8041 if (isWindow && !isEmbedded) {
8042 if ((q->windowType() == Qt::Tool) || (q->windowType() == Qt::Popup) || q->windowType() == Qt::ToolTip) {
8043 q->raise();
8044 if (q->parentWidget() && q->parentWidget()->window()->testAttribute(attribute: Qt::WA_KeyboardFocusChange))
8045 q->setAttribute(Qt::WA_KeyboardFocusChange);
8046 } else {
8047 while (QApplication::activePopupWidget()) {
8048 if (!QApplication::activePopupWidget()->close())
8049 break;
8050 }
8051 }
8052 }
8053
8054 // Automatic embedding of child windows of widgets already embedded into
8055 // QGraphicsProxyWidget when they are shown the first time.
8056#if QT_CONFIG(graphicsview)
8057 if (isWindow) {
8058 if (!isEmbedded && !bypassGraphicsProxyWidget(p: q)) {
8059 QGraphicsProxyWidget *ancestorProxy = nearestGraphicsProxyWidget(origin: q->parentWidget());
8060 if (ancestorProxy) {
8061 isEmbedded = true;
8062 ancestorProxy->d_func()->embedSubWindow(q);
8063 }
8064 }
8065 }
8066#else
8067 Q_UNUSED(isEmbedded);
8068#endif
8069
8070 // send the show event before showing the window
8071 QShowEvent showEvent;
8072 QCoreApplication::sendEvent(receiver: q, event: &showEvent);
8073
8074 show_sys();
8075
8076 if (!isEmbedded && q->windowType() == Qt::Popup)
8077 qApp->d_func()->openPopup(popup: q);
8078
8079#if QT_CONFIG(accessibility)
8080 if (q->windowType() != Qt::ToolTip) { // Tooltips are read aloud twice in MS narrator.
8081 QAccessibleEvent event(q, QAccessible::ObjectShow);
8082 QAccessible::updateAccessibility(event: &event);
8083 }
8084#endif
8085
8086 if (QApplicationPrivate::hidden_focus_widget == q) {
8087 QApplicationPrivate::hidden_focus_widget = nullptr;
8088 q->setFocus(Qt::OtherFocusReason);
8089 }
8090
8091 // Process events when showing a Qt::SplashScreen widget before the event loop
8092 // is spinnning; otherwise it might not show up on particular platforms.
8093 // This makes QSplashScreen behave the same on all platforms.
8094 if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen)
8095 QCoreApplication::processEvents();
8096
8097 data.in_show = false; // reset qws optimization
8098}
8099
8100void QWidgetPrivate::show_sys()
8101{
8102 Q_Q(QWidget);
8103
8104 auto window = qobject_cast<QWidgetWindow *>(object: windowHandle());
8105
8106 if (q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
8107 invalidateBackingStore(q->rect());
8108 q->setAttribute(Qt::WA_Mapped);
8109 // add our window the modal window list (native dialogs)
8110 if (window && q->isWindow()
8111#if QT_CONFIG(graphicsview)
8112 && (!extra || !extra->proxyWidget)
8113#endif
8114 && q->windowModality() != Qt::NonModal) {
8115 QGuiApplicationPrivate::showModalWindow(window);
8116 }
8117 return;
8118 }
8119
8120 if (renderToTexture && !q->isWindow())
8121 QCoreApplication::postEvent(receiver: q->parentWidget(), event: new QUpdateLaterEvent(q->geometry()));
8122 else
8123 QCoreApplication::postEvent(receiver: q, event: new QUpdateLaterEvent(q->rect()));
8124
8125 if ((!q->isWindow() && !q->testAttribute(attribute: Qt::WA_NativeWindow))
8126 || q->testAttribute(attribute: Qt::WA_OutsideWSRange)) {
8127 return;
8128 }
8129
8130 if (window) {
8131 if (q->isWindow())
8132 fixPosIncludesFrame();
8133 QRect geomRect = q->geometry();
8134 if (!q->isWindow()) {
8135 QPoint topLeftOfWindow = q->mapTo(parent: q->nativeParentWidget(),pos: QPoint());
8136 geomRect.moveTopLeft(p: topLeftOfWindow);
8137 }
8138 const QRect windowRect = window->geometry();
8139 if (windowRect != geomRect) {
8140 if (q->testAttribute(attribute: Qt::WA_Moved)
8141 || !QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowManagement))
8142 window->setGeometry(geomRect);
8143 else
8144 window->resize(newSize: geomRect.size());
8145 }
8146
8147#ifndef QT_NO_CURSOR
8148 qt_qpa_set_cursor(w: q, force: false); // Needed in case cursor was set before show
8149#endif
8150 invalidateBackingStore(q->rect());
8151 window->setNativeWindowVisibility(true);
8152 // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
8153 if (window->isTopLevel()) {
8154 const QPoint crectTopLeft = q->data->crect.topLeft();
8155 const QPoint windowTopLeft = window->geometry().topLeft();
8156 if (crectTopLeft == QPoint(0, 0) && windowTopLeft != crectTopLeft)
8157 q->data->crect.moveTopLeft(p: windowTopLeft);
8158 }
8159 }
8160}
8161
8162/*!
8163 Hides the widget. This function is equivalent to
8164 setVisible(false).
8165
8166
8167 \note If you are working with QDialog or its subclasses and you invoke
8168 the show() function after this function, the dialog will be displayed in
8169 its original position.
8170
8171 \sa hideEvent(), isHidden(), show(), setVisible(), isVisible(), close()
8172*/
8173void QWidget::hide()
8174{
8175 setVisible(false);
8176}
8177
8178/*!\internal
8179 */
8180void QWidgetPrivate::hide_helper()
8181{
8182 Q_Q(QWidget);
8183
8184 bool isEmbedded = false;
8185#if QT_CONFIG(graphicsview)
8186 isEmbedded = q->isWindow() && !bypassGraphicsProxyWidget(p: q) && nearestGraphicsProxyWidget(origin: q->parentWidget()) != nullptr;
8187#else
8188 Q_UNUSED(isEmbedded);
8189#endif
8190
8191 if (!isEmbedded && (q->windowType() == Qt::Popup))
8192 qApp->d_func()->closePopup(popup: q);
8193
8194 q->setAttribute(Qt::WA_Mapped, on: false);
8195 hide_sys();
8196
8197 bool wasVisible = q->testAttribute(attribute: Qt::WA_WState_Visible);
8198
8199 if (wasVisible) {
8200 q->setAttribute(Qt::WA_WState_Visible, on: false);
8201
8202 }
8203
8204 QHideEvent hideEvent;
8205 QCoreApplication::sendEvent(receiver: q, event: &hideEvent);
8206 hideChildren(spontaneous: false);
8207
8208 // next bit tries to move the focus if the focus widget is now
8209 // hidden.
8210 if (wasVisible) {
8211 qApp->d_func()->sendSyntheticEnterLeave(widget: q);
8212 QWidget *fw = QApplication::focusWidget();
8213 while (fw && !fw->isWindow()) {
8214 if (fw == q) {
8215 q->focusNextPrevChild(next: true);
8216 break;
8217 }
8218 fw = fw->parentWidget();
8219 }
8220 }
8221
8222 if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
8223 repaintManager->removeDirtyWidget(w: q);
8224
8225#if QT_CONFIG(accessibility)
8226 if (wasVisible) {
8227 QAccessibleEvent event(q, QAccessible::ObjectHide);
8228 QAccessible::updateAccessibility(event: &event);
8229 }
8230#endif
8231}
8232
8233void QWidgetPrivate::hide_sys()
8234{
8235 Q_Q(QWidget);
8236
8237 auto window = qobject_cast<QWidgetWindow *>(object: windowHandle());
8238
8239 if (q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
8240 q->setAttribute(Qt::WA_Mapped, on: false);
8241 // remove our window from the modal window list (native dialogs)
8242 if (window && q->isWindow()
8243#if QT_CONFIG(graphicsview)
8244 && (!extra || !extra->proxyWidget)
8245#endif
8246 && q->windowModality() != Qt::NonModal) {
8247 QGuiApplicationPrivate::hideModalWindow(window);
8248 }
8249 // do not return here, if window non-zero, we must hide it
8250 }
8251
8252 deactivateWidgetCleanup();
8253
8254 if (!q->isWindow()) {
8255 QWidget *p = q->parentWidget();
8256 if (p &&p->isVisible()) {
8257 if (renderToTexture)
8258 p->d_func()->invalidateBackingStore(q->geometry());
8259 else
8260 invalidateBackingStore(q->rect());
8261 }
8262 } else {
8263 invalidateBackingStore(q->rect());
8264 }
8265
8266 if (window)
8267 window->setNativeWindowVisibility(false);
8268}
8269
8270/*!
8271 \fn bool QWidget::isHidden() const
8272
8273 Returns \c true if the widget is hidden, otherwise returns \c false.
8274
8275 A hidden widget will only become visible when show() is called on
8276 it. It will not be automatically shown when the parent is shown.
8277
8278 To check visibility, use !isVisible() instead (notice the exclamation mark).
8279
8280 isHidden() implies !isVisible(), but a widget can be not visible
8281 and not hidden at the same time. This is the case for widgets that are children of
8282 widgets that are not visible.
8283
8284
8285 Widgets are hidden if:
8286 \list
8287 \li they were created as independent windows,
8288 \li they were created as children of visible widgets,
8289 \li hide() or setVisible(false) was called.
8290 \endlist
8291*/
8292
8293void QWidget::setVisible(bool visible)
8294{
8295 Q_D(QWidget);
8296 qCDebug(lcWidgetShowHide) << "Setting visibility of" << this
8297 << "with attributes" << WidgetAttributes{.widget: this}
8298 << "to" << visible << "via QWidget";
8299
8300 if (testAttribute(attribute: Qt::WA_WState_ExplicitShowHide) && testAttribute(attribute: Qt::WA_WState_Hidden) == !visible)
8301 return;
8302
8303 if (d->dontSetExplicitShowHide) {
8304 d->dontSetExplicitShowHide = false;
8305 } else {
8306 // Remember that setVisible was called explicitly
8307 setAttribute(Qt::WA_WState_ExplicitShowHide);
8308 }
8309
8310 d->setVisible(visible);
8311}
8312
8313// This method is called from QWidgetWindow in response to QWindow::setVisible,
8314// and should match the semantics of QWindow::setVisible. QWidget::setVisible on
8315// the other hand keeps track of WA_WState_ExplicitShowHide in addition.
8316void QWidgetPrivate::setVisible(bool visible)
8317{
8318 Q_Q(QWidget);
8319 qCDebug(lcWidgetShowHide) << "Setting visibility of" << q
8320 << "with attributes" << WidgetAttributes{.widget: q}
8321 << "to" << visible << "via QWidgetPrivate";
8322
8323 if (visible) { // show
8324 // Designer uses a trick to make grabWidget work without showing
8325 if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
8326 && !q->parentWidget()->testAttribute(attribute: Qt::WA_WState_Created))
8327 q->parentWidget()->window()->d_func()->createRecursively();
8328
8329 //create toplevels but not children of non-visible parents
8330 QWidget *pw = q->parentWidget();
8331 if (!q->testAttribute(attribute: Qt::WA_WState_Created)
8332 && (q->isWindow() || pw->testAttribute(attribute: Qt::WA_WState_Created))) {
8333 q->create();
8334 }
8335
8336 bool wasResized = q->testAttribute(attribute: Qt::WA_Resized);
8337 Qt::WindowStates initialWindowState = q->windowState();
8338
8339 // polish if necessary
8340 q->ensurePolished();
8341
8342 // whether we need to inform the parent widget immediately
8343 bool needUpdateGeometry = !q->isWindow() && q->testAttribute(attribute: Qt::WA_WState_Hidden);
8344 // we are no longer hidden
8345 q->setAttribute(Qt::WA_WState_Hidden, on: false);
8346
8347 if (needUpdateGeometry)
8348 updateGeometry_helper(forceUpdate: true);
8349
8350 // activate our layout before we and our children become visible
8351 if (layout)
8352 layout->activate();
8353
8354 if (!q->isWindow()) {
8355 QWidget *parent = q->parentWidget();
8356 while (parent && parent->isVisible() && parent->d_func()->layout && !parent->data->in_show) {
8357 parent->d_func()->layout->activate();
8358 if (parent->isWindow())
8359 break;
8360 parent = parent->parentWidget();
8361 }
8362 if (parent)
8363 parent->d_func()->setDirtyOpaqueRegion();
8364 }
8365
8366 // adjust size if necessary
8367 if (!wasResized
8368 && (q->isWindow() || !q->parentWidget()->d_func()->layout)) {
8369 if (q->isWindow()) {
8370 q->adjustSize();
8371 if (q->windowState() != initialWindowState)
8372 q->setWindowState(initialWindowState);
8373 } else {
8374 q->adjustSize();
8375 }
8376 q->setAttribute(Qt::WA_Resized, on: false);
8377 }
8378
8379 q->setAttribute(Qt::WA_KeyboardFocusChange, on: false);
8380
8381 if (q->isWindow() || q->parentWidget()->isVisible()) {
8382 show_helper();
8383
8384 qApp->d_func()->sendSyntheticEnterLeave(widget: q);
8385 }
8386
8387 QEvent showToParentEvent(QEvent::ShowToParent);
8388 QCoreApplication::sendEvent(receiver: q, event: &showToParentEvent);
8389 } else { // hide
8390 if (QApplicationPrivate::hidden_focus_widget == q)
8391 QApplicationPrivate::hidden_focus_widget = nullptr;
8392
8393 // hw: The test on getOpaqueRegion() needs to be more intelligent
8394 // currently it doesn't work if the widget is hidden (the region will
8395 // be clipped). The real check should be testing the cached region
8396 // (and dirty flag) directly.
8397 if (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty())
8398 q->parentWidget()->d_func()->setDirtyOpaqueRegion();
8399
8400 if (!q->testAttribute(attribute: Qt::WA_WState_Hidden)) {
8401 q->setAttribute(Qt::WA_WState_Hidden);
8402 hide_helper();
8403 }
8404
8405 // invalidate layout similar to updateGeometry()
8406 if (!q->isWindow() && q->parentWidget()) {
8407 if (q->parentWidget()->d_func()->layout)
8408 q->parentWidget()->d_func()->layout->invalidate();
8409 else if (q->parentWidget()->isVisible())
8410 QCoreApplication::postEvent(receiver: q->parentWidget(), event: new QEvent(QEvent::LayoutRequest));
8411 }
8412
8413 QEvent hideToParentEvent(QEvent::HideToParent);
8414 QCoreApplication::sendEvent(receiver: q, event: &hideToParentEvent);
8415 }
8416}
8417
8418/*!
8419 Convenience function, equivalent to setVisible(!\a hidden).
8420*/
8421void QWidget::setHidden(bool hidden)
8422{
8423 setVisible(!hidden);
8424}
8425
8426bool QWidgetPrivate::isExplicitlyHidden() const
8427{
8428 Q_Q(const QWidget);
8429 return q->isHidden() && q->testAttribute(attribute: Qt::WA_WState_ExplicitShowHide);
8430}
8431
8432void QWidgetPrivate::_q_showIfNotHidden()
8433{
8434 Q_Q(QWidget);
8435 if (!isExplicitlyHidden())
8436 q->setVisible(true);
8437}
8438
8439void QWidgetPrivate::showChildren(bool spontaneous)
8440{
8441 Q_Q(QWidget);
8442 qCDebug(lcWidgetShowHide) << "Showing children of" << q
8443 << "spontaneously" << spontaneous;
8444
8445 QList<QObject*> childList = children;
8446 for (int i = 0; i < childList.size(); ++i) {
8447 QWidget *widget = qobject_cast<QWidget*>(o: childList.at(i));
8448 if (!widget)
8449 continue;
8450 qCDebug(lcWidgetShowHide) << "Considering" << widget
8451 << "with attributes" << WidgetAttributes{.widget: widget};
8452 if (widget->windowHandle() && !widget->testAttribute(attribute: Qt::WA_WState_ExplicitShowHide))
8453 widget->setAttribute(Qt::WA_WState_Hidden, on: false);
8454 if (widget->isWindow() || widget->testAttribute(attribute: Qt::WA_WState_Hidden))
8455 continue;
8456 if (spontaneous) {
8457 widget->setAttribute(Qt::WA_Mapped);
8458 widget->d_func()->showChildren(spontaneous: true);
8459 QShowEvent e;
8460 QApplication::sendSpontaneousEvent(receiver: widget, event: &e);
8461 } else {
8462 if (widget->testAttribute(attribute: Qt::WA_WState_ExplicitShowHide)) {
8463 widget->d_func()->show_recursive();
8464 } else {
8465 // Call QWidget::setVisible() here, so that subclasses
8466 // that (wrongly) override setVisible to do initialization
8467 // will still be notified that they are made visible, but
8468 // do so without triggering ExplicitShowHide.
8469 widget->d_func()->dontSetExplicitShowHide = true;
8470 widget->setVisible(true);
8471 widget->d_func()->dontSetExplicitShowHide = false;
8472 }
8473 }
8474 }
8475}
8476
8477void QWidgetPrivate::hideChildren(bool spontaneous)
8478{
8479 Q_Q(QWidget);
8480 qCDebug(lcWidgetShowHide) << "Hiding children of" << q
8481 << "spontaneously" << spontaneous;
8482
8483 QList<QObject*> childList = children;
8484 for (int i = 0; i < childList.size(); ++i) {
8485 QWidget *widget = qobject_cast<QWidget*>(o: childList.at(i));
8486 if (!widget)
8487 continue;
8488 qCDebug(lcWidgetShowHide) << "Considering" << widget
8489 << "with attributes" << WidgetAttributes{.widget: widget};
8490 if (widget->isWindow() || widget->testAttribute(attribute: Qt::WA_WState_Hidden))
8491 continue;
8492
8493 if (spontaneous)
8494 widget->setAttribute(Qt::WA_Mapped, on: false);
8495 else
8496 widget->setAttribute(Qt::WA_WState_Visible, on: false);
8497 widget->d_func()->hideChildren(spontaneous);
8498 QHideEvent e;
8499 if (spontaneous) {
8500 QApplication::sendSpontaneousEvent(receiver: widget, event: &e);
8501 } else {
8502 QCoreApplication::sendEvent(receiver: widget, event: &e);
8503 if (widget->internalWinId()
8504 && widget->testAttribute(attribute: Qt::WA_DontCreateNativeAncestors)) {
8505 // hide_sys() on an ancestor won't have any affect on this
8506 // widget, so it needs an explicit hide_sys() of its own
8507 widget->d_func()->hide_sys();
8508 }
8509 }
8510 qApp->d_func()->sendSyntheticEnterLeave(widget);
8511#if QT_CONFIG(accessibility)
8512 if (!spontaneous) {
8513 QAccessibleEvent event(widget, QAccessible::ObjectHide);
8514 QAccessible::updateAccessibility(event: &event);
8515 }
8516#endif
8517 }
8518
8519 // If the window of this widget is not closed, then the leave event
8520 // will eventually handle the widget under mouse use case.
8521 // Otherwise, we need to explicitly handle it here.
8522 if (QWidget* widgetWindow = q->window();
8523 widgetWindow && widgetWindow->data->is_closing) {
8524 q->setAttribute(Qt::WA_UnderMouse, on: false);
8525 }
8526}
8527
8528/*!
8529 \internal
8530
8531 For windows, this is called from the QWidgetWindow::handleCloseEvent implementation,
8532 which QWidget::close indirectly calls by closing the QWindow. \a mode will be
8533 CloseWithEvent if QWidgetWindow::handleCloseEvent is called indirectly by
8534 QWindow::close, and CloseWithSpontaneousEvent if the close event originates from the
8535 system (i.e. the user clicked the close button in the title bar).
8536
8537 QDialog calls this method directly in its hide() implementation, which might be
8538 called from the QDialog::closeEvent override. \a mode will be set to CloseNoEvent
8539 to prevent recursion.
8540
8541 For non-windows, this is called directly by QWidget::close, and \a mode will be
8542 CloseWithEvent.
8543
8544 The function is also called by the QWidget destructor, with \a mode set to CloseNoEvent.
8545*/
8546bool QWidgetPrivate::handleClose(CloseMode mode)
8547{
8548 Q_Q(QWidget);
8549 qCDebug(lcWidgetShowHide) << "Handling close event for" << q;
8550
8551 if (data.is_closing)
8552 return true;
8553
8554 // We might not have initiated the close, so update the state now that we know
8555 data.is_closing = true;
8556
8557 QPointer<QWidget> that = q;
8558
8559 if (data.in_destructor)
8560 mode = CloseNoEvent;
8561
8562 if (mode != CloseNoEvent) {
8563 QCloseEvent e;
8564 if (mode == CloseWithSpontaneousEvent)
8565 QApplication::sendSpontaneousEvent(receiver: q, event: &e);
8566 else
8567 QCoreApplication::sendEvent(receiver: q, event: &e);
8568 if (!that.isNull() && !e.isAccepted()) {
8569 data.is_closing = false;
8570 return false;
8571 }
8572 }
8573
8574 // even for windows, make sure we deliver a hide event and that all children get hidden
8575 if (!that.isNull() && !q->isHidden())
8576 q->hide();
8577
8578 if (!that.isNull()) {
8579 data.is_closing = false;
8580 if (q->testAttribute(attribute: Qt::WA_DeleteOnClose)) {
8581 q->setAttribute(Qt::WA_DeleteOnClose, on: false);
8582 q->deleteLater();
8583 }
8584 }
8585 return true;
8586}
8587
8588
8589/*!
8590 Closes this widget. Returns \c true if the widget was closed;
8591 otherwise returns \c false.
8592
8593 First it sends the widget a QCloseEvent. The widget is
8594 \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
8595 the close event. If it \l{QEvent::ignore()}{ignores}
8596 the event, nothing happens. The default
8597 implementation of QWidget::closeEvent() accepts the close event.
8598
8599 If the widget has the Qt::WA_DeleteOnClose flag, the widget
8600 is also deleted. A close events is delivered to the widget no
8601 matter if the widget is visible or not.
8602
8603 The \l QGuiApplication::lastWindowClosed() signal is emitted when the
8604 last visible primary window (i.e. window with no parent) with the
8605 Qt::WA_QuitOnClose attribute set is closed. By default this
8606 attribute is set for all widgets except transient windows such as
8607 splash screens, tool windows, and popup menus.
8608
8609*/
8610
8611bool QWidget::close()
8612{
8613 return d_func()->close();
8614}
8615
8616bool QWidgetPrivate::close()
8617{
8618 // FIXME: We're not setting is_closing here, even though that would
8619 // make sense, as the code below will not end up in handleClose to
8620 // reset is_closing when there's a QWindow, but no QPlatformWindow,
8621 // and we can't assume close is synchronous so we can't reset it here.
8622
8623 // Close native widgets via QWindow::close() in order to run QWindow
8624 // close code. The QWidget-specific close code in handleClose() will
8625 // in this case be called from the Close event handler in QWidgetWindow.
8626 if (QWindow *widgetWindow = windowHandle()) {
8627 if (widgetWindow->isTopLevel())
8628 return widgetWindow->close();
8629 }
8630
8631 return handleClose(mode: QWidgetPrivate::CloseWithEvent);
8632}
8633
8634/*!
8635 \property QWidget::visible
8636 \brief whether the widget is visible
8637
8638 Calling setVisible(true) or show() sets the widget to visible
8639 status if all its parent widgets up to the window are visible. If
8640 an ancestor is not visible, the widget won't become visible until
8641 all its ancestors are shown. If its size or position has changed,
8642 Qt guarantees that a widget gets move and resize events just
8643 before it is shown. If the widget has not been resized yet, Qt
8644 will adjust the widget's size to a useful default using
8645 adjustSize().
8646
8647 Calling setVisible(false) or hide() hides a widget explicitly. An
8648 explicitly hidden widget will never become visible, even if all
8649 its ancestors become visible, unless you show it.
8650
8651 A widget receives show and hide events when its visibility status
8652 changes. Between a hide and a show event, there is no need to
8653 waste CPU cycles preparing or displaying information to the user.
8654 A video application, for example, might simply stop generating new
8655 frames.
8656
8657 A widget that happens to be obscured by other windows on the
8658 screen is considered to be visible. The same applies to iconified
8659 windows and windows that exist on another virtual
8660 desktop (on platforms that support this concept). A widget
8661 receives spontaneous show and hide events when its mapping status
8662 is changed by the window system, e.g. a spontaneous hide event
8663 when the user minimizes the window, and a spontaneous show event
8664 when the window is restored again.
8665
8666 You seldom have to reimplement the setVisible() function. If
8667 you need to change some settings before a widget is shown, use
8668 showEvent() instead. If you need to do some delayed initialization
8669 use the Polish event delivered to the event() function.
8670
8671 \sa show(), hide(), isHidden(), isVisibleTo(), isMinimized(),
8672 showEvent(), hideEvent()
8673*/
8674
8675
8676/*!
8677 Returns \c true if this widget would become visible if \a ancestor is
8678 shown; otherwise returns \c false.
8679
8680 The true case occurs if neither the widget itself nor any parent
8681 up to but excluding \a ancestor has been explicitly hidden.
8682
8683 This function will still return true if the widget is obscured by
8684 other windows on the screen, but could be physically visible if it
8685 or they were to be moved.
8686
8687 isVisibleTo(0) is identical to isVisible().
8688
8689 \sa show(), hide(), isVisible()
8690*/
8691
8692bool QWidget::isVisibleTo(const QWidget *ancestor) const
8693{
8694 if (!ancestor)
8695 return isVisible();
8696 const QWidget * w = this;
8697 while (!w->isHidden()
8698 && !w->isWindow()
8699 && w->parentWidget()
8700 && w->parentWidget() != ancestor)
8701 w = w->parentWidget();
8702 return !w->isHidden();
8703}
8704
8705
8706/*!
8707 Returns the unobscured region where paint events can occur.
8708
8709 For visible widgets, this is an approximation of the area not
8710 covered by other widgets; otherwise, this is an empty region.
8711
8712 The repaint() function calls this function if necessary, so in
8713 general you do not need to call it.
8714
8715*/
8716QRegion QWidget::visibleRegion() const
8717{
8718 Q_D(const QWidget);
8719
8720 QRect clipRect = d->clipRect();
8721 if (clipRect.isEmpty())
8722 return QRegion();
8723 QRegion r(clipRect);
8724 d->subtractOpaqueChildren(source&: r, clipRect);
8725 d->subtractOpaqueSiblings(sourceRegion&: r);
8726 return r;
8727}
8728
8729
8730QSize QWidgetPrivate::adjustedSize() const
8731{
8732 Q_Q(const QWidget);
8733
8734 QSize s = q->sizeHint();
8735
8736 if (q->isWindow()) {
8737 Qt::Orientations exp;
8738 if (layout) {
8739 if (layout->hasHeightForWidth())
8740 s.setHeight(layout->totalHeightForWidth(w: s.width()));
8741 exp = layout->expandingDirections();
8742 } else
8743 {
8744 if (q->sizePolicy().hasHeightForWidth())
8745 s.setHeight(q->heightForWidth(s.width()));
8746 exp = q->sizePolicy().expandingDirections();
8747 }
8748 if (exp & Qt::Horizontal)
8749 s.setWidth(qMax(a: s.width(), b: 200));
8750 if (exp & Qt::Vertical)
8751 s.setHeight(qMax(a: s.height(), b: 100));
8752
8753 QRect screen;
8754 if (const QScreen *screenAtPoint = QGuiApplication::screenAt(point: q->pos()))
8755 screen = screenAtPoint->geometry();
8756 else
8757 screen = QGuiApplication::primaryScreen()->geometry();
8758
8759 s.setWidth(qMin(a: s.width(), b: screen.width()*2/3));
8760 s.setHeight(qMin(a: s.height(), b: screen.height()*2/3));
8761
8762 if (QTLWExtra *extra = maybeTopData())
8763 extra->sizeAdjusted = true;
8764 }
8765
8766 if (!s.isValid()) {
8767 QRect r = q->childrenRect(); // get children rectangle
8768 if (r.isNull())
8769 return s;
8770 s = r.size() + QSize(2 * r.x(), 2 * r.y());
8771 }
8772
8773 return s;
8774}
8775
8776/*!
8777 Adjusts the size of the widget to fit its contents.
8778
8779 This function uses sizeHint() if it is valid, i.e., the size hint's width
8780 and height are \>= 0. Otherwise, it sets the size to the children
8781 rectangle that covers all child widgets (the union of all child widget
8782 rectangles).
8783
8784 For windows, the screen size is also taken into account. If the sizeHint()
8785 is less than (200, 100) and the size policy is \l{QSizePolicy::Expanding}
8786 {expanding}, the window will be at least (200, 100). The maximum size of
8787 a window is 2/3 of the screen's width and height.
8788
8789 \sa sizeHint(), childrenRect()
8790*/
8791
8792void QWidget::adjustSize()
8793{
8794 Q_D(QWidget);
8795 ensurePolished();
8796 QSize s = d->adjustedSize();
8797
8798 if (d->layout)
8799 d->layout->activate();
8800
8801 if (s.isValid())
8802 resize(s);
8803}
8804
8805
8806/*!
8807 \property QWidget::sizeHint
8808 \brief the recommended size for the widget
8809
8810 If the value of this property is an invalid size, no size is
8811 recommended.
8812
8813 The default implementation of sizeHint() returns an invalid size
8814 if there is no layout for this widget, and returns the layout's
8815 preferred size otherwise.
8816
8817 \sa QSize::isValid(), minimumSizeHint(), sizePolicy(),
8818 setMinimumSize(), updateGeometry()
8819*/
8820
8821QSize QWidget::sizeHint() const
8822{
8823 Q_D(const QWidget);
8824 if (d->layout)
8825 return d->layout->totalSizeHint();
8826 return QSize(-1, -1);
8827}
8828
8829/*!
8830 \property QWidget::minimumSizeHint
8831 \brief the recommended minimum size for the widget
8832
8833 If the value of this property is an invalid size, no minimum size
8834 is recommended.
8835
8836 The default implementation of minimumSizeHint() returns an invalid
8837 size if there is no layout for this widget, and returns the
8838 layout's minimum size otherwise. Most built-in widgets reimplement
8839 minimumSizeHint().
8840
8841 \l QLayout will never resize a widget to a size smaller than the
8842 minimum size hint unless minimumSize() is set or the size policy is
8843 set to QSizePolicy::Ignore. If minimumSize() is set, the minimum
8844 size hint will be ignored.
8845
8846 \sa QSize::isValid(), resize(), setMinimumSize(), sizePolicy()
8847*/
8848QSize QWidget::minimumSizeHint() const
8849{
8850 Q_D(const QWidget);
8851 if (d->layout)
8852 return d->layout->totalMinimumSize();
8853 return QSize(-1, -1);
8854}
8855
8856
8857/*!
8858 \fn QWidget *QWidget::parentWidget() const
8859
8860 Returns the parent of this widget, or \nullptr if it does not have any
8861 parent widget.
8862*/
8863
8864
8865/*!
8866 Returns \c true if this widget is a parent, (or grandparent and so on
8867 to any level), of the given \a child, and both widgets are within
8868 the same window; otherwise returns \c false.
8869*/
8870
8871bool QWidget::isAncestorOf(const QWidget *child) const
8872{
8873 while (child) {
8874 if (child == this)
8875 return true;
8876 if (child->isWindow())
8877 return false;
8878 child = child->parentWidget();
8879 }
8880 return false;
8881}
8882
8883/*****************************************************************************
8884 QWidget event handling
8885 *****************************************************************************/
8886
8887/*!
8888 This is the main event handler; it handles event \a event. You can
8889 reimplement this function in a subclass, but we recommend using
8890 one of the specialized event handlers instead.
8891
8892 Key press and release events are treated differently from other
8893 events. event() checks for Tab and Shift+Tab and tries to move the
8894 focus appropriately. If there is no widget to move the focus to
8895 (or the key press is not Tab or Shift+Tab), event() calls
8896 keyPressEvent().
8897
8898 Mouse and tablet event handling is also slightly special: only
8899 when the widget is \l enabled, event() will call the specialized
8900 handlers such as mousePressEvent(); otherwise it will discard the
8901 event.
8902
8903 This function returns \c true if the event was recognized, otherwise
8904 it returns \c false. If the recognized event was accepted (see \l
8905 QEvent::accepted), any further processing such as event
8906 propagation to the parent widget stops.
8907
8908 \sa closeEvent(), focusInEvent(), focusOutEvent(), enterEvent(),
8909 keyPressEvent(), keyReleaseEvent(), leaveEvent(),
8910 mouseDoubleClickEvent(), mouseMoveEvent(), mousePressEvent(),
8911 mouseReleaseEvent(), moveEvent(), paintEvent(), resizeEvent(),
8912 QObject::event(), QObject::timerEvent()
8913*/
8914
8915bool QWidget::event(QEvent *event)
8916{
8917 Q_D(QWidget);
8918
8919 // ignore mouse and key events when disabled
8920 if (!isEnabled()) {
8921 switch(event->type()) {
8922 case QEvent::TabletPress:
8923 case QEvent::TabletRelease:
8924 case QEvent::TabletMove:
8925 case QEvent::MouseButtonPress:
8926 case QEvent::MouseButtonRelease:
8927 case QEvent::MouseButtonDblClick:
8928 case QEvent::MouseMove:
8929 case QEvent::TouchBegin:
8930 case QEvent::TouchUpdate:
8931 case QEvent::TouchEnd:
8932 case QEvent::TouchCancel:
8933 case QEvent::ContextMenu:
8934 case QEvent::KeyPress:
8935 case QEvent::KeyRelease:
8936#if QT_CONFIG(wheelevent)
8937 case QEvent::Wheel:
8938#endif
8939 return false;
8940 default:
8941 break;
8942 }
8943 }
8944 switch (event->type()) {
8945 case QEvent::PlatformSurface: {
8946 // Sync up QWidget's view of whether or not the widget has been created
8947 switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
8948 case QPlatformSurfaceEvent::SurfaceCreated:
8949 if (!testAttribute(attribute: Qt::WA_WState_Created))
8950 create();
8951 break;
8952 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
8953 if (testAttribute(attribute: Qt::WA_WState_Created)) {
8954 // Child windows have already been destroyed by QWindow,
8955 // so we skip them here.
8956 destroy(destroyWindow: false, destroySubWindows: false);
8957 }
8958 break;
8959 }
8960 break;
8961 }
8962 case QEvent::MouseMove:
8963 mouseMoveEvent(event: (QMouseEvent*)event);
8964 break;
8965
8966 case QEvent::MouseButtonPress:
8967 mousePressEvent(event: (QMouseEvent*)event);
8968 break;
8969
8970 case QEvent::MouseButtonRelease:
8971 mouseReleaseEvent(event: (QMouseEvent*)event);
8972 break;
8973
8974 case QEvent::MouseButtonDblClick:
8975 mouseDoubleClickEvent(event: (QMouseEvent*)event);
8976 break;
8977#if QT_CONFIG(wheelevent)
8978 case QEvent::Wheel:
8979 wheelEvent(event: (QWheelEvent*)event);
8980 break;
8981#endif
8982#if QT_CONFIG(tabletevent)
8983 case QEvent::TabletMove:
8984 if (static_cast<QTabletEvent *>(event)->buttons() == Qt::NoButton && !testAttribute(attribute: Qt::WA_TabletTracking))
8985 break;
8986 Q_FALLTHROUGH();
8987 case QEvent::TabletPress:
8988 case QEvent::TabletRelease:
8989 tabletEvent(event: (QTabletEvent*)event);
8990 break;
8991#endif
8992 case QEvent::KeyPress: {
8993 QKeyEvent *k = static_cast<QKeyEvent *>(event);
8994 bool res = false;
8995 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
8996 if (k->key() == Qt::Key_Backtab
8997 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
8998 res = focusNextPrevChild(next: false);
8999 else if (k->key() == Qt::Key_Tab)
9000 res = focusNextPrevChild(next: true);
9001 if (res)
9002 break;
9003 }
9004 keyPressEvent(event: k);
9005#ifdef QT_KEYPAD_NAVIGATION
9006 if (!k->isAccepted() && QApplication::keypadNavigationEnabled()
9007 && !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier))) {
9008 if (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder) {
9009 if (k->key() == Qt::Key_Up)
9010 res = focusNextPrevChild(false);
9011 else if (k->key() == Qt::Key_Down)
9012 res = focusNextPrevChild(true);
9013 } else if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
9014 if (k->key() == Qt::Key_Up)
9015 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionNorth);
9016 else if (k->key() == Qt::Key_Right)
9017 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionEast);
9018 else if (k->key() == Qt::Key_Down)
9019 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionSouth);
9020 else if (k->key() == Qt::Key_Left)
9021 res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionWest);
9022 }
9023 if (res) {
9024 k->accept();
9025 break;
9026 }
9027 }
9028#endif
9029#if QT_CONFIG(whatsthis)
9030 if (!k->isAccepted()
9031 && k->modifiers() & Qt::ShiftModifier && k->key() == Qt::Key_F1
9032 && d->whatsThis.size()) {
9033 QWhatsThis::showText(pos: mapToGlobal(inputMethodQuery(Qt::ImCursorRectangle).toRect().center()), text: d->whatsThis, w: this);
9034 k->accept();
9035 }
9036#endif
9037 }
9038 break;
9039
9040 case QEvent::KeyRelease:
9041 keyReleaseEvent(event: (QKeyEvent*)event);
9042 Q_FALLTHROUGH();
9043 case QEvent::ShortcutOverride:
9044 break;
9045
9046 case QEvent::InputMethod:
9047 inputMethodEvent((QInputMethodEvent *) event);
9048 break;
9049
9050 case QEvent::InputMethodQuery: {
9051 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(event);
9052 Qt::InputMethodQueries queries = query->queries();
9053 for (uint i = 0; i < 32; ++i) {
9054 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
9055 if (q) {
9056 QVariant v = inputMethodQuery(q);
9057 if (q == Qt::ImEnabled && !v.isValid() && isEnabled()) {
9058 // Qt:ImEnabled was added in Qt 5.3. So not all widgets support it, even
9059 // if they implement IM otherwise (by overriding inputMethodQuery()). Instead
9060 // they set the widget attribute Qt::WA_InputMethodEnabled. But this attribute
9061 // will only be set if the widget supports IM _and_ is not read-only. So for
9062 // read-only widgets, not all IM features will be supported when ImEnabled is
9063 // not implemented explicitly (e.g selection handles for read-only widgets on iOS).
9064 v = QVariant(testAttribute(attribute: Qt::WA_InputMethodEnabled));
9065 }
9066 query->setValue(query: q, value: v);
9067 }
9068 }
9069 query->accept();
9070 }
9071 break;
9072
9073 case QEvent::PolishRequest:
9074 ensurePolished();
9075 break;
9076
9077 case QEvent::Polish: {
9078 style()->polish(widget: this);
9079 setAttribute(Qt::WA_WState_Polished);
9080 if (!QApplication::font(this).isCopyOf(QApplication::font()))
9081 d->resolveFont();
9082 if (!QApplication::palette(this).isCopyOf(p: QGuiApplication::palette()))
9083 d->resolvePalette();
9084 }
9085 break;
9086
9087 case QEvent::ApplicationWindowIconChange:
9088 if (isWindow() && !testAttribute(attribute: Qt::WA_SetWindowIcon)) {
9089 d->setWindowIcon_sys();
9090 d->setWindowIcon_helper();
9091 }
9092 break;
9093 case QEvent::FocusIn:
9094 focusInEvent(event: (QFocusEvent*)event);
9095 d->updateWidgetTransform(event);
9096 break;
9097
9098 case QEvent::FocusOut:
9099 focusOutEvent(event: (QFocusEvent*)event);
9100 break;
9101
9102 case QEvent::Enter:
9103#if QT_CONFIG(statustip)
9104 if (d->statusTip.size()) {
9105 QStatusTipEvent tip(d->statusTip);
9106 QCoreApplication::sendEvent(receiver: const_cast<QWidget *>(this), event: &tip);
9107 }
9108#endif
9109 enterEvent(event: static_cast<QEnterEvent*>(event));
9110 break;
9111
9112 case QEvent::Leave:
9113#if QT_CONFIG(statustip)
9114 if (d->statusTip.size()) {
9115 QString empty;
9116 QStatusTipEvent tip(empty);
9117 QCoreApplication::sendEvent(receiver: const_cast<QWidget *>(this), event: &tip);
9118 }
9119#endif
9120 leaveEvent(event);
9121 break;
9122
9123 case QEvent::HoverEnter:
9124 case QEvent::HoverLeave:
9125 update();
9126 break;
9127
9128 case QEvent::Paint:
9129 // At this point the event has to be delivered, regardless
9130 // whether the widget isVisible() or not because it
9131 // already went through the filters
9132 paintEvent(event: (QPaintEvent*)event);
9133 break;
9134
9135 case QEvent::Move:
9136 moveEvent(event: (QMoveEvent*)event);
9137 d->updateWidgetTransform(event);
9138 break;
9139
9140 case QEvent::Resize:
9141 resizeEvent(event: (QResizeEvent*)event);
9142 d->updateWidgetTransform(event);
9143 break;
9144
9145 case QEvent::Close:
9146 closeEvent(event: (QCloseEvent *)event);
9147 break;
9148
9149#ifndef QT_NO_CONTEXTMENU
9150 case QEvent::ContextMenu:
9151 switch (data->context_menu_policy) {
9152 case Qt::PreventContextMenu:
9153 break;
9154 case Qt::DefaultContextMenu:
9155 contextMenuEvent(event: static_cast<QContextMenuEvent *>(event));
9156 break;
9157 case Qt::CustomContextMenu:
9158 emit customContextMenuRequested(pos: static_cast<QContextMenuEvent *>(event)->pos());
9159 break;
9160#if QT_CONFIG(menu)
9161 case Qt::ActionsContextMenu:
9162 if (d->actions.size()) {
9163 QMenu::exec(actions: d->actions, pos: static_cast<QContextMenuEvent *>(event)->globalPos(),
9164 at: nullptr, parent: this);
9165 break;
9166 }
9167 Q_FALLTHROUGH();
9168#endif
9169 default:
9170 event->ignore();
9171 break;
9172 }
9173 break;
9174#endif // QT_NO_CONTEXTMENU
9175
9176#if QT_CONFIG(draganddrop)
9177 case QEvent::Drop:
9178 dropEvent(event: (QDropEvent*) event);
9179 break;
9180
9181 case QEvent::DragEnter:
9182 dragEnterEvent(event: (QDragEnterEvent*) event);
9183 break;
9184
9185 case QEvent::DragMove:
9186 dragMoveEvent(event: (QDragMoveEvent*) event);
9187 break;
9188
9189 case QEvent::DragLeave:
9190 dragLeaveEvent(event: (QDragLeaveEvent*) event);
9191 break;
9192#endif
9193
9194 case QEvent::Show:
9195 showEvent(event: (QShowEvent*) event);
9196 break;
9197
9198 case QEvent::Hide:
9199 hideEvent(event: (QHideEvent*) event);
9200 break;
9201
9202 case QEvent::ShowWindowRequest:
9203 if (!isHidden())
9204 d->show_sys();
9205 break;
9206
9207 case QEvent::ApplicationFontChange:
9208 d->resolveFont();
9209 break;
9210 case QEvent::ApplicationPaletteChange:
9211 if (!(windowType() == Qt::Desktop))
9212 d->resolvePalette();
9213 break;
9214
9215 case QEvent::ToolBarChange:
9216 case QEvent::ActivationChange:
9217 case QEvent::EnabledChange:
9218 case QEvent::FontChange:
9219 case QEvent::StyleChange:
9220 case QEvent::PaletteChange:
9221 case QEvent::WindowTitleChange:
9222 case QEvent::IconTextChange:
9223 case QEvent::ModifiedChange:
9224 case QEvent::MouseTrackingChange:
9225 case QEvent::TabletTrackingChange:
9226 case QEvent::ParentChange:
9227 case QEvent::LocaleChange:
9228 case QEvent::MacSizeChange:
9229 case QEvent::ContentsRectChange:
9230 case QEvent::ThemeChange:
9231 case QEvent::ReadOnlyChange:
9232 changeEvent(event);
9233 break;
9234
9235 case QEvent::WindowStateChange: {
9236 const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
9237 if (wasMinimized != isMinimized()) {
9238 QWidget *widget = const_cast<QWidget *>(this);
9239 if (wasMinimized) {
9240 // Always send the spontaneous events here, otherwise it can break the application!
9241 if (!d->childrenShownByExpose) {
9242 // Show widgets only when they are not yet shown by the expose event
9243 d->showChildren(spontaneous: true);
9244 QShowEvent showEvent;
9245 QCoreApplication::sendSpontaneousEvent(receiver: widget, event: &showEvent);
9246 }
9247 d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
9248 } else {
9249 QHideEvent hideEvent;
9250 QCoreApplication::sendSpontaneousEvent(receiver: widget, event: &hideEvent);
9251 d->hideChildren(spontaneous: true);
9252 d->childrenHiddenByWState = true;
9253 }
9254 d->childrenShownByExpose = false; // Set it always to "false" when window state changes
9255 }
9256 changeEvent(event);
9257 }
9258 break;
9259
9260 case QEvent::WindowActivate:
9261 case QEvent::WindowDeactivate: {
9262 if (isVisible() && !palette().isEqual(cr1: QPalette::Active, cr2: QPalette::Inactive))
9263 update();
9264 QList<QObject*> childList = d->children;
9265 for (int i = 0; i < childList.size(); ++i) {
9266 QWidget *w = qobject_cast<QWidget *>(o: childList.at(i));
9267 if (w && w->isVisible() && !w->isWindow())
9268 QCoreApplication::sendEvent(receiver: w, event);
9269 }
9270 break; }
9271
9272 case QEvent::LanguageChange:
9273 changeEvent(event);
9274 {
9275 QList<QObject*> childList = d->children;
9276 for (int i = 0; i < childList.size(); ++i) {
9277 QObject *o = childList.at(i);
9278 if (o)
9279 QCoreApplication::sendEvent(receiver: o, event);
9280 }
9281 }
9282 update();
9283 break;
9284
9285 case QEvent::ApplicationLayoutDirectionChange:
9286 d->resolveLayoutDirection();
9287 break;
9288
9289 case QEvent::LayoutDirectionChange:
9290 if (d->layout)
9291 d->layout->invalidate();
9292 update();
9293 changeEvent(event);
9294 break;
9295 case QEvent::UpdateRequest:
9296 d->syncBackingStore();
9297 break;
9298 case QEvent::UpdateLater:
9299 update(static_cast<QUpdateLaterEvent*>(event)->region());
9300 break;
9301 case QEvent::StyleAnimationUpdate:
9302 if (isVisible() && !window()->isMinimized()) {
9303 event->accept();
9304 update();
9305 }
9306 break;
9307
9308 case QEvent::WindowBlocked:
9309 case QEvent::WindowUnblocked:
9310 if (!d->children.isEmpty()) {
9311 QWidget *modalWidget = QApplication::activeModalWidget();
9312 for (int i = 0; i < d->children.size(); ++i) {
9313 QObject *o = d->children.at(i);
9314 if (o && o != modalWidget && o->isWidgetType()) {
9315 QWidget *w = static_cast<QWidget *>(o);
9316 // do not forward the event to child windows; QApplication does this for us
9317 if (!w->isWindow())
9318 QCoreApplication::sendEvent(receiver: w, event);
9319 }
9320 }
9321 }
9322 break;
9323#if QT_CONFIG(tooltip)
9324 case QEvent::ToolTip:
9325 if (!d->toolTip.isEmpty())
9326 QToolTip::showText(pos: static_cast<QHelpEvent*>(event)->globalPos(), text: d->toolTip, w: this, rect: QRect(), msecShowTime: d->toolTipDuration);
9327 else
9328 event->ignore();
9329 break;
9330#endif
9331#if QT_CONFIG(whatsthis)
9332 case QEvent::WhatsThis:
9333 if (d->whatsThis.size())
9334 QWhatsThis::showText(pos: static_cast<QHelpEvent *>(event)->globalPos(), text: d->whatsThis, w: this);
9335 else
9336 event->ignore();
9337 break;
9338 case QEvent::QueryWhatsThis:
9339 if (d->whatsThis.isEmpty())
9340 event->ignore();
9341 break;
9342#endif
9343 case QEvent::EmbeddingControl:
9344 d->topData()->frameStrut.setCoords(xp1: 0 ,yp1: 0, xp2: 0, yp2: 0);
9345 data->fstrut_dirty = false;
9346 break;
9347#ifndef QT_NO_ACTION
9348 case QEvent::ActionAdded:
9349 case QEvent::ActionRemoved:
9350 case QEvent::ActionChanged:
9351 actionEvent(event: (QActionEvent*)event);
9352 break;
9353#endif
9354
9355 case QEvent::KeyboardLayoutChange:
9356 {
9357 changeEvent(event);
9358
9359 // inform children of the change
9360 QList<QObject*> childList = d->children;
9361 for (int i = 0; i < childList.size(); ++i) {
9362 QWidget *w = qobject_cast<QWidget *>(o: childList.at(i));
9363 if (w && w->isVisible() && !w->isWindow())
9364 QCoreApplication::sendEvent(receiver: w, event);
9365 }
9366 break;
9367 }
9368 case QEvent::TouchBegin:
9369 case QEvent::TouchUpdate:
9370 case QEvent::TouchEnd:
9371 case QEvent::TouchCancel:
9372 {
9373 event->ignore();
9374 break;
9375 }
9376#ifndef QT_NO_GESTURES
9377 case QEvent::Gesture:
9378 event->ignore();
9379 break;
9380#endif
9381 case QEvent::ScreenChangeInternal:
9382 if (const QTLWExtra *te = d->maybeTopData()) {
9383 const QWindow *win = te->window;
9384 d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
9385 }
9386 break;
9387 case QEvent::DevicePixelRatioChange:
9388 if (d->data.fnt.d->dpi != logicalDpiY())
9389 d->updateFont(font: d->data.fnt);
9390 d->renderToTextureReallyDirty = 1;
9391 break;
9392 case QEvent::DynamicPropertyChange: {
9393 const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
9394 if (propName.size() == 13 && !qstrncmp(str1: propName, str2: "_q_customDpi", len: 12)) {
9395 uint value = property(name: propName.constData()).toUInt();
9396 if (!d->extra)
9397 d->createExtra();
9398 const char axis = propName.at(i: 12);
9399 if (axis == 'X')
9400 d->extra->customDpiX = value;
9401 else if (axis == 'Y')
9402 d->extra->customDpiY = value;
9403 d->updateFont(font: d->data.fnt);
9404 }
9405 if (windowHandle() && !qstrncmp(str1: propName, str2: "_q_platform_", len: 12))
9406 windowHandle()->setProperty(name: propName, value: property(name: propName));
9407 Q_FALLTHROUGH();
9408 }
9409 default:
9410 return QObject::event(event);
9411 }
9412 return true;
9413}
9414
9415/*!
9416 This event handler can be reimplemented to handle state changes.
9417
9418 The state being changed in this event can be retrieved through the \a event
9419 supplied.
9420
9421 Change events include: QEvent::ToolBarChange,
9422 QEvent::ActivationChange, QEvent::EnabledChange, QEvent::FontChange,
9423 QEvent::StyleChange, QEvent::PaletteChange,
9424 QEvent::WindowTitleChange, QEvent::IconTextChange,
9425 QEvent::ModifiedChange, QEvent::MouseTrackingChange,
9426 QEvent::ParentChange, QEvent::WindowStateChange,
9427 QEvent::LanguageChange, QEvent::LocaleChange,
9428 QEvent::LayoutDirectionChange, QEvent::ReadOnlyChange.
9429
9430*/
9431void QWidget::changeEvent(QEvent * event)
9432{
9433 switch(event->type()) {
9434 case QEvent::EnabledChange: {
9435 update();
9436#if QT_CONFIG(accessibility)
9437 QAccessible::State s;
9438 s.disabled = true;
9439 QAccessibleStateChangeEvent event(this, s);
9440 QAccessible::updateAccessibility(event: &event);
9441#endif
9442 break;
9443 }
9444
9445 case QEvent::FontChange:
9446 case QEvent::StyleChange: {
9447 Q_D(QWidget);
9448 update();
9449 updateGeometry();
9450 if (d->layout)
9451 d->layout->invalidate();
9452 break;
9453 }
9454
9455 case QEvent::PaletteChange:
9456 update();
9457 break;
9458
9459 case QEvent::ThemeChange:
9460 if (QGuiApplication::desktopSettingsAware() && windowType() != Qt::Desktop
9461 && qApp && !QCoreApplication::closingDown()) {
9462 if (testAttribute(attribute: Qt::WA_WState_Polished))
9463 QApplication::style()->unpolish(widget: this);
9464 if (testAttribute(attribute: Qt::WA_WState_Polished))
9465 QApplication::style()->polish(widget: this);
9466 QEvent styleChangedEvent(QEvent::StyleChange);
9467 QCoreApplication::sendEvent(receiver: this, event: &styleChangedEvent);
9468 if (isVisible())
9469 update();
9470 }
9471 break;
9472
9473#ifdef Q_OS_MAC
9474 case QEvent::MacSizeChange:
9475 updateGeometry();
9476 break;
9477#endif
9478
9479 default:
9480 break;
9481 }
9482}
9483
9484/*!
9485 This event handler, for event \a event, can be reimplemented in a
9486 subclass to receive mouse move events for the widget.
9487
9488 If mouse tracking is switched off, mouse move events only occur if
9489 a mouse button is pressed while the mouse is being moved. If mouse
9490 tracking is switched on, mouse move events occur even if no mouse
9491 button is pressed.
9492
9493 QMouseEvent::pos() reports the position of the mouse cursor,
9494 relative to this widget. For press and release events, the
9495 position is usually the same as the position of the last mouse
9496 move event, but it might be different if the user's hand shakes.
9497 This is a feature of the underlying window system, not Qt.
9498
9499 If you want to show a tooltip immediately, while the mouse is
9500 moving (e.g., to get the mouse coordinates with QMouseEvent::pos()
9501 and show them as a tooltip), you must first enable mouse tracking
9502 as described above. Then, to ensure that the tooltip is updated
9503 immediately, you must call QToolTip::showText() instead of
9504 setToolTip() in your implementation of mouseMoveEvent().
9505
9506 \sa setMouseTracking(), mousePressEvent(), mouseReleaseEvent(),
9507 mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}
9508*/
9509
9510void QWidget::mouseMoveEvent(QMouseEvent *event)
9511{
9512 event->ignore();
9513}
9514
9515/*!
9516 This event handler, for event \a event, can be reimplemented in a
9517 subclass to receive mouse press events for the widget.
9518
9519 If you create new widgets in the mousePressEvent() the
9520 mouseReleaseEvent() may not end up where you expect, depending on
9521 the underlying window system (or X11 window manager), the widgets'
9522 location and maybe more.
9523
9524 The default implementation implements the closing of popup widgets
9525 when you click outside the window. For other widget types it does
9526 nothing.
9527
9528 \sa mouseReleaseEvent(), mouseDoubleClickEvent(),
9529 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9530*/
9531
9532void QWidget::mousePressEvent(QMouseEvent *event)
9533{
9534 event->ignore();
9535 if ((windowType() == Qt::Popup)) {
9536 event->accept();
9537 QWidget* w;
9538 while ((w = QApplication::activePopupWidget()) && w != this){
9539 w->close();
9540 if (QApplication::activePopupWidget() == w) // widget does not want to disappear
9541 w->hide(); // hide at least
9542 }
9543 if (!rect().contains(p: event->position().toPoint())){
9544 close();
9545 }
9546 }
9547}
9548
9549/*!
9550 This event handler, for event \a event, can be reimplemented in a
9551 subclass to receive mouse release events for the widget.
9552
9553 \sa mousePressEvent(), mouseDoubleClickEvent(),
9554 mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}
9555*/
9556
9557void QWidget::mouseReleaseEvent(QMouseEvent *event)
9558{
9559 event->ignore();
9560}
9561
9562/*!
9563 This event handler, for event \a event, can be reimplemented in a
9564 subclass to receive mouse double click events for the widget.
9565
9566 The default implementation calls mousePressEvent().
9567
9568 \note The widget will also receive mouse press and mouse release
9569 events in addition to the double click event. And if another widget
9570 that overlaps this widget disappears in response to press or
9571 release events, then this widget will only receive the double click
9572 event. It is up to the developer to ensure that the application
9573 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(key: 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 events 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(attribute: 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(query: 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(queries: 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(receiver: const_cast<QWidget *>(this), event: &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(receiver: d->parent, event: &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(msg: "QWidget::setLayout: Cannot set layout to 0");
10293 return;
10294 }
10295 if (layout()) {
10296 if (Q_UNLIKELY(layout() != l))
10297 qWarning(msg: "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(msg: "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(mw: 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 *>(o: children.at(i));
10491 if (!child || child->isWindow() || child->isHidden() || child->testAttribute(attribute: 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(p: childPoint))
10502 continue;
10503
10504 // Do the same for the child's descendants.
10505 if (QWidget *w = child->d_func()->childAtRecursiveHelper(p: 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(receiver: parent, event: 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(forceUpdate: 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 \sa setWindowFlags(), windowFlags(), windowType()
10579*/
10580void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
10581{
10582 Q_D(QWidget);
10583 if (on)
10584 d->setWindowFlags(data->window_flags | flag);
10585 else
10586 d->setWindowFlags(data->window_flags & ~flag);
10587}
10588
10589/*! \internal
10590
10591 Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
10592*/
10593void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
10594{
10595 Q_Q(QWidget);
10596 if (q->data->window_flags == flags)
10597 return;
10598
10599 if ((q->data->window_flags | flags) & Qt::Window) {
10600 // the old type was a window and/or the new type is a window
10601 QPoint oldPos = q->pos();
10602 bool visible = q->isVisible();
10603 const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
10604 q->setParent(parent: q->parentWidget(), f: flags);
10605
10606 // if both types are windows or neither of them are, we restore
10607 // the old position
10608 if (!windowFlagChanged && (visible || q->testAttribute(attribute: Qt::WA_Moved)))
10609 q->move(p: oldPos);
10610 // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
10611 adjustQuitOnCloseAttribute();
10612 } else {
10613 q->data->window_flags = flags;
10614 }
10615}
10616
10617/*!
10618 Sets the window flags for the widget to \a flags,
10619 \e without telling the window system.
10620
10621 \warning Do not call this function unless you really know what
10622 you're doing.
10623
10624 \sa setWindowFlags()
10625*/
10626void QWidget::overrideWindowFlags(Qt::WindowFlags flags)
10627{
10628 data->window_flags = flags;
10629}
10630
10631/*!
10632 \fn Qt::WindowType QWidget::windowType() const
10633
10634 Returns the window type of this widget. This is identical to
10635 windowFlags() & Qt::WindowType_Mask.
10636
10637 \sa windowFlags
10638*/
10639
10640/*!
10641 Sets the parent of the widget to \a parent, and resets the window
10642 flags. The widget is moved to position (0, 0) in its new parent.
10643
10644 If the new parent widget is in a different window, the
10645 reparented widget and its children are appended to the end of the
10646 \l{setFocusPolicy()}{tab chain} of the new parent
10647 widget, in the same internal order as before. If one of the moved
10648 widgets had keyboard focus, setParent() calls clearFocus() for that
10649 widget.
10650
10651 If the new parent widget is in the same window as the
10652 old parent, setting the parent doesn't change the tab order or
10653 keyboard focus.
10654
10655 If the "new" parent widget is the old parent widget, this function
10656 does nothing.
10657
10658 \note The widget becomes invisible as part of changing its parent,
10659 even if it was previously visible. You must call show() to make the
10660 widget visible again.
10661
10662 \warning It is very unlikely that you will ever need this
10663 function. If you have a widget that changes its content
10664 dynamically, it is far easier to use \l QStackedWidget.
10665
10666 \sa setWindowFlags()
10667*/
10668void QWidget::setParent(QWidget *parent)
10669{
10670 if (parent == parentWidget())
10671 return;
10672 setParent(parent: (QWidget*)parent, f: windowFlags() & ~Qt::WindowType_Mask);
10673}
10674
10675void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType)
10676{
10677 QWidgetPrivate *d = QWidgetPrivate::get(w: widget);
10678 if (d->renderToTexture) {
10679 QEvent e(eventType);
10680 QCoreApplication::sendEvent(receiver: widget, event: &e);
10681 }
10682
10683 for (int i = 0; i < d->children.size(); ++i) {
10684 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
10685 if (w && !w->isWindow())
10686 qSendWindowChangeToTextureChildrenRecursively(widget: w, eventType);
10687 }
10688
10689 // Notify QWidgetWindow after we've notified all child QWidgets
10690 if (auto *window = d->windowHandle(mode: QWidgetPrivate::WindowHandleMode::Direct)) {
10691 QEvent e(eventType);
10692 QCoreApplication::sendEvent(receiver: window, event: &e);
10693 }
10694}
10695
10696/*!
10697 \overload
10698
10699 This function also takes widget flags, \a f as an argument.
10700*/
10701
10702void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
10703{
10704 Q_D(QWidget);
10705 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
10706#ifdef QT_DEBUG
10707 const auto checkForParentChildLoops = qScopeGuard(f: [&](){
10708 int depth = 0;
10709 auto p = parentWidget();
10710 while (p) {
10711 if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
10712 qWarning(msg: "QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
10713 "this is undefined behavior",
10714 this, metaObject()->className(), qPrintable(objectName()));
10715 }
10716 p = p->parentWidget();
10717 }
10718 });
10719#endif
10720
10721 const bool resized = testAttribute(attribute: Qt::WA_Resized);
10722 const bool wasCreated = testAttribute(attribute: Qt::WA_WState_Created);
10723 QWidget *oldtlw = window();
10724 Q_ASSERT(oldtlw);
10725 QWidget *oldParentWithWindow = d->closestParentWidgetWithWindowHandle();
10726
10727 if (f & Qt::Window) // Frame geometry likely changes, refresh.
10728 d->data.fstrut_dirty = true;
10729
10730 QWidget *desktopWidget = nullptr;
10731 if (parent && parent->windowType() == Qt::Desktop)
10732 desktopWidget = parent;
10733 bool newParent = (parent != parentWidget()) || desktopWidget;
10734
10735 if (newParent && parent && !desktopWidget) {
10736 if (testAttribute(attribute: Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(attribute: Qt::AA_DontCreateNativeWidgetSiblings))
10737 parent->d_func()->enforceNativeChildren();
10738 else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(attribute: Qt::WA_PaintOnScreen))
10739 setAttribute(Qt::WA_NativeWindow);
10740 }
10741
10742 if (wasCreated) {
10743 if (!testAttribute(attribute: Qt::WA_WState_Hidden)) {
10744 // Hiding the widget will set WA_WState_Hidden as well, which would
10745 // normally require the widget to be explicitly shown again to become
10746 // visible, even as a child widget. But we refine this value later in
10747 // setParent_sys(), applying WA_WState_Hidden based on whether the
10748 // widget is a top level or not.
10749 hide();
10750
10751 // We reset WA_WState_ExplicitShowHide here, likely as a remnant of
10752 // when we only had QWidget::setVisible(), which is treated as an
10753 // explicit show/hide. Nowadays we have QWidgetPrivate::setVisible(),
10754 // that allows us to hide a widget without affecting ExplicitShowHide.
10755 // Though it can be argued that ExplicitShowHide should reflect the
10756 // last update of the widget's state, so if we hide the widget as a
10757 // side effect of changing parent, perhaps we _should_ reset it?
10758 setAttribute(Qt::WA_WState_ExplicitShowHide, on: false);
10759 }
10760 if (newParent) {
10761 QEvent e(QEvent::ParentAboutToChange);
10762 QCoreApplication::sendEvent(receiver: this, event: &e);
10763 }
10764 }
10765
10766 // texture-based widgets need a pre-notification when their associated top-level window changes
10767 // This is not under the wasCreated/newParent conditions above in order to also play nice with QDockWidget.
10768 const bool oldWidgetUsesRhiFlush = oldParentWithWindow ? oldParentWithWindow->d_func()->usesRhiFlush
10769 : oldtlw->d_func()->usesRhiFlush;
10770 if (oldWidgetUsesRhiFlush && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw)))
10771 qSendWindowChangeToTextureChildrenRecursively(widget: this, eventType: QEvent::WindowAboutToChangeInternal);
10772
10773 // If we get parented into another window, children will be folded
10774 // into the new parent's focus chain, so clear focus now.
10775 if (newParent && isAncestorOf(child: focusWidget()) && !(f & Qt::Window))
10776 focusWidget()->clearFocus();
10777
10778 d->setParent_sys(parent, f);
10779
10780 if (desktopWidget)
10781 parent = nullptr;
10782
10783 if (d->textureChildSeen && parent) {
10784 // set the textureChildSeen flag up the whole parent chain
10785 QWidgetPrivate::get(w: parent)->setTextureChildSeen();
10786 }
10787
10788 if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
10789 if (newParent)
10790 oldPaintManager->removeDirtyWidget(w: this);
10791 // Move the widget and all its static children from
10792 // the old backing store to the new one.
10793 oldPaintManager->moveStaticWidgets(reparented: this);
10794 }
10795
10796 d->reparentFocusWidgets(oldtlw);
10797 setAttribute(Qt::WA_Resized, on: resized);
10798
10799 const bool useStyleSheetPropagationInWidgetStyles =
10800 QCoreApplication::testAttribute(attribute: Qt::AA_UseStyleSheetPropagationInWidgetStyles);
10801
10802 if (!useStyleSheetPropagationInWidgetStyles && !testAttribute(attribute: Qt::WA_StyleSheet)
10803 && (!parent || !parent->testAttribute(attribute: Qt::WA_StyleSheet))) {
10804 // if the parent has a font set or inherited, then propagate the mask to the new child
10805 if (parent) {
10806 const auto pd = parent->d_func();
10807 d->inheritedFontResolveMask = pd->directFontResolveMask | pd->inheritedFontResolveMask;
10808 d->inheritedPaletteResolveMask = pd->directPaletteResolveMask | pd->inheritedPaletteResolveMask;
10809 }
10810 d->resolveFont();
10811 d->resolvePalette();
10812 }
10813 d->resolveLayoutDirection();
10814 d->resolveLocale();
10815
10816 // Note: GL widgets under WGL or EGL will always need a ParentChange
10817 // event to handle recreation/rebinding of the GL context, hence the
10818 // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
10819 // platforms).
10820 if (newParent || !wasCreated
10821#if QT_CONFIG(opengles2)
10822 || (f & Qt::MSWindowsOwnDC)
10823#endif
10824 ) {
10825 // propagate enabled updates enabled state to non-windows
10826 if (!isWindow()) {
10827 if (!testAttribute(attribute: Qt::WA_ForceDisabled))
10828 d->setEnabled_helper(parent ? parent->isEnabled() : true);
10829 if (!testAttribute(attribute: Qt::WA_ForceUpdatesDisabled))
10830 d->setUpdatesEnabled_helper(parent ? parent->updatesEnabled() : true);
10831 }
10832 d->inheritStyle();
10833
10834 // send and post remaining QObject events
10835 if (parent && d->sendChildEvents) {
10836 QChildEvent e(QEvent::ChildAdded, this);
10837 QCoreApplication::sendEvent(receiver: parent, event: &e);
10838 }
10839
10840 if (parent && d->sendChildEvents && d->polished) {
10841 QChildEvent e(QEvent::ChildPolished, this);
10842 QCoreApplication::sendEvent(receiver: parent, event: &e);
10843 }
10844
10845 QEvent e(QEvent::ParentChange);
10846 QCoreApplication::sendEvent(receiver: this, event: &e);
10847 }
10848
10849 // texture-based widgets need another event when their top-level window
10850 // changes (more precisely, has already changed at this point)
10851 if (oldWidgetUsesRhiFlush && oldtlw != window())
10852 qSendWindowChangeToTextureChildrenRecursively(widget: this, eventType: QEvent::WindowChangeInternal);
10853
10854 if (!wasCreated) {
10855 if (isWindow() || parentWidget()->isVisible())
10856 setAttribute(Qt::WA_WState_Hidden, on: true);
10857 else if (!testAttribute(attribute: Qt::WA_WState_ExplicitShowHide))
10858 setAttribute(Qt::WA_WState_Hidden, on: false);
10859 }
10860
10861 d->updateIsOpaque();
10862
10863#if QT_CONFIG(graphicsview)
10864 // Embed the widget into a proxy if the parent is embedded.
10865 // ### Doesn't handle reparenting out of an embedded widget.
10866 if (oldtlw->graphicsProxyWidget()) {
10867 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(origin: oldtlw))
10868 ancestorProxy->d_func()->unembedSubWindow(this);
10869 }
10870 if (isWindow() && parent && !graphicsProxyWidget() && !bypassGraphicsProxyWidget(p: this)) {
10871 if (QGraphicsProxyWidget *ancestorProxy = d->nearestGraphicsProxyWidget(origin: parent))
10872 ancestorProxy->d_func()->embedSubWindow(this);
10873 }
10874#endif
10875
10876 if (d->extra && d->extra->hasWindowContainer)
10877 QWindowContainer::parentWasChanged(parent: this);
10878
10879 QWidget *newParentWithWindow = d->closestParentWidgetWithWindowHandle();
10880 if (newParentWithWindow && newParentWithWindow != oldParentWithWindow) {
10881 // Check if the native parent now needs to switch to RHI
10882 qCDebug(lcWidgetPainting) << "Evaluating whether reparenting of" << this
10883 << "into" << parent << "requires RHI enablement for" << newParentWithWindow;
10884
10885 QPlatformBackingStoreRhiConfig rhiConfig;
10886 QSurface::SurfaceType surfaceType = QSurface::RasterSurface;
10887
10888 // First evaluate whether the reparented widget uses RHI.
10889 // We do this as a separate step because the performance
10890 // implications of always checking the native parent are
10891 // problematic when it comes to large widget trees.
10892 if (q_evaluateRhiConfig(w: this, outConfig: &rhiConfig, outType: &surfaceType)) {
10893 // Then check whether the native parent requires RHI
10894 // as a result. It may not, if this widget is a native
10895 // window, and can handle its own RHI flushing.
10896 if (q_evaluateRhiConfig(w: newParentWithWindow, outConfig: nullptr, outType: nullptr)) {
10897 // Finally, check whether we need to recreate the
10898 // native parent to enable RHI flushing.
10899 auto *existingWindow = newParentWithWindow->windowHandle();
10900 auto existingSurfaceType = existingWindow->surfaceType();
10901 if (existingSurfaceType != surfaceType) {
10902 qCDebug(lcWidgetPainting)
10903 << "Recreating" << existingWindow
10904 << "with current type" << existingSurfaceType
10905 << "to support" << surfaceType;
10906 const auto windowStateBeforeDestroy = newParentWithWindow->windowState();
10907 const auto visibilityBeforeDestroy = newParentWithWindow->isVisible();
10908 newParentWithWindow->destroy();
10909 newParentWithWindow->create();
10910 Q_ASSERT(newParentWithWindow->windowHandle());
10911 newParentWithWindow->windowHandle()->setWindowStates(windowStateBeforeDestroy);
10912 QWidgetPrivate::get(w: newParentWithWindow)->setVisible(visibilityBeforeDestroy);
10913 } else if (auto *backingStore = newParentWithWindow->backingStore()) {
10914 // If we don't recreate we still need to make sure the native parent
10915 // widget has a RHI config that the reparented widget can use.
10916 backingStore->handle()->createRhi(window: existingWindow, config: rhiConfig);
10917 // And that it knows it's now flushing with RHI
10918 QWidgetPrivate::get(w: newParentWithWindow)->usesRhiFlush = true;
10919 }
10920 }
10921 }
10922 }
10923}
10924
10925void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
10926{
10927 Q_Q(QWidget);
10928
10929 Qt::WindowFlags oldFlags = data.window_flags;
10930 bool wasCreated = q->testAttribute(attribute: Qt::WA_WState_Created);
10931
10932 QScreen *targetScreen = nullptr;
10933 // Handle a request to move the widget to a particular screen
10934 if (newparent && newparent->windowType() == Qt::Desktop) {
10935 // make sure the widget is created on the same screen as the
10936 // programmer specified desktop widget
10937 targetScreen = newparent->screen();
10938 newparent = nullptr;
10939 }
10940
10941 setWinId(0);
10942
10943 if (!newparent) {
10944 f |= Qt::Window;
10945 if (parent)
10946 targetScreen = q->parentWidget()->window()->screen();
10947 }
10948
10949 const bool destroyWindow = (
10950 // Reparenting top level to child
10951 (oldFlags & Qt::Window) && !(f & Qt::Window)
10952 // And we can dispose of the window
10953 && wasCreated && !q->testAttribute(attribute: Qt::WA_NativeWindow)
10954 );
10955
10956 if (parent != newparent) {
10957 // Update object parent now, so we can resolve new parent window below
10958 QObjectPrivate::setParent_helper(newparent);
10959
10960 if (q->windowHandle())
10961 q->windowHandle()->setFlags(f);
10962
10963 // If the widget itself or any of its children have been created,
10964 // we need to reparent their QWindows as well.
10965 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
10966 // But if the widget is about to be destroyed we must skip the
10967 // widget itself, and only reparent children.
10968 if (destroyWindow) {
10969 reparentWidgetWindowChildren(parentWithWindow);
10970 } else {
10971 // During reparentWidgetWindows() we need to know whether the reparented
10972 // QWindow should be a top level (with a transient parent) or not. This
10973 // widget has not updated its window flags yet, so we can't ask the widget
10974 // directly at that point. Nor can we use the QWindow flags, as unlike QWidgets
10975 // the QWindow flags always reflect Qt::Window, even for child windows. And
10976 // we can't use QWindow::isTopLevel() either, as that depends on the parent,
10977 // which we are in the process of updating. So we propagate the
10978 // new flags of the reparented window here.
10979 reparentWidgetWindows(parentWithWindow, windowFlags: f);
10980 }
10981 }
10982
10983 bool explicitlyHidden = isExplicitlyHidden();
10984
10985 if (destroyWindow) {
10986 if (extra && extra->hasWindowContainer)
10987 QWindowContainer::toplevelAboutToBeDestroyed(parent: q);
10988
10989 // There shouldn't be any QWindow children left, but if there
10990 // are, re-parent them now, before we destroy.
10991 if (!q->windowHandle()->children().isEmpty()) {
10992 QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
10993 QWindow *newParentWindow = parentWithWindow ? parentWithWindow->windowHandle() : nullptr;
10994 for (QObject *child : q->windowHandle()->children()) {
10995 if (QWindow *childWindow = qobject_cast<QWindow *>(o: child)) {
10996 qCWarning(lcWidgetWindow) << "Reparenting" << childWindow
10997 << "before destroying" << this;
10998 childWindow->setParent(newParentWindow);
10999 }
11000 }
11001 }
11002
11003 // We have reparented any child windows of the widget we are
11004 // about to destroy to the new parent window handle, so we can
11005 // safely destroy this widget without destroying sub windows.
11006 q->destroy(destroyWindow: true, destroySubWindows: false);
11007 }
11008
11009 adjustFlags(flags&: f, w: q);
11010 data.window_flags = f;
11011 q->setAttribute(Qt::WA_WState_Created, on: false);
11012 q->setAttribute(Qt::WA_WState_Visible, on: false);
11013 q->setAttribute(Qt::WA_WState_Hidden, on: false);
11014
11015 if (newparent && wasCreated && (q->testAttribute(attribute: Qt::WA_NativeWindow) || (f & Qt::Window)))
11016 q->createWinId();
11017
11018 if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
11019 q->setAttribute(Qt::WA_WState_Hidden);
11020 q->setAttribute(Qt::WA_WState_ExplicitShowHide, on: explicitlyHidden);
11021
11022 // move the window to the selected screen
11023 if (!newparent && targetScreen) {
11024 // only if it is already created
11025 if (q->testAttribute(attribute: Qt::WA_WState_Created))
11026 q->windowHandle()->setScreen(targetScreen);
11027 else
11028 topData()->initialScreen = targetScreen;
11029 }
11030}
11031
11032void QWidgetPrivate::reparentWidgetWindows(QWidget *parentWithWindow, Qt::WindowFlags windowFlags)
11033{
11034 if (QWindow *window = windowHandle()) {
11035 // Reparent this QWindow, and all QWindow children will follow
11036 if (parentWithWindow) {
11037 if (windowFlags & Qt::Window) {
11038 // Top level windows can only have transient parents,
11039 // and the transient parent must be another top level.
11040 QWidget *topLevel = parentWithWindow->window();
11041 auto *transientParent = topLevel->windowHandle();
11042 Q_ASSERT(transientParent);
11043 qCDebug(lcWidgetWindow) << "Setting" << window << "transient parent to" << transientParent;
11044 window->setTransientParent(transientParent);
11045 window->setParent(nullptr);
11046 } else {
11047 auto *parentWindow = parentWithWindow->windowHandle();
11048 qCDebug(lcWidgetWindow) << "Reparenting" << window << "into" << parentWindow;
11049 window->setTransientParent(nullptr);
11050 window->setParent(parentWindow);
11051 }
11052 } else {
11053 qCDebug(lcWidgetWindow) << "Making" << window << "top level window";
11054 window->setTransientParent(nullptr);
11055 window->setParent(nullptr);
11056 }
11057 } else {
11058 reparentWidgetWindowChildren(parentWithWindow);
11059 }
11060}
11061
11062void QWidgetPrivate::reparentWidgetWindowChildren(QWidget *parentWithWindow)
11063{
11064 for (auto *child : std::as_const(t&: children)) {
11065 if (auto *childWidget = qobject_cast<QWidget*>(o: child)) {
11066 auto *childPrivate = QWidgetPrivate::get(w: childWidget);
11067 // Child widgets with QWindows should always continue to be child
11068 // windows, so we pass on the child's current window flags here.
11069 childPrivate->reparentWidgetWindows(parentWithWindow, windowFlags: childWidget->windowFlags());
11070 }
11071 }
11072}
11073
11074/*!
11075 Scrolls the widget including its children \a dx pixels to the
11076 right and \a dy downward. Both \a dx and \a dy may be negative.
11077
11078 After scrolling, the widgets will receive paint events for
11079 the areas that need to be repainted. For widgets that Qt knows to
11080 be opaque, this is only the newly exposed parts.
11081 For example, if an opaque widget is scrolled 8 pixels to the left,
11082 only an 8-pixel wide stripe at the right edge needs updating.
11083
11084 Since widgets propagate the contents of their parents by default,
11085 you need to set the \l autoFillBackground property, or use
11086 setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make
11087 a widget opaque.
11088
11089 For widgets that use contents propagation, a scroll will cause an
11090 update of the entire scroll area.
11091
11092 \sa {Transparency and Double Buffering}
11093*/
11094
11095void QWidget::scroll(int dx, int dy)
11096{
11097 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11098 return;
11099 if (dx == 0 && dy == 0)
11100 return;
11101 Q_D(QWidget);
11102#if QT_CONFIG(graphicsview)
11103 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(origin: this)) {
11104 // Graphics View maintains its own dirty region as a list of rects;
11105 // until we can connect item updates directly to the view, we must
11106 // separately add a translated dirty region.
11107 for (const QRect &rect : d->dirty)
11108 proxy->update(rect: rect.translated(dx, dy));
11109 proxy->scroll(dx, dy, rect: proxy->subWidgetRect(widget: this));
11110 return;
11111 }
11112#endif
11113 d->setDirtyOpaqueRegion();
11114 d->scroll_sys(dx, dy);
11115}
11116
11117void QWidgetPrivate::scroll_sys(int dx, int dy)
11118{
11119 Q_Q(QWidget);
11120 scrollChildren(dx, dy);
11121 scrollRect(q->rect(), dx, dy);
11122}
11123
11124/*!
11125 \overload
11126
11127 This version only scrolls \a r and does not move the children of
11128 the widget.
11129
11130 If \a r is empty or invalid, the result is undefined.
11131
11132 \sa QScrollArea
11133*/
11134void QWidget::scroll(int dx, int dy, const QRect &r)
11135{
11136
11137 if ((!updatesEnabled() && children().size() == 0) || !isVisible())
11138 return;
11139 if (dx == 0 && dy == 0)
11140 return;
11141 Q_D(QWidget);
11142#if QT_CONFIG(graphicsview)
11143 if (QGraphicsProxyWidget *proxy = QWidgetPrivate::nearestGraphicsProxyWidget(origin: this)) {
11144 // Graphics View maintains its own dirty region as a list of rects;
11145 // until we can connect item updates directly to the view, we must
11146 // separately add a translated dirty region.
11147 if (!d->dirty.isEmpty()) {
11148 for (const QRect &rect : d->dirty.translated(dx, dy) & r)
11149 proxy->update(rect);
11150 }
11151 proxy->scroll(dx, dy, rect: r.translated(p: proxy->subWidgetRect(widget: this).topLeft().toPoint()));
11152 return;
11153 }
11154#endif
11155 d->scroll_sys(dx, dy, r);
11156}
11157
11158void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
11159{
11160 scrollRect(r, dx, dy);
11161}
11162
11163/*!
11164 Repaints the widget directly by calling paintEvent() immediately,
11165 unless updates are disabled or the widget is hidden.
11166
11167 We suggest only using repaint() if you need an immediate repaint,
11168 for example during animation. In most circumstances update()
11169 is better, as it permits Qt to optimize for speed and minimize
11170 flicker.
11171
11172 \warning If you call repaint() in a function which may itself be
11173 called from paintEvent(), you may get infinite recursion. The
11174 update() function never causes recursion.
11175
11176 \sa update(), paintEvent(), setUpdatesEnabled()
11177*/
11178
11179void QWidget::repaint()
11180{
11181 repaint(rect());
11182}
11183
11184/*! \overload
11185
11186 This version repaints a rectangle (\a x, \a y, \a w, \a h) inside
11187 the widget.
11188
11189 If \a w is negative, it is replaced with \c{width() - x}, and if
11190 \a h is negative, it is replaced width \c{height() - y}.
11191*/
11192void QWidget::repaint(int x, int y, int w, int h)
11193{
11194 if (x > data->crect.width() || y > data->crect.height())
11195 return;
11196
11197 if (w < 0)
11198 w = data->crect.width() - x;
11199 if (h < 0)
11200 h = data->crect.height() - y;
11201
11202 repaint(QRect(x, y, w, h));
11203}
11204
11205/*! \overload
11206
11207 This version repaints a rectangle \a rect inside the widget.
11208*/
11209void QWidget::repaint(const QRect &rect)
11210{
11211 Q_D(QWidget);
11212 d->repaint(r: rect);
11213}
11214
11215/*!
11216 \overload
11217
11218 This version repaints a region \a rgn inside the widget.
11219*/
11220void QWidget::repaint(const QRegion &rgn)
11221{
11222 Q_D(QWidget);
11223 d->repaint(r: rgn);
11224}
11225
11226template <typename T>
11227void QWidgetPrivate::repaint(T r)
11228{
11229 Q_Q(QWidget);
11230
11231 if (!q->isVisible() || !q->updatesEnabled() || r.isEmpty())
11232 return;
11233
11234 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11235 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11236 tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
11237}
11238
11239/*!
11240 Updates the widget unless updates are disabled or the widget is
11241 hidden.
11242
11243 This function does not cause an immediate repaint; instead it
11244 schedules a paint event for processing when Qt returns to the main
11245 event loop. This permits Qt to optimize for more speed and less
11246 flicker than a call to repaint() does.
11247
11248 Calling update() several times normally results in just one
11249 paintEvent() call.
11250
11251 Qt normally erases the widget's area before the paintEvent() call.
11252 If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
11253 responsible for painting all its pixels with an opaque color.
11254
11255 \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock}
11256*/
11257void QWidget::update()
11258{
11259 update(rect());
11260}
11261
11262/*! \fn void QWidget::update(int x, int y, int w, int h)
11263 \overload
11264
11265 This version updates a rectangle (\a x, \a y, \a w, \a h) inside
11266 the widget.
11267*/
11268
11269/*!
11270 \overload
11271
11272 This version updates a rectangle \a rect inside the widget.
11273*/
11274void QWidget::update(const QRect &rect)
11275{
11276 Q_D(QWidget);
11277 d->update(r: rect);
11278}
11279
11280/*!
11281 \overload
11282
11283 This version repaints a region \a rgn inside the widget.
11284*/
11285void QWidget::update(const QRegion &rgn)
11286{
11287 Q_D(QWidget);
11288 d->update(r: rgn);
11289}
11290
11291template <typename T>
11292void QWidgetPrivate::update(T r)
11293{
11294 Q_Q(QWidget);
11295
11296 if (renderToTexture && !q->isVisible()) {
11297 renderToTextureReallyDirty = 1;
11298 return;
11299 }
11300
11301 if (!q->isVisible() || !q->updatesEnabled())
11302 return;
11303
11304 T clipped = r & q->rect();
11305
11306 if (clipped.isEmpty())
11307 return;
11308
11309 if (q->testAttribute(attribute: Qt::WA_WState_InPaintEvent)) {
11310 QCoreApplication::postEvent(receiver: q, event: new QUpdateLaterEvent(clipped));
11311 return;
11312 }
11313
11314 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
11315 if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
11316 tlwExtra->repaintManager->markDirty(clipped, q);
11317}
11318
11319 /*!
11320 \internal
11321
11322 This just sets the corresponding attribute bit to 1 or 0
11323 */
11324static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
11325 QWidgetPrivate *d)
11326{
11327 if (attribute < int(8*sizeof(uint))) {
11328 if (on)
11329 data->widget_attributes |= (1<<attribute);
11330 else
11331 data->widget_attributes &= ~(1<<attribute);
11332 } else {
11333 const int x = attribute - 8*sizeof(uint);
11334 const int int_off = x / (8*sizeof(uint));
11335 if (on)
11336 d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
11337 else
11338 d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
11339 }
11340}
11341
11342#ifdef Q_OS_MAC
11343void QWidgetPrivate::macUpdateSizeAttribute()
11344{
11345 Q_Q(QWidget);
11346 QEvent event(QEvent::MacSizeChange);
11347 QCoreApplication::sendEvent(q, &event);
11348 for (int i = 0; i < children.size(); ++i) {
11349 QWidget *w = qobject_cast<QWidget *>(children.at(i));
11350 if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
11351 && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent
11352 && !w->testAttribute(Qt::WA_MacSmallSize)
11353 && !w->testAttribute(Qt::WA_MacNormalSize))
11354 w->d_func()->macUpdateSizeAttribute();
11355 }
11356 resolveFont();
11357}
11358#endif
11359
11360/*!
11361 Sets the attribute \a attribute on this widget if \a on is true;
11362 otherwise clears the attribute.
11363
11364 \sa testAttribute()
11365*/
11366void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
11367{
11368 if (testAttribute(attribute) == on)
11369 return;
11370
11371 Q_D(QWidget);
11372 static_assert(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
11373 "QWidget::setAttribute(WidgetAttribute, bool): "
11374 "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
11375#ifdef Q_OS_WIN
11376 // ### Don't use PaintOnScreen+paintEngine() to do native painting in some future release
11377 if (attribute == Qt::WA_PaintOnScreen && on && windowType() != Qt::Desktop && !inherits("QGLWidget")) {
11378 // see ::paintEngine for details
11379 paintEngine();
11380 if (d->noPaintOnScreen)
11381 return;
11382 }
11383#endif
11384
11385 // Don't set WA_NativeWindow on platforms that don't support it -- except for QGLWidget, which depends on it
11386 if (attribute == Qt::WA_NativeWindow && !d->mustHaveWindowHandle) {
11387 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
11388 if (!platformIntegration->hasCapability(cap: QPlatformIntegration::NativeWidgets))
11389 return;
11390 }
11391
11392 setAttribute_internal(attribute, on, data, d);
11393
11394 switch (attribute) {
11395
11396#if QT_CONFIG(draganddrop)
11397 case Qt::WA_AcceptDrops: {
11398 if (on && !testAttribute(attribute: Qt::WA_DropSiteRegistered))
11399 setAttribute(attribute: Qt::WA_DropSiteRegistered, on: true);
11400 else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(attribute: Qt::WA_DropSiteRegistered)))
11401 setAttribute(attribute: Qt::WA_DropSiteRegistered, on: false);
11402 QEvent e(QEvent::AcceptDropsChange);
11403 QCoreApplication::sendEvent(receiver: this, event: &e);
11404 break;
11405 }
11406 case Qt::WA_DropSiteRegistered: {
11407 for (int i = 0; i < d->children.size(); ++i) {
11408 QWidget *w = qobject_cast<QWidget *>(o: d->children.at(i));
11409 if (w && !w->isWindow() && !w->testAttribute(attribute: Qt::WA_AcceptDrops) && w->testAttribute(attribute: Qt::WA_DropSiteRegistered) != on)
11410 w->setAttribute(attribute: Qt::WA_DropSiteRegistered, on);
11411 }
11412 break;
11413 }
11414#endif
11415
11416 case Qt::WA_NoChildEventsForParent:
11417 d->sendChildEvents = !on;
11418 break;
11419 case Qt::WA_NoChildEventsFromChildren:
11420 d->receiveChildEvents = !on;
11421 break;
11422 case Qt::WA_MacNormalSize:
11423 case Qt::WA_MacSmallSize:
11424 case Qt::WA_MacMiniSize:
11425#ifdef Q_OS_MAC
11426 {
11427 // We can only have one of these set at a time
11428 const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
11429 Qt::WA_MacMiniSize };
11430 for (int i = 0; i < 3; ++i) {
11431 if (MacSizes[i] != attribute)
11432 setAttribute_internal(MacSizes[i], false, data, d);
11433 }
11434 d->macUpdateSizeAttribute();
11435 }
11436#endif
11437 break;
11438 case Qt::WA_ShowModal:
11439 if (!on) {
11440 // reset modality type to NonModal when clearing WA_ShowModal
11441 data->window_modality = Qt::NonModal;
11442 } else if (data->window_modality == Qt::NonModal) {
11443 // If modality hasn't been set prior to setting WA_ShowModal, use
11444 // ApplicationModal.
11445 data->window_modality = Qt::ApplicationModal;
11446 // Some window managers do not allow us to enter modality after the
11447 // window is visible.The window must be hidden before changing the
11448 // windowModality property and then reshown.
11449 }
11450 if (testAttribute(attribute: Qt::WA_WState_Created)) {
11451 // don't call setModal_sys() before create()
11452 d->setModal_sys();
11453 }
11454 break;
11455 case Qt::WA_MouseTracking: {
11456 QEvent e(QEvent::MouseTrackingChange);
11457 QCoreApplication::sendEvent(receiver: this, event: &e);
11458 break; }
11459 case Qt::WA_TabletTracking: {
11460 QEvent e(QEvent::TabletTrackingChange);
11461 QCoreApplication::sendEvent(receiver: this, event: &e);
11462 break; }
11463 case Qt::WA_NativeWindow: {
11464 d->createTLExtra();
11465 if (on)
11466 d->createTLSysExtra();
11467#ifndef QT_NO_IM
11468 QWidget *focusWidget = d->effectiveFocusWidget();
11469 if (on && !internalWinId() && this == QGuiApplication::focusObject()
11470 && focusWidget->testAttribute(attribute: Qt::WA_InputMethodEnabled)) {
11471 QGuiApplication::inputMethod()->commit();
11472 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
11473 }
11474 if (!QCoreApplication::testAttribute(attribute: Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget())
11475 parentWidget()->d_func()->enforceNativeChildren();
11476 if (on && !internalWinId() && testAttribute(attribute: Qt::WA_WState_Created))
11477 d->createWinId();
11478 if (isEnabled() && focusWidget->isEnabled() && this == QGuiApplication::focusObject()
11479 && focusWidget->testAttribute(attribute: Qt::WA_InputMethodEnabled)) {
11480 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
11481 }
11482#endif //QT_NO_IM
11483 break;
11484 }
11485 case Qt::WA_PaintOnScreen:
11486 d->updateIsOpaque();
11487 Q_FALLTHROUGH();
11488 case Qt::WA_OpaquePaintEvent:
11489 d->updateIsOpaque();
11490 break;
11491 case Qt::WA_NoSystemBackground:
11492 d->updateIsOpaque();
11493 Q_FALLTHROUGH();
11494 case Qt::WA_UpdatesDisabled:
11495 d->updateSystemBackground();
11496 break;
11497 case Qt::WA_TransparentForMouseEvents:
11498 break;
11499 case Qt::WA_InputMethodEnabled: {
11500#ifndef QT_NO_IM
11501 if (QGuiApplication::focusObject() == this) {
11502 if (!on)
11503 QGuiApplication::inputMethod()->commit();
11504 QGuiApplication::inputMethod()->update(queries: Qt::ImEnabled);
11505 }
11506#endif //QT_NO_IM
11507 break;
11508 }
11509 case Qt::WA_WindowPropagation:
11510 d->resolvePalette();
11511 d->resolveFont();
11512 d->resolveLocale();
11513 break;
11514 case Qt::WA_DontShowOnScreen: {
11515 if (on && isVisible()) {
11516 // Make sure we keep the current state and only hide the widget
11517 // from the desktop. show_sys will only update platform specific
11518 // attributes at this point.
11519 d->hide_sys();
11520 d->show_sys();
11521 }
11522 break;
11523 }
11524
11525 case Qt::WA_X11NetWmWindowTypeDesktop:
11526 case Qt::WA_X11NetWmWindowTypeDock:
11527 case Qt::WA_X11NetWmWindowTypeToolBar:
11528 case Qt::WA_X11NetWmWindowTypeMenu:
11529 case Qt::WA_X11NetWmWindowTypeUtility:
11530 case Qt::WA_X11NetWmWindowTypeSplash:
11531 case Qt::WA_X11NetWmWindowTypeDialog:
11532 case Qt::WA_X11NetWmWindowTypeDropDownMenu:
11533 case Qt::WA_X11NetWmWindowTypePopupMenu:
11534 case Qt::WA_X11NetWmWindowTypeToolTip:
11535 case Qt::WA_X11NetWmWindowTypeNotification:
11536 case Qt::WA_X11NetWmWindowTypeCombo:
11537 case Qt::WA_X11NetWmWindowTypeDND:
11538 d->setNetWmWindowTypes();
11539 break;
11540
11541 case Qt::WA_StaticContents:
11542 if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) {
11543 if (on)
11544 repaintManager->addStaticWidget(widget: this);
11545 else
11546 repaintManager->removeStaticWidget(widget: this);
11547 }
11548 break;
11549 case Qt::WA_TranslucentBackground:
11550 if (on)
11551 setAttribute(attribute: Qt::WA_NoSystemBackground);
11552 d->updateIsTranslucent();
11553
11554 break;
11555 case Qt::WA_AcceptTouchEvents:
11556 break;
11557 default:
11558 break;
11559 }
11560}
11561
11562/*! \fn bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
11563
11564 Returns \c true if attribute \a attribute is set on this widget;
11565 otherwise returns \c false.
11566
11567 \sa setAttribute()
11568 */
11569bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const
11570{
11571 Q_D(const QWidget);
11572 const int x = attribute - 8*sizeof(uint);
11573 const int int_off = x / (8*sizeof(uint));
11574 return (d->high_attributes[int_off] & (1<<(x-(int_off*8*sizeof(uint)))));
11575}
11576
11577/*!
11578 \property QWidget::windowOpacity
11579
11580 \brief The level of opacity for the window.
11581
11582 The valid range of opacity is from 1.0 (completely opaque) to
11583 0.0 (completely transparent).
11584
11585 By default the value of this property is 1.0.
11586
11587 This feature is available on Embedded Linux, \macos, Windows,
11588 and X11 platforms that support the Composite extension.
11589
11590 \note On X11 you need to have a composite manager running,
11591 and the X11 specific _NET_WM_WINDOW_OPACITY atom needs to be
11592 supported by the window manager you are using.
11593
11594 \warning Changing this property from opaque to transparent might issue a
11595 paint event that needs to be processed before the window is displayed
11596 correctly. This affects mainly the use of QScreen::grabWindow(). Also note
11597 that semi-transparent windows update and resize significantly slower than
11598 opaque windows.
11599
11600 \sa setMask()
11601*/
11602qreal QWidget::windowOpacity() const
11603{
11604 Q_D(const QWidget);
11605 return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
11606}
11607
11608void QWidget::setWindowOpacity(qreal opacity)
11609{
11610 Q_D(QWidget);
11611 if (!isWindow())
11612 return;
11613
11614 opacity = qBound(min: qreal(0.0), val: opacity, max: qreal(1.0));
11615 QTLWExtra *extra = d->topData();
11616 extra->opacity = uint(opacity * 255);
11617 setAttribute(attribute: Qt::WA_WState_WindowOpacitySet);
11618 d->setWindowOpacity_sys(opacity);
11619
11620 if (!testAttribute(attribute: Qt::WA_WState_Created))
11621 return;
11622
11623#if QT_CONFIG(graphicsview)
11624 if (QGraphicsProxyWidget *proxy = graphicsProxyWidget()) {
11625 // Avoid invalidating the cache if set.
11626 if (proxy->cacheMode() == QGraphicsItem::NoCache)
11627 proxy->update();
11628 else if (QGraphicsScene *scene = proxy->scene())
11629 scene->update(rect: proxy->sceneBoundingRect());
11630 return;
11631 }
11632#endif
11633}
11634
11635void QWidgetPrivate::setWindowOpacity_sys(qreal level)
11636{
11637 Q_Q(QWidget);
11638 if (q->windowHandle())
11639 q->windowHandle()->setOpacity(level);
11640}
11641
11642/*!
11643 \property QWidget::windowModified
11644 \brief whether the document shown in the window has unsaved changes
11645
11646 A modified window is a window whose content has changed but has
11647 not been saved to disk. This flag will have different effects
11648 varied by the platform. On \macos the close button will have a
11649 modified look; on other platforms, the window title will have an
11650 '*' (asterisk).
11651
11652 The window title must contain a "[*]" placeholder, which
11653 indicates where the '*' should appear. Normally, it should appear
11654 right after the file name (e.g., "document1.txt[*] - Text
11655 Editor"). If the window isn't modified, the placeholder is simply
11656 removed.
11657
11658 Note that if a widget is set as modified, all its ancestors will
11659 also be set as modified. However, if you call \c
11660 {setWindowModified(false)} on a widget, this will not propagate to
11661 its parent because other children of the parent might have been
11662 modified.
11663
11664 \sa windowTitle
11665*/
11666bool QWidget::isWindowModified() const
11667{
11668 return testAttribute(attribute: Qt::WA_WindowModified);
11669}
11670
11671void QWidget::setWindowModified(bool mod)
11672{
11673 Q_D(QWidget);
11674 setAttribute(attribute: Qt::WA_WindowModified, on: mod);
11675
11676 d->setWindowModified_helper();
11677
11678 QEvent e(QEvent::ModifiedChange);
11679 QCoreApplication::sendEvent(receiver: this, event: &e);
11680}
11681
11682void QWidgetPrivate::setWindowModified_helper()
11683{
11684 Q_Q(QWidget);
11685 QWindow *window = q->windowHandle();
11686 if (!window)
11687 return;
11688 QPlatformWindow *platformWindow = window->handle();
11689 if (!platformWindow)
11690 return;
11691 bool on = q->testAttribute(attribute: Qt::WA_WindowModified);
11692 if (!platformWindow->setWindowModified(on)) {
11693 if (Q_UNLIKELY(on && !q->windowTitle().contains("[*]"_L1)))
11694 qWarning(msg: "QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
11695 setWindowTitle_helper(q->windowTitle());
11696 setWindowIconText_helper(q->windowIconText());
11697 }
11698}
11699
11700#if QT_CONFIG(tooltip)
11701/*!
11702 \property QWidget::toolTip
11703
11704 \brief the widget's tooltip
11705
11706 Note that by default tooltips are only shown for widgets that are
11707 children of the active window. You can change this behavior by
11708 setting the attribute Qt::WA_AlwaysShowToolTips on the \e window,
11709 not on the widget with the tooltip.
11710
11711 If you want to control a tooltip's behavior, you can intercept the
11712 event() function and catch the QEvent::ToolTip event (e.g., if you
11713 want to customize the area for which the tooltip should be shown).
11714
11715 By default, this property contains an empty string.
11716
11717 \sa QToolTip, statusTip, whatsThis
11718*/
11719void QWidget::setToolTip(const QString &s)
11720{
11721 Q_D(QWidget);
11722 d->toolTip = s;
11723
11724 QEvent event(QEvent::ToolTipChange);
11725 QCoreApplication::sendEvent(receiver: this, event: &event);
11726}
11727
11728QString QWidget::toolTip() const
11729{
11730 Q_D(const QWidget);
11731 return d->toolTip;
11732}
11733
11734/*!
11735 \property QWidget::toolTipDuration
11736 \brief the widget's tooltip duration
11737 \since 5.2
11738
11739 Specifies how long time the tooltip will be displayed, in milliseconds.
11740 If the value is -1 (default) the duration is calculated depending on the length of the tooltip.
11741
11742 \sa toolTip
11743*/
11744
11745void QWidget::setToolTipDuration(int msec)
11746{
11747 Q_D(QWidget);
11748 d->toolTipDuration = msec;
11749}
11750
11751int QWidget::toolTipDuration() const
11752{
11753 Q_D(const QWidget);
11754 return d->toolTipDuration;
11755}
11756
11757#endif // QT_CONFIG(tooltip)
11758
11759
11760#if QT_CONFIG(statustip)
11761/*!
11762 \property QWidget::statusTip
11763 \brief the widget's status tip
11764
11765 By default, this property contains an empty string.
11766
11767 \sa toolTip, whatsThis
11768*/
11769void QWidget::setStatusTip(const QString &s)
11770{
11771 Q_D(QWidget);
11772 d->statusTip = s;
11773}
11774
11775QString QWidget::statusTip() const
11776{
11777 Q_D(const QWidget);
11778 return d->statusTip;
11779}
11780#endif // QT_CONFIG(statustip)
11781
11782#if QT_CONFIG(whatsthis)
11783/*!
11784 \property QWidget::whatsThis
11785
11786 \brief the widget's What's This help text.
11787
11788 By default, this property contains an empty string.
11789
11790 \sa QWhatsThis, QWidget::toolTip, QWidget::statusTip
11791*/
11792void QWidget::setWhatsThis(const QString &s)
11793{
11794 Q_D(QWidget);
11795 d->whatsThis = s;
11796}
11797
11798QString QWidget::whatsThis() const
11799{
11800 Q_D(const QWidget);
11801 return d->whatsThis;
11802}
11803#endif // QT_CONFIG(whatsthis)
11804
11805#if QT_CONFIG(accessibility)
11806/*!
11807 \property QWidget::accessibleName
11808
11809 \brief the widget's name as seen by assistive technologies
11810
11811 This is the primary name by which assistive technology such as screen readers
11812 announce this widget. For most widgets setting this property is not required.
11813 For example for QPushButton the button's text will be used.
11814
11815 It is important to set this property when the widget does not provide any
11816 text. For example a button that only contains an icon needs to set this
11817 property to work with screen readers.
11818 The name should be short and equivalent to the visual information conveyed
11819 by the widget.
11820
11821 This property has to be \l{Internationalization with Qt}{localized}.
11822
11823 By default, this property contains an empty string.
11824
11825 \sa QWidget::accessibleDescription, QAccessibleInterface::text()
11826*/
11827void QWidget::setAccessibleName(const QString &name)
11828{
11829 Q_D(QWidget);
11830 d->accessibleName = name;
11831 QAccessibleEvent event(this, QAccessible::NameChanged);
11832 QAccessible::updateAccessibility(event: &event);
11833}
11834
11835QString QWidget::accessibleName() const
11836{
11837 Q_D(const QWidget);
11838 return d->accessibleName;
11839}
11840
11841/*!
11842 \property QWidget::accessibleDescription
11843
11844 \brief the widget's description as seen by assistive technologies
11845
11846 The accessible description of a widget should convey what a widget does.
11847 While the \l accessibleName should be a short and concise string (e.g. \gui{Save}),
11848 the description should give more context, such as \gui{Saves the current document}.
11849
11850 This property has to be \l{Internationalization with Qt}{localized}.
11851
11852 By default, this property contains an empty string and Qt falls back
11853 to using the tool tip to provide this information.
11854
11855 \sa QWidget::accessibleName, QAccessibleInterface::text()
11856*/
11857void QWidget::setAccessibleDescription(const QString &description)
11858{
11859 Q_D(QWidget);
11860 d->accessibleDescription = description;
11861 QAccessibleEvent event(this, QAccessible::DescriptionChanged);
11862 QAccessible::updateAccessibility(event: &event);
11863}
11864
11865QString QWidget::accessibleDescription() const
11866{
11867 Q_D(const QWidget);
11868 return d->accessibleDescription;
11869}
11870#endif // QT_CONFIG(accessibility)
11871
11872#ifndef QT_NO_SHORTCUT
11873/*!
11874 Adds a shortcut to Qt's shortcut system that watches for the given
11875 \a key sequence in the given \a context. If the \a context is
11876 Qt::ApplicationShortcut, the shortcut applies to the application as a
11877 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
11878 or to the window itself, Qt::WindowShortcut.
11879
11880 If the same \a key sequence has been grabbed by several widgets,
11881 when the \a key sequence occurs a QEvent::Shortcut event is sent
11882 to all the widgets to which it applies in a non-deterministic
11883 order, but with the ``ambiguous'' flag set to true.
11884
11885 \warning You should not normally need to use this function;
11886 instead create \l{QAction}s with the shortcut key sequences you
11887 require (if you also want equivalent menu options and toolbar
11888 buttons), or create \l{QShortcut}s if you just need key sequences.
11889 Both QAction and QShortcut handle all the event filtering for you,
11890 and provide signals which are triggered when the user triggers the
11891 key sequence, so are much easier to use than this low-level
11892 function.
11893
11894 \sa releaseShortcut(), setShortcutEnabled()
11895*/
11896int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context)
11897{
11898 Q_ASSERT(qApp);
11899 if (key.isEmpty())
11900 return 0;
11901 setAttribute(attribute: Qt::WA_GrabbedShortcut);
11902 return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(owner: this, key, context, matcher: qWidgetShortcutContextMatcher);
11903}
11904
11905/*!
11906 Removes the shortcut with the given \a id from Qt's shortcut
11907 system. The widget will no longer receive QEvent::Shortcut events
11908 for the shortcut's key sequence (unless it has other shortcuts
11909 with the same key sequence).
11910
11911 \warning You should not normally need to use this function since
11912 Qt's shortcut system removes shortcuts automatically when their
11913 parent widget is destroyed. It is best to use QAction or
11914 QShortcut to handle shortcuts, since they are easier to use than
11915 this low-level function. Note also that this is an expensive
11916 operation.
11917
11918 \sa grabShortcut(), setShortcutEnabled()
11919*/
11920void QWidget::releaseShortcut(int id)
11921{
11922 Q_ASSERT(qApp);
11923 if (id)
11924 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, owner: this, key: 0);
11925}
11926
11927/*!
11928 If \a enable is true, the shortcut with the given \a id is
11929 enabled; otherwise the shortcut is disabled.
11930
11931 \warning You should not normally need to use this function since
11932 Qt's shortcut system enables/disables shortcuts automatically as
11933 widgets become hidden/visible and gain or lose focus. It is best
11934 to use QAction or QShortcut to handle shortcuts, since they are
11935 easier to use than this low-level function.
11936
11937 \sa grabShortcut(), releaseShortcut()
11938*/
11939void QWidget::setShortcutEnabled(int id, bool enable)
11940{
11941 Q_ASSERT(qApp);
11942 if (id)
11943 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, owner: this, key: 0);
11944}
11945
11946/*!
11947 \since 4.2
11948
11949 If \a enable is true, auto repeat of the shortcut with the
11950 given \a id is enabled; otherwise it is disabled.
11951
11952 \sa grabShortcut(), releaseShortcut()
11953*/
11954void QWidget::setShortcutAutoRepeat(int id, bool enable)
11955{
11956 Q_ASSERT(qApp);
11957 if (id)
11958 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on: enable, id, owner: this, key: 0);
11959}
11960#endif // QT_NO_SHORTCUT
11961
11962/*!
11963 Updates the widget's micro focus and informs input methods
11964 that the state specified by \a query has changed.
11965*/
11966void QWidget::updateMicroFocus(Qt::InputMethodQuery query)
11967{
11968 if (this == QGuiApplication::focusObject())
11969 QGuiApplication::inputMethod()->update(queries: query);
11970}
11971
11972/*!
11973 Raises this widget to the top of the parent widget's stack.
11974
11975 After this call the widget will be visually in front of any
11976 overlapping sibling widgets.
11977
11978 \note When using activateWindow(), you can call this function to
11979 ensure that the window is stacked on top.
11980
11981 \sa lower(), stackUnder()
11982*/
11983
11984void QWidget::raise()
11985{
11986 Q_D(QWidget);
11987 if (!isWindow()) {
11988 QWidget *p = parentWidget();
11989 const int parentChildCount = p->d_func()->children.size();
11990 if (parentChildCount < 2)
11991 return;
11992 const int from = p->d_func()->children.indexOf(t: this);
11993 Q_ASSERT(from >= 0);
11994 // Do nothing if the widget is already in correct stacking order _and_ created.
11995 if (from != parentChildCount -1)
11996 p->d_func()->children.move(from, to: parentChildCount - 1);
11997 if (!testAttribute(attribute: Qt::WA_WState_Created) && p->testAttribute(attribute: Qt::WA_WState_Created))
11998 create();
11999 else if (from == parentChildCount - 1)
12000 return;
12001
12002 QRegion region(rect());
12003 d->subtractOpaqueSiblings(sourceRegion&: region);
12004 d->invalidateBackingStore(region);
12005 }
12006 if (testAttribute(attribute: Qt::WA_WState_Created))
12007 d->raise_sys();
12008
12009 if (d->extra && d->extra->hasWindowContainer)
12010 QWindowContainer::parentWasRaised(parent: this);
12011
12012 QEvent e(QEvent::ZOrderChange);
12013 QCoreApplication::sendEvent(receiver: this, event: &e);
12014}
12015
12016void QWidgetPrivate::raise_sys()
12017{
12018 Q_Q(QWidget);
12019 if (q->isWindow() || q->testAttribute(attribute: Qt::WA_NativeWindow)) {
12020 q->windowHandle()->raise();
12021 } else if (renderToTexture) {
12022 if (QWidget *p = q->parentWidget()) {
12023 setDirtyOpaqueRegion();
12024 p->d_func()->invalidateBackingStore(effectiveRectFor(rect: q->geometry()));
12025 }
12026 }
12027}
12028
12029/*!
12030 Lowers the widget to the bottom of the parent widget's stack.
12031
12032 After this call the widget will be visually behind (and therefore
12033 obscured by) any overlapping sibling widgets.
12034
12035 \sa raise(), stackUnder()
12036*/
12037
12038void QWidget::lower()
12039{
12040 Q_D(QWidget);
12041 if (!isWindow()) {
12042 QWidget *p = parentWidget();
12043 const int parentChildCount = p->d_func()->children.size();
12044 if (parentChildCount < 2)
12045 return;
12046 const int from = p->d_func()->children.indexOf(t: this);
12047 Q_ASSERT(from >= 0);
12048 // Do nothing if the widget is already in correct stacking order _and_ created.
12049 if (from != 0)
12050 p->d_func()->children.move(from, to: 0);
12051 if (!testAttribute(attribute: Qt::WA_WState_Created) && p->testAttribute(attribute: Qt::WA_WState_Created))
12052 create();
12053 else if (from == 0)
12054 return;
12055 }
12056 if (testAttribute(attribute: Qt::WA_WState_Created))
12057 d->lower_sys();
12058
12059 if (d->extra && d->extra->hasWindowContainer)
12060 QWindowContainer::parentWasLowered(parent: this);
12061
12062 QEvent e(QEvent::ZOrderChange);
12063 QCoreApplication::sendEvent(receiver: this, event: &e);
12064}
12065
12066void QWidgetPrivate::lower_sys()
12067{
12068 Q_Q(QWidget);
12069 if (q->isWindow() || q->testAttribute(attribute: Qt::WA_NativeWindow)) {
12070 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
12071 q->windowHandle()->lower();
12072 } else if (QWidget *p = q->parentWidget()) {
12073 setDirtyOpaqueRegion();
12074 p->d_func()->invalidateBackingStore(effectiveRectFor(rect: q->geometry()));
12075 }
12076}
12077
12078/*!
12079 Places the widget under \a w in the parent widget's stack.
12080
12081 To make this work, the widget itself and \a w must be siblings.
12082
12083 \sa raise(), lower()
12084*/
12085void QWidget::stackUnder(QWidget* w)
12086{
12087 Q_D(QWidget);
12088 QWidget *p = parentWidget();
12089 if (!w || isWindow() || p != w->parentWidget() || this == w)
12090 return;
12091 if (p) {
12092 int from = p->d_func()->children.indexOf(t: this);
12093 int to = p->d_func()->children.indexOf(t: w);
12094 Q_ASSERT(from >= 0);
12095 Q_ASSERT(to >= 0);
12096 if (from < to)
12097 --to;
12098 // Do nothing if the widget is already in correct stacking order _and_ created.
12099 if (from != to)
12100 p->d_func()->children.move(from, to);
12101 if (!testAttribute(attribute: Qt::WA_WState_Created) && p->testAttribute(attribute: Qt::WA_WState_Created))
12102 create();
12103 else if (from == to)
12104 return;
12105 }
12106 if (testAttribute(attribute: Qt::WA_WState_Created))
12107 d->stackUnder_sys(w);
12108
12109 QEvent e(QEvent::ZOrderChange);
12110 QCoreApplication::sendEvent(receiver: this, event: &e);
12111}
12112
12113void QWidgetPrivate::stackUnder_sys(QWidget*)
12114{
12115 Q_Q(QWidget);
12116 if (QWidget *p = q->parentWidget()) {
12117 setDirtyOpaqueRegion();
12118 p->d_func()->invalidateBackingStore(effectiveRectFor(rect: q->geometry()));
12119 }
12120}
12121
12122/*!
12123 \fn bool QWidget::isTopLevel() const
12124 \deprecated
12125
12126 Use isWindow() instead.
12127*/
12128
12129/*!
12130 \fn bool QWidget::isRightToLeft() const
12131 \internal
12132*/
12133
12134/*!
12135 \fn bool QWidget::isLeftToRight() const
12136 \internal
12137*/
12138
12139/*!
12140 \macro QWIDGETSIZE_MAX
12141 \relates QWidget
12142
12143 Defines the maximum size for a QWidget object.
12144
12145 The largest allowed size for a widget is QSize(QWIDGETSIZE_MAX,
12146 QWIDGETSIZE_MAX), i.e. QSize (16777215,16777215).
12147
12148 \sa QWidget::setMaximumSize()
12149*/
12150
12151/*!
12152 \fn QWidget::setupUi(QWidget *widget)
12153
12154 Sets up the user interface for the specified \a widget.
12155
12156 \note This function is available with widgets that derive from user
12157 interface descriptions created using \l{uic}.
12158
12159 \sa {Using a Designer UI File in Your Application}
12160*/
12161
12162QRect QWidgetPrivate::frameStrut() const
12163{
12164 Q_Q(const QWidget);
12165 if (!q->isWindow() || (q->windowType() == Qt::Desktop) || q->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
12166 // x2 = x1 + w - 1, so w/h = 1
12167 return QRect(0, 0, 1, 1);
12168 }
12169
12170 if (data.fstrut_dirty
12171 // ### Fix properly for 4.3
12172 && q->isVisible()
12173 && q->testAttribute(attribute: Qt::WA_WState_Created))
12174 const_cast<QWidgetPrivate *>(this)->updateFrameStrut();
12175
12176 return maybeTopData() ? maybeTopData()->frameStrut : QRect();
12177}
12178
12179void QWidgetPrivate::updateFrameStrut()
12180{
12181 Q_Q(QWidget);
12182 if (q->data->fstrut_dirty) {
12183 if (QTLWExtra *te = maybeTopData()) {
12184 if (te->window && te->window->handle()) {
12185 const QMargins margins = te->window->frameMargins();
12186 if (!margins.isNull()) {
12187 te->frameStrut.setCoords(xp1: margins.left(), yp1: margins.top(), xp2: margins.right(), yp2: margins.bottom());
12188 q->data->fstrut_dirty = false;
12189 }
12190 }
12191 }
12192 }
12193}
12194
12195#ifdef QT_KEYPAD_NAVIGATION
12196/*!
12197 \internal
12198
12199 Changes the focus from the current focusWidget to a widget in
12200 the \a direction.
12201
12202 Returns \c true, if there was a widget in that direction
12203*/
12204bool QWidgetPrivate::navigateToDirection(Direction direction)
12205{
12206 QWidget *targetWidget = widgetInNavigationDirection(direction);
12207 if (targetWidget)
12208 targetWidget->setFocus();
12209 return (targetWidget != 0);
12210}
12211
12212/*!
12213 \internal
12214
12215 Searches for a widget that is positioned in the \a direction, starting
12216 from the current focusWidget.
12217
12218 Returns the pointer to a found widget or \nullptr, if there was no widget
12219 in that direction.
12220*/
12221QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction)
12222{
12223 const QWidget *sourceWidget = QApplication::focusWidget();
12224 if (!sourceWidget)
12225 return nullptr;
12226 const QRect sourceRect = sourceWidget->rect().translated(sourceWidget->mapToGlobal(QPoint()));
12227 const int sourceX =
12228 (direction == DirectionNorth || direction == DirectionSouth) ?
12229 (sourceRect.left() + (sourceRect.right() - sourceRect.left()) / 2)
12230 :(direction == DirectionEast ? sourceRect.right() : sourceRect.left());
12231 const int sourceY =
12232 (direction == DirectionEast || direction == DirectionWest) ?
12233 (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2)
12234 :(direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top());
12235 const QPoint sourcePoint(sourceX, sourceY);
12236 const QPoint sourceCenter = sourceRect.center();
12237 const QWidget *sourceWindow = sourceWidget->window();
12238
12239 QWidget *targetWidget = nullptr;
12240 int shortestDistance = INT_MAX;
12241
12242 const auto targetCandidates = QApplication::allWidgets();
12243 for (QWidget *targetCandidate : targetCandidates) {
12244
12245 const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint()));
12246
12247 // For focus proxies, the child widget handling the focus can have keypad navigation focus,
12248 // but the owner of the proxy cannot.
12249 // Additionally, empty widgets should be ignored.
12250 if (targetCandidate->focusProxy() || targetCandidateRect.isEmpty())
12251 continue;
12252
12253 // Only navigate to a target widget that...
12254 if ( targetCandidate != sourceWidget
12255 // ...takes the focus,
12256 && targetCandidate->focusPolicy() & Qt::TabFocus
12257 // ...is above if DirectionNorth,
12258 && !(direction == DirectionNorth && targetCandidateRect.bottom() > sourceRect.top())
12259 // ...is on the right if DirectionEast,
12260 && !(direction == DirectionEast && targetCandidateRect.left() < sourceRect.right())
12261 // ...is below if DirectionSouth,
12262 && !(direction == DirectionSouth && targetCandidateRect.top() < sourceRect.bottom())
12263 // ...is on the left if DirectionWest,
12264 && !(direction == DirectionWest && targetCandidateRect.right() > sourceRect.left())
12265 // ...is enabled,
12266 && targetCandidate->isEnabled()
12267 // ...is visible,
12268 && targetCandidate->isVisible()
12269 // ...is in the same window,
12270 && targetCandidate->window() == sourceWindow) {
12271 const int targetCandidateDistance = [](const QPoint &sourcePoint,
12272 const QRect &targetCandidateRect) {
12273 int dx = 0;
12274 int dy = 0;
12275 if (p.x() < r.left())
12276 dx = r.left() - p.x();
12277 else if (p.x() > r.right())
12278 dx = p.x() - r.right();
12279 if (p.y() < r.top())
12280 dy = r.top() - p.y();
12281 else if (p.y() > r.bottom())
12282 dy = p.y() - r.bottom();
12283 return dx + dy;
12284 }();
12285 if (targetCandidateDistance < shortestDistance) {
12286 shortestDistance = targetCandidateDistance;
12287 targetWidget = targetCandidate;
12288 }
12289 }
12290 }
12291 return targetWidget;
12292}
12293
12294/*!
12295 \internal
12296
12297 Tells us if it there is currently a reachable widget by keypad navigation in
12298 a certain \a orientation.
12299 If no navigation is possible, occurring key events in that \a orientation may
12300 be used to interact with the value in the focused widget, even though it
12301 currently has not the editFocus.
12302
12303 \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus()
12304*/
12305bool QWidgetPrivate::canKeypadNavigate(Qt::Orientation orientation)
12306{
12307 return orientation == Qt::Horizontal?
12308 (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast)
12309 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest))
12310 :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth)
12311 || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth));
12312}
12313/*!
12314 \internal
12315
12316 Checks, if the \a widget is inside a QTabWidget. If is is inside
12317 one, left/right key events will be used to switch between tabs in keypad
12318 navigation. If there is no QTabWidget, the horizontal key events can be used
12319to
12320 interact with the value in the focused widget, even though it currently has
12321 not the editFocus.
12322
12323 \sa QWidget::hasEditFocus()
12324*/
12325bool QWidgetPrivate::inTabWidget(QWidget *widget)
12326{
12327 for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget())
12328 if (qobject_cast<const QTabWidget*>(tabWidget))
12329 return true;
12330 return false;
12331}
12332#endif
12333
12334/*!
12335 \since 5.0
12336 \internal
12337
12338 Sets the backing store to be the \a store specified.
12339 The QWidget will take ownership of the \a store.
12340*/
12341void QWidget::setBackingStore(QBackingStore *store)
12342{
12343 // ### createWinId() ??
12344
12345 if (!isWindow())
12346 return;
12347
12348 Q_D(QWidget);
12349
12350 QTLWExtra *topData = d->topData();
12351 if (topData->backingStore == store)
12352 return;
12353
12354 QBackingStore *oldStore = topData->backingStore;
12355 delete topData->backingStore;
12356 topData->backingStore = store;
12357
12358 QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
12359 if (!repaintManager)
12360 return;
12361
12362 if (isWindow()) {
12363 if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store)
12364 delete repaintManager->backingStore();
12365 repaintManager->setBackingStore(store);
12366 }
12367}
12368
12369/*!
12370 \since 5.0
12371
12372 Returns the QBackingStore this widget will be drawn into.
12373*/
12374QBackingStore *QWidget::backingStore() const
12375{
12376 Q_D(const QWidget);
12377 QTLWExtra *extra = d->maybeTopData();
12378 if (extra && extra->backingStore)
12379 return extra->backingStore;
12380
12381 if (!isWindow())
12382 return window()->backingStore();
12383
12384 return nullptr;
12385}
12386
12387void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
12388{
12389 if (left)
12390 *left = (int)leftLayoutItemMargin;
12391 if (top)
12392 *top = (int)topLayoutItemMargin;
12393 if (right)
12394 *right = (int)rightLayoutItemMargin;
12395 if (bottom)
12396 *bottom = (int)bottomLayoutItemMargin;
12397}
12398
12399void QWidgetPrivate::setLayoutItemMargins(int left, int top, int right, int bottom)
12400{
12401 if (leftLayoutItemMargin == left
12402 && topLayoutItemMargin == top
12403 && rightLayoutItemMargin == right
12404 && bottomLayoutItemMargin == bottom)
12405 return;
12406
12407 Q_Q(QWidget);
12408 leftLayoutItemMargin = (signed char)left;
12409 topLayoutItemMargin = (signed char)top;
12410 rightLayoutItemMargin = (signed char)right;
12411 bottomLayoutItemMargin = (signed char)bottom;
12412 q->updateGeometry();
12413}
12414
12415void QWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
12416{
12417 Q_Q(QWidget);
12418 QStyleOption myOpt;
12419 if (!opt) {
12420 myOpt.initFrom(w: q);
12421 myOpt.rect.setRect(ax: 0, ay: 0, aw: 32768, ah: 32768); // arbitrary
12422 opt = &myOpt;
12423 }
12424
12425 QRect liRect = q->style()->subElementRect(subElement: element, option: opt, widget: q);
12426 if (liRect.isValid()) {
12427 leftLayoutItemMargin = (signed char)(opt->rect.left() - liRect.left());
12428 topLayoutItemMargin = (signed char)(opt->rect.top() - liRect.top());
12429 rightLayoutItemMargin = (signed char)(liRect.right() - opt->rect.right());
12430 bottomLayoutItemMargin = (signed char)(liRect.bottom() - opt->rect.bottom());
12431 } else {
12432 leftLayoutItemMargin = 0;
12433 topLayoutItemMargin = 0;
12434 rightLayoutItemMargin = 0;
12435 bottomLayoutItemMargin = 0;
12436 }
12437}
12438// resets the Qt::WA_QuitOnClose attribute to the default value for transient widgets.
12439void QWidgetPrivate::adjustQuitOnCloseAttribute()
12440{
12441 Q_Q(QWidget);
12442
12443 if (!q->parentWidget()) {
12444 Qt::WindowType type = q->windowType();
12445 if (type == Qt::Widget || type == Qt::SubWindow)
12446 type = Qt::Window;
12447 if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
12448 q->setAttribute(attribute: Qt::WA_QuitOnClose, on: false);
12449 }
12450}
12451
12452void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
12453{
12454 QWidgetPrivate *wd = QWidgetPrivate::get(w);
12455 if (!wd->textureChildSeen)
12456 return;
12457 if (end)
12458 wd->endCompose();
12459 else
12460 wd->beginCompose();
12461 for (int i = 0; i < wd->children.size(); ++i) {
12462 w = qobject_cast<QWidget *>(o: wd->children.at(i));
12463 if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
12464 sendComposeStatus(w, end);
12465 }
12466}
12467
12468Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
12469{
12470 return widget->data;
12471}
12472
12473Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget)
12474{
12475 return widget->d_func();
12476}
12477
12478
12479#if QT_CONFIG(graphicsview)
12480/*!
12481 \since 4.5
12482
12483 Returns the proxy widget for the corresponding embedded widget in a graphics
12484 view; otherwise returns \nullptr.
12485
12486 \sa QGraphicsProxyWidget::createProxyForChildWidget(),
12487 QGraphicsScene::addWidget()
12488 */
12489QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
12490{
12491 Q_D(const QWidget);
12492 if (d->extra) {
12493 return d->extra->proxyWidget;
12494 }
12495 return nullptr;
12496}
12497#endif
12498
12499#ifndef QT_NO_GESTURES
12500/*!
12501 Subscribes the widget to a given \a gesture with specific \a flags.
12502
12503 \sa ungrabGesture(), QGestureEvent
12504 \since 4.6
12505*/
12506void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
12507{
12508 Q_D(QWidget);
12509 d->gestureContext.insert(key: gesture, value: flags);
12510 (void)QGestureManager::instance(); // create a gesture manager
12511}
12512
12513/*!
12514 Unsubscribes the widget from a given \a gesture type
12515
12516 \sa grabGesture(), QGestureEvent
12517 \since 4.6
12518*/
12519void QWidget::ungrabGesture(Qt::GestureType gesture)
12520{
12521 // if you modify this function, check the inlined version in ~QWidget, too
12522 Q_D(QWidget);
12523 if (d->gestureContext.remove(key: gesture)) {
12524 if (QGestureManager *manager = QGestureManager::instance())
12525 manager->cleanupCachedGestures(target: this, type: gesture);
12526 }
12527}
12528#endif // QT_NO_GESTURES
12529
12530/*!
12531 \fn void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12532
12533 Frees up window system resources. Destroys the widget window if \a
12534 destroyWindow is true.
12535
12536 destroy() calls itself recursively for all the child widgets,
12537 passing \a destroySubWindows for the \a destroyWindow parameter.
12538 To have more control over destruction of subwidgets, destroy
12539 subwidgets selectively first.
12540
12541 This function is usually called from the QWidget destructor.
12542*/
12543void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
12544{
12545 Q_D(QWidget);
12546
12547 d->aboutToDestroy();
12548 if (!isWindow() && parentWidget())
12549 parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(rect: geometry()));
12550 d->deactivateWidgetCleanup();
12551
12552 if ((windowType() == Qt::Popup) && qApp)
12553 qApp->d_func()->closePopup(popup: this);
12554
12555 if (this == qApp->activeWindow())
12556 QApplicationPrivate::setActiveWindow(nullptr);
12557 if (QWidget::mouseGrabber() == this)
12558 releaseMouse();
12559 if (QWidget::keyboardGrabber() == this)
12560 releaseKeyboard();
12561
12562 setAttribute(attribute: Qt::WA_WState_Created, on: false);
12563
12564 if (windowType() != Qt::Desktop) {
12565 if (destroySubWindows) {
12566 QObjectList childList(children());
12567 for (int i = 0; i < childList.size(); i++) {
12568 QWidget *widget = qobject_cast<QWidget *>(o: childList.at(i));
12569 if (widget && widget->testAttribute(attribute: Qt::WA_NativeWindow)) {
12570 if (widget->windowHandle()) {
12571 widget->destroy();
12572 }
12573 }
12574 }
12575 }
12576 if (destroyWindow) {
12577 d->deleteTLSysExtra();
12578 } else {
12579 if (parentWidget() && parentWidget()->testAttribute(attribute: Qt::WA_WState_Created)) {
12580 d->hide_sys();
12581 }
12582 }
12583
12584 d->setWinId(0);
12585 }
12586}
12587
12588/*!
12589 \fn QPaintEngine *QWidget::paintEngine() const
12590
12591 Returns the widget's paint engine.
12592
12593 Note that this function should not be called explicitly by the
12594 user, since it's meant for reimplementation purposes only. The
12595 function is called by Qt internally, and the default
12596 implementation may not always return a valid pointer.
12597*/
12598QPaintEngine *QWidget::paintEngine() const
12599{
12600 qWarning(msg: "QWidget::paintEngine: Should no longer be called");
12601
12602#ifdef Q_OS_WIN
12603 // We set this bit which is checked in setAttribute for
12604 // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
12605 //
12606 // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
12607 // Windows which would mean suddenly their widgets stop working.
12608 //
12609 // 2. Users set paint on screen and subclass paintEngine() to
12610 // return 0, in which case we have a "hole" in the backingstore
12611 // allowing use of GDI or DirectX directly.
12612 //
12613 // 1 is WRONG, but to minimize silent failures, we have set this
12614 // bit to ignore the setAttribute call. 2. needs to be
12615 // supported because its our only means of embedding native
12616 // graphics stuff.
12617 const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
12618#endif
12619
12620 return nullptr; //##### @@@
12621}
12622
12623// Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing.
12624static inline bool canMapPosition(QWindow *window)
12625{
12626 return window->handle() && !qt_window_private(window)->resizeEventPending;
12627}
12628
12629#if QT_CONFIG(graphicsview)
12630static inline QGraphicsProxyWidget *graphicsProxyWidget(const QWidget *w)
12631{
12632 QGraphicsProxyWidget *result = nullptr;
12633 const QWidgetPrivate *d = qt_widget_private(widget: const_cast<QWidget *>(w));
12634 if (d->extra)
12635 result = d->extra->proxyWidget;
12636 return result;
12637}
12638#endif // QT_CONFIG(graphicsview)
12639
12640struct MapToGlobalTransformResult {
12641 QTransform transform;
12642 QWindow *window;
12643};
12644
12645static MapToGlobalTransformResult mapToGlobalTransform(const QWidget *w)
12646{
12647 MapToGlobalTransformResult result;
12648 result.window = nullptr;
12649 for ( ; w ; w = w->parentWidget()) {
12650#if QT_CONFIG(graphicsview)
12651 if (QGraphicsProxyWidget *qgpw = graphicsProxyWidget(w)) {
12652 if (const QGraphicsScene *scene = qgpw->scene()) {
12653 const QList <QGraphicsView *> views = scene->views();
12654 if (!views.isEmpty()) {
12655 auto *viewP = static_cast<QGraphicsViewPrivate *>(qt_widget_private(widget: views.constFirst()));
12656 result.transform *= viewP->mapToViewTransform(item: qgpw);
12657 w = views.first()->viewport();
12658 }
12659 }
12660 }
12661#endif // QT_CONFIG(graphicsview)
12662 QWindow *window = w->windowHandle();
12663 if (window && canMapPosition(window)) {
12664 result.window = window;
12665 break;
12666 }
12667
12668 const auto &geometry = w->geometry();
12669 result.transform *= QTransform::fromTranslate(dx: geometry.x(), dy: geometry.y());
12670 if (w->isWindow())
12671 break;
12672 }
12673 return result;
12674}
12675
12676/*!
12677 \fn QPointF QWidget::mapToGlobal(const QPointF &pos) const
12678
12679 Translates the widget coordinate \a pos to global screen
12680 coordinates. For example, \c{mapToGlobal(QPointF(0,0))} would give
12681 the global coordinates of the top-left pixel of the widget.
12682
12683 \sa mapFromGlobal(), mapTo(), mapToParent()
12684 \since 6.0
12685*/
12686QPointF QWidget::mapToGlobal(const QPointF &pos) const
12687{
12688 const MapToGlobalTransformResult t = mapToGlobalTransform(w: this);
12689 const QPointF g = t.transform.map(p: pos);
12690 return t.window ? t.window->mapToGlobal(pos: g) : g;
12691}
12692
12693/*!
12694 \overload
12695*/
12696QPoint QWidget::mapToGlobal(const QPoint &pos) const
12697{
12698 return mapToGlobal(pos: QPointF(pos)).toPoint();
12699}
12700
12701/*!
12702 \fn QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12703
12704 Translates the global screen coordinate \a pos to widget
12705 coordinates.
12706
12707 \sa mapToGlobal(), mapFrom(), mapFromParent()
12708 \since 6.0
12709*/
12710QPointF QWidget::mapFromGlobal(const QPointF &pos) const
12711{
12712 const MapToGlobalTransformResult t = mapToGlobalTransform(w: this);
12713 const QPointF windowLocal = t.window ? t.window->mapFromGlobal(pos) : pos;
12714 return t.transform.inverted().map(p: windowLocal);
12715}
12716
12717/*!
12718 \overload
12719*/
12720QPoint QWidget::mapFromGlobal(const QPoint &pos) const
12721{
12722 return mapFromGlobal(pos: QPointF(pos)).toPoint();
12723}
12724
12725QWidget *qt_pressGrab = nullptr;
12726QWidget *qt_mouseGrb = nullptr;
12727static bool mouseGrabWithCursor = false;
12728static QWidget *keyboardGrb = nullptr;
12729
12730static inline QWindow *grabberWindow(const QWidget *w)
12731{
12732 QWindow *window = w->windowHandle();
12733 if (!window)
12734 if (const QWidget *nativeParent = w->nativeParentWidget())
12735 window = nativeParent->windowHandle();
12736 return window;
12737}
12738
12739#ifndef QT_NO_CURSOR
12740static void grabMouseForWidget(QWidget *widget, const QCursor *cursor = nullptr)
12741#else
12742static void grabMouseForWidget(QWidget *widget)
12743#endif
12744{
12745 if (qt_mouseGrb)
12746 qt_mouseGrb->releaseMouse();
12747
12748 mouseGrabWithCursor = false;
12749 if (QWindow *window = grabberWindow(w: widget)) {
12750#ifndef QT_NO_CURSOR
12751 if (cursor) {
12752 mouseGrabWithCursor = true;
12753 QGuiApplication::setOverrideCursor(*cursor);
12754 }
12755#endif // !QT_NO_CURSOR
12756 window->setMouseGrabEnabled(true);
12757 }
12758
12759 qt_mouseGrb = widget;
12760 qt_pressGrab = nullptr;
12761}
12762
12763static void releaseMouseGrabOfWidget(QWidget *widget)
12764{
12765 if (qt_mouseGrb == widget) {
12766 if (QWindow *window = grabberWindow(w: widget)) {
12767#ifndef QT_NO_CURSOR
12768 if (mouseGrabWithCursor) {
12769 QGuiApplication::restoreOverrideCursor();
12770 mouseGrabWithCursor = false;
12771 }
12772#endif // !QT_NO_CURSOR
12773 window->setMouseGrabEnabled(false);
12774 }
12775 }
12776 qt_mouseGrb = nullptr;
12777}
12778
12779/*!
12780 \fn void QWidget::grabMouse()
12781
12782 Grabs the mouse input.
12783
12784 This widget receives all mouse events until releaseMouse() is
12785 called; other widgets get no mouse events at all. Keyboard
12786 events are not affected. Use grabKeyboard() if you want to grab
12787 that.
12788
12789 \warning Bugs in mouse-grabbing applications very often lock the
12790 terminal. Use this function with extreme caution, and consider
12791 using the \c -nograb command line option while debugging.
12792
12793 It is seldom necessary to grab the mouse when using Qt, as
12794 Qt grabs and releases it sensibly. In particular, Qt grabs the
12795 mouse when a mouse button is pressed and keeps it until the last
12796 button is released.
12797
12798 \note Only visible widgets can grab mouse input. If isVisible()
12799 returns \c false for a widget, that widget cannot call grabMouse().
12800
12801 \note On Windows, grabMouse() only works when the mouse is inside a window
12802 owned by the process.
12803 On \macos, grabMouse() only works when the mouse is inside the frame of that widget.
12804
12805 \sa releaseMouse(), grabKeyboard(), releaseKeyboard()
12806*/
12807void QWidget::grabMouse()
12808{
12809 grabMouseForWidget(widget: this);
12810}
12811
12812/*!
12813 \fn void QWidget::grabMouse(const QCursor &cursor)
12814 \overload grabMouse()
12815
12816 Grabs the mouse input and changes the cursor shape.
12817
12818 The cursor will assume shape \a cursor (for as long as the mouse
12819 focus is grabbed) and this widget will be the only one to receive
12820 mouse events until releaseMouse() is called().
12821
12822 \warning Grabbing the mouse might lock the terminal.
12823
12824 \note See the note in QWidget::grabMouse().
12825
12826 \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
12827*/
12828#ifndef QT_NO_CURSOR
12829void QWidget::grabMouse(const QCursor &cursor)
12830{
12831 grabMouseForWidget(widget: this, cursor: &cursor);
12832}
12833#endif
12834
12835bool QWidgetPrivate::stealMouseGrab(bool grab)
12836{
12837 // This is like a combination of grab/releaseMouse() but with error checking
12838 // and it has no effect on the result of mouseGrabber().
12839 Q_Q(QWidget);
12840 QWindow *window = grabberWindow(w: q);
12841 return window ? window->setMouseGrabEnabled(grab) : false;
12842}
12843
12844/*!
12845 \fn void QWidget::releaseMouse()
12846
12847 Releases the mouse grab.
12848
12849 \sa grabMouse(), grabKeyboard(), releaseKeyboard()
12850*/
12851void QWidget::releaseMouse()
12852{
12853 releaseMouseGrabOfWidget(widget: this);
12854}
12855
12856/*!
12857 \fn void QWidget::grabKeyboard()
12858
12859 Grabs the keyboard input.
12860
12861 This widget receives all keyboard events until releaseKeyboard()
12862 is called; other widgets get no keyboard events at all. Mouse
12863 events are not affected. Use grabMouse() if you want to grab that.
12864
12865 The focus widget is not affected, except that it doesn't receive
12866 any keyboard events. setFocus() moves the focus as usual, but the
12867 new focus widget receives keyboard events only after
12868 releaseKeyboard() is called.
12869
12870 If a different widget is currently grabbing keyboard input, that
12871 widget's grab is released first.
12872
12873 \sa releaseKeyboard(), grabMouse(), releaseMouse(), focusWidget()
12874*/
12875void QWidget::grabKeyboard()
12876{
12877 if (keyboardGrb)
12878 keyboardGrb->releaseKeyboard();
12879 if (QWindow *window = grabberWindow(w: this))
12880 window->setKeyboardGrabEnabled(true);
12881 keyboardGrb = this;
12882}
12883
12884bool QWidgetPrivate::stealKeyboardGrab(bool grab)
12885{
12886 // This is like a combination of grab/releaseKeyboard() but with error
12887 // checking and it has no effect on the result of keyboardGrabber().
12888 Q_Q(QWidget);
12889 QWindow *window = grabberWindow(w: q);
12890 return window ? window->setKeyboardGrabEnabled(grab) : false;
12891}
12892
12893/*!
12894 \fn void QWidget::releaseKeyboard()
12895
12896 Releases the keyboard grab.
12897
12898 \sa grabKeyboard(), grabMouse(), releaseMouse()
12899*/
12900void QWidget::releaseKeyboard()
12901{
12902 if (keyboardGrb == this) {
12903 if (QWindow *window = grabberWindow(w: this))
12904 window->setKeyboardGrabEnabled(false);
12905 keyboardGrb = nullptr;
12906 }
12907}
12908
12909/*!
12910 \fn QWidget *QWidget::mouseGrabber()
12911
12912 Returns the widget that is currently grabbing the mouse input.
12913
12914 If no widget in this application is currently grabbing the mouse,
12915 \nullptr is returned.
12916
12917 \sa grabMouse(), keyboardGrabber()
12918*/
12919QWidget *QWidget::mouseGrabber()
12920{
12921 if (qt_mouseGrb)
12922 return qt_mouseGrb;
12923 return qt_pressGrab;
12924}
12925
12926/*!
12927 \fn QWidget *QWidget::keyboardGrabber()
12928
12929 Returns the widget that is currently grabbing the keyboard input.
12930
12931 If no widget in this application is currently grabbing the
12932 keyboard, \nullptr is returned.
12933
12934 \sa grabMouse(), mouseGrabber()
12935*/
12936QWidget *QWidget::keyboardGrabber()
12937{
12938 return keyboardGrb;
12939}
12940
12941/*!
12942 \fn void QWidget::activateWindow()
12943
12944 Sets the top-level widget containing this widget to be the active
12945 window.
12946
12947 An active window is a visible top-level window that has the
12948 keyboard input focus.
12949
12950 This function performs the same operation as clicking the mouse on
12951 the title bar of a top-level window. On X11, the result depends on
12952 the Window Manager. If you want to ensure that the window is
12953 stacked on top as well you should also call raise(). Note that the
12954 window must be visible, otherwise activateWindow() has no effect.
12955
12956 On Windows, if you are calling this when the application is not
12957 currently the active one then it will not make it the active
12958 window. It will change the color of the taskbar entry to indicate
12959 that the window has changed in some way. This is because Microsoft
12960 does not allow an application to interrupt what the user is currently
12961 doing in another application.
12962
12963 \sa isActiveWindow(), window(), show()
12964*/
12965void QWidget::activateWindow()
12966{
12967 QWindow *const wnd = window()->windowHandle();
12968
12969 if (wnd)
12970 wnd->requestActivate();
12971}
12972
12973/*!
12974
12975 Internal implementation of the virtual QPaintDevice::metric()
12976 function.
12977
12978 \a m is the metric to get.
12979*/
12980int QWidget::metric(PaintDeviceMetric m) const
12981{
12982 QScreen *screen = this->screen();
12983
12984 if (!screen) {
12985 if (m == PdmDpiX || m == PdmDpiY)
12986 return 72;
12987 return QPaintDevice::metric(metric: m);
12988 }
12989
12990 auto resolveDevicePixelRatio = [this, screen]() -> qreal {
12991
12992 // Note: keep in sync with QBackingStorePrivate::backingStoreDevicePixelRatio()!
12993 static bool downscale = qEnvironmentVariableIntValue(varName: "QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
12994 QWindow *window = this->window()->windowHandle();
12995 if (window)
12996 return downscale ? std::ceil(x: window->devicePixelRatio()) : window->devicePixelRatio();
12997 return screen->devicePixelRatio();
12998 };
12999
13000 switch (m) {
13001 case PdmWidth:
13002 return data->crect.width();
13003 case PdmWidthMM:
13004 return data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
13005 case PdmHeight:
13006 return data->crect.height();
13007 case PdmHeightMM:
13008 return data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
13009 case PdmDepth:
13010 return screen->depth();
13011 case PdmDpiX:
13012 for (const QWidget *p = this; p; p = p->parentWidget()) {
13013 if (p->d_func()->extra && p->d_func()->extra->customDpiX)
13014 return p->d_func()->extra->customDpiX;
13015 }
13016 return qRound(d: screen->logicalDotsPerInchX());
13017 case PdmDpiY:
13018 for (const QWidget *p = this; p; p = p->parentWidget()) {
13019 if (p->d_func()->extra && p->d_func()->extra->customDpiY)
13020 return p->d_func()->extra->customDpiY;
13021 }
13022 return qRound(d: screen->logicalDotsPerInchY());
13023 case PdmPhysicalDpiX:
13024 return qRound(d: screen->physicalDotsPerInchX());
13025 case PdmPhysicalDpiY:
13026 return qRound(d: screen->physicalDotsPerInchY());
13027 case PdmDevicePixelRatio:
13028 return resolveDevicePixelRatio();
13029 case PdmDevicePixelRatioScaled:
13030 return QPaintDevice::devicePixelRatioFScale() * resolveDevicePixelRatio();
13031 case PdmDevicePixelRatioF_EncodedA:
13032 Q_FALLTHROUGH();
13033 case PdmDevicePixelRatioF_EncodedB:
13034 return QPaintDevice::encodeMetricF(metric: m, value: resolveDevicePixelRatio());
13035 default:
13036 break;
13037 }
13038 return QPaintDevice::metric(metric: m);
13039}
13040
13041/*!
13042 Initializes the \a painter pen, background and font to the same as
13043 the given widget's. This function is called automatically when the
13044 painter is opened on a QWidget.
13045*/
13046void QWidget::initPainter(QPainter *painter) const
13047{
13048 const QPalette &pal = palette();
13049 painter->d_func()->state->pen = QPen(pal.brush(cr: foregroundRole()), 1);
13050 painter->d_func()->state->bgBrush = pal.brush(cr: backgroundRole());
13051 QFont f(font(), const_cast<QWidget *>(this));
13052 painter->d_func()->state->deviceFont = f;
13053 painter->d_func()->state->font = f;
13054}
13055
13056/*!
13057 \internal
13058
13059 Do PaintDevice rendering with the specified \a offset.
13060*/
13061QPaintDevice *QWidget::redirected(QPoint *offset) const
13062{
13063 return d_func()->redirected(offset);
13064}
13065
13066/*!
13067 \internal
13068
13069 A painter that is shared among other instances of QPainter.
13070*/
13071QPainter *QWidget::sharedPainter() const
13072{
13073 // Someone sent a paint event directly to the widget
13074 if (!d_func()->redirectDev)
13075 return nullptr;
13076
13077 QPainter *sp = d_func()->sharedPainter();
13078 if (!sp || !sp->isActive())
13079 return nullptr;
13080
13081 if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
13082 return nullptr;
13083
13084 return sp;
13085}
13086
13087/*!
13088 \fn void QWidget::setMask(const QRegion &region)
13089 \overload
13090
13091 Causes only the parts of the widget which overlap \a region to be
13092 visible. If the region includes pixels outside the rect() of the
13093 widget, window system controls in that area may or may not be
13094 visible, depending on the platform.
13095
13096 Since QRegion allows arbitrarily complex regions to be created, widget
13097 masks can be made to suit the most unconventionally-shaped windows, and
13098 even allow widgets to be displayed with holes in them. Note that this
13099 effect can be slow if the region is particularly complex.
13100
13101 Widget masks are used to hint to the window system that the application
13102 does not want mouse events for areas outside the mask. On most systems,
13103 they also result in coarse visual clipping. To get smooth window edges, use
13104 translucent background and anti-aliased painting instead, as shown in the
13105 \l{Translucent Background} example.
13106
13107 \sa windowOpacity
13108*/
13109void QWidget::setMask(const QRegion &newMask)
13110{
13111 Q_D(QWidget);
13112
13113 d->createExtra();
13114 if (newMask == d->extra->mask)
13115 return;
13116
13117#ifndef QT_NO_BACKINGSTORE
13118 const QRegion oldMask(d->extra->mask);
13119#endif
13120
13121 d->extra->mask = newMask;
13122 d->extra->hasMask = !newMask.isEmpty();
13123
13124 if (!testAttribute(attribute: Qt::WA_WState_Created))
13125 return;
13126
13127 d->setMask_sys(newMask);
13128
13129#ifndef QT_NO_BACKINGSTORE
13130 if (!isVisible())
13131 return;
13132
13133 if (!d->extra->hasMask) {
13134 // Mask was cleared; update newly exposed area.
13135 QRegion expose(rect());
13136 expose -= oldMask;
13137 if (!expose.isEmpty()) {
13138 d->setDirtyOpaqueRegion();
13139 update(rgn: expose);
13140 }
13141 return;
13142 }
13143
13144 if (!isWindow()) {
13145 // Update newly exposed area on the parent widget.
13146 QRegion parentExpose(rect());
13147 parentExpose -= newMask;
13148 if (!parentExpose.isEmpty()) {
13149 d->setDirtyOpaqueRegion();
13150 parentExpose.translate(p: data->crect.topLeft());
13151 parentWidget()->update(rgn: parentExpose);
13152 }
13153
13154 // Update newly exposed area on this widget
13155 if (!oldMask.isEmpty())
13156 update(rgn: newMask - oldMask);
13157 }
13158#endif
13159}
13160
13161void QWidgetPrivate::setMask_sys(const QRegion &region)
13162{
13163 Q_Q(QWidget);
13164 if (QWindow *window = q->windowHandle())
13165 window->setMask(region);
13166}
13167
13168/*!
13169 \fn void QWidget::setMask(const QBitmap &bitmap)
13170
13171 Causes only the pixels of the widget for which \a bitmap has a
13172 corresponding 1 bit to be visible. If the region includes pixels
13173 outside the rect() of the widget, window system controls in that
13174 area may or may not be visible, depending on the platform.
13175
13176 Note that this effect can be slow if the region is particularly
13177 complex.
13178
13179 The following code shows how an image with an alpha channel can be
13180 used to generate a mask for a widget:
13181
13182 \snippet widget-mask/main.cpp 0
13183
13184 The label shown by this code is masked using the image it contains,
13185 giving the appearance that an irregularly-shaped image is being drawn
13186 directly onto the screen.
13187
13188 Masked widgets receive mouse events only on their visible
13189 portions.
13190
13191 \sa clearMask(), windowOpacity()
13192*/
13193void QWidget::setMask(const QBitmap &bitmap)
13194{
13195 setMask(QRegion(bitmap));
13196}
13197
13198/*!
13199 \fn void QWidget::clearMask()
13200
13201 Removes any mask set by setMask().
13202
13203 \sa setMask()
13204*/
13205void QWidget::clearMask()
13206{
13207 Q_D(QWidget);
13208 if (!d->extra || !d->extra->hasMask)
13209 return;
13210 setMask(QRegion());
13211}
13212
13213void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent)
13214{
13215 Q_ASSERT(widgetAsObject->isWidgetType());
13216 Q_ASSERT(!newParent || newParent->isWidgetType());
13217 QWidget *widget = static_cast<QWidget*>(widgetAsObject);
13218 widget->setParent(static_cast<QWidget*>(newParent));
13219}
13220
13221std::string QWidgetPrivate::flagsForDumping() const
13222{
13223 Q_Q(const QWidget);
13224 std::string flags = QObjectPrivate::flagsForDumping();
13225 if (QApplication::focusWidget() == q)
13226 flags += 'F';
13227 if (q->isVisible()) {
13228 std::stringstream s;
13229 s << '<'
13230 << q->width() << 'x' << q->height()
13231 << std::showpos << q->x() << q->y()
13232 << '>';
13233 flags += s.str();
13234 } else {
13235 flags += 'I';
13236 }
13237 return flags;
13238}
13239
13240void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
13241{
13242#if QT_CONFIG(xcb)
13243 Q_Q(QWidget);
13244
13245 if (!q->windowHandle())
13246 return;
13247
13248 QXcbWindow::WindowTypes wmWindowType = QXcbWindow::None;
13249 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDesktop))
13250 wmWindowType |= QXcbWindow::Desktop;
13251 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDock))
13252 wmWindowType |= QXcbWindow::Dock;
13253 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeToolBar))
13254 wmWindowType |= QXcbWindow::Toolbar;
13255 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeMenu))
13256 wmWindowType |= QXcbWindow::Menu;
13257 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeUtility))
13258 wmWindowType |= QXcbWindow::Utility;
13259 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeSplash))
13260 wmWindowType |= QXcbWindow::Splash;
13261 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDialog))
13262 wmWindowType |= QXcbWindow::Dialog;
13263 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDropDownMenu))
13264 wmWindowType |= QXcbWindow::DropDownMenu;
13265 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypePopupMenu))
13266 wmWindowType |= QXcbWindow::PopupMenu;
13267 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeToolTip))
13268 wmWindowType |= QXcbWindow::Tooltip;
13269 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeNotification))
13270 wmWindowType |= QXcbWindow::Notification;
13271 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeCombo))
13272 wmWindowType |= QXcbWindow::Combo;
13273 if (q->testAttribute(attribute: Qt::WA_X11NetWmWindowTypeDND))
13274 wmWindowType |= QXcbWindow::Dnd;
13275
13276 if (wmWindowType == QXcbWindow::None && skipIfMissing)
13277 return;
13278
13279 if (auto *xcbWindow = dynamic_cast<QXcbWindow*>(q->windowHandle()->handle()))
13280 xcbWindow->setWindowType(wmWindowType);
13281#else
13282 Q_UNUSED(skipIfMissing);
13283#endif
13284}
13285
13286/*!
13287 \internal
13288 \return \c true, if a child with \param policy exists and isn't a child of \param excludeChildrenOf.
13289 Return false otherwise.
13290 */
13291bool QWidgetPrivate::hasChildWithFocusPolicy(Qt::FocusPolicy policy, const QWidget *excludeChildrenOf) const
13292{
13293 Q_Q(const QWidget);
13294 const QWidgetList &children = q->findChildren<QWidget *>(options: Qt::FindChildrenRecursively);
13295 for (const auto *child : children) {
13296 if (child->focusPolicy() == policy && child->isEnabled()
13297 && (!excludeChildrenOf || !excludeChildrenOf->isAncestorOf(child))) {
13298 return true;
13299 }
13300 }
13301 return false;
13302}
13303
13304#ifndef QT_NO_DEBUG_STREAM
13305
13306namespace {
13307QDebug operator<<(QDebug debug, const WidgetAttributes &attributes)
13308{
13309 const QDebugStateSaver saver(debug);
13310 debug.nospace();
13311 debug << '[';
13312 if (const QWidget *widget = attributes.widget) {
13313 const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
13314 const QMetaEnum me = qtMo->enumerator(index: qtMo->indexOfEnumerator(name: "WidgetAttribute"));
13315 int count = 0;
13316 for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
13317 if (widget->testAttribute(attribute: static_cast<Qt::WidgetAttribute>(a))) {
13318 if (count++)
13319 debug << ',';
13320 debug << me.valueToKey(value: a);
13321 }
13322 }
13323 }
13324 debug << ']';
13325 return debug;
13326}
13327}
13328
13329QDebug operator<<(QDebug debug, const QWidget *widget)
13330{
13331 const QDebugStateSaver saver(debug);
13332 debug.nospace();
13333 if (widget) {
13334 debug << widget->metaObject()->className() << '(' << (const void *)widget;
13335 if (!widget->objectName().isEmpty())
13336 debug << ", name=" << widget->objectName();
13337 if (debug.verbosity() > 2) {
13338 const QRect geometry = widget->geometry();
13339 const QRect frameGeometry = widget->frameGeometry();
13340 if (widget->isVisible())
13341 debug << ", visible";
13342 if (!widget->isEnabled())
13343 debug << ", disabled";
13344 debug << ", states=" << widget->windowState()
13345 << ", type=" << widget->windowType() << ", flags=" << widget->windowFlags();
13346 debug << ", attributes=" << WidgetAttributes{.widget: widget};
13347 if (widget->isWindow())
13348 debug << ", window";
13349 debug << ", " << geometry.width() << 'x' << geometry.height()
13350 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
13351 if (frameGeometry != geometry) {
13352 const QMargins margins(geometry.x() - frameGeometry.x(),
13353 geometry.y() - frameGeometry.y(),
13354 frameGeometry.right() - geometry.right(),
13355 frameGeometry.bottom() - geometry.bottom());
13356 debug << ", margins=" << margins;
13357 }
13358 debug << ", devicePixelRatio=" << widget->devicePixelRatio();
13359 if (const WId wid = widget->internalWinId())
13360 debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
13361 }
13362 debug << ')';
13363 } else {
13364 debug << "QWidget(0x0)";
13365 }
13366 return debug;
13367}
13368#endif // !QT_NO_DEBUG_STREAM
13369
13370
13371// *************************** Focus abstraction ************************************
13372
13373#define FOCUS_NEXT(w) w->d_func()->focus_next
13374#define FOCUS_PREV(w) w->d_func()->focus_prev
13375
13376/*!
13377 \internal
13378 \return next or previous element in the focus chain, depending on
13379 \param direction, irrespective of focus proxies or widgets with Qt::NoFocus.
13380 */
13381QWidget *QWidgetPrivate::nextPrevElementInFocusChain(FocusDirection direction) const
13382{
13383 Q_Q(const QWidget);
13384 return direction == FocusDirection::Next ? FOCUS_NEXT(q) : FOCUS_PREV(q);
13385}
13386
13387/*!
13388 \internal
13389 Removes a widget from the focus chain, respecting the flags set in \param rules.
13390 \list
13391 \li EnsureFocusOut: If the widget has input focus, transfer focus to the next or previous widget
13392 in the focus chain, depending on \param direction.
13393 \li RemoveInconsistent: Remove the widget, even if its focus chain is inconsistent.
13394 \li AssertConsistency: qFatal, if the focus chain is inconsistent. This is used in the QWidget destructor.
13395 \endlist
13396 \return \c true if the widget has been removed, otherwise \c false.
13397 */
13398bool QWidgetPrivate::removeFromFocusChain(FocusChainRemovalRules rules, FocusDirection direction)
13399{
13400 Q_Q(QWidget);
13401 if (!isFocusChainConsistent()) {
13402#ifdef QT_DEBUG
13403 if (rules.testFlag(flag: FocusChainRemovalRule::AssertConsistency))
13404 qFatal() << q << "has inconsistent focus chain.";
13405#endif
13406 qCDebug(lcWidgetFocus) << q << "wasn't removed, because of inconsistent focus chain.";
13407 return false;
13408 }
13409
13410 if (!isInFocusChain()) {
13411 qCDebug(lcWidgetFocus) << q << "wasn't removed, because it is not part of a focus chain.";
13412 return false;
13413 }
13414
13415 if (rules.testFlag(flag: FocusChainRemovalRule::EnsureFocusOut))
13416 q->focusNextPrevChild(next: direction == FocusDirection::Next);
13417
13418 FOCUS_NEXT(FOCUS_PREV(q)) = FOCUS_NEXT(q);
13419 FOCUS_PREV(FOCUS_NEXT(q)) = FOCUS_PREV(q);
13420 initFocusChain();
13421 qCDebug(lcWidgetFocus) << q << "removed from focus chain.";
13422 return true;
13423}
13424
13425/*!
13426 \internal
13427 Initialises the focus chain by making the widget point to itself.
13428 */
13429void QWidgetPrivate::initFocusChain()
13430{
13431 Q_Q(QWidget);
13432 qCDebug(lcWidgetFocus) << "Initializing focus chain of" << q;
13433 FOCUS_PREV(q) = q;
13434 FOCUS_NEXT(q) = q;
13435}
13436
13437/*!
13438 \internal
13439 Reads QWidget children, which are not part of a focus chain yet.
13440 Inserts them into the focus chain before or after the widget,
13441 depending on \param direction and in the order of their creation.
13442 This is used, when QWidget::setParent() causes a widget to change toplevel windows.
13443 */
13444void QWidgetPrivate::reparentFocusChildren(FocusDirection direction)
13445{
13446 Q_Q(QWidget);
13447
13448 // separate the focus chain into new (children of myself) and old (the rest)
13449 QWidget *firstOld = nullptr;
13450 QWidget *lastOld = nullptr; // last in the old list
13451 QWidget *lastNew = q; // last in the new list
13452 bool prevWasNew = true;
13453 QWidget *widget = nextPrevElementInFocusChain(direction);
13454
13455 // For efficiency, do not maintain the list invariant inside the loop.
13456 // Append items to the relevant list, and we optimize by not changing pointers,
13457 // when subsequent items are going into the same list.
13458 while (widget != q) {
13459 bool currentIsNew = q->isAncestorOf(child: widget);
13460 if (currentIsNew) {
13461 if (!prevWasNew) {
13462 // previous was old => append to new list
13463 FOCUS_NEXT(lastNew) = widget;
13464 FOCUS_PREV(widget) = lastNew;
13465 }
13466 lastNew = widget;
13467 } else {
13468 if (prevWasNew) {
13469 // prev was new => append to old list, if it exists
13470 if (lastOld) {
13471 FOCUS_NEXT(lastOld) = widget;
13472 FOCUS_PREV(widget) = lastOld;
13473 } else {
13474 // start the old list
13475 firstOld = widget;
13476 }
13477 }
13478 lastOld = widget;
13479 }
13480 widget = widget->d_func()->nextPrevElementInFocusChain(direction);
13481 prevWasNew = currentIsNew;
13482 }
13483
13484 // repair old list:
13485 if (firstOld) {
13486 FOCUS_NEXT(lastOld) = firstOld;
13487 FOCUS_PREV(firstOld) = lastOld;
13488 }
13489
13490 if (!q->isWindow()) {
13491 QWidget *topLevel = q->window();
13492 // insert new chain into toplevel's chain
13493 QWidget *prev = FOCUS_PREV(topLevel);
13494 FOCUS_PREV(topLevel) = lastNew;
13495 FOCUS_NEXT(prev) = q;
13496 FOCUS_PREV(q) = prev;
13497 FOCUS_NEXT(lastNew) = topLevel;
13498 } else {
13499 // repair new list
13500 FOCUS_NEXT(lastNew) = q;
13501 FOCUS_PREV(q) = lastNew;
13502 }
13503}
13504
13505/*!
13506 \internal
13507 Inserts a widget into the focus chain before or after \param position, depending on
13508 \param direction.
13509 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13510 */
13511bool QWidgetPrivate::insertIntoFocusChain(FocusDirection direction, QWidget *position)
13512{
13513 Q_Q(QWidget);
13514 Q_ASSERT(position);
13515 QWidget *next = FOCUS_NEXT(q);
13516 QWidget *previous = FOCUS_PREV(q);
13517
13518 switch (direction) {
13519 case FocusDirection::Next:
13520 if (previous == position) {
13521 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already before" << position;
13522 return false;
13523 }
13524
13525 removeFromFocusChain(rules: FocusChainRemovalRule::AssertConsistency);
13526
13527 FOCUS_NEXT(q) = FOCUS_NEXT(position);
13528 FOCUS_PREV(FOCUS_NEXT(position)) = q;
13529 FOCUS_NEXT(position) = q;
13530 FOCUS_PREV(q) = position;
13531 qCDebug(lcWidgetFocus) << q << "inserted after" << position;
13532 break;
13533
13534 case FocusDirection::Previous:
13535 if (next == position) {
13536 qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already after" << position;
13537 return false;
13538 }
13539
13540 removeFromFocusChain(rules: FocusChainRemovalRule::AssertConsistency);
13541
13542 FOCUS_PREV(q) = FOCUS_PREV(position);
13543 FOCUS_NEXT(FOCUS_PREV(position)) = q;
13544 FOCUS_PREV(position) = q;
13545 FOCUS_NEXT(q) = position;
13546 qCDebug(lcWidgetFocus) << q << "inserted before" << position;
13547 break;
13548 }
13549
13550 Q_ASSERT(isFocusChainConsistent());
13551 return true;
13552}
13553
13554/*!
13555 \internal
13556 Convenience override to insert a QWidgetList \param toBeInserted into the focus chain
13557 before or after \param position, depending on \param direction.
13558 \return \c true, if the insertion has changed the focus chain, otherwise \c false.
13559 \note
13560 \param toBeInserted must be a consistent focus chain.
13561 */
13562bool QWidgetPrivate::insertIntoFocusChain(const QWidgetList &toBeInserted,
13563 FocusDirection direction, QWidget *position)
13564{
13565 if (toBeInserted.isEmpty()) {
13566 qCDebug(lcWidgetFocus) << "No-op insertion of an empty list";
13567 return false;
13568 }
13569
13570 Q_ASSERT_X(!toBeInserted.contains(position),
13571 Q_FUNC_INFO,
13572 "Coding error: toBeInserted contains position");
13573
13574 QWidget *first = toBeInserted.constFirst();
13575 QWidget *last = toBeInserted.constLast();
13576
13577 // Call QWidget override to log accordingly
13578 if (toBeInserted.count() == 1)
13579 return first->d_func()->insertIntoFocusChain(direction, position);
13580
13581 Q_ASSERT(first != last);
13582 switch (direction) {
13583 case FocusDirection::Previous:
13584 if (FOCUS_PREV(position) == last) {
13585 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already before"
13586 << position;
13587 return false;
13588 }
13589 FOCUS_NEXT(FOCUS_PREV(position)) = first;
13590 FOCUS_PREV(first) = FOCUS_PREV(position);
13591 FOCUS_NEXT(last) = position;
13592 FOCUS_PREV(position) = last;
13593 qCDebug(lcWidgetFocus) << toBeInserted << "inserted before" << position;
13594 break;
13595 case FocusDirection::Next:
13596 if (FOCUS_PREV(position) == last) {
13597 qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already after"
13598 << position;
13599 return false;
13600 }
13601 FOCUS_PREV(FOCUS_NEXT(position)) = last;
13602 FOCUS_NEXT(last) = FOCUS_NEXT(position);
13603 FOCUS_PREV(first) = position;
13604 FOCUS_NEXT(position) = first;
13605 qCDebug(lcWidgetFocus) << toBeInserted << "inserted after" << position;
13606 break;
13607 }
13608
13609 Q_ASSERT(position->d_func()->isFocusChainConsistent());
13610 return true;
13611}
13612
13613/*!
13614 \internal
13615 \return a QWidgetList, representing the part of the focus chain,
13616 starting with \param from and ending with \param to, in \param direction.
13617 */
13618QWidgetList focusPath(QWidget *from, QWidget *to, QWidgetPrivate::FocusDirection direction)
13619{
13620 QWidgetList path({from});
13621 if (from == to)
13622 return path;
13623
13624 QWidget *current = from;
13625 do {
13626 switch (direction) {
13627 case QWidgetPrivate::FocusDirection::Previous:
13628 current = current->previousInFocusChain();
13629 break;
13630 case QWidgetPrivate::FocusDirection::Next:
13631 current = current->nextInFocusChain();
13632 break;
13633 }
13634 if (path.contains(t: current))
13635 return QWidgetList();
13636 path << current;
13637 } while (current != to);
13638
13639 return path;
13640}
13641
13642/*!
13643 \internal
13644 Removes the part from the focus chain starting with \param from and ending with \param to,
13645 in \param direction.
13646 \return removed part as a QWidgetList.
13647 */
13648QWidgetList QWidgetPrivate::takeFromFocusChain(QWidget *from,
13649 QWidget *to,
13650 FocusDirection direction)
13651{
13652 // Check if there is a path from->to in direction
13653 const QWidgetList path = focusPath(from, to , direction);
13654 if (path.isEmpty()) {
13655 qCDebug(lcWidgetFocus) << "No-op removal. Focus chain from" << from << "doesn't lead to " << to;
13656 return QWidgetList();
13657 }
13658
13659 QWidget *first = path.constFirst();
13660 QWidget *last = path.constLast();
13661 if (first == last) {
13662 first->d_func()->removeFromFocusChain();
13663 return QWidgetList({first});
13664 }
13665
13666 FOCUS_NEXT(FOCUS_PREV(first)) = FOCUS_NEXT(last);
13667 FOCUS_PREV(FOCUS_NEXT(last)) = FOCUS_PREV(first);
13668 FOCUS_PREV(first) = last;
13669 FOCUS_NEXT(last) = first;
13670 qCDebug(lcWidgetFocus) << path << "removed from focus chain";
13671 return path;
13672}
13673
13674/*!
13675 \internal
13676 \return The last focus child of the widget, traversing the focus chain no further than
13677 \param noFurtherThan.
13678 */
13679QWidget *QWidgetPrivate::determineLastFocusChild(QWidget *noFurtherThan)
13680{
13681 Q_Q(QWidget);
13682 // Since we need to repeat the same logic for both 'first' and 'second', we add a function
13683 // that determines the last focus child for a widget, taking proxies and compound widgets into
13684 // account. If the target is not a compound widget (it doesn't have a focus proxy that points
13685 // to a child), 'lastFocusChild' will be set to the target itself.
13686 QWidget *lastFocusChild = q;
13687
13688 QWidget *focusProxy = deepestFocusProxy();
13689 if (!focusProxy) {
13690 // QTBUG-81097: Another case is possible here. We can have a child
13691 // widget, that sets its focusProxy() to the parent (target).
13692 // An example of such widget is a QLineEdit, nested into
13693 // a QAbstractSpinBox. In this case such widget should be considered
13694 // the last focus child.
13695 for (auto *object : std::as_const(t: q->children())) {
13696 QWidget *w = qobject_cast<QWidget *>(o: object);
13697 if (w && w->focusProxy() == q) {
13698 lastFocusChild = w;
13699 break;
13700 }
13701 }
13702 } else if (q->isAncestorOf(child: focusProxy)) {
13703 lastFocusChild = focusProxy;
13704 for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
13705 focusNext != focusProxy && q->isAncestorOf(child: focusNext)
13706 && focusNext->window() == focusProxy->window();
13707 focusNext = focusNext->nextInFocusChain()) {
13708 if (focusNext == noFurtherThan)
13709 break;
13710 if (focusNext->focusPolicy() != Qt::NoFocus)
13711 lastFocusChild = focusNext;
13712 }
13713 }
13714 return lastFocusChild;
13715};
13716
13717/*!
13718 \internal
13719 \return \c true, if the widget is part of a focus chain and \c false otherwise.
13720 A widget is considered to be part of a focus chain, neither FOCUS_NEXT, nor FOCUS_PREV
13721 are pointing to the widget itself.
13722
13723 \note
13724 This method doesn't check the consistency of the focus chain.
13725 If multiple widgets have been removed from the focus chain by takeFromFocusChain(),
13726 isInFocusChain() will return \c true for all of those widgets, even if they represent
13727 an inconsistent focus chain.
13728 */
13729bool QWidgetPrivate::isInFocusChain() const
13730{
13731 Q_Q(const QWidget);
13732 return !(FOCUS_NEXT(q) == q && FOCUS_PREV(q) == q);
13733}
13734
13735/*!
13736 \internal
13737 A focus chain is consistent, when it is circular: Following the chain in either direction
13738 has to return to the beginning. This is why a newly constructed widget points to itself,
13739 when the focus chain has been initialized. A newly constructed widget is considered to have
13740 a consistent focus chain, while not being part of a focus chain.
13741
13742 The method always returns \c true, when the logging category "qt.widgets.focus" is disabled.
13743 When it is enabled, the method returns \c true early, if a widget is pointing to itself.
13744 It returns \c false, if one of the following is detected:
13745 \list
13746 \li nullptr found in a previous/next pointer.
13747 \li broken chain: widget A is B's previous, but B isn't A's next.
13748 \li chain isn't closed: starting at A doesn't lead back to A.
13749 \endlist
13750 It return \c true, if none of the above is observed.
13751
13752 \note
13753 The focus chain is checked only in forward direction.
13754 This is sufficient, because the check for a broken chain asserts consistent paths
13755 in both directions.
13756 */
13757bool QWidgetPrivate::isFocusChainConsistent() const
13758{
13759 Q_Q(const QWidget);
13760 const bool skip = !QLoggingCategory("qt.widgets.focus").isDebugEnabled();
13761 if (skip)
13762 return true;
13763
13764 if (!isInFocusChain())
13765 return true;
13766
13767 const QWidget *position = q;
13768
13769 for (int i = 0; i < QApplication::allWidgets().count(); ++i) {
13770 if (!FOCUS_PREV(position) || !FOCUS_NEXT(position)) {
13771 qCDebug(lcWidgetFocus) << "Nullptr found at:" << position
13772 << "Previous pointing to" << FOCUS_PREV(position)
13773 << "Next pointing to" << FOCUS_NEXT(position);
13774 return false;
13775 }
13776 if (!(FOCUS_PREV(FOCUS_NEXT(position)) == position
13777 && FOCUS_NEXT(FOCUS_PREV(position)) == position)) {
13778 qCDebug(lcWidgetFocus) << "Inconsistent focus chain at:" << position
13779 << "Previous pointing to" << FOCUS_PREV(FOCUS_NEXT(position))
13780 << "Next pointing to" << FOCUS_NEXT(FOCUS_PREV(position));
13781 return false;
13782 }
13783 position = FOCUS_NEXT(position);
13784 if (position == q)
13785 return true;
13786
13787 }
13788
13789 qCDebug(lcWidgetFocus) << "Focus chain leading from" << q << "to" << position << "is not closed.";
13790 return false;
13791}
13792
13793#undef FOCUS_NEXT
13794#undef FOCUS_PREV
13795
13796
13797QT_END_NAMESPACE
13798
13799#include "moc_qwidget.cpp"
13800#include "moc_qwidget_p.cpp"
13801

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtbase/src/widgets/kernel/qwidget.cpp